@elytracms/studio 0.0.94 → 0.0.96
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/convex/asset-alt-migration.test.ts +2 -2
- package/convex/asset-meta-patch.test.ts +218 -0
- package/convex/asset-replace-delete-race.test.ts +127 -0
- package/convex/assets.ts +27 -2
- package/convex/cms.ts +124 -8
- package/convex/delivery-redirects.test.ts +167 -0
- package/convex/delivery.ts +15 -5
- package/convex/rail-write-parity.test.ts +6 -6
- package/convex/redirects.ts +1 -1
- package/convex/schema.ts +6 -0
- package/convex/strict-reference-race.test.ts +139 -0
- package/dist/addon.d.ts +1 -1
- package/dist/addon.js.map +1 -1
- package/dist/components/ai/ai-chat-panel.js +15 -2
- package/dist/components/ai/ai-chat-panel.js.map +1 -1
- package/dist/components/ai/translate-document-action.d.ts +6 -0
- package/dist/components/ai/translate-document-action.js.map +1 -1
- package/dist/components/ai/translate-document-dialog.d.ts +1 -1
- package/dist/components/ai/translate-document-dialog.js +5 -5
- package/dist/components/ai/translate-document-dialog.js.map +1 -1
- package/dist/components/assets/asset-detail.js +29 -11
- package/dist/components/assets/asset-detail.js.map +1 -1
- package/dist/components/assets/asset-locale.d.ts +16 -0
- package/dist/components/assets/asset-locale.js +30 -0
- package/dist/components/assets/asset-locale.js.map +1 -0
- package/dist/components/assets/asset-meta-drift-notice.d.ts +13 -0
- package/dist/components/assets/asset-meta-drift-notice.js +22 -0
- package/dist/components/assets/asset-meta-drift-notice.js.map +1 -0
- package/dist/components/assets/asset-meta-label.d.ts +13 -0
- package/dist/components/assets/asset-meta-label.js +17 -0
- package/dist/components/assets/asset-meta-label.js.map +1 -0
- package/dist/components/assets/asset-metadata.d.ts +89 -15
- package/dist/components/assets/asset-metadata.js +123 -11
- package/dist/components/assets/asset-metadata.js.map +1 -1
- package/dist/components/assets/asset-search.d.ts +6 -2
- package/dist/components/assets/asset-search.js +19 -3
- package/dist/components/assets/asset-search.js.map +1 -1
- package/dist/components/assets/asset-thumb.js +6 -2
- package/dist/components/assets/asset-thumb.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.d.ts +25 -9
- package/dist/components/assets/assets-collection-view-source.js +80 -26
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/assets/assets-store.js +17 -4
- package/dist/components/assets/assets-store.js.map +1 -1
- package/dist/components/builder/builder-store.d.ts +21 -0
- package/dist/components/builder/builder-store.js +22 -0
- package/dist/components/builder/builder-store.js.map +1 -1
- package/dist/components/builder/canvas-commit-boundary.d.ts +22 -0
- package/dist/components/builder/canvas-commit-boundary.js +27 -0
- package/dist/components/builder/canvas-commit-boundary.js.map +1 -0
- package/dist/components/builder/canvas-rebase.d.ts +101 -0
- package/dist/components/builder/canvas-rebase.js +179 -0
- package/dist/components/builder/canvas-rebase.js.map +1 -0
- package/dist/components/builder/canvas-render-context.d.ts +6 -3
- package/dist/components/builder/canvas-render-context.js +17 -8
- package/dist/components/builder/canvas-render-context.js.map +1 -1
- package/dist/components/builder/composition-field-editor.d.ts +26 -2
- package/dist/components/builder/composition-field-editor.js +46 -27
- package/dist/components/builder/composition-field-editor.js.map +1 -1
- package/dist/components/builder/node-factory.js +15 -3
- package/dist/components/builder/node-factory.js.map +1 -1
- package/dist/components/builder/property-inspector.js +3 -1
- package/dist/components/builder/property-inspector.js.map +1 -1
- package/dist/components/builder/run-inspector.js +10 -6
- package/dist/components/builder/run-inspector.js.map +1 -1
- package/dist/components/cms/asset-field.d.ts +5 -2
- package/dist/components/cms/asset-field.js +34 -17
- package/dist/components/cms/asset-field.js.map +1 -1
- package/dist/components/cms/asset-picker-core.d.ts +2 -2
- package/dist/components/cms/asset-picker-core.js +2 -2
- package/dist/components/cms/asset-picker-core.js.map +1 -1
- package/dist/components/cms/asset-picker.js +6 -2
- package/dist/components/cms/asset-picker.js.map +1 -1
- package/dist/components/cms/canvas-commit.d.ts +62 -0
- package/dist/components/cms/canvas-commit.js +39 -0
- package/dist/components/cms/canvas-commit.js.map +1 -0
- package/dist/components/cms/cms-store.d.ts +21 -8
- package/dist/components/cms/cms-store.js +19 -10
- package/dist/components/cms/cms-store.js.map +1 -1
- package/dist/components/cms/collection-table.js +27 -18
- package/dist/components/cms/collection-table.js.map +1 -1
- package/dist/components/cms/commit-policy.d.ts +6 -2
- package/dist/components/cms/commit-policy.js +1 -1
- package/dist/components/cms/commit-policy.js.map +1 -1
- package/dist/components/cms/detail-editor.js +12 -2
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/draft-commit.d.ts +16 -3
- package/dist/components/cms/draft-commit.js +3 -2
- package/dist/components/cms/draft-commit.js.map +1 -1
- package/dist/components/cms/use-document-draft.d.ts +121 -5
- package/dist/components/cms/use-document-draft.js +197 -54
- package/dist/components/cms/use-document-draft.js.map +1 -1
- package/dist/components/cms/use-live-url.d.ts +6 -1
- package/dist/components/cms/use-live-url.js +12 -9
- package/dist/components/cms/use-live-url.js.map +1 -1
- package/dist/components/collection-view/cms-collection-view-source.js +11 -5
- package/dist/components/collection-view/cms-collection-view-source.js.map +1 -1
- package/dist/components/components/transfer-dialog.js +6 -4
- package/dist/components/components/transfer-dialog.js.map +1 -1
- package/dist/components/deployment-setup-gate.js +10 -1
- package/dist/components/deployment-setup-gate.js.map +1 -1
- package/dist/components/records/record-lens.js +3 -8
- package/dist/components/records/record-lens.js.map +1 -1
- package/dist/lib/ai/chat-state.d.ts +7 -0
- package/dist/lib/ai/chat-state.js.map +1 -1
- package/dist/lib/ai/tools.d.ts +8 -0
- package/dist/lib/ai/tools.js +4 -0
- package/dist/lib/ai/tools.js.map +1 -1
- package/dist/lib/assets/upload.d.ts +25 -7
- package/dist/lib/assets/upload.js +30 -21
- package/dist/lib/assets/upload.js.map +1 -1
- package/dist/lib/cms/published-documents.d.ts +24 -6
- package/dist/lib/cms/published-documents.js +39 -6
- package/dist/lib/cms/published-documents.js.map +1 -1
- package/dist/lib/cms-views/view-model.d.ts +25 -105
- package/dist/lib/cms-views/view-model.js +36 -103
- package/dist/lib/cms-views/view-model.js.map +1 -1
- package/dist/lib/collection-view/__fixtures__/document-writes.js +1 -0
- package/dist/lib/collection-view/__fixtures__/document-writes.js.map +1 -1
- package/dist/lib/collection-view/collection-view-source.d.ts +21 -8
- package/dist/lib/collection-view/collection-view-source.js.map +1 -1
- package/dist/lib/data/collection-content.js +5 -0
- package/dist/lib/data/collection-content.js.map +1 -1
- package/dist/lib/engine-version.d.ts +1 -1
- package/dist/lib/engine-version.js +1 -1
- package/dist/lib/engine-version.js.map +1 -1
- package/dist/lib/i18n/messages.de.js +20 -4
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +16 -1
- package/dist/lib/i18n/messages.en.js +22 -5
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/operations/cms-persistence.d.ts +80 -35
- package/dist/lib/operations/cms-persistence.js +348 -85
- package/dist/lib/operations/cms-persistence.js.map +1 -1
- package/dist/lib/operations/config-manifest-lookup.d.ts +1 -1
- package/dist/lib/operations/config-manifest-lookup.js +3 -3
- package/dist/lib/operations/config-manifest-lookup.js.map +1 -1
- package/dist/lib/persistence/convex-adapter.js +54 -8
- package/dist/lib/persistence/convex-adapter.js.map +1 -1
- package/dist/lib/persistence/deployment-readiness.js +14 -11
- package/dist/lib/persistence/deployment-readiness.js.map +1 -1
- package/dist/lib/persona/labels.js +2 -0
- package/dist/lib/persona/labels.js.map +1 -1
- package/dist/lib/query/index.d.ts +2 -2
- package/dist/lib/query/index.js +1 -1
- package/dist/lib/query/index.js.map +1 -1
- package/dist/lib/query/operations-query.d.ts +26 -0
- package/dist/lib/query/operations-query.js +12 -0
- package/dist/lib/query/operations-query.js.map +1 -1
- package/dist/lib/registry/index.js +2 -2
- package/dist/lib/registry/index.js.map +1 -1
- package/dist/lib/registry/preview.d.ts +10 -0
- package/dist/lib/registry/preview.js +13 -4
- package/dist/lib/registry/preview.js.map +1 -1
- package/dist/lib/routes/route-issues.js +6 -3
- package/dist/lib/routes/route-issues.js.map +1 -1
- package/dist/lib/workspace/workspace-source.js +6 -7
- package/dist/lib/workspace/workspace-source.js.map +1 -1
- package/dist/previews/entry-node.d.ts +14 -0
- package/dist/previews/entry-node.js +22 -0
- package/dist/previews/entry-node.js.map +1 -0
- package/dist/previews/harness.js +2 -16
- package/dist/previews/harness.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cms-persistence.js","sourceRoot":"","sources":["../../../src/lib/operations/cms-persistence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n applyDocumentPatches,\n documentKey,\n formatValuePath,\n selfTypeDocument,\n touchedPaths,\n valuePathsOverlap,\n} from '@elytracms/core/cms-core'\nimport type {\n CmsDocument,\n CollectionDef,\n DocumentPatch,\n DocumentRef,\n PropFieldLookup,\n RefusedPatch,\n ValuePath,\n} from '@elytracms/core/cms-core'\nimport type { CmsDocumentRecord } from '@elytracms/core/persistence'\nimport type { OperationError, OperationResult, OperationsClient } from './operations-package'\nimport { createPersistQueue } from './persist-queue'\n\n/**\n * CMS session → operations persistence (EC-141 → EC-595 part A2): the PATCH QUEUE.\n *\n * The CMS session keeps documents as optimistic, synchronous state; every write is\n * mirrored onto the operations layer through the revisioned aggregate's two verbs\n * (EC-595, ratified 2026-10-24): `documents.patch` for editing, `documents.replace`\n * for whole-document writers (create, import). There is no document diffing anywhere:\n * every writer EMITS the patches it made at its source (the form's field path, the\n * canvas's node patches, the AI proposal's field changes, bulk set-field, transfer) and\n * hands them to {@link CmsPersister.commit}.\n *\n * **Per document, the persister keeps** the server row it last adopted (`base` — its\n * revision is what a patch is made against), the committed-but-unacknowledged patches\n * (each with the revision the user's view was at when it was made), and the refused\n * paths awaiting a decision. It derives the session's view of the document from them:\n *\n * display = base.document ⊕ unresolved conflicts (mine) ⊕ in-flight ⊕ queued\n *\n * by re-applying the patches with THE merge (`applyDocumentPatches`, `since: []`) — the\n * same pure function both stores run. So local edits win on their paths until they are\n * flushed (EC-595 point 7), and a server row adopted underneath them (a write result,\n * a subscription push, a conflict's `current`) shows everywhere else at once.\n *\n * **Base revisions are per patch** (not per call): a patch is checked against the\n * changes in `(its base, current]`, so a colleague's change that arrived (by subscribe)\n * AFTER the user started typing in a field is still detected on that field. A patch\n * whose path our own successful write just covered moves its base to that write's\n * revision — the server guarantees no other session touched the path in between, so\n * a second edit of a field during the first one's flight never conflicts with itself.\n * Consecutive runs of equal base are sent in commit order, one `documents.patch` call\n * per run.\n *\n * **A refused path is a conflict ON THAT FIELD** ({@link DocumentConflict}): the\n * session shows \"changed by X — take theirs / keep mine\"; until the user decides, the\n * field keeps showing mine (and further edits of it replace mine without being sent);\n * keep-mine re-sends at the current base, take-theirs drops mine. Never a\n * whole-document dialog, never a silent overwrite.\n */\n\n/** One refused patch awaiting the user's decision (EC-595 binding point 5). */\nexport interface DocumentConflict {\n /** Stable id for the UI (`<key>|<path>`); one conflict per path. */\n readonly id: string\n readonly ref: DocumentRef\n /** The refused patch — \"mine\". */\n readonly patch: DocumentPatch\n /** The submitted target path. */\n readonly path: ValuePath\n /** The value at that path on the server NOW — \"theirs\" (`undefined` = absent). */\n readonly theirs: unknown\n /** `conflict` — changed since the base; `invalid` — never resolved (e.g. its node is gone). */\n readonly reason: RefusedPatch['reason']\n /** The server revision the refusal was made at. */\n readonly revision: number\n /** Who changed the path (the patch log's actor), once resolved; `undefined` while unknown. */\n readonly actor?: string\n}\n\n/** How one {@link CmsPersister.commit} ended once its patches were acknowledged. */\nexport type CommitOutcome =\n | { readonly status: 'applied'; readonly record: CmsDocumentRecord }\n /** Refused per field — the conflicts stay open on the document for the user to resolve. */\n | { readonly status: 'refused'; readonly conflicts: readonly DocumentConflict[] }\n /** A transport / authorization failure (also reported through `onError`). */\n | { readonly status: 'failed'; readonly error: OperationError }\n\nexport interface CmsPersister {\n /** Adopt a server row as this session's base for its document (hydration, a create result). */\n track(row: TrackedRow): void\n /** The revision the session's view of a document is at (`undefined` = untracked). */\n revisionOf(ref: DocumentRef): number | undefined\n /** The session's view of a tracked document (base ⊕ local), or `undefined`. */\n documentOf(ref: DocumentRef): CmsDocument | undefined\n /**\n * Commit patches a writer made (at the session's current view) and flush them. The\n * session's view updates synchronously (via `onDocument`); the patches persist in\n * order through `documents.patch`. `view` — the session's current document, the\n * provisional base of a document this session holds no revision for (a staged\n * transfer); its revision is read before the first send. `bases` — per patch, the\n * revision the user's view was at when they STARTED that edit (an editor field typed\n * across a colleague's change); absent → the revision the view is at now.\n */\n commit(\n ref: DocumentRef,\n patches: readonly DocumentPatch[],\n view?: CmsDocument,\n bases?: readonly (number | undefined)[],\n ): Promise<CommitOutcome>\n /** Adopt a server row one of the session's OWN direct writes returned (publish, restore). */\n adoptRecord(record: CmsDocumentRecord): void\n /** Create a document (insert-if-absent: `documents.replace` `{ ifAbsent: true }`). */\n create(document: CmsDocument): void\n /**\n * Write a whole document at the session's tracked revision (or insert-if-absent when\n * untracked): an import. A move since then is refused as a conflict, never overwritten.\n */\n replace(document: CmsDocument): void\n deleteDocument(ref: DocumentRef): void\n unpublishDocument(ref: DocumentRef): void\n /**\n * Adopt a server row pushed by the document subscription (EC-595 point 7): applied\n * under the local patches (local wins until flushed); held while a write is in flight\n * and applied after it, so an echo of our own write never races its result.\n * `undefined` = the document is gone.\n */\n adoptSnapshot(ref: DocumentRef, record: CmsDocumentRecord | undefined): void\n /** The unresolved conflicts on a document. */\n conflicts(ref: DocumentRef): readonly DocumentConflict[]\n /** Resolve a conflict: `theirs` adopts the server value; `mine` re-sends at the current base. */\n resolveConflict(ref: DocumentRef, conflictId: string, choice: 'theirs' | 'mine'): void\n /** Await every queued write (of one document, or all). The FORCED FLUSH's persistence half. */\n flush(ref?: DocumentRef): Promise<void>\n}\n\nexport interface CmsPersisterOptions {\n projectId: string\n getOperations: () => Promise<OperationsClient>\n /** The session's collections (read lazily via a ref) — the create/import canonicaliser's lens. */\n getCollections: () => readonly CollectionDef[]\n /** Component-prop field-defs (EC-277), so a created document's composition props are canonical too. */\n lookupManifest?: PropFieldLookup\n /** A failed / denied write that is not a per-field conflict — rendered by the session, never silent. */\n onError: (error: OperationError) => void\n /**\n * The session's view of a document changed (an optimistic commit, an adopted server\n * row, a resolved conflict) — `undefined` when the document is gone. Synchronous.\n */\n onDocument?: (ref: DocumentRef, document: CmsDocument | undefined) => void\n /**\n * A server row was adopted (EC-449 and friends): the session stamps the chokepoint's\n * `hasUnpublishedChanges`, `updatedAt`, `publishedAt` from it — and, since the row\n * carries the CANONICAL saved values, the session adopts those too (EC-586\n * found-but-left: the studio never adopted the saved canonical document).\n */\n onRecord?: (record: CmsDocumentRecord) => void\n /** A document's conflict list changed. */\n onConflicts?: (ref: DocumentRef, conflicts: readonly DocumentConflict[]) => void\n}\n\n/** What the session hydrated for a document: its value and the revision it is at. */\nexport type TrackedRow = Pick<CmsDocumentRecord, 'document' | 'revision'>\n\n/** A committed patch and the revision the user's view was at when it was made (`undefined`: on top of our own pending create). */\ninterface QueuedPatch {\n readonly patch: DocumentPatch\n base: number | undefined\n /** The commits waiting on this patch (a superseded value write hands its waiters on). */\n readonly settle: ((outcome: CommitOutcome) => void)[]\n}\n\n/** A patch's identity within one call: op + target path (no two value writes of one path share a run). */\nfunction targetKey(op: DocumentPatch['op'], path: ValuePath): string {\n return `${op} ${formatValuePath(path)}`\n}\n\nfunction patchTarget(patch: DocumentPatch): ValuePath {\n return patch.op === 'insert' ? [...patch.at.parent, { kind: 'node', id: patch.node.id }] : patch.path\n}\n\ninterface Entry {\n readonly ref: DocumentRef\n base: TrackedRow | undefined\n /** The session's document while no server row is adopted yet (a create in flight, an untracked doc). */\n provisional: CmsDocument | undefined\n /** Committed, not yet sent. */\n queue: QueuedPatch[]\n /** Sent, awaiting the result. */\n inFlight: QueuedPatch[]\n /** A whole-document write (create / replace / unpublish / delete) in flight. */\n busy: boolean\n conflicts: DocumentConflict[]\n /** A subscription row that arrived during a write (`null` = gone); adopted after it. */\n held: CmsDocumentRecord | null | undefined\n /** A drain is queued. */\n scheduled: boolean\n deleted: boolean\n}\n\nfunction conflictId(ref: DocumentRef, path: ValuePath): string {\n return `${documentKey(ref)}|${formatValuePath(path)}`\n}\n\n/** Paths two patches have in common (either touches a prefix of the other's). */\nfunction patchesOverlap(a: DocumentPatch, b: DocumentPatch): boolean {\n return touchedPaths(a).some((p) => touchedPaths(b).some((q) => valuePathsOverlap(p, q)))\n}\n\n/** A `set`/`unset` on exactly one path — the shape a later edit of the same field supersedes. */\nfunction isValueWrite(patch: DocumentPatch): patch is Extract<DocumentPatch, { op: 'set' | 'unset' }> {\n return patch.op === 'set' || patch.op === 'unset'\n}\n\nfunction samePath(a: ValuePath, b: ValuePath): boolean {\n return a.length === b.length && valuePathsOverlap(a, b)\n}\n\nexport function createCmsPersister(options: CmsPersisterOptions): CmsPersister {\n const queue = createPersistQueue((error) => {\n options.onError({\n code: 'unknown',\n message: error instanceof Error ? error.message : String(error),\n })\n })\n const entries = new Map<string, Entry>()\n\n function entryOf(ref: DocumentRef): Entry {\n const key = documentKey(ref)\n let entry = entries.get(key)\n if (!entry) {\n entry = {\n ref: { collection: ref.collection, id: ref.id },\n base: undefined,\n provisional: undefined,\n queue: [],\n inFlight: [],\n busy: false,\n conflicts: [],\n held: undefined,\n scheduled: false,\n deleted: false,\n }\n entries.set(key, entry)\n }\n return entry\n }\n\n /** EC-586: THE write canonicaliser over a whole document a writer hands us (create/import). */\n function canonical(doc: CmsDocument): CmsDocument {\n const collection = options.getCollections().find((c) => c.id === doc.collection)\n if (!collection) return doc\n return selfTypeDocument(doc, collection, options.lookupManifest ? { lookupManifest: options.lookupManifest } : {})\n }\n\n /** The session's view: base ⊕ unresolved mine ⊕ in-flight ⊕ queued (the pure merge, no log). */\n function display(entry: Entry): CmsDocument | undefined {\n const baseDocument = entry.base?.document ?? entry.provisional\n if (entry.deleted || !baseDocument) return undefined\n const patches = [\n ...entry.conflicts.map((conflict) => conflict.patch),\n ...entry.inFlight.map((queued) => queued.patch),\n ...entry.queue.map((queued) => queued.patch),\n ]\n if (patches.length === 0) return baseDocument\n return applyDocumentPatches({ document: baseDocument, patches, since: [] }).document\n }\n\n function emitDocument(entry: Entry): void {\n if (entry.deleted) return\n const shown = display(entry)\n if (shown) options.onDocument?.(entry.ref, shown)\n }\n\n function emitConflicts(entry: Entry): void {\n options.onConflicts?.(entry.ref, [...entry.conflicts])\n }\n\n /** Adopt a server row as the base (never a lower revision), re-derive the view. */\n function adopt(entry: Entry, record: CmsDocumentRecord): void {\n if (entry.base && record.revision < entry.base.revision) return\n entry.base = record\n options.onRecord?.(record)\n emitDocument(entry)\n }\n\n /** After a write: apply a subscription row that arrived meanwhile, if newer. */\n function adoptHeld(entry: Entry): void {\n const held = entry.held\n entry.held = undefined\n if (held === undefined) return\n if (held === null) {\n markGone(entry)\n return\n }\n if (!entry.base || held.revision > entry.base.revision) adopt(entry, held)\n }\n\n function markGone(entry: Entry): void {\n if (entry.deleted) return\n entry.deleted = true\n entry.queue = []\n options.onDocument?.(entry.ref, undefined)\n }\n\n function schedule(entry: Entry): void {\n if (entry.scheduled) return\n entry.scheduled = true\n queue.push(async () => {\n entry.scheduled = false\n await drain(entry)\n adoptHeld(entry)\n })\n }\n\n /** Who changed a refused path — the newest patch-log row in (base, current] touching it. Best-effort. */\n async function resolveActors(entry: Entry, sentBase: number, refused: readonly DocumentConflict[]): Promise<void> {\n try {\n const operations = await options.getOperations()\n const log = await operations.documents.listPatches({\n projectId: options.projectId,\n ref: entry.ref,\n afterRevision: sentBase,\n })\n if (!log.ok) return\n let changed = false\n entry.conflicts = entry.conflicts.map((conflict) => {\n if (conflict.actor !== undefined || !refused.some((r) => r.id === conflict.id)) return conflict\n const row = [...log.value]\n .reverse()\n .find(\n (candidate) =>\n candidate.kind === 'replace' ||\n candidate.patches.some((patch) =>\n touchedPaths(patch).some((path) => valuePathsOverlap(path, conflict.path)),\n ),\n )\n if (!row?.actor) return conflict\n changed = true\n return { ...conflict, actor: row.actor }\n })\n if (changed) emitConflicts(entry)\n } catch {\n // The actor is decoration on a conflict the user can already resolve.\n }\n }\n\n /** Send the queue, one run of equal base at a time, until it is empty or a write fails. */\n async function drain(entry: Entry): Promise<void> {\n while (entry.queue.length > 0 && !entry.deleted) {\n const operations = await options.getOperations()\n if (!entry.base) {\n // Untracked (a document the session never hydrated a revision for): read it.\n // The user's view of it is the session's, so this is the narrowest window left.\n const read = await operations.documents.get({ projectId: options.projectId, ref: entry.ref })\n if (!read.ok) {\n options.onError(read.error)\n return\n }\n entry.base = read.value\n }\n const resolveBase = (queued: QueuedPatch) => queued.base ?? entry.base!.revision\n const first = resolveBase(entry.queue[0]!)\n let end = 1\n while (end < entry.queue.length && resolveBase(entry.queue[end]!) === first) end += 1\n const run = entry.queue.splice(0, end)\n entry.inFlight = run\n const result = await operations.documents.patch({\n projectId: options.projectId,\n ref: entry.ref,\n baseRevision: first,\n patches: run.map((queued) => queued.patch),\n })\n entry.inFlight = []\n if (result.ok) {\n rebaseCovered(entry, run, result.value.revision)\n adopt(entry, result.value)\n adoptHeld(entry)\n settleAll(run, { status: 'applied', record: result.value })\n continue\n }\n const error = result.error\n if (error.code === 'conflict' && error.refused && error.current) {\n const current = error.current\n // Refusals are matched to the run by op + target path (the operation re-parses\n // and canonicalises the patches, so object identity does not survive the call).\n const refusedByKey = new Map(\n error.refused.map((refused) => [targetKey(refused.patch.op, refused.path), refused]),\n )\n const applied: QueuedPatch[] = []\n const conflicts: DocumentConflict[] = []\n for (const queued of run) {\n const refused = refusedByKey.get(targetKey(queued.patch.op, patchTarget(queued.patch)))\n if (!refused) {\n applied.push(queued)\n continue\n }\n // MINE is what the user wrote (the queued patch), not the canonicalised echo.\n const conflict = upsertConflict(entry, { ...refused, patch: queued.patch }, current.revision)\n conflicts.push(conflict)\n for (const settle of queued.settle) settle({ status: 'refused', conflicts: [conflict] })\n }\n rebaseCovered(entry, applied, current.revision)\n adopt(entry, current)\n adoptHeld(entry)\n emitConflicts(entry)\n settleAll(applied, { status: 'applied', record: current })\n void resolveActors(entry, first, conflicts)\n continue\n }\n if (error.code === 'conflict' && 'current' in error && error.current === null) {\n // The document was deleted since — nothing to write into.\n markGone(entry)\n options.onError(error)\n settleAll(run, { status: 'failed', error })\n return\n }\n // A transport / authorization failure: the patches stay local (shown, unsent) and\n // the error is visible; the next commit or forced flush retries them. The commits\n // waiting on them learn of the failure now.\n settleAll(run, { status: 'failed', error })\n entry.queue.unshift(...run.map((queued) => ({ ...queued, settle: [] })))\n adoptHeld(entry)\n options.onError(error)\n return\n }\n }\n\n function settleAll(queued: readonly QueuedPatch[], outcome: CommitOutcome): void {\n for (const item of queued) for (const settle of item.settle) settle(outcome)\n }\n\n /** Queued patches on a path our own write just covered move their base to that write's revision. */\n function rebaseCovered(entry: Entry, written: readonly QueuedPatch[], revision: number): void {\n if (written.length === 0) return\n for (const queued of entry.queue) {\n if (queued.base !== undefined && queued.base >= revision) continue\n if (written.some((done) => patchesOverlap(done.patch, queued.patch))) queued.base = revision\n }\n }\n\n function upsertConflict(entry: Entry, refused: RefusedPatch, revision: number): DocumentConflict {\n const conflict: DocumentConflict = {\n id: conflictId(entry.ref, refused.path),\n ref: entry.ref,\n patch: refused.patch,\n path: refused.path,\n theirs: refused.current,\n reason: refused.reason,\n revision,\n }\n entry.conflicts = [...entry.conflicts.filter((c) => c.id !== conflict.id), conflict]\n return conflict\n }\n\n function command(entry: Entry, run: (operations: OperationsClient) => Promise<OperationResult<unknown>>): void {\n queue.push(async () => {\n const operations = await options.getOperations()\n entry.busy = true\n try {\n const result = await run(operations)\n if (!result.ok) options.onError(result.error)\n } finally {\n entry.busy = false\n adoptHeld(entry)\n }\n })\n }\n\n return {\n track(row) {\n const entry = entryOf(row.document)\n if (!entry.base || row.revision > entry.base.revision) entry.base = row\n },\n revisionOf: (ref) => entries.get(documentKey(ref))?.base?.revision,\n documentOf: (ref) => {\n const entry = entries.get(documentKey(ref))\n return entry ? display(entry) : undefined\n },\n adoptRecord(record) {\n const entry = entryOf(record.document)\n if (entry.deleted) return\n if (!entry.base || record.revision > entry.base.revision) adopt(entry, record)\n },\n commit(ref, patches, view, bases) {\n const entry = entryOf(ref)\n if (patches.length === 0 || entry.deleted) {\n return Promise.resolve<CommitOutcome>({\n status: 'failed',\n error: { code: 'not-found', message: 'The document is gone.', entity: 'cms-document', key: documentKey(ref) },\n })\n }\n if (!entry.base && !entry.provisional && view) entry.provisional = view\n let conflictsChanged = false\n const waits: Promise<CommitOutcome>[] = []\n for (const [index, patch] of patches.entries()) {\n const madeAt = bases?.[index] ?? entry.base?.revision\n let settle!: (outcome: CommitOutcome) => void\n waits.push(new Promise<CommitOutcome>((resolve) => (settle = resolve)))\n // A field with an unresolved conflict: the new value replaces MINE, unsent —\n // the user decides (keep mine sends it), never an implicit overwrite of theirs.\n const open = entry.conflicts.find((conflict) => patchesOverlap(conflict.patch, patch))\n if (open && isValueWrite(patch) && isValueWrite(open.patch) && samePath(open.patch.path, patch.path)) {\n const replaced: DocumentConflict = { ...open, patch }\n entry.conflicts = entry.conflicts.map((c) => (c === open ? replaced : c))\n conflictsChanged = true\n settle({ status: 'refused', conflicts: [replaced] })\n continue\n }\n // A later value write of the same field supersedes an unsent one (keeping the\n // EARLIER base — the user never saw a foreign value of a field they were typing in).\n if (isValueWrite(patch)) {\n const pending = entry.queue.findIndex(\n (queued) => isValueWrite(queued.patch) && samePath(queued.patch.path, patch.path),\n )\n if (pending >= 0) {\n const superseded = entry.queue[pending]!\n entry.queue[pending] = { patch, base: superseded.base, settle: [...superseded.settle, settle] }\n continue\n }\n }\n entry.queue.push({ patch, base: madeAt, settle: [settle] })\n }\n emitDocument(entry)\n if (conflictsChanged) emitConflicts(entry)\n schedule(entry)\n // The commit's outcome: failed if any of its patches failed, refused if any was.\n return Promise.all(waits).then((outcomes): CommitOutcome => {\n const failed = outcomes.find((o) => o.status === 'failed')\n if (failed) return failed\n const refused = outcomes.flatMap((o) => (o.status === 'refused' ? o.conflicts : []))\n if (refused.length > 0) return { status: 'refused', conflicts: refused }\n return outcomes[outcomes.length - 1]!\n })\n },\n create(document) {\n const doc = canonical(document)\n const entry = entryOf(doc)\n entry.deleted = false\n // Optimistic: the session shows the document at once; the base is the created row.\n entry.provisional = doc\n options.onDocument?.(entry.ref, doc)\n queue.push(async () => {\n const operations = await options.getOperations()\n entry.busy = true\n try {\n const result = await operations.documents.replace({\n projectId: options.projectId,\n document: doc,\n precondition: { ifAbsent: true },\n })\n if (result.ok) adopt(entry, result.value)\n else options.onError(result.error)\n } finally {\n entry.busy = false\n adoptHeld(entry)\n }\n if (entry.queue.length > 0) await drain(entry)\n })\n },\n replace(document) {\n const doc = canonical(document)\n const entry = entryOf(doc)\n if (!entry.base) entry.provisional = doc\n options.onDocument?.(entry.ref, doc)\n queue.push(async () => {\n await drain(entry)\n const operations = await options.getOperations()\n entry.busy = true\n try {\n const result = await operations.documents.replace({\n projectId: options.projectId,\n document: doc,\n precondition: entry.base ? { revision: entry.base.revision } : { ifAbsent: true },\n })\n if (result.ok) adopt(entry, result.value)\n else {\n if (result.error.code === 'conflict' && 'current' in result.error && result.error.current) {\n adopt(entry, result.error.current)\n }\n options.onError(result.error)\n }\n } finally {\n entry.busy = false\n adoptHeld(entry)\n }\n })\n },\n deleteDocument(ref) {\n const entry = entryOf(ref)\n entry.queue = []\n entry.conflicts = []\n entry.deleted = true\n emitConflicts(entry)\n command(entry, (operations) => operations.documents.delete({ projectId: options.projectId, ref }))\n },\n unpublishDocument(ref) {\n const entry = entryOf(ref)\n queue.push(async () => {\n await drain(entry)\n const operations = await options.getOperations()\n entry.busy = true\n try {\n const result = await operations.documents.unpublish({ projectId: options.projectId, ref })\n if (result.ok) adopt(entry, result.value)\n else options.onError(result.error)\n } finally {\n entry.busy = false\n adoptHeld(entry)\n }\n })\n },\n adoptSnapshot(ref, record) {\n const entry = entryOf(ref)\n if (entry.inFlight.length > 0 || entry.busy || entry.scheduled) {\n // Hold it: the write's own result decides first; the newer of the two wins.\n if (record === undefined) entry.held = null\n else if (!entry.held || record.revision > entry.held.revision) entry.held = record\n return\n }\n if (record === undefined) {\n if (entry.base) markGone(entry)\n return\n }\n if (!entry.base || record.revision > entry.base.revision) adopt(entry, record)\n },\n conflicts: (ref) => entries.get(documentKey(ref))?.conflicts ?? [],\n resolveConflict(ref, id, choice) {\n const entry = entries.get(documentKey(ref))\n if (!entry) return\n const conflict = entry.conflicts.find((c) => c.id === id)\n if (!conflict) return\n entry.conflicts = entry.conflicts.filter((c) => c !== conflict)\n if (choice === 'mine') {\n // Keep mine: re-send at the CURRENT base — a visible, explicit second write.\n entry.queue.push({ patch: conflict.patch, base: entry.base?.revision, settle: [] })\n schedule(entry)\n }\n emitDocument(entry)\n emitConflicts(entry)\n },\n async flush(ref) {\n if (ref) {\n const entry = entries.get(documentKey(ref))\n if (entry && entry.queue.length > 0) schedule(entry)\n }\n await queue.flush()\n },\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cms-persistence.js","sourceRoot":"","sources":["../../../src/lib/operations/cms-persistence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n applyDocumentPatches,\n documentKey,\n formatValuePath,\n isValuePathPrefix,\n readValueAt,\n selfTypeDocument,\n semanticValueEqual,\n touchedPaths,\n valuePathsOverlap,\n} from '@elytracms/core/cms-core'\nimport type {\n CmsDocument,\n CollectionDef,\n DocumentPatch,\n DocumentRef,\n PropFieldLookup,\n RefusedPatch,\n ValuePath,\n} from '@elytracms/core/cms-core'\nimport type { CmsDocumentRecord } from '@elytracms/core/persistence'\nimport type { OperationError, OperationResult, OperationsClient } from './operations-package'\nimport { createPersistQueue } from './persist-queue'\n\n/**\n * CMS session → operations persistence (EC-141 → EC-595 part A2 → EC-647): the PATCH QUEUE.\n *\n * The CMS session keeps documents as optimistic, synchronous state; every write is\n * mirrored onto the operations layer through the revisioned aggregate's two verbs\n * (EC-595, ratified 2026-10-24): `documents.patch` for editing, `documents.replace`\n * for whole-document writers (create, import, the slot alias). There is no document\n * diffing anywhere: every writer EMITS the patches it made at its source (the form's\n * field path, the canvas's node patches, the AI proposal's field changes, bulk\n * set-field, transfer) and hands them to {@link CmsPersister.commit}.\n *\n * **Per document, the persister keeps** the server row it last adopted (`base`), the\n * committed-but-unacknowledged writes (each with the revision it was AUTHORED against),\n * the refused paths awaiting a decision, and the writes it made itself (the own-write\n * ledger). It derives the session's view of the document from them:\n *\n * display = base.document ⊕ unresolved conflicts (mine) ⊕ in-flight ⊕ queued\n *\n * by re-applying the patches with THE merge (`applyDocumentPatches`, `since: []`) — the\n * same pure function both stores run (a queued whole-document write resets the view to\n * its snapshot at its place in the order). So local edits win on their paths until they\n * are flushed (EC-595 point 7), and a server row adopted underneath them (a write\n * result, a subscription push, a conflict's `current`) shows everywhere else at once.\n *\n * **A value and the revision it was authored against travel together (EC-647).** Every\n * view this persister shows is registered with the revision it is at\n * ({@link CmsPersister.revisionOfView} — the shown document object IS the token), and a\n * writer hands each patch over WITH the revision of the view it was authored on\n * (`bases`, required). The persister never substitutes a newer revision for it — not at\n * commit (the old `bases ?? tracked revision` default), not at send (the old\n * `queued.base ?? entry.base.revision`), not in a whole-document `replace` (which read\n * the tracked revision at SEND time — Codex F10), and not for an untracked document\n * (which sent at whatever revision a later read returned). A write that cannot name the\n * revision it was authored against is refused, visibly — it never borrows one.\n *\n * - **A position under one of this session's own unacknowledged writes** (queued, in\n * flight, or an open conflict's \"mine\") was authored against THAT write's base: the\n * view showed mine there, not a colleague's change that may sit underneath it. The\n * later write takes the earlier base, so a colleague's hidden change is still refused\n * on it (same-field supersession has always kept the earlier base for this reason).\n * - **The own-write ledger.** A base may be LIFTED, at send time, across revisions this\n * persister wrote — and only those: across a run of consecutive own revisions right\n * after it (nothing foreign happened in between), or to an own write's revision when\n * the patch only touches positions that write covered and the write was sent at or\n * below the patch's base (the store refused every foreign change of those positions in\n * between, or the write would not have applied). Without it, the session's second\n * edit of a position, made at the revision its first was authored against, would be\n * refused by its own first write.\n * - **The provisional view** (`undefined` authoring revision): a document whose view\n * has no revision yet — our own create in flight, or a document the session never\n * tracked (a staged transfer). Writes on it are based on the revision our create\n * landed at, or — untracked — on a read of the document that EQUALS the view they were\n * authored on; anything else is refused as a conflict per position.\n *\n * Consecutive runs of equal (lifted) base are sent in commit order, one\n * `documents.patch` call per run; a queued whole-document write is sent in its place in\n * that order.\n *\n * **A refused path is a conflict ON THAT FIELD** ({@link DocumentConflict}): the\n * session shows \"changed by X — take theirs / keep mine\"; until the user decides, the\n * field keeps showing mine (and further edits of it replace mine without being sent);\n * keep-mine re-sends at the current base — the ONE deliberate \"at the current base\"\n * write: the user chose it after seeing theirs; take-theirs drops mine. Never a\n * whole-document dialog, never a silent overwrite.\n */\n\n/** One refused patch awaiting the user's decision (EC-595 binding point 5). */\nexport interface DocumentConflict {\n /** Stable id for the UI (`<key>|<path>`); one conflict per path. */\n readonly id: string\n readonly ref: DocumentRef\n /** The refused patch — \"mine\". */\n readonly patch: DocumentPatch\n /** The submitted target path. */\n readonly path: ValuePath\n /** The value at that path on the server NOW — \"theirs\" (`undefined` = absent). */\n readonly theirs: unknown\n /** `conflict` — changed since the base; `invalid` — never resolved (e.g. its node is gone). */\n readonly reason: RefusedPatch['reason']\n /** The server revision the refusal was made at. */\n readonly revision: number\n /** Who changed the path (the patch log's actor), once resolved; `undefined` while unknown. */\n readonly actor?: string\n}\n\n/** How one {@link CmsPersister.commit} ended once its patches were acknowledged. */\nexport type CommitOutcome =\n | { readonly status: 'applied'; readonly record: CmsDocumentRecord }\n /** Refused per field — the conflicts stay open on the document for the user to resolve. */\n | { readonly status: 'refused'; readonly conflicts: readonly DocumentConflict[] }\n /** A transport / authorization failure, or a write that named no authoring revision (also reported through `onError`). */\n | { readonly status: 'failed'; readonly error: OperationError }\n\nexport interface CmsPersister {\n /** Adopt a server row as this session's base for its document (hydration, a create result). */\n track(row: TrackedRow): void\n /** The revision the session's view of a document is at now (`undefined` = untracked). */\n revisionOf(ref: DocumentRef): number | undefined\n /** The session's view of a tracked document (base ⊕ local), or `undefined`. */\n documentOf(ref: DocumentRef): CmsDocument | undefined\n /**\n * EC-647 — the revision a document value this persister SHOWED is at: every view it\n * emits (`onDocument`, {@link documentOf}) and every row it tracks is registered with\n * its revision, so a writer holding the value it displayed holds its revision too —\n * the pair cannot drift apart. `undefined` for a value the persister never showed (a\n * copy, a fixture), or a provisional view (our own create in flight, an untracked\n * document).\n */\n revisionOfView(view: CmsDocument): number | undefined\n /**\n * Commit patches a writer made and flush them. The session's view updates\n * synchronously (via `onDocument`); the patches persist in order through\n * `documents.patch`. `bases` — REQUIRED, one per patch: the revision of the view the\n * writer authored that patch against (an editor field: the revision its draft was at\n * when the user STARTED that edit; the canvas: the revision of the value its delta is\n * measured from; a table row: {@link revisionOfView} of the row it showed; an AI\n * proposal: the revision of the read it was built from). `undefined` entries mean the\n * view was provisional (see the module doc) — on a document this session tracks and\n * did not create, such a patch is refused. `view` — the session's current document,\n * the provisional view of a document this session holds no revision for (a staged\n * transfer).\n */\n commit(\n ref: DocumentRef,\n patches: readonly DocumentPatch[],\n bases: readonly (number | undefined)[],\n view?: CmsDocument,\n ): Promise<CommitOutcome>\n /** Adopt a server row one of the session's OWN direct writes returned (publish, restore). */\n adoptRecord(record: CmsDocumentRecord): void\n /** Create a document (insert-if-absent: `documents.replace` `{ ifAbsent: true }`). */\n create(document: CmsDocument): void\n /**\n * Write a whole document at the revision it was AUTHORED against (EC-647 — the\n * snapshot and its revision travel together; Codex F10): an import, the slot alias. A\n * move since then — by anyone but this session's own writes — is refused as a\n * conflict, never overwritten. `revision` `undefined`: the snapshot was authored on a\n * provisional view (our own pending create; insert-if-absent when untracked). Sent in\n * its place among the session's queued patches.\n */\n replace(document: CmsDocument, revision: number | undefined): void\n deleteDocument(ref: DocumentRef): void\n unpublishDocument(ref: DocumentRef): void\n /**\n * Adopt a server row pushed by the document subscription (EC-595 point 7): applied\n * under the local patches (local wins until flushed); held while a write is in flight\n * and applied after it, so an echo of our own write never races its result.\n * `undefined` = the document is gone.\n */\n adoptSnapshot(ref: DocumentRef, record: CmsDocumentRecord | undefined): void\n /** The unresolved conflicts on a document. */\n conflicts(ref: DocumentRef): readonly DocumentConflict[]\n /** Resolve a conflict: `theirs` adopts the server value; `mine` re-sends at the current base. */\n resolveConflict(ref: DocumentRef, conflictId: string, choice: 'theirs' | 'mine'): void\n /** Await every queued write (of one document, or all). The FORCED FLUSH's persistence half. */\n flush(ref?: DocumentRef): Promise<void>\n}\n\nexport interface CmsPersisterOptions {\n projectId: string\n getOperations: () => Promise<OperationsClient>\n /** The session's collections (read lazily via a ref) — the create/import canonicaliser's lens. */\n getCollections: () => readonly CollectionDef[]\n /** Component-prop field-defs (EC-277), so a created document's composition props are canonical too. */\n lookupManifest?: PropFieldLookup\n /** A failed / denied write that is not a per-field conflict — rendered by the session, never silent. */\n onError: (error: OperationError) => void\n /**\n * The session's view of a document changed (an optimistic commit, an adopted server\n * row, a resolved conflict) — `undefined` when the document is gone. Synchronous. The\n * document object is registered with its revision ({@link CmsPersister.revisionOfView}).\n */\n onDocument?: (ref: DocumentRef, document: CmsDocument | undefined) => void\n /**\n * A server row was adopted (EC-449 and friends): the session stamps the chokepoint's\n * `hasUnpublishedChanges`, `updatedAt`, `publishedAt` from it — and, since the row\n * carries the CANONICAL saved values, the session adopts those too (EC-586\n * found-but-left: the studio never adopted the saved canonical document).\n */\n onRecord?: (record: CmsDocumentRecord) => void\n /** A document's conflict list changed. */\n onConflicts?: (ref: DocumentRef, conflicts: readonly DocumentConflict[]) => void\n}\n\n/** What the session hydrated for a document: its value and the revision it is at. */\nexport type TrackedRow = Pick<CmsDocumentRecord, 'document' | 'revision'>\n\n/** A committed patch and the revision it was AUTHORED against (EC-647 — never a tracked one). */\ninterface QueuedPatch {\n readonly kind: 'patch'\n readonly patch: DocumentPatch\n /** `undefined`: authored on the provisional view (our own pending create / an untracked document). */\n base: number | undefined\n /** The commits waiting on this patch (a superseded value write hands its waiters on). */\n readonly settle: ((outcome: CommitOutcome) => void)[]\n}\n\n/** A whole-document write, queued in its place among the patches (EC-647). */\ninterface QueuedReplace {\n readonly kind: 'replace'\n readonly document: CmsDocument\n /** The revision the snapshot was authored against (`undefined`: on the provisional view). */\n base: number | undefined\n}\n\ntype QueuedWrite = QueuedPatch | QueuedReplace\n\n/** One write THIS persister made and the store acknowledged (EC-647 — the own-write ledger). */\ninterface OwnWrite {\n readonly revision: number\n /** The base revision it was sent at (`undefined`: insert-if-absent, or a write with no base). */\n readonly sentBase: number | undefined\n /**\n * The positions its APPLIED patches touched: `undefined` = the whole document (a\n * replace / create — lifted across only as a consecutive own revision); `[]` = none\n * (an unpublish).\n */\n readonly paths: readonly ValuePath[] | undefined\n}\n\n/** How many own writes a document's ledger keeps (an older base just stops lifting — a conflict, never a borrow). */\nconst OWN_WRITES_KEPT = 256\n\n/** A patch's identity within one call: op + target path (no two value writes of one path share a run). */\nfunction targetKey(op: DocumentPatch['op'], path: ValuePath): string {\n return `${op} ${formatValuePath(path)}`\n}\n\nfunction patchTarget(patch: DocumentPatch): ValuePath {\n return patch.op === 'insert' ? [...patch.at.parent, { kind: 'node', id: patch.node.id }] : patch.path\n}\n\ninterface Entry {\n readonly ref: DocumentRef\n base: TrackedRow | undefined\n /** The session's document while no server row is adopted yet (a create in flight, an untracked doc). */\n provisional: CmsDocument | undefined\n /** Committed, not yet sent — patches and whole-document writes, in commit order. */\n queue: QueuedWrite[]\n /** Sent, awaiting the result. */\n inFlight: QueuedPatch[]\n /** A queued whole-document write that was sent, awaiting the result. */\n inFlightReplace: QueuedReplace | undefined\n /** A whole-document write (create / replace / unpublish / delete) in flight. */\n busy: boolean\n conflicts: DocumentConflict[]\n /** The base each open conflict's \"mine\" was authored against (by conflict id). */\n conflictBases: Map<string, number | undefined>\n /** A subscription row that arrived during a write (`null` = gone); adopted after it. */\n held: CmsDocumentRecord | null | undefined\n /** A drain is queued. */\n scheduled: boolean\n deleted: boolean\n /** Our own create of this document is in flight. */\n creating: boolean\n /** The revision our own create landed at (the base of every write authored on its provisional view). */\n created: number | undefined\n /** The own-write ledger (newest last). */\n own: OwnWrite[]\n}\n\nfunction conflictId(ref: DocumentRef, path: ValuePath): string {\n return `${documentKey(ref)}|${formatValuePath(path)}`\n}\n\n/** Paths two patches have in common (either touches a prefix of the other's). */\nfunction patchesOverlap(a: DocumentPatch, b: DocumentPatch): boolean {\n return touchedPaths(a).some((p) => touchedPaths(b).some((q) => valuePathsOverlap(p, q)))\n}\n\n/** A `set`/`unset` on exactly one path — the shape a later edit of the same field supersedes. */\nfunction isValueWrite(patch: DocumentPatch): patch is Extract<DocumentPatch, { op: 'set' | 'unset' }> {\n return patch.op === 'set' || patch.op === 'unset'\n}\n\nfunction samePath(a: ValuePath, b: ValuePath): boolean {\n return a.length === b.length && valuePathsOverlap(a, b)\n}\n\n/** The earlier of two authoring bases (`undefined` — the provisional view — is the earliest of all). */\nfunction earlierBase(a: number | undefined, b: number | undefined): number | undefined {\n return a === undefined || b === undefined ? undefined : Math.min(a, b)\n}\n\n/** The refusal of a write that names no revision it was authored against (EC-647). */\nfunction unauthoredError(ref: DocumentRef): OperationError {\n return {\n code: 'conflict',\n key: documentKey(ref),\n message:\n 'A change was not saved: it does not say which revision of the document it was made on, so it could overwrite a change made since (EC-647).',\n messageRef: { key: 'cms.conflict.unauthored' },\n }\n}\n\nexport function createCmsPersister(options: CmsPersisterOptions): CmsPersister {\n const queue = createPersistQueue((error) => {\n options.onError({\n code: 'unknown',\n message: error instanceof Error ? error.message : String(error),\n })\n })\n const entries = new Map<string, Entry>()\n /** EC-647: every document value this persister showed or tracked → the revision it is at. */\n const shown = new WeakMap<CmsDocument, number>()\n\n function entryOf(ref: DocumentRef): Entry {\n const key = documentKey(ref)\n let entry = entries.get(key)\n if (!entry) {\n entry = {\n ref: { collection: ref.collection, id: ref.id },\n base: undefined,\n provisional: undefined,\n queue: [],\n inFlight: [],\n inFlightReplace: undefined,\n busy: false,\n conflicts: [],\n conflictBases: new Map(),\n held: undefined,\n scheduled: false,\n deleted: false,\n creating: false,\n created: undefined,\n own: [],\n }\n entries.set(key, entry)\n }\n return entry\n }\n\n /** EC-586: THE write canonicaliser over a whole document a writer hands us (create/import). */\n function canonical(doc: CmsDocument): CmsDocument {\n const collection = options.getCollections().find((c) => c.id === doc.collection)\n if (!collection) return doc\n return selfTypeDocument(doc, collection, options.lookupManifest ? { lookupManifest: options.lookupManifest } : {})\n }\n\n /** The queued patches (not whole-document writes). */\n function queuedPatches(entry: Entry): QueuedPatch[] {\n return entry.queue.filter((queued): queued is QueuedPatch => queued.kind === 'patch')\n }\n\n /**\n * The session's view: base ⊕ unresolved mine ⊕ in-flight ⊕ queued (the pure merge, no\n * log; a whole-document write resets it to its snapshot). Registered with the revision\n * it is at (EC-647) — the base's; a provisional view has none.\n */\n function display(entry: Entry): CmsDocument | undefined {\n const baseDocument = entry.base?.document ?? entry.provisional\n if (entry.deleted || !baseDocument) return undefined\n let document = baseDocument\n let patches: DocumentPatch[] = entry.conflicts.map((conflict) => conflict.patch)\n const pending: QueuedWrite[] = [\n ...entry.inFlight,\n ...(entry.inFlightReplace ? [entry.inFlightReplace] : []),\n ...entry.queue,\n ]\n for (const queued of pending) {\n if (queued.kind === 'replace') {\n // The snapshot was authored over everything before it (the editor's draft).\n patches = []\n document = queued.document\n } else patches.push(queued.patch)\n }\n if (patches.length > 0) document = applyDocumentPatches({ document, patches, since: [] }).document\n if (entry.base) shown.set(document, entry.base.revision)\n return document\n }\n\n function emitDocument(entry: Entry): void {\n if (entry.deleted) return\n const view = display(entry)\n if (view) options.onDocument?.(entry.ref, view)\n }\n\n function emitConflicts(entry: Entry): void {\n options.onConflicts?.(entry.ref, [...entry.conflicts])\n }\n\n /** Adopt a server row as the base (never a lower revision), re-derive the view. */\n function adopt(entry: Entry, record: CmsDocumentRecord): void {\n if (entry.base && record.revision < entry.base.revision) return\n entry.base = record\n shown.set(record.document, record.revision)\n options.onRecord?.(record)\n emitDocument(entry)\n }\n\n /** After a write: apply a subscription row that arrived meanwhile, if newer. */\n function adoptHeld(entry: Entry): void {\n const held = entry.held\n entry.held = undefined\n if (held === undefined) return\n if (held === null) {\n markGone(entry)\n return\n }\n if (!entry.base || held.revision > entry.base.revision) adopt(entry, held)\n }\n\n function settleAll(queued: readonly QueuedPatch[], outcome: CommitOutcome): void {\n for (const item of queued) for (const settle of item.settle) settle(outcome)\n }\n\n /** Drop every queued write, settling its waiters (the document is gone, or the writes cannot be based). */\n function dropQueued(entry: Entry, outcome: CommitOutcome, which: (queued: QueuedWrite) => boolean = () => true): void {\n const dropped = entry.queue.filter(which)\n entry.queue = entry.queue.filter((queued) => !which(queued))\n settleAll(\n dropped.filter((queued): queued is QueuedPatch => queued.kind === 'patch'),\n outcome,\n )\n }\n\n function markGone(entry: Entry): void {\n if (entry.deleted) return\n entry.deleted = true\n dropQueued(entry, {\n status: 'failed',\n error: { code: 'not-found', message: 'The document is gone.', entity: 'cms-document', key: documentKey(entry.ref) },\n })\n options.onDocument?.(entry.ref, undefined)\n }\n\n function schedule(entry: Entry): void {\n if (entry.scheduled) return\n entry.scheduled = true\n queue.push(async () => {\n entry.scheduled = false\n await drain(entry)\n adoptHeld(entry)\n })\n }\n\n /** EC-647: record one of this persister's acknowledged writes (the own-write ledger). */\n function recordOwn(entry: Entry, write: OwnWrite): void {\n entry.own.push(write)\n if (entry.own.length > OWN_WRITES_KEPT) entry.own.splice(0, entry.own.length - OWN_WRITES_KEPT)\n }\n\n /**\n * EC-647 — THE lift: the base a write authored at `base` is SENT at. Only across this\n * persister's own writes (see the module doc): a run of consecutive own revisions\n * right after the base, or an own write that covered every position `paths` touch and\n * was sent at or below the base. Never across a revision anyone else wrote.\n */\n function lift(entry: Entry, base: number, paths: readonly ValuePath[] | undefined): number {\n let lifted = base\n for (;;) {\n if (entry.own.some((write) => write.revision === lifted + 1)) {\n lifted += 1\n continue\n }\n const covering = paths\n ? entry.own.find(\n (write) =>\n write.revision > lifted &&\n write.paths !== undefined &&\n write.sentBase !== undefined &&\n write.sentBase <= lifted &&\n paths.every((path) => write.paths!.some((covered) => isValuePathPrefix(covered, path))),\n )\n : undefined\n if (!covering) return lifted\n lifted = covering.revision\n }\n }\n\n /**\n * EC-647 — the base a write is QUEUED with: the revision it was authored against, or\n * the earlier base of an own unacknowledged write on the same positions (the view\n * showed mine there, not whatever may sit underneath it).\n */\n function authoredBase(entry: Entry, patch: DocumentPatch | undefined, authored: number | undefined): number | undefined {\n let base = authored\n const overlaps = (other: DocumentPatch) => patch === undefined || patchesOverlap(other, patch)\n for (const queued of [...entry.inFlight, ...entry.queue]) {\n if (queued.kind === 'replace' || overlaps(queued.patch)) base = earlierBase(base, queued.base)\n }\n if (entry.inFlightReplace) base = earlierBase(base, entry.inFlightReplace.base)\n for (const conflict of entry.conflicts) {\n if (overlaps(conflict.patch)) base = earlierBase(base, entry.conflictBases.get(conflict.id))\n }\n return base\n }\n\n /** Whether a write may be authored on a provisional view (our own create, or an untracked document). */\n function provisionalAllowed(entry: Entry): boolean {\n return entry.creating || entry.created !== undefined || !entry.base\n }\n\n /** Our own create landed (or failed): base every write authored on its provisional view. */\n function baseOnCreated(entry: Entry): void {\n if (entry.created === undefined) return\n for (const queued of entry.queue) if (queued.base === undefined) queued.base = entry.created\n }\n\n /**\n * EC-647 — writes authored on the provisional view of a document this session holds no\n * revision for (a staged transfer): read it; when it still EQUALS the view they were\n * authored on, that read's revision is theirs — otherwise each is refused as a\n * conflict on its position (theirs = the read). Never \"whatever revision the read\n * returns\". `false` when the read failed (the writes stay queued, the error shows).\n */\n async function baseOnRead(entry: Entry, operations: OperationsClient): Promise<boolean> {\n if (!entry.queue.some((queued) => queued.kind === 'patch' && queued.base === undefined)) return true\n if (entry.created !== undefined) {\n baseOnCreated(entry)\n return true\n }\n if (entry.base) {\n // A tracked document this session did not create: commit already refused these.\n const error = unauthoredError(entry.ref)\n dropQueued(entry, { status: 'failed', error }, (queued) => queued.kind === 'patch' && queued.base === undefined)\n options.onError(error)\n return true\n }\n const read = await operations.documents.get({ projectId: options.projectId, ref: entry.ref })\n if (!read.ok) {\n options.onError(read.error)\n return false\n }\n const record = read.value\n const authoredOn = entry.provisional\n if (authoredOn && semanticValueEqual(record.document, authoredOn)) {\n for (const queued of entry.queue) if (queued.kind === 'patch' && queued.base === undefined) queued.base = record.revision\n } else {\n const refused: DocumentConflict[] = []\n for (const queued of queuedPatches(entry)) {\n if (queued.base !== undefined) continue\n const path = patchTarget(queued.patch)\n const conflict = upsertConflict(\n entry,\n {\n patch: queued.patch,\n reason: 'conflict',\n path,\n current: readValueAt(record.document, path),\n detail: 'the document changed since the view this edit was made on',\n },\n record.revision,\n record.revision,\n )\n refused.push(conflict)\n for (const settle of queued.settle) settle({ status: 'refused', conflicts: [conflict] })\n }\n entry.queue = entry.queue.filter((queued) => !(queued.kind === 'patch' && queued.base === undefined))\n if (refused.length > 0) emitConflicts(entry)\n }\n adopt(entry, record)\n return true\n }\n\n /** Who changed a refused path — the newest patch-log row in (base, current] touching it. Best-effort. */\n async function resolveActors(entry: Entry, sentBase: number, refused: readonly DocumentConflict[]): Promise<void> {\n try {\n const operations = await options.getOperations()\n const log = await operations.documents.listPatches({\n projectId: options.projectId,\n ref: entry.ref,\n afterRevision: sentBase,\n })\n if (!log.ok) return\n let changed = false\n entry.conflicts = entry.conflicts.map((conflict) => {\n if (conflict.actor !== undefined || !refused.some((r) => r.id === conflict.id)) return conflict\n const row = [...log.value]\n .reverse()\n .find(\n (candidate) =>\n candidate.kind === 'replace' ||\n candidate.patches.some((patch) =>\n touchedPaths(patch).some((path) => valuePathsOverlap(path, conflict.path)),\n ),\n )\n if (!row?.actor) return conflict\n changed = true\n return { ...conflict, actor: row.actor }\n })\n if (changed) emitConflicts(entry)\n } catch {\n // The actor is decoration on a conflict the user can already resolve.\n }\n }\n\n /** Send one queued whole-document write at the revision its snapshot was authored against. `false` → stop draining. */\n async function sendReplace(entry: Entry, operations: OperationsClient, write: QueuedReplace): Promise<boolean> {\n const precondition =\n write.base !== undefined\n ? { revision: lift(entry, write.base, undefined) }\n : entry.created !== undefined\n ? { revision: lift(entry, entry.created, undefined) }\n : !entry.base\n ? { ifAbsent: true as const }\n : undefined\n entry.queue.shift()\n if (!precondition) {\n // A tracked document this session did not create, written whole from a view with no revision.\n options.onError(unauthoredError(entry.ref))\n emitDocument(entry)\n return true\n }\n entry.inFlightReplace = write\n entry.busy = true\n try {\n const result = await operations.documents.replace({\n projectId: options.projectId,\n document: write.document,\n precondition,\n })\n entry.inFlightReplace = undefined\n if (result.ok) {\n recordOwn(entry, {\n revision: result.value.revision,\n sentBase: 'revision' in precondition ? precondition.revision : undefined,\n paths: undefined,\n })\n adopt(entry, result.value)\n } else {\n if (result.error.code === 'conflict' && 'current' in result.error && result.error.current) {\n adopt(entry, result.error.current)\n } else emitDocument(entry)\n options.onError(result.error)\n }\n } finally {\n entry.inFlightReplace = undefined\n entry.busy = false\n adoptHeld(entry)\n }\n return true\n }\n\n /** Send the queue — runs of equal (lifted) base, whole-document writes in their place — until it is empty or a write fails. */\n async function drain(entry: Entry): Promise<void> {\n while (entry.queue.length > 0 && !entry.deleted) {\n const operations = await options.getOperations()\n if (!(await baseOnRead(entry, operations))) return\n const head = entry.queue[0]\n if (!head) return\n if (head.kind === 'replace') {\n await sendReplace(entry, operations, head)\n continue\n }\n const sendBase = (queued: QueuedPatch) => lift(entry, queued.base!, touchedPaths(queued.patch))\n const first = sendBase(head)\n let end = 1\n while (end < entry.queue.length) {\n const next = entry.queue[end]!\n if (next.kind !== 'patch' || sendBase(next) !== first) break\n end += 1\n }\n const run = entry.queue.splice(0, end) as QueuedPatch[]\n entry.inFlight = run\n const result = await operations.documents.patch({\n projectId: options.projectId,\n ref: entry.ref,\n baseRevision: first,\n patches: run.map((queued) => queued.patch),\n })\n entry.inFlight = []\n if (result.ok) {\n recordOwn(entry, {\n revision: result.value.revision,\n sentBase: first,\n paths: run.flatMap((queued) => touchedPaths(queued.patch)),\n })\n adopt(entry, result.value)\n adoptHeld(entry)\n settleAll(run, { status: 'applied', record: result.value })\n continue\n }\n const error = result.error\n if (error.code === 'conflict' && error.refused && error.current) {\n const current = error.current\n // Refusals are matched to the run by op + target path (the operation re-parses\n // and canonicalises the patches, so object identity does not survive the call).\n const refusedByKey = new Map(\n error.refused.map((refused) => [targetKey(refused.patch.op, refused.path), refused]),\n )\n const applied: QueuedPatch[] = []\n const conflicts: DocumentConflict[] = []\n for (const queued of run) {\n const refused = refusedByKey.get(targetKey(queued.patch.op, patchTarget(queued.patch)))\n if (!refused) {\n applied.push(queued)\n continue\n }\n // MINE is what the user wrote (the queued patch), not the canonicalised echo.\n const conflict = upsertConflict(entry, { ...refused, patch: queued.patch }, current.revision, queued.base)\n conflicts.push(conflict)\n for (const settle of queued.settle) settle({ status: 'refused', conflicts: [conflict] })\n }\n // A partially applied run IS a write of ours (the row it returns is after it);\n // a wholly refused one wrote nothing — its row is someone else's revision.\n if (applied.length > 0) {\n recordOwn(entry, {\n revision: current.revision,\n sentBase: first,\n paths: applied.flatMap((queued) => touchedPaths(queued.patch)),\n })\n }\n adopt(entry, current)\n adoptHeld(entry)\n emitConflicts(entry)\n settleAll(applied, { status: 'applied', record: current })\n void resolveActors(entry, first, conflicts)\n continue\n }\n if (error.code === 'conflict' && 'current' in error && error.current === null) {\n // The document was deleted since — nothing to write into.\n markGone(entry)\n options.onError(error)\n settleAll(run, { status: 'failed', error })\n return\n }\n // A transport / authorization failure: the patches stay local (shown, unsent) and\n // the error is visible; the next commit or forced flush retries them. The commits\n // waiting on them learn of the failure now.\n settleAll(run, { status: 'failed', error })\n entry.queue.unshift(...run.map((queued) => ({ ...queued, settle: [] })))\n adoptHeld(entry)\n options.onError(error)\n return\n }\n }\n\n function upsertConflict(\n entry: Entry,\n refused: RefusedPatch,\n revision: number,\n base: number | undefined,\n ): DocumentConflict {\n const conflict: DocumentConflict = {\n id: conflictId(entry.ref, refused.path),\n ref: entry.ref,\n patch: refused.patch,\n path: refused.path,\n theirs: refused.current,\n reason: refused.reason,\n revision,\n }\n entry.conflicts = [...entry.conflicts.filter((c) => c.id !== conflict.id), conflict]\n entry.conflictBases.set(conflict.id, base)\n return conflict\n }\n\n function command(entry: Entry, run: (operations: OperationsClient) => Promise<OperationResult<unknown>>): void {\n queue.push(async () => {\n const operations = await options.getOperations()\n entry.busy = true\n try {\n const result = await run(operations)\n if (!result.ok) options.onError(result.error)\n } finally {\n entry.busy = false\n adoptHeld(entry)\n }\n })\n }\n\n return {\n track(row) {\n const entry = entryOf(row.document)\n shown.set(row.document, row.revision)\n if (!entry.base || row.revision > entry.base.revision) entry.base = row\n },\n revisionOf: (ref) => entries.get(documentKey(ref))?.base?.revision,\n documentOf: (ref) => {\n const entry = entries.get(documentKey(ref))\n return entry ? display(entry) : undefined\n },\n revisionOfView: (view) => shown.get(view),\n adoptRecord(record) {\n const entry = entryOf(record.document)\n if (entry.deleted) return\n if (!entry.base || record.revision > entry.base.revision) adopt(entry, record)\n },\n commit(ref, patches, bases, view) {\n const entry = entryOf(ref)\n if (patches.length === 0 || entry.deleted) {\n return Promise.resolve<CommitOutcome>({\n status: 'failed',\n error: { code: 'not-found', message: 'The document is gone.', entity: 'cms-document', key: documentKey(ref) },\n })\n }\n if (!Array.isArray(bases)) {\n // EC-647: a writer that names no authoring revision at all — never given the tracked one.\n const error = unauthoredError(ref)\n options.onError(error)\n return Promise.resolve<CommitOutcome>({ status: 'failed', error })\n }\n if (!entry.base && !entry.provisional && view) entry.provisional = view\n let conflictsChanged = false\n let unauthored = false\n const waits: Promise<CommitOutcome>[] = []\n for (const [index, patch] of patches.entries()) {\n const authored = bases[index]\n let settle!: (outcome: CommitOutcome) => void\n waits.push(new Promise<CommitOutcome>((resolve) => (settle = resolve)))\n if (authored === undefined && !provisionalAllowed(entry)) {\n // EC-647: authored on a view with no revision, on a document this session\n // tracks and did not create — it cannot be checked, so it is not sent.\n unauthored = true\n settle({ status: 'failed', error: unauthoredError(ref) })\n continue\n }\n // A field with an unresolved conflict: the new value replaces MINE, unsent —\n // the user decides (keep mine sends it), never an implicit overwrite of theirs.\n const open = entry.conflicts.find((conflict) => patchesOverlap(conflict.patch, patch))\n if (open && isValueWrite(patch) && isValueWrite(open.patch) && samePath(open.patch.path, patch.path)) {\n const replaced: DocumentConflict = { ...open, patch }\n entry.conflicts = entry.conflicts.map((c) => (c === open ? replaced : c))\n conflictsChanged = true\n settle({ status: 'refused', conflicts: [replaced] })\n continue\n }\n const base = authoredBase(entry, patch, authored)\n // A later value write of the same field supersedes an unsent one (keeping the\n // EARLIER base — the user never saw a foreign value of a field they were typing\n // in). Only after the last queued whole-document write: one before it is sent\n // before the snapshot that was authored over it.\n if (isValueWrite(patch)) {\n let after = 0\n entry.queue.forEach((queued, at) => {\n if (queued.kind === 'replace') after = at + 1\n })\n const pending = entry.queue.findIndex(\n (queued, at) =>\n at >= after && queued.kind === 'patch' && isValueWrite(queued.patch) && samePath(queued.patch.path, patch.path),\n )\n if (pending >= 0) {\n const superseded = entry.queue[pending] as QueuedPatch\n entry.queue[pending] = {\n kind: 'patch',\n patch,\n base: earlierBase(superseded.base, base),\n settle: [...superseded.settle, settle],\n }\n continue\n }\n }\n entry.queue.push({ kind: 'patch', patch, base, settle: [settle] })\n }\n if (unauthored) options.onError(unauthoredError(ref))\n emitDocument(entry)\n if (conflictsChanged) emitConflicts(entry)\n schedule(entry)\n // The commit's outcome: failed if any of its patches failed, refused if any was.\n return Promise.all(waits).then((outcomes): CommitOutcome => {\n const failed = outcomes.find((o) => o.status === 'failed')\n if (failed) return failed\n const refused = outcomes.flatMap((o) => (o.status === 'refused' ? o.conflicts : []))\n if (refused.length > 0) return { status: 'refused', conflicts: refused }\n return outcomes[outcomes.length - 1]!\n })\n },\n create(document) {\n const doc = canonical(document)\n const entry = entryOf(doc)\n // A fresh document: nothing of an earlier incarnation of this ref carries over.\n entry.deleted = false\n entry.base = undefined\n entry.own = []\n entry.created = undefined\n entry.creating = true\n // Optimistic: the session shows the document at once; the base is the created row.\n entry.provisional = doc\n options.onDocument?.(entry.ref, doc)\n queue.push(async () => {\n const operations = await options.getOperations()\n entry.busy = true\n try {\n const result = await operations.documents.replace({\n projectId: options.projectId,\n document: doc,\n precondition: { ifAbsent: true },\n })\n if (result.ok) {\n entry.created = result.value.revision\n recordOwn(entry, { revision: result.value.revision, sentBase: undefined, paths: undefined })\n baseOnCreated(entry)\n adopt(entry, result.value)\n } else {\n options.onError(result.error)\n // EC-647: the writes authored on the document we meant to create have no\n // revision to be based on — never the revision of a row someone else wrote.\n dropQueued(entry, { status: 'failed', error: result.error }, (queued) => queued.base === undefined)\n }\n } finally {\n entry.creating = false\n entry.busy = false\n adoptHeld(entry)\n }\n if (entry.queue.length > 0) await drain(entry)\n })\n },\n replace(document, revision) {\n const doc = canonical(document)\n const entry = entryOf(doc)\n if (!entry.base && !entry.provisional) entry.provisional = doc\n // Queued in its place: the patches committed before it are sent first (the snapshot\n // holds them), the ones committed after it are sent after it (it does not). EC-647\n // (Codex F10): one with no authoring revision on a document this session tracks and\n // did not create is refused there, in order — never sent at the tracked revision.\n entry.queue.push({ kind: 'replace', document: doc, base: authoredBase(entry, undefined, revision) })\n emitDocument(entry)\n schedule(entry)\n },\n deleteDocument(ref) {\n const entry = entryOf(ref)\n dropQueued(entry, {\n status: 'failed',\n error: { code: 'not-found', message: 'The document is gone.', entity: 'cms-document', key: documentKey(ref) },\n })\n entry.conflicts = []\n entry.conflictBases.clear()\n entry.deleted = true\n emitConflicts(entry)\n command(entry, (operations) => operations.documents.delete({ projectId: options.projectId, ref }))\n },\n unpublishDocument(ref) {\n const entry = entryOf(ref)\n queue.push(async () => {\n await drain(entry)\n const operations = await options.getOperations()\n entry.busy = true\n try {\n const result = await operations.documents.unpublish({ projectId: options.projectId, ref })\n if (result.ok) {\n recordOwn(entry, { revision: result.value.revision, sentBase: undefined, paths: [] })\n adopt(entry, result.value)\n } else options.onError(result.error)\n } finally {\n entry.busy = false\n adoptHeld(entry)\n }\n })\n },\n adoptSnapshot(ref, record) {\n const entry = entryOf(ref)\n if (entry.inFlight.length > 0 || entry.busy || entry.scheduled) {\n // Hold it: the write's own result decides first; the newer of the two wins.\n if (record === undefined) entry.held = null\n else if (!entry.held || record.revision > entry.held.revision) entry.held = record\n return\n }\n if (record === undefined) {\n if (entry.base) markGone(entry)\n return\n }\n if (!entry.base || record.revision > entry.base.revision) adopt(entry, record)\n },\n conflicts: (ref) => entries.get(documentKey(ref))?.conflicts ?? [],\n resolveConflict(ref, id, choice) {\n const entry = entries.get(documentKey(ref))\n if (!entry) return\n const conflict = entry.conflicts.find((c) => c.id === id)\n if (!conflict) return\n entry.conflicts = entry.conflicts.filter((c) => c !== conflict)\n entry.conflictBases.delete(conflict.id)\n if (choice === 'mine') {\n // Keep mine: re-send at the CURRENT base — a visible, explicit second write, and\n // the one deliberate \"at the current base\" write (EC-647): the user chose it\n // after seeing theirs.\n entry.queue.push({ kind: 'patch', patch: conflict.patch, base: entry.base?.revision, settle: [] })\n schedule(entry)\n }\n emitDocument(entry)\n emitConflicts(entry)\n },\n async flush(ref) {\n if (ref) {\n const entry = entries.get(documentKey(ref))\n if (entry && entry.queue.length > 0) schedule(entry)\n }\n await queue.flush()\n },\n }\n}\n"]}
|
|
@@ -14,7 +14,7 @@ interface ManifestEntry {
|
|
|
14
14
|
* stays off that edge (`lib/cms/document-gate.ts` explains the same constraint for the
|
|
15
15
|
* validator seam). The manifests ARE the config's — the registry reads the very same
|
|
16
16
|
* entries — so reading them here is the same declaration, one reader per layer, not a
|
|
17
|
-
* second source. Only `component-registry`'s `
|
|
17
|
+
* second source. Only `component-registry`'s `manifestValueProps` (the one prop-def
|
|
18
18
|
* projection, name-injected) is imported.
|
|
19
19
|
*
|
|
20
20
|
* `entries` is read lazily on every lookup (the active project's list can be
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { manifestValueProps } from '@elytracms/core/component-registry';
|
|
2
2
|
/**
|
|
3
3
|
* EC-595 A1 (critic correction 4) — the operations context's manifest half of the write
|
|
4
4
|
* canonicaliser, built from the CONFIG's component entries (`elytra.config.ts`
|
|
@@ -9,7 +9,7 @@ import { manifestPropFields } from '@elytracms/core/component-registry';
|
|
|
9
9
|
* stays off that edge (`lib/cms/document-gate.ts` explains the same constraint for the
|
|
10
10
|
* validator seam). The manifests ARE the config's — the registry reads the very same
|
|
11
11
|
* entries — so reading them here is the same declaration, one reader per layer, not a
|
|
12
|
-
* second source. Only `component-registry`'s `
|
|
12
|
+
* second source. Only `component-registry`'s `manifestValueProps` (the one prop-def
|
|
13
13
|
* projection, name-injected) is imported.
|
|
14
14
|
*
|
|
15
15
|
* `entries` is read lazily on every lookup (the active project's list can be
|
|
@@ -28,7 +28,7 @@ export function configManifestLookup(entries) {
|
|
|
28
28
|
for (const entry of list ?? []) {
|
|
29
29
|
if (cachedById.has(entry.manifest.id))
|
|
30
30
|
continue;
|
|
31
|
-
cachedById.set(entry.manifest.id,
|
|
31
|
+
cachedById.set(entry.manifest.id, manifestValueProps(entry.manifest));
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
return cachedById.get(componentId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-manifest-lookup.js","sourceRoot":"","sources":["../../../src/lib/operations/config-manifest-lookup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAA;AASvE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAmD;IAEnD,IAAI,UAAgD,CAAA;IACpD,IAAI,UAAU,GAAG,IAAI,GAAG,EAAoC,CAAA;IAC5D,OAAO,CAAC,WAAW,EAAE,EAAE;QACrB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;QACtB,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,UAAU,GAAG,IAAI,CAAA;YACjB,UAAU,GAAG,IAAI,GAAG,EAAE,CAAA;YACtB,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;gBAC/B,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAAE,SAAQ;gBAC/C,UAAU,CAAC,GAAG,CACZ,KAAK,CAAC,QAAQ,CAAC,EAAE,EACjB,
|
|
1
|
+
{"version":3,"file":"config-manifest-lookup.js","sourceRoot":"","sources":["../../../src/lib/operations/config-manifest-lookup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAA;AASvE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAmD;IAEnD,IAAI,UAAgD,CAAA;IACpD,IAAI,UAAU,GAAG,IAAI,GAAG,EAAoC,CAAA;IAC5D,OAAO,CAAC,WAAW,EAAE,EAAE;QACrB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;QACtB,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,UAAU,GAAG,IAAI,CAAA;YACjB,UAAU,GAAG,IAAI,GAAG,EAAE,CAAA;YACtB,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;gBAC/B,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAAE,SAAQ;gBAC/C,UAAU,CAAC,GAAG,CACZ,KAAK,CAAC,QAAQ,CAAC,EAAE,EACjB,kBAAkB,CAAC,KAAK,CAAC,QAAQ,CAAC,CACnC,CAAA;YACH,CAAC;QACH,CAAC;QACD,OAAO,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACpC,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,UAAuE;IAEvE,MAAM,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAA;IACpD,OAAO,CAAC,SAAS,EAAE,EAAE;QACnB,IAAI,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACrC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,oBAAoB,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAA;YAC1D,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QAClC,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;AACH,CAAC","sourcesContent":["import { manifestValueProps } from '@elytracms/core/component-registry'\nimport type { ComponentManifest } from '@elytracms/core/component-registry'\nimport type { FieldDef, PropFieldLookup } from '@elytracms/core/cms-core'\n\n/** The one part of a config component entry the lookup reads. */\ninterface ManifestEntry {\n readonly manifest: ComponentManifest\n}\n\n/**\n * EC-595 A1 (critic correction 4) — the operations context's manifest half of the write\n * canonicaliser, built from the CONFIG's component entries (`elytra.config.ts`\n * `components`: `{ manifest, implementation }` pairs).\n *\n * Why not the studio registry's `studioManifestLookup()`: `lib/registry` registers the\n * implementations through `runtime-renderer`, and the operations bootstrap deliberately\n * stays off that edge (`lib/cms/document-gate.ts` explains the same constraint for the\n * validator seam). The manifests ARE the config's — the registry reads the very same\n * entries — so reading them here is the same declaration, one reader per layer, not a\n * second source. Only `component-registry`'s `manifestValueProps` (the one prop-def\n * projection, name-injected) is imported.\n *\n * `entries` is read lazily on every lookup (the active project's list can be\n * re-resolved); the per-list cache keeps a hot path a map read. A duplicate component id\n * resolves to the FIRST entry — the registry's `registerComponents` reports duplicates as\n * a visible issue, so a duplicate is already a broken config the studio surfaces.\n */\nexport function configManifestLookup(\n entries: () => readonly ManifestEntry[] | undefined,\n): PropFieldLookup {\n let cachedList: readonly ManifestEntry[] | undefined\n let cachedById = new Map<string, Record<string, FieldDef>>()\n return (componentId) => {\n const list = entries()\n if (list !== cachedList) {\n cachedList = list\n cachedById = new Map()\n for (const entry of list ?? []) {\n if (cachedById.has(entry.manifest.id)) continue\n cachedById.set(\n entry.manifest.id,\n manifestValueProps(entry.manifest),\n )\n }\n }\n return cachedById.get(componentId)\n }\n}\n\n/**\n * EC-595 A2 (A1 found-but-left #1) — the manifest lookup for the operation's OWN\n * project: the operations context's `manifestLookup` resolver. One operations bundle is\n * cached per deployment key and may serve several config projects with different\n * component lists, so a write to an inactive project canonicalises its props with THAT\n * project's manifests, never the active one's. `entriesFor` reads the config project\n * by id (see `configProjectFor`); one cached lookup per project id.\n */\nexport function projectManifestLookup(\n entriesFor: (projectId: string) => readonly ManifestEntry[] | undefined,\n): (projectId: string) => PropFieldLookup {\n const byProject = new Map<string, PropFieldLookup>()\n return (projectId) => {\n let lookup = byProject.get(projectId)\n if (!lookup) {\n lookup = configManifestLookup(() => entriesFor(projectId))\n byProject.set(projectId, lookup)\n }\n return lookup\n }\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConvexError } from 'convex/values';
|
|
2
2
|
import { DRAFT_VARIANT, documentKey, documentSchema } from '@elytracms/core/cms-core';
|
|
3
|
-
import { PRESENCE_TTL_MS, RecordNotFoundError, PersistenceValidationError, presenceInputSchema, assetCreateDefaults, assetRecordFromRow, compareReferenceEntries, persistenceIssueSchema, presentWriteKeys, recordEntryFromWire, validateForPersistence, versionNotPinnableError, } from '@elytracms/core/persistence';
|
|
3
|
+
import { PRESENCE_TTL_MS, RecordNotFoundError, PersistenceValidationError, StrictReferencePreconditionError, presenceInputSchema, assetCreateDefaults, assetRecordFromRow, compareReferenceEntries, persistenceIssueSchema, presentWriteKeys, recordEntryFromWire, validateForPersistence, versionNotPinnableError, } from '@elytracms/core/persistence';
|
|
4
4
|
import { normalizeInviteEmail } from '@elytracms/core/persistence';
|
|
5
5
|
import { createUuidIdFactory } from '@elytracms/core/determinism';
|
|
6
6
|
import { SUBSCRIPTION_UNAUTHENTICATED_MESSAGE, queryRef, mutationRef } from './convex-client.js';
|
|
@@ -55,6 +55,18 @@ function versionRecordFromDoc(doc, projectId) {
|
|
|
55
55
|
...(doc.kind ? { kind: doc.kind } : {}),
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
+
/** EC-649 — a document ref as the mutations' validators take it (exactly two keys). */
|
|
59
|
+
function wireRefs(refs) {
|
|
60
|
+
return refs.map((ref) => ({ collection: ref.collection, id: ref.id }));
|
|
61
|
+
}
|
|
62
|
+
/** EC-649 — the judged published referrers as `cms:unpublishDocument` / `cms:deleteDocument` take them. */
|
|
63
|
+
function wireReferrers(referrers) {
|
|
64
|
+
return referrers.map((referrer) => ({
|
|
65
|
+
collection: referrer.ref.collection,
|
|
66
|
+
id: referrer.ref.id,
|
|
67
|
+
publishedVersion: referrer.publishedVersion,
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
58
70
|
/**
|
|
59
71
|
* The Convex CMS repository — the client half of the revisioned aggregate (EC-595). It
|
|
60
72
|
* maps the handlers' outcomes onto the provider-neutral contract (a conflict is DATA,
|
|
@@ -113,10 +125,15 @@ class ConvexCmsRepository {
|
|
|
113
125
|
...(options.label ? { label: options.label } : {}),
|
|
114
126
|
...(options.origin ? { origin: options.origin } : {}),
|
|
115
127
|
at: this.clock(),
|
|
128
|
+
// EC-649: re-checked in the mutation's transaction (data-only, EC-565 1e).
|
|
129
|
+
...(options.strictTargets?.length ? { strictTargets: wireRefs(options.strictTargets) } : {}),
|
|
116
130
|
}));
|
|
117
131
|
if (result.status === 'missing') {
|
|
118
132
|
throw new RecordNotFoundError('cms-document', `${projectId}/${documentKey(ref)}`);
|
|
119
133
|
}
|
|
134
|
+
if (result.status === 'strict-targets') {
|
|
135
|
+
throw new StrictReferencePreconditionError('unpublished-targets', `${projectId}/${documentKey(ref)}`, result.refs);
|
|
136
|
+
}
|
|
120
137
|
if (result.status === 'conflict') {
|
|
121
138
|
return { status: 'conflict', current: docRecordFromDoc(result.current, projectId) };
|
|
122
139
|
}
|
|
@@ -249,13 +266,30 @@ class ConvexCmsRepository {
|
|
|
249
266
|
.map((doc) => documentSchema.parse(doc))
|
|
250
267
|
.sort((a, b) => (documentKey(a) < documentKey(b) ? -1 : 1));
|
|
251
268
|
}
|
|
252
|
-
async deleteDocument(projectId, ref) {
|
|
269
|
+
async deleteDocument(projectId, ref, precondition) {
|
|
253
270
|
// EC-153 parity: deleting a missing document is not-found, never a no-op.
|
|
254
271
|
await this.getDocument(projectId, ref);
|
|
255
|
-
|
|
272
|
+
// EC-648 / EC-649: checked in the mutation's transaction (data-only, EC-565 1e); sent only
|
|
273
|
+
// when it says something, so a delete without one keeps the pre-EC-648 arguments.
|
|
274
|
+
const wire = {
|
|
275
|
+
...(precondition?.revision !== undefined ? { revision: precondition.revision } : {}),
|
|
276
|
+
...(precondition?.publishedReferrers ? { publishedReferrers: wireReferrers(precondition.publishedReferrers) } : {}),
|
|
277
|
+
};
|
|
278
|
+
const result = (await this.client.mutation(mutationRef('cms:deleteDocument'), {
|
|
256
279
|
collection: ref.collection,
|
|
257
280
|
docId: ref.id,
|
|
258
|
-
|
|
281
|
+
...(Object.keys(wire).length > 0 ? { precondition: wire } : {}),
|
|
282
|
+
}));
|
|
283
|
+
if (result?.status === 'conflict') {
|
|
284
|
+
// Gone between the preflight and the mutation: the EC-153 not-found, as above.
|
|
285
|
+
if (!result.current)
|
|
286
|
+
throw new RecordNotFoundError('cms-document', `${projectId}/${documentKey(ref)}`);
|
|
287
|
+
return { status: 'conflict', current: docRecordFromDoc(result.current, projectId) };
|
|
288
|
+
}
|
|
289
|
+
if (result?.status === 'unjudged-referrers') {
|
|
290
|
+
throw new StrictReferencePreconditionError('unjudged-referrers', `${projectId}/${documentKey(ref)}`, result.refs);
|
|
291
|
+
}
|
|
292
|
+
return { status: 'ok' };
|
|
259
293
|
}
|
|
260
294
|
async clearDocuments(_projectId) {
|
|
261
295
|
// EC-576: one deployment is one project — the mutation clears both tables at once.
|
|
@@ -295,7 +329,7 @@ class ConvexCmsRepository {
|
|
|
295
329
|
}
|
|
296
330
|
return versionRecordFromDoc(doc, projectId);
|
|
297
331
|
}
|
|
298
|
-
async publishDocumentVersion(projectId, ref, version) {
|
|
332
|
+
async publishDocumentVersion(projectId, ref, version, precondition) {
|
|
299
333
|
// EC-595: pin integrity is enforced IN the transaction (the version must exist for
|
|
300
334
|
// this document); the outcomes map onto the EC-153 not-found taxonomy here. EC-447:
|
|
301
335
|
// one `now` for both stamps — the publish-action instant is the SET-ONCE candidate.
|
|
@@ -306,6 +340,8 @@ class ConvexCmsRepository {
|
|
|
306
340
|
version,
|
|
307
341
|
updatedAt: now,
|
|
308
342
|
publishedAt: now,
|
|
343
|
+
// EC-649: re-checked in the mutation's transaction (data-only, EC-565 1e).
|
|
344
|
+
...(precondition?.strictTargets?.length ? { strictTargets: wireRefs(precondition.strictTargets) } : {}),
|
|
309
345
|
}));
|
|
310
346
|
if (result.status === 'missing') {
|
|
311
347
|
throw new RecordNotFoundError('cms-document', `${projectId}/${documentKey(ref)}`);
|
|
@@ -317,9 +353,12 @@ class ConvexCmsRepository {
|
|
|
317
353
|
// refusal the in-memory store raises.
|
|
318
354
|
if (result.status === 'not-pinnable')
|
|
319
355
|
throw versionNotPinnableError(`${projectId}/${documentKey(ref)}`, version);
|
|
356
|
+
if (result.status === 'strict-targets') {
|
|
357
|
+
throw new StrictReferencePreconditionError('unpublished-targets', `${projectId}/${documentKey(ref)}`, result.refs);
|
|
358
|
+
}
|
|
320
359
|
return docRecordFromDoc(result.row, projectId);
|
|
321
360
|
}
|
|
322
|
-
async unpublishDocument(projectId, ref) {
|
|
361
|
+
async unpublishDocument(projectId, ref, precondition) {
|
|
323
362
|
const existing = await this.getDocument(projectId, ref);
|
|
324
363
|
if (existing.publishedVersion === undefined) {
|
|
325
364
|
throw new PersistenceValidationError('Document is not currently published.', [
|
|
@@ -330,12 +369,19 @@ class ConvexCmsRepository {
|
|
|
330
369
|
},
|
|
331
370
|
]);
|
|
332
371
|
}
|
|
333
|
-
const
|
|
372
|
+
const result = (await this.client.mutation(mutationRef('cms:unpublishDocument'), {
|
|
334
373
|
collection: ref.collection,
|
|
335
374
|
docId: ref.id,
|
|
336
375
|
updatedAt: this.clock(),
|
|
376
|
+
// EC-649: re-checked in the mutation's transaction (data-only, EC-565 1e).
|
|
377
|
+
...(precondition?.publishedReferrers
|
|
378
|
+
? { publishedReferrers: wireReferrers(precondition.publishedReferrers) }
|
|
379
|
+
: {}),
|
|
337
380
|
}));
|
|
338
|
-
|
|
381
|
+
if ('status' in result && result.status === 'unjudged-referrers') {
|
|
382
|
+
throw new StrictReferencePreconditionError('unjudged-referrers', `${projectId}/${documentKey(ref)}`, result.refs);
|
|
383
|
+
}
|
|
384
|
+
return docRecordFromDoc(result, projectId);
|
|
339
385
|
}
|
|
340
386
|
}
|
|
341
387
|
/**
|