@elytracms/studio 0.0.91 → 0.0.93
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 +127 -0
- package/convex/asset-replace.test.ts +168 -0
- package/convex/asset-revalidate.test.ts +6 -6
- package/convex/assets.ts +41 -5
- package/convex/cms.ts +537 -177
- package/convex/contract-parity.test.ts +173 -19
- package/convex/delivery.ts +26 -13
- package/convex/document-revalidate.test.ts +17 -16
- package/convex/orphan-hydration.test.ts +116 -0
- package/convex/presence-cost.test.ts +89 -0
- package/convex/rail-write-parity.test.ts +17 -14
- package/convex/referenceMaintenance.ts +15 -15
- package/convex/schema.ts +70 -5
- package/convex/triggers.ts +21 -8
- package/convex/write-limits.ts +1 -1
- package/dist/components/ai/ai-chat-panel.js +33 -22
- package/dist/components/ai/ai-chat-panel.js.map +1 -1
- package/dist/components/ai/proposal-card.js +2 -1
- package/dist/components/ai/proposal-card.js.map +1 -1
- package/dist/components/ai/translate-document-action.d.ts +8 -2
- 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 +14 -8
- package/dist/components/ai/translate-document-dialog.js.map +1 -1
- package/dist/components/ai/translate-skipped.d.ts +19 -0
- package/dist/components/ai/translate-skipped.js +46 -0
- package/dist/components/ai/translate-skipped.js.map +1 -0
- package/dist/components/app-views/default-modules.d.ts +23 -6
- package/dist/components/app-views/default-modules.js +33 -14
- package/dist/components/app-views/default-modules.js.map +1 -1
- package/dist/components/assets/asset-detail.js +18 -8
- package/dist/components/assets/asset-detail.js.map +1 -1
- package/dist/components/assets/asset-metadata.d.ts +15 -4
- package/dist/components/assets/asset-metadata.js +15 -2
- package/dist/components/assets/asset-metadata.js.map +1 -1
- package/dist/components/assets/asset-search.js +4 -1
- package/dist/components/assets/asset-search.js.map +1 -1
- package/dist/components/assets/asset-selection.d.ts +0 -8
- package/dist/components/assets/asset-selection.js +4 -23
- package/dist/components/assets/asset-selection.js.map +1 -1
- package/dist/components/assets/asset-thumb.js +3 -2
- package/dist/components/assets/asset-thumb.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.d.ts +3 -3
- package/dist/components/assets/assets-collection-view-source.js +9 -5
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/assets/assets-store.d.ts +14 -0
- package/dist/components/assets/assets-store.js +23 -1
- package/dist/components/assets/assets-store.js.map +1 -1
- package/dist/components/assets/replace-file.d.ts +22 -0
- package/dist/components/assets/replace-file.js +59 -0
- package/dist/components/assets/replace-file.js.map +1 -0
- package/dist/components/builder/blocks-model.d.ts +14 -26
- package/dist/components/builder/blocks-model.js +35 -41
- package/dist/components/builder/blocks-model.js.map +1 -1
- package/dist/components/builder/blocks-panel.d.ts +7 -3
- package/dist/components/builder/blocks-panel.js +6 -5
- package/dist/components/builder/blocks-panel.js.map +1 -1
- package/dist/components/builder/builder-store.d.ts +126 -30
- package/dist/components/builder/builder-store.js +169 -67
- package/dist/components/builder/builder-store.js.map +1 -1
- package/dist/components/builder/canvas-body.d.ts +30 -0
- package/dist/components/builder/canvas-body.js +38 -0
- package/dist/components/builder/canvas-body.js.map +1 -0
- package/dist/components/builder/canvas-chrome-css.js +7 -0
- package/dist/components/builder/canvas-chrome-css.js.map +1 -1
- package/dist/components/builder/canvas-dnd.d.ts +7 -7
- package/dist/components/builder/canvas-dnd.js +5 -5
- package/dist/components/builder/canvas-dnd.js.map +1 -1
- package/dist/components/builder/canvas-render-context.d.ts +30 -22
- package/dist/components/builder/canvas-render-context.js +44 -44
- package/dist/components/builder/canvas-render-context.js.map +1 -1
- package/dist/components/builder/canvas-runs.d.ts +45 -0
- package/dist/components/builder/canvas-runs.js +51 -0
- package/dist/components/builder/canvas-runs.js.map +1 -0
- package/dist/components/builder/canvas.d.ts +5 -4
- package/dist/components/builder/canvas.js +34 -6
- package/dist/components/builder/canvas.js.map +1 -1
- package/dist/components/builder/clipboard-actions.d.ts +15 -0
- package/dist/components/builder/clipboard-actions.js +50 -13
- package/dist/components/builder/clipboard-actions.js.map +1 -1
- package/dist/components/builder/composition-field-editor.d.ts +10 -16
- package/dist/components/builder/composition-field-editor.js +30 -40
- package/dist/components/builder/composition-field-editor.js.map +1 -1
- package/dist/components/builder/composition-patches.d.ts +7 -0
- package/dist/components/builder/composition-patches.js +256 -0
- package/dist/components/builder/composition-patches.js.map +1 -0
- package/dist/components/builder/delete-key.d.ts +5 -0
- package/dist/components/builder/delete-key.js +4 -0
- package/dist/components/builder/delete-key.js.map +1 -1
- package/dist/components/builder/insert-context.d.ts +17 -25
- package/dist/components/builder/insert-context.js +45 -92
- package/dist/components/builder/insert-context.js.map +1 -1
- package/dist/components/builder/page-tree.d.ts +3 -3
- package/dist/components/builder/page-tree.js +3 -3
- package/dist/components/builder/page-tree.js.map +1 -1
- package/dist/components/builder/placement-refusal.d.ts +18 -0
- package/dist/components/builder/placement-refusal.js +46 -0
- package/dist/components/builder/placement-refusal.js.map +1 -0
- package/dist/components/builder/property-inspector.js +4 -0
- package/dist/components/builder/property-inspector.js.map +1 -1
- package/dist/components/builder/reuse-context.js +65 -26
- package/dist/components/builder/reuse-context.js.map +1 -1
- package/dist/components/builder/reuse.d.ts +79 -8
- package/dist/components/builder/reuse.js +71 -23
- package/dist/components/builder/reuse.js.map +1 -1
- package/dist/components/builder/run-inspector.d.ts +11 -0
- package/dist/components/builder/run-inspector.js +33 -0
- package/dist/components/builder/run-inspector.js.map +1 -0
- package/dist/components/cms/asset-field.d.ts +38 -1
- package/dist/components/cms/asset-field.js +182 -58
- package/dist/components/cms/asset-field.js.map +1 -1
- package/dist/components/cms/asset-picker-core.d.ts +16 -0
- package/dist/components/cms/asset-picker-core.js +20 -0
- package/dist/components/cms/asset-picker-core.js.map +1 -1
- package/dist/components/cms/asset-picker.js +12 -18
- package/dist/components/cms/asset-picker.js.map +1 -1
- package/dist/components/cms/bulk-actions.d.ts +4 -20
- package/dist/components/cms/bulk-actions.js +3 -24
- package/dist/components/cms/bulk-actions.js.map +1 -1
- package/dist/components/cms/cell-edit.d.ts +5 -5
- package/dist/components/cms/cell-edit.js.map +1 -1
- package/dist/components/cms/cell.js.map +1 -1
- package/dist/components/cms/cms-store.d.ts +87 -45
- package/dist/components/cms/cms-store.js +347 -203
- package/dist/components/cms/cms-store.js.map +1 -1
- package/dist/components/cms/collection-table.js +7 -2
- package/dist/components/cms/collection-table.js.map +1 -1
- package/dist/components/cms/commit-policy.d.ts +24 -0
- package/dist/components/cms/commit-policy.js +37 -0
- package/dist/components/cms/commit-policy.js.map +1 -0
- package/dist/components/cms/detail-editor.js +83 -137
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/document-diff-view.d.ts +3 -1
- package/dist/components/cms/document-diff-view.js +12 -7
- package/dist/components/cms/document-diff-view.js.map +1 -1
- package/dist/components/cms/draft-commit.d.ts +70 -0
- package/dist/components/cms/draft-commit.js +82 -0
- package/dist/components/cms/draft-commit.js.map +1 -0
- package/dist/components/cms/duplicate-document.d.ts +11 -13
- package/dist/components/cms/duplicate-document.js +26 -34
- package/dist/components/cms/duplicate-document.js.map +1 -1
- package/dist/components/cms/field-anchors.d.ts +7 -4
- package/dist/components/cms/field-anchors.js +9 -7
- package/dist/components/cms/field-anchors.js.map +1 -1
- package/dist/components/cms/field-collaboration.d.ts +47 -0
- package/dist/components/cms/field-collaboration.js +87 -0
- package/dist/components/cms/field-collaboration.js.map +1 -0
- package/dist/components/cms/field-control-lib.d.ts +22 -1
- package/dist/components/cms/field-control-lib.js +33 -4
- package/dist/components/cms/field-control-lib.js.map +1 -1
- package/dist/components/cms/field-control.js +17 -14
- package/dist/components/cms/field-control.js.map +1 -1
- package/dist/components/cms/gate-validation.d.ts +21 -30
- package/dist/components/cms/gate-validation.js +11 -22
- package/dist/components/cms/gate-validation.js.map +1 -1
- package/dist/components/cms/object-array-field.js +4 -4
- package/dist/components/cms/object-array-field.js.map +1 -1
- package/dist/components/cms/prop-fields.d.ts +7 -2
- package/dist/components/cms/prop-fields.js +13 -6
- package/dist/components/cms/prop-fields.js.map +1 -1
- package/dist/components/cms/reference-confirm.js +10 -4
- package/dist/components/cms/reference-confirm.js.map +1 -1
- package/dist/components/cms/rich-text/embed-picker.d.ts +1 -1
- package/dist/components/cms/rich-text/embed-picker.js.map +1 -1
- package/dist/components/cms/rich-text/insert.d.ts +20 -9
- package/dist/components/cms/rich-text/insert.js +25 -17
- package/dist/components/cms/rich-text/insert.js.map +1 -1
- package/dist/components/cms/use-document-draft.d.ts +96 -0
- package/dist/components/cms/use-document-draft.js +283 -0
- package/dist/components/cms/use-document-draft.js.map +1 -0
- package/dist/components/cms/use-document-versions.js +2 -2
- package/dist/components/cms/use-document-versions.js.map +1 -1
- package/dist/components/cms/use-live-url.d.ts +6 -12
- package/dist/components/cms/use-live-url.js +16 -15
- package/dist/components/cms/use-live-url.js.map +1 -1
- package/dist/components/cms/use-publish-controller.d.ts +13 -18
- package/dist/components/cms/use-publish-controller.js +24 -41
- package/dist/components/cms/use-publish-controller.js.map +1 -1
- package/dist/components/cms/use-published-perspective.d.ts +2 -3
- package/dist/components/cms/use-published-perspective.js +4 -3
- package/dist/components/cms/use-published-perspective.js.map +1 -1
- package/dist/components/cms/versions-pane.js +8 -1
- package/dist/components/cms/versions-pane.js.map +1 -1
- package/dist/components/collection-view/cms-collection-view-source.js +24 -7
- package/dist/components/collection-view/cms-collection-view-source.js.map +1 -1
- package/dist/components/components/transfer-dialog.js +28 -23
- package/dist/components/components/transfer-dialog.js.map +1 -1
- package/dist/components/components/transfer.d.ts +31 -21
- package/dist/components/components/transfer.js +49 -35
- package/dist/components/components/transfer.js.map +1 -1
- package/dist/components/project-list.js.map +1 -1
- package/dist/components/project-session.d.ts +6 -3
- package/dist/components/project-session.js +14 -8
- package/dist/components/project-session.js.map +1 -1
- package/dist/components/project-switcher.js.map +1 -1
- package/dist/components/rail-view-source.js +2 -1
- package/dist/components/rail-view-source.js.map +1 -1
- package/dist/components/section-nav.js +1 -1
- package/dist/components/section-nav.js.map +1 -1
- package/dist/lib/ai/apply-content.js +56 -116
- package/dist/lib/ai/apply-content.js.map +1 -1
- package/dist/lib/ai/chat-context.d.ts +8 -0
- package/dist/lib/ai/chat-context.js +37 -6
- package/dist/lib/ai/chat-context.js.map +1 -1
- package/dist/lib/ai/chat-state.d.ts +14 -1
- package/dist/lib/ai/chat-state.js.map +1 -1
- package/dist/lib/ai/constraints.d.ts +20 -5
- package/dist/lib/ai/constraints.js +125 -33
- package/dist/lib/ai/constraints.js.map +1 -1
- package/dist/lib/ai/fake-provider.d.ts +16 -3
- package/dist/lib/ai/fake-provider.js +22 -6
- package/dist/lib/ai/fake-provider.js.map +1 -1
- package/dist/lib/ai/index.d.ts +2 -0
- package/dist/lib/ai/index.js +2 -0
- package/dist/lib/ai/index.js.map +1 -1
- package/dist/lib/ai/leash.d.ts +34 -0
- package/dist/lib/ai/leash.js +28 -0
- package/dist/lib/ai/leash.js.map +1 -0
- package/dist/lib/ai/provenance.d.ts +1 -1
- package/dist/lib/ai/provenance.js.map +1 -1
- package/dist/lib/ai/rich-text-input.d.ts +8 -8
- package/dist/lib/ai/rich-text-input.js +2 -1
- package/dist/lib/ai/rich-text-input.js.map +1 -1
- package/dist/lib/ai/rich-text-translate.d.ts +27 -4
- package/dist/lib/ai/rich-text-translate.js +28 -10
- package/dist/lib/ai/rich-text-translate.js.map +1 -1
- package/dist/lib/ai/shape.d.ts +13 -13
- package/dist/lib/ai/shape.js +69 -93
- package/dist/lib/ai/shape.js.map +1 -1
- package/dist/lib/ai/tools.d.ts +36 -41
- package/dist/lib/ai/tools.js +85 -87
- package/dist/lib/ai/tools.js.map +1 -1
- package/dist/lib/ai/translate-document.d.ts +39 -5
- package/dist/lib/ai/translate-document.js +160 -51
- package/dist/lib/ai/translate-document.js.map +1 -1
- package/dist/lib/ai/types.d.ts +34 -23
- package/dist/lib/ai/types.js.map +1 -1
- package/dist/lib/ai/update-fields.d.ts +21 -12
- package/dist/lib/ai/update-fields.js +118 -177
- package/dist/lib/ai/update-fields.js.map +1 -1
- package/dist/lib/ai/writer-form.d.ts +116 -0
- package/dist/lib/ai/writer-form.js +429 -0
- package/dist/lib/ai/writer-form.js.map +1 -0
- package/dist/lib/ai-current-document.d.ts +11 -11
- package/dist/lib/ai-current-document.js +4 -4
- package/dist/lib/ai-current-document.js.map +1 -1
- package/dist/lib/assets/upload.d.ts +31 -2
- package/dist/lib/assets/upload.js +61 -6
- package/dist/lib/assets/upload.js.map +1 -1
- package/dist/lib/clipboard/os-clipboard.d.ts +10 -2
- package/dist/lib/clipboard/os-clipboard.js +8 -4
- package/dist/lib/clipboard/os-clipboard.js.map +1 -1
- package/dist/lib/clipboard/paste-target.d.ts +18 -9
- package/dist/lib/clipboard/paste-target.js +8 -7
- package/dist/lib/clipboard/paste-target.js.map +1 -1
- package/dist/lib/cms/field-patch.d.ts +15 -0
- package/dist/lib/cms/field-patch.js +25 -0
- package/dist/lib/cms/field-patch.js.map +1 -0
- package/dist/lib/cms/published-documents.d.ts +1 -1
- package/dist/lib/cms/published-documents.js +1 -1
- package/dist/lib/cms/published-documents.js.map +1 -1
- package/dist/lib/cms-views/view-model.d.ts +3 -3
- package/dist/lib/collection-view/__fixtures__/document-writes.d.ts +6 -0
- package/dist/lib/collection-view/__fixtures__/document-writes.js +23 -0
- package/dist/lib/collection-view/__fixtures__/document-writes.js.map +1 -0
- package/dist/lib/collection-view/collection-view-source.d.ts +69 -6
- package/dist/lib/collection-view/collection-view-source.js.map +1 -1
- package/dist/lib/data/collection-content.d.ts +4 -13
- package/dist/lib/data/collection-content.js +11 -5
- package/dist/lib/data/collection-content.js.map +1 -1
- package/dist/lib/dnd/drop-rules.d.ts +25 -31
- package/dist/lib/dnd/drop-rules.js +53 -59
- package/dist/lib/dnd/drop-rules.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 +72 -15
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +61 -12
- package/dist/lib/i18n/messages.en.js +76 -16
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/operations/__fixtures__/write-document.d.ts +30 -0
- package/dist/lib/operations/__fixtures__/write-document.js +16 -0
- package/dist/lib/operations/__fixtures__/write-document.js.map +1 -0
- package/dist/lib/operations/cms-persistence.d.ts +124 -31
- package/dist/lib/operations/cms-persistence.js +447 -68
- package/dist/lib/operations/cms-persistence.js.map +1 -1
- package/dist/lib/operations/config-manifest-lookup.d.ts +35 -0
- package/dist/lib/operations/config-manifest-lookup.js +56 -0
- package/dist/lib/operations/config-manifest-lookup.js.map +1 -0
- package/dist/lib/operations/project-runtime-config.d.ts +39 -0
- package/dist/lib/operations/project-runtime-config.js +54 -0
- package/dist/lib/operations/project-runtime-config.js.map +1 -0
- package/dist/lib/operations/publish-with-revision.d.ts +64 -0
- package/dist/lib/operations/publish-with-revision.js +66 -0
- package/dist/lib/operations/publish-with-revision.js.map +1 -0
- package/dist/lib/operations/runtime-validator.d.ts +32 -0
- package/dist/lib/operations/runtime-validator.js +18 -0
- package/dist/lib/operations/runtime-validator.js.map +1 -0
- package/dist/lib/operations/session-hydration.d.ts +31 -14
- package/dist/lib/operations/session-hydration.js +12 -16
- package/dist/lib/operations/session-hydration.js.map +1 -1
- package/dist/lib/operations/studio-operations.d.ts +59 -2
- package/dist/lib/operations/studio-operations.js +76 -14
- package/dist/lib/operations/studio-operations.js.map +1 -1
- package/dist/lib/persistence/convex-adapter.d.ts +13 -5
- package/dist/lib/persistence/convex-adapter.js +189 -74
- package/dist/lib/persistence/convex-adapter.js.map +1 -1
- package/dist/lib/persistence/convex-client.d.ts +65 -5
- package/dist/lib/persistence/convex-client.js +106 -3
- package/dist/lib/persistence/convex-client.js.map +1 -1
- package/dist/lib/persistence/index.js +17 -18
- package/dist/lib/persistence/index.js.map +1 -1
- package/dist/lib/persona/labels.js +4 -1
- package/dist/lib/persona/labels.js.map +1 -1
- package/dist/lib/query/operations-query.d.ts +1 -1
- package/dist/lib/query/operations-query.js +1 -1
- package/dist/lib/query/operations-query.js.map +1 -1
- package/dist/lib/references/impact.d.ts +21 -15
- package/dist/lib/references/impact.js +13 -26
- package/dist/lib/references/impact.js.map +1 -1
- package/dist/lib/references/references-store.d.ts +9 -0
- package/dist/lib/references/references-store.js +24 -4
- package/dist/lib/references/references-store.js.map +1 -1
- package/dist/lib/routes/route-issues.d.ts +6 -6
- package/dist/lib/routes/route-issues.js +26 -80
- package/dist/lib/routes/route-issues.js.map +1 -1
- package/dist/lib/workspace/config-issues.js +2 -1
- package/dist/lib/workspace/config-issues.js.map +1 -1
- package/dist/lib/workspace/index.d.ts +31 -1
- package/dist/lib/workspace/index.js +64 -17
- package/dist/lib/workspace/index.js.map +1 -1
- package/dist/lib/workspace/switcher-source.d.ts +3 -3
- package/dist/lib/workspace/switcher-source.js.map +1 -1
- package/dist/lib/workspace/workspace-source.d.ts +2 -2
- package/dist/lib/workspace/workspace-source.js +2 -1
- package/dist/lib/workspace/workspace-source.js.map +1 -1
- package/package.json +3 -3
- package/dist/components/cms/cms-composition-validators.d.ts +0 -16
- package/dist/components/cms/cms-composition-validators.js +0 -133
- package/dist/components/cms/cms-composition-validators.js.map +0 -1
- package/dist/components/cms/publish-clean.d.ts +0 -28
- package/dist/components/cms/publish-clean.js +0 -38
- package/dist/components/cms/publish-clean.js.map +0 -1
- package/dist/components/cms/use-save-mode.d.ts +0 -35
- package/dist/components/cms/use-save-mode.js +0 -54
- package/dist/components/cms/use-save-mode.js.map +0 -1
- package/dist/lib/assets/asset-placements.d.ts +0 -28
- package/dist/lib/assets/asset-placements.js +0 -83
- package/dist/lib/assets/asset-placements.js.map +0 -1
- package/dist/lib/cms/document-gate.d.ts +0 -47
- package/dist/lib/cms/document-gate.js +0 -61
- package/dist/lib/cms/document-gate.js.map +0 -1
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { ConvexError } from 'convex/values';
|
|
2
|
-
import { documentKey, documentSchema } from '@elytracms/core/cms-core';
|
|
3
|
-
import { RecordNotFoundError, PersistenceValidationError, assetCreateDefaults, assetRecordFromRow, compareReferenceEntries, highestRole, isKnownRole, persistenceIssueSchema, presentWriteKeys, redirectEntryFromRow, validateForPersistence, } from '@elytracms/core/persistence';
|
|
2
|
+
import { DRAFT_VARIANT, documentKey, documentSchema } from '@elytracms/core/cms-core';
|
|
3
|
+
import { PRESENCE_TTL_MS, RecordNotFoundError, PersistenceValidationError, presenceInputSchema, assetCreateDefaults, assetRecordFromRow, compareReferenceEntries, highestRole, isKnownRole, persistenceIssueSchema, presentWriteKeys, redirectEntryFromRow, validateForPersistence, versionNotPinnableError, } from '@elytracms/core/persistence';
|
|
4
4
|
import { normalizeInviteEmail } from '@elytracms/core/persistence';
|
|
5
|
-
import {
|
|
5
|
+
import { createUuidIdFactory } from '@elytracms/core/determinism';
|
|
6
|
+
import { SUBSCRIPTION_UNAUTHENTICATED_MESSAGE, queryRef, mutationRef } from './convex-client.js';
|
|
6
7
|
import { ConvexBlobStorage } from './convex-blob-storage.js';
|
|
7
8
|
const realClock = () => new Date().toISOString();
|
|
8
|
-
function newId(prefix) {
|
|
9
|
-
const rand = typeof globalThis.crypto?.randomUUID === 'function'
|
|
10
|
-
? globalThis.crypto.randomUUID()
|
|
11
|
-
: Math.abs(Date.parse(new Date().toISOString())).toString(36);
|
|
12
|
-
return `${prefix}_${rand}`;
|
|
13
|
-
}
|
|
14
|
-
// --- CMS, Assets ----------------------------------------------------------
|
|
15
9
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
10
|
+
* EC-578: asset and redirect ids come from the ONE id factory documents and nodes use
|
|
11
|
+
* (`createUuidIdFactory`, `crypto.getRandomValues`). The old fallback minted a
|
|
12
|
+
* millisecond timestamp when `crypto.randomUUID` was missing (any non-secure context),
|
|
13
|
+
* so two writes in one millisecond collided; the factory refuses loudly instead.
|
|
19
14
|
*/
|
|
20
|
-
|
|
15
|
+
let mintUuid;
|
|
16
|
+
function newId(prefix) {
|
|
17
|
+
mintUuid ??= createUuidIdFactory();
|
|
18
|
+
return `${prefix}_${mintUuid()}`;
|
|
19
|
+
}
|
|
21
20
|
/**
|
|
22
21
|
* Row → contract record. `projectId` is the caller's (the row has none): before
|
|
23
22
|
* EC-577 this copied the row's nonexistent `projectId`, so every connected
|
|
@@ -27,6 +26,8 @@ function docRecordFromDoc(doc, projectId) {
|
|
|
27
26
|
return {
|
|
28
27
|
projectId,
|
|
29
28
|
document: doc.document,
|
|
29
|
+
variant: doc.variant ?? DRAFT_VARIANT,
|
|
30
|
+
revision: doc.revision,
|
|
30
31
|
...(doc.publishedVersion !== undefined ? { publishedVersion: doc.publishedVersion } : {}),
|
|
31
32
|
// EC-447: carry the materialized publish instant onto the contract record so the
|
|
32
33
|
// studio's $publishedAt column + its reconcile read the authoritative value.
|
|
@@ -51,66 +52,168 @@ function versionRecordFromDoc(doc, projectId) {
|
|
|
51
52
|
createdAt: doc.createdAt,
|
|
52
53
|
...(doc.label ? { label: doc.label } : {}),
|
|
53
54
|
...(doc.origin ? { origin: doc.origin } : {}),
|
|
55
|
+
...(doc.kind ? { kind: doc.kind } : {}),
|
|
54
56
|
};
|
|
55
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* The Convex CMS repository — the client half of the revisioned aggregate (EC-595). It
|
|
60
|
+
* maps the handlers' outcomes onto the provider-neutral contract (a conflict is DATA,
|
|
61
|
+
* never a throw) and keeps the EC-153 not-found taxonomy client-side. EC-583: documents
|
|
62
|
+
* only — no schema methods (the collections ride the operations context).
|
|
63
|
+
*/
|
|
56
64
|
class ConvexCmsRepository {
|
|
57
65
|
client;
|
|
58
|
-
|
|
66
|
+
reactive;
|
|
59
67
|
clock;
|
|
60
|
-
|
|
61
|
-
* @param collections the active project's config-owned CMS collections
|
|
62
|
-
* (EC-183, AD-11), injected from `elytra.config.ts`. The Convex backend has
|
|
63
|
-
* no `cmsSchemas` table — `findSchema`/`getSchema` serve these instead.
|
|
64
|
-
*/
|
|
65
|
-
constructor(client, collections = [], clock = realClock) {
|
|
68
|
+
constructor(client, reactive, clock = realClock) {
|
|
66
69
|
this.client = client;
|
|
67
|
-
this.
|
|
70
|
+
this.reactive = reactive;
|
|
68
71
|
this.clock = clock;
|
|
69
72
|
}
|
|
70
|
-
async
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
/** Config-owned schema (EC-183): the active project's collections from config. */
|
|
85
|
-
configSchema(projectId) {
|
|
73
|
+
async replaceDocument(projectId, document, precondition, _options) {
|
|
74
|
+
// A pure document store (EC-183, AD-11): shape-parse only. The actor the patch log
|
|
75
|
+
// records is the server's authenticated caller, never a client claim.
|
|
76
|
+
const parsedDoc = documentSchema.parse(document);
|
|
77
|
+
const result = (await this.client.mutation(mutationRef('cms:replaceDocument'), {
|
|
78
|
+
collection: parsedDoc.collection,
|
|
79
|
+
docId: parsedDoc.id,
|
|
80
|
+
document: parsedDoc,
|
|
81
|
+
precondition,
|
|
82
|
+
at: this.clock(),
|
|
83
|
+
}));
|
|
84
|
+
if (result.status === 'ok')
|
|
85
|
+
return { status: 'ok', record: docRecordFromDoc(result.row, projectId) };
|
|
86
86
|
return {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
updatedAt: CONFIG_SCHEMA_TIMESTAMP,
|
|
87
|
+
status: 'conflict',
|
|
88
|
+
current: result.current ? docRecordFromDoc(result.current, projectId) : undefined,
|
|
89
|
+
...(result.existing ? { existing: docRecordFromDoc(result.existing, projectId) } : {}),
|
|
91
90
|
};
|
|
92
91
|
}
|
|
93
|
-
async
|
|
94
|
-
|
|
92
|
+
async patchDocument(projectId, ref, patches, baseRevision, _options) {
|
|
93
|
+
const result = (await this.client.mutation(mutationRef('cms:patchDocument'), {
|
|
94
|
+
collection: ref.collection,
|
|
95
|
+
docId: ref.id,
|
|
96
|
+
patches: [...patches],
|
|
97
|
+
baseRevision,
|
|
98
|
+
at: this.clock(),
|
|
99
|
+
}));
|
|
100
|
+
if (result.status === 'missing') {
|
|
101
|
+
throw new RecordNotFoundError('cms-document', `${projectId}/${documentKey(ref)}`);
|
|
102
|
+
}
|
|
103
|
+
const record = docRecordFromDoc(result.row, projectId);
|
|
104
|
+
return result.status === 'ok'
|
|
105
|
+
? { status: 'ok', record }
|
|
106
|
+
: { status: 'conflict', record, refused: result.refused, appliedCount: result.appliedCount };
|
|
95
107
|
}
|
|
96
|
-
async
|
|
97
|
-
|
|
108
|
+
async publishDocument(projectId, ref, expectedRevision, options = {}) {
|
|
109
|
+
const result = (await this.client.mutation(mutationRef('cms:publishDocument'), {
|
|
110
|
+
collection: ref.collection,
|
|
111
|
+
docId: ref.id,
|
|
112
|
+
expectedRevision,
|
|
113
|
+
...(options.label ? { label: options.label } : {}),
|
|
114
|
+
...(options.origin ? { origin: options.origin } : {}),
|
|
115
|
+
at: this.clock(),
|
|
116
|
+
}));
|
|
117
|
+
if (result.status === 'missing') {
|
|
118
|
+
throw new RecordNotFoundError('cms-document', `${projectId}/${documentKey(ref)}`);
|
|
119
|
+
}
|
|
120
|
+
if (result.status === 'conflict') {
|
|
121
|
+
return { status: 'conflict', current: docRecordFromDoc(result.current, projectId) };
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
status: 'ok',
|
|
125
|
+
record: docRecordFromDoc(result.row, projectId),
|
|
126
|
+
version: versionRecordFromDoc(result.version, projectId),
|
|
127
|
+
};
|
|
98
128
|
}
|
|
99
|
-
async
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
collection:
|
|
108
|
-
docId:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
129
|
+
async listDocumentPatches(projectId, ref, afterRevision) {
|
|
130
|
+
const rows = (await this.client.query(queryRef('cms:listDocumentPatches'), {
|
|
131
|
+
collection: ref.collection,
|
|
132
|
+
docId: ref.id,
|
|
133
|
+
...(afterRevision !== undefined ? { afterRevision } : {}),
|
|
134
|
+
}));
|
|
135
|
+
return rows.map((row) => ({
|
|
136
|
+
projectId,
|
|
137
|
+
collection: row.collection,
|
|
138
|
+
docId: row.docId,
|
|
139
|
+
variant: row.variant,
|
|
140
|
+
revision: row.revision,
|
|
141
|
+
kind: row.kind,
|
|
142
|
+
...(row.actor !== undefined ? { actor: row.actor } : {}),
|
|
143
|
+
at: row.at,
|
|
144
|
+
patches: row.patches,
|
|
112
145
|
}));
|
|
113
|
-
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* EC-595 binding point 7 — the narrow document subscription over the REACTIVE client:
|
|
149
|
+
* TWO reactive queries behind this one subject — `cms:watchDocument` (the draft row)
|
|
150
|
+
* and `cms:watchPresence` (its heartbeats) — merged into one snapshot stream, the
|
|
151
|
+
* first snapshot once both have answered (EC-595 A2: one query re-pushed the whole row
|
|
152
|
+
* on every heartbeat — measured in `convex/presence-cost.test.ts`). A rejected session
|
|
153
|
+
* token surfaces as `onError(Unauthenticated …)` — EC-403's session-expired predicate
|
|
154
|
+
* matches it — never as a silently stopped stream. Without a reactive client the
|
|
155
|
+
* subscription fails loudly through `onError`.
|
|
156
|
+
*/
|
|
157
|
+
subscribeDocument(projectId, ref, listener) {
|
|
158
|
+
if (!this.reactive) {
|
|
159
|
+
listener.onError?.(new Error('subscribeDocument: this Convex adapter was built without a reactive client.'));
|
|
160
|
+
return () => { };
|
|
161
|
+
}
|
|
162
|
+
const reactive = this.reactive();
|
|
163
|
+
const args = { collection: ref.collection, docId: ref.id };
|
|
164
|
+
let row;
|
|
165
|
+
let presence;
|
|
166
|
+
// One failure (a dropped socket, an expired token) reaches BOTH queries: report it
|
|
167
|
+
// once, until a query answers again.
|
|
168
|
+
let reported;
|
|
169
|
+
const fail = (error) => {
|
|
170
|
+
if (reported === error.message)
|
|
171
|
+
return;
|
|
172
|
+
reported = error.message;
|
|
173
|
+
listener.onError?.(error);
|
|
174
|
+
};
|
|
175
|
+
const emit = () => {
|
|
176
|
+
reported = undefined;
|
|
177
|
+
if (row === undefined || presence === undefined)
|
|
178
|
+
return;
|
|
179
|
+
listener.onSnapshot({
|
|
180
|
+
record: row.value ? docRecordFromDoc(row.value, projectId) : undefined,
|
|
181
|
+
presence,
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
const unsubscribeRow = reactive.onUpdate(queryRef('cms:watchDocument'), args, (value) => {
|
|
185
|
+
row = { value: value.row };
|
|
186
|
+
emit();
|
|
187
|
+
}, fail);
|
|
188
|
+
const unsubscribePresence = reactive.onUpdate(queryRef('cms:watchPresence'), args, (value) => {
|
|
189
|
+
presence = value;
|
|
190
|
+
emit();
|
|
191
|
+
}, fail);
|
|
192
|
+
const unhookAuth = reactive.onAuthLost(() => fail(new Error(SUBSCRIPTION_UNAUTHENTICATED_MESSAGE)));
|
|
193
|
+
return () => {
|
|
194
|
+
unhookAuth();
|
|
195
|
+
unsubscribeRow();
|
|
196
|
+
unsubscribePresence();
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
async reportPresence(projectId, ref, presence) {
|
|
200
|
+
const parsed = presenceInputSchema.parse(presence);
|
|
201
|
+
await this.client.mutation(mutationRef('cms:reportPresence'), {
|
|
202
|
+
collection: ref.collection,
|
|
203
|
+
docId: ref.id,
|
|
204
|
+
sessionId: parsed.sessionId,
|
|
205
|
+
...(parsed.actorName !== undefined ? { actorName: parsed.actorName } : {}),
|
|
206
|
+
...(parsed.path !== undefined ? { path: parsed.path } : {}),
|
|
207
|
+
at: this.clock(),
|
|
208
|
+
ttlMs: PRESENCE_TTL_MS,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
async clearPresence(projectId, ref, sessionId) {
|
|
212
|
+
await this.client.mutation(mutationRef('cms:clearPresence'), {
|
|
213
|
+
collection: ref.collection,
|
|
214
|
+
docId: ref.id,
|
|
215
|
+
sessionId,
|
|
216
|
+
});
|
|
114
217
|
}
|
|
115
218
|
async getDocument(projectId, ref) {
|
|
116
219
|
const found = await this.findDocument(projectId, ref);
|
|
@@ -193,22 +296,28 @@ class ConvexCmsRepository {
|
|
|
193
296
|
return versionRecordFromDoc(doc, projectId);
|
|
194
297
|
}
|
|
195
298
|
async publishDocumentVersion(projectId, ref, version) {
|
|
196
|
-
//
|
|
197
|
-
// the
|
|
198
|
-
|
|
199
|
-
await this.getDocumentVersion(projectId, ref, version);
|
|
200
|
-
// EC-447: pass a fresh publish-action instant as the SET-ONCE candidate (the
|
|
201
|
-
// handler writes it only when the row has no `publishedAt` yet). One `now` for
|
|
202
|
-
// both stamps — this IS the publish moment.
|
|
299
|
+
// EC-595: pin integrity is enforced IN the transaction (the version must exist for
|
|
300
|
+
// this document); the outcomes map onto the EC-153 not-found taxonomy here. EC-447:
|
|
301
|
+
// one `now` for both stamps — the publish-action instant is the SET-ONCE candidate.
|
|
203
302
|
const now = this.clock();
|
|
204
|
-
const
|
|
303
|
+
const result = (await this.client.mutation(mutationRef('cms:publishDocumentVersion'), {
|
|
205
304
|
collection: ref.collection,
|
|
206
305
|
docId: ref.id,
|
|
207
306
|
version,
|
|
208
307
|
updatedAt: now,
|
|
209
308
|
publishedAt: now,
|
|
210
309
|
}));
|
|
211
|
-
|
|
310
|
+
if (result.status === 'missing') {
|
|
311
|
+
throw new RecordNotFoundError('cms-document', `${projectId}/${documentKey(ref)}`);
|
|
312
|
+
}
|
|
313
|
+
if (result.status === 'missing-version') {
|
|
314
|
+
throw new RecordNotFoundError('cms-document-version', `${projectId}/${documentKey(ref)}#${version}`);
|
|
315
|
+
}
|
|
316
|
+
// EC-585: the version was recorded by a snapshot, never by a publish — the same
|
|
317
|
+
// refusal the in-memory store raises.
|
|
318
|
+
if (result.status === 'not-pinnable')
|
|
319
|
+
throw versionNotPinnableError(`${projectId}/${documentKey(ref)}`, version);
|
|
320
|
+
return docRecordFromDoc(result.row, projectId);
|
|
212
321
|
}
|
|
213
322
|
async unpublishDocument(projectId, ref) {
|
|
214
323
|
const existing = await this.getDocument(projectId, ref);
|
|
@@ -715,13 +824,19 @@ export class ConvexPersistenceAdapter {
|
|
|
715
824
|
* @param client the Convex client bound to this deployment (one project).
|
|
716
825
|
* @param projectId the slug of this deployment's one project (EC-179). Used to
|
|
717
826
|
* stamp deployment-scoped member records onto the still-project-keyed contract.
|
|
718
|
-
*
|
|
719
|
-
*
|
|
720
|
-
* the
|
|
827
|
+
*
|
|
828
|
+
* @param options.reactive the reactive client a document subscription runs on (EC-595),
|
|
829
|
+
* built lazily — the studio passes `() => getReactiveConvexClient(url)`. Absent (a
|
|
830
|
+
* seed script, a test double without push), `subscribeDocument` fails loudly.
|
|
831
|
+
*
|
|
832
|
+
* EC-583: the third argument is no longer the collections. They only fed the
|
|
833
|
+
* synthesized schema record (`getSchema`/`findSchema`), which the contract no longer
|
|
834
|
+
* has — collections reach the operations layer on its context
|
|
835
|
+
* (`createOperations({ collections })`).
|
|
721
836
|
*/
|
|
722
|
-
constructor(client, projectId,
|
|
837
|
+
constructor(client, projectId, options = {}) {
|
|
723
838
|
this.client = client;
|
|
724
|
-
this.cms = new ConvexCmsRepository(client,
|
|
839
|
+
this.cms = new ConvexCmsRepository(client, options.reactive);
|
|
725
840
|
this.assets = new ConvexAssetRepository(client);
|
|
726
841
|
this.references = new ConvexReferenceIndexRepository(client);
|
|
727
842
|
this.members = new ConvexMembersRepository(client, projectId);
|