@mdfn/server 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,8 +7,9 @@ authorization hooks, and a Web Standard router. The incoming
7
7
 
8
8
  Durable mode is the default and rejects database adapters without transaction
9
9
  and relational-constraint support. Create/update/restore/editorial writes
10
- validate both Markdown and the complete sidecar, run atomically, and support idempotency through the
11
- `Idempotency-Key` header or request body. Delete atomically removes the
10
+ validate both Markdown and the complete sidecar and run atomically. Update,
11
+ restore, and editorial writes support idempotency through the `Idempotency-Key`
12
+ header or request body; document creation does not. Delete atomically removes the
12
13
  document, revisions, receipts, and collaboration updates. Ephemeral mode must
13
14
  be selected explicitly and is intended only for memory-backed tests.
14
15
 
package/dist/index.cjs CHANGED
@@ -723,7 +723,7 @@ function createMdfnServer(config) {
723
723
  const service = createMdfnService(config);
724
724
  return { service, router: createMdfnRouter(config, service), schema: getSchema() };
725
725
  }
726
- var MDFN_SERVER_VERSION = "0.1.0";
726
+ var MDFN_SERVER_VERSION = "0.1.1";
727
727
  // Annotate the CommonJS export names for ESM import in node:
728
728
  0 && (module.exports = {
729
729
  MDFN_SERVER_SCHEMA_VERSION,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n createCommentThread,\n createEditor,\n createSuggestion,\n decideSuggestion,\n hashString,\n mapSidecar,\n replyToComment,\n resolveExtensions,\n setCommentResolved,\n transitionReview,\n validateMdfnSidecar,\n type MdfnExtension,\n type MdfnSidecar,\n type ReviewState,\n type SidecarAnchor,\n} from \"@mdfn/core\";\nimport { createMarkdownProjector, parseMarkdown, type MarkdownOptions } from \"@mdfn/markdown\";\nimport { wrapWithSchema, type Adapter, type TableSchema } from \"@superfunctions/db\";\nimport { createRouter, RouterError, type Router } from \"@superfunctions/http\";\n\nconst DOCUMENTS = \"mdfnDocuments\";\nconst VERSIONS = \"mdfnVersions\";\nconst RECEIPTS = \"mdfnReceipts\";\nconst COLLAB_UPDATES = \"mdfnCollaborationUpdates\";\nexport const MDFN_SERVER_SCHEMA_VERSION = 2;\n\nexport interface MdfnPrincipal { readonly id: string; readonly tenantId?: string; readonly roles?: readonly string[]; }\nexport type MdfnServerAction =\n | \"create\"\n | \"read\"\n | \"update\"\n | \"delete\"\n | \"history\"\n | \"history:restore\"\n | \"collaborate\"\n | \"compact-collaboration\"\n | \"comment:create\"\n | \"comment:reply\"\n | \"comment:resolve\"\n | \"suggestion:create\"\n | \"suggestion:decide\"\n | \"review:transition\";\n\nexport interface MdfnDocumentRecord {\n readonly id: string;\n /** Immutable identity for collaboration rows across delete/recreate cycles. */\n readonly collaborationGeneration: string;\n readonly ownerId: string;\n readonly tenantId?: string;\n readonly title?: string;\n readonly markdown: string;\n readonly sourceHash: string;\n readonly schemaHash: string;\n readonly sidecar?: MdfnSidecar;\n readonly version: number;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n}\n\nexport interface MdfnVersionRecord extends MdfnDocumentRecord { readonly documentId: string; readonly authorId: string; readonly changeSource: string; }\n\nexport type MdfnVersionSummary = Omit<MdfnVersionRecord, \"markdown\" | \"sidecar\">;\n\nexport interface MdfnVersionBatch {\n readonly versions: readonly MdfnVersionSummary[];\n readonly nextCursor?: string;\n}\n\nexport interface MdfnCollaborationUpdateBatch {\n readonly updates: readonly string[];\n /** Exact persisted update ids represented by `updates` and therefore safe to compact. */\n readonly includedUpdateIds: readonly string[];\n /** Opaque continuation for the next bounded batch, when more updates remain. */\n readonly nextCursor?: string;\n}\n\nexport interface MdfnServerConfig {\n readonly database: Adapter;\n readonly authorize: (action: MdfnServerAction, principal: MdfnPrincipal, document?: MdfnDocumentRecord) => boolean | Promise<boolean>;\n readonly resolvePrincipal?: (request: Request) => MdfnPrincipal | Promise<MdfnPrincipal>;\n readonly extensions?: readonly MdfnExtension[];\n readonly markdown?: MarkdownOptions;\n readonly basePath?: string;\n readonly createId?: () => string;\n /** Injectable lifecycle identity for deterministic hosts and tests. */\n readonly createCollaborationGeneration?: () => string;\n /** Injectable clock for deterministic hosts and tests. */\n readonly now?: () => Date;\n readonly maxCollaborationUpdateBytes?: number;\n readonly maxCollaborationBatchBytes?: number;\n readonly maxCollaborationBatchUpdates?: number;\n /** Maximum encoded request body accepted by JSON-writing routes. */\n readonly maxRequestBodyBytes?: number;\n /** Maximum UTF-8 bytes accepted for a persisted document title. */\n readonly maxTitleBytes?: number;\n /** Durable storage requires adapter transactions. Ephemeral is intended only for in-memory/test hosts. */\n readonly durability?: \"required\" | \"ephemeral\";\n}\n\nexport class MdfnServerError extends Error {\n constructor(readonly code: string, readonly status: number, message = code) { super(message); this.name = \"MdfnServerError\"; }\n}\n\nfunction configuredDocumentBytes(config: MdfnServerConfig): number {\n return config.markdown?.maxBytes ?? 2 * 1024 * 1024;\n}\n\nfunction configuredCollaborationUpdateBytes(config: MdfnServerConfig): number {\n if (config.maxCollaborationUpdateBytes !== undefined) return config.maxCollaborationUpdateBytes;\n const documentBytes = configuredDocumentBytes(config);\n const yjsOverhead = Math.max(64 * 1024, Math.ceil(documentBytes / 16));\n return 4 * Math.ceil((documentBytes + yjsOverhead) / 3);\n}\n\ninterface CollaborationCursor {\n readonly documentId: string;\n readonly key: string;\n}\n\nfunction collaborationCursorKey(previousKey?: string): string {\n const match = previousKey?.match(/^v2:(\\d{20})$/);\n if (previousKey?.startsWith(\"v2:\") && !match) throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 500);\n const sequence = (match ? BigInt(match[1]) : 0n) + 1n;\n const encoded = sequence.toString().padStart(20, \"0\");\n if (encoded.length > 20) throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_EXHAUSTED\", 500);\n return `v2:${encoded}`;\n}\n\nfunction isUniqueConflict(error: unknown): boolean {\n const value = error as { readonly code?: unknown; readonly message?: unknown; readonly cause?: unknown };\n const cause = value?.cause as { readonly code?: unknown; readonly message?: unknown } | undefined;\n return /(?:unique|duplicate|23505|p2002)/i.test([value?.code, value?.message, cause?.code, cause?.message].filter(Boolean).join(\" \"));\n}\n\nfunction encodeCollaborationCursor(documentId: string, key: string): string {\n return encodeURIComponent(JSON.stringify({ documentId, key }));\n}\n\nfunction decodeCollaborationCursor(cursor: string, documentId: string): string {\n try {\n const parsed = JSON.parse(decodeURIComponent(cursor)) as Partial<CollaborationCursor>;\n if (parsed.documentId !== documentId || typeof parsed.key !== \"string\" || !parsed.key) {\n throw new Error(\"invalid cursor\");\n }\n return parsed.key;\n } catch {\n throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 422);\n }\n}\n\nexport function getSchema(): { version: number; schemas: TableSchema[] } {\n const date = { type: \"date\" as const, required: true, dateValueType: \"date\" as const };\n return { version: MDFN_SERVER_SCHEMA_VERSION, schemas: [\n { modelName: DOCUMENTS, fields: { id: { type: \"string\", required: true }, collaborationGeneration: { type: \"string\", required: true }, ownerId: { type: \"string\", required: true }, tenantId: { type: \"string\" }, title: { type: \"string\" }, markdown: { type: \"string\", required: true }, sourceHash: { type: \"string\", required: true }, schemaHash: { type: \"string\", required: true }, sidecar: { type: \"json\" }, version: { type: \"number\", required: true }, createdAt: date, updatedAt: date }, indexes: [{ name: \"idx_mdfn_documents_owner\", fields: [\"ownerId\"] }, { name: \"idx_mdfn_documents_tenant\", fields: [\"tenantId\"] }] },\n { modelName: VERSIONS, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true }, collaborationGeneration: { type: \"string\", required: true }, ownerId: { type: \"string\", required: true }, tenantId: { type: \"string\" }, title: { type: \"string\" }, markdown: { type: \"string\", required: true }, sourceHash: { type: \"string\", required: true }, schemaHash: { type: \"string\", required: true }, sidecar: { type: \"json\" }, version: { type: \"number\", required: true }, authorId: { type: \"string\", required: true }, changeSource: { type: \"string\", required: true }, createdAt: date, updatedAt: date }, indexes: [{ name: \"idx_mdfn_versions_document_version\", fields: [\"documentId\", \"version\"], unique: true }] },\n { modelName: RECEIPTS, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true }, idempotencyKey: { type: \"string\", required: true }, operation: { type: \"string\", required: true }, payloadHash: { type: \"string\", required: true }, result: { type: \"json\", required: true }, createdAt: date }, indexes: [{ name: \"idx_mdfn_receipts_key\", fields: [\"documentId\", \"idempotencyKey\"], unique: true }] },\n { modelName: COLLAB_UPDATES, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true, references: { model: DOCUMENTS, field: \"id\", onDelete: \"cascade\" } }, documentGeneration: { type: \"string\", required: true }, authorId: { type: \"string\", required: true }, update: { type: \"string\", required: true }, cursorKey: { type: \"string\", required: true }, createdAt: date }, indexes: [{ name: \"idx_mdfn_collab_generation_cursor\", fields: [\"documentId\", \"documentGeneration\", \"cursorKey\"], unique: true }] },\n ] };\n}\n\nexport interface MdfnService {\n create(principal: MdfnPrincipal, input: { readonly id?: string; readonly title?: string; readonly markdown: string; readonly sidecar?: MdfnSidecar }): Promise<MdfnDocumentRecord>;\n read(principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord>;\n list(principal: MdfnPrincipal, options?: { readonly limit?: number; readonly offset?: number }): Promise<readonly MdfnDocumentRecord[]>;\n update(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly markdown?: string; readonly title?: string; readonly sidecar?: MdfnSidecar; readonly changeSource?: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n delete(principal: MdfnPrincipal, id: string): Promise<void>;\n versions(\n principal: MdfnPrincipal,\n id: string,\n options?: { readonly cursor?: string; readonly limit?: number },\n ): Promise<MdfnVersionBatch>;\n version(principal: MdfnPrincipal, id: string, version: number): Promise<MdfnVersionRecord>;\n restoreVersion(principal: MdfnPrincipal, id: string, input: { readonly version: number; readonly expectedVersion: number; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n createComment(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly anchor: SidecarAnchor; readonly body: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n replyComment(principal: MdfnPrincipal, id: string, threadId: string, input: { readonly expectedVersion: number; readonly body: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n resolveComment(principal: MdfnPrincipal, id: string, threadId: string, input: { readonly expectedVersion: number; readonly resolved: boolean; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n createSuggestion(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly anchor: SidecarAnchor; readonly replacement: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n decideSuggestion(principal: MdfnPrincipal, id: string, suggestionId: string, input: { readonly expectedVersion: number; readonly decision: \"accepted\" | \"rejected\"; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n transitionReview(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly state: ReviewState; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n appendCollaborationUpdate(principal: MdfnPrincipal, id: string, update: string): Promise<string>;\n collaborationUpdates(\n principal: MdfnPrincipal,\n id: string,\n options?: { readonly cursor?: string; readonly limit?: number },\n ): Promise<MdfnCollaborationUpdateBatch>;\n compactCollaborationUpdates(principal: MdfnPrincipal, id: string, snapshot: string, includedUpdateIds: readonly string[]): Promise<string>;\n}\n\nasync function allowed(config: MdfnServerConfig, action: MdfnServerAction, principal: MdfnPrincipal, document?: MdfnDocumentRecord): Promise<void> {\n if (!(await config.authorize(action, principal, document))) throw new MdfnServerError(\"MDFN_FORBIDDEN\", 403);\n}\n\nfunction whereId(id: string) { return [{ field: \"id\", operator: \"eq\" as const, value: id }]; }\n\nexport function createMdfnService(config: MdfnServerConfig): MdfnService {\n const database = wrapWithSchema(config.database, getSchema());\n if ((config.durability ?? \"required\") === \"required\") {\n if (!database.capabilities.transactions.supported) {\n throw new MdfnServerError(\"MDFN_TRANSACTIONAL_DATABASE_REQUIRED\", 500);\n }\n if (!database.capabilities.schema.constraints) {\n throw new MdfnServerError(\"MDFN_RELATIONAL_CONSTRAINTS_REQUIRED\", 500);\n }\n }\n const registry = resolveExtensions(config.extensions ?? []);\n const markdownOptions: MarkdownOptions = { ...config.markdown, extensions: registry };\n const createId = config.createId ?? (() => crypto.randomUUID());\n const createCollaborationGeneration = config.createCollaborationGeneration ?? (() => crypto.randomUUID());\n const now = config.now ?? (() => new Date());\n const collaborationUpdateBytes = configuredCollaborationUpdateBytes(config);\n const collaborationBatchBytes = Math.max(\n collaborationUpdateBytes,\n config.maxCollaborationBatchBytes ?? collaborationUpdateBytes * 4,\n );\n const collaborationBatchUpdates = Math.min(1_000, Math.max(1, config.maxCollaborationBatchUpdates ?? 100));\n const parse = (source: string, sidecar?: MdfnSidecar): void => {\n try {\n parseMarkdown(source, markdownOptions);\n validateMdfnSidecar(sidecar, { markdownLength: source.length });\n } catch {\n throw new MdfnServerError(\"MDFN_DOCUMENT_INVALID\", 422);\n }\n };\n type Storage = Pick<Adapter, \"create\" | \"findOne\" | \"findMany\" | \"update\" | \"delete\" | \"deleteMany\">;\n const loadFrom = async (storage: Pick<Adapter, \"findOne\">, id: string): Promise<MdfnDocumentRecord> => {\n const result = await storage.findOne<MdfnDocumentRecord>({ model: DOCUMENTS, where: whereId(id) });\n if (!result) throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n return result;\n };\n const load = (id: string): Promise<MdfnDocumentRecord> => loadFrom(database, id);\n const loadScopedFrom = async (storage: Pick<Adapter, \"findOne\">, principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord> => {\n const document = await loadFrom(storage, id);\n const inScope = principal.tenantId\n ? document.tenantId === principal.tenantId\n : document.tenantId === undefined && document.ownerId === principal.id;\n if (!inScope) throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n return document;\n };\n const loadScoped = (principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord> => loadScopedFrom(database, principal, id);\n const revision = (document: MdfnDocumentRecord, authorId: string, changeSource: string): MdfnVersionRecord => ({ ...document, id: `${document.id}:${document.version}`, documentId: document.id, authorId, changeSource });\n const withStorage = <T>(callback: (storage: Storage) => Promise<T>): Promise<T> => database.capabilities.transactions.supported\n ? database.transaction((transaction) => callback(transaction))\n : callback(database);\n const collaborationWriteTails = new Map<string, Promise<void>>();\n const serializeCollaborationWrite = async <T>(documentId: string, callback: () => Promise<T>): Promise<T> => {\n const previous = collaborationWriteTails.get(documentId) ?? Promise.resolve();\n let release!: () => void;\n const gate = new Promise<void>((resolve) => { release = resolve; });\n const tail = previous.then(() => gate);\n collaborationWriteTails.set(documentId, tail);\n await previous;\n try {\n return await callback();\n } finally {\n release();\n if (collaborationWriteTails.get(documentId) === tail) collaborationWriteTails.delete(documentId);\n }\n };\n const withCollaborationWrite = <T>(\n principal: MdfnPrincipal,\n documentId: string,\n action: \"collaborate\" | \"compact-collaboration\",\n callback: (storage: Storage, cursorKey: string, documentGeneration: string) => Promise<T>,\n ): Promise<T> => (\n serializeCollaborationWrite(documentId, async () => {\n const authorizedDocument = await loadScoped(principal, documentId);\n await allowed(config, action, principal, authorizedDocument);\n const documentGeneration = authorizedDocument.collaborationGeneration;\n let lastConflict: unknown;\n for (let attempt = 0; attempt < 5; attempt += 1) {\n try {\n const result = await withStorage(async (storage) => {\n const storedDocument = await loadScopedFrom(storage, principal, documentId);\n if (storedDocument.collaborationGeneration !== documentGeneration) {\n throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n }\n const latest = await storage.findMany<{ readonly cursorKey: string }>({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: documentId },\n { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration },\n ],\n select: [\"cursorKey\"],\n orderBy: [{ field: \"cursorKey\", direction: \"desc\" }],\n limit: 1,\n });\n return callback(storage, collaborationCursorKey(latest[0]?.cursorKey), documentGeneration);\n });\n let latestDocument: MdfnDocumentRecord | undefined;\n try {\n latestDocument = await loadScoped(principal, documentId);\n } catch (error) {\n if (!(error instanceof MdfnServerError && error.code === \"MDFN_DOCUMENT_NOT_FOUND\")) throw error;\n }\n if (latestDocument?.collaborationGeneration !== documentGeneration) {\n await database.deleteMany({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: documentId },\n { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration },\n ],\n });\n throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n }\n return result;\n } catch (error) {\n if (!isUniqueConflict(error)) throw error;\n lastConflict = error;\n }\n }\n throw lastConflict;\n })\n );\n let service!: MdfnService;\n const editorialActor = (principal: MdfnPrincipal) => ({ id: principal.id, createId, now: () => now().toISOString() });\n const maxTitleBytes = config.maxTitleBytes ?? 512;\n if (!Number.isSafeInteger(maxTitleBytes) || maxTitleBytes < 1) {\n throw new MdfnServerError(\"MDFN_TITLE_LIMIT_INVALID\", 500);\n }\n const validateTitle = (title: string | undefined): void => {\n if (title !== undefined && new TextEncoder().encode(title).byteLength > maxTitleBytes) {\n throw new MdfnServerError(\"MDFN_TITLE_TOO_LARGE\", 413);\n }\n };\n type UpdateInput = Parameters<MdfnService[\"update\"]>[2];\n type RestoreSnapshot = Pick<MdfnVersionRecord, \"title\" | \"markdown\" | \"sidecar\">;\n interface WriteUpdateOptions {\n readonly trustedEditorial?: boolean;\n readonly authorizationAction?: MdfnServerAction;\n readonly restoreSnapshot?: RestoreSnapshot;\n readonly idempotencyOperation?: string;\n readonly idempotencyPayload?: unknown;\n }\n const canonicalJson = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(canonicalJson);\n if (value === null || typeof value !== \"object\") return value;\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)\n .map(([key, entry]) => [key, canonicalJson(entry)]),\n );\n };\n const hashValue = (value: unknown): string => hashString(JSON.stringify(canonicalJson(value)));\n const protectedSidecar = (value: MdfnSidecar | undefined): string => JSON.stringify(canonicalJson({\n comments: value?.comments ?? [],\n suggestions: value?.suggestions ?? [],\n reviewState: value?.reviewState ?? \"draft\",\n audit: value?.audit ?? [],\n }));\n const coarseChangedRanges = (before: string, after: string, offset: number): Array<{ from: number; to: number; insertedLength: number }> => {\n const ranges: Array<{ from: number; to: number; insertedLength: number }> = [];\n const syncLength = 16;\n const initialLookahead = 2_048;\n let remainingSearchWork = 65_536;\n let left = 0;\n let right = 0;\n let position = offset;\n while (left < before.length || right < after.length) {\n while (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) {\n left += 1;\n right += 1;\n position += 1;\n }\n if (left === before.length && right === after.length) break;\n const from = position;\n let match: { left: number; right: number; cost: number } | undefined;\n let lookahead = initialLookahead;\n const beforeAnchors = new Map<string, number>();\n const afterAnchors = new Map<string, number>();\n let beforeScannedTo = left - 1;\n let afterScannedTo = right - 1;\n while (!match) {\n const beforeLimit = Math.min(before.length - syncLength, left + lookahead);\n for (let candidate = beforeScannedTo + 1; candidate <= beforeLimit; candidate += 1) {\n if (remainingSearchWork === 0) break;\n remainingSearchWork -= 1;\n const key = before.slice(candidate, candidate + syncLength);\n if (!beforeAnchors.has(key)) beforeAnchors.set(key, candidate);\n const matchingRight = afterAnchors.get(key);\n if (matchingRight !== undefined) {\n const cost = candidate - left + matchingRight - right;\n if (!match || cost < match.cost) match = { left: candidate, right: matchingRight, cost };\n }\n beforeScannedTo = candidate;\n }\n const afterLimit = Math.min(after.length - syncLength, right + lookahead);\n for (let candidate = afterScannedTo + 1; candidate <= afterLimit; candidate += 1) {\n if (remainingSearchWork === 0) break;\n remainingSearchWork -= 1;\n const key = after.slice(candidate, candidate + syncLength);\n if (!afterAnchors.has(key)) afterAnchors.set(key, candidate);\n const matchingLeft = beforeAnchors.get(key);\n if (matchingLeft !== undefined) {\n const cost = matchingLeft - left + candidate - right;\n if (!match || cost < match.cost) match = { left: matchingLeft, right: candidate, cost };\n }\n afterScannedTo = candidate;\n }\n const searchedAllBefore = before.length - left < syncLength || beforeScannedTo >= before.length - syncLength;\n const searchedAllAfter = after.length - right < syncLength || afterScannedTo >= after.length - syncLength;\n if (match || remainingSearchWork === 0 || (searchedAllBefore && searchedAllAfter)) break;\n lookahead = Math.min(\n Math.max(before.length - left, after.length - right),\n lookahead * 2,\n );\n }\n if (!match || match.cost === 0) {\n ranges.push({ from, to: from + before.length - left, insertedLength: after.length - right });\n break;\n }\n const removed = match.left - left;\n const insertedLength = match.right - right;\n ranges.push({ from, to: from + removed, insertedLength });\n left = match.left;\n right = match.right;\n position += insertedLength;\n }\n return ranges;\n };\n const changedRanges = (previous: string, next: string): Array<{ from: number; to: number; insertedLength: number }> => {\n if (previous === next) return [];\n let prefix = 0;\n while (prefix < previous.length && prefix < next.length && previous.charCodeAt(prefix) === next.charCodeAt(prefix)) prefix += 1;\n let previousEnd = previous.length;\n let nextEnd = next.length;\n while (previousEnd > prefix && nextEnd > prefix && previous.charCodeAt(previousEnd - 1) === next.charCodeAt(nextEnd - 1)) { previousEnd -= 1; nextEnd -= 1; }\n const before = previous.slice(prefix, previousEnd);\n const after = next.slice(prefix, nextEnd);\n if (before.length * after.length > 250_000) return coarseChangedRanges(before, after, prefix);\n const width = after.length + 1;\n const lcs = new Uint32Array((before.length + 1) * width);\n for (let left = before.length - 1; left >= 0; left -= 1) {\n for (let right = after.length - 1; right >= 0; right -= 1) {\n const index = left * width + right;\n lcs[index] = before.charCodeAt(left) === after.charCodeAt(right)\n ? lcs[(left + 1) * width + right + 1] + 1\n : Math.max(lcs[(left + 1) * width + right], lcs[index + 1]);\n }\n }\n const ranges: Array<{ from: number; to: number; insertedLength: number }> = [];\n let left = 0;\n let right = 0;\n let position = prefix;\n while (left < before.length || right < after.length) {\n if (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) {\n left += 1; right += 1; position += 1; continue;\n }\n const from = position;\n let removed = 0;\n let insertedLength = 0;\n while (left < before.length || right < after.length) {\n if (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) break;\n if (right < after.length && (left === before.length || lcs[left * width + right + 1] >= lcs[(left + 1) * width + right])) {\n right += 1; insertedLength += 1;\n } else {\n left += 1; removed += 1;\n }\n }\n ranges.push({ from, to: from + removed, insertedLength });\n position += insertedLength;\n }\n return ranges;\n };\n const mapForMarkdownChange = (sidecar: MdfnSidecar | undefined, previous: string, next: string): MdfnSidecar | undefined => {\n if (!sidecar || previous === next) return sidecar;\n return mapSidecar(sidecar, changedRanges(previous, next));\n };\n interface Receipt { readonly operation: string; readonly payloadHash: string; readonly result: MdfnDocumentRecord; }\n const replayReceipt = async (storage: Storage, documentId: string, idempotencyKey: string, operation: string, payloadHash: string): Promise<MdfnDocumentRecord | undefined> => {\n const receipt = await storage.findOne<Receipt>({ model: RECEIPTS, where: [{ field: \"documentId\", operator: \"eq\", value: documentId }, { field: \"idempotencyKey\", operator: \"eq\", value: idempotencyKey }] });\n if (!receipt) return undefined;\n if (receipt.operation !== operation || receipt.payloadHash !== payloadHash) throw new MdfnServerError(\"MDFN_IDEMPOTENCY_KEY_REUSED\", 409);\n return receipt.result;\n };\n const writeUpdate = async (principal: MdfnPrincipal, id: string, input: UpdateInput, options: WriteUpdateOptions = {}): Promise<MdfnDocumentRecord> => {\n const current = await loadScoped(principal, id);\n await allowed(config, options.authorizationAction ?? \"update\", principal, current);\n const operation = options.idempotencyOperation ?? \"document:update\";\n const payloadHash = hashValue(options.idempotencyPayload ?? {\n ...input,\n idempotencyKey: undefined,\n restoreSnapshot: options.restoreSnapshot,\n });\n if (input.idempotencyKey) {\n const replay = await replayReceipt(database, id, input.idempotencyKey, operation, payloadHash);\n if (replay) return replay;\n }\n if (current.version !== input.expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n const markdown = options.restoreSnapshot?.markdown ?? input.markdown ?? current.markdown;\n if (!options.trustedEditorial && input.sidecar && protectedSidecar(input.sidecar) !== protectedSidecar(current.sidecar)) {\n throw new MdfnServerError(\"MDFN_EDITORIAL_MUTATION_FORBIDDEN\", 403);\n }\n const mappedSidecar = mapForMarkdownChange(current.sidecar, current.markdown, markdown);\n const sidecar = options.restoreSnapshot\n ? options.restoreSnapshot.sidecar\n : options.trustedEditorial\n ? input.sidecar ?? mappedSidecar\n : input.sidecar\n ? {\n ...input.sidecar,\n comments: mappedSidecar?.comments,\n suggestions: mappedSidecar?.suggestions,\n reviewState: mappedSidecar?.reviewState,\n audit: mappedSidecar?.audit,\n }\n : mappedSidecar;\n parse(markdown, sidecar);\n const title = options.restoreSnapshot ? options.restoreSnapshot.title : input.title ?? current.title;\n validateTitle(title);\n const next: MdfnDocumentRecord = { ...current, title, markdown, sourceHash: hashString(markdown), schemaHash: registry.schemaHash, sidecar, version: current.version + 1, updatedAt: now() };\n return withStorage(async (storage) => {\n if (input.idempotencyKey) {\n const replay = await replayReceipt(storage, id, input.idempotencyKey, operation, payloadHash);\n if (replay) return replay;\n }\n const latest = await storage.findOne<MdfnDocumentRecord>({ model: DOCUMENTS, where: whereId(id) });\n if (!latest || latest.version !== input.expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n const updated = await storage.update<MdfnDocumentRecord>({ model: DOCUMENTS, where: [{ field: \"id\", operator: \"eq\", value: id }, { field: \"version\", operator: \"eq\", value: input.expectedVersion }], data: next });\n await storage.create({ model: VERSIONS, data: revision(updated, principal.id, input.changeSource ?? \"update\") });\n if (input.idempotencyKey) await storage.create({ model: RECEIPTS, data: { id: createId(), documentId: id, idempotencyKey: input.idempotencyKey, operation, payloadHash, result: updated, createdAt: now() } });\n return updated;\n });\n };\n const mutateEditorial = async (\n principal: MdfnPrincipal,\n id: string,\n expectedVersion: number,\n authorizationAction: MdfnServerAction,\n changeSource: string,\n idempotencyKey: string | undefined,\n idempotencyPayload: unknown,\n mutate: (document: MdfnDocumentRecord) => { readonly markdown?: string; readonly sidecar: MdfnSidecar },\n ): Promise<MdfnDocumentRecord> => {\n const current = await loadScoped(principal, id);\n await allowed(config, authorizationAction, principal, current);\n if (idempotencyKey) {\n const replay = await replayReceipt(database, id, idempotencyKey, changeSource, hashValue(idempotencyPayload));\n if (replay) return replay;\n }\n if (current.version !== expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n try {\n const next = mutate(current);\n return writeUpdate(principal, id, { expectedVersion, markdown: next.markdown, sidecar: next.sidecar, changeSource, idempotencyKey }, { trustedEditorial: true, authorizationAction, idempotencyOperation: changeSource, idempotencyPayload });\n } catch (error) {\n if (error instanceof MdfnServerError) throw error;\n throw new MdfnServerError(\"MDFN_EDITORIAL_INVALID\", 422);\n }\n };\n service = {\n async create(principal, input) {\n await allowed(config, \"create\", principal);\n parse(input.markdown, input.sidecar);\n validateTitle(input.title);\n if (input.id !== undefined && (typeof input.id !== \"string\" || input.id.trim().length === 0)) {\n throw new MdfnServerError(\"MDFN_DOCUMENT_ID_INVALID\", 422);\n }\n if (input.sidecar && protectedSidecar(input.sidecar) !== protectedSidecar(undefined)) {\n throw new MdfnServerError(\"MDFN_EDITORIAL_MUTATION_FORBIDDEN\", 403);\n }\n const createdAt = now();\n const collaborationGeneration = createCollaborationGeneration();\n if (typeof collaborationGeneration !== \"string\" || collaborationGeneration.length === 0) {\n throw new MdfnServerError(\"MDFN_COLLAB_GENERATION_INVALID\", 500);\n }\n const document: MdfnDocumentRecord = { id: input.id ?? createId(), collaborationGeneration, ownerId: principal.id, tenantId: principal.tenantId, title: input.title, markdown: input.markdown, sourceHash: hashString(input.markdown), schemaHash: registry.schemaHash, sidecar: input.sidecar, version: 1, createdAt, updatedAt: createdAt };\n return withStorage(async (storage) => {\n const created = await storage.create<MdfnDocumentRecord>({ model: DOCUMENTS, data: document });\n await storage.create({ model: VERSIONS, data: revision(created, principal.id, \"create\") });\n return created;\n });\n },\n async read(principal, id) { const document = await loadScoped(principal, id); await allowed(config, \"read\", principal, document); return document; },\n async list(principal, options = {}) {\n await allowed(config, \"read\", principal);\n const where = principal.tenantId ? [{ field: \"tenantId\", operator: \"eq\" as const, value: principal.tenantId }] : [{ field: \"ownerId\", operator: \"eq\" as const, value: principal.id }];\n const offset = Math.max(0, options.offset ?? 0);\n const limit = Math.min(100, Math.max(1, options.limit ?? 50));\n const pageSize = Math.max(25, limit);\n const visible: MdfnDocumentRecord[] = [];\n let databaseOffset = 0;\n let authorizedOffset = 0;\n while (visible.length < limit) {\n const candidates = await database.findMany<MdfnDocumentRecord>({\n model: DOCUMENTS,\n where,\n orderBy: [{ field: \"updatedAt\", direction: \"desc\" }, { field: \"id\", direction: \"desc\" }],\n limit: pageSize,\n offset: databaseOffset,\n });\n databaseOffset += candidates.length;\n for (const document of candidates) {\n if (!principal.tenantId && document.tenantId !== undefined && document.tenantId !== null) continue;\n if (!(await config.authorize(\"read\", principal, document))) continue;\n if (authorizedOffset < offset) {\n authorizedOffset += 1;\n continue;\n }\n visible.push(document);\n if (visible.length === limit) break;\n }\n if (candidates.length < pageSize) break;\n }\n return visible;\n },\n async update(principal, id, input) { return writeUpdate(principal, id, input); },\n async delete(principal, id) {\n await serializeCollaborationWrite(id, async () => {\n const current = await loadScoped(principal, id);\n await allowed(config, \"delete\", principal, current);\n await withStorage(async (storage) => {\n const documentWhere = [{ field: \"documentId\", operator: \"eq\" as const, value: id }];\n await storage.deleteMany({ model: COLLAB_UPDATES, where: documentWhere });\n await storage.deleteMany({ model: RECEIPTS, where: documentWhere });\n await storage.deleteMany({ model: VERSIONS, where: documentWhere });\n await storage.delete({ model: DOCUMENTS, where: whereId(id) });\n });\n });\n },\n async versions(principal, id, options = {}) {\n const document = await loadScoped(principal, id);\n await allowed(config, \"history\", principal, document);\n const cursor = options.cursor === undefined ? undefined : Number(options.cursor);\n const requestedLimit = options.limit ?? 50;\n if ((cursor !== undefined && (!Number.isSafeInteger(cursor) || cursor < 1)) ||\n !Number.isSafeInteger(requestedLimit) || requestedLimit < 1) {\n throw new MdfnServerError(\"MDFN_VERSION_CURSOR_INVALID\", 422);\n }\n const limit = Math.min(100, requestedLimit);\n const where = [\n { field: \"documentId\", operator: \"eq\" as const, value: id },\n ...(cursor === undefined ? [] : [{ field: \"version\", operator: \"lt\" as const, value: cursor }]),\n ];\n const rows = await database.findMany<MdfnVersionSummary>({\n model: VERSIONS,\n where,\n select: [\n \"id\", \"documentId\", \"collaborationGeneration\", \"ownerId\", \"tenantId\", \"title\", \"sourceHash\", \"schemaHash\",\n \"version\", \"authorId\", \"changeSource\", \"createdAt\", \"updatedAt\",\n ],\n orderBy: [{ field: \"version\", direction: \"desc\" }],\n limit: limit + 1,\n });\n const versions = rows.slice(0, limit);\n return {\n versions,\n ...(rows.length > limit ? { nextCursor: String(versions.at(-1)!.version) } : {}),\n };\n },\n async version(principal, id, version) { const document = await loadScoped(principal, id); await allowed(config, \"history\", principal, document); const result = await database.findOne<MdfnVersionRecord>({ model: VERSIONS, where: [{ field: \"documentId\", operator: \"eq\", value: id }, { field: \"version\", operator: \"eq\", value: version }] }); if (!result) throw new MdfnServerError(\"MDFN_VERSION_NOT_FOUND\", 404); return result; },\n async restoreVersion(principal, id, input) {\n const current = await loadScoped(principal, id);\n await allowed(config, \"history:restore\", principal, current);\n const restored = await database.findOne<MdfnVersionRecord>({\n model: VERSIONS,\n where: [\n { field: \"documentId\", operator: \"eq\", value: id },\n { field: \"version\", operator: \"eq\", value: input.version },\n ],\n });\n if (!restored) throw new MdfnServerError(\"MDFN_VERSION_NOT_FOUND\", 404);\n return writeUpdate(\n principal,\n id,\n { expectedVersion: input.expectedVersion, changeSource: `restore:${input.version}`, idempotencyKey: input.idempotencyKey },\n {\n trustedEditorial: true,\n authorizationAction: \"history:restore\",\n restoreSnapshot: restored,\n idempotencyOperation: \"document:restore\",\n idempotencyPayload: input,\n },\n );\n },\n async createComment(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:create\", \"editorial:comment-created\", input.idempotencyKey, input, (document) => createCommentThread({ sidecar: document.sidecar, anchor: input.anchor, body: input.body, actor: editorialActor(principal), markdownLength: document.markdown.length }));\n },\n async replyComment(principal, id, threadId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:reply\", \"editorial:comment-replied\", input.idempotencyKey, { threadId, ...input }, (document) => ({ sidecar: replyToComment({ sidecar: document.sidecar ?? {}, threadId, body: input.body, actor: editorialActor(principal) }) }));\n },\n async resolveComment(principal, id, threadId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:resolve\", input.resolved ? \"editorial:comment-resolved\" : \"editorial:comment-reopened\", input.idempotencyKey, { threadId, ...input }, (document) => ({ sidecar: setCommentResolved({ sidecar: document.sidecar ?? {}, threadId, resolved: input.resolved, actor: editorialActor(principal) }) }));\n },\n async createSuggestion(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"suggestion:create\", \"editorial:suggestion-created\", input.idempotencyKey, input, (document) => createSuggestion({ sidecar: document.sidecar, anchor: input.anchor, replacement: input.replacement, actor: editorialActor(principal), markdownLength: document.markdown.length }));\n },\n async decideSuggestion(principal, id, suggestionId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"suggestion:decide\", `editorial:suggestion-${input.decision}`, input.idempotencyKey, { suggestionId, ...input }, (document) => {\n const controller = createEditor({ markdown: document.markdown, projector: createMarkdownProjector(markdownOptions), extensions: config.extensions, sidecar: document.sidecar });\n try {\n decideSuggestion({ controller, suggestionId, decision: input.decision, actor: editorialActor(principal) });\n const state = controller.getState();\n return { markdown: state.markdown, sidecar: state.sidecar ?? {} };\n } finally { controller.destroy(); }\n });\n },\n async transitionReview(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"review:transition\", \"editorial:review-transitioned\", input.idempotencyKey, input, (document) => ({ sidecar: transitionReview({ sidecar: document.sidecar, to: input.state, actor: editorialActor(principal) }) }));\n },\n async appendCollaborationUpdate(principal, id, update) {\n if (new TextEncoder().encode(update).byteLength > collaborationUpdateBytes) throw new MdfnServerError(\"MDFN_COLLAB_UPDATE_TOO_LARGE\", 413);\n const updateId = createId();\n const createdAt = now();\n await withCollaborationWrite(principal, id, \"collaborate\", async (storage, cursorKey, documentGeneration) => {\n await storage.create({\n model: COLLAB_UPDATES,\n data: { id: updateId, documentId: id, documentGeneration, authorId: principal.id, update, cursorKey, createdAt },\n });\n });\n return updateId;\n },\n async collaborationUpdates(principal, id, options = {}) {\n const document = await loadScoped(principal, id);\n await allowed(config, \"collaborate\", principal, document);\n const requestedLimit = options.limit ?? collaborationBatchUpdates;\n if (!Number.isSafeInteger(requestedLimit) || requestedLimit < 1) {\n throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 422);\n }\n const limit = Math.min(collaborationBatchUpdates, requestedLimit);\n type CollaborationRow = { readonly id: string; readonly update: string; readonly cursorKey: string };\n const cursor = options.cursor === undefined ? undefined : decodeCollaborationCursor(options.cursor, id);\n const rows = await database.findMany<CollaborationRow>({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: id },\n { field: \"documentGeneration\", operator: \"eq\", value: document.collaborationGeneration },\n ...(cursor === undefined ? [] : [{ field: \"cursorKey\", operator: \"gt\" as const, value: cursor }]),\n ],\n orderBy: [{ field: \"cursorKey\", direction: \"asc\" }],\n limit: limit + 1,\n });\n const included: CollaborationRow[] = [];\n let encodedBytes = 0;\n for (const row of rows.slice(0, limit)) {\n const rowBytes = new TextEncoder().encode(row.update).byteLength;\n if (included.length > 0 && encodedBytes + rowBytes > collaborationBatchBytes) break;\n included.push(row);\n encodedBytes += rowBytes;\n }\n const hasMore = included.length < rows.length;\n return {\n updates: included.map((row) => row.update),\n includedUpdateIds: included.map((row) => row.id),\n ...(hasMore ? { nextCursor: encodeCollaborationCursor(id, included.at(-1)!.cursorKey) } : {}),\n };\n },\n async compactCollaborationUpdates(principal, id, snapshot, includedUpdateIds) {\n if (new TextEncoder().encode(snapshot).byteLength > collaborationUpdateBytes) throw new MdfnServerError(\"MDFN_COLLAB_UPDATE_TOO_LARGE\", 413);\n if (!Array.isArray(includedUpdateIds) || includedUpdateIds.some((updateId) => typeof updateId !== \"string\" || !updateId)) {\n throw new MdfnServerError(\"MDFN_COLLAB_COMPACTION_INVALID\", 422);\n }\n const uniqueUpdateIds = [...new Set(includedUpdateIds)];\n const updateId = createId();\n const createdAt = now();\n await withCollaborationWrite(principal, id, \"compact-collaboration\", async (storage, cursorKey, documentGeneration) => {\n if (uniqueUpdateIds.length > 0) {\n await storage.deleteMany({ model: COLLAB_UPDATES, where: [{ field: \"documentId\", operator: \"eq\", value: id }, { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration }, { field: \"id\", operator: \"in\", value: uniqueUpdateIds }] });\n }\n await storage.create({ model: COLLAB_UPDATES, data: { id: updateId, documentId: id, documentGeneration, authorId: principal.id, update: snapshot, cursorKey, createdAt } });\n });\n return updateId;\n },\n };\n return service;\n}\n\nfunction etag(document: MdfnDocumentRecord): string { return `\\\"mdfn-${document.version}-${document.sourceHash}\\\"`; }\nfunction response(document: MdfnDocumentRecord, status = 200): Response { return Response.json(document, { status, headers: { ETag: etag(document), \"Cache-Control\": \"no-store\" } }); }\nfunction idempotent<T extends { readonly idempotencyKey?: string }>(request: Request, body: T): T {\n return { ...body, idempotencyKey: body.idempotencyKey ?? request.headers.get(\"Idempotency-Key\") ?? undefined };\n}\n\nexport function createMdfnRouter(config: MdfnServerConfig, service = createMdfnService(config)): Router<{ principal: MdfnPrincipal }> {\n const principal = config.resolvePrincipal ?? (() => { throw new MdfnServerError(\"MDFN_UNAUTHENTICATED\", 401); });\n const defaultBodyBytes = Math.max(\n configuredDocumentBytes(config) + 4 * 1024 * 1024,\n configuredCollaborationUpdateBytes(config) + 64 * 1024,\n );\n return createRouter({\n basePath: config.basePath ?? \"/api/mdfn\",\n maxBodyBytes: config.maxRequestBodyBytes ?? defaultBodyBytes,\n context: async (request) => ({ principal: await principal(request) }),\n onError: (error) => error instanceof MdfnServerError\n ? Response.json({ error: error.code }, { status: error.status })\n : error instanceof RouterError\n ? error.toResponse()\n : Response.json({ error: \"MDFN_INTERNAL_ERROR\" }, { status: 500 }),\n routes: [\n { method: \"GET\", path: \"/documents\", handler: (_request, context) => service.list(context.principal, { limit: Number(context.query.get(\"limit\") ?? 50), offset: Number(context.query.get(\"offset\") ?? 0) }).then((documents) => Response.json({ documents })) },\n { method: \"POST\", path: \"/documents\", handler: async (_request, context) => response(await service.create(context.principal, await context.json()), 201) },\n { method: \"GET\", path: \"/documents/:id\", handler: async (_request, context) => response(await service.read(context.principal, context.params.id!)) },\n { method: \"PATCH\", path: \"/documents/:id\", handler: async (request, context) => response(await service.update(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"DELETE\", path: \"/documents/:id\", handler: async (_request, context) => { await service.delete(context.principal, context.params.id!); return new Response(null, { status: 204 }); } },\n { method: \"GET\", path: \"/documents/:id/versions\", handler: async (_request, context) => Response.json(await service.versions(context.principal, context.params.id!, { cursor: context.query.get(\"cursor\") ?? undefined, limit: context.query.has(\"limit\") ? Number(context.query.get(\"limit\")) : undefined })) },\n { method: \"GET\", path: \"/documents/:id/versions/:version\", handler: async (_request, context) => Response.json(await service.version(context.principal, context.params.id!, Number(context.params.version))) },\n { method: \"POST\", path: \"/documents/:id/restore\", handler: async (request, context) => response(await service.restoreVersion(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"GET\", path: \"/documents/:id/sidecar\", handler: async (_request, context) => Response.json((await service.read(context.principal, context.params.id!)).sidecar ?? {}) },\n { method: \"PUT\", path: \"/documents/:id/sidecar\", handler: async (request, context) => { const body = idempotent(request, await context.json<{ expectedVersion: number; sidecar: MdfnSidecar; idempotencyKey?: string }>()); return response(await service.update(context.principal, context.params.id!, { ...body, changeSource: \"sidecar\" })); } },\n { method: \"GET\", path: \"/documents/:id/audit\", handler: async (_request, context) => Response.json({ audit: (await service.read(context.principal, context.params.id!)).sidecar?.audit ?? [] }) },\n { method: \"POST\", path: \"/documents/:id/comments\", handler: async (request, context) => response(await service.createComment(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"POST\", path: \"/documents/:id/comments/:threadId/replies\", handler: async (request, context) => response(await service.replyComment(context.principal, context.params.id!, context.params.threadId!, idempotent(request, await context.json()))) },\n { method: \"PATCH\", path: \"/documents/:id/comments/:threadId\", handler: async (request, context) => response(await service.resolveComment(context.principal, context.params.id!, context.params.threadId!, idempotent(request, await context.json()))) },\n { method: \"POST\", path: \"/documents/:id/suggestions\", handler: async (request, context) => response(await service.createSuggestion(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"PATCH\", path: \"/documents/:id/suggestions/:suggestionId\", handler: async (request, context) => response(await service.decideSuggestion(context.principal, context.params.id!, context.params.suggestionId!, idempotent(request, await context.json()))) },\n { method: \"PUT\", path: \"/documents/:id/review\", handler: async (request, context) => response(await service.transitionReview(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"GET\", path: \"/documents/:id/collaboration-updates\", handler: async (_request, context) => Response.json(await service.collaborationUpdates(context.principal, context.params.id!, { cursor: context.query.get(\"cursor\") ?? undefined, limit: context.query.has(\"limit\") ? Number(context.query.get(\"limit\")) : undefined })) },\n { method: \"POST\", path: \"/documents/:id/collaboration-updates\", handler: async (_request, context) => { const body = await context.json<{ update: string }>(); return Response.json({ id: await service.appendCollaborationUpdate(context.principal, context.params.id!, body.update) }, { status: 201 }); } },\n { method: \"PUT\", path: \"/documents/:id/collaboration-updates/compact\", handler: async (_request, context) => { const body = await context.json<{ snapshot: string; includedUpdateIds: string[] }>(); return Response.json({ id: await service.compactCollaborationUpdates(context.principal, context.params.id!, body.snapshot, body.includedUpdateIds) }); } },\n ],\n });\n}\n\nexport function createMdfnServer(config: MdfnServerConfig): { readonly service: MdfnService; readonly router: Router<{ principal: MdfnPrincipal }>; readonly schema: ReturnType<typeof getSchema> } {\n const service = createMdfnService(config);\n return { service, router: createMdfnRouter(config, service), schema: getSchema() };\n}\n\nexport const MDFN_SERVER_VERSION = \"0.1.0\" as const;\n"],"mappings":"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","names":["left","right","updateId"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n createCommentThread,\n createEditor,\n createSuggestion,\n decideSuggestion,\n hashString,\n mapSidecar,\n replyToComment,\n resolveExtensions,\n setCommentResolved,\n transitionReview,\n validateMdfnSidecar,\n type MdfnExtension,\n type MdfnSidecar,\n type ReviewState,\n type SidecarAnchor,\n} from \"@mdfn/core\";\nimport { createMarkdownProjector, parseMarkdown, type MarkdownOptions } from \"@mdfn/markdown\";\nimport { wrapWithSchema, type Adapter, type TableSchema } from \"@superfunctions/db\";\nimport { createRouter, RouterError, type Router } from \"@superfunctions/http\";\n\nconst DOCUMENTS = \"mdfnDocuments\";\nconst VERSIONS = \"mdfnVersions\";\nconst RECEIPTS = \"mdfnReceipts\";\nconst COLLAB_UPDATES = \"mdfnCollaborationUpdates\";\nexport const MDFN_SERVER_SCHEMA_VERSION = 2;\n\nexport interface MdfnPrincipal { readonly id: string; readonly tenantId?: string; readonly roles?: readonly string[]; }\nexport type MdfnServerAction =\n | \"create\"\n | \"read\"\n | \"update\"\n | \"delete\"\n | \"history\"\n | \"history:restore\"\n | \"collaborate\"\n | \"compact-collaboration\"\n | \"comment:create\"\n | \"comment:reply\"\n | \"comment:resolve\"\n | \"suggestion:create\"\n | \"suggestion:decide\"\n | \"review:transition\";\n\nexport interface MdfnDocumentRecord {\n readonly id: string;\n /** Immutable identity for collaboration rows across delete/recreate cycles. */\n readonly collaborationGeneration: string;\n readonly ownerId: string;\n readonly tenantId?: string;\n readonly title?: string;\n readonly markdown: string;\n readonly sourceHash: string;\n readonly schemaHash: string;\n readonly sidecar?: MdfnSidecar;\n readonly version: number;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n}\n\nexport interface MdfnVersionRecord extends MdfnDocumentRecord { readonly documentId: string; readonly authorId: string; readonly changeSource: string; }\n\nexport type MdfnVersionSummary = Omit<MdfnVersionRecord, \"markdown\" | \"sidecar\">;\n\nexport interface MdfnVersionBatch {\n readonly versions: readonly MdfnVersionSummary[];\n readonly nextCursor?: string;\n}\n\nexport interface MdfnCollaborationUpdateBatch {\n readonly updates: readonly string[];\n /** Exact persisted update ids represented by `updates` and therefore safe to compact. */\n readonly includedUpdateIds: readonly string[];\n /** Opaque continuation for the next bounded batch, when more updates remain. */\n readonly nextCursor?: string;\n}\n\nexport interface MdfnServerConfig {\n readonly database: Adapter;\n readonly authorize: (action: MdfnServerAction, principal: MdfnPrincipal, document?: MdfnDocumentRecord) => boolean | Promise<boolean>;\n readonly resolvePrincipal?: (request: Request) => MdfnPrincipal | Promise<MdfnPrincipal>;\n readonly extensions?: readonly MdfnExtension[];\n readonly markdown?: MarkdownOptions;\n readonly basePath?: string;\n readonly createId?: () => string;\n /** Injectable lifecycle identity for deterministic hosts and tests. */\n readonly createCollaborationGeneration?: () => string;\n /** Injectable clock for deterministic hosts and tests. */\n readonly now?: () => Date;\n readonly maxCollaborationUpdateBytes?: number;\n readonly maxCollaborationBatchBytes?: number;\n readonly maxCollaborationBatchUpdates?: number;\n /** Maximum encoded request body accepted by JSON-writing routes. */\n readonly maxRequestBodyBytes?: number;\n /** Maximum UTF-8 bytes accepted for a persisted document title. */\n readonly maxTitleBytes?: number;\n /** Durable storage requires adapter transactions. Ephemeral is intended only for in-memory/test hosts. */\n readonly durability?: \"required\" | \"ephemeral\";\n}\n\nexport class MdfnServerError extends Error {\n constructor(readonly code: string, readonly status: number, message = code) { super(message); this.name = \"MdfnServerError\"; }\n}\n\nfunction configuredDocumentBytes(config: MdfnServerConfig): number {\n return config.markdown?.maxBytes ?? 2 * 1024 * 1024;\n}\n\nfunction configuredCollaborationUpdateBytes(config: MdfnServerConfig): number {\n if (config.maxCollaborationUpdateBytes !== undefined) return config.maxCollaborationUpdateBytes;\n const documentBytes = configuredDocumentBytes(config);\n const yjsOverhead = Math.max(64 * 1024, Math.ceil(documentBytes / 16));\n return 4 * Math.ceil((documentBytes + yjsOverhead) / 3);\n}\n\ninterface CollaborationCursor {\n readonly documentId: string;\n readonly key: string;\n}\n\nfunction collaborationCursorKey(previousKey?: string): string {\n const match = previousKey?.match(/^v2:(\\d{20})$/);\n if (previousKey?.startsWith(\"v2:\") && !match) throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 500);\n const sequence = (match ? BigInt(match[1]) : 0n) + 1n;\n const encoded = sequence.toString().padStart(20, \"0\");\n if (encoded.length > 20) throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_EXHAUSTED\", 500);\n return `v2:${encoded}`;\n}\n\nfunction isUniqueConflict(error: unknown): boolean {\n const value = error as { readonly code?: unknown; readonly message?: unknown; readonly cause?: unknown };\n const cause = value?.cause as { readonly code?: unknown; readonly message?: unknown } | undefined;\n return /(?:unique|duplicate|23505|p2002)/i.test([value?.code, value?.message, cause?.code, cause?.message].filter(Boolean).join(\" \"));\n}\n\nfunction encodeCollaborationCursor(documentId: string, key: string): string {\n return encodeURIComponent(JSON.stringify({ documentId, key }));\n}\n\nfunction decodeCollaborationCursor(cursor: string, documentId: string): string {\n try {\n const parsed = JSON.parse(decodeURIComponent(cursor)) as Partial<CollaborationCursor>;\n if (parsed.documentId !== documentId || typeof parsed.key !== \"string\" || !parsed.key) {\n throw new Error(\"invalid cursor\");\n }\n return parsed.key;\n } catch {\n throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 422);\n }\n}\n\nexport function getSchema(): { version: number; schemas: TableSchema[] } {\n const date = { type: \"date\" as const, required: true, dateValueType: \"date\" as const };\n return { version: MDFN_SERVER_SCHEMA_VERSION, schemas: [\n { modelName: DOCUMENTS, fields: { id: { type: \"string\", required: true }, collaborationGeneration: { type: \"string\", required: true }, ownerId: { type: \"string\", required: true }, tenantId: { type: \"string\" }, title: { type: \"string\" }, markdown: { type: \"string\", required: true }, sourceHash: { type: \"string\", required: true }, schemaHash: { type: \"string\", required: true }, sidecar: { type: \"json\" }, version: { type: \"number\", required: true }, createdAt: date, updatedAt: date }, indexes: [{ name: \"idx_mdfn_documents_owner\", fields: [\"ownerId\"] }, { name: \"idx_mdfn_documents_tenant\", fields: [\"tenantId\"] }] },\n { modelName: VERSIONS, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true }, collaborationGeneration: { type: \"string\", required: true }, ownerId: { type: \"string\", required: true }, tenantId: { type: \"string\" }, title: { type: \"string\" }, markdown: { type: \"string\", required: true }, sourceHash: { type: \"string\", required: true }, schemaHash: { type: \"string\", required: true }, sidecar: { type: \"json\" }, version: { type: \"number\", required: true }, authorId: { type: \"string\", required: true }, changeSource: { type: \"string\", required: true }, createdAt: date, updatedAt: date }, indexes: [{ name: \"idx_mdfn_versions_document_version\", fields: [\"documentId\", \"version\"], unique: true }] },\n { modelName: RECEIPTS, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true }, idempotencyKey: { type: \"string\", required: true }, operation: { type: \"string\", required: true }, payloadHash: { type: \"string\", required: true }, result: { type: \"json\", required: true }, createdAt: date }, indexes: [{ name: \"idx_mdfn_receipts_key\", fields: [\"documentId\", \"idempotencyKey\"], unique: true }] },\n { modelName: COLLAB_UPDATES, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true, references: { model: DOCUMENTS, field: \"id\", onDelete: \"cascade\" } }, documentGeneration: { type: \"string\", required: true }, authorId: { type: \"string\", required: true }, update: { type: \"string\", required: true }, cursorKey: { type: \"string\", required: true }, createdAt: date }, indexes: [{ name: \"idx_mdfn_collab_generation_cursor\", fields: [\"documentId\", \"documentGeneration\", \"cursorKey\"], unique: true }] },\n ] };\n}\n\nexport interface MdfnService {\n create(principal: MdfnPrincipal, input: { readonly id?: string; readonly title?: string; readonly markdown: string; readonly sidecar?: MdfnSidecar }): Promise<MdfnDocumentRecord>;\n read(principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord>;\n list(principal: MdfnPrincipal, options?: { readonly limit?: number; readonly offset?: number }): Promise<readonly MdfnDocumentRecord[]>;\n update(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly markdown?: string; readonly title?: string; readonly sidecar?: MdfnSidecar; readonly changeSource?: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n delete(principal: MdfnPrincipal, id: string): Promise<void>;\n versions(\n principal: MdfnPrincipal,\n id: string,\n options?: { readonly cursor?: string; readonly limit?: number },\n ): Promise<MdfnVersionBatch>;\n version(principal: MdfnPrincipal, id: string, version: number): Promise<MdfnVersionRecord>;\n restoreVersion(principal: MdfnPrincipal, id: string, input: { readonly version: number; readonly expectedVersion: number; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n createComment(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly anchor: SidecarAnchor; readonly body: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n replyComment(principal: MdfnPrincipal, id: string, threadId: string, input: { readonly expectedVersion: number; readonly body: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n resolveComment(principal: MdfnPrincipal, id: string, threadId: string, input: { readonly expectedVersion: number; readonly resolved: boolean; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n createSuggestion(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly anchor: SidecarAnchor; readonly replacement: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n decideSuggestion(principal: MdfnPrincipal, id: string, suggestionId: string, input: { readonly expectedVersion: number; readonly decision: \"accepted\" | \"rejected\"; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n transitionReview(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly state: ReviewState; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n appendCollaborationUpdate(principal: MdfnPrincipal, id: string, update: string): Promise<string>;\n collaborationUpdates(\n principal: MdfnPrincipal,\n id: string,\n options?: { readonly cursor?: string; readonly limit?: number },\n ): Promise<MdfnCollaborationUpdateBatch>;\n compactCollaborationUpdates(principal: MdfnPrincipal, id: string, snapshot: string, includedUpdateIds: readonly string[]): Promise<string>;\n}\n\nasync function allowed(config: MdfnServerConfig, action: MdfnServerAction, principal: MdfnPrincipal, document?: MdfnDocumentRecord): Promise<void> {\n if (!(await config.authorize(action, principal, document))) throw new MdfnServerError(\"MDFN_FORBIDDEN\", 403);\n}\n\nfunction whereId(id: string) { return [{ field: \"id\", operator: \"eq\" as const, value: id }]; }\n\nexport function createMdfnService(config: MdfnServerConfig): MdfnService {\n const database = wrapWithSchema(config.database, getSchema());\n if ((config.durability ?? \"required\") === \"required\") {\n if (!database.capabilities.transactions.supported) {\n throw new MdfnServerError(\"MDFN_TRANSACTIONAL_DATABASE_REQUIRED\", 500);\n }\n if (!database.capabilities.schema.constraints) {\n throw new MdfnServerError(\"MDFN_RELATIONAL_CONSTRAINTS_REQUIRED\", 500);\n }\n }\n const registry = resolveExtensions(config.extensions ?? []);\n const markdownOptions: MarkdownOptions = { ...config.markdown, extensions: registry };\n const createId = config.createId ?? (() => crypto.randomUUID());\n const createCollaborationGeneration = config.createCollaborationGeneration ?? (() => crypto.randomUUID());\n const now = config.now ?? (() => new Date());\n const collaborationUpdateBytes = configuredCollaborationUpdateBytes(config);\n const collaborationBatchBytes = Math.max(\n collaborationUpdateBytes,\n config.maxCollaborationBatchBytes ?? collaborationUpdateBytes * 4,\n );\n const collaborationBatchUpdates = Math.min(1_000, Math.max(1, config.maxCollaborationBatchUpdates ?? 100));\n const parse = (source: string, sidecar?: MdfnSidecar): void => {\n try {\n parseMarkdown(source, markdownOptions);\n validateMdfnSidecar(sidecar, { markdownLength: source.length });\n } catch {\n throw new MdfnServerError(\"MDFN_DOCUMENT_INVALID\", 422);\n }\n };\n type Storage = Pick<Adapter, \"create\" | \"findOne\" | \"findMany\" | \"update\" | \"delete\" | \"deleteMany\">;\n const loadFrom = async (storage: Pick<Adapter, \"findOne\">, id: string): Promise<MdfnDocumentRecord> => {\n const result = await storage.findOne<MdfnDocumentRecord>({ model: DOCUMENTS, where: whereId(id) });\n if (!result) throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n return result;\n };\n const load = (id: string): Promise<MdfnDocumentRecord> => loadFrom(database, id);\n const loadScopedFrom = async (storage: Pick<Adapter, \"findOne\">, principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord> => {\n const document = await loadFrom(storage, id);\n const inScope = principal.tenantId\n ? document.tenantId === principal.tenantId\n : document.tenantId === undefined && document.ownerId === principal.id;\n if (!inScope) throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n return document;\n };\n const loadScoped = (principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord> => loadScopedFrom(database, principal, id);\n const revision = (document: MdfnDocumentRecord, authorId: string, changeSource: string): MdfnVersionRecord => ({ ...document, id: `${document.id}:${document.version}`, documentId: document.id, authorId, changeSource });\n const withStorage = <T>(callback: (storage: Storage) => Promise<T>): Promise<T> => database.capabilities.transactions.supported\n ? database.transaction((transaction) => callback(transaction))\n : callback(database);\n const collaborationWriteTails = new Map<string, Promise<void>>();\n const serializeCollaborationWrite = async <T>(documentId: string, callback: () => Promise<T>): Promise<T> => {\n const previous = collaborationWriteTails.get(documentId) ?? Promise.resolve();\n let release!: () => void;\n const gate = new Promise<void>((resolve) => { release = resolve; });\n const tail = previous.then(() => gate);\n collaborationWriteTails.set(documentId, tail);\n await previous;\n try {\n return await callback();\n } finally {\n release();\n if (collaborationWriteTails.get(documentId) === tail) collaborationWriteTails.delete(documentId);\n }\n };\n const withCollaborationWrite = <T>(\n principal: MdfnPrincipal,\n documentId: string,\n action: \"collaborate\" | \"compact-collaboration\",\n callback: (storage: Storage, cursorKey: string, documentGeneration: string) => Promise<T>,\n ): Promise<T> => (\n serializeCollaborationWrite(documentId, async () => {\n const authorizedDocument = await loadScoped(principal, documentId);\n await allowed(config, action, principal, authorizedDocument);\n const documentGeneration = authorizedDocument.collaborationGeneration;\n let lastConflict: unknown;\n for (let attempt = 0; attempt < 5; attempt += 1) {\n try {\n const result = await withStorage(async (storage) => {\n const storedDocument = await loadScopedFrom(storage, principal, documentId);\n if (storedDocument.collaborationGeneration !== documentGeneration) {\n throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n }\n const latest = await storage.findMany<{ readonly cursorKey: string }>({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: documentId },\n { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration },\n ],\n select: [\"cursorKey\"],\n orderBy: [{ field: \"cursorKey\", direction: \"desc\" }],\n limit: 1,\n });\n return callback(storage, collaborationCursorKey(latest[0]?.cursorKey), documentGeneration);\n });\n let latestDocument: MdfnDocumentRecord | undefined;\n try {\n latestDocument = await loadScoped(principal, documentId);\n } catch (error) {\n if (!(error instanceof MdfnServerError && error.code === \"MDFN_DOCUMENT_NOT_FOUND\")) throw error;\n }\n if (latestDocument?.collaborationGeneration !== documentGeneration) {\n await database.deleteMany({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: documentId },\n { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration },\n ],\n });\n throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n }\n return result;\n } catch (error) {\n if (!isUniqueConflict(error)) throw error;\n lastConflict = error;\n }\n }\n throw lastConflict;\n })\n );\n let service!: MdfnService;\n const editorialActor = (principal: MdfnPrincipal) => ({ id: principal.id, createId, now: () => now().toISOString() });\n const maxTitleBytes = config.maxTitleBytes ?? 512;\n if (!Number.isSafeInteger(maxTitleBytes) || maxTitleBytes < 1) {\n throw new MdfnServerError(\"MDFN_TITLE_LIMIT_INVALID\", 500);\n }\n const validateTitle = (title: string | undefined): void => {\n if (title !== undefined && new TextEncoder().encode(title).byteLength > maxTitleBytes) {\n throw new MdfnServerError(\"MDFN_TITLE_TOO_LARGE\", 413);\n }\n };\n type UpdateInput = Parameters<MdfnService[\"update\"]>[2];\n type RestoreSnapshot = Pick<MdfnVersionRecord, \"title\" | \"markdown\" | \"sidecar\">;\n interface WriteUpdateOptions {\n readonly trustedEditorial?: boolean;\n readonly authorizationAction?: MdfnServerAction;\n readonly restoreSnapshot?: RestoreSnapshot;\n readonly idempotencyOperation?: string;\n readonly idempotencyPayload?: unknown;\n }\n const canonicalJson = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(canonicalJson);\n if (value === null || typeof value !== \"object\") return value;\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)\n .map(([key, entry]) => [key, canonicalJson(entry)]),\n );\n };\n const hashValue = (value: unknown): string => hashString(JSON.stringify(canonicalJson(value)));\n const protectedSidecar = (value: MdfnSidecar | undefined): string => JSON.stringify(canonicalJson({\n comments: value?.comments ?? [],\n suggestions: value?.suggestions ?? [],\n reviewState: value?.reviewState ?? \"draft\",\n audit: value?.audit ?? [],\n }));\n const coarseChangedRanges = (before: string, after: string, offset: number): Array<{ from: number; to: number; insertedLength: number }> => {\n const ranges: Array<{ from: number; to: number; insertedLength: number }> = [];\n const syncLength = 16;\n const initialLookahead = 2_048;\n let remainingSearchWork = 65_536;\n let left = 0;\n let right = 0;\n let position = offset;\n while (left < before.length || right < after.length) {\n while (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) {\n left += 1;\n right += 1;\n position += 1;\n }\n if (left === before.length && right === after.length) break;\n const from = position;\n let match: { left: number; right: number; cost: number } | undefined;\n let lookahead = initialLookahead;\n const beforeAnchors = new Map<string, number>();\n const afterAnchors = new Map<string, number>();\n let beforeScannedTo = left - 1;\n let afterScannedTo = right - 1;\n while (!match) {\n const beforeLimit = Math.min(before.length - syncLength, left + lookahead);\n for (let candidate = beforeScannedTo + 1; candidate <= beforeLimit; candidate += 1) {\n if (remainingSearchWork === 0) break;\n remainingSearchWork -= 1;\n const key = before.slice(candidate, candidate + syncLength);\n if (!beforeAnchors.has(key)) beforeAnchors.set(key, candidate);\n const matchingRight = afterAnchors.get(key);\n if (matchingRight !== undefined) {\n const cost = candidate - left + matchingRight - right;\n if (!match || cost < match.cost) match = { left: candidate, right: matchingRight, cost };\n }\n beforeScannedTo = candidate;\n }\n const afterLimit = Math.min(after.length - syncLength, right + lookahead);\n for (let candidate = afterScannedTo + 1; candidate <= afterLimit; candidate += 1) {\n if (remainingSearchWork === 0) break;\n remainingSearchWork -= 1;\n const key = after.slice(candidate, candidate + syncLength);\n if (!afterAnchors.has(key)) afterAnchors.set(key, candidate);\n const matchingLeft = beforeAnchors.get(key);\n if (matchingLeft !== undefined) {\n const cost = matchingLeft - left + candidate - right;\n if (!match || cost < match.cost) match = { left: matchingLeft, right: candidate, cost };\n }\n afterScannedTo = candidate;\n }\n const searchedAllBefore = before.length - left < syncLength || beforeScannedTo >= before.length - syncLength;\n const searchedAllAfter = after.length - right < syncLength || afterScannedTo >= after.length - syncLength;\n if (match || remainingSearchWork === 0 || (searchedAllBefore && searchedAllAfter)) break;\n lookahead = Math.min(\n Math.max(before.length - left, after.length - right),\n lookahead * 2,\n );\n }\n if (!match || match.cost === 0) {\n ranges.push({ from, to: from + before.length - left, insertedLength: after.length - right });\n break;\n }\n const removed = match.left - left;\n const insertedLength = match.right - right;\n ranges.push({ from, to: from + removed, insertedLength });\n left = match.left;\n right = match.right;\n position += insertedLength;\n }\n return ranges;\n };\n const changedRanges = (previous: string, next: string): Array<{ from: number; to: number; insertedLength: number }> => {\n if (previous === next) return [];\n let prefix = 0;\n while (prefix < previous.length && prefix < next.length && previous.charCodeAt(prefix) === next.charCodeAt(prefix)) prefix += 1;\n let previousEnd = previous.length;\n let nextEnd = next.length;\n while (previousEnd > prefix && nextEnd > prefix && previous.charCodeAt(previousEnd - 1) === next.charCodeAt(nextEnd - 1)) { previousEnd -= 1; nextEnd -= 1; }\n const before = previous.slice(prefix, previousEnd);\n const after = next.slice(prefix, nextEnd);\n if (before.length * after.length > 250_000) return coarseChangedRanges(before, after, prefix);\n const width = after.length + 1;\n const lcs = new Uint32Array((before.length + 1) * width);\n for (let left = before.length - 1; left >= 0; left -= 1) {\n for (let right = after.length - 1; right >= 0; right -= 1) {\n const index = left * width + right;\n lcs[index] = before.charCodeAt(left) === after.charCodeAt(right)\n ? lcs[(left + 1) * width + right + 1] + 1\n : Math.max(lcs[(left + 1) * width + right], lcs[index + 1]);\n }\n }\n const ranges: Array<{ from: number; to: number; insertedLength: number }> = [];\n let left = 0;\n let right = 0;\n let position = prefix;\n while (left < before.length || right < after.length) {\n if (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) {\n left += 1; right += 1; position += 1; continue;\n }\n const from = position;\n let removed = 0;\n let insertedLength = 0;\n while (left < before.length || right < after.length) {\n if (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) break;\n if (right < after.length && (left === before.length || lcs[left * width + right + 1] >= lcs[(left + 1) * width + right])) {\n right += 1; insertedLength += 1;\n } else {\n left += 1; removed += 1;\n }\n }\n ranges.push({ from, to: from + removed, insertedLength });\n position += insertedLength;\n }\n return ranges;\n };\n const mapForMarkdownChange = (sidecar: MdfnSidecar | undefined, previous: string, next: string): MdfnSidecar | undefined => {\n if (!sidecar || previous === next) return sidecar;\n return mapSidecar(sidecar, changedRanges(previous, next));\n };\n interface Receipt { readonly operation: string; readonly payloadHash: string; readonly result: MdfnDocumentRecord; }\n const replayReceipt = async (storage: Storage, documentId: string, idempotencyKey: string, operation: string, payloadHash: string): Promise<MdfnDocumentRecord | undefined> => {\n const receipt = await storage.findOne<Receipt>({ model: RECEIPTS, where: [{ field: \"documentId\", operator: \"eq\", value: documentId }, { field: \"idempotencyKey\", operator: \"eq\", value: idempotencyKey }] });\n if (!receipt) return undefined;\n if (receipt.operation !== operation || receipt.payloadHash !== payloadHash) throw new MdfnServerError(\"MDFN_IDEMPOTENCY_KEY_REUSED\", 409);\n return receipt.result;\n };\n const writeUpdate = async (principal: MdfnPrincipal, id: string, input: UpdateInput, options: WriteUpdateOptions = {}): Promise<MdfnDocumentRecord> => {\n const current = await loadScoped(principal, id);\n await allowed(config, options.authorizationAction ?? \"update\", principal, current);\n const operation = options.idempotencyOperation ?? \"document:update\";\n const payloadHash = hashValue(options.idempotencyPayload ?? {\n ...input,\n idempotencyKey: undefined,\n restoreSnapshot: options.restoreSnapshot,\n });\n if (input.idempotencyKey) {\n const replay = await replayReceipt(database, id, input.idempotencyKey, operation, payloadHash);\n if (replay) return replay;\n }\n if (current.version !== input.expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n const markdown = options.restoreSnapshot?.markdown ?? input.markdown ?? current.markdown;\n if (!options.trustedEditorial && input.sidecar && protectedSidecar(input.sidecar) !== protectedSidecar(current.sidecar)) {\n throw new MdfnServerError(\"MDFN_EDITORIAL_MUTATION_FORBIDDEN\", 403);\n }\n const mappedSidecar = mapForMarkdownChange(current.sidecar, current.markdown, markdown);\n const sidecar = options.restoreSnapshot\n ? options.restoreSnapshot.sidecar\n : options.trustedEditorial\n ? input.sidecar ?? mappedSidecar\n : input.sidecar\n ? {\n ...input.sidecar,\n comments: mappedSidecar?.comments,\n suggestions: mappedSidecar?.suggestions,\n reviewState: mappedSidecar?.reviewState,\n audit: mappedSidecar?.audit,\n }\n : mappedSidecar;\n parse(markdown, sidecar);\n const title = options.restoreSnapshot ? options.restoreSnapshot.title : input.title ?? current.title;\n validateTitle(title);\n const next: MdfnDocumentRecord = { ...current, title, markdown, sourceHash: hashString(markdown), schemaHash: registry.schemaHash, sidecar, version: current.version + 1, updatedAt: now() };\n return withStorage(async (storage) => {\n if (input.idempotencyKey) {\n const replay = await replayReceipt(storage, id, input.idempotencyKey, operation, payloadHash);\n if (replay) return replay;\n }\n const latest = await storage.findOne<MdfnDocumentRecord>({ model: DOCUMENTS, where: whereId(id) });\n if (!latest || latest.version !== input.expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n const updated = await storage.update<MdfnDocumentRecord>({ model: DOCUMENTS, where: [{ field: \"id\", operator: \"eq\", value: id }, { field: \"version\", operator: \"eq\", value: input.expectedVersion }], data: next });\n await storage.create({ model: VERSIONS, data: revision(updated, principal.id, input.changeSource ?? \"update\") });\n if (input.idempotencyKey) await storage.create({ model: RECEIPTS, data: { id: createId(), documentId: id, idempotencyKey: input.idempotencyKey, operation, payloadHash, result: updated, createdAt: now() } });\n return updated;\n });\n };\n const mutateEditorial = async (\n principal: MdfnPrincipal,\n id: string,\n expectedVersion: number,\n authorizationAction: MdfnServerAction,\n changeSource: string,\n idempotencyKey: string | undefined,\n idempotencyPayload: unknown,\n mutate: (document: MdfnDocumentRecord) => { readonly markdown?: string; readonly sidecar: MdfnSidecar },\n ): Promise<MdfnDocumentRecord> => {\n const current = await loadScoped(principal, id);\n await allowed(config, authorizationAction, principal, current);\n if (idempotencyKey) {\n const replay = await replayReceipt(database, id, idempotencyKey, changeSource, hashValue(idempotencyPayload));\n if (replay) return replay;\n }\n if (current.version !== expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n try {\n const next = mutate(current);\n return writeUpdate(principal, id, { expectedVersion, markdown: next.markdown, sidecar: next.sidecar, changeSource, idempotencyKey }, { trustedEditorial: true, authorizationAction, idempotencyOperation: changeSource, idempotencyPayload });\n } catch (error) {\n if (error instanceof MdfnServerError) throw error;\n throw new MdfnServerError(\"MDFN_EDITORIAL_INVALID\", 422);\n }\n };\n service = {\n async create(principal, input) {\n await allowed(config, \"create\", principal);\n parse(input.markdown, input.sidecar);\n validateTitle(input.title);\n if (input.id !== undefined && (typeof input.id !== \"string\" || input.id.trim().length === 0)) {\n throw new MdfnServerError(\"MDFN_DOCUMENT_ID_INVALID\", 422);\n }\n if (input.sidecar && protectedSidecar(input.sidecar) !== protectedSidecar(undefined)) {\n throw new MdfnServerError(\"MDFN_EDITORIAL_MUTATION_FORBIDDEN\", 403);\n }\n const createdAt = now();\n const collaborationGeneration = createCollaborationGeneration();\n if (typeof collaborationGeneration !== \"string\" || collaborationGeneration.length === 0) {\n throw new MdfnServerError(\"MDFN_COLLAB_GENERATION_INVALID\", 500);\n }\n const document: MdfnDocumentRecord = { id: input.id ?? createId(), collaborationGeneration, ownerId: principal.id, tenantId: principal.tenantId, title: input.title, markdown: input.markdown, sourceHash: hashString(input.markdown), schemaHash: registry.schemaHash, sidecar: input.sidecar, version: 1, createdAt, updatedAt: createdAt };\n return withStorage(async (storage) => {\n const created = await storage.create<MdfnDocumentRecord>({ model: DOCUMENTS, data: document });\n await storage.create({ model: VERSIONS, data: revision(created, principal.id, \"create\") });\n return created;\n });\n },\n async read(principal, id) { const document = await loadScoped(principal, id); await allowed(config, \"read\", principal, document); return document; },\n async list(principal, options = {}) {\n await allowed(config, \"read\", principal);\n const where = principal.tenantId ? [{ field: \"tenantId\", operator: \"eq\" as const, value: principal.tenantId }] : [{ field: \"ownerId\", operator: \"eq\" as const, value: principal.id }];\n const offset = Math.max(0, options.offset ?? 0);\n const limit = Math.min(100, Math.max(1, options.limit ?? 50));\n const pageSize = Math.max(25, limit);\n const visible: MdfnDocumentRecord[] = [];\n let databaseOffset = 0;\n let authorizedOffset = 0;\n while (visible.length < limit) {\n const candidates = await database.findMany<MdfnDocumentRecord>({\n model: DOCUMENTS,\n where,\n orderBy: [{ field: \"updatedAt\", direction: \"desc\" }, { field: \"id\", direction: \"desc\" }],\n limit: pageSize,\n offset: databaseOffset,\n });\n databaseOffset += candidates.length;\n for (const document of candidates) {\n if (!principal.tenantId && document.tenantId !== undefined && document.tenantId !== null) continue;\n if (!(await config.authorize(\"read\", principal, document))) continue;\n if (authorizedOffset < offset) {\n authorizedOffset += 1;\n continue;\n }\n visible.push(document);\n if (visible.length === limit) break;\n }\n if (candidates.length < pageSize) break;\n }\n return visible;\n },\n async update(principal, id, input) { return writeUpdate(principal, id, input); },\n async delete(principal, id) {\n await serializeCollaborationWrite(id, async () => {\n const current = await loadScoped(principal, id);\n await allowed(config, \"delete\", principal, current);\n await withStorage(async (storage) => {\n const documentWhere = [{ field: \"documentId\", operator: \"eq\" as const, value: id }];\n await storage.deleteMany({ model: COLLAB_UPDATES, where: documentWhere });\n await storage.deleteMany({ model: RECEIPTS, where: documentWhere });\n await storage.deleteMany({ model: VERSIONS, where: documentWhere });\n await storage.delete({ model: DOCUMENTS, where: whereId(id) });\n });\n });\n },\n async versions(principal, id, options = {}) {\n const document = await loadScoped(principal, id);\n await allowed(config, \"history\", principal, document);\n const cursor = options.cursor === undefined ? undefined : Number(options.cursor);\n const requestedLimit = options.limit ?? 50;\n if ((cursor !== undefined && (!Number.isSafeInteger(cursor) || cursor < 1)) ||\n !Number.isSafeInteger(requestedLimit) || requestedLimit < 1) {\n throw new MdfnServerError(\"MDFN_VERSION_CURSOR_INVALID\", 422);\n }\n const limit = Math.min(100, requestedLimit);\n const where = [\n { field: \"documentId\", operator: \"eq\" as const, value: id },\n ...(cursor === undefined ? [] : [{ field: \"version\", operator: \"lt\" as const, value: cursor }]),\n ];\n const rows = await database.findMany<MdfnVersionSummary>({\n model: VERSIONS,\n where,\n select: [\n \"id\", \"documentId\", \"collaborationGeneration\", \"ownerId\", \"tenantId\", \"title\", \"sourceHash\", \"schemaHash\",\n \"version\", \"authorId\", \"changeSource\", \"createdAt\", \"updatedAt\",\n ],\n orderBy: [{ field: \"version\", direction: \"desc\" }],\n limit: limit + 1,\n });\n const versions = rows.slice(0, limit);\n return {\n versions,\n ...(rows.length > limit ? { nextCursor: String(versions.at(-1)!.version) } : {}),\n };\n },\n async version(principal, id, version) { const document = await loadScoped(principal, id); await allowed(config, \"history\", principal, document); const result = await database.findOne<MdfnVersionRecord>({ model: VERSIONS, where: [{ field: \"documentId\", operator: \"eq\", value: id }, { field: \"version\", operator: \"eq\", value: version }] }); if (!result) throw new MdfnServerError(\"MDFN_VERSION_NOT_FOUND\", 404); return result; },\n async restoreVersion(principal, id, input) {\n const current = await loadScoped(principal, id);\n await allowed(config, \"history:restore\", principal, current);\n const restored = await database.findOne<MdfnVersionRecord>({\n model: VERSIONS,\n where: [\n { field: \"documentId\", operator: \"eq\", value: id },\n { field: \"version\", operator: \"eq\", value: input.version },\n ],\n });\n if (!restored) throw new MdfnServerError(\"MDFN_VERSION_NOT_FOUND\", 404);\n return writeUpdate(\n principal,\n id,\n { expectedVersion: input.expectedVersion, changeSource: `restore:${input.version}`, idempotencyKey: input.idempotencyKey },\n {\n trustedEditorial: true,\n authorizationAction: \"history:restore\",\n restoreSnapshot: restored,\n idempotencyOperation: \"document:restore\",\n idempotencyPayload: input,\n },\n );\n },\n async createComment(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:create\", \"editorial:comment-created\", input.idempotencyKey, input, (document) => createCommentThread({ sidecar: document.sidecar, anchor: input.anchor, body: input.body, actor: editorialActor(principal), markdownLength: document.markdown.length }));\n },\n async replyComment(principal, id, threadId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:reply\", \"editorial:comment-replied\", input.idempotencyKey, { threadId, ...input }, (document) => ({ sidecar: replyToComment({ sidecar: document.sidecar ?? {}, threadId, body: input.body, actor: editorialActor(principal) }) }));\n },\n async resolveComment(principal, id, threadId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:resolve\", input.resolved ? \"editorial:comment-resolved\" : \"editorial:comment-reopened\", input.idempotencyKey, { threadId, ...input }, (document) => ({ sidecar: setCommentResolved({ sidecar: document.sidecar ?? {}, threadId, resolved: input.resolved, actor: editorialActor(principal) }) }));\n },\n async createSuggestion(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"suggestion:create\", \"editorial:suggestion-created\", input.idempotencyKey, input, (document) => createSuggestion({ sidecar: document.sidecar, anchor: input.anchor, replacement: input.replacement, actor: editorialActor(principal), markdownLength: document.markdown.length }));\n },\n async decideSuggestion(principal, id, suggestionId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"suggestion:decide\", `editorial:suggestion-${input.decision}`, input.idempotencyKey, { suggestionId, ...input }, (document) => {\n const controller = createEditor({ markdown: document.markdown, projector: createMarkdownProjector(markdownOptions), extensions: config.extensions, sidecar: document.sidecar });\n try {\n decideSuggestion({ controller, suggestionId, decision: input.decision, actor: editorialActor(principal) });\n const state = controller.getState();\n return { markdown: state.markdown, sidecar: state.sidecar ?? {} };\n } finally { controller.destroy(); }\n });\n },\n async transitionReview(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"review:transition\", \"editorial:review-transitioned\", input.idempotencyKey, input, (document) => ({ sidecar: transitionReview({ sidecar: document.sidecar, to: input.state, actor: editorialActor(principal) }) }));\n },\n async appendCollaborationUpdate(principal, id, update) {\n if (new TextEncoder().encode(update).byteLength > collaborationUpdateBytes) throw new MdfnServerError(\"MDFN_COLLAB_UPDATE_TOO_LARGE\", 413);\n const updateId = createId();\n const createdAt = now();\n await withCollaborationWrite(principal, id, \"collaborate\", async (storage, cursorKey, documentGeneration) => {\n await storage.create({\n model: COLLAB_UPDATES,\n data: { id: updateId, documentId: id, documentGeneration, authorId: principal.id, update, cursorKey, createdAt },\n });\n });\n return updateId;\n },\n async collaborationUpdates(principal, id, options = {}) {\n const document = await loadScoped(principal, id);\n await allowed(config, \"collaborate\", principal, document);\n const requestedLimit = options.limit ?? collaborationBatchUpdates;\n if (!Number.isSafeInteger(requestedLimit) || requestedLimit < 1) {\n throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 422);\n }\n const limit = Math.min(collaborationBatchUpdates, requestedLimit);\n type CollaborationRow = { readonly id: string; readonly update: string; readonly cursorKey: string };\n const cursor = options.cursor === undefined ? undefined : decodeCollaborationCursor(options.cursor, id);\n const rows = await database.findMany<CollaborationRow>({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: id },\n { field: \"documentGeneration\", operator: \"eq\", value: document.collaborationGeneration },\n ...(cursor === undefined ? [] : [{ field: \"cursorKey\", operator: \"gt\" as const, value: cursor }]),\n ],\n orderBy: [{ field: \"cursorKey\", direction: \"asc\" }],\n limit: limit + 1,\n });\n const included: CollaborationRow[] = [];\n let encodedBytes = 0;\n for (const row of rows.slice(0, limit)) {\n const rowBytes = new TextEncoder().encode(row.update).byteLength;\n if (included.length > 0 && encodedBytes + rowBytes > collaborationBatchBytes) break;\n included.push(row);\n encodedBytes += rowBytes;\n }\n const hasMore = included.length < rows.length;\n return {\n updates: included.map((row) => row.update),\n includedUpdateIds: included.map((row) => row.id),\n ...(hasMore ? { nextCursor: encodeCollaborationCursor(id, included.at(-1)!.cursorKey) } : {}),\n };\n },\n async compactCollaborationUpdates(principal, id, snapshot, includedUpdateIds) {\n if (new TextEncoder().encode(snapshot).byteLength > collaborationUpdateBytes) throw new MdfnServerError(\"MDFN_COLLAB_UPDATE_TOO_LARGE\", 413);\n if (!Array.isArray(includedUpdateIds) || includedUpdateIds.some((updateId) => typeof updateId !== \"string\" || !updateId)) {\n throw new MdfnServerError(\"MDFN_COLLAB_COMPACTION_INVALID\", 422);\n }\n const uniqueUpdateIds = [...new Set(includedUpdateIds)];\n const updateId = createId();\n const createdAt = now();\n await withCollaborationWrite(principal, id, \"compact-collaboration\", async (storage, cursorKey, documentGeneration) => {\n if (uniqueUpdateIds.length > 0) {\n await storage.deleteMany({ model: COLLAB_UPDATES, where: [{ field: \"documentId\", operator: \"eq\", value: id }, { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration }, { field: \"id\", operator: \"in\", value: uniqueUpdateIds }] });\n }\n await storage.create({ model: COLLAB_UPDATES, data: { id: updateId, documentId: id, documentGeneration, authorId: principal.id, update: snapshot, cursorKey, createdAt } });\n });\n return updateId;\n },\n };\n return service;\n}\n\nfunction etag(document: MdfnDocumentRecord): string { return `\\\"mdfn-${document.version}-${document.sourceHash}\\\"`; }\nfunction response(document: MdfnDocumentRecord, status = 200): Response { return Response.json(document, { status, headers: { ETag: etag(document), \"Cache-Control\": \"no-store\" } }); }\nfunction idempotent<T extends { readonly idempotencyKey?: string }>(request: Request, body: T): T {\n return { ...body, idempotencyKey: body.idempotencyKey ?? request.headers.get(\"Idempotency-Key\") ?? undefined };\n}\n\nexport function createMdfnRouter(config: MdfnServerConfig, service = createMdfnService(config)): Router<{ principal: MdfnPrincipal }> {\n const principal = config.resolvePrincipal ?? (() => { throw new MdfnServerError(\"MDFN_UNAUTHENTICATED\", 401); });\n const defaultBodyBytes = Math.max(\n configuredDocumentBytes(config) + 4 * 1024 * 1024,\n configuredCollaborationUpdateBytes(config) + 64 * 1024,\n );\n return createRouter({\n basePath: config.basePath ?? \"/api/mdfn\",\n maxBodyBytes: config.maxRequestBodyBytes ?? defaultBodyBytes,\n context: async (request) => ({ principal: await principal(request) }),\n onError: (error) => error instanceof MdfnServerError\n ? Response.json({ error: error.code }, { status: error.status })\n : error instanceof RouterError\n ? error.toResponse()\n : Response.json({ error: \"MDFN_INTERNAL_ERROR\" }, { status: 500 }),\n routes: [\n { method: \"GET\", path: \"/documents\", handler: (_request, context) => service.list(context.principal, { limit: Number(context.query.get(\"limit\") ?? 50), offset: Number(context.query.get(\"offset\") ?? 0) }).then((documents) => Response.json({ documents })) },\n { method: \"POST\", path: \"/documents\", handler: async (_request, context) => response(await service.create(context.principal, await context.json()), 201) },\n { method: \"GET\", path: \"/documents/:id\", handler: async (_request, context) => response(await service.read(context.principal, context.params.id!)) },\n { method: \"PATCH\", path: \"/documents/:id\", handler: async (request, context) => response(await service.update(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"DELETE\", path: \"/documents/:id\", handler: async (_request, context) => { await service.delete(context.principal, context.params.id!); return new Response(null, { status: 204 }); } },\n { method: \"GET\", path: \"/documents/:id/versions\", handler: async (_request, context) => Response.json(await service.versions(context.principal, context.params.id!, { cursor: context.query.get(\"cursor\") ?? undefined, limit: context.query.has(\"limit\") ? Number(context.query.get(\"limit\")) : undefined })) },\n { method: \"GET\", path: \"/documents/:id/versions/:version\", handler: async (_request, context) => Response.json(await service.version(context.principal, context.params.id!, Number(context.params.version))) },\n { method: \"POST\", path: \"/documents/:id/restore\", handler: async (request, context) => response(await service.restoreVersion(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"GET\", path: \"/documents/:id/sidecar\", handler: async (_request, context) => Response.json((await service.read(context.principal, context.params.id!)).sidecar ?? {}) },\n { method: \"PUT\", path: \"/documents/:id/sidecar\", handler: async (request, context) => { const body = idempotent(request, await context.json<{ expectedVersion: number; sidecar: MdfnSidecar; idempotencyKey?: string }>()); return response(await service.update(context.principal, context.params.id!, { ...body, changeSource: \"sidecar\" })); } },\n { method: \"GET\", path: \"/documents/:id/audit\", handler: async (_request, context) => Response.json({ audit: (await service.read(context.principal, context.params.id!)).sidecar?.audit ?? [] }) },\n { method: \"POST\", path: \"/documents/:id/comments\", handler: async (request, context) => response(await service.createComment(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"POST\", path: \"/documents/:id/comments/:threadId/replies\", handler: async (request, context) => response(await service.replyComment(context.principal, context.params.id!, context.params.threadId!, idempotent(request, await context.json()))) },\n { method: \"PATCH\", path: \"/documents/:id/comments/:threadId\", handler: async (request, context) => response(await service.resolveComment(context.principal, context.params.id!, context.params.threadId!, idempotent(request, await context.json()))) },\n { method: \"POST\", path: \"/documents/:id/suggestions\", handler: async (request, context) => response(await service.createSuggestion(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"PATCH\", path: \"/documents/:id/suggestions/:suggestionId\", handler: async (request, context) => response(await service.decideSuggestion(context.principal, context.params.id!, context.params.suggestionId!, idempotent(request, await context.json()))) },\n { method: \"PUT\", path: \"/documents/:id/review\", handler: async (request, context) => response(await service.transitionReview(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"GET\", path: \"/documents/:id/collaboration-updates\", handler: async (_request, context) => Response.json(await service.collaborationUpdates(context.principal, context.params.id!, { cursor: context.query.get(\"cursor\") ?? undefined, limit: context.query.has(\"limit\") ? Number(context.query.get(\"limit\")) : undefined })) },\n { method: \"POST\", path: \"/documents/:id/collaboration-updates\", handler: async (_request, context) => { const body = await context.json<{ update: string }>(); return Response.json({ id: await service.appendCollaborationUpdate(context.principal, context.params.id!, body.update) }, { status: 201 }); } },\n { method: \"PUT\", path: \"/documents/:id/collaboration-updates/compact\", handler: async (_request, context) => { const body = await context.json<{ snapshot: string; includedUpdateIds: string[] }>(); return Response.json({ id: await service.compactCollaborationUpdates(context.principal, context.params.id!, body.snapshot, body.includedUpdateIds) }); } },\n ],\n });\n}\n\nexport function createMdfnServer(config: MdfnServerConfig): { readonly service: MdfnService; readonly router: Router<{ principal: MdfnPrincipal }>; readonly schema: ReturnType<typeof getSchema> } {\n const service = createMdfnService(config);\n return { service, router: createMdfnRouter(config, service), schema: getSchema() };\n}\n\nexport const MDFN_SERVER_VERSION = \"0.1.1\" as const;\n"],"mappings":"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","names":["left","right","updateId"]}
