@elytracms/next 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/index.d.ts +18 -18
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/package.json +2 -7
package/dist/client.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ContentAssetView, ContentClient, ContentClientProvider, ContentDocumentView, ContentQuery, RenderErrorBoundary, RenderErrorFallback, createFixtureContentClient, useContentClient } from '@elytracms/runtime-renderer/client';
|
|
1
|
+
export { ContentAssetView, ContentClient, ContentClientProvider, ContentDocumentView, ContentQuery, RenderErrorBoundary, RenderErrorFallback, createFixtureContentClient, useContentClient } from '@elytracms/core/runtime-renderer/client';
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
'use client'
|
|
2
|
-
export { ContentClientProvider, RenderErrorBoundary, RenderErrorFallback, createFixtureContentClient, useContentClient } from '@elytracms/runtime-renderer/client';
|
|
2
|
+
export { ContentClientProvider, RenderErrorBoundary, RenderErrorFallback, createFixtureContentClient, useContentClient } from '@elytracms/core/runtime-renderer/client';
|
|
3
3
|
//# sourceMappingURL=client.js.map
|
|
4
4
|
//# sourceMappingURL=client.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { ComponentType, ReactNode } from 'react';
|
|
2
|
-
import { ComponentRegistry, ComponentIssue, ComponentManifest } from '@elytracms/component-registry';
|
|
3
|
-
export { ComponentManifest, PropField, SlotSpec, defineComponent } from '@elytracms/component-registry';
|
|
4
|
-
import { ComponentImplementations, ResolveBinding, RelationTarget } from '@elytracms/runtime-renderer';
|
|
5
|
-
export { ComponentImplementations, RenderAsset } from '@elytracms/runtime-renderer';
|
|
6
|
-
import { ResolvePageResult, ResolvedAsset, Perspective, ContentClient, CacheTags, ContentDocumentSource } from '@elytracms/content';
|
|
7
|
-
export { Perspective } from '@elytracms/content';
|
|
8
|
-
import { ProjectGraph, ComponentNode } from '@elytracms/project-graph';
|
|
9
|
-
export { ComponentNode, PROJECT_GRAPH_SCHEMA_VERSION, ProjectGraph, parseProjectGraph } from '@elytracms/project-graph';
|
|
10
|
-
import { LocaleConfig, Locale, RouteRecord, RedirectRecord, CollectionDef } from '@elytracms/cms-core';
|
|
11
|
-
export { CmsDocument, CollectionDef, FieldDef, Locale, LocaleConfig, RedirectRecord, RouteRecord, documentSchema, localeConfigSchema, redirectRecordSchema, routeRecordSchema } from '@elytracms/cms-core';
|
|
12
|
-
import { AssetRecord, PersistenceAdapter } from '@elytracms/persistence';
|
|
13
|
-
export { AssetRecord } from '@elytracms/persistence';
|
|
2
|
+
import { ComponentRegistry, ComponentIssue, ComponentManifest } from '@elytracms/core/component-registry';
|
|
3
|
+
export { ComponentManifest, PropField, SlotSpec, defineComponent } from '@elytracms/core/component-registry';
|
|
4
|
+
import { ComponentImplementations, ResolveBinding, RelationTarget } from '@elytracms/core/runtime-renderer';
|
|
5
|
+
export { ComponentImplementations, RenderAsset } from '@elytracms/core/runtime-renderer';
|
|
6
|
+
import { ResolvePageResult, ResolvedAsset, Perspective, ContentClient, CacheTags, ContentDocumentSource } from '@elytracms/core/content';
|
|
7
|
+
export { Perspective } from '@elytracms/core/content';
|
|
8
|
+
import { ProjectGraph, ComponentNode } from '@elytracms/core/project-graph';
|
|
9
|
+
export { ComponentNode, PROJECT_GRAPH_SCHEMA_VERSION, ProjectGraph, parseProjectGraph } from '@elytracms/core/project-graph';
|
|
10
|
+
import { LocaleConfig, Locale, RouteRecord, RedirectRecord, CollectionDef } from '@elytracms/core/cms-core';
|
|
11
|
+
export { CmsDocument, CollectionDef, FieldDef, Locale, LocaleConfig, RedirectRecord, RouteRecord, documentSchema, localeConfigSchema, redirectRecordSchema, routeRecordSchema } from '@elytracms/core/cms-core';
|
|
12
|
+
import { AssetRecord, PersistenceAdapter } from '@elytracms/core/persistence';
|
|
13
|
+
export { AssetRecord } from '@elytracms/core/persistence';
|
|
14
14
|
import { Metadata, MetadataRoute } from 'next';
|
|
15
15
|
import { z } from 'zod';
|
|
16
16
|
export { z } from 'zod';
|
|
@@ -40,7 +40,7 @@ interface HostComponents {
|
|
|
40
40
|
interface DefineHostComponentsOptions {
|
|
41
41
|
/**
|
|
42
42
|
* Include the platform primitives (`base.primitives.*`) that ship with
|
|
43
|
-
* `@elytracms/runtime-renderer`. Defaults to `true` — graphs authored in the
|
|
43
|
+
* `@elytracms/core/runtime-renderer`. Defaults to `true` — graphs authored in the
|
|
44
44
|
* builder assume them.
|
|
45
45
|
*/
|
|
46
46
|
includeBasePrimitives?: boolean;
|
|
@@ -62,7 +62,7 @@ declare function defineHostComponents(components?: readonly HostComponent[], opt
|
|
|
62
62
|
* (e.g. a `listDocuments` result for a posts repeater).
|
|
63
63
|
*
|
|
64
64
|
* This is a deliberately small, pure resolver — the embedded runtime never
|
|
65
|
-
* imports `@elytracms/data-binding` (a builder-side package). Semantics mirror
|
|
65
|
+
* imports `@elytracms/core/data-binding` (a builder-side package). Semantics mirror
|
|
66
66
|
* EC-023 tokens: a binding token is a JSON Pointer (RFC 6901) into the
|
|
67
67
|
* payload; a miss resolves to `undefined`, never a throw (the renderer turns
|
|
68
68
|
* unresolvable bindings into visible fallback behavior, EC-015).
|
|
@@ -122,7 +122,7 @@ declare function createBindingResolver(payloads: BindingPayloads): ResolveBindin
|
|
|
122
122
|
/**
|
|
123
123
|
* `<CanvasRenderer />` (EC-144, vision AD-1): an async React Server Component
|
|
124
124
|
* that renders a resolved page (from `resolvePage`, EC-143) through
|
|
125
|
-
* `@elytracms/runtime-renderer` with the host app's component registry. EC-015
|
|
125
|
+
* `@elytracms/core/runtime-renderer` with the host app's component registry. EC-015
|
|
126
126
|
* fallback behavior is identical to the builder: a missing component, invalid
|
|
127
127
|
* prop, or missing required slot renders a visible fallback — a page never
|
|
128
128
|
* crashes and never silently omits a node.
|
|
@@ -188,7 +188,7 @@ declare function CanvasRenderer(props: CanvasRendererProps): Promise<ReactNode>;
|
|
|
188
188
|
*/
|
|
189
189
|
/**
|
|
190
190
|
* One data-source definition the published graph's bindings reference
|
|
191
|
-
* (EC-166 delivery): the structural shape of an `@elytracms/data-binding`
|
|
191
|
+
* (EC-166 delivery): the structural shape of an `@elytracms/core/data-binding`
|
|
192
192
|
* `DataSource`, declared here so the embedded runtime stays free of
|
|
193
193
|
* builder-side packages. Only `cms`-kind sources with the EC-166 per-scope id
|
|
194
194
|
* prefixes (`cms.section.<nodeId>` / `cms.template.<pageId>`) participate in
|
|
@@ -198,7 +198,7 @@ interface CanvasDataSource {
|
|
|
198
198
|
kind: string;
|
|
199
199
|
id: string;
|
|
200
200
|
label?: string;
|
|
201
|
-
/** Kind-specific config; cms query configs parse via `@elytracms/content`. */
|
|
201
|
+
/** Kind-specific config; cms query configs parse via `@elytracms/core/content`. */
|
|
202
202
|
config?: unknown;
|
|
203
203
|
}
|
|
204
204
|
interface ContentSource {
|
|
@@ -391,7 +391,7 @@ declare function mergeRouteRecords(stored: readonly RouteRecord[], fallback: rea
|
|
|
391
391
|
* {@link createContentSnapshot}, shared with hosts that fetched the data
|
|
392
392
|
* themselves (e.g. the EC-156 live delivery snapshot). Accessor semantics are
|
|
393
393
|
* byte-identical across both paths: the same `ContentLookup` feeds the same
|
|
394
|
-
* pure `@elytracms/content` client.
|
|
394
|
+
* pure `@elytracms/core/content` client.
|
|
395
395
|
*/
|
|
396
396
|
declare function createStaticContentSource(data: StaticContentData): ContentSnapshot;
|
|
397
397
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { ComponentRegistry } from '@elytracms/component-registry';
|
|
2
|
-
export { defineComponent } from '@elytracms/component-registry';
|
|
3
|
-
import { basePrimitives, getImplementation, renderCompositionInLayout, renderComposition, ImageManifest, serializeListingQuery, RenderErrorBoundary, collectReferencedAssetIds, collectReferencedRelations, collectReferencedListings, normalizeImageSource } from '@elytracms/runtime-renderer';
|
|
1
|
+
import { ComponentRegistry } from '@elytracms/core/component-registry';
|
|
2
|
+
export { defineComponent } from '@elytracms/core/component-registry';
|
|
3
|
+
import { basePrimitives, getImplementation, renderCompositionInLayout, renderComposition, ImageManifest, serializeListingQuery, RenderErrorBoundary, collectReferencedAssetIds, collectReferencedRelations, collectReferencedListings, normalizeImageSource } from '@elytracms/core/runtime-renderer';
|
|
4
4
|
import { isValidElement } from 'react';
|
|
5
5
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
6
|
-
import { cacheTags, isSectionSourceId, parseCmsSourceQueryConfig, listQueryOfCmsConfig, isDocumentHistory, resolvedAsset, createContentClient, createContentContext } from '@elytracms/content';
|
|
7
|
-
import { documentKey, splitPath, hierarchyMount, composePath } from '@elytracms/cms-core';
|
|
8
|
-
export { documentSchema, localeConfigSchema, redirectRecordSchema, routeRecordSchema } from '@elytracms/cms-core';
|
|
6
|
+
import { cacheTags, isSectionSourceId, parseCmsSourceQueryConfig, listQueryOfCmsConfig, isDocumentHistory, resolvedAsset, createContentClient, createContentContext } from '@elytracms/core/content';
|
|
7
|
+
import { documentKey, splitPath, hierarchyMount, composePath } from '@elytracms/core/cms-core';
|
|
8
|
+
export { documentSchema, localeConfigSchema, redirectRecordSchema, routeRecordSchema } from '@elytracms/core/cms-core';
|
|
9
9
|
import { revalidateTag, unstable_cache } from 'next/cache';
|
|
10
10
|
import { draftMode } from 'next/headers';
|
|
11
11
|
import { redirect, notFound, permanentRedirect } from 'next/navigation';
|
|
@@ -13,7 +13,7 @@ import { createHmac, timingSafeEqual } from 'crypto';
|
|
|
13
13
|
import { z } from 'zod';
|
|
14
14
|
export { z } from 'zod';
|
|
15
15
|
import NextImage from 'next/image';
|
|
16
|
-
export { PROJECT_GRAPH_SCHEMA_VERSION, parseProjectGraph } from '@elytracms/project-graph';
|
|
16
|
+
export { PROJECT_GRAPH_SCHEMA_VERSION, parseProjectGraph } from '@elytracms/core/project-graph';
|
|
17
17
|
|
|
18
18
|
// src/components.ts
|
|
19
19
|
function defineHostComponents(components = [], options = {}) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components.ts","../src/payloads.ts","../src/canvas-renderer.tsx","../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":["splitPath","cacheTags","jsx","outcome","draftMode","redirect"],"mappings":"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","file":"index.js","sourcesContent":["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). The\n * composition field can be named anything the host's collection schema chooses:\n * the conventional `body` (a `page`) or `content` (a routed content collection\n * like a `post`), but ALSO a host-specific name such as Konditorei's\n * `pageBuilder` (migrated faithfully from Sanity, EC-263). So the field is chosen\n * by VALUE — a composition is a `ComponentNode` or an array of them — NEVER by\n * name: a `body ?? content` name heuristic both picks a post's rich-text `body`\n * string over its `content` composition AND misses a `pageBuilder` entirely,\n * rendering nothing.\n *\n * `body` then `content` keep priority (so a content document's unrelated rich-text\n * `body` never shadows the conventional `content` composition); any other\n * composition-valued field is the generalized fallback.\n */\nfunction compositionOf(document: Record<string, unknown>): unknown {\n const body = document['body']\n if (Array.isArray(body) || isComponentNodeValue(body)) return body\n const content = document['content']\n if (Array.isArray(content) || isComponentNodeValue(content)) return content\n // Generalized (EC-263): the first field whose value is a composition — a node or\n // a non-empty array of nodes. `body`/`content` already took priority above.\n for (const value of Object.values(document)) {\n if (isComponentNodeValue(value)) return value\n if (Array.isArray(value) && value.length > 0 && value.every(isComponentNodeValue)) return value\n }\n return undefined\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 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 — (EC-227) tagged for invalidation when that\n // asset record is edited. EC-266: a `type:'asset'` seoOgImage field is delivered\n // as a ResolvedAsset OBJECT ({ id, url }); a string is a raw id (or a passthrough\n // URL, which has no asset id to tag). Take the id from whichever shape.\n const ogImage = result.document?.['seoOgImage']\n const ogImageId =\n typeof ogImage === 'string'\n ? ogImage\n : ogImage && typeof ogImage === 'object' && typeof (ogImage as { id?: unknown }).id === 'string'\n ? (ogImage as { id: string }).id\n : null\n if (ogImageId) ids.add(ogImageId)\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: a delivery-resolved asset OBJECT →\n * its `url` (EC-266); a URL string → passed through; a raw asset-id string →\n * resolved against the baked assets; anything unresolvable → dropped (EC-202).\n */\nfunction resolveOgImage(value: unknown, assets: readonly ResolvedAsset[]): string | null {\n // EC-266: a `seoOgImage` modelled as a `type:'asset'` FIELD (e.g. Konditorei,\n // migrated from Sanity) is resolved by delivery to a ResolvedAsset OBJECT\n // ({ id, url, … }), NOT a string — so read its `url`. A string value is the\n // legacy shape: a passthrough URL, or a raw asset id resolved against the baked\n // assets. A `str()`-only path turned the object into null, dropping og:image.\n if (value && typeof value === 'object') {\n const url = (value as { url?: unknown }).url\n return typeof url === 'string' && url.length > 0 ? url : null\n }\n if (typeof value !== 'string' || value.length === 0) 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(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"]}
|
|
1
|
+
{"version":3,"sources":["../src/components.ts","../src/payloads.ts","../src/canvas-renderer.tsx","../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":["splitPath","cacheTags","jsx","outcome","draftMode","redirect"],"mappings":"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","file":"index.js","sourcesContent":["import type { ComponentType } from 'react'\nimport { ComponentRegistry } from '@elytracms/core/component-registry'\nimport type { ComponentIssue, ComponentManifest } from '@elytracms/core/component-registry'\nimport { basePrimitives, getImplementation } from '@elytracms/core/runtime-renderer'\nimport type { ComponentImplementations } from '@elytracms/core/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/core/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/core/project-graph'\nimport type { ItemContext, ResolveBinding } from '@elytracms/core/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/core/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/core/content'\nimport type { ComponentNode, ProjectGraph } from '@elytracms/core/project-graph'\nimport {\n RenderErrorBoundary,\n renderComposition,\n renderCompositionInLayout,\n serializeListingQuery,\n} from '@elytracms/core/runtime-renderer'\nimport type {\n RelationTarget,\n RenderAsset,\n RenderContext,\n ResolveBinding,\n ResolveListing,\n ResolveRelation,\n} from '@elytracms/core/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/core/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). The\n * composition field can be named anything the host's collection schema chooses:\n * the conventional `body` (a `page`) or `content` (a routed content collection\n * like a `post`), but ALSO a host-specific name such as Konditorei's\n * `pageBuilder` (migrated faithfully from Sanity, EC-263). So the field is chosen\n * by VALUE — a composition is a `ComponentNode` or an array of them — NEVER by\n * name: a `body ?? content` name heuristic both picks a post's rich-text `body`\n * string over its `content` composition AND misses a `pageBuilder` entirely,\n * rendering nothing.\n *\n * `body` then `content` keep priority (so a content document's unrelated rich-text\n * `body` never shadows the conventional `content` composition); any other\n * composition-valued field is the generalized fallback.\n */\nfunction compositionOf(document: Record<string, unknown>): unknown {\n const body = document['body']\n if (Array.isArray(body) || isComponentNodeValue(body)) return body\n const content = document['content']\n if (Array.isArray(content) || isComponentNodeValue(content)) return content\n // Generalized (EC-263): the first field whose value is a composition — a node or\n // a non-empty array of nodes. `body`/`content` already took priority above.\n for (const value of Object.values(document)) {\n if (isComponentNodeValue(value)) return value\n if (Array.isArray(value) && value.length > 0 && value.every(isComponentNodeValue)) return value\n }\n return undefined\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 type { Locale, LocaleConfig, RouteRecord } from '@elytracms/core/cms-core'\nimport { cacheTags } from '@elytracms/core/content'\nimport type { CacheTags, ContentClient, Perspective, ResolvedAsset } from '@elytracms/core/content'\nimport type { ProjectGraph } from '@elytracms/core/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/core/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/core/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/core/content'\nimport type { CacheTags, ContentClient, ResolvePageResult } from '@elytracms/core/content'\nimport type { ComponentNode, ProjectGraph } from '@elytracms/core/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/core/cms-core'\nimport type {\n CmsDocument,\n CollectionDef,\n DocumentRef,\n Locale,\n LocaleConfig,\n RedirectRecord,\n RouteRecord,\n} from '@elytracms/core/cms-core'\nimport {\n createContentClient,\n createContentContext,\n isDocumentHistory,\n resolvedAsset,\n} from '@elytracms/core/content'\nimport type {\n ContentClient,\n ContentDocumentSource,\n ContentLookup,\n Perspective,\n ResolvedAsset,\n} from '@elytracms/core/content'\nimport type { AssetRecord, PersistenceAdapter } from '@elytracms/core/persistence'\nimport type { ProjectGraph } from '@elytracms/core/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/core/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/core/cms-core'\nimport type { Locale, LocaleConfig } from '@elytracms/core/cms-core'\nimport { cacheTags } from '@elytracms/core/content'\nimport type {\n CacheTags,\n ContentClient,\n Perspective,\n ResolvedAsset,\n ResolvePageResult,\n} from '@elytracms/core/content'\nimport type { ComponentNode, ProjectGraph } from '@elytracms/core/project-graph'\nimport type { ComponentRegistry } from '@elytracms/core/component-registry'\nimport {\n collectReferencedAssetIds,\n collectReferencedListings,\n collectReferencedRelations,\n} from '@elytracms/core/runtime-renderer'\nimport type { ListingQuery, RelationTarget } from '@elytracms/core/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 — (EC-227) tagged for invalidation when that\n // asset record is edited. EC-266: a `type:'asset'` seoOgImage field is delivered\n // as a ResolvedAsset OBJECT ({ id, url }); a string is a raw id (or a passthrough\n // URL, which has no asset id to tag). Take the id from whichever shape.\n const ogImage = result.document?.['seoOgImage']\n const ogImageId =\n typeof ogImage === 'string'\n ? ogImage\n : ogImage && typeof ogImage === 'object' && typeof (ogImage as { id?: unknown }).id === 'string'\n ? (ogImage as { id: string }).id\n : null\n if (ogImageId) ids.add(ogImageId)\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/core/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/core/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: a delivery-resolved asset OBJECT →\n * its `url` (EC-266); a URL string → passed through; a raw asset-id string →\n * resolved against the baked assets; anything unresolvable → dropped (EC-202).\n */\nfunction resolveOgImage(value: unknown, assets: readonly ResolvedAsset[]): string | null {\n // EC-266: a `seoOgImage` modelled as a `type:'asset'` FIELD (e.g. Konditorei,\n // migrated from Sanity) is resolved by delivery to a ResolvedAsset OBJECT\n // ({ id, url, … }), NOT a string — so read its `url`. A string value is the\n // legacy shape: a passthrough URL, or a raw asset id resolved against the baked\n // assets. A `str()`-only path turned the object into null, dropping og:image.\n if (value && typeof value === 'object') {\n const url = (value as { url?: unknown }).url\n return typeof url === 'string' && url.length > 0 ? url : null\n }\n if (typeof value !== 'string' || value.length === 0) 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(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/core/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/core/cms-core'\nimport type { CmsDocument, Locale, RouteRecord } from '@elytracms/core/cms-core'\nimport type { ContentClient } from '@elytracms/core/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/core/content'\nimport { ImageManifest, normalizeImageSource } from '@elytracms/core/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/core/component-registry'\n// EC-190: component props are field-defs (`PropField`), not the retired `PropSpec`.\nexport type { ComponentManifest, PropField, SlotSpec } from '@elytracms/core/component-registry'\nexport type { ComponentImplementations, RenderAsset } from '@elytracms/core/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/core/cms-core'\nexport type {\n CollectionDef,\n CmsDocument,\n FieldDef,\n LocaleConfig,\n Locale,\n RouteRecord,\n RedirectRecord,\n} from '@elytracms/core/cms-core'\n// Graph data shapes (the page composition is graph data, per AD-12).\nexport { PROJECT_GRAPH_SCHEMA_VERSION, parseProjectGraph } from '@elytracms/core/project-graph'\nexport type { ComponentNode, ProjectGraph } from '@elytracms/core/project-graph'\n// The delivery perspective (draft | published).\nexport type { Perspective } from '@elytracms/core/content'\n// The delivery shape of an asset (resolved url + metadata).\nexport type { AssetRecord } from '@elytracms/core/persistence'\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elytracms/next",
|
|
3
3
|
"author": "finaldream <hi@finaldream.de>",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.6",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
7
7
|
"type": "module",
|
|
@@ -25,12 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"zod": "^4.0.0",
|
|
28
|
-
"@elytracms/
|
|
29
|
-
"@elytracms/content": "^0.0.1",
|
|
30
|
-
"@elytracms/component-registry": "^0.0.1",
|
|
31
|
-
"@elytracms/runtime-renderer": "^0.0.1",
|
|
32
|
-
"@elytracms/project-graph": "^0.0.1",
|
|
33
|
-
"@elytracms/persistence": "^0.0.1"
|
|
28
|
+
"@elytracms/core": "^0.0.6"
|
|
34
29
|
},
|
|
35
30
|
"peerDependencies": {
|
|
36
31
|
"next": ">=16.0.0",
|