// The notes module's manifest (spec §4.1, §16): the one place it registers anything. // // The example module of the template and the pattern a product's own follows. It is small on // purpose and uses every seam a module has: // // - a contract, a core of pure use cases and a Kysely-bound repository (entities.ts, migrations/); // - the kernel's files module for attachments: the browser uploads through the files procedures // (`files.file.beginUpload`, `putPart`, `completeUpload`; the platform's Blob store; one audit // event and one usage fact per upload, recorded by the files module) and links the file with // `notes.attachment.add`; // - audit events and a usage meter that hang off the module's own outbox events, exactly once; // - a feature flag (`notes.attachments`), evaluated through a port; // - messages in English and Lithuanian, a navigation entry and the pages (`ui/pages.tsx`), which // the web shell mounts from `modules/index.ts` with no route file of its own. import { defineModule, subscribe } from "@conusai-kit/core" import { repositoryBindings } from "@conusai-kit/data" import { fileDeleted } from "@conusai-kit/files" import { NOTE_PROCEDURES } from "./adapters/procedures.js" import { ATTACHMENT_ADDED, ATTACHMENT_REMOVED, attachmentAdded, attachmentRemoved, NOTE_CREATED, NOTE_DELETED, NOTE_UPDATED, NOTES_CREATED_METER, NOTES_ENTITIES, NOTES_EVENTS, NOTES_FLAG_DEFAULTS, noteCreated, noteDeleted, noteUpdated, } from "./contract/index.js" import { onAttachmentAdded, onAttachmentRemoved, onFileDeleted, onNoteCreated, onNoteDeleted, onNoteUpdated, } from "./core/subscribers.js" import { NOTES_GUIDES } from "./guides/index.js" // kit:guides import { en, lt } from "./i18n/index.js" const tables = repositoryBindings(...NOTES_ENTITIES) export const notesModule = defineModule({ id: "notes", version: "0.1.0", kit: "^0.1.0", requires: ["tenancy", "files"], permissions: { "notes.note.read": "viewer", "notes.note.write": "editor", "notes.note.delete": "editor", "notes.attachment.write": "editor", }, procedures: NOTE_PROCEDURES, repositories: { postgres: tables, mariadb: tables, mongodb: tables, convex: tables }, // Forward-only migrations, one numbered file per change per dialect (spec §5.3: the dialect // differences are explicit, not generated), run by the migrate job after the app's own. migrations: { postgres: "migrations", mariadb: "adapters/kysely/mysql/migrations", mongodb: "adapters/mongo/migrations", }, events: { publishes: NOTES_EVENTS, subscribes: [ subscribe(noteCreated, onNoteCreated), subscribe(noteUpdated, onNoteUpdated), subscribe(noteDeleted, onNoteDeleted), subscribe(attachmentAdded, onAttachmentAdded), subscribe(attachmentRemoved, onAttachmentRemoved), // A deleted file takes its links with it. subscribe(fileDeleted, onFileDeleted), ], }, audit: [NOTE_CREATED, NOTE_UPDATED, NOTE_DELETED, ATTACHMENT_ADDED, ATTACHMENT_REMOVED], usage: { meters: [NOTES_CREATED_METER] }, flags: Object.fromEntries(Object.entries(NOTES_FLAG_DEFAULTS).map(([flag, value]) => [flag, { default: value }])), // The project-level entry the org home lists next to each project; `notes` is the segment the // web shell's module mount routes to `notesPages` (ui/pages.tsx). ui: { nav: [{ scope: "project", label: "notes.title", href: "notes", permission: "notes.note.read" }] }, // Both languages, as objects: kit-i18n merges them from the registry (AT-D23). i18n: { en, lt }, extends: [...NOTES_GUIDES], // kit:guides -- the code tour, checklist and survey of guides/ })