canopycms 0.0.67-int.90 → 0.0.67-int.91

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 (539) hide show
  1. package/README.md +30 -3
  2. package/dist/ai/generate.js +1 -27
  3. package/dist/ai/handler.d.ts +0 -4
  4. package/dist/ai/handler.js +0 -11
  5. package/dist/ai/index.d.ts +1 -8
  6. package/dist/ai/index.js +1 -8
  7. package/dist/ai/json-to-markdown.js +15 -58
  8. package/dist/ai/resolve-branch.d.ts +2 -7
  9. package/dist/ai/resolve-branch.js +2 -8
  10. package/dist/ai/strip-mdx.d.ts +5 -13
  11. package/dist/ai/strip-mdx.js +5 -17
  12. package/dist/ai/to-plain-text.d.ts +10 -28
  13. package/dist/ai/to-plain-text.js +10 -28
  14. package/dist/ai/transform-components.d.ts +2 -4
  15. package/dist/ai/transform-components.js +8 -19
  16. package/dist/ai/types.d.ts +5 -10
  17. package/dist/api/admin-branch-health.d.ts +4 -12
  18. package/dist/api/admin-branch-health.js +26 -66
  19. package/dist/api/admin.d.ts +4 -12
  20. package/dist/api/admin.js +10 -26
  21. package/dist/api/assets.d.ts +0 -25
  22. package/dist/api/assets.js +50 -91
  23. package/dist/api/branch-merge.d.ts +1 -1
  24. package/dist/api/branch-merge.js +0 -2
  25. package/dist/api/branch-review.d.ts +0 -8
  26. package/dist/api/branch-review.js +0 -13
  27. package/dist/api/branch-status.d.ts +0 -3
  28. package/dist/api/branch-status.js +8 -33
  29. package/dist/api/branch-withdraw.d.ts +0 -1
  30. package/dist/api/branch-withdraw.js +6 -9
  31. package/dist/api/branch.d.ts +7 -12
  32. package/dist/api/branch.js +7 -44
  33. package/dist/api/client.d.ts +71 -224
  34. package/dist/api/client.js +82 -233
  35. package/dist/api/comments.d.ts +2 -4
  36. package/dist/api/comments.js +0 -17
  37. package/dist/api/content.d.ts +0 -6
  38. package/dist/api/content.js +66 -142
  39. package/dist/api/entries-constants.d.ts +5 -9
  40. package/dist/api/entries-constants.js +5 -9
  41. package/dist/api/entries.d.ts +8 -13
  42. package/dist/api/entries.js +20 -51
  43. package/dist/api/github-sync.d.ts +2 -4
  44. package/dist/api/github-sync.js +4 -8
  45. package/dist/api/groups.d.ts +3 -0
  46. package/dist/api/groups.js +8 -21
  47. package/dist/api/guards.d.ts +4 -16
  48. package/dist/api/guards.js +3 -22
  49. package/dist/api/index.d.ts +4 -4
  50. package/dist/api/permissions.d.ts +2 -0
  51. package/dist/api/permissions.js +18 -40
  52. package/dist/api/reference-options.d.ts +0 -1
  53. package/dist/api/reference-options.js +3 -11
  54. package/dist/api/request-body-hash.d.ts +12 -23
  55. package/dist/api/request-body-hash.js +12 -23
  56. package/dist/api/resolve-references.d.ts +0 -1
  57. package/dist/api/resolve-references.js +13 -28
  58. package/dist/api/route-builder.d.ts +3 -7
  59. package/dist/api/route-builder.js +1 -1
  60. package/dist/api/routes.d.ts +12 -0
  61. package/dist/api/routes.js +47 -0
  62. package/dist/api/schema.d.ts +23 -33
  63. package/dist/api/schema.js +20 -74
  64. package/dist/api/settings-helpers.js +4 -5
  65. package/dist/api/types.d.ts +0 -5
  66. package/dist/api/user.js +0 -5
  67. package/dist/api/validators.d.ts +14 -52
  68. package/dist/api/validators.js +14 -52
  69. package/dist/assets/asset-prefixes.d.ts +4 -8
  70. package/dist/assets/asset-prefixes.js +4 -8
  71. package/dist/assets/asset-src.d.ts +5 -22
  72. package/dist/assets/asset-src.js +5 -21
  73. package/dist/assets/factory.d.ts +1 -2
  74. package/dist/assets/factory.js +1 -2
  75. package/dist/assets/finalize.d.ts +3 -1
  76. package/dist/assets/finalize.js +3 -1
  77. package/dist/assets/index.d.ts +3 -3
  78. package/dist/assets/index.js +1 -1
  79. package/dist/assets/keys.d.ts +5 -3
  80. package/dist/assets/keys.js +6 -3
  81. package/dist/assets/pipeline.d.ts +3 -2
  82. package/dist/assets/pipeline.js +22 -56
  83. package/dist/assets/sharp-loader.d.ts +2 -10
  84. package/dist/assets/sharp-loader.js +2 -10
  85. package/dist/assets/store-local.d.ts +1 -2
  86. package/dist/assets/store-local.js +1 -2
  87. package/dist/assets/store-s3.d.ts +3 -4
  88. package/dist/assets/svg-sanitizer.d.ts +6 -14
  89. package/dist/assets/svg-sanitizer.js +6 -14
  90. package/dist/assets/transform-directives.d.ts +3 -4
  91. package/dist/assets/transform-directives.js +1 -1
  92. package/dist/assets/transform.d.ts +19 -30
  93. package/dist/assets/transform.js +18 -31
  94. package/dist/auth/cache.d.ts +2 -3
  95. package/dist/auth/cache.js +2 -3
  96. package/dist/auth/caching-auth-plugin.d.ts +11 -22
  97. package/dist/auth/caching-auth-plugin.js +12 -14
  98. package/dist/auth/context-helpers.d.ts +6 -20
  99. package/dist/auth/context-helpers.js +5 -17
  100. package/dist/auth/file-based-auth-cache.d.ts +10 -21
  101. package/dist/auth/file-based-auth-cache.js +23 -51
  102. package/dist/auth/plugin.d.ts +29 -61
  103. package/dist/auth/plugin.js +9 -13
  104. package/dist/auth/types.d.ts +11 -20
  105. package/dist/authorization/branch.d.ts +30 -49
  106. package/dist/authorization/branch.js +16 -42
  107. package/dist/authorization/content.d.ts +11 -40
  108. package/dist/authorization/content.js +13 -45
  109. package/dist/authorization/groups/index.d.ts +0 -3
  110. package/dist/authorization/groups/index.js +0 -3
  111. package/dist/authorization/groups/loader.d.ts +14 -28
  112. package/dist/authorization/groups/loader.js +14 -38
  113. package/dist/authorization/groups/schema.d.ts +0 -6
  114. package/dist/authorization/groups/schema.js +4 -7
  115. package/dist/authorization/helpers.d.ts +9 -28
  116. package/dist/authorization/helpers.js +9 -28
  117. package/dist/authorization/index.d.ts +3 -25
  118. package/dist/authorization/index.js +3 -35
  119. package/dist/authorization/path.d.ts +6 -13
  120. package/dist/authorization/path.js +8 -25
  121. package/dist/authorization/permissions/index.d.ts +0 -3
  122. package/dist/authorization/permissions/index.js +0 -3
  123. package/dist/authorization/permissions/loader.d.ts +14 -27
  124. package/dist/authorization/permissions/loader.js +14 -32
  125. package/dist/authorization/permissions/schema.d.ts +1 -6
  126. package/dist/authorization/permissions/schema.js +6 -13
  127. package/dist/authorization/protected-branch.d.ts +36 -65
  128. package/dist/authorization/protected-branch.js +29 -41
  129. package/dist/authorization/settings-file-store.d.ts +38 -81
  130. package/dist/authorization/settings-file-store.js +38 -79
  131. package/dist/authorization/types.d.ts +4 -26
  132. package/dist/authorization/types.js +0 -6
  133. package/dist/authorization/validation.d.ts +1 -23
  134. package/dist/authorization/validation.js +1 -24
  135. package/dist/branch-health.d.ts +39 -67
  136. package/dist/branch-health.js +27 -43
  137. package/dist/branch-metadata-file.d.ts +16 -32
  138. package/dist/branch-metadata-file.js +13 -26
  139. package/dist/branch-metadata.d.ts +49 -80
  140. package/dist/branch-metadata.js +57 -87
  141. package/dist/branch-registry.d.ts +26 -64
  142. package/dist/branch-registry.js +44 -93
  143. package/dist/branch-schema-cache.d.ts +34 -124
  144. package/dist/branch-schema-cache.js +49 -155
  145. package/dist/branch-workspace.d.ts +4 -4
  146. package/dist/branch-workspace.js +15 -19
  147. package/dist/build/generate-ai-content.d.ts +1 -0
  148. package/dist/build/generate-ai-content.js +12 -25
  149. package/dist/build-canopy.d.ts +17 -27
  150. package/dist/build-canopy.js +16 -23
  151. package/dist/build-mode.d.ts +25 -27
  152. package/dist/build-mode.js +25 -29
  153. package/dist/cli/cli.d.ts +15 -26
  154. package/dist/cli/cli.js +601 -978
  155. package/dist/cli/generate-ai-content.js +351 -628
  156. package/dist/cli/github-app-manifest.d.ts +84 -0
  157. package/dist/cli/github-app-manifest.js +161 -0
  158. package/dist/cli/init-github-app.d.ts +110 -444
  159. package/dist/cli/init-github-app.js +236 -773
  160. package/dist/cli/init.js +39 -80
  161. package/dist/cli/migrate.d.ts +13 -10
  162. package/dist/cli/migrate.js +22 -30
  163. package/dist/cli/project-detect.d.ts +17 -31
  164. package/dist/cli/project-detect.js +31 -42
  165. package/dist/cli/project-root.d.ts +4 -11
  166. package/dist/cli/project-root.js +4 -11
  167. package/dist/cli/prompt.d.ts +10 -0
  168. package/dist/cli/prompt.js +67 -0
  169. package/dist/cli/sync.d.ts +0 -8
  170. package/dist/cli/sync.js +8 -28
  171. package/dist/cli/template-files/middleware.ts.template +15 -29
  172. package/dist/cli/templates.d.ts +2 -12
  173. package/dist/cli/templates.js +4 -4
  174. package/dist/client.d.ts +1 -1
  175. package/dist/comment-store.d.ts +32 -53
  176. package/dist/comment-store.js +32 -52
  177. package/dist/config/flatten.d.ts +0 -3
  178. package/dist/config/flatten.js +2 -12
  179. package/dist/config/helpers.js +2 -2
  180. package/dist/config/index.d.ts +2 -2
  181. package/dist/config/index.js +1 -4
  182. package/dist/config/schemas/collection.d.ts +0 -8
  183. package/dist/config/schemas/collection.js +0 -10
  184. package/dist/config/schemas/config.d.ts +6 -78
  185. package/dist/config/schemas/config.js +38 -54
  186. package/dist/config/schemas/field.d.ts +2 -242
  187. package/dist/config/schemas/field.js +9 -20
  188. package/dist/config/schemas/media.js +1 -1
  189. package/dist/config/schemas/permissions.js +0 -2
  190. package/dist/config/schemas/url.d.ts +5 -6
  191. package/dist/config/schemas/url.js +5 -6
  192. package/dist/config/types.d.ts +45 -33
  193. package/dist/config/types.js +0 -1
  194. package/dist/config.d.ts +1 -8
  195. package/dist/config.js +1 -9
  196. package/dist/content-id-index.d.ts +76 -188
  197. package/dist/content-id-index.js +79 -230
  198. package/dist/content-index-generation.d.ts +27 -48
  199. package/dist/content-index-generation.js +35 -84
  200. package/dist/content-index-registry.d.ts +15 -24
  201. package/dist/content-index-registry.js +5 -9
  202. package/dist/content-listing.d.ts +64 -107
  203. package/dist/content-listing.js +68 -118
  204. package/dist/content-reader.d.ts +20 -29
  205. package/dist/content-reader.js +10 -18
  206. package/dist/content-store.d.ts +210 -336
  207. package/dist/content-store.js +413 -657
  208. package/dist/content-tree.d.ts +44 -86
  209. package/dist/content-tree.js +26 -54
  210. package/dist/context.d.ts +67 -94
  211. package/dist/context.js +53 -72
  212. package/dist/dev-content-watcher.d.ts +18 -18
  213. package/dist/dev-content-watcher.js +41 -44
  214. package/dist/editor/BranchManager.d.ts +3 -6
  215. package/dist/editor/BranchManager.js +24 -44
  216. package/dist/editor/CanopyEditor.js +5 -2
  217. package/dist/editor/CommentsPanel.js +0 -2
  218. package/dist/editor/Editor.js +19 -76
  219. package/dist/editor/EditorAuthGate.d.ts +27 -0
  220. package/dist/editor/EditorAuthGate.js +140 -0
  221. package/dist/editor/EntryNavigator.js +0 -20
  222. package/dist/editor/FormRenderer.d.ts +1 -2
  223. package/dist/editor/FormRenderer.js +8 -23
  224. package/dist/editor/admin/SystemHealthPanel.js +20 -37
  225. package/dist/editor/admin/useSystemHealth.d.ts +2 -3
  226. package/dist/editor/admin/useSystemHealth.js +10 -12
  227. package/dist/editor/client-reference-resolver.d.ts +2 -5
  228. package/dist/editor/client-reference-resolver.js +2 -19
  229. package/dist/editor/comments/BranchComments.js +0 -4
  230. package/dist/editor/comments/EntryComments.js +0 -4
  231. package/dist/editor/comments/FieldWrapper.js +0 -4
  232. package/dist/editor/comments/InlineCommentThread.js +0 -2
  233. package/dist/editor/comments/ThreadCarousel.d.ts +0 -58
  234. package/dist/editor/comments/ThreadCarousel.js +0 -12
  235. package/dist/editor/components/EditorFooter.d.ts +0 -8
  236. package/dist/editor/components/EditorFooter.js +0 -5
  237. package/dist/editor/components/EditorHeader.d.ts +0 -31
  238. package/dist/editor/components/EditorHeader.js +21 -71
  239. package/dist/editor/components/EditorSidebar.d.ts +0 -19
  240. package/dist/editor/components/EditorSidebar.js +0 -16
  241. package/dist/editor/components/EntryCreateModal.d.ts +4 -4
  242. package/dist/editor/components/EntryCreateModal.js +7 -22
  243. package/dist/editor/components/RenameEntryModal.js +0 -4
  244. package/dist/editor/components/UserBadge.js +0 -10
  245. package/dist/editor/components/index.js +0 -2
  246. package/dist/editor/context/ApiClientContext.d.ts +8 -7
  247. package/dist/editor/context/ApiClientContext.js +39 -11
  248. package/dist/editor/context/AssetContext.d.ts +7 -17
  249. package/dist/editor/context/AssetContext.js +7 -17
  250. package/dist/editor/context/EditorIdentityContext.d.ts +13 -0
  251. package/dist/editor/context/EditorIdentityContext.js +7 -0
  252. package/dist/editor/context/EditorStateContext.d.ts +10 -41
  253. package/dist/editor/context/EditorStateContext.js +7 -23
  254. package/dist/editor/context/SWRProvider.d.ts +3 -6
  255. package/dist/editor/context/index.d.ts +1 -20
  256. package/dist/editor/context/index.js +1 -20
  257. package/dist/editor/editor-utils.d.ts +8 -47
  258. package/dist/editor/editor-utils.js +19 -72
  259. package/dist/editor/fields/BlockField.d.ts +2 -2
  260. package/dist/editor/fields/BlockField.js +1 -2
  261. package/dist/editor/fields/CodeField.d.ts +0 -1
  262. package/dist/editor/fields/CodeField.js +0 -1
  263. package/dist/editor/fields/DateTimeField.d.ts +15 -22
  264. package/dist/editor/fields/DateTimeField.js +17 -26
  265. package/dist/editor/fields/ImageField.d.ts +2 -2
  266. package/dist/editor/fields/ImageField.js +8 -14
  267. package/dist/editor/fields/InlineGroupField.d.ts +0 -1
  268. package/dist/editor/fields/InlineGroupField.js +0 -1
  269. package/dist/editor/fields/MarkdownField.d.ts +0 -1
  270. package/dist/editor/fields/MarkdownField.js +6 -11
  271. package/dist/editor/fields/MdxImageDialog.d.ts +1 -1
  272. package/dist/editor/fields/MdxImageDialog.js +0 -1
  273. package/dist/editor/fields/NumberField.d.ts +9 -19
  274. package/dist/editor/fields/NumberField.js +11 -22
  275. package/dist/editor/fields/NumberListField.d.ts +7 -10
  276. package/dist/editor/fields/NumberListField.js +7 -10
  277. package/dist/editor/fields/ObjectField.d.ts +5 -8
  278. package/dist/editor/fields/ObjectField.js +0 -1
  279. package/dist/editor/fields/ReferenceField.d.ts +1 -1
  280. package/dist/editor/fields/ReferenceField.js +11 -16
  281. package/dist/editor/fields/SelectField.d.ts +2 -2
  282. package/dist/editor/fields/SelectField.js +0 -1
  283. package/dist/editor/fields/StringListField.d.ts +0 -4
  284. package/dist/editor/fields/StringListField.js +4 -9
  285. package/dist/editor/fields/TextField.d.ts +0 -1
  286. package/dist/editor/fields/TextField.js +0 -1
  287. package/dist/editor/fields/ToggleField.d.ts +0 -1
  288. package/dist/editor/fields/ToggleField.js +0 -1
  289. package/dist/editor/fields/entry-link/EntryLinkContext.js +2 -4
  290. package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +0 -3
  291. package/dist/editor/fields/entry-link/InsertEntryLink.js +0 -4
  292. package/dist/editor/group-manager/ExternalGroupsTab.d.ts +0 -3
  293. package/dist/editor/group-manager/ExternalGroupsTab.js +0 -1
  294. package/dist/editor/group-manager/GroupCard.d.ts +0 -3
  295. package/dist/editor/group-manager/GroupForm.d.ts +0 -3
  296. package/dist/editor/group-manager/InternalGroupsTab.d.ts +0 -3
  297. package/dist/editor/group-manager/InternalGroupsTab.js +0 -2
  298. package/dist/editor/group-manager/MemberList.d.ts +0 -3
  299. package/dist/editor/group-manager/hooks/useExternalGroupSearch.d.ts +0 -3
  300. package/dist/editor/group-manager/hooks/useExternalGroupSearch.js +0 -3
  301. package/dist/editor/group-manager/hooks/useGroupState.d.ts +0 -3
  302. package/dist/editor/group-manager/hooks/useGroupState.js +0 -5
  303. package/dist/editor/group-manager/hooks/useUserSearch.d.ts +0 -3
  304. package/dist/editor/group-manager/hooks/useUserSearch.js +0 -3
  305. package/dist/editor/group-manager/index.d.ts +0 -6
  306. package/dist/editor/group-manager/index.js +0 -10
  307. package/dist/editor/group-manager/types.d.ts +2 -5
  308. package/dist/editor/group-manager/types.js +0 -3
  309. package/dist/editor/hooks/index.d.ts +6 -11
  310. package/dist/editor/hooks/index.js +6 -12
  311. package/dist/editor/hooks/useBranchActions.d.ts +0 -14
  312. package/dist/editor/hooks/useBranchActions.js +0 -22
  313. package/dist/editor/hooks/useBranchManager.d.ts +2 -48
  314. package/dist/editor/hooks/useBranchManager.js +4 -64
  315. package/dist/editor/hooks/useBranchesData.d.ts +7 -6
  316. package/dist/editor/hooks/useBranchesData.js +7 -6
  317. package/dist/editor/hooks/useCommentSystem.d.ts +0 -49
  318. package/dist/editor/hooks/useCommentSystem.js +1 -36
  319. package/dist/editor/hooks/useDraftManager.d.ts +2 -35
  320. package/dist/editor/hooks/useDraftManager.js +23 -64
  321. package/dist/editor/hooks/useEditorLayout.d.ts +0 -20
  322. package/dist/editor/hooks/useEditorLayout.js +0 -23
  323. package/dist/editor/hooks/useEntriesData.d.ts +1 -0
  324. package/dist/editor/hooks/useEntriesData.js +2 -3
  325. package/dist/editor/hooks/useEntryLinkResolution.d.ts +2 -2
  326. package/dist/editor/hooks/useEntryLinkResolution.js +2 -2
  327. package/dist/editor/hooks/useEntryManager.d.ts +2 -27
  328. package/dist/editor/hooks/useEntryManager.js +29 -78
  329. package/dist/editor/hooks/useGroupManager.d.ts +0 -21
  330. package/dist/editor/hooks/useGroupManager.js +0 -21
  331. package/dist/editor/hooks/usePermissionManager.d.ts +0 -20
  332. package/dist/editor/hooks/usePermissionManager.js +0 -20
  333. package/dist/editor/hooks/useReferenceResolution.d.ts +2 -33
  334. package/dist/editor/hooks/useReferenceResolution.js +1 -48
  335. package/dist/editor/hooks/useSchemaManager.d.ts +8 -27
  336. package/dist/editor/hooks/useSchemaManager.js +0 -19
  337. package/dist/editor/hooks/useUserContext.d.ts +2 -9
  338. package/dist/editor/hooks/useUserContext.js +10 -10
  339. package/dist/editor/hooks/useUserMetadata.d.ts +0 -2
  340. package/dist/editor/hooks/useUserMetadata.js +0 -3
  341. package/dist/editor/media/AssetCard.d.ts +0 -1
  342. package/dist/editor/media/AssetCard.js +1 -2
  343. package/dist/editor/media/CropStep.d.ts +0 -1
  344. package/dist/editor/media/CropStep.js +0 -1
  345. package/dist/editor/media/MediaLibrary.d.ts +1 -2
  346. package/dist/editor/media/MediaLibrary.js +1 -2
  347. package/dist/editor/media/MediaLibraryBody.d.ts +0 -1
  348. package/dist/editor/media/MediaLibraryBody.js +0 -1
  349. package/dist/editor/media/crop-math.d.ts +1 -1
  350. package/dist/editor/media/crop-math.js +1 -1
  351. package/dist/editor/permission-manager/GroupSelector.d.ts +0 -3
  352. package/dist/editor/permission-manager/PermissionEditor.d.ts +0 -4
  353. package/dist/editor/permission-manager/PermissionEditor.js +0 -1
  354. package/dist/editor/permission-manager/PermissionLevelBadge.d.ts +0 -7
  355. package/dist/editor/permission-manager/PermissionLevelBadge.js +0 -4
  356. package/dist/editor/permission-manager/PermissionTree.d.ts +0 -4
  357. package/dist/editor/permission-manager/UserSelector.d.ts +0 -3
  358. package/dist/editor/permission-manager/constants.d.ts +0 -3
  359. package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts +0 -3
  360. package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js +0 -10
  361. package/dist/editor/permission-manager/hooks/usePermissionTree.d.ts +0 -14
  362. package/dist/editor/permission-manager/hooks/usePermissionTree.js +0 -11
  363. package/dist/editor/permission-manager/index.d.ts +0 -7
  364. package/dist/editor/permission-manager/index.js +0 -16
  365. package/dist/editor/permission-manager/types.d.ts +2 -12
  366. package/dist/editor/permission-manager/types.js +0 -3
  367. package/dist/editor/permission-manager/utils.d.ts +0 -28
  368. package/dist/editor/permission-manager/utils.js +9 -23
  369. package/dist/editor/preview-bridge.d.ts +5 -1
  370. package/dist/editor/preview-bridge.js +4 -4
  371. package/dist/editor/schema-editor/CollectionEditor.d.ts +0 -5
  372. package/dist/editor/schema-editor/CollectionEditor.js +9 -31
  373. package/dist/editor/schema-editor/EntryTypeEditor.d.ts +0 -6
  374. package/dist/editor/schema-editor/EntryTypeEditor.js +3 -24
  375. package/dist/editor/schema-editor/index.d.ts +0 -7
  376. package/dist/editor/schema-editor/index.js +0 -7
  377. package/dist/editor/utils/env.d.ts +3 -18
  378. package/dist/editor/utils/env.js +6 -25
  379. package/dist/entry-link-resolver.d.ts +13 -35
  380. package/dist/entry-link-resolver.js +20 -53
  381. package/dist/entry-schema-registry.d.ts +20 -60
  382. package/dist/entry-schema-registry.js +20 -69
  383. package/dist/entry-schema.d.ts +118 -223
  384. package/dist/entry-schema.js +46 -91
  385. package/dist/git-manager.d.ts +101 -200
  386. package/dist/git-manager.js +211 -384
  387. package/dist/github-service.d.ts +34 -75
  388. package/dist/github-service.js +37 -91
  389. package/dist/http/handler.d.ts +6 -37
  390. package/dist/http/handler.js +65 -120
  391. package/dist/http/router.d.ts +15 -32
  392. package/dist/http/router.js +34 -99
  393. package/dist/http/types.d.ts +15 -40
  394. package/dist/http/types.js +3 -7
  395. package/dist/id.d.ts +4 -10
  396. package/dist/id.js +4 -10
  397. package/dist/index.js +6 -9
  398. package/dist/operating-mode/client-safe-strategy.d.ts +7 -14
  399. package/dist/operating-mode/client-safe-strategy.js +8 -28
  400. package/dist/operating-mode/client-unsafe-strategy.d.ts +6 -16
  401. package/dist/operating-mode/client-unsafe-strategy.js +9 -34
  402. package/dist/operating-mode/client.d.ts +3 -10
  403. package/dist/operating-mode/client.js +3 -8
  404. package/dist/operating-mode/deployment-name-fixtures.d.ts +14 -18
  405. package/dist/operating-mode/deployment-name-fixtures.js +14 -18
  406. package/dist/operating-mode/deployment-name.d.ts +19 -29
  407. package/dist/operating-mode/deployment-name.js +29 -47
  408. package/dist/operating-mode/index.d.ts +4 -25
  409. package/dist/operating-mode/index.js +9 -31
  410. package/dist/operating-mode/mode-env.d.ts +32 -54
  411. package/dist/operating-mode/mode-env.js +36 -58
  412. package/dist/operating-mode/types.d.ts +24 -72
  413. package/dist/operating-mode/types.js +1 -7
  414. package/dist/paths/branch-name.d.ts +30 -40
  415. package/dist/paths/branch-name.js +30 -40
  416. package/dist/paths/branch.d.ts +4 -18
  417. package/dist/paths/branch.js +6 -22
  418. package/dist/paths/index.d.ts +2 -13
  419. package/dist/paths/index.js +3 -23
  420. package/dist/paths/normalize-server.d.ts +3 -15
  421. package/dist/paths/normalize-server.js +3 -15
  422. package/dist/paths/normalize.d.ts +13 -33
  423. package/dist/paths/normalize.js +13 -33
  424. package/dist/paths/resolve.d.ts +4 -17
  425. package/dist/paths/resolve.js +4 -22
  426. package/dist/paths/types.d.ts +12 -34
  427. package/dist/paths/types.js +5 -7
  428. package/dist/paths/validation.d.ts +22 -119
  429. package/dist/paths/validation.js +30 -148
  430. package/dist/reference-resolver.d.ts +0 -13
  431. package/dist/reference-resolver.js +0 -18
  432. package/dist/resolve-canopy-user.d.ts +16 -18
  433. package/dist/resolve-canopy-user.js +17 -26
  434. package/dist/resource-generation.d.ts +16 -25
  435. package/dist/resource-generation.js +34 -97
  436. package/dist/schema/meta-loader.d.ts +2 -14
  437. package/dist/schema/meta-loader.js +15 -64
  438. package/dist/schema/resolver.d.ts +1 -4
  439. package/dist/schema/resolver.js +1 -6
  440. package/dist/schema/schema-store-types.d.ts +0 -12
  441. package/dist/schema/schema-store.d.ts +61 -138
  442. package/dist/schema/schema-store.js +85 -282
  443. package/dist/schema/types.d.ts +0 -4
  444. package/dist/server.d.ts +62 -93
  445. package/dist/server.js +63 -94
  446. package/dist/services.d.ts +23 -47
  447. package/dist/services.js +55 -98
  448. package/dist/settings-workspace.d.ts +17 -30
  449. package/dist/settings-workspace.js +51 -81
  450. package/dist/static/index.d.ts +26 -52
  451. package/dist/static/index.js +33 -67
  452. package/dist/{worker/task-queue.d.ts → task-queue/cms-task-queue.d.ts} +7 -9
  453. package/dist/task-queue/cms-task-queue.js +13 -0
  454. package/dist/task-queue/task-queue-config.d.ts +3 -0
  455. package/dist/{worker → task-queue}/task-queue-config.js +1 -6
  456. package/dist/task-queue/task-queue.d.ts +16 -22
  457. package/dist/task-queue/task-queue.js +20 -44
  458. package/dist/task-queue/types.d.ts +0 -1
  459. package/dist/task-queue/worker-status.d.ts +35 -0
  460. package/dist/task-queue/worker-status.js +40 -0
  461. package/dist/types.d.ts +40 -51
  462. package/dist/url-collision.d.ts +26 -40
  463. package/dist/url-collision.js +47 -63
  464. package/dist/url-exclusivity-fixtures.d.ts +15 -20
  465. package/dist/url-exclusivity-fixtures.js +14 -19
  466. package/dist/url-path-resolver.d.ts +8 -16
  467. package/dist/url-path-resolver.js +19 -29
  468. package/dist/user.d.ts +8 -21
  469. package/dist/user.js +10 -19
  470. package/dist/utils/async-mutex.js +4 -6
  471. package/dist/utils/atomic-write.d.ts +2 -11
  472. package/dist/utils/atomic-write.js +2 -11
  473. package/dist/utils/body-field.d.ts +8 -15
  474. package/dist/utils/body-field.js +8 -15
  475. package/dist/utils/content-serialize.d.ts +18 -24
  476. package/dist/utils/content-serialize.js +109 -160
  477. package/dist/utils/content-write-lock.d.ts +51 -106
  478. package/dist/utils/content-write-lock.js +66 -111
  479. package/dist/utils/debug.d.ts +7 -23
  480. package/dist/utils/debug.js +7 -23
  481. package/dist/utils/entry-url.d.ts +11 -23
  482. package/dist/utils/entry-url.js +11 -26
  483. package/dist/utils/error.d.ts +25 -90
  484. package/dist/utils/error.js +60 -147
  485. package/dist/utils/flatten-group-fields.d.ts +5 -7
  486. package/dist/utils/flatten-group-fields.js +5 -7
  487. package/dist/utils/format.d.ts +1 -5
  488. package/dist/utils/format.js +1 -5
  489. package/dist/utils/fs.d.ts +3 -4
  490. package/dist/utils/fs.js +3 -4
  491. package/dist/utils/git.d.ts +52 -83
  492. package/dist/utils/git.js +79 -125
  493. package/dist/utils/logger.d.ts +35 -50
  494. package/dist/utils/logger.js +35 -52
  495. package/dist/utils/provisioning-lock.d.ts +23 -35
  496. package/dist/utils/provisioning-lock.js +49 -69
  497. package/dist/utils/sanitize-href.d.ts +5 -10
  498. package/dist/utils/sanitize-href.js +8 -18
  499. package/dist/utils/title-field.d.ts +17 -20
  500. package/dist/utils/title-field.js +18 -27
  501. package/dist/utils/typed-filename.d.ts +20 -48
  502. package/dist/utils/typed-filename.js +25 -61
  503. package/dist/utils/url-prefix.d.ts +3 -3
  504. package/dist/utils/url-prefix.js +3 -3
  505. package/dist/validation/block-structural-keys.d.ts +16 -31
  506. package/dist/validation/block-structural-keys.js +19 -29
  507. package/dist/validation/deletion-checker.d.ts +0 -34
  508. package/dist/validation/deletion-checker.js +1 -43
  509. package/dist/validation/entry-link-validator.d.ts +6 -13
  510. package/dist/validation/entry-link-validator.js +4 -13
  511. package/dist/validation/entry-type-reference-validator.d.ts +13 -18
  512. package/dist/validation/entry-type-reference-validator.js +13 -18
  513. package/dist/validation/entry-validator.d.ts +13 -25
  514. package/dist/validation/entry-validator.js +15 -32
  515. package/dist/validation/field-traversal.d.ts +3 -30
  516. package/dist/validation/field-traversal.js +1 -32
  517. package/dist/validation/reference-validator.d.ts +5 -24
  518. package/dist/validation/reference-validator.js +5 -30
  519. package/dist/worker/cms-worker.d.ts +172 -232
  520. package/dist/worker/cms-worker.js +241 -333
  521. package/dist/worker/git-sync.d.ts +32 -133
  522. package/dist/worker/git-sync.js +129 -191
  523. package/dist/worker/github-auth.d.ts +13 -19
  524. package/dist/worker/github-auth.js +13 -19
  525. package/dist/worker/history-rewrite.d.ts +53 -66
  526. package/dist/worker/history-rewrite.js +54 -60
  527. package/dist/worker/log.d.ts +24 -41
  528. package/dist/worker/log.js +25 -42
  529. package/dist/worker/rebase.d.ts +20 -110
  530. package/dist/worker/rebase.js +279 -354
  531. package/dist/worker/task-runner.d.ts +32 -66
  532. package/dist/worker/task-runner.js +126 -162
  533. package/dist/worker/worker-context.d.ts +41 -81
  534. package/package.json +4 -4
  535. package/dist/cli/template-files/middleware-clerk.ts.template +0 -37
  536. package/dist/worker/task-queue-config.d.ts +0 -8
  537. package/dist/worker/task-queue.js +0 -19
  538. package/dist/worker/worker-status.d.ts +0 -47
  539. package/dist/worker/worker-status.js +0 -52
