@elytracms/studio 0.0.93 → 0.0.95

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 (541) hide show
  1. package/convex/analytics-cost.test.ts +817 -0
  2. package/convex/asset-alt-migration.test.ts +2 -2
  3. package/convex/asset-meta-patch.test.ts +218 -0
  4. package/convex/asset-replace-delete-race.test.ts +127 -0
  5. package/convex/assets.ts +27 -2
  6. package/convex/auth.ts +5 -2
  7. package/convex/authority.ts +35 -11
  8. package/convex/contract-parity.test.ts +7 -0
  9. package/convex/delivery-redirects.test.ts +167 -0
  10. package/convex/delivery.ts +23 -10
  11. package/convex/guard.ts +9 -7
  12. package/convex/http-routes.test.ts +18 -8
  13. package/convex/http.ts +23 -17
  14. package/convex/ingest.test.ts +326 -0
  15. package/convex/ingest.ts +281 -0
  16. package/convex/invites.ts +13 -5
  17. package/convex/members.ts +10 -4
  18. package/convex/rail-write-parity.test.ts +6 -6
  19. package/convex/record-functions.ts +325 -0
  20. package/convex/records.test.ts +156 -0
  21. package/convex/redirect-migration.test.ts +205 -0
  22. package/convex/redirect-revalidate.test.ts +5 -1
  23. package/convex/redirects.ts +120 -79
  24. package/convex/role-policy.test.ts +315 -0
  25. package/convex/roles.ts +83 -0
  26. package/convex/schema.ts +36 -0
  27. package/convex/triggers.ts +21 -1
  28. package/dist/addon.d.ts +71 -0
  29. package/dist/addon.js +67 -0
  30. package/dist/addon.js.map +1 -0
  31. package/dist/components/account/account-settings.js +2 -2
  32. package/dist/components/account/account-settings.js.map +1 -1
  33. package/dist/components/account/credential-panel.js +2 -2
  34. package/dist/components/account/credential-panel.js.map +1 -1
  35. package/dist/components/account/self-account-schema.d.ts +6 -15
  36. package/dist/components/account/self-account-schema.js +52 -34
  37. package/dist/components/account/self-account-schema.js.map +1 -1
  38. package/dist/components/account/self-account-view-source.d.ts +1 -1
  39. package/dist/components/account/self-account-view-source.js +6 -4
  40. package/dist/components/account/self-account-view-source.js.map +1 -1
  41. package/dist/components/ai/ai-chat-panel-lazy.js +1 -1
  42. package/dist/components/ai/ai-chat-panel-lazy.js.map +1 -1
  43. package/dist/components/ai/ai-chat-panel.js +6 -6
  44. package/dist/components/ai/ai-chat-panel.js.map +1 -1
  45. package/dist/components/ai/ai-cms-panel.js +2 -2
  46. package/dist/components/ai/ai-cms-panel.js.map +1 -1
  47. package/dist/components/ai/ai-panel-toggle.js +4 -4
  48. package/dist/components/ai/ai-panel-toggle.js.map +1 -1
  49. package/dist/components/ai/chat-ui.js +2 -2
  50. package/dist/components/ai/chat-ui.js.map +1 -1
  51. package/dist/components/ai/proposal-card.d.ts +2 -2
  52. package/dist/components/ai/proposal-card.js +2 -2
  53. package/dist/components/ai/proposal-card.js.map +1 -1
  54. package/dist/components/ai/proposal-issues.js +2 -2
  55. package/dist/components/ai/proposal-issues.js.map +1 -1
  56. package/dist/components/ai/translate-document-action.js +2 -2
  57. package/dist/components/ai/translate-document-action.js.map +1 -1
  58. package/dist/components/ai/translate-document-dialog.js +6 -6
  59. package/dist/components/ai/translate-document-dialog.js.map +1 -1
  60. package/dist/components/ai/translate-skipped.d.ts +1 -1
  61. package/dist/components/ai/translate-skipped.js +2 -2
  62. package/dist/components/ai/translate-skipped.js.map +1 -1
  63. package/dist/components/app-views/default-modules.d.ts +50 -2
  64. package/dist/components/app-views/default-modules.js +65 -20
  65. package/dist/components/app-views/default-modules.js.map +1 -1
  66. package/dist/components/app-views/module.d.ts +53 -3
  67. package/dist/components/app-views/module.js +14 -7
  68. package/dist/components/app-views/module.js.map +1 -1
  69. package/dist/components/app-views/sidebar.js +1 -1
  70. package/dist/components/app-views/sidebar.js.map +1 -1
  71. package/dist/components/app-views/studio-config.d.ts +11 -2
  72. package/dist/components/app-views/studio-config.js.map +1 -1
  73. package/dist/components/assets/asset-detail.js +28 -13
  74. package/dist/components/assets/asset-detail.js.map +1 -1
  75. package/dist/components/assets/asset-grid.js +2 -2
  76. package/dist/components/assets/asset-grid.js.map +1 -1
  77. package/dist/components/assets/asset-locale.d.ts +9 -0
  78. package/dist/components/assets/asset-locale.js +16 -0
  79. package/dist/components/assets/asset-locale.js.map +1 -0
  80. package/dist/components/assets/asset-meta-label.d.ts +12 -0
  81. package/dist/components/assets/asset-meta-label.js +15 -0
  82. package/dist/components/assets/asset-meta-label.js.map +1 -0
  83. package/dist/components/assets/asset-metadata.d.ts +69 -15
  84. package/dist/components/assets/asset-metadata.js +99 -11
  85. package/dist/components/assets/asset-metadata.js.map +1 -1
  86. package/dist/components/assets/asset-search.js +8 -2
  87. package/dist/components/assets/asset-search.js.map +1 -1
  88. package/dist/components/assets/asset-thumb.js +9 -5
  89. package/dist/components/assets/asset-thumb.js.map +1 -1
  90. package/dist/components/assets/assets-collection-view-source.d.ts +25 -11
  91. package/dist/components/assets/assets-collection-view-source.js +78 -26
  92. package/dist/components/assets/assets-collection-view-source.js.map +1 -1
  93. package/dist/components/assets/assets-module.js +1 -1
  94. package/dist/components/assets/assets-module.js.map +1 -1
  95. package/dist/components/assets/assets-store.d.ts +2 -2
  96. package/dist/components/assets/assets-store.js +22 -9
  97. package/dist/components/assets/assets-store.js.map +1 -1
  98. package/dist/components/assets/assets-view-preference.js +1 -1
  99. package/dist/components/assets/assets-view-preference.js.map +1 -1
  100. package/dist/components/assets/replace-file.js +1 -1
  101. package/dist/components/assets/replace-file.js.map +1 -1
  102. package/dist/components/auth-context.d.ts +1 -1
  103. package/dist/components/auth-context.js +6 -6
  104. package/dist/components/auth-context.js.map +1 -1
  105. package/dist/components/builder/blocks-model.d.ts +1 -1
  106. package/dist/components/builder/blocks-model.js +3 -3
  107. package/dist/components/builder/blocks-model.js.map +1 -1
  108. package/dist/components/builder/blocks-panel.d.ts +1 -1
  109. package/dist/components/builder/blocks-panel.js +4 -4
  110. package/dist/components/builder/blocks-panel.js.map +1 -1
  111. package/dist/components/builder/builder-store.d.ts +21 -0
  112. package/dist/components/builder/builder-store.js +24 -2
  113. package/dist/components/builder/builder-store.js.map +1 -1
  114. package/dist/components/builder/canvas-breakpoints.js +1 -1
  115. package/dist/components/builder/canvas-breakpoints.js.map +1 -1
  116. package/dist/components/builder/canvas-commit-boundary.d.ts +22 -0
  117. package/dist/components/builder/canvas-commit-boundary.js +27 -0
  118. package/dist/components/builder/canvas-commit-boundary.js.map +1 -0
  119. package/dist/components/builder/canvas-dnd.d.ts +2 -2
  120. package/dist/components/builder/canvas-dnd.js +1 -1
  121. package/dist/components/builder/canvas-dnd.js.map +1 -1
  122. package/dist/components/builder/canvas-inline-editing.d.ts +1 -1
  123. package/dist/components/builder/canvas-inline-editing.js.map +1 -1
  124. package/dist/components/builder/canvas-overlay-geometry.d.ts +1 -1
  125. package/dist/components/builder/canvas-overlay-geometry.js.map +1 -1
  126. package/dist/components/builder/canvas-rebase.d.ts +77 -0
  127. package/dist/components/builder/canvas-rebase.js +169 -0
  128. package/dist/components/builder/canvas-rebase.js.map +1 -0
  129. package/dist/components/builder/canvas-render-context.d.ts +7 -4
  130. package/dist/components/builder/canvas-render-context.js +21 -13
  131. package/dist/components/builder/canvas-render-context.js.map +1 -1
  132. package/dist/components/builder/canvas-theme-notice.js +2 -2
  133. package/dist/components/builder/canvas-theme-notice.js.map +1 -1
  134. package/dist/components/builder/canvas.js +3 -3
  135. package/dist/components/builder/canvas.js.map +1 -1
  136. package/dist/components/builder/clipboard-actions.d.ts +2 -2
  137. package/dist/components/builder/clipboard-actions.js +4 -4
  138. package/dist/components/builder/clipboard-actions.js.map +1 -1
  139. package/dist/components/builder/composition-field-editor-lazy.js +1 -1
  140. package/dist/components/builder/composition-field-editor-lazy.js.map +1 -1
  141. package/dist/components/builder/composition-field-editor.d.ts +21 -3
  142. package/dist/components/builder/composition-field-editor.js +48 -30
  143. package/dist/components/builder/composition-field-editor.js.map +1 -1
  144. package/dist/components/builder/drag-session.d.ts +1 -1
  145. package/dist/components/builder/drag-session.js.map +1 -1
  146. package/dist/components/builder/fixture-thumbnail.js +1 -1
  147. package/dist/components/builder/fixture-thumbnail.js.map +1 -1
  148. package/dist/components/builder/insert-context.d.ts +1 -1
  149. package/dist/components/builder/insert-context.js +3 -3
  150. package/dist/components/builder/insert-context.js.map +1 -1
  151. package/dist/components/builder/layout-inspector.js +1 -1
  152. package/dist/components/builder/layout-inspector.js.map +1 -1
  153. package/dist/components/builder/node-factory.js +15 -3
  154. package/dist/components/builder/node-factory.js.map +1 -1
  155. package/dist/components/builder/node-title.js +1 -1
  156. package/dist/components/builder/node-title.js.map +1 -1
  157. package/dist/components/builder/page-tree.d.ts +1 -1
  158. package/dist/components/builder/page-tree.js +5 -5
  159. package/dist/components/builder/page-tree.js.map +1 -1
  160. package/dist/components/builder/placement-refusal.js +3 -3
  161. package/dist/components/builder/placement-refusal.js.map +1 -1
  162. package/dist/components/builder/property-inspector.js +7 -5
  163. package/dist/components/builder/property-inspector.js.map +1 -1
  164. package/dist/components/builder/reuse-context.js +4 -4
  165. package/dist/components/builder/reuse-context.js.map +1 -1
  166. package/dist/components/builder/reuse.js +1 -1
  167. package/dist/components/builder/reuse.js.map +1 -1
  168. package/dist/components/builder/rich-text-toolbar.js +1 -1
  169. package/dist/components/builder/rich-text-toolbar.js.map +1 -1
  170. package/dist/components/builder/run-inspector.js +11 -7
  171. package/dist/components/builder/run-inspector.js.map +1 -1
  172. package/dist/components/builder/selection-overlay.js +3 -3
  173. package/dist/components/builder/selection-overlay.js.map +1 -1
  174. package/dist/components/builder/spacing-handles.d.ts +2 -2
  175. package/dist/components/builder/spacing-handles.js +3 -3
  176. package/dist/components/builder/spacing-handles.js.map +1 -1
  177. package/dist/components/cms/asset-field.d.ts +5 -2
  178. package/dist/components/cms/asset-field.js +36 -19
  179. package/dist/components/cms/asset-field.js.map +1 -1
  180. package/dist/components/cms/asset-picker.js +5 -3
  181. package/dist/components/cms/asset-picker.js.map +1 -1
  182. package/dist/components/cms/bulk-actions.d.ts +1 -1
  183. package/dist/components/cms/bulk-actions.js +2 -2
  184. package/dist/components/cms/bulk-actions.js.map +1 -1
  185. package/dist/components/cms/bulk-bar.d.ts +2 -2
  186. package/dist/components/cms/bulk-bar.js +2 -2
  187. package/dist/components/cms/bulk-bar.js.map +1 -1
  188. package/dist/components/cms/canvas-commit.d.ts +56 -0
  189. package/dist/components/cms/canvas-commit.js +35 -0
  190. package/dist/components/cms/canvas-commit.js.map +1 -0
  191. package/dist/components/cms/cell-edit.d.ts +1 -1
  192. package/dist/components/cms/cell-edit.js +1 -1
  193. package/dist/components/cms/cell-edit.js.map +1 -1
  194. package/dist/components/cms/cell.d.ts +1 -1
  195. package/dist/components/cms/cell.js +3 -3
  196. package/dist/components/cms/cell.js.map +1 -1
  197. package/dist/components/cms/cms-index.js +2 -2
  198. package/dist/components/cms/cms-index.js.map +1 -1
  199. package/dist/components/cms/cms-labels.js +2 -2
  200. package/dist/components/cms/cms-labels.js.map +1 -1
  201. package/dist/components/cms/cms-store.d.ts +2 -2
  202. package/dist/components/cms/cms-store.js +10 -10
  203. package/dist/components/cms/cms-store.js.map +1 -1
  204. package/dist/components/cms/collection-table.js +30 -14
  205. package/dist/components/cms/collection-table.js.map +1 -1
  206. package/dist/components/cms/commit-policy.d.ts +6 -2
  207. package/dist/components/cms/commit-policy.js +1 -1
  208. package/dist/components/cms/commit-policy.js.map +1 -1
  209. package/dist/components/cms/detail-editor.d.ts +5 -2
  210. package/dist/components/cms/detail-editor.js +31 -15
  211. package/dist/components/cms/detail-editor.js.map +1 -1
  212. package/dist/components/cms/details-pane.js +1 -1
  213. package/dist/components/cms/details-pane.js.map +1 -1
  214. package/dist/components/cms/doc-state.js +1 -1
  215. package/dist/components/cms/doc-state.js.map +1 -1
  216. package/dist/components/cms/document-diff-view.js +5 -5
  217. package/dist/components/cms/document-diff-view.js.map +1 -1
  218. package/dist/components/cms/document-editor-context.js +1 -1
  219. package/dist/components/cms/document-editor-context.js.map +1 -1
  220. package/dist/components/cms/document-staging.js +1 -1
  221. package/dist/components/cms/document-staging.js.map +1 -1
  222. package/dist/components/cms/document-url-path.js +2 -2
  223. package/dist/components/cms/document-url-path.js.map +1 -1
  224. package/dist/components/cms/duplicate-document.d.ts +1 -1
  225. package/dist/components/cms/duplicate-document.js.map +1 -1
  226. package/dist/components/cms/editable-cell.js +3 -3
  227. package/dist/components/cms/editable-cell.js.map +1 -1
  228. package/dist/components/cms/field-collaboration.d.ts +1 -1
  229. package/dist/components/cms/field-collaboration.js +1 -1
  230. package/dist/components/cms/field-collaboration.js.map +1 -1
  231. package/dist/components/cms/field-connection.d.ts +1 -1
  232. package/dist/components/cms/field-connection.js +2 -2
  233. package/dist/components/cms/field-connection.js.map +1 -1
  234. package/dist/components/cms/field-control-lib.js +1 -1
  235. package/dist/components/cms/field-control-lib.js.map +1 -1
  236. package/dist/components/cms/field-control.js +4 -4
  237. package/dist/components/cms/field-control.js.map +1 -1
  238. package/dist/components/cms/field-renderer.d.ts +1 -1
  239. package/dist/components/cms/field-renderer.js +2 -2
  240. package/dist/components/cms/field-renderer.js.map +1 -1
  241. package/dist/components/cms/filter-builder.d.ts +1 -1
  242. package/dist/components/cms/filter-builder.js +3 -3
  243. package/dist/components/cms/filter-builder.js.map +1 -1
  244. package/dist/components/cms/gate-validation.js +1 -1
  245. package/dist/components/cms/gate-validation.js.map +1 -1
  246. package/dist/components/cms/import-export.js +2 -2
  247. package/dist/components/cms/import-export.js.map +1 -1
  248. package/dist/components/cms/issue-copy.js +1 -1
  249. package/dist/components/cms/issue-copy.js.map +1 -1
  250. package/dist/components/cms/issues-pane.js +3 -3
  251. package/dist/components/cms/issues-pane.js.map +1 -1
  252. package/dist/components/cms/object-array-field.js +2 -2
  253. package/dist/components/cms/object-array-field.js.map +1 -1
  254. package/dist/components/cms/prop-fields.js +2 -2
  255. package/dist/components/cms/prop-fields.js.map +1 -1
  256. package/dist/components/cms/reference-confirm.d.ts +1 -1
  257. package/dist/components/cms/reference-confirm.js +2 -2
  258. package/dist/components/cms/reference-confirm.js.map +1 -1
  259. package/dist/components/cms/relation-picker.js +2 -2
  260. package/dist/components/cms/relation-picker.js.map +1 -1
  261. package/dist/components/cms/rich-text/block-style.js +1 -1
  262. package/dist/components/cms/rich-text/block-style.js.map +1 -1
  263. package/dist/components/cms/rich-text/component-embed.js +4 -4
  264. package/dist/components/cms/rich-text/component-embed.js.map +1 -1
  265. package/dist/components/cms/rich-text/editor.js +3 -3
  266. package/dist/components/cms/rich-text/editor.js.map +1 -1
  267. package/dist/components/cms/rich-text/embed-picker.js +3 -3
  268. package/dist/components/cms/rich-text/embed-picker.js.map +1 -1
  269. package/dist/components/cms/rich-text/embed-props.js +3 -3
  270. package/dist/components/cms/rich-text/embed-props.js.map +1 -1
  271. package/dist/components/cms/rich-text/extensions.js +1 -1
  272. package/dist/components/cms/rich-text/extensions.js.map +1 -1
  273. package/dist/components/cms/rich-text/font-size-control.d.ts +1 -1
  274. package/dist/components/cms/rich-text/font-size-control.js +2 -2
  275. package/dist/components/cms/rich-text/font-size-control.js.map +1 -1
  276. package/dist/components/cms/rich-text/lazy.js +1 -1
  277. package/dist/components/cms/rich-text/lazy.js.map +1 -1
  278. package/dist/components/cms/rich-text/link-control.js +2 -2
  279. package/dist/components/cms/rich-text/link-control.js.map +1 -1
  280. package/dist/components/cms/rich-text/slash-command.js +3 -3
  281. package/dist/components/cms/rich-text/slash-command.js.map +1 -1
  282. package/dist/components/cms/rich-text/toolbar.js +1 -1
  283. package/dist/components/cms/rich-text/toolbar.js.map +1 -1
  284. package/dist/components/cms/rich-text/unknown-node.js +2 -2
  285. package/dist/components/cms/rich-text/unknown-node.js.map +1 -1
  286. package/dist/components/cms/rich-text-preview.js +2 -2
  287. package/dist/components/cms/rich-text-preview.js.map +1 -1
  288. package/dist/components/cms/row-actions.d.ts +1 -1
  289. package/dist/components/cms/row-actions.js.map +1 -1
  290. package/dist/components/cms/scalar-value-editor.d.ts +1 -1
  291. package/dist/components/cms/scalar-value-editor.js +2 -2
  292. package/dist/components/cms/scalar-value-editor.js.map +1 -1
  293. package/dist/components/cms/use-discard-controller.d.ts +1 -1
  294. package/dist/components/cms/use-discard-controller.js +1 -1
  295. package/dist/components/cms/use-discard-controller.js.map +1 -1
  296. package/dist/components/cms/use-document-draft.d.ts +69 -5
  297. package/dist/components/cms/use-document-draft.js +118 -34
  298. package/dist/components/cms/use-document-draft.js.map +1 -1
  299. package/dist/components/cms/use-document-versions.js +1 -1
  300. package/dist/components/cms/use-document-versions.js.map +1 -1
  301. package/dist/components/cms/use-field-focus.d.ts +1 -1
  302. package/dist/components/cms/use-field-focus.js +2 -2
  303. package/dist/components/cms/use-field-focus.js.map +1 -1
  304. package/dist/components/cms/use-live-url.d.ts +7 -2
  305. package/dist/components/cms/use-live-url.js +15 -12
  306. package/dist/components/cms/use-live-url.js.map +1 -1
  307. package/dist/components/cms/use-publish-controller.d.ts +1 -1
  308. package/dist/components/cms/use-publish-controller.js +1 -1
  309. package/dist/components/cms/use-publish-controller.js.map +1 -1
  310. package/dist/components/cms/use-published-perspective.d.ts +1 -1
  311. package/dist/components/cms/use-published-perspective.js.map +1 -1
  312. package/dist/components/cms/use-restore-version.d.ts +1 -1
  313. package/dist/components/cms/use-restore-version.js +1 -1
  314. package/dist/components/cms/use-restore-version.js.map +1 -1
  315. package/dist/components/cms/version-compare-lazy.js +1 -1
  316. package/dist/components/cms/version-compare-lazy.js.map +1 -1
  317. package/dist/components/cms/version-compare.js +1 -1
  318. package/dist/components/cms/version-compare.js.map +1 -1
  319. package/dist/components/cms/versions-pane.js +3 -3
  320. package/dist/components/cms/versions-pane.js.map +1 -1
  321. package/dist/components/cms/view-bar.js +3 -3
  322. package/dist/components/cms/view-bar.js.map +1 -1
  323. package/dist/components/collection-view/cms-collection-view-source.d.ts +1 -1
  324. package/dist/components/collection-view/cms-collection-view-source.js +11 -7
  325. package/dist/components/collection-view/cms-collection-view-source.js.map +1 -1
  326. package/dist/components/collection-view/collection-view-context.d.ts +1 -1
  327. package/dist/components/collection-view/collection-view-context.js +1 -1
  328. package/dist/components/collection-view/collection-view-context.js.map +1 -1
  329. package/dist/components/collection-view/collection-view-surface.d.ts +13 -0
  330. package/dist/components/collection-view/collection-view-surface.js +18 -0
  331. package/dist/components/collection-view/collection-view-surface.js.map +1 -0
  332. package/dist/components/components/component-detail.js +10 -10
  333. package/dist/components/components/component-detail.js.map +1 -1
  334. package/dist/components/components/component-preview.d.ts +2 -2
  335. package/dist/components/components/component-preview.js +5 -5
  336. package/dist/components/components/component-preview.js.map +1 -1
  337. package/dist/components/components/component-status.d.ts +1 -1
  338. package/dist/components/components/component-status.js +1 -1
  339. package/dist/components/components/component-status.js.map +1 -1
  340. package/dist/components/components/components-index.js +2 -2
  341. package/dist/components/components/components-index.js.map +1 -1
  342. package/dist/components/components/field-inspector.js +1 -1
  343. package/dist/components/components/field-inspector.js.map +1 -1
  344. package/dist/components/components/registry-browser.js +3 -3
  345. package/dist/components/components/registry-browser.js.map +1 -1
  346. package/dist/components/components/taxonomy.d.ts +1 -1
  347. package/dist/components/components/taxonomy.js.map +1 -1
  348. package/dist/components/components/transfer-dialog.js +3 -3
  349. package/dist/components/components/transfer-dialog.js.map +1 -1
  350. package/dist/components/current-user-menu.js +1 -1
  351. package/dist/components/current-user-menu.js.map +1 -1
  352. package/dist/components/delivery-health-banner.js +2 -2
  353. package/dist/components/delivery-health-banner.js.map +1 -1
  354. package/dist/components/deployment-setup-gate.js +13 -4
  355. package/dist/components/deployment-setup-gate.js.map +1 -1
  356. package/dist/components/dev-login-badge.js +2 -2
  357. package/dist/components/dev-login-badge.js.map +1 -1
  358. package/dist/components/guards.js +1 -1
  359. package/dist/components/guards.js.map +1 -1
  360. package/dist/components/inspector/document-panes.d.ts +54 -0
  361. package/dist/components/inspector/document-panes.js +41 -0
  362. package/dist/components/inspector/document-panes.js.map +1 -0
  363. package/dist/components/inspector/inspector-sidebar.js +1 -1
  364. package/dist/components/inspector/inspector-sidebar.js.map +1 -1
  365. package/dist/components/nav-issues-registry.d.ts +53 -0
  366. package/dist/components/nav-issues-registry.js +69 -0
  367. package/dist/components/nav-issues-registry.js.map +1 -0
  368. package/dist/components/nav-issues.js +4 -4
  369. package/dist/components/nav-issues.js.map +1 -1
  370. package/dist/components/operation-error.d.ts +1 -1
  371. package/dist/components/operation-error.js +4 -4
  372. package/dist/components/operation-error.js.map +1 -1
  373. package/dist/components/playground-badge.js +2 -2
  374. package/dist/components/playground-badge.js.map +1 -1
  375. package/dist/components/project-list.js +3 -3
  376. package/dist/components/project-list.js.map +1 -1
  377. package/dist/components/project-session.d.ts +2 -2
  378. package/dist/components/project-session.js +5 -5
  379. package/dist/components/project-session.js.map +1 -1
  380. package/dist/components/project-switcher.js +2 -2
  381. package/dist/components/project-switcher.js.map +1 -1
  382. package/dist/components/rail-store-status.js +1 -1
  383. package/dist/components/rail-store-status.js.map +1 -1
  384. package/dist/components/rail-view-source.d.ts +6 -5
  385. package/dist/components/rail-view-source.js +4 -3
  386. package/dist/components/rail-view-source.js.map +1 -1
  387. package/dist/components/records/record-lens.d.ts +51 -0
  388. package/dist/components/records/record-lens.js +151 -0
  389. package/dist/components/records/record-lens.js.map +1 -0
  390. package/dist/components/records/record-rail.d.ts +86 -0
  391. package/dist/components/records/record-rail.js +241 -0
  392. package/dist/components/records/record-rail.js.map +1 -0
  393. package/dist/components/redirects/redirects-schema.js +1 -1
  394. package/dist/components/redirects/redirects-schema.js.map +1 -1
  395. package/dist/components/references/references-panel.js +2 -2
  396. package/dist/components/references/references-panel.js.map +1 -1
  397. package/dist/components/section-nav.js +27 -11
  398. package/dist/components/section-nav.js.map +1 -1
  399. package/dist/components/section-state.js +2 -2
  400. package/dist/components/section-state.js.map +1 -1
  401. package/dist/components/section-surface.js +2 -2
  402. package/dist/components/section-surface.js.map +1 -1
  403. package/dist/components/session-expired-overlay.js +3 -3
  404. package/dist/components/session-expired-overlay.js.map +1 -1
  405. package/dist/components/settings-form.js +1 -1
  406. package/dist/components/settings-form.js.map +1 -1
  407. package/dist/components/sign-in-needed-badge.js +1 -1
  408. package/dist/components/sign-in-needed-badge.js.map +1 -1
  409. package/dist/components/sign-in-view.d.ts +2 -2
  410. package/dist/components/sign-in-view.js +5 -5
  411. package/dist/components/sign-in-view.js.map +1 -1
  412. package/dist/components/studio-context.js +3 -3
  413. package/dist/components/studio-context.js.map +1 -1
  414. package/dist/components/studio-project-screen.js +30 -3
  415. package/dist/components/studio-project-screen.js.map +1 -1
  416. package/dist/components/studio-shell.js +6 -5
  417. package/dist/components/studio-shell.js.map +1 -1
  418. package/dist/components/theme-context.d.ts +1 -1
  419. package/dist/components/theme-context.js +2 -2
  420. package/dist/components/theme-context.js.map +1 -1
  421. package/dist/components/use-hydration-phase.d.ts +1 -1
  422. package/dist/components/use-hydration-phase.js +1 -1
  423. package/dist/components/use-hydration-phase.js.map +1 -1
  424. package/dist/components/users/invite-user-bar.d.ts +27 -0
  425. package/dist/components/users/invite-user-bar.js +25 -9
  426. package/dist/components/users/invite-user-bar.js.map +1 -1
  427. package/dist/components/users/role-policy-drift-issues.d.ts +38 -0
  428. package/dist/components/users/role-policy-drift-issues.js +71 -0
  429. package/dist/components/users/role-policy-drift-issues.js.map +1 -0
  430. package/dist/components/users/users-collection-view-source.d.ts +1 -1
  431. package/dist/components/users/users-collection-view-source.js +4 -2
  432. package/dist/components/users/users-collection-view-source.js.map +1 -1
  433. package/dist/components/users/users-module.js +1 -1
  434. package/dist/components/users/users-module.js.map +1 -1
  435. package/dist/components/users/users-schema.d.ts +10 -1
  436. package/dist/components/users/users-schema.js +45 -25
  437. package/dist/components/users/users-schema.js.map +1 -1
  438. package/dist/components/users/users-store.js +3 -3
  439. package/dist/components/users/users-store.js.map +1 -1
  440. package/dist/components/workspace-projects.d.ts +1 -1
  441. package/dist/components/workspace-projects.js +1 -1
  442. package/dist/components/workspace-projects.js.map +1 -1
  443. package/dist/lib/ai/index.d.ts +1 -1
  444. package/dist/lib/ai/index.js +1 -1
  445. package/dist/lib/ai/index.js.map +1 -1
  446. package/dist/lib/ai/node-handler.d.ts +1 -1
  447. package/dist/lib/ai/node-handler.js.map +1 -1
  448. package/dist/lib/ai/translate-document.js +1 -1
  449. package/dist/lib/ai/translate-document.js.map +1 -1
  450. package/dist/lib/assets/upload.d.ts +25 -7
  451. package/dist/lib/assets/upload.js +30 -21
  452. package/dist/lib/assets/upload.js.map +1 -1
  453. package/dist/lib/clipboard/paste-issues.js +1 -1
  454. package/dist/lib/clipboard/paste-issues.js.map +1 -1
  455. package/dist/lib/clipboard/paste-target.js +2 -2
  456. package/dist/lib/clipboard/paste-target.js.map +1 -1
  457. package/dist/lib/cms/published-documents.d.ts +24 -6
  458. package/dist/lib/cms/published-documents.js +39 -6
  459. package/dist/lib/cms/published-documents.js.map +1 -1
  460. package/dist/lib/cms-views/view-model.d.ts +12 -99
  461. package/dist/lib/cms-views/view-model.js +22 -103
  462. package/dist/lib/cms-views/view-model.js.map +1 -1
  463. package/dist/lib/collection-view/collection-view-source.d.ts +13 -3
  464. package/dist/lib/collection-view/collection-view-source.js.map +1 -1
  465. package/dist/lib/data/content-session-refresh.d.ts +1 -1
  466. package/dist/lib/data/content-session-refresh.js.map +1 -1
  467. package/dist/lib/data/playground-unload-guard.d.ts +1 -1
  468. package/dist/lib/data/playground-unload-guard.js +1 -1
  469. package/dist/lib/data/playground-unload-guard.js.map +1 -1
  470. package/dist/lib/engine-version.d.ts +1 -1
  471. package/dist/lib/engine-version.js +1 -1
  472. package/dist/lib/engine-version.js.map +1 -1
  473. package/dist/lib/i18n/i18n.js +1 -1
  474. package/dist/lib/i18n/i18n.js.map +1 -1
  475. package/dist/lib/i18n/messages.de.js +11 -3
  476. package/dist/lib/i18n/messages.de.js.map +1 -1
  477. package/dist/lib/i18n/messages.en.d.ts +9 -1
  478. package/dist/lib/i18n/messages.en.js +16 -4
  479. package/dist/lib/i18n/messages.en.js.map +1 -1
  480. package/dist/lib/operations/config-manifest-lookup.d.ts +1 -1
  481. package/dist/lib/operations/config-manifest-lookup.js +3 -3
  482. package/dist/lib/operations/config-manifest-lookup.js.map +1 -1
  483. package/dist/lib/operations/project-runtime-config.d.ts +9 -0
  484. package/dist/lib/operations/project-runtime-config.js +13 -0
  485. package/dist/lib/operations/project-runtime-config.js.map +1 -1
  486. package/dist/lib/operations/studio-operations.d.ts +9 -1
  487. package/dist/lib/operations/studio-operations.js +6 -1
  488. package/dist/lib/operations/studio-operations.js.map +1 -1
  489. package/dist/lib/persistence/convex-adapter.d.ts +16 -3
  490. package/dist/lib/persistence/convex-adapter.js +78 -47
  491. package/dist/lib/persistence/convex-adapter.js.map +1 -1
  492. package/dist/lib/persistence/deployment-readiness.js +14 -11
  493. package/dist/lib/persistence/deployment-readiness.js.map +1 -1
  494. package/dist/lib/persistence/index.js +14 -1
  495. package/dist/lib/persistence/index.js.map +1 -1
  496. package/dist/lib/persona/labels.js +2 -1
  497. package/dist/lib/persona/labels.js.map +1 -1
  498. package/dist/lib/query/index.d.ts +2 -2
  499. package/dist/lib/query/index.js +1 -1
  500. package/dist/lib/query/index.js.map +1 -1
  501. package/dist/lib/query/operations-query.d.ts +27 -1
  502. package/dist/lib/query/operations-query.js +13 -1
  503. package/dist/lib/query/operations-query.js.map +1 -1
  504. package/dist/lib/references/reference-model.js +1 -1
  505. package/dist/lib/references/reference-model.js.map +1 -1
  506. package/dist/lib/references/references-store.js +1 -1
  507. package/dist/lib/references/references-store.js.map +1 -1
  508. package/dist/lib/registry/index.js +2 -2
  509. package/dist/lib/registry/index.js.map +1 -1
  510. package/dist/lib/registry/preview.d.ts +10 -0
  511. package/dist/lib/registry/preview.js +13 -4
  512. package/dist/lib/registry/preview.js.map +1 -1
  513. package/dist/lib/routes/route-issues.js +6 -3
  514. package/dist/lib/routes/route-issues.js.map +1 -1
  515. package/dist/lib/workspace/index.d.ts +6 -0
  516. package/dist/lib/workspace/index.js +8 -0
  517. package/dist/lib/workspace/index.js.map +1 -1
  518. package/dist/lib/workspace/workspace-source.js +6 -7
  519. package/dist/lib/workspace/workspace-source.js.map +1 -1
  520. package/dist/mount.d.ts +28 -0
  521. package/dist/mount.js +27 -0
  522. package/dist/mount.js.map +1 -0
  523. package/dist/previews/entry-node.d.ts +14 -0
  524. package/dist/previews/entry-node.js +22 -0
  525. package/dist/previews/entry-node.js.map +1 -0
  526. package/dist/previews/harness.js +2 -16
  527. package/dist/previews/harness.js.map +1 -1
  528. package/dist/router/root.js +10 -10
  529. package/dist/router/root.js.map +1 -1
  530. package/dist/ui/badge.d.ts +1 -1
  531. package/dist/ui/button.d.ts +2 -2
  532. package/package.json +15 -11
  533. package/dist/components/redirects/redirects-collection-view-source.d.ts +0 -53
  534. package/dist/components/redirects/redirects-collection-view-source.js +0 -146
  535. package/dist/components/redirects/redirects-collection-view-source.js.map +0 -1
  536. package/dist/components/redirects/redirects-module.d.ts +0 -21
  537. package/dist/components/redirects/redirects-module.js +0 -40
  538. package/dist/components/redirects/redirects-module.js.map +0 -1
  539. package/dist/components/redirects/redirects-store.d.ts +0 -68
  540. package/dist/components/redirects/redirects-store.js +0 -132
  541. package/dist/components/redirects/redirects-store.js.map +0 -1
