@elytracms/studio 0.0.52 → 0.0.53

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.
Files changed (308) hide show
  1. package/dist/components/account/account-settings.js +4 -4
  2. package/dist/components/account/credential-panel.js +1 -1
  3. package/dist/components/account/self-account-view-source.js +3 -3
  4. package/dist/components/ai/ai-chat-panel-lazy.js +1 -1
  5. package/dist/components/ai/ai-chat-panel.js +4 -4
  6. package/dist/components/ai/ai-cms-panel.js +1 -1
  7. package/dist/components/ai/proposal-card.js +4 -4
  8. package/dist/components/ai/translate-document-action.js +1 -1
  9. package/dist/components/ai/translate-document-dialog.d.ts +1 -1
  10. package/dist/components/app-views/default-modules.d.ts +3 -3
  11. package/dist/components/app-views/default-modules.js +20 -20
  12. package/dist/components/app-views/sidebar.d.ts +1 -1
  13. package/dist/components/app-views/sidebar.js +2 -2
  14. package/dist/components/app-views/studio-config.d.ts +1 -1
  15. package/dist/components/assets/asset-detail.js +9 -9
  16. package/dist/components/assets/asset-grid.js +7 -7
  17. package/dist/components/assets/asset-thumb.d.ts +1 -1
  18. package/dist/components/assets/asset-thumb.js +2 -2
  19. package/dist/components/assets/assets-collection-view-source.js +3 -3
  20. package/dist/components/assets/assets-module.js +8 -8
  21. package/dist/components/assets/assets-store.d.ts +1 -1
  22. package/dist/components/assets/assets-store.js +1 -1
  23. package/dist/components/builder/blocks-model.js +1 -1
  24. package/dist/components/builder/blocks-panel.d.ts +1 -1
  25. package/dist/components/builder/blocks-panel.js +6 -6
  26. package/dist/components/builder/canvas.js +11 -11
  27. package/dist/components/builder/clipboard-actions.js +2 -2
  28. package/dist/components/builder/composition-field-editor-lazy.d.ts +1 -1
  29. package/dist/components/builder/composition-field-editor-lazy.js +1 -1
  30. package/dist/components/builder/composition-field-editor.d.ts +1 -1
  31. package/dist/components/builder/composition-field-editor.js +9 -9
  32. package/dist/components/builder/insert-context.d.ts +2 -2
  33. package/dist/components/builder/insert-context.js +2 -2
  34. package/dist/components/builder/insert-menu.d.ts +2 -2
  35. package/dist/components/builder/insert-menu.js +1 -1
  36. package/dist/components/builder/layout-inspector.js +1 -1
  37. package/dist/components/builder/page-tree.js +5 -5
  38. package/dist/components/builder/property-inspector.js +3 -3
  39. package/dist/components/builder/reuse-context.d.ts +1 -1
  40. package/dist/components/builder/reuse-context.js +3 -3
  41. package/dist/components/builder/spacing-handles.js +2 -2
  42. package/dist/components/cms/asset-picker.js +4 -4
  43. package/dist/components/cms/bulk-actions.js +1 -1
  44. package/dist/components/cms/bulk-bar.d.ts +1 -1
  45. package/dist/components/cms/bulk-bar.js +3 -3
  46. package/dist/components/cms/cell-edit.js +1 -1
  47. package/dist/components/cms/cell.js +2 -2
  48. package/dist/components/cms/cms-index.js +1 -1
  49. package/dist/components/cms/cms-store.d.ts +2 -2
  50. package/dist/components/cms/cms-store.js +6 -6
  51. package/dist/components/cms/collection-table.js +17 -17
  52. package/dist/components/cms/detail-editor.js +31 -31
  53. package/dist/components/cms/document-diff-view.js +4 -4
  54. package/dist/components/cms/editable-cell.d.ts +1 -1
  55. package/dist/components/cms/editable-cell.js +6 -6
  56. package/dist/components/cms/field-control.js +15 -15
  57. package/dist/components/cms/field-renderer.d.ts +2 -2
  58. package/dist/components/cms/filter-builder.js +3 -3
  59. package/dist/components/cms/import-export.js +1 -1
  60. package/dist/components/cms/issues-pane.js +1 -1
  61. package/dist/components/cms/prop-fields.js +3 -3
  62. package/dist/components/cms/reference-confirm.js +1 -1
  63. package/dist/components/cms/relation-picker.js +1 -1
  64. package/dist/components/cms/rich-text/block-commands.d.ts +1 -1
  65. package/dist/components/cms/rich-text/component-embed.js +2 -2
  66. package/dist/components/cms/rich-text/editor.js +8 -8
  67. package/dist/components/cms/rich-text/embed-inspector.d.ts +1 -1
  68. package/dist/components/cms/rich-text/embed-inspector.js +2 -2
  69. package/dist/components/cms/rich-text/embed-picker.js +1 -1
  70. package/dist/components/cms/rich-text/embed-props.js +1 -1
  71. package/dist/components/cms/rich-text/extensions.d.ts +1 -1
  72. package/dist/components/cms/rich-text/extensions.js +4 -4
  73. package/dist/components/cms/rich-text/index.d.ts +1 -1
  74. package/dist/components/cms/rich-text/index.js +1 -1
  75. package/dist/components/cms/rich-text/insert.d.ts +1 -1
  76. package/dist/components/cms/rich-text/lazy.d.ts +1 -1
  77. package/dist/components/cms/rich-text/lazy.js +1 -1
  78. package/dist/components/cms/rich-text/slash-command.js +1 -1
  79. package/dist/components/cms/rich-text/toolbar.d.ts +1 -1
  80. package/dist/components/cms/rich-text/toolbar.js +4 -4
  81. package/dist/components/cms/use-cell-edit.d.ts +1 -1
  82. package/dist/components/cms/use-cell-edit.js +2 -2
  83. package/dist/components/cms/use-compare-selection.d.ts +1 -1
  84. package/dist/components/cms/use-discard-controller.d.ts +1 -1
  85. package/dist/components/cms/use-discard-controller.js +2 -2
  86. package/dist/components/cms/use-document-versions.d.ts +1 -1
  87. package/dist/components/cms/use-document-versions.js +1 -1
  88. package/dist/components/cms/use-embed-inspector-host.d.ts +1 -1
  89. package/dist/components/cms/use-published-perspective.d.ts +2 -2
  90. package/dist/components/cms/use-published-perspective.js +2 -2
  91. package/dist/components/cms/use-restore-version.js +1 -1
  92. package/dist/components/cms/version-compare-lazy.js +1 -1
  93. package/dist/components/cms/version-compare.js +6 -6
  94. package/dist/components/cms/versions-model.d.ts +1 -1
  95. package/dist/components/cms/versions-pane.js +5 -5
  96. package/dist/components/cms/view-bar.js +2 -2
  97. package/dist/components/collab/collab-context.js +1 -1
  98. package/dist/components/collection-view/cms-collection-view-source.js +2 -2
  99. package/dist/components/components/component-preview.js +3 -3
  100. package/dist/components/components/components-index.js +2 -2
  101. package/dist/components/components/registry-browser.js +2 -2
  102. package/dist/components/components/transfer-dialog.js +5 -5
  103. package/dist/components/components/transfer.js +4 -4
  104. package/dist/components/current-user-menu.js +2 -2
  105. package/dist/components/delivery-health-banner.js +2 -2
  106. package/dist/components/operation-error.js +1 -1
  107. package/dist/components/project-list.js +5 -5
  108. package/dist/components/project-session.js +1 -1
  109. package/dist/components/project-switcher.js +3 -3
  110. package/dist/components/rail-store-status.js +1 -1
  111. package/dist/components/redirects/redirects-collection-view-source.js +3 -3
  112. package/dist/components/redirects/redirects-module.js +6 -6
  113. package/dist/components/section-nav.js +3 -3
  114. package/dist/components/section-surface.js +1 -1
  115. package/dist/components/studio-project-screen.js +7 -7
  116. package/dist/components/studio-shell.js +9 -9
  117. package/dist/components/use-hydration-phase.js +1 -1
  118. package/dist/components/users/users-collection-view-source.js +4 -4
  119. package/dist/components/users/users-module.js +9 -9
  120. package/dist/components/workspace-projects.js +1 -1
  121. package/dist/customization.d.ts +9 -9
  122. package/dist/customization.js +5 -5
  123. package/dist/lib/ai/anthropic-provider.d.ts +1 -1
  124. package/dist/lib/ai/apply-content.d.ts +1 -1
  125. package/dist/lib/ai/apply-content.js +3 -3
  126. package/dist/lib/ai/chat-state.d.ts +2 -2
  127. package/dist/lib/ai/config.d.ts +1 -1
  128. package/dist/lib/ai/create-flow.d.ts +2 -2
  129. package/dist/lib/ai/create-flow.js +3 -3
  130. package/dist/lib/ai/fake-provider.d.ts +1 -1
  131. package/dist/lib/ai/index.d.ts +15 -15
  132. package/dist/lib/ai/index.js +15 -15
  133. package/dist/lib/ai/knowledge.d.ts +1 -1
  134. package/dist/lib/ai/provenance.d.ts +1 -1
  135. package/dist/lib/ai/route-provider.d.ts +1 -1
  136. package/dist/lib/ai/route.d.ts +1 -1
  137. package/dist/lib/ai/shape.d.ts +1 -1
  138. package/dist/lib/ai/translate-document.d.ts +1 -1
  139. package/dist/lib/ai/translate-document.js +3 -3
  140. package/dist/lib/ai-panel.js +1 -1
  141. package/dist/lib/assets/index.d.ts +4 -4
  142. package/dist/lib/assets/index.js +4 -4
  143. package/dist/lib/assets/upload.d.ts +2 -2
  144. package/dist/lib/assets/upload.js +2 -2
  145. package/dist/lib/auth/convex-auth-adapter.d.ts +2 -2
  146. package/dist/lib/auth/convex-auth-adapter.js +1 -1
  147. package/dist/lib/auth/dev-auto-login-adapter.d.ts +1 -1
  148. package/dist/lib/auth/index.d.ts +9 -9
  149. package/dist/lib/auth/index.js +10 -10
  150. package/dist/lib/auth/local-auth-adapter.d.ts +1 -1
  151. package/dist/lib/auth/route-guard.d.ts +1 -1
  152. package/dist/lib/auth-errors.d.ts +1 -1
  153. package/dist/lib/clipboard/index.d.ts +3 -3
  154. package/dist/lib/clipboard/index.js +3 -3
  155. package/dist/lib/cms/published-documents.d.ts +1 -1
  156. package/dist/lib/cms-views/index.d.ts +2 -2
  157. package/dist/lib/cms-views/index.js +2 -2
  158. package/dist/lib/collection-view/collection-view-source.d.ts +4 -4
  159. package/dist/lib/data/collection-content.js +1 -1
  160. package/dist/lib/data/data-store.js +6 -6
  161. package/dist/lib/data/index.d.ts +4 -4
  162. package/dist/lib/data/index.js +4 -4
  163. package/dist/lib/data/sample-capture.js +4 -4
  164. package/dist/lib/data/sources-store.d.ts +1 -1
  165. package/dist/lib/diff-view-preference.js +1 -1
  166. package/dist/lib/dnd/gap-drag.d.ts +1 -1
  167. package/dist/lib/i18n/i18n.d.ts +1 -1
  168. package/dist/lib/i18n/i18n.js +1 -1
  169. package/dist/lib/i18n/index.d.ts +4 -4
  170. package/dist/lib/i18n/index.js +3 -3
  171. package/dist/lib/i18n/messages.en.d.ts +1 -1
  172. package/dist/lib/i18n/messages.en.js +1 -1
  173. package/dist/lib/locale/binding-fallback.d.ts +1 -1
  174. package/dist/lib/locale/binding-fallback.js +2 -2
  175. package/dist/lib/locale/index.d.ts +6 -6
  176. package/dist/lib/locale/index.js +6 -6
  177. package/dist/lib/locale/locale-switcher.js +3 -3
  178. package/dist/lib/locale/use-studio-locale.js +1 -1
  179. package/dist/lib/operations/asset-repository.d.ts +1 -1
  180. package/dist/lib/operations/cms-persistence.d.ts +1 -1
  181. package/dist/lib/operations/cms-persistence.js +1 -1
  182. package/dist/lib/operations/index.d.ts +6 -6
  183. package/dist/lib/operations/index.js +6 -6
  184. package/dist/lib/operations/session-hydration.d.ts +1 -1
  185. package/dist/lib/operations/session-hydration.js +1 -1
  186. package/dist/lib/operations/studio-operations.d.ts +1 -1
  187. package/dist/lib/operations/studio-operations.js +3 -3
  188. package/dist/lib/persistence/convex-adapter.js +2 -2
  189. package/dist/lib/persistence/convex-blob-storage.d.ts +1 -1
  190. package/dist/lib/persistence/convex-blob-storage.js +1 -1
  191. package/dist/lib/persistence/deployment-readiness.d.ts +2 -2
  192. package/dist/lib/persistence/index.d.ts +6 -6
  193. package/dist/lib/persistence/index.js +7 -7
  194. package/dist/lib/persona/labels.js +1 -1
  195. package/dist/lib/query/index.d.ts +2 -2
  196. package/dist/lib/query/index.js +1 -1
  197. package/dist/lib/rail.js +1 -1
  198. package/dist/lib/references/impact.d.ts +1 -1
  199. package/dist/lib/references/impact.js +1 -1
  200. package/dist/lib/references/index.d.ts +3 -3
  201. package/dist/lib/references/index.js +3 -3
  202. package/dist/lib/references/references-store.d.ts +2 -2
  203. package/dist/lib/references/references-store.js +3 -3
  204. package/dist/lib/registry/index.js +2 -2
  205. package/dist/lib/theme.js +1 -1
  206. package/dist/lib/webhooks/config.d.ts +1 -1
  207. package/dist/lib/webhooks/config.js +2 -2
  208. package/dist/lib/webhooks/dispatcher.js +2 -2
  209. package/dist/lib/webhooks/index.d.ts +6 -6
  210. package/dist/lib/webhooks/index.js +4 -4
  211. package/dist/lib/workspace/index.d.ts +7 -7
  212. package/dist/lib/workspace/index.js +3 -3
  213. package/dist/lib/workspace/switcher-source.d.ts +1 -1
  214. package/dist/router/index.d.ts +1 -1
  215. package/dist/router/index.js +1 -1
  216. package/dist/ui/avatar.js +1 -1
  217. package/dist/ui/badge.js +1 -1
  218. package/dist/ui/button.js +1 -1
  219. package/dist/ui/card.js +1 -1
  220. package/dist/ui/collapsible-section.js +2 -2
  221. package/dist/ui/dialog.js +1 -1
  222. package/dist/ui/dropdown-menu.js +1 -1
  223. package/dist/ui/field.js +1 -1
  224. package/dist/ui/index.d.ts +19 -19
  225. package/dist/ui/index.js +19 -19
  226. package/dist/ui/input.js +1 -1
  227. package/dist/ui/inspector.js +1 -1
  228. package/dist/ui/layout.js +1 -1
  229. package/dist/ui/panel.js +2 -2
  230. package/dist/ui/popover.js +1 -1
  231. package/dist/ui/row-item.js +2 -2
  232. package/dist/ui/segmented-control.js +1 -1
  233. package/dist/ui/separator.js +1 -1
  234. package/dist/ui/toolbar.js +2 -2
  235. package/dist/ui/typography.js +1 -1
  236. package/package.json +3 -3
  237. package/dist/components/assets/asset-library.d.ts +0 -14
  238. package/dist/components/assets/asset-library.js +0 -202
  239. package/dist/components/assets/asset-library.js.map +0 -1
  240. package/dist/components/backend-gate.d.ts +0 -19
  241. package/dist/components/backend-gate.js +0 -64
  242. package/dist/components/backend-gate.js.map +0 -1
  243. package/dist/components/builder/composition-scope.d.ts +0 -16
  244. package/dist/components/builder/composition-scope.js +0 -7
  245. package/dist/components/builder/composition-scope.js.map +0 -1
  246. package/dist/components/cms/alias-selector.d.ts +0 -20
  247. package/dist/components/cms/alias-selector.js +0 -34
  248. package/dist/components/cms/alias-selector.js.map +0 -1
  249. package/dist/components/cms/collections-sidebar.d.ts +0 -18
  250. package/dist/components/cms/collections-sidebar.js +0 -36
  251. package/dist/components/cms/collections-sidebar.js.map +0 -1
  252. package/dist/components/cms/new-page-dialog.d.ts +0 -22
  253. package/dist/components/cms/new-page-dialog.js +0 -42
  254. package/dist/components/cms/new-page-dialog.js.map +0 -1
  255. package/dist/components/cms/rich-text/embed-control.d.ts +0 -17
  256. package/dist/components/cms/rich-text/embed-control.js +0 -62
  257. package/dist/components/cms/rich-text/embed-control.js.map +0 -1
  258. package/dist/components/cms/rich-text/image-control.d.ts +0 -16
  259. package/dist/components/cms/rich-text/image-control.js +0 -36
  260. package/dist/components/cms/rich-text/image-control.js.map +0 -1
  261. package/dist/components/components/fixture-runner.d.ts +0 -10
  262. package/dist/components/components/fixture-runner.js +0 -27
  263. package/dist/components/components/fixture-runner.js.map +0 -1
  264. package/dist/components/references/builder-deep-link.d.ts +0 -12
  265. package/dist/components/references/builder-deep-link.js +0 -53
  266. package/dist/components/references/builder-deep-link.js.map +0 -1
  267. package/dist/components/routes/redirect-chain.d.ts +0 -9
  268. package/dist/components/routes/redirect-chain.js +0 -16
  269. package/dist/components/routes/redirect-chain.js.map +0 -1
  270. package/dist/components/routes/redirect-manager.d.ts +0 -13
  271. package/dist/components/routes/redirect-manager.js +0 -24
  272. package/dist/components/routes/redirect-manager.js.map +0 -1
  273. package/dist/components/routes/route-list.d.ts +0 -35
  274. package/dist/components/routes/route-list.js +0 -69
  275. package/dist/components/routes/route-list.js.map +0 -1
  276. package/dist/components/routes/routes-shell.d.ts +0 -14
  277. package/dist/components/routes/routes-shell.js +0 -68
  278. package/dist/components/routes/routes-shell.js.map +0 -1
  279. package/dist/components/sections.d.ts +0 -37
  280. package/dist/components/sections.js +0 -62
  281. package/dist/components/sections.js.map +0 -1
  282. package/dist/components/users/user-search.d.ts +0 -8
  283. package/dist/components/users/user-search.js +0 -13
  284. package/dist/components/users/user-search.js.map +0 -1
  285. package/dist/components/workspace-gate.d.ts +0 -12
  286. package/dist/components/workspace-gate.js +0 -28
  287. package/dist/components/workspace-gate.js.map +0 -1
  288. package/dist/lib/cms-views/views-store.d.ts +0 -70
  289. package/dist/lib/cms-views/views-store.js +0 -129
  290. package/dist/lib/cms-views/views-store.js.map +0 -1
  291. package/dist/lib/operations/graph-commands.d.ts +0 -136
  292. package/dist/lib/operations/graph-commands.js +0 -85
  293. package/dist/lib/operations/graph-commands.js.map +0 -1
  294. package/dist/lib/operations/graph-persistence.d.ts +0 -27
  295. package/dist/lib/operations/graph-persistence.js +0 -35
  296. package/dist/lib/operations/graph-persistence.js.map +0 -1
  297. package/dist/lib/routing/index.d.ts +0 -10
  298. package/dist/lib/routing/index.js +0 -11
  299. package/dist/lib/routing/index.js.map +0 -1
  300. package/dist/lib/routing/routing-analysis.d.ts +0 -26
  301. package/dist/lib/routing/routing-analysis.js +0 -37
  302. package/dist/lib/routing/routing-analysis.js.map +0 -1
  303. package/dist/lib/routing/routing-store.d.ts +0 -50
  304. package/dist/lib/routing/routing-store.js +0 -72
  305. package/dist/lib/routing/routing-store.js.map +0 -1
  306. package/dist/lib/working-graph.d.ts +0 -82
  307. package/dist/lib/working-graph.js +0 -113
  308. package/dist/lib/working-graph.js.map +0 -1
