@elytracms/next 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../cms-core/src/issues.ts","../../cms-core/src/fields.ts","../../cms-core/src/collections.ts","../../cms-core/src/documents.ts","../../cms-core/src/localization.ts","../../cms-core/src/routes.ts","../../cms-core/src/hierarchy.ts","../../cms-core/src/validate-document.ts","../../cms-core/src/versions.ts","../../cms-core/src/fixtures.ts","../../component-registry/src/manifest.ts","../../project-graph/src/json.ts","../../project-graph/src/ids.ts","../../project-graph/src/binding.ts","../../project-graph/src/node.ts","../../project-graph/src/structure.ts","../../project-graph/src/container.ts","../../project-graph/src/issues.ts","../../project-graph/src/serialize.ts","../../project-graph/src/fixtures.ts","../../component-registry/src/registry.ts","../../runtime-renderer/src/context.ts","../../runtime-renderer/src/condition.ts","../../runtime-renderer/src/content-client.tsx","../../runtime-renderer/src/fallback.tsx","../../runtime-renderer/src/render.tsx","../../rich-text/src/schema.ts","../../rich-text/src/embed.ts","../../rich-text/src/registry.tsx","../../rich-text/src/render.tsx","../../rich-text/src/fixtures.tsx","../../runtime-renderer/src/rich-text.tsx","../../runtime-renderer/src/primitives.tsx","../src/components.ts","../src/payloads.ts","../src/canvas-renderer.tsx","../../content/src/context.ts","../../content/src/perspective.ts","../../content/src/locale.ts","../../content/src/populate.ts","../../content/src/assets.ts","../../content/src/resolve.ts","../../content/src/query.ts","../../content/src/cursor.ts","../../content/src/tags.ts","../../content/src/client.ts","../../content/src/binding-sources.ts","../src/source.ts","../src/source-payloads.ts","../src/snapshot.ts","../src/route-core.ts","../src/cache.ts","../src/metadata.ts","../src/route.tsx","../src/sitemap.ts","../src/revalidate-core.ts","../src/revalidate.ts","../src/image.tsx","../src/preview-core.ts","../src/preview.ts","../src/index.ts"],"names":["z","jsx","createElement","resolved","Fragment","renderNode","isPlainObject","ref","normalizePath","route","str","outcome","draftMode","redirect"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod'\n\n/**\n * Stable codes for structured CMS validation issues (brief §4.11, §7.4).\n *\n * We mirror the conventions of `@elytracms/project-graph`'s `ValidationIssue`\n * (a structured object with `code`/`severity`/`message`/`path`, never a thrown\n * error) so callers can treat graph and CMS issues uniformly. The code set here\n * is CMS-specific; the shape is shared.\n */\nexport const cmsIssueCodeSchema = z.enum([\n // collections & fields (EC-016)\n 'duplicate-collection',\n 'duplicate-field',\n 'unknown-collection',\n 'invalid-collection-config',\n 'invalid-field-config',\n 'missing-required-field',\n 'invalid-field-value',\n // relations & assets (EC-017)\n 'unknown-relation-target',\n // broken published references after a weak unpublish (EC-173)\n 'unpublished-relation-target',\n 'cardinality-violation',\n 'unknown-asset',\n 'duplicate-document',\n // localization (EC-018)\n 'unknown-locale',\n 'missing-localized-value',\n // routes / redirects / resolution (EC-019, EC-020)\n 'route-conflict',\n 'redirect-loop',\n 'unknown-route-target',\n // page hierarchy (EC-218): a parent chain that loops\n 'hierarchy-cycle',\n // versions (EC-021)\n 'unknown-version',\n])\nexport type CmsIssueCode = z.infer<typeof cmsIssueCodeSchema>\n\nexport const cmsIssueSeveritySchema = z.enum(['error', 'warning'])\nexport type CmsIssueSeverity = z.infer<typeof cmsIssueSeveritySchema>\n\n/** A JSON-serializable scalar carried in issue metadata. */\nexport type CmsIssueMetaValue = string | number | boolean | null | readonly (string | number)[]\n\n/**\n * A structured CMS validation issue. Same conventions as\n * `@elytracms/project-graph`'s `ValidationIssue`: a path locating the offending\n * data, optional document/collection identity, and free-form metadata.\n */\nexport const cmsValidationIssueSchema = z.object({\n code: cmsIssueCodeSchema,\n severity: cmsIssueSeveritySchema,\n message: z.string(),\n /** Path into the CMS data, e.g. ['collections', 'post', 'fields', 'author']. */\n path: z.array(z.union([z.string(), z.number()])),\n /** The offending collection id, when applicable. */\n collectionId: z.string().optional(),\n /** The offending document id, when applicable. */\n documentId: z.string().optional(),\n meta: z.record(z.string(), z.unknown()).optional(),\n})\nexport type CmsValidationIssue = z.infer<typeof cmsValidationIssueSchema>\n\nexport type CmsPath = ReadonlyArray<string | number>\n\nexport interface CmsIssueInit {\n code: CmsIssueCode\n severity?: CmsIssueSeverity\n message: string\n path: CmsPath\n collectionId?: string\n documentId?: string\n meta?: Record<string, unknown>\n}\n\n/** Construct a structured CMS issue. `severity` defaults to `error`. */\nexport function cmsIssue(init: CmsIssueInit): CmsValidationIssue {\n return {\n code: init.code,\n severity: init.severity ?? 'error',\n message: init.message,\n path: [...init.path],\n ...(init.collectionId ? { collectionId: init.collectionId } : {}),\n ...(init.documentId ? { documentId: init.documentId } : {}),\n ...(init.meta ? { meta: init.meta } : {}),\n }\n}\n\n/** True if a set of CMS issues contains no error-severity entries. */\nexport function isCmsValid(issues: readonly CmsValidationIssue[]): boolean {\n return !issues.some((i) => i.severity === 'error')\n}\n","import { z } from 'zod'\n\n/**\n * Provider-neutral field type catalogue (brief §7.4). Relation and asset are\n * first-class field types but carry extra config (target collection, cardinality),\n * so they're modelled as discriminated variants below rather than bare strings.\n */\nexport const fieldTypeSchema = z.enum([\n 'text',\n 'number',\n 'boolean',\n 'date',\n 'select',\n 'richText',\n 'relation',\n 'asset',\n // Composition field (EC-186, AD-12): the value is a constrained tree of\n // registry components (a canvas), not a scalar. The vocabulary is code.\n 'blocks',\n // Object / repeater field (EC-253): a nested group of field-defs — a single\n // object (`cardinality: 'one'`) or an ordered array of them (`'many'`). The\n // missing array-of-objects primitive real sites lean on (menus, forms, galleries).\n 'object',\n])\nexport type FieldType = z.infer<typeof fieldTypeSchema>\n\n/** How many related documents a relation field points at. */\nexport const cardinalitySchema = z.enum(['one', 'many'])\nexport type Cardinality = z.infer<typeof cardinalitySchema>\n\n/**\n * Where a field-def is valid (EC-190 \"props as fields\"): a CMS document field, a\n * component prop, or both. The same field-def vocabulary drives documents AND\n * component props through one inspector/form engine — `context` only gates which\n * document-only attributes apply, never the stored value or emitted JSON Schema.\n */\nexport const fieldContextSchema = z.enum(['document', 'prop', 'both'])\nexport type FieldContext = z.infer<typeof fieldContextSchema>\n\n/**\n * Preferred input control when a field type maps to several presentation forms\n * (e.g. a `text` field rendered as a single input, a textarea, a colour picker, or\n * a JSON editor). Presentation only — never affects validation or stored values.\n */\nexport const fieldControlSchema = z.enum(['input', 'textarea', 'color', 'json'])\nexport type FieldControl = z.infer<typeof fieldControlSchema>\n\n/**\n * Form/authoring metadata for a field (brief §7.4: groups/tabs/labels/order).\n * Pure presentation hints — never affects validation or stored values.\n */\nexport const fieldFormMetaSchema = z.object({\n /** Human label shown in the editor; falls back to the field name when omitted. */\n label: z.string().optional(),\n /** Helper/description text shown under the field. */\n description: z.string().optional(),\n /** Placeholder for text-like inputs. */\n placeholder: z.string().optional(),\n /** Grouping section the field belongs to (a fieldset). */\n group: z.string().optional(),\n /** Tab the field belongs to (for tabbed editors). */\n tab: z.string().optional(),\n /** Sort order within its group/tab; lower comes first. */\n order: z.number().optional(),\n /** When true the editor renders the field read-only. */\n readOnly: z.boolean().optional(),\n /** When true the editor hides the field (still validated/stored). */\n hidden: z.boolean().optional(),\n /** Preferred input control when the field type maps to several (EC-190). */\n control: fieldControlSchema.optional(),\n /**\n * When true the editor edits this value inline on the canvas (EC-158) rather\n * than as a form row — used for text-like component props rendered as visible\n * content. The single home for inline-editing across documents and props.\n */\n inlineEditable: z.boolean().optional(),\n})\nexport type FieldFormMeta = z.infer<typeof fieldFormMetaSchema>\n\n/**\n * Declarative validation metadata for a field (brief §7.4). These constraints\n * are provider-neutral and drive both runtime validation (`validateDocument`)\n * and JSON Schema output. They never throw — violations surface as structured\n * issues.\n */\nexport const fieldValidationSchema = z.object({\n /** When true a value must be present (and non-empty for strings/arrays). */\n required: z.boolean().optional(),\n /** Minimum string length / array length / numeric value (type-dependent). */\n min: z.number().optional(),\n /** Maximum string length / array length / numeric value (type-dependent). */\n max: z.number().optional(),\n /** RegExp source string a text value must match. */\n pattern: z.string().optional(),\n /** Value must be unique across the collection's documents. */\n unique: z.boolean().optional(),\n})\nexport type FieldValidation = z.infer<typeof fieldValidationSchema>\n\n/** A single allowed option for a `select` field. */\nexport const selectOptionSchema = z.object({\n value: z.string(),\n label: z.string().optional(),\n})\nexport type SelectOption = z.infer<typeof selectOptionSchema>\n\nconst baseFieldShape = {\n /** Stable field name (the key in a document's values; survives label changes). */\n name: z.string().min(1),\n /** When true the field stores a separate value per locale (EC-018). */\n localized: z.boolean().optional(),\n /**\n * Marks the field as filterable/sortable for the closed-form list accessors\n * (EC-143, vision AD-3). `listDocuments` filters and sorts are permitted only\n * on declared fields — this keeps backend indexes honest and stops filter\n * vocabulary creep. Never affects stored values or validation.\n */\n filterable: z.boolean().optional(),\n /**\n * Where this field-def is valid (EC-190): a CMS document field, a component\n * prop, or both. Defaults to `document` when omitted (back-compat — every\n * existing collection field-def stays a document field). Document-only\n * attributes (`filterable`, `validation.unique`) declared on a `context:'prop'`\n * field are a structured issue (`assertPropFieldDef`), never silent.\n */\n context: fieldContextSchema.optional(),\n /**\n * Default value applied when none is set (EC-190). On a component prop this is\n * the renderer's static fallback (EC-015); on a document field it seeds new\n * documents — the per-field starter-content mechanism (no template entity\n * needed). Never affects whether a value is *stored*, only what fills a gap.\n */\n default: z.unknown().optional(),\n form: fieldFormMetaSchema.optional(),\n validation: fieldValidationSchema.optional(),\n}\n\n/** A schema of just the shared base attributes — the source for {@link BaseFieldDef}. */\nconst baseFieldObjectSchema = z.object(baseFieldShape)\n/** Attributes every field-def carries, derived from {@link baseFieldShape}. */\ntype BaseFieldDef = z.infer<typeof baseFieldObjectSchema>\n\n/**\n * A field definition (the shape {@link fieldDefSchema} parses to). Written\n * explicitly rather than via `z.infer` because the `object` variant is recursive\n * — its `fields` reference `FieldDef` itself — and TypeScript cannot infer a\n * self-referential `z.infer`. The schema below is annotated with this type and the\n * two are kept in lock-step (`object-field.test.ts` round-trips against drift).\n *\n * A discriminated union on `type` so relation/asset/select/object carry exactly\n * the extra config they need and nothing more.\n */\nexport type FieldDef =\n | (BaseFieldDef & { type: 'text' })\n | (BaseFieldDef & { type: 'number' })\n | (BaseFieldDef & { type: 'boolean' })\n | (BaseFieldDef & { type: 'date' })\n | (BaseFieldDef & { type: 'select'; options: SelectOption[]; multiple?: boolean })\n | (BaseFieldDef & { type: 'richText'; allow?: string[] })\n | (BaseFieldDef & {\n type: 'relation'\n target: string\n cardinality: Cardinality\n populate?: boolean\n strict?: boolean\n })\n | (BaseFieldDef & { type: 'asset'; cardinality: Cardinality; accept?: string[] })\n | (BaseFieldDef & { type: 'blocks'; allow?: string[]; cardinality: Cardinality })\n // EC-253: object / repeater — recursive (a subfield may itself be `object`).\n | (BaseFieldDef & { type: 'object'; fields: FieldDef[]; cardinality: Cardinality })\n\n/**\n * The Zod schema mirroring {@link FieldDef}. The `object` member's `fields` is\n * wrapped in `z.lazy` so the schema can reference itself, while the discriminator\n * stays a static `z.literal('object')` so `discriminatedUnion` can still read it\n * at construction time. The explicit `z.ZodType<FieldDef>` annotation breaks the\n * self-referential inference cycle; the cast reconciles the parsed output (where\n * defaulted `cardinality` is always present) with the union's optional-input type.\n */\nexport const fieldDefSchema: z.ZodType<FieldDef> = z.discriminatedUnion('type', [\n z.object({ ...baseFieldShape, type: z.literal('text') }),\n z.object({ ...baseFieldShape, type: z.literal('number') }),\n z.object({ ...baseFieldShape, type: z.literal('boolean') }),\n z.object({ ...baseFieldShape, type: z.literal('date') }),\n z.object({\n ...baseFieldShape,\n type: z.literal('select'),\n options: z.array(selectOptionSchema).min(1),\n /** Allow selecting multiple options (stored as an array). */\n multiple: z.boolean().optional(),\n }),\n z.object({\n ...baseFieldShape,\n type: z.literal('richText'),\n /**\n * Embeddable composition vocabulary (EC-189, AD-12): component ids editors\n * may embed as `componentEmbed` blocks inside the prose — the SAME `allow`\n * mechanism a `blocks` field uses, applied to rich-text embeds. Each embed\n * holds a single `ComponentNode` validated against this list by\n * `validateCompositionValue` (`@elytracms/project-graph`). Omit to allow any\n * registered component; deeper nesting is governed by each component's slot\n * `allow`. The leash is code.\n */\n allow: z.array(z.string().min(1)).optional(),\n }),\n z.object({\n ...baseFieldShape,\n type: z.literal('relation'),\n /** Id of the collection this relation points at. */\n target: z.string().min(1),\n cardinality: cardinalitySchema,\n /**\n * Delivery-shape population declaration (EC-142). Defaults to populated:\n * delivery resolution expands the relation to a depth-1 populated reference.\n * Set to `false` to opt out and receive reference stubs\n * (`{ id, collection }`) instead. Never affects stored values.\n */\n populate: z.boolean().optional(),\n /**\n * Strict referential integrity (EC-173). References are **weak by\n * default**: unpublishing/deleting a referenced target is allowed and the\n * reference degrades to an explicit validation issue plus a delivery\n * fallback. `strict: true` is the deliberate opt-in that inverts this for\n * one field: while any document references a target through this field,\n * deleting the target is blocked — and while a *published* document does,\n * unpublishing it is blocked too (enforced in `@elytracms/operations`).\n */\n strict: z.boolean().optional(),\n }),\n z.object({\n ...baseFieldShape,\n type: z.literal('asset'),\n cardinality: cardinalitySchema.default('one'),\n /** Restrict to specific asset kinds (e.g. 'image', 'file'); empty = any. */\n accept: z.array(z.string()).optional(),\n }),\n z.object({\n ...baseFieldShape,\n type: z.literal('blocks'),\n /**\n * The composition vocabulary (EC-186, AD-12): allowed component ids editors\n * may place as TOP-LEVEL blocks. Omit to allow any registered component;\n * deeper nesting is governed by each component's slot `allow`. The value\n * (a `ComponentNode` tree) is validated against this by\n * `validateCompositionValue` (`@elytracms/project-graph`). The leash is code.\n */\n allow: z.array(z.string().min(1)).optional(),\n /** `one` = a single root component; `many` = an ordered list (default). */\n cardinality: cardinalitySchema.default('many'),\n }),\n z.object({\n ...baseFieldShape,\n type: z.literal('object'),\n /**\n * The nested field-defs. Recursive via `z.lazy` (a subfield may itself be an\n * `object`), so Konditorei's nested menu, the form builder's groups→fields,\n * and multi-entry settings model faithfully. Subfields carry their own `name`\n * (they are object keys), so this is the full `FieldDef`, not the prop shape.\n */\n fields: z.lazy(() => z.array(fieldDefSchema)),\n /** `one` = a single nested object; `many` = an ordered array (the repeater). */\n cardinality: cardinalitySchema.default('one'),\n }),\n]) as z.ZodType<FieldDef>\n\n/** A relation field, narrowed. */\nexport type RelationFieldDef = Extract<FieldDef, { type: 'relation' }>\n/** An asset field, narrowed. */\nexport type AssetFieldDef = Extract<FieldDef, { type: 'asset' }>\n/** A select field, narrowed. */\nexport type SelectFieldDef = Extract<FieldDef, { type: 'select' }>\n/** A composition (blocks) field, narrowed (EC-186). */\nexport type BlocksFieldDef = Extract<FieldDef, { type: 'blocks' }>\n/** A rich-text field, narrowed (EC-159/EC-189: carries the embed `allow` list). */\nexport type RichTextFieldDef = Extract<FieldDef, { type: 'richText' }>\n/** An object / repeater field, narrowed (EC-253). */\nexport type ObjectFieldDef = Extract<FieldDef, { type: 'object' }>\n\n/** Narrowing helpers. */\nexport function isRelationField(field: FieldDef): field is RelationFieldDef {\n return field.type === 'relation'\n}\nexport function isAssetField(field: FieldDef): field is AssetFieldDef {\n return field.type === 'asset'\n}\nexport function isSelectField(field: FieldDef): field is SelectFieldDef {\n return field.type === 'select'\n}\nexport function isBlocksField(field: FieldDef): field is BlocksFieldDef {\n return field.type === 'blocks'\n}\nexport function isRichTextField(field: FieldDef): field is RichTextFieldDef {\n return field.type === 'richText'\n}\nexport function isObjectField(field: FieldDef): field is ObjectFieldDef {\n return field.type === 'object'\n}\n\n/** Resolve a field-def's context, defaulting to `document` (EC-190). */\nexport function fieldContext(field: FieldDef): FieldContext {\n return field.context ?? 'document'\n}\n\n/** True if the field-def may be used as a component prop (EC-190). */\nexport function isPropContext(field: FieldDef): boolean {\n const c = fieldContext(field)\n return c === 'prop' || c === 'both'\n}\n\n/** True if the field-def may be used as a CMS document field (EC-190). */\nexport function isDocumentContext(field: FieldDef): boolean {\n const c = fieldContext(field)\n return c === 'document' || c === 'both'\n}\n","import { z } from 'zod'\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 holds exactly ONE fixed document — Settings,\n * Menus, Footer, Homepage SEO… (EC-217). The studio skips the list view and\n * opens the detail editor directly on the single document. Pure authoring\n * sugar: internally identical to a `document` collection, so the engine,\n * delivery, and validation paths are unchanged. Meaningless on an `asset`\n * collection (flagged as `invalid-collection-config`).\n */\n singleton: z.boolean().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/**\n * The fixed document id for a singleton collection (EC-217): the collection id\n * itself, so the one document is predictable and addressable\n * (`{ collection: 'settings', id: 'settings' }`) without a generated key.\n */\nexport function singletonDocId(collection: CollectionDef): string {\n return collection.id\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 // 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","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 /** 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","import { z } from 'zod'\nimport type { CollectionDef } from './collections'\nimport { fieldOf } from './collections'\nimport type { CmsDocument, FieldValues, Locale } from './documents'\nimport { cmsIssue } from './issues'\nimport type { CmsValidationIssue } from './issues'\n\n/**\n * Locale configuration for a project (EC-018): the set of supported locales and\n * the default used for fallback. Provider-neutral.\n */\nexport const localeConfigSchema = z.object({\n default: z.string().min(1),\n locales: z.array(z.string().min(1)).min(1),\n})\nexport type LocaleConfig = z.infer<typeof localeConfigSchema>\n\n/** Build a locale config, ensuring the default is included in the locale set. */\nexport function createLocaleConfig(init: {\n default: Locale\n locales: readonly Locale[]\n}): LocaleConfig {\n const locales = init.locales.includes(init.default)\n ? [...init.locales]\n : [init.default, ...init.locales]\n return { default: init.default, locales }\n}\n\n/** True if a locale is part of the configured set. */\nexport function isKnownLocale(config: LocaleConfig, locale: Locale): boolean {\n return config.locales.includes(locale)\n}\n\n/** Whether a given field stores per-locale values. */\nexport function isFieldLocalized(collection: CollectionDef, fieldName: string): boolean {\n return fieldOf(collection, fieldName)?.localized === true\n}\n\n/** The document's authoring/default locale, falling back to the project default. */\nexport function documentDefaultLocale(doc: CmsDocument, config: LocaleConfig): Locale {\n return doc.defaultLocale ?? config.default\n}\n\nexport interface ResolvedField {\n value: unknown\n /** The locale the value was actually read from (may differ from requested). */\n sourceLocale: Locale\n /** True when the requested locale had no value and fallback was used. */\n fellBack: boolean\n}\n\n/**\n * Resolve a single field's value for a requested locale with default-locale\n * fallback (EC-018):\n * - Non-localized fields always read from `doc.values`.\n * - Localized fields read `doc.localized[locale]`; if absent, fall back to the\n * document's default locale, then to `doc.values` as a last resort.\n */\nexport function resolveField(\n collection: CollectionDef,\n doc: CmsDocument,\n fieldName: string,\n locale: Locale,\n config: LocaleConfig,\n): ResolvedField {\n if (!isFieldLocalized(collection, fieldName)) {\n return { value: doc.values[fieldName], sourceLocale: locale, fellBack: false }\n }\n\n const requested = doc.localized?.[locale]\n if (requested && fieldName in requested) {\n return { value: requested[fieldName], sourceLocale: locale, fellBack: false }\n }\n\n const fallbackLocale = documentDefaultLocale(doc, config)\n if (fallbackLocale !== locale) {\n const fallback = doc.localized?.[fallbackLocale]\n if (fallback && fieldName in fallback) {\n return { value: fallback[fieldName], sourceLocale: fallbackLocale, fellBack: true }\n }\n }\n\n // Last resort: a value stored on the shared bag (e.g. authored before the\n // field was localized). Reported as a fallback to the default locale.\n if (fieldName in doc.values) {\n return { value: doc.values[fieldName], sourceLocale: fallbackLocale, fellBack: true }\n }\n\n return { value: undefined, sourceLocale: fallbackLocale, fellBack: fallbackLocale !== locale }\n}\n\n/**\n * Resolve the full field-values view of a document for a locale, applying\n * default-locale fallback per field (EC-018). The returned bag is flat:\n * `{ [field]: value }`, suitable for rendering or relation resolution.\n */\nexport function resolveDocumentForLocale(\n collection: CollectionDef,\n doc: CmsDocument,\n locale: Locale,\n config: LocaleConfig,\n): FieldValues {\n const out: FieldValues = {}\n for (const field of collection.fields) {\n out[field.name] = resolveField(collection, doc, field.name, locale, config).value\n }\n return out\n}\n\n/**\n * Validate that requesting `locale` is well-formed against the project config\n * (EC-018): emits `unknown-locale` for unsupported locales. Resolution itself\n * never throws; this surfaces an explicit structured issue.\n */\nexport function validateLocale(\n config: LocaleConfig,\n locale: Locale,\n path: ReadonlyArray<string | number> = ['locale'],\n): CmsValidationIssue[] {\n if (isKnownLocale(config, locale)) return []\n return [\n cmsIssue({\n code: 'unknown-locale',\n message: `Locale \"${locale}\" is not in the configured locale set.`,\n path,\n meta: { locale, configured: config.locales },\n }),\n ]\n}\n","import { z } from 'zod'\nimport { localeSchema } from './documents'\nimport type { DocumentRef } from './documents'\nimport { cmsIssue } from './issues'\nimport type { CmsValidationIssue } from './issues'\n\n/**\n * A route record (EC-019, reshaped by EC-187). A path pattern may contain\n * dynamic segments written `:name` (e.g. `/blog/:slug`). A route maps a concrete\n * URL to a **render target = a collection + document** via its `document` ref\n * — `/` → `{ collection: 'page', id: 'home' }`, `/blog/:slug` →\n * `{ collection: 'post', id: ':slug' }`. The catch-all dispatches on the\n * resolved document's collection. There is no `templateId`/`pageId` anymore:\n * page content is a `page`-collection document, not a graph page.\n */\nexport const routeRecordSchema = z.object({\n id: z.string().min(1),\n /** Path pattern, leading slash, with optional `:param` segments. */\n pattern: z.string().min(1),\n /** Locale this route serves (EC-018). Omitted = locale-agnostic. */\n locale: localeSchema.optional(),\n /**\n * The document this route resolves to: a `page`-collection document (whose\n * `body` composition renders into a layout), or a content-collection document\n * (rendered by a dev route component). The `id` may be a `:param` placeholder\n * materialized from the matched URL (EC-166).\n */\n document: z\n .object({ collection: z.string().min(1), id: z.string().min(1) })\n .optional(),\n})\nexport type RouteRecord = z.infer<typeof routeRecordSchema>\n\n/** A redirect record (EC-019/020). */\nexport const redirectRecordSchema = z.object({\n id: z.string().min(1),\n from: z.string().min(1),\n to: z.string().min(1),\n /** 301 permanent (default) or 302 temporary. */\n permanent: z.boolean().default(true),\n})\nexport type RedirectRecord = z.infer<typeof redirectRecordSchema>\n\n/** Result of `resolveUrl` (EC-019). */\nexport type ResolveStatus = 'ok' | 'redirect' | 'notFound'\n\nexport interface ResolveResult {\n status: ResolveStatus\n /** The matched route, when status is `ok`. */\n route?: RouteRecord\n /** The document the URL resolves to, when known. */\n documentRef?: DocumentRef\n /** The terminal redirect target, when status is `redirect`. */\n redirectTarget?: string\n /** Extracted dynamic params, e.g. `{ slug: 'hello' }`. */\n dynamicParams: Record<string, string>\n /** True when resolution fell back to a default-locale route (EC-018). */\n fallback: boolean\n /** Whether the matched redirect is permanent (301) vs temporary (302). */\n permanent?: boolean\n}\n\ninterface CompiledRoute {\n route: RouteRecord\n segments: PatternSegment[]\n}\n\ntype PatternSegment =\n | { kind: 'static'; value: string }\n | { kind: 'param'; name: string }\n\n/** Split a path into non-empty segments, ignoring a trailing slash. */\nexport function splitPath(path: string): string[] {\n const [pathname] = path.split(/[?#]/, 1)\n return (pathname ?? '')\n .split('/')\n .filter((s) => s.length > 0)\n}\n\nfunction compilePattern(pattern: string): PatternSegment[] {\n return splitPath(pattern).map((seg) =>\n seg.startsWith(':')\n ? { kind: 'param', name: seg.slice(1) }\n : { kind: 'static', value: seg },\n )\n}\n\n/**\n * Match a concrete URL path against a compiled pattern. Returns extracted params\n * or `undefined` if it doesn't match. Segment counts must be equal.\n */\nfunction matchSegments(\n segments: PatternSegment[],\n urlSegments: string[],\n): Record<string, string> | undefined {\n if (segments.length !== urlSegments.length) return undefined\n const params: Record<string, string> = {}\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i]\n const value = urlSegments[i]\n if (seg === undefined || value === undefined) return undefined\n if (seg.kind === 'static') {\n if (seg.value !== value) return undefined\n } else {\n params[seg.name] = decodeURIComponent(value)\n }\n }\n return params\n}\n\n/**\n * A \"specificity key\": more static segments and fewer params win when two routes\n * could match. Used to choose deterministically and to detect *true* conflicts\n * (two patterns with identical specificity matching the same concrete URL).\n */\nfunction specificity(segments: PatternSegment[]): string {\n return segments.map((s) => (s.kind === 'static' ? 'S' : 'P')).join('')\n}\n\n/**\n * The router (EC-019/020). Compiles routes + redirects once, then answers\n * `resolveUrl`. Construction surfaces structural issues (route conflicts,\n * redirect loops) as structured issues — it never throws or loops.\n */\nexport interface Router {\n readonly issues: readonly CmsValidationIssue[]\n resolveUrl(url: string, locale?: string): ResolveResult\n /** Resolve a redirect chain from `from` to its terminus (EC-020). */\n followRedirects(from: string): RedirectResolution\n}\n\nexport interface RouterOptions {\n /** Default locale used for locale fallback during resolution (EC-018). */\n defaultLocale?: string\n}\n\nexport interface RedirectResolution {\n /** Final URL after following all hops. */\n target: string\n /** Ordered list of intermediate URLs visited (including `from` and `target`). */\n chain: string[]\n /** True if a loop was detected; `target` is then the loop entry point. */\n loop: boolean\n /** Whether every hop was permanent. */\n permanent: boolean\n}\n\nfunction normalizePath(path: string): string {\n const [pathname] = path.split(/[?#]/, 1)\n const segs = splitPath(pathname ?? '')\n return '/' + segs.join('/')\n}\n\n/** Build a router from route + redirect records. */\nexport function createRouter(\n routes: readonly RouteRecord[],\n redirects: readonly RedirectRecord[] = [],\n options: RouterOptions = {},\n): Router {\n const issues: CmsValidationIssue[] = []\n\n const compiled: CompiledRoute[] = routes.map((route) => ({\n route,\n segments: compilePattern(route.pattern),\n }))\n\n // --- Route conflict detection (EC-020) ---\n // Two routes conflict when, for the same locale, they would match the exact\n // same set of concrete URLs: identical specificity signature AND the static\n // segments line up at the same positions.\n const conflictKey = (c: CompiledRoute): string => {\n const locale = c.route.locale ?? '*'\n const sig = c.segments\n .map((s) => (s.kind === 'static' ? `s:${s.value}` : 'p'))\n .join('/')\n return `${locale}|${sig}`\n }\n const byKey = new Map<string, CompiledRoute>()\n for (const c of compiled) {\n const key = conflictKey(c)\n const existing = byKey.get(key)\n if (existing) {\n issues.push(\n cmsIssue({\n code: 'route-conflict',\n message: `Routes \"${existing.route.id}\" and \"${c.route.id}\" both match the same URLs (pattern \"${c.route.pattern}\").`,\n path: ['routes', c.route.id],\n meta: { conflictsWith: existing.route.id, pattern: c.route.pattern },\n }),\n )\n } else {\n byKey.set(key, c)\n }\n }\n\n // --- Redirect map + loop detection (EC-020) ---\n const redirectMap = new Map<string, RedirectRecord>()\n for (const r of redirects) {\n redirectMap.set(normalizePath(r.from), r)\n }\n\n const followRedirects = (from: string): RedirectResolution => {\n const chain: string[] = []\n const seen = new Set<string>()\n let current = normalizePath(from)\n let permanent = true\n chain.push(current)\n // Bounded by the number of redirects; the `seen` guard makes loops impossible.\n while (true) {\n const hop = redirectMap.get(current)\n if (!hop) {\n return { target: current, chain, loop: false, permanent }\n }\n if (!hop.permanent) permanent = false\n const next = normalizePath(hop.to)\n if (seen.has(next) || next === current) {\n chain.push(next)\n return { target: next, chain, loop: true, permanent }\n }\n seen.add(current)\n current = next\n chain.push(current)\n }\n }\n\n // Eagerly report redirect loops as structured issues (EC-020).\n const loopReported = new Set<string>()\n for (const r of redirects) {\n const res = followRedirects(r.from)\n if (res.loop && !loopReported.has(res.target)) {\n loopReported.add(res.target)\n issues.push(\n cmsIssue({\n code: 'redirect-loop',\n message: `Redirect chain starting at \"${r.from}\" loops (…${res.chain.slice(-3).join(' -> ')}).`,\n path: ['redirects', r.id],\n meta: { chain: res.chain },\n }),\n )\n }\n }\n\n const orderedMatches = (\n urlSegments: string[],\n locale: string | undefined,\n ): { compiled: CompiledRoute; params: Record<string, string> }[] => {\n const matches: { compiled: CompiledRoute; params: Record<string, string> }[] = []\n for (const c of compiled) {\n if (locale !== undefined && c.route.locale !== undefined && c.route.locale !== locale) {\n continue\n }\n const params = matchSegments(c.segments, urlSegments)\n if (params) matches.push({ compiled: c, params })\n }\n // Most specific first (fewest params, more static).\n matches.sort((a, b) => specificity(a.compiled.segments).localeCompare(specificity(b.compiled.segments)) * -1)\n return matches\n }\n\n const resolveUrl = (url: string, locale?: string): ResolveResult => {\n const path = normalizePath(url)\n\n // 1. Redirects take precedence (resolve to terminus).\n if (redirectMap.has(path)) {\n const res = followRedirects(path)\n return {\n status: 'redirect',\n redirectTarget: res.target,\n permanent: res.permanent,\n dynamicParams: {},\n fallback: false,\n }\n }\n\n const urlSegments = splitPath(path)\n\n // 2. Match routes for the requested locale.\n let fallback = false\n let matches = orderedMatches(urlSegments, locale)\n\n // 3. Locale fallback to the default locale (EC-018).\n if (matches.length === 0 && locale && options.defaultLocale && locale !== options.defaultLocale) {\n const fallbackMatches = orderedMatches(urlSegments, options.defaultLocale)\n if (fallbackMatches.length > 0) {\n matches = fallbackMatches\n fallback = true\n }\n }\n // 3b. As a last resort try locale-agnostic routes (no locale on requested pass).\n if (matches.length === 0 && locale === undefined) {\n matches = orderedMatches(urlSegments, undefined)\n }\n\n const best = matches[0]\n if (!best) {\n return { status: 'notFound', dynamicParams: {}, fallback }\n }\n\n const route = best.compiled.route\n return {\n status: 'ok',\n route,\n ...(route.document ? { documentRef: route.document } : {}),\n dynamicParams: best.params,\n fallback,\n }\n }\n\n return { issues, resolveUrl, followRedirects }\n}\n","import type { CollectionDef } from './collections'\nimport type { CmsDocument } from './documents'\nimport type { RelationFieldDef } from './fields'\nimport type { RouteRecord } from './routes'\nimport { splitPath } from './routes'\n\n/**\n * Page hierarchy (EC-218, vision §3.4 / AD-6).\n *\n * A routable collection models nesting with a **`parent` self-relation** + a\n * local **`slug`** — never a stored full path. The full nested URL is *composed*\n * by walking the parent chain (the Payload nested-docs / Sanity page-tree\n * pattern), so moving or renaming a parent re-derives every descendant's URL\n * with no denormalized bulk rewrite. Every walk here is cycle-safe by\n * construction: a parent chain that loops stops at the repeat and is surfaced as\n * a structured issue, never an infinite loop or a crash.\n *\n * The slug is read non-localized (one segment per document, per the EC-218\n * decision); locale-specific routes are still expressed by the route record's\n * own `locale`.\n */\n\nexport interface HierarchyConfig {\n /** Self-relation field naming a document's parent (default `parent`). */\n parentField?: string\n /** Text field holding the local URL segment (default `slug`). */\n slugField?: string\n}\n\nconst DEFAULT_PARENT_FIELD = 'parent'\nconst DEFAULT_SLUG_FIELD = 'slug'\n\n/** Resolve a {@link HierarchyConfig} to its concrete field names. */\nexport function hierarchyFields(config: HierarchyConfig = {}): {\n parentField: string\n slugField: string\n} {\n return {\n parentField: config.parentField ?? DEFAULT_PARENT_FIELD,\n slugField: config.slugField ?? DEFAULT_SLUG_FIELD,\n }\n}\n\n/**\n * The self-relation field that names a document's parent, if this collection\n * declares one: a single-valued `relation` field, named per the config, whose\n * target is the collection itself.\n */\nexport function parentRelationField(\n collection: CollectionDef,\n config: HierarchyConfig = {},\n): RelationFieldDef | undefined {\n const { parentField } = hierarchyFields(config)\n const field = collection.fields.find((f) => f.name === parentField)\n if (\n field &&\n field.type === 'relation' &&\n field.target === collection.id &&\n field.cardinality === 'one'\n ) {\n return field\n }\n return undefined\n}\n\n/** Does this collection model a parent/child hierarchy (a `parent` self-relation)? */\nexport function isHierarchical(collection: CollectionDef, config: HierarchyConfig = {}): boolean {\n return parentRelationField(collection, config) !== undefined\n}\n\n/** The parent document id from a `one` self-relation value (a `DocumentRef` or bare id). */\nfunction readParentId(doc: CmsDocument, parentField: string): string | undefined {\n const value = doc.values[parentField]\n if (value == null) return undefined\n if (typeof value === 'string') return value.length > 0 ? value : undefined\n if (typeof value === 'object' && 'id' in value) {\n const id = (value as { id?: unknown }).id\n return typeof id === 'string' && id.length > 0 ? id : undefined\n }\n return undefined\n}\n\n/** The local slug segment of a document, or undefined when unset/empty. */\nfunction readSlug(doc: CmsDocument, slugField: string): string | undefined {\n const value = doc.values[slugField]\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n\nexport interface ComposedPath {\n /** Slug segments from root to leaf. */\n segments: string[]\n /** True iff the path is clean: no cycle, no missing slug, no dangling parent. */\n ok: boolean\n /** The parent chain loops. */\n cycle: boolean\n /** A document in the chain (this one or an ancestor) has no slug. */\n missingSlug: boolean\n /** A parent ref pointed at a document that is not present. */\n danglingParent: boolean\n}\n\n/**\n * Compose a document's full path segments by walking its parent chain from the\n * leaf up, then ordering root → leaf. Cycle-safe: revisiting a document stops\n * the walk and flags `cycle`. `getById` looks documents up *within the same\n * collection* (a self-relation never crosses collections).\n */\nexport function composePath(\n doc: CmsDocument,\n getById: (id: string) => CmsDocument | undefined,\n config: HierarchyConfig = {},\n): ComposedPath {\n const { parentField, slugField } = hierarchyFields(config)\n const segments: string[] = []\n const seen = new Set<string>([doc.id])\n let cycle = false\n let missingSlug = false\n let danglingParent = false\n let current: CmsDocument | undefined = doc\n while (current) {\n const slug = readSlug(current, slugField)\n if (slug === undefined) missingSlug = true\n else segments.unshift(slug)\n const parentId = readParentId(current, parentField)\n if (parentId === undefined) break\n const parent = getById(parentId)\n if (!parent) {\n danglingParent = true\n break\n }\n if (seen.has(parent.id)) {\n cycle = true\n break\n }\n seen.add(parent.id)\n current = parent\n }\n return { segments, ok: !cycle && !missingSlug && !danglingParent, cycle, missingSlug, danglingParent }\n}\n\n/** Does a document's parent chain loop? (cycle-safe; uses {@link composePath}). */\nexport function hasParentCycle(\n doc: CmsDocument,\n getById: (id: string) => CmsDocument | undefined,\n config: HierarchyConfig = {},\n): boolean {\n return composePath(doc, getById, config).cycle\n}\n\nexport interface HierarchyRow {\n doc: CmsDocument\n /** Nesting depth: 0 for roots, 1 for their children, … */\n depth: number\n /** Whether this document has at least one child. */\n hasChildren: boolean\n}\n\n/**\n * Order documents as a depth-first hierarchy (parents immediately before their\n * children, siblings in input order), annotating each with its depth. Roots are\n * documents with no parent, or whose parent is absent (orphans surface at the\n * root). Cycle-safe: documents trapped in a parent cycle are never lost — they\n * are appended at depth 0 rather than recursed into. The read-side of the\n * hierarchical list view (EC-218).\n */\nexport function orderHierarchically(\n docs: readonly CmsDocument[],\n config: HierarchyConfig = {},\n): HierarchyRow[] {\n const { parentField } = hierarchyFields(config)\n const byId = new Map(docs.map((d) => [d.id, d]))\n // Bucket each document under its effective parent key (null = a root).\n const children = new Map<string | null, CmsDocument[]>()\n for (const doc of docs) {\n const parentId = readParentId(doc, parentField)\n const key = parentId != null && parentId !== doc.id && byId.has(parentId) ? parentId : null\n const bucket = children.get(key)\n if (bucket) bucket.push(doc)\n else children.set(key, [doc])\n }\n const rows: HierarchyRow[] = []\n const visited = new Set<string>()\n const walk = (parentKey: string | null, depth: number): void => {\n for (const doc of children.get(parentKey) ?? []) {\n if (visited.has(doc.id)) continue\n visited.add(doc.id)\n rows.push({ doc, depth, hasChildren: (children.get(doc.id)?.length ?? 0) > 0 })\n walk(doc.id, depth + 1)\n }\n }\n walk(null, 0)\n // Any document not reached from a root is trapped in a cycle — surface it at\n // the root so the list never silently drops a document. It may still have\n // (cycle-trapped) children, so report hasChildren the same way the main walk does.\n for (const doc of docs) {\n if (!visited.has(doc.id)) {\n visited.add(doc.id)\n rows.push({ doc, depth: 0, hasChildren: (children.get(doc.id)?.length ?? 0) > 0 })\n }\n }\n return rows\n}\n\n/**\n * The ids of every descendant of `rootId` (children, grandchildren, …). Used to\n * keep a `parent` picker from offering a document its own subtree — which would\n * create a cycle. Excludes `rootId` itself; cycle-safe.\n */\nexport function descendantIds(\n rootId: string,\n docs: readonly CmsDocument[],\n config: HierarchyConfig = {},\n): Set<string> {\n const { parentField } = hierarchyFields(config)\n const children = new Map<string, CmsDocument[]>()\n for (const doc of docs) {\n const parentId = readParentId(doc, parentField)\n if (parentId == null) continue\n const bucket = children.get(parentId)\n if (bucket) bucket.push(doc)\n else children.set(parentId, [doc])\n }\n const out = new Set<string>()\n const stack: string[] = [rootId]\n while (stack.length > 0) {\n const id = stack.pop()!\n for (const child of children.get(id) ?? []) {\n if (child.id !== rootId && !out.has(child.id)) {\n out.add(child.id)\n stack.push(child.id)\n }\n }\n }\n return out\n}\n\n/**\n * Is this route a hierarchy mount? — its pattern ends with a catch-all param\n * segment (`:name*`), declaring \"this collection's documents are served by their\n * composed nested paths under this prefix\" (EC-218). The host pulls these out of\n * the router and resolves them per-request with {@link resolveByPath}, so the\n * URL→document mapping stays perspective-aware (draft vs published) and the path\n * stays derived, never stored.\n */\nexport function isHierarchyTemplate(route: RouteRecord): boolean {\n if (!route.document) return false\n const segments = splitPath(route.pattern)\n const last = segments[segments.length - 1]\n return last !== undefined && last.startsWith(':') && last.endsWith('*')\n}\n\nexport interface HierarchyMount {\n /** The collection whose documents are served by composed path. */\n collection: string\n /** Static URL segments before the catch-all (empty = mounted at the root). */\n prefix: string[]\n /** Locale this mount serves, if the template declared one. */\n locale?: string\n}\n\n/**\n * Parse a hierarchy mount from a catch-all template route (EC-218), or undefined\n * when the route is not a valid mount (not a catch-all, or its prefix contains a\n * dynamic segment, which a composed-path mount does not support).\n */\nexport function hierarchyMount(route: RouteRecord): HierarchyMount | undefined {\n if (!isHierarchyTemplate(route) || !route.document) return undefined\n const prefix = splitPath(route.pattern).slice(0, -1)\n if (prefix.some((segment) => segment.startsWith(':'))) return undefined\n return {\n collection: route.document.collection,\n prefix,\n ...(route.locale ? { locale: route.locale } : {}),\n }\n}\n\n/**\n * Resolve a path (its slug segments, prefix already stripped) to the one document\n * whose composed nested path matches (EC-218). The caller supplies the documents\n * already selected for the active perspective (draft/published), so resolution is\n * perspective-aware. Documents with a broken or cyclic chain never match.\n * Deterministic on the rare duplicate composed path: the lowest id wins (the same\n * tie-break the single-slug fallback uses).\n */\nexport function resolveByPath(\n segments: readonly string[],\n docs: readonly CmsDocument[],\n config: HierarchyConfig = {},\n): CmsDocument | undefined {\n if (segments.length === 0) return undefined\n const byId = new Map(docs.map((d) => [d.id, d]))\n const getById = (id: string) => byId.get(id)\n const target = segments.join('/')\n let match: CmsDocument | undefined\n for (const doc of docs) {\n const composed = composePath(doc, getById, config)\n if (!composed.ok) continue\n if (composed.segments.join('/') === target && (!match || doc.id < match.id)) {\n match = doc\n }\n }\n return match\n}\n","import type { CollectionRegistry } from './collections'\nimport type { CollectionDef } from './collections'\nimport type {\n AssetFieldDef,\n BlocksFieldDef,\n FieldDef,\n RelationFieldDef,\n RichTextFieldDef,\n} from './fields'\nimport type { CmsDocument, DocumentRef, FieldValues } from './documents'\nimport { documentKey } from './documents'\nimport type { LocaleConfig } from './localization'\nimport { isFieldLocalized, resolveField } from './localization'\nimport { hasParentCycle, parentRelationField } from './hierarchy'\nimport { cmsIssue } from './issues'\nimport type { CmsPath, CmsValidationIssue } from './issues'\n\n/** Index of documents by identity, used to validate relation/asset targets. */\nexport interface DocumentStore {\n has(ref: DocumentRef): boolean\n get(ref: DocumentRef): CmsDocument | undefined\n}\n\n/** Build a `DocumentStore` from a flat list of documents. */\nexport function createDocumentStore(docs: readonly CmsDocument[]): DocumentStore & {\n list(): CmsDocument[]\n issues: readonly CmsValidationIssue[]\n} {\n const byKey = new Map<string, CmsDocument>()\n const issues: CmsValidationIssue[] = []\n for (const doc of docs) {\n const key = documentKey(doc)\n if (byKey.has(key)) {\n issues.push(\n cmsIssue({\n code: 'duplicate-document',\n message: `Duplicate document \"${doc.id}\" in collection \"${doc.collection}\".`,\n path: ['documents', key],\n collectionId: doc.collection,\n documentId: doc.id,\n }),\n )\n continue\n }\n byKey.set(key, doc)\n }\n return {\n issues,\n has: (ref) => byKey.has(documentKey(ref)),\n get: (ref) => byKey.get(documentKey(ref)),\n list: () => [...byKey.values()],\n }\n}\n\nfunction isEmpty(value: unknown): boolean {\n if (value === undefined || value === null) return true\n if (typeof value === 'string') return value.length === 0\n if (Array.isArray(value)) return value.length === 0\n // EC-253: a plain object with no keys is empty — so a required `object` field\n // whose value is `{}` is flagged missing. Object-shaped values that DO carry\n // keys (relation refs `{collection,id}`, rich-text envelopes) are never empty.\n if (isPlainObject(value)) return Object.keys(value).length === 0\n return false\n}\n\n/** A non-null, non-array object — the shape an `object` field value takes (EC-253). */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Whether a value must still be validated even though {@link isEmpty} is true\n * (EC-253). A PRESENT plain object of an `object` field is validated even with no\n * keys, so its required subfields surface (`{}` is not the same as absent); every\n * other empty/absent value has nothing to validate — `required` owns presence.\n */\nfunction isPresentObjectValue(field: FieldDef, value: unknown): boolean {\n return field.type === 'object' && isPlainObject(value)\n}\n\nfunction coerceRef(value: unknown): DocumentRef | undefined {\n if (\n typeof value === 'object' &&\n value !== null &&\n 'collection' in value &&\n 'id' in value &&\n typeof (value as { collection: unknown }).collection === 'string' &&\n typeof (value as { id: unknown }).id === 'string'\n ) {\n const v = value as { collection: string; id: string }\n return { collection: v.collection, id: v.id }\n }\n return undefined\n}\n\ninterface FieldCtx {\n collection: CollectionDef\n field: FieldDef\n value: unknown\n path: ReadonlyArray<string | number>\n registry: CollectionRegistry\n store: DocumentStore | undefined\n documentId: string\n /**\n * Whether the document being validated is published (EC-173/EC-224). Sourced\n * from the version POINTER via the injected {@link ValidateDocumentOptions.isPublished}\n * predicate — never a flat `state` flag.\n */\n isSourcePublished: boolean\n /** Is a referenced target published? (the same pointer predicate). */\n isPublished: (ref: DocumentRef) => boolean\n /** Asset-existence oracle (assets live in their own repository, not the doc store). */\n assetExists: ((id: string) => boolean) | undefined\n}\n\nfunction validateScalarType(ctx: FieldCtx, issues: CmsValidationIssue[]): void {\n const { field, value, path, collection, documentId } = ctx\n const bad = (detail: string) =>\n issues.push(\n cmsIssue({\n code: 'invalid-field-value',\n message: `Field \"${field.name}\" ${detail}.`,\n path,\n collectionId: collection.id,\n documentId,\n meta: { field: field.name, type: field.type },\n }),\n )\n\n switch (field.type) {\n case 'text':\n if (typeof value !== 'string') bad('expects a string')\n break\n case 'richText':\n // A rich-text value is either a plain string (CMS markdown/HTML) or the\n // structured @elytracms/rich-text storage envelope (an object) carrying\n // formatting + composition embeds (EC-159/EC-189). Mirrors the prop-side\n // `checkScalarType`; deep validation is delegated (the renderer parse guard\n // + the injected rich-text-embed validator).\n if (typeof value !== 'string' && !(typeof value === 'object' && value !== null)) {\n bad('expects rich-text content (a string or a rich-text value)')\n }\n break\n case 'number':\n if (typeof value !== 'number' || Number.isNaN(value)) bad('expects a number')\n break\n case 'boolean':\n if (typeof value !== 'boolean') bad('expects a boolean')\n break\n case 'date':\n // Accept ISO date strings or epoch numbers; reject anything unparseable.\n if (typeof value === 'string') {\n if (Number.isNaN(Date.parse(value))) bad('expects a valid date string')\n } else if (typeof value !== 'number') {\n bad('expects a date (ISO string or epoch number)')\n }\n break\n case 'select': {\n const allowed = new Set(field.options.map((o) => o.value))\n const values = field.multiple ? (Array.isArray(value) ? value : [value]) : [value]\n for (const v of values) {\n if (typeof v !== 'string' || !allowed.has(v)) {\n bad(`has value \"${String(v)}\" not among its options`)\n }\n }\n break\n }\n case 'object':\n // EC-253: only the TOP-LEVEL shape is checked here (an array of objects for\n // `many`, a single object for `one`); recursion into the subfields lives in\n // `validateObject`, which skips malformed items this already reported.\n if (field.cardinality === 'many') {\n if (!Array.isArray(value) || value.some((item) => !isPlainObject(item))) {\n bad('expects a list of objects')\n }\n } else if (!isPlainObject(value)) {\n bad('expects an object')\n }\n break\n case 'relation':\n case 'asset':\n case 'blocks':\n // Validated structurally elsewhere (targets / composition), not as scalars.\n break\n default: {\n // Exhaustiveness: a new field type must add a case above (EC-253).\n const _exhaustive: never = field\n void _exhaustive\n }\n }\n}\n\n/**\n * Validate a `blocks` composition field value via the injected callback (EC-188).\n * The composition tree is validated against the field's `allow` vocabulary + the\n * component registry by the studio-supplied `validateComposition`; each finding is\n * wrapped into a field-keyed issue so it surfaces inline like any other field\n * error. A no-op when the field is not a `blocks` field or no validator is wired\n * (e.g. headless contexts without a registry).\n */\nfunction validateBlocks(\n ctx: FieldCtx,\n issues: CmsValidationIssue[],\n validateComposition: ValidateDocumentOptions['validateComposition'],\n): void {\n if (ctx.field.type !== 'blocks' || !validateComposition) return\n const { field, value, path, collection, documentId } = ctx\n for (const finding of validateComposition(value, field)) {\n issues.push(\n cmsIssue({\n code: 'invalid-field-value',\n severity: finding.severity ?? 'error',\n message: `Field \"${field.name}\": ${finding.message}`,\n path,\n collectionId: collection.id,\n documentId,\n meta: {\n field: field.name,\n type: 'blocks',\n ...(finding.nodePath ? { nodePath: finding.nodePath } : {}),\n },\n }),\n )\n }\n}\n\n/**\n * Validate the composition embeds inside a `richText` field value via the injected\n * callback (EC-189). A rich-text value may carry `componentEmbed` nodes, each\n * holding a single `ComponentNode` constrained by the field's `allow` vocabulary —\n * the SAME leash a `blocks` field uses, applied to prose embeds. The studio-supplied\n * `validateRichTextEmbeds` walks the embeds and validates each via\n * `validateCompositionValue`; each finding is wrapped into a field-keyed issue,\n * carrying the rich-text node path. A no-op when the field is not `richText` or no\n * validator is wired (e.g. headless contexts without a registry).\n */\nfunction validateRichTextEmbeds(\n ctx: FieldCtx,\n issues: CmsValidationIssue[],\n validateRichText: ValidateDocumentOptions['validateRichTextEmbeds'],\n): void {\n if (ctx.field.type !== 'richText' || !validateRichText) return\n const { field, value, path, collection, documentId } = ctx\n for (const finding of validateRichText(value, field)) {\n issues.push(\n cmsIssue({\n code: 'invalid-field-value',\n severity: finding.severity ?? 'error',\n message: `Field \"${field.name}\": ${finding.message}`,\n path,\n collectionId: collection.id,\n documentId,\n meta: {\n field: field.name,\n type: 'richText',\n ...(finding.nodePath ? { nodePath: finding.nodePath } : {}),\n },\n }),\n )\n }\n}\n\nfunction validateConstraints(ctx: FieldCtx, issues: CmsValidationIssue[]): void {\n const { field, value, path, collection, documentId } = ctx\n const rules = field.validation\n if (!rules) return\n const push = (detail: string) =>\n issues.push(\n cmsIssue({\n code: 'invalid-field-value',\n message: `Field \"${field.name}\" ${detail}.`,\n path,\n collectionId: collection.id,\n documentId,\n meta: { field: field.name },\n }),\n )\n\n if (typeof value === 'string') {\n if (rules.min !== undefined && value.length < rules.min) push(`is shorter than min length ${rules.min}`)\n if (rules.max !== undefined && value.length > rules.max) push(`is longer than max length ${rules.max}`)\n if (rules.pattern !== undefined) {\n let re: RegExp | undefined\n try {\n re = new RegExp(rules.pattern)\n } catch {\n re = undefined\n }\n if (re && !re.test(value)) push(`does not match pattern ${rules.pattern}`)\n }\n } else if (typeof value === 'number') {\n if (rules.min !== undefined && value < rules.min) push(`is less than min ${rules.min}`)\n if (rules.max !== undefined && value > rules.max) push(`is greater than max ${rules.max}`)\n } else if (Array.isArray(value)) {\n if (rules.min !== undefined && value.length < rules.min) push(`has fewer than ${rules.min} items`)\n if (rules.max !== undefined && value.length > rules.max) push(`has more than ${rules.max} items`)\n }\n}\n\nfunction validateRelation(ctx: FieldCtx, issues: CmsValidationIssue[]): void {\n const { field, value, path, collection, registry, store, documentId } = ctx\n if (field.type !== 'relation') return\n\n if (!registry.has(field.target)) {\n issues.push(\n cmsIssue({\n code: 'unknown-relation-target',\n message: `Relation field \"${field.name}\" targets unknown collection \"${field.target}\".`,\n path,\n collectionId: collection.id,\n documentId,\n meta: { field: field.name, target: field.target },\n }),\n )\n return\n }\n\n const refs = Array.isArray(value) ? value : value === undefined || value === null ? [] : [value]\n\n if (field.cardinality === 'one' && Array.isArray(value) && value.length > 1) {\n issues.push(\n cmsIssue({\n code: 'cardinality-violation',\n message: `Relation field \"${field.name}\" is single-valued but has ${value.length} targets.`,\n path,\n collectionId: collection.id,\n documentId,\n meta: { field: field.name, cardinality: 'one' },\n }),\n )\n }\n\n refs.forEach((raw, i) => {\n const ref = coerceRef(raw)\n if (!ref) {\n issues.push(\n cmsIssue({\n code: 'invalid-field-value',\n message: `Relation field \"${field.name}\" holds a value that is not a document reference.`,\n path: [...path, i],\n collectionId: collection.id,\n documentId,\n meta: { field: field.name },\n }),\n )\n return\n }\n if (ref.collection !== field.target) {\n issues.push(\n cmsIssue({\n code: 'unknown-relation-target',\n message: `Relation field \"${field.name}\" points at collection \"${ref.collection}\" but targets \"${field.target}\".`,\n path: [...path, i],\n collectionId: collection.id,\n documentId,\n meta: { field: field.name, target: field.target, got: ref.collection },\n }),\n )\n return\n }\n if (store) {\n const target = store.get(ref)\n if (!target) {\n issues.push(\n cmsIssue({\n code: 'unknown-relation-target',\n message: `Relation field \"${field.name}\" references missing document \"${ref.id}\" in \"${ref.collection}\".`,\n path: [...path, i],\n collectionId: collection.id,\n documentId,\n meta: { field: field.name, target: ref.collection, id: ref.id },\n }),\n )\n } else if (ctx.isSourcePublished && !ctx.isPublished(ref)) {\n // EC-173 weak-reference aftermath: the source is published but the\n // target is not, so published delivery serves the declared fallback\n // for this reference. Explicit and visible — but a warning, never an\n // error: weak references must not block saving or re-publishing the\n // source. Re-publishing the target clears it.\n issues.push(\n cmsIssue({\n code: 'unpublished-relation-target',\n severity: 'warning',\n message: `Relation field \"${field.name}\" references unpublished document \"${ref.id}\" in \"${ref.collection}\" — the published site shows a fallback there.`,\n path: [...path, i],\n collectionId: collection.id,\n documentId,\n meta: { field: field.name, target: ref.collection, id: ref.id },\n }),\n )\n }\n }\n })\n}\n\nfunction validateAsset(ctx: FieldCtx, issues: CmsValidationIssue[]): void {\n const { field, value, path, collection, registry, store, documentId } = ctx\n if (field.type !== 'asset') return\n\n const assetCollections = registry.assetCollections()\n if (assetCollections.length === 0) {\n issues.push(\n cmsIssue({\n code: 'invalid-field-config',\n message: `Asset field \"${field.name}\" requires an asset collection, but none is registered.`,\n path,\n collectionId: collection.id,\n documentId,\n meta: { field: field.name },\n }),\n )\n return\n }\n\n const ids = Array.isArray(value) ? value : value === undefined || value === null ? [] : [value]\n if (field.cardinality === 'one' && Array.isArray(value) && value.length > 1) {\n issues.push(\n cmsIssue({\n code: 'cardinality-violation',\n message: `Asset field \"${field.name}\" is single-valued but has ${value.length} targets.`,\n path,\n collectionId: collection.id,\n documentId,\n meta: { field: field.name, cardinality: 'one' },\n }),\n )\n }\n\n ids.forEach((raw, i) => {\n // An asset value is the id of a document in some asset collection.\n if (typeof raw !== 'string') {\n issues.push(\n cmsIssue({\n code: 'invalid-field-value',\n message: `Asset field \"${field.name}\" expects an asset id string.`,\n path: [...path, i],\n collectionId: collection.id,\n documentId,\n meta: { field: field.name },\n }),\n )\n return\n }\n // Asset existence is checked against the asset library when the caller\n // supplies an oracle (assets live in their own repository, not as CMS\n // documents — EC-212 follow-up); otherwise it falls back to the document\n // store (fixtures that model assets as documents). With neither, existence\n // is simply not checked (`undefined` → skip), never wrongly flagged.\n const exists = ctx.assetExists\n ? ctx.assetExists(raw)\n : store\n ? assetCollections.some((c) => store.has({ collection: c.id, id: raw }))\n : undefined\n if (exists === false) {\n issues.push(\n cmsIssue({\n code: 'unknown-asset',\n message: `Asset field \"${field.name}\" references unknown asset \"${raw}\".`,\n path: [...path, i],\n collectionId: collection.id,\n documentId,\n meta: { field: field.name, asset: raw },\n }),\n )\n }\n })\n}\n\n/** The injected composition/rich-text validators, threaded through the recursion. */\ninterface FieldValidators {\n validateComposition: ValidateDocumentOptions['validateComposition']\n validateRichText: ValidateDocumentOptions['validateRichTextEmbeds']\n}\n\n/**\n * Validate an `object` / repeater field value (EC-253) by recursing into each\n * item's subfields. `cardinality: 'many'` is an array of objects (each item keyed\n * by index in the path); `'one'` is a single object. Malformed items (already\n * reported by {@link validateScalarType}) are skipped. The same {@link FieldCtx}\n * (registry/store/asset oracle) is threaded so nested relation/asset subfields get\n * the same target-existence checks they would at the top level.\n */\nfunction validateObject(\n ctx: FieldCtx,\n issues: CmsValidationIssue[],\n v: FieldValidators,\n): void {\n const { field } = ctx\n if (field.type !== 'object') return\n const items =\n field.cardinality === 'many' ? (Array.isArray(ctx.value) ? ctx.value : []) : [ctx.value]\n items.forEach((item, index) => {\n if (!isPlainObject(item)) return\n const itemPath = field.cardinality === 'many' ? [...ctx.path, index] : ctx.path\n for (const sub of field.fields) {\n const subValue = item[sub.name]\n const subPath = [...itemPath, sub.name]\n if (isEmpty(subValue)) {\n if (sub.validation?.required) {\n issues.push(\n cmsIssue({\n code: 'missing-required-field',\n message: `Required field \"${sub.name}\" is missing.`,\n path: subPath,\n collectionId: ctx.collection.id,\n documentId: ctx.documentId,\n meta: { field: sub.name },\n }),\n )\n continue\n }\n // EC-253 (C1): an optional but PRESENT nested object still recurses so its\n // own required subfields surface; any other empty/absent value is skipped.\n if (!isPresentObjectValue(sub, subValue)) continue\n }\n validateFieldValue({ ...ctx, field: sub, value: subValue, path: subPath }, issues, v)\n }\n })\n}\n\n/**\n * Run every per-field validator for one field/value/path. The single dispatch\n * point shared by the document loop and the {@link validateObject} recursion, so\n * a subfield is validated exactly as a top-level field would be (EC-253).\n */\nfunction validateFieldValue(\n ctx: FieldCtx,\n issues: CmsValidationIssue[],\n v: FieldValidators,\n): void {\n validateScalarType(ctx, issues)\n validateConstraints(ctx, issues)\n validateRelation(ctx, issues)\n validateAsset(ctx, issues)\n validateBlocks(ctx, issues, v.validateComposition)\n validateRichTextEmbeds(ctx, issues, v.validateRichText)\n validateObject(ctx, issues, v)\n}\n\n/**\n * A composition-validation finding, returned by the injected `validateComposition`\n * callback (EC-188). cms-core stays free of `@elytracms/project-graph`: the studio\n * wires the callback to `validateCompositionValue` + the component registry and\n * returns these plain findings, which cms-core wraps into `CmsValidationIssue`s\n * keyed on the field (so they surface inline like every other field issue).\n */\nexport interface CompositionIssue {\n message: string\n severity?: 'error' | 'warning'\n /** Slash-joined node path within the composition tree, for richer surfacing. */\n nodePath?: string\n}\n\nexport interface ValidateDocumentOptions {\n /** When provided, relation/asset targets are checked for existence (EC-017). */\n store?: DocumentStore\n /** When provided, localized required fields are checked across all locales (EC-018). */\n localeConfig?: LocaleConfig\n /**\n * When provided, `blocks` composition field values are validated (EC-188).\n * Injected so cms-core does not depend on `@elytracms/project-graph`; the studio\n * binds it to `validateCompositionValue(value, { allow, components })`.\n */\n validateComposition?: (value: unknown, field: BlocksFieldDef) => readonly CompositionIssue[]\n /**\n * When provided, the composition embeds inside a `richText` field value are\n * validated (EC-189). Injected so cms-core depends on neither\n * `@elytracms/project-graph` nor `@elytracms/rich-text`; the studio binds it to walk\n * the value's `componentEmbed` nodes and validate each embedded `ComponentNode`\n * via `validateCompositionValue(node, { allow, components })` against the field's\n * `allow` vocabulary. Findings carry the rich-text node path.\n */\n validateRichTextEmbeds?: (\n value: unknown,\n field: RichTextFieldDef,\n ) => readonly CompositionIssue[]\n /**\n * Published-ness oracle for the EC-173 weak-reference warning (EC-224): does a\n * given document ref serve the published site? Sourced from the version\n * pointer by the caller (the studio passes `cms.isPublished`). Absent → treated\n * as \"nothing is published\", so the warning simply does not fire — the flat\n * `state` flag is never consulted.\n */\n isPublished?: (ref: DocumentRef) => boolean\n /**\n * Asset-existence oracle (EC-212 follow-up): assets live in their own\n * repository, not as CMS documents, so the studio passes a predicate over the\n * real asset library. When provided, it is the source of truth for asset-field\n * existence; otherwise existence falls back to the document `store` (fixtures\n * that model assets as documents). With neither, asset existence is not checked.\n */\n assetExists?: (id: string) => boolean\n}\n\n/**\n * Validate a document against its collection (EC-016/017/018). Returns structured\n * issues; never throws. Checks unknown collection, missing required fields,\n * scalar type correctness, declared constraints, relation targets, asset\n * references, and required localized values across configured locales.\n */\nexport function validateDocument(\n registry: CollectionRegistry,\n doc: CmsDocument,\n options: ValidateDocumentOptions = {},\n): CmsValidationIssue[] {\n const issues: CmsValidationIssue[] = []\n const collection = registry.get(doc.collection)\n const basePath: ReadonlyArray<string | number> = ['documents', documentKey(doc)]\n\n if (!collection) {\n issues.push(\n cmsIssue({\n code: 'unknown-collection',\n message: `Document \"${doc.id}\" references unknown collection \"${doc.collection}\".`,\n path: basePath,\n documentId: doc.id,\n meta: { collection: doc.collection },\n }),\n )\n return issues\n }\n\n const { store, localeConfig, validateComposition } = options\n const validateRichText = options.validateRichTextEmbeds\n // EC-224: published-ness is the version pointer, supplied by the caller. With\n // no predicate, nothing is treated as published (the EC-173 warning is inert).\n const isPublished = options.isPublished ?? (() => false)\n const isSourcePublished = isPublished({ collection: doc.collection, id: doc.id })\n\n for (const field of collection.fields) {\n const fieldPath = [...basePath, 'values', field.name]\n const localized = isFieldLocalized(collection, field.name)\n\n // Determine the locales over which we validate this field's value.\n const locales =\n localized && localeConfig ? localeConfig.locales : [localeConfig?.default ?? '*']\n\n const defaultLocale = localeConfig\n ? doc.defaultLocale ?? localeConfig.default\n : undefined\n\n for (const locale of locales) {\n // The fallback-resolved value (what would render) is used for type/constraint\n // checks; the *raw* per-locale value drives the localized-required check so we\n // can distinguish \"genuinely missing\" from \"satisfied via default-locale fallback\".\n const resolved = localized\n ? localeConfig\n ? resolveField(collection, doc, field.name, locale, localeConfig).value\n : doc.localized?.[locale]?.[field.name]\n : doc.values[field.name]\n const rawLocaleValue = localized ? doc.localized?.[locale]?.[field.name] : resolved\n\n const path = localized ? [...basePath, 'localized', locale, field.name] : fieldPath\n\n // Required check.\n if (field.validation?.required) {\n if (!localized) {\n if (isEmpty(resolved)) {\n issues.push(\n cmsIssue({\n code: 'missing-required-field',\n message: `Required field \"${field.name}\" is missing.`,\n path,\n collectionId: collection.id,\n documentId: doc.id,\n meta: { field: field.name },\n }),\n )\n continue\n }\n } else {\n const isDefault = locale === defaultLocale\n if (isDefault && isEmpty(rawLocaleValue)) {\n // A required localized field MUST have a value in the default locale —\n // it is the fallback source for every other locale. Missing here is an\n // error (no fallback can rescue it).\n issues.push(\n cmsIssue({\n code: 'missing-localized-value',\n message: `Required localized field \"${field.name}\" is missing for the default locale \"${locale}\".`,\n path,\n collectionId: collection.id,\n documentId: doc.id,\n meta: { field: field.name, locale },\n }),\n )\n } else if (!isDefault && isEmpty(rawLocaleValue) && isEmpty(resolved)) {\n // Non-default locale missing AND no fallback value available.\n issues.push(\n cmsIssue({\n code: 'missing-localized-value',\n severity: 'warning',\n message: `Localized field \"${field.name}\" has no value for locale \"${locale}\" and no fallback.`,\n path,\n collectionId: collection.id,\n documentId: doc.id,\n meta: { field: field.name, locale },\n }),\n )\n }\n if (isEmpty(resolved)) continue\n }\n }\n if (isEmpty(resolved) && !isPresentObjectValue(field, resolved)) continue\n\n const value = resolved\n const ctx: FieldCtx = {\n collection,\n field,\n value,\n path,\n registry,\n store,\n documentId: doc.id,\n isSourcePublished,\n isPublished,\n assetExists: options.assetExists,\n }\n validateFieldValue(ctx, issues, { validateComposition, validateRichText })\n }\n }\n\n // EC-218: a `parent` self-relation must not form a cycle. Needs the store to\n // walk the chain (other documents); the walk is cycle-safe, so this only\n // reports — it never loops. Only checked when the collection declares a parent\n // self-relation and a store is supplied.\n if (store && parentRelationField(collection)) {\n if (hasParentCycle(doc, (id) => store.get({ collection: collection.id, id }))) {\n issues.push(\n cmsIssue({\n code: 'hierarchy-cycle',\n message: `Document \"${doc.id}\" is its own ancestor — the parent chain forms a cycle.`,\n path: [...basePath, 'values', 'parent'],\n collectionId: collection.id,\n documentId: doc.id,\n meta: { field: 'parent' },\n }),\n )\n }\n }\n\n return issues\n}\n\n/** Validate every document in a list against the registry. */\nexport function validateDocuments(\n registry: CollectionRegistry,\n docs: readonly CmsDocument[],\n options: ValidateDocumentOptions = {},\n): CmsValidationIssue[] {\n return docs.flatMap((d) => validateDocument(registry, d, options))\n}\n\n// --- EC-190: props as fields -------------------------------------------------\n// Component props are field-defs (the same vocabulary as document fields). The\n// helpers below are the prop-side mirror of the document validators: pure,\n// store-free type/constraint checks plus a prop-keyed `validateComponentProps`.\n// They share field-type semantics with the document path; `fields.test.ts`\n// guards against drift between the two.\n\n/**\n * Pure scalar/structural type check for a field value (EC-190). Returns a human\n * detail string when the value is the wrong shape for the field type, or null\n * when it is acceptable. Existence checks (relation/asset targets) are NOT done\n * here — they need a document store. Assumes a present value (the `required`\n * check owns presence).\n */\nexport function checkScalarType(field: FieldDef, value: unknown): string | null {\n switch (field.type) {\n case 'text':\n return typeof value === 'string' ? null : 'expects a string'\n case 'richText':\n // A rich-text value is either a plain string (CMS markdown/HTML) or the\n // structured @elytracms/rich-text storage envelope (an object) used by the\n // canvas RichText component. Deep validation is delegated (the renderer's\n // parse guard / a future injected rich-text validator, mirroring blocks).\n return typeof value === 'string' || (typeof value === 'object' && value !== null)\n ? null\n : 'expects rich-text content (a string or a rich-text value)'\n case 'number':\n return typeof value === 'number' && !Number.isNaN(value) ? null : 'expects a number'\n case 'boolean':\n return typeof value === 'boolean' ? null : 'expects a boolean'\n case 'date':\n if (typeof value === 'string') {\n return Number.isNaN(Date.parse(value)) ? 'expects a valid date string' : null\n }\n return typeof value === 'number' ? null : 'expects a date (ISO string or epoch number)'\n case 'select': {\n const allowed = new Set(field.options.map((o) => o.value))\n const values = field.multiple ? (Array.isArray(value) ? value : [value]) : [value]\n for (const v of values) {\n if (typeof v !== 'string' || !allowed.has(v)) {\n return `has value \"${String(v)}\" not among its options`\n }\n }\n return null\n }\n case 'object':\n // EC-253: top-level shape only (deep subfield validation lives in\n // `validateComponentProps`, which needs the same per-field machinery).\n if (field.cardinality === 'many') {\n return Array.isArray(value) && value.every((item) => isPlainObject(item))\n ? null\n : 'expects a list of objects'\n }\n return isPlainObject(value) ? null : 'expects an object'\n case 'relation':\n case 'asset':\n case 'blocks':\n // relation / asset / blocks are validated structurally, not as scalars.\n return null\n default: {\n // Exhaustiveness: a new field type must add a case above (EC-253).\n const _exhaustive: never = field\n void _exhaustive\n return null\n }\n }\n}\n\n/**\n * Pure declarative-constraint check (min/max/pattern) for a field value (EC-190).\n * Returns the list of human detail strings for each violation (empty = valid).\n * Mirrors `validateConstraints` without the issue-construction coupling.\n */\nexport function checkConstraints(field: FieldDef, value: unknown): string[] {\n const out: string[] = []\n const rules = field.validation\n if (!rules) return out\n if (typeof value === 'string') {\n if (rules.min !== undefined && value.length < rules.min) out.push(`is shorter than min length ${rules.min}`)\n if (rules.max !== undefined && value.length > rules.max) out.push(`is longer than max length ${rules.max}`)\n if (rules.pattern !== undefined) {\n let re: RegExp | undefined\n try {\n re = new RegExp(rules.pattern)\n } catch {\n re = undefined\n }\n if (re && !re.test(value)) out.push(`does not match pattern ${rules.pattern}`)\n }\n } else if (typeof value === 'number') {\n if (rules.min !== undefined && value < rules.min) out.push(`is less than min ${rules.min}`)\n if (rules.max !== undefined && value > rules.max) out.push(`is greater than max ${rules.max}`)\n } else if (Array.isArray(value)) {\n if (rules.min !== undefined && value.length < rules.min) out.push(`has fewer than ${rules.min} items`)\n if (rules.max !== undefined && value.length > rules.max) out.push(`has more than ${rules.max} items`)\n }\n return out\n}\n\nfunction checkRelationStructure(field: RelationFieldDef, value: unknown): string[] {\n const out: string[] = []\n if (field.cardinality === 'one' && Array.isArray(value) && value.length > 1) {\n out.push(`is single-valued but has ${value.length} targets`)\n }\n const refs = Array.isArray(value) ? value : [value]\n for (const raw of refs) {\n const ref = coerceRef(raw)\n if (!ref) out.push('holds a value that is not a document reference')\n else if (ref.collection !== field.target) {\n out.push(`points at collection \"${ref.collection}\" but targets \"${field.target}\"`)\n }\n }\n return out\n}\n\nfunction checkAssetStructure(field: AssetFieldDef, value: unknown): string[] {\n const out: string[] = []\n if (field.cardinality === 'one' && Array.isArray(value) && value.length > 1) {\n out.push(`is single-valued but has ${value.length} targets`)\n }\n const ids = Array.isArray(value) ? value : [value]\n for (const raw of ids) {\n if (typeof raw !== 'string') out.push('expects an asset id string')\n }\n return out\n}\n\n/**\n * Build a pure, store-free validator for a single field-def's value (EC-190).\n * Used by the renderer (invalid static prop → EC-015 visible fallback) and the\n * inspector. Returns true when the value is structurally acceptable for the field\n * type; absent values (undefined/null/'') are acceptable — the `required` check\n * owns presence. Relation/asset existence and composition depth are validated\n * elsewhere (they need a store / registry).\n */\nexport function fieldValueValidator(field: FieldDef): (value: unknown) => boolean {\n return (value) => {\n if (isEmpty(value)) return true\n return checkScalarType(field, value) === null && checkConstraints(field, value).length === 0\n }\n}\n\n/**\n * Lint a field-def used as a component prop (EC-190): document-only attributes\n * (`filterable`, `validation.unique`) make no sense on a prop and surface as\n * structured issues, never silently ignored. Returns [] for a valid prop\n * field-def.\n */\nexport function assertPropFieldDef(field: FieldDef): CmsValidationIssue[] {\n const issues: CmsValidationIssue[] = []\n if (field.filterable) {\n issues.push(\n cmsIssue({\n code: 'invalid-field-config',\n message: `Component prop \"${field.name}\" declares \"filterable\", which only applies to document fields.`,\n path: ['props', field.name],\n meta: { field: field.name },\n }),\n )\n }\n if (field.validation?.unique) {\n issues.push(\n cmsIssue({\n code: 'invalid-field-config',\n message: `Component prop \"${field.name}\" declares \"unique\", which only applies across a collection's documents.`,\n path: ['props', field.name],\n meta: { field: field.name },\n }),\n )\n }\n // EC-253: a nested object prop's subfields are props too — lint them as well, so\n // a `filterable`/`unique` buried inside a repeater is surfaced, not silently kept.\n if (field.type === 'object') {\n for (const sub of field.fields) issues.push(...assertPropFieldDef(sub))\n }\n return issues\n}\n\nexport interface ValidateComponentPropsOptions {\n /**\n * When provided, `blocks` prop values are validated (EC-188 callback wired to\n * `validateCompositionValue` + the component registry by the studio).\n */\n validateComposition?: ValidateDocumentOptions['validateComposition']\n /**\n * When provided, the composition embeds inside a `richText` prop value are\n * validated (EC-189) — the prop-side mirror of the document callback.\n */\n validateRichTextEmbeds?: ValidateDocumentOptions['validateRichTextEmbeds']\n}\n\n/**\n * Validate a component's static prop values against its prop field-defs (EC-190).\n * The prop-side mirror of `validateDocument`: the same per-field type / constraint\n * / relation-structure / asset-structure / blocks checks, keyed by prop name,\n * MINUS collection-scoped concerns (uniqueness, filterability, localization) and\n * store-backed existence (relation/asset target *existence* is a where-used /\n * reference-integrity concern handled in EC-190 slice 6). Returns structured\n * issues; never throws. The inspector surfaces these inline exactly like document\n * field issues.\n */\n/**\n * Validate one prop value against its field-def, recursing into `object` subfields\n * (EC-253). The prop-side mirror of {@link validateFieldValue}: pure type +\n * constraint + relation/asset-structure + composition checks, keyed by `path`.\n * Shared by the top-level loop and the object recursion so a repeater item's\n * subfields are validated exactly as a top-level prop would be.\n */\nfunction validatePropFieldValue(\n field: FieldDef,\n value: unknown,\n path: CmsPath,\n options: ValidateComponentPropsOptions,\n issues: CmsValidationIssue[],\n): void {\n const push = (detail: string, code: CmsValidationIssue['code'] = 'invalid-field-value') =>\n issues.push(cmsIssue({ code, message: `Prop \"${field.name}\" ${detail}.`, path, meta: { field: field.name } }))\n\n if (isEmpty(value)) {\n if (field.validation?.required) {\n issues.push(\n cmsIssue({\n code: 'missing-required-field',\n message: `Required prop \"${field.name}\" is missing.`,\n path,\n meta: { field: field.name },\n }),\n )\n return\n }\n // EC-253 (C1): an optional but PRESENT object prop still recurses so its own\n // required subfields surface; any other empty/absent value has nothing to check.\n if (!isPresentObjectValue(field, value)) return\n }\n\n const typeErr = checkScalarType(field, value)\n if (typeErr) push(typeErr)\n for (const detail of checkConstraints(field, value)) push(detail)\n\n if (field.type === 'relation') {\n for (const detail of checkRelationStructure(field, value)) push(detail)\n } else if (field.type === 'asset') {\n for (const detail of checkAssetStructure(field, value)) push(detail)\n } else if (field.type === 'blocks' && options.validateComposition) {\n for (const finding of options.validateComposition(value, field)) {\n issues.push(\n cmsIssue({\n code: 'invalid-field-value',\n severity: finding.severity ?? 'error',\n message: `Prop \"${field.name}\": ${finding.message}`,\n path,\n meta: {\n field: field.name,\n type: 'blocks',\n ...(finding.nodePath ? { nodePath: finding.nodePath } : {}),\n },\n }),\n )\n }\n } else if (field.type === 'richText' && options.validateRichTextEmbeds) {\n // EC-189: validate the composition embeds carried by a richText prop value\n // (e.g. the RichText primitive's `content`) against the prop's `allow`.\n for (const finding of options.validateRichTextEmbeds(value, field)) {\n issues.push(\n cmsIssue({\n code: 'invalid-field-value',\n severity: finding.severity ?? 'error',\n message: `Prop \"${field.name}\": ${finding.message}`,\n path,\n meta: {\n field: field.name,\n type: 'richText',\n ...(finding.nodePath ? { nodePath: finding.nodePath } : {}),\n },\n }),\n )\n }\n } else if (field.type === 'object') {\n // EC-253: recurse into each item's subfields, mirroring the document path.\n const items =\n field.cardinality === 'many' ? (Array.isArray(value) ? value : []) : [value]\n items.forEach((item, index) => {\n if (!isPlainObject(item)) return\n const itemPath = field.cardinality === 'many' ? [...path, index] : path\n for (const sub of field.fields) {\n validatePropFieldValue(sub, item[sub.name], [...itemPath, sub.name], options, issues)\n }\n })\n }\n}\n\nexport function validateComponentProps(\n fieldDefs: readonly FieldDef[],\n props: Record<string, unknown>,\n options: ValidateComponentPropsOptions = {},\n): CmsValidationIssue[] {\n const issues: CmsValidationIssue[] = []\n for (const field of fieldDefs) {\n issues.push(...assertPropFieldDef(field))\n validatePropFieldValue(field, props[field.name], ['props', field.name], options, issues)\n }\n return issues\n}\n\n/** Resolve a relation value into the referenced documents (EC-017). */\nexport function resolveRelation(\n store: DocumentStore,\n value: unknown,\n): CmsDocument[] {\n const raws = Array.isArray(value) ? value : value === undefined || value === null ? [] : [value]\n const out: CmsDocument[] = []\n for (const raw of raws) {\n const ref = coerceRef(raw)\n if (!ref) continue\n const doc = store.get(ref)\n if (doc) out.push(doc)\n }\n return out\n}\n\n/** Build a flat values bag (non-localized only) — convenience for tests/consumers. */\nexport function plainValues(doc: CmsDocument): FieldValues {\n return { ...doc.values }\n}\n","import { z } from 'zod'\nimport { documentSchema } from './documents'\nimport type { CmsDocument } from './documents'\nimport { cmsIssue } from './issues'\nimport type { CmsValidationIssue } from './issues'\n\n/**\n * A snapshot of a document at a point in time (EC-021 version history). Stores a\n * full copy of the document's stored state plus bookkeeping. Snapshots are\n * immutable records of prior states.\n */\nexport const documentVersionSchema = z.object({\n /** Monotonic version number, starting at 1. */\n version: z.number().int().positive(),\n /** Full document snapshot at this version. */\n snapshot: documentSchema,\n /** When the snapshot was recorded (epoch ms). */\n createdAt: z.number().int().nonnegative(),\n /** Optional label, e.g. \"published\" or an author note. */\n label: z.string().optional(),\n})\nexport type DocumentVersion = z.infer<typeof documentVersionSchema>\n\n/**\n * Draft/published primitives + version history for a single document (EC-021).\n *\n * Holds the live `draft` state, the last `published` state (if any), and an\n * ordered history of recorded versions. All mutations return new states or\n * append history; nothing is silently dropped, and retrieving an unknown\n * version yields a structured issue rather than throwing.\n */\nexport interface DocumentHistory {\n /** The current working draft. */\n readonly draft: CmsDocument\n /** The last published snapshot, if the document has ever been published. */\n readonly published: CmsDocument | undefined\n /** Recorded versions, oldest first. */\n readonly versions: readonly DocumentVersion[]\n}\n\nfunction clone(doc: CmsDocument): CmsDocument {\n // Parse re-applies defaults and produces a detached, JSON-safe copy.\n return documentSchema.parse(structuredClone(doc))\n}\n\n/** Create a fresh history seeded with an initial draft (EC-021). */\nexport function createHistory(initial: CmsDocument): DocumentHistory {\n return {\n draft: clone(initial),\n published: undefined,\n versions: [],\n }\n}\n\n/** Replace the working draft (does not record a version). */\nexport function updateDraft(history: DocumentHistory, draft: CmsDocument): DocumentHistory {\n return { ...history, draft: clone(draft) }\n}\n\nexport interface PublishOptions {\n /** Timestamp for the recorded version (epoch ms); defaults to `Date.now()`. */\n now?: number\n label?: string\n}\n\n/**\n * Publish the current draft (EC-021): records it as a new version and promotes\n * it to `published`. The presence of `published` IS the published signal now\n * (EC-224 retired the flat `state` flag); the live `draft` is a detached copy.\n */\nexport function publish(history: DocumentHistory, options: PublishOptions = {}): DocumentHistory {\n const now = options.now ?? Date.now()\n const versions = [...history.versions]\n\n const promoted: CmsDocument = clone(history.draft)\n const nextVersion = (versions[versions.length - 1]?.version ?? 0) + 1\n versions.push({\n version: nextVersion,\n snapshot: clone(promoted),\n createdAt: now,\n ...(options.label ? { label: options.label } : { label: 'published' }),\n })\n\n return {\n draft: clone(promoted),\n published: promoted,\n versions,\n }\n}\n\n/** Snapshot the current draft into history without publishing (EC-021). */\nexport function snapshotDraft(\n history: DocumentHistory,\n options: PublishOptions = {},\n): DocumentHistory {\n const now = options.now ?? Date.now()\n const versions = [...history.versions]\n const nextVersion = (versions[versions.length - 1]?.version ?? 0) + 1\n versions.push({\n version: nextVersion,\n snapshot: clone(history.draft),\n createdAt: now,\n ...(options.label ? { label: options.label } : {}),\n })\n return { ...history, versions }\n}\n\nexport type VersionLookup =\n | { ok: true; version: DocumentVersion }\n | { ok: false; issue: CmsValidationIssue }\n\n/** Retrieve a prior version by number (EC-021). Unknown version → structured issue. */\nexport function getVersion(history: DocumentHistory, version: number): VersionLookup {\n const found = history.versions.find((v) => v.version === version)\n if (found) return { ok: true, version: found }\n return {\n ok: false,\n issue: cmsIssue({\n code: 'unknown-version',\n message: `No version ${version} recorded for document \"${history.draft.id}\".`,\n path: ['versions', version],\n documentId: history.draft.id,\n meta: { requested: version, available: history.versions.map((v) => v.version) },\n }),\n }\n}\n\n/**\n * Restore a prior version as the new working draft (EC-021). The current draft is\n * NOT lost — callers can snapshot it first if desired. Returns the updated\n * history, or a structured issue if the version is unknown.\n */\nexport function restoreVersion(\n history: DocumentHistory,\n version: number,\n): { ok: true; history: DocumentHistory } | { ok: false; issue: CmsValidationIssue } {\n const lookup = getVersion(history, version)\n if (!lookup.ok) return { ok: false, issue: lookup.issue }\n return { ok: true, history: updateDraft(history, lookup.version.snapshot) }\n}\n","import type { CollectionDef } from './collections'\nimport type { CmsDocument } from './documents'\nimport { documentKey, refOf } from './documents'\nimport type { LocaleConfig } from './localization'\nimport type { RedirectRecord, RouteRecord } from './routes'\n\n/**\n * Sample CMS model used across tests and as a worked example (mirrors the role of\n * `validSampleGraph` in `@elytracms/project-graph`). Provider-neutral, deterministic.\n */\n\nexport const sampleLocaleConfig: LocaleConfig = {\n default: 'en',\n locales: ['en', 'de'],\n}\n\n/** An asset collection (EC-017). */\nexport const assetCollection: CollectionDef = {\n id: 'asset',\n kind: 'asset',\n titleField: 'filename',\n fields: [\n { name: 'filename', type: 'text', validation: { required: true } },\n { name: 'alt', type: 'text', localized: true },\n { name: 'url', type: 'text', validation: { required: true } },\n ],\n}\n\n/** An author collection used as a relation target. */\nexport const authorCollection: CollectionDef = {\n id: 'author',\n kind: 'document',\n titleField: 'name',\n fields: [\n { name: 'name', type: 'text', validation: { required: true } },\n { name: 'bio', type: 'richText' },\n ],\n}\n\n/** A localized blog-post collection exercising every field type. */\nexport const postCollection: CollectionDef = {\n id: 'post',\n kind: 'document',\n localized: true,\n titleField: 'title',\n form: {\n label: 'Posts',\n labelSingular: 'Post',\n groups: ['content', 'meta'],\n tabs: ['main', 'seo'],\n },\n fields: [\n {\n name: 'title',\n type: 'text',\n localized: true,\n validation: { required: true, min: 1, max: 120 },\n form: { label: 'Title', group: 'content', tab: 'main', order: 1 },\n },\n {\n name: 'slug',\n type: 'text',\n validation: { required: true, pattern: '^[a-z0-9-]+$', unique: true },\n form: { label: 'Slug', group: 'content', tab: 'main', order: 2 },\n },\n {\n name: 'body',\n type: 'richText',\n localized: true,\n form: { label: 'Body', group: 'content', tab: 'main', order: 3 },\n },\n {\n name: 'views',\n type: 'number',\n validation: { min: 0 },\n form: { label: 'Views', group: 'meta', tab: 'main' },\n },\n {\n name: 'featured',\n type: 'boolean',\n form: { label: 'Featured', group: 'meta', tab: 'main' },\n },\n {\n name: 'publishedAt',\n type: 'date',\n form: { label: 'Published at', group: 'meta', tab: 'main' },\n },\n {\n name: 'status',\n type: 'select',\n options: [\n { value: 'news', label: 'News' },\n { value: 'guide', label: 'Guide' },\n ],\n form: { label: 'Status', group: 'meta', tab: 'main' },\n },\n {\n name: 'author',\n type: 'relation',\n target: 'author',\n cardinality: 'one',\n validation: { required: true },\n form: { label: 'Author', group: 'meta', tab: 'main' },\n },\n {\n name: 'related',\n type: 'relation',\n target: 'post',\n cardinality: 'many',\n form: { label: 'Related posts', group: 'meta', tab: 'main' },\n },\n {\n name: 'cover',\n type: 'asset',\n cardinality: 'one',\n accept: ['image'],\n form: { label: 'Cover image', group: 'content', tab: 'main' },\n },\n ],\n}\n\n/**\n * EC-187: the `page` collection — a document collection whose body IS a\n * composition (`blocks`) field, surfaced on its own \"Canvas\" fieldset tab\n * (EC-188). This is the config-owned model a routed page document is authored\n * against: `name` (title), the `body` canvas, structured SEO, and a `layoutId`\n * selecting which graph layout wraps the rendered composition at delivery.\n *\n * ADDITIVE + INERT (EC-187 slices 1–3): the collection exists in config so the\n * studio can author page documents and the reference index walks their `body`\n * tree, but NOTHING routes to it yet — the OLD `graph.pages` delivery path stays\n * canonical until the breaking cutover wires routes/host/seed to `page`.\n *\n * The `body` field mirrors the post `content` blocks field EXACTLY (same `allow`\n * code-leashed vocabulary, same `cardinality: 'many'`) so both composition\n * surfaces deliver and index through one identical code path.\n */\nexport const pageCollection: CollectionDef = {\n id: 'page',\n kind: 'document',\n titleField: 'name',\n form: {\n label: 'Pages',\n labelSingular: 'Page',\n tabs: ['main', 'canvas', 'seo'],\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n validation: { required: true },\n form: { tab: 'main' },\n },\n {\n name: 'body',\n type: 'blocks',\n allow: [\n 'base.primitives.Heading',\n 'base.primitives.Text',\n 'base.primitives.Image',\n 'base.primitives.Button',\n 'base.primitives.Stack',\n 'project.MarketingHero',\n 'project.FeatureCard',\n 'project.PricingCallout',\n ],\n cardinality: 'many',\n form: { label: 'Canvas', tab: 'canvas' },\n },\n { name: 'layoutId', type: 'text', form: { tab: 'main' } },\n { name: 'seoTitle', type: 'text', form: { tab: 'seo' } },\n { name: 'seoDescription', type: 'text', form: { tab: 'seo' } },\n { name: 'seoCanonical', type: 'text', form: { tab: 'seo' } },\n { name: 'seoOgTitle', type: 'text', form: { tab: 'seo' } },\n { name: 'seoOgImage', type: 'text', form: { tab: 'seo' } },\n { name: 'seoNoindex', type: 'boolean', form: { tab: 'seo' } },\n ],\n}\n\nexport const sampleCollections: CollectionDef[] = [\n assetCollection,\n authorCollection,\n postCollection,\n pageCollection,\n]\n\n/**\n * The canonical EC-143 `filterable` declarations for the sample model — the\n * single set the seeded schema (`@elytracms/persistence`), the accessor\n * fixtures (`@elytracms/content`), and the studio sessions share, so the\n * filter/sort pickers and the delivery engine agree on exactly one\n * declaration set (EC-169 fix-pack).\n *\n * Deliberately *not* filterable: `title` (tests prove that filtering a\n * real-but-undeclared field fails as a structured error) and the whole\n * `asset` collection (a collection with no filterable fields).\n */\nexport const sampleFilterableFields: Record<string, readonly string[]> = {\n author: ['name'],\n post: ['slug', 'views', 'featured', 'publishedAt', 'status', 'author'],\n}\n\nfunction withSampleFilterable(collection: CollectionDef): CollectionDef {\n const filterable = new Set(sampleFilterableFields[collection.id] ?? [])\n if (filterable.size === 0) return collection\n return {\n ...collection,\n fields: collection.fields.map((field) =>\n filterable.has(field.name) ? { ...field, filterable: true } : field,\n ),\n }\n}\n\n/**\n * `sampleCollections` with the canonical `filterable` declarations applied —\n * same ids, same field shapes. `sampleCollections` itself stays undeclared on\n * purpose (fixtures proving \"no declarations → nothing offered\" rely on it);\n * schema-bearing surfaces (the persistence seed, accessor fixtures) use this\n * variant.\n */\nexport const sampleFilterableCollections: CollectionDef[] =\n sampleCollections.map(withSampleFilterable)\n\n// ---- Sample documents ----\n\nexport const coverAsset: CmsDocument = {\n collection: 'asset',\n id: 'asset-cover',\n values: { filename: 'cover.png', url: 'https://cdn/cover.png' },\n localized: { en: { alt: 'A cover' }, de: { alt: 'Ein Titelbild' } },\n defaultLocale: 'en',\n}\n\n/**\n * The CMS counterpart of the seeded asset-library record (`@elytracms/persistence`\n * `SEED_ASSET`, id `asset_cover` — the EC-152 library). Sharing the library's\n * id means picking that real library asset validates clean against the asset\n * collection (EC-168/EC-172 fix-pack: the seeded post's `cover` previously had\n * no library-matching asset document, so a re-pick failed validation).\n * `coverAsset` above ('asset-cover') intentionally has NO library record — it\n * remains the \"missing asset record\" delivery demo.\n */\nexport const libraryCoverAsset: CmsDocument = {\n collection: 'asset',\n id: 'asset_cover',\n values: { filename: 'cover.jpg', url: 'https://cdn/cover.jpg' },\n localized: { en: { alt: 'Cover image' }, de: { alt: 'Titelbild' } },\n defaultLocale: 'en',\n}\n\nexport const authorAda: CmsDocument = {\n collection: 'author',\n id: 'author-ada',\n values: { name: 'Ada Lovelace', bio: 'Pioneer.' },\n}\n\n/** A valid, localized post that resolves all of its relations/assets. */\nexport const validPost: CmsDocument = {\n collection: 'post',\n id: 'post-hello',\n values: {\n slug: 'hello-world',\n views: 10,\n featured: true,\n publishedAt: '2026-01-02T00:00:00.000Z',\n status: 'news',\n author: { collection: 'author', id: 'author-ada' },\n related: [],\n cover: 'asset-cover',\n },\n localized: {\n en: { title: 'Hello World', body: '<p>Hi</p>' },\n de: { title: 'Hallo Welt', body: '<p>Hallo</p>' },\n },\n defaultLocale: 'en',\n}\n\n/** A post localized only in the default locale (exercises fallback, EC-018). */\nexport const partiallyLocalizedPost: CmsDocument = {\n collection: 'post',\n id: 'post-fallback',\n values: {\n slug: 'fallback',\n author: { collection: 'author', id: 'author-ada' },\n },\n localized: {\n en: { title: 'Only English', body: '<p>en</p>' },\n // no `de` variant — `de` requests must fall back to `en`\n },\n defaultLocale: 'en',\n}\n\n/**\n * The home page as a `page`-collection document (EC-187): `name`, a static\n * `body` composition (no bindings — v1 static props), a `layoutId` selecting the\n * graph layout, and flat `seo*` fields. This is what a routed page resolves to;\n * the catch-all renders `body` into `layoutId` via `renderCompositionInLayout`.\n */\nexport const samplePageHome: CmsDocument = {\n collection: 'page',\n id: 'home',\n values: {\n name: 'Home',\n layoutId: 'layout.main',\n seoTitle: 'Welcome to Elytra',\n seoDescription: 'A code-first website builder.',\n body: [\n {\n id: 'p-home-heading',\n componentId: 'base.primitives.Heading',\n props: {\n level: { kind: 'static', value: 1 },\n text: { kind: 'static', value: 'Welcome to Elytra' },\n },\n },\n {\n id: 'p-home-intro',\n componentId: 'base.primitives.Text',\n props: { value: { kind: 'static', value: 'A code-first website builder.' } },\n },\n ],\n },\n defaultLocale: 'en',\n}\n\nexport const samplePageDocuments: CmsDocument[] = [samplePageHome]\n\nexport const sampleDocuments: CmsDocument[] = [\n coverAsset,\n authorAda,\n validPost,\n partiallyLocalizedPost,\n libraryCoverAsset,\n samplePageHome,\n]\n\n/**\n * The sample documents that are PUBLISHED (EC-224), as an explicit\n * version-POINTER set — computed from each doc's identity, never a flat `state`\n * flag, so it survives the field's removal (B-3c-4). Seeds pin exactly these;\n * the playground/preview treat exactly these as live. (Every current sample doc\n * is published; a future draft sample would be omitted here.)\n */\nexport const samplePublishedKeys: readonly string[] = sampleDocuments.map((doc) =>\n documentKey(refOf(doc)),\n)\n\n// ---- Sample routes & redirects ----\n\nexport const sampleRoutes: RouteRecord[] = [\n { id: 'r-home', pattern: '/', locale: 'en', document: { collection: 'page', id: 'home' } },\n { id: 'r-home-de', pattern: '/', locale: 'de', document: { collection: 'page', id: 'home' } },\n {\n id: 'r-post',\n pattern: '/blog/:slug',\n locale: 'en',\n document: { collection: 'post', id: ':slug' },\n },\n {\n id: 'r-about',\n pattern: '/about',\n locale: 'en',\n document: { collection: 'post', id: 'post-hello' },\n },\n]\n\nexport const sampleRedirects: RedirectRecord[] = [\n { id: 'rd-1', from: '/old', to: '/about', permanent: true },\n { id: 'rd-chain-1', from: '/a', to: '/b', permanent: true },\n { id: 'rd-chain-2', from: '/b', to: '/c', permanent: true },\n { id: 'rd-chain-3', from: '/c', to: '/about', permanent: false },\n]\n\n/** Two routes that match the exact same concrete URLs (EC-020 conflict). */\nexport const conflictingRoutes: RouteRecord[] = [\n {\n id: 'r-a',\n pattern: '/blog/:slug',\n locale: 'en',\n document: { collection: 'post', id: ':slug' },\n },\n { id: 'r-b', pattern: '/blog/:id', locale: 'en', document: { collection: 'post', id: ':id' } },\n]\n\n/** A redirect loop (EC-020). */\nexport const loopingRedirects: RedirectRecord[] = [\n { id: 'l1', from: '/x', to: '/y', permanent: true },\n { id: 'l2', from: '/y', to: '/x', permanent: true },\n]\n","import type { FieldDef } from '@elytracms/cms-core'\nimport { fieldValueValidator } from '@elytracms/cms-core'\nimport type { JsonValue, ManifestView } from '@elytracms/project-graph'\n\n/** Distributive `Omit` that preserves a discriminated union (one variant per member). */\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never\n\n/**\n * A component prop is a **field-def** (EC-190 \"props as fields\", AD-12): the SAME\n * vocabulary the CMS uses for document fields (`@elytracms/cms-core` `FieldDef`) —\n * text/number/boolean/select/date/relation/asset/richText/blocks — minus the\n * `name` (the record key on `ComponentManifest.props` IS the prop name). One\n * schema vocabulary, one inspector/form engine, recursively: a prop of type\n * `blocks` carries a nested composition. Authoring metadata (label, default,\n * inline-editing, control hint) lives on the field-def's `form` and `default`.\n * Use `context: 'prop'` (or `'both'`); document-only attributes (`filterable`,\n * `unique`) are flagged by cms-core's `assertPropFieldDef`, never silently honoured.\n */\nexport type PropField = DistributiveOmit<FieldDef, 'name'>\n\n/** A named child insertion point. */\nexport interface SlotSpec {\n name: string\n label?: string\n required?: boolean\n /** Restrict which component ids may be inserted (omit to allow any). */\n allow?: string[]\n}\n\n/** A deterministic preview fixture for a component state. */\nexport interface ComponentFixture {\n name: string\n props?: Record<string, JsonValue>\n /** Named slots rendered with literal child component ids for preview. */\n slotChildren?: Record<string, string[]>\n}\n\n/** Declares that a component iterates a list prop over an item slot (e.g. Repeater). */\nexport interface IterateSpec {\n itemsProp: string\n itemSlot: string\n}\n\n/**\n * Declares that a component renders a composition FIELD VALUE (EC-188, AD-12): the\n * `valueProp` carries a stored composition (one `ComponentNode` root or an ordered\n * list — a `blocks` field's value), which the renderer renders as the component's\n * children via `renderComposition`, with the live `RenderContext`. The mirror of\n * `IterateSpec`: a manifest opts a host component into rendering a composition tree\n * wherever it is placed (e.g. a post template's body), so the same renderer/export\n * pipeline that renders pages renders block fields too.\n */\nexport interface CompositionSpec {\n valueProp: string\n}\n\n/**\n * Declares that a component renders a LISTING — a live, query-resolved set of\n * documents (EC-255, un-parks AD-9 \"this section repeats over a collection,\n * filtered, sorted\"). The `prop` receives the matching documents (delivery-shaped),\n * injected by the host exactly like a composition's children — NOT a static\n * relation pick the editor maintains by hand. The filter binds the listed\n * collection's `field` to the ref a SIBLING authored prop (`fromProp`) carries:\n * a ProductGrid picks one `category`, and the listing lists `product` where its\n * `categories` (a `many` relation) contains that pick. `sort`/`limit` are the\n * closed AD-3 query envelope. The mirror of {@link CompositionSpec} for a\n * query-resolved prop — so the same renderer/export pipeline that renders pages\n * renders dynamic grids, and adding/removing a member re-renders them.\n */\nexport interface ListingSpec {\n /** Prop the resolved documents are injected as (read by the implementation). */\n prop: string\n /** Collection to list (e.g. `product`). */\n collection: string\n /**\n * The membership filter: the listed collection's `field` must contain the ref\n * the sibling authored prop `fromProp` holds (a relation pick, reduced to its\n * target id). Closed to a single equality/contains term — the AD-3 vocabulary.\n */\n filter: { field: string; fromProp: string }\n /** Optional single-field sort (ties break by id, like every list — EC-143). */\n sort?: { field: string; direction?: 'asc' | 'desc' }\n /** Optional page-size cap. */\n limit?: number\n}\n\n/** The typed manifest each editable component declares (brief §7.2). */\nexport interface ComponentManifest {\n /** Namespaced id, e.g. `base.primitives.Stack` or `project.MarketingHero`. */\n id: string\n /** Source namespace: `base.primitives` for platform primitives, `project` for project code. */\n namespace: string\n title?: string\n description?: string\n category?: string\n /** Editable props as field-defs (EC-190), keyed by prop name. */\n props: Record<string, PropField>\n slots: SlotSpec[]\n /** Design-token usage hints (e.g. `['color.surface', 'space.gap']`). */\n designTokens?: string[]\n fixtures?: ComponentFixture[]\n iterate?: IterateSpec\n /** Marks the component as a composition host: `valueProp` holds a block-field tree (EC-188). */\n composition?: CompositionSpec\n /** Marks the component as a listing host: `prop` receives a live query's documents (EC-255). */\n listing?: ListingSpec\n /**\n * Canvas-eligibility (EC-191). Editors place components on a **client-rendered**\n * canvas, so a placeable component must be client-renderable (isomorphic React).\n * Defaults to eligible; set `clientRenderable: false` for a server-only / RSC\n * component — it stays usable in dev frames (`page.tsx` / `layout.tsx`) but the\n * blocks panel won't offer it and a composition that contains it is invalid.\n */\n clientRenderable?: boolean\n}\n\n/** Identity helper that infers nothing but documents intent at call sites. */\nexport function defineComponent(manifest: ComponentManifest): ComponentManifest {\n return manifest\n}\n\n/** Names of props flagged `form.inlineEditable`, in manifest declaration order. */\nexport function inlineEditablePropNames(manifest: ComponentManifest): string[] {\n return Object.entries(manifest.props)\n .filter(([, field]) => field.form?.inlineEditable === true)\n .map(([name]) => name)\n}\n\n/**\n * Return a copy of `manifest` with the named props flagged inline-editable\n * (EC-158, now `form.inlineEditable`). Names that don't exist on the manifest are\n * ignored. Used by hosts that assemble a registry from manifests they don't author\n * (e.g. the studio opting in platform-primitive content props).\n */\nexport function withInlineEditableProps(\n manifest: ComponentManifest,\n propNames: readonly string[],\n): ComponentManifest {\n const props: Record<string, PropField> = {}\n for (const [name, field] of Object.entries(manifest.props)) {\n props[name] = propNames.includes(name)\n ? ({ ...field, form: { ...field.form, inlineEditable: true } } as PropField)\n : field\n }\n return { ...manifest, props }\n}\n\n/**\n * Present a manifest's props as a `FieldDef[]` (EC-190) — the prop name injected\n * from the record key — so the shared inspector/form engine renders component\n * props with the exact control set, validation, and layout it renders document\n * fields. Declaration order is preserved.\n */\nexport function manifestPropFields(manifest: ComponentManifest): FieldDef[] {\n return Object.entries(manifest.props).map(([name, field]) => ({ ...field, name }) as FieldDef)\n}\n\n/** One manifest prop as a full `FieldDef` (name injected from the key), or undefined. */\nexport function manifestPropField(manifest: ComponentManifest, name: string): FieldDef | undefined {\n const field = manifest.props[name]\n return field ? ({ ...field, name }) as FieldDef : undefined\n}\n\n/**\n * The effective named child-region slots of a component (EC-190 \"slots are blocks\n * props\"). A `blocks`-type prop IS a slot: a named child region with an `allow`\n * leash, edited as a composition. So the manifest's declared `slots` are merged\n * with every `blocks` prop (carrying its `allow`/`required`/`label`) — EXCEPT a\n * `composition.valueProp`, which is a blocks VALUE passed to the host as a prop\n * (a delivery field value, stored in `node.props`), not a canvas child region\n * (stored in `node.slots`). Per DD3 the child trees stay in `node.slots`; the\n * field-def vocabulary just expresses the declaration + leash. For a manifest with\n * no `blocks` props this returns `manifest.slots` unchanged.\n */\nexport function manifestSlots(manifest: ComponentManifest): SlotSpec[] {\n const compositionValueProp = manifest.composition?.valueProp\n const fromBlocksProps: SlotSpec[] = []\n for (const [name, field] of Object.entries(manifest.props)) {\n if (field.type !== 'blocks') continue\n if (name === compositionValueProp) continue\n fromBlocksProps.push({\n name,\n ...(field.form?.label ? { label: field.form.label } : {}),\n ...(field.validation?.required ? { required: true } : {}),\n ...(field.allow ? { allow: field.allow } : {}),\n })\n }\n return fromBlocksProps.length === 0 ? manifest.slots : [...manifest.slots, ...fromBlocksProps]\n}\n\n/**\n * The value-validator for one manifest prop (EC-190): the SAME field-def value\n * check the CMS applies to a document field. The renderer uses it for the\n * invalid-static-prop → default fallback (EC-015) without importing cms-core.\n * Returns undefined when the prop is not declared (an unknown prop passes through).\n */\nexport function propValueValidator(\n manifest: ComponentManifest,\n name: string,\n): ((value: unknown) => boolean) | undefined {\n const field = manifestPropField(manifest, name)\n return field ? fieldValueValidator(field) : undefined\n}\n\n/** Namespace of a component id (the segment before the first dot-group). */\nexport function namespaceOf(id: string): string {\n if (id.startsWith('base.primitives.')) return 'base.primitives'\n const first = id.split('.')[0]\n return first ?? ''\n}\n\nexport function isPrimitive(id: string): boolean {\n return id.startsWith('base.primitives.')\n}\n\n/**\n * Canvas-eligibility (EC-191): true when an editor may place this component on the\n * client-rendered canvas. Eligible by default; `clientRenderable: false` (a\n * server-only / RSC component) opts out — the blocks panel hides it and a\n * composition that contains it fails `validateCompositionValue`.\n */\nexport function isCanvasEligible(manifest: ComponentManifest): boolean {\n return manifest.clientRenderable !== false\n}\n\n/** Bridge a manifest to the structural `ManifestView` the graph validator consumes. */\nexport function toManifestView(manifest: ComponentManifest): ManifestView {\n const props: NonNullable<ManifestView['props']> = {}\n for (const [name, field] of Object.entries(manifest.props)) {\n props[name] = {\n // EC-190: props are static; the binding path retires in slice 5. Until then\n // every prop reports bindable so the graph validator's binding branch stays\n // inert (no false `binding-not-allowed`). `validate` is the field-def value\n // validator — the SAME check the CMS uses for a document field value.\n bindable: true,\n validate: fieldValueValidator({ ...field, name } as FieldDef),\n }\n }\n return {\n id: manifest.id,\n props,\n // EC-191: carry canvas-eligibility so `validateCompositionValue` can reject a\n // server-only component placed in a composition.\n ...(manifest.clientRenderable === false ? { clientRenderable: false } : {}),\n // EC-186: carry the slot's placement vocabulary (`allow`) through to the\n // graph validator so it can enforce `forbidden-component` — previously\n // dropped here, leaving slot `allow` declared-but-unenforced. EC-190:\n // `manifestSlots` folds in `blocks`-type props as slots, so a blocks prop's\n // `allow` leash is enforced through the same path.\n slots: manifestSlots(manifest).map((s) => ({\n name: s.name,\n required: s.required,\n ...(s.allow ? { allow: s.allow } : {}),\n })),\n }\n}\n","import { z } from 'zod'\n\n/** A JSON-serializable value. The project graph contains only these — never functions or runtime handles. */\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue }\n\nexport const jsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>\n z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.null(),\n z.array(jsonValueSchema),\n z.record(z.string(), jsonValueSchema),\n ]),\n)\n","import { z } from 'zod'\n\n/** Generic non-empty identifier used for node / page / layout / project ids. */\nexport const idSchema = z.string().min(1)\nexport type Id = z.infer<typeof idSchema>\n\n/**\n * Namespaced component id, e.g. `base.primitives.Stack` or `project.MarketingHero`.\n *\n * NOTE: the graph schema stores component ids as plain non-empty strings so that a\n * graph referencing a badly-named or unknown component still *parses* (the renderer\n * can show a fallback and the validator can emit a structured issue). Naming is\n * checked semantically in `validate.ts`, not at parse time.\n */\nexport const COMPONENT_ID_PATTERN =\n /^(base\\.primitives|project)\\.[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$/\n\nexport function isValidComponentId(componentId: string): boolean {\n return COMPONENT_ID_PATTERN.test(componentId)\n}\n\n/** The reserved default-children slot name and the layout outlet slot name. */\nexport const DEFAULT_SLOT = 'children'\nexport const OUTLET_SLOT = 'outlet'\n","import { z } from 'zod'\nimport { idSchema } from './ids'\nimport { jsonValueSchema } from './json'\n\n/**\n * How a bound prop is applied. Shared by REST, CMS, and Convex sources (one uniform\n * binding model — see brief §4.6).\n * - `value` bind a primitive value\n * - `object` bind an object value\n * - `spread` spread an object's keys across the component's props\n * - `repeaterItem` resolve relative to the current repeater item context\n * - `condition` used as the source of a conditional render\n */\nexport const bindingModeSchema = z.enum(['value', 'object', 'spread', 'repeaterItem', 'condition'])\nexport type BindingMode = z.infer<typeof bindingModeSchema>\n\n/** A pointer from the graph into a data source via a stable path token. */\nexport const bindingReferenceSchema = z.object({\n /** Id of a data source (REST / CMS query / Convex query). */\n sourceId: idSchema,\n /** Stable path token (JSON Pointer / JSONPath) that survives UI label changes. */\n token: z.string().min(1),\n mode: bindingModeSchema,\n})\nexport type BindingReference = z.infer<typeof bindingReferenceSchema>\n\nexport const conditionOperatorSchema = z.enum([\n 'truthy',\n 'exists',\n 'eq',\n 'neq',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n])\nexport type ConditionOperator = z.infer<typeof conditionOperatorSchema>\n\n/** Gates whether a node renders. The left operand is resolved from a binding. */\nexport const conditionSchema = z.object({\n source: bindingReferenceSchema,\n operator: conditionOperatorSchema,\n /** Right-hand comparison value for binary operators (omitted for truthy/exists). */\n value: jsonValueSchema.optional(),\n})\nexport type Condition = z.infer<typeof conditionSchema>\n","import { z } from 'zod'\nimport { bindingReferenceSchema, conditionSchema } from './binding'\nimport type { BindingReference, Condition } from './binding'\nimport { idSchema } from './ids'\nimport { jsonValueSchema } from './json'\nimport type { JsonValue } from './json'\n\n/** A prop value is either a static JSON value or a binding into a data source. */\nexport const propValueSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('static'), value: jsonValueSchema }),\n z.object({ kind: z.literal('binding'), binding: bindingReferenceSchema }),\n])\nexport type PropValue = z.infer<typeof propValueSchema>\n\n/**\n * An instance of a registered component. Recursive via `slots`: each named slot\n * holds an ordered list of child nodes. The reserved slot `children` is the default\n * insertion point.\n */\nexport interface ComponentNode {\n id: string\n /** Namespaced registered component id (validated semantically, not at parse time). */\n componentId: string\n props?: Record<string, PropValue>\n slots?: Record<string, ComponentNode[]>\n condition?: Condition\n}\n\nexport const componentNodeSchema: z.ZodType<ComponentNode> = z.lazy(() =>\n z.object({\n id: idSchema,\n componentId: idSchema,\n props: z.record(z.string(), propValueSchema).optional(),\n slots: z.record(z.string(), z.array(componentNodeSchema)).optional(),\n condition: conditionSchema.optional(),\n }),\n)\n\n/** Convenience constructors for prop values. */\nexport function staticProp(value: JsonValue): PropValue {\n return { kind: 'static', value }\n}\n\nexport function boundProp(binding: BindingReference): PropValue {\n return { kind: 'binding', binding }\n}\n\n/** Structural guard for a stored component node (id + componentId present). */\nexport function isComponentNode(value: unknown): value is ComponentNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { id?: unknown }).id === 'string' &&\n typeof (value as { componentId?: unknown }).componentId === 'string'\n )\n}\n\n/**\n * Coerce a stored blocks/composition field value into its root node list — the\n * inverse of how a `blocks` field persists (a single node for cardinality\n * `one`, an array for `many`). Non-node entries are dropped; anything else\n * yields `[]`.\n */\nexport function blockRootsOf(value: unknown): ComponentNode[] {\n if (Array.isArray(value)) return value.filter(isComponentNode)\n return isComponentNode(value) ? [value] : []\n}\n","import { z } from 'zod'\nimport { idSchema } from './ids'\nimport { componentNodeSchema } from './node'\n\n/**\n * A shared layout wrapper. Its root tree contains an `outlet` slot where a page\n * composition renders (EC-187). Layouts are the dev-frame scaffolding — they\n * change rarely and remain in the canonical graph; pages moved OUT of the graph\n * into `page`-collection documents (their `body` is a composition field value).\n */\nexport const layoutSchema = z.object({\n id: idSchema,\n name: z.string().min(1),\n root: componentNodeSchema,\n})\nexport type Layout = z.infer<typeof layoutSchema>\n\n/**\n * Schema version 2 (EC-187): the graph is LAYOUTS-ONLY. Version 1 carried a\n * `pages` array (page-as-graph-node); v2 removes it — a page is now a document\n * in the `page` collection whose `body` composition renders into a layout via\n * `renderCompositionInLayout`. A deployment NOT reseeded to v2 serves a null\n * graph, so the host degrades to its visible fallback rather than crashing.\n */\nexport const PROJECT_GRAPH_SCHEMA_VERSION = 2\n\n/**\n * The canonical project graph — LAYOUTS-ONLY (EC-187). The single source of\n * truth for the dev-frame layout scaffolding; page content lives in the `page`\n * collection.\n */\nexport const projectGraphSchema = z.object({\n id: idSchema,\n schemaVersion: z.number().int().nonnegative(),\n metadata: z.object({ name: z.string().optional() }).optional(),\n /** Link to project settings owned by studio-core. */\n settingsRef: idSchema.optional(),\n layouts: z.array(layoutSchema).default([]),\n})\nexport type ProjectGraph = z.infer<typeof projectGraphSchema>\n","import { z } from 'zod'\nimport { DEFAULT_SLOT } from './ids'\nimport type { ComponentNode, PropValue } from './node'\nimport type { GraphPath, ValidationIssue } from './issues'\n\n/**\n * Canonical layout-container semantics (EC-161, vision §3.1 / AD-10).\n *\n * `Stack` and `Grid` are the two layout containers of the project graph. They are\n * ordinary `ComponentNode`s (componentId `base.primitives.Stack` / `base.primitives.Grid`)\n * — the registry renders them — but their *semantics* are owned here, by the graph:\n * direction, gap, alignment and columns are canonical graph values, normalization\n * (see `normalize.ts`) keeps them healthy, and malformed values surface as explicit\n * validation issues.\n *\n * Spacing values are stored as **token references** into the design-token spacing\n * scale (step names such as `'4'`), never raw CSS lengths. The scale below mirrors\n * `@elytracms/design-tokens` `spacingScale` (the graph package stays dependency-free,\n * so the names + CSS lengths are restated here as the canonical contract).\n */\n\n// ---------------------------------------------------------------------------\n// Container identity\n// ---------------------------------------------------------------------------\n\nexport const STACK_COMPONENT_ID = 'base.primitives.Stack'\nexport const GRID_COMPONENT_ID = 'base.primitives.Grid'\n\n/** The component ids the graph treats as layout containers (normalized, token-validated). */\nexport const LAYOUT_CONTAINER_COMPONENT_IDS: readonly string[] = [\n STACK_COMPONENT_ID,\n GRID_COMPONENT_ID,\n]\n\n/** True when a component id is a canonical layout container (`Stack`/`Grid`). */\nexport function isLayoutContainerId(componentId: string): boolean {\n return componentId === STACK_COMPONENT_ID || componentId === GRID_COMPONENT_ID\n}\n\n/** True when a node is a canonical layout container node. */\nexport function isLayoutContainerNode(node: ComponentNode): boolean {\n return isLayoutContainerId(node.componentId)\n}\n\n// ---------------------------------------------------------------------------\n// Token-bound values\n// ---------------------------------------------------------------------------\n\n/**\n * The spacing scale step names a container `gap` may reference. Mirrors the\n * `@elytracms/design-tokens` `spacingScale` step names — gap values are token\n * references, never CSS lengths (AD-10).\n */\nexport const SPACING_TOKEN_NAMES = ['px', '1', '2', '3', '4', '6', '8'] as const\nexport const spacingTokenNameSchema = z.enum(SPACING_TOKEN_NAMES)\nexport type SpacingTokenName = z.infer<typeof spacingTokenNameSchema>\n\n/** CSS length per spacing step — the resolution the renderer/export emit. */\nexport const SPACING_TOKEN_CSS: Record<SpacingTokenName, string> = {\n px: '1px',\n '1': '0.25rem',\n '2': '0.5rem',\n '3': '0.75rem',\n '4': '1rem',\n '6': '1.5rem',\n '8': '2rem',\n}\n\nexport function isSpacingTokenName(value: unknown): value is SpacingTokenName {\n return typeof value === 'string' && (SPACING_TOKEN_NAMES as readonly string[]).includes(value)\n}\n\n/** Resolve a spacing token name to its CSS length (undefined for unknown names). */\nexport function spacingTokenCss(name: string): string | undefined {\n return isSpacingTokenName(name) ? SPACING_TOKEN_CSS[name] : undefined\n}\n\n/**\n * Map a legacy numeric gap (pre-token graphs stored small integers, rendered as\n * `n * 4px`) onto the token scale. `0` means \"no gap\" (no token needed) and maps to\n * `null`; off-scale numbers return `undefined` (not representable as a token).\n */\nexport function spacingTokenFromLegacyGap(value: number): SpacingTokenName | null | undefined {\n if (!Number.isInteger(value) || value < 0) return undefined\n if (value === 0) return null\n const name = String(value)\n return isSpacingTokenName(name) ? name : undefined\n}\n\n/**\n * Responsive defaults (EC-163, vision §3.1 / AD-10): a `Grid`'s columns stack\n * vertically on phones **by default** — pages are responsive by construction,\n * not by editor diligence. The per-container override is an explicit opt-OUT\n * stored in the graph: `stackOnMobile: false` keeps the column tracks on\n * phones. Absence of the prop means the default (stack) — so the default\n * never needs to be written, and the override is always a visible, explicit\n * graph value.\n */\nexport const STACK_ON_MOBILE_PROP = 'stackOnMobile'\nexport const stackOnMobileSchema = z.boolean()\n\n/**\n * Whether a `Grid` node stacks its columns on mobile. `true` unless the node\n * carries the explicit static opt-out (`stackOnMobile: false`). Non-Grid nodes\n * never stack (the prop is Grid semantics). Bound or malformed values keep the\n * default — validation flags them; rendering degrades to the safe default.\n */\nexport function gridStacksOnMobile(node: ComponentNode): boolean {\n if (node.componentId !== GRID_COMPONENT_ID) return false\n const prop = node.props?.[STACK_ON_MOBILE_PROP]\n return !(prop?.kind === 'static' && prop.value === false)\n}\n\nexport const STACK_DIRECTIONS = ['vertical', 'horizontal'] as const\nexport const stackDirectionSchema = z.enum(STACK_DIRECTIONS)\nexport type StackDirection = z.infer<typeof stackDirectionSchema>\n\nexport const CONTAINER_ALIGNMENTS = ['start', 'center', 'end', 'stretch'] as const\nexport const containerAlignmentSchema = z.enum(CONTAINER_ALIGNMENTS)\nexport type ContainerAlignment = z.infer<typeof containerAlignmentSchema>\n\n/** Grid column-count bounds: a constrained count, validated at graph level. */\nexport const GRID_MIN_COLUMNS = 1\nexport const GRID_MAX_COLUMNS = 12\nexport const gridColumnsSchema = z.number().int().min(GRID_MIN_COLUMNS).max(GRID_MAX_COLUMNS)\n\n/**\n * A container gap as stored in the graph: a spacing token name (canonical) or a\n * legacy non-negative integer (accepted for backward compatibility; on-scale\n * integers are equivalent to their token, off-scale ones are flagged by validation).\n */\nexport const containerGapValueSchema = z.union([\n spacingTokenNameSchema,\n z.number().int().nonnegative(),\n])\nexport type ContainerGapValue = z.infer<typeof containerGapValueSchema>\n\n// ---------------------------------------------------------------------------\n// Node constructors (fixtures, gestures, tests)\n// ---------------------------------------------------------------------------\n\nexport interface StackContainerOptions {\n direction?: StackDirection\n gap?: SpacingTokenName\n align?: ContainerAlignment\n}\n\nexport interface GridContainerOptions {\n columns?: number\n gap?: SpacingTokenName\n align?: ContainerAlignment\n /** Explicit opt-out of the responsive default: `false` keeps columns on phones (EC-163). */\n stackOnMobile?: boolean\n}\n\nfunction staticProps(values: Record<string, unknown>): Record<string, PropValue> | undefined {\n const entries = Object.entries(values).filter(([, v]) => v !== undefined)\n if (entries.length === 0) return undefined\n return Object.fromEntries(\n entries.map(([name, value]) => [name, { kind: 'static', value } as PropValue]),\n )\n}\n\n/** Build a canonical `Stack` container node with token-bound props. */\nexport function stackContainerNode(\n id: string,\n options: StackContainerOptions,\n children: ComponentNode[],\n): ComponentNode {\n const props = staticProps({\n direction: options.direction,\n gap: options.gap,\n align: options.align,\n })\n return {\n id,\n componentId: STACK_COMPONENT_ID,\n ...(props ? { props } : {}),\n slots: { [DEFAULT_SLOT]: children },\n }\n}\n\n/** Build a canonical `Grid` container node with token-bound props. */\nexport function gridContainerNode(\n id: string,\n options: GridContainerOptions,\n children: ComponentNode[],\n): ComponentNode {\n const props = staticProps({\n columns: options.columns,\n gap: options.gap,\n align: options.align,\n stackOnMobile: options.stackOnMobile,\n })\n return {\n id,\n componentId: GRID_COMPONENT_ID,\n ...(props ? { props } : {}),\n slots: { [DEFAULT_SLOT]: children },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Container validation (called from validate.ts for every Stack/Grid node)\n// ---------------------------------------------------------------------------\n\nfunction containerIssue(\n code: ValidationIssue['code'],\n severity: ValidationIssue['severity'],\n message: string,\n path: GraphPath,\n nodeId: string,\n meta?: ValidationIssue['meta'],\n): ValidationIssue {\n return { code, severity, message, path: [...path], nodeId, ...(meta ? { meta } : {}) }\n}\n\n/** The static value of a prop, or `undefined` when absent or bound (bindings resolve at runtime). */\nfunction staticValueOf(node: ComponentNode, name: string): unknown {\n const prop = node.props?.[name]\n return prop?.kind === 'static' ? prop.value : undefined\n}\n\nfunction hasStaticProp(node: ComponentNode, name: string): boolean {\n return node.props?.[name]?.kind === 'static'\n}\n\n/**\n * Collect validation issues for a layout container node's canonical props. Only\n * static values are checked — bound props resolve at runtime and degrade in the\n * renderer. Non-container nodes yield no issues.\n */\nexport function collectContainerIssues(node: ComponentNode, path: GraphPath): ValidationIssue[] {\n if (!isLayoutContainerNode(node)) return []\n const issues: ValidationIssue[] = []\n\n // gap — token name (canonical) or legacy non-negative integer on the scale.\n if (hasStaticProp(node, 'gap')) {\n const gap = staticValueOf(node, 'gap')\n const gapPath: GraphPath = [...path, 'props', 'gap']\n if (typeof gap === 'string') {\n if (!isSpacingTokenName(gap)) {\n issues.push(\n containerIssue(\n 'invalid-container-gap',\n 'error',\n `Container gap \"${gap}\" is not a spacing token (expected one of ${SPACING_TOKEN_NAMES.join(', ')}).`,\n gapPath,\n node.id,\n { gap },\n ),\n )\n }\n } else if (typeof gap === 'number') {\n const token = spacingTokenFromLegacyGap(gap)\n if (token === undefined) {\n issues.push(\n containerIssue(\n 'invalid-container-gap',\n gap >= 0 && Number.isInteger(gap) ? 'warning' : 'error',\n `Container gap ${gap} is not on the spacing token scale (${SPACING_TOKEN_NAMES.join(', ')}).`,\n gapPath,\n node.id,\n { gap },\n ),\n )\n }\n } else {\n issues.push(\n containerIssue(\n 'invalid-container-gap',\n 'error',\n `Container gap must be a spacing token name, got ${JSON.stringify(gap)}.`,\n gapPath,\n node.id,\n ),\n )\n }\n }\n\n // align — both containers share the alignment enum.\n if (hasStaticProp(node, 'align')) {\n const align = staticValueOf(node, 'align')\n if (!containerAlignmentSchema.safeParse(align).success) {\n issues.push(\n containerIssue(\n 'invalid-container-alignment',\n 'error',\n `Container alignment ${JSON.stringify(align)} is invalid (expected ${CONTAINER_ALIGNMENTS.join(', ')}).`,\n [...path, 'props', 'align'],\n node.id,\n ),\n )\n }\n }\n\n if (node.componentId === STACK_COMPONENT_ID && hasStaticProp(node, 'direction')) {\n const direction = staticValueOf(node, 'direction')\n if (!stackDirectionSchema.safeParse(direction).success) {\n issues.push(\n containerIssue(\n 'invalid-container-direction',\n 'error',\n `Stack direction ${JSON.stringify(direction)} is invalid (expected ${STACK_DIRECTIONS.join(' or ')}).`,\n [...path, 'props', 'direction'],\n node.id,\n ),\n )\n }\n }\n\n // stackOnMobile — Grid-only responsive override (EC-163): a boolean or nothing.\n if (node.componentId === GRID_COMPONENT_ID && hasStaticProp(node, STACK_ON_MOBILE_PROP)) {\n const value = staticValueOf(node, STACK_ON_MOBILE_PROP)\n if (!stackOnMobileSchema.safeParse(value).success) {\n issues.push(\n containerIssue(\n 'invalid-container-responsive',\n 'error',\n `Grid ${STACK_ON_MOBILE_PROP} must be true or false, got ${JSON.stringify(value)}.`,\n [...path, 'props', STACK_ON_MOBILE_PROP],\n node.id,\n ),\n )\n }\n }\n\n if (node.componentId === GRID_COMPONENT_ID && hasStaticProp(node, 'columns')) {\n const columns = staticValueOf(node, 'columns')\n if (!gridColumnsSchema.safeParse(columns).success) {\n issues.push(\n containerIssue(\n 'invalid-container-columns',\n 'error',\n `Grid column count ${JSON.stringify(columns)} is invalid (expected an integer between ${GRID_MIN_COLUMNS} and ${GRID_MAX_COLUMNS}).`,\n [...path, 'props', 'columns'],\n node.id,\n ),\n )\n }\n }\n\n return issues\n}\n","import { z } from 'zod'\nimport { idSchema } from './ids'\nimport { jsonValueSchema } from './json'\n\n/** Stable codes for structured validation issues (brief §4.11, §7.1). */\nexport const issueCodeSchema = z.enum([\n 'invalid-component-name',\n 'unknown-component',\n 'duplicate-node-id',\n 'unknown-prop',\n 'invalid-prop',\n 'binding-not-allowed',\n 'unresolved-binding',\n 'missing-required-slot',\n 'unknown-slot',\n // Placement constraints (EC-186): a component appears where its slot's `allow`\n // vocabulary — or a composition field's `allow` — forbids it.\n 'forbidden-component',\n // Canvas-eligibility (EC-191): a server-only (RSC / non-client-renderable)\n // component was placed in an editor composition, which is client-rendered.\n // Such components belong in dev frames (page.tsx / layout.tsx), not the canvas.\n 'server-only-component',\n 'unknown-layout',\n 'route-conflict',\n // Layout containers (EC-161): malformed Stack/Grid canonical props.\n 'invalid-container-direction',\n 'invalid-container-alignment',\n 'invalid-container-gap',\n 'invalid-container-columns',\n // Responsive defaults (EC-163): malformed Grid stack-on-mobile override.\n 'invalid-container-responsive',\n])\nexport type IssueCode = z.infer<typeof issueCodeSchema>\n\nexport const issueSeveritySchema = z.enum(['error', 'warning'])\nexport type IssueSeverity = z.infer<typeof issueSeveritySchema>\n\n/** A structured validation issue carrying a JSON path into the graph. */\nexport const validationIssueSchema = z.object({\n code: issueCodeSchema,\n severity: issueSeveritySchema,\n message: z.string(),\n /** JSON path into the graph, e.g. ['pages', 0, 'root', 'slots', 'children', 1]. */\n path: z.array(z.union([z.string(), z.number()])),\n /** The offending node id, when applicable. */\n nodeId: idSchema.optional(),\n meta: z.record(z.string(), jsonValueSchema).optional(),\n})\nexport type ValidationIssue = z.infer<typeof validationIssueSchema>\n\nexport type GraphPath = ReadonlyArray<string | number>\n","import type { z } from 'zod'\nimport { PROJECT_GRAPH_SCHEMA_VERSION, projectGraphSchema } from './structure'\nimport type { ProjectGraph } from './structure'\nimport { componentNodeSchema } from './node'\nimport type { ComponentNode } from './node'\n\n/**\n * Serialize a project graph to JSON. Parsing first guarantees the output contains no\n * runtime-only values and that defaults are applied (brief §7.1).\n */\nexport function serializeProjectGraph(graph: ProjectGraph): string {\n const parsed = projectGraphSchema.parse(graph)\n return JSON.stringify(parsed)\n}\n\nexport type ParseResult =\n | { ok: true; graph: ProjectGraph }\n | { ok: false; error: z.ZodError }\n\n/** Parse a project graph from a JSON string or already-parsed value. Never throws on invalid input. */\nexport function parseProjectGraph(input: string | unknown): ParseResult {\n let json: unknown\n try {\n json = typeof input === 'string' ? JSON.parse(input) : input\n } catch {\n // Treat malformed JSON the same as a failed schema parse of `undefined`.\n json = undefined\n }\n const result = projectGraphSchema.safeParse(json)\n return result.success ? { ok: true, graph: result.data } : { ok: false, error: result.error }\n}\n\n/** True if the graph's schema version matches the version this package understands. */\nexport function isCompatibleSchemaVersion(graph: ProjectGraph): boolean {\n return graph.schemaVersion === PROJECT_GRAPH_SCHEMA_VERSION\n}\n\n/**\n * Serialize a composition **field value** (EC-186, AD-12) — a single\n * `ComponentNode` tree, not a whole graph. Parsing first applies defaults and\n * strips runtime-only values, exactly like {@link serializeProjectGraph}. A\n * field value is an untethered tree (no `schemaVersion` wrapper); revisions ride\n * the document that holds it.\n */\nexport function serializeComponentNode(node: ComponentNode): string {\n const parsed = componentNodeSchema.parse(node)\n return JSON.stringify(parsed)\n}\n\nexport type ParseNodeResult =\n | { ok: true; node: ComponentNode }\n | { ok: false; error: z.ZodError }\n\n/** Parse a composition field value from a JSON string or value. Never throws on invalid input. */\nexport function parseComponentNode(input: string | unknown): ParseNodeResult {\n let json: unknown\n try {\n json = typeof input === 'string' ? JSON.parse(input) : input\n } catch {\n json = undefined\n }\n const result = componentNodeSchema.safeParse(json)\n return result.success ? { ok: true, node: result.data } : { ok: false, error: result.error }\n}\n","import { OUTLET_SLOT } from './ids'\nimport type { ComponentNode } from './node'\nimport type { ProjectGraph } from './structure'\nimport { PROJECT_GRAPH_SCHEMA_VERSION } from './structure'\nimport type { ManifestView } from './validate'\nimport {\n containerAlignmentSchema,\n gridColumnsSchema,\n gridContainerNode,\n isSpacingTokenName,\n stackContainerNode,\n stackDirectionSchema,\n} from './container'\n\nconst isGapValue = (v: unknown): boolean =>\n isSpacingTokenName(v) || (typeof v === 'number' && Number.isInteger(v) && v >= 0)\n\n/**\n * Minimal manifest views for the primitives used by the sample graphs. Lets the graph\n * package validate its own fixtures without depending on the component registry. The\n * registry's real manifests satisfy the same `ManifestView` shape.\n */\nexport const sampleManifestViews: Record<string, ManifestView> = {\n 'base.primitives.Stack': {\n id: 'base.primitives.Stack',\n props: {\n // Token name (canonical) or legacy non-negative integer (EC-161).\n gap: { bindable: true, validate: isGapValue },\n direction: { bindable: false, validate: (v) => stackDirectionSchema.safeParse(v).success },\n align: { bindable: false, validate: (v) => containerAlignmentSchema.safeParse(v).success },\n },\n slots: [{ name: 'children' }],\n },\n 'base.primitives.Grid': {\n id: 'base.primitives.Grid',\n props: {\n columns: { bindable: true, validate: (v) => gridColumnsSchema.safeParse(v).success },\n gap: { bindable: true, validate: isGapValue },\n align: { bindable: false, validate: (v) => containerAlignmentSchema.safeParse(v).success },\n },\n slots: [{ name: 'children' }],\n },\n 'base.primitives.Heading': {\n id: 'base.primitives.Heading',\n props: {\n level: { bindable: false, validate: (v) => typeof v === 'number' && v >= 1 && v <= 6 },\n text: { bindable: true, validate: (v) => typeof v === 'string' },\n },\n },\n 'base.primitives.Text': {\n id: 'base.primitives.Text',\n props: { value: { bindable: true, validate: (v) => typeof v === 'string' } },\n },\n 'base.primitives.Repeater': {\n id: 'base.primitives.Repeater',\n props: { items: { bindable: true } },\n slots: [{ name: 'item', required: true }],\n },\n 'base.primitives.Container': {\n id: 'base.primitives.Container',\n // The outlet is filled by the renderer (composition injection), so it is not authored-required.\n slots: [{ name: OUTLET_SLOT }],\n },\n}\n\nexport const sampleKnownSourceIds: ReadonlySet<string> = new Set(['cms.posts'])\n\nconst mainLayoutRoot: ComponentNode = {\n id: 'n-layout-root',\n componentId: 'base.primitives.Container',\n slots: { [OUTLET_SLOT]: [] },\n}\n\n/**\n * A sample composition (EC-187): the home page's `body` field value — an ordered\n * list of component nodes the renderer composes into a layout outlet. This is the\n * page content that used to live on `validSampleGraph.pages[0].root`; the graph is\n * now layouts-only, so the page body lives here (and, at delivery, in a `page`\n * collection document — see `@elytracms/cms-core` `samplePageDocuments`).\n */\nexport const sampleHomeComposition: ComponentNode[] = [\n {\n id: 'n-heading',\n componentId: 'base.primitives.Heading',\n props: {\n level: { kind: 'static', value: 1 },\n text: { kind: 'static', value: 'Welcome to Elytra' },\n },\n },\n {\n id: 'n-intro',\n componentId: 'base.primitives.Text',\n props: { value: { kind: 'static', value: 'A code-first website builder.' } },\n },\n {\n id: 'n-repeater',\n componentId: 'base.primitives.Repeater',\n props: { items: { kind: 'binding', binding: { sourceId: 'cms.posts', token: '/', mode: 'value' } } },\n slots: {\n item: [\n {\n id: 'n-post-title',\n componentId: 'base.primitives.Text',\n props: {\n value: { kind: 'binding', binding: { sourceId: 'cms.posts', token: '/title', mode: 'repeaterItem' } },\n },\n },\n ],\n },\n },\n]\n\n/** A valid sample project graph (brief §10 / Phase 1) — LAYOUTS-ONLY (EC-187). */\nexport const validSampleGraph: ProjectGraph = {\n id: 'proj-sample',\n schemaVersion: PROJECT_GRAPH_SCHEMA_VERSION,\n metadata: { name: 'Sample Project' },\n layouts: [{ id: 'layout.main', name: 'Main', root: mainLayoutRoot }],\n}\n\n// ---- Invalid-state fixtures (each isolates exactly one issue) ----\n//\n// EC-187: `validateProjectGraph` walks LAYOUTS only — a page is a composition\n// field value validated by `validateCompositionValue`. So each invalid-state\n// fixture places its single defect on a LAYOUT root, and the matching bare\n// `ComponentNode` is also exported for tests that validate a composition value\n// directly (`validateComponentNode` / `validateCompositionValue`).\n\n/** A layouts-only graph wrapping one defective root as a layout. */\nfunction layoutGraph(id: string, root: ComponentNode): ProjectGraph {\n return {\n id,\n schemaVersion: PROJECT_GRAPH_SCHEMA_VERSION,\n layouts: [{ id: `${id}.layout`, name: 'Layout', root }],\n }\n}\n\nexport const nodeWithInvalidComponentName: ComponentNode = {\n id: 'n-bad',\n componentId: 'NotNamespaced',\n props: {},\n}\nexport const graphWithInvalidComponentName: ProjectGraph = layoutGraph(\n 'proj-bad-name',\n nodeWithInvalidComponentName,\n)\n\nexport const nodeWithUnknownComponent: ComponentNode = {\n id: 'n-missing',\n componentId: 'project.DoesNotExist',\n}\nexport const graphWithUnknownComponent: ProjectGraph = layoutGraph(\n 'proj-unknown',\n nodeWithUnknownComponent,\n)\n\nexport const nodeWithMissingRequiredSlot: ComponentNode = {\n id: 'n-empty-repeater',\n componentId: 'base.primitives.Repeater',\n props: {},\n slots: {},\n}\nexport const graphWithMissingRequiredSlot: ProjectGraph = layoutGraph(\n 'proj-missing-slot',\n nodeWithMissingRequiredSlot,\n)\n\nexport const nodeWithUnresolvedBinding: ComponentNode = {\n id: 'n-text',\n componentId: 'base.primitives.Text',\n props: { value: { kind: 'binding', binding: { sourceId: 'missing.source', token: '/x', mode: 'value' } } },\n}\nexport const graphWithUnresolvedBinding: ProjectGraph = layoutGraph(\n 'proj-unresolved',\n nodeWithUnresolvedBinding,\n)\n\nexport const nodeWithDuplicateIds: ComponentNode = {\n id: 'dup',\n componentId: 'base.primitives.Stack',\n slots: { children: [{ id: 'dup', componentId: 'base.primitives.Text', props: { value: { kind: 'static', value: 'x' } } }] },\n}\nexport const graphWithDuplicateIds: ProjectGraph = layoutGraph('proj-dupe', nodeWithDuplicateIds)\n\n/** A simple in-memory `ComponentLookup` over the sample manifest views. */\nexport const sampleComponentLookup = {\n has: (id: string) => id in sampleManifestViews,\n get: (id: string) => sampleManifestViews[id],\n}\n\n// ---- Layout-container fixtures (EC-161) ----\n\nconst textNode = (id: string, value: string): ComponentNode => ({\n id,\n componentId: 'base.primitives.Text',\n props: { value: { kind: 'static', value } },\n})\n\nfunction containerGraph(id: string, root: ComponentNode): ProjectGraph {\n return {\n id,\n schemaVersion: PROJECT_GRAPH_SCHEMA_VERSION,\n layouts: [{ id: `${id}.layout`, name: 'Layout', root }],\n }\n}\n\n/**\n * A valid container graph with every canonical prop token-bound: a vertical Stack\n * (gap `4`, align `start`) holding a 2-column Grid (gap `2`) of mixed children and\n * a horizontal Stack. Round-trips losslessly through serialization.\n */\nexport const tokenizedContainersGraph: ProjectGraph = containerGraph(\n 'proj-containers',\n stackContainerNode('n-root', { direction: 'vertical', gap: '4', align: 'start' }, [\n gridContainerNode('n-grid', { columns: 2, gap: '2', align: 'stretch' }, [\n textNode('n-cell-1', 'Cell one'),\n {\n id: 'n-cell-2',\n componentId: 'base.primitives.Heading',\n props: { level: { kind: 'static', value: 2 }, text: { kind: 'static', value: 'Cell two' } },\n },\n ]),\n stackContainerNode('n-row', { direction: 'horizontal', gap: '2', align: 'center' }, [\n textNode('n-row-a', 'Left'),\n textNode('n-row-b', 'Right'),\n ]),\n ]),\n)\n\n/**\n * Degenerate \"wrapper soup\": single-child Stack chains, an empty Grid, and a\n * container-of-containers — the canonical input for normalization tests.\n * `normalizeContainers` collapses it to a root Stack with two Text children.\n */\nexport const wrapperSoupGraph: ProjectGraph = containerGraph(\n 'proj-soup',\n stackContainerNode('n-root', { gap: '4' }, [\n stackContainerNode('n-wrap-1', { gap: '2' }, [\n stackContainerNode('n-wrap-2', {}, [\n gridContainerNode('n-wrap-3', { columns: 2 }, [textNode('n-deep', 'Deeply wrapped')]),\n ]),\n ]),\n gridContainerNode('n-empty-grid', { columns: 3, gap: '2' }, []),\n textNode('n-plain', 'Plain sibling'),\n ]),\n)\n\n// Malformed-container fixtures — each isolates exactly one issue.\n\nexport const graphWithInvalidContainerDirection: ProjectGraph = containerGraph('proj-bad-direction', {\n id: 'n-bad-direction',\n componentId: 'base.primitives.Stack',\n props: { direction: { kind: 'static', value: 'diagonal' } },\n slots: { children: [textNode('n-d1', 'a'), textNode('n-d2', 'b')] },\n})\n\nexport const graphWithInvalidContainerGap: ProjectGraph = containerGraph('proj-bad-gap', {\n id: 'n-bad-gap',\n componentId: 'base.primitives.Stack',\n props: { gap: { kind: 'static', value: '17rem' } },\n slots: { children: [textNode('n-g1', 'a'), textNode('n-g2', 'b')] },\n})\n\nexport const graphWithInvalidContainerColumns: ProjectGraph = containerGraph('proj-bad-columns', {\n id: 'n-bad-columns',\n componentId: 'base.primitives.Grid',\n props: { columns: { kind: 'static', value: 0 } },\n slots: { children: [textNode('n-c1', 'a'), textNode('n-c2', 'b')] },\n})\n\nexport const graphWithInvalidContainerAlignment: ProjectGraph = containerGraph('proj-bad-align', {\n id: 'n-bad-align',\n componentId: 'base.primitives.Grid',\n props: { columns: { kind: 'static', value: 2 }, align: { kind: 'static', value: 'justify' } },\n slots: { children: [textNode('n-a1', 'a'), textNode('n-a2', 'b')] },\n})\n","import { isValidComponentId } from '@elytracms/project-graph'\nimport type { ComponentLookup, ManifestView } from '@elytracms/project-graph'\nimport type { ComponentIssue } from './issues'\nimport type { ComponentManifest } from './manifest'\nimport { isPrimitive, namespaceOf, toManifestView } from './manifest'\n\nexport interface ListFilter {\n namespace?: string\n category?: string\n /** Case-insensitive substring match over id / title / category. */\n query?: string\n}\n\n/**\n * The component registry serves the Builder, renderer, AI tools, export pipeline, and\n * CLI. It distinguishes platform primitives from project components, supports lookup,\n * filtering, required lookups, and reports duplicate ids as structured issues.\n */\nexport class ComponentRegistry {\n private readonly byId = new Map<string, ComponentManifest>()\n private readonly viewCache = new Map<string, ManifestView>()\n readonly issues: ComponentIssue[] = []\n\n constructor(manifests: Iterable<ComponentManifest> = []) {\n for (const manifest of manifests) this.register(manifest)\n }\n\n register(manifest: ComponentManifest): void {\n if (!isValidComponentId(manifest.id)) {\n this.issues.push({\n code: 'invalid-id',\n componentId: manifest.id,\n message: `Component id \"${manifest.id}\" is not namespaced under base.primitives.* or project.*.`,\n })\n }\n if (this.byId.has(manifest.id)) {\n this.issues.push({\n code: 'duplicate-id',\n componentId: manifest.id,\n message: `Duplicate component id \"${manifest.id}\" — keeping the first registration.`,\n })\n return\n }\n this.byId.set(manifest.id, manifest)\n }\n\n has(id: string): boolean {\n return this.byId.has(id)\n }\n\n getManifest(id: string): ComponentManifest | undefined {\n return this.byId.get(id)\n }\n\n /** Required lookup — throws when the component is not registered. */\n require(id: string): ComponentManifest {\n const manifest = this.byId.get(id)\n if (!manifest) throw new Error(`Unknown component \"${id}\".`)\n return manifest\n }\n\n list(filter: ListFilter = {}): ComponentManifest[] {\n const q = filter.query?.toLowerCase()\n return [...this.byId.values()].filter((m) => {\n if (filter.namespace && namespaceOf(m.id) !== filter.namespace) return false\n if (filter.category && m.category !== filter.category) return false\n if (q) {\n const hay = `${m.id} ${m.title ?? ''} ${m.category ?? ''}`.toLowerCase()\n if (!hay.includes(q)) return false\n }\n return true\n })\n }\n\n /** Platform primitives (`base.primitives.*`). */\n primitives(): ComponentManifest[] {\n return this.list().filter((m) => isPrimitive(m.id))\n }\n\n /** Project-level components (everything not under `base.primitives.*`). */\n projectComponents(): ComponentManifest[] {\n return this.list().filter((m) => !isPrimitive(m.id))\n }\n\n get size(): number {\n return this.byId.size\n }\n\n /** A `ComponentLookup` view for the project-graph validator. */\n get lookup(): ComponentLookup {\n return {\n has: (id) => this.byId.has(id),\n get: (id) => {\n if (!this.byId.has(id)) return undefined\n let view = this.viewCache.get(id)\n if (!view) {\n view = toManifestView(this.byId.get(id)!)\n this.viewCache.set(id, view)\n }\n return view\n },\n }\n }\n}\n","import type { ComponentType, ReactNode } from 'react'\nimport type { BindingReference, ComponentNode } from '@elytracms/project-graph'\nimport type { ComponentRegistry } from '@elytracms/component-registry'\nimport type { ContentClient } from './content-client'\n\n/**\n * A single repeater item scope. When set, `repeaterItem`-mode bindings resolve against\n * `item` rather than the root data source (brief §4.6 — uniform binding model).\n */\nexport interface ItemContext {\n item: unknown\n index: number\n}\n\n/**\n * Resolves a binding to a runtime value. INJECTED by the host (builder preview, export\n * runtime, tests) so the renderer never imports `@elytracms/data-binding`. When an\n * `ItemContext` is active, it is passed through so `repeaterItem` bindings resolve\n * relative to the current item.\n */\nexport type ResolveBinding = (ref: BindingReference, item?: ItemContext) => unknown\n\n/**\n * A resolved asset, ready to hand to an image implementation (EC-195). The\n * delivery-shaped subset of `@elytracms/content`'s `ResolvedAsset` the renderer\n * needs — kept minimal so the renderer takes no dependency on the content or\n * persistence packages. `width`/`height` are intrinsic dimensions (so the host\n * can reserve space and `next/image` can size variants); `null` when unknown.\n */\nexport interface RenderAsset {\n url: string\n width: number | null\n height: number | null\n alt: string | null\n /**\n * Normalized focal point `{ x, y }` in 0–1 (EC-230) → CSS `object-position` so\n * an art-directed image keeps its subject in frame when cropped; `null` when\n * none. Kept as a plain pair so the renderer stays free of content/persistence.\n */\n focalPoint: { x: number; y: number } | null\n}\n\n/**\n * Resolves a stored asset id to a usable asset (EC-195), or `null` when the\n * asset is missing (the renderer then shows the EC-015 visible fallback rather\n * than crashing). INJECTED by the host/studio exactly like {@link ResolveBinding},\n * so the renderer never imports the asset store or content packages.\n */\nexport type ResolveAsset = (assetId: string) => RenderAsset | null\n\n/**\n * A relation target populated to delivery shape (EC-254): identity plus the\n * target document's resolved fields (relations inside stay `{ id, collection }`\n * stubs at depth-1; assets inside resolve to objects). Opaque to the renderer —\n * the host's content layer produces it, the component implementation reads its\n * fields. The minimal structural face is `{ id, collection }`.\n */\nexport type RelationTarget = { id: string; collection: string } & Record<string, unknown>\n\n/**\n * Resolves a composition-node `relation` PROP's stored reference to its populated\n * target (EC-254), or `null` when the target is missing or not visible in the\n * delivery perspective — the prop is then omitted (`one`) or dropped from the\n * array (`many`), the same graceful degradation as a missing {@link ResolveAsset}.\n *\n * INJECTED by the host/studio exactly like {@link ResolveAsset}, wired to\n * `@elytracms/content`'s depth-1 population (`ContentClient.resolveRelation`), so\n * the renderer never imports the content/persistence packages. This populates the\n * relation props of the nodes INSIDE a page's `blocks` composition — which\n * document resolution leaves raw, never descending into a composition value.\n */\nexport type ResolveRelation = (ref: { collection: string; id: string }) => RelationTarget | null\n\n/**\n * A resolved listing query (EC-255): the collection to list plus a closed,\n * AND-only filter (`field → required scalar`, a relation field reduced to its\n * target id — the v1 AD-3 vocabulary), with optional single-field sort and\n * limit. Built by {@link listingQueryOf} from a node's `listing` manifest and\n * its filter-source prop pick. Plain & serializable — primitives only, no\n * content/query-package types — so a host can key a baked result by it and the\n * renderer stays free of the content/persistence packages.\n */\nexport interface ListingQuery {\n collection: string\n /** Field → required scalar; every entry must hold (AND). Empty matches all. */\n where: Record<string, string | number | boolean>\n sort?: { field: string; direction?: 'asc' | 'desc' }\n limit?: number\n}\n\n/**\n * Resolves a {@link ListingQuery} to its matching documents in depth-1 delivery\n * shape (EC-255), or `null` when no resolver is wired / the query is unresolvable.\n * The first un-parked **listing binding** (AD-9): a block renders documents from a\n * live query, not a static pick. INJECTED by the host exactly like\n * {@link ResolveRelation} — the Next host bakes a serialized-query→docs map and\n * the studio runs the query live — so the renderer never imports the content/query\n * packages. A `null`/absent result degrades to the block's own empty state, the\n * same graceful degradation as a missing relation target.\n */\nexport type ResolveListing = (query: ListingQuery) => RelationTarget[] | null\n\n/**\n * A composition renderer injected as a PROP (EC-254 transclusion) into any\n * component that declares a `relation` prop — server-safe like the EC-189 embed\n * renderer (a function cannot cross the RSC boundary through a `'use client'`\n * context provider). The implementation calls it on a populated relation target's\n * `blocks`-typed field value (e.g. `project.Reusable` rendering the referenced\n * `reusable`'s `content`), so a referenced document's sub-blocks compose inline.\n */\nexport type RenderBlocks = (value: unknown) => ReactNode\n\n/**\n * Maps namespaced component ids to their React implementations. Implementations receive\n * resolved props plus rendered slot children: the default slot `children` maps to React\n * `children`, and every other named slot is passed as a prop named after the slot.\n */\nexport type ComponentImplementations =\n | Record<string, ComponentType<Record<string, unknown>>>\n | Map<string, ComponentType<Record<string, unknown>>>\n\n/** Everything the renderer needs to turn a node into React, with no builder-only imports. */\nexport interface RenderContext {\n /** Source of component manifests (prop schemas, slots, iterate specs). */\n registry: ComponentRegistry\n /** React implementations keyed by component id. */\n implementations: ComponentImplementations\n /** Injected binding resolver — the renderer's only link to data. */\n resolveBinding: ResolveBinding\n /**\n * Injected asset resolver (EC-195). When set, a static `asset`-typed prop\n * holding an asset id resolves to a {@link RenderAsset} (url + intrinsic\n * dimensions + alt) before reaching the implementation — so an uploaded image\n * placed on a page renders optimized on the host. Unset → asset-typed props\n * pass through unresolved (raw value), the same graceful degradation as a\n * missing binding resolver.\n */\n resolveAsset?: ResolveAsset\n /**\n * Injected relation resolver (EC-254). When set, a static `relation`-typed prop\n * holding a `{ collection, id }` ref (the editor's document pick on a block,\n * e.g. a ProductGrid's `products`) is populated to its depth-1 delivery shape\n * before reaching the implementation — so a block reads `product.title` /\n * `product.gallery[0].url`, not a raw ref. Unset → relation props pass through\n * unresolved (raw ref), the same graceful degradation as a missing asset\n * resolver. Wired by the host to `ContentClient.resolveRelation`.\n */\n resolveRelation?: ResolveRelation\n /**\n * Injected listing resolver (EC-255). When set, a component whose manifest\n * declares a `listing` (e.g. a ProductGrid keyed to a picked `category`) has\n * its declared listing prop populated with the documents the query matches —\n * a live, dynamic grid, not a hand-maintained static relation. Built from the\n * node's filter-source prop via {@link listingQueryOf}; the host runs the query\n * (Next bakes it, the studio runs it live). Unset → the listing prop is an empty\n * array (the block shows its empty state), the same graceful degradation as a\n * missing relation resolver. Wired by the host to `ContentClient.listDocuments`.\n */\n resolveListing?: ResolveListing\n /**\n * Read-content client for self-fetching components (EC-191). When set, the\n * renderer's composite entry points wrap the output in a `ContentClientProvider`\n * so components reach it via `useContentClient()`. Host-injected (live), studio\n * (read), or fixture-backed (tests) — components render real data uniformly.\n */\n content?: ContentClient\n /**\n * The chain of relation-target keys (`collection:id`) currently being\n * TRANSCLUDED through {@link RenderBlocks} (EC-254). Extended each time a\n * component transcludes a populated relation target's blocks; a relation prop\n * whose ref is already in this chain is NOT re-populated, breaking reference\n * cycles (a `reusable` that transitively references itself) without looping.\n * Empty/absent on an ordinary page render — no relation is ever skipped.\n */\n transcludePath?: readonly string[]\n /** Active repeater item scope, when rendering inside a repeater item slot. */\n item?: ItemContext\n /**\n * Optional per-node decorator (brief §8.2). When set, the renderer wraps every\n * rendered node so a host (the Builder) can attach selection markers/overlays.\n * Unset for export/preview — zero overhead and identical output.\n */\n decorateNode?: (node: ComponentNode, rendered: ReactNode) => ReactNode\n}\n\n/** Read an implementation regardless of whether implementations is a Map or a record. */\nexport function getImplementation(\n implementations: ComponentImplementations,\n id: string,\n): ComponentType<Record<string, unknown>> | undefined {\n if (implementations instanceof Map) return implementations.get(id)\n return implementations[id]\n}\n","import type { Condition } from '@elytracms/project-graph'\nimport type { ItemContext, ResolveBinding } from './context'\n\n/**\n * Evaluate a node's render condition. The left operand is resolved from the condition's\n * binding source; the operator is applied against `condition.value`. A thrown resolver\n * error is treated as a failed condition (node renders nothing) rather than a crash.\n */\nexport function evaluateCondition(\n condition: Condition,\n resolveBinding: ResolveBinding,\n item?: ItemContext,\n): boolean {\n let left: unknown\n try {\n left = resolveBinding(condition.source, item)\n } catch {\n return false\n }\n\n switch (condition.operator) {\n case 'truthy':\n return Boolean(left)\n case 'exists':\n return left !== undefined && left !== null\n case 'eq':\n return left === condition.value\n case 'neq':\n return left !== condition.value\n case 'gt':\n return compare(left, condition.value, (a, b) => a > b)\n case 'gte':\n return compare(left, condition.value, (a, b) => a >= b)\n case 'lt':\n return compare(left, condition.value, (a, b) => a < b)\n case 'lte':\n return compare(left, condition.value, (a, b) => a <= b)\n default: {\n // Exhaustiveness guard: unknown operators never render.\n const _never: never = condition.operator\n return Boolean(_never)\n }\n }\n}\n\n/**\n * Numeric ordering comparison. Ordering operators are numeric-only: a non-number operand yields\n * `false`. This matches `@elytracms/data-binding`'s `resolveCondition`, so the canvas and the\n * Builder's inspector/page-tree previews evaluate identically (one canonical model).\n */\nfunction compare(left: unknown, right: unknown, op: (a: number, b: number) => boolean): boolean {\n if (typeof left !== 'number' || typeof right !== 'number') return false\n return op(left, right)\n}\n","'use client'\n\nimport { createContext, createElement, useContext } from 'react'\nimport type { ReactNode } from 'react'\n\n/**\n * Read-only content access for self-fetching components (EC-191). With editor\n * bindings gone (EC-190), dynamic data lives INSIDE dev components: a component\n * reads what it needs from the injected client and renders it. The host provides a\n * live client (Convex-backed), the studio a read client, tests a fixture-backed\n * deterministic one — so the SAME component renders real data on the canvas, at\n * delivery, and in tests (the AGENTS.md determinism rule).\n *\n * The client is **synchronous**: it reads already-loaded content (the host fetches\n * for delivery, the studio pre-loads for preview, the test holds fixtures), which\n * keeps render deterministic and Suspense-free. A component may ALSO fetch arbitrary\n * external content through its own async hooks — the client is one source, not the\n * only one.\n */\nexport interface ContentDocumentView {\n collection: string\n id: string\n values: Record<string, unknown>\n}\n\n/** A resolved asset (EC-191) — id plus delivery-shape url/alt when known. */\nexport interface ContentAssetView {\n id: string\n url?: string\n alt?: string\n}\n\n/** A minimal list query (EC-191). Kept deliberately small for v1. */\nexport interface ContentQuery {\n collection: string\n /** Cap the number of returned documents. */\n limit?: number\n}\n\n/** The read-content contract injected into the render context (EC-191). */\nexport interface ContentClient {\n getDocument(collection: string, id: string): ContentDocumentView | undefined\n listDocuments(query: ContentQuery): ContentDocumentView[]\n resolveAsset(id: string): ContentAssetView | undefined\n}\n\nconst ContentClientContext = createContext<ContentClient | null>(null)\n\n/**\n * Provide a `ContentClient` to the rendered subtree. The renderer wraps its public\n * composite entry points (page/composition) in this when `ctx.content` is set; a\n * host rendering nodes directly can wrap manually.\n */\nexport function ContentClientProvider({\n client,\n children,\n}: {\n client: ContentClient\n children: ReactNode\n}): ReactNode {\n return createElement(ContentClientContext.Provider, { value: client }, children)\n}\n\n/**\n * Read the injected `ContentClient` inside a component implementation (EC-191).\n * Returns `null` when none is provided (e.g. a pure-static render) — a self-fetching\n * component must degrade visibly, never crash, when content access is absent.\n */\nexport function useContentClient(): ContentClient | null {\n return useContext(ContentClientContext)\n}\n\n/**\n * A deterministic, in-memory `ContentClient` over fixed documents + assets (EC-191).\n * The studio preview and tests use it so a self-fetching component renders the same\n * content every time. `limit` is the only query knob in v1.\n */\nexport function createFixtureContentClient(fixtures: {\n documents?: readonly ContentDocumentView[]\n assets?: readonly ContentAssetView[]\n}): ContentClient {\n const docs = fixtures.documents ?? []\n const assets = new Map((fixtures.assets ?? []).map((a) => [a.id, a]))\n return {\n getDocument: (collection, id) =>\n docs.find((d) => d.collection === collection && d.id === id),\n listDocuments: (query) => {\n const matched = docs.filter((d) => d.collection === query.collection)\n return query.limit === undefined ? matched : matched.slice(0, query.limit)\n },\n resolveAsset: (id) => assets.get(id),\n }\n}\n","'use client'\n\nimport { Component } from 'react'\nimport type { ErrorInfo, ReactNode } from 'react'\n\n/**\n * Visible fallback for a node whose component has no manifest or no implementation.\n * Renders instead of throwing so a single bad reference never blanks the page (brief §4.11).\n */\nexport function MissingComponentFallback(props: {\n nodeId: string\n componentId: string\n}): ReactNode {\n return (\n <div\n data-ec-fallback=\"missing-component\"\n data-ec-node-id={props.nodeId}\n data-ec-component-id={props.componentId}\n >\n {`Missing component \"${props.componentId}\" (node ${props.nodeId})`}\n </div>\n )\n}\n\n/** Visible placeholder rendered in the position of a required slot that has no children. */\nexport function MissingSlotPlaceholder(props: { nodeId: string; slot: string }): ReactNode {\n return (\n <div data-ec-fallback=\"missing-slot\" data-ec-node-id={props.nodeId} data-ec-slot={props.slot}>\n {`Missing required slot \"${props.slot}\" (node ${props.nodeId})`}\n </div>\n )\n}\n\n/** Visible fallback for a node that threw while resolving props/bindings or while rendering. */\nexport function RenderErrorFallback(props: { nodeId: string; message?: string }): ReactNode {\n return (\n <div data-ec-fallback=\"render-error\" data-ec-node-id={props.nodeId}>\n {props.message\n ? `Render error in node ${props.nodeId}: ${props.message}`\n : `Render error in node ${props.nodeId}`}\n </div>\n )\n}\n\ninterface ErrorBoundaryProps {\n nodeId: string\n children: ReactNode\n}\n\ninterface ErrorBoundaryState {\n error: Error | null\n}\n\n/**\n * Client-side error boundary: when a descendant component throws during render, this swaps\n * in a visible fallback rather than unmounting the whole tree. Server rendering cannot use\n * boundaries to recover, so the renderer additionally wraps resolution in try/catch.\n */\nexport class RenderErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props)\n this.state = { error: null }\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { error }\n }\n\n override componentDidCatch(_error: Error, _info: ErrorInfo): void {\n // Intentionally swallowed: the fallback is the user-visible signal. Hosts may add\n // their own logging by wrapping this boundary.\n }\n\n override render(): ReactNode {\n if (this.state.error) {\n return <RenderErrorFallback nodeId={this.props.nodeId} message={this.state.error.message} />\n }\n return this.props.children\n }\n}\n","import { createElement, Fragment } from 'react'\nimport type { ReactNode } from 'react'\nimport type { ComponentNode, ProjectGraph, PropValue } from '@elytracms/project-graph'\nimport { DEFAULT_SLOT, OUTLET_SLOT } from '@elytracms/project-graph'\nimport type {\n ComponentManifest,\n ComponentRegistry,\n CompositionSpec,\n IterateSpec,\n ListingSpec,\n} from '@elytracms/component-registry'\nimport { manifestSlots, propValueValidator } from '@elytracms/component-registry'\nimport type { FieldDef } from '@elytracms/cms-core'\nimport type {\n ItemContext,\n ListingQuery,\n RelationTarget,\n RenderContext,\n ResolveRelation,\n} from './context'\nimport { getImplementation } from './context'\nimport type { RichTextEmbedRenderer } from '@elytracms/rich-text'\nimport { ContentClientProvider } from './content-client'\nimport { evaluateCondition } from './condition'\nimport {\n MissingComponentFallback,\n MissingSlotPlaceholder,\n RenderErrorBoundary,\n RenderErrorFallback,\n} from './fallback'\n\n/** Resolved props plus the node's slot children, ready to hand to an implementation. */\ninterface ResolvedRender {\n props: Record<string, unknown>\n slotProps: Record<string, ReactNode>\n children: ReactNode\n}\n\n/**\n * Render a single component node to React. Never throws on a node: missing components,\n * invalid props, missing required slots, and resolver errors all degrade to visible\n * fallbacks (brief §4.11).\n */\nexport function renderNode(node: ComponentNode, ctx: RenderContext): ReactNode {\n // Condition gate — render nothing when false.\n if (node.condition && !evaluateCondition(node.condition, ctx.resolveBinding, ctx.item)) {\n return null\n }\n\n const manifest = ctx.registry.getManifest(node.componentId)\n const implementation = getImplementation(ctx.implementations, node.componentId)\n\n // Missing component: no manifest OR no implementation.\n if (!manifest || !implementation) {\n return decorate(\n ctx,\n node,\n <MissingComponentFallback nodeId={node.id} componentId={node.componentId} />,\n )\n }\n\n let resolved: ResolvedRender\n try {\n resolved = resolveRender(node, manifest, ctx)\n } catch (error) {\n // A thrown resolver (binding/prop) error yields a fallback, not a crash.\n return decorate(ctx, node, <RenderErrorFallback nodeId={node.id} message={messageOf(error)} />)\n }\n\n const element = createElement(\n implementation,\n { ...resolved.props, ...resolved.slotProps, key: node.id },\n resolved.children,\n )\n\n // Wrap each node so a throw during the implementation's own render degrades on the client.\n return decorate(\n ctx,\n node,\n <RenderErrorBoundary key={node.id} nodeId={node.id}>\n {element}\n </RenderErrorBoundary>,\n )\n}\n\n/** Apply the host's optional per-node decorator (Builder selection markers). */\nfunction decorate(ctx: RenderContext, node: ComponentNode, rendered: ReactNode): ReactNode {\n return ctx.decorateNode ? ctx.decorateNode(node, rendered) : rendered\n}\n\n/**\n * Bind a `RichTextEmbedRenderer` (EC-189) to a `RenderContext`: each embedded\n * composition node renders through `renderComposition` with the SAME context, so an\n * embed reuses the EC-015 visible fallbacks, the injected binding resolver, the\n * content client, and any active item scope exactly as on a page.\n *\n * The bound renderer is a FUNCTION closed over `ctx`, so it is injected into the\n * consuming component as a **prop** (see `resolveRender`), never through a\n * `'use client'` React-context provider: a function cannot cross the RSC\n * server→client boundary into a client component, so the provider approach\n * 500s a server-rendered (host) page. A server→server prop is fine, and the\n * studio's client render injects the identical prop the same way.\n */\nexport function createEmbedRenderer(ctx: RenderContext): RichTextEmbedRenderer {\n return (node: ComponentNode) => renderComposition(node, ctx)\n}\n\n/** Whether a manifest declares a `richText` prop — i.e. it may render embeds (EC-189). */\nfunction manifestConsumesEmbeds(manifest: ComponentManifest): boolean {\n return Object.values(manifest.props).some((field) => field.type === 'richText')\n}\n\n/**\n * Bind a blocks renderer to a `RenderContext` (EC-254 transclusion): renders a\n * populated relation target's `blocks` field value as a composition through the\n * SAME `renderComposition` pipeline (EC-015 fallbacks, the injected resolvers, any\n * active item scope), so a referenced document's sub-blocks compose inline exactly\n * like a page's. Like {@link createEmbedRenderer}, it is a FUNCTION closed over\n * `ctx` injected as a PROP (`renderBlocks`), never a `'use client'` context\n * provider — a function cannot cross the RSC boundary into a client component.\n */\nexport function createBlocksRenderer(ctx: RenderContext): (value: unknown) => ReactNode {\n return (value: unknown) => renderComposition(value, ctx)\n}\n\n/** Whether a manifest declares a `relation` prop — i.e. it populates/transcludes (EC-254). */\nfunction manifestConsumesRelations(manifest: ComponentManifest): boolean {\n return Object.values(manifest.props).some((field) => field.type === 'relation')\n}\n\n/** A `{ collection, id }` relation reference, or `null` when the value is not one. */\nfunction relationRefOf(value: unknown): { collection: string; id: string } | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return null\n const { collection, id } = value as { collection?: unknown; id?: unknown }\n return typeof collection === 'string' &&\n collection !== '' &&\n typeof id === 'string' &&\n id !== ''\n ? { collection, id }\n : null\n}\n\n/** Stable cycle-guard key for a relation target. */\nfunction relationKey(ref: { collection: string; id: string }): string {\n return `${ref.collection}:${ref.id}`\n}\n\n/** The cycle-guard keys (`collection:id`) of a node's static relation props (EC-254). */\nfunction nodeRelationKeys(node: ComponentNode, manifest: ComponentManifest): string[] {\n const keys: string[] = []\n for (const [name, value] of Object.entries(node.props ?? {})) {\n if (value.kind !== 'static') continue\n const spec = manifest.props[name]\n if (spec?.type !== 'relation') continue\n const refs =\n spec.cardinality === 'many' ? (Array.isArray(value.value) ? value.value : []) : [value.value]\n for (const raw of refs) {\n const ref = relationRefOf(raw)\n if (ref) keys.push(relationKey(ref))\n }\n }\n return keys\n}\n\n/**\n * Populate a static `relation` prop's stored value to delivery shape (EC-254).\n * `one` → the single populated target, or `undefined` (omit the prop) when the\n * ref is malformed, unresolved (missing/invisible target), or cyclic. `many` →\n * the array of populated targets with such entries dropped. A ref already on the\n * transclude path is skipped — the cycle guard. Mirrors the asset branch's\n * \"resolved object or graceful omission\" contract; the caller only assigns a\n * defined result.\n */\nfunction resolveRelationProp(\n cardinality: 'one' | 'many',\n value: unknown,\n ctx: RenderContext,\n): unknown {\n const resolveOne = (raw: unknown): RelationTarget | null => {\n const ref = relationRefOf(raw)\n if (!ref) return null\n if (ctx.transcludePath?.includes(relationKey(ref))) return null // reference cycle\n return ctx.resolveRelation?.(ref) ?? null\n }\n\n if (cardinality === 'many') {\n const refs = Array.isArray(value) ? value : []\n const out: RelationTarget[] = []\n for (const raw of refs) {\n const target = resolveOne(raw)\n if (target) out.push(target)\n }\n return out\n }\n return resolveOne(value) ?? undefined\n}\n\n/**\n * Wrap a composite render in the `ContentClientProvider` when a content client is\n * injected (EC-191), so self-fetching components reach it via `useContentClient()`.\n * Nested wraps are harmless (inner provider wins with an equivalent value).\n *\n * Note (EC-189): the rich-text embed renderer is NOT wrapped here — it is a\n * function and a `'use client'` provider cannot receive it across the RSC\n * boundary (it threw \"Functions cannot be passed directly to Client Components\"\n * on every server-rendered page). It is injected as a prop in `resolveRender`.\n */\nfunction withContent(ctx: RenderContext, rendered: ReactNode): ReactNode {\n if (ctx.content)\n return <ContentClientProvider client={ctx.content}>{rendered}</ContentClientProvider>\n return rendered\n}\n\n/** Resolve a node's props and slot children. Throws only if a resolver throws (caught upstream). */\nfunction resolveRender(\n node: ComponentNode,\n manifest: ComponentManifest,\n ctx: RenderContext,\n): ResolvedRender {\n const props = resolveProps(node, manifest, ctx)\n\n // EC-189: a component with a `richText` prop (the RichText primitive) renders\n // `componentEmbed` nodes through the renderer. Inject the embed renderer as a\n // prop — server-safe (a server→server function prop), unlike a `'use client'`\n // context provider, which cannot receive a function across the RSC boundary.\n if (manifestConsumesEmbeds(manifest)) props.renderEmbed = createEmbedRenderer(ctx)\n\n // EC-254: a component with a `relation` prop may transclude a populated target's\n // `blocks` field (e.g. `project.Reusable` rendering the referenced `reusable`'s\n // `content`). Inject a composition renderer — server-safe like `renderEmbed` —\n // closed over a context whose cycle-guard path includes THIS node's relation\n // targets, so a transcluded sub-block that references an ancestor target degrades\n // instead of looping. Population above ran with `ctx` (the un-extended path), so\n // the node's OWN targets are populated, never pre-blocked.\n if (manifestConsumesRelations(manifest)) {\n props.renderBlocks = createBlocksRenderer({\n ...ctx,\n transcludePath: [...(ctx.transcludePath ?? []), ...nodeRelationKeys(node, manifest)],\n })\n }\n\n // EC-255: a component whose manifest declares a `listing` renders documents from\n // a LIVE query (a dynamic grid), not a static pick. Build the query from its\n // filter-source prop and inject the resolved documents as the declared prop — the\n // host runs the query (Next bakes it, the studio runs it live); the renderer never\n // executes one. No resolver wired, or no usable pick, yields an empty array, so the\n // block shows its own empty state rather than listing the whole collection.\n if (manifest.listing) {\n const query = listingQueryOf(node, manifest.listing)\n props[manifest.listing.prop] = (query && ctx.resolveListing?.(query)) || []\n }\n\n // Repeater nodes iterate their items prop over the item slot template.\n if (manifest.iterate) {\n return resolveRepeater(node, manifest, manifest.iterate, props, ctx)\n }\n\n // Composition hosts render a block-field value (a ComponentNode tree) as children.\n if (manifest.composition) {\n return resolveComposition(manifest.composition, props, ctx)\n }\n\n const { children, slotProps } = renderSlots(node, manifest, ctx)\n return { props, slotProps, children }\n}\n\n/**\n * Render a composition host: the resolved `valueProp` holds a stored composition\n * (a `ComponentNode` tree), which becomes the component's children via\n * `renderComposition` — so a `blocks` field value composes inside a page/template\n * exactly like authored nodes (EC-188, AD-12). Mirrors `resolveRepeater`: the raw\n * value stays in `props` (harmless; the implementation typically ignores it) and the\n * rendered tree is handed over as `children`.\n */\nfunction resolveComposition(\n spec: CompositionSpec,\n props: Record<string, unknown>,\n ctx: RenderContext,\n): ResolvedRender {\n return { props, slotProps: {}, children: renderComposition(props[spec.valueProp], ctx) }\n}\n\n/** Resolve every prop of a node into a concrete runtime value. */\nfunction resolveProps(\n node: ComponentNode,\n manifest: ComponentManifest,\n ctx: RenderContext,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n const entries = Object.entries(node.props ?? {})\n const isSpread = (value: PropValue): boolean =>\n value.kind === 'binding' && value.binding.mode === 'spread'\n // Apply spread bindings first, then explicit props — so a named static/value prop always wins\n // over a same-named spread key, predictably and independent of authoring order (EC-089).\n for (const [name, value] of entries)\n if (isSpread(value)) resolveProp(name, value, manifest, ctx, out)\n for (const [name, value] of entries)\n if (!isSpread(value)) resolveProp(name, value, manifest, ctx, out)\n return out\n}\n\n/**\n * A value an `asset` prop can carry verbatim instead of an asset id: an absolute\n * URL (`https://…`, protocol-relative `//…`), a root-relative path (`/…`), or an\n * inline `data:`/`blob:` source. Lets the Image primitive keep accepting plain\n * URLs (back-compat: `Image.src` was a free `text` prop before EC-195) and keeps\n * the renderer usable with no asset store wired.\n */\nfunction isUrlLike(value: string): boolean {\n return (\n /^(https?:)?\\/\\//.test(value) ||\n value.startsWith('/') ||\n value.startsWith('data:') ||\n value.startsWith('blob:')\n )\n}\n\n/**\n * Collect the asset ids a node tree resolves through `resolveAsset` (EC-205): the\n * STATIC `asset`-typed props holding a real asset id (not a passthrough URL/path).\n * Mirrors {@link resolveProp}'s asset branch exactly, so the set is COMPLETE (no\n * referenced asset is missed → no broken image) and MINIMAL (only ids the renderer\n * would resolve). Bound asset props resolve via bindings, and document asset FIELDS\n * resolve separately — neither uses the baked asset list, so neither is collected.\n * Lets a delivery host page-scope the baked assets to exactly what a page uses.\n */\nexport function collectReferencedAssetIds(\n node: ComponentNode,\n registry: ComponentRegistry,\n into: Set<string> = new Set(),\n): Set<string> {\n const manifest = registry.getManifest(node.componentId)\n if (manifest) {\n for (const [name, value] of Object.entries(node.props ?? {})) {\n if (value.kind !== 'static') continue\n const spec = manifest.props[name]\n if (spec?.type === 'asset') {\n const raw = value.value\n if (typeof raw === 'string' && raw !== '' && !isUrlLike(raw)) into.add(raw)\n } else if (spec?.type === 'object') {\n // EC-253: a gallery/repeater prop nests asset ids — collect them too, so the\n // delivery host bakes every referenced asset and no nested image is missed.\n collectObjectPropAssetIds(spec.fields, spec.cardinality, value.value, into)\n }\n }\n }\n for (const children of Object.values(node.slots ?? {})) {\n for (const child of children) collectReferencedAssetIds(child, registry, into)\n }\n return into\n}\n\n/**\n * Walk a composition (a page's blocks + its layout root) and POPULATE every static\n * `relation` prop it references into a serializable `{ \"collection:id\": target }`\n * map (EC-254) — the relation analog of {@link collectReferencedAssetIds}. A\n * delivery host bakes this into its (serializable) render outcome and rebuilds\n * `RenderContext.resolveRelation` from the map inside the RSC, exactly as it does\n * with the page-scoped asset list — because a function (the content client) can\n * ride neither the data cache nor the RSC server→client boundary.\n *\n * Transclusion-aware + cycle-safe: a populated target's composition-shaped fields\n * (a `reusable`'s `content` blocks, which a component renders inline via\n * `renderBlocks`) are recursively walked so those blocks' own relations are\n * populated too; a target already in the map is never re-walked, so a reference\n * cycle terminates. `resolveRelation` is the injected populate (depth-1) — passed\n * in, never imported, so this stays free of the content/persistence packages.\n *\n * Optional `refKeys` records the `collection:id` of EVERY referenced pick — even\n * one that resolved to `null` (an unpublished/missing target) — so a delivery host\n * can cache-tag the page by it (EC-254/EC-146): editing or publishing a referenced\n * document then invalidates the embedding page, including a previously-unpublished\n * pick that should appear the moment it publishes.\n */\nexport function collectReferencedRelations(\n nodes: readonly ComponentNode[],\n registry: ComponentRegistry,\n resolveRelation: ResolveRelation,\n into: Record<string, RelationTarget> = {},\n refKeys?: Set<string>,\n): Record<string, RelationTarget> {\n for (const node of nodes) {\n const manifest = registry.getManifest(node.componentId)\n if (manifest) {\n for (const [name, value] of Object.entries(node.props ?? {})) {\n if (value.kind !== 'static') continue\n const spec = manifest.props[name]\n if (spec?.type === 'relation') {\n const refs =\n spec.cardinality === 'many'\n ? Array.isArray(value.value)\n ? value.value\n : []\n : [value.value]\n for (const raw of refs) {\n const ref = relationRefOf(raw)\n if (!ref) continue\n const key = relationKey(ref)\n refKeys?.add(key) // tag every pick, even an unresolved one (negative dependency)\n if (key in into) continue // already populated → also terminates cycles\n const target = resolveRelation(ref)\n if (!target) continue\n into[key] = target\n // Transclusion: recurse into the target's composition-shaped fields so a\n // reusable's inlined `content` blocks get their own relations populated.\n for (const fieldValue of Object.values(target)) {\n const childNodes = compositionRoots(fieldValue)\n if (childNodes.length > 0) {\n collectReferencedRelations(childNodes, registry, resolveRelation, into, refKeys)\n }\n }\n }\n } else if (spec?.type === 'object' && value.value != null) {\n // EC-256: a `relation` nested in an `object` prop (a link object's `page`\n // ref) is baked + tagged like a top-level pick, so renaming the target page\n // invalidates the embedding page. Depth-1, NO transclusion — a link target\n // is read for its path, not inlined (else link-following bakes the whole\n // linked-site relation graph).\n collectObjectPropRelations(\n spec.fields,\n spec.cardinality,\n value.value,\n resolveRelation,\n into,\n refKeys,\n )\n }\n }\n // A composition host stores its composed blocks in `node.props[valueProp]` (a\n // blocks VALUE), NOT `node.slots` — and `manifestSlots` excludes the valueProp\n // — so the slot recursion below misses them. Walk those composed nodes too, so\n // a relation prop on a block nested inside a composition is collected (and thus\n // baked for the host), matching what the render path resolves at depth.\n if (manifest.composition) {\n const composed = node.props?.[manifest.composition.valueProp]\n if (composed?.kind === 'static') {\n collectReferencedRelations(\n compositionRoots(composed.value),\n registry,\n resolveRelation,\n into,\n refKeys,\n )\n }\n }\n }\n for (const children of Object.values(node.slots ?? {})) {\n collectReferencedRelations(children, registry, resolveRelation, into, refKeys)\n }\n }\n return into\n}\n\n/**\n * Build the {@link ListingQuery} a node's `listing` manifest declares (EC-255),\n * or `null` when its filter-source prop carries no usable pick — the block then\n * renders empty rather than listing the whole collection. Reads the `fromProp`\n * STATIC pick (a relation value `{ collection, id }` reduced to its id, or a bare\n * id string) and binds it to the listed collection's filter `field`. Pure (node\n * props + manifest only; no content import), so the Next bake and the studio live\n * resolver build the IDENTICAL query — and thus agree on the baked cache key.\n */\nexport function listingQueryOf(node: ComponentNode, spec: ListingSpec): ListingQuery | null {\n const pick = node.props?.[spec.filter.fromProp]\n if (!pick || pick.kind !== 'static') return null\n const ref = relationRefOf(pick.value)\n const id = ref ? ref.id : typeof pick.value === 'string' && pick.value !== '' ? pick.value : null\n if (id === null) return null\n const query: ListingQuery = { collection: spec.collection, where: { [spec.filter.field]: id } }\n if (spec.sort) query.sort = spec.sort\n if (spec.limit !== undefined) query.limit = spec.limit\n return query\n}\n\n/**\n * Deterministic cache key for a {@link ListingQuery} (EC-255): a stable JSON shape\n * (where-keys sorted, sort/limit normalized) so the Next host can key its baked\n * `query → docs` map and the rebuilt resolver looks the listing up by the SAME key\n * the renderer's {@link listingQueryOf} produces. Mirrors `@elytracms/content`'s\n * `serializeListQuery`, kept local so the renderer takes no content dependency.\n */\nexport function serializeListingQuery(query: ListingQuery): string {\n const where: Record<string, string | number | boolean> = {}\n for (const key of Object.keys(query.where).sort()) {\n const value = query.where[key]\n if (value !== undefined) where[key] = value\n }\n return JSON.stringify({\n collection: query.collection,\n where,\n sort: query.sort ? { field: query.sort.field, direction: query.sort.direction ?? 'asc' } : null,\n limit: query.limit ?? null,\n })\n}\n\n/**\n * Walk a composition (a page's blocks + its layout root) and resolve every\n * `listing` a node declares into a serializable `{ serializedQuery: docs[] }` map\n * (EC-255) — the listing analog of {@link collectReferencedRelations}. A delivery\n * host bakes this into its (serializable) render outcome and rebuilds\n * `RenderContext.resolveListing` from the map inside the RSC, exactly as it does\n * with relations and the page-scoped asset list, because the content client (which\n * runs the query) can ride neither the data cache nor the RSC server→client\n * boundary.\n *\n * `runListing` is the injected query executor (the host's `listDocuments`) — passed\n * in, never imported, so this stays free of the content/persistence packages. The\n * key is {@link serializeListingQuery}, so two nodes with the same query share a\n * single execution.\n *\n * Transclusion-aware + cycle-safe, exactly like {@link collectReferencedRelations}:\n * a composition host's composed blocks, child slots, AND a populated relation\n * target's composition-shaped fields (a `reusable`'s `content` a block transcludes\n * via `renderBlocks`) are all walked — so a listing nested inside a transcluded\n * reusable is baked too, matching what the render path resolves at depth. Without\n * this the Next host would render such a grid empty (the studio's live resolver\n * still works) AND drop its collection-membership cache tag. `resolveRelation` is\n * the injected populate (depth-1) used to reach those transcluded fields; a target\n * already visited is never re-walked, so a reference cycle terminates.\n */\nexport function collectReferencedListings(\n nodes: readonly ComponentNode[],\n registry: ComponentRegistry,\n runListing: (query: ListingQuery) => RelationTarget[],\n resolveRelation: ResolveRelation,\n into: Record<string, RelationTarget[]> = {},\n visitedRelations: Set<string> = new Set(),\n): Record<string, RelationTarget[]> {\n for (const node of nodes) {\n const manifest = registry.getManifest(node.componentId)\n if (manifest?.listing) {\n const query = listingQueryOf(node, manifest.listing)\n if (query) {\n const key = serializeListingQuery(query)\n if (!(key in into)) into[key] = runListing(query)\n }\n }\n if (manifest) {\n // Transclusion: a static `relation` prop (e.g. `Reusable.element`) inlines its\n // target's composition-shaped fields via `renderBlocks` at render — walk them\n // so a listing nested in a transcluded reusable's content is baked too (the\n // listing analog of `collectReferencedRelations`' transclusion recursion).\n for (const [name, value] of Object.entries(node.props ?? {})) {\n if (value.kind !== 'static') continue\n const spec = manifest.props[name]\n if (spec?.type !== 'relation') continue\n const refs =\n spec.cardinality === 'many' ? (Array.isArray(value.value) ? value.value : []) : [value.value]\n for (const raw of refs) {\n const ref = relationRefOf(raw)\n if (!ref) continue\n const relKey = relationKey(ref)\n if (visitedRelations.has(relKey)) continue // already walked → terminates cycles\n visitedRelations.add(relKey)\n const target = resolveRelation(ref)\n if (!target) continue\n for (const fieldValue of Object.values(target)) {\n const childNodes = compositionRoots(fieldValue)\n if (childNodes.length > 0) {\n collectReferencedListings(\n childNodes,\n registry,\n runListing,\n resolveRelation,\n into,\n visitedRelations,\n )\n }\n }\n }\n }\n }\n if (manifest?.composition) {\n const composed = node.props?.[manifest.composition.valueProp]\n if (composed?.kind === 'static') {\n collectReferencedListings(\n compositionRoots(composed.value),\n registry,\n runListing,\n resolveRelation,\n into,\n visitedRelations,\n )\n }\n }\n for (const children of Object.values(node.slots ?? {})) {\n collectReferencedListings(children, registry, runListing, resolveRelation, into, visitedRelations)\n }\n }\n return into\n}\n\n/** Collect the asset ids nested inside an `object` prop value (mirrors {@link resolveObjectProps}). */\nfunction collectObjectPropAssetIds(\n fields: readonly FieldDef[],\n cardinality: 'one' | 'many',\n value: unknown,\n into: Set<string>,\n): void {\n const items = cardinality === 'many' ? (Array.isArray(value) ? value : []) : [value]\n for (const item of items) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) continue\n const record = item as Record<string, unknown>\n for (const sub of fields) {\n const sv = record[sub.name]\n if (sub.type === 'asset' && typeof sv === 'string' && sv !== '' && !isUrlLike(sv)) into.add(sv)\n else if (sub.type === 'object' && sv != null)\n collectObjectPropAssetIds(sub.fields, sub.cardinality, sv, into)\n }\n }\n}\n\n/**\n * Populate (depth-1) the `relation` refs nested inside an `object` prop value into\n * the relations bake map + refKeys (EC-256) — the relation analog of\n * {@link collectObjectPropAssetIds}, so a `page` ref inside a link object\n * (`buttons[].link.page`) is baked and cache-tagged exactly like a top-level pick.\n * Recurses into nested `object` subfields. UNLIKE the top-level relation walk it\n * does NOT transclude the target's composition-shaped fields: a link's target page\n * is read for its path (depth-1), never inlined — following it would bake the whole\n * linked-site relation graph into every embedding page. `refKeys` tags every pick\n * (even an unresolved one) so publishing/renaming the target invalidates the page.\n */\nfunction collectObjectPropRelations(\n fields: readonly FieldDef[],\n cardinality: 'one' | 'many',\n value: unknown,\n resolveRelation: ResolveRelation,\n into: Record<string, RelationTarget>,\n refKeys: Set<string> | undefined,\n): void {\n const items = cardinality === 'many' ? (Array.isArray(value) ? value : []) : [value]\n for (const item of items) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) continue\n const record = item as Record<string, unknown>\n for (const sub of fields) {\n const sv = record[sub.name]\n if (sub.type === 'relation' && sv != null) {\n const refs = sub.cardinality === 'many' ? (Array.isArray(sv) ? sv : []) : [sv]\n for (const raw of refs) {\n const ref = relationRefOf(raw)\n if (!ref) continue\n const key = relationKey(ref)\n refKeys?.add(key)\n if (key in into) continue\n const target = resolveRelation(ref)\n if (target) into[key] = target // depth-1 only — never transclude a link target\n }\n } else if (sub.type === 'object' && sv != null) {\n collectObjectPropRelations(sub.fields, sub.cardinality, sv, resolveRelation, into, refKeys)\n }\n }\n }\n}\n\n/**\n * Resolve the `asset` and `relation` subfields nested inside an `object` / repeater\n * prop value to delivery shape (EC-253 assets, EC-256 relations). The top-level\n * branches of {@link resolveProp} only resolve a TOP-LEVEL `asset`/`relation` prop,\n * so an asset nested in an `object` (a gallery's `images[].image`) or a relation\n * nested in one (a link object's `buttons[].link.page`) would otherwise reach the\n * implementation as a raw id/ref. This walks the prop's declared subfields:\n *\n * - `asset` → `ctx.resolveAsset` (url-like values pass through; an unresolved id\n * drops the subfield), exactly as the top level does.\n * - `relation` → `ctx.resolveRelation` depth-1 via {@link resolveRelationProp}, so\n * the implementation reads the target's fields (e.g. a link's `page.slug` → a live\n * path). No resolver → the raw ref passes through (graceful degradation); an\n * unresolved `one` drops the subfield. Depth-1 only — a nested relation is never\n * transcluded (a link target is read, not inlined).\n *\n * and recurses into nested `object` subfields. Pure; non-object items pass through.\n */\nfunction resolveObjectProps(\n fields: readonly FieldDef[],\n cardinality: 'one' | 'many',\n value: unknown,\n ctx: RenderContext,\n): unknown {\n const items = cardinality === 'many' ? (Array.isArray(value) ? value : []) : [value]\n const resolvedItems = items.map((item) => {\n if (!item || typeof item !== 'object' || Array.isArray(item)) return item\n const next: Record<string, unknown> = { ...(item as Record<string, unknown>) }\n for (const sub of fields) {\n const sv = next[sub.name]\n if (sub.type === 'asset' && typeof sv === 'string') {\n if (sv === '' || isUrlLike(sv)) continue\n const resolved = ctx.resolveAsset?.(sv)\n if (resolved) next[sub.name] = resolved\n else delete next[sub.name]\n } else if (sub.type === 'relation' && sv != null) {\n if (!ctx.resolveRelation) continue // no resolver → leave the raw ref (degrade)\n const resolved = resolveRelationProp(sub.cardinality, sv, ctx)\n if (resolved !== undefined) next[sub.name] = resolved\n else delete next[sub.name] // unresolved `one` → drop the subfield\n } else if (sub.type === 'object' && sv != null) {\n next[sub.name] = resolveObjectProps(sub.fields, sub.cardinality, sv, ctx)\n }\n }\n return next\n })\n return cardinality === 'many' ? resolvedItems : resolvedItems[0]\n}\n\n/** Resolve a single prop into `out`, applying invalid-static-prop fallbacks and spread. */\nfunction resolveProp(\n name: string,\n value: PropValue,\n manifest: ComponentManifest,\n ctx: RenderContext,\n out: Record<string, unknown>,\n): void {\n const spec = manifest.props[name]\n\n if (value.kind === 'static') {\n // Validate against the prop's field-def (EC-190); on failure use the field's\n // `default` or omit — the EC-015 invalid-static-prop visible fallback.\n const validate = propValueValidator(manifest, name)\n if (validate && !validate(value.value)) {\n if (spec?.default !== undefined) out[name] = spec.default\n // else: omit the prop entirely and continue.\n return\n }\n // EC-195: an `asset`-typed prop stores an asset id; resolve it to a usable\n // asset (url + intrinsic dimensions + alt) so an uploaded image renders\n // optimized. A raw URL/path value passes through (back-compat, and so the\n // renderer never *requires* an asset store). A missing asset omits the prop\n // — the implementation shows its own empty/fallback state, never a crash.\n if (spec?.type === 'asset' && typeof value.value === 'string') {\n const raw = value.value\n if (raw === '' || isUrlLike(raw)) {\n out[name] = raw\n return\n }\n const resolved = ctx.resolveAsset?.(raw)\n if (resolved) out[name] = resolved\n // else omit — unresolved asset id → visible fallback in the implementation.\n return\n }\n // EC-253/EC-256: an `object` / repeater prop may nest `asset` subfields (a\n // gallery's `images[].image`) or `relation` subfields (a link object's\n // `buttons[].link.page`); resolve those to delivery shape so the implementation\n // reads `item.image.url` / `link.page.slug`, mirroring the top-level branches at\n // every depth.\n if (spec?.type === 'object' && value.value != null) {\n out[name] = resolveObjectProps(spec.fields, spec.cardinality, value.value, ctx)\n return\n }\n // EC-254: a `relation` prop stores a `{ collection, id }` ref (or an array for\n // `many`) — the editor's document pick on a block. Populate it to the target's\n // depth-1 delivery shape so the implementation reads resolved fields, not a raw\n // ref. Mirrors the asset branch: unresolved → omit (`one`) / drop (`many`); no\n // resolver wired → the raw ref passes through (the same graceful degradation).\n if (spec?.type === 'relation') {\n if (!ctx.resolveRelation) {\n out[name] = value.value\n return\n }\n const resolved = resolveRelationProp(spec.cardinality, value.value, ctx)\n if (resolved !== undefined) out[name] = resolved\n return\n }\n out[name] = value.value\n return\n }\n\n // Bound prop — resolve through the injected resolver (may throw; caught by caller).\n // NB (EC-254): relation population is intentionally STATIC-only — a relation prop\n // is the editor's document pick (v1 props are static, AD-12; prop bindings are\n // parked). A bound value passes through as the resolver returns it, never through\n // `resolveRelationProp`, so a relation prop should not be bound until prop bindings\n // and their population are designed together.\n const resolved = ctx.resolveBinding(value.binding, ctx.item)\n if (value.binding.mode === 'spread') {\n if (resolved && typeof resolved === 'object' && !Array.isArray(resolved)) {\n Object.assign(out, resolved as Record<string, unknown>)\n }\n return\n }\n out[name] = resolved\n}\n\n/** Render the named slots of a node: `children` maps to React children, others to props. */\nfunction renderSlots(\n node: ComponentNode,\n manifest: ComponentManifest,\n ctx: RenderContext,\n): { children: ReactNode; slotProps: Record<string, ReactNode> } {\n const slots = node.slots ?? {}\n const slotProps: Record<string, ReactNode> = {}\n let children: ReactNode = renderSlotChildren(slots[DEFAULT_SLOT], ctx)\n\n // EC-190: `blocks` props are slots too (named child regions); `manifestSlots`\n // folds them in (a no-op for manifests without blocks props).\n const declaredSlots = manifestSlots(manifest)\n for (const slotSpec of declaredSlots) {\n if (slotSpec.name === DEFAULT_SLOT) continue\n const nodes = slots[slotSpec.name]\n if ((!nodes || nodes.length === 0) && slotSpec.required) {\n // Missing required named slot — visible placeholder in that slot position.\n slotProps[slotSpec.name] = <MissingSlotPlaceholder nodeId={node.id} slot={slotSpec.name} />\n continue\n }\n slotProps[slotSpec.name] = renderSlotChildren(nodes, ctx)\n }\n\n // Pass through any node slots not declared on the manifest (e.g. a Switch's dynamic\n // `case:*` slots), so dynamic-slot components receive their children as props.\n const declared = new Set(declaredSlots.map((s) => s.name))\n for (const [name, nodes] of Object.entries(slots)) {\n if (name === DEFAULT_SLOT || declared.has(name)) continue\n slotProps[name] = renderSlotChildren(nodes, ctx)\n }\n\n // Missing required default slot — placeholder as children.\n const defaultSpec = declaredSlots.find((s) => s.name === DEFAULT_SLOT)\n const defaultNodes = slots[DEFAULT_SLOT]\n if (defaultSpec?.required && (!defaultNodes || defaultNodes.length === 0)) {\n children = <MissingSlotPlaceholder nodeId={node.id} slot={DEFAULT_SLOT} />\n }\n\n return { children, slotProps }\n}\n\n/**\n * Render an ordered list of slot child nodes (array order preserved). Each\n * entry is wrapped in a Fragment keyed by the node id: `renderNode`'s return\n * value may be an unkeyed fallback element (missing component, render error)\n * or have its key stripped by a host `decorateNode`, and unkeyed entries in\n * this array would trigger React's `unique \"key\" prop` warning on every page.\n */\nfunction renderSlotChildren(nodes: ComponentNode[] | undefined, ctx: RenderContext): ReactNode {\n if (!nodes || nodes.length === 0) return null\n return (\n <Fragment>\n {nodes.map((child) => (\n <Fragment key={child.id}>{renderNode(child, ctx)}</Fragment>\n ))}\n </Fragment>\n )\n}\n\n/**\n * Render a repeater: resolve `itemsProp` to an array and render the `itemSlot` template\n * once per item, with `ItemContext` set so `repeaterItem`-mode bindings resolve against\n * the item. The repeater implementation receives the rendered items as `children`.\n */\nfunction resolveRepeater(\n node: ComponentNode,\n manifest: ComponentManifest,\n iterate: IterateSpec,\n props: Record<string, unknown>,\n ctx: RenderContext,\n): ResolvedRender {\n const itemsValue = props[iterate.itemsProp]\n const items = Array.isArray(itemsValue) ? itemsValue : []\n const template = node.slots?.[iterate.itemSlot]\n\n const slotSpec = manifest.slots.find((s) => s.name === iterate.itemSlot)\n if ((!template || template.length === 0) && slotSpec?.required) {\n // No item template but the slot is required — visible placeholder, no iteration.\n return {\n props,\n slotProps: {},\n children: <MissingSlotPlaceholder nodeId={node.id} slot={iterate.itemSlot} />,\n }\n }\n\n const rendered = items.map((item, index) => {\n const itemCtx: RenderContext = { ...ctx, item: { item, index } satisfies ItemContext }\n return (\n <Fragment key={index}>\n {(template ?? []).map((child) => (\n // Keyed per template node for the same reason as renderSlotChildren.\n <Fragment key={child.id}>{renderNode(child, itemCtx)}</Fragment>\n ))}\n </Fragment>\n )\n })\n\n return { props, slotProps: {}, children: <Fragment>{rendered}</Fragment> }\n}\n\n/**\n * Render a composition FIELD VALUE (EC-188, AD-12): one `ComponentNode` root or an\n * ordered list of them — a `blocks` field's stored value. Each root renders through\n * `renderNode` with the SAME `RenderContext`, so the EC-015 visible fallbacks, the\n * injected binding resolver, and any active item scope all apply exactly as on a\n * page. An empty/absent value renders nothing (the host component owns its own empty\n * state). Roots are keyed by id — `renderNode` may return an unkeyed fallback —\n * mirroring `renderSlotChildren`.\n *\n * This is the shared delivery primitive for every composition surface: the block\n * field (here), and later the page collection (EC-187) and rich-text embeds (EC-189).\n */\nexport function renderComposition(value: unknown, ctx: RenderContext): ReactNode {\n const roots = compositionRoots(value)\n if (roots.length === 0) return null\n return withContent(\n ctx,\n <Fragment>\n {roots.map((root) => (\n <Fragment key={root.id}>{renderNode(root, ctx)}</Fragment>\n ))}\n </Fragment>,\n )\n}\n\n/** Coerce a stored composition value (one node, many, or absent) to a root list. */\nfunction compositionRoots(value: unknown): ComponentNode[] {\n if (Array.isArray(value)) return value.filter(isComponentNode)\n if (isComponentNode(value)) return [value]\n return []\n}\n\n/** Structural ComponentNode guard — the stored value is opaque at the type level. */\nfunction isComponentNode(value: unknown): value is ComponentNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { id?: unknown }).id === 'string' &&\n typeof (value as { componentId?: unknown }).componentId === 'string'\n )\n}\n\n/**\n * Render a composition (`blocks`) field value composed INTO a graph layout\n * (EC-187): the page collection's delivery primitive. The composition renders\n * via `renderComposition` (the same per-node pipeline + EC-015 fallbacks), and\n * the result is injected into the layout root's `outlet` slot — so a\n * page-collection document's `body` composes inside its layout chrome.\n *\n * Degrades, never crashes: an `undefined`/unknown `layoutId`, or a graph with no\n * matching layout, renders the bare composition (no layout chrome) rather than\n * blanking the page. `withContent` wraps the output so a `ContentClient` on\n * `ctx` propagates to self-fetching blocks (EC-191).\n */\nexport function renderCompositionInLayout(\n graph: ProjectGraph,\n layoutId: string | undefined,\n value: unknown,\n ctx: RenderContext,\n): ReactNode {\n const layout = layoutId ? graph.layouts.find((l) => l.id === layoutId) : undefined\n // No layout selected, or the selected layout is absent from the graph: render\n // the bare composition rather than blanking the page.\n if (!layout) return withContent(ctx, renderComposition(value, ctx))\n\n // With a layout, inject the composition's roots into the layout root's outlet\n // slot, so the composition renders through the layout's chrome via the\n // identical per-node pipeline. `compositionRoots` coerces the stored value\n // (one node, many, or absent) to the outlet's `ComponentNode[]`.\n const root = injectNodesIntoOutlet(layout.root, compositionRoots(value))\n return withContent(ctx, renderNode(root, ctx))\n}\n\n/**\n * Produce a layout tree with `nodes` inserted into the layout root's `outlet`\n * slot. The original graph is never mutated.\n */\nfunction injectNodesIntoOutlet(root: ComponentNode, nodes: ComponentNode[]): ComponentNode {\n return {\n ...root,\n slots: {\n ...(root.slots ?? {}),\n [OUTLET_SLOT]: nodes,\n },\n }\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n","import { z } from 'zod'\nimport { jsonValueSchema } from '@elytracms/project-graph'\nimport type { JsonValue } from '@elytracms/project-graph'\n\n/**\n * Rich-text storage format (brief §7.6).\n *\n * The on-disk shape is intentionally ProseMirror/TipTap-shaped: a JSON document is\n * a tree of nodes `{ type, attrs?, content?, marks?, text? }`. Keeping the storage\n * format identical to ProseMirror's lets a TipTap editor plug in later behind the\n * {@link RichTextAdapter} seam without a migration — the editor reads/writes the\n * exact same JSON this package validates and renders.\n *\n * Nothing in this module imports TipTap. The format is modelled directly so the\n * spike has no required dependency on a paid or cloud editor service.\n */\n\n/** The schema version this build of the package reads and writes. Stored per value. */\nexport const RICH_TEXT_SCHEMA_VERSION = 1\n\n/** Attribute bag carried by a node or mark. Plain JSON only — never runtime handles. */\nexport const richTextAttrsSchema = z.record(z.string(), jsonValueSchema)\nexport type RichTextAttrs = Record<string, JsonValue>\n\n/**\n * A mark applied to inline text (bold, italic, code, link, …). Marks are\n * ProseMirror-shaped: a `type` plus an optional attribute bag (e.g. a link `href`).\n */\nexport const richTextMarkSchema = z.object({\n type: z.string().min(1),\n attrs: richTextAttrsSchema.optional(),\n})\nexport type RichTextMark = z.infer<typeof richTextMarkSchema>\n\n/**\n * A single node in the document tree.\n *\n * - Leaf text nodes carry `text` (and optional `marks`).\n * - Block/inline nodes carry `content` (ordered children) and/or `attrs`.\n *\n * The schema deliberately keeps `type` an open string: a document referencing an\n * unknown node type still *parses* so the renderer can show a visible fallback and\n * tooling can report a structured issue — mirroring how the project graph keeps\n * component ids as open strings (see `@elytracms/project-graph`).\n */\nexport interface RichTextNode {\n type: string\n attrs?: RichTextAttrs\n content?: RichTextNode[]\n marks?: RichTextMark[]\n text?: string\n}\n\nexport const richTextNodeSchema: z.ZodType<RichTextNode> = z.lazy(() =>\n z.object({\n type: z.string().min(1),\n attrs: richTextAttrsSchema.optional(),\n content: z.array(richTextNodeSchema).optional(),\n marks: z.array(richTextMarkSchema).optional(),\n text: z.string().optional(),\n }),\n)\n\n/** The root document node. By ProseMirror convention its `type` is `doc`. */\nexport const richTextDocSchema = z.object({\n type: z.literal('doc'),\n content: z.array(richTextNodeSchema).default([]),\n})\nexport type RichTextDoc = z.infer<typeof richTextDocSchema>\n\n/**\n * A stored rich-text value. Every value carries the schema {@link version} it was\n * written under so old content stays readable across format changes (brief §7.6).\n */\nexport const richTextValueSchema = z.object({\n /** Schema version this value was written under. */\n version: z.number().int().nonnegative(),\n doc: richTextDocSchema,\n})\nexport type RichTextValue = z.infer<typeof richTextValueSchema>\n\n/** Wrap a document tree in a versioned value, stamping the current schema version. */\nexport function createRichTextValue(doc: RichTextDoc): RichTextValue {\n return { version: RICH_TEXT_SCHEMA_VERSION, doc }\n}\n\n/** Convenience constructor for an empty (but valid) versioned value. */\nexport function emptyRichTextValue(): RichTextValue {\n return createRichTextValue({ type: 'doc', content: [] })\n}\n\nexport type ParseRichTextResult =\n | { ok: true; value: RichTextValue }\n | { ok: false; error: z.ZodError }\n\n/**\n * Parse a rich-text value from a JSON string or already-parsed object. Never throws\n * on invalid input — returns a structured failure instead (validation is\n * first-class; see AGENTS.md).\n */\nexport function parseRichTextValue(input: string | unknown): ParseRichTextResult {\n let json: unknown\n try {\n json = typeof input === 'string' ? JSON.parse(input) : input\n } catch {\n json = undefined\n }\n const result = richTextValueSchema.safeParse(json)\n return result.success ? { ok: true, value: result.data } : { ok: false, error: result.error }\n}\n\n/** Serialize a rich-text value to JSON, parsing first so output is always valid. */\nexport function serializeRichTextValue(value: RichTextValue): string {\n return JSON.stringify(richTextValueSchema.parse(value))\n}\n\n/** True when a value's stored version matches the version this build understands. */\nexport function isCompatibleRichTextVersion(value: RichTextValue): boolean {\n return value.version === RICH_TEXT_SCHEMA_VERSION\n}\n","import { componentNodeSchema } from '@elytracms/project-graph'\nimport type { ComponentNode } from '@elytracms/project-graph'\nimport type { JsonValue } from '@elytracms/project-graph'\nimport type { RichTextDoc, RichTextNode } from './schema'\n\n/**\n * Rich-text component embeds (EC-189, AD-12).\n *\n * A `componentEmbed` is a custom *block* node in the rich-text storage format\n * whose single `attrs.node` holds a composition value — one `ComponentNode` (an\n * embedded registry component plus its static field-value props). It is the third\n * place constrained composition lives (after the page collection and `blocks`\n * fields): a registry component embedded in long-form prose, Portable-Text-style.\n *\n * The embed serializes through the EXISTING storage format with no schema change:\n * `richTextNodeSchema` keeps `type` an open string and `attrs` a plain-JSON bag, a\n * `ComponentNode` is plain JSON (Zod-validated, no runtime handles), so an embed\n * round-trips byte-for-byte through `parseRichTextValue`/`serializeRichTextValue`.\n * The helpers below give the embed a named type, a typed accessor, and a\n * constructor so consumers (renderer, extractor, validator) never reach into the\n * raw `attrs` bag. An embed whose `attrs.node` is missing or malformed degrades to\n * the renderer's visible fallback — never a crash, never silent (AGENTS.md).\n */\n\n/** The storage `node.type` for an embedded registry component. */\nexport const COMPONENT_EMBED_NODE_TYPE = 'componentEmbed'\n\n/**\n * A rich-text embed node, narrowed: a `componentEmbed` whose `attrs.node` is the\n * embedded composition value. `attrs.node` is typed `JsonValue` at the storage\n * layer (the format never carries runtime handles); read it through\n * {@link embeddedComponentNode}, which validates it as a `ComponentNode`.\n */\nexport interface ComponentEmbedNode extends RichTextNode {\n type: typeof COMPONENT_EMBED_NODE_TYPE\n attrs?: { node?: JsonValue } & Record<string, JsonValue>\n}\n\n/** Structural test for a `componentEmbed` node (by `node.type`). */\nexport function isComponentEmbedNode(node: RichTextNode): node is ComponentEmbedNode {\n return node.type === COMPONENT_EMBED_NODE_TYPE\n}\n\n/**\n * Read the embedded composition value (a single `ComponentNode`) from a\n * `componentEmbed` node, validating it via `componentNodeSchema`. Returns\n * `undefined` for an embed with no/malformed `attrs.node` (the renderer shows its\n * visible fallback; validation reports the structured issue). Never throws.\n */\nexport function embeddedComponentNode(node: RichTextNode): ComponentNode | undefined {\n if (!isComponentEmbedNode(node)) return undefined\n const raw = node.attrs?.node\n const parsed = componentNodeSchema.safeParse(raw)\n return parsed.success ? parsed.data : undefined\n}\n\n/**\n * Build a `componentEmbed` storage node wrapping a single composition root. The\n * node carries no `content` (an embed is an atom — the embedded component owns its\n * own children through the composition's slots, not the rich-text tree).\n */\nexport function componentEmbedNode(node: ComponentNode): ComponentEmbedNode {\n return { type: COMPONENT_EMBED_NODE_TYPE, attrs: { node: node as unknown as JsonValue } }\n}\n\n/**\n * One `componentEmbed` occurrence found while walking a rich-text document: the\n * raw storage node, the embedded composition value (or `undefined` when malformed),\n * and the `/`-joined content-index node path within the document tree (e.g.\n * `doc/content/2`). The path mirrors the reference-extraction encoding so validation\n * findings and where-used entries key the same location. Walks arbitrary depth.\n */\nexport interface RichTextEmbedOccurrence {\n node: ComponentEmbedNode\n embedded: ComponentNode | undefined\n nodePath: string\n}\n\n/**\n * Collect every `componentEmbed` in a rich-text document, at any nesting depth.\n * Pure + structural; never throws. The returned `nodePath` is `doc`-rooted and\n * `/`-joined (`doc/content/<i>/content/<j>/...`), matching the persistence\n * reference-extraction path convention so a validation finding's `nodePath` lines\n * up with the where-used entry for the same embed.\n */\nexport function collectComponentEmbeds(doc: RichTextDoc): RichTextEmbedOccurrence[] {\n const out: RichTextEmbedOccurrence[] = []\n const walk = (nodes: readonly RichTextNode[] | undefined, path: string): void => {\n if (!nodes) return\n nodes.forEach((node, i) => {\n const here = `${path}/content/${i}`\n if (isComponentEmbedNode(node)) {\n out.push({ node, embedded: embeddedComponentNode(node), nodePath: here })\n }\n walk(node.content, here)\n })\n }\n walk(doc.content, 'doc')\n return out\n}\n","import type { ReactElement, ReactNode } from 'react'\nimport type { RichTextNode } from './schema'\n\n/**\n * Registration hooks for rendering custom rich-text nodes (brief §7.6).\n *\n * Two flavours, mirroring TipTap's node groups:\n * - **block** components — full-width blocks (e.g. a callout, a CTA card) that the\n * builder surfaces from the component registry as custom blocks.\n * - **inline** components — mentions, badges, tokens, and data references that sit\n * inside a paragraph alongside text.\n *\n * The renderer (see `render.tsx`) is server-safe and only knows the *shape* of a\n * registry, not where it comes from. Consumers build a registry from their own\n * component manifests and pass it in, keeping the renderer decoupled from the\n * project's component registry package.\n */\n\n/** Props handed to a custom node renderer. */\nexport interface CustomNodeRenderProps {\n /** The raw storage node, so the component can read its `attrs`. */\n node: RichTextNode\n /**\n * Already-rendered children (present for block components with inline/leaf\n * content). Inline atoms typically ignore this.\n */\n children?: ReactNode\n}\n\nexport type CustomNodeRenderer = (props: CustomNodeRenderProps) => ReactElement | null\n\nexport interface CustomNodeDefinition {\n /** The storage `node.type` this renderer handles, e.g. `callout` or `mention`. */\n type: string\n group: 'block' | 'inline'\n render: CustomNodeRenderer\n}\n\n/**\n * A read-only registry of custom node renderers. Look-ups are keyed by storage\n * `node.type`; the renderer falls back to a visible placeholder when a type is not\n * registered and is not a built-in.\n */\nexport interface RichTextRegistry {\n has(type: string): boolean\n get(type: string): CustomNodeDefinition | undefined\n /** Whether a registered custom node renders inline (vs. as a block). */\n isInline(type: string): boolean\n}\n\n/** Build an immutable {@link RichTextRegistry} from a list of definitions. */\nexport function createRichTextRegistry(\n definitions: readonly CustomNodeDefinition[] = [],\n): RichTextRegistry {\n const byType = new Map<string, CustomNodeDefinition>()\n for (const def of definitions) {\n // Last registration wins, matching how a builder would override a block.\n byType.set(def.type, def)\n }\n return {\n has: (type) => byType.has(type),\n get: (type) => byType.get(type),\n isInline: (type) => byType.get(type)?.group === 'inline',\n }\n}\n\n/** An empty registry — convenient default for callers with no custom blocks. */\nexport const emptyRichTextRegistry: RichTextRegistry = createRichTextRegistry()\n","import { Fragment, createElement } from 'react'\nimport type { ReactElement, ReactNode } from 'react'\nimport type { ComponentNode, JsonValue } from '@elytracms/project-graph'\nimport type { RichTextDoc, RichTextMark, RichTextNode, RichTextValue } from './schema'\nimport { COMPONENT_EMBED_NODE_TYPE, embeddedComponentNode } from './embed'\nimport { emptyRichTextRegistry } from './registry'\nimport type { RichTextRegistry } from './registry'\n\n/**\n * Server-safe read-only renderer: rich-text storage JSON → React (brief §7.6).\n *\n * \"Server-safe\" means this module imports only `react` (no `react-dom`, no browser\n * globals, no editor bundle), so an exported Next.js app can render content on the\n * server. It returns React elements; callers turn them into markup with\n * `react-dom/server` or hydrate them as-is.\n *\n * Unknown node types never crash: each one renders a visible fallback and is\n * collected as a structured {@link RichTextRenderIssue} (validation is first-class).\n */\n\n/**\n * A structured problem found while rendering: an unknown node type, or a\n * `componentEmbed` whose embedded composition value is missing/malformed (EC-189).\n */\nexport interface RichTextRenderIssue {\n code: 'unknown-node' | 'invalid-embed'\n message: string\n /** The offending storage `node.type`. */\n nodeType: string\n /** Index path into the document tree (content indices), for tooling. */\n path: number[]\n}\n\n/**\n * Renders an embedded composition value (a single `ComponentNode`, EC-189) to\n * React. INJECTED by the host so the rich-text package stays free of\n * `@elytracms/runtime-renderer` (which already depends on rich-text via the RichText\n * primitive). The host binds this to `renderComposition(node, renderContext)`, so\n * an embed renders byte-equivalent to the same component in a page/block field.\n * Omit to fall back to the visible placeholder (e.g. server-safe validation passes\n * with no registry/implementations available).\n */\nexport type RichTextEmbedRenderer = (node: ComponentNode) => ReactNode\n\nexport interface RenderRichTextOptions {\n /** Registry of custom block/inline renderers. Defaults to empty. */\n registry?: RichTextRegistry\n /**\n * Renders `componentEmbed` nodes (EC-189). Bound by the host to\n * `renderComposition`. When absent, embeds show the visible fallback.\n */\n renderEmbed?: RichTextEmbedRenderer\n /**\n * Collector invoked once per unknown node encountered. Lets tooling surface\n * issues without re-walking the tree.\n */\n onIssue?: (issue: RichTextRenderIssue) => void\n /** className applied to the wrapping element of the document. */\n className?: string\n}\n\n/** Built-in node types this renderer understands without any registry. */\nexport const BUILTIN_NODE_TYPES = [\n 'doc',\n 'paragraph',\n 'text',\n 'heading',\n 'bulletList',\n 'orderedList',\n 'listItem',\n 'blockquote',\n 'codeBlock',\n 'hardBreak',\n 'horizontalRule',\n 'image',\n 'embed',\n // EC-189: an embedded registry component (a composition value). Built-in so a\n // document carrying embeds is never flagged \"unknown-node\" — its render is\n // delegated to the injected embed renderer (see `RichTextEmbedRenderer`).\n COMPONENT_EMBED_NODE_TYPE,\n] as const\n\n/** Built-in mark types this renderer understands. */\nexport const BUILTIN_MARK_TYPES = ['bold', 'italic', 'code', 'link', 'strike', 'underline'] as const\n\nfunction attrString(value: JsonValue | undefined): string | undefined {\n return typeof value === 'string' ? value : undefined\n}\n\nfunction attrNumber(value: JsonValue | undefined): number | undefined {\n return typeof value === 'number' ? value : undefined\n}\n\n/** Wrap inline content in the elements implied by its marks, innermost-first. */\nfunction applyMarks(content: ReactNode, marks: readonly RichTextMark[] | undefined, key: string): ReactNode {\n if (!marks || marks.length === 0) return content\n return marks.reduce<ReactNode>((acc, mark, i) => {\n const markKey = `${key}-m${i}`\n switch (mark.type) {\n case 'bold':\n return createElement('strong', { key: markKey }, acc)\n case 'italic':\n return createElement('em', { key: markKey }, acc)\n case 'code':\n return createElement('code', { key: markKey }, acc)\n case 'strike':\n return createElement('s', { key: markKey }, acc)\n case 'underline':\n return createElement('u', { key: markKey }, acc)\n case 'link': {\n const href = attrString(mark.attrs?.href) ?? '#'\n const target = attrString(mark.attrs?.target)\n const rel = target === '_blank' ? 'noopener noreferrer' : attrString(mark.attrs?.rel)\n return createElement('a', { key: markKey, href, ...(target ? { target } : {}), ...(rel ? { rel } : {}) }, acc)\n }\n default:\n // Unknown mark: keep the text visible, wrapped in a tagged span so it is\n // inspectable but never lost.\n return createElement('span', { key: markKey, 'data-unknown-mark': mark.type }, acc)\n }\n }, content)\n}\n\ninterface RenderCtx {\n registry: RichTextRegistry\n renderEmbed: RichTextEmbedRenderer | undefined\n onIssue: ((issue: RichTextRenderIssue) => void) | undefined\n}\n\n/** The visible fallback shown for an embed the renderer cannot resolve (EC-189). */\nfunction invalidEmbedFallback(key: string): ReactElement {\n return createElement(\n 'div',\n { key, 'data-invalid-embed': '', className: 'rich-text-invalid-embed', role: 'note' },\n 'Invalid embedded component.',\n )\n}\n\nfunction renderChildren(nodes: readonly RichTextNode[] | undefined, ctx: RenderCtx, path: number[]): ReactNode[] {\n if (!nodes) return []\n return nodes.map((child, i) => renderNode(child, ctx, [...path, i]))\n}\n\n/** The visible fallback shown for any node type the renderer cannot resolve. */\nfunction unknownFallback(node: RichTextNode, key: string): ReactElement {\n return createElement(\n 'div',\n { key, 'data-unknown-node': node.type, className: 'rich-text-unknown', role: 'note' },\n `Unknown content block: ${node.type}`,\n )\n}\n\nfunction renderNode(node: RichTextNode, ctx: RenderCtx, path: number[]): ReactNode {\n const key = `n-${path.join('-')}`\n\n // Leaf text node.\n if (node.type === 'text') {\n return applyMarks(node.text ?? '', node.marks, key)\n }\n\n switch (node.type) {\n case 'paragraph':\n return createElement('p', { key }, ...renderChildren(node.content, ctx, path))\n case 'heading': {\n const level = attrNumber(node.attrs?.level)\n const clamped = level && level >= 1 && level <= 6 ? level : 1\n return createElement(`h${clamped}`, { key }, ...renderChildren(node.content, ctx, path))\n }\n case 'bulletList':\n return createElement('ul', { key }, ...renderChildren(node.content, ctx, path))\n case 'orderedList':\n return createElement('ol', { key }, ...renderChildren(node.content, ctx, path))\n case 'listItem':\n return createElement('li', { key }, ...renderChildren(node.content, ctx, path))\n case 'blockquote':\n return createElement('blockquote', { key }, ...renderChildren(node.content, ctx, path))\n case 'codeBlock': {\n const language = attrString(node.attrs?.language)\n return createElement(\n 'pre',\n { key },\n createElement(\n 'code',\n language ? { className: `language-${language}` } : {},\n ...renderChildren(node.content, ctx, path),\n ),\n )\n }\n case 'hardBreak':\n return createElement('br', { key })\n case 'horizontalRule':\n return createElement('hr', { key })\n case 'image': {\n const src = attrString(node.attrs?.src) ?? ''\n const alt = attrString(node.attrs?.alt) ?? ''\n const title = attrString(node.attrs?.title)\n return createElement('img', { key, src, alt, ...(title ? { title } : {}) })\n }\n case 'embed': {\n // Generic media/embed: an iframe by URL (e.g. video, map). Server-safe.\n const src = attrString(node.attrs?.src) ?? ''\n const title = attrString(node.attrs?.title) ?? 'Embedded content'\n return createElement('iframe', {\n key,\n src,\n title,\n loading: 'lazy',\n 'data-embed-provider': attrString(node.attrs?.provider) ?? undefined,\n })\n }\n case COMPONENT_EMBED_NODE_TYPE: {\n // EC-189: an embedded registry component. Resolve the embedded composition\n // value and delegate to the injected embed renderer (bound to\n // `renderComposition`), so the embed renders identically to the same\n // component in a page/block field. A missing renderer or a malformed embed\n // degrades to the visible fallback — never a crash, never silent.\n const embedded = embeddedComponentNode(node)\n if (!embedded) {\n ctx.onIssue?.({\n code: 'invalid-embed',\n message: 'Component embed is missing a valid embedded component node.',\n nodeType: node.type,\n path,\n })\n return invalidEmbedFallback(key)\n }\n if (!ctx.renderEmbed) return invalidEmbedFallback(key)\n return createElement(Fragment, { key }, ctx.renderEmbed(embedded))\n }\n default: {\n // Custom node from the registry (block or inline).\n const def = ctx.registry.get(node.type)\n if (def) {\n const children = node.content && node.content.length > 0 ? renderChildren(node.content, ctx, path) : undefined\n const element = def.render({ node, children })\n return element ? createElement(Fragment, { key }, element) : null\n }\n // Unknown: visible fallback + structured issue. Never throws.\n ctx.onIssue?.({\n code: 'unknown-node',\n message: `No renderer registered for rich-text node type \"${node.type}\".`,\n nodeType: node.type,\n path,\n })\n return unknownFallback(node, key)\n }\n }\n}\n\n/**\n * Render a parsed rich-text document tree to a React element. Pure: no DOM access.\n * The wrapping element is a `div.rich-text` so consumers can scope styles.\n */\nexport function renderRichTextDoc(doc: RichTextDoc, options: RenderRichTextOptions = {}): ReactElement {\n const ctx: RenderCtx = {\n registry: options.registry ?? emptyRichTextRegistry,\n renderEmbed: options.renderEmbed,\n onIssue: options.onIssue,\n }\n const children = renderChildren(doc.content, ctx, [])\n return createElement(\n 'div',\n { className: options.className ? `rich-text ${options.className}` : 'rich-text' },\n ...children,\n )\n}\n\n/** Render a versioned rich-text value (convenience over {@link renderRichTextDoc}). */\nexport function renderRichTextValue(value: RichTextValue, options: RenderRichTextOptions = {}): ReactElement {\n return renderRichTextDoc(value.doc, options)\n}\n\n/**\n * Walk a document and collect every unknown-node issue *without* rendering. Useful\n * for pre-flight validation (e.g. before export) where you only want the issues.\n */\nexport function findUnknownNodes(doc: RichTextDoc, registry: RichTextRegistry = emptyRichTextRegistry): RichTextRenderIssue[] {\n const issues: RichTextRenderIssue[] = []\n const builtins = new Set<string>(BUILTIN_NODE_TYPES)\n const walk = (nodes: readonly RichTextNode[] | undefined, path: number[]): void => {\n if (!nodes) return\n nodes.forEach((node, i) => {\n const here = [...path, i]\n if (!builtins.has(node.type) && !registry.has(node.type)) {\n issues.push({\n code: 'unknown-node',\n message: `No renderer registered for rich-text node type \"${node.type}\".`,\n nodeType: node.type,\n path: here,\n })\n }\n walk(node.content, here)\n })\n }\n walk(doc.content, [])\n return issues\n}\n","import { createElement } from 'react'\nimport type { JsonValue } from '@elytracms/project-graph'\nimport { RICH_TEXT_SCHEMA_VERSION, createRichTextValue } from './schema'\nimport type { RichTextDoc, RichTextNode, RichTextValue } from './schema'\nimport { createRichTextRegistry } from './registry'\nimport type { CustomNodeDefinition, RichTextRegistry } from './registry'\n\n/**\n * Fixtures for the rich-text spike (brief §7.6: \"fixtures for every custom block\").\n *\n * Every important rendered state is reproducible from these fixtures, per the\n * determinism convention in AGENTS.md.\n */\n\nfunction str(value: JsonValue | undefined): string {\n return typeof value === 'string' ? value : ''\n}\n\n// ---- Custom block + inline definitions -----------------------------------\n\n/**\n * `callout` — a custom *block* component (e.g. surfaced from the project\n * component registry). Reads a `tone` and renders its inline children.\n */\nexport const calloutBlock: CustomNodeDefinition = {\n type: 'callout',\n group: 'block',\n render: ({ node, children }) =>\n createElement(\n 'aside',\n { className: 'callout', 'data-tone': str(node.attrs?.tone) || 'info', role: 'note' },\n children,\n ),\n}\n\n/**\n * `mention` — a custom *inline* atom (a data reference / @-mention). Renders a\n * compact badge from its `label` and `id` attrs.\n */\nexport const mentionInline: CustomNodeDefinition = {\n type: 'mention',\n group: 'inline',\n render: ({ node }) =>\n createElement(\n 'span',\n { className: 'mention', 'data-mention-id': str(node.attrs?.id) },\n `@${str(node.attrs?.label)}`,\n ),\n}\n\n/** A registry wired with the sample custom block + inline definitions. */\nexport const sampleRichTextRegistry: RichTextRegistry = createRichTextRegistry([\n calloutBlock,\n mentionInline,\n])\n\n// ---- Sample documents -----------------------------------------------------\n\n/**\n * A representative document exercising headings, marks, lists, quote, code, a\n * link, an image, an embed, plus the custom block and inline atom.\n */\nexport const sampleDoc: RichTextDoc = {\n type: 'doc',\n content: [\n { type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: 'Elytra' }] },\n {\n type: 'paragraph',\n content: [\n { type: 'text', text: 'A ' },\n { type: 'text', text: 'code-first', marks: [{ type: 'bold' }] },\n { type: 'text', text: ' website builder with ' },\n { type: 'text', text: 'rich text', marks: [{ type: 'italic' }] },\n { type: 'text', text: ' and ' },\n { type: 'text', text: 'inline code', marks: [{ type: 'code' }] },\n { type: 'text', text: '.' },\n ],\n },\n {\n type: 'paragraph',\n content: [\n { type: 'text', text: 'See the ' },\n { type: 'text', text: 'project brief', marks: [{ type: 'link', attrs: { href: 'https://example.com/brief' } }] },\n { type: 'text', text: ' for details.' },\n ],\n },\n {\n type: 'bulletList',\n content: [\n { type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'First point' }] }] },\n { type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Second point' }] }] },\n ],\n },\n {\n type: 'orderedList',\n content: [\n { type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Step one' }] }] },\n { type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Step two' }] }] },\n ],\n },\n { type: 'blockquote', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Stay determined.' }] }] },\n { type: 'codeBlock', attrs: { language: 'ts' }, content: [{ type: 'text', text: 'const x = 1' }] },\n { type: 'image', attrs: { src: 'https://example.com/a.png', alt: 'Diagram' } },\n { type: 'embed', attrs: { src: 'https://example.com/video', provider: 'video', title: 'Demo video' } },\n {\n type: 'callout',\n attrs: { tone: 'warning' },\n content: [{ type: 'text', text: 'Heads up: this is a custom block.' }],\n },\n {\n type: 'paragraph',\n content: [\n { type: 'text', text: 'Owned by ' },\n { type: 'mention', attrs: { id: 'user-1', label: 'ada' } },\n { type: 'text', text: '.' },\n ],\n },\n ],\n}\n\n/** The same sample content as a stored, versioned value. */\nexport const sampleRichTextValue: RichTextValue = createRichTextValue(sampleDoc)\n\n/** A document containing an unknown node type, to exercise fallback rendering. */\nexport const docWithUnknownNode: RichTextDoc = {\n type: 'doc',\n content: [\n { type: 'paragraph', content: [{ type: 'text', text: 'Before.' }] },\n { type: 'mysteryWidget', attrs: { foo: 'bar' } } as RichTextNode,\n { type: 'paragraph', content: [{ type: 'text', text: 'After.' }] },\n ],\n}\n\n/** A value at a future, incompatible schema version (for version checks). */\nexport const futureVersionValue: RichTextValue = {\n version: RICH_TEXT_SCHEMA_VERSION + 1,\n doc: { type: 'doc', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'newer' }] }] },\n}\n","import type { ReactNode } from 'react'\nimport { defineComponent } from '@elytracms/component-registry'\nimport {\n parseRichTextValue,\n renderRichTextValue,\n sampleRichTextRegistry,\n} from '@elytracms/rich-text'\nimport type { RichTextValue, RichTextEmbedRenderer } from '@elytracms/rich-text'\nimport type { JsonValue } from '@elytracms/project-graph'\n\n/**\n * RichText — the rich-text content primitive (EC-159). Its `content` prop is a\n * stored `@elytracms/rich-text` value (the versioned, ProseMirror-shaped storage\n * JSON); rendering goes through the package's server-safe renderer with the\n * project's custom block/inline registry, so custom blocks render identically\n * on the canvas, in fixtures, and in an exported app. Unknown node types\n * degrade to the renderer's visible fallback — never a crash, never silent.\n *\n * The prop is flagged `inlineEditable`: the builder canvas edits the rendered\n * element in place (EC-158 semantics extended to rich text), committing back\n * to the same storage format.\n */\n\n/**\n * The custom block/inline registry the primitive renders with. The sample\n * registry (callout block + mention inline) stands in for project-registered\n * blocks, mirroring how `project.*` components stand in for project code.\n */\nexport const richTextPrimitiveRegistry = sampleRichTextRegistry\n\n/**\n * Stored rich-text values are plain JSON by construction (Zod-validated, no\n * runtime handles), but `RichTextNode` is an interface without an index\n * signature, so the structural `JsonValue` assignment needs this one cast.\n */\nfunction asJson(value: RichTextValue): JsonValue {\n return value as unknown as JsonValue\n}\n\n/** Default content for a freshly inserted RichText node. */\nexport const RICH_TEXT_DEFAULT_VALUE: RichTextValue = {\n version: 1,\n doc: {\n type: 'doc',\n content: [\n {\n type: 'paragraph',\n content: [{ type: 'text', text: 'Rich text. Select to format, double-click to edit.' }],\n },\n ],\n },\n}\n\n/** A fixture document exercising marks, a link, a list, and the custom blocks. */\nconst RICH_TEXT_FIXTURE_VALUE: RichTextValue = {\n version: 1,\n doc: {\n type: 'doc',\n content: [\n { type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: 'Rich text block' }] },\n {\n type: 'paragraph',\n content: [\n { type: 'text', text: 'Formatted ' },\n { type: 'text', text: 'bold', marks: [{ type: 'bold' }] },\n { type: 'text', text: ' and ' },\n { type: 'text', text: 'italic', marks: [{ type: 'italic' }] },\n { type: 'text', text: ' copy with a ' },\n { type: 'text', text: 'link', marks: [{ type: 'link', attrs: { href: 'https://example.com' } }] },\n { type: 'text', text: '.' },\n ],\n },\n {\n type: 'callout',\n attrs: { tone: 'info' },\n content: [{ type: 'text', text: 'A custom block, rendered by the project registry.' }],\n },\n ],\n },\n}\n\nexport function RichText(props: Record<string, unknown> & { children?: ReactNode }): ReactNode {\n // The embed renderer (EC-189), injected by the renderer as a prop (bound to\n // `renderComposition`). A prop — not a `'use client'` React context — keeps this\n // server-safe: the renderer runs in the host's RSC pass, and a function cannot\n // cross the server→client boundary into a context provider. When present,\n // `componentEmbed` nodes render through the same pipeline as a page/block field;\n // when absent (a bare render), embeds degrade to the visible fallback.\n const renderEmbed =\n typeof props.renderEmbed === 'function'\n ? (props.renderEmbed as RichTextEmbedRenderer)\n : undefined\n // Unset content renders the manifest default (the renderer omits unset\n // props rather than applying defaults — mirrors Heading/Text fallbacks).\n const parsed = parseRichTextValue(props.content ?? RICH_TEXT_DEFAULT_VALUE)\n if (!parsed.ok) {\n // Schema-invalid static values are normally replaced by the manifest\n // default before render; this guards bound values — visibly.\n return (\n <div data-ec-primitive=\"RichText\" className=\"rich-text-invalid\" role=\"note\">\n Invalid rich-text content.\n </div>\n )\n }\n return (\n <div data-ec-primitive=\"RichText\">\n {renderRichTextValue(parsed.value, { registry: richTextPrimitiveRegistry, renderEmbed })}\n </div>\n )\n}\n\nexport const RichTextManifest = defineComponent({\n id: 'base.primitives.RichText',\n namespace: 'base.primitives',\n title: 'Rich Text',\n category: 'content',\n description: 'Formatted long-form content stored in the rich-text format.',\n props: {\n content: {\n // The structured @elytracms/rich-text storage value (EC-159); validated by\n // the renderer's parse guard rather than a scalar string check.\n type: 'richText',\n context: 'prop',\n default: asJson(RICH_TEXT_DEFAULT_VALUE),\n // Rich-text content prop, editable in place on the canvas (EC-159).\n form: { label: 'Content', inlineEditable: true },\n },\n },\n slots: [],\n fixtures: [\n { name: 'Default' },\n { name: 'Formatted', props: { content: asJson(RICH_TEXT_FIXTURE_VALUE) } },\n ],\n})\n","import { createElement } from 'react'\nimport type { ComponentType, CSSProperties, ReactNode } from 'react'\nimport {\n CONTAINER_ALIGNMENTS,\n GRID_MAX_COLUMNS,\n GRID_MIN_COLUMNS,\n SPACING_TOKEN_NAMES,\n spacingTokenCss,\n} from '@elytracms/project-graph'\nimport type { ContainerAlignment } from '@elytracms/project-graph'\nimport { defineComponent } from '@elytracms/component-registry'\nimport type { ComponentManifest } from '@elytracms/component-registry'\nimport { ComponentRegistry } from '@elytracms/component-registry'\nimport type { ComponentImplementations } from './context'\nimport { RichText, RichTextManifest } from './rich-text'\n\n/**\n * Common shape for primitive implementations: resolved props (arbitrary keys) plus React\n * children for the default slot and any named-slot props.\n */\ntype PrimitiveProps = Record<string, unknown> & { children?: ReactNode }\n\nfunction asString(value: unknown, fallback = ''): string {\n return typeof value === 'string' ? value : fallback\n}\n\n// ---------------------------------------------------------------------------\n// Layout-container styling (EC-161) — gap/alignment resolve from the canonical\n// design-token spacing scale; legacy numeric gaps (`n` → `n * 4px`) stay\n// renderable so pre-token graphs keep their layout.\n// ---------------------------------------------------------------------------\n\nfunction gapCss(value: unknown): string | undefined {\n if (typeof value === 'string') return spacingTokenCss(value)\n if (typeof value === 'number' && Number.isFinite(value) && value > 0) return `${value * 4}px`\n return undefined\n}\n\nconst ALIGN_ITEMS: Record<ContainerAlignment, CSSProperties['alignItems']> = {\n start: 'flex-start',\n center: 'center',\n end: 'flex-end',\n stretch: 'stretch',\n}\n\n/** `alignItems` for a container `align` prop; undefined for `stretch` (the CSS default) or junk. */\nfunction alignItemsCss(value: unknown): CSSProperties['alignItems'] {\n if (value === 'start' || value === 'center' || value === 'end') return ALIGN_ITEMS[value]\n return undefined\n}\n\nconst SPACING_OPTIONS = SPACING_TOKEN_NAMES.map((name) => ({ label: name, value: name }))\nconst ALIGN_OPTIONS = CONTAINER_ALIGNMENTS.map((name) => ({ label: name, value: name }))\n\n// ---------------------------------------------------------------------------\n// Container — a generic block wrapper with a single default slot.\n// ---------------------------------------------------------------------------\n\nfunction Container(props: PrimitiveProps): ReactNode {\n // The default `children` slot and the layout `outlet` slot both render here; the outlet\n // is where `renderCompositionInLayout` injects the page body when this Container is a layout root.\n return (\n <div data-ec-primitive=\"Container\">\n {props.children}\n {props.outlet as ReactNode}\n </div>\n )\n}\n\nconst ContainerManifest = defineComponent({\n id: 'base.primitives.Container',\n namespace: 'base.primitives',\n title: 'Container',\n category: 'layout',\n props: {},\n // The outlet is filled by page injection, so it is not authored-required.\n slots: [{ name: 'children' }, { name: 'outlet' }],\n})\n\n// ---------------------------------------------------------------------------\n// Stack — flex layout container (EC-161): direction, token-bound gap, alignment.\n// ---------------------------------------------------------------------------\n\nfunction Stack(props: PrimitiveProps): ReactNode {\n const style: CSSProperties = {\n display: 'flex',\n flexDirection: props.direction === 'horizontal' ? 'row' : 'column',\n }\n const gap = gapCss(props.gap)\n if (gap !== undefined) style.gap = gap\n const alignItems = alignItemsCss(props.align)\n if (alignItems !== undefined) style.alignItems = alignItems\n return (\n <div data-ec-primitive=\"Stack\" style={style}>\n {props.children}\n </div>\n )\n}\n\nconst StackManifest = defineComponent({\n id: 'base.primitives.Stack',\n namespace: 'base.primitives',\n title: 'Stack',\n category: 'layout',\n props: {\n direction: {\n type: 'select',\n context: 'prop',\n default: 'vertical',\n options: [\n { value: 'vertical', label: 'Vertical' },\n { value: 'horizontal', label: 'Horizontal' },\n ],\n form: { label: 'Direction' },\n },\n gap: {\n // A design-token spacing step name (EC-161); legacy numeric gaps still render.\n type: 'select',\n context: 'prop',\n default: '4',\n options: SPACING_OPTIONS,\n form: { label: 'Gap' },\n },\n align: {\n type: 'select',\n context: 'prop',\n default: 'stretch',\n options: ALIGN_OPTIONS,\n form: { label: 'Align' },\n },\n },\n slots: [{ name: 'children' }],\n designTokens: ['space.gap'],\n})\n\n// ---------------------------------------------------------------------------\n// Grid — CSS grid container (EC-161): column count, token-bound gap, alignment.\n// ---------------------------------------------------------------------------\n\nfunction asColumns(value: unknown): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) return GRID_MIN_COLUMNS\n return Math.min(Math.max(GRID_MIN_COLUMNS, Math.floor(value)), GRID_MAX_COLUMNS)\n}\n\n/**\n * Responsive defaults (EC-163): below this viewport width a Grid's columns\n * stack into one. 640px (the Tailwind `sm` boundary) sits between the\n * builder's deterministic preview widths — phone (390px) stacks, tablet\n * (768px) keeps columns.\n */\nexport const GRID_MOBILE_BREAKPOINT_PX = 640\n\n/**\n * The stack-on-mobile rule a stacking Grid carries with it. A **viewport media\n * query** (not a container query), deliberately: the builder canvas renders\n * into an iframe — a true viewport — so constraining the iframe to the phone\n * width makes this exact rule fire in the preview; and the identical markup\n * server-renders in `@elytracms/next` (App Router SSR) with no client JS, no\n * extra stylesheet wiring, and no `container-type` context that every consumer\n * would otherwise have to guarantee around every grid. The rule is emitted as\n * an inline `<style>` child of the grid itself (style elements generate no\n * grid item), so the behavior is self-contained wherever the implementation\n * renders — canvas iframe portal, static markup, or RSC payload — and the\n * `!important` lets the stylesheet rule beat the grid's own inline column\n * template. Opted-out grids (`stackOnMobile: false`) carry neither the\n * attribute nor the rule.\n */\nexport const GRID_STACK_CSS = `@media (max-width: ${GRID_MOBILE_BREAKPOINT_PX}px){[data-ec-grid-stack]{grid-template-columns:minmax(0,1fr) !important}}`\n\nfunction Grid(props: PrimitiveProps): ReactNode {\n const style: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: `repeat(${asColumns(props.columns)}, minmax(0, 1fr))`,\n }\n const gap = gapCss(props.gap)\n if (gap !== undefined) style.gap = gap\n const alignItems = alignItemsCss(props.align)\n if (alignItems !== undefined) style.alignItems = alignItems\n // Stack-on-mobile is the default; only the explicit opt-out keeps columns.\n const stacksOnMobile = props.stackOnMobile !== false\n return (\n <div\n data-ec-primitive=\"Grid\"\n {...(stacksOnMobile ? { 'data-ec-grid-stack': '' } : {})}\n style={style}\n >\n {stacksOnMobile ? <style>{GRID_STACK_CSS}</style> : null}\n {props.children}\n </div>\n )\n}\n\nconst GridManifest = defineComponent({\n id: 'base.primitives.Grid',\n namespace: 'base.primitives',\n title: 'Grid',\n category: 'layout',\n props: {\n columns: {\n type: 'number',\n context: 'prop',\n default: 2,\n validation: { min: GRID_MIN_COLUMNS, max: GRID_MAX_COLUMNS },\n form: { label: 'Columns' },\n },\n gap: {\n type: 'select',\n context: 'prop',\n default: '4',\n options: SPACING_OPTIONS,\n form: { label: 'Gap' },\n },\n align: {\n type: 'select',\n context: 'prop',\n default: 'stretch',\n options: ALIGN_OPTIONS,\n form: { label: 'Align' },\n },\n stackOnMobile: {\n // Responsive default (EC-163): stacking is on unless explicitly opted out.\n type: 'boolean',\n context: 'prop',\n default: true,\n form: { label: 'Stack on phones' },\n },\n },\n slots: [{ name: 'children' }],\n designTokens: ['space.gap'],\n})\n\n// ---------------------------------------------------------------------------\n// Text — a paragraph of text driven by the `value` prop.\n// ---------------------------------------------------------------------------\n\nfunction Text(props: PrimitiveProps): ReactNode {\n return <p data-ec-primitive=\"Text\">{asString(props.value)}</p>\n}\n\nconst TextManifest = defineComponent({\n id: 'base.primitives.Text',\n namespace: 'base.primitives',\n title: 'Text',\n category: 'content',\n props: {\n value: {\n type: 'text',\n context: 'prop',\n default: '',\n // Plain-text content prop, editable in place on the canvas (EC-158).\n form: { label: 'Text', control: 'textarea', inlineEditable: true },\n },\n },\n slots: [],\n})\n\n// ---------------------------------------------------------------------------\n// Heading — h1..h6 heading driven by `text` + `level`. Needed by the sample graph.\n// ---------------------------------------------------------------------------\n\nfunction Heading(props: PrimitiveProps): ReactNode {\n const level =\n typeof props.level === 'number' && props.level >= 1 && props.level <= 6 ? props.level : 2\n const tag = `h${level}`\n return createElement(tag, { 'data-ec-primitive': 'Heading' }, asString(props.text))\n}\n\nconst HeadingManifest = defineComponent({\n id: 'base.primitives.Heading',\n namespace: 'base.primitives',\n title: 'Heading',\n category: 'content',\n props: {\n text: {\n type: 'text',\n context: 'prop',\n default: '',\n // Plain-text content prop, editable in place on the canvas (EC-158).\n form: { label: 'Text', inlineEditable: true },\n },\n level: {\n // A numeric heading level 1–6 (the impl clamps out-of-range to 2).\n type: 'number',\n context: 'prop',\n default: 2,\n validation: { min: 1, max: 6 },\n form: { label: 'Level' },\n },\n },\n slots: [],\n})\n\n// ---------------------------------------------------------------------------\n// Image — an <img> with src/alt plus intrinsic dimensions (EC-152). Width and\n// height come from the asset metadata record (bindable to the delivery\n// shape's `width`/`height`) so rendered images reserve layout space — no\n// layout shift. A plain <img> is correct for non-Next contexts (the builder\n// canvas runs on Vite); `@elytracms/next` overrides this implementation with\n// `ElytraImage` (next/image) for host apps.\n// ---------------------------------------------------------------------------\n\nfunction asPositiveInt(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : undefined\n}\n\n/**\n * The Image `src` may be a resolved asset (EC-195: an `asset`-typed prop the\n * renderer resolved from an asset id) or a plain URL string. Normalize to\n * `{ url, width, height, alt }`, letting the asset's intrinsic dimensions/alt\n * fill in when the explicit props are unset — so an uploaded image reserves the\n * right box (no layout shift) and carries its alt text by default.\n */\nexport interface ImageSource {\n url: string\n width: number | undefined\n height: number | undefined\n alt: string\n /** Normalized focal point `{ x, y }` 0–1 (EC-230) → CSS object-position; null when none. */\n focalPoint: { x: number; y: number } | null\n}\n\n/** Read a resolved asset's `focalPoint` defensively (a `{ x, y }` pair in 0–1). */\nfunction asFocalPoint(value: unknown): { x: number; y: number } | null {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n const point = value as { x?: unknown; y?: unknown }\n if (typeof point.x === 'number' && typeof point.y === 'number') {\n return { x: point.x, y: point.y }\n }\n }\n return null\n}\n\nexport function normalizeImageSource(props: PrimitiveProps): ImageSource {\n const src = props.src\n const asset =\n src && typeof src === 'object' && !Array.isArray(src)\n ? (src as {\n url?: unknown\n width?: unknown\n height?: unknown\n alt?: unknown\n focalPoint?: unknown\n })\n : null\n const url = asset ? asString(asset.url) : asString(src)\n const width = asPositiveInt(props.width) ?? (asset ? asPositiveInt(asset.width) : undefined)\n const height = asPositiveInt(props.height) ?? (asset ? asPositiveInt(asset.height) : undefined)\n const alt = asString(props.alt) || (asset ? asString(asset.alt) : '')\n const focalPoint = asset ? asFocalPoint(asset.focalPoint) : null\n return { url, width, height, alt, focalPoint }\n}\n\n/** EC-230: a focal point becomes a CSS `object-position` string (percent of each axis). */\nexport function focalPointObjectPosition(focalPoint: { x: number; y: number } | null): string | undefined {\n return focalPoint ? `${focalPoint.x * 100}% ${focalPoint.y * 100}%` : undefined\n}\n\nfunction Image(props: PrimitiveProps): ReactNode {\n const { url, width, height, alt, focalPoint } = normalizeImageSource(props)\n const objectPosition = focalPointObjectPosition(focalPoint)\n // No resolved url (no asset picked yet, or an unresolved id): a visible\n // placeholder, never a broken `<img src=\"\">` (EC-195 / EC-015).\n if (url === '') {\n return (\n <span\n data-ec-primitive=\"Image\"\n data-ec-image=\"empty\"\n role=\"img\"\n aria-label={alt || 'No image selected'}\n >\n No image selected\n </span>\n )\n }\n return (\n <img\n data-ec-primitive=\"Image\"\n src={url}\n alt={alt}\n {...(width !== undefined ? { width } : {})}\n {...(height !== undefined ? { height } : {})}\n {...(objectPosition ? { style: { objectPosition } } : {})}\n />\n )\n}\n\nconst ImageManifest = defineComponent({\n id: 'base.primitives.Image',\n namespace: 'base.primitives',\n title: 'Image',\n category: 'media',\n props: {\n // EC-195: `asset`-typed, so the editor picks an uploaded asset (the renderer\n // resolves the id to a url + intrinsic dimensions at delivery) — a plain URL\n // string still works (the resolver passes URL-like values through).\n src: {\n type: 'asset',\n cardinality: 'one',\n context: 'prop',\n default: '',\n form: { label: 'Image' },\n },\n alt: {\n type: 'text',\n context: 'prop',\n default: '',\n form: { label: 'Alt text' },\n },\n width: {\n type: 'number',\n context: 'prop',\n validation: { min: 1 },\n form: { label: 'Width' },\n },\n height: {\n type: 'number',\n context: 'prop',\n validation: { min: 1 },\n form: { label: 'Height' },\n },\n // EC-195: above-the-fold images load eagerly (`next/image priority`) so the\n // host can opt the hero image out of lazy-loading.\n priority: {\n type: 'boolean',\n context: 'prop',\n default: false,\n form: { label: 'Load eagerly (above the fold)' },\n },\n },\n slots: [],\n})\n\n// ---------------------------------------------------------------------------\n// Button — labelled button with an optional href.\n// ---------------------------------------------------------------------------\n\nfunction Button(props: PrimitiveProps): ReactNode {\n const label = asString(props.label, 'Button')\n if (typeof props.href === 'string' && props.href.length > 0) {\n return (\n <a data-ec-primitive=\"Button\" href={props.href} role=\"button\">\n {label}\n </a>\n )\n }\n return (\n <button data-ec-primitive=\"Button\" type=\"button\">\n {label}\n </button>\n )\n}\n\nconst ButtonManifest = defineComponent({\n id: 'base.primitives.Button',\n namespace: 'base.primitives',\n title: 'Button',\n category: 'content',\n props: {\n label: {\n type: 'text',\n context: 'prop',\n default: 'Button',\n form: { label: 'Label' },\n },\n href: {\n type: 'text',\n context: 'prop',\n form: { label: 'Link' },\n },\n },\n slots: [],\n})\n\n// ---------------------------------------------------------------------------\n// Repeater — renders its `item` slot template once per item (iteration is done by the\n// renderer; this implementation only frames the rendered items).\n// ---------------------------------------------------------------------------\n\nfunction Repeater(props: PrimitiveProps): ReactNode {\n return <div data-ec-primitive=\"Repeater\">{props.children}</div>\n}\n\nconst RepeaterManifest = defineComponent({\n id: 'base.primitives.Repeater',\n namespace: 'base.primitives',\n title: 'Repeater',\n category: 'data',\n // EC-190 DD7: iterate-over-a-source is a binding construct designed out of v1.\n // The `items` value (an array) has no static field-def type; it rides node.props\n // undeclared (passing through the renderer) until the binding/iteration removal in\n // slice 5 decides Repeater's fate. No editable static prop is exposed meanwhile.\n props: {},\n slots: [{ name: 'item', label: 'Item template', required: true }],\n iterate: { itemsProp: 'items', itemSlot: 'item' },\n})\n\n// ---------------------------------------------------------------------------\n// Switch — renders exactly one named case slot, chosen by the `case` prop/binding.\n// ---------------------------------------------------------------------------\n\nfunction Switch(props: PrimitiveProps): ReactNode {\n const key = asString(props.case)\n const selected = props[`case:${key}`] ?? props.fallback\n return <div data-ec-primitive=\"Switch\">{selected as ReactNode}</div>\n}\n\nconst SwitchManifest = defineComponent({\n id: 'base.primitives.Switch',\n namespace: 'base.primitives',\n title: 'Switch',\n category: 'data',\n props: {\n case: {\n type: 'text',\n context: 'prop',\n default: '',\n form: { label: 'Case' },\n },\n },\n // Named case slots are dynamic; `fallback` renders when no case matches.\n slots: [{ name: 'fallback', label: 'Fallback' }],\n})\n\n// ---------------------------------------------------------------------------\n// Aggregation\n// ---------------------------------------------------------------------------\n\n/** Pairs of manifest + implementation in registration order. */\nconst PRIMITIVES: { manifest: ComponentManifest; implementation: ComponentType<PrimitiveProps> }[] =\n [\n { manifest: ContainerManifest, implementation: Container },\n { manifest: StackManifest, implementation: Stack },\n { manifest: GridManifest, implementation: Grid },\n { manifest: TextManifest, implementation: Text },\n { manifest: HeadingManifest, implementation: Heading },\n // Rich-text content primitive (EC-159) — content prop is the stored\n // `@elytracms/rich-text` value, flagged inline-editable.\n { manifest: RichTextManifest, implementation: RichText },\n { manifest: ImageManifest, implementation: Image },\n { manifest: ButtonManifest, implementation: Button },\n { manifest: RepeaterManifest, implementation: Repeater },\n { manifest: SwitchManifest, implementation: Switch },\n ]\n\nexport interface BasePrimitives {\n manifests: ComponentManifest[]\n implementations: ComponentImplementations\n}\n\n/** The platform starter components: every `base.primitives.*` manifest + implementation. */\nexport function basePrimitives(): BasePrimitives {\n const implementations: Record<string, ComponentType<Record<string, unknown>>> = {}\n for (const { manifest, implementation } of PRIMITIVES) {\n implementations[manifest.id] = implementation as ComponentType<Record<string, unknown>>\n }\n return {\n manifests: PRIMITIVES.map((p) => p.manifest),\n implementations,\n }\n}\n\n/** A `ComponentRegistry` preloaded with the primitive manifests. */\nexport function createPrimitiveRegistry(): ComponentRegistry {\n return new ComponentRegistry(basePrimitives().manifests)\n}\n\nexport {\n Container,\n Stack,\n Grid,\n Text,\n Heading,\n Image,\n Button,\n Repeater,\n Switch,\n ContainerManifest,\n StackManifest,\n GridManifest,\n TextManifest,\n HeadingManifest,\n ImageManifest,\n ButtonManifest,\n RepeaterManifest,\n SwitchManifest,\n}\n","import type { ComponentType } from 'react'\nimport { ComponentRegistry } from '@elytracms/component-registry'\nimport type { ComponentIssue, ComponentManifest } from '@elytracms/component-registry'\nimport { basePrimitives, getImplementation } from '@elytracms/runtime-renderer'\nimport type { ComponentImplementations } from '@elytracms/runtime-renderer'\n\n/**\n * One host-repo component: the manifest the builder edits against plus the\n * real React implementation that renders it (vision AD-2 — project components\n * are real code in the host repo, never generated).\n */\nexport interface HostComponent {\n manifest: ComponentManifest\n implementation: ComponentType<Record<string, unknown>>\n}\n\n/**\n * The registered component surface a host app hands to `<CanvasRenderer />`\n * and the catch-all route helper: a manifest registry plus the implementation\n * map, with registration problems surfaced as structured issues (never\n * thrown — an unknown component renders the EC-015 fallback).\n */\nexport interface HostComponents {\n registry: ComponentRegistry\n implementations: ComponentImplementations\n /** Structural registration issues (duplicate ids, invalid namespaces). */\n issues: readonly ComponentIssue[]\n}\n\nexport interface DefineHostComponentsOptions {\n /**\n * Include the platform primitives (`base.primitives.*`) that ship with\n * `@elytracms/runtime-renderer`. Defaults to `true` — graphs authored in the\n * builder assume them.\n */\n includeBasePrimitives?: boolean\n}\n\n/**\n * Component registration API for the embedded runtime (EC-144). The host repo\n * supplies real implementations + manifests; base primitives are included by\n * default. A host implementation registered under a primitive id replaces the\n * default implementation (the manifest of the first registration wins, which\n * is the primitive's — by design, so prop schemas stay canonical).\n */\nexport function defineHostComponents(\n components: readonly HostComponent[] = [],\n options: DefineHostComponentsOptions = {},\n): HostComponents {\n const includeBase = options.includeBasePrimitives !== false\n const base = includeBase ? basePrimitives() : { manifests: [], implementations: {} }\n\n const registry = new ComponentRegistry([...base.manifests, ...components.map((c) => c.manifest)])\n\n const implementations: Record<string, ComponentType<Record<string, unknown>>> = {}\n for (const manifest of base.manifests) {\n const implementation = getImplementation(base.implementations, manifest.id)\n if (implementation) implementations[manifest.id] = implementation\n }\n for (const component of components) {\n implementations[component.manifest.id] = component.implementation\n }\n\n return { registry, implementations, issues: registry.issues }\n}\n","import type { BindingReference } from '@elytracms/project-graph'\nimport type { ItemContext, ResolveBinding } from '@elytracms/runtime-renderer'\n\n/**\n * Binding payloads for the embedded runtime (EC-144): one payload value per\n * binding `sourceId`. The catch-all route helper provides `document` (the\n * route-bound resolved document) and `params` (dynamic route params) by\n * default; hosts add more through the route helper's `payloads` factory\n * (e.g. a `listDocuments` result for a posts repeater).\n *\n * This is a deliberately small, pure resolver — the embedded runtime never\n * imports `@elytracms/data-binding` (a builder-side package). Semantics mirror\n * EC-023 tokens: a binding token is a JSON Pointer (RFC 6901) into the\n * payload; a miss resolves to `undefined`, never a throw (the renderer turns\n * unresolvable bindings into visible fallback behavior, EC-015).\n */\nexport type BindingPayloads = Record<string, unknown>\n\n/**\n * Marker key of an {@link SourcePayloadError} payload. A plain string property\n * (not a Symbol) on purpose: the route helper's cached path JSON-serializes\n * payloads through `unstable_cache`, and the marker must survive that\n * round-trip.\n */\nconst SOURCE_PAYLOAD_ERROR_KEY = '__elytraSourcePayloadError'\n\n/**\n * Explicit issue payload for a source whose stored query was REJECTED at\n * delivery (EC-177 gap 3) — e.g. a sort/filter field that is no longer\n * filterable in the live schema. Materialization stores this instead of a\n * silently-absent payload; `createBindingResolver` throws on it, which the\n * renderer converts into its visible per-node render-error fallback (EC-015).\n * Validation principle: a broken stored query is a visible state, never an\n * empty section.\n */\nexport interface SourcePayloadError {\n [SOURCE_PAYLOAD_ERROR_KEY]: true\n sourceId: string\n /** Human-readable messages of the structured query errors. */\n messages: string[]\n}\n\n/** Build the explicit issue payload for one failed source query. */\nexport function sourcePayloadError(\n sourceId: string,\n messages: readonly string[],\n): SourcePayloadError {\n return { [SOURCE_PAYLOAD_ERROR_KEY]: true, sourceId, messages: [...messages] }\n}\n\n/** `true` when a payload value is an explicit {@link SourcePayloadError}. */\nexport function isSourcePayloadError(value: unknown): value is SourcePayloadError {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as Record<string, unknown>)[SOURCE_PAYLOAD_ERROR_KEY] === true &&\n typeof (value as { sourceId?: unknown }).sourceId === 'string' &&\n Array.isArray((value as { messages?: unknown }).messages)\n )\n}\n\n/** Unescape one RFC 6901 reference token (`~1` → `/`, `~0` → `~`). */\nfunction unescapeRefToken(token: string): string {\n return token.replace(/~1/g, '/').replace(/~0/g, '~')\n}\n\n/** Parse a JSON Pointer into segments; `''`/`'/'` is the root. `undefined` = malformed. */\nfunction pathFromToken(token: string): string[] | undefined {\n if (token === '' || token === '/') return []\n if (!token.startsWith('/')) return undefined\n return token.slice(1).split('/').map(unescapeRefToken)\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * Resolve a JSON Pointer token within a payload value. Numeric segments index\n * arrays; string segments index plain objects. Any miss (unknown key,\n * out-of-range index, traversal through a primitive) yields `undefined`.\n */\nexport function resolvePayloadToken(payload: unknown, token: string): unknown {\n const path = pathFromToken(token)\n if (path === undefined) return undefined\n let current: unknown = payload\n for (const segment of path) {\n if (Array.isArray(current)) {\n if (!/^(0|[1-9][0-9]*)$/.test(segment)) return undefined\n const index = Number(segment)\n if (index >= current.length) return undefined\n current = current[index]\n continue\n }\n if (isPlainObject(current)) {\n if (!Object.prototype.hasOwnProperty.call(current, segment)) return undefined\n current = current[segment]\n continue\n }\n return undefined\n }\n return current\n}\n\n/**\n * Create the renderer's `ResolveBinding` over a payload map. Mode semantics\n * (brief §4.6, uniform binding model):\n *\n * - `value` / `object` / `condition` — the value at the token within the\n * payload named by `sourceId`.\n * - `spread` — same lookup; the renderer spreads the resulting object.\n * - `repeaterItem` — the token resolves against the active repeater item,\n * not the root payload.\n *\n * Total for data misses: an unknown `sourceId` or missing path resolves to\n * `undefined` — the renderer (EC-015) degrades visibly instead of crashing.\n * An explicit {@link SourcePayloadError} payload (a REJECTED stored query, not\n * merely missing data) throws instead: the renderer catches per node and\n * renders its visible render-error fallback with the query error message;\n * conditions treat the throw as `false` (the node hides) — never a page crash.\n */\nexport function createBindingResolver(payloads: BindingPayloads): ResolveBinding {\n return (ref: BindingReference, item?: ItemContext): unknown => {\n if (ref.mode === 'repeaterItem') {\n return item === undefined ? undefined : resolvePayloadToken(item.item, ref.token)\n }\n if (!Object.prototype.hasOwnProperty.call(payloads, ref.sourceId)) return undefined\n const payload = payloads[ref.sourceId]\n if (isSourcePayloadError(payload)) {\n throw new Error(\n `Source \"${payload.sourceId}\" query was rejected: ${payload.messages.join('; ')}`,\n )\n }\n return resolvePayloadToken(payload, ref.token)\n }\n}\n","import { isValidElement } from 'react'\nimport type { ReactNode } from 'react'\nimport type { ResolvedAsset, ResolvePageResult } from '@elytracms/content'\nimport type { ComponentNode, ProjectGraph } from '@elytracms/project-graph'\nimport {\n RenderErrorBoundary,\n renderComposition,\n renderCompositionInLayout,\n serializeListingQuery,\n} from '@elytracms/runtime-renderer'\nimport type {\n RelationTarget,\n RenderAsset,\n RenderContext,\n ResolveBinding,\n ResolveListing,\n ResolveRelation,\n} from '@elytracms/runtime-renderer'\nimport type { HostComponents } from './components'\nimport { createBindingResolver } from './payloads'\nimport type { BindingPayloads } from './payloads'\n\n/**\n * `<CanvasRenderer />` (EC-144, vision AD-1): an async React Server Component\n * that renders a resolved page (from `resolvePage`, EC-143) through\n * `@elytracms/runtime-renderer` with the host app's component registry. EC-015\n * fallback behavior is identical to the builder: a missing component, invalid\n * prop, or missing required slot renders a visible fallback — a page never\n * crashes and never silently omits a node.\n */\nexport interface CanvasRendererProps {\n /** The `resolvePage` result for the current URL. */\n result: ResolvePageResult\n /** Host component surface from `defineHostComponents`. */\n components: HostComponents\n /**\n * The full project graph for the active perspective (from\n * `ContentSource.graph`). Needed for layout composition; without it the\n * page root renders without its layout.\n */\n graph?: ProjectGraph | null\n /**\n * Binding payloads keyed by `sourceId`. Defaults to\n * `{ document, params }` derived from the result.\n */\n payloads?: BindingPayloads\n /** Full custom binding resolver — overrides `payloads` when provided. */\n resolveBinding?: ResolveBinding\n /**\n * Delivery-shaped assets the page may reference (EC-195, from the render\n * outcome). An `asset`-typed Image prop resolves through these to a url +\n * intrinsic dimensions; an unknown id degrades to the visible fallback.\n */\n assets?: readonly ResolvedAsset[]\n /**\n * Populated composition-node `relation` props, keyed `collection:id` (EC-254,\n * from the render outcome). A block's `relation` prop (e.g. a ProductGrid's\n * picked products) resolves through these to the populated target; an unknown\n * key degrades to the block's own empty state. Absent → relation props pass\n * through unresolved (raw ref), the same degradation as a missing asset list.\n */\n relations?: Record<string, RelationTarget>\n /**\n * Documents each `listing` block resolved to, keyed by serialized query (EC-255,\n * from the render outcome). A ProductGrid keyed to a picked `category` reads its\n * products through this; an unknown key (or absent map) degrades to the block's\n * own empty state — the same degradation as a missing relation.\n */\n listings?: Record<string, RelationTarget[]>\n}\n\n/** Build the renderer's relation resolver from the baked, populated targets (EC-254). */\nfunction relationResolver(relations: Record<string, RelationTarget>): ResolveRelation {\n return (ref) => relations[`${ref.collection}:${ref.id}`] ?? null\n}\n\n/** Build the renderer's listing resolver from the baked, query-keyed documents (EC-255). */\nfunction listingResolver(listings: Record<string, RelationTarget[]>): ResolveListing {\n return (query) => listings[serializeListingQuery(query)] ?? null\n}\n\n/** Build the renderer's asset resolver from the baked delivery assets (EC-195). */\nfunction assetResolver(assets: readonly ResolvedAsset[]): (id: string) => RenderAsset | null {\n const byId = new Map(assets.map((asset) => [asset.id, asset]))\n return (id) => {\n const asset = byId.get(id)\n return asset\n ? {\n url: asset.url,\n width: asset.width,\n height: asset.height,\n alt: asset.alt,\n focalPoint: asset.focalPoint,\n }\n : null\n }\n}\n\n/** Visible fallback when the renderer is handed a non-`ok` resolution. */\nfunction UnresolvedPageFallback(props: { status: string }): ReactNode {\n return (\n <div data-ec-fallback=\"unresolved-page\" data-ec-status={props.status}>\n {`This URL did not resolve to a page (status: ${props.status}).`}\n </div>\n )\n}\n\n/** Visible fallback when an `ok` resolution carries no renderable document. */\nfunction MissingDocumentFallback(): ReactNode {\n return (\n <div data-ec-fallback=\"missing-document\">\n {`Route resolved but carried no page document to render.`}\n </div>\n )\n}\n\n/**\n * Server-side per-node decorator: unwrap the renderer's client error\n * boundary. React Server Components cannot render class components, and a\n * boundary cannot recover during server rendering anyway (the renderer\n * already converts resolution errors into visible fallbacks before this\n * point). The wrapped element keeps its key, so output is unchanged.\n */\nfunction stripServerErrorBoundary(_node: ComponentNode, rendered: ReactNode): ReactNode {\n if (isValidElement(rendered) && rendered.type === RenderErrorBoundary) {\n return (rendered.props as { children?: ReactNode }).children ?? null\n }\n return rendered\n}\n\n/** Default payloads: the route-bound document and the dynamic route params. */\nexport function defaultBindingPayloads(result: ResolvePageResult): BindingPayloads {\n return { document: result.document, params: result.dynamicParams }\n}\n\n/**\n * Render a resolved page server-side. Async so hosts can compose it like any\n * other RSC; resolution itself is synchronous (the content was prefetched by\n * the `ContentSource`).\n */\nexport async function CanvasRenderer(props: CanvasRendererProps): Promise<ReactNode> {\n const { result, components } = props\n\n if (result.status !== 'ok') {\n // The route helper answers redirect/notFound before rendering; direct\n // users of <CanvasRenderer /> still get a visible state, never a crash.\n return <UnresolvedPageFallback status={result.status} />\n }\n\n const resolveBinding =\n props.resolveBinding ?? createBindingResolver(props.payloads ?? defaultBindingPayloads(result))\n\n const ctx: RenderContext = {\n registry: components.registry,\n implementations: components.implementations,\n resolveBinding,\n resolveAsset: assetResolver(props.assets ?? []),\n // EC-254: wire relation population only when the host baked the populated\n // targets, so a host that did not opt in keeps the raw-ref passthrough.\n ...(props.relations ? { resolveRelation: relationResolver(props.relations) } : {}),\n // EC-255: wire the listing resolver only when the host baked the query results,\n // so a host that did not opt in keeps listing props empty (the block's own state).\n ...(props.listings ? { resolveListing: listingResolver(props.listings) } : {}),\n decorateNode: stripServerErrorBoundary,\n }\n\n const graph = props.graph ?? null\n const document = result.document\n\n // EC-187: a routed document delivers a composition field into a graph layout.\n // A `page`-collection document uses its `body` field; a content-collection\n // document routed for delivery uses its `content` composition field (e.g. a\n // post's `content`). The composition composes into the layout selected by the\n // document's `layoutId` flat field. `renderCompositionInLayout` degrades a\n // missing/absent graph or layout to the bare composition (never crashes); with\n // no document at all, a visible fallback.\n if (document) {\n const layoutId = typeof document['layoutId'] === 'string' ? document['layoutId'] : undefined\n const composition = compositionOf(document)\n if (graph) return <>{renderCompositionInLayout(graph, layoutId, composition, ctx)}</>\n // No graph: render the bare composition (no layout chrome available).\n return <>{renderComposition(composition, ctx)}</>\n }\n\n return <MissingDocumentFallback />\n}\n\n/**\n * Select the delivery composition from a resolved document (EC-187). A\n * `page`-collection document holds it in `body`; a routed content collection\n * (e.g. `post`) holds it in `content` — and a content document may ALSO carry an\n * unrelated `body` field (a post's localized rich-text article body). So the\n * field is chosen by VALUE — a composition is a `ComponentNode` or an array of\n * them — NOT by name: a `body ?? content` name heuristic picks the post's\n * rich-text `body` string over its `content` composition and renders nothing.\n */\nfunction compositionOf(document: Record<string, unknown>): unknown {\n const body = document['body']\n if (Array.isArray(body) || isComponentNodeValue(body)) return body\n return document['content']\n}\n\n/**\n * The routed document's composition as a `ComponentNode[]` (EC-205): the same\n * `body`-or-`content` selection the renderer uses, normalized to an array so a\n * delivery host can walk it (e.g. to page-scope baked assets). Non-node values\n * are dropped. `null`/no-document yields an empty array.\n */\nexport function compositionNodesOf(\n document: Record<string, unknown> | null | undefined,\n): ComponentNode[] {\n if (!document) return []\n const composition = compositionOf(document)\n const candidates = Array.isArray(composition) ? composition : [composition]\n return candidates.filter((node): node is ComponentNode => isComponentNodeValue(node))\n}\n\n/** Structural `ComponentNode` guard — a resolved field value is opaque at the type level. */\nfunction isComponentNodeValue(value: unknown): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { id?: unknown }).id === 'string' &&\n typeof (value as { componentId?: unknown }).componentId === 'string'\n )\n}\n","import { z } from 'zod'\nimport type { Locale, LocaleConfig } from '@elytracms/cms-core'\n\n/**\n * Which side of the draft/published split a delivery request reads from\n * (EC-021, vision AD-4). `published` never exposes draft content; `draft` is\n * the editor/preview view.\n */\nexport const perspectiveSchema = z.enum(['draft', 'published'])\nexport type Perspective = z.infer<typeof perspectiveSchema>\n\n/**\n * Ambient request context (vision AD-4): locale and perspective are set once\n * per request and threaded through every resolution function — never per-call\n * ceremony. The locale config travels along so EC-018 fallback needs no extra\n * arguments either.\n */\nexport interface ContentContext {\n /** The locale requested for this delivery (EC-018 fallback applies). */\n readonly locale: Locale\n /** Draft or published perspective (EC-021). */\n readonly perspective: Perspective\n /** The project's locale configuration (default + supported set). */\n readonly locales: LocaleConfig\n}\n\nexport interface ContentContextInit {\n locale: Locale\n perspective: Perspective\n locales: LocaleConfig\n}\n\n/**\n * Create the ambient `{ locale, perspective }` context for a delivery request.\n * Construction never throws — an unknown locale is surfaced as a structured\n * `unknown-locale` issue by `resolveDocument`, while resolution still proceeds\n * with default-locale fallback.\n */\nexport function createContentContext(init: ContentContextInit): ContentContext {\n return {\n locale: init.locale,\n perspective: init.perspective,\n locales: init.locales,\n }\n}\n","import type { CmsDocument, DocumentHistory } from '@elytracms/cms-core'\nimport type { ContentContext } from './context'\n\n/**\n * What delivery resolution accepts as a document source: either a bare stored\n * row (`CmsDocument`, always a working draft — EC-224 retired the `state` flag)\n * or the full draft/published history (`DocumentHistory`, EC-021) whose\n * `published` field carries the pinned snapshot. Lookups hand these in;\n * resolution stays pure — no fetching at this layer.\n */\nexport type ContentDocumentSource = CmsDocument | DocumentHistory\n\n/** Narrow a source to a `DocumentHistory` (draft/published split, EC-021). */\nexport function isDocumentHistory(source: ContentDocumentSource): source is DocumentHistory {\n return 'draft' in source && 'versions' in source\n}\n\n/**\n * Select the stored row visible under the context's perspective (EC-021):\n *\n * - For a `DocumentHistory`: `draft` returns the working draft, `published`\n * returns the last published snapshot — or `null` if the document has never\n * been published. Draft content is never leaked into `published`.\n * - For a bare `CmsDocument`: `draft` sees the row as-is; `published` returns\n * `null`. A bare row carries no publish signal (EC-224 retired `state`), so\n * it is treated as never-published here — fail-closed. Published content\n * reaches this layer ONLY as a `DocumentHistory` whose `published` field the\n * feeder set (the live host wraps each published snapshot; the adapter path\n * wraps a pinned record), never as a bare row.\n *\n * Returning `null` means \"not visible in this perspective\" — that is correct\n * delivery behavior for unpublished content, not a validation issue.\n */\nexport function selectPerspective(\n context: ContentContext,\n source: ContentDocumentSource,\n): CmsDocument | null {\n if (isDocumentHistory(source)) {\n if (context.perspective === 'draft') return source.draft\n return source.published ?? null\n }\n if (context.perspective === 'draft') return source\n return null\n}\n","import { resolveField } from '@elytracms/cms-core'\nimport type { CmsDocument, CmsPath, CollectionDef, FieldValues, Locale } from '@elytracms/cms-core'\nimport type { ContentContext } from './context'\n\n/**\n * A report entry for one field whose value was served from a different locale\n * than the one requested (EC-018 default-locale fallback). Paths are rooted at\n * the resolved document, e.g. `['title']` or `['author', 'bio']` for a field\n * inside a populated relation.\n */\nexport interface FieldLocaleFallback {\n path: CmsPath\n /** The field name (last path segment, repeated for convenience). */\n field: string\n /** The locale the request asked for. */\n requestedLocale: Locale\n /** The locale the value was actually read from. */\n sourceLocale: Locale\n}\n\nexport interface LocaleResolution {\n /** Flat field values for the requested locale, fallback applied. Fields with\n * no value anywhere are omitted (never `undefined` entries). */\n values: FieldValues\n /** Which fields used fallback, and from where (EC-018 reporting). */\n fallbacks: FieldLocaleFallback[]\n}\n\n/**\n * Resolve a stored row's field values for the context locale with EC-018\n * default-locale fallback, reporting every field that actually fell back.\n * Pure: reads only the given document; never throws.\n */\nexport function resolveLocaleValues(\n context: ContentContext,\n collection: CollectionDef,\n doc: CmsDocument,\n basePath: CmsPath = [],\n): LocaleResolution {\n const values: FieldValues = {}\n const fallbacks: FieldLocaleFallback[] = []\n\n for (const field of collection.fields) {\n const resolved = resolveField(collection, doc, field.name, context.locale, context.locales)\n if (resolved.value === undefined) continue\n values[field.name] = resolved.value\n if (resolved.fellBack) {\n fallbacks.push({\n path: [...basePath, field.name],\n field: field.name,\n requestedLocale: context.locale,\n sourceLocale: resolved.sourceLocale,\n })\n }\n }\n\n return { values, fallbacks }\n}\n","import { documentRefSchema } from '@elytracms/cms-core'\nimport type { DocumentRef, RelationFieldDef } from '@elytracms/cms-core'\n\n/**\n * The unpopulated form of a relation in delivery shape (vision AD-4): always a\n * `{ id, collection }` object, never a bare id string. Returned when a field\n * declares `populate: false`, and for relations *inside* a populated document\n * (population never recurses past depth-1).\n */\nexport interface DocumentStub {\n id: string\n collection: string\n}\n\n/**\n * Whether delivery resolution populates this relation to depth-1 (EC-142).\n * Population is the default; `populate: false` is the schema-level opt-out.\n */\nexport function isPopulatedRelation(field: RelationFieldDef): boolean {\n return field.populate !== false\n}\n\n/** Build the reference stub for a relation target. */\nexport function relationStub(ref: DocumentRef): DocumentStub {\n return { id: ref.id, collection: ref.collection }\n}\n\n/**\n * Parse a stored relation value into a `DocumentRef`, tolerating malformed\n * data: anything that is not `{ collection, id }`-shaped yields `undefined`\n * so the caller can surface a structured issue instead of crashing.\n */\nexport function parseRelationRef(value: unknown): DocumentRef | undefined {\n const parsed = documentRefSchema.safeParse(value)\n return parsed.success ? parsed.data : undefined\n}\n","import { cmsIssue } from '@elytracms/cms-core'\nimport type { CmsPath, CmsValidationIssue } from '@elytracms/cms-core'\nimport type { AssetRecord } from '@elytracms/persistence'\n\n/**\n * The delivery shape of an asset (vision AD-4): a directly usable object, not\n * an id. Optional metadata that the stored record lacks is `null` (never\n * `undefined`) so resolved documents stay JSON-stable.\n */\nexport interface ResolvedAsset {\n /** The asset id the field stored (kept for cache keys and re-lookup). */\n id: string\n /** Resolvable URL for the asset bytes (EC-044 blob storage locator). */\n url: string\n width: number | null\n height: number | null\n alt: string | null\n mimeType: string\n /**\n * Normalized image focal point `{ x, y }` in 0–1 (EC-230), or `null`. Threaded\n * to the image primitive's CSS `object-position` so a migrated hotspot keeps\n * the subject in frame when a layout crops the image (`object-fit: cover`).\n */\n focalPoint: { x: number; y: number } | null\n}\n\n/**\n * Pure lookup boundary for asset metadata (EC-044). The caller pre-fetches;\n * resolution only reads. `assetUrl` turns a metadata record into a resolvable\n * URL (e.g. via the blob storage adapter's `url(storageKey)`).\n */\nexport interface AssetLookup {\n asset(id: string): AssetRecord | undefined\n assetUrl(asset: AssetRecord): string\n}\n\n/** Map a persisted asset record (+ resolved URL) to its delivery shape. */\nexport function resolvedAsset(record: AssetRecord, url: string): ResolvedAsset {\n return {\n id: record.id,\n url,\n width: record.width ?? null,\n height: record.height ?? null,\n alt: record.alt ?? null,\n mimeType: record.contentType,\n focalPoint: record.focalPoint ?? null,\n }\n}\n\nexport interface AssetResolution {\n /** The delivery-shaped asset, or `null` when the asset is missing. */\n asset: ResolvedAsset | null\n issues: CmsValidationIssue[]\n}\n\nexport interface AssetResolutionLocation {\n path: CmsPath\n collectionId?: string\n documentId?: string\n}\n\n/**\n * Resolve one stored asset id to its delivery shape. A missing asset is a\n * structured `unknown-asset` issue plus a `null` value — never a crash\n * (EC-142 acceptance).\n */\nexport function resolveAssetValue(\n lookup: AssetLookup,\n assetId: string,\n location: AssetResolutionLocation,\n): AssetResolution {\n const record = lookup.asset(assetId)\n if (!record) {\n return {\n asset: null,\n issues: [\n cmsIssue({\n code: 'unknown-asset',\n message: `Asset \"${assetId}\" could not be resolved.`,\n path: location.path,\n ...(location.collectionId ? { collectionId: location.collectionId } : {}),\n ...(location.documentId ? { documentId: location.documentId } : {}),\n meta: { assetId },\n }),\n ],\n }\n }\n return { asset: resolvedAsset(record, lookup.assetUrl(record)), issues: [] }\n}\n","import { cmsIssue, validateLocale } from '@elytracms/cms-core'\nimport type {\n CmsDocument,\n CmsPath,\n CmsValidationIssue,\n CollectionDef,\n DocumentRef,\n FieldDef,\n FieldValues,\n Locale,\n} from '@elytracms/cms-core'\nimport { resolveAssetValue } from './assets'\nimport type { AssetLookup, ResolvedAsset } from './assets'\nimport type { ContentContext, Perspective } from './context'\nimport { resolveLocaleValues } from './locale'\nimport type { FieldLocaleFallback } from './locale'\nimport { selectPerspective } from './perspective'\nimport type { ContentDocumentSource } from './perspective'\nimport { isPopulatedRelation, parseRelationRef, relationStub } from './populate'\n\n/**\n * Pure lookup boundary for delivery resolution (vision AD-4): the caller\n * (content kit, export, tests) pre-fetches schema, documents, and asset\n * metadata; resolution only reads through these synchronous functions. No\n * fetching, no Convex, no React at this layer.\n */\nexport interface ContentLookup extends AssetLookup {\n collection(id: string): CollectionDef | undefined\n document(ref: DocumentRef): ContentDocumentSource | undefined\n /**\n * All document sources of a collection (EC-143, additive). Required by\n * `listDocuments` and by `getDocument`'s slug fallback; a lookup without it\n * still supports plain resolution, and `listDocuments` degrades to a\n * structured `list-not-supported` error.\n */\n documents?(collectionId: string): readonly ContentDocumentSource[]\n}\n\n/**\n * A document in delivery shape: identity plus resolved field values, flat —\n * `post.title`, `post.author.name`, `post.cover.url`. The precise per-collection\n * shape is what `generateDeliveryTypes` emits (EC-142 codegen).\n */\nexport type ResolvedDocument = { id: string; collection: string } & Record<string, unknown>\n\n/**\n * The minimal structural face of any delivery-shaped document — what the typed\n * accessors (EC-143) constrain their per-collection generics against. The\n * generated interfaces from `generateDeliveryTypes` (e.g. `Post`) satisfy this\n * where they cannot satisfy `ResolvedDocument`'s index signature.\n */\nexport interface DeliveryDocument {\n id: string\n collection: string\n}\n\n/**\n * Structured information about *how* a document was resolved — most notably\n * which fields served their value via EC-018 locale fallback.\n */\nexport interface ResolutionInfo {\n locale: Locale\n perspective: Perspective\n localeFallbacks: FieldLocaleFallback[]\n}\n\nexport interface ResolveDocumentResult {\n /**\n * The delivery-shaped document, or `null` when the source is not visible in\n * the context perspective (e.g. never published) or its collection is\n * unknown. `null` plus an empty issue list simply means \"not available\n * here\" — unpublished content in the published perspective is correct\n * behavior, not an error.\n */\n document: ResolvedDocument | null\n info: ResolutionInfo\n issues: CmsValidationIssue[]\n}\n\n/** Mutable accumulator threaded through one resolution pass. */\ninterface ResolutionAccumulator {\n fallbacks: FieldLocaleFallback[]\n issues: CmsValidationIssue[]\n}\n\nfunction invalidValueIssue(\n field: FieldDef,\n collection: CollectionDef,\n documentId: string,\n path: CmsPath,\n expected: string,\n): CmsValidationIssue {\n return cmsIssue({\n code: 'invalid-field-value',\n message: `Field \"${field.name}\" on \"${collection.id}\" holds a value that is not ${expected}.`,\n path,\n collectionId: collection.id,\n documentId,\n meta: { field: field.name, expected },\n })\n}\n\n/**\n * Resolve a single relation target. At depth 0 with population enabled this\n * returns the depth-1 populated reference (`{ id, collection, ...fields }`);\n * otherwise the `{ id, collection }` stub. A missing or perspective-invisible\n * target degrades to the stub plus an `unknown-relation-target` issue — the\n * value is never a bare id string and resolution never throws.\n */\nfunction resolveRelationTarget(\n context: ContentContext,\n lookup: ContentLookup,\n ref: DocumentRef,\n populate: boolean,\n path: CmsPath,\n ownerCollectionId: string,\n ownerDocumentId: string,\n acc: ResolutionAccumulator,\n): Record<string, unknown> {\n if (!populate) return { ...relationStub(ref) }\n\n const missing = (reason: string): Record<string, unknown> => {\n acc.issues.push(\n cmsIssue({\n code: 'unknown-relation-target',\n message: `Relation target \"${ref.collection}:${ref.id}\" could not be populated (${reason}).`,\n path,\n collectionId: ownerCollectionId,\n documentId: ownerDocumentId,\n meta: { targetCollection: ref.collection, targetId: ref.id, reason },\n }),\n )\n return { ...relationStub(ref) }\n }\n\n const targetCollection = lookup.collection(ref.collection)\n if (!targetCollection) return missing('unknown collection')\n\n const source = lookup.document(ref)\n if (!source) return missing('document not found')\n\n const visible = selectPerspective(context, source)\n if (!visible) return missing(`not visible in ${context.perspective} perspective`)\n\n // Depth-1 populated reference: id + resolved fields. Relations inside it\n // stay stubs (depth > 0); assets inside it still resolve to objects.\n const fields = resolveFields(context, lookup, targetCollection, visible, 1, path, acc)\n return { id: ref.id, collection: ref.collection, ...fields }\n}\n\nfunction resolveRelationField(\n context: ContentContext,\n lookup: ContentLookup,\n collection: CollectionDef,\n doc: CmsDocument,\n field: Extract<FieldDef, { type: 'relation' }>,\n value: unknown,\n depth: number,\n path: CmsPath,\n acc: ResolutionAccumulator,\n): unknown {\n const populate = depth === 0 && isPopulatedRelation(field)\n\n if (field.cardinality === 'many') {\n if (!Array.isArray(value)) {\n acc.issues.push(invalidValueIssue(field, collection, doc.id, path, 'an array of references'))\n return undefined\n }\n const out: Record<string, unknown>[] = []\n value.forEach((entry, index) => {\n const ref = parseRelationRef(entry)\n if (!ref) {\n acc.issues.push(\n invalidValueIssue(\n field,\n collection,\n doc.id,\n [...path, index],\n 'a { collection, id } reference',\n ),\n )\n return\n }\n out.push(\n resolveRelationTarget(\n context,\n lookup,\n ref,\n populate,\n [...path, index],\n collection.id,\n doc.id,\n acc,\n ),\n )\n })\n return out\n }\n\n const ref = parseRelationRef(value)\n if (!ref) {\n acc.issues.push(\n invalidValueIssue(field, collection, doc.id, path, 'a { collection, id } reference'),\n )\n return undefined\n }\n return resolveRelationTarget(context, lookup, ref, populate, path, collection.id, doc.id, acc)\n}\n\nfunction resolveAssetField(\n lookup: ContentLookup,\n collection: CollectionDef,\n doc: CmsDocument,\n field: Extract<FieldDef, { type: 'asset' }>,\n value: unknown,\n path: CmsPath,\n acc: ResolutionAccumulator,\n): unknown {\n const resolveOne = (assetId: unknown, entryPath: CmsPath): ResolvedAsset | null => {\n if (typeof assetId !== 'string' || assetId.length === 0) {\n acc.issues.push(invalidValueIssue(field, collection, doc.id, entryPath, 'an asset id string'))\n return null\n }\n const resolution = resolveAssetValue(lookup, assetId, {\n path: entryPath,\n collectionId: collection.id,\n documentId: doc.id,\n })\n acc.issues.push(...resolution.issues)\n return resolution.asset\n }\n\n if (field.cardinality === 'many') {\n if (!Array.isArray(value)) {\n acc.issues.push(invalidValueIssue(field, collection, doc.id, path, 'an array of asset ids'))\n return undefined\n }\n // Unresolvable entries are dropped from the array (each already reported\n // as an issue) so consumers never iterate over null holes.\n return value\n .map((entry, index) => resolveOne(entry, [...path, index]))\n .filter((asset): asset is ResolvedAsset => asset !== null)\n }\n\n return resolveOne(value, path)\n}\n\n/**\n * Resolve an `object` / repeater field value (EC-253) by resolving each item's\n * subfields at the same population depth, so a nested relation/asset subfield is\n * populated exactly as a top-level field would be (depth-1 populated at the top,\n * stubs inside a populated ref). `many` is an array of objects; `one` a single\n * object. Malformed items are reported and dropped — resolution never throws.\n */\nfunction resolveObjectField(\n context: ContentContext,\n lookup: ContentLookup,\n collection: CollectionDef,\n doc: CmsDocument,\n field: Extract<FieldDef, { type: 'object' }>,\n value: unknown,\n depth: number,\n path: CmsPath,\n acc: ResolutionAccumulator,\n): unknown {\n const resolveItem = (item: unknown, itemPath: CmsPath): Record<string, unknown> | null => {\n if (typeof item !== 'object' || item === null || Array.isArray(item)) {\n acc.issues.push(invalidValueIssue(field, collection, doc.id, itemPath, 'an object'))\n return null\n }\n const record = item as Record<string, unknown>\n const out: Record<string, unknown> = {}\n for (const sub of field.fields) {\n const subValue = record[sub.name]\n if (subValue === undefined) continue\n const resolved = resolveFieldValue(\n context,\n lookup,\n collection,\n doc,\n sub,\n subValue,\n depth,\n [...itemPath, sub.name],\n acc,\n )\n if (resolved !== undefined) out[sub.name] = resolved\n }\n return out\n }\n\n if (field.cardinality === 'many') {\n if (!Array.isArray(value)) {\n acc.issues.push(invalidValueIssue(field, collection, doc.id, path, 'an array of objects'))\n return undefined\n }\n return value\n .map((item, index) => resolveItem(item, [...path, index]))\n .filter((item): item is Record<string, unknown> => item !== null)\n }\n\n return resolveItem(value, path) ?? undefined\n}\n\n/**\n * Resolve one field value at a population depth — the switch shared by the\n * document loop and the {@link resolveObjectField} recursion (EC-253). Relation\n * population (depth-1 only) and asset resolution stay identical at every level.\n */\nfunction resolveFieldValue(\n context: ContentContext,\n lookup: ContentLookup,\n collection: CollectionDef,\n doc: CmsDocument,\n field: FieldDef,\n value: unknown,\n depth: number,\n path: CmsPath,\n acc: ResolutionAccumulator,\n): unknown {\n switch (field.type) {\n case 'relation':\n return resolveRelationField(context, lookup, collection, doc, field, value, depth, path, acc)\n case 'asset':\n return resolveAssetField(lookup, collection, doc, field, value, path, acc)\n case 'object':\n return resolveObjectField(context, lookup, collection, doc, field, value, depth, path, acc)\n default:\n return value\n }\n}\n\n/**\n * Resolve all field values of one stored row at a given population depth:\n * locale fallback first (EC-018), then relation population (depth-1 only),\n * then asset resolution. Shared by the top-level document (depth 0) and by\n * populated relation targets (depth 1, where relations stay stubs).\n */\nfunction resolveFields(\n context: ContentContext,\n lookup: ContentLookup,\n collection: CollectionDef,\n doc: CmsDocument,\n depth: number,\n basePath: CmsPath,\n acc: ResolutionAccumulator,\n): FieldValues {\n const localeResolution = resolveLocaleValues(context, collection, doc, basePath)\n acc.fallbacks.push(...localeResolution.fallbacks)\n\n const out: FieldValues = {}\n for (const field of collection.fields) {\n const value = localeResolution.values[field.name]\n if (value === undefined) continue\n\n const resolved = resolveFieldValue(\n context,\n lookup,\n collection,\n doc,\n field,\n value,\n depth,\n [...basePath, field.name],\n acc,\n )\n if (resolved !== undefined) out[field.name] = resolved\n }\n return out\n}\n\n/**\n * Resolve one document source into delivery shape (vision AD-4): locale\n * fallback applied (EC-018), draft/published perspective applied (EC-021),\n * relations populated to depth-1 as declared in schema, and assets resolved to\n * `{ url, width, height, alt, mimeType }` objects. Pure and total: invalid\n * states surface as structured issues alongside the result — never thrown.\n */\nexport function resolveDocument(\n context: ContentContext,\n lookup: ContentLookup,\n source: ContentDocumentSource,\n): ResolveDocumentResult {\n const acc: ResolutionAccumulator = {\n fallbacks: [],\n issues: [...validateLocale(context.locales, context.locale)],\n }\n const info = (): ResolutionInfo => ({\n locale: context.locale,\n perspective: context.perspective,\n localeFallbacks: acc.fallbacks,\n })\n\n const doc = selectPerspective(context, source)\n if (!doc) return { document: null, info: info(), issues: acc.issues }\n\n const collection = lookup.collection(doc.collection)\n if (!collection) {\n acc.issues.push(\n cmsIssue({\n code: 'unknown-collection',\n message: `Document \"${doc.id}\" belongs to unknown collection \"${doc.collection}\".`,\n path: ['collection'],\n collectionId: doc.collection,\n documentId: doc.id,\n }),\n )\n return { document: null, info: info(), issues: acc.issues }\n }\n\n const fields = resolveFields(context, lookup, collection, doc, 0, [], acc)\n return {\n document: { id: doc.id, collection: doc.collection, ...fields },\n info: info(),\n issues: acc.issues,\n }\n}\n\n/** Result of populating a single relation reference (EC-254). */\nexport interface PopulateRelationResult {\n /**\n * The relation target populated to depth-1 delivery shape (`{ id, collection,\n * ...fields }`), or `null` when the target's collection is unknown, the\n * document is missing, or it is not visible in the context perspective — so a\n * consuming block degrades cleanly rather than rendering a stub.\n */\n document: ResolvedDocument | null\n issues: CmsValidationIssue[]\n}\n\n/**\n * Populate a single relation reference to depth-1 delivery shape — the public\n * entry a renderer host wires as `RenderContext.resolveRelation` to populate a\n * COMPOSITION-NODE relation PROP (EC-254). This is distinct from a document\n * FIELD relation, which {@link resolveDocument} already populates inline via the\n * internal `resolveRelationTarget`: a page's `blocks` field passes through as raw\n * composition, so the relation props of the nodes inside it (e.g. a ProductGrid's\n * picked `product`s) are never touched by document resolution and need this.\n *\n * Mirrors `resolveRelationTarget`'s populated branch exactly — perspective gated\n * (EC-021), relations inside the target stay stubs (depth-1), assets inside it\n * resolve to objects — but returns `null` (not the `{ id, collection }` stub) on\n * a miss, the cleaner \"populated or nothing\" contract a prop wants. Pure and\n * total: never throws; the reason for a miss is collected as a structured issue.\n */\nexport function populateRelationRef(\n context: ContentContext,\n lookup: ContentLookup,\n ref: DocumentRef,\n): PopulateRelationResult {\n const acc: ResolutionAccumulator = { fallbacks: [], issues: [] }\n\n const miss = (reason: string): PopulateRelationResult => {\n acc.issues.push(\n cmsIssue({\n code: 'unknown-relation-target',\n message: `Relation target \"${ref.collection}:${ref.id}\" could not be populated (${reason}).`,\n path: [ref.collection, ref.id],\n collectionId: ref.collection,\n documentId: ref.id,\n meta: { targetCollection: ref.collection, targetId: ref.id, reason },\n }),\n )\n return { document: null, issues: acc.issues }\n }\n\n const targetCollection = lookup.collection(ref.collection)\n if (!targetCollection) return miss('unknown collection')\n\n const source = lookup.document(ref)\n if (!source) return miss('document not found')\n\n const visible = selectPerspective(context, source)\n if (!visible) return miss(`not visible in ${context.perspective} perspective`)\n\n // Depth-1: the target's own relations stay stubs, its assets resolve to objects.\n const fields = resolveFields(context, lookup, targetCollection, visible, 1, [], acc)\n return {\n document: { id: ref.id, collection: ref.collection, ...fields },\n issues: acc.issues,\n }\n}\n","import type { CmsPath, CollectionDef, FieldDef } from '@elytracms/cms-core'\n\n/**\n * The closed v1 filter vocabulary (vision AD-3): equality, `in`, comparisons\n * (lt/lte/gt/gte), AND-only composition. Multiple `where` keys AND together;\n * multiple operators inside one condition AND together. There is no OR, no\n * nesting, no anything else — by design, so every query is enumerable,\n * cache-taggable, and honest about backend indexes.\n */\nexport const FILTER_OPERATORS = ['eq', 'gt', 'gte', 'in', 'lt', 'lte'] as const\nexport type FilterOperator = (typeof FILTER_OPERATORS)[number]\n\n/** A scalar a filter can compare against (relation/asset filters use the id). */\nexport type FilterScalar = string | number | boolean\n\n/** One field's filter: every present operator must hold (AND). */\nexport interface FilterCondition {\n eq?: FilterScalar\n gt?: FilterScalar\n gte?: FilterScalar\n in?: readonly FilterScalar[]\n lt?: FilterScalar\n lte?: FilterScalar\n}\n\n/**\n * The `where` input: field name → condition. A bare scalar is shorthand for\n * `{ eq: value }`. Generated per-collection types (`PostWhere`) narrow the\n * keys to the fields declared `filterable` in the schema.\n */\nexport type WhereInput = Readonly<Record<string, FilterScalar | FilterCondition | undefined>>\n\nexport type SortDirection = 'asc' | 'desc'\n\n/** Single-field sort; ties always break by document id ascending. */\nexport interface SortInput {\n field: string\n direction?: SortDirection\n}\n\n/** The full `listDocuments` query envelope (vision AD-3, rung 3). */\nexport interface ListDocumentsQuery<TWhere extends WhereInput = WhereInput> {\n where?: TWhere\n sort?: SortInput\n limit?: number\n cursor?: string\n}\n\n// ---------------------------------------------------------------------------\n// Structured query errors\n// ---------------------------------------------------------------------------\n\n/**\n * Codes for structured accessor query errors (EC-143). These describe *caller*\n * mistakes (bad filter, bad cursor), as opposed to `CmsValidationIssue`s which\n * describe content/schema problems. Accessors never throw — invalid queries\n * come back as an error result carrying these.\n */\nexport type ContentQueryErrorCode =\n | 'unknown-collection'\n | 'list-not-supported'\n | 'non-filterable-field'\n | 'invalid-filter'\n | 'invalid-sort'\n | 'invalid-limit'\n | 'invalid-cursor'\n\nexport interface ContentQueryError {\n code: ContentQueryErrorCode\n message: string\n /** Path into the query input, e.g. ['where', 'title'] or ['sort', 'field']. */\n path: CmsPath\n meta?: Record<string, unknown>\n}\n\nexport function queryError(\n code: ContentQueryErrorCode,\n message: string,\n path: CmsPath,\n meta?: Record<string, unknown>,\n): ContentQueryError {\n return { code, message, path, ...(meta ? { meta } : {}) }\n}\n\n// ---------------------------------------------------------------------------\n// Normalization\n// ---------------------------------------------------------------------------\n\n/** A condition with the `eq` shorthand expanded, operators in stable order. */\nexport type NormalizedCondition = Partial<\n Record<FilterOperator, FilterScalar | readonly FilterScalar[]>\n>\n\nexport interface NormalizedWhereEntry {\n field: string\n condition: NormalizedCondition\n}\n\nfunction isFilterScalar(value: unknown): value is FilterScalar {\n return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n}\n\nfunction isOperator(key: string): key is FilterOperator {\n return (FILTER_OPERATORS as readonly string[]).includes(key)\n}\n\n/**\n * Normalize a `where` input into entries sorted by field name, with the bare\n * scalar shorthand expanded to `{ eq: value }` and operators in the stable\n * `FILTER_OPERATORS` order. Both serialization and execution run on this\n * normal form, so `{ slug: 'x' }` and `{ slug: { eq: 'x' } }` are the same\n * query (and produce the same cache key).\n */\nexport function normalizeWhere(where: WhereInput): NormalizedWhereEntry[] {\n const entries: NormalizedWhereEntry[] = []\n for (const field of Object.keys(where).sort()) {\n const raw = where[field]\n if (raw === undefined) continue\n if (isFilterScalar(raw)) {\n entries.push({ field, condition: { eq: raw } })\n continue\n }\n const condition: NormalizedCondition = {}\n for (const op of FILTER_OPERATORS) {\n const value = (raw as Record<string, unknown>)[op]\n if (value === undefined) continue\n condition[op] = value as FilterScalar | readonly FilterScalar[]\n }\n entries.push({ field, condition })\n }\n return entries\n}\n\n// ---------------------------------------------------------------------------\n// Validation (filterable-field enforcement, EC-143)\n// ---------------------------------------------------------------------------\n\nfunction fieldByName(collection: CollectionDef, name: string): FieldDef | undefined {\n return collection.fields.find((f) => f.name === name)\n}\n\n/** The fields of a collection declared `filterable` (EC-143 schema flag). */\nexport function filterableFields(collection: CollectionDef): FieldDef[] {\n return collection.fields.filter((f) => f.filterable === true)\n}\n\n/**\n * Validate a `where` input against a collection schema. Filters are permitted\n * **only** on fields declared `filterable` — anything else is a structured\n * `non-filterable-field` error. Unknown operators and malformed operator\n * values are `invalid-filter` errors. All errors are collected (sorted by\n * field, deterministic), never thrown.\n */\nexport function validateWhere(collection: CollectionDef, where: WhereInput): ContentQueryError[] {\n const errors: ContentQueryError[] = []\n for (const field of Object.keys(where).sort()) {\n const raw = where[field]\n if (raw === undefined) continue\n const path: CmsPath = ['where', field]\n\n const def = fieldByName(collection, field)\n if (!def || def.filterable !== true) {\n errors.push(\n queryError(\n 'non-filterable-field',\n def\n ? `Field \"${field}\" on \"${collection.id}\" is not declared filterable.`\n : `Field \"${field}\" does not exist on \"${collection.id}\".`,\n path,\n { collection: collection.id, field },\n ),\n )\n continue\n }\n\n if (isFilterScalar(raw)) continue\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n errors.push(\n queryError(\n 'invalid-filter',\n `Filter for \"${field}\" must be a scalar or an operator object.`,\n path,\n ),\n )\n continue\n }\n\n const keys = Object.keys(raw).sort()\n if (keys.length === 0) {\n errors.push(queryError('invalid-filter', `Filter for \"${field}\" has no operators.`, path))\n continue\n }\n for (const key of keys) {\n const value = (raw as Record<string, unknown>)[key]\n if (value === undefined) continue\n const opPath: CmsPath = ['where', field, key]\n if (!isOperator(key)) {\n errors.push(\n queryError(\n 'invalid-filter',\n `Unknown filter operator \"${key}\" on \"${field}\" — the vocabulary is exactly ${FILTER_OPERATORS.join(', ')}.`,\n opPath,\n { operator: key },\n ),\n )\n continue\n }\n if (key === 'in') {\n if (!Array.isArray(value) || !value.every(isFilterScalar)) {\n errors.push(\n queryError(\n 'invalid-filter',\n `Operator \"in\" on \"${field}\" requires an array of scalars.`,\n opPath,\n ),\n )\n }\n continue\n }\n if (!isFilterScalar(value)) {\n errors.push(\n queryError(\n 'invalid-filter',\n `Operator \"${key}\" on \"${field}\" requires a scalar value.`,\n opPath,\n ),\n )\n }\n }\n }\n return errors\n}\n\n/**\n * Validate a sort input. Sorting uses the same `filterable` declaration as\n * filtering (same rationale: backend indexes stay honest).\n */\nexport function validateSort(collection: CollectionDef, sort: SortInput): ContentQueryError[] {\n const def = fieldByName(collection, sort.field)\n if (!def || def.filterable !== true) {\n return [\n queryError(\n 'invalid-sort',\n def\n ? `Sort field \"${sort.field}\" on \"${collection.id}\" is not declared filterable.`\n : `Sort field \"${sort.field}\" does not exist on \"${collection.id}\".`,\n ['sort', 'field'],\n { collection: collection.id, field: sort.field },\n ),\n ]\n }\n if (sort.direction !== undefined && sort.direction !== 'asc' && sort.direction !== 'desc') {\n return [\n queryError('invalid-sort', `Sort direction must be \"asc\" or \"desc\".`, ['sort', 'direction']),\n ]\n }\n return []\n}\n\n/** Validate a limit: a positive integer (or absent = no pagination). */\nexport function validateLimit(limit: number): ContentQueryError[] {\n if (!Number.isInteger(limit) || limit < 1) {\n return [queryError('invalid-limit', 'Limit must be a positive integer.', ['limit'])]\n }\n return []\n}\n\n// ---------------------------------------------------------------------------\n// Matching & ordering (pure, deterministic)\n// ---------------------------------------------------------------------------\n\n/**\n * Reduce a stored field value to the scalar filters compare against: scalars\n * pass through, relation refs compare by target id, anything else (arrays,\n * rich objects, missing) is `null` and never matches a condition.\n */\nexport function filterScalarOf(value: unknown): FilterScalar | null {\n if (isFilterScalar(value)) return value\n if (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n typeof (value as { id?: unknown }).id === 'string'\n ) {\n return (value as { id: string }).id\n }\n return null\n}\n\n/**\n * Three-way compare, or `null` when the values are uncomparable: an UNSET field\n * (`value === null`) or a type mismatch. Callers treat `null` as \"does not\n * match\", so an unset field is EXCLUDED from every comparison operator — unset\n * never satisfies a value comparison (EC-205). Pinned by query.test.ts.\n */\nfunction compares(value: FilterScalar | null, bound: FilterScalar): number | null {\n if (value === null) return null\n if (typeof value === 'number' && typeof bound === 'number') {\n return value < bound ? -1 : value > bound ? 1 : 0\n }\n if (typeof value === 'string' && typeof bound === 'string') {\n // Code-unit comparison: deterministic across environments (no locale tables).\n return value < bound ? -1 : value > bound ? 1 : 0\n }\n return null\n}\n\n/**\n * Does a stored field value satisfy one normalized condition? Scalars and single\n * relation/asset refs reduce via {@link filterScalarOf} and match directly. An\n * ARRAY field — a `many` relation/asset (EC-255) — matches with **contains**\n * semantics: the condition holds if ANY element satisfies it, so\n * `where: { categories: catId }` lists products whose `categories` array\n * contains `catId`. An empty array matches nothing. Scalar fields keep their\n * exact prior behavior (the non-array branch is the original reduce-then-match).\n */\nexport function matchesFieldValue(value: unknown, condition: NormalizedCondition): boolean {\n if (Array.isArray(value)) {\n return value.some((element) => matchesCondition(filterScalarOf(element), condition))\n }\n return matchesCondition(filterScalarOf(value), condition)\n}\n\n/** Does a (scalar-reduced) value satisfy one normalized condition? AND-only. */\nexport function matchesCondition(\n value: FilterScalar | null,\n condition: NormalizedCondition,\n): boolean {\n for (const op of FILTER_OPERATORS) {\n const bound = condition[op]\n if (bound === undefined) continue\n switch (op) {\n case 'eq':\n if (value !== bound) return false\n break\n case 'in':\n if (value === null || !(bound as readonly FilterScalar[]).includes(value)) return false\n break\n case 'lt':\n case 'lte':\n case 'gt':\n case 'gte': {\n const cmp = compares(value, bound as FilterScalar)\n if (cmp === null) return false\n if (op === 'lt' && !(cmp < 0)) return false\n if (op === 'lte' && !(cmp <= 0)) return false\n if (op === 'gt' && !(cmp > 0)) return false\n if (op === 'gte' && !(cmp >= 0)) return false\n break\n }\n }\n }\n return true\n}\n\n/**\n * Total, deterministic order over sort values: numbers first (numeric order),\n * then strings (code-unit order), then booleans (false < true), then missing\n * values (`null`). `desc` flips this entire order; the id tiebreak stays\n * ascending either way (see `compareListEntries`).\n */\nexport function compareSortValues(a: FilterScalar | null, b: FilterScalar | null): number {\n const rank = (v: FilterScalar | null): number =>\n typeof v === 'number' ? 0 : typeof v === 'string' ? 1 : typeof v === 'boolean' ? 2 : 3\n const ra = rank(a)\n const rb = rank(b)\n if (ra !== rb) return ra - rb\n if (typeof a === 'number' && typeof b === 'number') return a < b ? -1 : a > b ? 1 : 0\n if (typeof a === 'string' && typeof b === 'string') return a < b ? -1 : a > b ? 1 : 0\n if (typeof a === 'boolean' && typeof b === 'boolean') return a === b ? 0 : a ? 1 : -1\n return 0\n}\n\n/** One row in list ordering: its id plus its (scalar-reduced) sort value. */\nexport interface ListPosition {\n id: string\n sortValue: FilterScalar | null\n}\n\n/**\n * The canonical list order (and cursor position order): sort value in the\n * requested direction, then id ascending as the unconditional tiebreak — so\n * pagination is total, stable, and reproducible from fixtures.\n */\nexport function compareListEntries(\n a: ListPosition,\n b: ListPosition,\n direction: SortDirection,\n): number {\n const byValue = compareSortValues(a.sortValue, b.sortValue)\n const directed = direction === 'desc' ? -byValue : byValue\n if (directed !== 0) return directed\n return a.id < b.id ? -1 : a.id > b.id ? 1 : 0\n}\n","import { z } from 'zod'\nimport type { FilterScalar, SortDirection } from './query'\n\n/**\n * Deterministic cursor pagination for `listDocuments` (EC-143).\n *\n * Format: `ec1.<base64url(JSON payload)>` where the payload is\n * `{\"v\":1,\"f\":<sort field|null>,\"d\":\"asc\"|\"desc\",\"s\":<sort value|null>,\"i\":<doc id>}`\n * — the sort position (`f`/`d`/`s`) plus the id (`i`) of the last document\n * returned, with keys always written in that order. The next page is every\n * entry strictly after that position in the canonical list order\n * (`compareListEntries`). Encoding the sort spec into the cursor lets decode\n * reject a cursor reused with a different sort as `invalid-cursor` instead of\n * silently misordering.\n *\n * Encoding is byte-stable: same position in, same cursor string out.\n */\n\nexport const LIST_CURSOR_PREFIX = 'ec1.'\n\nconst cursorPayloadSchema = z.object({\n v: z.literal(1),\n f: z.string().nullable(),\n d: z.enum(['asc', 'desc']),\n s: z.union([z.string(), z.number(), z.boolean(), z.null()]),\n i: z.string().min(1),\n})\n\nexport interface ListCursor {\n /** Sort field the cursor was minted under (`null` = id order). */\n sortField: string | null\n direction: SortDirection\n /** Sort value of the last returned document (`null` when missing). */\n sortValue: FilterScalar | null\n /** Id of the last returned document (the unconditional tiebreak). */\n id: string\n}\n\nconst BASE64URL = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n\n/** Unpadded base64url over raw bytes — environment-independent (no Buffer). */\nfunction toBase64Url(bytes: Uint8Array): string {\n let out = ''\n for (let i = 0; i < bytes.length; i += 3) {\n const a = bytes[i] ?? 0\n const b = bytes[i + 1]\n const c = bytes[i + 2]\n out += BASE64URL[a >> 2]\n out += BASE64URL[((a & 0b11) << 4) | ((b ?? 0) >> 4)]\n if (b !== undefined) out += BASE64URL[((b & 0b1111) << 2) | ((c ?? 0) >> 6)]\n if (c !== undefined) out += BASE64URL[c & 0b111111]\n }\n return out\n}\n\nfunction fromBase64Url(text: string): Uint8Array | null {\n const values: number[] = []\n for (const char of text) {\n const value = BASE64URL.indexOf(char)\n if (value === -1) return null\n values.push(value)\n }\n if (values.length % 4 === 1) return null\n const bytes: number[] = []\n for (let i = 0; i < values.length; i += 4) {\n const [a, b, c, d] = [values[i], values[i + 1], values[i + 2], values[i + 3]]\n if (a === undefined || b === undefined) break\n bytes.push((a << 2) | (b >> 4))\n if (c !== undefined) bytes.push(((b & 0b1111) << 4) | (c >> 2))\n if (d !== undefined) bytes.push((((c ?? 0) & 0b11) << 6) | d)\n }\n return new Uint8Array(bytes)\n}\n\n/** Encode a list position into an opaque, URL-safe cursor string. */\nexport function encodeListCursor(cursor: ListCursor): string {\n // Key order is fixed by construction (v, f, d, s, i) — byte-stable output.\n const payload = JSON.stringify({\n v: 1,\n f: cursor.sortField,\n d: cursor.direction,\n s: cursor.sortValue,\n i: cursor.id,\n })\n return LIST_CURSOR_PREFIX + toBase64Url(new TextEncoder().encode(payload))\n}\n\n/**\n * Decode a cursor string. Returns `null` for anything malformed — wrong\n * prefix, bad base64, bad JSON, wrong shape. Never throws; the caller maps\n * `null` to a structured `invalid-cursor` error.\n */\nexport function decodeListCursor(text: string): ListCursor | null {\n if (!text.startsWith(LIST_CURSOR_PREFIX)) return null\n const bytes = fromBase64Url(text.slice(LIST_CURSOR_PREFIX.length))\n if (!bytes) return null\n let parsed: unknown\n try {\n parsed = JSON.parse(new TextDecoder().decode(bytes))\n } catch {\n return null\n }\n const payload = cursorPayloadSchema.safeParse(parsed)\n if (!payload.success) return null\n return {\n sortField: payload.data.f,\n direction: payload.data.d,\n sortValue: payload.data.s,\n id: payload.data.i,\n }\n}\n","import { documentKey } from '@elytracms/cms-core'\nimport type { CollectionDef, Locale } from '@elytracms/cms-core'\nimport type { ResolvedDocument } from './resolve'\n\n/**\n * Cache-tag metadata carried by every accessor result (EC-143, vision AD-5):\n * fetch-time tagging of what was *actually returned*, so EC-146 can map each\n * entry to a `revalidateTag` call. Deterministic by construction — every list\n * is sorted and deduplicated.\n */\nexport interface CacheTags {\n /**\n * Identities of every document whose content is present in the result —\n * the returned documents themselves plus their depth-1 populated relation\n * targets. Entries are `documentKey` strings (`collection:id`), sorted.\n */\n docs: string[]\n /**\n * Collections the accessor read from (the coarse membership tags of AD-5:\n * create/delete/publish in a collection sweeps them). Sorted.\n */\n collections: string[]\n /**\n * Normalized URL paths the accessor touched (`resolvePage` only): the\n * requested path, plus every hop of a redirect chain — editing any hop\n * changes the result. Sorted.\n */\n routes: string[]\n /**\n * Asset ids the result *baked* its delivery shape from (EC-227): the page's\n * page-scoped `ResolvedAsset` set (url/dimensions/alt) + its `seoOgImage`.\n * Editing the asset record (alt/dimensions/re-upload) must drop the page that\n * baked it — without this dimension the only invalidation triggers are\n * unrelated (doc/collection/project), so an asset-only edit serves stale\n * until one of those fires. Sorted.\n */\n assets: string[]\n /** The locale the result was resolved for. */\n locale: Locale\n}\n\nexport interface CacheTagsInit {\n docs?: readonly string[]\n collections?: readonly string[]\n routes?: readonly string[]\n assets?: readonly string[]\n locale: Locale\n}\n\nfunction sortedUnique(values: readonly string[]): string[] {\n return [...new Set(values)].sort()\n}\n\n/** Build a `CacheTags` with deterministic (sorted, deduplicated) entries. */\nexport function cacheTags(init: CacheTagsInit): CacheTags {\n return {\n docs: sortedUnique(init.docs ?? []),\n collections: sortedUnique(init.collections ?? []),\n routes: sortedUnique(init.routes ?? []),\n assets: sortedUnique(init.assets ?? []),\n locale: init.locale,\n }\n}\n\n/**\n * The document tags one resolved document contributes: its own identity plus\n * every relation target referenced in its top-level relation fields. Populated\n * targets had their content returned (so a change to them must invalidate);\n * stubs are included too — slightly coarse, always correct (AD-5 stance).\n */\nexport function documentCacheKeys(collection: CollectionDef, document: ResolvedDocument): string[] {\n const keys = [documentKey({ collection: document.collection, id: document.id })]\n for (const field of collection.fields) {\n if (field.type !== 'relation') continue\n const value = document[field.name]\n const entries = Array.isArray(value) ? value : [value]\n for (const entry of entries) {\n if (\n entry !== null &&\n typeof entry === 'object' &&\n typeof (entry as { id?: unknown }).id === 'string' &&\n typeof (entry as { collection?: unknown }).collection === 'string'\n ) {\n const ref = entry as { id: string; collection: string }\n keys.push(documentKey({ collection: ref.collection, id: ref.id }))\n }\n }\n }\n return keys\n}\n","import {\n cmsIssue,\n createRouter,\n hierarchyMount,\n isHierarchical,\n isHierarchyTemplate,\n resolveByPath,\n resolveField,\n splitPath,\n} from '@elytracms/cms-core'\nimport type {\n CmsDocument,\n CmsValidationIssue,\n CollectionDef,\n DocumentRef,\n HierarchyMount,\n Locale,\n RedirectRecord,\n ResolveStatus,\n RouteRecord,\n} from '@elytracms/cms-core'\nimport type { ContentContext } from './context'\nimport { decodeListCursor, encodeListCursor } from './cursor'\nimport { selectPerspective } from './perspective'\nimport type { ContentDocumentSource } from './perspective'\nimport {\n compareListEntries,\n filterScalarOf,\n matchesFieldValue,\n normalizeWhere,\n queryError,\n validateLimit,\n validateSort,\n validateWhere,\n} from './query'\nimport type {\n ContentQueryError,\n FilterScalar,\n ListDocumentsQuery,\n SortDirection,\n WhereInput,\n} from './query'\nimport { populateRelationRef, resolveDocument } from './resolve'\nimport type { ContentLookup, DeliveryDocument, ResolutionInfo, ResolvedDocument } from './resolve'\nimport { resolveLocaleValues } from './locale'\nimport { cacheTags, documentCacheKeys } from './tags'\nimport type { CacheTags } from './tags'\n\n/**\n * The closed-form v1 query surface (EC-143, vision AD-3): `resolvePage`,\n * `getDocument`, `listDocuments` — no query language. Every result is\n * delivery-shaped (EC-142) and carries deterministic `CacheTags` for EC-146.\n *\n * Pure and synchronous like the rest of the package: the client reads through\n * a `ContentLookup`; EC-144/EC-145 bind it to Convex/Next later. The ambient\n * `{ locale, perspective }` context is taken once at creation — never per-call\n * ceremony (per-call `locale` overrides exist for route-level needs only).\n */\n\n// ---------------------------------------------------------------------------\n// Result shapes\n// ---------------------------------------------------------------------------\n\nexport interface ResolvePageResult {\n /** Route resolution status (EC-019 parity): ok | redirect | notFound. */\n status: ResolveStatus\n /** The matched route record, when status is `ok`. */\n route: RouteRecord | null\n /** Extracted dynamic params, e.g. `{ slug: 'hello-world' }`. */\n dynamicParams: Record<string, string>\n /** True when route matching fell back to the default locale (EC-018). */\n localeFallback: boolean\n /** Terminal redirect target + permanence, when status is `redirect`. */\n redirect: { target: string; permanent: boolean } | null\n /**\n * The document this URL resolves to, delivery-shaped (EC-142, EC-187). A\n * `page`-collection document (its `body` composition renders into a layout)\n * or a content-collection document (rendered by a dev route component). SEO\n * for a page is read from this document's flat `seo*` fields — there is no\n * separate page-graph `seo` block anymore.\n */\n document: ResolvedDocument | null\n issues: CmsValidationIssue[]\n tags: CacheTags\n}\n\nexport interface GetDocumentResult<TDoc extends DeliveryDocument = ResolvedDocument> {\n /**\n * The delivery-shaped document, or `null` when not found / not visible in\n * the context perspective (correct behavior, not an error — see EC-142).\n */\n document: TDoc | null\n info: ResolutionInfo | null\n issues: CmsValidationIssue[]\n tags: CacheTags\n}\n\nexport type ListDocumentsResult<TDoc extends DeliveryDocument = ResolvedDocument> =\n | {\n ok: true\n documents: TDoc[]\n /** Cursor for the next page, `null` when this page exhausts the list. */\n nextCursor: string | null\n issues: CmsValidationIssue[]\n tags: CacheTags\n }\n | {\n /** The query itself was invalid (never thrown — structured errors). */\n ok: false\n errors: ContentQueryError[]\n tags: CacheTags\n }\n\nexport interface ContentClient {\n readonly context: ContentContext\n /** Structural route issues from construction (conflicts, redirect loops). */\n readonly routerIssues: readonly CmsValidationIssue[]\n resolvePage(url: string, locale?: Locale): ResolvePageResult\n getDocument<TDoc extends DeliveryDocument = ResolvedDocument>(\n collection: string,\n idOrSlug: string,\n locale?: Locale,\n ): GetDocumentResult<TDoc>\n listDocuments<\n TDoc extends DeliveryDocument = ResolvedDocument,\n TWhere extends WhereInput = WhereInput,\n >(\n collection: string,\n query?: ListDocumentsQuery<TWhere>,\n ): ListDocumentsResult<TDoc>\n /**\n * Populate a relation reference to depth-1 delivery shape (EC-254), or `null`\n * when the target is missing or not visible in the active perspective. A\n * renderer host wires this as `RenderContext.resolveRelation` to populate the\n * COMPOSITION-NODE relation props of the nodes inside a page's `blocks` field\n * (e.g. a ProductGrid block's picked `product`s) — which `resolvePage` leaves\n * raw, since document resolution does not descend into a composition value.\n */\n resolveRelation(ref: DocumentRef): ResolvedDocument | null\n}\n\nexport interface ContentClientInit {\n lookup: ContentLookup\n context: ContentContext\n /** Route records for `resolvePage` (EC-019). */\n routes?: readonly RouteRecord[]\n /** Redirect records for `resolvePage` (EC-019/020). */\n redirects?: readonly RedirectRecord[]\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\nfunction withLocale(context: ContentContext, locale: Locale | undefined): ContentContext {\n return locale === undefined || locale === context.locale ? context : { ...context, locale }\n}\n\nfunction normalizePath(url: string): string {\n return '/' + splitPath(url).join('/')\n}\n\n/** Internal row used for list ordering before delivery resolution. */\ninterface ListEntry {\n source: ContentDocumentSource\n id: string\n sortValue: FilterScalar | null\n}\n\n/**\n * Template routes (EC-166): a route-bound document ref may be parameterized —\n * `document: { collection: 'post', id: ':slug' }` — so one route record serves\n * *every* document of a collection through its dynamic pattern. The `:name`\n * placeholder names a dynamic param of the pattern; resolution substitutes the\n * matched URL value, which may be a document id or a slug (the bound-document\n * lookup accepts either).\n */\nfunction materializeRouteDocumentRef(\n ref: { collection: string; id: string },\n params: Record<string, string>,\n): { ok: true; ref: { collection: string; id: string } } | { ok: false; missingParam: string } {\n if (!ref.id.startsWith(':')) return { ok: true, ref }\n const param = ref.id.slice(1)\n const value = params[param]\n if (value === undefined || value.length === 0) return { ok: false, missingParam: param }\n return { ok: true, ref: { collection: ref.collection, id: value } }\n}\n\n/** The catch-all param name of a hierarchy mount template (`/docs/:path*` → `path`). */\nfunction mountParamName(route: RouteRecord): string {\n const last = splitPath(route.pattern).at(-1) ?? ''\n return last.replace(/^:/, '').replace(/\\*$/, '')\n}\n\n/** Create the typed accessor client (vision AD-3 ladder, rungs 1–3). */\nexport function createContentClient(init: ContentClientInit): ContentClient {\n const { lookup, context } = init\n const allRoutes = init.routes ?? []\n // EC-218: a hierarchy mount (`{ pattern: '/:path*', document: { collection } }`)\n // serves a collection's documents by their COMPOSED nested path. Mounts are\n // pulled out of the router and resolved per-request (below) so the URL→document\n // mapping stays perspective-aware (draft vs published) and the path stays\n // derived from the parent chain, never stored. Ordinary routes are unaffected.\n const mounts = allRoutes\n .map((route) => {\n const mount = hierarchyMount(route)\n return mount ? { mount, route } : undefined\n })\n .filter((m): m is { mount: HierarchyMount; route: RouteRecord } => m !== undefined)\n const router = createRouter(\n allRoutes.filter((route) => !isHierarchyTemplate(route)),\n init.redirects ?? [],\n { defaultLocale: context.locales.default },\n )\n\n const resolveBoundDocument = (\n ctx: ContentContext,\n ref: { collection: string; id: string },\n issues: CmsValidationIssue[],\n docKeys: string[],\n collections: string[],\n ): ResolvedDocument | null => {\n collections.push(ref.collection)\n const collection = lookup.collection(ref.collection)\n // Template routes substitute a URL param into the ref id; the value may be\n // a slug rather than an id, so fall back to the deterministic slug lookup.\n const source =\n lookup.document(ref) ?? (collection ? findBySlug(ctx, collection, ref.id) : undefined)\n if (!source) {\n issues.push(\n cmsIssue({\n code: 'unknown-route-target',\n message: `Route-bound document \"${ref.collection}:${ref.id}\" was not found.`,\n path: ['document'],\n collectionId: ref.collection,\n documentId: ref.id,\n }),\n )\n return null\n }\n const result = resolveDocument(ctx, lookup, source)\n issues.push(...result.issues)\n if (result.document && collection) {\n docKeys.push(...documentCacheKeys(collection, result.document))\n }\n return result.document\n }\n\n const resolvePage = (url: string, locale?: Locale): ResolvePageResult => {\n const ctx = withLocale(context, locale)\n const path = normalizePath(url)\n const resolution = router.resolveUrl(path, ctx.locale)\n\n const issues: CmsValidationIssue[] = []\n const docKeys: string[] = []\n const collections: string[] = []\n const routePaths: string[] = [path]\n\n if (resolution.status === 'redirect') {\n // Tag every hop: editing any redirect in the chain changes this result.\n const chain = router.followRedirects(path)\n routePaths.push(...chain.chain)\n return {\n status: 'redirect',\n route: null,\n dynamicParams: {},\n localeFallback: false,\n redirect: {\n target: resolution.redirectTarget ?? chain.target,\n permanent: resolution.permanent ?? chain.permanent,\n },\n document: null,\n issues,\n tags: cacheTags({ routes: routePaths, locale: ctx.locale }),\n }\n }\n\n if (resolution.status === 'notFound') {\n // EC-218: a router miss falls through to the hierarchy mounts — resolve the\n // URL against a collection's composed page tree. Explicit/static routes and\n // templates already had precedence (they would not have missed). The first\n // mount whose prefix matches and that resolves a page wins.\n const urlSegments = splitPath(path)\n for (const { mount, route } of mounts) {\n if (mount.locale !== undefined && mount.locale !== ctx.locale) continue\n if (urlSegments.length <= mount.prefix.length) continue\n if (!mount.prefix.every((seg, i) => urlSegments[i] === seg)) continue\n const collection = lookup.collection(mount.collection)\n if (!collection || !isHierarchical(collection)) continue\n const rest = urlSegments.slice(mount.prefix.length)\n const source = findByComposedPath(ctx, mount.collection, rest)\n if (!source) continue\n collections.push(mount.collection)\n const result = resolveDocument(ctx, lookup, source)\n issues.push(...result.issues)\n if (!result.document) continue\n docKeys.push(...documentCacheKeys(collection, result.document))\n return {\n status: 'ok',\n route,\n dynamicParams: { [mountParamName(route)]: rest.join('/') },\n localeFallback: false,\n redirect: null,\n document: result.document,\n issues,\n tags: cacheTags({ docs: docKeys, collections, routes: routePaths, locale: ctx.locale }),\n }\n }\n return {\n status: 'notFound',\n route: null,\n dynamicParams: {},\n localeFallback: resolution.fallback,\n redirect: null,\n document: null,\n issues,\n tags: cacheTags({ routes: routePaths, locale: ctx.locale }),\n }\n }\n\n const route = resolution.route ?? null\n\n let document: ResolvedDocument | null = null\n let documentMissing = false\n if (resolution.documentRef) {\n const materialized = materializeRouteDocumentRef(\n resolution.documentRef,\n resolution.dynamicParams,\n )\n if (materialized.ok) {\n document = resolveBoundDocument(ctx, materialized.ref, issues, docKeys, collections)\n documentMissing = document === null\n } else {\n documentMissing = true\n // Parameterized document ref whose param the pattern never captures —\n // a structured issue, never a silent null (EC-166).\n collections.push(resolution.documentRef.collection)\n issues.push(\n cmsIssue({\n code: 'unknown-route-target',\n message: `Route \"${route?.id ?? path}\" binds its document to URL parameter \":${materialized.missingParam}\", which pattern \"${route?.pattern ?? path}\" does not capture.`,\n path: ['routes', route?.id ?? path, 'document'],\n collectionId: resolution.documentRef.collection,\n meta: { param: materialized.missingParam, pattern: route?.pattern },\n }),\n )\n }\n }\n\n // A document-bound route whose document does not resolve in this\n // perspective is NOT a page (EC-177 gap 6): the URL of an unpublished\n // document must be a notFound result — the host's 404 — never a bare\n // contentless template served as 200. The draft perspective still\n // resolves the draft row, so preview keeps seeing the page. The\n // structured issues and the doc/collection cache tags are carried so the\n // cached 404 revalidates the moment the document (re)publishes.\n if (documentMissing) {\n return {\n status: 'notFound',\n route: null,\n dynamicParams: resolution.dynamicParams,\n localeFallback: resolution.fallback,\n redirect: null,\n document: null,\n issues,\n tags: cacheTags({ docs: docKeys, collections, routes: routePaths, locale: ctx.locale }),\n }\n }\n\n return {\n status: 'ok',\n route,\n dynamicParams: resolution.dynamicParams,\n localeFallback: resolution.fallback,\n redirect: null,\n document,\n issues,\n tags: cacheTags({ docs: docKeys, collections, routes: routePaths, locale: ctx.locale }),\n }\n }\n\n /** Deterministic slug fallback: visible rows whose `slug` resolves to the value, lowest id wins. */\n const findBySlug = (\n ctx: ContentContext,\n collection: CollectionDef,\n slug: string,\n ): ContentDocumentSource | undefined => {\n if (!lookup.documents) return undefined\n if (!collection.fields.some((f) => f.name === 'slug')) return undefined\n const matches: { id: string; source: ContentDocumentSource }[] = []\n for (const source of lookup.documents(collection.id)) {\n const row = selectPerspective(ctx, source)\n if (!row) continue\n const value = resolveField(collection, row, 'slug', ctx.locale, ctx.locales).value\n if (value === slug) matches.push({ id: row.id, source })\n }\n matches.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))\n return matches[0]?.source\n }\n\n /**\n * EC-218: resolve a composed nested path (prefix already stripped) to the page\n * document whose parent chain of slugs matches it. Matches against the rows\n * visible in the active perspective, so an unpublished page simply does not\n * resolve on the published site (correct, not an issue) while preview still\n * sees the draft. Returns the source so the normal `resolveDocument` path runs.\n */\n const findByComposedPath = (\n ctx: ContentContext,\n collectionId: string,\n segments: string[],\n ): ContentDocumentSource | undefined => {\n if (!lookup.documents) return undefined\n const rows: CmsDocument[] = []\n const sourceById = new Map<string, ContentDocumentSource>()\n for (const source of lookup.documents(collectionId)) {\n const row = selectPerspective(ctx, source)\n if (!row) continue\n rows.push(row)\n sourceById.set(row.id, source)\n }\n const matched = resolveByPath(segments, rows)\n return matched ? sourceById.get(matched.id) : undefined\n }\n\n const getDocument = <TDoc extends DeliveryDocument = ResolvedDocument>(\n collectionId: string,\n idOrSlug: string,\n locale?: Locale,\n ): GetDocumentResult<TDoc> => {\n const ctx = withLocale(context, locale)\n const baseTags = { collections: [collectionId], locale: ctx.locale }\n\n const collection = lookup.collection(collectionId)\n if (!collection) {\n return {\n document: null,\n info: null,\n issues: [\n cmsIssue({\n code: 'unknown-collection',\n message: `Collection \"${collectionId}\" is not defined.`,\n path: ['collection'],\n collectionId,\n }),\n ],\n tags: cacheTags(baseTags),\n }\n }\n\n const source =\n lookup.document({ collection: collectionId, id: idOrSlug }) ??\n findBySlug(ctx, collection, idOrSlug)\n if (!source) {\n return { document: null, info: null, issues: [], tags: cacheTags(baseTags) }\n }\n\n const result = resolveDocument(ctx, lookup, source)\n const docKeys = result.document ? documentCacheKeys(collection, result.document) : []\n return {\n // The generated per-collection delivery type (EC-142 codegen) is the\n // static face of what resolveDocument produces for this collection.\n document: result.document as TDoc | null,\n info: result.info,\n issues: result.issues,\n tags: cacheTags({ ...baseTags, docs: docKeys }),\n }\n }\n\n const listDocuments = <\n TDoc extends DeliveryDocument = ResolvedDocument,\n TWhere extends WhereInput = WhereInput,\n >(\n collectionId: string,\n query: ListDocumentsQuery<TWhere> = {},\n ): ListDocumentsResult<TDoc> => {\n const ctx = context\n const errorTags = cacheTags({ collections: [collectionId], locale: ctx.locale })\n const errors: ContentQueryError[] = []\n\n const collection = lookup.collection(collectionId)\n if (!collection) {\n errors.push(\n queryError('unknown-collection', `Collection \"${collectionId}\" is not defined.`, [\n 'collection',\n ]),\n )\n return { ok: false, errors, tags: errorTags }\n }\n if (!lookup.documents) {\n errors.push(\n queryError(\n 'list-not-supported',\n 'This content lookup does not provide a `documents` capability.',\n [],\n ),\n )\n return { ok: false, errors, tags: errorTags }\n }\n\n if (query.where) errors.push(...validateWhere(collection, query.where))\n if (query.sort) errors.push(...validateSort(collection, query.sort))\n if (query.limit !== undefined) errors.push(...validateLimit(query.limit))\n\n const sortField = query.sort?.field ?? null\n const direction: SortDirection = query.sort?.direction ?? 'asc'\n\n let after: { sortValue: FilterScalar | null; id: string } | null = null\n if (query.cursor !== undefined) {\n const decoded = decodeListCursor(query.cursor)\n if (!decoded || decoded.sortField !== sortField || decoded.direction !== direction) {\n errors.push(\n queryError(\n 'invalid-cursor',\n decoded\n ? 'Cursor was minted under a different sort and cannot be reused.'\n : 'Cursor is malformed.',\n ['cursor'],\n ),\n )\n } else {\n after = { sortValue: decoded.sortValue, id: decoded.id }\n }\n }\n\n if (errors.length > 0) return { ok: false, errors, tags: errorTags }\n\n const where = normalizeWhere(query.where ?? {})\n\n // Filter + order over locale-resolved raw values (EC-018 fallback applies\n // to filtering too); delivery resolution runs only on the returned page.\n const entries: ListEntry[] = []\n for (const source of lookup.documents(collectionId)) {\n const row = selectPerspective(ctx, source)\n if (!row || row.collection !== collectionId) continue\n const values = resolveLocaleValues(ctx, collection, row).values\n const matches = where.every((entry) =>\n matchesFieldValue(values[entry.field], entry.condition),\n )\n if (!matches) continue\n entries.push({\n source,\n id: row.id,\n sortValue: sortField === null ? row.id : filterScalarOf(values[sortField]),\n })\n }\n entries.sort((a, b) =>\n compareListEntries(\n { id: a.id, sortValue: a.sortValue },\n { id: b.id, sortValue: b.sortValue },\n direction,\n ),\n )\n\n const afterPosition = after\n const fromIndex = afterPosition\n ? entries.findIndex(\n (entry) =>\n compareListEntries(\n { id: entry.id, sortValue: entry.sortValue },\n afterPosition,\n direction,\n ) > 0,\n )\n : 0\n const start = fromIndex === -1 ? entries.length : fromIndex\n const end = query.limit !== undefined ? start + query.limit : entries.length\n const pageEntries = entries.slice(start, end)\n const hasMore = end < entries.length\n\n const documents: ResolvedDocument[] = []\n const issues: CmsValidationIssue[] = []\n const docKeys: string[] = []\n for (const entry of pageEntries) {\n const result = resolveDocument(ctx, lookup, entry.source)\n issues.push(...result.issues)\n if (result.document) {\n documents.push(result.document)\n docKeys.push(...documentCacheKeys(collection, result.document))\n }\n }\n\n const last = pageEntries[pageEntries.length - 1]\n const nextCursor =\n hasMore && last\n ? encodeListCursor({ sortField, direction, sortValue: last.sortValue, id: last.id })\n : null\n\n return {\n ok: true,\n // The generated per-collection delivery type (EC-142 codegen) is the\n // static face of what resolveDocument produces for this collection.\n documents: documents as TDoc[],\n nextCursor,\n issues,\n tags: cacheTags({\n docs: docKeys,\n collections: [collectionId],\n locale: ctx.locale,\n }),\n }\n }\n\n const resolveRelation = (ref: DocumentRef): ResolvedDocument | null =>\n populateRelationRef(context, lookup, ref).document\n\n return {\n context,\n routerIssues: router.issues,\n resolvePage,\n getDocument,\n listDocuments,\n resolveRelation,\n }\n}\n","import type { ListDocumentsQuery, SortInput, WhereInput } from './query'\n\n/**\n * Binding-source identities & stored-query replay (EC-166 delivery half).\n *\n * The builder models collection-driven layouts as per-scope CMS sources. A\n * repeating section is a per-section list source `cms.section.<nodeId>` whose\n * config carries the closed AD-3 query (where/sort/limit).\n *\n * This prefix is a delivery contract: when a published graph renders in the\n * embedded runtime, the host materializes each section source by replaying the\n * stored query through `listDocuments` (published perspective, ambient locale).\n * The constant lives here — the delivery side — so the builder and every host\n * speak the same identity scheme.\n *\n * EC-187: the `cms.template.<pageId>` \"current document\" source is RETIRED.\n * Pages are `page`-collection documents (no template page), and a collection\n * detail route binds its document directly via the route's `document` ref —\n * the dev route component reads it, no per-page source indirection.\n */\n\nexport const SECTION_SOURCE_PREFIX = 'cms.section.'\n\n/** The per-section list source id of a repeating section node. */\nexport function sectionSourceId(nodeId: string): string {\n return `${SECTION_SOURCE_PREFIX}${nodeId}`\n}\n\nexport function isSectionSourceId(sourceId: string): boolean {\n return sourceId.startsWith(SECTION_SOURCE_PREFIX)\n}\n\n/**\n * The stored config of a CMS query source, as the builder persists it\n * (`@elytracms/data-binding`'s cms config): the AD-3 `where` shape stored\n * verbatim in `filter`, plus optional `sort` and `limit`. Structural — this\n * package does not depend on the builder-side source schemas.\n */\nexport interface CmsSourceQueryConfig {\n collectionId: string\n /** Set on single-document sources (template pages); list sources omit it. */\n documentId?: string\n /** AD-3 `where` input (eq/in/lt/lte/gt/gte, AND-only), stored verbatim. */\n filter?: WhereInput\n sort?: SortInput\n limit?: number\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * Read a stored source config back into its structural shape. Total and\n * lenient by design: only the envelope is checked here — `where`/`sort`/\n * `limit` *contents* are validated by `listDocuments` itself, which answers\n * invalid queries as structured errors (never a throw). A malformed envelope\n * yields `undefined`, so the caller degrades to an unresolved binding (the\n * renderer's visible fallback), never a crash.\n */\nexport function parseCmsSourceQueryConfig(value: unknown): CmsSourceQueryConfig | undefined {\n if (!isPlainObject(value)) return undefined\n const collectionId = value.collectionId\n if (typeof collectionId !== 'string' || collectionId.length === 0) return undefined\n\n const config: CmsSourceQueryConfig = { collectionId }\n if (typeof value.documentId === 'string') config.documentId = value.documentId\n if (isPlainObject(value.filter)) config.filter = value.filter as WhereInput\n if (typeof value.limit === 'number') config.limit = value.limit\n\n const sort = value.sort\n if (isPlainObject(sort) && typeof sort.field === 'string') {\n const direction = sort.direction\n config.sort = {\n field: sort.field,\n ...(direction === 'asc' || direction === 'desc' ? { direction } : {}),\n }\n }\n\n return config\n}\n\n/**\n * The `listDocuments` query a stored section config replays at delivery —\n * exactly the where/sort/limit the editor picked in the builder (the canonical\n * validators run inside `listDocuments`; nothing is widened here).\n */\nexport function listQueryOfCmsConfig(config: CmsSourceQueryConfig): ListDocumentsQuery {\n return {\n ...(config.filter !== undefined && Object.keys(config.filter).length > 0\n ? { where: config.filter }\n : {}),\n ...(config.sort !== undefined ? { sort: config.sort } : {}),\n ...(config.limit !== undefined ? { limit: config.limit } : {}),\n }\n}\n","import type { Locale, LocaleConfig, RouteRecord } from '@elytracms/cms-core'\nimport { cacheTags } from '@elytracms/content'\nimport type { CacheTags, ContentClient, Perspective, ResolvedAsset } from '@elytracms/content'\nimport type { ProjectGraph } from '@elytracms/project-graph'\n\n/**\n * The content seam of the embedded runtime (EC-144, vision AD-1/AD-4): the\n * catch-all route helper consumes this interface, so where the content comes\n * from is swappable. EC-144 ships the in-memory snapshot bridge\n * (`createContentSnapshot` over a `PersistenceAdapter`); EC-145/146 plug a\n * Convex-backed source into the exact same seam.\n *\n * Accessors are synchronous over a prefetched `ContentLookup` (vision AD-4);\n * any fetching happens when the source is loaded, before clients are minted.\n */\n/**\n * One data-source definition the published graph's bindings reference\n * (EC-166 delivery): the structural shape of an `@elytracms/data-binding`\n * `DataSource`, declared here so the embedded runtime stays free of\n * builder-side packages. Only `cms`-kind sources with the EC-166 per-scope id\n * prefixes (`cms.section.<nodeId>` / `cms.template.<pageId>`) participate in\n * automatic payload materialization; everything else is ignored.\n */\nexport interface CanvasDataSource {\n kind: string\n id: string\n label?: string\n /** Kind-specific config; cms query configs parse via `@elytracms/content`. */\n config?: unknown\n}\n\nexport interface ContentSource {\n /** The project's locale configuration (default + supported set, EC-018). */\n readonly locales: LocaleConfig\n /**\n * Mint a typed accessor client (EC-143) bound to a perspective. The locale\n * defaults to the project default; the route helper overrides it per\n * request from the URL's locale prefix.\n */\n client(init: { perspective: Perspective; locale?: Locale }): ContentClient\n /**\n * The full project graph visible in a perspective — `draft` is the latest\n * working revision, `published` the revision pinned by publishing state.\n * `null` when nothing is visible (e.g. never published). The renderer needs\n * the graph (not just the page) for layout composition.\n */\n graph(perspective: Perspective): ProjectGraph | null\n /**\n * The route records the source's clients resolve against (EC-171, additive).\n * Lets enumerating consumers — the sitemap helper — walk the same route\n * table `resolvePage` uses, instead of keeping a second list. Optional so\n * existing custom sources stay valid; without it the sitemap helper needs\n * explicit routes.\n */\n readonly routes?: readonly RouteRecord[]\n /**\n * Data-source definitions the graph's bindings reference (EC-166 delivery,\n * additive). When present, the route helper materializes per-section list\n * sources automatically by replaying their stored where/sort/limit through\n * `listDocuments` — see `materializeSourcePayloads`. Optional so existing\n * custom sources stay valid; absent definitions degrade to unresolved\n * bindings (the renderer's visible fallbacks), never a crash.\n */\n readonly sources?: readonly CanvasDataSource[]\n /**\n * The project's delivery-shaped assets (EC-195, additive). Lets the route\n * helper bake the assets a page may reference into the (serializable) render\n * outcome, so the renderer can resolve an `asset`-typed Image prop to a usable\n * url + intrinsic dimensions — and a cached page keeps its images during a\n * backend outage. Optional so existing custom sources stay valid; without it,\n * asset-typed props fall back to their raw value (the renderer's visible\n * degradation), never a crash.\n */\n assets?(): readonly ResolvedAsset[]\n}\n\n/**\n * Merge accessor cache tags into one deterministic set (sorted, deduplicated)\n * — used by the route helper to combine the `resolvePage` tags with tags\n * added by the host's payload factory (e.g. a `listDocuments` call). The\n * merged set is what the EC-146 `onTags` hook receives.\n */\nexport function mergeCacheTags(first: CacheTags, ...rest: readonly CacheTags[]): CacheTags {\n const all = [first, ...rest]\n return cacheTags({\n docs: all.flatMap((t) => t.docs),\n collections: all.flatMap((t) => t.collections),\n routes: all.flatMap((t) => t.routes),\n assets: all.flatMap((t) => t.assets),\n locale: first.locale,\n })\n}\n","import {\n isSectionSourceId,\n listQueryOfCmsConfig,\n parseCmsSourceQueryConfig,\n} from '@elytracms/content'\nimport type { CacheTags, ContentClient, ResolvePageResult } from '@elytracms/content'\nimport type { ComponentNode, ProjectGraph } from '@elytracms/project-graph'\nimport { sourcePayloadError } from './payloads'\nimport type { BindingPayloads } from './payloads'\nimport type { CanvasDataSource } from './source'\n\n/**\n * Automatic payload materialization for EC-166 repeating sections — the\n * delivery half of the builder's collection-driven LAYOUTS (EC-187: layouts\n * are the only graph trees that can bind section sources now). A published\n * layout may carry bindings against per-scope CMS sources; the renderer needs\n * the source PAYLOADS:\n *\n * - **Repeating sections** (`cms.section.<nodeId>`): the stored source config\n * carries the closed AD-3 query. For every section source a referenced\n * layout tree actually binds, the stored where/sort/limit replays through\n * the request client's `listDocuments` — published perspective and ambient\n * locale come from the client itself. The list result's `CacheTags` (the\n * fetch-time doc tags of what was actually returned plus the coarse\n * collection tag — the EC-146 contract) are surfaced so the route helper\n * merges them into the request tag set.\n *\n * The `cms.template.<pageId>` \"current document\" source is RETIRED (EC-187):\n * there is no template page, and a routed page document's `body` uses static\n * props (v1). A collection detail route's document is read by the dev route\n * component directly via the route's `document` ref.\n *\n * Everything degrades visibly, never a crash:\n *\n * - a missing source definition, a non-cms kind, or a malformed config leaves\n * the payload absent, so the binding resolves to `undefined` and the\n * renderer shows its EC-015 fallback (an empty list renders the section's\n * empty state);\n * - a structured query error (the stored query was REJECTED at delivery, e.g.\n * a sort field no longer filterable in the live schema) stores an explicit\n * {@link sourcePayloadError} payload instead — the binding resolver throws\n * on it and the renderer shows its visible per-node render-error fallback,\n * not a silently empty section (EC-177 gap 3).\n */\n\n/** Collect every binding `sourceId` referenced in a node tree (props, conditions, slots). */\nexport function collectBindingSourceIds(\n node: ComponentNode,\n into: Set<string> = new Set(),\n): Set<string> {\n for (const value of Object.values(node.props ?? {})) {\n if (value.kind === 'binding') into.add(value.binding.sourceId)\n }\n if (node.condition) into.add(node.condition.source.sourceId)\n for (const children of Object.values(node.slots ?? {})) {\n for (const child of children) collectBindingSourceIds(child, into)\n }\n return into\n}\n\nexport interface MaterializeSourcePayloadsInput {\n /** Accessor client bound to this request's perspective + locale. */\n client: ContentClient\n result: ResolvePageResult\n /** The graph for the active perspective (layout trees may bind sections too). */\n graph: ProjectGraph | null\n /** Source definitions from the `ContentSource` (absent ones simply skip). */\n sources: readonly CanvasDataSource[]\n}\n\nexport interface MaterializedSourcePayloads {\n payloads: BindingPayloads\n /** `CacheTags` of every accessor call made here (one entry per section list). */\n tags: CacheTags[]\n}\n\n/**\n * Materialize the EC-166 source payloads for one resolved page. Pure over the\n * prefetched source — `listDocuments` is synchronous; tags are returned (not\n * applied) so the caller owns the merge.\n */\nexport function materializeSourcePayloads(\n input: MaterializeSourcePayloadsInput,\n): MaterializedSourcePayloads {\n const { client, result, graph, sources } = input\n const payloads: BindingPayloads = {}\n const tags: CacheTags[] = []\n\n if (result.status !== 'ok') return { payloads, tags }\n\n // --- Repeating sections: replay each referenced section source -----------\n // EC-187: page bodies use static props (v1), so section bindings live on the\n // LAYOUT that wraps the routed page document. Collect the layout the document\n // selects via its `layoutId` flat field.\n const referenced = new Set<string>()\n const layoutId = result.document?.['layoutId']\n if (graph && typeof layoutId === 'string') {\n const layout = graph.layouts.find((candidate) => candidate.id === layoutId)\n if (layout) collectBindingSourceIds(layout.root, referenced)\n }\n\n const byId = new Map(sources.map((source) => [source.id, source]))\n for (const sourceId of [...referenced].sort()) {\n if (!isSectionSourceId(sourceId)) continue\n const definition = byId.get(sourceId)\n if (!definition || definition.kind !== 'cms') continue\n const config = parseCmsSourceQueryConfig(definition.config)\n // Single-document configs are not lists; leave the binding unresolved.\n if (!config || config.documentId !== undefined) continue\n\n const list = client.listDocuments(config.collectionId, listQueryOfCmsConfig(config))\n // Both arms carry at least the collection tag; the ok arm additionally\n // tags every document actually returned (fetch-time tagging, EC-146).\n tags.push(list.tags)\n if (list.ok) {\n payloads[sourceId] = list.documents\n } else {\n // A rejected stored query is a VISIBLE state: the explicit issue\n // payload makes the binding resolver throw, which the renderer turns\n // into its per-node render-error fallback — never a silent empty list.\n payloads[sourceId] = sourcePayloadError(\n sourceId,\n list.errors.map((error) => error.message),\n )\n }\n }\n\n return { payloads, tags }\n}\n","import { documentKey, splitPath } from '@elytracms/cms-core'\nimport type {\n CmsDocument,\n CollectionDef,\n DocumentRef,\n Locale,\n LocaleConfig,\n RedirectRecord,\n RouteRecord,\n} from '@elytracms/cms-core'\nimport {\n createContentClient,\n createContentContext,\n isDocumentHistory,\n resolvedAsset,\n} from '@elytracms/content'\nimport type {\n ContentClient,\n ContentDocumentSource,\n ContentLookup,\n Perspective,\n ResolvedAsset,\n} from '@elytracms/content'\nimport type { AssetRecord, PersistenceAdapter } from '@elytracms/persistence'\nimport type { ProjectGraph } from '@elytracms/project-graph'\nimport type { CanvasDataSource, ContentSource } from './source'\n\n/**\n * Bridge from a `PersistenceAdapter` to the synchronous `ContentLookup` the\n * accessors (EC-143) read through: prefetch the project's collections,\n * documents, assets, and graphs ONCE (async), then serve every accessor call\n * synchronously from memory. This is how `apps/example-site` reads the seeded\n * in-memory fixture project; a Convex-backed `ContentSource` (EC-145/146)\n * replaces this bridge without touching the route helper.\n *\n * The assembly half is exposed separately as {@link createStaticContentSource}\n * (EC-156): a host that already holds the prefetched data as plain values —\n * e.g. a delivery-snapshot payload fetched over Convex's public HTTP query\n * API — assembles the exact same `ContentSource` without faking an adapter.\n */\n\nconst DEFAULT_LOCALES: LocaleConfig = { default: 'en', locales: ['en'] }\n\nexport interface ContentSnapshotOptions {\n /** Route records served by `resolvePage` (EC-019). */\n routes?: readonly RouteRecord[]\n /** Redirect records served by `resolvePage` (EC-019/020). */\n redirects?: readonly RedirectRecord[]\n /** Locale configuration; defaults to English-only. */\n locales?: LocaleConfig\n /**\n * Data-source definitions the graph's bindings reference (EC-166): section\n * sources (`cms.section.<nodeId>`) carry their stored where/sort/limit, and\n * the route helper materializes their payloads automatically.\n */\n sources?: readonly CanvasDataSource[]\n}\n\nexport interface ContentSnapshot extends ContentSource {\n readonly projectId: string\n}\n\n/**\n * Plain prefetched data for {@link createStaticContentSource} (EC-156): the\n * same inputs `createContentSnapshot` reads from a `PersistenceAdapter`, as\n * already-loaded values. Everything content-bearing is optional — an absent\n * piece simply resolves to \"not visible\", with the runtime's explicit\n * fallbacks (never a crash).\n */\nexport interface StaticContentData {\n projectId: string\n /** Locale configuration; defaults to English-only. */\n locales?: LocaleConfig\n /** Route records served by `resolvePage` (EC-019). */\n routes?: readonly RouteRecord[]\n /** Redirect records served by `resolvePage` (EC-019/020). */\n redirects?: readonly RedirectRecord[]\n collections?: readonly CollectionDef[]\n /**\n * Stored document sources. Either a bare `CmsDocument` (gated by its own\n * `state`) or a `DocumentHistory` carrying the live draft + the pinned\n * published snapshot (EC-224). Perspective gating happens in the pure\n * accessors (`selectPerspective`, EC-142): a `published` client sees a\n * history's pinned snapshot (or nothing), and never a bare `draft` row.\n */\n documents?: readonly ContentDocumentSource[]\n assets?: readonly AssetRecord[]\n /**\n * The graph visible per perspective: `draft` is the latest working\n * revision, `published` the revision pinned by publishing state. `null` /\n * absent means \"nothing visible in that perspective\".\n */\n graphs?: { draft?: ProjectGraph | null; published?: ProjectGraph | null }\n /**\n * Resolve a serve URL for assets without a stored `url`. Defaults to an\n * explicit unresolved-placeholder scheme (never a silent empty string).\n */\n assetUrl?: (asset: AssetRecord) => string\n /**\n * Data-source definitions the graph's bindings reference (EC-166 delivery).\n * Absent definitions degrade to unresolved bindings, never a crash.\n */\n sources?: readonly CanvasDataSource[]\n}\n\n/** Normalized pattern key: `/blog//x/` and `/blog/x` address the same URLs. */\nfunction patternKey(pattern: string): string {\n return '/' + splitPath(pattern).join('/')\n}\n\n/**\n * Merge stored route records with derived fallback routes (EC-177 gap 2):\n * stored records win per pattern+locale; fallback routes only fill patterns\n * the stored set does not cover. Never XOR — the first stored route must not\n * drop the implicit per-locale home-page fallback (or vice versa).\n *\n * Coverage rules mirror the router's locale matching (EC-018/019): a stored\n * locale-agnostic route (no `locale`) covers its pattern for every locale; a\n * locale-specific stored route covers only that locale, so fallbacks for the\n * other locales still apply.\n */\nexport function mergeRouteRecords(\n stored: readonly RouteRecord[],\n fallback: readonly RouteRecord[],\n): RouteRecord[] {\n const agnostic = new Set<string>()\n const localized = new Set<string>()\n for (const route of stored) {\n if (route.locale === undefined) agnostic.add(patternKey(route.pattern))\n else localized.add(`${route.locale}|${patternKey(route.pattern)}`)\n }\n const covered = (route: RouteRecord): boolean => {\n const key = patternKey(route.pattern)\n if (agnostic.has(key)) return true\n return route.locale !== undefined && localized.has(`${route.locale}|${key}`)\n }\n // Stored first: on equal specificity the router prefers earlier records.\n return [...stored, ...fallback.filter((route) => !covered(route))]\n}\n\n/**\n * Assemble a `ContentSource` from plain prefetched data — the pure half of\n * {@link createContentSnapshot}, shared with hosts that fetched the data\n * themselves (e.g. the EC-156 live delivery snapshot). Accessor semantics are\n * byte-identical across both paths: the same `ContentLookup` feeds the same\n * pure `@elytracms/content` client.\n */\nexport function createStaticContentSource(data: StaticContentData): ContentSnapshot {\n const locales = data.locales ?? DEFAULT_LOCALES\n const routes = data.routes ?? []\n const redirects = data.redirects ?? []\n const draftGraph = data.graphs?.draft ?? null\n const publishedGraph = data.graphs?.published ?? null\n const assetUrl =\n data.assetUrl ?? ((asset: AssetRecord) => `asset://unresolved/${asset.storageKey}`)\n\n const collections = new Map<string, CollectionDef>()\n for (const collection of data.collections ?? []) collections.set(collection.id, collection)\n\n const documents = new Map<string, ContentDocumentSource>()\n const byCollection = new Map<string, ContentDocumentSource[]>()\n for (const source of data.documents ?? []) {\n const doc = isDocumentHistory(source) ? source.draft : source\n documents.set(documentKey(doc), source)\n const list = byCollection.get(doc.collection) ?? []\n list.push(source)\n byCollection.set(doc.collection, list)\n }\n\n const assets = new Map<string, AssetRecord>()\n for (const record of data.assets ?? []) assets.set(record.id, record)\n\n const graphFor = (perspective: Perspective): ProjectGraph | null =>\n perspective === 'draft' ? draftGraph : publishedGraph\n\n const lookupFor = (_perspective: Perspective): ContentLookup => ({\n collection: (id) => collections.get(id),\n document: (ref: DocumentRef) => documents.get(documentKey(ref)),\n documents: (collectionId) => byCollection.get(collectionId) ?? [],\n asset: (id) => assets.get(id),\n assetUrl: (asset) => asset.url ?? assetUrl(asset),\n })\n\n const client = (init: { perspective: Perspective; locale?: Locale }): ContentClient =>\n createContentClient({\n lookup: lookupFor(init.perspective),\n context: createContentContext({\n locale: init.locale ?? locales.default,\n perspective: init.perspective,\n locales,\n }),\n routes,\n redirects,\n })\n\n return {\n projectId: data.projectId,\n locales,\n client,\n graph: graphFor,\n routes,\n // EC-195: the delivery-shaped assets, so the renderer can resolve an\n // `asset`-typed Image prop (an asset id) to a usable url + intrinsic\n // dimensions. Baked into the (serializable) render outcome by the route\n // helper, so a cached page keeps its images during a backend outage.\n assets: () =>\n [...assets.values()].map((record) => resolvedAsset(record, record.url ?? assetUrl(record))),\n ...(data.sources ? { sources: data.sources } : {}),\n }\n}\n\n/**\n * Prefetch a project's content from a `PersistenceAdapter` into an in-memory\n * `ContentSource`. The snapshot is a point-in-time view: load once per\n * request (or memoize across requests for fixture-backed sites) — accessors\n * never reach back to the adapter.\n */\nexport async function createContentSnapshot(\n adapter: PersistenceAdapter,\n projectId: string,\n options: ContentSnapshotOptions = {},\n): Promise<ContentSnapshot> {\n // --- Prefetch (the only async part) ------------------------------------\n const schema = await adapter.cms.findSchema(projectId)\n const documentRecords = await adapter.cms.listDocuments(projectId)\n const versionRecords = await adapter.cms.listAllDocumentVersions(projectId)\n const assetRecords = await adapter.assets.listAssets(projectId)\n\n // Hybrid sources (EC-224): a `publishedVersion` pointer yields a\n // `DocumentHistory` (draft = the live row, published = the pinned snapshot);\n // an unpinned record stays a bare `CmsDocument` gated by its `state`.\n // Backward-compatible — pre-pointer data resolves exactly as before.\n const versionsByKey = new Map<string, Map<number, CmsDocument>>()\n for (const record of versionRecords) {\n const key = `${record.collection}:${record.docId}`\n let byVersion = versionsByKey.get(key)\n if (!byVersion) {\n byVersion = new Map()\n versionsByKey.set(key, byVersion)\n }\n byVersion.set(record.version, record.snapshot)\n }\n const documents: ContentDocumentSource[] = documentRecords.map((record) => {\n if (record.publishedVersion === undefined) return record.document\n // A dangling pin under-serves to `null` for `published` — never the draft.\n const published = versionsByKey\n .get(`${record.document.collection}:${record.document.id}`)\n ?.get(record.publishedVersion)\n return { draft: record.document, published, versions: [] }\n })\n\n // Draft perspective sees the latest working revision; published sees the\n // revision pinned by the deployment's publishing state (EC-021 at the graph\n // level). Single-environment (EC-179).\n const draftGraph = (await adapter.graphs.hasGraph(projectId))\n ? (await adapter.graphs.getLatest(projectId)).graph\n : null\n const publishState = await adapter.publishing.findState(projectId)\n const publishedGraph =\n publishState?.status === 'published' && publishState.publishedRevision !== undefined\n ? (await adapter.graphs.getRevision(projectId, publishState.publishedRevision)).graph\n : null\n\n // --- Assemble via the shared pure path ----------------------------------\n // Captured once: `BlobStorageAdapter.url` is synchronous by contract.\n return createStaticContentSource({\n projectId,\n ...(options.locales ? { locales: options.locales } : {}),\n ...(options.routes ? { routes: options.routes } : {}),\n ...(options.redirects ? { redirects: options.redirects } : {}),\n ...(options.sources ? { sources: options.sources } : {}),\n ...(schema ? { collections: schema.collections } : {}),\n documents,\n assets: assetRecords,\n graphs: { draft: draftGraph, published: publishedGraph },\n assetUrl: (asset) => adapter.blobs.url(asset.storageKey),\n })\n}\n","import { splitPath } from '@elytracms/cms-core'\nimport type { Locale, LocaleConfig } from '@elytracms/cms-core'\nimport { cacheTags } from '@elytracms/content'\nimport type {\n CacheTags,\n ContentClient,\n Perspective,\n ResolvedAsset,\n ResolvePageResult,\n} from '@elytracms/content'\nimport type { ComponentNode, ProjectGraph } from '@elytracms/project-graph'\nimport type { ComponentRegistry } from '@elytracms/component-registry'\nimport {\n collectReferencedAssetIds,\n collectReferencedListings,\n collectReferencedRelations,\n} from '@elytracms/runtime-renderer'\nimport type { ListingQuery, RelationTarget } from '@elytracms/runtime-renderer'\nimport type { BindingPayloads } from './payloads'\nimport { mergeCacheTags } from './source'\nimport type { ContentSource } from './source'\nimport { materializeSourcePayloads } from './source-payloads'\nimport { compositionNodesOf, defaultBindingPayloads } from './canvas-renderer'\n\n/**\n * The pure half of the catch-all route helper (EC-144): URL → outcome, with\n * no Next.js imports — so redirects, 404s, locale handling, payload assembly,\n * and tag merging are all unit-testable as plain functions. `route.tsx` maps\n * each outcome onto `redirect()` / `permanentRedirect()` / `notFound()` /\n * `<CanvasRenderer />`.\n */\n\n/** What the host's payload factory sees for one request. */\nexport interface CanvasPayloadContext {\n /** Accessor client bound to this request's perspective + locale. */\n client: ContentClient\n result: ResolvePageResult\n perspective: Perspective\n /** The normalized request path (locale prefix stripped). */\n path: string\n params: Record<string, string>\n /**\n * Register the `CacheTags` of any extra accessor call this factory makes\n * (e.g. `listDocuments`) so they join the request's merged tag set — the\n * EC-146 invalidation hook sees everything the request actually read.\n */\n addTags(tags: CacheTags): void\n}\n\n/**\n * Builds the binding payloads for a page render. The defaults\n * (`document`, `params`) are always present; factory entries win on conflict.\n */\nexport type CanvasPayloadsFactory = (\n ctx: CanvasPayloadContext,\n) => BindingPayloads | Promise<BindingPayloads>\n\nexport type CanvasPageOutcome =\n | { kind: 'redirect'; target: string; permanent: boolean; tags: CacheTags }\n | { kind: 'not-found'; tags: CacheTags }\n | {\n kind: 'render'\n result: ResolvePageResult\n graph: ProjectGraph | null\n payloads: BindingPayloads\n /**\n * The delivery-shaped assets the page may reference (EC-195). Baked into\n * the outcome (serializable) so the renderer resolves `asset`-typed Image\n * props to a url + intrinsic dimensions, and a cached page keeps its\n * images during a backend outage.\n */\n assets: readonly ResolvedAsset[]\n /**\n * The composition-node `relation` props this page references, populated to\n * depth-1 delivery shape and keyed `collection:id` (EC-254). Baked into the\n * outcome (serializable) so `<CanvasRenderer />` rebuilds\n * `RenderContext.resolveRelation` from it inside the RSC — a function (the\n * content client) cannot ride the data cache or cross the RSC boundary, so\n * the data is baked exactly as the page-scoped `assets` list is.\n */\n relations: Record<string, RelationTarget>\n /**\n * The documents each `listing` block on this page resolved to (EC-255),\n * keyed by serialized query. Baked into the outcome (serializable) so\n * `<CanvasRenderer />` rebuilds `RenderContext.resolveListing` from it inside\n * the RSC — like `relations`, because the content client that runs the query\n * cannot ride the data cache or cross the RSC boundary. A listing depends on\n * collection MEMBERSHIP (a product joining/leaving the category), so its\n * invalidation rides the per-query `listDocuments` tags merged into `tags`.\n */\n listings: Record<string, RelationTarget[]>\n tags: CacheTags\n }\n\n/** Build the request path from a Next catch-all `slug` param. */\nexport function pathFromSlug(slug: readonly string[] | undefined): string {\n return '/' + (slug ?? []).join('/')\n}\n\n/**\n * Derive the request locale from a leading URL segment (`/de/about` → locale\n * `de`, path `/about`) and return the remaining path. No prefix (or the\n * default locale's own content at root) falls back to the default locale.\n */\nexport function splitLocalePath(\n url: string,\n locales: LocaleConfig,\n): { locale: Locale; path: string } {\n const segments = splitPath(url)\n const first = segments[0]\n if (first !== undefined && first !== locales.default && locales.locales.includes(first)) {\n return { locale: first, path: '/' + segments.slice(1).join('/') }\n }\n return { locale: locales.default, path: '/' + segments.join('/') }\n}\n\nexport interface ResolveCanvasPageOptions {\n payloads?: CanvasPayloadsFactory\n /**\n * Component registry (EC-205): when provided, the baked {@link CanvasPageOutcome}\n * `assets` are PAGE-SCOPED to exactly the asset ids this page's composition +\n * layout resolve through `resolveAsset` — not the whole project asset list,\n * which otherwise rides in every page's cache entry + RSC payload. Omitted →\n * all source assets (back-compat). Scoping mirrors the renderer's asset\n * resolution exactly, so no referenced image is ever dropped.\n */\n registry?: ComponentRegistry\n}\n\n/**\n * Page-scope the baked assets to those the page actually resolves (EC-205): the\n * static `asset`-typed props of its composition + selected layout tree. Document\n * asset FIELDS resolve into the document payload separately, and bound asset\n * props resolve through bindings — neither uses this list, so neither widens it.\n */\nfunction scopeAssetsToPage(\n allAssets: readonly ResolvedAsset[],\n registry: ComponentRegistry,\n result: ResolvePageResult,\n graph: ProjectGraph | null,\n): readonly ResolvedAsset[] {\n if (allAssets.length === 0) return allAssets\n const ids = new Set<string>()\n for (const node of compositionNodesOf(result.document)) {\n collectReferencedAssetIds(node, registry, ids)\n }\n const layoutId = result.document?.['layoutId']\n if (graph && typeof layoutId === 'string') {\n const layout = graph.layouts.find((candidate) => candidate.id === layoutId)\n if (layout) collectReferencedAssetIds(layout.root, registry, ids)\n }\n // EC-202: the OG image is an asset the page uses (for its `og:image` meta), so\n // it joins the page-scoped set — making it resolvable in `canvasPageMetadata`\n // and (EC-227) tagged for invalidation when that asset record is edited.\n const ogImage = result.document?.['seoOgImage']\n if (typeof ogImage === 'string') ids.add(ogImage)\n return ids.size === 0 ? [] : allAssets.filter((asset) => ids.has(asset.id))\n}\n\n/** The page's composition nodes plus its selected layout root (EC-254 relation scan). */\nfunction pageCompositionNodes(\n result: ResolvePageResult,\n graph: ProjectGraph | null,\n): ComponentNode[] {\n const nodes = [...compositionNodesOf(result.document)]\n const layoutId = result.document?.['layoutId']\n if (graph && typeof layoutId === 'string') {\n const layout = graph.layouts.find((candidate) => candidate.id === layoutId)\n if (layout) nodes.push(layout.root)\n }\n return nodes\n}\n\n/**\n * Populate every composition-node `relation` prop the page references to depth-1,\n * keyed `collection:id` (EC-254). Walks the page composition + layout (and, through\n * `collectReferencedRelations`, transcluded reusable content) and resolves each ref\n * through the request's client. Empty when no registry is supplied (the collector\n * needs manifests to know which props are relations) — relation props then pass\n * through raw, the graceful degradation a host without a registry already gets.\n *\n * `docKeys` carries the `collection:id` of every referenced pick (resolved or not),\n * so the caller cache-tags the page by them (EC-146): editing/publishing a picked\n * document — including a previously-unpublished one that should now appear — drops\n * exactly the pages that embed it. A fixed pick depends on the document's identity,\n * not on its collection's membership, so no coarse collection tag is added.\n */\nfunction populatePageRelations(\n result: ResolvePageResult,\n graph: ProjectGraph | null,\n client: ContentClient,\n registry: ComponentRegistry | undefined,\n): { relations: Record<string, RelationTarget>; docKeys: string[] } {\n if (!registry) return { relations: {}, docKeys: [] }\n const refKeys = new Set<string>()\n const relations = collectReferencedRelations(\n pageCompositionNodes(result, graph),\n registry,\n (ref) => client.resolveRelation(ref),\n {},\n refKeys,\n )\n return { relations, docKeys: [...refKeys] }\n}\n\n/**\n * Resolve every `listing` block on the page to its matching documents (EC-255),\n * keyed by serialized query for `<CanvasRenderer />` to rebuild `resolveListing`.\n * Runs each listing's query through the request's client (so perspective + locale\n * match the rest of the resolution — published-only on a live page, per AD-5), and\n * returns the per-query `listDocuments` `CacheTags` so the caller folds them into\n * the page's tag set: those carry both the COLLECTION tag (membership — a product\n * joining/leaving the category re-renders the grid) and the listed documents' own\n * tags (a member's content edit re-renders it). Empty when no registry is supplied\n * (the collector needs manifests to know which blocks declare a listing).\n */\nfunction populatePageListings(\n result: ResolvePageResult,\n graph: ProjectGraph | null,\n client: ContentClient,\n registry: ComponentRegistry | undefined,\n): { listings: Record<string, RelationTarget[]>; tags: CacheTags[] } {\n if (!registry) return { listings: {}, tags: [] }\n const tags: CacheTags[] = []\n const listings = collectReferencedListings(\n pageCompositionNodes(result, graph),\n registry,\n (query: ListingQuery) => {\n const listed = client.listDocuments(query.collection, {\n where: query.where,\n ...(query.sort ? { sort: query.sort } : {}),\n ...(query.limit !== undefined ? { limit: query.limit } : {}),\n })\n tags.push(listed.tags)\n return listed.ok ? (listed.documents as RelationTarget[]) : []\n },\n // EC-255: reach listings nested inside transcluded reusable content (the same\n // depth-1 populate the relation bake uses), so a grid inside a reusable bakes —\n // and its membership tag is folded in — instead of rendering empty on the host.\n (ref) => client.resolveRelation(ref),\n )\n return { listings, tags }\n}\n\n/**\n * Resolve one request URL against a content source: split the locale, run\n * `resolvePage` in the requested perspective, assemble binding payloads, and\n * merge every accessor's `CacheTags` into one deterministic set. Pure — all\n * data was prefetched by the source.\n */\nexport async function resolveCanvasPage(\n source: ContentSource,\n url: string,\n perspective: Perspective,\n options: ResolveCanvasPageOptions = {},\n): Promise<CanvasPageOutcome> {\n const { locale, path } = splitLocalePath(url, source.locales)\n const client = source.client({ perspective, locale })\n const result = client.resolvePage(path)\n\n if (result.status === 'redirect' && result.redirect) {\n return {\n kind: 'redirect',\n target: result.redirect.target,\n permanent: result.redirect.permanent,\n tags: result.tags,\n }\n }\n\n if (result.status !== 'ok') {\n return { kind: 'not-found', tags: result.tags }\n }\n\n const graph = source.graph(perspective)\n const extraTags: CacheTags[] = []\n let payloads: BindingPayloads = defaultBindingPayloads(result)\n\n // EC-166 delivery: materialize template-page documents and replay each\n // referenced repeating-section query (stored where/sort/limit) through this\n // request's client — published perspective and ambient locale included.\n // Section list tags join the merged set (fetch-time doc tags + collection).\n const materialized = materializeSourcePayloads({\n client,\n result,\n graph,\n sources: source.sources ?? [],\n })\n payloads = { ...payloads, ...materialized.payloads }\n extraTags.push(...materialized.tags)\n\n if (options.payloads) {\n const custom = await options.payloads({\n client,\n result,\n perspective,\n path,\n params: result.dynamicParams,\n addTags: (tags) => extraTags.push(tags),\n })\n payloads = { ...payloads, ...custom }\n }\n\n const allAssets = source.assets?.() ?? []\n // EC-205: page-scope the baked assets when a registry is supplied (the route\n // helper passes it); else keep the full list (back-compat).\n const bakedAssets = options.registry\n ? scopeAssetsToPage(allAssets, options.registry, result, graph)\n : allAssets\n // EC-227: tag the cache entry with every asset it baked, so editing an asset\n // record (alt/dimensions/re-upload) drops exactly the pages carrying it. The\n // locale is irrelevant for asset tags (an asset record is locale-agnostic) —\n // `cacheTags` just needs one; `result.tags.locale` is the page's.\n const assetTags = cacheTags({\n assets: bakedAssets.map((asset) => asset.id),\n locale: result.tags.locale,\n })\n // EC-254: populate the relation props of the nodes inside the page's blocks\n // (e.g. a ProductGrid's picked products), keyed for `<CanvasRenderer />` to\n // rebuild `resolveRelation`. Reuses the request's client, so perspective +\n // locale match the rest of the resolution.\n const { relations, docKeys: relationDocKeys } = populatePageRelations(\n result,\n graph,\n client,\n options.registry,\n )\n // EC-146: tag the page by every picked document so editing/publishing one drops\n // the embedding page (the locale is the page's; doc tags are locale-agnostic).\n const relationTags = cacheTags({ docs: relationDocKeys, locale: result.tags.locale })\n // EC-255: resolve every listing block's query (e.g. a ProductGrid keyed to a\n // category) and bake the result keyed by serialized query. The per-query\n // `listDocuments` tags (collection membership + listed docs) join the merged set,\n // so adding/removing a member or editing one invalidates the embedding page.\n const { listings, tags: listingTags } = populatePageListings(\n result,\n graph,\n client,\n options.registry,\n )\n return {\n kind: 'render',\n result,\n graph,\n payloads,\n assets: bakedAssets,\n relations,\n listings,\n tags: mergeCacheTags(result.tags, ...extraTags, ...listingTags, assetTags, relationTags),\n }\n}\n","import type { CacheTags } from '@elytracms/content'\n\n/**\n * Cache-tag pipeline (EC-146, vision AD-5) — the pure half.\n *\n * This module defines (a) the **canonical Next.js tag string format** mapping\n * the accessor-level `CacheTags` (EC-143) onto `revalidateTag` keys, and (b)\n * the **tag-discovery caching logic** the catch-all route helper runs inside\n * `unstable_cache`. No Next.js imports — everything here is unit-testable;\n * `route.tsx` injects the real `unstable_cache` via {@link CacheWrapper}.\n *\n * ## Tag format\n *\n * - `doc:<collection>:<id>` — one per document whose content was actually in\n * the response (fetch-time tagging: includes depth-1 populated relation\n * targets, and documents inside filtered/dynamic lists *after* the filter\n * ran).\n * - `collection:<name>:<locale>` — the coarse membership tag: every response\n * that read from a collection carries it, so create/delete/newly-matching\n * documents sweep cached lists without read-set tracking.\n * - `route:<pattern>:<locale>` — the resolved URL path plus every hop of a\n * redirect chain.\n * - `asset:<id>` — one per asset whose delivery shape the page *baked*\n * (page-scoped images + `seoOgImage`, EC-227); editing that asset record\n * (alt/dimensions/re-upload) drops exactly the pages that baked it. Not\n * locale-scoped — an asset record is locale-agnostic.\n * - `project` — the whole-project sweep tag attached to **every** cached\n * entry; graph publish/unpublish emits it (a layout or route change can\n * affect any page, so the honest v1 fallback is a full project sweep).\n *\n * ## Project scope\n *\n * Every tag is prefixed `p:<projectId>:` when a scope is configured (e.g.\n * `p:prj_aurora:doc:post:post-1`). The cost is a few bytes per tag and it\n * keeps multi-project hosts (one Next app serving several builder projects)\n * from cross-invalidating, so the prefix is **on whenever the host knows its\n * project id** — decision: include it. The emitter (the studio's webhook\n * dispatcher, `apps/builder/src/lib/webhooks`) always scopes with the\n * operation's `projectId`; a host that omits `cache.scope` therefore will not\n * match studio-emitted tags. Configure `cache.scope` with the same project id\n * the studio publishes under.\n *\n * The studio-side emitter cannot depend on this package (it would drag the\n * `next` peer dependency into the builder), so\n * `apps/builder/src/lib/webhooks/tags.ts` mirrors these formatters; tests on\n * both sides pin the exact literal strings to keep them in lock-step.\n */\n\n/** Apply the optional multi-project scope prefix to one tag. */\nexport function scopeCacheTag(tag: string, scope?: string): string {\n return scope === undefined || scope.length === 0 ? tag : `p:${scope}:${tag}`\n}\n\n/**\n * Tag for one document identity. `docKey` is the EC-143 `documentKey` string\n * (`<collection>:<id>`), exactly as found in `CacheTags.docs`.\n */\nexport function docCacheTag(docKey: string, scope?: string): string {\n return scopeCacheTag(`doc:${docKey}`, scope)\n}\n\n/** The coarse membership tag of one collection in one locale. */\nexport function collectionCacheTag(collection: string, locale: string, scope?: string): string {\n return scopeCacheTag(`collection:${collection}:${locale}`, scope)\n}\n\n/** Tag for one resolved route path (or redirect-chain hop) in one locale. */\nexport function routeCacheTag(pattern: string, locale: string, scope?: string): string {\n return scopeCacheTag(`route:${pattern}:${locale}`, scope)\n}\n\n/**\n * Tag for one baked asset (EC-227). `assetId` is the bare asset id, as found in\n * `CacheTags.assets`. Not locale-scoped: an asset record is one row shared\n * across locales, so an edit invalidates the baking pages in every locale.\n */\nexport function assetCacheTag(assetId: string, scope?: string): string {\n return scopeCacheTag(`asset:${assetId}`, scope)\n}\n\n/**\n * The whole-project sweep tag. Attached to every cached page entry; emitted\n * on graph publish/unpublish (and as the emitter's honest fallback when a\n * change's precise tag set is unknowable).\n */\nexport function projectSweepTag(scope?: string): string {\n return scopeCacheTag('project', scope)\n}\n\n/**\n * Map an accessor-level `CacheTags` (what one request actually read) onto the\n * full, deterministic (sorted, deduplicated) set of Next tag strings for the\n * cache entry — including the project sweep tag.\n */\nexport function nextCacheTags(tags: CacheTags, scope?: string): string[] {\n const all = new Set<string>()\n all.add(projectSweepTag(scope))\n for (const docKey of tags.docs) all.add(docCacheTag(docKey, scope))\n for (const collection of tags.collections) {\n all.add(collectionCacheTag(collection, tags.locale, scope))\n }\n for (const route of tags.routes) all.add(routeCacheTag(route, tags.locale, scope))\n for (const assetId of tags.assets) all.add(assetCacheTag(assetId, scope))\n return [...all].sort()\n}\n\n// --- Tag-discovery caching over `unstable_cache` ------------------------------\n\n/**\n * The slice of `unstable_cache` the discovery logic needs, injectable so the\n * logic is testable against a faithful in-memory model (and so the test model\n * can mirror the real semantics this design depends on — see below).\n */\nexport interface CacheWrapperOptions {\n tags: string[]\n /** `false` = never expire by time (tag-driven invalidation only). */\n revalidate: number | false\n}\n\nexport type CacheWrapper = <T>(\n cb: () => Promise<T>,\n keyParts: string[],\n options: CacheWrapperOptions,\n) => () => Promise<T>\n\n/** What one cached request stores: the outcome plus its own discovered tags. */\nexport interface CachedEntry<T> {\n value: T\n /** The Next tag strings discovered at fetch time by the run that wrote this entry. */\n tags: string[]\n}\n\n/**\n * Internal sentinel: thrown by the probe callback after a cache **miss** ran\n * the loader, so `unstable_cache` never persists the entry under the\n * incomplete baseline tag set (a thrown callback caches nothing).\n */\nclass CacheDiscoveryBail extends Error {\n constructor() {\n super('elytra cache discovery bail (never user-visible)')\n this.name = 'CacheDiscoveryBail'\n }\n}\n\n/**\n * Both the probe and the write wrapper get their callback from this single\n * factory, so the two callbacks have **identical source text**. This matters:\n * `unstable_cache` derives its cache key from `cb.toString()` + `keyParts`,\n * so identical source is what makes the write pass store the entry under the\n * exact key future probe passes read.\n */\nfunction passthrough<T>(impl: () => Promise<T>): () => Promise<T> {\n return async () => impl()\n}\n\n/**\n * Fetch-time tag discovery over `unstable_cache` — the heart of EC-146.\n *\n * The problem: `unstable_cache` fixes an entry's tags when the *wrapper* is\n * created (`options.tags` is validated and **copied** at construction time in\n * Next 15 — mutating the array during the callback does not propagate), but\n * the correct tags are only known *after* the loader resolved the page. So a\n * single wrapper can never both (a) run the loader and (b) store the result\n * under the tags that run discovered.\n *\n * The design (\"resolve once, cache with discovered tags, serve cached\n * thereafter\") uses two wrapper constructions per request around **one**\n * cache entry:\n *\n * 1. **Probe pass** — a wrapper keyed by `keyParts` whose callback runs the\n * loader, captures the result + its discovered tags into the closure, and\n * then throws an internal sentinel.\n * - Cache **hit**: the stored entry (written by a previous request with\n * its full discovered tags) is returned; the callback — and therefore\n * the loader and any backend access — never runs. This is the outage\n * story: fully cached routes keep serving when the backend is down.\n * - Cache **miss**: the loader runs exactly once; the sentinel throw\n * prevents `unstable_cache` from persisting the entry under the\n * incomplete baseline tags (thrown callbacks cache nothing).\n * 2. **Write pass** (miss only) — a second wrapper is constructed *now that\n * the tags are known*, with `options.tags` = the discovered set, same key.\n * Its callback just returns the already-loaded entry, so the backend is\n * not hit again; `unstable_cache` persists the entry under the full\n * fetch-time tag set. `revalidateTag` on any of those tags drops the\n * entry and the next request repeats the cycle with fresh data.\n *\n * The loader runs **once per revalidation cycle** (per key), never once per\n * request. Time-based revalidation is intentionally not exposed: a\n * stale-while-revalidate background refresh would re-run the probe callback\n * (whose bail aborts the refresh), so this design is tag-driven only —\n * `revalidate: false` — which is exactly the AD-5 model.\n *\n * Concurrency: wrappers and the captured closure are per-request, so there is\n * no cross-request mutation; two racing first requests both resolve and the\n * last write wins (deterministic content ⇒ identical entries).\n */\nexport async function loadCachedEntry<T>(\n cache: CacheWrapper,\n keyParts: string[],\n baselineTags: readonly string[],\n load: () => Promise<CachedEntry<T>>,\n): Promise<CachedEntry<T>> {\n let fresh: CachedEntry<T> | undefined\n\n const probe = cache(\n passthrough(async (): Promise<CachedEntry<T>> => {\n fresh = await load()\n throw new CacheDiscoveryBail()\n }),\n keyParts,\n { tags: [...baselineTags], revalidate: false },\n )\n\n try {\n return await probe()\n } catch (error) {\n // Loader failures (backend down on a cold cache) propagate to the caller\n // — explicit, never silently cached. Only our own sentinel is absorbed.\n if (!(error instanceof CacheDiscoveryBail)) throw error\n }\n\n // Miss path: `fresh` was assigned before the sentinel was thrown.\n const entry = fresh as CachedEntry<T>\n const write = cache(\n passthrough(async () => entry),\n keyParts,\n { tags: entry.tags, revalidate: false },\n )\n return write()\n}\n","import type { Metadata } from 'next'\nimport type { ResolvedAsset, ResolvePageResult } from '@elytracms/content'\n\n/**\n * Resolved page → Next.js `Metadata` (EC-171, reshaped by EC-187). SEO now\n * lives on the resolved **document**: a `page`-collection document carries flat\n * `seo*` fields (`seoTitle`, `seoDescription`, `seoOgTitle`, `seoOgImage`,\n * `seoNoindex`); a content-collection document falls back to its `title`. There\n * is no separate page-graph `seo` block anymore.\n *\n * ```ts\n * // app/[[...slug]]/page.tsx — generateMetadata already applies this helper:\n * export const generateMetadata = route.generateMetadata\n * ```\n *\n * Mapping (in fallback order):\n * - `title`: `seoTitle` → document `name`/`title`.\n * - `description`: `seoDescription`.\n * - `openGraph`: OG title (`seoOgTitle` → effective title), description, and the\n * OG image URL (`seoOgImage`).\n * - `robots`: `seoNoindex` → `{ index: false }`.\n * - `alternates.canonical`: `seoCanonical` (EC-228) — an absolute or\n * root-relative URL, passed through verbatim. Real Sanity sites declare one per\n * page; omitted when unset so Next applies its own default.\n *\n * `hreflang` language alternates are intentionally NOT derived here: correct\n * hreflang needs a per-page translation map (which locale variants actually\n * exist), and auto-deriving from configured locales would emit alternates for\n * translations that don't exist — an SEO anti-pattern. Tracked as a follow-up.\n *\n * `seoOgImage` resolution (EC-202): the field holds either an absolute URL or\n * an **asset id**. An asset id is resolved to its delivery URL against the\n * page's baked `assets` (the same page-scoped set the renderer gets, widened to\n * include the OG asset in `route-core`). An asset id that can't be resolved is\n * **dropped** rather than emitted — an `<meta property=\"og:image\">` must carry a\n * real URL, never leak an internal id.\n *\n * Pure data-in/data-out — safe inside `generateMetadata` on both the cached\n * and uncached paths.\n */\nfunction str(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null\n}\n\n/** An already-resolvable image URL (absolute or root-relative), not an asset id. */\nfunction looksLikeUrl(value: string): boolean {\n return /^(https?:)?\\/\\//.test(value) || value.startsWith('/')\n}\n\n/**\n * Resolve a `seoOgImage` field value to a URL: pass a URL through, resolve an\n * asset id against the baked assets, drop an unresolvable id (EC-202).\n */\nfunction resolveOgImage(value: string | null, assets: readonly ResolvedAsset[]): string | null {\n if (value === null) return null\n if (looksLikeUrl(value)) return value\n return assets.find((asset) => asset.id === value)?.url ?? null\n}\n\nexport function canvasPageMetadata(\n result: ResolvePageResult,\n assets: readonly ResolvedAsset[] = [],\n): Metadata {\n const doc = result.document\n\n const seoTitle = str(doc?.['seoTitle'])\n const seoDescription = str(doc?.['seoDescription'])\n const seoOgTitle = str(doc?.['seoOgTitle'])\n const seoOgImage = resolveOgImage(str(doc?.['seoOgImage']), assets)\n const seoNoindex = doc?.['seoNoindex'] === true\n const seoCanonical = str(doc?.['seoCanonical'])\n\n // Fallback title: the page document's `name`, or a content document's `title`.\n const docTitle = str(doc?.['name']) ?? str(doc?.['title'])\n const title = seoTitle ?? docTitle\n\n const metadata: Metadata = {}\n if (title !== null) metadata.title = title\n if (seoDescription) metadata.description = seoDescription\n\n const ogTitle = seoOgTitle ?? title\n if (ogTitle !== null || seoDescription || seoOgImage) {\n metadata.openGraph = {\n ...(ogTitle !== null ? { title: ogTitle } : {}),\n ...(seoDescription ? { description: seoDescription } : {}),\n ...(seoOgImage ? { images: [{ url: seoOgImage }] } : {}),\n }\n }\n\n if (seoNoindex) metadata.robots = { index: false }\n\n // EC-228: a page-declared canonical URL. Passed through verbatim (absolute or\n // root-relative); Next resolves it against `metadataBase` when relative.\n if (seoCanonical) metadata.alternates = { canonical: seoCanonical }\n\n return metadata\n}\n","import type { Metadata } from 'next'\nimport { unstable_cache } from 'next/cache'\nimport { draftMode } from 'next/headers'\nimport { notFound, permanentRedirect, redirect } from 'next/navigation'\nimport type { ReactNode } from 'react'\nimport type { CacheTags, Perspective, ResolvedAsset, ResolvePageResult } from '@elytracms/content'\nimport { loadCachedEntry, nextCacheTags, projectSweepTag } from './cache'\nimport type { CacheWrapper } from './cache'\nimport { CanvasRenderer } from './canvas-renderer'\nimport { canvasPageMetadata } from './metadata'\nimport type { HostComponents } from './components'\nimport { pathFromSlug, resolveCanvasPage } from './route-core'\nimport type { CanvasPageOutcome, CanvasPayloadsFactory } from './route-core'\nimport type { ContentSource } from './source'\n\n/**\n * Catch-all route helper (EC-144): the factory a host app calls once in\n * `app/[[...slug]]/page.tsx` to wire `resolvePage` → `<CanvasRenderer />`,\n * with redirects answered by Next's `redirect()`/`permanentRedirect()` (per\n * the route's `permanent` flag), unknown URLs answered by `notFound()` (the\n * host's 404 renders), and the perspective chosen by Next `draftMode()` —\n * draft when enabled (via the token-gated preview route), published\n * otherwise.\n *\n * With `cache` configured (EC-146), the published-perspective resolve+render\n * data work runs inside `unstable_cache`, keyed by URL and tagged with the\n * fetch-time tag set of what the response actually contained (see\n * `cache.ts`). Publishing in the studio then invalidates exactly the affected\n * entries via the signed `/api/revalidate` webhook — and while the content\n * backend is unreachable, cached entries keep serving because a cache hit\n * never invokes `loadContent`.\n */\n\nexport interface CanvasRequestInfo {\n /** The raw request path (including any locale prefix). */\n url: string\n perspective: Perspective\n}\n\nexport interface CanvasCacheOptions {\n /**\n * Project scope prefix for every tag (`p:<scope>:…`) — must be the project\n * id the studio publishes under, so the webhook dispatcher's tags match.\n * Omit only when the emitter also emits unscoped tags (see `cache.ts`).\n */\n scope?: string\n}\n\n/**\n * What the route helper tells the content loader about the request it is\n * loading for (EC-156). Loaders that serve both perspectives from one\n * prefetched source (the fixture snapshot) can ignore it; a live loader uses\n * it to fetch the draft-perspective snapshot only for draft-mode requests —\n * it must NOT call request APIs like `draftMode()` itself, because on the\n * cached published path the loader runs inside `unstable_cache`, where\n * dynamic request APIs are unavailable.\n */\nexport interface CanvasContentRequest {\n perspective: Perspective\n}\n\nexport interface CanvasRouteOptions {\n /**\n * Async content loader — the seam EC-145/146 plug Convex into. For the\n * fixture-backed example this memoizes a `createContentSnapshot` call.\n * Invoked per request; cache/memoize inside the loader as appropriate.\n * With `cache` configured it only runs on a cache miss (once per\n * revalidation cycle) — cache hits never touch the content backend.\n * Receives the request's perspective (see {@link CanvasContentRequest});\n * zero-arg loaders remain valid.\n */\n loadContent: (request: CanvasContentRequest) => Promise<ContentSource>\n /** Host component surface from `defineHostComponents`. */\n components: HostComponents\n /** Extra binding payloads per request (e.g. `listDocuments` for a list page). */\n payloads?: CanvasPayloadsFactory\n /**\n * EC-146 instant publish: cache the published-perspective resolution in\n * Next's data cache (`unstable_cache`), tagged with the response's own\n * fetch-time tags, invalidated by the `/api/revalidate` webhook. Draft mode\n * always bypasses this cache entirely. Tag-driven only — no time-based\n * revalidation (the AD-5 model). Cached values are JSON-serialized, so\n * payload factories must return plain data on the cached path.\n */\n cache?: CanvasCacheOptions\n /**\n * EC-146 hook: receives the merged `CacheTags` of everything this request\n * read (the `resolvePage` tags plus any tags the payload factory\n * registered via `addTags`). On a cache hit these are the stored tags of\n * the run that wrote the entry.\n */\n onTags?: (tags: CacheTags, info: CanvasRequestInfo) => void\n /** Override the generated `<head>` metadata for a resolved page. */\n metadata?: (result: ResolvePageResult, info: CanvasRequestInfo) => Metadata\n}\n\nexport interface CanvasRouteProps {\n params: Promise<{ slug?: string[] }>\n}\n\nexport interface CanvasRoute {\n /** The page component: `export default route.Page`. */\n Page: (props: CanvasRouteProps) => Promise<ReactNode>\n /** Next metadata hook: `export const generateMetadata = route.generateMetadata`. */\n generateMetadata: (props: CanvasRouteProps) => Promise<Metadata>\n}\n\n/**\n * Default metadata (EC-171): the page's canonical SEO fields — title,\n * description, OG tags, robots noindex — with document-title / page-name\n * fallbacks. `export const generateMetadata = route.generateMetadata` is the\n * one line a host needs; a custom `metadata` option overrides this entirely.\n */\nfunction defaultMetadata(result: ResolvePageResult, assets: readonly ResolvedAsset[]): Metadata {\n return canvasPageMetadata(result, assets)\n}\n\nasync function requestPerspective(): Promise<Perspective> {\n const { isEnabled } = await draftMode()\n return isEnabled ? 'draft' : 'published'\n}\n\n/** `unstable_cache` narrowed to the injectable seam the pure logic consumes. */\nconst nextCacheWrapper: CacheWrapper = (cb, keyParts, options) =>\n unstable_cache(cb, keyParts, { tags: options.tags, revalidate: options.revalidate })\n\n/** Create the `{ Page, generateMetadata }` pair for `app/[[...slug]]/page.tsx`. */\nexport function createCanvasRoute(options: CanvasRouteOptions): CanvasRoute {\n /**\n * Resolve one request, optionally through the tagged data cache. Shared by\n * `Page` and `generateMetadata` from a single call site, so both read (and\n * on a miss, write) the same cache entry.\n */\n const loadOutcome = async (url: string, perspective: Perspective): Promise<CanvasPageOutcome> => {\n const resolveFresh = async (): Promise<CanvasPageOutcome> => {\n const source = await options.loadContent({ perspective })\n return resolveCanvasPage(source, url, perspective, {\n ...(options.payloads ? { payloads: options.payloads } : {}),\n // EC-205: page-scope the baked assets to what the page actually uses.\n registry: options.components.registry,\n })\n }\n\n // Draft mode BYPASSES the cache entirely: draft content is per-editor,\n // changes on every keystroke, and must never be persisted into (or served\n // from) the shared published-data cache.\n //\n // `next dev` ALSO bypasses it: the tag-based instant-publish webhook (the\n // only cache invalidation, AD-5) can't reach a localhost host, so a\n // published change would stay stale until the dev server restarts (which\n // clears `.next`). Scoped to `development` so tests (`NODE_ENV=test`) and\n // production (`next build`/`start`) keep the tag-driven cache unchanged.\n const devBypass = process.env.NODE_ENV === 'development'\n if (!options.cache || perspective !== 'published' || devBypass) return resolveFresh()\n\n const scope = options.cache.scope\n const entry = await loadCachedEntry(\n nextCacheWrapper,\n ['elytra-route', scope ?? '', url],\n [projectSweepTag(scope)],\n async () => {\n const outcome = await resolveFresh()\n return { value: outcome, tags: nextCacheTags(outcome.tags, scope) }\n },\n )\n return entry.value\n }\n\n const Page = async (props: CanvasRouteProps): Promise<ReactNode> => {\n const { slug } = await props.params\n const url = pathFromSlug(slug)\n const perspective = await requestPerspective()\n\n const outcome = await loadOutcome(url, perspective)\n options.onTags?.(outcome.tags, { url, perspective })\n\n switch (outcome.kind) {\n case 'redirect':\n // 301 vs 302 per the redirect record's `permanent` flag (EC-019/020).\n return outcome.permanent ? permanentRedirect(outcome.target) : redirect(outcome.target)\n case 'not-found':\n return notFound()\n case 'render':\n return (\n <CanvasRenderer\n result={outcome.result}\n graph={outcome.graph}\n components={options.components}\n payloads={outcome.payloads}\n assets={outcome.assets}\n relations={outcome.relations}\n listings={outcome.listings}\n />\n )\n }\n }\n\n const generateMetadata = async (props: CanvasRouteProps): Promise<Metadata> => {\n const { slug } = await props.params\n const url = pathFromSlug(slug)\n const perspective = await requestPerspective()\n\n // Cached path: shares `Page`'s entry (same call site/key), so metadata is\n // a cache read, not a second resolution. Uncached path: resolve without\n // the payload factory — metadata only needs the resolution itself, and\n // side effects (addTags/onTags) must fire exactly once per request, in Page.\n if (options.cache && perspective === 'published') {\n const outcome = await loadOutcome(url, perspective)\n if (outcome.kind !== 'render') return {}\n return options.metadata\n ? options.metadata(outcome.result, { url, perspective })\n : defaultMetadata(outcome.result, outcome.assets)\n }\n\n const source = await options.loadContent({ perspective })\n const outcome = await resolveCanvasPage(source, url, perspective)\n if (outcome.kind !== 'render') return {}\n return options.metadata\n ? options.metadata(outcome.result, { url, perspective })\n : defaultMetadata(outcome.result, outcome.assets)\n }\n\n return { Page, generateMetadata }\n}\n","import type { MetadataRoute } from 'next'\nimport { composePath, hierarchyMount, splitPath } from '@elytracms/cms-core'\nimport type { CmsDocument, Locale, RouteRecord } from '@elytracms/cms-core'\nimport type { ContentClient } from '@elytracms/content'\nimport type { ContentSource } from './source'\n\n/**\n * `sitemap.xml` from published routes (EC-171): walk the same route records\n * `resolvePage` resolves against, resolve every candidate URL in the\n * **published** perspective, and emit `MetadataRoute.Sitemap` entries per\n * locale — Next's `app/sitemap.ts` convention. Pages marked `noindex` (and\n * URLs that do not resolve, e.g. a page that was never published) are\n * omitted.\n *\n * Dynamic routes (`/blog/:slug`): a route record does not declare which\n * collection feeds its params, so enumeration is delegated to the host's\n * {@link SitemapParamsProvider} — it gets a published-perspective accessor\n * client and returns one param record per concrete URL (typically from\n * `listDocuments`). **Honest limit:** parameterized routes without a provider\n * (or provider entries missing a param) are skipped and reported in\n * `skipped`, never guessed. `lastModified` is omitted — the delivery shape\n * carries no per-page timestamps today.\n *\n * Hierarchy mounts (`/:path*`, EC-218): a page-tree mount self-describes its\n * URLs, so it is enumerated automatically from the collection's published\n * documents (composing each page's nested path from its parent chain) — no\n * params provider entry needed.\n *\n * Host usage (`app/sitemap.ts`):\n *\n * ```ts\n * import { createCanvasSitemap } from '@elytracms/next'\n * import { loadContent } from '../lib/content'\n *\n * export default createCanvasSitemap({\n * loadContent,\n * baseUrl: 'https://example.com',\n * params: ({ route, client }) =>\n * route.id === 'r-post'\n * ? (client.listDocuments('post').ok ? … : []) // slug per published post\n * : null,\n * })\n * ```\n */\n\nexport interface SitemapRouteContext {\n route: RouteRecord\n locale: Locale\n /** Published-perspective accessor client bound to `locale`. */\n client: ContentClient\n}\n\n/**\n * Enumerate the param sets of one dynamic route — one record per concrete\n * URL (e.g. `[{ slug: 'hello-world' }, …]`). Return `null`/`undefined` to\n * skip the route (reported in `skipped`).\n */\nexport type SitemapParamsProvider = (\n ctx: SitemapRouteContext,\n) => readonly Record<string, string>[] | null | undefined\n\nexport interface CanvasSitemapOptions {\n /** Absolute site origin, e.g. `https://example.com` (no trailing slash needed). */\n baseUrl: string\n /** Route records to enumerate; defaults to the source's own route table. */\n routes?: readonly RouteRecord[]\n /** Param enumeration for dynamic routes (see {@link SitemapParamsProvider}). */\n params?: SitemapParamsProvider\n}\n\nexport interface SitemapSkippedRoute {\n routeId: string\n pattern: string\n reason: string\n}\n\nexport interface CanvasSitemapResult {\n entries: MetadataRoute.Sitemap\n /** Routes that could not be enumerated — explicit, never silent. */\n skipped: SitemapSkippedRoute[]\n}\n\nfunction paramNamesOf(pattern: string): string[] {\n return splitPath(pattern)\n .filter((segment) => segment.startsWith(':'))\n .map((segment) => segment.slice(1))\n}\n\n/** Substitute `:name` segments; `null` when a param is missing from the record. */\nfunction fillPattern(pattern: string, params: Record<string, string>): string | null {\n const segments: string[] = []\n for (const segment of splitPath(pattern)) {\n if (!segment.startsWith(':')) {\n segments.push(segment)\n continue\n }\n const value = params[segment.slice(1)]\n if (value === undefined || value.length === 0) return null\n segments.push(encodeURIComponent(value))\n }\n return '/' + segments.join('/')\n}\n\n/** Default locale serves the root; other locales get a `/locale` prefix. */\nfunction absoluteUrl(baseUrl: string, locale: Locale, defaultLocale: Locale, path: string): string {\n const origin = baseUrl.replace(/\\/+$/, '')\n if (locale === defaultLocale) return origin + path\n return origin + (path === '/' ? `/${locale}` : `/${locale}${path}`)\n}\n\n/**\n * Enumerate the sitemap entries of one content source (published\n * perspective). Pure over the prefetched source — synchronous accessors,\n * deterministic ordering (sorted by URL).\n */\nexport function canvasSitemapEntries(\n source: ContentSource,\n options: CanvasSitemapOptions,\n): CanvasSitemapResult {\n const routes = options.routes ?? source.routes ?? []\n const locales = source.locales\n const skipped: SitemapSkippedRoute[] = []\n const skip = (route: RouteRecord, reason: string): void => {\n if (!skipped.some((s) => s.routeId === route.id && s.reason === reason)) {\n skipped.push({ routeId: route.id, pattern: route.pattern, reason })\n }\n }\n\n const clients = new Map<Locale, ContentClient>()\n const clientFor = (locale: Locale): ContentClient => {\n let client = clients.get(locale)\n if (!client) {\n client = source.client({ perspective: 'published', locale })\n clients.set(locale, client)\n }\n return client\n }\n\n // path → locale → absolute URL (alternates group per concrete path).\n const byPath = new Map<string, Map<Locale, string>>()\n\n for (const route of routes) {\n const paramNames = paramNamesOf(route.pattern)\n // EC-218: a hierarchy mount (`/:path*`) serves a collection's pages by their\n // COMPOSED nested path — it self-describes its tree, so it is enumerated from\n // the collection's published documents, not the host's params provider.\n const mount = hierarchyMount(route)\n const routeLocales = route.locale ? [route.locale] : locales.locales\n\n for (const locale of routeLocales) {\n const client = clientFor(locale)\n\n let paths: string[]\n if (mount) {\n const listed = client.listDocuments(mount.collection)\n if (!listed.ok) {\n skip(route, `hierarchy collection \"${mount.collection}\" could not be listed`)\n continue\n }\n // Delivery docs are flat (`{ id, slug, parent, … }`); rebuild the minimal\n // CmsDocument shape composePath reads. Published perspective already\n // filtered to published rows, so a child whose parent is unpublished has a\n // dangling chain and drops out — exactly as live resolution would 404 it.\n const rows: CmsDocument[] = listed.documents.map((doc) => ({\n collection: mount.collection,\n id: doc.id,\n values: { slug: doc['slug'], parent: doc['parent'] },\n }))\n const byId = new Map(rows.map((row) => [row.id, row]))\n paths = []\n for (const row of rows) {\n // Only documents with their own slug are addressed through the mount\n // (a page routed explicitly elsewhere carries none).\n if (typeof row.values['slug'] !== 'string' || row.values['slug'] === '') continue\n const composed = composePath(row, (id) => byId.get(id))\n if (!composed.ok) continue\n paths.push('/' + [...mount.prefix, ...composed.segments].join('/'))\n }\n } else if (paramNames.length === 0) {\n paths = [route.pattern]\n } else {\n const paramSets = options.params?.({ route, locale, client })\n if (paramSets == null) {\n skip(route, 'dynamic route not enumerated (no params provider entry)')\n continue\n }\n paths = []\n for (const paramSet of paramSets) {\n const path = fillPattern(route.pattern, paramSet)\n if (path === null) {\n skip(route, `params entry missing one of :${paramNames.join(', :')}`)\n continue\n }\n paths.push(path)\n }\n }\n\n for (const path of paths) {\n // Same resolution the live request performs: only URLs that resolve\n // `ok` in the published perspective — and are not noindex — qualify.\n // Redirect-shadowed paths drop out (their targets are listed via\n // their own routes), and so do routes whose bound page/template is\n // not visible in the published graph (never published).\n const result = client.resolvePage(path, locale)\n // A document-bound route whose document is not published already\n // resolves `notFound` (EC-177 gap 6), so `status !== 'ok'` covers the\n // never-published case. A `page`-collection document carries its own\n // `seoNoindex` flat field (EC-187); honor it for the page sitemap.\n if (result.status !== 'ok') continue\n if (result.document?.['seoNoindex'] === true) continue\n const perLocale = byPath.get(path) ?? new Map<Locale, string>()\n perLocale.set(locale, absoluteUrl(options.baseUrl, locale, locales.default, path))\n byPath.set(path, perLocale)\n }\n }\n }\n\n const entries: MetadataRoute.Sitemap = []\n for (const perLocale of byPath.values()) {\n const languages = Object.fromEntries(perLocale)\n for (const url of perLocale.values()) {\n entries.push({\n url,\n ...(perLocale.size > 1 ? { alternates: { languages } } : {}),\n })\n }\n }\n entries.sort((a, b) => (a.url < b.url ? -1 : a.url > b.url ? 1 : 0))\n\n return { entries, skipped }\n}\n\nexport interface CreateCanvasSitemapOptions extends CanvasSitemapOptions {\n /** The same content loader the catch-all route uses (published perspective). */\n loadContent: (request: { perspective: 'published' }) => Promise<ContentSource>\n}\n\n/**\n * The `app/sitemap.ts` one-liner: `export default createCanvasSitemap({ … })`.\n * Loads the published content source and returns the enumerated entries\n * (skipped routes are dropped here — use {@link canvasSitemapEntries} to\n * inspect them).\n */\nexport function createCanvasSitemap(\n options: CreateCanvasSitemapOptions,\n): () => Promise<MetadataRoute.Sitemap> {\n return async () => {\n const source = await options.loadContent({ perspective: 'published' })\n return canvasSitemapEntries(source, options).entries\n }\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto'\nimport { z } from 'zod'\n\n/**\n * Pure signature/payload logic of the revalidation webhook receiver (EC-146),\n * kept free of Next.js imports so it is unit-testable. `revalidate.ts` wires\n * it into a route handler with `revalidateTag`.\n *\n * Scheme: HMAC-SHA256 over the **raw request body** with a shared secret,\n * carried as `x-elytra-signature: sha256=<hex>`. The emitter (the studio's\n * webhook dispatcher) signs the exact JSON string it sends; the receiver\n * verifies over the raw text *before* parsing, with a timing-safe compare.\n */\n\n/** Header carrying the HMAC signature. */\nexport const REVALIDATE_SIGNATURE_HEADER = 'x-elytra-signature'\n\n/** The webhook body: which tags to revalidate, and why. */\nexport const revalidatePayloadSchema = z.object({\n projectId: z.string().min(1),\n /** The operation that fired, e.g. `documents.setState`, `publishing.publish`. */\n event: z.string().min(1),\n /** Fully-formatted Next tag strings (already scoped) — revalidated verbatim. */\n tags: z.array(z.string().min(1)),\n /** ISO timestamp of emission. Informational in v1 (no replay window). */\n timestamp: z.string().min(1),\n})\nexport type RevalidatePayload = z.infer<typeof revalidatePayloadSchema>\n\n/** Compute the signature header value for a raw body (emitter/test side). */\nexport function signRevalidateBody(rawBody: string, secret: string): string {\n return `sha256=${createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex')}`\n}\n\nexport type RevalidateEvaluation =\n | { ok: true; payload: RevalidatePayload }\n | { ok: false; status: 400 | 401; message: string }\n\nconst SIGNATURE_PREFIX = 'sha256='\nconst HEX_PATTERN = /^[0-9a-f]+$/\n\n/**\n * Evaluate one webhook request: verify the HMAC first (auth before parsing),\n * then validate the payload shape.\n *\n * - unconfigured (empty) secret → 401 for every request: the endpoint stays\n * closed until a secret is deliberately configured (mirrors EC-144 preview);\n * - missing/malformed/mismatched signature → 401 (timing-safe compare);\n * - unparseable or schema-invalid body → 400 with no tag revalidated.\n */\nexport function evaluateRevalidateRequest(\n rawBody: string,\n signature: string | null | undefined,\n secret: string | undefined,\n): RevalidateEvaluation {\n if (secret === undefined || secret.length === 0) {\n return { ok: false, status: 401, message: 'Revalidation webhook is not configured.' }\n }\n\n if (signature === null || signature === undefined || !signature.startsWith(SIGNATURE_PREFIX)) {\n return { ok: false, status: 401, message: 'Missing or malformed webhook signature.' }\n }\n\n const providedHex = signature.slice(SIGNATURE_PREFIX.length).toLowerCase()\n const expectedHex = createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex')\n // Length must match before `timingSafeEqual` (it throws otherwise); the\n // digest length is public knowledge, so this comparison leaks nothing.\n if (\n providedHex.length !== expectedHex.length ||\n !HEX_PATTERN.test(providedHex) ||\n !timingSafeEqual(Buffer.from(providedHex, 'hex'), Buffer.from(expectedHex, 'hex'))\n ) {\n return { ok: false, status: 401, message: 'Invalid webhook signature.' }\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(rawBody)\n } catch {\n return { ok: false, status: 400, message: 'Webhook body is not valid JSON.' }\n }\n\n const payload = revalidatePayloadSchema.safeParse(parsed)\n if (!payload.success) {\n return { ok: false, status: 400, message: 'Webhook payload has an invalid shape.' }\n }\n\n return { ok: true, payload: payload.data }\n}\n","import { revalidateTag } from 'next/cache'\nimport { REVALIDATE_SIGNATURE_HEADER, evaluateRevalidateRequest } from './revalidate-core'\n\n/**\n * Revalidation webhook route handler (EC-146): the receiving end of the\n * publish → live-in-seconds pipeline. The studio's dispatcher POSTs a signed\n * `{projectId, event, tags, timestamp}` payload; this handler verifies the\n * HMAC over the raw body and calls `revalidateTag` for each tag, dropping\n * exactly the cached entries whose fetch-time tag sets contained them.\n *\n * Server-only by construction — consumed from an App Router route handler\n * file, never from client bundles.\n */\n\nexport interface RevalidateRouteOptions {\n /**\n * Shared HMAC secret. An empty/undefined secret rejects every request with\n * 401 — the endpoint stays closed until deliberately configured.\n */\n secret: string | undefined\n /**\n * CORS origin allowed to call this endpoint (e.g. the studio's origin).\n * The v1 dispatcher is a browser `fetch` from the studio, and the custom\n * signature header always triggers a CORS preflight — so cross-origin\n * studio → host dispatch only works when this is set. Server-side emitters\n * (the Convex action variant, CLIs, CI) need no CORS and may leave it\n * unset. Never use `*` with a real secret-bearing deployment unless you\n * accept that any origin may *attempt* deliveries (they still need the\n * secret to have any effect).\n */\n allowOrigin?: string\n}\n\nexport interface RevalidateRouteHandlers {\n POST(request: Request): Promise<Response>\n OPTIONS(): Promise<Response>\n}\n\nfunction corsHeaders(allowOrigin: string | undefined): Record<string, string> {\n if (allowOrigin === undefined || allowOrigin.length === 0) return {}\n return {\n 'access-control-allow-origin': allowOrigin,\n 'access-control-allow-methods': 'POST, OPTIONS',\n 'access-control-allow-headers': `content-type, ${REVALIDATE_SIGNATURE_HEADER}`,\n }\n}\n\n/**\n * Create the webhook route handlers for `app/api/revalidate/route.ts`:\n *\n * ```ts\n * export const { POST, OPTIONS } = createRevalidateRoute({\n * secret: process.env.REVALIDATE_SECRET,\n * })\n * ```\n *\n * Unsigned/invalid requests are rejected with 401 (timing-safe HMAC check,\n * see `evaluateRevalidateRequest`); valid requests revalidate every carried\n * tag and answer `{ revalidated: tags }`.\n */\nexport function createRevalidateRoute(options: RevalidateRouteOptions): RevalidateRouteHandlers {\n const cors = corsHeaders(options.allowOrigin)\n return {\n async POST(request: Request): Promise<Response> {\n const rawBody = await request.text()\n const signature = request.headers.get(REVALIDATE_SIGNATURE_HEADER)\n const evaluation = evaluateRevalidateRequest(rawBody, signature, options.secret)\n if (!evaluation.ok) {\n return Response.json(\n { error: evaluation.message },\n { status: evaluation.status, headers: cors },\n )\n }\n // Next 16 requires a cache-life profile as the second argument; `'max'`\n // is the documented drop-in that preserves the legacy \"drop every entry\n // carrying this tag\" semantics our `unstable_cache` flow relies on (the\n // one-arg form is deprecated). `updateTag` is not an option here — it is\n // Server-Action-only and throws from a route handler.\n for (const tag of evaluation.payload.tags) revalidateTag(tag, 'max')\n return Response.json({ revalidated: evaluation.payload.tags }, { headers: cors })\n },\n async OPTIONS(): Promise<Response> {\n // Preflight for the browser-dispatch path; 204 either way, CORS headers\n // only when an origin is configured.\n return new Response(null, { status: 204, headers: cors })\n },\n }\n}\n","import NextImage from 'next/image'\nimport type { ImageLoader } from 'next/image'\nimport type { ReactNode } from 'react'\nimport type { ResolvedAsset } from '@elytracms/content'\nimport { ImageManifest, normalizeImageSource } from '@elytracms/runtime-renderer'\nimport type { HostComponent } from './components'\n\n/**\n * Image delivery for the embedded runtime (EC-152).\n *\n * ## The honest v1 design\n *\n * Stored asset bytes are served from plain blob-storage URLs (Convex file\n * storage serve URLs in production). Those URLs do **not** transform — there\n * is no `?w=`/`?q=` resizing service behind them, and no image CDN build-out\n * in v1. The standard, no-CDN path is therefore `next/image` with its\n * **default loader**: the host app's own Next.js optimizer fetches the remote\n * asset URL, resizes/re-encodes it, and serves the variants same-origin from\n * `/_next/image`. That is exactly what {@link ElytraImage} does.\n *\n * For that to work the host app must allowlist the asset origin in\n * `next.config.mjs`:\n *\n * ```js\n * const nextConfig = {\n * images: {\n * remotePatterns: [\n * // Convex file storage serve URLs:\n * { protocol: 'https', hostname: '*.convex.cloud' },\n * ],\n * },\n * }\n * ```\n *\n * {@link createAssetImageLoader} exists for the day the asset URLs sit behind\n * a CDN that *does* honor width/quality query params — it appends them and\n * nothing more. Pointing it at raw Convex serve URLs would silently serve\n * full-size bytes while pretending to resize, so it is **not** the default.\n */\n\n/**\n * The slice of the {@link ResolvedAsset} delivery shape an image needs:\n * the resolvable URL, intrinsic dimensions for layout stability, and alt\n * text. Structurally satisfied by every `ResolvedAsset`.\n */\nexport type ElytraImageAsset = Pick<\n ResolvedAsset,\n 'url' | 'width' | 'height' | 'alt' | 'focalPoint'\n>\n\nexport interface ElytraImageProps {\n /** The resolved asset (delivery shape). `null` renders nothing. */\n asset: ElytraImageAsset | null | undefined\n /** `sizes` hint forwarded to `next/image` for responsive variants. */\n sizes?: string\n /** Preload hint forwarded to `next/image` (above-the-fold images). */\n priority?: boolean\n /** Quality (1–100) forwarded to `next/image`; Next defaults to 75. */\n quality?: number\n className?: string\n /**\n * Custom `next/image` loader (e.g. from {@link createAssetImageLoader})\n * when assets sit behind a transforming CDN. Omit for the v1 default:\n * Next's own optimizer.\n */\n loader?: ImageLoader\n}\n\n/**\n * Render a resolved asset through `next/image` (EC-152).\n *\n * - With known intrinsic dimensions the optimizer serves resized variants\n * and the reserved width/height prevent layout shift.\n * - Without dimensions `next/image` cannot render (it requires `width` +\n * `height` or `fill`), so the component degrades to a plain `<img>` —\n * un-optimized but visible, never a crash. Records written by the EC-151\n * upload flow always carry detected dimensions.\n * - A `null`/empty asset renders nothing (missing assets surface as\n * structured `unknown-asset` validation issues upstream, not here).\n */\nexport function ElytraImage(props: ElytraImageProps): ReactNode {\n const { asset, sizes, priority, quality, className, loader } = props\n if (!asset || asset.url.length === 0) return null\n const alt = asset.alt ?? ''\n // EC-230: a focal point becomes CSS `object-position`, so an art-directed image\n // keeps its subject in frame when a layout crops it (`object-fit: cover`).\n // Inert under the default fit — harmless to set, correct once a layout crops.\n const objectPosition = asset.focalPoint\n ? `${asset.focalPoint.x * 100}% ${asset.focalPoint.y * 100}%`\n : undefined\n if (asset.width === null || asset.height === null) {\n // Honest fallback: next/image requires intrinsic dimensions; a\n // dimensionless record degrades to an unoptimized <img> instead of\n // crashing the page.\n return (\n <img\n data-ec-image=\"fallback\"\n src={asset.url}\n alt={alt}\n className={className}\n {...(objectPosition ? { style: { objectPosition } } : {})}\n />\n )\n }\n return (\n <NextImage\n data-ec-image=\"next\"\n src={asset.url}\n alt={alt}\n width={asset.width}\n height={asset.height}\n {...(sizes !== undefined ? { sizes } : {})}\n {...(priority !== undefined ? { priority } : {})}\n {...(quality !== undefined ? { quality } : {})}\n {...(className !== undefined ? { className } : {})}\n {...(loader !== undefined ? { loader } : {})}\n {...(objectPosition ? { style: { objectPosition } } : {})}\n />\n )\n}\n\nexport interface AssetImageLoaderOptions {\n /** Query param name for the requested width. Default `\"w\"`. */\n widthParam?: string\n /** Query param name for the requested quality. Default `\"q\"`. */\n qualityParam?: string\n /** Quality used when `next/image` passes none. Default `75`. */\n defaultQuality?: number\n}\n\n/**\n * A `next/image` loader for asset URLs served through a transforming CDN:\n * it appends width/quality query params to the asset URL and returns it.\n *\n * Be honest about what this does: it only *requests* a transform. Plain\n * Convex file-storage serve URLs ignore these params and return the original\n * bytes, so this loader is only correct once the asset origin actually\n * resizes (e.g. an image CDN in front of storage). Until then, use the\n * default `next/image` loader (see module docs) — that is the v1 path.\n */\nexport function createAssetImageLoader(options: AssetImageLoaderOptions = {}): ImageLoader {\n const widthParam = options.widthParam ?? 'w'\n const qualityParam = options.qualityParam ?? 'q'\n const defaultQuality = options.defaultQuality ?? 75\n return ({ src, width, quality }) => {\n const separator = src.includes('?') ? '&' : '?'\n return `${src}${separator}${widthParam}=${width}&${qualityParam}=${quality ?? defaultQuality}`\n }\n}\n\n/**\n * The `base.primitives.Image` implementation for Next.js host apps: same\n * canonical manifest, rendered optimized through {@link ElytraImage}. The\n * renderer resolves an `asset`-typed `src` (EC-195) to `{ url, width, height,\n * alt }` before this runs, so `normalizeImageSource` yields intrinsic dimensions\n * (→ no layout shift, sized variants) whether the editor picked an uploaded asset\n * or pasted a URL. `priority` opts an above-the-fold image out of lazy-loading.\n */\nfunction NextImagePrimitive(props: Record<string, unknown>): ReactNode {\n const { url, width, height, alt, focalPoint } = normalizeImageSource(props)\n if (url.length === 0) return null\n return (\n <ElytraImage\n asset={{ url, width: width ?? null, height: height ?? null, alt, focalPoint }}\n {...(props.priority === true ? { priority: true } : {})}\n />\n )\n}\n\n/**\n * Host registration that swaps the `base.primitives.Image` implementation\n * for {@link ElytraImage} while keeping the primitive's canonical manifest\n * (the first registration's manifest wins in `defineHostComponents` — by\n * design, so prop schemas stay canonical; the duplicate-id registry issue it\n * reports is the documented override signal, not an error):\n *\n * ```ts\n * export const hostComponents = defineHostComponents([\n * nextImagePrimitive(),\n * // ...project components\n * ])\n * ```\n */\nexport function nextImagePrimitive(): HostComponent {\n return {\n manifest: ImageManifest,\n implementation: NextImagePrimitive,\n }\n}\n","/**\n * Pure token/target logic of the draft-preview routes (EC-144), kept free of\n * Next.js imports so it is unit-testable. `preview.ts` wires it into route\n * handlers with `draftMode()`.\n */\n\nexport type PreviewEvaluation =\n | { ok: true; redirectTo: string }\n | { ok: false; status: 400 | 401; message: string }\n\n/**\n * Only same-site path targets are accepted (`/...` but not `//host`), so the\n * preview endpoint can never be used as an open redirect.\n */\nexport function safeRedirectTarget(\n value: string | null | undefined,\n fallback = '/',\n): string | null {\n if (value === null || value === undefined || value === '') return fallback\n if (!value.startsWith('/') || value.startsWith('//')) return null\n return value\n}\n\n/**\n * Evaluate a preview-enable request. Drafts are token-gated (EC-144\n * acceptance: without the token, drafts are never reachable):\n *\n * - an unconfigured (empty) expected token rejects every request — preview\n * cannot be accidentally left open;\n * - a missing or mismatched `token` query param is a 401;\n * - an off-site `redirect` target is a 400.\n */\nexport function evaluatePreviewRequest(\n requestUrl: string | URL,\n expectedToken: string | undefined,\n): PreviewEvaluation {\n if (expectedToken === undefined || expectedToken.length === 0) {\n return { ok: false, status: 401, message: 'Draft preview is not configured.' }\n }\n\n let url: URL\n try {\n url = typeof requestUrl === 'string' ? new URL(requestUrl, 'http://localhost') : requestUrl\n } catch {\n return { ok: false, status: 400, message: 'Malformed preview request URL.' }\n }\n\n const token = url.searchParams.get('token')\n if (token !== expectedToken) {\n return { ok: false, status: 401, message: 'Invalid preview token.' }\n }\n\n const redirectTo = safeRedirectTarget(url.searchParams.get('redirect'))\n if (redirectTo === null) {\n return { ok: false, status: 400, message: 'Preview redirect target must be a same-site path.' }\n }\n\n return { ok: true, redirectTo }\n}\n","import { draftMode } from 'next/headers'\nimport { redirect } from 'next/navigation'\nimport { evaluatePreviewRequest, safeRedirectTarget } from './preview-core'\n\n/**\n * Draft preview route handlers (EC-144): Next.js `draftMode()` integration.\n * Server-only by construction — these factories are consumed from App Router\n * route handler files, never from client bundles.\n */\n\nexport interface PreviewRouteOptions {\n /**\n * The shared secret gating draft preview. An empty/undefined token means\n * every request is rejected with 401 — drafts stay unreachable until a\n * token is configured.\n */\n token: string | undefined\n}\n\n/** The shape an `app/api/.../route.ts` file re-exports. */\nexport interface PreviewRouteHandlers {\n GET(request: Request): Promise<Response>\n}\n\n/**\n * Create the preview-enable route handler for\n * `app/api/preview/route.ts`:\n *\n * ```ts\n * export const { GET } = createPreviewRoute({ token: process.env.PREVIEW_TOKEN })\n * ```\n *\n * `GET /api/preview?token=...&redirect=/some/path` checks the token, enables\n * Next draft mode (the catch-all helper then renders the `draft`\n * perspective), and redirects to the target path. Wrong/missing token → 401.\n */\nexport function createPreviewRoute(options: PreviewRouteOptions): PreviewRouteHandlers {\n return {\n async GET(request: Request): Promise<Response> {\n const evaluation = evaluatePreviewRequest(request.url, options.token)\n if (!evaluation.ok) {\n return new Response(evaluation.message, { status: evaluation.status })\n }\n const draft = await draftMode()\n draft.enable()\n redirect(evaluation.redirectTo)\n },\n }\n}\n\n/**\n * Create the preview-disable route handler (e.g.\n * `app/api/preview/disable/route.ts`). Disabling needs no token — it only\n * ever reduces visibility back to the published perspective.\n */\nexport function createPreviewDisableRoute(): PreviewRouteHandlers {\n return {\n async GET(request: Request): Promise<Response> {\n const draft = await draftMode()\n draft.disable()\n let target: string | null = '/'\n try {\n target = safeRedirectTarget(new URL(request.url).searchParams.get('redirect'))\n } catch {\n target = '/'\n }\n redirect(target ?? '/')\n },\n }\n}\n","/**\n * @elytracms/next — the embedded runtime (EC-144, vision AD-1): render\n * builder-managed pages inside the user's own Next.js App Router repo with\n * the user's own components. Drop `createCanvasRoute` into a catch-all\n * route, register components with `defineHostComponents`, done.\n *\n * Nothing here imports builder-only code (no studio, no operations, no\n * TanStack) — only the runtime packages: content accessors, the component\n * registry, and the runtime renderer.\n */\nexport const PACKAGE = '@elytracms/next'\n\n// Component registration (host components + base primitives).\nexport { defineHostComponents } from './components'\nexport type { DefineHostComponentsOptions, HostComponent, HostComponents } from './components'\n\n// The server component.\nexport { CanvasRenderer, defaultBindingPayloads } from './canvas-renderer'\nexport type { CanvasRendererProps } from './canvas-renderer'\n\n// Binding payloads (embedded-runtime binding resolution). The explicit\n// source-payload issue value makes rejected stored queries render visibly.\nexport {\n createBindingResolver,\n isSourcePayloadError,\n resolvePayloadToken,\n sourcePayloadError,\n} from './payloads'\nexport type { BindingPayloads, SourcePayloadError } from './payloads'\n\n// Content source seam + cache-tag merging (EC-145/146 plug in here).\nexport { mergeCacheTags } from './source'\nexport type { CanvasDataSource, ContentSource } from './source'\n\n// EC-166 delivery: automatic payload materialization for repeating sections\n// (replayed stored queries) and template pages (the route-bound document).\nexport { collectBindingSourceIds, materializeSourcePayloads } from './source-payloads'\nexport type {\n MaterializeSourcePayloadsInput,\n MaterializedSourcePayloads,\n} from './source-payloads'\n\n// PersistenceAdapter → ContentLookup snapshot bridge, plus the plain-data\n// assembler for hosts that prefetched the content themselves (EC-156).\nexport {\n createContentSnapshot,\n createStaticContentSource,\n mergeRouteRecords,\n} from './snapshot'\nexport type { ContentSnapshot, ContentSnapshotOptions, StaticContentData } from './snapshot'\n\n// Catch-all route helper (pure core + Next wiring).\nexport { pathFromSlug, resolveCanvasPage, splitLocalePath } from './route-core'\nexport type {\n CanvasPageOutcome,\n CanvasPayloadContext,\n CanvasPayloadsFactory,\n ResolveCanvasPageOptions,\n} from './route-core'\nexport { createCanvasRoute } from './route'\nexport type {\n CanvasCacheOptions,\n CanvasContentRequest,\n CanvasRequestInfo,\n CanvasRoute,\n CanvasRouteOptions,\n CanvasRouteProps,\n} from './route'\n\n// Per-page SEO → Next metadata, and sitemap.xml from published routes (EC-171).\nexport { canvasPageMetadata } from './metadata'\nexport { canvasSitemapEntries, createCanvasSitemap } from './sitemap'\nexport type {\n CanvasSitemapOptions,\n CanvasSitemapResult,\n CreateCanvasSitemapOptions,\n SitemapParamsProvider,\n SitemapRouteContext,\n SitemapSkippedRoute,\n} from './sitemap'\n\n// Cache tags & instant publish (EC-146): tag format, tag-discovery caching,\n// and the signed revalidation webhook receiver.\nexport {\n collectionCacheTag,\n docCacheTag,\n loadCachedEntry,\n nextCacheTags,\n projectSweepTag,\n routeCacheTag,\n scopeCacheTag,\n} from './cache'\nexport type { CacheWrapper, CacheWrapperOptions, CachedEntry } from './cache'\nexport {\n REVALIDATE_SIGNATURE_HEADER,\n evaluateRevalidateRequest,\n revalidatePayloadSchema,\n signRevalidateBody,\n} from './revalidate-core'\nexport type { RevalidateEvaluation, RevalidatePayload } from './revalidate-core'\nexport { createRevalidateRoute } from './revalidate'\nexport type { RevalidateRouteHandlers, RevalidateRouteOptions } from './revalidate'\n\n// Asset-pipeline image primitive (EC-147).\nexport { ElytraImage, createAssetImageLoader, nextImagePrimitive } from './image'\nexport type { AssetImageLoaderOptions, ElytraImageAsset, ElytraImageProps } from './image'\n\n// Draft preview (token-gated draftMode integration).\nexport { evaluatePreviewRequest, safeRedirectTarget } from './preview-core'\nexport type { PreviewEvaluation } from './preview-core'\nexport { createPreviewDisableRoute, createPreviewRoute } from './preview'\nexport type { PreviewRouteHandlers, PreviewRouteOptions } from './preview'\n\n// Re-exports so host apps can author manifests, declare their config, and shape\n// content WITHOUT depending on the internal packages (or on zod) directly — a\n// consuming repo installs ONLY `@elytracms/next` for delivery (EC-193).\nexport { defineComponent } from '@elytracms/component-registry'\n// EC-190: component props are field-defs (`PropField`), not the retired `PropSpec`.\nexport type { ComponentManifest, PropField, SlotSpec } from '@elytracms/component-registry'\nexport type { ComponentImplementations, RenderAsset } from '@elytracms/runtime-renderer'\nexport { z } from 'zod'\n\n// Config + content shapes a host declares (collections, locales, routes,\n// documents) — the public surface of the structure that lives in the repo\n// (AD-11). Re-exported here so the host imports one package (EC-193).\nexport {\n documentSchema,\n routeRecordSchema,\n redirectRecordSchema,\n localeConfigSchema,\n} from '@elytracms/cms-core'\nexport type {\n CollectionDef,\n CmsDocument,\n FieldDef,\n LocaleConfig,\n Locale,\n RouteRecord,\n RedirectRecord,\n} from '@elytracms/cms-core'\n// Graph data shapes (the page composition is graph data, per AD-12).\nexport { PROJECT_GRAPH_SCHEMA_VERSION, parseProjectGraph } from '@elytracms/project-graph'\nexport type { ComponentNode, ProjectGraph } from '@elytracms/project-graph'\n// The delivery perspective (draft | published).\nexport type { Perspective } from '@elytracms/content'\n// The delivery shape of an asset (resolved url + metadata).\nexport type { AssetRecord } from '@elytracms/persistence'\n"]}