@@ -1,5 +1,7 @@
1
1
  import type { CmsDocument } from '@elytracms/core/cms-core';
2
+ import type { OperationError } from '@elytracms/core/operations';
2
3
  import type { OperationsClient } from '../operations/index.js';
4
+ import type { ReadState } from '../query/index.js';
3
5
  /**
4
6
  * The PUBLISHED-perspective documents of a collection (EC-205, "live = published")
5
7
  * — the pinned published snapshot of each currently-published document, keyed by
@@ -13,12 +15,13 @@ import type { OperationsClient } from '../operations/index.js';
13
15
  * seam — invalidated only when a command that moves a live pin succeeds (NOT on
14
16
  * every autosave upsert — a draft edit doesn't change what's published). Cost: ONE
15
17
  * bulk `documents.listPublished` read (EC-307).
18
+ *
19
+ * EC-628: the pool is a {@link ReadState} — `ready` carries the pinned published snapshot
20
+ * per published document id; a failed read is `error` with the localized reason, and
21
+ * every surface reading the pool (the list's URL column, the editor header's live link)
22
+ * shows it. A failure is never an empty pool: an empty pool says "nothing is published".
16
23
  */
17
- export interface PublishedDocuments {
18
- /** Pinned published snapshot per published document id. Empty while loading. */
19
- byId: ReadonlyMap<string, CmsDocument>;
20
- status: 'loading' | 'ready';
21
- }
24
+ export type PublishedDocuments = ReadState<ReadonlyMap<string, CmsDocument>>;
22
25
  /**
23
26
  * Commands that change which version is pinned live (and thus the pool).
24
27
  *
@@ -30,12 +33,27 @@ export interface PublishedDocuments {
30
33
  * move or the delete of a pinned row changes published output.
31
34
  */