package/dist/index.d.cts CHANGED
@@ -154,6 +154,6 @@ declare function createMdfnServer(config: MdfnServerConfig): {
154
154
  }>;
155
155
  readonly schema: ReturnType<typeof getSchema>;
156
156
  };
157
- declare const MDFN_SERVER_VERSION: "0.1.0";
157
+ declare const MDFN_SERVER_VERSION: "0.1.1";
158
158
 
159
159
  export { MDFN_SERVER_SCHEMA_VERSION, MDFN_SERVER_VERSION, type MdfnCollaborationUpdateBatch, type MdfnDocumentRecord, type MdfnPrincipal, type MdfnServerAction, type MdfnServerConfig, MdfnServerError, type MdfnService, type MdfnVersionBatch, type MdfnVersionRecord, type MdfnVersionSummary, createMdfnRouter, createMdfnServer, createMdfnService, getSchema };
package/dist/index.d.ts CHANGED
@@ -154,6 +154,6 @@ declare function createMdfnServer(config: MdfnServerConfig): {
154
154
  }>;
155
155
  readonly schema: ReturnType<typeof getSchema>;
156
156
  };
157
- declare const MDFN_SERVER_VERSION: "0.1.0";
157
+ declare const MDFN_SERVER_VERSION: "0.1.1";
158
158
 
