canopycms 0.0.67-int.90 → 0.0.67

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
@@ -26,17 +26,11 @@ const entryTypeMetaSchema = z.object({
26
26
  maxItems: z.number().int().positive().optional(),
27
27
  });
28
28
  /**
29
- * Zod schema for .collection.json files
30
- *
31
- * A collection folder can contain:
32
- * - entries: Array of entry types with their own schemas
33
- * - collections: Nested collections (discovered via their own .collection.json files)
34
- *
35
- * Note: We can't validate `schema` against entry schema registry keys at parse time because:
36
- * 1. Entry schema registry is passed at runtime (not available during Zod schema definition)
37
- * 2. Would create circular dependency (loader → services → config → loader)
38
- *
39
- * Validation of schema references happens in resolution functions with clear error messages.
29
+ * Zod schema for .collection.json files. `schema` can't be validated against
30
+ * the entry schema registry here — the registry is only available at
31
+ * runtime, and checking at parse time would create a loader → services →
32
+ * config → loader circular dependency — so schema references are checked in
33
+ * the resolution functions instead, with clear error messages.
40
34
  */
41
35
  const collectionMetaSchema = z
42
36
  .object({
@@ -58,31 +52,21 @@ const rootCollectionMetaSchema = z.object({
58
52
  entries: z.array(entryTypeMetaSchema).optional(),
59
53
  order: z.array(z.string()).optional(), // Embedded IDs for ordering items
60
54
  });
55
+ /** Extracts the slug only — e.g. "post.hello-world.{id}.md" -> "hello-world" (the entry-type prefix and extension are dropped too, not just the ID). */
56
+ function stripEmbeddedIdFromName(name) {
57
+ return extractSlugFromFilename(name);
58
+ }
61
59
  /**
62
- * Recursively scans a directory for .collection.json files.
63
- *
64
- * Discovery Rules:
65
- * - Scans recursively from the base directory (content root)
66
- * - Each directory can have at most ONE .collection.json file
67
- * - Collection path is derived from the directory structure (e.g., "docs/api" for content/docs/api/)
68
- * - Collection name comes from the "name" field in .collection.json, NOT the directory name
69
- * - Directories without .collection.json are still scanned for nested collections
70
- * - Invalid .collection.json files cause the entire scan to fail with a descriptive error
60
+ * Recursively scans a directory for .collection.json files. Each directory
61
+ * has at most one; a directory without one is still scanned for nested
62
+ * collections beneath it. A collection's name comes from `.collection.json`'s
63
+ * "name" field, not the directory name. An invalid file fails the whole scan
64
+ * with a descriptive error.
71
65
  *
72
66
  * @param baseDir - The directory to scan (absolute path)
73
67
  * @param relativePath - Current path relative to content root (used for recursion)
74
68
  * @returns Array of collection metadata with resolved paths
75
69
  */
76
- /**
77
- * Strip embedded ID from a directory or file name, leaving the slug.
78
- * e.g., "docs.bChqT78gcaLd" -> "docs"
79
- * e.g., "post.hello-world.vh2WdhwAFiSL.md" -> "hello-world" (the SLUG, not the entry type)
80
- * e.g., "home.index.agfzDt2RLpSn.json" -> "index"
81
- */
82
- function stripEmbeddedIdFromName(name) {
83
- // Use extractSlugFromFilename which handles the ID extraction logic
84
- return extractSlugFromFilename(name);
85
- }
86
70
  async function scanForCollectionMeta(baseDir, relativePath = '') {
87
71
  const collections = [];
88
72
  try {
@@ -91,27 +75,22 @@ async function scanForCollectionMeta(baseDir, relativePath = '') {
91
75
  if (!entry.isDirectory())
92
76
  continue;
93
77
  const folderName = entry.name;
94
- // Strip embedded ID from folder name for logical path
95
- // e.g., "docs.bChqT78gcaLd" -> "docs"
96
78
  const logicalName = stripEmbeddedIdFromName(folderName);
97
79
  // Extract embedded ContentId from directory name (e.g., "posts.a1b2c3d4e5f6" → "a1b2c3d4e5f6")
98
80
  const collectionContentId = extractIdFromFilename(folderName) ?? undefined;
99
81
  const folderPath = relativePath ? `${relativePath}/${logicalName}` : logicalName;
100
82
  const absolutePath = join(baseDir, folderName);
101
83
  const metaPath = join(absolutePath, '.collection.json');
102
- // Try to load collection meta file
103
84
  try {
104
85
  await fs.access(metaPath);
105
86
  const content = await fs.readFile(metaPath, 'utf-8');
106
87
  const parsed = JSON.parse(content);
107
- // Validate with Zod
108
88
  const meta = collectionMetaSchema.parse(parsed);
109
89
  collections.push({
110
90
  ...meta,
111
- path: folderPath, // Path derived from folder name
91
+ path: folderPath,
112
92
  contentId: collectionContentId,
113
93
  });
114
- // Recursively scan for nested collection folders (they'll have their own .collection.json files)
115
94
  const nestedCollections = await scanForCollectionMeta(absolutePath, folderPath);
116
95
  collections.push(...nestedCollections);
117
96
  }
@@ -138,11 +117,6 @@ async function scanForCollectionMeta(baseDir, relativePath = '') {
138
117
  /**
139
118
  * Loads all .collection.json meta files from contentRoot, including root.
140
119
  *
141
- * This function orchestrates the complete discovery process:
142
- * 1. Attempts to load the root .collection.json (contentRoot/.collection.json) - optional
143
- * 2. Recursively scans all subdirectories for .collection.json files
144
- * 3. Returns both root configuration and nested collections
145
- *
146
120
  * Meta File Structure:
147
121
  * - Root: contentRoot/.collection.json (optional, defines root-level entry types)
148
122
  * - Collections: contentRoot/[path]/.collection.json (defines collection in that directory)
@@ -152,14 +126,12 @@ async function scanForCollectionMeta(baseDir, relativePath = '') {
152
126
  * @throws Error if any .collection.json file is malformed or invalid
153
127
  */
154
128
  export async function loadCollectionMetaFiles(contentRoot) {
155
- // Load root .collection.json (optional)
156
129
  let root = null;
157
130
  const rootMetaPath = join(contentRoot, '.collection.json');
158
131
  try {
159
132
  await fs.access(rootMetaPath);
160
133
  }
161
134
  catch (err) {
162
- // No root .collection.json - that's okay
163
135
  if (err.code === 'ENOENT') {
164
136
  // File doesn't exist, that's fine
165
137
  }
@@ -167,7 +139,6 @@ export async function loadCollectionMetaFiles(contentRoot) {
167
139
  throw err;
168
140
  }
169
141
  }
170
- // If file exists, try to read and parse it
171
142
  try {
172
143
  const content = await fs.readFile(rootMetaPath, 'utf-8');
173
144
  const parsed = JSON.parse(content);
@@ -180,13 +151,9 @@ export async function loadCollectionMetaFiles(contentRoot) {
180
151
  throw new Error(`Invalid root .collection.json`);
181
152
  }
182
153
  }
183
- // Scan for collection folders
184
154
  const collections = await scanForCollectionMeta(contentRoot);
185
155
  return { root, collections };
186
156
  }
187
- /**
188
- * Resolve schema references for entry types
189
- */
190
157
  function resolveEntryTypes(entryTypes, entrySchemaRegistry, contextName) {
191
158
  return entryTypes.map((entryType) => {
192
159
  const resolvedSchema = entrySchemaRegistry[entryType.schema];
@@ -208,11 +175,7 @@ function resolveEntryTypes(entryTypes, entrySchemaRegistry, contextName) {
208
175
  };
209
176
  });
210
177
  }
211
- /**
212
- * Resolve schema references for a single collection
213
- */
214
178
  function resolveCollectionMeta(meta, entrySchemaRegistry, allCollections) {
215
- // Resolve entry types
216
179
  const entries = meta.entries && meta.entries.length > 0
217
180
  ? resolveEntryTypes(meta.entries, entrySchemaRegistry, `collection "${meta.name}"`)
218
181
  : undefined;
@@ -240,11 +203,6 @@ function resolveCollectionMeta(meta, entrySchemaRegistry, allCollections) {
240
203
  * This function takes the loaded meta files (which contain string references like "postSchema")
241
204
  * and resolves them to actual EntrySchema arrays from the entry schema registry.
242
205
  *
243
- * Resolution Process:
244
- * 1. Root entry types: Resolve "schema" string to entry schema registry lookup
245
- * 2. Top-level collections: Resolve recursively, building nested tree structure
246
- * 3. Nested collections: Automatically grouped under their parent collections
247
- *
248
206
  * @param metaFiles - Loaded meta files from loadCollectionMetaFiles()
249
207
  * @param entrySchemaRegistry - Map of schema names to EntrySchema arrays
250
208
  * @returns Fully resolved root collection config ready for use by CanopyCMS
@@ -253,15 +211,12 @@ function resolveCollectionMeta(meta, entrySchemaRegistry, allCollections) {
253
211
  export function resolveCollectionReferences(metaFiles, entrySchemaRegistry) {
254
212
  // Build result object dynamically to avoid readonly conflicts
255
213
  const result = {};
256
- // Pass through root label if present
257
214
  if (metaFiles.root?.label) {
258
215
  result.label = metaFiles.root.label;
259
216
  }
260
- // Resolve root entry types
261
217
  if (metaFiles.root?.entries && metaFiles.root.entries.length > 0) {
262
218
  result.entries = resolveEntryTypes(metaFiles.root.entries, entrySchemaRegistry, 'root collection');
263
219
  }
264
- // Pass through root order array (embedded IDs for sorting)
265
220
  if (metaFiles.root?.order) {
266
221
  result.order = metaFiles.root.order;
267
222
  }
@@ -272,9 +227,6 @@ export function resolveCollectionReferences(metaFiles, entrySchemaRegistry) {
272
227
  }
273
228
  return result;
274
229
  }
275
- /**
276
- * Watch for changes to .collection.json files
277
- */
278
230
  export function watchCollectionMetaFiles(contentRoot, onChange) {
279
231
  const watcher = chokidar.watch(`${contentRoot}/**/.collection.json`, {
280
232
  ignoreInitial: true,
@@ -284,6 +236,5 @@ export function watchCollectionMetaFiles(contentRoot, onChange) {
284
236
  watcher.on('unlink', onChange);
285
237
  // Handle watcher errors (e.g. inotify ENOSPC/EMFILE) so an unhandled 'error' event can't crash dev.
286
238
  watcher.on('error', (err) => canopyLogWarn(`CanopyCMS: .collection.json watcher error: ${getErrorMessage(err)}`));
287
- // Return cleanup function
288
239
  return () => watcher.close();
289
240
  }
@@ -12,10 +12,6 @@ import type { EntrySchemaRegistry, SchemaResolutionResult } from './types.js';
12
12
  /**
13
13
  * Resolve schema from .collection.json files.
14
14
  *
15
- * This is the primary entry point for loading schema configuration.
16
- * It discovers all .collection.json files in the content directory
17
- * and resolves schema references using the provided registry.
18
- *
19
15
  * @param contentRoot - Path to the content directory
20
16
  * @param entrySchemaRegistry - Map of entry schema names to field definitions
21
17
  * @returns Resolved schema configuration
@@ -27,6 +23,7 @@ export declare function resolveSchema(contentRoot: string, entrySchemaRegistry:
27
23
  *
28
24
  * @param contentRoot - Path to the content directory
29
25
  * @returns true if at least one .collection.json file exists
26
+ * @internal No importer; deletion candidate in knip-no-importer-deletion-candidates.md.
30
27
  */
31
28
  export declare function hasSchemaFiles(contentRoot: string): Promise<boolean>;
32
29
  /**
@@ -11,17 +11,12 @@ import { loadCollectionMetaFiles, resolveCollectionReferences } from './meta-loa
11
11
  /**
12
12
  * Resolve schema from .collection.json files.
13
13
  *
14
- * This is the primary entry point for loading schema configuration.
15
- * It discovers all .collection.json files in the content directory
16
- * and resolves schema references using the provided registry.
17
- *
18
14
  * @param contentRoot - Path to the content directory
19
15
  * @param entrySchemaRegistry - Map of entry schema names to field definitions
20
16
  * @returns Resolved schema configuration
21
17
  * @throws Error if schema references cannot be resolved
22
18
  */
23
19
  export async function resolveSchema(contentRoot, entrySchemaRegistry) {
24
- // Load all .collection.json meta files
25
20
  const metaFiles = await loadCollectionMetaFiles(contentRoot);
26
21
  // Build source info for debugging
27
22
  const sources = [];
@@ -39,7 +34,6 @@ export async function resolveSchema(contentRoot, entrySchemaRegistry) {
39
34
  collections: [collection.name],
40
35
  });
41
36
  }
42
- // Resolve schema references to actual field definitions
43
37
  const schema = resolveCollectionReferences(metaFiles, entrySchemaRegistry);
44
38
  return { schema, sources };
45
39
  }
@@ -48,6 +42,7 @@ export async function resolveSchema(contentRoot, entrySchemaRegistry) {
48
42
  *
49
43
  * @param contentRoot - Path to the content directory
50
44
  * @returns true if at least one .collection.json file exists
45
+ * @internal No importer; deletion candidate in knip-no-importer-deletion-candidates.md.
51
46
  */
52
47
  export async function hasSchemaFiles(contentRoot) {
53
48
  const metaFiles = await loadCollectionMetaFiles(contentRoot);
@@ -6,18 +6,12 @@
6
6
  */
7
7
  import type { ContentFormat } from '../config/index.js';
8
8
  import type { LogicalPath } from '../paths/types.js';
9
- /**
10
- * Input for creating a new collection
11
- */
12
9
  export interface CreateCollectionInput {
13
10
  name: string;
14
11
  label?: string;
15
12
  parentPath?: LogicalPath;
16
13
  entries: CreateEntryTypeInput[];
17
14
  }
18
- /**
19
- * Input for creating a new entry type
20
- */
21
15
  export interface CreateEntryTypeInput {
22
16
  name: string;
23
17
  label?: string;
@@ -26,18 +20,12 @@ export interface CreateEntryTypeInput {
26
20
  default?: boolean;
27
21
  maxItems?: number;
28
22
  }
29
- /**
30
- * Input for updating a collection
31
- */
32
23
  export interface UpdateCollectionInput {
33
24
  name?: string;
34
25
  label?: string;
35
26
  slug?: string;
36
27
  order?: string[];
37
28
  }
38
- /**
39
- * Input for updating an entry type
40
- */
41
29
  export interface UpdateEntryTypeInput {
42
30
  label?: string;
43
31
  format?: ContentFormat;
@@ -1,47 +1,32 @@
1
1
  /**
2
2
  * Schema Store - handles reading and writing .collection.json files.
3
- *
4
- * This module provides CRUD operations for collection schema metadata:
5
- * - Create/update/delete collections
6
- * - Add/update/remove entry types
7
- * - Update ordering of items within collections
8
- *
9
3
  * All mutations are branch-specific (like content edits).
10
4
  *
11
5
  * ## Concurrency
12
6
  *
13
- * `.collection.json` is read-modify-written by every mutator below, and is
14
- * mutated cross-host: two warm Lambda containers (or a Lambda + the EC2
15
- * worker) on EFS can both read the same pre-mutation file and have the
16
- * second write silently clobber the first. This deviates from the standard
17
- * 3-layer recipe in docs/concurrency.md in one deliberate way: NO OCC
18
- * `version`/`writeId` fields go into `.collection.json` itself, and no
19
- * lockfile lives in the content tree. Two reasons:
7
+ * `.collection.json` is read-modify-written by every mutator below and
8
+ * mutated cross-host — two warm Lambdas, or a Lambda + the EC2 worker, on
9
+ * EFS can both read the same pre-mutation file and clobber each other's
10
+ * write. This deviates from the standard 3-layer recipe in
11
+ * docs/concurrency.md: no OCC `version`/`writeId` field goes into
12
+ * `.collection.json` itself, and no lockfile lives in the content tree —
13
+ * both are adopter-visible, git-committed files, so a rebase would make a
14
+ * version counter meaningless and a crash-leftover lockfile would land in a
15
+ * commit an adopter reviews.
20
16
  *
21
- * - `.collection.json` is an adopter-visible, git-committed content file.
22
- * Rebases rewrite it wholesale from upstream, so a `version` counter would
23
- * be meaningless (and actively misleading) the moment a rebase lands.
24
- * - A lockfile crash-leftover inside the content tree would be swept into
25
- * `git add .` at publish time — a `.lock` or `.tmp` file has no business
26
- * ending up in a commit an adopter reviews.
17
+ * Protection is instead layer 1 ({@link withLock}) + layer 3
18
+ * ({@link withOccFileLock}) on one COARSE per-branch SURROGATE lock path
19
+ * OUTSIDE the content tree (`{branchRoot}/.canopy-meta/schema`, see
20
+ * `withSchemaLock`), covering every schema mutation on the branch including
21
+ * multi-file ones. Layer 2 (OCC read-back) is skipped, since there's no
22
+ * version field to check; layer 4 (generation marker) guards the schema
23
+ * CACHE separately, not this write path.
27
24
  *
28
- * Protection is instead: layer 1 ({@link withLock}) + layer 3
29
- * ({@link withOccFileLock}) on a single COARSE per-branch SURROGATE lock
30
- * path OUTSIDE the content tree — `{branchRoot}/.canopy-meta/schema` (see
31
- * `withSchemaLock`). One lock covers every schema mutation on the branch,
32
- * including multi-file mutations (`createCollection` writes the new child's
33
- * meta AND the parent's). Layer 2 (OCC read-back) is skipped entirely since
34
- * there is no version field to check; layer 4 (generation marker) is used
35
- * separately, for the schema CACHE, not for this write path.
36
- *
37
- * Accepted residual: `deleteBranch` does NOT take this lock before its
38
- * recursive `rm` — an in-flight schema write can race a concurrent branch
39
- * deletion (the write's `rm`/rename can hit ENOTEMPTY or land in a
40
- * half-deleted tree). This mirrors the same residual documented on
41
- * `BranchMetadataFileManager.save()` in branch-metadata.ts and is not closed
42
- * here either; see `withSchemaLock`'s doc comment for the phantom-guard that
43
- * IS in place for the common ordering (branch already gone before this call
44
- * ever starts).
25
+ * Accepted residual: `deleteBranch` does not take this lock before its
26
+ * recursive `rm`, so an in-flight write can race a concurrent branch
27
+ * deletion (mirrors the residual on `BranchMetadataFileManager.save()` in
28
+ * branch-metadata.ts) — see `withSchemaLock`'s doc for the phantom-guard
29
+ * covering the common ordering instead.
45
30
  */
46
31
  import { z } from 'zod';
47
32
  import type { ContentFormat } from '../config/index.js';
@@ -219,43 +204,35 @@ export declare class SchemaOps {
219
204
  constructor(contentRoot: string, entrySchemaRegistry: EntrySchemaRegistry, services?: CanopyServices | undefined, branchRoot?: string);
220
205
  /**
221
206
  * Serialize an entire read-modify-write schema mutation behind the coarse
222
- * per-branch surrogate lock described in the module doc comment. Layers,
223
- * outermost to innermost (same structure as
224
- * `BranchMetadataFileManager.save()` — see branch-metadata.ts):
225
- *
226
- * 1. {@link withLock} — in-process FIFO mutex, deterministic same-process
227
- * serialization.
228
- * 2. {@link withOccFileLock} — server-enforced, cross-process/cross-host
229
- * mutual exclusion (proper-lockfile, mkdir-based), immune to NFS client
230
- * dentry/attribute caching.
207
+ * per-branch surrogate lock described in the module doc comment: layer 1
208
+ * ({@link withLock}, in-process FIFO mutex) wraps layer 3
209
+ * ({@link withOccFileLock}, cross-process/cross-host mkdir-based mutual
210
+ * exclusion, immune to NFS attribute caching), same structure as
211
+ * `BranchMetadataFileManager.save()` in branch-metadata.ts.
231
212
  *
232
- * NOT re-entrant: callers must never invoke this (directly or via a public
233
- * mutator) from inside a callback already running under it — `withLock`
234
- * would deadlock waiting on itself. This is why `updateOrderInner` calls
235
- * `updateCollectionInner` directly instead of the public `updateCollection`.
213
+ * NOT re-entrant — callers must never invoke this from inside a callback
214
+ * already running under it, or `withLock` deadlocks waiting on itself;
215
+ * that's why `updateOrderInner` calls `updateCollectionInner` directly
216
+ * instead of the public `updateCollection`.
236
217
  *
237
218
  * Phantom-resurrection guard: `branchRoot` can be removed by a concurrent
238
219
  * `deleteBranch` between the caller resolving its BranchContext and this
239
- * call reaching its own lock acquisition. `withOccFileLock`'s own
240
- * `mkdir({recursive:true})` on the lock directory would otherwise silently
241
- * recreate `.canopy-meta/` inside a directory tree that no longer exists
242
- * anywhere else. Checking BEFORE the lock (not after) fails fast without
243
- * paying for an acquisition on a doomed mutation.
244
- *
245
- * Residual window (accepted, same shape as branch-metadata.ts's): a call
246
- * that passes this check can still race a `deleteBranch` `rm` that starts
247
- * moments later and is still mid-flight when this call's write lands,
248
- * resurrecting the tree. `deleteBranch` does not take this lock at all
249
- * (see the module doc comment), so that race is not closed here either.
220
+ * call's own lock acquisition, which would otherwise let
221
+ * `withOccFileLock`'s `mkdir({recursive:true})` silently recreate
222
+ * `.canopy-meta/` in an otherwise-deleted tree. Checking BEFORE the lock
223
+ * fails fast instead. Residual (accepted, same shape as
224
+ * branch-metadata.ts's): a call that passes this check can still race a
225
+ * `deleteBranch` `rm` starting moments later — not closed here either,
226
+ * since `deleteBranch` never takes this lock (see the module doc comment).
250
227
  *
251
228
  * Translation happens ONLY at this boundary: inner code always sees the
252
- * raw {@link OccWriteConflictError} bubble up to here (never catches or
253
- * re-translates it itself).
229
+ * raw {@link OccWriteConflictError} bubble up here untranslated.
254
230
  */
255
231
  private withSchemaLock;
256
232
  /**
257
233
  * Invalidate schema cache for this branch after mutations, then eagerly
258
- * re-resolve on THIS host.
234
+ * re-resolve on THIS host. Every mutator calls this after `withSchemaLock`
235
+ * has returned, never inside the critical section.
259
236
  *
260
237
  * The eager re-resolve is the durable-snapshot window-E mitigation (see
261
238
  * BranchSchemaCache's class docs): the mutating host's own scan is
@@ -296,92 +273,50 @@ export declare class SchemaOps {
296
273
  private invalidateContentIdIndexes;
297
274
  /**
298
275
  * The single normalisation boundary for logical collection paths entering
299
- * this class. Every public method that accepts a logical collection path
300
- * (or, for `createCollection`, `input.parentPath`) calls this exactly once
301
- * before doing anything else with the path — that is the whole fix for the
302
- * "Collection not found" bug: `flattenSchema` (branch-schema-cache.ts)
303
- * produces content-root-prefixed logical paths (e.g. "content/posts", or
304
- * "cms/content/posts" for a multi-segment `contentRoot: 'cms/content'`),
305
- * the editor round-trips those straight back into every mutator
306
- * (`CollectionEditor.tsx` passes `editingCollection.logicalPath` as-is),
307
- * but `resolveCollectionPath(this.contentRoot, ...)` treats its second
308
- * argument as relative to `this.contentRoot` — which already embeds the
309
- * content-root segment(s). A prefixed path therefore resolved one level
310
- * too deep and was reported as not found. `updateCollectionInner` used to
311
- * strip the prefix itself (the only mutator that did); that bespoke strip
312
- * is gone now that every entry point normalises here instead.
276
+ * this class. Every public method that accepts one calls this exactly
277
+ * once, before touching the path: `flattenSchema` (branch-schema-cache.ts)
278
+ * produces content-root-prefixed logical paths (e.g. "content/posts") that
279
+ * the editor round-trips straight back into every mutator, but
280
+ * `resolveCollectionPath` treats its path argument as already relative to
281
+ * `this.contentRoot` — without stripping, a prefixed path resolves one
282
+ * level too deep and is reported as not found.
313
283
  *
314
- * Prefix-only: strips ONE leading `"{contentRootName}/"` if present (exact
315
- * string match against the full, possibly multi-segment, `contentRootName`
316
- * — never `path.basename()`, which would break a multi-segment root like
317
- * "cms/content"), otherwise returns the path unchanged. So both prefixed
318
- * (production/editor) and unprefixed (existing store tests, adopters
319
- * calling SchemaOps directly) input work. Deliberately does NOT touch the
320
- * bare root-collection sentinel (`collectionPath === this.contentRootName`,
321
- * no trailing segment): that has no trailing "/" to match, so it passes
322
- * through unchanged and the `=== this.contentRootName` checks in
284
+ * Strips ONE leading `"{contentRootName}/"` if present — exact string
285
+ * match against the full, possibly multi-segment, `contentRootName`, never
286
+ * `path.basename()` (which would break a root like "cms/content") —
287
+ * otherwise returns the path unchanged, so both prefixed and unprefixed
288
+ * callers work. Leaves the bare root-collection sentinel
289
+ * (`collectionPath === this.contentRootName`) untouched: it has no
290
+ * trailing "/" to strip, so the `=== this.contentRootName` checks in
323
291
  * `updateCollectionInner`/`updateOrderInner` keep working.
324
292
  *
325
- * CALL EXACTLY ONCE PER ENTRY POINT — it is NOT idempotent, and an earlier
326
- * version of this comment claimed it was. A sub-collection literally named
327
- * after the content root defeats the "already normalised" reasoning: with
328
- * `contentRoot: 'content'`, "content/content/x" normalises to "content/x"
329
- * and again to "x", and "content/content" normalises to "content", which
330
- * the `=== this.contentRootName` checks above then treat as the ROOT
331
- * collection — so a second call mutates a DIFFERENT collection rather than
332
- * reporting not-found. Every entry point calls this exactly once today, so
333
- * the ambiguity is unreachable; removing it needs the editor to send an
334
- * unambiguously-scoped path, tracked in
335
- * .claude/future-tasks/collection-path-content-root-ambiguity.md.
336
- *
337
- * A future public method that accepts a logical collection path must call
338
- * this first, and only once, the same way every existing one does — that is
339
- * the "safe by construction" contract this boundary is meant to provide.
293
+ * NOT idempotent — a sub-collection literally named after the content
294
+ * root can re-normalise to the ROOT collection on a second call, mutating
295
+ * the wrong one instead of reporting not-found. Every entry point calls
296
+ * this exactly once today, so the ambiguity is unreachable; see
297
+ * .claude/future-tasks/collection-path-content-root-ambiguity.md. A future
298
+ * method that accepts a logical collection path must do the same.
340
299
  */
341
300
  private normalizeCollectionPath;
342
- /**
343
- * Validate that a schema reference exists in the registry
344
- */
345
301
  validateSchemaReference(schemaKey: string): boolean;
346
- /**
347
- * Validate all schema references in entry types
348
- */
349
302
  private validateEntryTypeSchemas;
350
303
  /**
351
304
  * Validate path to prevent traversal attacks
352
305
  */
353
306
  private validatePath;
354
- /**
355
- * Read a collection's .collection.json file
356
- */
357
307
  readCollectionMeta(collectionPath: LogicalPath): Promise<CollectionMetaFile | null>;
358
- /**
359
- * Read root collection meta (content/.collection.json)
360
- */
361
308
  readRootCollectionMeta(): Promise<RootCollectionMetaFile | null>;
362
309
  /**
363
310
  * Check if a collection is empty (has no content files or child collections)
364
311
  */
365
312
  isCollectionEmpty(collectionPath: LogicalPath): Promise<boolean>;
366
- /**
367
- * Write a collection's .collection.json file
368
- */
369
313
  private writeCollectionMeta;
370
- /**
371
- * Write root collection meta
372
- */
373
314
  private writeRootCollectionMeta;
374
- /**
375
- * Create a new collection
376
- */
377
315
  createCollection(input: CreateCollectionInput): Promise<{
378
316
  collectionPath: LogicalPath;
379
317
  contentId: ContentId;
380
318
  }>;
381
319
  private createCollectionInner;
382
- /**
383
- * Update a collection's metadata
384
- */
385
320
  updateCollection(collectionPath: LogicalPath, updates: UpdateCollectionInput): Promise<void>;
386
321
  /**
387
322
  * Body of updateCollection, holding the schema lock for its full
@@ -401,24 +336,15 @@ export declare class SchemaOps {
401
336
  */
402
337
  deleteCollection(collectionPath: LogicalPath): Promise<void>;
403
338
  private deleteCollectionInner;
404
- /**
405
- * Add an entry type to a collection
406
- */
407
339
  addEntryType(collectionPath: LogicalPath, entryType: CreateEntryTypeInput): Promise<void>;
408
340
  private addEntryTypeInner;
409
- /**
410
- * Update an entry type in a collection
411
- */
412
341
  updateEntryType(collectionPath: LogicalPath, entryTypeName: string, updates: UpdateEntryTypeInput): Promise<void>;
413
342
  private updateEntryTypeInner;
414
- /**
415
- * Remove an entry type from a collection
416
- */
417
343
  removeEntryType(collectionPath: LogicalPath, entryTypeName: string): Promise<void>;
418
344
  private removeEntryTypeInner;
419
345
  /**
420
346
  * Count the number of entries using a specific entry type in a collection.
421
- * This is used to prevent breaking changes to entry types that have existing content.
347
+ * Prevents breaking changes to entry types that have existing content.
422
348
  *
423
349
  * @param collectionPath - Logical path to the collection (e.g., "content/posts")
424
350
  * @param entryTypeName - Name of the entry type to count
@@ -433,9 +359,6 @@ export declare class SchemaOps {
433
359
  * ```
434
360
  */
435
361
  countEntriesUsingType(collectionPath: LogicalPath, entryTypeName: string): Promise<number>;
436
- /**
437
- * Update the order of items in a collection
438
- */
439
362
  updateOrder(collectionPath: LogicalPath, order: string[]): Promise<void>;
440
363
  private updateOrderInner;
441
364
  }