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
@@ -31,7 +31,7 @@ export declare const shouldRetrySecondaryRateLimit: (retryAfter: number, retryCo
31
31
  *
32
32
  * A deployment using an App constructs the strategy and passes it through here
33
33
  * — see `packages/canopycms-cdk/worker/github-app-auth.ts` and
34
- * `docs/adopter-migration.md` for a hand-written entrypoint.
34
+ * `CHANGELOG.md` for a hand-written entrypoint.
35
35
  */
36
36
  export interface OctokitAuthStrategyOptions {
37
37
  /**
@@ -57,7 +57,23 @@ export type CanopyOctokitAuthOptions = {
57
57
  * for the safety net this doesn't cover: exhausted plugin retries and
58
58
  * errors the plugin never sees, like non-403 network failures).
59
59
  */
60
- export declare function createCanopyOctokit(options: CanopyOctokitAuthOptions): Octokit;
60
+ export declare function createCanopyOctokit(options: CanopyOctokitAuthOptions,
61
+ /**
62
+ * Where Octokit's own log and the throttle's warnings go: the GitHub gateway passes its own,
63
+ * which scrubs and escapes. Without one, Octokit logs to the console as it does by default.
64
+ */
65
+ logger?: {
66
+ warn: (...args: unknown[]) => void;
67
+ error: (...args: unknown[]) => void;
68
+ },
69
+ /**
70
+ * Told of every request's `authorization` header just before it is sent, which is the only
71
+ * place the FINAL header is visible: a token an auth strategy minted or rotated shows up here
72
+ * before anything has logged or thrown it. The GitHub gateway registers it for scrubbing.
73
+ */
74
+ observe?: {
75
+ onAuthorization: (authorization: string) => void;
76
+ }): Octokit;
61
77
  export interface GitHubServiceOptions {
62
78
  token: string;
63
79
  owner: string;
@@ -95,6 +111,8 @@ export interface CreateOrUpdatePullRequestParams {
95
111
  mergeSectionIntoBody?: boolean;
96
112
  /** Forwarded to all GitHub requests (worker task-timeout abort). */
97
113
  signal?: AbortSignal;
114
+ /** Where its warnings go (default `canopyLogWarn`): the GitHub gateway passes its own. */
115
+ warn?: (...args: unknown[]) => void;
98
116
  }
99
117
  /**
100
118
  * Create or update a pull request, idempotently: an open PR from head to base
@@ -112,6 +130,25 @@ export declare function createOrUpdatePullRequest(params: CreateOrUpdatePullRequ
112
130
  url: string;
113
131
  created: boolean;
114
132
  }>;
133
+ /**
134
+ * Whether a `git.deleteRef` failure means the branch is already gone from GitHub, so the delete
135
+ * has nothing left to do. A missing ref is a 422 "Reference does not exist"; the message check
136
+ * matters because a 422 also refuses deleting the default branch. A 404 counts too, though it
137
+ * can also mean the repo is not visible to the credential.
138
+ */
139
+ export declare function isRefAlreadyGoneError(err: unknown): boolean;
140
+ /**
141
+ * Whether a PR create failed because the head branch has no commits its base lacks. GitHub
142
+ * answers 422 "Validation Failed" with the reason in `response.data.errors[].message`, which
143
+ * Octokit also folds into `err.message`. Other 422s (a duplicate PR, an unknown base) never match.
144
+ */
145
+ export declare function isNoCommitsBetweenError(err: unknown): boolean;
146
+ /**
147
+ * The `authorization` header of a request's headers: a plain object (lower-case keys, as Octokit
148
+ * sends them), a `Headers`, or a list of pairs.
149
+ * @internal Exported for tests.
150
+ */
151
+ export declare function authorizationOf(headers: HeadersInit | undefined): string | undefined;
115
152
  export declare class GitHubService {
116
153
  private octokit;
117
154
  private owner;
@@ -8,6 +8,7 @@ import { getErrorMessage } from './utils/error.js';
8
8
  // is plain console. See utils/logger.ts.
9
9
  import { canopyLogWarn } from './utils/logger.js';
10
10
  import { mergePrSection } from './submission-attribution.js';
11
+ import { baseBranchOf } from './utils/base-branch.js';
11
12
  const ThrottledOctokit = Octokit.plugin(throttling);
12
13
  /**
13
14
  * Retry primary rate limits at most twice and only for short waits; beyond
@@ -30,25 +31,64 @@ export const shouldRetrySecondaryRateLimit = (retryAfter, retryCount) => retryCo
30
31
  * for the safety net this doesn't cover: exhausted plugin retries and
31
32
  * errors the plugin never sees, like non-403 network failures).
32
33
  */
33
- export function createCanopyOctokit(options) {
34
+ export function createCanopyOctokit(options,
35
+ /**
36
+ * Where Octokit's own log and the throttle's warnings go: the GitHub gateway passes its own,
37
+ * which scrubs and escapes. Without one, Octokit logs to the console as it does by default.
38
+ */
39
+ logger,
40
+ /**
41
+ * Told of every request's `authorization` header just before it is sent, which is the only
42
+ * place the FINAL header is visible: a token an auth strategy minted or rotated shows up here
43
+ * before anything has logged or thrown it. The GitHub gateway registers it for scrubbing.
44
+ */
45
+ observe) {
46
+ const warn = logger?.warn ?? canopyLogWarn;
34
47
  // Pick the two auth fields out EXPLICITLY, never spread: `baseUrl`,
35
48
  // `request`, `log` and `userAgent` are all live `OctokitOptions`, and a
36
49
  // non-literal argument slips past TypeScript's excess-property check. The
37
50
  // contract is "our Octokit, authenticated the way you say", not "configured
38
- // however you like".
51
+ // however you like". The one `request` we set is `observe`'s fetch: an auth
52
+ // strategy's hook is the innermost `request` wrap, so a hook added after
53
+ // construction runs before it sets the header. `@octokit/auth-app`'s hook
54
+ // mints through the `request` it wraps (`request.defaults`), so the JWT of a
55
+ // mint an Octokit request triggers passes the fetch too; a mint outside one
56
+ // (`mintInstallationToken`) uses auth-app's own `request`, and does not.
39
57
  const auth = 'authStrategy' in options
40
58
  ? { authStrategy: options.authStrategy, auth: options.auth }
41
59
  : { auth: options.auth };
42
60
  return new ThrottledOctokit({
43
61
  ...auth,
62
+ ...(observe === undefined
63
+ ? {}
64
+ : {
65
+ request: {
66
+ fetch: (url, init) => {
67
+ const authorization = authorizationOf(init?.headers);
68
+ if (authorization !== undefined)
69
+ observe.onAuthorization(authorization);
70
+ return globalThis.fetch(url, init);
71
+ },
72
+ },
73
+ }),
74
+ ...(logger === undefined
75
+ ? {}
76
+ : {
77
+ log: {
78
+ debug: () => undefined,
79
+ info: () => undefined,
80
+ warn: logger.warn,
81
+ error: logger.error,
82
+ },
83
+ }),
44
84
  throttle: {
45
85
  onRateLimit: (retryAfter, requestOptions, _octokit, retryCount) => {
46
- canopyLogWarn(`CanopyCMS: GitHub primary rate limit hit for ${requestOptions.method} ${requestOptions.url} ` +
86
+ warn(`CanopyCMS: GitHub primary rate limit hit for ${requestOptions.method} ${requestOptions.url} ` +
47
87
  `(retryAfter=${retryAfter}s, retryCount=${retryCount})`);
48
88
  return shouldRetryRateLimit(retryAfter, retryCount);
49
89
  },
50
90
  onSecondaryRateLimit: (retryAfter, requestOptions, _octokit, retryCount) => {
51
- canopyLogWarn(`CanopyCMS: GitHub secondary rate limit hit for ${requestOptions.method} ${requestOptions.url} ` +
91
+ warn(`CanopyCMS: GitHub secondary rate limit hit for ${requestOptions.method} ${requestOptions.url} ` +
52
92
  `(retryAfter=${retryAfter}s, retryCount=${retryCount})`);
53
93
  return shouldRetrySecondaryRateLimit(retryAfter, retryCount);
54
94
  },
@@ -68,6 +108,7 @@ export function createCanopyOctokit(options) {
68
108
  */
69
109
  export async function createOrUpdatePullRequest(params) {
70
110
  const { octokit, owner, repo, head, base, title, body, markReadyIfDraft, signal } = params;
111
+ const warn = params.warn ?? canopyLogWarn;
71
112
  const mergeSection = params.mergeSectionIntoBody === true;
72
113
  // CONDITIONAL spread: with no signal, the request objects below carry no
73
114
  // `request` key at all (github-service.test.ts asserts on their exact shape).
@@ -87,7 +128,7 @@ export async function createOrUpdatePullRequest(params) {
87
128
  let existing = existingPRs.data[0];
88
129
  if (existingPRs.data.length > 1) {
89
130
  existing = [...existingPRs.data].sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime())[0];
90
- canopyLogWarn(`CanopyCMS: Found ${existingPRs.data.length} open PRs for ${head} -> ${base}; updating the most recently updated (#${existing.number})`);
131
+ warn(`CanopyCMS: Found ${existingPRs.data.length} open PRs for ${head} -> ${base}; updating the most recently updated (#${existing.number})`);
91
132
  }
92
133
  await octokit.pulls.update({
93
134
  owner,
@@ -126,7 +167,7 @@ export async function createOrUpdatePullRequest(params) {
126
167
  });
127
168
  }
128
169
  catch (err) {
129
- canopyLogWarn(`CanopyCMS: Failed to convert PR #${existing.number} to ready for review (the PR update itself succeeded; continuing):`, getErrorMessage(err));
170
+ warn(`CanopyCMS: Failed to convert PR #${existing.number} to ready for review (the PR update itself succeeded; continuing):`, getErrorMessage(err));
130
171
  }
131
172
  }
132
173
  return { number: existing.number, url: existing.html_url, created: false };
@@ -142,6 +183,59 @@ export async function createOrUpdatePullRequest(params) {
142
183
  });
143
184
  return { number: pr.data.number, url: pr.data.html_url, created: true };
144
185
  }
186
+ /**
187
+ * Whether a `git.deleteRef` failure means the branch is already gone from GitHub, so the delete
188
+ * has nothing left to do. A missing ref is a 422 "Reference does not exist"; the message check
189
+ * matters because a 422 also refuses deleting the default branch. A 404 counts too, though it
190
+ * can also mean the repo is not visible to the credential.
191
+ */
192
+ export function isRefAlreadyGoneError(err) {
193
+ if (!(err instanceof Error) || !('status' in err))
194
+ return false;
195
+ const { status } = err;
196
+ if (status === 404)
197
+ return true;
198
+ return status === 422 && /reference does not exist/i.test(err.message);
199
+ }
200
+ const NO_COMMITS_BETWEEN = /^No commits between /;
201
+ /**
202
+ * Whether a PR create failed because the head branch has no commits its base lacks. GitHub
203
+ * answers 422 "Validation Failed" with the reason in `response.data.errors[].message`, which
204
+ * Octokit also folds into `err.message`. Other 422s (a duplicate PR, an unknown base) never match.
205
+ */
206
+ export function isNoCommitsBetweenError(err) {
207
+ if (!(err instanceof Error) || !('status' in err) || err.status !== 422)
208
+ return false;
209
+ const data = 'response' in err ? err.response?.data : null;
210
+ const errors = typeof data === 'object' && data !== null && 'errors' in data ? data.errors : undefined;
211
+ if (Array.isArray(errors)) {
212
+ return errors.some((e) => typeof e === 'object' &&
213
+ e !== null &&
214
+ 'message' in e &&
215
+ typeof e.message === 'string' &&
216
+ NO_COMMITS_BETWEEN.test(e.message));
217
+ }
218
+ return /"message":"No commits between /.test(err.message);
219
+ }
220
+ /**
221
+ * The `authorization` header of a request's headers: a plain object (lower-case keys, as Octokit
222
+ * sends them), a `Headers`, or a list of pairs.
223
+ * @internal Exported for tests.
224
+ */
225
+ export function authorizationOf(headers) {
226
+ if (headers === undefined)
227
+ return undefined;
228
+ if (headers instanceof Headers)
229
+ return headers.get('authorization') ?? undefined;
230
+ if (Array.isArray(headers)) {
231
+ return headers.find(([name]) => name.toLowerCase() === 'authorization')?.[1];
232
+ }
233
+ for (const [name, value] of Object.entries(headers)) {
234
+ if (name.toLowerCase() === 'authorization' && typeof value === 'string')
235
+ return value;
236
+ }
237
+ return undefined;
238
+ }
145
239
  export class GitHubService {
146
240
  constructor(options) {
147
241
  this.octokit = createCanopyOctokit({ auth: options.token });
@@ -311,7 +405,7 @@ export const createGitHubService = (config, remoteUrl) => {
311
405
  token,
312
406
  owner,
313
407
  repo,
314
- baseBranch: config.defaultBaseBranch ?? 'main',
408
+ baseBranch: baseBranchOf(config),
315
409
  });
316
410
  }
317
411
  catch (err) {
@@ -1,10 +1,14 @@
1
1
  import { jsonResponse, isCanopyBinaryResponse } from './types.js';
2
2
  import { workerNotReadyResponse } from './worker-not-ready.js';
3
+ import { SchemaUnavailableError } from '../schema/schema-unavailable-error.js';
3
4
  import { createCanopyRouter } from './router.js';
4
5
  import { assertAuthPluginAllowedForMode } from '../auth/plugin.js';
5
6
  import { createCanopyServices } from '../services.js';
7
+ import { recordConfiguredSparseCone } from '../branch-sparse.js';
8
+ import { recordServedSchemaRegistry } from '../schema-registry-record.js';
6
9
  import { loadBranchContext, BranchWorkspaceManager } from '../branch-workspace.js';
7
10
  import { BranchMetadataCorruptError } from '../branch-metadata.js';
11
+ import { BRANCH_METADATA_CORRUPT_MESSAGE } from '../branch-metadata-error.js';
8
12
  import { resolveCanopyUser } from '../resolve-canopy-user.js';
9
13
  import { authResultToCanopyUser } from '../user.js';
10
14
  import { isAdmin } from '../authorization/index.js';
@@ -14,13 +18,18 @@ import { getErrorMessage, redactCredentials, sanitizeErrorMessage } from '../uti
14
18
  // canopyLogError, not console.error: this is shared code and not guaranteed to
15
19
  // stay out of the worker's runtime import closure, so new log lines here go
16
20
  // through the indirection (utils/logger.ts).
17
- import { canopyLogError } from '../utils/logger.js';
21
+ import { canopyLogError, canopyLogWarn } from '../utils/logger.js';
22
+ import { EDITOR_MODE_HEADER, EDITOR_MODE_MISMATCH_STATUS, editorModeMismatchMessage, parseEditorModeHeader, } from '../operating-mode/editor-mode-check.js';
18
23
  import { runWithRequestTiming, setRequestTimingRoute, timeRequestPhase, } from '../utils/request-timing.js';
24
+ import { baseBranchOf } from '../utils/base-branch.js';
25
+ import { SYSTEM_USER_ID } from '../system-users.js';
19
26
  const buildContext = async (options) => {
20
27
  const services = options.services ?? (options.config ? await createCanopyServices(options.config) : undefined);
21
28
  if (!services) {
22
29
  throw new Error('CanopyCMS: config or services is required');
23
30
  }
31
+ await recordConfiguredSparseCone(services.config);
32
+ await recordServedSchemaRegistry(services.config, services.entrySchemaRegistry);
24
33
  const operatingMode = services.config.mode;
25
34
  // Derived from the strategy, which resolves deploymentName; a literal here
26
35
  // would miss a deployment-namespaced settings branch (say canopycms-settings-acme).
@@ -41,7 +50,7 @@ const buildContext = async (options) => {
41
50
  }
42
51
  // Read from services.config per-request, not a captured variable, so a
43
52
  // refreshActiveBranch() update takes effect immediately.
44
- const baseBranch = services.config.defaultBaseBranch ?? 'main';
53
+ const baseBranch = baseBranchOf(services.config);
45
54
  const activeBranch = services.config.defaultActiveBranch ?? baseBranch;
46
55
  const shouldAutoCreate = clientOperatingStrategy(operatingMode).supportsBranching() &&
47
56
  (branch === baseBranch || branch === activeBranch);
@@ -50,7 +59,7 @@ const buildContext = async (options) => {
50
59
  const context = await manager.openOrCreateBranch({
51
60
  branchName: branch,
52
61
  mode: operatingMode,
53
- createdBy: 'canopycms-system',
62
+ createdBy: SYSTEM_USER_ID,
54
63
  });
55
64
  if (opts?.loadSchema && context) {
56
65
  const contentRootName = services.config.contentRoot || 'content';
@@ -84,6 +93,11 @@ const parseQueryParams = (url) => {
84
93
  return {};
85
94
  }
86
95
  };
96
+ /**
97
+ * The answer to a request with no accepted session. The body's `status: 401` is what the client
98
+ * detects sign-out from, so it stays 401 whatever HTTP status `unauthenticatedStatus` picks.
99
+ */
100
+ const unauthenticatedResponse = (config, error) => jsonResponse({ ok: false, status: 401, error: error ?? 'Unauthorized' }, config.unauthenticatedStatus ?? 401);
87
101
  /**
88
102
  * The core handler behind every Canopy API request. A framework adapter
89
103
  * (Next.js, Express, Hono) converts its request to a CanopyRequest, extracts
@@ -95,6 +109,26 @@ export function createCanopyRequestHandler(options) {
95
109
  const mode = options.services?.config.mode ?? options.config?.mode;
96
110
  assertAuthPluginAllowedForMode(options.authPlugin, mode);
97
111
  const router = createCanopyRouter();
112
+ // Before auth, because a dev bundle against a prod server cannot authenticate: see
113
+ // editor-mode-check.ts.
114
+ let modeMismatchLogged = false;
115
+ const editorModeMismatchResponse = (req) => {
116
+ const editorMode = parseEditorModeHeader(req.header(EDITOR_MODE_HEADER));
117
+ if (!mode || !editorMode || editorMode === mode)
118
+ return null;
119
+ if (!modeMismatchLogged) {
120
+ modeMismatchLogged = true;
121
+ canopyLogWarn(`CanopyCMS: an editor built with NEXT_PUBLIC_CANOPY_MODE="${editorMode}" called this server, ` +
122
+ `which runs in "${mode}" mode. Its requests are refused with ${EDITOR_MODE_MISMATCH_STATUS} ` +
123
+ `until the editor is rebuilt with NEXT_PUBLIC_CANOPY_MODE=${mode}. Logged once per request handler.`);
124
+ }
125
+ return jsonResponse({
126
+ ok: false,
127
+ status: EDITOR_MODE_MISMATCH_STATUS,
128
+ code: 'EDITOR_MODE_MISMATCH',
129
+ error: editorModeMismatchMessage(editorMode),
130
+ }, EDITOR_MODE_MISMATCH_STATUS);
131
+ };
98
132
  // Built once and reused across requests in the same warm container. On
99
133
  // rejection (transient cold start, EFS not yet mounted) the cache is cleared
100
134
  // (API-H3) so the NEXT request retries instead of replaying the rejection.
@@ -119,6 +153,9 @@ export function createCanopyRequestHandler(options) {
119
153
  return jsonResponse({ ok: false, status: 404, error: 'Not found' }, 404);
120
154
  }
121
155
  setRequestTimingRoute(match.pattern.join('/') || '(malformed path)');
156
+ const modeMismatch = editorModeMismatchResponse(req);
157
+ if (modeMismatch)
158
+ return modeMismatch;
122
159
  const apiCtx = await timeRequestPhase('context', getContext);
123
160
  // In dev mode, re-check if the developer switched git branches
124
161
  await timeRequestPhase('refreshBranch', () => apiCtx.services.refreshActiveBranch());
@@ -127,13 +164,30 @@ export function createCanopyRequestHandler(options) {
127
164
  // any workspace provisioning below, so they can neither trigger expensive
128
165
  // git operations nor read provisioning error details.
129
166
  if (!authResult.success || !authResult.user) {
130
- return jsonResponse({ ok: false, status: 401, error: authResult.error ?? 'Unauthorized' }, 401);
167
+ return unauthenticatedResponse(apiCtx.services.config, authResult.error);
168
+ }
169
+ // Whether a worker's recorded failure may be named in a not-ready 503: admins only, as in
170
+ // System health. With no remote there are no internal groups, so this is the bootstrap
171
+ // admins, and /admin is behind the same 503, so this answer is where they read it.
172
+ const mayReadWorkerFailure = () => isAdmin(authResultToCanopyUser(authResult, apiCtx.services.bootstrapAdminIds).groups);
173
+ // A prod base branch still pending since creation resolves here, once the
174
+ // worker has created the remote; until then this answers the not-ready 503.
175
+ try {
176
+ await timeRequestPhase('baseBranch', () => apiCtx.services.resolvePendingBaseBranch());
177
+ }
178
+ catch (err) {
179
+ const notReady = workerNotReadyResponse(err, {
180
+ workerFailureDetail: mayReadWorkerFailure(),
181
+ });
182
+ if (notReady)
183
+ return notReady;
184
+ throw err;
131
185
  }
132
186
  // Provision the base/active branch workspace on first request, so the many
133
187
  // endpoints that assume it exists (registry reads and the like) don't return
134
188
  // confusing empty results on a cold start. A real provisioning error fails
135
189
  // loudly here rather than surprising a later handler.
136
- const baseBranch = apiCtx.services.config.defaultBaseBranch ?? 'main';
190
+ const baseBranch = baseBranchOf(apiCtx.services.config);
137
191
  try {
138
192
  await apiCtx.getBranchContext(baseBranch);
139
193
  }
@@ -151,7 +205,9 @@ export function createCanopyRequestHandler(options) {
151
205
  // (authenticated) client. Credentials, which git errors can embed, are
152
206
  // redacted even from the server logs.
153
207
  console.error(`CanopyCMS: Failed to provision workspace for base branch '${baseBranch}': ${redactCredentials(message)}`);
154
- const notReady = workerNotReadyResponse(err);
208
+ const notReady = workerNotReadyResponse(err, {
209
+ workerFailureDetail: mayReadWorkerFailure(),
210
+ });
155
211
  if (notReady)
156
212
  return notReady;
157
213
  return jsonResponse({
@@ -182,7 +238,9 @@ export function createCanopyRequestHandler(options) {
182
238
  // No remote means no settings workspace, so /admin cannot load either:
183
239
  // the worker has not created the remote yet, so every caller gets the
184
240
  // not-ready 503, bootstrap admins included.
185
- const notReady = workerNotReadyResponse(err);
241
+ const notReady = workerNotReadyResponse(err, {
242
+ workerFailureDetail: mayReadWorkerFailure(),
243
+ });
186
244
  if (notReady)
187
245
  return notReady;
188
246
  // Same trade as the base-branch degradation above: /admin is the recovery
@@ -220,7 +278,7 @@ export function createCanopyRequestHandler(options) {
220
278
  }
221
279
  }
222
280
  if (user.type === 'anonymous') {
223
- return jsonResponse({ ok: false, status: 401, error: authResult.error ?? 'Unauthorized' }, 401);
281
+ return unauthenticatedResponse(apiCtx.services.config, authResult.error);
224
282
  }
225
283
  const queryParams = parseQueryParams(req.url);
226
284
  const mergedParams = { ...queryParams, ...match.params };
@@ -274,10 +332,17 @@ export function createCanopyRequestHandler(options) {
274
332
  catch (err) {
275
333
  // Last-resort boundary (API-C1): see handleRequest's doc comment above.
276
334
  const message = getErrorMessage(err);
277
- console.error('CanopyCMS: Unhandled error in API request handler:', message);
335
+ // Not per refused request: branch-schema-cache.ts logs each missing schema once per process.
336
+ if (!(err instanceof SchemaUnavailableError)) {
337
+ console.error('CanopyCMS: Unhandled error in API request handler:', message);
338
+ }
278
339
  const notReady = workerNotReadyResponse(err);
279
340
  if (notReady)
280
341
  return notReady;
342
+ // Its message is a path and a parse error, neither of which helps an editor.
343
+ if (err instanceof BranchMetadataCorruptError) {
344
+ return jsonResponse({ ok: false, status: 500, error: BRANCH_METADATA_CORRUPT_MESSAGE }, 500);
345
+ }
281
346
  return jsonResponse({ ok: false, status: 500, error: sanitizeErrorMessage(message) }, 500);
282
347
  }
283
348
  };
@@ -37,6 +37,8 @@ export interface CanopyBinaryResponse {
37
37
  contentDisposition?: string;
38
38
  cacheControl?: string;
39
39
  etag?: string;
40
+ /** Redirect target, for a 3xx `status`; `body` is then empty. */
41
+ location?: string;
40
42
  };
41
43
  }
42
44
  export declare function jsonResponse<T>(body: T, status?: number, headers?: Record<string, string>): CanopyResponse<T>;
@@ -2,8 +2,13 @@ import type { ApiResponse } from '../api/types.js';
2
2
  import { type CanopyResponse } from './types.js';
3
3
  export declare const WORKER_NOT_READY_MESSAGE = "CMS worker not ready \u2014 it may still be starting. Try again in a minute; if this persists, ask an admin to check the CMS worker.";
4
4
  /**
5
- * The 503 for a request that hit {@link RemoteNotReadyError}, or `undefined`
6
- * for any other error. The single mapping point for the core handler, the AI route and
7
- * every framework adapter's backstop, so the message and `Retry-After` cannot diverge.
5
+ * The 503 for a request that hit {@link RemoteNotReadyError},
6
+ * {@link BranchProvisioningBusyError} or {@link SchemaUnavailableError}, or `undefined` for any
7
+ * other error. Retriable (with `Retry-After`) unless the worker recorded that its latest start
8
+ * failed; `workerFailureDetail` names that failure, for an authenticated admin only. The single
9
+ * mapping point for the core handler, the AI route and every framework adapter's backstop, so
10
+ * the message and `Retry-After` cannot diverge.
8
11
  */
9
- export declare function workerNotReadyResponse(err: unknown): CanopyResponse<ApiResponse> | undefined;
12
+ export declare function workerNotReadyResponse(err: unknown, options?: {
13
+ workerFailureDetail?: boolean;
14
+ }): CanopyResponse<ApiResponse> | undefined;
@@ -1,17 +1,70 @@
1
+ import { BranchProvisioningBusyError } from '../branch-provisioning.js';
1
2
  import { RemoteNotReadyError } from '../git-manager.js';
3
+ import { sanitizeErrorMessage } from '../utils/error.js';
4
+ import { SchemaUnavailableError } from '../schema/schema-unavailable-error.js';
2
5
  import { jsonResponse } from './types.js';
3
6
  /** Seconds a client should wait before retrying while the worker boots. */
4
7
  const RETRY_AFTER_SECONDS = '30';
8
+ /**
9
+ * Seconds before retrying an unavailable entry type. The editor's client never resends a 503
10
+ * (api/client.ts resends only a 429), so this informs other clients; the editor tells authors to
11
+ * reload.
12
+ */
13
+ const SCHEMA_RETRY_AFTER_SECONDS = '60';
5
14
  export const WORKER_NOT_READY_MESSAGE = 'CMS worker not ready — it may still be starting. Try again in a minute; if this persists, ask an admin to check the CMS worker.';
6
15
  /**
7
- * The 503 for a request that hit {@link RemoteNotReadyError}, or `undefined`
8
- * for any other error. The single mapping point for the core handler, the AI route and
9
- * every framework adapter's backstop, so the message and `Retry-After` cannot diverge.
16
+ * An AWS account id, as twelve digits or the console's dddd-dddd-dddd. A secret's ARN in a
17
+ * worker error carries one; the region and names around it are what an admin needs.
18
+ */
19
+ const ACCOUNT_ID = /(?<![0-9A-Za-z-])[0-9]{4}-[0-9]{4}-[0-9]{4}(?![0-9A-Za-z-])|(?<![0-9A-Za-z])[0-9]{12}(?![0-9A-Za-z])/g;
20
+ /**
21
+ * The 503 for a worker that recorded a startup failure. The worker's message, sanitized and with
22
+ * account ids masked, is included only with `detail`: it names secrets, paths and the repository,
23
+ * so it is for an admin the handler has authenticated, never anyone else.
24
+ */
25
+ function workerFailureResponse(failure, detail) {
26
+ const named = detail
27
+ ? ` (${failure.at}): ${sanitizeErrorMessage(failure.message).replace(ACCOUNT_ID, (id) => id.replace(/[0-9]/g, '*'))}`
28
+ : '.';
29
+ if (failure.current) {
30
+ return jsonResponse({
31
+ ok: false,
32
+ status: 503,
33
+ error: `The CMS worker failed to start${named} An admin needs to fix the worker; retrying will not help until then.`,
34
+ code: 'WORKER_FAILED',
35
+ }, 503);
36
+ }
37
+ return jsonResponse({
38
+ ok: false,
39
+ status: 503,
40
+ error: detail
41
+ ? `CMS worker not ready — it is starting again after a failure${named} Try again in a minute; if this persists, ask an admin to check the CMS worker.`
42
+ : WORKER_NOT_READY_MESSAGE,
43
+ }, 503, { 'Retry-After': RETRY_AFTER_SECONDS });
44
+ }
45
+ /**
46
+ * The 503 for a request that hit {@link RemoteNotReadyError},
47
+ * {@link BranchProvisioningBusyError} or {@link SchemaUnavailableError}, or `undefined` for any
48
+ * other error. Retriable (with `Retry-After`) unless the worker recorded that its latest start
49
+ * failed; `workerFailureDetail` names that failure, for an authenticated admin only. The single
50
+ * mapping point for the core handler, the AI route and every framework adapter's backstop, so
51
+ * the message and `Retry-After` cannot diverge.
10
52
  */
11
- export function workerNotReadyResponse(err) {
12
- if (!(err instanceof RemoteNotReadyError))
53
+ export function workerNotReadyResponse(err, options = {}) {
54
+ if (err instanceof SchemaUnavailableError) {
55
+ return jsonResponse({ ok: false, status: 503, error: err.message, code: 'SCHEMA_UNAVAILABLE' }, 503, { 'Retry-After': SCHEMA_RETRY_AFTER_SECONDS });
56
+ }
57
+ if (err instanceof RemoteNotReadyError && err.workerStartupFailure) {
58
+ return workerFailureResponse(err.workerStartupFailure, options.workerFailureDetail === true);
59
+ }
60
+ const message = err instanceof RemoteNotReadyError
61
+ ? WORKER_NOT_READY_MESSAGE
62
+ : err instanceof BranchProvisioningBusyError
63
+ ? err.message
64
+ : undefined;
65
+ if (message === undefined)
13
66
  return undefined;
14
- return jsonResponse({ ok: false, status: 503, error: WORKER_NOT_READY_MESSAGE }, 503, {
67
+ return jsonResponse({ ok: false, status: 503, error: message }, 503, {
15
68
  'Retry-After': RETRY_AFTER_SECONDS,
16
69
  });
17
70
  }
package/dist/index.d.ts CHANGED
@@ -15,3 +15,5 @@ export type { ListEntriesItem, ListEntriesOptions } from './content-listing.js';
15
15
  export { assetUrl, assetSrcSet } from './assets/asset-url.js';
16
16
  export type { AssetRef, AssetUrlOptions } from './assets/asset-url.js';
17
17
  export type { OutputFormat, CropRect, TransformDirectives } from './assets/transform-directives.js';
18
+ export { fieldAttrs, scopeFieldProps } from './editor/field-props.js';
19
+ export type { FieldAttrs, FieldProps } from './editor/field-props.js';
package/dist/index.js CHANGED
@@ -15,3 +15,6 @@ export { isCanopyRequest, isHeadersLike, extractHeaders, validateAuthContext, }
15
15
  // Asset URL helpers — client-safe (no node: imports). Build/adjust transform URLs for <img>/srcset
16
16
  // from stored asset refs without the server-only transform engine (assets/transform.ts, sharp).
17
17
  export { assetUrl, assetSrcSet } from './assets/asset-url.js';
18
+ // Preview field marks — pure, so server components call them too (`canopycms/preview` is
19
+ // 'use client'); see editor/field-props.ts.
20
+ export { fieldAttrs, scopeFieldProps } from './editor/field-props.js';
@@ -0,0 +1,46 @@
1
+ import type { BlockFieldConfig, FieldConfig, ObjectFieldConfig } from './config/index.js';
2
+ /**
3
+ * The key each object-list item and block carries in content, naming that item among its list's
4
+ * items for as long as it exists: a move or an edit keeps it, a copy gets a new one. Field comment
5
+ * threads name the items on their path by it (`CommentThread.itemKeys`). Beside `template` on a
6
+ * block, never inside its `value`; a schema may not define a field of this name.
7
+ *
8
+ * Dependency-free: the editor and the server both use this module.
9
+ */
10
+ export declare const ITEM_KEY = "_key";
11
+ /** A usable item key: 1-64 letters, digits, `_` or `-`, starting with a letter or digit. */
12
+ export declare const isItemKey: (value: unknown) => value is string;
13
+ /** A new random item key: 12 Base58 characters. */
14
+ export declare function mintItemKey(): string;
15
+ /**
16
+ * How `withItemKeys` keys an item that lacks a usable key, or repeats one an earlier item of its
17
+ * list holds:
18
+ * - `content`: from a hash of the item, so every reader and writer of the same file names it
19
+ * alike before a save writes the key down, and an item added to the file later never inherits
20
+ * a key a removed one held unless it is the same content;
21
+ * - `random`: a fresh key;
22
+ * - `fresh`: a fresh key for EVERY item, keyed or not, as a copy needs.
23
+ */
24
+ export type ItemKeyFill = 'content' | 'random' | 'fresh';
25
+ type ListField = ObjectFieldConfig | BlockFieldConfig;
26
+ /**
27
+ * `data` with every object-list item and block keyed, each unique in its list, nested lists
28
+ * included; the same object when nothing needed a key. A usable key is kept unless `fill` is
29
+ * `fresh`.
30
+ */
31
+ export declare function withItemKeys(fields: readonly FieldConfig[], data: Record<string, unknown>, fill: ItemKeyFill): Record<string, unknown>;
32
+ /** `item`, a copy about to join `field`'s list, with fresh keys for it and every item inside it. */
33
+ export declare function withFreshItemKeys<T>(field: ListField, item: T): T;
34
+ /**
35
+ * The keys of the list items on `canopyPath` in `value`, outermost first: what a new field thread
36
+ * stores to name them. Undefined when an item on the path has no usable key or the path isn't
37
+ * there.
38
+ */
39
+ export declare function itemKeysOnPath(fields: readonly FieldConfig[], value: Record<string, unknown>, canopyPath: string): string[] | undefined;
40
+ /**
41
+ * Where a field thread made at `canopyPath` on the items named by `itemKeys` is in `value` now:
42
+ * its path with each index replaced by that item's current one, or `null` when one of the items
43
+ * is gone. A path with no keys (one through no list) is returned as it is.
44
+ */
45
+ export declare function resolveThreadPath(fields: readonly FieldConfig[], value: Record<string, unknown>, canopyPath: string, itemKeys: readonly string[] | undefined): string | null;
46
+ export {};