159
159
  export { MDFN_SERVER_SCHEMA_VERSION, MDFN_SERVER_VERSION, type MdfnCollaborationUpdateBatch, type MdfnDocumentRecord, type MdfnPrincipal, type MdfnServerAction, type MdfnServerConfig, MdfnServerError, type MdfnService, type MdfnVersionBatch, type MdfnVersionRecord, type MdfnVersionSummary, createMdfnRouter, createMdfnServer, createMdfnService, getSchema };
package/dist/index.js CHANGED
@@ -705,7 +705,7 @@ function createMdfnServer(config) {
705
705
  const service = createMdfnService(config);
706
706
  return { service, router: createMdfnRouter(config, service), schema: getSchema() };
707
707
  }
708
- var MDFN_SERVER_VERSION = "0.1.0";
708
+ var MDFN_SERVER_VERSION = "0.1.1";
709
709
  export {
710
710
  MDFN_SERVER_SCHEMA_VERSION,
711
711
  MDFN_SERVER_VERSION,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n createCommentThread,\n createEditor,\n createSuggestion,\n decideSuggestion,\n hashString,\n mapSidecar,\n replyToComment,\n resolveExtensions,\n setCommentResolved,\n transitionReview,\n validateMdfnSidecar,\n type MdfnExtension,\n type MdfnSidecar,\n type ReviewState,\n type SidecarAnchor,\n} from \"@mdfn/core\";\nimport { createMarkdownProjector, parseMarkdown, type MarkdownOptions } from \"@mdfn/markdown\";\nimport { wrapWithSchema, type Adapter, type TableSchema } from \"@superfunctions/db\";\nimport { createRouter, RouterError, type Router } from \"@superfunctions/http\";\n\nconst DOCUMENTS = \"mdfnDocuments\";\nconst VERSIONS = \"mdfnVersions\";\nconst RECEIPTS = \"mdfnReceipts\";\nconst COLLAB_UPDATES = \"mdfnCollaborationUpdates\";\nexport const MDFN_SERVER_SCHEMA_VERSION = 2;\n\nexport interface MdfnPrincipal { readonly id: string; readonly tenantId?: string; readonly roles?: readonly string[]; }\nexport type MdfnServerAction =\n | \"create\"\n | \"read\"\n | \"update\"\n | \"delete\"\n | \"history\"\n | \"history:restore\"\n | \"collaborate\"\n | \"compact-collaboration\"\n | \"comment:create\"\n | \"comment:reply\"\n | \"comment:resolve\"\n | \"suggestion:create\"\n | \"suggestion:decide\"\n | \"review:transition\";\n\nexport interface MdfnDocumentRecord {\n readonly id: string;\n /** Immutable identity for collaboration rows across delete/recreate cycles. */\n readonly collaborationGeneration: string;\n readonly ownerId: string;\n readonly tenantId?: string;\n readonly title?: string;\n readonly markdown: string;\n readonly sourceHash: string;\n readonly schemaHash: string;\n readonly sidecar?: MdfnSidecar;\n readonly version: number;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n}\n\nexport interface MdfnVersionRecord extends MdfnDocumentRecord { readonly documentId: string; readonly authorId: string; readonly changeSource: string; }\n\nexport type MdfnVersionSummary = Omit<MdfnVersionRecord, \"markdown\" | \"sidecar\">;\n\nexport interface MdfnVersionBatch {\n readonly versions: readonly MdfnVersionSummary[];\n readonly nextCursor?: string;\n}\n\nexport interface MdfnCollaborationUpdateBatch {\n readonly updates: readonly string[];\n /** Exact persisted update ids represented by `updates` and therefore safe to compact. */\n readonly includedUpdateIds: readonly string[];\n /** Opaque continuation for the next bounded batch, when more updates remain. */\n readonly nextCursor?: string;\n}\n\nexport interface MdfnServerConfig {\n readonly database: Adapter;\n readonly authorize: (action: MdfnServerAction, principal: MdfnPrincipal, document?: MdfnDocumentRecord) => boolean | Promise<boolean>;\n readonly resolvePrincipal?: (request: Request) => MdfnPrincipal | Promise<MdfnPrincipal>;\n readonly extensions?: readonly MdfnExtension[];\n readonly markdown?: MarkdownOptions;\n readonly basePath?: string;\n readonly createId?: () => string;\n /** Injectable lifecycle identity for deterministic hosts and tests. */\n readonly createCollaborationGeneration?: () => string;\n /** Injectable clock for deterministic hosts and tests. */\n readonly now?: () => Date;\n readonly maxCollaborationUpdateBytes?: number;\n readonly maxCollaborationBatchBytes?: number;\n readonly maxCollaborationBatchUpdates?: number;\n /** Maximum encoded request body accepted by JSON-writing routes. */\n readonly maxRequestBodyBytes?: number;\n /** Maximum UTF-8 bytes accepted for a persisted document title. */\n readonly maxTitleBytes?: number;\n /** Durable storage requires adapter transactions. Ephemeral is intended only for in-memory/test hosts. */\n readonly durability?: \"required\" | \"ephemeral\";\n}\n\nexport class MdfnServerError extends Error {\n constructor(readonly code: string, readonly status: number, message = code) { super(message); this.name = \"MdfnServerError\"; }\n}\n\nfunction configuredDocumentBytes(config: MdfnServerConfig): number {\n return config.markdown?.maxBytes ?? 2 * 1024 * 1024;\n}\n\nfunction configuredCollaborationUpdateBytes(config: MdfnServerConfig): number {\n if (config.maxCollaborationUpdateBytes !== undefined) return config.maxCollaborationUpdateBytes;\n const documentBytes = configuredDocumentBytes(config);\n const yjsOverhead = Math.max(64 * 1024, Math.ceil(documentBytes / 16));\n return 4 * Math.ceil((documentBytes + yjsOverhead) / 3);\n}\n\ninterface CollaborationCursor {\n readonly documentId: string;\n readonly key: string;\n}\n\nfunction collaborationCursorKey(previousKey?: string): string {\n const match = previousKey?.match(/^v2:(\\d{20})$/);\n if (previousKey?.startsWith(\"v2:\") && !match) throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 500);\n const sequence = (match ? BigInt(match[1]) : 0n) + 1n;\n const encoded = sequence.toString().padStart(20, \"0\");\n if (encoded.length > 20) throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_EXHAUSTED\", 500);\n return `v2:${encoded}`;\n}\n\nfunction isUniqueConflict(error: unknown): boolean {\n const value = error as { readonly code?: unknown; readonly message?: unknown; readonly cause?: unknown };\n const cause = value?.cause as { readonly code?: unknown; readonly message?: unknown } | undefined;\n return /(?:unique|duplicate|23505|p2002)/i.test([value?.code, value?.message, cause?.code, cause?.message].filter(Boolean).join(\" \"));\n}\n\nfunction encodeCollaborationCursor(documentId: string, key: string): string {\n return encodeURIComponent(JSON.stringify({ documentId, key }));\n}\n\nfunction decodeCollaborationCursor(cursor: string, documentId: string): string {\n try {\n const parsed = JSON.parse(decodeURIComponent(cursor)) as Partial<CollaborationCursor>;\n if (parsed.documentId !== documentId || typeof parsed.key !== \"string\" || !parsed.key) {\n throw new Error(\"invalid cursor\");\n }\n return parsed.key;\n } catch {\n throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 422);\n }\n}\n\nexport function getSchema(): { version: number; schemas: TableSchema[] } {\n const date = { type: \"date\" as const, required: true, dateValueType: \"date\" as const };\n return { version: MDFN_SERVER_SCHEMA_VERSION, schemas: [\n { modelName: DOCUMENTS, fields: { id: { type: \"string\", required: true }, collaborationGeneration: { type: \"string\", required: true }, ownerId: { type: \"string\", required: true }, tenantId: { type: \"string\" }, title: { type: \"string\" }, markdown: { type: \"string\", required: true }, sourceHash: { type: \"string\", required: true }, schemaHash: { type: \"string\", required: true }, sidecar: { type: \"json\" }, version: { type: \"number\", required: true }, createdAt: date, updatedAt: date }, indexes: [{ name: \"idx_mdfn_documents_owner\", fields: [\"ownerId\"] }, { name: \"idx_mdfn_documents_tenant\", fields: [\"tenantId\"] }] },\n { modelName: VERSIONS, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true }, collaborationGeneration: { type: \"string\", required: true }, ownerId: { type: \"string\", required: true }, tenantId: { type: \"string\" }, title: { type: \"string\" }, markdown: { type: \"string\", required: true }, sourceHash: { type: \"string\", required: true }, schemaHash: { type: \"string\", required: true }, sidecar: { type: \"json\" }, version: { type: \"number\", required: true }, authorId: { type: \"string\", required: true }, changeSource: { type: \"string\", required: true }, createdAt: date, updatedAt: date }, indexes: [{ name: \"idx_mdfn_versions_document_version\", fields: [\"documentId\", \"version\"], unique: true }] },\n { modelName: RECEIPTS, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true }, idempotencyKey: { type: \"string\", required: true }, operation: { type: \"string\", required: true }, payloadHash: { type: \"string\", required: true }, result: { type: \"json\", required: true }, createdAt: date }, indexes: [{ name: \"idx_mdfn_receipts_key\", fields: [\"documentId\", \"idempotencyKey\"], unique: true }] },\n { modelName: COLLAB_UPDATES, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true, references: { model: DOCUMENTS, field: \"id\", onDelete: \"cascade\" } }, documentGeneration: { type: \"string\", required: true }, authorId: { type: \"string\", required: true }, update: { type: \"string\", required: true }, cursorKey: { type: \"string\", required: true }, createdAt: date }, indexes: [{ name: \"idx_mdfn_collab_generation_cursor\", fields: [\"documentId\", \"documentGeneration\", \"cursorKey\"], unique: true }] },\n ] };\n}\n\nexport interface MdfnService {\n create(principal: MdfnPrincipal, input: { readonly id?: string; readonly title?: string; readonly markdown: string; readonly sidecar?: MdfnSidecar }): Promise<MdfnDocumentRecord>;\n read(principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord>;\n list(principal: MdfnPrincipal, options?: { readonly limit?: number; readonly offset?: number }): Promise<readonly MdfnDocumentRecord[]>;\n update(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly markdown?: string; readonly title?: string; readonly sidecar?: MdfnSidecar; readonly changeSource?: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n delete(principal: MdfnPrincipal, id: string): Promise<void>;\n versions(\n principal: MdfnPrincipal,\n id: string,\n options?: { readonly cursor?: string; readonly limit?: number },\n ): Promise<MdfnVersionBatch>;\n version(principal: MdfnPrincipal, id: string, version: number): Promise<MdfnVersionRecord>;\n restoreVersion(principal: MdfnPrincipal, id: string, input: { readonly version: number; readonly expectedVersion: number; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n createComment(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly anchor: SidecarAnchor; readonly body: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n replyComment(principal: MdfnPrincipal, id: string, threadId: string, input: { readonly expectedVersion: number; readonly body: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n resolveComment(principal: MdfnPrincipal, id: string, threadId: string, input: { readonly expectedVersion: number; readonly resolved: boolean; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n createSuggestion(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly anchor: SidecarAnchor; readonly replacement: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n decideSuggestion(principal: MdfnPrincipal, id: string, suggestionId: string, input: { readonly expectedVersion: number; readonly decision: \"accepted\" | \"rejected\"; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n transitionReview(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly state: ReviewState; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n appendCollaborationUpdate(principal: MdfnPrincipal, id: string, update: string): Promise<string>;\n collaborationUpdates(\n principal: MdfnPrincipal,\n id: string,\n options?: { readonly cursor?: string; readonly limit?: number },\n ): Promise<MdfnCollaborationUpdateBatch>;\n compactCollaborationUpdates(principal: MdfnPrincipal, id: string, snapshot: string, includedUpdateIds: readonly string[]): Promise<string>;\n}\n\nasync function allowed(config: MdfnServerConfig, action: MdfnServerAction, principal: MdfnPrincipal, document?: MdfnDocumentRecord): Promise<void> {\n if (!(await config.authorize(action, principal, document))) throw new MdfnServerError(\"MDFN_FORBIDDEN\", 403);\n}\n\nfunction whereId(id: string) { return [{ field: \"id\", operator: \"eq\" as const, value: id }]; }\n\nexport function createMdfnService(config: MdfnServerConfig): MdfnService {\n const database = wrapWithSchema(config.database, getSchema());\n if ((config.durability ?? \"required\") === \"required\") {\n if (!database.capabilities.transactions.supported) {\n throw new MdfnServerError(\"MDFN_TRANSACTIONAL_DATABASE_REQUIRED\", 500);\n }\n if (!database.capabilities.schema.constraints) {\n throw new MdfnServerError(\"MDFN_RELATIONAL_CONSTRAINTS_REQUIRED\", 500);\n }\n }\n const registry = resolveExtensions(config.extensions ?? []);\n const markdownOptions: MarkdownOptions = { ...config.markdown, extensions: registry };\n const createId = config.createId ?? (() => crypto.randomUUID());\n const createCollaborationGeneration = config.createCollaborationGeneration ?? (() => crypto.randomUUID());\n const now = config.now ?? (() => new Date());\n const collaborationUpdateBytes = configuredCollaborationUpdateBytes(config);\n const collaborationBatchBytes = Math.max(\n collaborationUpdateBytes,\n config.maxCollaborationBatchBytes ?? collaborationUpdateBytes * 4,\n );\n const collaborationBatchUpdates = Math.min(1_000, Math.max(1, config.maxCollaborationBatchUpdates ?? 100));\n const parse = (source: string, sidecar?: MdfnSidecar): void => {\n try {\n parseMarkdown(source, markdownOptions);\n validateMdfnSidecar(sidecar, { markdownLength: source.length });\n } catch {\n throw new MdfnServerError(\"MDFN_DOCUMENT_INVALID\", 422);\n }\n };\n type Storage = Pick<Adapter, \"create\" | \"findOne\" | \"findMany\" | \"update\" | \"delete\" | \"deleteMany\">;\n const loadFrom = async (storage: Pick<Adapter, \"findOne\">, id: string): Promise<MdfnDocumentRecord> => {\n const result = await storage.findOne<MdfnDocumentRecord>({ model: DOCUMENTS, where: whereId(id) });\n if (!result) throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n return result;\n };\n const load = (id: string): Promise<MdfnDocumentRecord> => loadFrom(database, id);\n const loadScopedFrom = async (storage: Pick<Adapter, \"findOne\">, principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord> => {\n const document = await loadFrom(storage, id);\n const inScope = principal.tenantId\n ? document.tenantId === principal.tenantId\n : document.tenantId === undefined && document.ownerId === principal.id;\n if (!inScope) throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n return document;\n };\n const loadScoped = (principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord> => loadScopedFrom(database, principal, id);\n const revision = (document: MdfnDocumentRecord, authorId: string, changeSource: string): MdfnVersionRecord => ({ ...document, id: `${document.id}:${document.version}`, documentId: document.id, authorId, changeSource });\n const withStorage = <T>(callback: (storage: Storage) => Promise<T>): Promise<T> => database.capabilities.transactions.supported\n ? database.transaction((transaction) => callback(transaction))\n : callback(database);\n const collaborationWriteTails = new Map<string, Promise<void>>();\n const serializeCollaborationWrite = async <T>(documentId: string, callback: () => Promise<T>): Promise<T> => {\n const previous = collaborationWriteTails.get(documentId) ?? Promise.resolve();\n let release!: () => void;\n const gate = new Promise<void>((resolve) => { release = resolve; });\n const tail = previous.then(() => gate);\n collaborationWriteTails.set(documentId, tail);\n await previous;\n try {\n return await callback();\n } finally {\n release();\n if (collaborationWriteTails.get(documentId) === tail) collaborationWriteTails.delete(documentId);\n }\n };\n const withCollaborationWrite = <T>(\n principal: MdfnPrincipal,\n documentId: string,\n action: \"collaborate\" | \"compact-collaboration\",\n callback: (storage: Storage, cursorKey: string, documentGeneration: string) => Promise<T>,\n ): Promise<T> => (\n serializeCollaborationWrite(documentId, async () => {\n const authorizedDocument = await loadScoped(principal, documentId);\n await allowed(config, action, principal, authorizedDocument);\n const documentGeneration = authorizedDocument.collaborationGeneration;\n let lastConflict: unknown;\n for (let attempt = 0; attempt < 5; attempt += 1) {\n try {\n const result = await withStorage(async (storage) => {\n const storedDocument = await loadScopedFrom(storage, principal, documentId);\n if (storedDocument.collaborationGeneration !== documentGeneration) {\n throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n }\n const latest = await storage.findMany<{ readonly cursorKey: string }>({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: documentId },\n { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration },\n ],\n select: [\"cursorKey\"],\n orderBy: [{ field: \"cursorKey\", direction: \"desc\" }],\n limit: 1,\n });\n return callback(storage, collaborationCursorKey(latest[0]?.cursorKey), documentGeneration);\n });\n let latestDocument: MdfnDocumentRecord | undefined;\n try {\n latestDocument = await loadScoped(principal, documentId);\n } catch (error) {\n if (!(error instanceof MdfnServerError && error.code === \"MDFN_DOCUMENT_NOT_FOUND\")) throw error;\n }\n if (latestDocument?.collaborationGeneration !== documentGeneration) {\n await database.deleteMany({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: documentId },\n { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration },\n ],\n });\n throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n }\n return result;\n } catch (error) {\n if (!isUniqueConflict(error)) throw error;\n lastConflict = error;\n }\n }\n throw lastConflict;\n })\n );\n let service!: MdfnService;\n const editorialActor = (principal: MdfnPrincipal) => ({ id: principal.id, createId, now: () => now().toISOString() });\n const maxTitleBytes = config.maxTitleBytes ?? 512;\n if (!Number.isSafeInteger(maxTitleBytes) || maxTitleBytes < 1) {\n throw new MdfnServerError(\"MDFN_TITLE_LIMIT_INVALID\", 500);\n }\n const validateTitle = (title: string | undefined): void => {\n if (title !== undefined && new TextEncoder().encode(title).byteLength > maxTitleBytes) {\n throw new MdfnServerError(\"MDFN_TITLE_TOO_LARGE\", 413);\n }\n };\n type UpdateInput = Parameters<MdfnService[\"update\"]>[2];\n type RestoreSnapshot = Pick<MdfnVersionRecord, \"title\" | \"markdown\" | \"sidecar\">;\n interface WriteUpdateOptions {\n readonly trustedEditorial?: boolean;\n readonly authorizationAction?: MdfnServerAction;\n readonly restoreSnapshot?: RestoreSnapshot;\n readonly idempotencyOperation?: string;\n readonly idempotencyPayload?: unknown;\n }\n const canonicalJson = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(canonicalJson);\n if (value === null || typeof value !== \"object\") return value;\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)\n .map(([key, entry]) => [key, canonicalJson(entry)]),\n );\n };\n const hashValue = (value: unknown): string => hashString(JSON.stringify(canonicalJson(value)));\n const protectedSidecar = (value: MdfnSidecar | undefined): string => JSON.stringify(canonicalJson({\n comments: value?.comments ?? [],\n suggestions: value?.suggestions ?? [],\n reviewState: value?.reviewState ?? \"draft\",\n audit: value?.audit ?? [],\n }));\n const coarseChangedRanges = (before: string, after: string, offset: number): Array<{ from: number; to: number; insertedLength: number }> => {\n const ranges: Array<{ from: number; to: number; insertedLength: number }> = [];\n const syncLength = 16;\n const initialLookahead = 2_048;\n let remainingSearchWork = 65_536;\n let left = 0;\n let right = 0;\n let position = offset;\n while (left < before.length || right < after.length) {\n while (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) {\n left += 1;\n right += 1;\n position += 1;\n }\n if (left === before.length && right === after.length) break;\n const from = position;\n let match: { left: number; right: number; cost: number } | undefined;\n let lookahead = initialLookahead;\n const beforeAnchors = new Map<string, number>();\n const afterAnchors = new Map<string, number>();\n let beforeScannedTo = left - 1;\n let afterScannedTo = right - 1;\n while (!match) {\n const beforeLimit = Math.min(before.length - syncLength, left + lookahead);\n for (let candidate = beforeScannedTo + 1; candidate <= beforeLimit; candidate += 1) {\n if (remainingSearchWork === 0) break;\n remainingSearchWork -= 1;\n const key = before.slice(candidate, candidate + syncLength);\n if (!beforeAnchors.has(key)) beforeAnchors.set(key, candidate);\n const matchingRight = afterAnchors.get(key);\n if (matchingRight !== undefined) {\n const cost = candidate - left + matchingRight - right;\n if (!match || cost < match.cost) match = { left: candidate, right: matchingRight, cost };\n }\n beforeScannedTo = candidate;\n }\n const afterLimit = Math.min(after.length - syncLength, right + lookahead);\n for (let candidate = afterScannedTo + 1; candidate <= afterLimit; candidate += 1) {\n if (remainingSearchWork === 0) break;\n remainingSearchWork -= 1;\n const key = after.slice(candidate, candidate + syncLength);\n if (!afterAnchors.has(key)) afterAnchors.set(key, candidate);\n const matchingLeft = beforeAnchors.get(key);\n if (matchingLeft !== undefined) {\n const cost = matchingLeft - left + candidate - right;\n if (!match || cost < match.cost) match = { left: matchingLeft, right: candidate, cost };\n }\n afterScannedTo = candidate;\n }\n const searchedAllBefore = before.length - left < syncLength || beforeScannedTo >= before.length - syncLength;\n const searchedAllAfter = after.length - right < syncLength || afterScannedTo >= after.length - syncLength;\n if (match || remainingSearchWork === 0 || (searchedAllBefore && searchedAllAfter)) break;\n lookahead = Math.min(\n Math.max(before.length - left, after.length - right),\n lookahead * 2,\n );\n }\n if (!match || match.cost === 0) {\n ranges.push({ from, to: from + before.length - left, insertedLength: after.length - right });\n break;\n }\n const removed = match.left - left;\n const insertedLength = match.right - right;\n ranges.push({ from, to: from + removed, insertedLength });\n left = match.left;\n right = match.right;\n position += insertedLength;\n }\n return ranges;\n };\n const changedRanges = (previous: string, next: string): Array<{ from: number; to: number; insertedLength: number }> => {\n if (previous === next) return [];\n let prefix = 0;\n while (prefix < previous.length && prefix < next.length && previous.charCodeAt(prefix) === next.charCodeAt(prefix)) prefix += 1;\n let previousEnd = previous.length;\n let nextEnd = next.length;\n while (previousEnd > prefix && nextEnd > prefix && previous.charCodeAt(previousEnd - 1) === next.charCodeAt(nextEnd - 1)) { previousEnd -= 1; nextEnd -= 1; }\n const before = previous.slice(prefix, previousEnd);\n const after = next.slice(prefix, nextEnd);\n if (before.length * after.length > 250_000) return coarseChangedRanges(before, after, prefix);\n const width = after.length + 1;\n const lcs = new Uint32Array((before.length + 1) * width);\n for (let left = before.length - 1; left >= 0; left -= 1) {\n for (let right = after.length - 1; right >= 0; right -= 1) {\n const index = left * width + right;\n lcs[index] = before.charCodeAt(left) === after.charCodeAt(right)\n ? lcs[(left + 1) * width + right + 1] + 1\n : Math.max(lcs[(left + 1) * width + right], lcs[index + 1]);\n }\n }\n const ranges: Array<{ from: number; to: number; insertedLength: number }> = [];\n let left = 0;\n let right = 0;\n let position = prefix;\n while (left < before.length || right < after.length) {\n if (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) {\n left += 1; right += 1; position += 1; continue;\n }\n const from = position;\n let removed = 0;\n let insertedLength = 0;\n while (left < before.length || right < after.length) {\n if (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) break;\n if (right < after.length && (left === before.length || lcs[left * width + right + 1] >= lcs[(left + 1) * width + right])) {\n right += 1; insertedLength += 1;\n } else {\n left += 1; removed += 1;\n }\n }\n ranges.push({ from, to: from + removed, insertedLength });\n position += insertedLength;\n }\n return ranges;\n };\n const mapForMarkdownChange = (sidecar: MdfnSidecar | undefined, previous: string, next: string): MdfnSidecar | undefined => {\n if (!sidecar || previous === next) return sidecar;\n return mapSidecar(sidecar, changedRanges(previous, next));\n };\n interface Receipt { readonly operation: string; readonly payloadHash: string; readonly result: MdfnDocumentRecord; }\n const replayReceipt = async (storage: Storage, documentId: string, idempotencyKey: string, operation: string, payloadHash: string): Promise<MdfnDocumentRecord | undefined> => {\n const receipt = await storage.findOne<Receipt>({ model: RECEIPTS, where: [{ field: \"documentId\", operator: \"eq\", value: documentId }, { field: \"idempotencyKey\", operator: \"eq\", value: idempotencyKey }] });\n if (!receipt) return undefined;\n if (receipt.operation !== operation || receipt.payloadHash !== payloadHash) throw new MdfnServerError(\"MDFN_IDEMPOTENCY_KEY_REUSED\", 409);\n return receipt.result;\n };\n const writeUpdate = async (principal: MdfnPrincipal, id: string, input: UpdateInput, options: WriteUpdateOptions = {}): Promise<MdfnDocumentRecord> => {\n const current = await loadScoped(principal, id);\n await allowed(config, options.authorizationAction ?? \"update\", principal, current);\n const operation = options.idempotencyOperation ?? \"document:update\";\n const payloadHash = hashValue(options.idempotencyPayload ?? {\n ...input,\n idempotencyKey: undefined,\n restoreSnapshot: options.restoreSnapshot,\n });\n if (input.idempotencyKey) {\n const replay = await replayReceipt(database, id, input.idempotencyKey, operation, payloadHash);\n if (replay) return replay;\n }\n if (current.version !== input.expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n const markdown = options.restoreSnapshot?.markdown ?? input.markdown ?? current.markdown;\n if (!options.trustedEditorial && input.sidecar && protectedSidecar(input.sidecar) !== protectedSidecar(current.sidecar)) {\n throw new MdfnServerError(\"MDFN_EDITORIAL_MUTATION_FORBIDDEN\", 403);\n }\n const mappedSidecar = mapForMarkdownChange(current.sidecar, current.markdown, markdown);\n const sidecar = options.restoreSnapshot\n ? options.restoreSnapshot.sidecar\n : options.trustedEditorial\n ? input.sidecar ?? mappedSidecar\n : input.sidecar\n ? {\n ...input.sidecar,\n comments: mappedSidecar?.comments,\n suggestions: mappedSidecar?.suggestions,\n reviewState: mappedSidecar?.reviewState,\n audit: mappedSidecar?.audit,\n }\n : mappedSidecar;\n parse(markdown, sidecar);\n const title = options.restoreSnapshot ? options.restoreSnapshot.title : input.title ?? current.title;\n validateTitle(title);\n const next: MdfnDocumentRecord = { ...current, title, markdown, sourceHash: hashString(markdown), schemaHash: registry.schemaHash, sidecar, version: current.version + 1, updatedAt: now() };\n return withStorage(async (storage) => {\n if (input.idempotencyKey) {\n const replay = await replayReceipt(storage, id, input.idempotencyKey, operation, payloadHash);\n if (replay) return replay;\n }\n const latest = await storage.findOne<MdfnDocumentRecord>({ model: DOCUMENTS, where: whereId(id) });\n if (!latest || latest.version !== input.expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n const updated = await storage.update<MdfnDocumentRecord>({ model: DOCUMENTS, where: [{ field: \"id\", operator: \"eq\", value: id }, { field: \"version\", operator: \"eq\", value: input.expectedVersion }], data: next });\n await storage.create({ model: VERSIONS, data: revision(updated, principal.id, input.changeSource ?? \"update\") });\n if (input.idempotencyKey) await storage.create({ model: RECEIPTS, data: { id: createId(), documentId: id, idempotencyKey: input.idempotencyKey, operation, payloadHash, result: updated, createdAt: now() } });\n return updated;\n });\n };\n const mutateEditorial = async (\n principal: MdfnPrincipal,\n id: string,\n expectedVersion: number,\n authorizationAction: MdfnServerAction,\n changeSource: string,\n idempotencyKey: string | undefined,\n idempotencyPayload: unknown,\n mutate: (document: MdfnDocumentRecord) => { readonly markdown?: string; readonly sidecar: MdfnSidecar },\n ): Promise<MdfnDocumentRecord> => {\n const current = await loadScoped(principal, id);\n await allowed(config, authorizationAction, principal, current);\n if (idempotencyKey) {\n const replay = await replayReceipt(database, id, idempotencyKey, changeSource, hashValue(idempotencyPayload));\n if (replay) return replay;\n }\n if (current.version !== expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n try {\n const next = mutate(current);\n return writeUpdate(principal, id, { expectedVersion, markdown: next.markdown, sidecar: next.sidecar, changeSource, idempotencyKey }, { trustedEditorial: true, authorizationAction, idempotencyOperation: changeSource, idempotencyPayload });\n } catch (error) {\n if (error instanceof MdfnServerError) throw error;\n throw new MdfnServerError(\"MDFN_EDITORIAL_INVALID\", 422);\n }\n };\n service = {\n async create(principal, input) {\n await allowed(config, \"create\", principal);\n parse(input.markdown, input.sidecar);\n validateTitle(input.title);\n if (input.id !== undefined && (typeof input.id !== \"string\" || input.id.trim().length === 0)) {\n throw new MdfnServerError(\"MDFN_DOCUMENT_ID_INVALID\", 422);\n }\n if (input.sidecar && protectedSidecar(input.sidecar) !== protectedSidecar(undefined)) {\n throw new MdfnServerError(\"MDFN_EDITORIAL_MUTATION_FORBIDDEN\", 403);\n }\n const createdAt = now();\n const collaborationGeneration = createCollaborationGeneration();\n if (typeof collaborationGeneration !== \"string\" || collaborationGeneration.length === 0) {\n throw new MdfnServerError(\"MDFN_COLLAB_GENERATION_INVALID\", 500);\n }\n const document: MdfnDocumentRecord = { id: input.id ?? createId(), collaborationGeneration, ownerId: principal.id, tenantId: principal.tenantId, title: input.title, markdown: input.markdown, sourceHash: hashString(input.markdown), schemaHash: registry.schemaHash, sidecar: input.sidecar, version: 1, createdAt, updatedAt: createdAt };\n return withStorage(async (storage) => {\n const created = await storage.create<MdfnDocumentRecord>({ model: DOCUMENTS, data: document });\n await storage.create({ model: VERSIONS, data: revision(created, principal.id, \"create\") });\n return created;\n });\n },\n async read(principal, id) { const document = await loadScoped(principal, id); await allowed(config, \"read\", principal, document); return document; },\n async list(principal, options = {}) {\n await allowed(config, \"read\", principal);\n const where = principal.tenantId ? [{ field: \"tenantId\", operator: \"eq\" as const, value: principal.tenantId }] : [{ field: \"ownerId\", operator: \"eq\" as const, value: principal.id }];\n const offset = Math.max(0, options.offset ?? 0);\n const limit = Math.min(100, Math.max(1, options.limit ?? 50));\n const pageSize = Math.max(25, limit);\n const visible: MdfnDocumentRecord[] = [];\n let databaseOffset = 0;\n let authorizedOffset = 0;\n while (visible.length < limit) {\n const candidates = await database.findMany<MdfnDocumentRecord>({\n model: DOCUMENTS,\n where,\n orderBy: [{ field: \"updatedAt\", direction: \"desc\" }, { field: \"id\", direction: \"desc\" }],\n limit: pageSize,\n offset: databaseOffset,\n });\n databaseOffset += candidates.length;\n for (const document of candidates) {\n if (!principal.tenantId && document.tenantId !== undefined && document.tenantId !== null) continue;\n if (!(await config.authorize(\"read\", principal, document))) continue;\n if (authorizedOffset < offset) {\n authorizedOffset += 1;\n continue;\n }\n visible.push(document);\n if (visible.length === limit) break;\n }\n if (candidates.length < pageSize) break;\n }\n return visible;\n },\n async update(principal, id, input) { return writeUpdate(principal, id, input); },\n async delete(principal, id) {\n await serializeCollaborationWrite(id, async () => {\n const current = await loadScoped(principal, id);\n await allowed(config, \"delete\", principal, current);\n await withStorage(async (storage) => {\n const documentWhere = [{ field: \"documentId\", operator: \"eq\" as const, value: id }];\n await storage.deleteMany({ model: COLLAB_UPDATES, where: documentWhere });\n await storage.deleteMany({ model: RECEIPTS, where: documentWhere });\n await storage.deleteMany({ model: VERSIONS, where: documentWhere });\n await storage.delete({ model: DOCUMENTS, where: whereId(id) });\n });\n });\n },\n async versions(principal, id, options = {}) {\n const document = await loadScoped(principal, id);\n await allowed(config, \"history\", principal, document);\n const cursor = options.cursor === undefined ? undefined : Number(options.cursor);\n const requestedLimit = options.limit ?? 50;\n if ((cursor !== undefined && (!Number.isSafeInteger(cursor) || cursor < 1)) ||\n !Number.isSafeInteger(requestedLimit) || requestedLimit < 1) {\n throw new MdfnServerError(\"MDFN_VERSION_CURSOR_INVALID\", 422);\n }\n const limit = Math.min(100, requestedLimit);\n const where = [\n { field: \"documentId\", operator: \"eq\" as const, value: id },\n ...(cursor === undefined ? [] : [{ field: \"version\", operator: \"lt\" as const, value: cursor }]),\n ];\n const rows = await database.findMany<MdfnVersionSummary>({\n model: VERSIONS,\n where,\n select: [\n \"id\", \"documentId\", \"collaborationGeneration\", \"ownerId\", \"tenantId\", \"title\", \"sourceHash\", \"schemaHash\",\n \"version\", \"authorId\", \"changeSource\", \"createdAt\", \"updatedAt\",\n ],\n orderBy: [{ field: \"version\", direction: \"desc\" }],\n limit: limit + 1,\n });\n const versions = rows.slice(0, limit);\n return {\n versions,\n ...(rows.length > limit ? { nextCursor: String(versions.at(-1)!.version) } : {}),\n };\n },\n async version(principal, id, version) { const document = await loadScoped(principal, id); await allowed(config, \"history\", principal, document); const result = await database.findOne<MdfnVersionRecord>({ model: VERSIONS, where: [{ field: \"documentId\", operator: \"eq\", value: id }, { field: \"version\", operator: \"eq\", value: version }] }); if (!result) throw new MdfnServerError(\"MDFN_VERSION_NOT_FOUND\", 404); return result; },\n async restoreVersion(principal, id, input) {\n const current = await loadScoped(principal, id);\n await allowed(config, \"history:restore\", principal, current);\n const restored = await database.findOne<MdfnVersionRecord>({\n model: VERSIONS,\n where: [\n { field: \"documentId\", operator: \"eq\", value: id },\n { field: \"version\", operator: \"eq\", value: input.version },\n ],\n });\n if (!restored) throw new MdfnServerError(\"MDFN_VERSION_NOT_FOUND\", 404);\n return writeUpdate(\n principal,\n id,\n { expectedVersion: input.expectedVersion, changeSource: `restore:${input.version}`, idempotencyKey: input.idempotencyKey },\n {\n trustedEditorial: true,\n authorizationAction: \"history:restore\",\n restoreSnapshot: restored,\n idempotencyOperation: \"document:restore\",\n idempotencyPayload: input,\n },\n );\n },\n async createComment(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:create\", \"editorial:comment-created\", input.idempotencyKey, input, (document) => createCommentThread({ sidecar: document.sidecar, anchor: input.anchor, body: input.body, actor: editorialActor(principal), markdownLength: document.markdown.length }));\n },\n async replyComment(principal, id, threadId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:reply\", \"editorial:comment-replied\", input.idempotencyKey, { threadId, ...input }, (document) => ({ sidecar: replyToComment({ sidecar: document.sidecar ?? {}, threadId, body: input.body, actor: editorialActor(principal) }) }));\n },\n async resolveComment(principal, id, threadId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:resolve\", input.resolved ? \"editorial:comment-resolved\" : \"editorial:comment-reopened\", input.idempotencyKey, { threadId, ...input }, (document) => ({ sidecar: setCommentResolved({ sidecar: document.sidecar ?? {}, threadId, resolved: input.resolved, actor: editorialActor(principal) }) }));\n },\n async createSuggestion(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"suggestion:create\", \"editorial:suggestion-created\", input.idempotencyKey, input, (document) => createSuggestion({ sidecar: document.sidecar, anchor: input.anchor, replacement: input.replacement, actor: editorialActor(principal), markdownLength: document.markdown.length }));\n },\n async decideSuggestion(principal, id, suggestionId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"suggestion:decide\", `editorial:suggestion-${input.decision}`, input.idempotencyKey, { suggestionId, ...input }, (document) => {\n const controller = createEditor({ markdown: document.markdown, projector: createMarkdownProjector(markdownOptions), extensions: config.extensions, sidecar: document.sidecar });\n try {\n decideSuggestion({ controller, suggestionId, decision: input.decision, actor: editorialActor(principal) });\n const state = controller.getState();\n return { markdown: state.markdown, sidecar: state.sidecar ?? {} };\n } finally { controller.destroy(); }\n });\n },\n async transitionReview(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"review:transition\", \"editorial:review-transitioned\", input.idempotencyKey, input, (document) => ({ sidecar: transitionReview({ sidecar: document.sidecar, to: input.state, actor: editorialActor(principal) }) }));\n },\n async appendCollaborationUpdate(principal, id, update) {\n if (new TextEncoder().encode(update).byteLength > collaborationUpdateBytes) throw new MdfnServerError(\"MDFN_COLLAB_UPDATE_TOO_LARGE\", 413);\n const updateId = createId();\n const createdAt = now();\n await withCollaborationWrite(principal, id, \"collaborate\", async (storage, cursorKey, documentGeneration) => {\n await storage.create({\n model: COLLAB_UPDATES,\n data: { id: updateId, documentId: id, documentGeneration, authorId: principal.id, update, cursorKey, createdAt },\n });\n });\n return updateId;\n },\n async collaborationUpdates(principal, id, options = {}) {\n const document = await loadScoped(principal, id);\n await allowed(config, \"collaborate\", principal, document);\n const requestedLimit = options.limit ?? collaborationBatchUpdates;\n if (!Number.isSafeInteger(requestedLimit) || requestedLimit < 1) {\n throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 422);\n }\n const limit = Math.min(collaborationBatchUpdates, requestedLimit);\n type CollaborationRow = { readonly id: string; readonly update: string; readonly cursorKey: string };\n const cursor = options.cursor === undefined ? undefined : decodeCollaborationCursor(options.cursor, id);\n const rows = await database.findMany<CollaborationRow>({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: id },\n { field: \"documentGeneration\", operator: \"eq\", value: document.collaborationGeneration },\n ...(cursor === undefined ? [] : [{ field: \"cursorKey\", operator: \"gt\" as const, value: cursor }]),\n ],\n orderBy: [{ field: \"cursorKey\", direction: \"asc\" }],\n limit: limit + 1,\n });\n const included: CollaborationRow[] = [];\n let encodedBytes = 0;\n for (const row of rows.slice(0, limit)) {\n const rowBytes = new TextEncoder().encode(row.update).byteLength;\n if (included.length > 0 && encodedBytes + rowBytes > collaborationBatchBytes) break;\n included.push(row);\n encodedBytes += rowBytes;\n }\n const hasMore = included.length < rows.length;\n return {\n updates: included.map((row) => row.update),\n includedUpdateIds: included.map((row) => row.id),\n ...(hasMore ? { nextCursor: encodeCollaborationCursor(id, included.at(-1)!.cursorKey) } : {}),\n };\n },\n async compactCollaborationUpdates(principal, id, snapshot, includedUpdateIds) {\n if (new TextEncoder().encode(snapshot).byteLength > collaborationUpdateBytes) throw new MdfnServerError(\"MDFN_COLLAB_UPDATE_TOO_LARGE\", 413);\n if (!Array.isArray(includedUpdateIds) || includedUpdateIds.some((updateId) => typeof updateId !== \"string\" || !updateId)) {\n throw new MdfnServerError(\"MDFN_COLLAB_COMPACTION_INVALID\", 422);\n }\n const uniqueUpdateIds = [...new Set(includedUpdateIds)];\n const updateId = createId();\n const createdAt = now();\n await withCollaborationWrite(principal, id, \"compact-collaboration\", async (storage, cursorKey, documentGeneration) => {\n if (uniqueUpdateIds.length > 0) {\n await storage.deleteMany({ model: COLLAB_UPDATES, where: [{ field: \"documentId\", operator: \"eq\", value: id }, { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration }, { field: \"id\", operator: \"in\", value: uniqueUpdateIds }] });\n }\n await storage.create({ model: COLLAB_UPDATES, data: { id: updateId, documentId: id, documentGeneration, authorId: principal.id, update: snapshot, cursorKey, createdAt } });\n });\n return updateId;\n },\n };\n return service;\n}\n\nfunction etag(document: MdfnDocumentRecord): string { return `\\\"mdfn-${document.version}-${document.sourceHash}\\\"`; }\nfunction response(document: MdfnDocumentRecord, status = 200): Response { return Response.json(document, { status, headers: { ETag: etag(document), \"Cache-Control\": \"no-store\" } }); }\nfunction idempotent<T extends { readonly idempotencyKey?: string }>(request: Request, body: T): T {\n return { ...body, idempotencyKey: body.idempotencyKey ?? request.headers.get(\"Idempotency-Key\") ?? undefined };\n}\n\nexport function createMdfnRouter(config: MdfnServerConfig, service = createMdfnService(config)): Router<{ principal: MdfnPrincipal }> {\n const principal = config.resolvePrincipal ?? (() => { throw new MdfnServerError(\"MDFN_UNAUTHENTICATED\", 401); });\n const defaultBodyBytes = Math.max(\n configuredDocumentBytes(config) + 4 * 1024 * 1024,\n configuredCollaborationUpdateBytes(config) + 64 * 1024,\n );\n return createRouter({\n basePath: config.basePath ?? \"/api/mdfn\",\n maxBodyBytes: config.maxRequestBodyBytes ?? defaultBodyBytes,\n context: async (request) => ({ principal: await principal(request) }),\n onError: (error) => error instanceof MdfnServerError\n ? Response.json({ error: error.code }, { status: error.status })\n : error instanceof RouterError\n ? error.toResponse()\n : Response.json({ error: \"MDFN_INTERNAL_ERROR\" }, { status: 500 }),\n routes: [\n { method: \"GET\", path: \"/documents\", handler: (_request, context) => service.list(context.principal, { limit: Number(context.query.get(\"limit\") ?? 50), offset: Number(context.query.get(\"offset\") ?? 0) }).then((documents) => Response.json({ documents })) },\n { method: \"POST\", path: \"/documents\", handler: async (_request, context) => response(await service.create(context.principal, await context.json()), 201) },\n { method: \"GET\", path: \"/documents/:id\", handler: async (_request, context) => response(await service.read(context.principal, context.params.id!)) },\n { method: \"PATCH\", path: \"/documents/:id\", handler: async (request, context) => response(await service.update(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"DELETE\", path: \"/documents/:id\", handler: async (_request, context) => { await service.delete(context.principal, context.params.id!); return new Response(null, { status: 204 }); } },\n { method: \"GET\", path: \"/documents/:id/versions\", handler: async (_request, context) => Response.json(await service.versions(context.principal, context.params.id!, { cursor: context.query.get(\"cursor\") ?? undefined, limit: context.query.has(\"limit\") ? Number(context.query.get(\"limit\")) : undefined })) },\n { method: \"GET\", path: \"/documents/:id/versions/:version\", handler: async (_request, context) => Response.json(await service.version(context.principal, context.params.id!, Number(context.params.version))) },\n { method: \"POST\", path: \"/documents/:id/restore\", handler: async (request, context) => response(await service.restoreVersion(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"GET\", path: \"/documents/:id/sidecar\", handler: async (_request, context) => Response.json((await service.read(context.principal, context.params.id!)).sidecar ?? {}) },\n { method: \"PUT\", path: \"/documents/:id/sidecar\", handler: async (request, context) => { const body = idempotent(request, await context.json<{ expectedVersion: number; sidecar: MdfnSidecar; idempotencyKey?: string }>()); return response(await service.update(context.principal, context.params.id!, { ...body, changeSource: \"sidecar\" })); } },\n { method: \"GET\", path: \"/documents/:id/audit\", handler: async (_request, context) => Response.json({ audit: (await service.read(context.principal, context.params.id!)).sidecar?.audit ?? [] }) },\n { method: \"POST\", path: \"/documents/:id/comments\", handler: async (request, context) => response(await service.createComment(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"POST\", path: \"/documents/:id/comments/:threadId/replies\", handler: async (request, context) => response(await service.replyComment(context.principal, context.params.id!, context.params.threadId!, idempotent(request, await context.json()))) },\n { method: \"PATCH\", path: \"/documents/:id/comments/:threadId\", handler: async (request, context) => response(await service.resolveComment(context.principal, context.params.id!, context.params.threadId!, idempotent(request, await context.json()))) },\n { method: \"POST\", path: \"/documents/:id/suggestions\", handler: async (request, context) => response(await service.createSuggestion(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"PATCH\", path: \"/documents/:id/suggestions/:suggestionId\", handler: async (request, context) => response(await service.decideSuggestion(context.principal, context.params.id!, context.params.suggestionId!, idempotent(request, await context.json()))) },\n { method: \"PUT\", path: \"/documents/:id/review\", handler: async (request, context) => response(await service.transitionReview(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"GET\", path: \"/documents/:id/collaboration-updates\", handler: async (_request, context) => Response.json(await service.collaborationUpdates(context.principal, context.params.id!, { cursor: context.query.get(\"cursor\") ?? undefined, limit: context.query.has(\"limit\") ? Number(context.query.get(\"limit\")) : undefined })) },\n { method: \"POST\", path: \"/documents/:id/collaboration-updates\", handler: async (_request, context) => { const body = await context.json<{ update: string }>(); return Response.json({ id: await service.appendCollaborationUpdate(context.principal, context.params.id!, body.update) }, { status: 201 }); } },\n { method: \"PUT\", path: \"/documents/:id/collaboration-updates/compact\", handler: async (_request, context) => { const body = await context.json<{ snapshot: string; includedUpdateIds: string[] }>(); return Response.json({ id: await service.compactCollaborationUpdates(context.principal, context.params.id!, body.snapshot, body.includedUpdateIds) }); } },\n ],\n });\n}\n\nexport function createMdfnServer(config: MdfnServerConfig): { readonly service: MdfnService; readonly router: Router<{ principal: MdfnPrincipal }>; readonly schema: ReturnType<typeof getSchema> } {\n const service = createMdfnService(config);\n return { service, router: createMdfnRouter(config, service), schema: getSchema() };\n}\n\nexport const MDFN_SERVER_VERSION = \"0.1.0\" as const;\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP,SAAS,yBAAyB,qBAA2C;AAC7E,SAAS,sBAAsD;AAC/D,SAAS,cAAc,mBAAgC;AAEvD,IAAM,YAAY;AAClB,IAAM,WAAW;AACjB,IAAM,WAAW;AACjB,IAAM,iBAAiB;AAChB,IAAM,6BAA6B;AA2EnC,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YAAqB,MAAuB,QAAgB,UAAU,MAAM;AAAE,UAAM,OAAO;AAAtE;AAAuB;AAAkD,SAAK,OAAO;AAAA,EAAmB;AAAA,EAAxG;AAAA,EAAuB;AAC9C;AAEA,SAAS,wBAAwB,QAAkC;AACjE,SAAO,OAAO,UAAU,YAAY,IAAI,OAAO;AACjD;AAEA,SAAS,mCAAmC,QAAkC;AAC5E,MAAI,OAAO,gCAAgC,OAAW,QAAO,OAAO;AACpE,QAAM,gBAAgB,wBAAwB,MAAM;AACpD,QAAM,cAAc,KAAK,IAAI,KAAK,MAAM,KAAK,KAAK,gBAAgB,EAAE,CAAC;AACrE,SAAO,IAAI,KAAK,MAAM,gBAAgB,eAAe,CAAC;AACxD;AAOA,SAAS,uBAAuB,aAA8B;AAC5D,QAAM,QAAQ,aAAa,MAAM,eAAe;AAChD,MAAI,aAAa,WAAW,KAAK,KAAK,CAAC,MAAO,OAAM,IAAI,gBAAgB,8BAA8B,GAAG;AACzG,QAAM,YAAY,QAAQ,OAAO,MAAM,CAAC,CAAC,IAAI,MAAM;AACnD,QAAM,UAAU,SAAS,SAAS,EAAE,SAAS,IAAI,GAAG;AACpD,MAAI,QAAQ,SAAS,GAAI,OAAM,IAAI,gBAAgB,gCAAgC,GAAG;AACtF,SAAO,MAAM,OAAO;AACtB;AAEA,SAAS,iBAAiB,OAAyB;AACjD,QAAM,QAAQ;AACd,QAAM,QAAQ,OAAO;AACrB,SAAO,oCAAoC,KAAK,CAAC,OAAO,MAAM,OAAO,SAAS,OAAO,MAAM,OAAO,OAAO,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CAAC;AACtI;AAEA,SAAS,0BAA0B,YAAoB,KAAqB;AAC1E,SAAO,mBAAmB,KAAK,UAAU,EAAE,YAAY,IAAI,CAAC,CAAC;AAC/D;AAEA,SAAS,0BAA0B,QAAgB,YAA4B;AAC7E,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,mBAAmB,MAAM,CAAC;AACpD,QAAI,OAAO,eAAe,cAAc,OAAO,OAAO,QAAQ,YAAY,CAAC,OAAO,KAAK;AACrF,YAAM,IAAI,MAAM,gBAAgB;AAAA,IAClC;AACA,WAAO,OAAO;AAAA,EAChB,QAAQ;AACN,UAAM,IAAI,gBAAgB,8BAA8B,GAAG;AAAA,EAC7D;AACF;AAEO,SAAS,YAAyD;AACvE,QAAM,OAAO,EAAE,MAAM,QAAiB,UAAU,MAAM,eAAe,OAAgB;AACrF,SAAO,EAAE,SAAS,4BAA4B,SAAS;AAAA,IACrD,EAAE,WAAW,WAAW,QAAQ,EAAE,IAAI,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,yBAAyB,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,SAAS,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,UAAU,EAAE,MAAM,SAAS,GAAG,OAAO,EAAE,MAAM,SAAS,GAAG,UAAU,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,YAAY,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,YAAY,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,SAAS,EAAE,MAAM,OAAO,GAAG,SAAS,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,WAAW,MAAM,WAAW,KAAK,GAAG,SAAS,CAAC,EAAE,MAAM,4BAA4B,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,6BAA6B,QAAQ,CAAC,UAAU,EAAE,CAAC,EAAE;AAAA,IACzmB,EAAE,WAAW,UAAU,QAAQ,EAAE,IAAI,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,YAAY,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,yBAAyB,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,SAAS,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,UAAU,EAAE,MAAM,SAAS,GAAG,OAAO,EAAE,MAAM,SAAS,GAAG,UAAU,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,YAAY,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,YAAY,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,SAAS,EAAE,MAAM,OAAO,GAAG,SAAS,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,UAAU,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,cAAc,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,WAAW,MAAM,WAAW,KAAK,GAAG,SAAS,CAAC,EAAE,MAAM,sCAAsC,QAAQ,CAAC,cAAc,SAAS,GAAG,QAAQ,KAAK,CAAC,EAAE;AAAA,IACjuB,EAAE,WAAW,UAAU,QAAQ,EAAE,IAAI,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,YAAY,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,gBAAgB,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,WAAW,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,aAAa,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,QAAQ,EAAE,MAAM,QAAQ,UAAU,KAAK,GAAG,WAAW,KAAK,GAAG,SAAS,CAAC,EAAE,MAAM,yBAAyB,QAAQ,CAAC,cAAc,gBAAgB,GAAG,QAAQ,KAAK,CAAC,EAAE;AAAA,IAC/a,EAAE,WAAW,gBAAgB,QAAQ,EAAE,IAAI,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,YAAY,EAAE,MAAM,UAAU,UAAU,MAAM,YAAY,EAAE,OAAO,WAAW,OAAO,MAAM,UAAU,UAAU,EAAE,GAAG,oBAAoB,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,UAAU,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,QAAQ,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,WAAW,EAAE,MAAM,UAAU,UAAU,KAAK,GAAG,WAAW,KAAK,GAAG,SAAS,CAAC,EAAE,MAAM,qCAAqC,QAAQ,CAAC,cAAc,sBAAsB,WAAW,GAAG,QAAQ,KAAK,CAAC,EAAE;AAAA,EAC3hB,EAAE;AACJ;AA8BA,eAAe,QAAQ,QAA0B,QAA0B,WAA0B,UAA8C;AACjJ,MAAI,CAAE,MAAM,OAAO,UAAU,QAAQ,WAAW,QAAQ,EAAI,OAAM,IAAI,gBAAgB,kBAAkB,GAAG;AAC7G;AAEA,SAAS,QAAQ,IAAY;AAAE,SAAO,CAAC,EAAE,OAAO,MAAM,UAAU,MAAe,OAAO,GAAG,CAAC;AAAG;AAEtF,SAAS,kBAAkB,QAAuC;AACvE,QAAM,WAAW,eAAe,OAAO,UAAU,UAAU,CAAC;AAC5D,OAAK,OAAO,cAAc,gBAAgB,YAAY;AACpD,QAAI,CAAC,SAAS,aAAa,aAAa,WAAW;AACjD,YAAM,IAAI,gBAAgB,wCAAwC,GAAG;AAAA,IACvE;AACA,QAAI,CAAC,SAAS,aAAa,OAAO,aAAa;AAC7C,YAAM,IAAI,gBAAgB,wCAAwC,GAAG;AAAA,IACvE;AAAA,EACF;AACA,QAAM,WAAW,kBAAkB,OAAO,cAAc,CAAC,CAAC;AAC1D,QAAM,kBAAmC,EAAE,GAAG,OAAO,UAAU,YAAY,SAAS;AACpF,QAAM,WAAW,OAAO,aAAa,MAAM,OAAO,WAAW;AAC7D,QAAM,gCAAgC,OAAO,kCAAkC,MAAM,OAAO,WAAW;AACvG,QAAM,MAAM,OAAO,QAAQ,MAAM,oBAAI,KAAK;AAC1C,QAAM,2BAA2B,mCAAmC,MAAM;AAC1E,QAAM,0BAA0B,KAAK;AAAA,IACnC;AAAA,IACA,OAAO,8BAA8B,2BAA2B;AAAA,EAClE;AACA,QAAM,4BAA4B,KAAK,IAAI,KAAO,KAAK,IAAI,GAAG,OAAO,gCAAgC,GAAG,CAAC;AACzG,QAAM,QAAQ,CAAC,QAAgB,YAAgC;AAC7D,QAAI;AACF,oBAAc,QAAQ,eAAe;AACrC,0BAAoB,SAAS,EAAE,gBAAgB,OAAO,OAAO,CAAC;AAAA,IAChE,QAAQ;AACN,YAAM,IAAI,gBAAgB,yBAAyB,GAAG;AAAA,IACxD;AAAA,EACF;AAEA,QAAM,WAAW,OAAO,SAAmC,OAA4C;AACrG,UAAM,SAAS,MAAM,QAAQ,QAA4B,EAAE,OAAO,WAAW,OAAO,QAAQ,EAAE,EAAE,CAAC;AACjG,QAAI,CAAC,OAAQ,OAAM,IAAI,gBAAgB,2BAA2B,GAAG;AACrE,WAAO;AAAA,EACT;AACA,QAAM,OAAO,CAAC,OAA4C,SAAS,UAAU,EAAE;AAC/E,QAAM,iBAAiB,OAAO,SAAmC,WAA0B,OAA4C;AACrI,UAAM,WAAW,MAAM,SAAS,SAAS,EAAE;AAC3C,UAAM,UAAU,UAAU,WACtB,SAAS,aAAa,UAAU,WAChC,SAAS,aAAa,UAAa,SAAS,YAAY,UAAU;AACtE,QAAI,CAAC,QAAS,OAAM,IAAI,gBAAgB,2BAA2B,GAAG;AACtE,WAAO;AAAA,EACT;AACA,QAAM,aAAa,CAAC,WAA0B,OAA4C,eAAe,UAAU,WAAW,EAAE;AAChI,QAAM,WAAW,CAAC,UAA8B,UAAkB,kBAA6C,EAAE,GAAG,UAAU,IAAI,GAAG,SAAS,EAAE,IAAI,SAAS,OAAO,IAAI,YAAY,SAAS,IAAI,UAAU,aAAa;AACxN,QAAM,cAAc,CAAI,aAA2D,SAAS,aAAa,aAAa,YAClH,SAAS,YAAY,CAAC,gBAAgB,SAAS,WAAW,CAAC,IAC3D,SAAS,QAAQ;AACrB,QAAM,0BAA0B,oBAAI,IAA2B;AAC/D,QAAM,8BAA8B,OAAU,YAAoB,aAA2C;AAC3G,UAAM,WAAW,wBAAwB,IAAI,UAAU,KAAK,QAAQ,QAAQ;AAC5E,QAAI;AACJ,UAAM,OAAO,IAAI,QAAc,CAAC,YAAY;AAAE,gBAAU;AAAA,IAAS,CAAC;AAClE,UAAM,OAAO,SAAS,KAAK,MAAM,IAAI;AACrC,4BAAwB,IAAI,YAAY,IAAI;AAC5C,UAAM;AACN,QAAI;AACF,aAAO,MAAM,SAAS;AAAA,IACxB,UAAE;AACA,cAAQ;AACR,UAAI,wBAAwB,IAAI,UAAU,MAAM,KAAM,yBAAwB,OAAO,UAAU;AAAA,IACjG;AAAA,EACF;AACA,QAAM,yBAAyB,CAC7B,WACA,YACA,QACA,aAEA,4BAA4B,YAAY,YAAY;AAClD,UAAM,qBAAqB,MAAM,WAAW,WAAW,UAAU;AACjE,UAAM,QAAQ,QAAQ,QAAQ,WAAW,kBAAkB;AAC3D,UAAM,qBAAqB,mBAAmB;AAC9C,QAAI;AACJ,aAAS,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG;AAC/C,UAAI;AACF,cAAM,SAAS,MAAM,YAAY,OAAO,YAAY;AAClD,gBAAM,iBAAiB,MAAM,eAAe,SAAS,WAAW,UAAU;AAC1E,cAAI,eAAe,4BAA4B,oBAAoB;AACjE,kBAAM,IAAI,gBAAgB,2BAA2B,GAAG;AAAA,UAC1D;AACA,gBAAM,SAAS,MAAM,QAAQ,SAAyC;AAAA,YACpE,OAAO;AAAA,YACP,OAAO;AAAA,cACL,EAAE,OAAO,cAAc,UAAU,MAAM,OAAO,WAAW;AAAA,cACzD,EAAE,OAAO,sBAAsB,UAAU,MAAM,OAAO,mBAAmB;AAAA,YAC3E;AAAA,YACA,QAAQ,CAAC,WAAW;AAAA,YACpB,SAAS,CAAC,EAAE,OAAO,aAAa,WAAW,OAAO,CAAC;AAAA,YACnD,OAAO;AAAA,UACT,CAAC;AACD,iBAAO,SAAS,SAAS,uBAAuB,OAAO,CAAC,GAAG,SAAS,GAAG,kBAAkB;AAAA,QAC3F,CAAC;AACD,YAAI;AACJ,YAAI;AACF,2BAAiB,MAAM,WAAW,WAAW,UAAU;AAAA,QACzD,SAAS,OAAO;AACd,cAAI,EAAE,iBAAiB,mBAAmB,MAAM,SAAS,2BAA4B,OAAM;AAAA,QAC7F;AACA,YAAI,gBAAgB,4BAA4B,oBAAoB;AAClE,gBAAM,SAAS,WAAW;AAAA,YACxB,OAAO;AAAA,YACP,OAAO;AAAA,cACL,EAAE,OAAO,cAAc,UAAU,MAAM,OAAO,WAAW;AAAA,cACzD,EAAE,OAAO,sBAAsB,UAAU,MAAM,OAAO,mBAAmB;AAAA,YAC3E;AAAA,UACF,CAAC;AACD,gBAAM,IAAI,gBAAgB,2BAA2B,GAAG;AAAA,QAC1D;AACA,eAAO;AAAA,MACT,SAAS,OAAO;AACd,YAAI,CAAC,iBAAiB,KAAK,EAAG,OAAM;AACpC,uBAAe;AAAA,MACjB;AAAA,IACF;AACA,UAAM;AAAA,EACR,CAAC;AAEH,MAAI;AACJ,QAAM,iBAAiB,CAAC,eAA8B,EAAE,IAAI,UAAU,IAAI,UAAU,KAAK,MAAM,IAAI,EAAE,YAAY,EAAE;AACnH,QAAM,gBAAgB,OAAO,iBAAiB;AAC9C,MAAI,CAAC,OAAO,cAAc,aAAa,KAAK,gBAAgB,GAAG;AAC7D,UAAM,IAAI,gBAAgB,4BAA4B,GAAG;AAAA,EAC3D;AACA,QAAM,gBAAgB,CAAC,UAAoC;AACzD,QAAI,UAAU,UAAa,IAAI,YAAY,EAAE,OAAO,KAAK,EAAE,aAAa,eAAe;AACrF,YAAM,IAAI,gBAAgB,wBAAwB,GAAG;AAAA,IACvD;AAAA,EACF;AAUA,QAAM,gBAAgB,CAAC,UAA4B;AACjD,QAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,aAAa;AACxD,QAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,WAAO,OAAO;AAAA,MACZ,OAAO,QAAQ,KAAgC,EAC5C,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MAAM,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC,EAClE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,cAAc,KAAK,CAAC,CAAC;AAAA,IACtD;AAAA,EACF;AACA,QAAM,YAAY,CAAC,UAA2B,WAAW,KAAK,UAAU,cAAc,KAAK,CAAC,CAAC;AAC7F,QAAM,mBAAmB,CAAC,UAA2C,KAAK,UAAU,cAAc;AAAA,IAChG,UAAU,OAAO,YAAY,CAAC;AAAA,IAC9B,aAAa,OAAO,eAAe,CAAC;AAAA,IACpC,aAAa,OAAO,eAAe;AAAA,IACnC,OAAO,OAAO,SAAS,CAAC;AAAA,EAC1B,CAAC,CAAC;AACF,QAAM,sBAAsB,CAAC,QAAgB,OAAe,WAAgF;AAC1I,UAAM,SAAsE,CAAC;AAC7E,UAAM,aAAa;AACnB,UAAM,mBAAmB;AACzB,QAAI,sBAAsB;AAC1B,QAAI,OAAO;AACX,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,WAAO,OAAO,OAAO,UAAU,QAAQ,MAAM,QAAQ;AACnD,aAAO,OAAO,OAAO,UAAU,QAAQ,MAAM,UAAU,OAAO,WAAW,IAAI,MAAM,MAAM,WAAW,KAAK,GAAG;AAC1G,gBAAQ;AACR,iBAAS;AACT,oBAAY;AAAA,MACd;AACA,UAAI,SAAS,OAAO,UAAU,UAAU,MAAM,OAAQ;AACtD,YAAM,OAAO;AACb,UAAI;AACJ,UAAI,YAAY;AAChB,YAAM,gBAAgB,oBAAI,IAAoB;AAC9C,YAAM,eAAe,oBAAI,IAAoB;AAC7C,UAAI,kBAAkB,OAAO;AAC7B,UAAI,iBAAiB,QAAQ;AAC7B,aAAO,CAAC,OAAO;AACb,cAAM,cAAc,KAAK,IAAI,OAAO,SAAS,YAAY,OAAO,SAAS;AACzE,iBAAS,YAAY,kBAAkB,GAAG,aAAa,aAAa,aAAa,GAAG;AAClF,cAAI,wBAAwB,EAAG;AAC/B,iCAAuB;AACvB,gBAAM,MAAM,OAAO,MAAM,WAAW,YAAY,UAAU;AAC1D,cAAI,CAAC,cAAc,IAAI,GAAG,EAAG,eAAc,IAAI,KAAK,SAAS;AAC7D,gBAAM,gBAAgB,aAAa,IAAI,GAAG;AAC1C,cAAI,kBAAkB,QAAW;AAC/B,kBAAM,OAAO,YAAY,OAAO,gBAAgB;AAChD,gBAAI,CAAC,SAAS,OAAO,MAAM,KAAM,SAAQ,EAAE,MAAM,WAAW,OAAO,eAAe,KAAK;AAAA,UACzF;AACA,4BAAkB;AAAA,QACpB;AACA,cAAM,aAAa,KAAK,IAAI,MAAM,SAAS,YAAY,QAAQ,SAAS;AACxE,iBAAS,YAAY,iBAAiB,GAAG,aAAa,YAAY,aAAa,GAAG;AAChF,cAAI,wBAAwB,EAAG;AAC/B,iCAAuB;AACvB,gBAAM,MAAM,MAAM,MAAM,WAAW,YAAY,UAAU;AACzD,cAAI,CAAC,aAAa,IAAI,GAAG,EAAG,cAAa,IAAI,KAAK,SAAS;AAC3D,gBAAM,eAAe,cAAc,IAAI,GAAG;AAC1C,cAAI,iBAAiB,QAAW;AAC9B,kBAAM,OAAO,eAAe,OAAO,YAAY;AAC/C,gBAAI,CAAC,SAAS,OAAO,MAAM,KAAM,SAAQ,EAAE,MAAM,cAAc,OAAO,WAAW,KAAK;AAAA,UACxF;AACA,2BAAiB;AAAA,QACnB;AACA,cAAM,oBAAoB,OAAO,SAAS,OAAO,cAAc,mBAAmB,OAAO,SAAS;AAClG,cAAM,mBAAmB,MAAM,SAAS,QAAQ,cAAc,kBAAkB,MAAM,SAAS;AAC/F,YAAI,SAAS,wBAAwB,KAAM,qBAAqB,iBAAmB;AACnF,oBAAY,KAAK;AAAA,UACf,KAAK,IAAI,OAAO,SAAS,MAAM,MAAM,SAAS,KAAK;AAAA,UACnD,YAAY;AAAA,QACd;AAAA,MACF;AACA,UAAI,CAAC,SAAS,MAAM,SAAS,GAAG;AAC9B,eAAO,KAAK,EAAE,MAAM,IAAI,OAAO,OAAO,SAAS,MAAM,gBAAgB,MAAM,SAAS,MAAM,CAAC;AAC3F;AAAA,MACF;AACA,YAAM,UAAU,MAAM,OAAO;AAC7B,YAAM,iBAAiB,MAAM,QAAQ;AACrC,aAAO,KAAK,EAAE,MAAM,IAAI,OAAO,SAAS,eAAe,CAAC;AACxD,aAAO,MAAM;AACb,cAAQ,MAAM;AACd,kBAAY;AAAA,IACd;AACA,WAAO;AAAA,EACT;AACA,QAAM,gBAAgB,CAAC,UAAkB,SAA8E;AACrH,QAAI,aAAa,KAAM,QAAO,CAAC;AAC/B,QAAI,SAAS;AACb,WAAO,SAAS,SAAS,UAAU,SAAS,KAAK,UAAU,SAAS,WAAW,MAAM,MAAM,KAAK,WAAW,MAAM,EAAG,WAAU;AAC9H,QAAI,cAAc,SAAS;AAC3B,QAAI,UAAU,KAAK;AACnB,WAAO,cAAc,UAAU,UAAU,UAAU,SAAS,WAAW,cAAc,CAAC,MAAM,KAAK,WAAW,UAAU,CAAC,GAAG;AAAE,qBAAe;AAAG,iBAAW;AAAA,IAAG;AAC5J,UAAM,SAAS,SAAS,MAAM,QAAQ,WAAW;AACjD,UAAM,QAAQ,KAAK,MAAM,QAAQ,OAAO;AACxC,QAAI,OAAO,SAAS,MAAM,SAAS,KAAS,QAAO,oBAAoB,QAAQ,OAAO,MAAM;AAC5F,UAAM,QAAQ,MAAM,SAAS;AAC7B,UAAM,MAAM,IAAI,aAAa,OAAO,SAAS,KAAK,KAAK;AACvD,aAASA,QAAO,OAAO,SAAS,GAAGA,SAAQ,GAAGA,SAAQ,GAAG;AACvD,eAASC,SAAQ,MAAM,SAAS,GAAGA,UAAS,GAAGA,UAAS,GAAG;AACzD,cAAM,QAAQD,QAAO,QAAQC;AAC7B,YAAI,KAAK,IAAI,OAAO,WAAWD,KAAI,MAAM,MAAM,WAAWC,MAAK,IAC3D,KAAKD,QAAO,KAAK,QAAQC,SAAQ,CAAC,IAAI,IACtC,KAAK,IAAI,KAAKD,QAAO,KAAK,QAAQC,MAAK,GAAG,IAAI,QAAQ,CAAC,CAAC;AAAA,MAC9D;AAAA,IACF;AACA,UAAM,SAAsE,CAAC;AAC7E,QAAI,OAAO;AACX,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,WAAO,OAAO,OAAO,UAAU,QAAQ,MAAM,QAAQ;AACnD,UAAI,OAAO,OAAO,UAAU,QAAQ,MAAM,UAAU,OAAO,WAAW,IAAI,MAAM,MAAM,WAAW,KAAK,GAAG;AACvG,gBAAQ;AAAG,iBAAS;AAAG,oBAAY;AAAG;AAAA,MACxC;AACA,YAAM,OAAO;AACb,UAAI,UAAU;AACd,UAAI,iBAAiB;AACrB,aAAO,OAAO,OAAO,UAAU,QAAQ,MAAM,QAAQ;AACnD,YAAI,OAAO,OAAO,UAAU,QAAQ,MAAM,UAAU,OAAO,WAAW,IAAI,MAAM,MAAM,WAAW,KAAK,EAAG;AACzG,YAAI,QAAQ,MAAM,WAAW,SAAS,OAAO,UAAU,IAAI,OAAO,QAAQ,QAAQ,CAAC,KAAK,KAAK,OAAO,KAAK,QAAQ,KAAK,IAAI;AACxH,mBAAS;AAAG,4BAAkB;AAAA,QAChC,OAAO;AACL,kBAAQ;AAAG,qBAAW;AAAA,QACxB;AAAA,MACF;AACA,aAAO,KAAK,EAAE,MAAM,IAAI,OAAO,SAAS,eAAe,CAAC;AACxD,kBAAY;AAAA,IACd;AACA,WAAO;AAAA,EACT;AACA,QAAM,uBAAuB,CAAC,SAAkC,UAAkB,SAA0C;AAC1H,QAAI,CAAC,WAAW,aAAa,KAAM,QAAO;AAC1C,WAAO,WAAW,SAAS,cAAc,UAAU,IAAI,CAAC;AAAA,EAC1D;AAEA,QAAM,gBAAgB,OAAO,SAAkB,YAAoB,gBAAwB,WAAmB,gBAAiE;AAC7K,UAAM,UAAU,MAAM,QAAQ,QAAiB,EAAE,OAAO,UAAU,OAAO,CAAC,EAAE,OAAO,cAAc,UAAU,MAAM,OAAO,WAAW,GAAG,EAAE,OAAO,kBAAkB,UAAU,MAAM,OAAO,eAAe,CAAC,EAAE,CAAC;AAC3M,QAAI,CAAC,QAAS,QAAO;AACrB,QAAI,QAAQ,cAAc,aAAa,QAAQ,gBAAgB,YAAa,OAAM,IAAI,gBAAgB,+BAA+B,GAAG;AACxI,WAAO,QAAQ;AAAA,EACjB;AACA,QAAM,cAAc,OAAO,WAA0B,IAAY,OAAoB,UAA8B,CAAC,MAAmC;AACrJ,UAAM,UAAU,MAAM,WAAW,WAAW,EAAE;AAC9C,UAAM,QAAQ,QAAQ,QAAQ,uBAAuB,UAAU,WAAW,OAAO;AACjF,UAAM,YAAY,QAAQ,wBAAwB;AAClD,UAAM,cAAc,UAAU,QAAQ,sBAAsB;AAAA,MAC1D,GAAG;AAAA,MACH,gBAAgB;AAAA,MAChB,iBAAiB,QAAQ;AAAA,IAC3B,CAAC;AACD,QAAI,MAAM,gBAAgB;AACxB,YAAM,SAAS,MAAM,cAAc,UAAU,IAAI,MAAM,gBAAgB,WAAW,WAAW;AAC7F,UAAI,OAAQ,QAAO;AAAA,IACrB;AACA,QAAI,QAAQ,YAAY,MAAM,gBAAiB,OAAM,IAAI,gBAAgB,yBAAyB,GAAG;AACrG,UAAM,WAAW,QAAQ,iBAAiB,YAAY,MAAM,YAAY,QAAQ;AAChF,QAAI,CAAC,QAAQ,oBAAoB,MAAM,WAAW,iBAAiB,MAAM,OAAO,MAAM,iBAAiB,QAAQ,OAAO,GAAG;AACvH,YAAM,IAAI,gBAAgB,qCAAqC,GAAG;AAAA,IACpE;AACA,UAAM,gBAAgB,qBAAqB,QAAQ,SAAS,QAAQ,UAAU,QAAQ;AACtF,UAAM,UAAU,QAAQ,kBACpB,QAAQ,gBAAgB,UACxB,QAAQ,mBACN,MAAM,WAAW,gBACnB,MAAM,UACJ;AAAA,MACE,GAAG,MAAM;AAAA,MACT,UAAU,eAAe;AAAA,MACzB,aAAa,eAAe;AAAA,MAC5B,aAAa,eAAe;AAAA,MAC5B,OAAO,eAAe;AAAA,IACxB,IACA;AACN,UAAM,UAAU,OAAO;AACvB,UAAM,QAAQ,QAAQ,kBAAkB,QAAQ,gBAAgB,QAAQ,MAAM,SAAS,QAAQ;AAC/F,kBAAc,KAAK;AACnB,UAAM,OAA2B,EAAE,GAAG,SAAS,OAAO,UAAU,YAAY,WAAW,QAAQ,GAAG,YAAY,SAAS,YAAY,SAAS,SAAS,QAAQ,UAAU,GAAG,WAAW,IAAI,EAAE;AAC3L,WAAO,YAAY,OAAO,YAAY;AACpC,UAAI,MAAM,gBAAgB;AACxB,cAAM,SAAS,MAAM,cAAc,SAAS,IAAI,MAAM,gBAAgB,WAAW,WAAW;AAC5F,YAAI,OAAQ,QAAO;AAAA,MACrB;AACA,YAAM,SAAS,MAAM,QAAQ,QAA4B,EAAE,OAAO,WAAW,OAAO,QAAQ,EAAE,EAAE,CAAC;AACjG,UAAI,CAAC,UAAU,OAAO,YAAY,MAAM,gBAAiB,OAAM,IAAI,gBAAgB,yBAAyB,GAAG;AAC/G,YAAM,UAAU,MAAM,QAAQ,OAA2B,EAAE,OAAO,WAAW,OAAO,CAAC,EAAE,OAAO,MAAM,UAAU,MAAM,OAAO,GAAG,GAAG,EAAE,OAAO,WAAW,UAAU,MAAM,OAAO,MAAM,gBAAgB,CAAC,GAAG,MAAM,KAAK,CAAC;AAClN,YAAM,QAAQ,OAAO,EAAE,OAAO,UAAU,MAAM,SAAS,SAAS,UAAU,IAAI,MAAM,gBAAgB,QAAQ,EAAE,CAAC;AAC/G,UAAI,MAAM,eAAgB,OAAM,QAAQ,OAAO,EAAE,OAAO,UAAU,MAAM,EAAE,IAAI,SAAS,GAAG,YAAY,IAAI,gBAAgB,MAAM,gBAAgB,WAAW,aAAa,QAAQ,SAAS,WAAW,IAAI,EAAE,EAAE,CAAC;AAC7M,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACA,QAAM,kBAAkB,OACtB,WACA,IACA,iBACA,qBACA,cACA,gBACA,oBACA,WACgC;AAChC,UAAM,UAAU,MAAM,WAAW,WAAW,EAAE;AAC9C,UAAM,QAAQ,QAAQ,qBAAqB,WAAW,OAAO;AAC7D,QAAI,gBAAgB;AAClB,YAAM,SAAS,MAAM,cAAc,UAAU,IAAI,gBAAgB,cAAc,UAAU,kBAAkB,CAAC;AAC5G,UAAI,OAAQ,QAAO;AAAA,IACrB;AACA,QAAI,QAAQ,YAAY,gBAAiB,OAAM,IAAI,gBAAgB,yBAAyB,GAAG;AAC/F,QAAI;AACF,YAAM,OAAO,OAAO,OAAO;AAC3B,aAAO,YAAY,WAAW,IAAI,EAAE,iBAAiB,UAAU,KAAK,UAAU,SAAS,KAAK,SAAS,cAAc,eAAe,GAAG,EAAE,kBAAkB,MAAM,qBAAqB,sBAAsB,cAAc,mBAAmB,CAAC;AAAA,IAC9O,SAAS,OAAO;AACd,UAAI,iBAAiB,gBAAiB,OAAM;AAC5C,YAAM,IAAI,gBAAgB,0BAA0B,GAAG;AAAA,IACzD;AAAA,EACF;AACA,YAAU;AAAA,IACR,MAAM,OAAO,WAAW,OAAO;AAC7B,YAAM,QAAQ,QAAQ,UAAU,SAAS;AACzC,YAAM,MAAM,UAAU,MAAM,OAAO;AACnC,oBAAc,MAAM,KAAK;AACzB,UAAI,MAAM,OAAO,WAAc,OAAO,MAAM,OAAO,YAAY,MAAM,GAAG,KAAK,EAAE,WAAW,IAAI;AAC5F,cAAM,IAAI,gBAAgB,4BAA4B,GAAG;AAAA,MAC3D;AACA,UAAI,MAAM,WAAW,iBAAiB,MAAM,OAAO,MAAM,iBAAiB,MAAS,GAAG;AACpF,cAAM,IAAI,gBAAgB,qCAAqC,GAAG;AAAA,MACpE;AACA,YAAM,YAAY,IAAI;AACtB,YAAM,0BAA0B,8BAA8B;AAC9D,UAAI,OAAO,4BAA4B,YAAY,wBAAwB,WAAW,GAAG;AACvF,cAAM,IAAI,gBAAgB,kCAAkC,GAAG;AAAA,MACjE;AACA,YAAM,WAA+B,EAAE,IAAI,MAAM,MAAM,SAAS,GAAG,yBAAyB,SAAS,UAAU,IAAI,UAAU,UAAU,UAAU,OAAO,MAAM,OAAO,UAAU,MAAM,UAAU,YAAY,WAAW,MAAM,QAAQ,GAAG,YAAY,SAAS,YAAY,SAAS,MAAM,SAAS,SAAS,GAAG,WAAW,WAAW,UAAU;AAC5U,aAAO,YAAY,OAAO,YAAY;AACpC,cAAM,UAAU,MAAM,QAAQ,OAA2B,EAAE,OAAO,WAAW,MAAM,SAAS,CAAC;AAC7F,cAAM,QAAQ,OAAO,EAAE,OAAO,UAAU,MAAM,SAAS,SAAS,UAAU,IAAI,QAAQ,EAAE,CAAC;AACzF,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,IACA,MAAM,KAAK,WAAW,IAAI;AAAE,YAAM,WAAW,MAAM,WAAW,WAAW,EAAE;AAAG,YAAM,QAAQ,QAAQ,QAAQ,WAAW,QAAQ;AAAG,aAAO;AAAA,IAAU;AAAA,IACnJ,MAAM,KAAK,WAAW,UAAU,CAAC,GAAG;AAClC,YAAM,QAAQ,QAAQ,QAAQ,SAAS;AACvC,YAAM,QAAQ,UAAU,WAAW,CAAC,EAAE,OAAO,YAAY,UAAU,MAAe,OAAO,UAAU,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,WAAW,UAAU,MAAe,OAAO,UAAU,GAAG,CAAC;AACpL,YAAM,SAAS,KAAK,IAAI,GAAG,QAAQ,UAAU,CAAC;AAC9C,YAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,QAAQ,SAAS,EAAE,CAAC;AAC5D,YAAM,WAAW,KAAK,IAAI,IAAI,KAAK;AACnC,YAAM,UAAgC,CAAC;AACvC,UAAI,iBAAiB;AACrB,UAAI,mBAAmB;AACvB,aAAO,QAAQ,SAAS,OAAO;AAC7B,cAAM,aAAa,MAAM,SAAS,SAA6B;AAAA,UAC7D,OAAO;AAAA,UACP;AAAA,UACA,SAAS,CAAC,EAAE,OAAO,aAAa,WAAW,OAAO,GAAG,EAAE,OAAO,MAAM,WAAW,OAAO,CAAC;AAAA,UACvF,OAAO;AAAA,UACP,QAAQ;AAAA,QACV,CAAC;AACD,0BAAkB,WAAW;AAC7B,mBAAW,YAAY,YAAY;AACjC,cAAI,CAAC,UAAU,YAAY,SAAS,aAAa,UAAa,SAAS,aAAa,KAAM;AAC1F,cAAI,CAAE,MAAM,OAAO,UAAU,QAAQ,WAAW,QAAQ,EAAI;AAC5D,cAAI,mBAAmB,QAAQ;AAC7B,gCAAoB;AACpB;AAAA,UACF;AACA,kBAAQ,KAAK,QAAQ;AACrB,cAAI,QAAQ,WAAW,MAAO;AAAA,QAChC;AACA,YAAI,WAAW,SAAS,SAAU;AAAA,MACpC;AACA,aAAO;AAAA,IACT;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,OAAO;AAAE,aAAO,YAAY,WAAW,IAAI,KAAK;AAAA,IAAG;AAAA,IAC/E,MAAM,OAAO,WAAW,IAAI;AAC1B,YAAM,4BAA4B,IAAI,YAAY;AAChD,cAAM,UAAU,MAAM,WAAW,WAAW,EAAE;AAC9C,cAAM,QAAQ,QAAQ,UAAU,WAAW,OAAO;AAClD,cAAM,YAAY,OAAO,YAAY;AACnC,gBAAM,gBAAgB,CAAC,EAAE,OAAO,cAAc,UAAU,MAAe,OAAO,GAAG,CAAC;AAClF,gBAAM,QAAQ,WAAW,EAAE,OAAO,gBAAgB,OAAO,cAAc,CAAC;AACxE,gBAAM,QAAQ,WAAW,EAAE,OAAO,UAAU,OAAO,cAAc,CAAC;AAClE,gBAAM,QAAQ,WAAW,EAAE,OAAO,UAAU,OAAO,cAAc,CAAC;AAClE,gBAAM,QAAQ,OAAO,EAAE,OAAO,WAAW,OAAO,QAAQ,EAAE,EAAE,CAAC;AAAA,QAC/D,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,IACA,MAAM,SAAS,WAAW,IAAI,UAAU,CAAC,GAAG;AAC1C,YAAM,WAAW,MAAM,WAAW,WAAW,EAAE;AAC/C,YAAM,QAAQ,QAAQ,WAAW,WAAW,QAAQ;AACpD,YAAM,SAAS,QAAQ,WAAW,SAAY,SAAY,OAAO,QAAQ,MAAM;AAC/E,YAAM,iBAAiB,QAAQ,SAAS;AACxC,UAAK,WAAW,WAAc,CAAC,OAAO,cAAc,MAAM,KAAK,SAAS,MACtE,CAAC,OAAO,cAAc,cAAc,KAAK,iBAAiB,GAAG;AAC7D,cAAM,IAAI,gBAAgB,+BAA+B,GAAG;AAAA,MAC9D;AACA,YAAM,QAAQ,KAAK,IAAI,KAAK,cAAc;AAC1C,YAAM,QAAQ;AAAA,QACZ,EAAE,OAAO,cAAc,UAAU,MAAe,OAAO,GAAG;AAAA,QAC1D,GAAI,WAAW,SAAY,CAAC,IAAI,CAAC,EAAE,OAAO,WAAW,UAAU,MAAe,OAAO,OAAO,CAAC;AAAA,MAC/F;AACA,YAAM,OAAO,MAAM,SAAS,SAA6B;AAAA,QACvD,OAAO;AAAA,QACP;AAAA,QACA,QAAQ;AAAA,UACN;AAAA,UAAM;AAAA,UAAc;AAAA,UAA2B;AAAA,UAAW;AAAA,UAAY;AAAA,UAAS;AAAA,UAAc;AAAA,UAC7F;AAAA,UAAW;AAAA,UAAY;AAAA,UAAgB;AAAA,UAAa;AAAA,QACtD;AAAA,QACA,SAAS,CAAC,EAAE,OAAO,WAAW,WAAW,OAAO,CAAC;AAAA,QACjD,OAAO,QAAQ;AAAA,MACjB,CAAC;AACD,YAAM,WAAW,KAAK,MAAM,GAAG,KAAK;AACpC,aAAO;AAAA,QACL;AAAA,QACA,GAAI,KAAK,SAAS,QAAQ,EAAE,YAAY,OAAO,SAAS,GAAG,EAAE,EAAG,OAAO,EAAE,IAAI,CAAC;AAAA,MAChF;AAAA,IACF;AAAA,IACA,MAAM,QAAQ,WAAW,IAAI,SAAS;AAAE,YAAM,WAAW,MAAM,WAAW,WAAW,EAAE;AAAG,YAAM,QAAQ,QAAQ,WAAW,WAAW,QAAQ;AAAG,YAAM,SAAS,MAAM,SAAS,QAA2B,EAAE,OAAO,UAAU,OAAO,CAAC,EAAE,OAAO,cAAc,UAAU,MAAM,OAAO,GAAG,GAAG,EAAE,OAAO,WAAW,UAAU,MAAM,OAAO,QAAQ,CAAC,EAAE,CAAC;AAAG,UAAI,CAAC,OAAQ,OAAM,IAAI,gBAAgB,0BAA0B,GAAG;AAAG,aAAO;AAAA,IAAQ;AAAA,IACza,MAAM,eAAe,WAAW,IAAI,OAAO;AACzC,YAAM,UAAU,MAAM,WAAW,WAAW,EAAE;AAC9C,YAAM,QAAQ,QAAQ,mBAAmB,WAAW,OAAO;AAC3D,YAAM,WAAW,MAAM,SAAS,QAA2B;AAAA,QACzD,OAAO;AAAA,QACP,OAAO;AAAA,UACL,EAAE,OAAO,cAAc,UAAU,MAAM,OAAO,GAAG;AAAA,UACjD,EAAE,OAAO,WAAW,UAAU,MAAM,OAAO,MAAM,QAAQ;AAAA,QAC3D;AAAA,MACF,CAAC;AACD,UAAI,CAAC,SAAU,OAAM,IAAI,gBAAgB,0BAA0B,GAAG;AACtE,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,EAAE,iBAAiB,MAAM,iBAAiB,cAAc,WAAW,MAAM,OAAO,IAAI,gBAAgB,MAAM,eAAe;AAAA,QACzH;AAAA,UACE,kBAAkB;AAAA,UAClB,qBAAqB;AAAA,UACrB,iBAAiB;AAAA,UACjB,sBAAsB;AAAA,UACtB,oBAAoB;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM,cAAc,WAAW,IAAI,OAAO;AACxC,aAAO,gBAAgB,WAAW,IAAI,MAAM,iBAAiB,kBAAkB,6BAA6B,MAAM,gBAAgB,OAAO,CAAC,aAAa,oBAAoB,EAAE,SAAS,SAAS,SAAS,QAAQ,MAAM,QAAQ,MAAM,MAAM,MAAM,OAAO,eAAe,SAAS,GAAG,gBAAgB,SAAS,SAAS,OAAO,CAAC,CAAC;AAAA,IAC/T;AAAA,IACA,MAAM,aAAa,WAAW,IAAI,UAAU,OAAO;AACjD,aAAO,gBAAgB,WAAW,IAAI,MAAM,iBAAiB,iBAAiB,6BAA6B,MAAM,gBAAgB,EAAE,UAAU,GAAG,MAAM,GAAG,CAAC,cAAc,EAAE,SAAS,eAAe,EAAE,SAAS,SAAS,WAAW,CAAC,GAAG,UAAU,MAAM,MAAM,MAAM,OAAO,eAAe,SAAS,EAAE,CAAC,EAAE,EAAE;AAAA,IACzS;AAAA,IACA,MAAM,eAAe,WAAW,IAAI,UAAU,OAAO;AACnD,aAAO,gBAAgB,WAAW,IAAI,MAAM,iBAAiB,mBAAmB,MAAM,WAAW,+BAA+B,8BAA8B,MAAM,gBAAgB,EAAE,UAAU,GAAG,MAAM,GAAG,CAAC,cAAc,EAAE,SAAS,mBAAmB,EAAE,SAAS,SAAS,WAAW,CAAC,GAAG,UAAU,UAAU,MAAM,UAAU,OAAO,eAAe,SAAS,EAAE,CAAC,EAAE,EAAE;AAAA,IACxW;AAAA,IACA,MAAM,iBAAiB,WAAW,IAAI,OAAO;AAC3C,aAAO,gBAAgB,WAAW,IAAI,MAAM,iBAAiB,qBAAqB,gCAAgC,MAAM,gBAAgB,OAAO,CAAC,aAAa,iBAAiB,EAAE,SAAS,SAAS,SAAS,QAAQ,MAAM,QAAQ,aAAa,MAAM,aAAa,OAAO,eAAe,SAAS,GAAG,gBAAgB,SAAS,SAAS,OAAO,CAAC,CAAC;AAAA,IAChV;AAAA,IACA,MAAM,iBAAiB,WAAW,IAAI,cAAc,OAAO;AACzD,aAAO,gBAAgB,WAAW,IAAI,MAAM,iBAAiB,qBAAqB,wBAAwB,MAAM,QAAQ,IAAI,MAAM,gBAAgB,EAAE,cAAc,GAAG,MAAM,GAAG,CAAC,aAAa;AAC1L,cAAM,aAAa,aAAa,EAAE,UAAU,SAAS,UAAU,WAAW,wBAAwB,eAAe,GAAG,YAAY,OAAO,YAAY,SAAS,SAAS,QAAQ,CAAC;AAC9K,YAAI;AACF,2BAAiB,EAAE,YAAY,cAAc,UAAU,MAAM,UAAU,OAAO,eAAe,SAAS,EAAE,CAAC;AACzG,gBAAM,QAAQ,WAAW,SAAS;AAClC,iBAAO,EAAE,UAAU,MAAM,UAAU,SAAS,MAAM,WAAW,CAAC,EAAE;AAAA,QAClE,UAAE;AAAU,qBAAW,QAAQ;AAAA,QAAG;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,IACA,MAAM,iBAAiB,WAAW,IAAI,OAAO;AAC3C,aAAO,gBAAgB,WAAW,IAAI,MAAM,iBAAiB,qBAAqB,iCAAiC,MAAM,gBAAgB,OAAO,CAAC,cAAc,EAAE,SAAS,iBAAiB,EAAE,SAAS,SAAS,SAAS,IAAI,MAAM,OAAO,OAAO,eAAe,SAAS,EAAE,CAAC,EAAE,EAAE;AAAA,IACjR;AAAA,IACA,MAAM,0BAA0B,WAAW,IAAI,QAAQ;AACrD,UAAI,IAAI,YAAY,EAAE,OAAO,MAAM,EAAE,aAAa,yBAA0B,OAAM,IAAI,gBAAgB,gCAAgC,GAAG;AACzI,YAAM,WAAW,SAAS;AAC1B,YAAM,YAAY,IAAI;AACtB,YAAM,uBAAuB,WAAW,IAAI,eAAe,OAAO,SAAS,WAAW,uBAAuB;AAC3G,cAAM,QAAQ,OAAO;AAAA,UACnB,OAAO;AAAA,UACP,MAAM,EAAE,IAAI,UAAU,YAAY,IAAI,oBAAoB,UAAU,UAAU,IAAI,QAAQ,WAAW,UAAU;AAAA,QACjH,CAAC;AAAA,MACH,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IACA,MAAM,qBAAqB,WAAW,IAAI,UAAU,CAAC,GAAG;AACtD,YAAM,WAAW,MAAM,WAAW,WAAW,EAAE;AAC/C,YAAM,QAAQ,QAAQ,eAAe,WAAW,QAAQ;AACxD,YAAM,iBAAiB,QAAQ,SAAS;AACxC,UAAI,CAAC,OAAO,cAAc,cAAc,KAAK,iBAAiB,GAAG;AAC/D,cAAM,IAAI,gBAAgB,8BAA8B,GAAG;AAAA,MAC7D;AACA,YAAM,QAAQ,KAAK,IAAI,2BAA2B,cAAc;AAEhE,YAAM,SAAS,QAAQ,WAAW,SAAY,SAAY,0BAA0B,QAAQ,QAAQ,EAAE;AACtG,YAAM,OAAO,MAAM,SAAS,SAA2B;AAAA,QACrD,OAAO;AAAA,QACP,OAAO;AAAA,UACL,EAAE,OAAO,cAAc,UAAU,MAAM,OAAO,GAAG;AAAA,UACjD,EAAE,OAAO,sBAAsB,UAAU,MAAM,OAAO,SAAS,wBAAwB;AAAA,UACvF,GAAI,WAAW,SAAY,CAAC,IAAI,CAAC,EAAE,OAAO,aAAa,UAAU,MAAe,OAAO,OAAO,CAAC;AAAA,QACjG;AAAA,QACA,SAAS,CAAC,EAAE,OAAO,aAAa,WAAW,MAAM,CAAC;AAAA,QAClD,OAAO,QAAQ;AAAA,MACjB,CAAC;AACD,YAAM,WAA+B,CAAC;AACtC,UAAI,eAAe;AACnB,iBAAW,OAAO,KAAK,MAAM,GAAG,KAAK,GAAG;AACtC,cAAM,WAAW,IAAI,YAAY,EAAE,OAAO,IAAI,MAAM,EAAE;AACtD,YAAI,SAAS,SAAS,KAAK,eAAe,WAAW,wBAAyB;AAC9E,iBAAS,KAAK,GAAG;AACjB,wBAAgB;AAAA,MAClB;AACA,YAAM,UAAU,SAAS,SAAS,KAAK;AACvC,aAAO;AAAA,QACL,SAAS,SAAS,IAAI,CAAC,QAAQ,IAAI,MAAM;AAAA,QACzC,mBAAmB,SAAS,IAAI,CAAC,QAAQ,IAAI,EAAE;AAAA,QAC/C,GAAI,UAAU,EAAE,YAAY,0BAA0B,IAAI,SAAS,GAAG,EAAE,EAAG,SAAS,EAAE,IAAI,CAAC;AAAA,MAC7F;AAAA,IACF;AAAA,IACA,MAAM,4BAA4B,WAAW,IAAI,UAAU,mBAAmB;AAC5E,UAAI,IAAI,YAAY,EAAE,OAAO,QAAQ,EAAE,aAAa,yBAA0B,OAAM,IAAI,gBAAgB,gCAAgC,GAAG;AAC3I,UAAI,CAAC,MAAM,QAAQ,iBAAiB,KAAK,kBAAkB,KAAK,CAACC,cAAa,OAAOA,cAAa,YAAY,CAACA,SAAQ,GAAG;AACxH,cAAM,IAAI,gBAAgB,kCAAkC,GAAG;AAAA,MACjE;AACA,YAAM,kBAAkB,CAAC,GAAG,IAAI,IAAI,iBAAiB,CAAC;AACtD,YAAM,WAAW,SAAS;AAC1B,YAAM,YAAY,IAAI;AACtB,YAAM,uBAAuB,WAAW,IAAI,yBAAyB,OAAO,SAAS,WAAW,uBAAuB;AACrH,YAAI,gBAAgB,SAAS,GAAG;AAC9B,gBAAM,QAAQ,WAAW,EAAE,OAAO,gBAAgB,OAAO,CAAC,EAAE,OAAO,cAAc,UAAU,MAAM,OAAO,GAAG,GAAG,EAAE,OAAO,sBAAsB,UAAU,MAAM,OAAO,mBAAmB,GAAG,EAAE,OAAO,MAAM,UAAU,MAAM,OAAO,gBAAgB,CAAC,EAAE,CAAC;AAAA,QACtP;AACA,cAAM,QAAQ,OAAO,EAAE,OAAO,gBAAgB,MAAM,EAAE,IAAI,UAAU,YAAY,IAAI,oBAAoB,UAAU,UAAU,IAAI,QAAQ,UAAU,WAAW,UAAU,EAAE,CAAC;AAAA,MAC5K,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,KAAK,UAAsC;AAAE,SAAO,SAAU,SAAS,OAAO,IAAI,SAAS,UAAU;AAAM;AACpH,SAAS,SAAS,UAA8B,SAAS,KAAe;AAAE,SAAO,SAAS,KAAK,UAAU,EAAE,QAAQ,SAAS,EAAE,MAAM,KAAK,QAAQ,GAAG,iBAAiB,WAAW,EAAE,CAAC;AAAG;AACtL,SAAS,WAA2D,SAAkB,MAAY;AAChG,SAAO,EAAE,GAAG,MAAM,gBAAgB,KAAK,kBAAkB,QAAQ,QAAQ,IAAI,iBAAiB,KAAK,OAAU;AAC/G;AAEO,SAAS,iBAAiB,QAA0B,UAAU,kBAAkB,MAAM,GAAyC;AACpI,QAAM,YAAY,OAAO,qBAAqB,MAAM;AAAE,UAAM,IAAI,gBAAgB,wBAAwB,GAAG;AAAA,EAAG;AAC9G,QAAM,mBAAmB,KAAK;AAAA,IAC5B,wBAAwB,MAAM,IAAI,IAAI,OAAO;AAAA,IAC7C,mCAAmC,MAAM,IAAI,KAAK;AAAA,EACpD;AACA,SAAO,aAAa;AAAA,IAClB,UAAU,OAAO,YAAY;AAAA,IAC7B,cAAc,OAAO,uBAAuB;AAAA,IAC5C,SAAS,OAAO,aAAa,EAAE,WAAW,MAAM,UAAU,OAAO,EAAE;AAAA,IACnE,SAAS,CAAC,UAAU,iBAAiB,kBACjC,SAAS,KAAK,EAAE,OAAO,MAAM,KAAK,GAAG,EAAE,QAAQ,MAAM,OAAO,CAAC,IAC7D,iBAAiB,cACf,MAAM,WAAW,IACjB,SAAS,KAAK,EAAE,OAAO,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACrE,QAAQ;AAAA,MACN,EAAE,QAAQ,OAAO,MAAM,cAAc,SAAS,CAAC,UAAU,YAAY,QAAQ,KAAK,QAAQ,WAAW,EAAE,OAAO,OAAO,QAAQ,MAAM,IAAI,OAAO,KAAK,EAAE,GAAG,QAAQ,OAAO,QAAQ,MAAM,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,cAAc,SAAS,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE;AAAA,MAC9P,EAAE,QAAQ,QAAQ,MAAM,cAAc,SAAS,OAAO,UAAU,YAAY,SAAS,MAAM,QAAQ,OAAO,QAAQ,WAAW,MAAM,QAAQ,KAAK,CAAC,GAAG,GAAG,EAAE;AAAA,MACzJ,EAAE,QAAQ,OAAO,MAAM,kBAAkB,SAAS,OAAO,UAAU,YAAY,SAAS,MAAM,QAAQ,KAAK,QAAQ,WAAW,QAAQ,OAAO,EAAG,CAAC,EAAE;AAAA,MACnJ,EAAE,QAAQ,SAAS,MAAM,kBAAkB,SAAS,OAAO,SAAS,YAAY,SAAS,MAAM,QAAQ,OAAO,QAAQ,WAAW,QAAQ,OAAO,IAAK,WAAW,SAAS,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE;AAAA,MACjM,EAAE,QAAQ,UAAU,MAAM,kBAAkB,SAAS,OAAO,UAAU,YAAY;AAAE,cAAM,QAAQ,OAAO,QAAQ,WAAW,QAAQ,OAAO,EAAG;AAAG,eAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AAAA,MAAG,EAAE;AAAA,MAC/L,EAAE,QAAQ,OAAO,MAAM,2BAA2B,SAAS,OAAO,UAAU,YAAY,SAAS,KAAK,MAAM,QAAQ,SAAS,QAAQ,WAAW,QAAQ,OAAO,IAAK,EAAE,QAAQ,QAAQ,MAAM,IAAI,QAAQ,KAAK,QAAW,OAAO,QAAQ,MAAM,IAAI,OAAO,IAAI,OAAO,QAAQ,MAAM,IAAI,OAAO,CAAC,IAAI,OAAU,CAAC,CAAC,EAAE;AAAA,MAC/S,EAAE,QAAQ,OAAO,MAAM,oCAAoC,SAAS,OAAO,UAAU,YAAY,SAAS,KAAK,MAAM,QAAQ,QAAQ,QAAQ,WAAW,QAAQ,OAAO,IAAK,OAAO,QAAQ,OAAO,OAAO,CAAC,CAAC,EAAE;AAAA,MAC7M,EAAE,QAAQ,QAAQ,MAAM,0BAA0B,SAAS,OAAO,SAAS,YAAY,SAAS,MAAM,QAAQ,eAAe,QAAQ,WAAW,QAAQ,OAAO,IAAK,WAAW,SAAS,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE;AAAA,MAChN,EAAE,QAAQ,OAAO,MAAM,0BAA0B,SAAS,OAAO,UAAU,YAAY,SAAS,MAAM,MAAM,QAAQ,KAAK,QAAQ,WAAW,QAAQ,OAAO,EAAG,GAAG,WAAW,CAAC,CAAC,EAAE;AAAA,MAChL,EAAE,QAAQ,OAAO,MAAM,0BAA0B,SAAS,OAAO,SAAS,YAAY;AAAE,cAAM,OAAO,WAAW,SAAS,MAAM,QAAQ,KAAiF,CAAC;AAAG,eAAO,SAAS,MAAM,QAAQ,OAAO,QAAQ,WAAW,QAAQ,OAAO,IAAK,EAAE,GAAG,MAAM,cAAc,UAAU,CAAC,CAAC;AAAA,MAAG,EAAE;AAAA,MAClV,EAAE,QAAQ,OAAO,MAAM,wBAAwB,SAAS,OAAO,UAAU,YAAY,SAAS,KAAK,EAAE,QAAQ,MAAM,QAAQ,KAAK,QAAQ,WAAW,QAAQ,OAAO,EAAG,GAAG,SAAS,SAAS,CAAC,EAAE,CAAC,EAAE;AAAA,MAChM,EAAE,QAAQ,QAAQ,MAAM,2BAA2B,SAAS,OAAO,SAAS,YAAY,SAAS,MAAM,QAAQ,cAAc,QAAQ,WAAW,QAAQ,OAAO,IAAK,WAAW,SAAS,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE;AAAA,MAChN,EAAE,QAAQ,QAAQ,MAAM,6CAA6C,SAAS,OAAO,SAAS,YAAY,SAAS,MAAM,QAAQ,aAAa,QAAQ,WAAW,QAAQ,OAAO,IAAK,QAAQ,OAAO,UAAW,WAAW,SAAS,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE;AAAA,MAC3P,EAAE,QAAQ,SAAS,MAAM,qCAAqC,SAAS,OAAO,SAAS,YAAY,SAAS,MAAM,QAAQ,eAAe,QAAQ,WAAW,QAAQ,OAAO,IAAK,QAAQ,OAAO,UAAW,WAAW,SAAS,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE;AAAA,MACtP,EAAE,QAAQ,QAAQ,MAAM,8BAA8B,SAAS,OAAO,SAAS,YAAY,SAAS,MAAM,QAAQ,iBAAiB,QAAQ,WAAW,QAAQ,OAAO,IAAK,WAAW,SAAS,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE;AAAA,MACtN,EAAE,QAAQ,SAAS,MAAM,4CAA4C,SAAS,OAAO,SAAS,YAAY,SAAS,MAAM,QAAQ,iBAAiB,QAAQ,WAAW,QAAQ,OAAO,IAAK,QAAQ,OAAO,cAAe,WAAW,SAAS,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE;AAAA,MACnQ,EAAE,QAAQ,OAAO,MAAM,yBAAyB,SAAS,OAAO,SAAS,YAAY,SAAS,MAAM,QAAQ,iBAAiB,QAAQ,WAAW,QAAQ,OAAO,IAAK,WAAW,SAAS,MAAM,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE;AAAA,MAChN,EAAE,QAAQ,OAAO,MAAM,wCAAwC,SAAS,OAAO,UAAU,YAAY,SAAS,KAAK,MAAM,QAAQ,qBAAqB,QAAQ,WAAW,QAAQ,OAAO,IAAK,EAAE,QAAQ,QAAQ,MAAM,IAAI,QAAQ,KAAK,QAAW,OAAO,QAAQ,MAAM,IAAI,OAAO,IAAI,OAAO,QAAQ,MAAM,IAAI,OAAO,CAAC,IAAI,OAAU,CAAC,CAAC,EAAE;AAAA,MACxU,EAAE,QAAQ,QAAQ,MAAM,wCAAwC,SAAS,OAAO,UAAU,YAAY;AAAE,cAAM,OAAO,MAAM,QAAQ,KAAyB;AAAG,eAAO,SAAS,KAAK,EAAE,IAAI,MAAM,QAAQ,0BAA0B,QAAQ,WAAW,QAAQ,OAAO,IAAK,KAAK,MAAM,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAAG,EAAE;AAAA,MAC7S,EAAE,QAAQ,OAAO,MAAM,gDAAgD,SAAS,OAAO,UAAU,YAAY;AAAE,cAAM,OAAO,MAAM,QAAQ,KAAwD;AAAG,eAAO,SAAS,KAAK,EAAE,IAAI,MAAM,QAAQ,4BAA4B,QAAQ,WAAW,QAAQ,OAAO,IAAK,KAAK,UAAU,KAAK,iBAAiB,EAAE,CAAC;AAAA,MAAG,EAAE;AAAA,IAChW;AAAA,EACF,CAAC;AACH;AAEO,SAAS,iBAAiB,QAAmK;AAClM,QAAM,UAAU,kBAAkB,MAAM;AACxC,SAAO,EAAE,SAAS,QAAQ,iBAAiB,QAAQ,OAAO,GAAG,QAAQ,UAAU,EAAE;AACnF;AAEO,IAAM,sBAAsB;","names":["left","right","updateId"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n createCommentThread,\n createEditor,\n createSuggestion,\n decideSuggestion,\n hashString,\n mapSidecar,\n replyToComment,\n resolveExtensions,\n setCommentResolved,\n transitionReview,\n validateMdfnSidecar,\n type MdfnExtension,\n type MdfnSidecar,\n type ReviewState,\n type SidecarAnchor,\n} from \"@mdfn/core\";\nimport { createMarkdownProjector, parseMarkdown, type MarkdownOptions } from \"@mdfn/markdown\";\nimport { wrapWithSchema, type Adapter, type TableSchema } from \"@superfunctions/db\";\nimport { createRouter, RouterError, type Router } from \"@superfunctions/http\";\n\nconst DOCUMENTS = \"mdfnDocuments\";\nconst VERSIONS = \"mdfnVersions\";\nconst RECEIPTS = \"mdfnReceipts\";\nconst COLLAB_UPDATES = \"mdfnCollaborationUpdates\";\nexport const MDFN_SERVER_SCHEMA_VERSION = 2;\n\nexport interface MdfnPrincipal { readonly id: string; readonly tenantId?: string; readonly roles?: readonly string[]; }\nexport type MdfnServerAction =\n | \"create\"\n | \"read\"\n | \"update\"\n | \"delete\"\n | \"history\"\n | \"history:restore\"\n | \"collaborate\"\n | \"compact-collaboration\"\n | \"comment:create\"\n | \"comment:reply\"\n | \"comment:resolve\"\n | \"suggestion:create\"\n | \"suggestion:decide\"\n | \"review:transition\";\n\nexport interface MdfnDocumentRecord {\n readonly id: string;\n /** Immutable identity for collaboration rows across delete/recreate cycles. */\n readonly collaborationGeneration: string;\n readonly ownerId: string;\n readonly tenantId?: string;\n readonly title?: string;\n readonly markdown: string;\n readonly sourceHash: string;\n readonly schemaHash: string;\n readonly sidecar?: MdfnSidecar;\n readonly version: number;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n}\n\nexport interface MdfnVersionRecord extends MdfnDocumentRecord { readonly documentId: string; readonly authorId: string; readonly changeSource: string; }\n\nexport type MdfnVersionSummary = Omit<MdfnVersionRecord, \"markdown\" | \"sidecar\">;\n\nexport interface MdfnVersionBatch {\n readonly versions: readonly MdfnVersionSummary[];\n readonly nextCursor?: string;\n}\n\nexport interface MdfnCollaborationUpdateBatch {\n readonly updates: readonly string[];\n /** Exact persisted update ids represented by `updates` and therefore safe to compact. */\n readonly includedUpdateIds: readonly string[];\n /** Opaque continuation for the next bounded batch, when more updates remain. */\n readonly nextCursor?: string;\n}\n\nexport interface MdfnServerConfig {\n readonly database: Adapter;\n readonly authorize: (action: MdfnServerAction, principal: MdfnPrincipal, document?: MdfnDocumentRecord) => boolean | Promise<boolean>;\n readonly resolvePrincipal?: (request: Request) => MdfnPrincipal | Promise<MdfnPrincipal>;\n readonly extensions?: readonly MdfnExtension[];\n readonly markdown?: MarkdownOptions;\n readonly basePath?: string;\n readonly createId?: () => string;\n /** Injectable lifecycle identity for deterministic hosts and tests. */\n readonly createCollaborationGeneration?: () => string;\n /** Injectable clock for deterministic hosts and tests. */\n readonly now?: () => Date;\n readonly maxCollaborationUpdateBytes?: number;\n readonly maxCollaborationBatchBytes?: number;\n readonly maxCollaborationBatchUpdates?: number;\n /** Maximum encoded request body accepted by JSON-writing routes. */\n readonly maxRequestBodyBytes?: number;\n /** Maximum UTF-8 bytes accepted for a persisted document title. */\n readonly maxTitleBytes?: number;\n /** Durable storage requires adapter transactions. Ephemeral is intended only for in-memory/test hosts. */\n readonly durability?: \"required\" | \"ephemeral\";\n}\n\nexport class MdfnServerError extends Error {\n constructor(readonly code: string, readonly status: number, message = code) { super(message); this.name = \"MdfnServerError\"; }\n}\n\nfunction configuredDocumentBytes(config: MdfnServerConfig): number {\n return config.markdown?.maxBytes ?? 2 * 1024 * 1024;\n}\n\nfunction configuredCollaborationUpdateBytes(config: MdfnServerConfig): number {\n if (config.maxCollaborationUpdateBytes !== undefined) return config.maxCollaborationUpdateBytes;\n const documentBytes = configuredDocumentBytes(config);\n const yjsOverhead = Math.max(64 * 1024, Math.ceil(documentBytes / 16));\n return 4 * Math.ceil((documentBytes + yjsOverhead) / 3);\n}\n\ninterface CollaborationCursor {\n readonly documentId: string;\n readonly key: string;\n}\n\nfunction collaborationCursorKey(previousKey?: string): string {\n const match = previousKey?.match(/^v2:(\\d{20})$/);\n if (previousKey?.startsWith(\"v2:\") && !match) throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 500);\n const sequence = (match ? BigInt(match[1]) : 0n) + 1n;\n const encoded = sequence.toString().padStart(20, \"0\");\n if (encoded.length > 20) throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_EXHAUSTED\", 500);\n return `v2:${encoded}`;\n}\n\nfunction isUniqueConflict(error: unknown): boolean {\n const value = error as { readonly code?: unknown; readonly message?: unknown; readonly cause?: unknown };\n const cause = value?.cause as { readonly code?: unknown; readonly message?: unknown } | undefined;\n return /(?:unique|duplicate|23505|p2002)/i.test([value?.code, value?.message, cause?.code, cause?.message].filter(Boolean).join(\" \"));\n}\n\nfunction encodeCollaborationCursor(documentId: string, key: string): string {\n return encodeURIComponent(JSON.stringify({ documentId, key }));\n}\n\nfunction decodeCollaborationCursor(cursor: string, documentId: string): string {\n try {\n const parsed = JSON.parse(decodeURIComponent(cursor)) as Partial<CollaborationCursor>;\n if (parsed.documentId !== documentId || typeof parsed.key !== \"string\" || !parsed.key) {\n throw new Error(\"invalid cursor\");\n }\n return parsed.key;\n } catch {\n throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 422);\n }\n}\n\nexport function getSchema(): { version: number; schemas: TableSchema[] } {\n const date = { type: \"date\" as const, required: true, dateValueType: \"date\" as const };\n return { version: MDFN_SERVER_SCHEMA_VERSION, schemas: [\n { modelName: DOCUMENTS, fields: { id: { type: \"string\", required: true }, collaborationGeneration: { type: \"string\", required: true }, ownerId: { type: \"string\", required: true }, tenantId: { type: \"string\" }, title: { type: \"string\" }, markdown: { type: \"string\", required: true }, sourceHash: { type: \"string\", required: true }, schemaHash: { type: \"string\", required: true }, sidecar: { type: \"json\" }, version: { type: \"number\", required: true }, createdAt: date, updatedAt: date }, indexes: [{ name: \"idx_mdfn_documents_owner\", fields: [\"ownerId\"] }, { name: \"idx_mdfn_documents_tenant\", fields: [\"tenantId\"] }] },\n { modelName: VERSIONS, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true }, collaborationGeneration: { type: \"string\", required: true }, ownerId: { type: \"string\", required: true }, tenantId: { type: \"string\" }, title: { type: \"string\" }, markdown: { type: \"string\", required: true }, sourceHash: { type: \"string\", required: true }, schemaHash: { type: \"string\", required: true }, sidecar: { type: \"json\" }, version: { type: \"number\", required: true }, authorId: { type: \"string\", required: true }, changeSource: { type: \"string\", required: true }, createdAt: date, updatedAt: date }, indexes: [{ name: \"idx_mdfn_versions_document_version\", fields: [\"documentId\", \"version\"], unique: true }] },\n { modelName: RECEIPTS, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true }, idempotencyKey: { type: \"string\", required: true }, operation: { type: \"string\", required: true }, payloadHash: { type: \"string\", required: true }, result: { type: \"json\", required: true }, createdAt: date }, indexes: [{ name: \"idx_mdfn_receipts_key\", fields: [\"documentId\", \"idempotencyKey\"], unique: true }] },\n { modelName: COLLAB_UPDATES, fields: { id: { type: \"string\", required: true }, documentId: { type: \"string\", required: true, references: { model: DOCUMENTS, field: \"id\", onDelete: \"cascade\" } }, documentGeneration: { type: \"string\", required: true }, authorId: { type: \"string\", required: true }, update: { type: \"string\", required: true }, cursorKey: { type: \"string\", required: true }, createdAt: date }, indexes: [{ name: \"idx_mdfn_collab_generation_cursor\", fields: [\"documentId\", \"documentGeneration\", \"cursorKey\"], unique: true }] },\n ] };\n}\n\nexport interface MdfnService {\n create(principal: MdfnPrincipal, input: { readonly id?: string; readonly title?: string; readonly markdown: string; readonly sidecar?: MdfnSidecar }): Promise<MdfnDocumentRecord>;\n read(principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord>;\n list(principal: MdfnPrincipal, options?: { readonly limit?: number; readonly offset?: number }): Promise<readonly MdfnDocumentRecord[]>;\n update(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly markdown?: string; readonly title?: string; readonly sidecar?: MdfnSidecar; readonly changeSource?: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n delete(principal: MdfnPrincipal, id: string): Promise<void>;\n versions(\n principal: MdfnPrincipal,\n id: string,\n options?: { readonly cursor?: string; readonly limit?: number },\n ): Promise<MdfnVersionBatch>;\n version(principal: MdfnPrincipal, id: string, version: number): Promise<MdfnVersionRecord>;\n restoreVersion(principal: MdfnPrincipal, id: string, input: { readonly version: number; readonly expectedVersion: number; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n createComment(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly anchor: SidecarAnchor; readonly body: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n replyComment(principal: MdfnPrincipal, id: string, threadId: string, input: { readonly expectedVersion: number; readonly body: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n resolveComment(principal: MdfnPrincipal, id: string, threadId: string, input: { readonly expectedVersion: number; readonly resolved: boolean; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n createSuggestion(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly anchor: SidecarAnchor; readonly replacement: string; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n decideSuggestion(principal: MdfnPrincipal, id: string, suggestionId: string, input: { readonly expectedVersion: number; readonly decision: \"accepted\" | \"rejected\"; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n transitionReview(principal: MdfnPrincipal, id: string, input: { readonly expectedVersion: number; readonly state: ReviewState; readonly idempotencyKey?: string }): Promise<MdfnDocumentRecord>;\n appendCollaborationUpdate(principal: MdfnPrincipal, id: string, update: string): Promise<string>;\n collaborationUpdates(\n principal: MdfnPrincipal,\n id: string,\n options?: { readonly cursor?: string; readonly limit?: number },\n ): Promise<MdfnCollaborationUpdateBatch>;\n compactCollaborationUpdates(principal: MdfnPrincipal, id: string, snapshot: string, includedUpdateIds: readonly string[]): Promise<string>;\n}\n\nasync function allowed(config: MdfnServerConfig, action: MdfnServerAction, principal: MdfnPrincipal, document?: MdfnDocumentRecord): Promise<void> {\n if (!(await config.authorize(action, principal, document))) throw new MdfnServerError(\"MDFN_FORBIDDEN\", 403);\n}\n\nfunction whereId(id: string) { return [{ field: \"id\", operator: \"eq\" as const, value: id }]; }\n\nexport function createMdfnService(config: MdfnServerConfig): MdfnService {\n const database = wrapWithSchema(config.database, getSchema());\n if ((config.durability ?? \"required\") === \"required\") {\n if (!database.capabilities.transactions.supported) {\n throw new MdfnServerError(\"MDFN_TRANSACTIONAL_DATABASE_REQUIRED\", 500);\n }\n if (!database.capabilities.schema.constraints) {\n throw new MdfnServerError(\"MDFN_RELATIONAL_CONSTRAINTS_REQUIRED\", 500);\n }\n }\n const registry = resolveExtensions(config.extensions ?? []);\n const markdownOptions: MarkdownOptions = { ...config.markdown, extensions: registry };\n const createId = config.createId ?? (() => crypto.randomUUID());\n const createCollaborationGeneration = config.createCollaborationGeneration ?? (() => crypto.randomUUID());\n const now = config.now ?? (() => new Date());\n const collaborationUpdateBytes = configuredCollaborationUpdateBytes(config);\n const collaborationBatchBytes = Math.max(\n collaborationUpdateBytes,\n config.maxCollaborationBatchBytes ?? collaborationUpdateBytes * 4,\n );\n const collaborationBatchUpdates = Math.min(1_000, Math.max(1, config.maxCollaborationBatchUpdates ?? 100));\n const parse = (source: string, sidecar?: MdfnSidecar): void => {\n try {\n parseMarkdown(source, markdownOptions);\n validateMdfnSidecar(sidecar, { markdownLength: source.length });\n } catch {\n throw new MdfnServerError(\"MDFN_DOCUMENT_INVALID\", 422);\n }\n };\n type Storage = Pick<Adapter, \"create\" | \"findOne\" | \"findMany\" | \"update\" | \"delete\" | \"deleteMany\">;\n const loadFrom = async (storage: Pick<Adapter, \"findOne\">, id: string): Promise<MdfnDocumentRecord> => {\n const result = await storage.findOne<MdfnDocumentRecord>({ model: DOCUMENTS, where: whereId(id) });\n if (!result) throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n return result;\n };\n const load = (id: string): Promise<MdfnDocumentRecord> => loadFrom(database, id);\n const loadScopedFrom = async (storage: Pick<Adapter, \"findOne\">, principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord> => {\n const document = await loadFrom(storage, id);\n const inScope = principal.tenantId\n ? document.tenantId === principal.tenantId\n : document.tenantId === undefined && document.ownerId === principal.id;\n if (!inScope) throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n return document;\n };\n const loadScoped = (principal: MdfnPrincipal, id: string): Promise<MdfnDocumentRecord> => loadScopedFrom(database, principal, id);\n const revision = (document: MdfnDocumentRecord, authorId: string, changeSource: string): MdfnVersionRecord => ({ ...document, id: `${document.id}:${document.version}`, documentId: document.id, authorId, changeSource });\n const withStorage = <T>(callback: (storage: Storage) => Promise<T>): Promise<T> => database.capabilities.transactions.supported\n ? database.transaction((transaction) => callback(transaction))\n : callback(database);\n const collaborationWriteTails = new Map<string, Promise<void>>();\n const serializeCollaborationWrite = async <T>(documentId: string, callback: () => Promise<T>): Promise<T> => {\n const previous = collaborationWriteTails.get(documentId) ?? Promise.resolve();\n let release!: () => void;\n const gate = new Promise<void>((resolve) => { release = resolve; });\n const tail = previous.then(() => gate);\n collaborationWriteTails.set(documentId, tail);\n await previous;\n try {\n return await callback();\n } finally {\n release();\n if (collaborationWriteTails.get(documentId) === tail) collaborationWriteTails.delete(documentId);\n }\n };\n const withCollaborationWrite = <T>(\n principal: MdfnPrincipal,\n documentId: string,\n action: \"collaborate\" | \"compact-collaboration\",\n callback: (storage: Storage, cursorKey: string, documentGeneration: string) => Promise<T>,\n ): Promise<T> => (\n serializeCollaborationWrite(documentId, async () => {\n const authorizedDocument = await loadScoped(principal, documentId);\n await allowed(config, action, principal, authorizedDocument);\n const documentGeneration = authorizedDocument.collaborationGeneration;\n let lastConflict: unknown;\n for (let attempt = 0; attempt < 5; attempt += 1) {\n try {\n const result = await withStorage(async (storage) => {\n const storedDocument = await loadScopedFrom(storage, principal, documentId);\n if (storedDocument.collaborationGeneration !== documentGeneration) {\n throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n }\n const latest = await storage.findMany<{ readonly cursorKey: string }>({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: documentId },\n { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration },\n ],\n select: [\"cursorKey\"],\n orderBy: [{ field: \"cursorKey\", direction: \"desc\" }],\n limit: 1,\n });\n return callback(storage, collaborationCursorKey(latest[0]?.cursorKey), documentGeneration);\n });\n let latestDocument: MdfnDocumentRecord | undefined;\n try {\n latestDocument = await loadScoped(principal, documentId);\n } catch (error) {\n if (!(error instanceof MdfnServerError && error.code === \"MDFN_DOCUMENT_NOT_FOUND\")) throw error;\n }\n if (latestDocument?.collaborationGeneration !== documentGeneration) {\n await database.deleteMany({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: documentId },\n { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration },\n ],\n });\n throw new MdfnServerError(\"MDFN_DOCUMENT_NOT_FOUND\", 404);\n }\n return result;\n } catch (error) {\n if (!isUniqueConflict(error)) throw error;\n lastConflict = error;\n }\n }\n throw lastConflict;\n })\n );\n let service!: MdfnService;\n const editorialActor = (principal: MdfnPrincipal) => ({ id: principal.id, createId, now: () => now().toISOString() });\n const maxTitleBytes = config.maxTitleBytes ?? 512;\n if (!Number.isSafeInteger(maxTitleBytes) || maxTitleBytes < 1) {\n throw new MdfnServerError(\"MDFN_TITLE_LIMIT_INVALID\", 500);\n }\n const validateTitle = (title: string | undefined): void => {\n if (title !== undefined && new TextEncoder().encode(title).byteLength > maxTitleBytes) {\n throw new MdfnServerError(\"MDFN_TITLE_TOO_LARGE\", 413);\n }\n };\n type UpdateInput = Parameters<MdfnService[\"update\"]>[2];\n type RestoreSnapshot = Pick<MdfnVersionRecord, \"title\" | \"markdown\" | \"sidecar\">;\n interface WriteUpdateOptions {\n readonly trustedEditorial?: boolean;\n readonly authorizationAction?: MdfnServerAction;\n readonly restoreSnapshot?: RestoreSnapshot;\n readonly idempotencyOperation?: string;\n readonly idempotencyPayload?: unknown;\n }\n const canonicalJson = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(canonicalJson);\n if (value === null || typeof value !== \"object\") return value;\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)\n .map(([key, entry]) => [key, canonicalJson(entry)]),\n );\n };\n const hashValue = (value: unknown): string => hashString(JSON.stringify(canonicalJson(value)));\n const protectedSidecar = (value: MdfnSidecar | undefined): string => JSON.stringify(canonicalJson({\n comments: value?.comments ?? [],\n suggestions: value?.suggestions ?? [],\n reviewState: value?.reviewState ?? \"draft\",\n audit: value?.audit ?? [],\n }));\n const coarseChangedRanges = (before: string, after: string, offset: number): Array<{ from: number; to: number; insertedLength: number }> => {\n const ranges: Array<{ from: number; to: number; insertedLength: number }> = [];\n const syncLength = 16;\n const initialLookahead = 2_048;\n let remainingSearchWork = 65_536;\n let left = 0;\n let right = 0;\n let position = offset;\n while (left < before.length || right < after.length) {\n while (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) {\n left += 1;\n right += 1;\n position += 1;\n }\n if (left === before.length && right === after.length) break;\n const from = position;\n let match: { left: number; right: number; cost: number } | undefined;\n let lookahead = initialLookahead;\n const beforeAnchors = new Map<string, number>();\n const afterAnchors = new Map<string, number>();\n let beforeScannedTo = left - 1;\n let afterScannedTo = right - 1;\n while (!match) {\n const beforeLimit = Math.min(before.length - syncLength, left + lookahead);\n for (let candidate = beforeScannedTo + 1; candidate <= beforeLimit; candidate += 1) {\n if (remainingSearchWork === 0) break;\n remainingSearchWork -= 1;\n const key = before.slice(candidate, candidate + syncLength);\n if (!beforeAnchors.has(key)) beforeAnchors.set(key, candidate);\n const matchingRight = afterAnchors.get(key);\n if (matchingRight !== undefined) {\n const cost = candidate - left + matchingRight - right;\n if (!match || cost < match.cost) match = { left: candidate, right: matchingRight, cost };\n }\n beforeScannedTo = candidate;\n }\n const afterLimit = Math.min(after.length - syncLength, right + lookahead);\n for (let candidate = afterScannedTo + 1; candidate <= afterLimit; candidate += 1) {\n if (remainingSearchWork === 0) break;\n remainingSearchWork -= 1;\n const key = after.slice(candidate, candidate + syncLength);\n if (!afterAnchors.has(key)) afterAnchors.set(key, candidate);\n const matchingLeft = beforeAnchors.get(key);\n if (matchingLeft !== undefined) {\n const cost = matchingLeft - left + candidate - right;\n if (!match || cost < match.cost) match = { left: matchingLeft, right: candidate, cost };\n }\n afterScannedTo = candidate;\n }\n const searchedAllBefore = before.length - left < syncLength || beforeScannedTo >= before.length - syncLength;\n const searchedAllAfter = after.length - right < syncLength || afterScannedTo >= after.length - syncLength;\n if (match || remainingSearchWork === 0 || (searchedAllBefore && searchedAllAfter)) break;\n lookahead = Math.min(\n Math.max(before.length - left, after.length - right),\n lookahead * 2,\n );\n }\n if (!match || match.cost === 0) {\n ranges.push({ from, to: from + before.length - left, insertedLength: after.length - right });\n break;\n }\n const removed = match.left - left;\n const insertedLength = match.right - right;\n ranges.push({ from, to: from + removed, insertedLength });\n left = match.left;\n right = match.right;\n position += insertedLength;\n }\n return ranges;\n };\n const changedRanges = (previous: string, next: string): Array<{ from: number; to: number; insertedLength: number }> => {\n if (previous === next) return [];\n let prefix = 0;\n while (prefix < previous.length && prefix < next.length && previous.charCodeAt(prefix) === next.charCodeAt(prefix)) prefix += 1;\n let previousEnd = previous.length;\n let nextEnd = next.length;\n while (previousEnd > prefix && nextEnd > prefix && previous.charCodeAt(previousEnd - 1) === next.charCodeAt(nextEnd - 1)) { previousEnd -= 1; nextEnd -= 1; }\n const before = previous.slice(prefix, previousEnd);\n const after = next.slice(prefix, nextEnd);\n if (before.length * after.length > 250_000) return coarseChangedRanges(before, after, prefix);\n const width = after.length + 1;\n const lcs = new Uint32Array((before.length + 1) * width);\n for (let left = before.length - 1; left >= 0; left -= 1) {\n for (let right = after.length - 1; right >= 0; right -= 1) {\n const index = left * width + right;\n lcs[index] = before.charCodeAt(left) === after.charCodeAt(right)\n ? lcs[(left + 1) * width + right + 1] + 1\n : Math.max(lcs[(left + 1) * width + right], lcs[index + 1]);\n }\n }\n const ranges: Array<{ from: number; to: number; insertedLength: number }> = [];\n let left = 0;\n let right = 0;\n let position = prefix;\n while (left < before.length || right < after.length) {\n if (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) {\n left += 1; right += 1; position += 1; continue;\n }\n const from = position;\n let removed = 0;\n let insertedLength = 0;\n while (left < before.length || right < after.length) {\n if (left < before.length && right < after.length && before.charCodeAt(left) === after.charCodeAt(right)) break;\n if (right < after.length && (left === before.length || lcs[left * width + right + 1] >= lcs[(left + 1) * width + right])) {\n right += 1; insertedLength += 1;\n } else {\n left += 1; removed += 1;\n }\n }\n ranges.push({ from, to: from + removed, insertedLength });\n position += insertedLength;\n }\n return ranges;\n };\n const mapForMarkdownChange = (sidecar: MdfnSidecar | undefined, previous: string, next: string): MdfnSidecar | undefined => {\n if (!sidecar || previous === next) return sidecar;\n return mapSidecar(sidecar, changedRanges(previous, next));\n };\n interface Receipt { readonly operation: string; readonly payloadHash: string; readonly result: MdfnDocumentRecord; }\n const replayReceipt = async (storage: Storage, documentId: string, idempotencyKey: string, operation: string, payloadHash: string): Promise<MdfnDocumentRecord | undefined> => {\n const receipt = await storage.findOne<Receipt>({ model: RECEIPTS, where: [{ field: \"documentId\", operator: \"eq\", value: documentId }, { field: \"idempotencyKey\", operator: \"eq\", value: idempotencyKey }] });\n if (!receipt) return undefined;\n if (receipt.operation !== operation || receipt.payloadHash !== payloadHash) throw new MdfnServerError(\"MDFN_IDEMPOTENCY_KEY_REUSED\", 409);\n return receipt.result;\n };\n const writeUpdate = async (principal: MdfnPrincipal, id: string, input: UpdateInput, options: WriteUpdateOptions = {}): Promise<MdfnDocumentRecord> => {\n const current = await loadScoped(principal, id);\n await allowed(config, options.authorizationAction ?? \"update\", principal, current);\n const operation = options.idempotencyOperation ?? \"document:update\";\n const payloadHash = hashValue(options.idempotencyPayload ?? {\n ...input,\n idempotencyKey: undefined,\n restoreSnapshot: options.restoreSnapshot,\n });\n if (input.idempotencyKey) {\n const replay = await replayReceipt(database, id, input.idempotencyKey, operation, payloadHash);\n if (replay) return replay;\n }\n if (current.version !== input.expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n const markdown = options.restoreSnapshot?.markdown ?? input.markdown ?? current.markdown;\n if (!options.trustedEditorial && input.sidecar && protectedSidecar(input.sidecar) !== protectedSidecar(current.sidecar)) {\n throw new MdfnServerError(\"MDFN_EDITORIAL_MUTATION_FORBIDDEN\", 403);\n }\n const mappedSidecar = mapForMarkdownChange(current.sidecar, current.markdown, markdown);\n const sidecar = options.restoreSnapshot\n ? options.restoreSnapshot.sidecar\n : options.trustedEditorial\n ? input.sidecar ?? mappedSidecar\n : input.sidecar\n ? {\n ...input.sidecar,\n comments: mappedSidecar?.comments,\n suggestions: mappedSidecar?.suggestions,\n reviewState: mappedSidecar?.reviewState,\n audit: mappedSidecar?.audit,\n }\n : mappedSidecar;\n parse(markdown, sidecar);\n const title = options.restoreSnapshot ? options.restoreSnapshot.title : input.title ?? current.title;\n validateTitle(title);\n const next: MdfnDocumentRecord = { ...current, title, markdown, sourceHash: hashString(markdown), schemaHash: registry.schemaHash, sidecar, version: current.version + 1, updatedAt: now() };\n return withStorage(async (storage) => {\n if (input.idempotencyKey) {\n const replay = await replayReceipt(storage, id, input.idempotencyKey, operation, payloadHash);\n if (replay) return replay;\n }\n const latest = await storage.findOne<MdfnDocumentRecord>({ model: DOCUMENTS, where: whereId(id) });\n if (!latest || latest.version !== input.expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n const updated = await storage.update<MdfnDocumentRecord>({ model: DOCUMENTS, where: [{ field: \"id\", operator: \"eq\", value: id }, { field: \"version\", operator: \"eq\", value: input.expectedVersion }], data: next });\n await storage.create({ model: VERSIONS, data: revision(updated, principal.id, input.changeSource ?? \"update\") });\n if (input.idempotencyKey) await storage.create({ model: RECEIPTS, data: { id: createId(), documentId: id, idempotencyKey: input.idempotencyKey, operation, payloadHash, result: updated, createdAt: now() } });\n return updated;\n });\n };\n const mutateEditorial = async (\n principal: MdfnPrincipal,\n id: string,\n expectedVersion: number,\n authorizationAction: MdfnServerAction,\n changeSource: string,\n idempotencyKey: string | undefined,\n idempotencyPayload: unknown,\n mutate: (document: MdfnDocumentRecord) => { readonly markdown?: string; readonly sidecar: MdfnSidecar },\n ): Promise<MdfnDocumentRecord> => {\n const current = await loadScoped(principal, id);\n await allowed(config, authorizationAction, principal, current);\n if (idempotencyKey) {\n const replay = await replayReceipt(database, id, idempotencyKey, changeSource, hashValue(idempotencyPayload));\n if (replay) return replay;\n }\n if (current.version !== expectedVersion) throw new MdfnServerError(\"MDFN_VERSION_CONFLICT\", 409);\n try {\n const next = mutate(current);\n return writeUpdate(principal, id, { expectedVersion, markdown: next.markdown, sidecar: next.sidecar, changeSource, idempotencyKey }, { trustedEditorial: true, authorizationAction, idempotencyOperation: changeSource, idempotencyPayload });\n } catch (error) {\n if (error instanceof MdfnServerError) throw error;\n throw new MdfnServerError(\"MDFN_EDITORIAL_INVALID\", 422);\n }\n };\n service = {\n async create(principal, input) {\n await allowed(config, \"create\", principal);\n parse(input.markdown, input.sidecar);\n validateTitle(input.title);\n if (input.id !== undefined && (typeof input.id !== \"string\" || input.id.trim().length === 0)) {\n throw new MdfnServerError(\"MDFN_DOCUMENT_ID_INVALID\", 422);\n }\n if (input.sidecar && protectedSidecar(input.sidecar) !== protectedSidecar(undefined)) {\n throw new MdfnServerError(\"MDFN_EDITORIAL_MUTATION_FORBIDDEN\", 403);\n }\n const createdAt = now();\n const collaborationGeneration = createCollaborationGeneration();\n if (typeof collaborationGeneration !== \"string\" || collaborationGeneration.length === 0) {\n throw new MdfnServerError(\"MDFN_COLLAB_GENERATION_INVALID\", 500);\n }\n const document: MdfnDocumentRecord = { id: input.id ?? createId(), collaborationGeneration, ownerId: principal.id, tenantId: principal.tenantId, title: input.title, markdown: input.markdown, sourceHash: hashString(input.markdown), schemaHash: registry.schemaHash, sidecar: input.sidecar, version: 1, createdAt, updatedAt: createdAt };\n return withStorage(async (storage) => {\n const created = await storage.create<MdfnDocumentRecord>({ model: DOCUMENTS, data: document });\n await storage.create({ model: VERSIONS, data: revision(created, principal.id, \"create\") });\n return created;\n });\n },\n async read(principal, id) { const document = await loadScoped(principal, id); await allowed(config, \"read\", principal, document); return document; },\n async list(principal, options = {}) {\n await allowed(config, \"read\", principal);\n const where = principal.tenantId ? [{ field: \"tenantId\", operator: \"eq\" as const, value: principal.tenantId }] : [{ field: \"ownerId\", operator: \"eq\" as const, value: principal.id }];\n const offset = Math.max(0, options.offset ?? 0);\n const limit = Math.min(100, Math.max(1, options.limit ?? 50));\n const pageSize = Math.max(25, limit);\n const visible: MdfnDocumentRecord[] = [];\n let databaseOffset = 0;\n let authorizedOffset = 0;\n while (visible.length < limit) {\n const candidates = await database.findMany<MdfnDocumentRecord>({\n model: DOCUMENTS,\n where,\n orderBy: [{ field: \"updatedAt\", direction: \"desc\" }, { field: \"id\", direction: \"desc\" }],\n limit: pageSize,\n offset: databaseOffset,\n });\n databaseOffset += candidates.length;\n for (const document of candidates) {\n if (!principal.tenantId && document.tenantId !== undefined && document.tenantId !== null) continue;\n if (!(await config.authorize(\"read\", principal, document))) continue;\n if (authorizedOffset < offset) {\n authorizedOffset += 1;\n continue;\n }\n visible.push(document);\n if (visible.length === limit) break;\n }\n if (candidates.length < pageSize) break;\n }\n return visible;\n },\n async update(principal, id, input) { return writeUpdate(principal, id, input); },\n async delete(principal, id) {\n await serializeCollaborationWrite(id, async () => {\n const current = await loadScoped(principal, id);\n await allowed(config, \"delete\", principal, current);\n await withStorage(async (storage) => {\n const documentWhere = [{ field: \"documentId\", operator: \"eq\" as const, value: id }];\n await storage.deleteMany({ model: COLLAB_UPDATES, where: documentWhere });\n await storage.deleteMany({ model: RECEIPTS, where: documentWhere });\n await storage.deleteMany({ model: VERSIONS, where: documentWhere });\n await storage.delete({ model: DOCUMENTS, where: whereId(id) });\n });\n });\n },\n async versions(principal, id, options = {}) {\n const document = await loadScoped(principal, id);\n await allowed(config, \"history\", principal, document);\n const cursor = options.cursor === undefined ? undefined : Number(options.cursor);\n const requestedLimit = options.limit ?? 50;\n if ((cursor !== undefined && (!Number.isSafeInteger(cursor) || cursor < 1)) ||\n !Number.isSafeInteger(requestedLimit) || requestedLimit < 1) {\n throw new MdfnServerError(\"MDFN_VERSION_CURSOR_INVALID\", 422);\n }\n const limit = Math.min(100, requestedLimit);\n const where = [\n { field: \"documentId\", operator: \"eq\" as const, value: id },\n ...(cursor === undefined ? [] : [{ field: \"version\", operator: \"lt\" as const, value: cursor }]),\n ];\n const rows = await database.findMany<MdfnVersionSummary>({\n model: VERSIONS,\n where,\n select: [\n \"id\", \"documentId\", \"collaborationGeneration\", \"ownerId\", \"tenantId\", \"title\", \"sourceHash\", \"schemaHash\",\n \"version\", \"authorId\", \"changeSource\", \"createdAt\", \"updatedAt\",\n ],\n orderBy: [{ field: \"version\", direction: \"desc\" }],\n limit: limit + 1,\n });\n const versions = rows.slice(0, limit);\n return {\n versions,\n ...(rows.length > limit ? { nextCursor: String(versions.at(-1)!.version) } : {}),\n };\n },\n async version(principal, id, version) { const document = await loadScoped(principal, id); await allowed(config, \"history\", principal, document); const result = await database.findOne<MdfnVersionRecord>({ model: VERSIONS, where: [{ field: \"documentId\", operator: \"eq\", value: id }, { field: \"version\", operator: \"eq\", value: version }] }); if (!result) throw new MdfnServerError(\"MDFN_VERSION_NOT_FOUND\", 404); return result; },\n async restoreVersion(principal, id, input) {\n const current = await loadScoped(principal, id);\n await allowed(config, \"history:restore\", principal, current);\n const restored = await database.findOne<MdfnVersionRecord>({\n model: VERSIONS,\n where: [\n { field: \"documentId\", operator: \"eq\", value: id },\n { field: \"version\", operator: \"eq\", value: input.version },\n ],\n });\n if (!restored) throw new MdfnServerError(\"MDFN_VERSION_NOT_FOUND\", 404);\n return writeUpdate(\n principal,\n id,\n { expectedVersion: input.expectedVersion, changeSource: `restore:${input.version}`, idempotencyKey: input.idempotencyKey },\n {\n trustedEditorial: true,\n authorizationAction: \"history:restore\",\n restoreSnapshot: restored,\n idempotencyOperation: \"document:restore\",\n idempotencyPayload: input,\n },\n );\n },\n async createComment(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:create\", \"editorial:comment-created\", input.idempotencyKey, input, (document) => createCommentThread({ sidecar: document.sidecar, anchor: input.anchor, body: input.body, actor: editorialActor(principal), markdownLength: document.markdown.length }));\n },\n async replyComment(principal, id, threadId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:reply\", \"editorial:comment-replied\", input.idempotencyKey, { threadId, ...input }, (document) => ({ sidecar: replyToComment({ sidecar: document.sidecar ?? {}, threadId, body: input.body, actor: editorialActor(principal) }) }));\n },\n async resolveComment(principal, id, threadId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"comment:resolve\", input.resolved ? \"editorial:comment-resolved\" : \"editorial:comment-reopened\", input.idempotencyKey, { threadId, ...input }, (document) => ({ sidecar: setCommentResolved({ sidecar: document.sidecar ?? {}, threadId, resolved: input.resolved, actor: editorialActor(principal) }) }));\n },\n async createSuggestion(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"suggestion:create\", \"editorial:suggestion-created\", input.idempotencyKey, input, (document) => createSuggestion({ sidecar: document.sidecar, anchor: input.anchor, replacement: input.replacement, actor: editorialActor(principal), markdownLength: document.markdown.length }));\n },\n async decideSuggestion(principal, id, suggestionId, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"suggestion:decide\", `editorial:suggestion-${input.decision}`, input.idempotencyKey, { suggestionId, ...input }, (document) => {\n const controller = createEditor({ markdown: document.markdown, projector: createMarkdownProjector(markdownOptions), extensions: config.extensions, sidecar: document.sidecar });\n try {\n decideSuggestion({ controller, suggestionId, decision: input.decision, actor: editorialActor(principal) });\n const state = controller.getState();\n return { markdown: state.markdown, sidecar: state.sidecar ?? {} };\n } finally { controller.destroy(); }\n });\n },\n async transitionReview(principal, id, input) {\n return mutateEditorial(principal, id, input.expectedVersion, \"review:transition\", \"editorial:review-transitioned\", input.idempotencyKey, input, (document) => ({ sidecar: transitionReview({ sidecar: document.sidecar, to: input.state, actor: editorialActor(principal) }) }));\n },\n async appendCollaborationUpdate(principal, id, update) {\n if (new TextEncoder().encode(update).byteLength > collaborationUpdateBytes) throw new MdfnServerError(\"MDFN_COLLAB_UPDATE_TOO_LARGE\", 413);\n const updateId = createId();\n const createdAt = now();\n await withCollaborationWrite(principal, id, \"collaborate\", async (storage, cursorKey, documentGeneration) => {\n await storage.create({\n model: COLLAB_UPDATES,\n data: { id: updateId, documentId: id, documentGeneration, authorId: principal.id, update, cursorKey, createdAt },\n });\n });\n return updateId;\n },\n async collaborationUpdates(principal, id, options = {}) {\n const document = await loadScoped(principal, id);\n await allowed(config, \"collaborate\", principal, document);\n const requestedLimit = options.limit ?? collaborationBatchUpdates;\n if (!Number.isSafeInteger(requestedLimit) || requestedLimit < 1) {\n throw new MdfnServerError(\"MDFN_COLLAB_CURSOR_INVALID\", 422);\n }\n const limit = Math.min(collaborationBatchUpdates, requestedLimit);\n type CollaborationRow = { readonly id: string; readonly update: string; readonly cursorKey: string };\n const cursor = options.cursor === undefined ? undefined : decodeCollaborationCursor(options.cursor, id);\n const rows = await database.findMany<CollaborationRow>({\n model: COLLAB_UPDATES,\n where: [\n { field: \"documentId\", operator: \"eq\", value: id },\n { field: \"documentGeneration\", operator: \"eq\", value: document.collaborationGeneration },\n ...(cursor === undefined ? [] : [{ field: \"cursorKey\", operator: \"gt\" as const, value: cursor }]),\n ],\n orderBy: [{ field: \"cursorKey\", direction: \"asc\" }],\n limit: limit + 1,\n });\n const included: CollaborationRow[] = [];\n let encodedBytes = 0;\n for (const row of rows.slice(0, limit)) {\n const rowBytes = new TextEncoder().encode(row.update).byteLength;\n if (included.length > 0 && encodedBytes + rowBytes > collaborationBatchBytes) break;\n included.push(row);\n encodedBytes += rowBytes;\n }\n const hasMore = included.length < rows.length;\n return {\n updates: included.map((row) => row.update),\n includedUpdateIds: included.map((row) => row.id),\n ...(hasMore ? { nextCursor: encodeCollaborationCursor(id, included.at(-1)!.cursorKey) } : {}),\n };\n },\n async compactCollaborationUpdates(principal, id, snapshot, includedUpdateIds) {\n if (new TextEncoder().encode(snapshot).byteLength > collaborationUpdateBytes) throw new MdfnServerError(\"MDFN_COLLAB_UPDATE_TOO_LARGE\", 413);\n if (!Array.isArray(includedUpdateIds) || includedUpdateIds.some((updateId) => typeof updateId !== \"string\" || !updateId)) {\n throw new MdfnServerError(\"MDFN_COLLAB_COMPACTION_INVALID\", 422);\n }\n const uniqueUpdateIds = [...new Set(includedUpdateIds)];\n const updateId = createId();\n const createdAt = now();\n await withCollaborationWrite(principal, id, \"compact-collaboration\", async (storage, cursorKey, documentGeneration) => {\n if (uniqueUpdateIds.length > 0) {\n await storage.deleteMany({ model: COLLAB_UPDATES, where: [{ field: \"documentId\", operator: \"eq\", value: id }, { field: \"documentGeneration\", operator: \"eq\", value: documentGeneration }, { field: \"id\", operator: \"in\", value: uniqueUpdateIds }] });\n }\n await storage.create({ model: COLLAB_UPDATES, data: { id: updateId, documentId: id, documentGeneration, authorId: principal.id, update: snapshot, cursorKey, createdAt } });\n });\n return updateId;\n },\n };\n return service;\n}\n\nfunction etag(document: MdfnDocumentRecord): string { return `\\\"mdfn-${document.version}-${document.sourceHash}\\\"`; }\nfunction response(document: MdfnDocumentRecord, status = 200): Response { return Response.json(document, { status, headers: { ETag: etag(document), \"Cache-Control\": \"no-store\" } }); }\nfunction idempotent<T extends { readonly idempotencyKey?: string }>(request: Request, body: T): T {\n return { ...body, idempotencyKey: body.idempotencyKey ?? request.headers.get(\"Idempotency-Key\") ?? undefined };\n}\n\nexport function createMdfnRouter(config: MdfnServerConfig, service = createMdfnService(config)): Router<{ principal: MdfnPrincipal }> {\n const principal = config.resolvePrincipal ?? (() => { throw new MdfnServerError(\"MDFN_UNAUTHENTICATED\", 401); });\n const defaultBodyBytes = Math.max(\n configuredDocumentBytes(config) + 4 * 1024 * 1024,\n configuredCollaborationUpdateBytes(config) + 64 * 1024,\n );\n return createRouter({\n basePath: config.basePath ?? \"/api/mdfn\",\n maxBodyBytes: config.maxRequestBodyBytes ?? defaultBodyBytes,\n context: async (request) => ({ principal: await principal(request) }),\n onError: (error) => error instanceof MdfnServerError\n ? Response.json({ error: error.code }, { status: error.status })\n : error instanceof RouterError\n ? error.toResponse()\n : Response.json({ error: \"MDFN_INTERNAL_ERROR\" }, { status: 500 }),\n routes: [\n { method: \"GET\", path: \"/documents\", handler: (_request, context) => service.list(context.principal, { limit: Number(context.query.get(\"limit\") ?? 50), offset: Number(context.query.get(\"offset\") ?? 0) }).then((documents) => Response.json({ documents })) },\n { method: \"POST\", path: \"/documents\", handler: async (_request, context) => response(await service.create(context.principal, await context.json()), 201) },\n { method: \"GET\", path: \"/documents/:id\", handler: async (_request, context) => response(await service.read(context.principal, context.params.id!)) },\n { method: \"PATCH\", path: \"/documents/:id\", handler: async (request, context) => response(await service.update(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"DELETE\", path: \"/documents/:id\", handler: async (_request, context) => { await service.delete(context.principal, context.params.id!); return new Response(null, { status: 204 }); } },\n { method: \"GET\", path: \"/documents/:id/versions\", handler: async (_request, context) => Response.json(await service.versions(context.principal, context.params.id!, { cursor: context.query.get(\"cursor\") ?? undefined, limit: context.query.has(\"limit\") ? Number(context.query.get(\"limit\")) : undefined })) },\n { method: \"GET\", path: \"/documents/:id/versions/:version\", handler: async (_request, context) => Response.json(await service.version(context.principal, context.params.id!, Number(context.params.version))) },\n { method: \"POST\", path: \"/documents/:id/restore\", handler: async (request, context) => response(await service.restoreVersion(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"GET\", path: \"/documents/:id/sidecar\", handler: async (_request, context) => Response.json((await service.read(context.principal, context.params.id!)).sidecar ?? {}) },\n { method: \"PUT\", path: \"/documents/:id/sidecar\", handler: async (request, context) => { const body = idempotent(request, await context.json<{ expectedVersion: number; sidecar: MdfnSidecar; idempotencyKey?: string }>()); return response(await service.update(context.principal, context.params.id!, { ...body, changeSource: \"sidecar\" })); } },\n { method: \"GET\", path: \"/documents/:id/audit\", handler: async (_request, context) => Response.json({ audit: (await service.read(context.principal, context.params.id!)).sidecar?.audit ?? [] }) },\n { method: \"POST\", path: \"/documents/:id/comments\", handler: async (request, context) => response(await service.createComment(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"POST\", path: \"/documents/:id/comments/:threadId/replies\", handler: async (request, context) => response(await service.replyComment(context.principal, context.params.id!, context.params.threadId!, idempotent(request, await context.json()))) },\n { method: \"PATCH\", path: \"/documents/:id/comments/:threadId\", handler: async (request, context) => response(await service.resolveComment(context.principal, context.params.id!, context.params.threadId!, idempotent(request, await context.json()))) },\n { method: \"POST\", path: \"/documents/:id/suggestions\", handler: async (request, context) => response(await service.createSuggestion(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"PATCH\", path: \"/documents/:id/suggestions/:suggestionId\", handler: async (request, context) => response(await service.decideSuggestion(context.principal, context.params.id!, context.params.suggestionId!, idempotent(request, await context.json()))) },\n { method: \"PUT\", path: \"/documents/:id/review\", handler: async (request, context) => response(await service.transitionReview(context.principal, context.params.id!, idempotent(request, await context.json()))) },\n { method: \"GET\", path: \"/documents/:id/collaboration-updates\", handler: async (_request, context) => Response.json(await service.collaborationUpdates(context.principal, context.params.id!, { cursor: context.query.get(\"cursor\") ?? undefined, limit: context.query.has(\"limit\") ? Number(context.query.get(\"limit\")) : undefined })) },\n { method: \"POST\", path: \"/documents/:id/collaboration-updates\", handler: async (_request, context) => { const body = await context.json<{ update: string }>(); return Response.json({ id: await service.appendCollaborationUpdate(context.principal, context.params.id!, body.update) }, { status: 201 }); } },\n { method: \"PUT\", path: \"/documents/:id/collaboration-updates/compact\", handler: async (_request, context) => { const body = await context.json<{ snapshot: string; includedUpdateIds: string[] }>(); return Response.json({ id: await service.compactCollaborationUpdates(context.principal, context.params.id!, body.snapshot, body.includedUpdateIds) }); } },\n ],\n });\n}\n\nexport function createMdfnServer(config: MdfnServerConfig): { readonly service: MdfnService; readonly router: Router<{ principal: MdfnPrincipal }>; readonly schema: ReturnType<typeof getSchema> } {\n const service = createMdfnService(config);\n return { service, router: createMdfnRouter(config, service), schema: getSchema() };\n}\n\nexport const MDFN_SERVER_VERSION = \"0.1.1\" as const;\n"],"mappings":"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","names":["left","right","updateId"]}
