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 | type ColineAppManifest, |
| 7 | type ColineAppManifestInput, |
| 8 | type ColineFileTypeDefinition, |
| 9 | type ColineFileTypeDefinitionInput, |
| 10 | type ColineAppRegistrationPayload, |
| 11 | type CreateNotificationInput, |
| 12 | type CreateNotificationInputInput, |
| 13 | type NotificationChannelDefinition, |
| 14 | type NotificationChannelDefinitionInput, |
| 15 | notificationChannelDefinitionSchema, |
| 16 | } from "./manifest"; |
| 17 |
| 18 | type UnknownPayload = Record<string, unknown>; |
| 19 |
| 20 | export interface HomeRenderContext extends UnknownPayload {} |
| 21 | export interface FileRenderContext extends UnknownPayload { |
| 22 | fileId?: string; |
| 23 | } |
| 24 | export interface IndexSyncContext extends UnknownPayload { |
| 25 | workspaceId?: string; |
| 26 | } |
| 27 |
| 28 | export type HomeRenderHandler = (context: HomeRenderContext) => unknown | Promise<unknown>; |
| 29 | export type FileRenderHandler = (context: FileRenderContext) => unknown | Promise<unknown>; |
| 30 | export type IndexSyncHandler = (context: IndexSyncContext) => unknown | Promise<unknown>; |
| 31 |
| 32 | export interface ColineAppDefinition { |
| 33 | manifest: ColineAppManifest; |
| 34 | fileTypes: ColineFileTypeDefinition[]; |
| 35 | notificationChannels: NotificationChannelDefinition[]; |
| 36 | handlers: { |
| 37 | homeRender?: HomeRenderHandler; |
| 38 | fileRender?: FileRenderHandler; |
| 39 | indexSync?: IndexSyncHandler; |
| 40 | }; |
| 41 | } |
| 42 |
| 43 | export class ColineApp { |
| 44 | readonly manifest: ColineAppManifest; |
| 45 | private readonly fileTypes = new Map<string, ColineFileTypeDefinition>(); |
| 46 | private readonly notificationChannels = new Map<string, NotificationChannelDefinition>(); |
| 47 | private readonly handlers: ColineAppDefinition["handlers"] = {}; |
| 48 |
| 49 | constructor(manifest: ColineAppManifestInput) { |
| 50 | this.manifest = colineAppManifestSchema.parse(manifest); |
| 51 | } |
| 52 |
| 53 | defineFileType(fileType: ColineFileTypeDefinitionInput): this { |
| 54 | const parsed = colineFileTypeSchema.parse(fileType); |
| 55 | this.fileTypes.set(parsed.typeKey, parsed); |
| 56 | return this; |
| 57 | } |
| 58 |
| 59 | defineNotificationChannel(channel: NotificationChannelDefinitionInput): this { |
| 60 | const parsed = notificationChannelDefinitionSchema.parse(channel); |
| 61 | this.notificationChannels.set(parsed.key, parsed); |
| 62 | return this; |
| 63 | } |
| 64 |
| 65 | onHomeRender(handler: HomeRenderHandler): this { |
| 66 | this.handlers.homeRender = handler; |
| 67 | return this; |
| 68 | } |
| 69 |
| 70 | onFileRender(handler: FileRenderHandler): this { |
| 71 | this.handlers.fileRender = handler; |
| 72 | return this; |
| 73 | } |
| 74 |
| 75 | onIndexSync(handler: IndexSyncHandler): this { |
| 76 | this.handlers.indexSync = handler; |
| 77 | return this; |
| 78 | } |
| 79 |
| 80 | getDefinition(): ColineAppDefinition { |
| 81 | const notificationChannels = [...this.notificationChannels.values()]; |
| 82 |
| 83 | return { |
| 84 | manifest: { |
| 85 | ...this.manifest, |
| 86 | notificationChannels, |
| 87 | }, |
| 88 | fileTypes: [...this.fileTypes.values()], |
| 89 | notificationChannels, |
| 90 | handlers: { ...this.handlers }, |
| 91 | }; |
| 92 | } |
| 93 |
| 94 | getRegistrationPayload(version: string): ColineAppRegistrationPayload { |
| 95 | const notificationChannels = [...this.notificationChannels.values()]; |
| 96 |
| 97 | return colineAppRegistrationPayloadSchema.parse({ |
| 98 | version, |
| 99 | manifest: { |
| 100 | ...this.manifest, |
| 101 | notificationChannels, |
| 102 | }, |
| 103 | fileTypes: [...this.fileTypes.values()], |
| 104 | }); |
| 105 | } |
| 106 |
| 107 | createNotification(input: CreateNotificationInputInput): CreateNotificationInput { |
| 108 | return createNotificationInputSchema.parse(input); |
| 109 | } |
| 110 | } |
| 111 |