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
@@ -2,7 +2,6 @@ import { z } from 'zod';
2
2
  import type { ApiResponse } from './types.js';
3
3
  import type { EntryValidationIssue } from '../config/index.js';
4
4
  import { type Slug } from '../paths/index.js';
5
- /** Response type for content read operations */
6
5
  export type ContentReadResponse = ApiResponse<{
7
6
  format: string;
8
7
  data: Record<string, unknown>;
@@ -10,7 +9,6 @@ export type ContentReadResponse = ApiResponse<{
10
9
  /** OCC version token: file mtime in ms. Pass back as `expectedVersion` on next write. */
11
10
  version?: number;
12
11
  }>;
13
- /** Response type for content write operations */
14
12
  export type ContentWriteResponse = ApiResponse<{
15
13
  format: string;
16
14
  data: Record<string, unknown>;
@@ -25,7 +23,6 @@ export type ContentWriteResponse = ApiResponse<{
25
23
  */
26
24
  validationWarnings?: EntryValidationIssue[];
27
25
  }>;
28
- /** Response type for reference validation */
29
26
  export type ReferenceValidationResponse = ApiResponse<{
30
27
  valid: boolean;
31
28
  errors?: Array<{
@@ -35,7 +32,6 @@ export type ReferenceValidationResponse = ApiResponse<{
35
32
  error: string;
36
33
  }>;
37
34
  }>;
38
- /** Response type for entry rename operations */
39
35
  export type RenameEntryResponse = ApiResponse<{
40
36
  newPath: string;
41
37
  }>;
@@ -58,8 +54,6 @@ export interface ValidateReferencesBody {
58
54
  export interface RenameEntryBody {
59
55
  newSlug: string;
60
56
  }
61
- /** Response type for reference options - re-exported for convenience */
62
- export type { ReferenceOptionsResponse } from './reference-options.js';
63
57
  /**
64
58
  * Exported routes for router registration
65
59
  */
@@ -22,9 +22,7 @@ function parseApiPath(apiPath, contentRoot) {
22
22
  * sentence rather than a wall of paths.
23
23
  */
24
24
  const UNKNOWN_KEY_WARNING_LIMIT = 10;
25
- // ============================================================================
26
- // Zod Schemas for Validation
27
- // ============================================================================
25
+ /** Re-exported for convenience. */
28
26
  const readContentParamsSchema = z.object({
29
27
  branch: branchNameSchema,
30
28
  path: logicalPathSchema,
@@ -78,10 +76,8 @@ const readContentHandler = async (gc, ctx, req, params) => {
78
76
  const store = new ContentStore(branchContext.branchRoot, flatSchema, {
79
77
  contentRootName: ctx.services.config.contentRoot || 'content',
80
78
  });
81
- // Parse path segments: params.path is like "content/posts/hello"
82
79
  const contentRoot = ctx.services.config.contentRoot || 'content';
83
80
  const logicalPathSegments = parseApiPath(params.path, contentRoot);
84
- // Use trivial path resolution
85
81
  let schemaItem;
86
82
  let slug;
87
83
  let relativePath;
@@ -117,10 +113,8 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
117
113
  const store = new ContentStore(branchContext.branchRoot, flatSchema, {
118
114
  contentRootName: ctx.services.config.contentRoot || 'content',
119
115
  });
120
- // Parse path segments: params.path is like "content/posts/hello" or "posts/hello"
121
116
  const contentRoot = ctx.services.config.contentRoot || 'content';
122
117
  const logicalPathSegments = parseApiPath(params.path, contentRoot);
123
- // Use trivial path resolution
124
118
  let schemaItem;
125
119
  let slug;
126
120
  let relativePath;
@@ -139,21 +133,15 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
139
133
  if (!access.allowed) {
140
134
  return { ok: false, status: 403, error: 'Forbidden' };
141
135
  }
142
- // ------------------------------------------------------------------
143
- // Authoritative schema validation at the write boundary (COMPOUND-2).
136
+ // Authoritative schema validation at the write boundary (COMPOUND-2): the server re-checks
137
+ // required fields, type/format correctness, and non-empty required references (rules shared
138
+ // with the editor via validation/entry-validator), plus reference EXISTENCE and
139
+ // EntryTypeConfig.maxItems (SCH-H3) — so a direct API call can't bypass what the editor's form
140
+ // enforces client-side.
144
141
  //
145
- // The server rejects structurally invalid entry data even when the client
146
- // is bypassed: required fields, type/format correctness, non-empty required
147
- // references (pure rules shared with the editor via validation/entry-validator),
148
- // plus reference EXISTENCE (server-only: reads the content ID index) and
149
- // EntryTypeConfig.maxItems at the create boundary (SCH-H3).
150
- //
151
- // One narrow carve-out: the editor's create flow scaffolds a brand-new entry
152
- // by writing entirely empty data (`{}` and an empty body) and only then lets
153
- // the user fill the form — so a create scaffold (target file does not exist
154
- // yet AND the payload is completely empty) skips field validation. Any write
155
- // carrying actual data, and every write to an existing entry, is validated.
156
- // ------------------------------------------------------------------
142
+ // Carve-out: a create scaffold (target doesn't exist yet, payload is entirely empty `{}`/no
143
+ // body) skips field validation, since the editor's create flow writes an empty scaffold before
144
+ // the user fills the form.
157
145
  // Resolve the entry-type config the store will write with (mirrors ContentStore.write)
158
146
  let entryTypeConfig;
159
147
  let fields = [];
@@ -182,7 +170,7 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
182
170
  // ContentStore.write() preserves it regardless of what's requested (see
183
171
  // buildPaths in content-store.ts) — so resolving from params.entryType
184
172
  // or the default here instead would let a direct API write validate a
185
- // payload against the WRONG entry type's schema (post-review M2). The
173
+ // payload against the WRONG entry type's schema. The
186
174
  // editor always sends the entry's real entryType, so this only changes
187
175
  // behavior for non-editor callers.
188
176
  const existingEntryType = await store.getExistingEntryType(schemaItem.logicalPath, slug);
@@ -212,19 +200,12 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
212
200
  const isDataOnly = isDataOnlyFormat(body.format);
213
201
  try {
214
202
  const exists = await store.documentExists(schemaItem.logicalPath, slug);
215
- // Create-intent guard (August 2026 baseline review, Critical finding): a
216
- // create request (expectedVersion === null, "must not already exist")
217
- // against a slug that already has content must never silently overwrite
218
- // it. Without this, an entry type with no required fields passes field
219
- // validation on the create path's empty payload and falls through to a
220
- // blind store.write() — this short-circuits with an unambiguous 409
221
- // before that validation (and the maxItems count below) even runs, so
222
- // the error always names the real problem instead of a confusing
223
- // "field is required" message or a bare conflict. store.write() also
224
- // enforces this same guard itself, inside its per-entry lock against a
225
- // fresh stat — that is the race-safe authoritative check; this early
226
- // return is just a cheaper, clearer-messaged fast path for the common
227
- // (non-racing) case.
203
+ // Create-intent guard: a create request (expectedVersion === null) against a slug that
204
+ // already has content must never silently overwrite it — short-circuit with 409 before field
205
+ // validation runs, so the error names the real problem instead of "field is required" or a
206
+ // bare conflict. store.write() re-enforces this itself inside its per-entry lock against a
207
+ // fresh stat (the race-safe authoritative check); this is just a cheaper fast path for the
208
+ // common case.
228
209
  if (body.expectedVersion === null && exists) {
229
210
  return {
230
211
  ok: false,
@@ -232,18 +213,15 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
232
213
  error: `An entry with slug "${slug}" already exists`,
233
214
  };
234
215
  }
235
- // [SLUG] Create-only routability check. `writeContentParamsSchema.path` runs
236
- // `parseLogicalPath`, which has no charset rule, and `ContentStore.resolvePath` casts the
237
- // last segment to `Slug` with only `.toLowerCase()` — so nothing on the write chain applied
238
- // `parseSlug` (only `renameEntry`'s `newSlug` did). A create with, say, `my_post` was
239
- // accepted, and `assertRoutableSlugs` then failed the adopter's next production build over
240
- // an entry that would 404 anyway. `store.write()` enforces this authoritatively inside its
241
- // per-entry lock; this is the cheaper, clearer-messaged fast path — without it a create that
242
- // is ALSO missing a required field reports the field, never the slug that is the real
243
- // problem (same reasoning as the create-intent guard above).
216
+ // [SLUG] Create-only routability check: `writeContentParamsSchema.path`'s `parseLogicalPath`
217
+ // has no charset rule, and `ContentStore.resolvePath` only lowercases the slug — so this is
218
+ // the only place on the write chain that applies `parseSlug` (besides `renameEntry`'s
219
+ // `newSlug`). Without it, a non-routable slug like `my_post` would build and then 404 on
220
+ // every visit. `store.write()` re-enforces this inside its per-entry lock; this is the
221
+ // cheaper, clearer-messaged fast path.
244
222
  //
245
- // Create-only on purpose: an entry that already carries a non-conforming slug must stay
246
- // saveable and renameable, since renaming it is the only way to fix the build.
223
+ // Create-only: an entry with an existing non-conforming slug must stay saveable and
224
+ // renameable, since renaming it is the only way to fix the build.
247
225
  if (!exists) {
248
226
  const routable = parseSlug(slug);
249
227
  if (!routable.ok) {
@@ -255,11 +233,10 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
255
233
  };
256
234
  }
257
235
  }
258
- // SCH-H3: enforce maxItems server-side at the create boundary. The editor
259
- // only gates its "Add" button; a direct API create could otherwise exceed
260
- // the cap. Best-effort under concurrency: the count-then-create below is
261
- // not atomic, so two simultaneous creates can still race past the cap —
262
- // the guard's real target is the single-request direct-API bypass.
236
+ // SCH-H3: enforce maxItems server-side — the editor only gates its "Add" button, so a direct
237
+ // API create could otherwise exceed the cap. Best-effort under concurrency: count-then-create
238
+ // isn't atomic, so two simultaneous creates can still race past the cap; this guards the
239
+ // single-request bypass, not the race.
263
240
  if (!exists && maxItems !== undefined && entryTypeName) {
264
241
  const collectionPath = schemaItem.type === 'entry-type' ? schemaItem.parentPath : schemaItem.logicalPath;
265
242
  const count = await store.countEntriesOfType(collectionPath, entryTypeName);
@@ -308,45 +285,24 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
308
285
  // 'warning' issues are returned alongside the successful write.
309
286
  let validationWarnings;
310
287
  const validateEntry = ctx.services.config.validateEntry;
311
- // Collapse resolved reference objects back to bare ID strings before PERSISTING, not just
312
- // before validating (the reference validator gets its own normalized copy above).
313
- //
314
- // The editor round-trips whole documents: its GET reads through `store.read()`, whose
315
- // `resolveReferences` defaults to TRUE, so form state holds `{...target data, id, slug,
316
- // collection, urlPath}` for every reference field, and a save posts that straight back. Left
317
- // unnormalized it lands in the content file verbatim — and because resolution only re-resolves
318
- // a `typeof value === 'string'`, every later read passes the frozen snapshot through and every
319
- // later save rewrites it. The reference is then permanently severed from its target: renaming
320
- // or editing the target changes nothing, silently.
321
- //
322
- // The mechanism predates reference resolution reaching listings, but `includeBody` makes it
323
- // materially worse — the snapshot now carries the target's entire prose — and `urlPath` adds a
324
- // value that goes stale the moment the target is renamed. Normalizing here is schema-driven and
325
- // idempotent: a payload that already holds ID strings is unchanged.
288
+ // Collapse resolved reference objects back to bare ID strings before persisting (the reference
289
+ // validator above gets its own copy). The editor's GET resolves references by default, so form
290
+ // state round-trips `{...target data, id, slug, collection, urlPath}` for each reference field;
291
+ // left unnormalized, a save would freeze that snapshot into the file (resolution only
292
+ // re-resolves plain ID strings), permanently severing the reference from its target. Idempotent:
293
+ // a payload that already holds ID strings is unchanged.
326
294
  const normalizedData = body.data === undefined ? undefined : normalizeReferenceValues(fields, body.data);
327
- //
328
- // Computed BEFORE the validateEntry hook and the entry-link scan, not just before the write,
329
- // so every consumer of the payload agrees with the bytes that land on disk. Otherwise an
330
- // adopter's hook inspecting a reference field saw a resolved object while the file got an ID
331
- // string -- and saw it only when the post came from the editor, since a client posting bare
332
- // IDs already gave the hook bare IDs. Normalizing first makes the hook's input deterministic
333
- // regardless of caller.
334
- // Keys with no counterpart in the schema. validateEntryData iterates the SCHEMA, so nothing
335
- // reported the inverse: a renamed or reshaped field left its old key on disk forever (the
336
- // editor round-trips the whole record, so every save rewrote it) and the only symptom was a
337
- // component receiving `undefined`. Adopter request log item 29.
338
- //
339
- // Run against normalizedData -- the shape that will actually be persisted -- so the report
340
- // matches the bytes, and so a resolved reference collapsed back to an ID string cannot be
341
- // mistaken for anything. A warning, never a rejection: the key is still written (with its
342
- // comments, see utils/content-serialize.ts), it is just not editable and nothing reads it.
343
- //
344
- // ONE issue, not one per key. The editor joins every warning into a single non-auto-closing
345
- // notification (useEntryManager.ts), so one-per-key repeated the same explanatory sentence
346
- // once per stale key, on every save, for a condition that is permanent until someone edits the
347
- // schema. The keys are listed in the message instead, capped so a schema-wide rename cannot
348
- // produce an unreadable wall of text. Worded for who can actually act: an editor cannot remove
349
- // a key the form does not render, and cannot change the schema.
295
+ // Computed before the validateEntry hook and the entry-link scan too, not just the write, so
296
+ // every consumer agrees on the same bytes — otherwise an adopter's hook could see a resolved
297
+ // object while the file got an ID string, depending on whether the post came from the editor.
298
+ // Keys with no counterpart in the schema: validateEntryData iterates the SCHEMA, so it can't
299
+ // catch the inverse — a renamed/reshaped field whose old key lingers on disk forever, silently
300
+ // read back as `undefined`. Checked against normalizedData (the bytes that will actually be
301
+ // persisted) so a resolved reference collapsed to an ID string isn't mistaken for a stray key.
302
+ // A warning, never a rejection: the key is kept in the file, just unread and uneditable — an
303
+ // editor can't remove a key the form doesn't render or change the schema. One issue listing all
304
+ // stale keys (capped), not one per key, since the editor renders warnings as a single
305
+ // notification (useEntryManager.ts).
350
306
  if (normalizedData !== undefined) {
351
307
  const unknownKeys = findUnknownKeys(fields, normalizedData);
352
308
  if (unknownKeys.length > 0) {
@@ -420,8 +376,7 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
420
376
  // Reuses the entry-type fields resolved above for schema validation. Folded into
421
377
  // `validationWarnings` (not a separate `entryLinkWarnings` field) so the editor's one
422
378
  // save-warnings notification (useEntryManager.ts) is the single place any save-time
423
- // warning surfaces -- a broken `entry:ID` link used to be computed and returned here
424
- // with no consumer anywhere in the editor, so it was silently discarded.
379
+ // warning surfaces.
425
380
  const idIndex = await store.idIndex();
426
381
  const linkValidation = validateEntryLinks(normalizedData ?? {}, fields, idIndex, body.body);
427
382
  if (linkValidation.warnings.length > 0) {
@@ -436,39 +391,27 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
436
391
  }
437
392
  catch (err) {
438
393
  if (err instanceof ContentConflictError) {
439
- // [SYNC-C1] Not an editor-vs-editor collision at all: the branch's
440
- // working tree is being rebased. Usually the write was refused outright
441
- // rather than acknowledged and then rolled back; the one exception is a
442
- // lock compromised mid-write, where the write DID land but we can no
443
- // longer prove it was exclusive. Each case carries its own message
444
- // (retry vs. reload-then-decide), so pass it through -- checked first,
445
- // since the generic branches below would otherwise blame another editor.
394
+ // [SYNC-C1] Not an editor collision: the branch is mid-rebase. Usually the write was
395
+ // refused outright, but a lock compromised mid-write can still land it — each case carries
396
+ // its own message, so pass `err.message` through rather than the generic conflict below.
446
397
  if (err instanceof BranchSyncingError) {
447
398
  return { ok: false, status: 409, error: err.message };
448
399
  }
449
- // [F1] Also not an editor-vs-editor collision: this entry's content ID
450
- // is on two files (ContentIdIndex's duplicate-ID quarantine), so the
451
- // save was refused rather than allowed to mutate an ambiguous target.
452
- // Surface its own message — the generic one below would tell the editor
453
- // to reload and retry, which cannot help and would have them hammering
454
- // a save that stays refused until an admin runs repair-content-duplicates.
400
+ // [F1] Also not an editor collision: this content ID is quarantined on two files
401
+ // (ContentIdIndex's duplicate-ID detection). The generic message below would send the
402
+ // editor into a reload-and-retry loop that can't help until an admin runs
403
+ // repair-content-duplicates, so surface this error's own message instead.
455
404
  if (err instanceof DuplicateContentIdError) {
456
405
  return { ok: false, status: 409, error: err.message };
457
406
  }
458
- // [URL] Also not an editor-vs-editor collision, and critically NOT the
459
- // same-slug case the branch below reports: no entry with this slug
460
- // exists in this collection (the early `exists` check passed). What
461
- // exists is a DIFFERENT entry claiming the same URL -- a sibling
462
- // collection's index entry, or the parent entry this index entry would
463
- // collide with. Falling through would tell the editor to look for an
464
- // entry that is not there, and discard the one message that names the
465
- // actual offender and what to do about it.
407
+ // [URL] Also not an editor collision, and not a same-slug conflict either — a DIFFERENT
408
+ // entry (a sibling collection's index entry, or this one's parent) claims the same URL.
409
+ // Surface its own message rather than telling the editor to look for an entry that exists.
466
410
  if (err instanceof UrlPathConflictError) {
467
411
  return { ok: false, status: 409, error: err.message };
468
412
  }
469
- // The early `exists` short-circuit above catches this in the common
470
- // case; this is the race-safe fallback for a collision that landed
471
- // between that check and store.write()'s in-lock stat.
413
+ // Race-safe fallback: the early `exists` check above catches the common case; this covers a
414
+ // collision that lands between that check and store.write()'s in-lock stat.
472
415
  if (body.expectedVersion === null) {
473
416
  return {
474
417
  ok: false,
@@ -482,12 +425,9 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
482
425
  error: 'Content conflict: entry was modified by another editor',
483
426
  };
484
427
  }
485
- // C2: a ContentStoreError is a known/expected client fault (validation,
486
- // bad slug, etc.) and keeps its existing 400. Anything else - ENOSPC,
487
- // EACCES, a bug - is a genuine server fault and must not be mislabeled
488
- // as the client's mistake; rethrow so it surfaces as a 500 (see
489
- // readContentHandler's store.read() catch above, which already follows
490
- // this same pattern).
428
+ // C2: a ContentStoreError is an expected client fault (bad slug, validation, etc.) and keeps
429
+ // its 400. Anything else — ENOSPC, EACCES, a bug — is a genuine server fault and must not be
430
+ // mislabeled as the client's mistake; rethrow so it surfaces as a 500.
491
431
  if (err instanceof ContentStoreError) {
492
432
  return { ok: false, status: 400, error: sanitizeErrorMessage(err.message) };
493
433
  }
@@ -500,7 +440,6 @@ const validateReferencesHandler = async (gc, ctx, req, params, body) => {
500
440
  const store = new ContentStore(branchContext.branchRoot, flatSchema, {
501
441
  contentRootName: ctx.services.config.contentRoot || 'content',
502
442
  });
503
- // Parse path segments to get collection/schema info
504
443
  const contentRoot = ctx.services.config.contentRoot || 'content';
505
444
  const logicalPathSegments = parseApiPath(params.path, contentRoot);
506
445
  let schemaItem;
@@ -522,7 +461,6 @@ const validateReferencesHandler = async (gc, ctx, req, params, body) => {
522
461
  }
523
462
  // Get ID index (automatically loads if needed)
524
463
  const idIndex = await store.idIndex();
525
- // Resolve fields from entry type schema
526
464
  let fields = [];
527
465
  if (schemaItem.type === 'entry-type') {
528
466
  fields = schemaItem.schema;
@@ -551,7 +489,6 @@ const validateReferencesHandler = async (gc, ctx, req, params, body) => {
551
489
  }
552
490
  fields = entryTypeConfig.schema || [];
553
491
  }
554
- // Validate references
555
492
  const validator = new ReferenceValidator(idIndex, fields, (name) => store.resolveCollectionItem(name)?.logicalPath);
556
493
  const result = await validator.validate(body.data);
557
494
  return {
@@ -569,10 +506,8 @@ const renameEntryHandler = async (gc, ctx, req, params, body) => {
569
506
  const store = new ContentStore(branchContext.branchRoot, flatSchema, {
570
507
  contentRootName: ctx.services.config.contentRoot || 'content',
571
508
  });
572
- // Parse path segments
573
509
  const contentRoot = ctx.services.config.contentRoot || 'content';
574
510
  const logicalPathSegments = parseApiPath(params.path, contentRoot);
575
- // Resolve to collection and slug
576
511
  let schemaItem;
577
512
  let currentSlug;
578
513
  let relativePath;
@@ -587,25 +522,19 @@ const renameEntryHandler = async (gc, ctx, req, params, body) => {
587
522
  const message = err instanceof ContentStoreError ? err.message : 'Invalid content request';
588
523
  return { ok: false, status: 400, error: sanitizeErrorMessage(message) };
589
524
  }
590
- // Check edit permission on current path
591
525
  const access = await ctx.services.checkContentAccess(branchContext, branchContext.branchRoot, relativePath, req.user, 'edit');
592
526
  if (!access.allowed) {
593
527
  return { ok: false, status: 403, error: 'Forbidden' };
594
528
  }
595
- // Rename the entry
596
529
  try {
597
530
  const result = await store.renameEntry(schemaItem.logicalPath, currentSlug, body.newSlug);
598
531
  return { ok: true, status: 200, data: { newPath: result.newPath } };
599
532
  }
600
533
  catch (err) {
601
- // [SYNC-C1] The rename was refused because the branch is mid-rebase, not
602
- // because the request was bad -- 409 + retry, never a 400.
534
+ // [SYNC-C1] Mid-rebase, not a bad request -- 409 + retry, never 400.
603
535
  if (err instanceof ContentConflictError) {
604
- // [URL] A contested-URL refusal must carry its own message. The generic
605
- // one below tells the editor to reload and retry, which cannot succeed
606
- // here -- the rename stays refused until they pick a different slug or
607
- // remove the other claimant -- which is exactly the loop
608
- // UrlPathConflictError's doc comment exists to prevent.
536
+ // [URL] A contested-URL refusal needs its own message: the generic one below tells the
537
+ // editor to reload and retry, which can't succeed until they pick a different slug.
609
538
  const passThrough = err instanceof BranchSyncingError || err instanceof UrlPathConflictError;
610
539
  return {
611
540
  ok: false,
@@ -613,19 +542,14 @@ const renameEntryHandler = async (gc, ctx, req, params, body) => {
613
542
  error: passThrough ? err.message : 'Content conflict: entry was modified by another editor',
614
543
  };
615
544
  }
616
- // C2: same distinction as writeContentHandler above - a ContentStoreError
617
- // is an expected client fault and keeps its 400; anything else is a
618
- // genuine server fault and must surface as a 500, not get mislabeled as
619
- // "Rename failed" (the client's mistake).
545
+ // C2: same rule as writeContentHandler's catch above (ContentStoreError -> 400, everything
546
+ // else -> 500).
620
547
  if (err instanceof ContentStoreError) {
621
548
  return { ok: false, status: 400, error: sanitizeErrorMessage(err.message) };
622
549
  }
623
550
  throw err;
624
551
  }
625
552
  };
626
- // ============================================================================
627
- // Route Definitions with defineEndpoint
628
- // ============================================================================
629
553
  /**
630
554
  * Read content using path-based routing
631
555
  * GET /:branch/content/:path*
@@ -1,15 +1,11 @@
1
1
  /**
2
- * Pagination constants for the entries list endpoint.
3
- *
4
- * Kept in a dependency-free module (no server-only imports) so the editor's
5
- * browser bundle can import the page-size cap without pulling in `entries.ts`
6
- * and its `node:fs`-backed transitive deps. `entries.ts` re-exports these for
7
- * API-surface discoverability.
2
+ * Pagination constants for the entries list endpoint. Kept dependency-free (no server-only
3
+ * imports) so the editor's browser bundle can import the page-size cap without pulling in
4
+ * `entries.ts` and its `node:fs`-backed deps; `entries.ts` re-exports these for API discoverability.
8
5
  */
9
6
  /**
10
- * Maximum entries the list endpoint returns per request. Larger `limit` values
11
- * are clamped to this. Paginating clients request this page size so they never
12
- * silently drift from the server's cap.
7
+ * Maximum entries the list endpoint returns per request; larger `limit` values are clamped to
8
+ * this so paginating clients never silently drift from the server's cap.
13
9
  */
14
10
  export declare const MAX_ENTRIES_PER_PAGE = 200;
15
11
  /** Default page size when a request omits `limit`. */
@@ -1,15 +1,11 @@
1
1
  /**
2
- * Pagination constants for the entries list endpoint.
3
- *
4
- * Kept in a dependency-free module (no server-only imports) so the editor's
5
- * browser bundle can import the page-size cap without pulling in `entries.ts`
6
- * and its `node:fs`-backed transitive deps. `entries.ts` re-exports these for
7
- * API-surface discoverability.
2
+ * Pagination constants for the entries list endpoint. Kept dependency-free (no server-only
3
+ * imports) so the editor's browser bundle can import the page-size cap without pulling in
4
+ * `entries.ts` and its `node:fs`-backed deps; `entries.ts` re-exports these for API discoverability.
8
5
  */
9
6
  /**
10
- * Maximum entries the list endpoint returns per request. Larger `limit` values
11
- * are clamped to this. Paginating clients request this page size so they never
12
- * silently drift from the server's cap.
7
+ * Maximum entries the list endpoint returns per request; larger `limit` values are clamped to
8
+ * this so paginating clients never silently drift from the server's cap.
13
9
  */
14
10
  export const MAX_ENTRIES_PER_PAGE = 200;
15
11
  /** Default page size when a request omits `limit`. */
@@ -2,10 +2,10 @@ import { z } from 'zod';
2
2
  import type { ContentFormat } from '../config/index.js';
3
3
  import type { ApiResponse } from './types.js';
4
4
  import type { LogicalPath, PhysicalPath, Slug, ContentId } from '../paths/types.js';
5
- export { MAX_ENTRIES_PER_PAGE, DEFAULT_ENTRIES_LIMIT } from './entries-constants.js';
6
5
  /**
7
6
  * Summary of an entry type for client display.
8
7
  * Simplified from EntryTypeConfig - doesn't include full field definitions.
8
+ * @internal No importer; deletion candidate in knip-no-importer-deletion-candidates.md.
9
9
  */
10
10
  export interface EntryTypeSummary {
11
11
  name: string;
@@ -28,6 +28,7 @@ export interface CollectionItem {
28
28
  exists?: boolean;
29
29
  canEdit?: boolean;
30
30
  }
31
+ /** @internal No importer; deletion candidate in knip-no-importer-deletion-candidates.md. */
31
32
  export interface ListEntriesParams {
32
33
  branch: string;
33
34
  collection?: LogicalPath;
@@ -49,6 +50,7 @@ export type EntriesResponse = ApiResponse<ListEntriesResponse>;
49
50
  /**
50
51
  * List entries for a branch
51
52
  * GET /:branch/entries
53
+ * @internal Exported for tests.
52
54
  */
53
55
  export declare const listEntries: import("./route-builder.js").RouteDefinition<z.ZodObject<{
54
56
  branch: z.ZodType<import("../paths/index.js").BranchName, z.ZodTypeDef, import("../paths/index.js").BranchName>;
@@ -81,21 +83,14 @@ export type DeleteEntryResponse = ApiResponse<{
81
83
  deleted: boolean;
82
84
  contentId?: string;
83
85
  /**
84
- * Set when the entry itself was deleted successfully but the collection's
85
- * order array could not be updated afterward (C6: order cleanup is
86
- * best-effort hygiene that runs AFTER the delete, so its failure must not
87
- * present as a failed delete - see content.ts's `validationWarnings` for
88
- * the same "warn, don't fail" precedent on the write path). The order
89
- * array still contains the now-nonexistent id until a later schema
90
- * mutation cleans it up.
86
+ * Set when the entry deleted successfully but the collection's order array couldn't be updated
87
+ * afterward (C6: best-effort hygiene after the delete, so its failure must not present as a
88
+ * failed delete — see content.ts's `validationWarnings`). The order array keeps the
89
+ * now-nonexistent id until the next schema mutation cleans it up.
91
90
  */
92
91
  warning?: string;
93
92
  }>;
94
- /**
95
- * Delete an entry
96
- * DELETE /:branch/entries/...entryPath
97
- * Note: Uses catch-all to support paths with slashes (e.g., content/posts/hello-world)
98
- */
93
+ /** @internal Exported for tests. */
99
94
  export declare const deleteEntry: import("./route-builder.js").RouteDefinition<z.ZodObject<{
100
95
  branch: z.ZodType<import("../paths/index.js").BranchName, z.ZodTypeDef, import("../paths/index.js").BranchName>;
101
96
  entryPath: z.ZodType<LogicalPath, z.ZodTypeDef, LogicalPath>;