@@ -1,50 +0,0 @@
1
- import type { RouteRecord } from '@elytracms/core/cms-core';
2
- /**
3
- * Pure template-route helpers for the Routes domain (EC-166, reshaped by
4
- * EC-187; route persistence retired by EC-207).
5
- *
6
- * Routes & redirects are config-sourced (EC-207 "routes as code"): they are
7
- * authored in `elytra.config.ts`, materialized by `composeProject`, and read
8
- * through `resolveDeploymentRoutes`/`resolveDeploymentRedirects` — never written
9
- * to or read from the backend. The former `routes`/`redirects` system
10
- * collections are retired. What survives here are pure functions over the
11
- * canonical `RouteRecord` schema, useful for authoring/inspecting template
12
- * routes in config.
13
- *
14
- * A template page is one page definition serving *every* document of a
15
- * collection through a dynamic pattern. It is expressed entirely in the
16
- * canonical route-record schema: the parameterized `document` ref
17
- * (`{ collection, id: ':slug' }`) names the collection plus the URL param
18
- * carrying the document's slug/id — `@elytracms/core/content`'s `resolvePage`
19
- * substitutes the matched value at request time. After EC-187 there is no
20
- * `templateId`; a template route is identified purely by its parameterized
21
- * `document` ref (a `:param` id over a collection). One template route per
22
- * collection. No new record shape, no parallel store.
23
- */
24
- /** Deterministic record id: one template route per collection (EC-187). */
25
- export declare function templateRouteId(collectionId: string): string;
26
- export interface TemplateRouteInit {
27
- collectionId: string;
28
- /** Dynamic pattern, e.g. `/blog/:slug`. Must capture {@link param}. */
29
- pattern: string;
30
- /** The URL param carrying the document slug or id. Defaults to `slug`. */
31
- param?: string;
32
- locale?: string;
33
- }
34
- /** What a template route binds, read back from a stored record. */
35
- export interface TemplateRouteBinding {
36
- collectionId: string;
37
- param: string;
38
- }
39
- /** Build the canonical route record of a template page. */
40
- export declare function buildTemplateRoute(init: TemplateRouteInit): RouteRecord;
41
- /** The collection + param a route record templates over, if it is one. */
42
- export declare function templateBindingOf(route: RouteRecord): TemplateRouteBinding | undefined;
43
- /** The template route serving a collection, if registered (EC-187). */
44
- export declare function templateRouteFor(routes: readonly RouteRecord[], collectionId: string): RouteRecord | undefined;
45
- /**
46
- * Plain-language validation of a template pattern: it must be a real dynamic
47
- * pattern that captures the document param exactly once. Returns `undefined`
48
- * when the pattern is usable.
49
- */
50
- export declare function templatePatternError(pattern: string, param?: string): string | undefined;
@@ -1,72 +0,0 @@
1
- import { routeRecordSchema } from '@elytracms/core/cms-core';
2
- /**
3
- * Pure template-route helpers for the Routes domain (EC-166, reshaped by
4
- * EC-187; route persistence retired by EC-207).
5
- *
6
- * Routes & redirects are config-sourced (EC-207 "routes as code"): they are
7
- * authored in `elytra.config.ts`, materialized by `composeProject`, and read
8
- * through `resolveDeploymentRoutes`/`resolveDeploymentRedirects` — never written
9
- * to or read from the backend. The former `routes`/`redirects` system
10
- * collections are retired. What survives here are pure functions over the
11
- * canonical `RouteRecord` schema, useful for authoring/inspecting template
12
- * routes in config.
13
- *
14
- * A template page is one page definition serving *every* document of a
15
- * collection through a dynamic pattern. It is expressed entirely in the
16
- * canonical route-record schema: the parameterized `document` ref
17
- * (`{ collection, id: ':slug' }`) names the collection plus the URL param
18
- * carrying the document's slug/id — `@elytracms/core/content`'s `resolvePage`
19
- * substitutes the matched value at request time. After EC-187 there is no
20
- * `templateId`; a template route is identified purely by its parameterized
21
- * `document` ref (a `:param` id over a collection). One template route per
22
- * collection. No new record shape, no parallel store.
23
- */
24
- /** Deterministic record id: one template route per collection (EC-187). */
25
- export function templateRouteId(collectionId) {
26
- return `route-template-${collectionId}`;
27
- }
28
- /** Build the canonical route record of a template page. */
29
- export function buildTemplateRoute(init) {
30
- const param = init.param ?? 'slug';
31
- return routeRecordSchema.parse({
32
- id: templateRouteId(init.collectionId),
33
- pattern: init.pattern,
34
- document: { collection: init.collectionId, id: `:${param}` },
35
- ...(init.locale !== undefined ? { locale: init.locale } : {}),
36
- });
37
- }
38
- /** The collection + param a route record templates over, if it is one. */
39
- export function templateBindingOf(route) {
40
- if (route.document === undefined)
41
- return undefined;
42
- if (!route.document.id.startsWith(':'))
43
- return undefined;
44
- return { collectionId: route.document.collection, param: route.document.id.slice(1) };
45
- }
46
- /** The template route serving a collection, if registered (EC-187). */
47
- export function templateRouteFor(routes, collectionId) {
48
- return routes.find((route) => templateBindingOf(route)?.collectionId === collectionId);
49
- }
50
- /**
51
- * Plain-language validation of a template pattern: it must be a real dynamic
52
- * pattern that captures the document param exactly once. Returns `undefined`
53
- * when the pattern is usable.
54
- */
55
- export function templatePatternError(pattern, param = 'slug') {
56
- if (!pattern.startsWith('/'))
57
- return 'The address must start with “/”.';
58
- const segments = pattern.split('/').filter((segment) => segment.length > 0);
59
- if (segments.length === 0)
60
- return `The address needs at least one part, e.g. “/posts/:${param}”.`;
61
- if (segments.some((segment) => segment === ':'))
62
- return 'A “:” part needs a name after it.';
63
- const params = segments.filter((segment) => segment.startsWith(':'));
64
- if (params.length === 0) {
65
- return `The address needs a “:${param}” part — that's where each entry's own address goes.`;
66
- }
67
- if (params.length > 1 || params[0] !== `:${param}`) {
68
- return `Use exactly one “:${param}” part so every entry gets its own address.`;
69
- }
70
- return undefined;
71
- }
72
- //# sourceMappingURL=routing-store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routing-store.js","sourceRoot":"","sources":["../../../src/lib/routing/routing-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAG5D;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,2EAA2E;AAC3E,MAAM,UAAU,eAAe,CAAC,YAAoB;IAClD,OAAO,kBAAkB,YAAY,EAAE,CAAA;AACzC,CAAC;AAiBD,2DAA2D;AAC3D,MAAM,UAAU,kBAAkB,CAAC,IAAuB;IACxD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,CAAA;IAClC,OAAO,iBAAiB,CAAC,KAAK,CAAC;QAC7B,EAAE,EAAE,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC;QACtC,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,IAAI,KAAK,EAAE,EAAE;QAC5D,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9D,CAAC,CAAA;AACJ,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,iBAAiB,CAAC,KAAkB;IAClD,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAClD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAA;IACxD,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;AACvF,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,gBAAgB,CAC9B,MAA8B,EAC9B,YAAoB;IAEpB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,YAAY,KAAK,YAAY,CAAC,CAAA;AACxF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,KAAK,GAAG,MAAM;IAClE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,kCAAkC,CAAA;IACvE,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC3E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,sDAAsD,KAAK,IAAI,CAAA;IACjG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,GAAG,CAAC;QAAE,OAAO,mCAAmC,CAAA;IAC3F,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAA;IACpE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,yBAAyB,KAAK,sDAAsD,CAAA;IAC7F,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,EAAE,EAAE,CAAC;QACnD,OAAO,qBAAqB,KAAK,6CAA6C,CAAA;IAChF,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC","sourcesContent":["import { routeRecordSchema } from '@elytracms/core/cms-core'\nimport type { RouteRecord } from '@elytracms/core/cms-core'\n\n/**\n * Pure template-route helpers for the Routes domain (EC-166, reshaped by\n * EC-187; route persistence retired by EC-207).\n *\n * Routes & redirects are config-sourced (EC-207 \"routes as code\"): they are\n * authored in `elytra.config.ts`, materialized by `composeProject`, and read\n * through `resolveDeploymentRoutes`/`resolveDeploymentRedirects` — never written\n * to or read from the backend. The former `routes`/`redirects` system\n * collections are retired. What survives here are pure functions over the\n * canonical `RouteRecord` schema, useful for authoring/inspecting template\n * routes in config.\n *\n * A template page is one page definition serving *every* document of a\n * collection through a dynamic pattern. It is expressed entirely in the\n * canonical route-record schema: the parameterized `document` ref\n * (`{ collection, id: ':slug' }`) names the collection plus the URL param\n * carrying the document's slug/id — `@elytracms/core/content`'s `resolvePage`\n * substitutes the matched value at request time. After EC-187 there is no\n * `templateId`; a template route is identified purely by its parameterized\n * `document` ref (a `:param` id over a collection). One template route per\n * collection. No new record shape, no parallel store.\n */\n\n/** Deterministic record id: one template route per collection (EC-187). */\nexport function templateRouteId(collectionId: string): string {\n return `route-template-${collectionId}`\n}\n\nexport interface TemplateRouteInit {\n collectionId: string\n /** Dynamic pattern, e.g. `/blog/:slug`. Must capture {@link param}. */\n pattern: string\n /** The URL param carrying the document slug or id. Defaults to `slug`. */\n param?: string\n locale?: string\n}\n\n/** What a template route binds, read back from a stored record. */\nexport interface TemplateRouteBinding {\n collectionId: string\n param: string\n}\n\n/** Build the canonical route record of a template page. */\nexport function buildTemplateRoute(init: TemplateRouteInit): RouteRecord {\n const param = init.param ?? 'slug'\n return routeRecordSchema.parse({\n id: templateRouteId(init.collectionId),\n pattern: init.pattern,\n document: { collection: init.collectionId, id: `:${param}` },\n ...(init.locale !== undefined ? { locale: init.locale } : {}),\n })\n}\n\n/** The collection + param a route record templates over, if it is one. */\nexport function templateBindingOf(route: RouteRecord): TemplateRouteBinding | undefined {\n if (route.document === undefined) return undefined\n if (!route.document.id.startsWith(':')) return undefined\n return { collectionId: route.document.collection, param: route.document.id.slice(1) }\n}\n\n/** The template route serving a collection, if registered (EC-187). */\nexport function templateRouteFor(\n routes: readonly RouteRecord[],\n collectionId: string,\n): RouteRecord | undefined {\n return routes.find((route) => templateBindingOf(route)?.collectionId === collectionId)\n}\n\n/**\n * Plain-language validation of a template pattern: it must be a real dynamic\n * pattern that captures the document param exactly once. Returns `undefined`\n * when the pattern is usable.\n */\nexport function templatePatternError(pattern: string, param = 'slug'): string | undefined {\n if (!pattern.startsWith('/')) return 'The address must start with “/”.'\n const segments = pattern.split('/').filter((segment) => segment.length > 0)\n if (segments.length === 0) return `The address needs at least one part, e.g. “/posts/:${param}”.`\n if (segments.some((segment) => segment === ':')) return 'A “:” part needs a name after it.'\n const params = segments.filter((segment) => segment.startsWith(':'))\n if (params.length === 0) {\n return `The address needs a “:${param}” part — that's where each entry's own address goes.`\n }\n if (params.length > 1 || params[0] !== `:${param}`) {\n return `Use exactly one “:${param}” part so every entry gets its own address.`\n }\n return undefined\n}\n"]}
@@ -1,82 +0,0 @@
1
- import type { ComponentNode, Layout, ProjectGraph } from '@elytracms/core/project-graph';
2
- /**
3
- * Builder-local WORKING GRAPH (EC-187).
4
- *
5
- * The canonical {@link ProjectGraph} is now LAYOUTS-ONLY — a page is a document
6
- * in the `page` collection (its `body` is a composition field value). But the
7
- * legacy `/builder` editor and the composition-field editor are *node-tree*
8
- * editors: they edit a single root-bearing surface with undo/redo, selection,
9
- * and the same structural edit ops. So the builder store keeps its own
10
- * root-bearing working type, decoupled from the page-less canonical schema.
11
- *
12
- * A `WorkingGraph` is a `ProjectGraph` (layouts + metadata) PLUS a `pages`
13
- * array of {@link WorkingPage} — exactly the shape the reducer/history/edit ops
14
- * have always operated on. It NEVER persists in this shape: page-body edits lift
15
- * into a CMS document (the composition-field editor), and layout edits persist
16
- * through the canonical layouts-only `graph.save`. {@link toProjectGraph} drops
17
- * the pages to produce the canonical graph when one is needed.
18
- */
19
- /**
20
- * Per-page SEO block (EC-171, legacy `/builder` chrome). The canonical
21
- * `PageSeo` shape lived in `@elytracms/core/project-graph` and was deleted with the
22
- * page node (EC-187); page SEO now lives on the `page` collection document's
23
- * flat `seo*` fields. The legacy page-SEO panel keeps editing this local block
24
- * so it stays compiling/tested until `/builder` is retired.
25
- */
26
- export interface WorkingPageSeo {
27
- title?: string;
28
- description?: string;
29
- ogTitle?: string;
30
- ogImage?: string;
31
- noindex?: boolean;
32
- }
33
- /** A page in the builder's working state — a root-bearing editable surface. */
34
- export interface WorkingPage {
35
- id: string;
36
- name: string;
37
- /** Optional shared layout wrapper id (canvas preview only). */
38
- layoutId?: string;
39
- /** Root node of the page's component tree (the edited surface). */
40
- root: ComponentNode;
41
- /** Legacy per-page SEO block (EC-171). */
42
- seo?: WorkingPageSeo;
43
- }
44
- /** The builder's internal working graph: the canonical layouts-only graph + editable pages. */
45
- export interface WorkingGraph {
46
- id: string;
47
- schemaVersion: number;
48
- metadata?: {
49
- name?: string;
50
- };
51
- settingsRef?: string;
52
- layouts: Layout[];
53
- pages: WorkingPage[];
54
- }
55
- /**
56
- * Lift a (layouts-only) canonical {@link ProjectGraph} into a {@link WorkingGraph}
57
- * with a single editable page, so the legacy builder canvas has a root to edit.
58
- * The page root is an empty Stack the editor fills; the page selects the first
59
- * layout for canvas preview (if any).
60
- */
61
- export declare function toWorkingGraph(graph: ProjectGraph): WorkingGraph;
62
- /** Drop the editable pages to produce the canonical (layouts-only) {@link ProjectGraph}. */
63
- export declare function toProjectGraph(graph: WorkingGraph): ProjectGraph;
64
- /** Build a working graph that wraps one composition value in a single editable page. */
65
- export declare function workingGraphFromPage(page: WorkingPage, layouts?: Layout[]): WorkingGraph;
66
- /**
67
- * Normalize every editable surface of a working graph — each page root AND
68
- * each layout root — via `normalizeContainers`. Mirrors the OLD
69
- * `normalizeProjectGraph` (which normalized pages too, before EC-187 made the
70
- * canonical graph layouts-only). Identity-preserving: returns the same graph
71
- * reference when nothing changed so undo histories can detect no-ops by
72
- * reference.
73
- */
74
- export declare function normalizeWorkingGraph(graph: WorkingGraph): WorkingGraph;
75
- /** Strip empty fields; an all-empty block becomes `undefined` (clear the block). */
76
- export declare function cleanWorkingPageSeo(seo: WorkingPageSeo): WorkingPageSeo | undefined;
77
- /**
78
- * Apply a (cleaned) SEO block to a page in the working graph. Identity on
79
- * no-ops — callers dispatch only when this returns a new graph. An `undefined`
80
- * block removes `seo` from the page entity entirely.
81
- */
82
- export declare function setWorkingPageSeo(graph: WorkingGraph, pageId: string, seo: WorkingPageSeo | undefined): WorkingGraph;
@@ -1,113 +0,0 @@
1
- import { normalizeContainers, PROJECT_GRAPH_SCHEMA_VERSION } from '@elytracms/core/project-graph';
2
- const SYNTH_PAGE_ID = 'page.working';
3
- /**
4
- * Lift a (layouts-only) canonical {@link ProjectGraph} into a {@link WorkingGraph}
5
- * with a single editable page, so the legacy builder canvas has a root to edit.
6
- * The page root is an empty Stack the editor fills; the page selects the first
7
- * layout for canvas preview (if any).
8
- */
9
- export function toWorkingGraph(graph) {
10
- return {
11
- ...graph,
12
- pages: [
13
- {
14
- id: SYNTH_PAGE_ID,
15
- name: graph.metadata?.name ?? 'Page',
16
- ...(graph.layouts[0] ? { layoutId: graph.layouts[0].id } : {}),
17
- root: { id: 'working.root', componentId: 'base.primitives.Stack', slots: { children: [] } },
18
- },
19
- ],
20
- };
21
- }
22
- /** Drop the editable pages to produce the canonical (layouts-only) {@link ProjectGraph}. */
23
- export function toProjectGraph(graph) {
24
- const { pages: _pages, ...canonical } = graph;
25
- return canonical;
26
- }
27
- /** Build a working graph that wraps one composition value in a single editable page. */
28
- export function workingGraphFromPage(page, layouts = []) {
29
- return {
30
- id: 'working',
31
- schemaVersion: PROJECT_GRAPH_SCHEMA_VERSION,
32
- layouts,
33
- pages: [page],
34
- };
35
- }
36
- /**
37
- * Normalize every editable surface of a working graph — each page root AND
38
- * each layout root — via `normalizeContainers`. Mirrors the OLD
39
- * `normalizeProjectGraph` (which normalized pages too, before EC-187 made the
40
- * canonical graph layouts-only). Identity-preserving: returns the same graph
41
- * reference when nothing changed so undo histories can detect no-ops by
42
- * reference.
43
- */
44
- export function normalizeWorkingGraph(graph) {
45
- let changed = false;
46
- const pages = graph.pages.map((page) => {
47
- const root = normalizeContainers(page.root);
48
- if (root !== page.root)
49
- changed = true;
50
- return root === page.root ? page : { ...page, root };
51
- });
52
- const layouts = graph.layouts.map((layout) => {
53
- const root = normalizeContainers(layout.root);
54
- if (root !== layout.root)
55
- changed = true;
56
- return root === layout.root ? layout : { ...layout, root };
57
- });
58
- return changed ? { ...graph, pages, layouts } : graph;
59
- }
60
- // ---- Legacy page SEO (EC-171) ----------------------------------------------
61
- //
62
- // The canonical `setPageSeo`/`cleanPageSeo`/`PageSeo` were deleted with the
63
- // page node (EC-187). These local helpers mirror the old behavior over the
64
- // working graph's per-page `seo` block so the legacy SEO panel keeps working.
65
- /** Strip empty fields; an all-empty block becomes `undefined` (clear the block). */
66
- export function cleanWorkingPageSeo(seo) {
67
- const trimmed = (value) => {
68
- const next = value?.trim();
69
- return next ? next : undefined;
70
- };
71
- const next = {};
72
- const title = trimmed(seo.title);
73
- const description = trimmed(seo.description);
74
- const ogTitle = trimmed(seo.ogTitle);
75
- const ogImage = trimmed(seo.ogImage);
76
- if (title !== undefined)
77
- next.title = title;
78
- if (description !== undefined)
79
- next.description = description;
80
- if (ogTitle !== undefined)
81
- next.ogTitle = ogTitle;
82
- if (ogImage !== undefined)
83
- next.ogImage = ogImage;
84
- if (seo.noindex)
85
- next.noindex = true;
86
- return Object.keys(next).length > 0 ? next : undefined;
87
- }
88
- /**
89
- * Apply a (cleaned) SEO block to a page in the working graph. Identity on
90
- * no-ops — callers dispatch only when this returns a new graph. An `undefined`
91
- * block removes `seo` from the page entity entirely.
92
- */
93
- export function setWorkingPageSeo(graph, pageId, seo) {
94
- const page = graph.pages.find((p) => p.id === pageId);
95
- if (!page)
96
- return graph;
97
- const sameBlock = JSON.stringify(page.seo ?? null) === JSON.stringify(seo ?? null);
98
- if (sameBlock)
99
- return graph;
100
- return {
101
- ...graph,
102
- pages: graph.pages.map((p) => {
103
- if (p.id !== pageId)
104
- return p;
105
- if (seo === undefined) {
106
- const { seo: _drop, ...rest } = p;
107
- return rest;
108
- }
109
- return { ...p, seo };
110
- }),
111
- };
112
- }
113
- //# sourceMappingURL=working-graph.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"working-graph.js","sourceRoot":"","sources":["../../src/lib/working-graph.ts"],"names":[],"mappings":"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","sourcesContent":["import { normalizeContainers, PROJECT_GRAPH_SCHEMA_VERSION } from '@elytracms/core/project-graph'\nimport type { ComponentNode, Layout, ProjectGraph } from '@elytracms/core/project-graph'\n\n/**\n * Builder-local WORKING GRAPH (EC-187).\n *\n * The canonical {@link ProjectGraph} is now LAYOUTS-ONLY — a page is a document\n * in the `page` collection (its `body` is a composition field value). But the\n * legacy `/builder` editor and the composition-field editor are *node-tree*\n * editors: they edit a single root-bearing surface with undo/redo, selection,\n * and the same structural edit ops. So the builder store keeps its own\n * root-bearing working type, decoupled from the page-less canonical schema.\n *\n * A `WorkingGraph` is a `ProjectGraph` (layouts + metadata) PLUS a `pages`\n * array of {@link WorkingPage} — exactly the shape the reducer/history/edit ops\n * have always operated on. It NEVER persists in this shape: page-body edits lift\n * into a CMS document (the composition-field editor), and layout edits persist\n * through the canonical layouts-only `graph.save`. {@link toProjectGraph} drops\n * the pages to produce the canonical graph when one is needed.\n */\n\n/**\n * Per-page SEO block (EC-171, legacy `/builder` chrome). The canonical\n * `PageSeo` shape lived in `@elytracms/core/project-graph` and was deleted with the\n * page node (EC-187); page SEO now lives on the `page` collection document's\n * flat `seo*` fields. The legacy page-SEO panel keeps editing this local block\n * so it stays compiling/tested until `/builder` is retired.\n */\nexport interface WorkingPageSeo {\n title?: string\n description?: string\n ogTitle?: string\n ogImage?: string\n noindex?: boolean\n}\n\n/** A page in the builder's working state — a root-bearing editable surface. */\nexport interface WorkingPage {\n id: string\n name: string\n /** Optional shared layout wrapper id (canvas preview only). */\n layoutId?: string\n /** Root node of the page's component tree (the edited surface). */\n root: ComponentNode\n /** Legacy per-page SEO block (EC-171). */\n seo?: WorkingPageSeo\n}\n\n/** The builder's internal working graph: the canonical layouts-only graph + editable pages. */\nexport interface WorkingGraph {\n id: string\n schemaVersion: number\n metadata?: { name?: string }\n settingsRef?: string\n layouts: Layout[]\n pages: WorkingPage[]\n}\n\nconst SYNTH_PAGE_ID = 'page.working'\n\n/**\n * Lift a (layouts-only) canonical {@link ProjectGraph} into a {@link WorkingGraph}\n * with a single editable page, so the legacy builder canvas has a root to edit.\n * The page root is an empty Stack the editor fills; the page selects the first\n * layout for canvas preview (if any).\n */\nexport function toWorkingGraph(graph: ProjectGraph): WorkingGraph {\n return {\n ...graph,\n pages: [\n {\n id: SYNTH_PAGE_ID,\n name: graph.metadata?.name ?? 'Page',\n ...(graph.layouts[0] ? { layoutId: graph.layouts[0].id } : {}),\n root: { id: 'working.root', componentId: 'base.primitives.Stack', slots: { children: [] } },\n },\n ],\n }\n}\n\n/** Drop the editable pages to produce the canonical (layouts-only) {@link ProjectGraph}. */\nexport function toProjectGraph(graph: WorkingGraph): ProjectGraph {\n const { pages: _pages, ...canonical } = graph\n return canonical\n}\n\n/** Build a working graph that wraps one composition value in a single editable page. */\nexport function workingGraphFromPage(page: WorkingPage, layouts: Layout[] = []): WorkingGraph {\n return {\n id: 'working',\n schemaVersion: PROJECT_GRAPH_SCHEMA_VERSION,\n layouts,\n pages: [page],\n }\n}\n\n/**\n * Normalize every editable surface of a working graph — each page root AND\n * each layout root — via `normalizeContainers`. Mirrors the OLD\n * `normalizeProjectGraph` (which normalized pages too, before EC-187 made the\n * canonical graph layouts-only). Identity-preserving: returns the same graph\n * reference when nothing changed so undo histories can detect no-ops by\n * reference.\n */\nexport function normalizeWorkingGraph(graph: WorkingGraph): WorkingGraph {\n let changed = false\n const pages = graph.pages.map((page) => {\n const root = normalizeContainers(page.root)\n if (root !== page.root) changed = true\n return root === page.root ? page : { ...page, root }\n })\n const layouts = graph.layouts.map((layout) => {\n const root = normalizeContainers(layout.root)\n if (root !== layout.root) changed = true\n return root === layout.root ? layout : { ...layout, root }\n })\n return changed ? { ...graph, pages, layouts } : graph\n}\n\n// ---- Legacy page SEO (EC-171) ----------------------------------------------\n//\n// The canonical `setPageSeo`/`cleanPageSeo`/`PageSeo` were deleted with the\n// page node (EC-187). These local helpers mirror the old behavior over the\n// working graph's per-page `seo` block so the legacy SEO panel keeps working.\n\n/** Strip empty fields; an all-empty block becomes `undefined` (clear the block). */\nexport function cleanWorkingPageSeo(seo: WorkingPageSeo): WorkingPageSeo | undefined {\n const trimmed = (value: string | undefined): string | undefined => {\n const next = value?.trim()\n return next ? next : undefined\n }\n const next: WorkingPageSeo = {}\n const title = trimmed(seo.title)\n const description = trimmed(seo.description)\n const ogTitle = trimmed(seo.ogTitle)\n const ogImage = trimmed(seo.ogImage)\n if (title !== undefined) next.title = title\n if (description !== undefined) next.description = description\n if (ogTitle !== undefined) next.ogTitle = ogTitle\n if (ogImage !== undefined) next.ogImage = ogImage\n if (seo.noindex) next.noindex = true\n return Object.keys(next).length > 0 ? next : undefined\n}\n\n/**\n * Apply a (cleaned) SEO block to a page in the working graph. Identity on\n * no-ops — callers dispatch only when this returns a new graph. An `undefined`\n * block removes `seo` from the page entity entirely.\n */\nexport function setWorkingPageSeo(\n graph: WorkingGraph,\n pageId: string,\n seo: WorkingPageSeo | undefined,\n): WorkingGraph {\n const page = graph.pages.find((p) => p.id === pageId)\n if (!page) return graph\n const sameBlock = JSON.stringify(page.seo ?? null) === JSON.stringify(seo ?? null)\n if (sameBlock) return graph\n return {\n ...graph,\n pages: graph.pages.map((p) => {\n if (p.id !== pageId) return p\n if (seo === undefined) {\n const { seo: _drop, ...rest } = p\n return rest\n }\n return { ...p, seo }\n }),\n }\n}\n"]}