The Coline App SDK: apps, tools, file types and surfaces that run inside Coline workspaces, and public websites with Coline Sites. TypeScript, with an in-memory test workspace. MIT.
| 6 | emitAmbientEventsInputSchema, |
| 7 | type ColineAppManifest, |
| 8 | type ColineAppManifestInput, |
| 9 | type ColineFileTypeDefinition, |
| 10 | type ColineFileTypeDefinitionInput, |
| 11 | type ColineAppRegistrationPayload, |
| 12 | type EmitAmbientEventsInput, |
| 13 | type EmitAmbientEventsInputInput, |
| 14 | type CreateNotificationInput, |
| 15 | type CreateNotificationInputInput, |
| 16 | type NotificationChannelDefinition, |
| 17 | type NotificationChannelDefinitionInput, |
| 18 | notificationChannelDefinitionSchema, |
| 19 | } from "./manifest"; |
| 20 |
| 21 | type UnknownPayload = Record<string, unknown>; |
| 22 |
| 23 | export interface HomeRenderContext extends UnknownPayload {} |
| 24 | export interface FileRenderContext extends UnknownPayload { |
| 25 | fileId?: string; |
| 26 | } |
| 27 | export interface IndexSyncContext extends UnknownPayload { |
| 28 | workspaceId?: string; |
| 29 | } |
| 30 |
| 31 | export type HomeRenderHandler = (context: HomeRenderContext) => unknown | Promise<unknown>; |
| 32 | export type FileRenderHandler = (context: FileRenderContext) => unknown | Promise<unknown>; |
| 33 | export type IndexSyncHandler = (context: IndexSyncContext) => unknown | Promise<unknown>; |
| 34 |
| 35 | export interface ColineAppDefinition { |
| 36 | manifest: ColineAppManifest; |
| 37 | fileTypes: ColineFileTypeDefinition[]; |
| 38 | notificationChannels: NotificationChannelDefinition[]; |
| 39 | handlers: { |
| 40 | homeRender?: HomeRenderHandler; |
| 41 | fileRender?: FileRenderHandler; |
| 42 | indexSync?: IndexSyncHandler; |
| 43 | }; |
| 44 | } |
| 45 |
| 46 | class ColineAmbientHelper { |
| 47 | emit(input: EmitAmbientEventsInputInput): EmitAmbientEventsInput { |
| 48 | return emitAmbientEventsInputSchema.parse(input); |
| 49 | } |
| 50 | } |
| 51 |
| 52 | export class ColineApp { |
| 53 | readonly manifest: ColineAppManifest; |
| 54 | readonly ambient = new ColineAmbientHelper(); |
| 55 | private readonly fileTypes = new Map<string, ColineFileTypeDefinition>(); |
| 56 | private readonly notificationChannels = new Map<string, NotificationChannelDefinition>(); |
| 57 | private readonly handlers: ColineAppDefinition["handlers"] = {}; |
| 58 |
| 59 | constructor(manifest: ColineAppManifestInput) { |
| 60 | this.manifest = colineAppManifestSchema.parse(manifest); |
| 61 | } |
| 62 |
| 63 | defineFileType(fileType: ColineFileTypeDefinitionInput): this { |
| 64 | const parsed = colineFileTypeSchema.parse(fileType); |
| 65 | this.fileTypes.set(parsed.typeKey, parsed); |
| 66 | return this; |
| 67 | } |
| 68 |
| 69 | defineNotificationChannel(channel: NotificationChannelDefinitionInput): this { |
| 70 | const parsed = notificationChannelDefinitionSchema.parse(channel); |
| 71 | this.notificationChannels.set(parsed.key, parsed); |
| 72 | return this; |
| 73 | } |
| 74 |
| 75 | onHomeRender(handler: HomeRenderHandler): this { |
| 76 | this.handlers.homeRender = handler; |
| 77 | return this; |
| 78 | } |
| 79 |
| 80 | onFileRender(handler: FileRenderHandler): this { |
| 81 | this.handlers.fileRender = handler; |
| 82 | return this; |
| 83 | } |
| 84 |
| 85 | onIndexSync(handler: IndexSyncHandler): this { |
| 86 | this.handlers.indexSync = handler; |
| 87 | return this; |
| 88 | } |
| 89 |
| 90 | getDefinition(): ColineAppDefinition { |
| 91 | const notificationChannels = [...this.notificationChannels.values()]; |
| 92 |
| 93 | return { |
| 94 | manifest: { |
| 95 | ...this.manifest, |
| 96 | notificationChannels, |
| 97 | }, |
| 98 | fileTypes: [...this.fileTypes.values()], |
| 99 | notificationChannels, |
| 100 | handlers: { ...this.handlers }, |
| 101 | }; |
| 102 | } |
| 103 |
| 104 | getRegistrationPayload(version: string): ColineAppRegistrationPayload { |
| 105 | const notificationChannels = [...this.notificationChannels.values()]; |
| 106 |
| 107 | return colineAppRegistrationPayloadSchema.parse({ |
| 108 | version, |
| 109 | manifest: { |
| 110 | ...this.manifest, |
| 111 | notificationChannels, |
| 112 | }, |
| 113 | fileTypes: [...this.fileTypes.values()], |
| 114 | }); |
| 115 | } |
| 116 |
| 117 | createNotification(input: CreateNotificationInputInput): CreateNotificationInput { |
| 118 | return createNotificationInputSchema.parse(input); |
| 119 | } |
| 120 |
| 121 | createAmbientEvents(input: EmitAmbientEventsInputInput): EmitAmbientEventsInput { |
| 122 | return this.ambient.emit(input); |
| 123 | } |
| 124 | } |
| 125 |