32
35
  export declare const PUBLISHED_RELOAD_OPS: readonly ["documents.publish", "documents.unpublish", "documents.pinVersion", "documents.delete", "documents.clear"];
36
+ /**
37
+ * A failed `documents.listPublished` read (EC-628), carrying the operation's typed error so
38
+ * the surface localizes it when it renders — the query cache outlives a UI-language switch.
39
+ */
40
+ export declare class PublishedReadError extends Error {
41
+ readonly error: OperationError;
42
+ constructor(error: OperationError);
43
+ }
33
44
  /**
34
45
  * Build the published pool of a collection (pure over the operations client): the
35
46
  * pinned published snapshot of every currently-published document, keyed by id.
36
47
  * EC-307: one bulk `documents.listPublished` read — the backend resolves each
37
48
  * `publishedVersion` pointer to its recorded snapshot — instead of a `list` plus a
38
- * per-document `listVersions` fan-out. Read failures degrade to an empty pool.
49
+ * per-document `listVersions` fan-out. A failed read REJECTS with
50
+ * {@link PublishedReadError} (EC-628) — it used to resolve to an empty pool.
39
51
  */
40
52
  export declare function loadPublishedDocuments(operations: OperationsClient, projectId: string, collectionId: string): Promise<Map<string, CmsDocument>>;
