// The ports the notes module's use cases are written against, and the one it adds: the feature flags. // // The audit and usage sinks and the scope of an event delivery are the kernel's own tokens // (`FILES_AUDIT`, `FILES_USAGE`, `FILES_SCOPE`): the worker binds them once for every module, so a // module that audits and meters needs no binding of its own and no line in the worker. import { type Container, type TenantScope, token } from "@conusai-kit/core" import type { DataSource } from "@conusai-kit/data" import type { FilesDeps } from "@conusai-kit/files" import { ATTACHMENTS_FLAG, NOTES_FLAG_DEFAULTS } from "../contract/index.js" /** A project scope: the only level a note can live at. */ export type NoteScope = TenantScope & { workspaceId: string; projectId: string } export interface NotesDeps { readonly data: DataSource /** The files module's ports: an attachment is one of its files. */ readonly files: FilesDeps readonly flags: NotesFlags } /** What a flag service answers for the project a call runs in. */ export interface NotesFlags { enabled(flag: keyof typeof NOTES_FLAG_DEFAULTS, scope: NoteScope): boolean | Promise } /** * Bound by an app that evaluates flags per organization, project or user (the platform's flag * service, through `@conusai-sdk/node-sdk/flags`). With nothing bound, a flag is its manifest default. */ export const NOTES_FLAGS = token("notes.flags") export const defaultFlags: NotesFlags = { enabled: (flag) => NOTES_FLAG_DEFAULTS[flag] } export const flagsOf = (container: Container): NotesFlags => container.has(NOTES_FLAGS) ? container.resolve(NOTES_FLAGS) : defaultFlags export const attachmentsEnabled = async (deps: NotesDeps, scope: NoteScope): Promise => deps.flags.enabled(ATTACHMENTS_FLAG, scope)