@elytracms/core 0.0.7 → 0.0.9
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/dist/clipboard/build.js.map +1 -1
- package/dist/clipboard/clipboard.js.map +1 -1
- package/dist/clipboard/fragment.js.map +1 -1
- package/dist/clipboard/html.js.map +1 -1
- package/dist/clipboard/index.js.map +1 -1
- package/dist/clipboard/references.js.map +1 -1
- package/dist/clipboard/serialize.js.map +1 -1
- package/dist/cms-core/collection-shape.d.ts +43 -0
- package/dist/cms-core/collection-shape.js +129 -0
- package/dist/cms-core/collection-shape.js.map +1 -0
- package/dist/cms-core/collections.d.ts +5 -6
- package/dist/cms-core/collections.js +26 -13
- package/dist/cms-core/collections.js.map +1 -1
- package/dist/cms-core/documents.d.ts +1 -0
- package/dist/cms-core/documents.js +10 -0
- package/dist/cms-core/documents.js.map +1 -1
- package/dist/cms-core/envelopes.js.map +1 -1
- package/dist/cms-core/fields.js.map +1 -1
- package/dist/cms-core/fixtures.js.map +1 -1
- package/dist/cms-core/hierarchy.js.map +1 -1
- package/dist/cms-core/index.d.ts +2 -0
- package/dist/cms-core/index.js +2 -0
- package/dist/cms-core/index.js.map +1 -1
- package/dist/cms-core/infer.js.map +1 -1
- package/dist/cms-core/issues.d.ts +10 -0
- package/dist/cms-core/issues.js +13 -0
- package/dist/cms-core/issues.js.map +1 -1
- package/dist/cms-core/json-schema.js.map +1 -1
- package/dist/cms-core/localization.js.map +1 -1
- package/dist/cms-core/nesting-depth.d.ts +44 -0
- package/dist/cms-core/nesting-depth.js +50 -0
- package/dist/cms-core/nesting-depth.js.map +1 -0
- package/dist/cms-core/routes.js.map +1 -1
- package/dist/cms-core/self-type.js.map +1 -1
- package/dist/cms-core/url-for-document.js.map +1 -1
- package/dist/cms-core/validate-document.d.ts +8 -0
- package/dist/cms-core/validate-document.js +35 -0
- package/dist/cms-core/validate-document.js.map +1 -1
- package/dist/cms-core/versions.d.ts +1 -0
- package/dist/cms-core/versions.js.map +1 -1
- package/dist/collaboration/approval.js.map +1 -1
- package/dist/collaboration/collaboration.js.map +1 -1
- package/dist/collaboration/comments.js.map +1 -1
- package/dist/collaboration/core.js.map +1 -1
- package/dist/collaboration/index.js.map +1 -1
- package/dist/collaboration/presence.js.map +1 -1
- package/dist/collaboration/publishing.js.map +1 -1
- package/dist/collaboration/versions.js.map +1 -1
- package/dist/component-registry/index.js.map +1 -1
- package/dist/component-registry/issues.js.map +1 -1
- package/dist/component-registry/manifest.js.map +1 -1
- package/dist/component-registry/registry.js.map +1 -1
- package/dist/content/__fixtures__/filterable-collections.js.map +1 -1
- package/dist/content/__fixtures__/sample-accessor-types.js.map +1 -1
- package/dist/content/__fixtures__/sample-delivery-types.js.map +1 -1
- package/dist/content/assets.js.map +1 -1
- package/dist/content/binding-sources.js.map +1 -1
- package/dist/content/client.js.map +1 -1
- package/dist/content/codegen.js.map +1 -1
- package/dist/content/context.js.map +1 -1
- package/dist/content/cursor.js.map +1 -1
- package/dist/content/index.js.map +1 -1
- package/dist/content/locale.js.map +1 -1
- package/dist/content/perspective.js.map +1 -1
- package/dist/content/populate.js.map +1 -1
- package/dist/content/query.js.map +1 -1
- package/dist/content/raw.js.map +1 -1
- package/dist/content/resolve.js.map +1 -1
- package/dist/content/serialize.js.map +1 -1
- package/dist/content/tags.js.map +1 -1
- package/dist/data-binding/fixtures.js.map +1 -1
- package/dist/data-binding/index.js.map +1 -1
- package/dist/data-binding/issues.js.map +1 -1
- package/dist/data-binding/resolve.js.map +1 -1
- package/dist/data-binding/sample.js.map +1 -1
- package/dist/data-binding/sources.js.map +1 -1
- package/dist/data-binding/tokens.js.map +1 -1
- package/dist/design-tokens/css.js.map +1 -1
- package/dist/design-tokens/index.js.map +1 -1
- package/dist/design-tokens/style-guide.js.map +1 -1
- package/dist/design-tokens/tokens.js.map +1 -1
- package/dist/export-sync/builder-source.d.ts +1 -0
- package/dist/export-sync/builder-source.js.map +1 -1
- package/dist/export-sync/check.js.map +1 -1
- package/dist/export-sync/cli.js.map +1 -1
- package/dist/export-sync/core.js.map +1 -1
- package/dist/export-sync/eject.js.map +1 -1
- package/dist/export-sync/fixtures.js.map +1 -1
- package/dist/export-sync/generate.js.map +1 -1
- package/dist/export-sync/index.js.map +1 -1
- package/dist/export-sync/init.js.map +1 -1
- package/dist/export-sync/manifest-host.js.map +1 -1
- package/dist/export-sync/node.js.map +1 -1
- package/dist/export-sync/push.js.map +1 -1
- package/dist/export-sync/registry-sync-client.js.map +1 -1
- package/dist/export-sync/sync.js.map +1 -1
- package/dist/export-sync/typegen.js.map +1 -1
- package/dist/export-sync/validate.js.map +1 -1
- package/dist/export-sync/watch.js.map +1 -1
- package/dist/operations/assets.js.map +1 -1
- package/dist/operations/authorization.js.map +1 -1
- package/dist/operations/changesets.js.map +1 -1
- package/dist/operations/client.js.map +1 -1
- package/dist/operations/core.js.map +1 -1
- package/dist/operations/documents.d.ts +21 -0
- package/dist/operations/documents.js.map +1 -1
- package/dist/operations/graph.js.map +1 -1
- package/dist/operations/index.js.map +1 -1
- package/dist/operations/members.js.map +1 -1
- package/dist/operations/publishing.js.map +1 -1
- package/dist/operations/references.js.map +1 -1
- package/dist/operations/schema.d.ts +18 -0
- package/dist/operations/schema.js.map +1 -1
- package/dist/operations/tokens.js.map +1 -1
- package/dist/persistence/adapter.js.map +1 -1
- package/dist/persistence/assets.js.map +1 -1
- package/dist/persistence/backend-validation.js.map +1 -1
- package/dist/persistence/cli-tokens.js.map +1 -1
- package/dist/persistence/cms.d.ts +3 -0
- package/dist/persistence/cms.js.map +1 -1
- package/dist/persistence/contract-scenarios.js.map +1 -1
- package/dist/persistence/core.js.map +1 -1
- package/dist/persistence/graph.js.map +1 -1
- package/dist/persistence/index.js.map +1 -1
- package/dist/persistence/members.js.map +1 -1
- package/dist/persistence/publishing.js.map +1 -1
- package/dist/persistence/reference-extraction.js.map +1 -1
- package/dist/persistence/reference-indexing.js.map +1 -1
- package/dist/persistence/references.js.map +1 -1
- package/dist/persistence/seed.js.map +1 -1
- package/dist/persistence/self-maintaining-adapter.js.map +1 -1
- package/dist/plugins/asset-storage.js.map +1 -1
- package/dist/plugins/component-package.js.map +1 -1
- package/dist/plugins/data-sources.js.map +1 -1
- package/dist/plugins/examples.js.map +1 -1
- package/dist/plugins/export-targets.js.map +1 -1
- package/dist/plugins/field-types.js.map +1 -1
- package/dist/plugins/hooks.js.map +1 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/marketplace.js.map +1 -1
- package/dist/plugins/plugin.js.map +1 -1
- package/dist/plugins/templates.js.map +1 -1
- package/dist/project-graph/binding.js.map +1 -1
- package/dist/project-graph/container.js.map +1 -1
- package/dist/project-graph/edit.js.map +1 -1
- package/dist/project-graph/fixtures.js.map +1 -1
- package/dist/project-graph/ids.js.map +1 -1
- package/dist/project-graph/index.js.map +1 -1
- package/dist/project-graph/issues.js.map +1 -1
- package/dist/project-graph/json.js.map +1 -1
- package/dist/project-graph/node.js.map +1 -1
- package/dist/project-graph/normalize.js.map +1 -1
- package/dist/project-graph/serialize.js.map +1 -1
- package/dist/project-graph/structure.js.map +1 -1
- package/dist/project-graph/validate.js.map +1 -1
- package/dist/rich-text/adapter.js.map +1 -1
- package/dist/rich-text/dom-editor.js.map +1 -1
- package/dist/rich-text/embed.js.map +1 -1
- package/dist/rich-text/fixtures.js.map +1 -1
- package/dist/rich-text/html.js.map +1 -1
- package/dist/rich-text/index.js.map +1 -1
- package/dist/rich-text/markdown.js.map +1 -1
- package/dist/rich-text/portable-text.js.map +1 -1
- package/dist/rich-text/registry.js.map +1 -1
- package/dist/rich-text/render.js.map +1 -1
- package/dist/rich-text/schema.js.map +1 -1
- package/dist/rich-text/test-support.js.map +1 -1
- package/dist/runtime-renderer/client.js.map +1 -1
- package/dist/runtime-renderer/condition.js.map +1 -1
- package/dist/runtime-renderer/content-client.js.map +1 -1
- package/dist/runtime-renderer/context.js.map +1 -1
- package/dist/runtime-renderer/fallback.js.map +1 -1
- package/dist/runtime-renderer/index.js.map +1 -1
- package/dist/runtime-renderer/primitives.js.map +1 -1
- package/dist/runtime-renderer/render.d.ts +14 -1
- package/dist/runtime-renderer/render.js +126 -126
- package/dist/runtime-renderer/render.js.map +1 -1
- package/dist/runtime-renderer/rich-text.js.map +1 -1
- package/dist/starter-kits/index.js.map +1 -1
- package/dist/starter-kits/instantiate.js.map +1 -1
- package/dist/starter-kits/kit.js.map +1 -1
- package/dist/starter-kits/kits.js.map +1 -1
- package/dist/starter-kits/manifests.js.map +1 -1
- package/dist/starter-kits/upgrade.js.map +1 -1
- package/dist/starter-kits/validate.js.map +1 -1
- package/dist/studio-core/context.js.map +1 -1
- package/dist/studio-core/errors.js.map +1 -1
- package/dist/studio-core/fixtures.js.map +1 -1
- package/dist/studio-core/ids.js.map +1 -1
- package/dist/studio-core/index.js.map +1 -1
- package/dist/studio-core/issues.js.map +1 -1
- package/dist/studio-core/metadata.js.map +1 -1
- package/dist/studio-core/repository.js.map +1 -1
- package/dist/studio-core/sections.d.ts +1 -1
- package/dist/studio-core/sections.js.map +1 -1
- package/dist/studio-core/validate.js.map +1 -1
- package/dist/studio-core/workspace-config.d.ts +4 -0
- package/dist/studio-core/workspace-config.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/clipboard/build.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/clipboard/build.ts"],"names":[],"mappings":"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","sourcesContent":["import { componentNodeSchema, getNode, staticProp } from '@elytracms/core/project-graph'\nimport type { ComponentNode, ProjectGraph } from '@elytracms/core/project-graph'\nimport type { ComponentFixture, ComponentManifest } from '@elytracms/core/component-registry'\nimport { CLIPBOARD_FRAGMENT_FORMAT, CLIPBOARD_FRAGMENT_VERSION } from './fragment'\nimport type { ClipboardFragment, FragmentSource } from './fragment'\nimport { collectAssetIds, collectBindingDeclarations, collectComponentIds } from './references'\n\n/**\n * Fragment construction. Two entry points feed the same builder so they produce\n * the same fragment shape by construction:\n *\n * - `buildFragmentFromGraph` — copy a live canvas subtree by node id, and\n * - `buildFragmentFromRegistryFixture` — materialize a manifest fixture\n * (the blocks panel's \"copy exact configuration\") as a node,\n *\n * both delegating to {@link buildFragmentFromSubtree}. Builders return typed\n * results for addressing failures (missing node / fixture) so a later paste\n * changeset (EC-175 over `@elytracms/core/operations` changesets) can map them onto\n * structured issues instead of catching exceptions.\n */\n\n/**\n * Manifest version used when no resolver is supplied. Registry manifests do not\n * carry a version yet; once they do, callers pass `resolveVersion` and this\n * default disappears from real fragments.\n */\nexport const DEFAULT_MANIFEST_VERSION = '0.0.0'\n\n/** Default root node id for fixture-materialized fragments (deterministic). */\nexport const FIXTURE_ROOT_NODE_ID = 'fragment-root'\n\nexport interface BuildFragmentOptions {\n /** Source project/locale metadata stamped onto the fragment. */\n source: FragmentSource\n /** Resolve a component id to its manifest version (defaults to {@link DEFAULT_MANIFEST_VERSION}). */\n resolveVersion?: (componentId: string) => string | undefined\n /** Extra asset ids the caller knows about (merged and de-duplicated with detected ones). */\n extraAssetIds?: readonly string[]\n}\n\nexport type BuildFragmentError =\n | { code: 'node-not-found'; nodeId: string; message: string }\n | { code: 'fixture-not-found'; componentId: string; fixtureName: string; message: string }\n\nexport type BuildFragmentResult =\n | { ok: true; fragment: ClipboardFragment }\n | { ok: false; error: BuildFragmentError }\n\n/**\n * Build a fragment from a subtree root. The node is detached (deep-copied via\n * schema parse) and every reference list is collected, sorted, and de-duplicated\n * — the single code path both the graph and fixture builders share.\n */\nexport function buildFragmentFromSubtree(\n root: ComponentNode,\n options: BuildFragmentOptions,\n): ClipboardFragment {\n const detached = componentNodeSchema.parse(root)\n const componentIds = collectComponentIds(detached)\n const assetIds = new Set<string>(collectAssetIds(detached))\n for (const id of options.extraAssetIds ?? []) assetIds.add(id)\n return {\n format: CLIPBOARD_FRAGMENT_FORMAT,\n version: CLIPBOARD_FRAGMENT_VERSION,\n payload: {\n root: detached,\n components: componentIds.map((id) => ({\n name: id,\n version: options.resolveVersion?.(id) ?? DEFAULT_MANIFEST_VERSION,\n })),\n bindings: collectBindingDeclarations(detached),\n assets: [...assetIds].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).map((id) => ({ id })),\n source: {\n projectId: options.source.projectId,\n ...(options.source.locale !== undefined ? { locale: options.source.locale } : {}),\n },\n },\n }\n}\n\n/**\n * Build a fragment from a graph subtree addressed by node id. Searches every\n * layout root (EC-187: the graph is layouts-only; page bodies are CMS document\n * compositions, searched via the composition editor, not here).\n */\nexport function buildFragmentFromGraph(\n graph: ProjectGraph,\n nodeId: string,\n options: BuildFragmentOptions,\n): BuildFragmentResult {\n for (const owner of graph.layouts) {\n const node = getNode(owner.root, nodeId)\n if (node) return { ok: true, fragment: buildFragmentFromSubtree(node, options) }\n }\n return {\n ok: false,\n error: {\n code: 'node-not-found',\n nodeId,\n message: `No node \"${nodeId}\" exists in any page or layout of graph \"${graph.id}\".`,\n },\n }\n}\n\n/**\n * Materialize a registry fixture as a component node: fixture props become\n * static prop values; `slotChildren` component ids become bare child nodes with\n * deterministic ids (`<rootId>.<slot>.<index>`).\n */\nexport function nodeFromFixture(\n componentId: string,\n fixture: ComponentFixture,\n nodeId: string = FIXTURE_ROOT_NODE_ID,\n): ComponentNode {\n const propEntries = Object.entries(fixture.props ?? {})\n const slotEntries = Object.entries(fixture.slotChildren ?? {})\n return {\n id: nodeId,\n componentId,\n ...(propEntries.length > 0\n ? { props: Object.fromEntries(propEntries.map(([name, value]) => [name, staticProp(value)])) }\n : {}),\n ...(slotEntries.length > 0\n ? {\n slots: Object.fromEntries(\n slotEntries.map(([slot, childIds]) => [\n slot,\n childIds.map((childComponentId, index) => ({\n id: `${nodeId}.${slot}.${index}`,\n componentId: childComponentId,\n })),\n ]),\n ),\n }\n : {}),\n }\n}\n\nexport interface FixtureFragmentOptions extends BuildFragmentOptions {\n /** Root node id for the materialized fixture (defaults to {@link FIXTURE_ROOT_NODE_ID}). */\n nodeId?: string\n}\n\n/**\n * Build a fragment from a component manifest's preview fixture (by name or as\n * an object). Produces exactly the same fragment shape as copying an equivalent\n * live canvas instance — both paths go through {@link buildFragmentFromSubtree}.\n */\nexport function buildFragmentFromRegistryFixture(\n manifest: ComponentManifest,\n fixture: string | ComponentFixture,\n options: FixtureFragmentOptions,\n): BuildFragmentResult {\n let resolved: ComponentFixture | undefined\n if (typeof fixture === 'string') {\n resolved = manifest.fixtures?.find((candidate) => candidate.name === fixture)\n if (!resolved) {\n return {\n ok: false,\n error: {\n code: 'fixture-not-found',\n componentId: manifest.id,\n fixtureName: fixture,\n message: `Component \"${manifest.id}\" declares no fixture named \"${fixture}\".`,\n },\n }\n }\n } else {\n resolved = fixture\n }\n const node = nodeFromFixture(manifest.id, resolved, options.nodeId)\n return { ok: true, fragment: buildFragmentFromSubtree(node, options) }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/clipboard/clipboard.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAA;AAC9D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAG9D;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,WAAW;CACT,CAAA;AAWV,uEAAuE;AACvE,MAAM,UAAU,0BAA0B,CAAC,QAA2B;IACpE,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACxC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAA;AAC7D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,IAAuC;IAEvC,MAAM,QAAQ,GAA0B,EAAE,CAAA;IAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACpE,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC5E,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACpE,OAAO,CACL,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,QAAQ,CAAC,CAAC,CAAC,IAAI;QACb,EAAE,EAAE,KAAK;QACT,KAAK,EAAE;YACL,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,gEAAgE;SAC1E;KACF,CACF,CAAA;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/clipboard/clipboard.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,QAAQ,CAAA;AAC9D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAG9D;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,WAAW;CACT,CAAA;AAWV,uEAAuE;AACvE,MAAM,UAAU,0BAA0B,CAAC,QAA2B;IACpE,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACxC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAA;AAC7D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,IAAuC;IAEvC,MAAM,QAAQ,GAA0B,EAAE,CAAA;IAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACpE,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC5E,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACpE,OAAO,CACL,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,QAAQ,CAAC,CAAC,CAAC,IAAI;QACb,EAAE,EAAE,KAAK;QACT,KAAK,EAAE;YACL,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,gEAAgE;SAC1E;KACF,CACF,CAAA;AACH,CAAC","sourcesContent":["import type { ClipboardFragment } from './fragment'\nimport { fragmentToHtml, parseFragmentFromHtml } from './html'\nimport { parseFragment, serializeFragment } from './serialize'\nimport type { ParseFragmentResult } from './serialize'\n\n/**\n * OS-clipboard representation helpers. A copy writes three representations of\n * the same fragment; a paste tries them in fidelity order. No DOM/Clipboard API\n * usage here — EC-175 wires these strings into `ClipboardItem`/`DataTransfer`.\n */\n\n/**\n * Clipboard types for each representation. The async Clipboard API requires the\n * `web ` prefix for custom formats; `DataTransfer` consumers can strip it.\n */\nexport const FRAGMENT_CLIPBOARD_TYPES = {\n json: 'web application/json',\n text: 'text/plain',\n html: 'text/html',\n} as const\n\nexport interface ClipboardRepresentations {\n /** Canonical fragment JSON (the `web application/json` entry). */\n json: string\n /** `text/plain` — the same canonical JSON, for plain-text-only targets. */\n text: string\n /** `text/html` — readable fallback with the JSON embedded losslessly. */\n html: string\n}\n\n/** Render every clipboard representation of a fragment in one pass. */\nexport function toClipboardRepresentations(fragment: ClipboardFragment): ClipboardRepresentations {\n const json = serializeFragment(fragment)\n return { json, text: json, html: fragmentToHtml(fragment) }\n}\n\n/**\n * Restore a fragment from whichever representations a clipboard offers, in\n * fidelity order: canonical JSON, then HTML (lossless embed), then plain text.\n * Returns the first successful parse, or the highest-fidelity structured error.\n * Never throws.\n */\nexport function parseFragmentFromClipboard(\n data: Partial<ClipboardRepresentations>,\n): ParseFragmentResult {\n const attempts: ParseFragmentResult[] = []\n if (data.json !== undefined) attempts.push(parseFragment(data.json))\n if (data.html !== undefined) attempts.push(parseFragmentFromHtml(data.html))\n if (data.text !== undefined) attempts.push(parseFragment(data.text))\n return (\n attempts.find((attempt) => attempt.ok) ??\n attempts[0] ?? {\n ok: false,\n error: {\n code: 'foreign-format',\n message: 'Clipboard offers no representation to restore a fragment from.',\n },\n }\n )\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fragment.js","sourceRoot":"","sources":["../../src/clipboard/fragment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAA;AAErG;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,mFAAmF;AACnF,MAAM,CAAC,MAAM,yBAAyB,GAAG,wBAAwB,CAAA;AAEjE,8FAA8F;AAC9F,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAA;AAE3C;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3B,CAAC,CAAA;AAGF,+EAA+E;AAC/E,MAAM,UAAU,eAAe,CAAC,GAAgB;IAC9C,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,EAAE,CAAA;AACrC,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAChC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IACvD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAA;AACjE,CAAC;AAED,uFAAuF;AACvF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACtB,CAAC,CAAA;AAGF,kGAAkG;AAClG,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,SAAS,EAAE,QAAQ;IACnB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAA;AAGF;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,sFAAsF;IACtF,IAAI,EAAE,mBAAmB;IACzB,gGAAgG;IAChG,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;IACtC,2EAA2E;IAC3E,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC;IACzC,0EAA0E;IAC1E,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;IAC/B,sCAAsC;IACtC,MAAM,EAAE,oBAAoB;CAC7B,CAAC,CAAA;AAGF,sFAAsF;AACtF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC;IAC5C,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,0BAA0B,CAAC;IAC9C,OAAO,EAAE,qBAAqB;CAC/B,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"fragment.js","sourceRoot":"","sources":["../../src/clipboard/fragment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAA;AAErG;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,mFAAmF;AACnF,MAAM,CAAC,MAAM,yBAAyB,GAAG,wBAAwB,CAAA;AAEjE,8FAA8F;AAC9F,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAA;AAE3C;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3B,CAAC,CAAA;AAGF,+EAA+E;AAC/E,MAAM,UAAU,eAAe,CAAC,GAAgB;IAC9C,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,EAAE,CAAA;AACrC,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAChC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IACvD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAA;AACjE,CAAC;AAED,uFAAuF;AACvF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACtB,CAAC,CAAA;AAGF,kGAAkG;AAClG,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,SAAS,EAAE,QAAQ;IACnB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAA;AAGF;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,sFAAsF;IACtF,IAAI,EAAE,mBAAmB;IACzB,gGAAgG;IAChG,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;IACtC,2EAA2E;IAC3E,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC;IACzC,0EAA0E;IAC1E,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;IAC/B,sCAAsC;IACtC,MAAM,EAAE,oBAAoB;CAC7B,CAAC,CAAA;AAGF,sFAAsF;AACtF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC;IAC5C,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,0BAA0B,CAAC;IAC9C,OAAO,EAAE,qBAAqB;CAC/B,CAAC,CAAA","sourcesContent":["import { z } from 'zod'\nimport { bindingReferenceSchema, componentNodeSchema, idSchema } from '@elytracms/core/project-graph'\n\n/**\n * The clipboard fragment (EC-174, vision 3.7): a spec'd, versioned interchange\n * envelope that makes copy/paste a real format instead of an app-internal\n * buffer. One Zod-validated envelope carries everything a paste target needs to\n * reconstruct a subtree:\n *\n * - the graph subtree itself (`payload.root`),\n * - component manifest references (`name` + `version`, renderable as\n * `name@version`) for every component the subtree uses,\n * - the binding declarations the subtree's props/conditions point at,\n * - asset references, and\n * - source metadata (project id, optional locale).\n *\n * The envelope is deliberately permissive about *semantics*: a fragment whose\n * components are unknown to the receiving registry, or whose bindings cannot be\n * resolved, still parses — flagging mismatches is the consumer's job (EC-175\n * diffing the enumerated references against its registry). Only structural\n * problems (foreign format, unsupported version, schema violations) are parse\n * errors, and those are structured results, never exceptions (see\n * `serialize.ts`).\n */\n\n/** Format identifier — foreign clipboard payloads are detected, not guessed at. */\nexport const CLIPBOARD_FRAGMENT_FORMAT = 'elytra-canvas/fragment'\n\n/** Spec version this package reads and writes. Newer payloads parse to a structured error. */\nexport const CLIPBOARD_FRAGMENT_VERSION = 1\n\n/**\n * A component manifest reference: registry component id (`name`) plus the\n * manifest version it was copied against. Rendered as `name@version`.\n */\nexport const manifestRefSchema = z.object({\n name: z.string().min(1),\n version: z.string().min(1),\n})\nexport type ManifestRef = z.infer<typeof manifestRefSchema>\n\n/** Render a manifest reference as its canonical `name@version` spec string. */\nexport function manifestRefSpec(ref: ManifestRef): string {\n return `${ref.name}@${ref.version}`\n}\n\n/** Parse a `name@version` spec string back into a manifest reference (or `undefined`). */\nexport function parseManifestRefSpec(spec: string): ManifestRef | undefined {\n const at = spec.lastIndexOf('@')\n if (at <= 0 || at === spec.length - 1) return undefined\n return { name: spec.slice(0, at), version: spec.slice(at + 1) }\n}\n\n/** A reference to a project asset used by the subtree (e.g. images bound to props). */\nexport const assetRefSchema = z.object({\n id: z.string().min(1),\n})\nexport type AssetRef = z.infer<typeof assetRefSchema>\n\n/** Where the fragment was copied from — lets paste targets detect cross-project/locale pastes. */\nexport const fragmentSourceSchema = z.object({\n projectId: idSchema,\n locale: z.string().min(1).optional(),\n})\nexport type FragmentSource = z.infer<typeof fragmentSourceSchema>\n\n/**\n * The fragment payload: the subtree plus everything needed to reconcile it at\n * the paste target. Reference lists are sorted and de-duplicated at build time\n * so equal subtrees produce byte-identical fragments.\n */\nexport const fragmentPayloadSchema = z.object({\n /** The copied graph subtree (same node schema as `@elytracms/core/project-graph`). */\n root: componentNodeSchema,\n /** Manifest references for every component id used anywhere in the subtree (sorted by name). */\n components: z.array(manifestRefSchema),\n /** Unique binding declarations referenced by props/conditions (sorted). */\n bindings: z.array(bindingReferenceSchema),\n /** Unique asset references found in static prop values (sorted by id). */\n assets: z.array(assetRefSchema),\n /** Source project/locale metadata. */\n source: fragmentSourceSchema,\n})\nexport type FragmentPayload = z.infer<typeof fragmentPayloadSchema>\n\n/** The versioned fragment envelope — the single shape written to the OS clipboard. */\nexport const clipboardFragmentSchema = z.object({\n format: z.literal(CLIPBOARD_FRAGMENT_FORMAT),\n version: z.literal(CLIPBOARD_FRAGMENT_VERSION),\n payload: fragmentPayloadSchema,\n})\nexport type ClipboardFragment = z.infer<typeof clipboardFragmentSchema>\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/clipboard/html.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/clipboard/html.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentNode } from '@elytracms/core/project-graph'\nimport type { ClipboardFragment } from './fragment'\nimport { parseFragment, serializeFragment } from './serialize'\nimport type { ParseFragmentResult } from './serialize'\n\n/**\n * HTML fallback representation. Many clipboard targets only accept `text/html`;\n * this rendering serves both audiences at once:\n *\n * - **humans** — pasting outside the studio shows a readable summary (component\n * names, static text content, source project), and\n * - **the studio** — the canonical fragment JSON is embedded losslessly in a\n * data attribute on the wrapper, so an HTML-only clipboard still restores the\n * exact fragment ({@link parseFragmentFromHtml} round-trips byte-identically).\n */\n\n/** The wrapper attribute carrying the canonical fragment JSON (HTML-escaped). */\nexport const FRAGMENT_HTML_DATA_ATTRIBUTE = 'data-elytra-clipboard-fragment'\n\nfunction escapeHtmlText(value: string): string {\n return value.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>')\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return escapeHtmlText(value).replaceAll('\"', '"')\n}\n\nfunction unescapeHtmlAttribute(value: string): string {\n return value\n .replaceAll('"', '\"')\n .replaceAll('>', '>')\n .replaceAll('<', '<')\n .replaceAll('&', '&')\n}\n\n/** A short human-readable summary of one node: component id plus static string props. */\nfunction nodeSummary(node: ComponentNode): string {\n const texts: string[] = []\n for (const [name, value] of Object.entries(node.props ?? {})) {\n if (value.kind === 'static' && typeof value.value === 'string') {\n texts.push(`${name}: ${JSON.stringify(value.value)}`)\n }\n }\n return texts.length > 0 ? `${node.componentId} — ${texts.join(', ')}` : node.componentId\n}\n\nfunction renderNodeList(nodes: readonly ComponentNode[]): string {\n const items = nodes.map((node) => {\n const childLists = Object.entries(node.slots ?? {})\n .filter(([, children]) => children.length > 0)\n .map(([, children]) => renderNodeList(children))\n .join('')\n return `<li>${escapeHtmlText(nodeSummary(node))}${childLists}</li>`\n })\n return `<ul>${items.join('')}</ul>`\n}\n\n/**\n * Render a fragment as its HTML clipboard representation: a readable summary\n * wrapped in an element whose data attribute embeds the canonical JSON.\n */\nexport function fragmentToHtml(fragment: ClipboardFragment): string {\n const json = serializeFragment(fragment)\n const { source, components } = fragment.payload\n const origin = source.locale ? `${source.projectId} (${source.locale})` : source.projectId\n const header =\n `Elytra fragment — ${components.length} component` +\n `${components.length === 1 ? '' : 's'} from project ${origin}`\n return (\n `<div ${FRAGMENT_HTML_DATA_ATTRIBUTE}=\"${escapeHtmlAttribute(json)}\">` +\n `<p>${escapeHtmlText(header)}</p>` +\n renderNodeList([fragment.payload.root]) +\n `</div>`\n )\n}\n\nconst FRAGMENT_ATTRIBUTE_PATTERN = new RegExp(`${FRAGMENT_HTML_DATA_ATTRIBUTE}=\"([^\"]*)\"`)\n\n/**\n * Restore a fragment from HTML clipboard content by extracting the embedded\n * canonical JSON. Never throws; HTML without an embedded fragment is a\n * structured `foreign-format` error, and the embedded JSON goes through the\n * same {@link parseFragment} taxonomy as the canonical representation.\n */\nexport function parseFragmentFromHtml(html: string): ParseFragmentResult {\n const match = FRAGMENT_ATTRIBUTE_PATTERN.exec(html)\n if (!match) {\n return {\n ok: false,\n error: {\n code: 'foreign-format',\n message: 'HTML clipboard content carries no embedded Elytra fragment.',\n },\n }\n }\n return parseFragment(unescapeHtmlAttribute(match[1]!))\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/clipboard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,2BAA2B,CAAA;AAElD,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/clipboard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,2BAA2B,CAAA;AAElD,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,aAAa,CAAA","sourcesContent":["/**\n * @elytracms/clipboard — the spec'd, versioned clipboard fragment (EC-174,\n * vision 3.7). Copy/paste as a real interchange format: a Zod-validated\n * envelope carrying a graph subtree, manifest references, binding declarations,\n * asset references, and source metadata, serialized to the OS clipboard as\n * canonical JSON with a human-readable (and losslessly round-tripping) HTML\n * fallback. Package-level only — EC-175 wires it into the studio.\n */\nexport const PACKAGE = '@elytracms/core/clipboard'\n\nexport * from './fragment'\nexport * from './references'\nexport * from './serialize'\nexport * from './build'\nexport * from './html'\nexport * from './clipboard'\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"references.js","sourceRoot":"","sources":["../../src/clipboard/references.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"references.js","sourceRoot":"","sources":["../../src/clipboard/references.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,eAAe,CAAA;AAErD,SAAS,SAAS,CAAC,IAAmB,EAAE,KAAoC;IAC1E,KAAK,CAAC,IAAI,CAAC,CAAA;IACX,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QACvD,KAAK,MAAM,KAAK,IAAI,QAAQ;YAAE,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IACvD,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAAwB;IAC3C,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACjE,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,mBAAmB,CAAC,IAAmB;IACrD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;IAC7B,SAAS,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAA;IACpD,OAAO,WAAW,CAAC,GAAG,CAAC,CAAA;AACzB,CAAC;AAED,SAAS,UAAU,CAAC,OAAyB;IAC3C,OAAO,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAA;AAC/D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAAmB;IAC5D,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAA;IACjD,MAAM,GAAG,GAAG,CAAC,OAAyB,EAAQ,EAAE;QAC9C,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE;YAC7B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC,CAAA;IACJ,CAAC,CAAA;IACD,SAAS,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;QACvB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;YACpD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;gBAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAClD,CAAC;QACD,IAAI,IAAI,CAAC,SAAS;YAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IACF,OAAO,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;SACxB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChD,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAA;AAClC,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAgB,EAAE,GAAgB;IAChE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,KAAK,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;YAC7C,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAA;YACrD,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;gBAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAChC,CAAC;QACD,OAAM;IACR,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,sBAAsB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAC3D,OAAM;IACR,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,MAAM,OAAO,GAAI,KAA+B,CAAC,OAAO,CAAA;QACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QACvE,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;YAAE,sBAAsB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAChF,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAmB;IACjD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;IAC7B,SAAS,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;QACvB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;YACpD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,sBAAsB,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACvE,CAAC;IACH,CAAC,CAAC,CAAA;IACF,OAAO,WAAW,CAAC,GAAG,CAAC,CAAA;AACzB,CAAC;AAoBD,4FAA4F;AAC5F,MAAM,UAAU,yBAAyB,CAAC,QAA2B;IACnE,OAAO;QACL,YAAY,EAAE,mBAAmB,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;QACxD,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;QACjE,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;QACtE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;KAC/D,CAAA;AACH,CAAC","sourcesContent":["import type { BindingReference, ComponentNode, JsonValue } from '@elytracms/core/project-graph'\nimport type { AssetRef, ClipboardFragment, ManifestRef } from './fragment'\n\n/**\n * Reference collection: deterministic, structural walks over a fragment subtree\n * that enumerate everything it points at — component ids, binding declarations,\n * asset ids. Builders use these to populate the payload's reference lists;\n * `parseFragment` recomputes them so consumers can diff a pasted fragment\n * against their registry/sources without re-walking the tree themselves.\n *\n * All collectors are pure, never throw, and return sorted, de-duplicated lists\n * so equal subtrees yield byte-identical fragments.\n */\n\n/**\n * Convention for asset references inside static prop values (shared with\n * rich-text link marks and persistence reference extraction, EC-155):\n * `elytra:asset/<id>` strings, or objects carrying an `assetId` string.\n */\nexport const ASSET_REFERENCE_PREFIX = 'elytra:asset/'\n\nfunction walkNodes(node: ComponentNode, visit: (node: ComponentNode) => void): void {\n visit(node)\n for (const children of Object.values(node.slots ?? {})) {\n for (const child of children) walkNodes(child, visit)\n }\n}\n\nfunction sortStrings(values: Iterable<string>): string[] {\n return [...values].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n}\n\n/** Every component id used anywhere in the subtree (sorted, unique). */\nexport function collectComponentIds(root: ComponentNode): string[] {\n const ids = new Set<string>()\n walkNodes(root, (node) => ids.add(node.componentId))\n return sortStrings(ids)\n}\n\nfunction bindingKey(binding: BindingReference): string {\n return `${binding.sourceId}\u0000${binding.token}\u0000${binding.mode}`\n}\n\n/**\n * Every binding declaration referenced by the subtree's bound props and render\n * conditions (sorted by source id, token, mode; unique).\n */\nexport function collectBindingDeclarations(root: ComponentNode): BindingReference[] {\n const byKey = new Map<string, BindingReference>()\n const add = (binding: BindingReference): void => {\n byKey.set(bindingKey(binding), {\n sourceId: binding.sourceId,\n token: binding.token,\n mode: binding.mode,\n })\n }\n walkNodes(root, (node) => {\n for (const value of Object.values(node.props ?? {})) {\n if (value.kind === 'binding') add(value.binding)\n }\n if (node.condition) add(node.condition.source)\n })\n return [...byKey.entries()]\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([, binding]) => binding)\n}\n\nfunction collectAssetsFromValue(value: JsonValue, out: Set<string>): void {\n if (typeof value === 'string') {\n if (value.startsWith(ASSET_REFERENCE_PREFIX)) {\n const id = value.slice(ASSET_REFERENCE_PREFIX.length)\n if (id.length > 0) out.add(id)\n }\n return\n }\n if (Array.isArray(value)) {\n for (const item of value) collectAssetsFromValue(item, out)\n return\n }\n if (typeof value === 'object' && value !== null) {\n const assetId = (value as { assetId?: unknown }).assetId\n if (typeof assetId === 'string' && assetId.length > 0) out.add(assetId)\n for (const nested of Object.values(value)) collectAssetsFromValue(nested, out)\n }\n}\n\n/**\n * Every asset id referenced by static prop values in the subtree (sorted,\n * unique). Detects the `elytra:asset/<id>` string convention and embedded\n * `assetId` attributes (e.g. rich-text image nodes).\n */\nexport function collectAssetIds(root: ComponentNode): string[] {\n const ids = new Set<string>()\n walkNodes(root, (node) => {\n for (const value of Object.values(node.props ?? {})) {\n if (value.kind === 'static') collectAssetsFromValue(value.value, ids)\n }\n })\n return sortStrings(ids)\n}\n\n/**\n * Everything a fragment references, enumerated for the consumer: the component\n * ids actually used by the subtree, the declared manifest refs, and the binding\n * and asset declarations. Paste targets diff these against their registry and\n * data sources — a mismatch is the consumer's structured issue, never a parse\n * failure here.\n */\nexport interface FragmentReferences {\n /** Component ids used anywhere in the subtree (sorted, unique). */\n componentIds: string[]\n /** Manifest references declared in the payload (`name@version`). */\n manifests: ManifestRef[]\n /** Binding declarations referenced by props/conditions. */\n bindings: BindingReference[]\n /** Asset references declared in the payload. */\n assets: AssetRef[]\n}\n\n/** Enumerate a fragment's references (recomputed from the subtree, plus declared lists). */\nexport function collectFragmentReferences(fragment: ClipboardFragment): FragmentReferences {\n return {\n componentIds: collectComponentIds(fragment.payload.root),\n manifests: fragment.payload.components.map((ref) => ({ ...ref })),\n bindings: fragment.payload.bindings.map((binding) => ({ ...binding })),\n assets: fragment.payload.assets.map((asset) => ({ ...asset })),\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serialize.js","sourceRoot":"","sources":["../../src/clipboard/serialize.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"serialize.js","sourceRoot":"","sources":["../../src/clipboard/serialize.ts"],"names":[],"mappings":"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","sourcesContent":["import { CLIPBOARD_FRAGMENT_FORMAT, CLIPBOARD_FRAGMENT_VERSION, clipboardFragmentSchema } from './fragment'\nimport type { ClipboardFragment } from './fragment'\nimport { collectFragmentReferences } from './references'\nimport type { FragmentReferences } from './references'\n\n/**\n * Fragment serialization, following `@elytracms/core/project-graph`'s conventions:\n * parse-before-serialize (the output contains no runtime-only values) and a\n * never-throw parse. On top of that, serialization is *canonical* — object keys\n * are sorted recursively — so build → serialize → parse → serialize is\n * byte-identical regardless of property insertion order. Canonical bytes are\n * what goes onto the OS clipboard (and into the HTML fallback's data\n * attribute), so two copies of the same subtree are comparable as strings.\n */\n\n/**\n * Deterministic JSON: arrays in order, object keys sorted recursively,\n * `undefined` object values dropped (matching `JSON.stringify`).\n */\nexport function canonicalJsonStringify(value: unknown): string {\n return canonicalize(value) ?? 'null'\n}\n\nfunction canonicalize(value: unknown): string | undefined {\n if (value === null) return 'null'\n switch (typeof value) {\n case 'string':\n case 'number':\n case 'boolean':\n return JSON.stringify(value)\n case 'object': {\n if (Array.isArray(value)) {\n // JSON.stringify renders un-serializable array items as null — match it.\n return `[${value.map((item) => canonicalize(item) ?? 'null').join(',')}]`\n }\n const entries = Object.entries(value as Record<string, unknown>)\n .map(([key, item]) => [key, canonicalize(item)] as const)\n .filter((entry): entry is readonly [string, string] => entry[1] !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([key, item]) => `${JSON.stringify(key)}:${item}`)\n return `{${entries.join(',')}}`\n }\n default:\n // undefined / function / symbol — not representable, dropped by the caller.\n return undefined\n }\n}\n\n/**\n * Serialize a fragment to canonical JSON. Parsing first guarantees the output\n * is exactly the spec'd envelope (programmer error in the input throws — this\n * is the trusted, in-process direction; `parseFragment` owns untrusted input).\n */\nexport function serializeFragment(fragment: ClipboardFragment): string {\n const parsed = clipboardFragmentSchema.parse(fragment)\n return canonicalJsonStringify(parsed)\n}\n\n/** One schema violation, flattened to a path string for display/logging. */\nexport interface FragmentIssue {\n path: string\n message: string\n}\n\n/**\n * The closed taxonomy of parse failures. Every way untrusted clipboard content\n * can be wrong maps to exactly one structured code — never an exception:\n *\n * - `corrupt-json` the string is not JSON at all\n * - `foreign-format` valid JSON, but not an Elytra fragment envelope\n * - `unsupported-version` our format, but a spec version this package does not read\n * - `invalid-payload` our format + version, but the payload violates the schema\n */\nexport type FragmentParseError =\n | { code: 'corrupt-json'; message: string }\n | { code: 'foreign-format'; message: string; format?: string }\n | { code: 'unsupported-version'; message: string; version: number }\n | { code: 'invalid-payload'; message: string; issues: FragmentIssue[] }\n\nexport type ParseFragmentResult =\n | { ok: true; fragment: ClipboardFragment; references: FragmentReferences }\n | { ok: false; error: FragmentParseError }\n\n/**\n * Parse a fragment from a JSON string or an already-parsed value. Never throws.\n *\n * Permissive by design: components unknown to the receiving registry and\n * bindings the target cannot resolve still parse — the result's `references`\n * enumerate every component/binding/asset the fragment points at so the\n * consumer can diff them against its registry and raise its own issues.\n */\nexport function parseFragment(input: string | unknown): ParseFragmentResult {\n let json: unknown\n if (typeof input === 'string') {\n try {\n json = JSON.parse(input)\n } catch (cause) {\n const detail = cause instanceof Error ? cause.message : String(cause)\n return {\n ok: false,\n error: { code: 'corrupt-json', message: `Clipboard content is not valid JSON: ${detail}` },\n }\n }\n } else {\n json = input\n }\n\n if (typeof json !== 'object' || json === null || Array.isArray(json)) {\n return {\n ok: false,\n error: {\n code: 'foreign-format',\n message: 'Clipboard content is not an Elytra fragment envelope.',\n },\n }\n }\n\n const probe = json as { format?: unknown; version?: unknown }\n if (probe.format !== CLIPBOARD_FRAGMENT_FORMAT) {\n return {\n ok: false,\n error: {\n code: 'foreign-format',\n message: `Clipboard content is not an Elytra fragment (expected format \"${CLIPBOARD_FRAGMENT_FORMAT}\").`,\n ...(typeof probe.format === 'string' ? { format: probe.format } : {}),\n },\n }\n }\n if (typeof probe.version === 'number' && probe.version !== CLIPBOARD_FRAGMENT_VERSION) {\n return {\n ok: false,\n error: {\n code: 'unsupported-version',\n message:\n probe.version > CLIPBOARD_FRAGMENT_VERSION\n ? `Fragment version ${probe.version} is newer than this studio supports (version ${CLIPBOARD_FRAGMENT_VERSION}).`\n : `Fragment version ${probe.version} is not supported (this studio reads version ${CLIPBOARD_FRAGMENT_VERSION}).`,\n version: probe.version,\n },\n }\n }\n\n const result = clipboardFragmentSchema.safeParse(json)\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: 'invalid-payload',\n message: 'Clipboard fragment violates the fragment schema.',\n issues: result.error.issues.map((issue) => ({\n path: issue.path.map(String).join('/'),\n message: issue.message,\n })),\n },\n }\n }\n return {\n ok: true,\n fragment: result.data,\n references: collectFragmentReferences(result.data),\n }\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { CollectionDef } from './collections';
|
|
2
|
+
import type { CmsDocument } from './documents';
|
|
3
|
+
import type { CmsValidationIssue } from './issues';
|
|
4
|
+
/**
|
|
5
|
+
* The resolution of a singleton collection against its documents (EC-274):
|
|
6
|
+
* - `ready` — exactly one document; skip the list and open it.
|
|
7
|
+
* - `empty` — no document yet; the studio implicitly creates one (generated id).
|
|
8
|
+
* - `drift` — more than one document; show the list + "for review" lane.
|
|
9
|
+
*
|
|
10
|
+
* `singletonDocId` is intentionally gone: the lone document keeps a normal id and
|
|
11
|
+
* is found at runtime, so no route, link, or config ever names a document id.
|
|
12
|
+
*/
|
|
13
|
+
export type SingletonResolution = {
|
|
14
|
+
readonly kind: 'ready';
|
|
15
|
+
readonly doc: CmsDocument;
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: 'empty';
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: 'drift';
|
|
20
|
+
readonly docs: readonly CmsDocument[];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Resolve a singleton collection against its documents. Not meaningful on a
|
|
24
|
+
* non-singleton collection — callers guard with {@link isSingleton}; we still
|
|
25
|
+
* answer defensively (one doc → `ready`, else by count) so routing never crashes.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveSingletonDocument(collection: CollectionDef, docs: readonly CmsDocument[]): SingletonResolution;
|
|
28
|
+
/** True when a singleton collection is in its expected shape (≤ 1 document). */
|
|
29
|
+
export declare function isSingletonInShape(collection: CollectionDef, docs: readonly CmsDocument[]): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Resolve a document by its alias slot (EC-284): `resolveByAlias(navigation,
|
|
32
|
+
* docs, 'footer')`. Code addresses documents this way — never by a literal id.
|
|
33
|
+
* Returns the (first) document assigned that alias, or `undefined`. Duplicate
|
|
34
|
+
* assignments are a drift issue ({@link validateCollectionShape}); resolution
|
|
35
|
+
* stays deterministic (first match in document order) so delivery never crashes.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveByAlias(collection: CollectionDef, docs: readonly CmsDocument[], alias: string): CmsDocument | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Cross-document shape validation for a collection (EC-274; aliases in EC-284).
|
|
40
|
+
* Emits the drift issues the studio surfaces in the "for review" lane. Pure and
|
|
41
|
+
* deterministic; returns `[]` for a collection in its expected shape.
|
|
42
|
+
*/
|
|
43
|
+
export declare function validateCollectionShape(collection: CollectionDef, docs: readonly CmsDocument[]): CmsValidationIssue[];
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { declaredAliases, hasAliases, isSingleton } from './collections';
|
|
2
|
+
import { cmsIssue } from './issues';
|
|
3
|
+
/**
|
|
4
|
+
* Collection *shape* resolution & drift detection (EC-274; extended for aliases
|
|
5
|
+
* in EC-284).
|
|
6
|
+
*
|
|
7
|
+
* A "lens" collection (a singleton, and later an alias-slotted collection) has an
|
|
8
|
+
* **expected shape**. While the collection matches it, the studio applies the
|
|
9
|
+
* lens — a singleton skips the list and opens its one document. When the data
|
|
10
|
+
* has **drifted** from the expected shape (more documents than the lens allows),
|
|
11
|
+
* the studio must NOT silently mis-apply the lens: it shows the list with the
|
|
12
|
+
* outliers in a "for review" lane so an editor resolves the conflict without a
|
|
13
|
+
* developer (EC-277 — embrace drift, surface it, never destroy data).
|
|
14
|
+
*
|
|
15
|
+
* Pure functions over `(collection, documents)` — no store, deterministic from
|
|
16
|
+
* fixtures. The studio owns the documents and drives routing / the review lane
|
|
17
|
+
* from these results.
|
|
18
|
+
*/
|
|
19
|
+
/** Documents in a collection (callers may pass the whole dataset; we filter). */
|
|
20
|
+
function documentsOf(collection, docs) {
|
|
21
|
+
return docs.filter((d) => d.collection === collection.id);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Resolve a singleton collection against its documents. Not meaningful on a
|
|
25
|
+
* non-singleton collection — callers guard with {@link isSingleton}; we still
|
|
26
|
+
* answer defensively (one doc → `ready`, else by count) so routing never crashes.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveSingletonDocument(collection, docs) {
|
|
29
|
+
const inCollection = documentsOf(collection, docs);
|
|
30
|
+
if (inCollection.length === 0)
|
|
31
|
+
return { kind: 'empty' };
|
|
32
|
+
if (inCollection.length === 1)
|
|
33
|
+
return { kind: 'ready', doc: inCollection[0] };
|
|
34
|
+
return { kind: 'drift', docs: inCollection };
|
|
35
|
+
}
|
|
36
|
+
/** True when a singleton collection is in its expected shape (≤ 1 document). */
|
|
37
|
+
export function isSingletonInShape(collection, docs) {
|
|
38
|
+
return resolveSingletonDocument(collection, docs).kind !== 'drift';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolve a document by its alias slot (EC-284): `resolveByAlias(navigation,
|
|
42
|
+
* docs, 'footer')`. Code addresses documents this way — never by a literal id.
|
|
43
|
+
* Returns the (first) document assigned that alias, or `undefined`. Duplicate
|
|
44
|
+
* assignments are a drift issue ({@link validateCollectionShape}); resolution
|
|
45
|
+
* stays deterministic (first match in document order) so delivery never crashes.
|
|
46
|
+
*/
|
|
47
|
+
export function resolveByAlias(collection, docs, alias) {
|
|
48
|
+
return documentsOf(collection, docs).find((d) => d.alias === alias);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Cross-document shape validation for a collection (EC-274; aliases in EC-284).
|
|
52
|
+
* Emits the drift issues the studio surfaces in the "for review" lane. Pure and
|
|
53
|
+
* deterministic; returns `[]` for a collection in its expected shape.
|
|
54
|
+
*/
|
|
55
|
+
export function validateCollectionShape(collection, docs) {
|
|
56
|
+
const issues = [];
|
|
57
|
+
if (isSingleton(collection)) {
|
|
58
|
+
const resolution = resolveSingletonDocument(collection, docs);
|
|
59
|
+
if (resolution.kind === 'drift') {
|
|
60
|
+
const ids = resolution.docs.map((d) => d.id);
|
|
61
|
+
issues.push(cmsIssue({
|
|
62
|
+
code: 'singleton-document-drift',
|
|
63
|
+
severity: 'warning',
|
|
64
|
+
message: `Singleton "${collection.id}" has ${ids.length} documents — it should have one. Keep the correct document and remove the others to open it directly.`,
|
|
65
|
+
path: ['collections', collection.id],
|
|
66
|
+
collectionId: collection.id,
|
|
67
|
+
meta: { documentIds: ids },
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (hasAliases(collection)) {
|
|
72
|
+
const declared = declaredAliases(collection);
|
|
73
|
+
const declaredSet = new Set(declared);
|
|
74
|
+
const inCollection = documentsOf(collection, docs);
|
|
75
|
+
const bySlot = new Map();
|
|
76
|
+
for (const doc of inCollection) {
|
|
77
|
+
if (doc.alias === undefined)
|
|
78
|
+
continue;
|
|
79
|
+
const list = bySlot.get(doc.alias);
|
|
80
|
+
if (list)
|
|
81
|
+
list.push(doc);
|
|
82
|
+
else
|
|
83
|
+
bySlot.set(doc.alias, [doc]);
|
|
84
|
+
}
|
|
85
|
+
// A document assigned an alias that isn't a declared slot (e.g. config dropped
|
|
86
|
+
// the slot) — an error: code that resolves the old slot now finds nothing.
|
|
87
|
+
for (const [alias, assigned] of bySlot) {
|
|
88
|
+
if (!declaredSet.has(alias)) {
|
|
89
|
+
issues.push(cmsIssue({
|
|
90
|
+
code: 'unknown-alias',
|
|
91
|
+
severity: 'error',
|
|
92
|
+
message: `${assigned.length === 1 ? 'A document is' : `${assigned.length} documents are`} assigned the alias "${alias}", which is not a declared slot of "${collection.id}" (${declared.join(', ') || 'none'}). Reassign to a valid slot.`,
|
|
93
|
+
path: ['collections', collection.id],
|
|
94
|
+
collectionId: collection.id,
|
|
95
|
+
meta: { alias, documentIds: assigned.map((d) => d.id) },
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Two+ documents claiming the same declared slot — an error: resolution is
|
|
100
|
+
// ambiguous (delivery falls back to the first, deterministically).
|
|
101
|
+
for (const slot of declared) {
|
|
102
|
+
const assigned = bySlot.get(slot) ?? [];
|
|
103
|
+
if (assigned.length > 1) {
|
|
104
|
+
issues.push(cmsIssue({
|
|
105
|
+
code: 'duplicate-alias',
|
|
106
|
+
severity: 'error',
|
|
107
|
+
message: `${assigned.length} documents share the alias "${slot}" in "${collection.id}". Each slot must be assigned to one document — reassign or clear the duplicates.`,
|
|
108
|
+
path: ['collections', collection.id],
|
|
109
|
+
collectionId: collection.id,
|
|
110
|
+
meta: { alias: slot, documentIds: assigned.map((d) => d.id) },
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
else if (assigned.length === 0) {
|
|
114
|
+
// A declared slot with no document — a warning: resolveByAlias returns
|
|
115
|
+
// nothing for it until a document is assigned.
|
|
116
|
+
issues.push(cmsIssue({
|
|
117
|
+
code: 'unfilled-slot',
|
|
118
|
+
severity: 'warning',
|
|
119
|
+
message: `The "${slot}" slot of "${collection.id}" has no document yet. Assign one so code that resolves "${slot}" finds it.`,
|
|
120
|
+
path: ['collections', collection.id],
|
|
121
|
+
collectionId: collection.id,
|
|
122
|
+
meta: { alias: slot },
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return issues;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=collection-shape.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-shape.js","sourceRoot":"","sources":["../../src/cms-core/collection-shape.ts"],"names":[],"mappings":"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","sourcesContent":["import { declaredAliases, hasAliases, isSingleton } from './collections'\nimport type { CollectionDef } from './collections'\nimport type { CmsDocument } from './documents'\nimport { cmsIssue } from './issues'\nimport type { CmsValidationIssue } from './issues'\n\n/**\n * Collection *shape* resolution & drift detection (EC-274; extended for aliases\n * in EC-284).\n *\n * A \"lens\" collection (a singleton, and later an alias-slotted collection) has an\n * **expected shape**. While the collection matches it, the studio applies the\n * lens — a singleton skips the list and opens its one document. When the data\n * has **drifted** from the expected shape (more documents than the lens allows),\n * the studio must NOT silently mis-apply the lens: it shows the list with the\n * outliers in a \"for review\" lane so an editor resolves the conflict without a\n * developer (EC-277 — embrace drift, surface it, never destroy data).\n *\n * Pure functions over `(collection, documents)` — no store, deterministic from\n * fixtures. The studio owns the documents and drives routing / the review lane\n * from these results.\n */\n\n/** Documents in a collection (callers may pass the whole dataset; we filter). */\nfunction documentsOf(\n collection: CollectionDef,\n docs: readonly CmsDocument[],\n): readonly CmsDocument[] {\n return docs.filter((d) => d.collection === collection.id)\n}\n\n/**\n * The resolution of a singleton collection against its documents (EC-274):\n * - `ready` — exactly one document; skip the list and open it.\n * - `empty` — no document yet; the studio implicitly creates one (generated id).\n * - `drift` — more than one document; show the list + \"for review\" lane.\n *\n * `singletonDocId` is intentionally gone: the lone document keeps a normal id and\n * is found at runtime, so no route, link, or config ever names a document id.\n */\nexport type SingletonResolution =\n | { readonly kind: 'ready'; readonly doc: CmsDocument }\n | { readonly kind: 'empty' }\n | { readonly kind: 'drift'; readonly docs: readonly CmsDocument[] }\n\n/**\n * Resolve a singleton collection against its documents. Not meaningful on a\n * non-singleton collection — callers guard with {@link isSingleton}; we still\n * answer defensively (one doc → `ready`, else by count) so routing never crashes.\n */\nexport function resolveSingletonDocument(\n collection: CollectionDef,\n docs: readonly CmsDocument[],\n): SingletonResolution {\n const inCollection = documentsOf(collection, docs)\n if (inCollection.length === 0) return { kind: 'empty' }\n if (inCollection.length === 1) return { kind: 'ready', doc: inCollection[0]! }\n return { kind: 'drift', docs: inCollection }\n}\n\n/** True when a singleton collection is in its expected shape (≤ 1 document). */\nexport function isSingletonInShape(\n collection: CollectionDef,\n docs: readonly CmsDocument[],\n): boolean {\n return resolveSingletonDocument(collection, docs).kind !== 'drift'\n}\n\n/**\n * Resolve a document by its alias slot (EC-284): `resolveByAlias(navigation,\n * docs, 'footer')`. Code addresses documents this way — never by a literal id.\n * Returns the (first) document assigned that alias, or `undefined`. Duplicate\n * assignments are a drift issue ({@link validateCollectionShape}); resolution\n * stays deterministic (first match in document order) so delivery never crashes.\n */\nexport function resolveByAlias(\n collection: CollectionDef,\n docs: readonly CmsDocument[],\n alias: string,\n): CmsDocument | undefined {\n return documentsOf(collection, docs).find((d) => d.alias === alias)\n}\n\n/**\n * Cross-document shape validation for a collection (EC-274; aliases in EC-284).\n * Emits the drift issues the studio surfaces in the \"for review\" lane. Pure and\n * deterministic; returns `[]` for a collection in its expected shape.\n */\nexport function validateCollectionShape(\n collection: CollectionDef,\n docs: readonly CmsDocument[],\n): CmsValidationIssue[] {\n const issues: CmsValidationIssue[] = []\n\n if (isSingleton(collection)) {\n const resolution = resolveSingletonDocument(collection, docs)\n if (resolution.kind === 'drift') {\n const ids = resolution.docs.map((d) => d.id)\n issues.push(\n cmsIssue({\n code: 'singleton-document-drift',\n severity: 'warning',\n message: `Singleton \"${collection.id}\" has ${ids.length} documents — it should have one. Keep the correct document and remove the others to open it directly.`,\n path: ['collections', collection.id],\n collectionId: collection.id,\n meta: { documentIds: ids },\n }),\n )\n }\n }\n\n if (hasAliases(collection)) {\n const declared = declaredAliases(collection)\n const declaredSet = new Set(declared)\n const inCollection = documentsOf(collection, docs)\n const bySlot = new Map<string, CmsDocument[]>()\n for (const doc of inCollection) {\n if (doc.alias === undefined) continue\n const list = bySlot.get(doc.alias)\n if (list) list.push(doc)\n else bySlot.set(doc.alias, [doc])\n }\n\n // A document assigned an alias that isn't a declared slot (e.g. config dropped\n // the slot) — an error: code that resolves the old slot now finds nothing.\n for (const [alias, assigned] of bySlot) {\n if (!declaredSet.has(alias)) {\n issues.push(\n cmsIssue({\n code: 'unknown-alias',\n severity: 'error',\n message: `${assigned.length === 1 ? 'A document is' : `${assigned.length} documents are`} assigned the alias \"${alias}\", which is not a declared slot of \"${collection.id}\" (${declared.join(', ') || 'none'}). Reassign to a valid slot.`,\n path: ['collections', collection.id],\n collectionId: collection.id,\n meta: { alias, documentIds: assigned.map((d) => d.id) },\n }),\n )\n }\n }\n\n // Two+ documents claiming the same declared slot — an error: resolution is\n // ambiguous (delivery falls back to the first, deterministically).\n for (const slot of declared) {\n const assigned = bySlot.get(slot) ?? []\n if (assigned.length > 1) {\n issues.push(\n cmsIssue({\n code: 'duplicate-alias',\n severity: 'error',\n message: `${assigned.length} documents share the alias \"${slot}\" in \"${collection.id}\". Each slot must be assigned to one document — reassign or clear the duplicates.`,\n path: ['collections', collection.id],\n collectionId: collection.id,\n meta: { alias: slot, documentIds: assigned.map((d) => d.id) },\n }),\n )\n } else if (assigned.length === 0) {\n // A declared slot with no document — a warning: resolveByAlias returns\n // nothing for it until a document is assigned.\n issues.push(\n cmsIssue({\n code: 'unfilled-slot',\n severity: 'warning',\n message: `The \"${slot}\" slot of \"${collection.id}\" has no document yet. Assign one so code that resolves \"${slot}\" finds it.`,\n path: ['collections', collection.id],\n collectionId: collection.id,\n meta: { alias: slot },\n }),\n )\n }\n }\n }\n\n return issues\n}\n"]}
|
|
@@ -43,6 +43,7 @@ export declare const collectionDefSchema: z.ZodObject<{
|
|
|
43
43
|
localized: z.ZodOptional<z.ZodBoolean>;
|
|
44
44
|
titleField: z.ZodOptional<z.ZodString>;
|
|
45
45
|
singleton: z.ZodOptional<z.ZodBoolean>;
|
|
46
|
+
aliases: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
46
47
|
}, z.core.$strip>;
|
|
47
48
|
export type CollectionDef = z.infer<typeof collectionDefSchema>;
|
|
48
49
|
/** Look up a field by name within a collection. */
|
|
@@ -57,12 +58,10 @@ export declare function titleFieldOf(collection: CollectionDef): FieldDef | unde
|
|
|
57
58
|
* misconfiguration as an `invalid-collection-config` issue.
|
|
58
59
|
*/
|
|
59
60
|
export declare function isSingleton(collection: CollectionDef): boolean;
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*/
|
|
65
|
-
export declare function singletonDocId(collection: CollectionDef): string;
|
|
61
|
+
/** The declared alias slots for a collection (EC-284), or `[]` when none. */
|
|
62
|
+
export declare function declaredAliases(collection: CollectionDef): readonly string[];
|
|
63
|
+
/** Does this collection address its documents by alias slots (EC-284)? */
|
|
64
|
+
export declare function hasAliases(collection: CollectionDef): boolean;
|
|
66
65
|
/**
|
|
67
66
|
* A metadata registry of collections, keyed by id (brief §7.4 "metadata
|
|
68
67
|
* registries"). Construction validates structural invariants (duplicate
|
|
@@ -36,14 +36,27 @@ export const collectionDefSchema = z.object({
|
|
|
36
36
|
/** Name of the field used as the document's display title (defaults to `title`). */
|
|
37
37
|
titleField: z.string().optional(),
|
|
38
38
|
/**
|
|
39
|
-
* When true, this collection
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
39
|
+
* When true, this collection is presented as a SINGLE document — Settings,
|
|
40
|
+
* Footer, Homepage SEO… (EC-217, re-scoped EC-274). A pure **UI lens**: the
|
|
41
|
+
* one document keeps a normal generated id (NOT the collection id — no code
|
|
42
|
+
* ever names a literal document id), and the studio skips the list to open it
|
|
43
|
+
* directly *only while the collection is in its expected shape* (exactly one
|
|
44
|
+
* document). On drift (>1 document) the list is shown with the outliers in a
|
|
45
|
+
* "for review" lane ({@link resolveSingletonDocument}). Reversible with no
|
|
46
|
+
* migration: flipping back to a normal collection just restores the list.
|
|
47
|
+
* Storage, engine, delivery, and validation paths are unchanged. Meaningless
|
|
48
|
+
* on an `asset` collection (flagged as `invalid-collection-config`).
|
|
45
49
|
*/
|
|
46
50
|
singleton: z.boolean().optional(),
|
|
51
|
+
/**
|
|
52
|
+
* Declared alias **slots** (EC-284): the fixed set of named handles documents in
|
|
53
|
+
* this collection can be assigned (`['main', 'mobile', 'footer', 'legal']`), so
|
|
54
|
+
* code resolves a specific document by `(collection, alias)` instead of an
|
|
55
|
+
* opaque id. Each document's `alias` must be one of these and unique within the
|
|
56
|
+
* collection; a declared-but-unfilled slot, a duplicate, or an out-of-set alias
|
|
57
|
+
* is surfaced as drift (the "for review" lane), never a silent failure.
|
|
58
|
+
*/
|
|
59
|
+
aliases: z.array(z.string().min(1)).optional(),
|
|
47
60
|
});
|
|
48
61
|
/** Look up a field by name within a collection. */
|
|
49
62
|
export function fieldOf(collection, name) {
|
|
@@ -64,13 +77,13 @@ export function titleFieldOf(collection) {
|
|
|
64
77
|
export function isSingleton(collection) {
|
|
65
78
|
return collection.singleton === true && collection.kind !== 'asset';
|
|
66
79
|
}
|
|
67
|
-
/**
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
*/
|
|
72
|
-
export function
|
|
73
|
-
return collection.
|
|
80
|
+
/** The declared alias slots for a collection (EC-284), or `[]` when none. */
|
|
81
|
+
export function declaredAliases(collection) {
|
|
82
|
+
return collection.aliases ?? [];
|
|
83
|
+
}
|
|
84
|
+
/** Does this collection address its documents by alias slots (EC-284)? */
|
|
85
|
+
export function hasAliases(collection) {
|
|
86
|
+
return declaredAliases(collection).length > 0;
|
|
74
87
|
}
|
|
75
88
|
/**
|
|
76
89
|
* Recursively validate a single field's shape (EC-253): select-option uniqueness,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/cms-core/collections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGnC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAA;AAGjE,+EAA+E;AAC/E,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,6CAA6C;IAC7C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,8CAA8C;IAC9C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,oDAAoD;IACpD,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACtC,sCAAsC;IACtC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAA;AAGF;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,IAAI,EAAE,oBAAoB,CAAC,OAAO,CAAC,UAAU,CAAC;IAC9C,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC3C,IAAI,EAAE,wBAAwB,CAAC,QAAQ,EAAE;IACzC,mFAAmF;IACnF,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACjC,oFAAoF;IACpF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC;;;;;;;OAOG;IACH,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAA;AAGF,mDAAmD;AACnD,MAAM,UAAU,OAAO,CAAC,UAAyB,EAAE,IAAY;IAC7D,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;AACvD,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,YAAY,CAAC,UAAyB;IACpD,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,IAAI,OAAO,CAAA;IAC7C,OAAO,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;AAClC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,UAAyB;IACnD,OAAO,UAAU,CAAC,SAAS,KAAK,IAAI,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO,CAAA;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,UAAyB;IACtD,OAAO,UAAU,CAAC,EAAE,CAAA;AACtB,CAAC;AAkBD;;;;GAIG;AACH,SAAS,kBAAkB,CACzB,KAAe,EACf,SAAyC,EACzC,YAAoB,EACpB,MAA4B;IAE5B,mFAAmF;IACnF,gFAAgF;IAChF,mFAAmF;IACnF,IAAI,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,CAAC,IAAI,CACT,QAAQ,CAAC;YACP,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,eAAe,KAAK,CAAC,IAAI,yDAAyD;YAC3F,IAAI,EAAE,CAAC,GAAG,SAAS,EAAE,MAAM,CAAC;YAC5B,YAAY;YACZ,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE;SAC5B,CAAC,CACH,CAAA;IACH,CAAC;IACD,gFAAgF;IAChF,qEAAqE;IACrE,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAA;QAChC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAChC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,IAAI,CACT,QAAQ,CAAC;oBACP,IAAI,EAAE,sBAAsB;oBAC5B,OAAO,EAAE,4BAA4B,GAAG,CAAC,KAAK,eAAe,KAAK,CAAC,IAAI,IAAI;oBAC3E,IAAI,EAAE,CAAC,GAAG,SAAS,EAAE,SAAS,CAAC;oBAC/B,YAAY;oBACZ,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE;iBAC/C,CAAC,CACH,CAAA;YACH,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACvB,CAAC;IACH,CAAC;SAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;QAC9B,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvB,MAAM,CAAC,IAAI,CACT,QAAQ,CAAC;oBACP,IAAI,EAAE,iBAAiB;oBACvB,OAAO,EAAE,oBAAoB,GAAG,CAAC,IAAI,sBAAsB,KAAK,CAAC,IAAI,IAAI;oBACzE,IAAI,EAAE,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;oBACjC,YAAY;oBACZ,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE;iBAC1B,CAAC,CACH,CAAA;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACpB,CAAC;YACD,kBAAkB,CAAC,GAAG,EAAE,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,CAAA;QAC5E,CAAC,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAAC,UAAyB;IACxD,MAAM,MAAM,GAAyB,EAAE,CAAA;IACvC,8EAA8E;IAC9E,kEAAkE;IAClE,IAAI,UAAU,CAAC,SAAS,KAAK,IAAI,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACjE,MAAM,CAAC,IAAI,CACT,QAAQ,CAAC;YACP,IAAI,EAAE,2BAA2B;YACjC,OAAO,EAAE,qBAAqB,UAAU,CAAC,EAAE,0BAA0B;YACrE,IAAI,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC,EAAE,CAAC;YACpC,YAAY,EAAE,UAAU,CAAC,EAAE;SAC5B,CAAC,CACH,CAAA;IACH,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAA;IACpC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACrC,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,MAAM,CAAC,IAAI,CACT,QAAQ,CAAC;gBACP,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,oBAAoB,KAAK,CAAC,IAAI,oBAAoB,UAAU,CAAC,EAAE,IAAI;gBAC5E,IAAI,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACjD,YAAY,EAAE,UAAU,CAAC,EAAE;gBAC3B,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE;aAC5B,CAAC,CACH,CAAA;QACH,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC5B,CAAC;QACD,kBAAkB,CAAC,KAAK,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IAC/F,CAAC,CAAC,CAAA;IACF,OAAO,MAAM,CAAA;AACf,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,wBAAwB,CAAC,IAA8B;IACrE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAyB,CAAA;IACpD,MAAM,MAAM,GAAyB,EAAE,CAAA;IAEvC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,0DAA0D;QAC1D,MAAM,GAAG,GAAG,mBAAmB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC1C,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,CACT,QAAQ,CAAC;gBACP,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,4BAA4B,GAAG,CAAC,EAAE,IAAI;gBAC/C,IAAI,EAAE,CAAC,aAAa,EAAE,GAAG,CAAC,EAAE,CAAC;gBAC7B,YAAY,EAAE,GAAG,CAAC,EAAE;aACrB,CAAC,CACH,CAAA;YACD,SAAQ;QACV,CAAC;QACD,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;QAC5B,MAAM,CAAC,IAAI,CAAC,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAA;IAC9C,CAAC;IAED,OAAO;QACL,WAAW;QACX,MAAM;QACN,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QAChC,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QAChC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC;QACrC,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC;KACpF,CAAA;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/cms-core/collections.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod'\nimport { RESERVED_NODE_KEYS } from './envelopes'\nimport { fieldDefSchema } from './fields'\nimport type { FieldDef } from './fields'\nimport { cmsIssue } from './issues'\nimport type { CmsValidationIssue } from './issues'\n\n/**\n * The kind of a collection (brief §7.4).\n * - `document` ordinary content collection (posts, pages, authors…).\n * - `asset` the asset collection concept: holds uploaded media/files that\n * `asset` fields point at (EC-017).\n */\nexport const collectionKindSchema = z.enum(['document', 'asset'])\nexport type CollectionKind = z.infer<typeof collectionKindSchema>\n\n/** Form metadata at the collection level (labels, ordering of groups/tabs). */\nexport const collectionFormMetaSchema = z.object({\n /** Plural human label, e.g. \"Blog Posts\". */\n label: z.string().optional(),\n /** Singular human label, e.g. \"Blog Post\". */\n labelSingular: z.string().optional(),\n description: z.string().optional(),\n /** Declared ordering of form groups (fieldsets). */\n groups: z.array(z.string()).optional(),\n /** Declared ordering of form tabs. */\n tabs: z.array(z.string()).optional(),\n})\nexport type CollectionFormMeta = z.infer<typeof collectionFormMetaSchema>\n\n/**\n * A collection definition: an id, a kind, an ordered list of fields, and\n * optional form metadata. The field whose value identifies a document for\n * routing/display defaults to `title` when present (see `titleFieldOf`).\n */\nexport const collectionDefSchema = z.object({\n id: z.string().min(1),\n kind: collectionKindSchema.default('document'),\n fields: z.array(fieldDefSchema).default([]),\n form: collectionFormMetaSchema.optional(),\n /** When true, documents in this collection support localized variants (EC-018). */\n localized: z.boolean().optional(),\n /** Name of the field used as the document's display title (defaults to `title`). */\n titleField: z.string().optional(),\n /**\n * When true, this collection is presented as a SINGLE document — Settings,\n * Footer, Homepage SEO… (EC-217, re-scoped EC-274). A pure **UI lens**: the\n * one document keeps a normal generated id (NOT the collection id — no code\n * ever names a literal document id), and the studio skips the list to open it\n * directly *only while the collection is in its expected shape* (exactly one\n * document). On drift (>1 document) the list is shown with the outliers in a\n * \"for review\" lane ({@link resolveSingletonDocument}). Reversible with no\n * migration: flipping back to a normal collection just restores the list.\n * Storage, engine, delivery, and validation paths are unchanged. Meaningless\n * on an `asset` collection (flagged as `invalid-collection-config`).\n */\n singleton: z.boolean().optional(),\n /**\n * Declared alias **slots** (EC-284): the fixed set of named handles documents in\n * this collection can be assigned (`['main', 'mobile', 'footer', 'legal']`), so\n * code resolves a specific document by `(collection, alias)` instead of an\n * opaque id. Each document's `alias` must be one of these and unique within the\n * collection; a declared-but-unfilled slot, a duplicate, or an out-of-set alias\n * is surfaced as drift (the \"for review\" lane), never a silent failure.\n */\n aliases: z.array(z.string().min(1)).optional(),\n})\nexport type CollectionDef = z.infer<typeof collectionDefSchema>\n\n/** Look up a field by name within a collection. */\nexport function fieldOf(collection: CollectionDef, name: string): FieldDef | undefined {\n return collection.fields.find((f) => f.name === name)\n}\n\n/** The field used as the display title, if resolvable. */\nexport function titleFieldOf(collection: CollectionDef): FieldDef | undefined {\n const name = collection.titleField ?? 'title'\n return fieldOf(collection, name)\n}\n\n/**\n * Is this a singleton collection — one fixed document, no list view (EC-217)?\n * A singleton `asset` collection is a config error (asset collections are\n * inherently multi-document); we defensively treat it as a normal asset\n * collection so routing never mis-branches, and the registry surfaces the\n * misconfiguration as an `invalid-collection-config` issue.\n */\nexport function isSingleton(collection: CollectionDef): boolean {\n return collection.singleton === true && collection.kind !== 'asset'\n}\n\n/** The declared alias slots for a collection (EC-284), or `[]` when none. */\nexport function declaredAliases(collection: CollectionDef): readonly string[] {\n return collection.aliases ?? []\n}\n\n/** Does this collection address its documents by alias slots (EC-284)? */\nexport function hasAliases(collection: CollectionDef): boolean {\n return declaredAliases(collection).length > 0\n}\n\n/**\n * A metadata registry of collections, keyed by id (brief §7.4 \"metadata\n * registries\"). Construction validates structural invariants (duplicate\n * collection/field ids) and surfaces them as structured issues rather than\n * throwing — an invalid registry is still inspectable.\n */\nexport interface CollectionRegistry {\n readonly collections: ReadonlyMap<string, CollectionDef>\n readonly issues: readonly CmsValidationIssue[]\n get(id: string): CollectionDef | undefined\n has(id: string): boolean\n list(): CollectionDef[]\n /** Asset-kind collections only (EC-017). */\n assetCollections(): CollectionDef[]\n}\n\n/**\n * Recursively validate a single field's shape (EC-253): select-option uniqueness,\n * plus — for an `object` field — unique subfield names and the same checks applied\n * recursively to its nested fields. Pure; collects structured issues, never throws.\n */\nfunction validateFieldShape(\n field: FieldDef,\n fieldPath: ReadonlyArray<string | number>,\n collectionId: string,\n issues: CmsValidationIssue[],\n): void {\n // EC-277 (AD-15): `type` is reserved as the self-describing node discriminator, so\n // a value object can never carry a user field that collides with it. The schema\n // lens forbids declaring such a field — surfaced as a visible issue, never silent.\n if (RESERVED_NODE_KEYS.has(field.name)) {\n issues.push(\n cmsIssue({\n code: 'reserved-field-name',\n message: `Field name \"${field.name}\" is reserved (the self-describing node discriminator).`,\n path: [...fieldPath, 'name'],\n collectionId,\n meta: { field: field.name },\n }),\n )\n }\n // select fields must declare at least one option (schema enforces min(1), but a\n // select with duplicate option values is a config error we surface).\n if (field.type === 'select') {\n const values = new Set<string>()\n for (const opt of field.options) {\n if (values.has(opt.value)) {\n issues.push(\n cmsIssue({\n code: 'invalid-field-config',\n message: `Duplicate select option \"${opt.value}\" on field \"${field.name}\".`,\n path: [...fieldPath, 'options'],\n collectionId,\n meta: { field: field.name, option: opt.value },\n }),\n )\n }\n values.add(opt.value)\n }\n } else if (field.type === 'object') {\n const seen = new Set<string>()\n field.fields.forEach((sub, i) => {\n if (seen.has(sub.name)) {\n issues.push(\n cmsIssue({\n code: 'duplicate-field',\n message: `Duplicate field \"${sub.name}\" in object field \"${field.name}\".`,\n path: [...fieldPath, 'fields', i],\n collectionId,\n meta: { field: sub.name },\n }),\n )\n } else {\n seen.add(sub.name)\n }\n validateFieldShape(sub, [...fieldPath, 'fields', i], collectionId, issues)\n })\n }\n}\n\nfunction validateCollectionShape(collection: CollectionDef): CmsValidationIssue[] {\n const issues: CmsValidationIssue[] = []\n // EC-217: an asset collection is inherently multi-document — `singleton` is a\n // nonsensical combination, surfaced rather than silently ignored.\n if (collection.singleton === true && collection.kind === 'asset') {\n issues.push(\n cmsIssue({\n code: 'invalid-collection-config',\n message: `Asset collection \"${collection.id}\" cannot be a singleton.`,\n path: ['collections', collection.id],\n collectionId: collection.id,\n }),\n )\n }\n const seenFields = new Set<string>()\n collection.fields.forEach((field, i) => {\n if (seenFields.has(field.name)) {\n issues.push(\n cmsIssue({\n code: 'duplicate-field',\n message: `Duplicate field \"${field.name}\" in collection \"${collection.id}\".`,\n path: ['collections', collection.id, 'fields', i],\n collectionId: collection.id,\n meta: { field: field.name },\n }),\n )\n } else {\n seenFields.add(field.name)\n }\n validateFieldShape(field, ['collections', collection.id, 'fields', i], collection.id, issues)\n })\n return issues\n}\n\n/** Build a collection registry from definitions, collecting structural issues. */\nexport function createCollectionRegistry(defs: readonly CollectionDef[]): CollectionRegistry {\n const collections = new Map<string, CollectionDef>()\n const issues: CmsValidationIssue[] = []\n\n for (const raw of defs) {\n // Apply schema defaults (kind, fields) deterministically.\n const def = collectionDefSchema.parse(raw)\n if (collections.has(def.id)) {\n issues.push(\n cmsIssue({\n code: 'duplicate-collection',\n message: `Duplicate collection id \"${def.id}\".`,\n path: ['collections', def.id],\n collectionId: def.id,\n }),\n )\n continue\n }\n collections.set(def.id, def)\n issues.push(...validateCollectionShape(def))\n }\n\n return {\n collections,\n issues,\n get: (id) => collections.get(id),\n has: (id) => collections.has(id),\n list: () => [...collections.values()],\n assetCollections: () => [...collections.values()].filter((c) => c.kind === 'asset'),\n }\n}\n"]}
|
|
@@ -62,6 +62,7 @@ export type FieldValues = Record<string, unknown>;
|
|
|
62
62
|
export declare const documentSchema: z.ZodObject<{
|
|
63
63
|
collection: z.ZodString;
|
|
64
64
|
id: z.ZodString;
|
|
65
|
+
alias: z.ZodOptional<z.ZodString>;
|
|
65
66
|
values: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
66
67
|
localized: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
67
68
|
defaultLocale: z.ZodOptional<z.ZodString>;
|
|
@@ -53,6 +53,16 @@ export const publicationStateSchema = z.enum(['draft', 'published']);
|
|
|
53
53
|
export const documentSchema = z.object({
|
|
54
54
|
collection: z.string().min(1),
|
|
55
55
|
id: z.string().min(1),
|
|
56
|
+
/**
|
|
57
|
+
* Slot assignment (EC-284): a stable, editable handle so code addresses this
|
|
58
|
+
* document by `(collection, alias)` — `resolveByAlias('navigation', 'footer')`
|
|
59
|
+
* — never by its opaque id. Identity-adjacent (like `id`), not a content value:
|
|
60
|
+
* non-localized, outside `values`, so it never reserves a field name or is
|
|
61
|
+
* caught by the EC-277 self-typing of `values`. Constrained to the collection's
|
|
62
|
+
* declared `aliases` and unique within the collection (validated, not enforced
|
|
63
|
+
* at the store — drift is surfaced, never silently dropped).
|
|
64
|
+
*/
|
|
65
|
+
alias: z.string().min(1).optional(),
|
|
56
66
|
/** Non-localized field values shared across locales. */
|
|
57
67
|
values: z.record(z.string(), z.unknown()).default({}),
|
|
58
68
|
/** Per-locale overrides for localized fields: `{ [locale]: { [field]: value } }`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/cms-core/documents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAG7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACtB,CAAC,CAAA;AAGF,oEAAoE;AACpE,MAAM,CAAC,MAAM,4BAA4B,GAAG,iBAAiB,CAAC,MAAM,CAAC;IACnE,MAAM,EAAE,YAAY;CACrB,CAAC,CAAA;AAGF,iDAAiD;AACjD,MAAM,UAAU,WAAW,CAAC,GAAgB;IAC1C,OAAO,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,EAAE,EAAE,CAAA;AACtC,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,sBAAsB,CAAC,GAA2B;IAChE,OAAO,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,EAAE,CAAA;AACpD,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAC,CAAc,EAAE,CAAc;IAC9D,OAAO,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAA;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAA;AAUpE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,wDAAwD;IACxD,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrD,qFAAqF;IACrF,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC/E,iFAAiF;IACjF,aAAa,EAAE,YAAY,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAA;AAGF,yCAAyC;AACzC,MAAM,UAAU,KAAK,CAAC,GAAgB;IACpC,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAA;AACnD,CAAC"}
|
|
1
|
+
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/cms-core/documents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAG7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACtB,CAAC,CAAA;AAGF,oEAAoE;AACpE,MAAM,CAAC,MAAM,4BAA4B,GAAG,iBAAiB,CAAC,MAAM,CAAC;IACnE,MAAM,EAAE,YAAY;CACrB,CAAC,CAAA;AAGF,iDAAiD;AACjD,MAAM,UAAU,WAAW,CAAC,GAAgB;IAC1C,OAAO,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,EAAE,EAAE,CAAA;AACtC,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,sBAAsB,CAAC,GAA2B;IAChE,OAAO,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,EAAE,CAAA;AACpD,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAC,CAAc,EAAE,CAAc;IAC9D,OAAO,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAA;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAA;AAUpE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB;;;;;;;;OAQG;IACH,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACnC,wDAAwD;IACxD,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrD,qFAAqF;IACrF,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC/E,iFAAiF;IACjF,aAAa,EAAE,YAAY,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAA;AAGF,yCAAyC;AACzC,MAAM,UAAU,KAAK,CAAC,GAAgB;IACpC,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAA;AACnD,CAAC","sourcesContent":["import { z } from 'zod'\n\n/**\n * A locale code (BCP-47-ish, e.g. `en`, `en-US`, `de`). Kept as a plain\n * non-empty string so unusual locales still parse; validity against a project's\n * declared locale set is checked semantically (EC-018).\n */\nexport const localeSchema = z.string().min(1)\nexport type Locale = z.infer<typeof localeSchema>\n\n/**\n * A document identity (EC-017): the stable pointer to a piece of content. A\n * document belongs to exactly one collection and has a stable id. For localized\n * content the *identity* is collection+id; a specific localized variant is\n * addressed by additionally carrying a locale (see `LocaleAwareDocumentRef`).\n */\nexport const documentRefSchema = z.object({\n collection: z.string().min(1),\n id: z.string().min(1),\n})\nexport type DocumentRef = z.infer<typeof documentRefSchema>\n\n/** A document identity together with a specific locale (EC-018). */\nexport const localeAwareDocumentRefSchema = documentRefSchema.extend({\n locale: localeSchema,\n})\nexport type LocaleAwareDocumentRef = z.infer<typeof localeAwareDocumentRefSchema>\n\n/** Stable string key for a document identity. */\nexport function documentKey(ref: DocumentRef): string {\n return `${ref.collection}:${ref.id}`\n}\n\n/** Stable string key for a locale-aware document identity. */\nexport function localeAwareDocumentKey(ref: LocaleAwareDocumentRef): string {\n return `${ref.collection}:${ref.id}@${ref.locale}`\n}\n\n/** Equality on document identity (collection + id), ignoring locale. */\nexport function documentRefEquals(a: DocumentRef, b: DocumentRef): boolean {\n return a.collection === b.collection && a.id === b.id\n}\n\n/**\n * Target state of a publish/unpublish *action* (EC-021). No longer a stored\n * document field (EC-224 retired it — publish-ness is the version pointer, see\n * `publishedVersion`); this enum names the *intent* of a bulk publish/unpublish\n * action (the studio's `applyState` contract), not a property a row carries.\n */\nexport const publicationStateSchema = z.enum(['draft', 'published'])\nexport type PublicationState = z.infer<typeof publicationStateSchema>\n\n/**\n * A bag of field values for a single (locale of a) document. Values are arbitrary\n * JSON — validated against the collection's fields by `validateDocument`, not at\n * this layer. Relations store `DocumentRef`(s); assets store asset ids.\n */\nexport type FieldValues = Record<string, unknown>\n\n/**\n * A stored document (EC-016/017/018). The live row is the continuous DRAFT\n * (the Sanity model, EC-224). Holds:\n * - identity (`collection` + `id`),\n * - non-localized field values in `values`,\n * - per-locale field values in `localized` (only for localized fields).\n *\n * Publish-ness is NOT a field here: a document is published when an append-only\n * version is pinned via the record's `publishedVersion` pointer (EC-224). The\n * delivery `published` perspective serves that pinned snapshot; this live row\n * is always the working draft.\n */\nexport const documentSchema = z.object({\n collection: z.string().min(1),\n id: z.string().min(1),\n /**\n * Slot assignment (EC-284): a stable, editable handle so code addresses this\n * document by `(collection, alias)` — `resolveByAlias('navigation', 'footer')`\n * — never by its opaque id. Identity-adjacent (like `id`), not a content value:\n * non-localized, outside `values`, so it never reserves a field name or is\n * caught by the EC-277 self-typing of `values`. Constrained to the collection's\n * declared `aliases` and unique within the collection (validated, not enforced\n * at the store — drift is surfaced, never silently dropped).\n */\n alias: z.string().min(1).optional(),\n /** Non-localized field values shared across locales. */\n values: z.record(z.string(), z.unknown()).default({}),\n /** Per-locale overrides for localized fields: `{ [locale]: { [field]: value } }`. */\n localized: z.record(localeSchema, z.record(z.string(), z.unknown())).optional(),\n /** The default locale this document was authored in (EC-018 fallback source). */\n defaultLocale: localeSchema.optional(),\n})\nexport type CmsDocument = z.infer<typeof documentSchema>\n\n/** The identity of a stored document. */\nexport function refOf(doc: CmsDocument): DocumentRef {\n return { collection: doc.collection, id: doc.id }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envelopes.js","sourceRoot":"","sources":["../../src/cms-core/envelopes.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"envelopes.js","sourceRoot":"","sources":["../../src/cms-core/envelopes.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod'\nimport { documentRefSchema } from './documents'\nimport type { DocumentRef } from './documents'\n\n/**\n * Self-describing content envelopes (EC-277, vision AD-15).\n *\n * A value's *type* used to be inferred from the schema at read time — a stored\n * relation was a bare `{ collection, id }`, an asset a bare id string, a rich-text\n * internal link a fuzzy `elytra:document/…` href. Interpreting those required the\n * schema (or the component manifest), which is exactly why structural derivation\n * (the reference index, where-used, validation) had to run in client/app code.\n *\n * Self-describing data inverts this: every node that *isn't* a plain scalar carries\n * an explicit `type` discriminator at rest, so a structural walk over content can\n * recognise references/assets/blocks **without the schema** — making derivation a\n * pure function of data the backend holds (AD-6 maintained-in-Convex).\n *\n * One discriminator, `type`, unifies with rich-text — ProseMirror nodes already\n * self-describe via `type` (`{ type: 'paragraph' }`), and a typed reference/asset/\n * block node is the *same* concept, not a separate one. `_type` elsewhere would\n * manufacture a seam through one content model.\n *\n * Scope note: only the *fixed-shape* nodes we fully own get an envelope here —\n * references, assets, blocks. User-content objects / array-items stay structural\n * (a plain bag walked key-by-key); their self-description comes free from their\n * typed subfields, and NOT wrapping them avoids `type` colliding with a user field\n * literally named `type`. A block already self-types via `componentId`; `type:\n * 'block'` is added only for walk-uniformity and is accepted-but-not-required.\n */\n\n/** Node `type` discriminators owned by the envelope layer. */\nexport const REFERENCE_NODE_TYPE = 'reference'\nexport const ASSET_NODE_TYPE = 'asset'\nexport const BLOCK_NODE_TYPE = 'block'\n\n/**\n * Field names reserved by the self-describing layer. The write-time schema lens\n * (validation) rejects a user field declared with one of these names — the single\n * cost of unifying on a plain `type` discriminator instead of a `_`-namespaced one,\n * enforced at the one write chokepoint we already own.\n */\nexport const RESERVED_NODE_KEYS: ReadonlySet<string> = new Set(['type'])\n\n/**\n * A self-typed reference to a document (EC-277). Wraps the collection-scoped\n * {@link DocumentRef} payload (kept as-is — it matches the reference index key\n * `collection:id`) behind an explicit `type: 'reference'` discriminator.\n */\nexport const referenceNodeSchema = documentRefSchema.extend({\n type: z.literal(REFERENCE_NODE_TYPE),\n})\nexport type ReferenceNode = z.infer<typeof referenceNodeSchema>\n\n/** A self-typed reference to an asset (EC-277). Replaces the bare asset-id string. */\nexport const assetNodeSchema = z.object({\n type: z.literal(ASSET_NODE_TYPE),\n id: z.string().min(1),\n})\nexport type AssetNode = z.infer<typeof assetNodeSchema>\n\n// --- Constructors -----------------------------------------------------------------\n\n/** Wrap a document identity in a self-typed reference node. */\nexport function referenceNode(ref: DocumentRef): ReferenceNode {\n return { type: REFERENCE_NODE_TYPE, collection: ref.collection, id: ref.id }\n}\n\n/** Wrap an asset id in a self-typed asset node. */\nexport function assetNode(id: string): AssetNode {\n return { type: ASSET_NODE_TYPE, id }\n}\n\n// --- Guards -----------------------------------------------------------------------\n\nfunction asNodeRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined\n}\n\n/** Structural test for a self-typed reference node. */\nexport function isReferenceNode(value: unknown): value is ReferenceNode {\n const record = asNodeRecord(value)\n return (\n record !== undefined &&\n record.type === REFERENCE_NODE_TYPE &&\n typeof record.collection === 'string' &&\n record.collection.length > 0 &&\n typeof record.id === 'string' &&\n record.id.length > 0\n )\n}\n\n/** Structural test for a self-typed asset node. */\nexport function isAssetNode(value: unknown): value is AssetNode {\n const record = asNodeRecord(value)\n return (\n record !== undefined &&\n record.type === ASSET_NODE_TYPE &&\n typeof record.id === 'string' &&\n record.id.length > 0\n )\n}\n\n/** The document identity carried by a reference node (strips the discriminator). */\nexport function refOfReferenceNode(node: ReferenceNode): DocumentRef {\n return { collection: node.collection, id: node.id }\n}\n\n// --- Tolerant readers (the lazy-on-read migration net) ----------------------------\n\n/**\n * Read a document identity out of a stored relation value, accepting BOTH the\n * self-typed envelope (`{ type: 'reference', collection, id }`) and a legacy bare\n * `{ collection, id }`. This is the single unwrap every relation reader routes\n * through — and the lazy-on-read half of the EC-277 migration: content that has not\n * yet been upgraded still reads correctly. Returns `undefined` for anything else.\n */\nexport function readDocumentRef(value: unknown): DocumentRef | undefined {\n if (isReferenceNode(value)) return { collection: value.collection, id: value.id }\n const record = asNodeRecord(value)\n if (\n record !== undefined &&\n record.type === undefined &&\n typeof record.collection === 'string' &&\n record.collection.length > 0 &&\n typeof record.id === 'string' &&\n record.id.length > 0\n ) {\n return { collection: record.collection, id: record.id }\n }\n return undefined\n}\n\n/**\n * Read an asset id out of a stored asset value, accepting BOTH the self-typed\n * envelope (`{ type: 'asset', id }`) and a legacy bare id string. The asset twin of\n * {@link readDocumentRef}. Returns `undefined` for anything else.\n */\nexport function readAssetId(value: unknown): string | undefined {\n if (isAssetNode(value)) return value.id\n if (typeof value === 'string' && value.length > 0) return value\n return undefined\n}\n"]}
|