53
+ /** The {@link PublishedDocuments} state of the pool's query (pure — the hook's mapping). */
54
+ export declare function publishedDocumentsState(query: {
55
+ readonly isError: boolean;
56
+ readonly error: unknown;
57
+ readonly data: ReadonlyMap<string, CmsDocument> | undefined;
58
+ }): PublishedDocuments;
41
59
  export declare function usePublishedDocuments(projectId: string | undefined, collectionId: string): PublishedDocuments;
@@ -1,4 +1,6 @@
1
- import { useOperationQuery } from '@elytracms/studio/lib/query';
1
+ import { readStateOf, useOperationQuery } from '../query/index.js';
2
+ import { translate } from '../i18n/index.js';
3
+ import { operationErrorMessage } from '../persona/labels.js';
2
4
  /**
3
5
  * Commands that change which version is pinned live (and thus the pool).
4
6
  *
@@ -16,23 +18,54 @@ export const PUBLISHED_RELOAD_OPS = [
16
18
  'documents.delete',
17
19
  'documents.clear',
18
20
  ];
19
- const EMPTY_POOL = new Map();
21
+ /** No project (a fixture session without a backend): nothing is published, by construction. */
22
+ const NO_PROJECT_POOL = { status: 'ready', value: new Map() };
23
+ /**
24
+ * A failed `documents.listPublished` read (EC-628), carrying the operation's typed error so
25
+ * the surface localizes it when it renders — the query cache outlives a UI-language switch.
26
+ */
27
+ export class PublishedReadError extends Error {
28
+ error;
29
+ constructor(error) {
30
+ super(error.message);
31
+ this.error = error;
32
+ this.name = 'PublishedReadError';
33
+ }
34
+ }
20
35
  /**
21
36
  * Build the published pool of a collection (pure over the operations client): the
22
37
  * pinned published snapshot of every currently-published document, keyed by id.
23
38
  * EC-307: one bulk `documents.listPublished` read — the backend resolves each
24
39
  * `publishedVersion` pointer to its recorded snapshot — instead of a `list` plus a
25
- * per-document `listVersions` fan-out. Read failures degrade to an empty pool.
40
+ * per-document `listVersions` fan-out. A failed read REJECTS with
41
+ * {@link PublishedReadError} (EC-628) — it used to resolve to an empty pool.
26
42
  */