package/README.md CHANGED
@@ -2,6 +2,32 @@
2
2
 
3
3
  CanopyCMS is a schema-driven, branch-aware CMS for websites that store their content in GitHub repositories.
4
4
 
5
+ ## Which documentation matches this build
6
+
7
+ This package ships code, not documentation. The guides — `docs/adopter-migration.md`,
8
+ `docs/deploying-to-aws.md` and the project README — live in the repository and change
9
+ alongside the code, so read them at the ref **your installed version was built from**, not at
10
+ `main`. The npm provenance attestation records that ref exactly:
11
+
12
+ ```bash
13
+ V=$(node -p "require('./node_modules/canopycms/package.json').version")
14
+ curl -s "https://registry.npmjs.org/-/npm/v1/attestations/canopycms@$V" | node -e '
15
+ let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{
16
+ const a=JSON.parse(s).attestations.find(x=>x.predicateType==="https://slsa.dev/provenance/v1")
17
+ const b=JSON.parse(Buffer.from(a.bundle.dsseEnvelope.payload,"base64")).predicate.buildDefinition
18
+ console.log(b.externalParameters.workflow.ref, b.resolvedDependencies[0].digest.gitCommit)
19
+ })'
20
+ ```
21
+
22
+ Then browse `https://github.com/safeinsights/canopycms/tree/<commit>/docs`.
23
+
24
+ Check this whenever a documented behaviour does not match what you observe. It matters most on
25
+ the `int` channel: a version like `0.0.67-int.90` is published from an integration branch that
26
+ has **not** merged to `main`, so `main`'s guides describe the last stable release and simply do
27
+ not contain the sections covering your build. A missing section reads exactly like a behaviour
28
+ you misunderstood, which is why it is worth resolving the ref rather than guessing. Stable
29
+ `X.Y.Z` builds are on `main`, at tag `vX.Y.Z`.
30
+
5
31
  ## What it does for you
