canopycms 0.0.68-int.98 → 0.1.0

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 (688) hide show
  1. package/CHANGELOG.md +2131 -0
  2. package/README.md +47 -63
  3. package/dist/ai/generate.d.ts +5 -0
  4. package/dist/ai/generate.js +244 -115
  5. package/dist/ai/index.d.ts +1 -1
  6. package/dist/ai/json-to-markdown.d.ts +21 -1
  7. package/dist/ai/json-to-markdown.js +120 -57
  8. package/dist/ai/references.d.ts +72 -0
  9. package/dist/ai/references.js +223 -0
  10. package/dist/ai/resolve-branch.js +9 -2
  11. package/dist/ai/to-plain-text.d.ts +17 -8
  12. package/dist/ai/to-plain-text.js +18 -15
  13. package/dist/ai/types.d.ts +84 -3
  14. package/dist/api/admin-branch-health.d.ts +24 -1
  15. package/dist/api/admin-branch-health.js +52 -20
  16. package/dist/api/admin.d.ts +23 -5
  17. package/dist/api/admin.js +36 -1
  18. package/dist/api/assets.js +88 -78
  19. package/dist/api/branch-create-window.d.ts +12 -0
  20. package/dist/api/branch-create-window.js +13 -0
  21. package/dist/api/branch-merge.d.ts +1 -1
  22. package/dist/api/branch-merge.js +1 -1
  23. package/dist/api/branch-review.d.ts +3 -3
  24. package/dist/api/branch-review.js +16 -7
  25. package/dist/api/branch-status.d.ts +16 -6
  26. package/dist/api/branch-status.js +57 -12
  27. package/dist/api/branch-withdraw.d.ts +2 -2
  28. package/dist/api/branch-withdraw.js +8 -3
  29. package/dist/api/branch.d.ts +25 -12
  30. package/dist/api/branch.js +164 -103
  31. package/dist/api/client.d.ts +78 -58
  32. package/dist/api/client.js +150 -117
  33. package/dist/api/comments.d.ts +12 -3
  34. package/dist/api/comments.js +118 -9
  35. package/dist/api/content.d.ts +9 -9
  36. package/dist/api/content.js +131 -22
  37. package/dist/api/entries-constants.d.ts +14 -3
  38. package/dist/api/entries-constants.js +14 -3
  39. package/dist/api/entries.d.ts +40 -2
  40. package/dist/api/entries.js +102 -6
  41. package/dist/api/github-sync.d.ts +19 -0
  42. package/dist/api/github-sync.js +50 -3
  43. package/dist/api/groups.d.ts +4 -4
  44. package/dist/api/groups.js +2 -1
  45. package/dist/api/guards.js +23 -3
  46. package/dist/api/index.d.ts +3 -1
  47. package/dist/api/index.js +1 -0
  48. package/dist/api/permissions.d.ts +21 -2
  49. package/dist/api/permissions.js +50 -3
  50. package/dist/api/request-deadline.d.ts +59 -0
  51. package/dist/api/request-deadline.js +73 -0
  52. package/dist/api/resolve-references.js +8 -7
  53. package/dist/api/route-builder.d.ts +14 -0
  54. package/dist/api/route-builder.js +14 -1
  55. package/dist/api/schema.d.ts +11 -9
  56. package/dist/api/schema.js +2 -0
  57. package/dist/api/settings-helpers.d.ts +5 -1
  58. package/dist/api/settings-helpers.js +10 -2
  59. package/dist/api/types.d.ts +18 -0
  60. package/dist/api/users-constants.d.ts +6 -0
  61. package/dist/api/users-constants.js +6 -0
  62. package/dist/assets/asset-url.d.ts +28 -16
  63. package/dist/assets/asset-url.js +51 -25
  64. package/dist/assets/finalize.js +3 -0
  65. package/dist/assets/index.d.ts +1 -1
  66. package/dist/assets/materialize.d.ts +153 -0
  67. package/dist/assets/materialize.js +402 -0
  68. package/dist/assets/store-local.d.ts +19 -5
  69. package/dist/assets/store-local.js +69 -10
  70. package/dist/assets/store-s3.d.ts +38 -7
  71. package/dist/assets/store-s3.js +128 -22
  72. package/dist/assets/transform-directives.d.ts +52 -13
  73. package/dist/assets/transform-directives.js +87 -27
  74. package/dist/assets/transform.d.ts +3 -3
  75. package/dist/assets/transform.js +13 -8
  76. package/dist/assets/types.d.ts +31 -4
  77. package/dist/auth/cache.d.ts +1 -1
  78. package/dist/auth/cache.js +1 -1
  79. package/dist/auth/caching-auth-plugin.d.ts +2 -0
  80. package/dist/auth/caching-auth-plugin.js +12 -2
  81. package/dist/auth/file-based-auth-cache.d.ts +8 -0
  82. package/dist/auth/file-based-auth-cache.js +18 -8
  83. package/dist/auth/person-name.d.ts +5 -0
  84. package/dist/auth/person-name.js +8 -0
  85. package/dist/auth/plugin.d.ts +10 -1
  86. package/dist/auth/types.d.ts +2 -0
  87. package/dist/auth/user-metadata-lookup.d.ts +21 -0
  88. package/dist/auth/user-metadata-lookup.js +116 -0
  89. package/dist/authorization/branch.d.ts +1 -1
  90. package/dist/authorization/branch.js +12 -13
  91. package/dist/authorization/groups/schema.d.ts +4 -4
  92. package/dist/authorization/helpers.d.ts +8 -0
  93. package/dist/authorization/helpers.js +8 -0
  94. package/dist/authorization/index.d.ts +1 -1
  95. package/dist/authorization/index.js +1 -1
  96. package/dist/authorization/protected-branch.d.ts +5 -4
  97. package/dist/authorization/protected-branch.js +7 -5
  98. package/dist/branch-health.d.ts +35 -8
  99. package/dist/branch-health.js +54 -18
  100. package/dist/branch-metadata-error.d.ts +27 -0
  101. package/dist/branch-metadata-error.js +23 -0
  102. package/dist/branch-metadata-file.d.ts +205 -24
  103. package/dist/branch-metadata-file.js +126 -25
  104. package/dist/branch-metadata.d.ts +45 -6
  105. package/dist/branch-metadata.js +142 -50
  106. package/dist/branch-provisioning.d.ts +167 -0
  107. package/dist/branch-provisioning.js +501 -0
  108. package/dist/branch-registry.d.ts +8 -0
  109. package/dist/branch-registry.js +61 -9
  110. package/dist/branch-schema-cache.d.ts +29 -12
  111. package/dist/branch-schema-cache.js +64 -21
  112. package/dist/branch-sparse.d.ts +23 -0
  113. package/dist/branch-sparse.js +118 -0
  114. package/dist/branch-workspace.d.ts +42 -3
  115. package/dist/branch-workspace.js +239 -100
  116. package/dist/build/asset-refs.d.ts +94 -0
  117. package/dist/build/asset-refs.js +267 -0
  118. package/dist/build/generate-ai-content.js +5 -0
  119. package/dist/build/inline-flight.d.ts +37 -0
  120. package/dist/build/inline-flight.js +142 -0
  121. package/dist/cli/asset-refs.d.ts +52 -0
  122. package/dist/cli/asset-refs.js +194 -0
  123. package/dist/cli/cli.d.ts +15 -1
  124. package/dist/cli/cli.js +8543 -3193
  125. package/dist/cli/configured-asset-store.d.ts +12 -0
  126. package/dist/cli/configured-asset-store.js +46 -0
  127. package/dist/cli/generate-ai-content.js +4244 -1072
  128. package/dist/cli/init.js +217 -126
  129. package/dist/cli/project-detect.d.ts +2 -0
  130. package/dist/cli/project-detect.js +2 -0
  131. package/dist/cli/template-files/Dockerfile.cms.template +13 -5
  132. package/dist/cli/template-files/cms-stack.ts.template +16 -13
  133. package/dist/client.d.ts +1 -2
  134. package/dist/client.js +1 -2
  135. package/dist/comment-store.d.ts +25 -0
  136. package/dist/comment-store.js +43 -8
  137. package/dist/config/flatten.js +2 -0
  138. package/dist/config/helpers.js +2 -2
  139. package/dist/config/index.d.ts +1 -1
  140. package/dist/config/schemas/config.d.ts +12 -29
  141. package/dist/config/schemas/config.js +9 -12
  142. package/dist/config/schemas/field.d.ts +3 -0
  143. package/dist/config/schemas/field.js +58 -4
  144. package/dist/config/schemas/media.d.ts +4 -13
  145. package/dist/config/schemas/media.js +5 -8
  146. package/dist/config/schemas/url.d.ts +2 -20
  147. package/dist/config/schemas/url.js +2 -25
  148. package/dist/config/types.d.ts +116 -22
  149. package/dist/config/types.js +3 -9
  150. package/dist/config/validation.d.ts +25 -4
  151. package/dist/config/validation.js +116 -3
  152. package/dist/content-id-index.js +2 -2
  153. package/dist/content-index-generation.d.ts +1 -1
  154. package/dist/content-index-generation.js +1 -1
  155. package/dist/content-listing.d.ts +10 -1
  156. package/dist/content-listing.js +22 -5
  157. package/dist/content-reader.d.ts +9 -0
  158. package/dist/content-reader.js +16 -11
  159. package/dist/content-store.d.ts +75 -12
  160. package/dist/content-store.js +249 -86
  161. package/dist/content-tree.js +2 -2
  162. package/dist/context.js +5 -2
  163. package/dist/dangling-reference-log.d.ts +17 -0
  164. package/dist/dangling-reference-log.js +29 -0
  165. package/dist/dev-content-watcher.d.ts +1 -1
  166. package/dist/dev-content-watcher.js +1 -1
  167. package/dist/editor/BranchManager.d.ts +23 -7
  168. package/dist/editor/BranchManager.js +119 -54
  169. package/dist/editor/CanopyEditor.d.ts +1 -1
  170. package/dist/editor/CanopyEditor.js +1 -2
  171. package/dist/editor/CommentsPanel.d.ts +14 -0
  172. package/dist/editor/CommentsPanel.js +68 -43
  173. package/dist/editor/Editor.d.ts +11 -5
  174. package/dist/editor/Editor.js +891 -218
  175. package/dist/editor/EditorAuthGate.d.ts +7 -1
  176. package/dist/editor/EditorAuthGate.js +41 -9
  177. package/dist/editor/EntryNavigator.d.ts +22 -0
  178. package/dist/editor/EntryNavigator.js +353 -105
  179. package/dist/editor/FormHeader.d.ts +25 -0
  180. package/dist/editor/FormHeader.js +82 -0
  181. package/dist/editor/FormRenderer.d.ts +27 -3
  182. package/dist/editor/FormRenderer.js +171 -76
  183. package/dist/editor/PreviewFrame.d.ts +40 -0
  184. package/dist/editor/PreviewFrame.js +215 -0
  185. package/dist/editor/PreviewPane.d.ts +47 -0
  186. package/dist/editor/PreviewPane.js +147 -0
  187. package/dist/editor/PreviewToolbarTools.d.ts +22 -0
  188. package/dist/editor/PreviewToolbarTools.js +73 -0
  189. package/dist/editor/admin/SystemHealthPanel.d.ts +2 -1
  190. package/dist/editor/admin/SystemHealthPanel.js +163 -33
  191. package/dist/editor/admin/useSystemHealth.d.ts +18 -0
  192. package/dist/editor/admin/useSystemHealth.js +70 -1
  193. package/dist/editor/branch-status.d.ts +17 -0
  194. package/dist/editor/branch-status.js +29 -0
  195. package/dist/editor/canopy-path.d.ts +9 -6
  196. package/dist/editor/canopy-path.js +8 -11
  197. package/dist/editor/client-reference-resolver.d.ts +43 -16
  198. package/dist/editor/client-reference-resolver.js +155 -64
  199. package/dist/editor/comments/BranchComments.d.ts +1 -1
  200. package/dist/editor/comments/BranchComments.js +2 -2
  201. package/dist/editor/comments/CloseRefusedNotice.d.ts +4 -0
  202. package/dist/editor/comments/CloseRefusedNotice.js +7 -0
  203. package/dist/editor/comments/CommentThreadsPopover.d.ts +47 -0
  204. package/dist/editor/comments/CommentThreadsPopover.js +274 -0
  205. package/dist/editor/comments/CommentWriteAlert.d.ts +11 -0
  206. package/dist/editor/comments/CommentWriteAlert.js +13 -0
  207. package/dist/editor/comments/EntryComments.d.ts +10 -4
  208. package/dist/editor/comments/EntryComments.js +14 -17
  209. package/dist/editor/comments/FieldWrapper.d.ts +18 -4
  210. package/dist/editor/comments/FieldWrapper.js +62 -28
  211. package/dist/editor/comments/InlineCommentThread.d.ts +9 -2
  212. package/dist/editor/comments/InlineCommentThread.js +11 -47
  213. package/dist/editor/comments/ThreadCarousel.d.ts +1 -1
  214. package/dist/editor/comments/ThreadCarousel.js +18 -21
  215. package/dist/editor/comments/ThreadReplyControls.d.ts +28 -0
  216. package/dist/editor/comments/ThreadReplyControls.js +92 -0
  217. package/dist/editor/comments/field-comment-context.d.ts +14 -0
  218. package/dist/editor/comments/field-comment-context.js +14 -0
  219. package/dist/editor/comments/form-comments.d.ts +48 -0
  220. package/dist/editor/comments/form-comments.js +178 -0
  221. package/dist/editor/comments/item-anchor-copy.d.ts +6 -0
  222. package/dist/editor/comments/item-anchor-copy.js +6 -0
  223. package/dist/editor/comments/move-focus-if-unmoved.d.ts +6 -0
  224. package/dist/editor/comments/move-focus-if-unmoved.js +11 -0
  225. package/dist/editor/comments/popover-placement.d.ts +18 -0
  226. package/dist/editor/comments/popover-placement.js +58 -0
  227. package/dist/editor/comments/use-tracked-writes.d.ts +16 -0
  228. package/dist/editor/comments/use-tracked-writes.js +53 -0
  229. package/dist/editor/components/BranchAccessList.d.ts +15 -0
  230. package/dist/editor/components/BranchAccessList.js +52 -0
  231. package/dist/editor/components/BranchLockBanner.d.ts +22 -0
  232. package/dist/editor/components/BranchLockBanner.js +39 -0
  233. package/dist/editor/components/BranchPill.d.ts +32 -0
  234. package/dist/editor/components/BranchPill.js +33 -0
  235. package/dist/editor/components/BranchesDrawer.d.ts +11 -0
  236. package/dist/editor/components/BranchesDrawer.js +5 -0
  237. package/dist/editor/components/ConfirmDeleteModal.d.ts +6 -1
  238. package/dist/editor/components/ConfirmDeleteModal.js +3 -2
  239. package/dist/editor/components/DestructiveMenuItem.d.ts +7 -0
  240. package/dist/editor/components/DestructiveMenuItem.js +8 -0
  241. package/dist/editor/components/EditorCrashScreen.d.ts +17 -0
  242. package/dist/editor/components/EditorCrashScreen.js +22 -0
  243. package/dist/editor/components/EditorErrorBoundary.d.ts +38 -0
  244. package/dist/editor/components/EditorErrorBoundary.js +40 -0
  245. package/dist/editor/components/EditorHeader.d.ts +56 -106
  246. package/dist/editor/components/EditorHeader.js +130 -131
  247. package/dist/editor/components/EditorRail.d.ts +49 -0
  248. package/dist/editor/components/EditorRail.js +65 -0
  249. package/dist/editor/components/EntryBreadcrumb.d.ts +33 -0
  250. package/dist/editor/components/EntryBreadcrumb.js +56 -0
  251. package/dist/editor/components/EntryCreateModal.d.ts +12 -7
  252. package/dist/editor/components/EntryCreateModal.js +51 -57
  253. package/dist/editor/components/NoEditPermissionNotice.d.ts +6 -5
  254. package/dist/editor/components/NoEditPermissionNotice.js +5 -4
  255. package/dist/editor/components/QuickOpenPalette.d.ts +22 -0
  256. package/dist/editor/components/QuickOpenPalette.js +66 -0
  257. package/dist/editor/components/ReadOnlyDraftNotice.d.ts +11 -0
  258. package/dist/editor/components/ReadOnlyDraftNotice.js +12 -0
  259. package/dist/editor/components/ReasonedMenuItem.d.ts +15 -0
  260. package/dist/editor/components/ReasonedMenuItem.js +15 -0
  261. package/dist/editor/components/ReferencedByList.d.ts +11 -0
  262. package/dist/editor/components/ReferencedByList.js +28 -0
  263. package/dist/editor/components/RelativeTime.d.ts +10 -0
  264. package/dist/editor/components/RelativeTime.js +10 -0
  265. package/dist/editor/components/RenameEntryModal.d.ts +9 -1
  266. package/dist/editor/components/RenameEntryModal.js +19 -31
  267. package/dist/editor/components/RetryToastMessage.d.ts +9 -0
  268. package/dist/editor/components/RetryToastMessage.js +6 -0
  269. package/dist/editor/components/SaveAllResult.d.ts +25 -0
  270. package/dist/editor/components/SaveAllResult.js +86 -0
  271. package/dist/editor/components/SaveSplitButton.d.ts +30 -0
  272. package/dist/editor/components/SaveSplitButton.js +108 -0
  273. package/dist/editor/components/StagedChangesDrawer.d.ts +39 -0
  274. package/dist/editor/components/StagedChangesDrawer.js +92 -0
  275. package/dist/editor/components/UnavailableEntryNotice.d.ts +6 -0
  276. package/dist/editor/components/UnavailableEntryNotice.js +9 -0
  277. package/dist/editor/components/UnavailableTypeMessage.d.ts +6 -0
  278. package/dist/editor/components/UnavailableTypeMessage.js +9 -0
  279. package/dist/editor/components/UndoToastMessage.d.ts +18 -0
  280. package/dist/editor/components/UndoToastMessage.js +10 -0
  281. package/dist/editor/components/UserBadge.d.ts +2 -5
  282. package/dist/editor/components/UserBadge.js +62 -33
  283. package/dist/editor/components/ValidationSummary.d.ts +14 -0
  284. package/dist/editor/components/ValidationSummary.js +24 -0
  285. package/dist/editor/components/index.d.ts +2 -2
  286. package/dist/editor/components/index.js +2 -2
  287. package/dist/editor/context/ApiClientContext.d.ts +8 -2
  288. package/dist/editor/context/ApiClientContext.js +19 -8
  289. package/dist/editor/context/AssetContext.d.ts +13 -35
  290. package/dist/editor/context/AssetContext.js +12 -31
  291. package/dist/editor/context/EditorStateContext.d.ts +4 -4
  292. package/dist/editor/context/EditorStateContext.js +4 -4
  293. package/dist/editor/context/SWRProvider.d.ts +3 -3
  294. package/dist/editor/context/SiteMdxAllowContext.d.ts +4 -0
  295. package/dist/editor/context/SiteMdxAllowContext.js +7 -0
  296. package/dist/editor/context/index.d.ts +2 -1
  297. package/dist/editor/context/index.js +2 -1
  298. package/dist/editor/contrast.d.ts +19 -0
  299. package/dist/editor/contrast.js +41 -0
  300. package/dist/editor/copy.d.ts +18 -0
  301. package/dist/editor/copy.js +18 -0
  302. package/dist/editor/editor-config.js +16 -0
  303. package/dist/editor/editor-utils.d.ts +34 -8
  304. package/dist/editor/editor-utils.js +42 -20
  305. package/dist/editor/entry-search.d.ts +20 -0
  306. package/dist/editor/entry-search.js +34 -0
  307. package/dist/editor/field-breadcrumb.d.ts +12 -0
  308. package/dist/editor/field-breadcrumb.js +85 -0
  309. package/dist/editor/field-props.d.ts +86 -0
  310. package/dist/editor/field-props.js +27 -0
  311. package/dist/editor/field-target.d.ts +30 -0
  312. package/dist/editor/field-target.js +77 -0
  313. package/dist/editor/fields/BlockField.d.ts +12 -0
  314. package/dist/editor/fields/BlockField.js +89 -73
  315. package/dist/editor/fields/CodeField.d.ts +2 -0
  316. package/dist/editor/fields/CodeField.js +6 -2
  317. package/dist/editor/fields/DateTimeField.d.ts +4 -29
  318. package/dist/editor/fields/DateTimeField.js +79 -41
  319. package/dist/editor/fields/ExpandAllButton.d.ts +6 -0
  320. package/dist/editor/fields/ExpandAllButton.js +4 -0
  321. package/dist/editor/fields/FieldCrashFallback.d.ts +17 -0
  322. package/dist/editor/fields/FieldCrashFallback.js +30 -0
  323. package/dist/editor/fields/FieldLabel.d.ts +37 -0
  324. package/dist/editor/fields/FieldLabel.js +19 -0
  325. package/dist/editor/fields/ImageField.d.ts +4 -0
  326. package/dist/editor/fields/ImageField.js +29 -14
  327. package/dist/editor/fields/InlineGroupField.js +4 -3
  328. package/dist/editor/fields/ItemList.d.ts +42 -0
  329. package/dist/editor/fields/ItemList.js +130 -0
  330. package/dist/editor/fields/MarkdownField.d.ts +32 -0
  331. package/dist/editor/fields/MarkdownField.js +223 -46
  332. package/dist/editor/fields/MdxImageDialog.js +1 -1
  333. package/dist/editor/fields/NumberField.d.ts +2 -0
  334. package/dist/editor/fields/NumberField.js +8 -5
  335. package/dist/editor/fields/NumberListField.d.ts +2 -0
  336. package/dist/editor/fields/NumberListField.js +19 -16
  337. package/dist/editor/fields/ObjectField.d.ts +2 -7
  338. package/dist/editor/fields/ObjectField.js +15 -5
  339. package/dist/editor/fields/ObjectListField.d.ts +29 -0
  340. package/dist/editor/fields/ObjectListField.js +57 -0
  341. package/dist/editor/fields/ReferenceField.d.ts +2 -0
  342. package/dist/editor/fields/ReferenceField.js +34 -9
  343. package/dist/editor/fields/SelectField.d.ts +2 -0
  344. package/dist/editor/fields/SelectField.js +11 -2
  345. package/dist/editor/fields/StringListField.d.ts +4 -1
  346. package/dist/editor/fields/StringListField.js +22 -8
  347. package/dist/editor/fields/TextField.d.ts +2 -0
  348. package/dist/editor/fields/TextField.js +6 -2
  349. package/dist/editor/fields/ToggleField.d.ts +2 -0
  350. package/dist/editor/fields/ToggleField.js +8 -3
  351. package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +1 -1
  352. package/dist/editor/fields/entry-link/InsertEntryLink.js +1 -1
  353. package/dist/editor/fields/form-expansion.d.ts +9 -0
  354. package/dist/editor/fields/form-expansion.js +2 -0
  355. package/dist/editor/fields/item-expansion.d.ts +15 -0
  356. package/dist/editor/fields/item-expansion.js +60 -0
  357. package/dist/editor/fields/list-item-keys.d.ts +8 -0
  358. package/dist/editor/fields/list-item-keys.js +50 -0
  359. package/dist/editor/fields/list-item-title.d.ts +20 -0
  360. package/dist/editor/fields/list-item-title.js +85 -0
  361. package/dist/editor/fields/markdown-export-options.d.ts +2 -0
  362. package/dist/editor/fields/markdown-export-options.js +8 -0
  363. package/dist/editor/fields/markdown-fidelity-visitors.d.ts +11 -0
  364. package/dist/editor/fields/markdown-fidelity-visitors.js +160 -0
  365. package/dist/editor/fields/mdx-jsx-support.d.ts +5 -1
  366. package/dist/editor/fields/mdx-jsx-support.js +157 -69
  367. package/dist/editor/fields/rich-text-failures.d.ts +5 -0
  368. package/dist/editor/fields/rich-text-failures.js +26 -0
  369. package/dist/editor/fields/toolbar-wrap.d.ts +7 -0
  370. package/dist/editor/fields/toolbar-wrap.js +35 -0
  371. package/dist/editor/form-outline.d.ts +13 -0
  372. package/dist/editor/form-outline.js +70 -0
  373. package/dist/editor/group-manager/GroupCard.d.ts +4 -1
  374. package/dist/editor/group-manager/GroupCard.js +12 -3
  375. package/dist/editor/group-manager/GroupForm.js +1 -1
  376. package/dist/editor/group-manager/InternalGroupsTab.d.ts +2 -1
  377. package/dist/editor/group-manager/InternalGroupsTab.js +4 -4
  378. package/dist/editor/group-manager/MemberList.d.ts +2 -1
  379. package/dist/editor/group-manager/MemberList.js +15 -4
  380. package/dist/editor/group-manager/hooks/useGroupState.d.ts +5 -0
  381. package/dist/editor/group-manager/hooks/useGroupState.js +30 -7
  382. package/dist/editor/group-manager/index.js +34 -5
  383. package/dist/editor/group-manager/types.d.ts +5 -2
  384. package/dist/editor/hooks/create-branch-request.d.ts +20 -0
  385. package/dist/editor/hooks/create-branch-request.js +54 -0
  386. package/dist/editor/hooks/save-all.d.ts +68 -0
  387. package/dist/editor/hooks/save-all.js +61 -0
  388. package/dist/editor/hooks/useBranchActions.d.ts +11 -1
  389. package/dist/editor/hooks/useBranchActions.js +42 -19
  390. package/dist/editor/hooks/useBranchManager.d.ts +21 -0
  391. package/dist/editor/hooks/useBranchManager.js +321 -125
  392. package/dist/editor/hooks/useBranchesData.d.ts +8 -4
  393. package/dist/editor/hooks/useBranchesData.js +9 -5
  394. package/dist/editor/hooks/useCommentSystem.d.ts +14 -2
  395. package/dist/editor/hooks/useCommentSystem.js +79 -55
  396. package/dist/editor/hooks/useCommentsData.d.ts +11 -7
  397. package/dist/editor/hooks/useCommentsData.js +20 -19
  398. package/dist/editor/hooks/useDraftManager.d.ts +77 -3
  399. package/dist/editor/hooks/useDraftManager.js +887 -94
  400. package/dist/editor/hooks/useEditorLayout.d.ts +53 -7
  401. package/dist/editor/hooks/useEditorLayout.js +98 -20
  402. package/dist/editor/hooks/useEntriesData.d.ts +2 -1
  403. package/dist/editor/hooks/useEntriesData.js +18 -4
  404. package/dist/editor/hooks/useEntryManager.d.ts +41 -2
  405. package/dist/editor/hooks/useEntryManager.js +227 -41
  406. package/dist/editor/hooks/useGroupManager.js +13 -16
  407. package/dist/editor/hooks/usePermissionManager.js +14 -6
  408. package/dist/editor/hooks/usePreviewMarks.d.ts +21 -0
  409. package/dist/editor/hooks/usePreviewMarks.js +33 -0
  410. package/dist/editor/hooks/useReferenceResolution.d.ts +10 -3
  411. package/dist/editor/hooks/useReferenceResolution.js +34 -177
  412. package/dist/editor/hooks/useSchemaManager.d.ts +25 -6
  413. package/dist/editor/hooks/useSchemaManager.js +97 -39
  414. package/dist/editor/hooks/useUserMetadata.d.ts +14 -4
  415. package/dist/editor/hooks/useUserMetadata.js +76 -47
  416. package/dist/editor/hooks/user-metadata-batcher.d.ts +8 -0
  417. package/dist/editor/hooks/user-metadata-batcher.js +33 -0
  418. package/dist/editor/media/AssetCard.d.ts +6 -7
  419. package/dist/editor/media/AssetCard.js +24 -31
  420. package/dist/editor/media/AssetListRow.d.ts +16 -0
  421. package/dist/editor/media/AssetListRow.js +41 -0
  422. package/dist/editor/media/CropStep.js +6 -1
  423. package/dist/editor/media/MediaLibrary.d.ts +4 -3
  424. package/dist/editor/media/MediaLibrary.js +11 -4
  425. package/dist/editor/media/MediaLibraryBody.d.ts +3 -3
  426. package/dist/editor/media/MediaLibraryBody.js +195 -80
  427. package/dist/editor/media/MediaLibrarySkeleton.d.ts +6 -0
  428. package/dist/editor/media/MediaLibrarySkeleton.js +14 -0
  429. package/dist/editor/media/crop-math.d.ts +3 -4
  430. package/dist/editor/media/crop-math.js +11 -22
  431. package/dist/editor/media/editor-image-src.d.ts +8 -0
  432. package/dist/editor/media/editor-image-src.js +10 -0
  433. package/dist/editor/media/format-bytes.d.ts +2 -0
  434. package/dist/editor/media/format-bytes.js +23 -0
  435. package/dist/editor/media/media-library-prefs.d.ts +23 -0
  436. package/dist/editor/media/media-library-prefs.js +49 -0
  437. package/dist/editor/media/media-library-view.d.ts +34 -0
  438. package/dist/editor/media/media-library-view.js +40 -0
  439. package/dist/editor/media/useAssetLibrary.d.ts +30 -0
  440. package/dist/editor/media/useAssetLibrary.js +126 -0
  441. package/dist/editor/media/useStableAssetOrder.d.ts +11 -0
  442. package/dist/editor/media/useStableAssetOrder.js +37 -0
  443. package/dist/editor/media/useThumbnailFailure.d.ts +6 -0
  444. package/dist/editor/media/useThumbnailFailure.js +16 -0
  445. package/dist/editor/permission-manager/GroupSelector.js +2 -2
  446. package/dist/editor/permission-manager/PermissionEditor.d.ts +1 -1
  447. package/dist/editor/permission-manager/PermissionEditor.js +15 -4
  448. package/dist/editor/permission-manager/PermissionLevelBadge.js +1 -1
  449. package/dist/editor/permission-manager/PermissionTree.d.ts +1 -1
  450. package/dist/editor/permission-manager/UserSelector.d.ts +1 -1
  451. package/dist/editor/permission-manager/UserSelector.js +3 -3
  452. package/dist/editor/permission-manager/index.js +12 -3
  453. package/dist/editor/permission-manager/types.d.ts +5 -2
  454. package/dist/editor/platform.d.ts +3 -0
  455. package/dist/editor/platform.js +9 -0
  456. package/dist/editor/preview-asset-base.d.ts +9 -0
  457. package/dist/editor/preview-asset-base.js +17 -0
  458. package/dist/editor/preview-bridge.d.ts +51 -27
  459. package/dist/editor/preview-bridge.js +103 -144
  460. package/dist/editor/preview-marks.d.ts +15 -0
  461. package/dist/editor/preview-marks.js +74 -0
  462. package/dist/editor/preview-path.d.ts +12 -0
  463. package/dist/editor/preview-path.js +45 -1
  464. package/dist/editor/preview-scale.d.ts +27 -0
  465. package/dist/editor/preview-scale.js +34 -0
  466. package/dist/editor/raw-asset-base.d.ts +5 -0
  467. package/dist/editor/raw-asset-base.js +14 -0
  468. package/dist/editor/relative-time.d.ts +4 -4
  469. package/dist/editor/relative-time.js +16 -8
  470. package/dist/editor/schema-editor/CollectionEditor.d.ts +20 -3
  471. package/dist/editor/schema-editor/CollectionEditor.js +361 -62
  472. package/dist/editor/schema-editor/EntryTypeEditor.d.ts +5 -1
  473. package/dist/editor/schema-editor/EntryTypeEditor.js +11 -6
  474. package/dist/editor/schema-editor/collection-draft.d.ts +22 -0
  475. package/dist/editor/schema-editor/collection-draft.js +40 -0
  476. package/dist/editor/schema-editor/index.d.ts +1 -1
  477. package/dist/editor/schema-label.d.ts +10 -0
  478. package/dist/editor/schema-label.js +17 -0
  479. package/dist/editor/settings-conflict.d.ts +5 -0
  480. package/dist/editor/settings-conflict.js +8 -0
  481. package/dist/editor/shell/ActivityRail.d.ts +37 -0
  482. package/dist/editor/shell/ActivityRail.js +91 -0
  483. package/dist/editor/shell/EditorShell.d.ts +17 -0
  484. package/dist/editor/shell/EditorShell.js +31 -0
  485. package/dist/editor/shell/PaneLayout.d.ts +28 -0
  486. package/dist/editor/shell/PaneLayout.js +116 -0
  487. package/dist/editor/shell/SidePanelHost.d.ts +35 -0
  488. package/dist/editor/shell/SidePanelHost.js +184 -0
  489. package/dist/editor/shell/TopBar.d.ts +12 -0
  490. package/dist/editor/shell/TopBar.js +14 -0
  491. package/dist/editor/shell/host-chrome.d.ts +16 -0
  492. package/dist/editor/shell/host-chrome.js +69 -0
  493. package/dist/editor/slug.d.ts +16 -0
  494. package/dist/editor/slug.js +43 -0
  495. package/dist/editor/theme.d.ts +2 -1
  496. package/dist/editor/theme.js +314 -13
  497. package/dist/editor/unanswered.d.ts +17 -0
  498. package/dist/editor/unanswered.js +26 -0
  499. package/dist/editor/unavailable-entry-type.d.ts +20 -0
  500. package/dist/editor/unavailable-entry-type.js +28 -0
  501. package/dist/editor/undo-removal.d.ts +57 -0
  502. package/dist/editor/undo-removal.js +163 -0
  503. package/dist/editor/user-display.d.ts +4 -0
  504. package/dist/editor/user-display.js +5 -0
  505. package/dist/editor/utils/confirm-modal.d.ts +8 -0
  506. package/dist/editor/utils/confirm-modal.js +12 -0
  507. package/dist/editor/utils/editor-errors.d.ts +19 -0
  508. package/dist/editor/utils/editor-errors.js +32 -0
  509. package/dist/editor/utils/focus-return.d.ts +56 -0
  510. package/dist/editor/utils/focus-return.js +106 -0
  511. package/dist/entry-link-resolver.d.ts +11 -1
  512. package/dist/entry-link-resolver.js +65 -5
  513. package/dist/entry-schema-registry.d.ts +3 -3
  514. package/dist/entry-schema-registry.js +7 -4
  515. package/dist/entry-schema.d.ts +49 -3
  516. package/dist/entry-schema.js +18 -0
  517. package/dist/git-manager.d.ts +172 -10
  518. package/dist/git-manager.js +449 -107
  519. package/dist/github-service.d.ts +39 -2
  520. package/dist/github-service.js +101 -7
  521. package/dist/http/handler.js +74 -9
  522. package/dist/http/types.d.ts +2 -0
  523. package/dist/http/worker-not-ready.d.ts +9 -4
  524. package/dist/http/worker-not-ready.js +59 -6
  525. package/dist/index.d.ts +2 -0
  526. package/dist/index.js +3 -0
  527. package/dist/item-keys.d.ts +46 -0
  528. package/dist/item-keys.js +235 -0
  529. package/dist/operating-mode/editor-mode-check.d.ts +15 -0
  530. package/dist/operating-mode/editor-mode-check.js +24 -0
  531. package/dist/operating-mode/mode-env.d.ts +13 -14
  532. package/dist/operating-mode/mode-env.js +13 -14
  533. package/dist/operating-mode/types.d.ts +2 -2
  534. package/dist/paths/branch.d.ts +0 -1
  535. package/dist/paths/branch.js +1 -8
  536. package/dist/paths/index.d.ts +1 -1
  537. package/dist/paths/index.js +1 -1
  538. package/dist/paths/validation.js +0 -2
  539. package/dist/preview.d.ts +8 -0
  540. package/dist/preview.js +7 -0
  541. package/dist/reference-resolver.js +1 -0
  542. package/dist/resolve-canopy-user.d.ts +1 -1
  543. package/dist/resolve-canopy-user.js +1 -1
  544. package/dist/schema/meta-loader.d.ts +18 -8
  545. package/dist/schema/meta-loader.js +42 -9
  546. package/dist/schema/registry-fingerprint.d.ts +14 -0
  547. package/dist/schema/registry-fingerprint.js +63 -0
  548. package/dist/schema/resolver.d.ts +7 -4
  549. package/dist/schema/resolver.js +7 -6
  550. package/dist/schema/schema-store.d.ts +7 -10
  551. package/dist/schema/schema-store.js +13 -11
  552. package/dist/schema/schema-unavailable-error.d.ts +11 -0
  553. package/dist/schema/schema-unavailable-error.js +15 -0
  554. package/dist/schema/types.d.ts +22 -0
  555. package/dist/schema-registry-record.d.ts +35 -0
  556. package/dist/schema-registry-record.js +134 -0
  557. package/dist/server.d.ts +79 -9
  558. package/dist/server.js +62 -8
  559. package/dist/services.d.ts +33 -5
  560. package/dist/services.js +155 -37
  561. package/dist/settings-workspace.d.ts +23 -3
  562. package/dist/settings-workspace.js +159 -45
  563. package/dist/stamp-on-publish.d.ts +36 -0
  564. package/dist/stamp-on-publish.js +71 -0
  565. package/dist/static/index.d.ts +58 -5
  566. package/dist/static/index.js +133 -3
  567. package/dist/static/seo.d.ts +5 -5
  568. package/dist/static/seo.js +5 -5
  569. package/dist/submission-attribution.d.ts +8 -0
  570. package/dist/submission-attribution.js +22 -0
  571. package/dist/system-users.d.ts +12 -0
  572. package/dist/system-users.js +12 -0
  573. package/dist/task-queue/cms-task-queue.d.ts +1 -1
  574. package/dist/task-queue/cms-task-queue.js +1 -1
  575. package/dist/task-queue/index.d.ts +1 -1
  576. package/dist/task-queue/index.js +1 -1
  577. package/dist/task-queue/task-queue.d.ts +6 -0
  578. package/dist/task-queue/task-queue.js +29 -0
  579. package/dist/task-queue/worker-status.d.ts +35 -9
  580. package/dist/task-queue/worker-status.js +84 -17
  581. package/dist/types.d.ts +90 -9
  582. package/dist/url-collision.js +3 -3
  583. package/dist/url-exclusivity-fixtures.d.ts +8 -1
  584. package/dist/url-exclusivity-fixtures.js +11 -1
  585. package/dist/user.js +2 -1
  586. package/dist/utils/atomic-write.js +2 -1
  587. package/dist/utils/base-branch.d.ts +13 -0
  588. package/dist/utils/base-branch.js +23 -0
  589. package/dist/utils/content-serialize.d.ts +15 -7
  590. package/dist/utils/content-serialize.js +353 -51
  591. package/dist/utils/content-write-lock.d.ts +6 -1
  592. package/dist/utils/content-write-lock.js +21 -6
  593. package/dist/utils/debug.d.ts +1 -1
  594. package/dist/utils/debug.js +5 -3
  595. package/dist/utils/error.js +13 -2
  596. package/dist/utils/escape-text.d.ts +7 -0
  597. package/dist/utils/escape-text.js +27 -0
  598. package/dist/utils/fs.d.ts +12 -4
  599. package/dist/utils/fs.js +18 -5
  600. package/dist/utils/git.d.ts +21 -1
  601. package/dist/utils/git.js +63 -8
  602. package/dist/utils/json-source-splice.d.ts +14 -0
  603. package/dist/utils/json-source-splice.js +120 -0
  604. package/dist/utils/markdown-body-splice.d.ts +39 -0
  605. package/dist/utils/markdown-body-splice.js +421 -0
  606. package/dist/utils/occ-json-write.js +18 -12
  607. package/dist/utils/provision-log.d.ts +25 -0
  608. package/dist/utils/provision-log.js +49 -0
  609. package/dist/utils/provisioning-lock.d.ts +32 -1
  610. package/dist/utils/provisioning-lock.js +78 -32
  611. package/dist/utils/sanitize-href.d.ts +9 -23
  612. package/dist/utils/sanitize-href.js +14 -28
  613. package/dist/utils/title-field.d.ts +10 -0
  614. package/dist/utils/title-field.js +47 -0
  615. package/dist/utils/yaml-source-splice.d.ts +58 -0
  616. package/dist/utils/yaml-source-splice.js +515 -0
  617. package/dist/validation/block-structural-keys.d.ts +1 -1
  618. package/dist/validation/block-structural-keys.js +1 -1
  619. package/dist/validation/deletion-checker.d.ts +21 -29
  620. package/dist/validation/deletion-checker.js +41 -117
  621. package/dist/validation/entry-validator.d.ts +6 -10
  622. package/dist/validation/entry-validator.js +19 -26
  623. package/dist/validation/field-traversal.d.ts +22 -0
  624. package/dist/validation/field-traversal.js +39 -8
  625. package/dist/validation/markdown-safety.d.ts +68 -0
  626. package/dist/validation/markdown-safety.js +596 -0
  627. package/dist/validation/mdx-allowlist.d.ts +55 -0
  628. package/dist/validation/mdx-allowlist.js +183 -0
  629. package/dist/validation/reference-validator.d.ts +2 -0
  630. package/dist/validation/reference-validator.js +3 -0
  631. package/dist/version.d.ts +1 -1
  632. package/dist/version.js +1 -1
  633. package/dist/worker/branch-policy.d.ts +124 -0
  634. package/dist/worker/branch-policy.js +243 -0
  635. package/dist/worker/bundle-header.d.ts +117 -0
  636. package/dist/worker/bundle-header.js +253 -0
  637. package/dist/worker/cms-worker.d.ts +236 -142
  638. package/dist/worker/cms-worker.js +772 -285
  639. package/dist/worker/gateway-egress.d.ts +43 -0
  640. package/dist/worker/gateway-egress.js +209 -0
  641. package/dist/worker/gateway-instance.d.ts +42 -0
  642. package/dist/worker/gateway-instance.js +129 -0
  643. package/dist/worker/git-process.d.ts +81 -0
  644. package/dist/worker/git-process.js +234 -0
  645. package/dist/worker/git-sync.d.ts +34 -17
  646. package/dist/worker/git-sync.js +394 -131
  647. package/dist/worker/github-auth.d.ts +9 -9
  648. package/dist/worker/github-auth.js +13 -15
  649. package/dist/worker/github-gateway-http.d.ts +62 -0
  650. package/dist/worker/github-gateway-http.js +977 -0
  651. package/dist/worker/github-gateway-wire.d.ts +590 -0
  652. package/dist/worker/github-gateway-wire.js +488 -0
  653. package/dist/worker/github-gateway.d.ts +238 -0
  654. package/dist/worker/github-gateway.js +726 -0
  655. package/dist/worker/github-mirror-upkeep.d.ts +75 -0
  656. package/dist/worker/github-mirror-upkeep.js +266 -0
  657. package/dist/worker/github-mirror.d.ts +364 -0
  658. package/dist/worker/github-mirror.js +1030 -0
  659. package/dist/worker/github-transfer.d.ts +56 -0
  660. package/dist/worker/github-transfer.js +444 -0
  661. package/dist/worker/history-rewrite.d.ts +4 -5
  662. package/dist/worker/history-rewrite.js +12 -17
  663. package/dist/worker/provisioned-workspace.d.ts +5 -5
  664. package/dist/worker/provisioned-workspace.js +5 -5
  665. package/dist/worker/rebase.d.ts +1 -1
  666. package/dist/worker/rebase.js +58 -54
  667. package/dist/worker/remote-git-maintenance.d.ts +3 -0
  668. package/dist/worker/remote-git-maintenance.js +12 -0
  669. package/dist/worker/schema-gate.d.ts +49 -0
  670. package/dist/worker/schema-gate.js +226 -0
  671. package/dist/worker/self-checks.d.ts +107 -0
  672. package/dist/worker/self-checks.js +358 -0
  673. package/dist/worker/shared-repo-git.d.ts +96 -0
  674. package/dist/worker/shared-repo-git.js +459 -0
  675. package/dist/worker/sparse-cone.d.ts +20 -0
  676. package/dist/worker/sparse-cone.js +136 -0
  677. package/dist/worker/stale-mirror.d.ts +82 -0
  678. package/dist/worker/stale-mirror.js +130 -0
  679. package/dist/worker/task-runner.d.ts +5 -3
  680. package/dist/worker/task-runner.js +287 -186
  681. package/dist/worker/worker-context.d.ts +36 -37
  682. package/package.json +35 -7
  683. package/dist/editor/EditorPanes.d.ts +0 -10
  684. package/dist/editor/EditorPanes.js +0 -98
  685. package/dist/editor/components/EditorFooter.d.ts +0 -11
  686. package/dist/editor/components/EditorFooter.js +0 -9
  687. package/dist/editor/components/EditorSidebar.d.ts +0 -67
  688. package/dist/editor/components/EditorSidebar.js +0 -22
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Collect the asset URLs a static build references, so a release can make them exist first.
3
+ *
4
+ * The public `/assets/t/` path serves only what is stored, and widths are chosen by site code at
5
+ * render time, so build output is the one place every final URL appears. The adopter contract
6
+ * that follows: every `/assets/t/` URL the site can request must appear as text in its build
7
+ * output (ARCHITECTURE.md, "Why transform by URL directive and materialize at release?").
8
+ */
9
+ import fs from 'node:fs/promises';
10
+ import path from 'node:path';
11
+ import { z } from 'zod';
12
+ import { ASSET_PREFIXES } from '../assets/asset-prefixes.js';
13
+ import { canonicalizeTransformPath } from '../assets/transform-directives.js';
14
+ import { atomicWriteFile } from '../utils/atomic-write.js';
15
+ import { extractInlineFlight } from './inline-flight.js';
16
+ /** @internal Written into the scanned directory, so a manifest the adopter builds afterwards covers it. */
17
+ export const ASSET_REFS_FILENAME = 'canopy-asset-refs.json';
18
+ /**
19
+ * Text outputs a URL can hide in: pages, RSC payloads, data, scripts, styles, feeds, generated
20
+ * markdown. A file with no extension (a route handler's output) is scanned unless it is binary.
21
+ */
22
+ const SCANNED_EXTENSIONS = new Set([
23
+ '',
24
+ '.html',
25
+ '.htm',
26
+ '.txt',
27
+ '.rsc',
28
+ '.json',
29
+ '.js',
30
+ '.mjs',
31
+ '.cjs',
32
+ '.css',
33
+ '.xml',
34
+ '.svg',
35
+ '.md',
36
+ '.webmanifest',
37
+ ]);
38
+ /**
39
+ * Anchored on the path, never on an origin or a mount prefix, so whatever precedes `/assets/` —
40
+ * an absolute origin, a basePath, the editor's authenticated prefix — is dropped. The directive
41
+ * and filename classes stop at anything that ends a URL in HTML, JSON, JS or CSS (quotes,
42
+ * whitespace, a backslash escape, parens, a query; the filename also at a srcset comma) or at any
43
+ * non-ASCII character (typographic quotes and dashes in prose; no stored key has one), and exclude
44
+ * `{`, `}` and `$`, so a URL template in a script never reads as a URL. A non-ASCII character
45
+ * inside a directive segment therefore ends the match and the URL is not seen. The hash class
46
+ * admits upper case only so that such a URL is reported rather than skipped.
47
+ */
48
+ const URL_STOP = String.raw `\s"'\x60<>()\\/?#&{}$\u0080-\uffff`;
49
+ // eslint-disable-next-line security/detect-non-literal-regexp -- built from constants above
50
+ const TRANSFORM_URL_RE = new RegExp(String.raw `/${ASSET_PREFIXES.transform}/([^${URL_STOP}]+)/([a-fA-F0-9]{32})/([^${URL_STOP},]+)`, 'g');
51
+ // eslint-disable-next-line security/detect-non-literal-regexp -- built from constants above
52
+ const STATIC_URL_RE = new RegExp(String.raw `/${ASSET_PREFIXES.public}/([a-fA-F0-9]{32})/([^${URL_STOP},]+)`, 'g');
53
+ const STATIC_FILENAME_RE = /^[a-z0-9-]+\.[a-z0-9]{1,10}$/;
54
+ const HASH32_RE = /^[a-f0-9]{32}$/;
55
+ const assetRefEntrySchema = z
56
+ .object({
57
+ key: z.string().min(1),
58
+ routes: z.array(z.string()),
59
+ files: z.array(z.string()),
60
+ })
61
+ .strict();
62
+ const assetRefsFileSchema = z
63
+ .object({
64
+ version: z.literal(1),
65
+ transforms: z.array(assetRefEntrySchema),
66
+ statics: z.array(assetRefEntrySchema),
67
+ })
68
+ .strict();
69
+ /** The output references URLs that cannot be served from the store; nothing was written. */
70
+ export class AssetRefsError extends Error {
71
+ constructor(problems) {
72
+ super(`${problems.length} asset URL(s) in the build output cannot be served from the store:\n` +
73
+ problems.map((p) => ` ${p.file}: ${p.url}\n ${p.error}`).join('\n'));
74
+ this.problems = problems;
75
+ this.name = 'AssetRefsError';
76
+ }
77
+ }
78
+ /** Output-relative POSIX paths of every file under `root` with a scanned extension, sorted. */
79
+ async function listScannedFiles(root) {
80
+ const entries = await fs.readdir(root, { recursive: true, withFileTypes: true });
81
+ return entries
82
+ .filter((entry) => entry.isFile() && SCANNED_EXTENSIONS.has(path.extname(entry.name)))
83
+ .map((entry) => path.relative(root, path.join(entry.parentPath, entry.name)))
84
+ .map((rel) => rel.split(path.sep).join('/'))
85
+ .filter((rel) => rel !== ASSET_REFS_FILENAME)
86
+ .sort();
87
+ }
88
+ const HTML_FILE_RE = /\.html?$/;
89
+ /** The route a static-export HTML file serves (`about/index.html` and `about.html` are `/about`). */
90
+ function routeForFile(file) {
91
+ if (!HTML_FILE_RE.test(file))
92
+ return undefined;
93
+ const withoutExt = file.replace(HTML_FILE_RE, '');
94
+ const route = withoutExt === 'index' ? '' : withoutExt.replace(/\/index$/, '');
95
+ return `/${route}`;
96
+ }
97
+ const ENCODED_ASSETS = /%2[fF]assets%2[fF]/g;
98
+ const RUN_STOP = /[\s"'`<>&]/;
99
+ /** Each `%XX` escape of an ASCII character, decoded on its own; anything else stays as written. */
100
+ function decodeAsciiEscapes(text) {
101
+ return text.replace(/%([0-7][0-9a-fA-F])/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
102
+ }
103
+ /** One malformed or non-UTF-8 escape elsewhere in the run must not hide the URL inside it. */
104
+ function decodeOrKeep(run) {
105
+ try {
106
+ return decodeURIComponent(run);
107
+ }
108
+ catch {
109
+ return decodeAsciiEscapes(run);
110
+ }
111
+ }
112
+ /**
113
+ * Decode, whole, each percent-encoded run holding an encoded `/assets/` (an image optimizer's
114
+ * `?url=`), so an encoded `%20` or `%3F` after the URL ends it just as a literal one would. Runs are
115
+ * found by expanding outward from each match, so the scan stays linear on long text with no stop
116
+ * character.
117
+ */
118
+ function decodeEncodedAssetRuns(text) {
119
+ let out = '';
120
+ let last = 0;
121
+ for (const match of text.matchAll(ENCODED_ASSETS)) {
122
+ if (match.index < last)
123
+ continue;
124
+ let start = match.index;
125
+ while (start > last && !RUN_STOP.test(text[start - 1]))
126
+ start--;
127
+ let end = match.index + match[0].length;
128
+ while (end < text.length && !RUN_STOP.test(text[end]))
129
+ end++;
130
+ out += text.slice(last, start) + decodeOrKeep(text.slice(start, end));
131
+ last = end;
132
+ }
133
+ return out + text.slice(last);
134
+ }
135
+ /** JSON and JS may escape `/` as a backslash-slash or a `u002F` unicode escape. */
136
+ function decodeUrlEscapes(text) {
137
+ return decodeEncodedAssetRuns(text.replace(/\\u002[fF]/g, '/').replace(/\\\//g, '/'));
138
+ }
139
+ /**
140
+ * A slug and ext end in `[a-z0-9]`, so punctuation after a URL in prose is not part of it. Trimmed
141
+ * wherever it occurs: an RSC payload carries prose as JSON strings, where a sentence-final URL is
142
+ * followed by a quote exactly as an attribute value is.
143
+ */
144
+ function trimTrailingPunctuation(url, filename) {
145
+ const trimmed = filename.replace(/[.:;!?]+$/, '');
146
+ return [url.slice(0, url.length - (filename.length - trimmed.length)), trimmed];
147
+ }
148
+ /** A NUL in the first 8 KiB marks a file binary, close to git's own test; only that block is read. */
149
+ async function startsBinary(filePath) {
150
+ const handle = await fs.open(filePath, 'r');
151
+ try {
152
+ const block = Buffer.alloc(8192);
153
+ const { bytesRead } = await handle.read(block, 0, block.length, 0);
154
+ return block.subarray(0, bytesRead).includes(0);
155
+ }
156
+ finally {
157
+ await handle.close();
158
+ }
159
+ }
160
+ class RefCollector {
161
+ constructor() {
162
+ this.entries = new Map();
163
+ }
164
+ add(key, file) {
165
+ const entry = this.entries.get(key) ?? { routes: new Set(), files: new Set() };
166
+ entry.files.add(file);
167
+ const route = routeForFile(file);
168
+ if (route !== undefined)
169
+ entry.routes.add(route);
170
+ this.entries.set(key, entry);
171
+ }
172
+ toEntries() {
173
+ return [...this.entries.keys()].sort().map((key) => {
174
+ const entry = this.entries.get(key);
175
+ return {
176
+ key,
177
+ routes: [...(entry?.routes ?? [])].sort(),
178
+ files: [...(entry?.files ?? [])].sort(),
179
+ };
180
+ });
181
+ }
182
+ }
183
+ /**
184
+ * Scan `outDir` for `/assets/t/...` transform URLs and `/assets/{hash32}/...` static URLs and
185
+ * write their stored keys to `outDir/canopy-asset-refs.json`, sorted so the same output always
186
+ * yields the same file. Throws `AssetRefsError`, writing nothing, if any transform URL is not in
187
+ * canonical form or any static URL is malformed: only canonical keys are stored, and the public
188
+ * path is to compute nothing on a miss.
189
+ */
190
+ export async function collectAssetRefs(outDir) {
191
+ const root = path.resolve(outDir);
192
+ const files = await listScannedFiles(root);
193
+ const transforms = new RefCollector();
194
+ const statics = new RefCollector();
195
+ const problems = [];
196
+ const scan = (file, raw) => {
197
+ const text = decodeUrlEscapes(raw);
198
+ for (const match of text.matchAll(TRANSFORM_URL_RE)) {
199
+ const [url, filename] = trimTrailingPunctuation(match[0], match[3]);
200
+ const [, encodedDirectives, hash32] = match;
201
+ // A loader that encodes the directive segment alone is still requesting this key.
202
+ const directives = decodeAsciiEscapes(encodedDirectives);
203
+ const canonical = canonicalizeTransformPath([directives, hash32, filename], 'any');
204
+ if (!canonical.ok) {
205
+ problems.push({ file, url, error: canonical.error });
206
+ }
207
+ else if (!canonical.isCanonical) {
208
+ problems.push({
209
+ file,
210
+ url,
211
+ error: `Not canonical; assetUrl would write /${ASSET_PREFIXES.transform}/${canonical.canonicalPath}`,
212
+ });
213
+ }
214
+ else {
215
+ transforms.add(`${ASSET_PREFIXES.transform}/${canonical.canonicalPath}`, file);
216
+ }
217
+ }
218
+ for (const match of text.matchAll(STATIC_URL_RE)) {
219
+ const [url, filename] = trimTrailingPunctuation(match[0], match[2]);
220
+ const hash32 = match[1];
221
+ if (!HASH32_RE.test(hash32) || !STATIC_FILENAME_RE.test(filename)) {
222
+ problems.push({ file, url, error: 'Not a stored static asset path' });
223
+ }
224
+ else {
225
+ statics.add(`${ASSET_PREFIXES.public}/${hash32}/${filename}`, file);
226
+ }
227
+ }
228
+ };
229
+ let scannedFiles = 0;
230
+ for (const file of files) {
231
+ const filePath = path.join(root, file);
232
+ if (path.extname(file) === '' && (await startsBinary(filePath)))
233
+ continue;
234
+ scannedFiles++;
235
+ const text = await fs.readFile(filePath, 'utf-8');
236
+ if (!HTML_FILE_RE.test(file)) {
237
+ scan(file, text);
238
+ continue;
239
+ }
240
+ // A page's inline RSC payload is split across scripts at arbitrary bytes (inline-flight.ts).
241
+ const page = extractInlineFlight(text);
242
+ scan(file, page.markup);
243
+ for (const flight of page.texts)
244
+ scan(file, flight);
245
+ for (const { script, error } of page.problems)
246
+ problems.push({ file, url: script, error });
247
+ }
248
+ if (problems.length > 0)
249
+ throw new AssetRefsError(problems);
250
+ const refs = {
251
+ version: 1,
252
+ transforms: transforms.toEntries(),
253
+ statics: statics.toEntries(),
254
+ };
255
+ const filePath = path.join(root, ASSET_REFS_FILENAME);
256
+ await atomicWriteFile(filePath, `${JSON.stringify(refs, null, 2)}\n`);
257
+ return { refs, filePath, scannedFiles };
258
+ }
259
+ /** Read and validate a refs file `collectAssetRefs` wrote. */
260
+ export async function readAssetRefsFile(filePath) {
261
+ const raw = JSON.parse(await fs.readFile(filePath, 'utf-8'));
262
+ const parsed = assetRefsFileSchema.safeParse(raw);
263
+ if (!parsed.success) {
264
+ throw new Error(`${filePath} is not a valid asset refs file: ${parsed.error.message}`);
265
+ }
266
+ return parsed.data;
267
+ }
@@ -181,6 +181,11 @@ export async function generateAIContentFiles(options) {
181
181
  else {
182
182
  const schemaCache = new BranchSchemaCache(config.mode);
183
183
  const cached = await schemaCache.getSchema(branchRoot, entrySchemaRegistry, contentRootName);
184
+ // A branch workspace resolves degraded (see BranchSchemaCache); a build command fails instead.
185
+ if (cached.issues.length > 0) {
186
+ throw new Error(`AI content generation: the schema in ${branchRoot} does not match this code's entry ` +
187
+ `schema registry:\n${cached.issues.map((issue) => ` - ${issue.message}`).join('\n')}`);
188
+ }
184
189
  flatSchema = cached.flatSchema;
185
190
  }
186
191
  // Fail the build on abandoned create-scaffolds (schema-invalid entries) rather than baking them
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Reassemble the RSC (flight) stream Next's App Router inlines into a page, so a URL the stream
3
+ * splits across two scripts is scanned whole.
4
+ *
5
+ * Next writes each chunk of the stream as its own `<script>`, and React Flight cuts chunks at
6
+ * arbitrary bytes (it fills fixed-size views and enqueues the partial one at every flush), so a URL
7
+ * can straddle two scripts and the page text holds only its fragments. The format is the same in Next 15.5.21 and 16.1.7
8
+ * (`createInlinedDataReadableStream` in `dist/server/app-render/use-flight-response.js`, read back
9
+ * by `nextServerDataCallback` in `dist/client/app-index.js`):
10
+ *
11
+ * - `(self.__next_f=self.__next_f||[]).push([0])` starts the stream, followed in the same script by
12
+ * `;self.__next_f.push([2,formState])` when there is form state;
13
+ * - each chunk is then `self.__next_f.push([1,text])`, or `[3,base64]` for a chunk that is not
14
+ * valid UTF-8, whose bytes join the same stream;
15
+ * - every argument is `JSON.stringify` output passed through `htmlEscapeJsonString`, which only
16
+ * rewrites `& < > U+2028 U+2029` as `\uXXXX` escapes, so it parses as JSON and never holds
17
+ * `</script`.
18
+ *
19
+ * Every push on a page joins one stream: Next inlines one flight stream per page.
20
+ */
21
+ export interface InlineFlight {
22
+ /** The page with each parsed flight script replaced by a space, so no fragment is scanned. */
23
+ markup: string;
24
+ /** The stream's text, joined in document order, then each form state as JSON. */
25
+ texts: string[];
26
+ /** Scripts that name `__next_f` but are not flight pushes; their data cannot be scanned. */
27
+ problems: {
28
+ script: string;
29
+ error: string;
30
+ }[];
31
+ }
32
+ /**
33
+ * Split `html` into its markup and its inline flight stream. Only a script whose body names
34
+ * `__next_f` is flight; one that does but does not parse stays in the markup and is reported,
35
+ * because skipping it could drop a reference.
36
+ */
37
+ export declare function extractInlineFlight(html: string): InlineFlight;
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Reassemble the RSC (flight) stream Next's App Router inlines into a page, so a URL the stream
3
+ * splits across two scripts is scanned whole.
4
+ *
5
+ * Next writes each chunk of the stream as its own `<script>`, and React Flight cuts chunks at
6
+ * arbitrary bytes (it fills fixed-size views and enqueues the partial one at every flush), so a URL
7
+ * can straddle two scripts and the page text holds only its fragments. The format is the same in Next 15.5.21 and 16.1.7
8
+ * (`createInlinedDataReadableStream` in `dist/server/app-render/use-flight-response.js`, read back
9
+ * by `nextServerDataCallback` in `dist/client/app-index.js`):
10
+ *
11
+ * - `(self.__next_f=self.__next_f||[]).push([0])` starts the stream, followed in the same script by
12
+ * `;self.__next_f.push([2,formState])` when there is form state;
13
+ * - each chunk is then `self.__next_f.push([1,text])`, or `[3,base64]` for a chunk that is not
14
+ * valid UTF-8, whose bytes join the same stream;
15
+ * - every argument is `JSON.stringify` output passed through `htmlEscapeJsonString`, which only
16
+ * rewrites `& < > U+2028 U+2029` as `\uXXXX` escapes, so it parses as JSON and never holds
17
+ * `</script`.
18
+ *
19
+ * Every push on a page joins one stream: Next inlines one flight stream per page.
20
+ */
21
+ import { getErrorMessage } from '../utils/error.js';
22
+ const PUSH_CALL_RE = /(?:\(self\.__next_f=self\.__next_f\|\|\[\]\)|self\.__next_f)\.push\(/y;
23
+ const BASE64_RE = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
24
+ /** The index just past the JSON array that opens at `start`; `JSON.parse` checks the rest. */
25
+ function jsonArrayEnd(body, start) {
26
+ if (body[start] !== '[')
27
+ throw new Error(`expected a JSON array at ${start}`);
28
+ let depth = 0;
29
+ let inString = false;
30
+ for (let i = start; i < body.length; i++) {
31
+ const c = body[i];
32
+ if (inString) {
33
+ if (c === '\\')
34
+ i++;
35
+ else if (c === '"')
36
+ inString = false;
37
+ }
38
+ else if (c === '"') {
39
+ inString = true;
40
+ }
41
+ else if (c === '[' || c === '{') {
42
+ depth++;
43
+ }
44
+ else if (c === ']' || c === '}') {
45
+ depth--;
46
+ if (depth === 0)
47
+ return i + 1;
48
+ }
49
+ }
50
+ throw new Error('unterminated JSON array');
51
+ }
52
+ /** The arguments of a script body that is nothing but `;`-joined `self.__next_f.push(...)` calls. */
53
+ function parsePushArguments(body) {
54
+ const args = [];
55
+ let pos = 0;
56
+ for (;;) {
57
+ PUSH_CALL_RE.lastIndex = pos;
58
+ if (!PUSH_CALL_RE.test(body))
59
+ throw new Error(`expected self.__next_f.push( at ${pos}`);
60
+ const end = jsonArrayEnd(body, PUSH_CALL_RE.lastIndex);
61
+ args.push(JSON.parse(body.slice(PUSH_CALL_RE.lastIndex, end)));
62
+ if (body[end] !== ')')
63
+ throw new Error(`expected ) at ${end}`);
64
+ pos = end + 1;
65
+ if (pos === body.length)
66
+ return args;
67
+ if (body[pos] !== ';')
68
+ throw new Error(`expected ; or the end of the script at ${pos}`);
69
+ pos++;
70
+ }
71
+ }
72
+ /** A push's contribution: bytes of the stream, form state as JSON, or nothing (the bootstrap). */
73
+ function readSegment(arg) {
74
+ if (!Array.isArray(arg))
75
+ throw new Error('argument is not an array');
76
+ const [kind, payload] = arg;
77
+ if (kind === 0 && arg.length === 1)
78
+ return {};
79
+ if (kind === 1 && arg.length === 2 && typeof payload === 'string') {
80
+ return { bytes: Buffer.from(payload, 'utf8') };
81
+ }
82
+ if (kind === 2 && arg.length === 2)
83
+ return { formState: JSON.stringify(payload) };
84
+ if (kind === 3 && arg.length === 2 && typeof payload === 'string' && BASE64_RE.test(payload)) {
85
+ return { bytes: Buffer.from(payload, 'base64') };
86
+ }
87
+ throw new Error(`unknown segment ${JSON.stringify(arg).slice(0, 40)}`);
88
+ }
89
+ /** Each script element's span and body, in document order; one pass, however the page ends. */
90
+ function* scriptElements(html) {
91
+ const openRe = /<script\b[^<>]*>/gi;
92
+ const closeRe = /<\/script\s*>/gi;
93
+ for (let open = openRe.exec(html); open; open = openRe.exec(html)) {
94
+ closeRe.lastIndex = openRe.lastIndex;
95
+ const close = closeRe.exec(html);
96
+ if (!close)
97
+ return;
98
+ yield {
99
+ start: open.index,
100
+ end: closeRe.lastIndex,
101
+ body: html.slice(openRe.lastIndex, close.index),
102
+ };
103
+ openRe.lastIndex = closeRe.lastIndex;
104
+ }
105
+ }
106
+ /**
107
+ * Split `html` into its markup and its inline flight stream. Only a script whose body names
108
+ * `__next_f` is flight; one that does but does not parse stays in the markup and is reported,
109
+ * because skipping it could drop a reference.
110
+ */
111
+ export function extractInlineFlight(html) {
112
+ const stream = [];
113
+ const formStates = [];
114
+ const problems = [];
115
+ let markup = '';
116
+ let last = 0;
117
+ for (const { start, end, body } of scriptElements(html)) {
118
+ if (!body.includes('__next_f'))
119
+ continue;
120
+ let segments;
121
+ try {
122
+ segments = parsePushArguments(body).map(readSegment);
123
+ }
124
+ catch (err) {
125
+ problems.push({
126
+ script: `<script> at offset ${start}`,
127
+ error: `Not a Next inline flight script (${getErrorMessage(err)}); its RSC payload cannot be scanned`,
128
+ });
129
+ continue;
130
+ }
131
+ for (const { bytes, formState } of segments) {
132
+ if (bytes)
133
+ stream.push(bytes);
134
+ if (formState !== undefined)
135
+ formStates.push(formState);
136
+ }
137
+ markup += `${html.slice(last, start)} `;
138
+ last = end;
139
+ }
140
+ const texts = stream.length > 0 ? [Buffer.concat(stream).toString('utf8'), ...formStates] : formStates;
141
+ return { markup: markup + html.slice(last), texts, problems };
142
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * CLI commands: `canopycms collect-asset-refs <outDir>` and
3
+ * `canopycms materialize-assets --refs <file>`, the two release steps that make every image URL a
4
+ * build references exist in the store before that build is served. The logic lives in
5
+ * `build/asset-refs.ts` and `assets/materialize.ts`; this file picks the store and reports.
6
+ */
7
+ import type { AssetStore } from '../assets/types.js';
8
+ /** @returns the process exit code. */
9
+ export declare function collectAssetRefsCLI(options: {
10
+ outDir: string | undefined;
11
+ }): Promise<number>;
12
+ /**
13
+ * @internal Exported for tests. `materialize-assets` exit codes: a release gates on them, so `1`
14
+ * means the run did not finish, `2` that it finished and some keys cannot be produced, and `3`
15
+ * that the store refused or kept failing, so nothing is known about the keys it could not check.
16
+ */
17
+ export declare const MATERIALIZE_EXIT_CODES: {
18
+ readonly ok: 0;
19
+ /** Bad flags, an unreadable refs file, a config or sharp failure, any uncaught throw. */
20
+ readonly error: 1;
21
+ /** Content failures only; `--allow-failures` turns this into `ok`. */
22
+ readonly contentFailures: 2;
23
+ /** Any store failure, whatever `--allow-failures` says. */
24
+ readonly storeFailures: 3;
25
+ };
26
+ export interface MaterializeAssetsCLIOptions {
27
+ /** The project root; read only when the store comes from `canopycms.config.ts`. */
28
+ projectDir?: string;
29
+ refsPath: string | undefined;
30
+ reportPath?: string;
31
+ allowFailures: boolean;
32
+ concurrency?: string;
33
+ transformConcurrency?: string;
34
+ /** With `region`, builds the S3 store directly and never loads the site config. */
35
+ bucket?: string;
36
+ region?: string;
37
+ /** Accept a non-S3 store resolved from the config. */
38
+ allowLocal?: boolean;
39
+ /** `MaterializeOptions.outputPrefix`; an invalid one exits 1 before anything is read. */
40
+ outputPrefix?: string;
41
+ /** @internal Test seam: skips resolving the store. */
42
+ store?: AssetStore;
43
+ }
44
+ /**
45
+ * `--allow-failures` tolerates content failures only — a reference to an asset the store can no
46
+ * longer produce — so one deleted image does not block a release. A store failure (access
47
+ * denied, an outage that outlasted the retries) still fails the run, since it says nothing about
48
+ * which images are actually fine.
49
+ *
50
+ * @returns a `MATERIALIZE_EXIT_CODES` value; a throw is caught and reported as `error`.
51
+ */
52
+ export declare function materializeAssetsCLI(options: MaterializeAssetsCLIOptions): Promise<number>;