27
43
  export async function loadPublishedDocuments(operations, projectId, collectionId) {
28
44
  const result = await operations.documents.listPublished({ projectId, collection: collectionId });
29
45
  if (!result.ok)
30
- return new Map();
46
+ throw new PublishedReadError(result.error);
31
47
  const byId = new Map();
32
48
  for (const snapshot of result.value)
33
49
  byId.set(snapshot.id, snapshot);
34
50
  return byId;
35
51
  }
52
+ /**
53
+ * The pool's sentence when its read failed (EC-628): one message, shown by every surface
54
+ * that reads the pool — the operation's reason in the UI language when it carries a
55
+ * catalog reference (EC-494), its English otherwise.
56
+ */
57
+ function publishedReadFailure(error) {
58
+ const reason = error instanceof PublishedReadError
59
+ ? operationErrorMessage(error.error)
60
+ : error instanceof Error
61
+ ? error.message
62
+ : String(error);
63
+ return translate('cms.editor.publishedReadFailed', { reason });
64
+ }
65
+ /** The {@link PublishedDocuments} state of the pool's query (pure — the hook's mapping). */
66
+ export function publishedDocumentsState(query) {
67
+ return readStateOf(query, publishedReadFailure);
68
+ }
36
69
  export function usePublishedDocuments(projectId, collectionId) {
37
70
  const query = useOperationQuery({
38
71
  // Playground/fixture mode (no backend) is `enabled: false` → never queried.
@@ -42,7 +75,7 @@ export function usePublishedDocuments(projectId, collectionId) {
42
75
  enabled: projectId !== undefined,
43
76
  });
44
77
  if (projectId === undefined)
45
- return { byId: EMPTY_POOL, status: 'ready' };
46
- return { byId: query.data ?? EMPTY_POOL, status: query.isPending ? 'loading' : 'ready' };
78
+ return NO_PROJECT_POOL;
79
+ return publishedDocumentsState(query);
47
80
  }
48
81
  //# sourceMappingURL=published-documents.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"published-documents.js","sourceRoot":"","sources":["../../../src/lib/cms/published-documents.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAsB/D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,mBAAmB;IACnB,qBAAqB;IACrB,sBAAsB;IACtB,kBAAkB;IAClB,iBAAiB;CACT,CAAA;AAEV,MAAM,UAAU,GAAqC,IAAI,GAAG,EAAE,CAAA;AAE9D;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAA4B,EAC5B,SAAiB,EACjB,YAAoB;IAEpB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,CAAA;IAChG,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,IAAI,GAAG,EAAE,CAAA;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAuB,CAAA;IAC3C,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,KAAK;QAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;IACpE,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,SAA6B,EAC7B,YAAoB;IAEpB,MAAM,KAAK,GAAG,iBAAiB,CAA2B;QACxD,4EAA4E;QAC5E,QAAQ,EAAE,CAAC,oBAAoB,EAAE,SAAS,IAAI,GAAG,EAAE,YAAY,CAAC;QAChE,MAAM,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,sBAAsB,CAAC,UAAU,EAAE,SAAmB,EAAE,YAAY,CAAC;QAC7F,YAAY,EAAE,oBAAoB;QAClC,OAAO,EAAE,SAAS,KAAK,SAAS;KACjC,CAAC,CAAA;IACF,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;IACzE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA;AAC1F,CAAC","sourcesContent":["import type { CmsDocument } from '@elytracms/core/cms-core'\nimport type { OperationsClient } from '../operations'\nimport { useOperationQuery } from '@elytracms/studio/lib/query'\n\n/**\n * The PUBLISHED-perspective documents of a collection (EC-205, \"live = published\")\n * — the pinned published snapshot of each currently-published document, keyed by\n * id. Live surfaces (a document's live URL + \"View live\", EC-216) MUST derive\n * from this, never from the draft rows the studio edits: an unpublished document,\n * or an unpublished `slug`/`parent` edit, must never leak into a \"live\" URL. The\n * pool is exactly the set the live site would serve, so composing a nested page's\n * URL from these ancestors yields the URL the live site actually resolves.\n *\n * EC-308/AD-17: loaded + kept fresh through the one `useOperationQuery` cache\n * seam — invalidated only when a command that moves a live pin succeeds (NOT on\n * every autosave upsert — a draft edit doesn't change what's published). Cost: ONE\n * bulk `documents.listPublished` read (EC-307).\n */\nexport interface PublishedDocuments {\n /** Pinned published snapshot per published document id. Empty while loading. */\n byId: ReadonlyMap<string, CmsDocument>\n status: 'loading' | 'ready'\n}\n\n/**\n * Commands that change which version is pinned live (and thus the pool).\n *\n * EC-579 (RESIDUE-2c): `documents.pinVersion` moves the pin too — it is how a\n * changeset revert restores a prior live version — and was missing, so a revert left\n * the live URLs on the old pool until a reload. `documents.restore` was here and\n * moves nothing: it writes the DRAFT from a recorded version (`documents.replace`),\n * never the pin. The same answer the Convex trigger gives server-side: only a pin\n * move or the delete of a pinned row changes published output.\n */\nexport const PUBLISHED_RELOAD_OPS = [\n 'documents.publish',\n 'documents.unpublish',\n 'documents.pinVersion',\n 'documents.delete',\n 'documents.clear',\n] as const\n\nconst EMPTY_POOL: ReadonlyMap<string, CmsDocument> = new Map()\n\n/**\n * Build the published pool of a collection (pure over the operations client): the\n * pinned published snapshot of every currently-published document, keyed by id.\n * EC-307: one bulk `documents.listPublished` read — the backend resolves each\n * `publishedVersion` pointer to its recorded snapshot — instead of a `list` plus a\n * per-document `listVersions` fan-out. Read failures degrade to an empty pool.\n */\nexport async function loadPublishedDocuments(\n operations: OperationsClient,\n projectId: string,\n collectionId: string,\n): Promise<Map<string, CmsDocument>> {\n const result = await operations.documents.listPublished({ projectId, collection: collectionId })\n if (!result.ok) return new Map()\n const byId = new Map<string, CmsDocument>()\n for (const snapshot of result.value) byId.set(snapshot.id, snapshot)\n return byId\n}\n\nexport function usePublishedDocuments(\n projectId: string | undefined,\n collectionId: string,\n): PublishedDocuments {\n const query = useOperationQuery<Map<string, CmsDocument>>({\n // Playground/fixture mode (no backend) is `enabled: false` → never queried.\n queryKey: ['publishedDocuments', projectId ?? '∅', collectionId],\n loader: (operations) => loadPublishedDocuments(operations, projectId as string, collectionId),\n invalidateOn: PUBLISHED_RELOAD_OPS,\n enabled: projectId !== undefined,\n })\n if (projectId === undefined) return { byId: EMPTY_POOL, status: 'ready' }\n return { byId: query.data ?? EMPTY_POOL, status: query.isPending ? 'loading' : 'ready' }\n}\n"]}
1
+ {"version":3,"file":"published-documents.js","sourceRoot":"","sources":["../../../src/lib/cms/published-documents.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAuBzD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,mBAAmB;IACnB,qBAAqB;IACrB,sBAAsB;IACtB,kBAAkB;IAClB,iBAAiB;CACT,CAAA;AAEV,+FAA+F;AAC/F,MAAM,eAAe,GAAuB,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,CAAA;AAEjF;;;GAGG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACtB;IAArB,YAAqB,KAAqB;QACxC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QADD,UAAK,GAAL,KAAK,CAAgB;QAExC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAA;IAClC,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAA4B,EAC5B,SAAiB,EACjB,YAAoB;IAEpB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,CAAA;IAChG,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAC1D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAuB,CAAA;IAC3C,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,KAAK;QAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;IACpE,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,KAAc;IAC1C,MAAM,MAAM,GACV,KAAK,YAAY,kBAAkB;QACjC,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,KAAK,CAAC;QACpC,CAAC,CAAC,KAAK,YAAY,KAAK;YACtB,CAAC,CAAC,KAAK,CAAC,OAAO;YACf,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACrB,OAAO,SAAS,CAAC,gCAAgC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;AAChE,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,uBAAuB,CAAC,KAIvC;IACC,OAAO,WAAW,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAA;AACjD,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,SAA6B,EAC7B,YAAoB;IAEpB,MAAM,KAAK,GAAG,iBAAiB,CAA2B;QACxD,4EAA4E;QAC5E,QAAQ,EAAE,CAAC,oBAAoB,EAAE,SAAS,IAAI,GAAG,EAAE,YAAY,CAAC;QAChE,MAAM,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,sBAAsB,CAAC,UAAU,EAAE,SAAmB,EAAE,YAAY,CAAC;QAC7F,YAAY,EAAE,oBAAoB;QAClC,OAAO,EAAE,SAAS,KAAK,SAAS;KACjC,CAAC,CAAA;IACF,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,eAAe,CAAA;IACnD,OAAO,uBAAuB,CAAC,KAAK,CAAC,CAAA;AACvC,CAAC","sourcesContent":["import type { CmsDocument } from '@elytracms/core/cms-core'\nimport type { OperationError } from '@elytracms/core/operations'\nimport type { OperationsClient } from '../operations'\nimport { readStateOf, useOperationQuery } from '../query'\nimport type { ReadState } from '../query'\nimport { translate } from '../i18n'\nimport { operationErrorMessage } from '../persona/labels'\n\n/**\n * The PUBLISHED-perspective documents of a collection (EC-205, \"live = published\")\n * — the pinned published snapshot of each currently-published document, keyed by\n * id. Live surfaces (a document's live URL + \"View live\", EC-216) MUST derive\n * from this, never from the draft rows the studio edits: an unpublished document,\n * or an unpublished `slug`/`parent` edit, must never leak into a \"live\" URL. The\n * pool is exactly the set the live site would serve, so composing a nested page's\n * URL from these ancestors yields the URL the live site actually resolves.\n *\n * EC-308/AD-17: loaded + kept fresh through the one `useOperationQuery` cache\n * seam — invalidated only when a command that moves a live pin succeeds (NOT on\n * every autosave upsert — a draft edit doesn't change what's published). Cost: ONE\n * bulk `documents.listPublished` read (EC-307).\n *\n * EC-628: the pool is a {@link ReadState} — `ready` carries the pinned published snapshot\n * per published document id; a failed read is `error` with the localized reason, and\n * every surface reading the pool (the list's URL column, the editor header's live link)\n * shows it. A failure is never an empty pool: an empty pool says \"nothing is published\".\n */\nexport type PublishedDocuments = ReadState<ReadonlyMap<string, CmsDocument>>\n\n/**\n * Commands that change which version is pinned live (and thus the pool).\n *\n * EC-579 (RESIDUE-2c): `documents.pinVersion` moves the pin too — it is how a\n * changeset revert restores a prior live version — and was missing, so a revert left\n * the live URLs on the old pool until a reload. `documents.restore` was here and\n * moves nothing: it writes the DRAFT from a recorded version (`documents.replace`),\n * never the pin. The same answer the Convex trigger gives server-side: only a pin\n * move or the delete of a pinned row changes published output.\n */\nexport const PUBLISHED_RELOAD_OPS = [\n 'documents.publish',\n 'documents.unpublish',\n 'documents.pinVersion',\n 'documents.delete',\n 'documents.clear',\n] as const\n\n/** No project (a fixture session without a backend): nothing is published, by construction. */\nconst NO_PROJECT_POOL: PublishedDocuments = { status: 'ready', value: new Map() }\n\n/**\n * A failed `documents.listPublished` read (EC-628), carrying the operation's typed error so\n * the surface localizes it when it renders — the query cache outlives a UI-language switch.\n */\nexport class PublishedReadError extends Error {\n constructor(readonly error: OperationError) {\n super(error.message)\n this.name = 'PublishedReadError'\n }\n}\n\n/**\n * Build the published pool of a collection (pure over the operations client): the\n * pinned published snapshot of every currently-published document, keyed by id.\n * EC-307: one bulk `documents.listPublished` read — the backend resolves each\n * `publishedVersion` pointer to its recorded snapshot — instead of a `list` plus a\n * per-document `listVersions` fan-out. A failed read REJECTS with\n * {@link PublishedReadError} (EC-628) — it used to resolve to an empty pool.\n */\nexport async function loadPublishedDocuments(\n operations: OperationsClient,\n projectId: string,\n collectionId: string,\n): Promise<Map<string, CmsDocument>> {\n const result = await operations.documents.listPublished({ projectId, collection: collectionId })\n if (!result.ok) throw new PublishedReadError(result.error)\n const byId = new Map<string, CmsDocument>()\n for (const snapshot of result.value) byId.set(snapshot.id, snapshot)\n return byId\n}\n\n/**\n * The pool's sentence when its read failed (EC-628): one message, shown by every surface\n * that reads the pool — the operation's reason in the UI language when it carries a\n * catalog reference (EC-494), its English otherwise.\n */\nfunction publishedReadFailure(error: unknown): string {\n const reason =\n error instanceof PublishedReadError\n ? operationErrorMessage(error.error)\n : error instanceof Error\n ? error.message\n : String(error)\n return translate('cms.editor.publishedReadFailed', { reason })\n}\n\n/** The {@link PublishedDocuments} state of the pool's query (pure — the hook's mapping). */\nexport function publishedDocumentsState(query: {\n readonly isError: boolean\n readonly error: unknown\n readonly data: ReadonlyMap<string, CmsDocument> | undefined\n}): PublishedDocuments {\n return readStateOf(query, publishedReadFailure)\n}\n\nexport function usePublishedDocuments(\n projectId: string | undefined,\n collectionId: string,\n): PublishedDocuments {\n const query = useOperationQuery<Map<string, CmsDocument>>({\n // Playground/fixture mode (no backend) is `enabled: false` → never queried.\n queryKey: ['publishedDocuments', projectId ?? '∅', collectionId],\n loader: (operations) => loadPublishedDocuments(operations, projectId as string, collectionId),\n invalidateOn: PUBLISHED_RELOAD_OPS,\n enabled: projectId !== undefined,\n })\n if (projectId === undefined) return NO_PROJECT_POOL\n return publishedDocumentsState(query)\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
- import type { CmsDocument, CollectionDef, FieldDef, Locale, LocaleConfig, LocalizedString } from '@elytracms/core/cms-core';
2
+ import { configViewSchema, filterClauseSchema, filterScalarSchema, isPseudoColumn, PUBLISHED_AT_FIELD, STATE_FIELD, UPDATED_AT_FIELD, URL_FIELD, viewSortSchema } from '@elytracms/core/cms-core';
3
+ import type { CmsDocument, CollectionDef, ConfigView, FieldDef, FilterClause, Locale, LocaleConfig, LocalizedString, ViewSort } from '@elytracms/core/cms-core';
3
4
  import type { FilterOperator, FilterScalar } from '@elytracms/core/content';
4
5
  /**
5
6
  * The pure table-view model for the CMS collection table (EC-169).
@@ -17,38 +18,12 @@ import type { FilterOperator, FilterScalar } from '@elytracms/core/content';
17
18
  * "show me drafts → bulk publish" working set and still speaks only the
18
19
  * closed vocabulary (`eq`/`in`).
19
20
  */
20
- export declare const filterScalarSchema: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>;
21
- export declare const filterClauseSchema: z.ZodObject<{
22
- field: z.ZodString;
23
- op: z.ZodEnum<{
24
- empty: "empty";
25
- contains: "contains";
26
- in: "in";
27
- endsWith: "endsWith";
28
- startsWith: "startsWith";
29
- eq: "eq";
30
- gt: "gt";
31
- gte: "gte";
32
- lt: "lt";
33
- lte: "lte";
34
- }>;
35
- value: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
36
- }, z.core.$strip>;
37
- export type FilterClause = z.infer<typeof filterClauseSchema>;
38
- export declare const viewSortSchema: z.ZodObject<{
39
- field: z.ZodString;
40
- dir: z.ZodEnum<{
41
- asc: "asc";
42
- desc: "desc";
43
- }>;
44
- }, z.core.$strip>;
45
- export type ViewSort = z.infer<typeof viewSortSchema>;
21
+ export { configViewSchema, filterClauseSchema, filterScalarSchema, isPseudoColumn, PUBLISHED_AT_FIELD, STATE_FIELD, UPDATED_AT_FIELD, URL_FIELD, viewSortSchema, };
22
+ export type { ConfigView, FilterClause, ViewSort };
46
23
  export declare const tableViewStateSchema: z.ZodObject<{
47
24
  filters: z.ZodArray<z.ZodObject<{
48
25
  field: z.ZodString;
49
26
  op: z.ZodEnum<{
50
- empty: "empty";
51
- contains: "contains";
52
27
  in: "in";
53
28
  endsWith: "endsWith";
54
29
  startsWith: "startsWith";
@@ -57,6 +32,8 @@ export declare const tableViewStateSchema: z.ZodObject<{
57
32
  gte: "gte";
58
33
  lt: "lt";
59
34
  lte: "lte";
35
+ contains: "contains";
36
+ empty: "empty";
60
37
  }>;
61
38
  value: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
62
39
  }, z.core.$strip>>;
@@ -71,36 +48,6 @@ export declare const tableViewStateSchema: z.ZodObject<{
71
48
  hidden: z.ZodDefault<z.ZodArray<z.ZodString>>;
72
49
  }, z.core.$strip>;
73
50
  export type TableViewState = z.infer<typeof tableViewStateSchema>;
74
- /**
75
- * Sentinel field key for the publication state. `$`-prefixed so it can never
76
- * collide with a schema field name (`fieldDefSchema` names are identifiers).
77
- */
78
- export declare const STATE_FIELD = "$state";
79
- /**
80
- * Reserved pseudo-COLUMN keys — the columns-axis siblings of the filter-axis
81
- * {@link STATE_FIELD}. `$`-prefixed so they can never collide with a schema field
82
- * name; they participate in a view's `columns` list AND the Display picker exactly
83
- * like a schema field (orderable / hideable / includable), but they are NOT drawn
84
- * from `collection.fields` — the column UNIVERSE is `[...schemaFields, ...pseudoColumns]`.
85
- *
86
- * - `$state` — publication status. A reserved `$`-key, but NO LONGER a reorderable
87
- * column: EC-448 promoted it to a FIXED structural leading column (checkbox →
88
- * status-dot → title), so it is NOT emitted by {@link pseudoColumns} and never
89
- * participates in the reorderable columns/hidden/order model. It stays a reserved
90
- * key (filter + sort) and {@link isPseudoColumn} still recognizes it, so an authored
91
- * view listing `$state` is a harmless no-op (see {@link resolveConfigColumns}).
92
- * - `$url` — the derived delivery URL (routable collections only; NON-sortable).
93
- * - `$updatedAt` — the record's last-write timestamp.
94
- * - `$publishedAt` — the record's FIRST-publish instant (EC-447; opt-in, HIDDEN by
95
- * default). Now materialized end-to-end (`cmsDocuments.publishedAt` → source
96
- * `timestamps.publishedAt`) and emitted by {@link pseudoColumns} when the source
97
- * both materializes timestamps and has a publish lifecycle.
98
- */
99
- export declare const URL_FIELD = "$url";
100
- export declare const PUBLISHED_AT_FIELD = "$publishedAt";
101
- export declare const UPDATED_AT_FIELD = "$updatedAt";
102
- /** Is `name` a reserved pseudo-column (a `$`-key, not a schema field)? */
103
- export declare function isPseudoColumn(name: string): boolean;
104
51
  /**
105
52
  * Capability signals that make a pseudo-column applicable to a collection/source
106
53
  * (EC-445). Supplied by the caller from the portable source — the model stays pure.
@@ -269,49 +216,14 @@ export declare function defaultViewState(collection: CollectionDef, pseudo?: rea
269
216
  * same shape {@link defaultViewState} produces, so {@link resolveColumns} renders
270
217
  * precisely the authored list, visible, in that order. An omitted (or empty) list
271
218
  * inherits the collection's default lens (all scalars visible, composites hidden).
272
- * Unknown names in the authored list (a field the schema no longer has) are dropped.
219
+ * An authored name outside the universe — no longer a field, or a reserved column that
220
+ * does not apply to this source — is skipped here so the list still renders; a name that
221
+ * is neither a top-level field nor a reserved `$` key never reaches a resolved config
222
+ * (EC-622: the config gate refuses it, `collectionViewFindings`).
273
223
  */
274
224
  export declare function resolveConfigColumns(collection: CollectionDef, visible: readonly string[] | undefined, pseudo?: readonly string[]): Pick<TableViewState, 'columns' | 'hidden'>;
275
225
  /** The reserved `views[]` id whose entry OVERRIDES the synthesized baseline view (EC-444). */
276
226
  export declare const DEFAULT_VIEW_OVERRIDE_ID = "default";
277
- /**
278
- * A config-declared view (EC-246b/EC-444) — the flat authoring shape a collection
279
- * declares in `cms/` config: `{ name, initial?, filters?, sort?, columns? }`.
280
- * Filters/sort/columns sit at the top level (no nested `state` wrapper). The
281
- * studio validates + interprets these; `cms-core` stores them opaquely (it
282
- * can't reference the filter vocabulary without a layering cycle).
283
- */
284
- export declare const configViewSchema: z.ZodObject<{
285
- id: z.ZodOptional<z.ZodString>;
286
- name: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
287
- initial: z.ZodOptional<z.ZodBoolean>;
288
- default: z.ZodOptional<z.ZodBoolean>;
289
- filters: z.ZodOptional<z.ZodArray<z.ZodObject<{
290
- field: z.ZodString;
291
- op: z.ZodEnum<{
292
- empty: "empty";
293
- contains: "contains";
294
- in: "in";
295
- endsWith: "endsWith";
296
- startsWith: "startsWith";
297
- eq: "eq";
298
- gt: "gt";
299
- gte: "gte";
300
- lt: "lt";
301
- lte: "lte";
302
- }>;
303
- value: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
304
- }, z.core.$strip>>>;
305
- sort: z.ZodOptional<z.ZodNullable<z.ZodObject<{
306
- field: z.ZodString;
307
- dir: z.ZodEnum<{
308
- asc: "asc";
309
- desc: "desc";
310
- }>;
311
- }, z.core.$strip>>>;
312
- columns: z.ZodOptional<z.ZodArray<z.ZodString>>;
313
- }, z.core.$strip>;
314
- export type ConfigView = z.infer<typeof configViewSchema>;
315
227
  /**
316
228
  * A resolved view: identity + the table state it restores (matches `SavedView`).
317
229
  * `name` stays a {@link LocalizedString} — resolved at the render site (EC-343), like
@@ -327,7 +239,8 @@ export interface ResolvedView {
327
239
  /**
328
240
  * Resolve a collection's config-declared `views` into full {@link ResolvedView}s
329
241
  * (EC-246b). Each is validated with {@link configViewSchema}; malformed entries
330
- * and duplicate ids are dropped (defensive). Columns fall back to the collection
242
+ * and duplicate ids are skipped (defensive — a malformed view never reaches a resolved
243
+ * config: the config gate refuses it, EC-622). Columns fall back to the collection
331
244
  * default when a view doesn't pin them, so a filter-only view still renders every
332
245
  * column. Config views are shared and change only in
333
246
  * code — the runtime never mutates them.
@@ -1,8 +1,8 @@
1
1
  import { z } from 'zod';
2
- import { canonicalDateValue, localizedStringSchema, resolveField, resolveLabel, titleFieldOf, } from '@elytracms/core/cms-core';
3
- import { localizedLabel, translate } from '@elytracms/studio/lib/i18n';
4
- import { contentQueryErrorMessage } from '@elytracms/studio/lib/persona/labels';
5
- import { FILTER_OPERATORS, compareListEntries, sortScalarOf, filterableFields, matchesFieldValue, validateWhere, } from '@elytracms/core/content';
2
+ import { canonicalDateValue, configViewSchema, filterClauseSchema, filterScalarSchema, isPseudoColumn, PUBLISHED_AT_FIELD, resolveField, resolveLabel, STATE_FIELD, titleFieldOf, UPDATED_AT_FIELD, URL_FIELD, viewSortSchema, } from '@elytracms/core/cms-core';
3
+ import { localizedLabel, translate } from '../i18n/index.js';
4
+ import { contentQueryErrorMessage } from '../persona/labels.js';
5
+ import { compareListEntries, sortScalarOf, filterableFields, matchesFieldValue, validateWhere, } from '@elytracms/core/content';
6
6
  /**
7
7
  * The pure table-view model for the CMS collection table (EC-169).
8
8
  *
@@ -20,18 +20,10 @@ import { FILTER_OPERATORS, compareListEntries, sortScalarOf, filterableFields, m
20
20
  * closed vocabulary (`eq`/`in`).
21
21
  */
22
22
  // --- Schemas (single source of truth — persisted view records reuse these) ----
23
- export const filterScalarSchema = z.union([z.string(), z.number(), z.boolean()]);
24
- export const filterClauseSchema = z.object({
25
- /** A schema field name, or {@link STATE_FIELD} for the publication state. */
26
- field: z.string().min(1),
27
- op: z.enum(FILTER_OPERATORS),
28
- /** `in` carries an array of scalars; every other operator one scalar. */
29
- value: z.union([filterScalarSchema, z.array(filterScalarSchema)]),
30
- });
31
- export const viewSortSchema = z.object({
32
- field: z.string().min(1),
33
- dir: z.enum(['asc', 'desc']),
34
- });
23
+ // EC-622: the authoring shape of a view and the reserved `$` keys are declared ONCE, in
24
+ // cms-core (`collection-views.ts`), where the config gate judges every declared view —
25
+ // re-exported here unchanged, so this module's public names stay what they were.
26
+ export { configViewSchema, filterClauseSchema, filterScalarSchema, isPseudoColumn, PUBLISHED_AT_FIELD, STATE_FIELD, UPDATED_AT_FIELD, URL_FIELD, viewSortSchema, };
35
27
  export const tableViewStateSchema = z.object({
36
28
  /** AND-only list of conditions (no OR, no nesting — vision AD-3). */
37
29
  filters: z.array(filterClauseSchema),
@@ -50,53 +42,16 @@ export const tableViewStateSchema = z.object({
50
42
  hidden: z.array(z.string().min(1)).default([]),
51
43
  });
52
44
  // --- The built-in publication-state filter column ------------------------------
53
- /**
54
- * Sentinel field key for the publication state. `$`-prefixed so it can never
55
- * collide with a schema field name (`fieldDefSchema` names are identifiers).
56
- */
57
- export const STATE_FIELD = '$state';
45
+ // `STATE_FIELD` (the publication-state sentinel) and the reserved pseudo-COLUMN keys
46
+ // (`$url`, `$updatedAt`, `$publishedAt` — EC-445/EC-447) are declared in cms-core
47
+ // (`collection-views.ts`, EC-622) and re-exported above. `$state` is a reserved key
48
+ // (filter + sort) but NOT a reorderable column: EC-448 made it the FIXED structural
49
+ // leading column, so {@link pseudoColumns} never emits it and an authored view listing
50
+ // `$state` is a harmless no-op (see {@link resolveConfigColumns}). Which reserved key
51
+ // APPLIES to a collection is this module's runtime decision ({@link pseudoColumns}); the
52
+ // config gate accepts every reserved key.
58
53
  const STATE_VALUES = ['draft', 'published'];
59
54
  // --- Reserved pseudo-COLUMNS (EC-445) ------------------------------------------
60
- /**
61
- * Reserved pseudo-COLUMN keys — the columns-axis siblings of the filter-axis
62
- * {@link STATE_FIELD}. `$`-prefixed so they can never collide with a schema field
63
- * name; they participate in a view's `columns` list AND the Display picker exactly
64
- * like a schema field (orderable / hideable / includable), but they are NOT drawn
65
- * from `collection.fields` — the column UNIVERSE is `[...schemaFields, ...pseudoColumns]`.
66
- *
67
- * - `$state` — publication status. A reserved `$`-key, but NO LONGER a reorderable
68
- * column: EC-448 promoted it to a FIXED structural leading column (checkbox →
69
- * status-dot → title), so it is NOT emitted by {@link pseudoColumns} and never
70
- * participates in the reorderable columns/hidden/order model. It stays a reserved
71
- * key (filter + sort) and {@link isPseudoColumn} still recognizes it, so an authored
72
- * view listing `$state` is a harmless no-op (see {@link resolveConfigColumns}).
73
- * - `$url` — the derived delivery URL (routable collections only; NON-sortable).
74
- * - `$updatedAt` — the record's last-write timestamp.
75
- * - `$publishedAt` — the record's FIRST-publish instant (EC-447; opt-in, HIDDEN by
76
- * default). Now materialized end-to-end (`cmsDocuments.publishedAt` → source
77
- * `timestamps.publishedAt`) and emitted by {@link pseudoColumns} when the source
78
- * both materializes timestamps and has a publish lifecycle.
79
- */
80
- export const URL_FIELD = '$url';
81
- export const PUBLISHED_AT_FIELD = '$publishedAt';
82
- export const UPDATED_AT_FIELD = '$updatedAt';
83
- /**
84
- * Every reserved pseudo-column key. `$state` is included (it is still a reserved
85
- * `$`-key: the filter/sort axis + the FIXED structural status column, EC-448) so
86
- * {@link isPseudoColumn} never mistakes it for a schema field — but it is NOT a
87
- * reorderable column, so it is absent from the `pseudo` sets {@link pseudoColumns}
88
- * emits into the order/hide/picker model.
89
- */
90
- const PSEUDO_COLUMN_FIELDS = [
91
- STATE_FIELD,
92
- URL_FIELD,
93
- PUBLISHED_AT_FIELD,
94
- UPDATED_AT_FIELD,
95
- ];
96
- /** Is `name` a reserved pseudo-column (a `$`-key, not a schema field)? */
97
- export function isPseudoColumn(name) {
98
- return PSEUDO_COLUMN_FIELDS.includes(name);
99
- }
100
55
  /**
101
56
  * Pseudo-columns HIDDEN by default (opt-in): the extra publish timestamp. Everything
102
57
  * else applicable (`$updatedAt`/`$state`/`$url`) is on by default (owner, 2026-07-17).
@@ -460,7 +415,10 @@ export function defaultViewState(collection, pseudo = []) {
460
415
  * same shape {@link defaultViewState} produces, so {@link resolveColumns} renders
461
416
  * precisely the authored list, visible, in that order. An omitted (or empty) list
462
417
  * inherits the collection's default lens (all scalars visible, composites hidden).
463
- * Unknown names in the authored list (a field the schema no longer has) are dropped.
418
+ * An authored name outside the universe — no longer a field, or a reserved column that
419
+ * does not apply to this source — is skipped here so the list still renders; a name that
420
+ * is neither a top-level field nor a reserved `$` key never reaches a resolved config
421
+ * (EC-622: the config gate refuses it, `collectionViewFindings`).
464
422
  */
465
423
  export function resolveConfigColumns(collection, visible, pseudo = []) {
466
424
  if (visible === undefined || visible.length === 0) {
@@ -494,46 +452,6 @@ export function resolveConfigColumns(collection, visible, pseudo = []) {
494
452
  }
495
453
  /** The reserved `views[]` id whose entry OVERRIDES the synthesized baseline view (EC-444). */
496
454
  export const DEFAULT_VIEW_OVERRIDE_ID = 'default';
497
- /**
498
- * A config-declared view (EC-246b/EC-444) — the flat authoring shape a collection
499
- * declares in `cms/` config: `{ name, initial?, filters?, sort?, columns? }`.
500
- * Filters/sort/columns sit at the top level (no nested `state` wrapper). The
501
- * studio validates + interprets these; `cms-core` stores them opaquely (it
502
- * can't reference the filter vocabulary without a layering cycle).
503
- */
504
- export const configViewSchema = z.object({
505
- /**
506
- * Optional stable id; defaults to a slug of `name`. The reserved value
507
- * {@link DEFAULT_VIEW_OVERRIDE_ID} (`'default'`) marks the baseline-override entry.
508
- */
509
- id: z.string().min(1).optional(),
510
- /**
511
- * View label; localizable (EC-343): a plain string or a `{ locale }` map, resolved
512
- * at the render site via the same `resolveLabel` path as `form.label` (EC-241).
513
- */
514
- name: localizedStringSchema,
515
- /**
516
- * When true this view seeds the collection's INITIAL active view (EC-343/EC-444) —
517
- * the curated lens an editor lands on before picking one. At most one per collection;
518
- * a duplicate is a visible validation issue ({@link configViewIssues}), never silent.
519
- * The baseline lens stays available and stays the fallback.
520
- */
521
- initial: z.boolean().optional(),
522
- /**
523
- * @deprecated EC-444 — renamed to {@link ConfigView.initial}. Still read as an alias
524
- * for one release (`initial ?? default`) with a console warning; removed next release.
525
- * Distinct from a field's default VALUE and from the reserved `id: 'default'` override.
526
- */
527
- default: z.boolean().optional(),
528
- filters: z.array(filterClauseSchema).optional(),
529
- sort: viewSortSchema.nullable().optional(),
530
- /**
531
- * The single ordered list of VISIBLE columns (EC-444): what you list is what shows,
532
- * in that order. Omit to inherit the collection's default columns (all scalars). The
533
- * two-axis `{columns, hidden}` internal state is derived by {@link resolveConfigColumns}.
534
- */
535
- columns: z.array(z.string().min(1)).optional(),
536
- });
537
455
  /**
538
456
  * Slug used to derive a config view's stable id from its name. A localized name
539
457
  * (EC-343) slugs its DEFAULT-locale text so the id is stable across the active UI
@@ -550,7 +468,8 @@ function configViewId(name, index) {
550
468
  /**
551
469
  * Resolve a collection's config-declared `views` into full {@link ResolvedView}s
552
470
  * (EC-246b). Each is validated with {@link configViewSchema}; malformed entries
553
- * and duplicate ids are dropped (defensive). Columns fall back to the collection
471
+ * and duplicate ids are skipped (defensive — a malformed view never reaches a resolved
472
+ * config: the config gate refuses it, EC-622). Columns fall back to the collection
554
473
  * default when a view doesn't pin them, so a filter-only view still renders every
555
474
  * column. Config views are shared and change only in
556
475
  * code — the runtime never mutates them.