package/package.json CHANGED
@@ -1,9 +1,57 @@
1
1
  {
2
- "name": "@mdfn/server", "version": "0.1.0", "description": "Self-hosted persistence, authorization, versioning, and HTTP routes for mdfn", "type": "module",
3
- "main": "dist/index.cjs", "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js", "require": "./dist/index.cjs" } },
4
- "scripts": { "build": "tsup src/index.ts --format esm,cjs --dts --sourcemap --clean", "test": "vitest run", "typecheck": "tsc --noEmit -p tsconfig.json", "lint": "tsc --noEmit -p tsconfig.json", "prepack": "npm run build" },
5
- "dependencies": { "@mdfn/core": "0.1.0", "@mdfn/markdown": "0.1.0", "@superfunctions/db": "0.1.4", "@superfunctions/http": "0.2.0" },
6
- "devDependencies": { "tsup": "^8.0.0", "typescript": "^5.3.0", "vitest": "3.2.4" },
7
- "files": ["dist", "README.md"], "sideEffects": false, "license": "MIT", "engines": { "node": ">=20 <25" }, "repository": { "type": "git", "url": "git+https://github.com/21nCo/super-functions.git", "directory": "mdfn/server" }, "publishConfig": { "access": "public" },
8
- "mdfn": { "status": "optional", "layer": "platform", "schemaVersion": 1 }
2
+ "name": "@mdfn/server",
3
+ "version": "0.1.1",
4
+ "description": "Self-hosted persistence, authorization, versioning, and HTTP routes for mdfn",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "scripts": {
17
+ "build": "tsup src/index.ts --format esm,cjs --dts --sourcemap --clean",
18
+ "test": "vitest run",
19
+ "typecheck": "tsc --noEmit -p tsconfig.json",
20
+ "lint": "tsc --noEmit -p tsconfig.json",
21
+ "prepack": "npm run build"
22
+ },
23
+ "dependencies": {
24
+ "@mdfn/core": "0.1.1",
25
+ "@mdfn/markdown": "0.1.1",
26
+ "@superfunctions/db": "0.1.4",
27
+ "@superfunctions/http": "0.2.0"
28
+ },
29
+ "devDependencies": {
30
+ "tsup": "^8.0.0",
31
+ "typescript": "^5.3.0",
32
+ "vitest": "3.2.4"
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md"
37
+ ],
38
+ "sideEffects": false,
39
+ "license": "MIT",
40
+ "engines": {
41
+ "node": ">=20 <25"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/21nCo/superfunctions.git",
46
+ "directory": "mdfn/server"
47
+ },
48
+ "publishConfig": {
49
+ "access": "public"
50
+ },
51
+ "mdfn": {
52
+ "status": "optional",
53
+ "layer": "platform",
54
+ "schemaVersion": 1
55
+ },
56
+ "gitHead": "699d9d09932199d660333c57fe7bc646492ea3bf"
9
57
  }