6
32
 
7
33
  - Lets you keep your site code and content in one repo.
@@ -644,6 +670,7 @@ to enable the interactive crop step, or `altOptional: true` for decorative image
644
670
 
645
671
  For deployment, the `canopycms-cdk` package ships an `AssetSupport` construct that provisions
646
672
  the bucket, the transform Lambda and the CloudFront behaviors. Fuller documentation — every
647
- config option, the transform directive syntax, and the AWS wiring — is in the
648
- [project README](https://github.com/safeinsights/canopycms#media-configuration) and
649
- [docs/deploying-to-aws.md](https://github.com/safeinsights/canopycms/blob/main/docs/deploying-to-aws.md).
673
+ config option, the transform directive syntax, and the AWS wiring — is in the project README's
674
+ `#media-configuration` section and in `docs/deploying-to-aws.md`. Read both at the ref this
675
+ build came from, not at `main` — see
676
+ [Which documentation matches this build](#which-documentation-matches-this-build).
@@ -24,9 +24,7 @@ import { resolveEntryLinksInText } from '../entry-link-resolver.js';
24
24
  export async function generateAIContent(options) {
25
25
  const { store, flatSchema, contentRoot, config, entryLinkUrl, generatedAt, buildId } = options;
26
26
  const files = new Map();
27
- // Build content ID index for entry link resolution
28
27
  const idIndex = await store.idIndex();
29
- // Build lookup maps from flat schema
30
28
  const collections = flatSchema.filter((item) => item.type === 'collection');
31
29
  // Track all entries for bundle filtering
32
30
  const allEntries = [];
@@ -34,12 +32,10 @@ export async function generateAIContent(options) {
34
32
  const manifestCollections = [];
35
33
  // Track root-level entries (entries in the content root, not in a subcollection)
36
34
  const rootEntries = [];
37
- // Process each collection
38
35
  for (const collection of collections) {
39
36
  // Skip the content root itself — we process its children
40
37
  if (collection.logicalPath === contentRoot)
41
38
  continue;
42
- // Check exclusion
43
39
  if (isCollectionExcluded(collection.logicalPath, contentRoot, config))
44
40
  continue;
45
41
  // Only process top-level collections and direct subcollections here
@@ -63,7 +59,6 @@ export async function generateAIContent(options) {
63
59
  }
64
60
  rootEntries.push(...rootResult.manifestEntries);
65
61
  }
66
- // Process bundles
67
62
  const manifestBundles = [];
68
63
  if (config?.bundles) {
69
64
  for (const bundle of config.bundles) {
@@ -87,8 +82,6 @@ export async function generateAIContent(options) {
87
82
  }
88
83
  }
89
84
  }
90
- // Build manifest.
91
- //
92
85
  // `generated` is emitted unless the caller named an artifact but no timestamp: a build id says
93
86
  // "this content is identified by an artifact, not by when a runner happened to build it", and a
94
87
  // wall clock alongside it would be a claim the artifact cannot support months later. Key order
@@ -108,7 +101,6 @@ async function processCollection(store, collection, flatSchema, contentRoot, con
108
101
  const entries = [];
109
102
  const cleanPath = stripContentRoot(collection.logicalPath, contentRoot);
110
103
  const manifestEntries = [];
111
- // Read entries directly in this collection (not subcollections)
112
104
  const listed = await store.getCollectionEntryPaths(collection.logicalPath);
113
105
  // Filter to only entries in this exact collection (not subcollections)
114
106
  const directEntries = listed.filter((e) => e.collection === collection.logicalPath);
@@ -116,10 +108,8 @@ async function processCollection(store, collection, flatSchema, contentRoot, con
116
108
  const entryTypeName = extractEntryTypeFromFilename(path.basename(listEntry.relativePath));
117
109
  if (!entryTypeName)
118
110
  continue;
119
- // Check entry type exclusion
120
111
  if (config?.exclude?.entryTypes?.includes(entryTypeName))
121
112
  continue;
122
- // Find the entry type config to get schema fields
123
113
  const entryTypeConfig = findEntryType(collection, entryTypeName);
124
114
  if (!entryTypeConfig)
125
115
  continue;
@@ -128,17 +118,14 @@ async function processCollection(store, collection, flatSchema, contentRoot, con
128
118
  resolveReferences: false,
129
119
  });
130
120
  const aiEntry = docToAIEntry(doc, listEntry.slug, entryTypeName, entryTypeConfig, cleanPath);
131
- // Resolve entry:ID links in body content
132
121
  if (aiEntry.body && idIndex) {
133
122
  aiEntry.body = resolveEntryLinksInText(aiEntry.body, idIndex, contentRoot, entryLinkUrl);
134
123
  }
135
- // Check predicate exclusion
136
124
  if (config?.exclude?.where?.(aiEntry))
137
125
  continue;
138
126
  // Fold in adopter-supplied markdown (e.g. a colocated sibling artifact), once per entry
139
127
  await runEntryTransform(aiEntry, doc.absolutePath, extractIdFromFilename(path.basename(listEntry.relativePath)), config);
140
128
  entries.push(aiEntry);
141
- // Write individual entry file
142
129
  const entryFilePath = `${cleanPath}/${listEntry.slug}.md`;
143
130
  const entryMarkdown = entryToMarkdown(aiEntry, config);
144
131
  files.set(entryFilePath, entryMarkdown);
@@ -153,7 +140,6 @@ async function processCollection(store, collection, flatSchema, contentRoot, con
153
140
  continue;
154
141
  }
155
142
  }
156
- // Process subcollections
157
143
  const subcollections = flatSchema.filter((item) => item.type === 'collection' && item.parentPath === collection.logicalPath);
158
144
  const manifestSubcollections = [];
159
145
  for (const sub of subcollections) {
@@ -205,7 +191,6 @@ async function processRootEntries(store, rootCollection, contentRoot, config, id
205
191
  resolveReferences: false,
206
192
  });
207
193
  const aiEntry = docToAIEntry(doc, listEntry.slug, entryTypeName, entryTypeConfig, '');
208
- // Resolve entry:ID links in body content
209
194
  if (aiEntry.body && idIndex) {
210
195
  aiEntry.body = resolveEntryLinksInText(aiEntry.body, idIndex, contentRoot, entryLinkUrl);
211
196
  }
@@ -230,17 +215,12 @@ async function processRootEntries(store, rootCollection, contentRoot, config, id
230
215
  }
231
216
  return { entries, files, manifestEntries };
232
217
  }
233
- // ---------------------------------------------------------------------------
234
- // Helpers
235
- // ---------------------------------------------------------------------------
236
- /** Strip contentRoot prefix from a logical path */
237
218
  function stripContentRoot(logicalPath, contentRoot) {
238
219
  if (logicalPath.startsWith(contentRoot + '/')) {
239
220
  return logicalPath.slice(contentRoot.length + 1);
240
221
  }
241
222
  return logicalPath;
242
223
  }
243
- /** Check if a collection is excluded by path */
244
224
  function isCollectionExcluded(logicalPath, contentRoot, config) {
245
225
  if (!config?.exclude?.collections)
246
226
  return false;
@@ -249,11 +229,9 @@ function isCollectionExcluded(logicalPath, contentRoot, config) {
249
229
  // Match against clean path or full logical path
250
230
  minimatch(cleanPath, pattern) || minimatch(logicalPath, pattern));
251
231
  }
252
- /** Find an entry type config by name within a collection */
253
232
  function findEntryType(collection, entryTypeName) {
254
233
  return collection.entries?.find((e) => e.name === entryTypeName);
255
234
  }
256
- /** Convert a ContentDocument to an AIEntry */
257
235
  function docToAIEntry(doc, slug, entryTypeName, entryTypeConfig, cleanCollectionPath) {
258
236
  return {
259
237
  slug,
@@ -326,9 +304,8 @@ async function runEntryTransform(entry, absolutePath, contentId, config) {
326
304
  console.warn(`AI content: entry transform for "${entry.slug}" (${entry.entryType}) failed:`, getErrorMessage(err));
327
305
  }
328
306
  }
329
- /** Check if an entry matches a bundle filter (filters are AND'd) */
307
+ /** Filters are AND'd: an entry must satisfy every filter field that's set. */
330
308
  function matchesBundleFilter(entry, filter, contentRoot) {
331
- // Collections filter
332
309
  if (filter.collections) {
333
310
  const matches = filter.collections.some((pattern) => {
334
311
  const cleanPattern = stripContentRoot(pattern, contentRoot);
@@ -339,19 +316,16 @@ function matchesBundleFilter(entry, filter, contentRoot) {
339
316
  if (!matches)
340
317
  return false;
341
318
  }
342
- // Entry types filter
343
319
  if (filter.entryTypes) {
344
320
  if (!filter.entryTypes.includes(entry.entryType))
345
321
  return false;
346
322
  }
347
- // Path glob filter
348
323
  if (filter.paths) {
349
324
  const entryPath = entry.collection ? `${entry.collection}/${entry.slug}` : entry.slug;
350
325
  const matches = filter.paths.some((pattern) => minimatch(entryPath, pattern));
351
326
  if (!matches)
352
327
  return false;
353
328
  }
354
- // Predicate filter
355
329
  if (filter.where) {
356
330
  if (!filter.where(entry))
357
331
  return false;
@@ -21,10 +21,6 @@ export interface AIContentHandlerOptions {
21
21
  _testFlatSchema?: FlatSchemaItem[];
22
22
  }
23
23
  /**
24
- * Create a Next.js GET handler for serving AI content.
25
- *
26
- * Returns a function compatible with Next.js route handlers.
27
- *
28
24
  * Caching strategy:
29
25
  * - Dev mode: regenerates on every request (content changes without deploys)
30
26
  * - Prod: generates once per process lifetime (Lambda instances are recycled on deploy,
@@ -16,10 +16,6 @@ import { getErrorMessage } from '../utils/error.js';
16
16
  import { generateAIContent } from './generate.js';
17
17
  import { resolveBranchRoot } from './resolve-branch.js';
18
18
  /**
19
- * Create a Next.js GET handler for serving AI content.
20
- *
21
- * Returns a function compatible with Next.js route handlers.
22
- *
23
19
  * Caching strategy:
24
20
  * - Dev mode: regenerates on every request (content changes without deploys)
25
21
  * - Prod: generates once per process lifetime (Lambda instances are recycled on deploy,
@@ -30,19 +26,15 @@ export function createAIContentHandler(options) {
30
26
  const schemaCache = new BranchSchemaCache(config.mode);
31
27
  let cachedResult = null;
32
28
  const generate = async () => {
33
- // In dev mode, always regenerate (content changes without deploys)
34
29
  if (config.mode !== 'prod') {
35
30
  cachedResult = null;
36
31
  }
37
32
  if (cachedResult)
38
33
  return cachedResult;
39
- // Resolve branch root
40
34
  const branchRoot = await resolveBranchRoot(config);
41
35
  const contentRootName = config.contentRoot || 'content';
42
- // Load schema (use test override if provided)
43
36
  const flatSchema = _testFlatSchema ??
44
37
  (await schemaCache.getSchema(branchRoot, entrySchemaRegistry, contentRootName)).flatSchema;
45
- // Create store and generate
46
38
  const store = new ContentStore(branchRoot, flatSchema, { contentRootName });
47
39
  const result = await generateAIContent({
48
40
  store,
@@ -58,9 +50,7 @@ export function createAIContentHandler(options) {
58
50
  try {
59
51
  const { path: pathSegments } = await ctx.params;
60
52
  const result = await generate();
61
- // Join path segments to get the file key
62
53
  const requestPath = pathSegments.join('/');
63
- // Check for manifest
64
54
  if (requestPath === 'manifest.json') {
65
55
  return new Response(result.files.get('manifest.json'), {
66
56
  headers: {
@@ -69,7 +59,6 @@ export function createAIContentHandler(options) {
69
59
  },
70
60
  });
71
61
  }
72
- // Check for generated file
73
62
  const content = result.files.get(requestPath);
74
63
  if (content) {
75
64
  return new Response(content, {
@@ -7,14 +7,7 @@
7
7
  export { defineAIContentConfig } from './types.js';
8
8
  export { createAIContentHandler } from './handler.js';
9
9
  export { generateAIContent } from './generate.js';
10
- /**
11
- * Convert MDX/Markdown body content to plain prose text (for a search index
12
- * or any other "just the words" consumer). Distinct from the AI-content
13
- * pipeline above: this strips markup down to human-readable text rather
14
- * than preparing MDX for model consumption. See the source JSDoc for the
15
- * full pipeline and why paired custom components keep their inner text
16
- * while losing their tags.
17
- */
10
+ /** See `to-plain-text.ts`'s module doc for the pipeline and why it differs from the AI-content path above. */
18
11
  export { toPlainText } from './to-plain-text.js';
19
12
  export type { AIContentConfig, ExcludeConfig, BundleConfig, BundleFilter, FieldTransformFn, FieldTransforms, ComponentProps, ComponentTransformFn, ComponentTransforms, BodyTransformFn, BodyTransforms, EntryTransformFn, EntryTransforms, EntryTransformContext, AIManifest, AIManifestCollection, AIManifestEntry, AIManifestBundle, AIEntry, AIEntryMeta, } from './types.js';
20
13
  export type { AIContentHandlerOptions } from './handler.js';
package/dist/ai/index.js CHANGED
@@ -7,12 +7,5 @@
7
7
  export { defineAIContentConfig } from './types.js';
8
8
  export { createAIContentHandler } from './handler.js';
9
9
  export { generateAIContent } from './generate.js';
10
- /**
11
- * Convert MDX/Markdown body content to plain prose text (for a search index
12
- * or any other "just the words" consumer). Distinct from the AI-content
13
- * pipeline above: this strips markup down to human-readable text rather
14
- * than preparing MDX for model consumption. See the source JSDoc for the
15
- * full pipeline and why paired custom components keep their inner text
16
- * while losing their tags.
17
- */
10
+ /** See `to-plain-text.ts`'s module doc for the pipeline and why it differs from the AI-content path above. */
18
11
  export { toPlainText } from './to-plain-text.js';
@@ -15,7 +15,6 @@ import { applyComponentTransforms } from './transform-components.js';
15
15
  */
16
16
  export function entryToMarkdown(entry, config) {
17
17
  const parts = [];
18
- // Entry header with YAML-style frontmatter
19
18
  parts.push('---');
20
19
  if (entry.data.title) {
21
20
  parts.push(`title: ${yamlValue(String(entry.data.title))}`);
@@ -30,11 +29,9 @@ export function entryToMarkdown(entry, config) {
30
29
  if (entry.data.title)
31
30
  skipFields.add('title');
32
31
  if (entry.format === 'md' || entry.format === 'mdx') {
33
- // For MD/MDX: render non-body fields as metadata, then body verbatim
34
32
  parts.push(...renderMarkdownEntry(entry, config, skipFields));
35
33
  }
36
34
  else {
37
- // For data-only formats (JSON/YAML): full schema-driven conversion
38
35
  parts.push(...renderJsonEntry(entry, config, skipFields));
39
36
  }
40
37
  // Markdown appended by an entry transform (e.g. a folded-in sibling artifact). Computed once
@@ -57,21 +54,18 @@ function renderMarkdownEntry(entry, config, skipFields) {
57
54
  const value = entry.data[field.name];
58
55
  if (value === undefined || value === null)
59
56
  continue;
60
- // Check for field transform
61
57
  const transformed = applyFieldTransform(entry, field, value, config);
62
58
  if (transformed !== undefined) {
63
59
  parts.push(transformed);
64
60
  parts.push('');
65
61
  continue;
66
62
  }
67
- // Simple inline rendering for metadata
68
63
  const label = field.label || field.name;
69
64
  parts.push(`**${label}:** ${formatInlineValue(field, value)}`);
70
65
  }
71
66
  if (parts.length > 0) {
72
67
  parts.push('');
73
68
  }
74
- // Append body — pipeline: stripMdxImports → componentTransforms → bodyTransforms
75
69
  if (entry.body) {
76
70
  let body = entry.format === 'mdx' ? stripMdxImports(entry.body) : entry.body;
77
71
  if (config?.componentTransforms && Object.keys(config.componentTransforms).length > 0) {
@@ -108,14 +102,9 @@ function renderJsonEntry(entry, config, skipFields) {
108
102
  /**
109
103
  * Render a single field to markdown.
110
104
  *
111
- * @param field - Field configuration from schema
112
- * @param value - The field's value
113
105
  * @param depth - Heading depth (2 = ##, 3 = ###, etc.)
114
- * @param entry - The parent entry (for transform lookups)
115
- * @param config - AI content config (for field transforms)
116
106
  */
117
107
  function renderField(field, value, depth, entry, config) {
118
- // Check for field transform override
119
108
  const transformed = applyFieldTransform(entry, field, value, config);
120
109
  if (transformed !== undefined) {
121
110
  return transformed;
@@ -127,7 +116,6 @@ function renderField(field, value, depth, entry, config) {
127
116
  // Adopters run this output through their own formatting, so emitting the form Prettier
128
117
  // already agrees with is what keeps a regenerated bundle diff-free.
129
118
  const descriptionLine = 'description' in field && field.description ? `\n\n_${field.description}_` : '';
130
- // Handle list fields
131
119
  if ('list' in field && field.list && Array.isArray(value)) {
132
120
  return renderListField(field, value, depth, label, heading, descriptionLine, entry, config);
133
121
  }
@@ -154,7 +142,6 @@ function renderField(field, value, depth, entry, config) {
154
142
  case 'block':
155
143
  return renderBlockField(field, value, depth, heading, label, descriptionLine, entry, config);
156
144
  default:
157
- // Custom or unknown field type — render as string
158
145
  return `${heading} ${label}${descriptionLine}\n\n${String(value)}`;
159
146
  }
160
147
  }
@@ -173,7 +160,6 @@ function renderListField(field, values, depth, label, heading, descriptionLine,
173
160
  }
174
161
  const isComplex = field.type === 'object' || field.type === 'block';
175
162
  if (isComplex) {
176
- // For complex types, render each item as a subsection
177
163
  const items = values
178
164
  .map((item, i) => {
179
165
  const itemLabel = `${label} ${i + 1}`;
@@ -195,7 +181,6 @@ function renderListField(field, values, depth, label, heading, descriptionLine,
195
181
  .filter(Boolean);
196
182
  return `${heading} ${label}${descriptionLine}\n\n${items.join('\n\n')}`;
197
183
  }
198
- // For primitive types, render as markdown list
199
184
  const items = values.map((v) => `- ${formatInlineValue(field, v)}`).join('\n');
200
185
  return `${heading} ${label}${descriptionLine}\n\n${items}`;
201
186
  }
@@ -275,9 +260,6 @@ function escapeTableCell(value) {
275
260
  .replace(/\r?\n+/g, ' ')
276
261
  .trim();
277
262
  }
278
- /**
279
- * Render a select field.
280
- */
281
263
  function renderSelectField(field, value, heading, label, descriptionLine) {
282
264
  if (Array.isArray(value)) {
283
265
  return `${heading} ${label}${descriptionLine}\n\n${value.map((v) => resolveSelectLabel(field, v)).join(', ')}`;
@@ -301,9 +283,6 @@ function resolveSelectLabel(field, value) {
301
283
  }
302
284
  return strValue;
303
285
  }
304
- /**
305
- * Render a reference field.
306
- */
307
286
  function renderReferenceField(value, heading, label, descriptionLine) {
308
287
  if (Array.isArray(value)) {
309
288
  const items = value.map((v) => `- ${formatReference(v)}`).join('\n');
@@ -311,7 +290,6 @@ function renderReferenceField(value, heading, label, descriptionLine) {
311
290
  }
312
291
  return `${heading} ${label}${descriptionLine}\n\n${formatReference(value)}`;
313
292
  }
314
- /** True for a plain object (not null, not an array) with a string `src`. */
315
293
  function isImageValueLike(value) {
316
294
  return (typeof value === 'object' &&
317
295
  value !== null &&
@@ -319,18 +297,11 @@ function isImageValueLike(value) {
319
297
  typeof value.src === 'string');
320
298
  }
321
299
  /**
322
- * Sanitize `alt` for the `[...]` link-text span of `![alt](src)`. `alt` is
323
- * user free-text, so a crafted value like `x](/a) [pwn](https://evil.com)`
324
- * could otherwise inject a second, attacker-chosen link/image right next to
325
- * the intended one. Strips (rather than backslash-escapes) `[`, `]`, and any
326
- * backslash: alt is a human-readable description, so losing a stray literal
327
- * bracket from it is a non-issue, and stripping sidesteps a real composability
328
- * bug backslash-escaping would have - `renderObjectListTable`'s
329
- * `escapeTableCell` blindly DOUBLES every backslash in a cell's final text
330
- * (to protect its own `|`-splitting), which would silently unescape a
331
- * `\[`/`\]` produced here the moment this markdown lands in a table cell
332
- * (formatCellValue's image case, below). Newlines collapse to spaces for the
333
- * same "can't break out of the link-text span" reason.
300
+ * Sanitizes `alt` for the `[...]` span of `![alt](src)`: unescaped, a crafted alt like
301
+ * `x](/a) [pwn](https://evil.com)` injects a second attacker-chosen link/image. Strips
302
+ * (rather than escapes) `[`, `]`, backslash, and newlines — losing a stray bracket from
303
+ * descriptive text is harmless, and escaping would break under `escapeTableCell`'s blind
304
+ * backslash-doubling once this lands in a table cell (formatCellValue's image case).
334
305
  */
335
306
  function sanitizeMarkdownAltText(text) {
336
307
  return text
@@ -339,13 +310,11 @@ function sanitizeMarkdownAltText(text) {
339
310
  .trim();
340
311
  }
341
312
  /**
342
- * Percent-encode the handful of characters that would otherwise break a
343
- * bare, unbracketed markdown link destination `(src)`: a literal `)` closes
344
- * the destination early, and a space or `(` confuses where it ends. Percent-
345
- * encoding (rather than wrapping in `<...>` or backslash-escaping) is used
346
- * deliberately: it introduces no backslash of its own, so - like
347
- * `sanitizeMarkdownAltText` above - it survives `escapeTableCell`'s blind
348
- * backslash-doubling unchanged when this lands in a table cell.
313
+ * Percent-encodes the characters that would break a bare markdown link destination
314
+ * `(src)`: `)` closes it early, a space or `(` confuses where it ends. Percent-encoding
315
+ * (not `<...>` wrapping or backslash-escaping) introduces no backslash, so — like
316
+ * `sanitizeMarkdownAltText` above — it survives `escapeTableCell`'s blind backslash-doubling
317
+ * in a table cell.
349
318
  */
350
319
  function encodeMarkdownLinkDestination(src) {
351
320
  return src
@@ -355,14 +324,11 @@ function encodeMarkdownLinkDestination(src) {
355
324
  .replace(/\)/g, '%29');
356
325
  }
357
326
  /**
358
- * Format an `image` field value as markdown image syntax: `![alt](src)`.
359
- * Uses the value's own `alt` when non-empty, otherwise `altFallback`. Both
360
- * `alt` and `src` are sanitized for their respective markdown contexts (see
361
- * `sanitizeMarkdownAltText`/`encodeMarkdownLinkDestination`) since `alt` is
362
- * user free-text and `src` may contain characters unsafe in a bare link
363
- * destination. Malformed values (not a `{ src, alt }`-shaped object — e.g. a
364
- * legacy bare URL string) degrade to a plain string, matching how neighboring
365
- * field serializers (e.g. renderObjectField, formatReference) handle
327
+ * Formats an `image` field as `![alt](src)`, using `value.alt` when non-empty else
328
+ * `altFallback`. Both are sanitized (see `sanitizeMarkdownAltText` /
329
+ * `encodeMarkdownLinkDestination`) since `alt` is free text and `src` may contain
330
+ * link-breaking characters. A malformed value (not `{ src, alt }`, e.g. a legacy bare URL
331
+ * string) degrades to a plain string, matching other field serializers' handling of
366
332
  * unexpected shapes.
367
333
  */
368
334
  function formatImageMarkdown(value, altFallback) {
@@ -373,7 +339,6 @@ function formatImageMarkdown(value, altFallback) {
373
339
  return `![${sanitizeMarkdownAltText(alt)}](${encodeMarkdownLinkDestination(value.src)})`;
374
340
  }
375
341
  /**
376
- * Format a single reference value.
377
342
  * References may be resolved (objects with data) or unresolved (string IDs).
378
343
  */
379
344
  function formatReference(value) {
@@ -387,9 +352,6 @@ function formatReference(value) {
387
352
  // Unresolved — raw ID or string
388
353
  return String(value);
389
354
  }
390
- /**
391
- * Render an object field with nested fields.
392
- */
393
355
  function renderObjectField(field, value, depth, heading, label, descriptionLine, entry, config) {
394
356
  if (typeof value !== 'object' || value === null) {
395
357
  return `${heading} ${label}${descriptionLine}\n\n${String(value)}`;
@@ -444,10 +406,6 @@ function renderBlockField(field, value, depth, heading, label, descriptionLine,
444
406
  return '';
445
407
  return `${heading} ${label}${descriptionLine}\n\n${items.join('\n\n')}`;
446
408
  }
447
- /**
448
- * Apply a field transform if one exists for this entry type + field name.
449
- * Returns undefined if no transform applies.
450
- */
451
409
  function applyFieldTransform(entry, field, value, config) {
452
410
  if (!config?.fieldTransforms)
453
411
  return undefined;
@@ -478,7 +436,6 @@ function formatInlineValue(field, value) {
478
436
  return String(value);
479
437
  }
480
438
  /**
481
- * Escape a value for YAML frontmatter.
482
439
  * Wraps in quotes if value contains special characters.
483
440
  */
484
441
  function yamlValue(value) {
@@ -6,12 +6,7 @@ import type { CanopyConfig } from '../config/index.js';
6
6
  /**
7
7
  * Resolve the branch root directory for reading content.
8
8
  *
9
- * - Static deployment, or any build: current working directory (content is in the checkout)
10
- * - Server (prod/dev) at run time: load or create the default active branch workspace
11
- *
12
- * Branch resolution priority (mirrors createActiveBranchDetector in services.ts):
13
- * 1. Explicit `defaultActiveBranch` in config
14
- * 2. In dev mode, auto-detect from git HEAD
15
- * 3. Fall back to `defaultBaseBranch` or 'main'
9
+ * The active-branch priority below mirrors `createActiveBranchDetector` in services.ts —
10
+ * keep the two in sync if either changes.
16
11
  */
17
12
  export declare function resolveBranchRoot(config: CanopyConfig): Promise<string>;
@@ -8,16 +8,10 @@ import { detectHeadBranch } from '../utils/git.js';
8
8
  /**
9
9
  * Resolve the branch root directory for reading content.
10
10
  *
11
- * - Static deployment, or any build: current working directory (content is in the checkout)
12
- * - Server (prod/dev) at run time: load or create the default active branch workspace
13
- *
14
- * Branch resolution priority (mirrors createActiveBranchDetector in services.ts):
15
- * 1. Explicit `defaultActiveBranch` in config
16
- * 2. In dev mode, auto-detect from git HEAD
17
- * 3. Fall back to `defaultBaseBranch` or 'main'
11
+ * The active-branch priority below mirrors `createActiveBranchDetector` in services.ts —
12
+ * keep the two in sync if either changes.
18
13
  */
19
14
  export async function resolveBranchRoot(config) {
20
- // Static deployments and builds read content directly from the checkout — no branch workspace needed
21
15
  if (readsFromCheckout(config)) {
22
16
  return process.cwd();
23
17
  }
@@ -1,18 +1,10 @@
1
1
  /**
2
2
  * Strip MDX-specific syntax from body content for AI consumption.
3
3
  *
4
- * Removes import/export statements (pure code, no content value).
5
- * Leaves JSX components intact — many carry semantic data in props
6
- * (e.g., <MatrixRow label="..." matches="1, 3" />) that would be lost
7
- * if stripped. AI models handle JSX props well for RAG.
8
- *
9
- * Handles:
10
- * - Single-line and multi-line import/export statements (brace tracking)
11
- * - Fenced code blocks (``` / ~~~) are preserved — imports/exports inside
12
- * code blocks are not stripped
13
- */
14
- /**
15
- * Remove import/export statements and collapse resulting blank lines.
16
- * Preserves content inside fenced code blocks.
4
+ * Removes import/export statements (pure code, no content value) and collapses the blank
5
+ * lines left behind. Leaves JSX components intact — many carry semantic data in props (e.g.,
6
+ * <MatrixRow label="..." matches="1, 3" />) that would be lost if stripped; AI models handle
7
+ * JSX props well for RAG. Handles both single-line and multi-line (brace-tracked) statements;
8
+ * fenced code blocks (``` / ~~~) are preserved untouched.
17
9
  */
18
10
  export declare function stripMdxImports(body: string): string;
@@ -1,19 +1,11 @@
1
1
  /**
2
2
  * Strip MDX-specific syntax from body content for AI consumption.
3
3
  *
4
- * Removes import/export statements (pure code, no content value).
5
- * Leaves JSX components intact — many carry semantic data in props
6
- * (e.g., <MatrixRow label="..." matches="1, 3" />) that would be lost
7
- * if stripped. AI models handle JSX props well for RAG.
8
- *
9
- * Handles:
10
- * - Single-line and multi-line import/export statements (brace tracking)
11
- * - Fenced code blocks (``` / ~~~) are preserved — imports/exports inside
12
- * code blocks are not stripped
13
- */
14
- /**
15
- * Remove import/export statements and collapse resulting blank lines.
16
- * Preserves content inside fenced code blocks.
4
+ * Removes import/export statements (pure code, no content value) and collapses the blank
5
+ * lines left behind. Leaves JSX components intact — many carry semantic data in props (e.g.,
6
+ * <MatrixRow label="..." matches="1, 3" />) that would be lost if stripped; AI models handle
7
+ * JSX props well for RAG. Handles both single-line and multi-line (brace-tracked) statements;
8
+ * fenced code blocks (``` / ~~~) are preserved untouched.
17
9
  */
18
10
  export function stripMdxImports(body) {
19
11
  const lines = body.split('\n');
@@ -23,13 +15,11 @@ export function stripMdxImports(body) {
23
15
  let depth = 0;
24
16
  for (const line of lines) {
25
17
  const trimmed = line.trim();
26
- // Track fenced code blocks (``` or ~~~)
27
18
  if (trimmed.startsWith('```') || trimmed.startsWith('~~~')) {
28
19
  inCodeBlock = !inCodeBlock;
29
20
  result.push(line);
30
21
  continue;
31
22
  }
32
- // Inside code blocks: keep everything
33
23
  if (inCodeBlock) {
34
24
  result.push(line);
35
25
  continue;
@@ -48,9 +38,7 @@ export function stripMdxImports(body) {
48
38
  }
49
39
  continue;
50
40
  }
51
- // Detect top-level import/export statements
52
41
  if (/^import\s/.test(trimmed) || /^export\s/.test(trimmed)) {
53
- // Count open/close braces to detect multi-line statements
54
42
  depth = 0;
55
43
  for (const ch of line) {
56
44
  if (ch === '{' || ch === '(')