import { colineAppManifestSchema, colineAppRegistrationPayloadSchema, colineFileTypeSchema, createNotificationInputSchema, emitAmbientEventsInputSchema, type ColineAppManifest, type ColineAppManifestInput, type ColineFileTypeDefinition, type ColineFileTypeDefinitionInput, type ColineAppRegistrationPayload, type EmitAmbientEventsInput, type EmitAmbientEventsInputInput, type CreateNotificationInput, type CreateNotificationInputInput, type NotificationChannelDefinition, type NotificationChannelDefinitionInput, notificationChannelDefinitionSchema, } from "./manifest"; import type { FileRenderContext, FileRenderResult, HomeRenderContext, HomeRenderResult, IndexSyncContext, } from "./contexts"; export type HomeRenderHandler = ( context: HomeRenderContext, ) => HomeRenderResult | Promise; export type FileRenderHandler = ( context: FileRenderContext, ) => FileRenderResult | Promise; export type IndexSyncHandler = (context: IndexSyncContext) => unknown | Promise; export interface ColineAppDefinition { manifest: ColineAppManifest; fileTypes: ColineFileTypeDefinition[]; notificationChannels: NotificationChannelDefinition[]; handlers: { homeRender?: HomeRenderHandler; fileRender?: FileRenderHandler; indexSync?: IndexSyncHandler; }; } class ColineAmbientHelper { emit(input: EmitAmbientEventsInputInput): EmitAmbientEventsInput { return emitAmbientEventsInputSchema.parse(input); } } export class ColineApp { readonly manifest: ColineAppManifest; readonly ambient = new ColineAmbientHelper(); private readonly fileTypes = new Map(); private readonly notificationChannels = new Map(); private readonly handlers: ColineAppDefinition["handlers"] = {}; constructor(manifest: ColineAppManifestInput) { this.manifest = colineAppManifestSchema.parse(manifest); } defineFileType(fileType: ColineFileTypeDefinitionInput): this { const parsed = colineFileTypeSchema.parse(fileType); this.fileTypes.set(parsed.typeKey, parsed); return this; } defineNotificationChannel(channel: NotificationChannelDefinitionInput): this { const parsed = notificationChannelDefinitionSchema.parse(channel); this.notificationChannels.set(parsed.key, parsed); return this; } onHomeRender(handler: HomeRenderHandler): this { this.handlers.homeRender = handler; return this; } onFileRender(handler: FileRenderHandler): this { this.handlers.fileRender = handler; return this; } onIndexSync(handler: IndexSyncHandler): this { this.handlers.indexSync = handler; return this; } getDefinition(): ColineAppDefinition { const notificationChannels = [...this.notificationChannels.values()]; return { manifest: { ...this.manifest, notificationChannels, }, fileTypes: [...this.fileTypes.values()], notificationChannels, handlers: { ...this.handlers }, }; } getRegistrationPayload(version: string): ColineAppRegistrationPayload { const notificationChannels = [...this.notificationChannels.values()]; return colineAppRegistrationPayloadSchema.parse({ version, manifest: { ...this.manifest, notificationChannels, }, fileTypes: [...this.fileTypes.values()], }); } createNotification(input: CreateNotificationInputInput): CreateNotificationInput { return createNotificationInputSchema.parse(input); } createAmbientEvents(input: EmitAmbientEventsInputInput): EmitAmbientEventsInput { return this.ambient.emit(input); } }