canopycms 0.0.0 → 0.0.2

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 (467) hide show
  1. package/dist/auth/plugin.d.ts +8 -0
  2. package/dist/auth/plugin.d.ts.map +1 -1
  3. package/dist/build-mode.d.ts +15 -5
  4. package/dist/build-mode.d.ts.map +1 -1
  5. package/dist/build-mode.js +18 -8
  6. package/dist/build-mode.js.map +1 -1
  7. package/dist/cli/init.d.ts +2 -2
  8. package/dist/cli/init.d.ts.map +1 -1
  9. package/dist/cli/init.js +37 -36
  10. package/dist/cli/init.js.map +1 -1
  11. package/dist/cli/template-files/ai-config.ts.template +21 -0
  12. package/dist/cli/template-files/ai-route.ts.template +10 -0
  13. package/dist/cli/template-files/canopy.ts.template +24 -0
  14. package/dist/cli/templates.d.ts +5 -1
  15. package/dist/cli/templates.d.ts.map +1 -1
  16. package/dist/cli/templates.js +9 -2
  17. package/dist/cli/templates.js.map +1 -1
  18. package/dist/config/schemas/config.d.ts +4 -0
  19. package/dist/config/schemas/config.d.ts.map +1 -1
  20. package/dist/config/schemas/config.js +2 -0
  21. package/dist/config/schemas/config.js.map +1 -1
  22. package/dist/config/types.d.ts +5 -0
  23. package/dist/config/types.d.ts.map +1 -1
  24. package/dist/content-reader.js +2 -2
  25. package/dist/content-reader.js.map +1 -1
  26. package/dist/context.js +5 -5
  27. package/dist/context.js.map +1 -1
  28. package/dist/operating-mode/client-unsafe-strategy.d.ts.map +1 -1
  29. package/dist/operating-mode/client-unsafe-strategy.js +15 -18
  30. package/dist/operating-mode/client-unsafe-strategy.js.map +1 -1
  31. package/dist/operating-mode/types.d.ts +8 -0
  32. package/dist/operating-mode/types.d.ts.map +1 -1
  33. package/dist/server.d.ts +2 -0
  34. package/dist/server.d.ts.map +1 -1
  35. package/dist/server.js +2 -0
  36. package/dist/server.js.map +1 -1
  37. package/package.json +5 -4
  38. package/src/cli/init.ts +43 -38
  39. package/dist/__integration__/fixtures/content-seeds.d.ts +0 -43
  40. package/dist/__integration__/fixtures/content-seeds.d.ts.map +0 -1
  41. package/dist/__integration__/fixtures/content-seeds.js +0 -99
  42. package/dist/__integration__/fixtures/content-seeds.js.map +0 -1
  43. package/dist/__integration__/fixtures/schemas.d.ts +0 -12
  44. package/dist/__integration__/fixtures/schemas.d.ts.map +0 -1
  45. package/dist/__integration__/fixtures/schemas.js +0 -65
  46. package/dist/__integration__/fixtures/schemas.js.map +0 -1
  47. package/dist/__integration__/test-utils/api-client.d.ts +0 -123
  48. package/dist/__integration__/test-utils/api-client.d.ts.map +0 -1
  49. package/dist/__integration__/test-utils/api-client.js +0 -118
  50. package/dist/__integration__/test-utils/api-client.js.map +0 -1
  51. package/dist/__integration__/test-utils/multi-user.d.ts +0 -25
  52. package/dist/__integration__/test-utils/multi-user.d.ts.map +0 -1
  53. package/dist/__integration__/test-utils/multi-user.js +0 -105
  54. package/dist/__integration__/test-utils/multi-user.js.map +0 -1
  55. package/dist/__integration__/test-utils/test-workspace.d.ts +0 -25
  56. package/dist/__integration__/test-utils/test-workspace.d.ts.map +0 -1
  57. package/dist/__integration__/test-utils/test-workspace.js +0 -102
  58. package/dist/__integration__/test-utils/test-workspace.js.map +0 -1
  59. package/dist/editor/BranchManager.stories.d.ts +0 -8
  60. package/dist/editor/BranchManager.stories.d.ts.map +0 -1
  61. package/dist/editor/BranchManager.stories.js +0 -74
  62. package/dist/editor/BranchManager.stories.js.map +0 -1
  63. package/dist/editor/CanopyEditor.stories.d.ts +0 -7
  64. package/dist/editor/CanopyEditor.stories.d.ts.map +0 -1
  65. package/dist/editor/CanopyEditor.stories.js +0 -99
  66. package/dist/editor/CanopyEditor.stories.js.map +0 -1
  67. package/dist/editor/CommentsPanel.stories.d.ts +0 -10
  68. package/dist/editor/CommentsPanel.stories.d.ts.map +0 -1
  69. package/dist/editor/CommentsPanel.stories.js +0 -175
  70. package/dist/editor/CommentsPanel.stories.js.map +0 -1
  71. package/dist/editor/Editor.stories.d.ts +0 -7
  72. package/dist/editor/Editor.stories.d.ts.map +0 -1
  73. package/dist/editor/Editor.stories.js +0 -95
  74. package/dist/editor/Editor.stories.js.map +0 -1
  75. package/dist/editor/EditorPanes.stories.d.ts +0 -7
  76. package/dist/editor/EditorPanes.stories.d.ts.map +0 -1
  77. package/dist/editor/EditorPanes.stories.js +0 -116
  78. package/dist/editor/EditorPanes.stories.js.map +0 -1
  79. package/dist/editor/EntryNavigator.stories.d.ts +0 -8
  80. package/dist/editor/EntryNavigator.stories.d.ts.map +0 -1
  81. package/dist/editor/EntryNavigator.stories.js +0 -42
  82. package/dist/editor/EntryNavigator.stories.js.map +0 -1
  83. package/dist/editor/FormRenderer.stories.d.ts +0 -7
  84. package/dist/editor/FormRenderer.stories.d.ts.map +0 -1
  85. package/dist/editor/FormRenderer.stories.js +0 -115
  86. package/dist/editor/FormRenderer.stories.js.map +0 -1
  87. package/dist/editor/GroupManager.stories.d.ts +0 -19
  88. package/dist/editor/GroupManager.stories.d.ts.map +0 -1
  89. package/dist/editor/GroupManager.stories.js +0 -265
  90. package/dist/editor/GroupManager.stories.js.map +0 -1
  91. package/dist/editor/PermissionManager.stories.d.ts +0 -20
  92. package/dist/editor/PermissionManager.stories.d.ts.map +0 -1
  93. package/dist/editor/PermissionManager.stories.js +0 -506
  94. package/dist/editor/PermissionManager.stories.js.map +0 -1
  95. package/dist/editor/comments/FieldWrapper.stories.d.ts +0 -10
  96. package/dist/editor/comments/FieldWrapper.stories.d.ts.map +0 -1
  97. package/dist/editor/comments/FieldWrapper.stories.js +0 -173
  98. package/dist/editor/comments/FieldWrapper.stories.js.map +0 -1
  99. package/dist/editor/fields/BlockField.stories.d.ts +0 -7
  100. package/dist/editor/fields/BlockField.stories.d.ts.map +0 -1
  101. package/dist/editor/fields/BlockField.stories.js +0 -50
  102. package/dist/editor/fields/BlockField.stories.js.map +0 -1
  103. package/dist/editor/fields/fields.stories.d.ts +0 -8
  104. package/dist/editor/fields/fields.stories.d.ts.map +0 -1
  105. package/dist/editor/fields/fields.stories.js +0 -34
  106. package/dist/editor/fields/fields.stories.js.map +0 -1
  107. package/dist/test-utils/api-test-helpers.d.ts +0 -238
  108. package/dist/test-utils/api-test-helpers.d.ts.map +0 -1
  109. package/dist/test-utils/api-test-helpers.js +0 -347
  110. package/dist/test-utils/api-test-helpers.js.map +0 -1
  111. package/dist/test-utils/console-spy.d.ts +0 -56
  112. package/dist/test-utils/console-spy.d.ts.map +0 -1
  113. package/dist/test-utils/console-spy.js +0 -81
  114. package/dist/test-utils/console-spy.js.map +0 -1
  115. package/dist/test-utils/git-helpers.d.ts +0 -21
  116. package/dist/test-utils/git-helpers.d.ts.map +0 -1
  117. package/dist/test-utils/git-helpers.js +0 -23
  118. package/dist/test-utils/git-helpers.js.map +0 -1
  119. package/dist/test-utils/index.d.ts +0 -5
  120. package/dist/test-utils/index.d.ts.map +0 -1
  121. package/dist/test-utils/index.js +0 -4
  122. package/dist/test-utils/index.js.map +0 -1
  123. package/src/__integration__/errors/invalid-content.test.ts +0 -238
  124. package/src/__integration__/errors/permission-denied.test.ts +0 -220
  125. package/src/__integration__/fixtures/content-seeds.ts +0 -105
  126. package/src/__integration__/fixtures/schemas.ts +0 -67
  127. package/src/__integration__/initialization/prod-sim-init.test.ts +0 -139
  128. package/src/__integration__/permissions/path-permissions.test.ts +0 -314
  129. package/src/__integration__/permissions/role-permissions.test.ts +0 -354
  130. package/src/__integration__/permissions/settings-branch-isolation.test.ts +0 -317
  131. package/src/__integration__/settings/groups-api.test.ts +0 -403
  132. package/src/__integration__/test-utils/api-client.ts +0 -167
  133. package/src/__integration__/test-utils/multi-user.ts +0 -129
  134. package/src/__integration__/test-utils/test-workspace.ts +0 -130
  135. package/src/__integration__/user/user-context.test.ts +0 -174
  136. package/src/__integration__/validation/input-validation.test.ts +0 -166
  137. package/src/__integration__/workflows/api-editing-workflow.test.ts +0 -244
  138. package/src/__integration__/workflows/conflict-resolution.test.ts +0 -259
  139. package/src/__integration__/workflows/editing-workflow.test.ts +0 -205
  140. package/src/__integration__/workflows/review-workflow.test.ts +0 -260
  141. package/src/ai/__tests__/build.integration.test.ts +0 -224
  142. package/src/ai/__tests__/generate.integration.test.ts +0 -495
  143. package/src/ai/__tests__/handler.integration.test.ts +0 -212
  144. package/src/ai/__tests__/json-to-markdown.test.ts +0 -553
  145. package/src/ai/generate.ts +0 -410
  146. package/src/ai/handler.ts +0 -123
  147. package/src/ai/index.ts +0 -26
  148. package/src/ai/json-to-markdown.ts +0 -424
  149. package/src/ai/resolve-branch.ts +0 -34
  150. package/src/ai/types.ts +0 -160
  151. package/src/api/AGENTS.md +0 -81
  152. package/src/api/__test__/mock-client.ts +0 -404
  153. package/src/api/assets.test.ts +0 -140
  154. package/src/api/assets.ts +0 -154
  155. package/src/api/branch-merge.test.ts +0 -163
  156. package/src/api/branch-merge.ts +0 -113
  157. package/src/api/branch-review.test.ts +0 -297
  158. package/src/api/branch-review.ts +0 -136
  159. package/src/api/branch-status.test.ts +0 -85
  160. package/src/api/branch-status.ts +0 -153
  161. package/src/api/branch-withdraw.test.ts +0 -146
  162. package/src/api/branch-withdraw.ts +0 -81
  163. package/src/api/branch-workflow.integration.test.ts +0 -578
  164. package/src/api/branch.test.ts +0 -620
  165. package/src/api/branch.ts +0 -492
  166. package/src/api/client.test.ts +0 -349
  167. package/src/api/client.ts +0 -506
  168. package/src/api/comments.test.ts +0 -285
  169. package/src/api/comments.ts +0 -210
  170. package/src/api/content.test.ts +0 -345
  171. package/src/api/content.ts +0 -454
  172. package/src/api/entries.test.ts +0 -1339
  173. package/src/api/entries.ts +0 -650
  174. package/src/api/github-sync.ts +0 -144
  175. package/src/api/groups.test.ts +0 -1013
  176. package/src/api/groups.ts +0 -375
  177. package/src/api/guards.test.ts +0 -533
  178. package/src/api/guards.ts +0 -271
  179. package/src/api/index.ts +0 -87
  180. package/src/api/permissions.test.ts +0 -766
  181. package/src/api/permissions.ts +0 -334
  182. package/src/api/reference-options.ts +0 -118
  183. package/src/api/resolve-references.ts +0 -107
  184. package/src/api/route-builder.ts +0 -289
  185. package/src/api/schema.test.ts +0 -840
  186. package/src/api/schema.ts +0 -936
  187. package/src/api/security.test.ts +0 -233
  188. package/src/api/settings-helpers.ts +0 -84
  189. package/src/api/types.ts +0 -40
  190. package/src/api/user.test.ts +0 -127
  191. package/src/api/user.ts +0 -42
  192. package/src/api/validators.test.ts +0 -275
  193. package/src/api/validators.ts +0 -176
  194. package/src/asset-store.test.ts +0 -37
  195. package/src/asset-store.ts +0 -110
  196. package/src/auth/cache.ts +0 -7
  197. package/src/auth/caching-auth-plugin.test.ts +0 -154
  198. package/src/auth/caching-auth-plugin.ts +0 -109
  199. package/src/auth/context-helpers.ts +0 -75
  200. package/src/auth/file-based-auth-cache.test.ts +0 -257
  201. package/src/auth/file-based-auth-cache.ts +0 -279
  202. package/src/auth/index.ts +0 -12
  203. package/src/auth/plugin.ts +0 -51
  204. package/src/auth/types.ts +0 -38
  205. package/src/authorization/__tests__/branch.test.ts +0 -260
  206. package/src/authorization/__tests__/content.test.ts +0 -142
  207. package/src/authorization/__tests__/path.test.ts +0 -133
  208. package/src/authorization/__tests__/permissions-loader.test.ts +0 -200
  209. package/src/authorization/branch.ts +0 -94
  210. package/src/authorization/content.ts +0 -93
  211. package/src/authorization/groups/index.ts +0 -11
  212. package/src/authorization/groups/loader.ts +0 -127
  213. package/src/authorization/groups/schema.ts +0 -48
  214. package/src/authorization/helpers.ts +0 -48
  215. package/src/authorization/index.ts +0 -84
  216. package/src/authorization/path.ts +0 -112
  217. package/src/authorization/permissions/index.ts +0 -11
  218. package/src/authorization/permissions/loader.ts +0 -116
  219. package/src/authorization/permissions/schema.ts +0 -66
  220. package/src/authorization/test-utils.ts +0 -15
  221. package/src/authorization/types.ts +0 -66
  222. package/src/authorization/validation.test.ts +0 -100
  223. package/src/authorization/validation.ts +0 -62
  224. package/src/branch-metadata.test.ts +0 -168
  225. package/src/branch-metadata.ts +0 -166
  226. package/src/branch-registry.test.ts +0 -248
  227. package/src/branch-registry.ts +0 -152
  228. package/src/branch-schema-cache.test.ts +0 -275
  229. package/src/branch-schema-cache.ts +0 -189
  230. package/src/branch-workspace.test.ts +0 -183
  231. package/src/branch-workspace.ts +0 -124
  232. package/src/build/generate-ai-content.ts +0 -78
  233. package/src/build/index.ts +0 -8
  234. package/src/build-mode.ts +0 -27
  235. package/src/cli/generate-ai-content.ts +0 -100
  236. package/src/cli/init.test.ts +0 -240
  237. package/src/cli/templates/canopy.ts.template +0 -55
  238. package/src/cli/templates.ts +0 -47
  239. package/src/client.ts +0 -12
  240. package/src/comment-store.test.ts +0 -442
  241. package/src/comment-store.ts +0 -301
  242. package/src/config/__tests__/config.test.ts +0 -513
  243. package/src/config/flatten.ts +0 -174
  244. package/src/config/helpers.ts +0 -167
  245. package/src/config/index.ts +0 -86
  246. package/src/config/schemas/collection.ts +0 -67
  247. package/src/config/schemas/config.ts +0 -77
  248. package/src/config/schemas/field.ts +0 -108
  249. package/src/config/schemas/media.ts +0 -27
  250. package/src/config/schemas/permissions.ts +0 -21
  251. package/src/config/types.ts +0 -321
  252. package/src/config/validation.ts +0 -70
  253. package/src/config-test.ts +0 -65
  254. package/src/config.ts +0 -11
  255. package/src/content-id-index.test.ts +0 -512
  256. package/src/content-id-index.ts +0 -479
  257. package/src/content-reader.test.ts +0 -478
  258. package/src/content-reader.ts +0 -214
  259. package/src/content-store.test.ts +0 -1126
  260. package/src/content-store.ts +0 -793
  261. package/src/context.ts +0 -111
  262. package/src/editor/BranchManager.stories.tsx +0 -80
  263. package/src/editor/BranchManager.test.tsx +0 -324
  264. package/src/editor/BranchManager.tsx +0 -461
  265. package/src/editor/CanopyEditor.stories.tsx +0 -128
  266. package/src/editor/CanopyEditor.test.tsx +0 -81
  267. package/src/editor/CanopyEditor.tsx +0 -73
  268. package/src/editor/CanopyEditorPage.test.tsx +0 -59
  269. package/src/editor/CanopyEditorPage.tsx +0 -25
  270. package/src/editor/CommentsPanel.stories.tsx +0 -184
  271. package/src/editor/CommentsPanel.tsx +0 -338
  272. package/src/editor/Editor.integration.test.tsx +0 -227
  273. package/src/editor/Editor.stories.tsx +0 -119
  274. package/src/editor/Editor.tsx +0 -1221
  275. package/src/editor/EditorPanes.stories.tsx +0 -256
  276. package/src/editor/EditorPanes.test.tsx +0 -77
  277. package/src/editor/EditorPanes.tsx +0 -180
  278. package/src/editor/EntryNavigator.stories.tsx +0 -65
  279. package/src/editor/EntryNavigator.test.tsx +0 -598
  280. package/src/editor/EntryNavigator.tsx +0 -665
  281. package/src/editor/FormRenderer.stories.tsx +0 -212
  282. package/src/editor/FormRenderer.test.tsx +0 -194
  283. package/src/editor/FormRenderer.tsx +0 -432
  284. package/src/editor/GroupManager.stories.tsx +0 -301
  285. package/src/editor/GroupManager.test.tsx +0 -682
  286. package/src/editor/GroupManager.tsx +0 -9
  287. package/src/editor/PermissionManager.stories.tsx +0 -539
  288. package/src/editor/PermissionManager.test.tsx +0 -864
  289. package/src/editor/PermissionManager.tsx +0 -12
  290. package/src/editor/canopy-path.test.ts +0 -23
  291. package/src/editor/canopy-path.ts +0 -52
  292. package/src/editor/client-reference-resolver.ts +0 -118
  293. package/src/editor/comments/BranchComments.tsx +0 -93
  294. package/src/editor/comments/EntryComments.tsx +0 -94
  295. package/src/editor/comments/FieldWrapper.stories.tsx +0 -210
  296. package/src/editor/comments/FieldWrapper.tsx +0 -129
  297. package/src/editor/comments/InlineCommentThread.test.tsx +0 -384
  298. package/src/editor/comments/InlineCommentThread.tsx +0 -246
  299. package/src/editor/comments/ThreadCarousel.test.tsx +0 -393
  300. package/src/editor/comments/ThreadCarousel.tsx +0 -525
  301. package/src/editor/components/ConfirmDeleteModal.tsx +0 -49
  302. package/src/editor/components/EditorContext.tsx +0 -49
  303. package/src/editor/components/EditorFooter.tsx +0 -47
  304. package/src/editor/components/EditorHeader.tsx +0 -492
  305. package/src/editor/components/EditorSidebar.tsx +0 -193
  306. package/src/editor/components/EntryCreateModal.tsx +0 -193
  307. package/src/editor/components/RenameEntryModal.tsx +0 -152
  308. package/src/editor/components/UserBadge.test.tsx +0 -274
  309. package/src/editor/components/UserBadge.tsx +0 -240
  310. package/src/editor/components/index.ts +0 -6
  311. package/src/editor/context/ApiClientContext.tsx +0 -56
  312. package/src/editor/context/EditorStateContext.tsx +0 -221
  313. package/src/editor/context/index.ts +0 -40
  314. package/src/editor/editor-config.test.ts +0 -385
  315. package/src/editor/editor-config.ts +0 -94
  316. package/src/editor/editor-utils.test.ts +0 -772
  317. package/src/editor/editor-utils.ts +0 -303
  318. package/src/editor/env.ts +0 -4
  319. package/src/editor/fields/BlockField.stories.tsx +0 -79
  320. package/src/editor/fields/BlockField.tsx +0 -267
  321. package/src/editor/fields/CodeField.tsx +0 -41
  322. package/src/editor/fields/MarkdownField.tsx +0 -205
  323. package/src/editor/fields/ObjectField.tsx +0 -71
  324. package/src/editor/fields/ReferenceField.tsx +0 -138
  325. package/src/editor/fields/SelectField.tsx +0 -76
  326. package/src/editor/fields/TextField.tsx +0 -35
  327. package/src/editor/fields/ToggleField.tsx +0 -37
  328. package/src/editor/fields/fields.stories.tsx +0 -40
  329. package/src/editor/group-manager/ExternalGroupsTab.tsx +0 -114
  330. package/src/editor/group-manager/GroupCard.tsx +0 -102
  331. package/src/editor/group-manager/GroupForm.tsx +0 -66
  332. package/src/editor/group-manager/InternalGroupsTab.tsx +0 -147
  333. package/src/editor/group-manager/MemberList.tsx +0 -184
  334. package/src/editor/group-manager/hooks/useExternalGroupSearch.ts +0 -63
  335. package/src/editor/group-manager/hooks/useGroupState.ts +0 -134
  336. package/src/editor/group-manager/hooks/useUserSearch.ts +0 -84
  337. package/src/editor/group-manager/index.tsx +0 -210
  338. package/src/editor/group-manager/types.ts +0 -28
  339. package/src/editor/hooks/README.md +0 -26
  340. package/src/editor/hooks/__test__/test-utils.tsx +0 -183
  341. package/src/editor/hooks/index.ts +0 -23
  342. package/src/editor/hooks/useBranchActions.test.tsx +0 -267
  343. package/src/editor/hooks/useBranchActions.tsx +0 -121
  344. package/src/editor/hooks/useBranchManager.test.tsx +0 -391
  345. package/src/editor/hooks/useBranchManager.tsx +0 -326
  346. package/src/editor/hooks/useCommentSystem.test.ts +0 -615
  347. package/src/editor/hooks/useCommentSystem.ts +0 -347
  348. package/src/editor/hooks/useDraftManager.test.ts +0 -375
  349. package/src/editor/hooks/useDraftManager.ts +0 -259
  350. package/src/editor/hooks/useEditorLayout.test.ts +0 -147
  351. package/src/editor/hooks/useEditorLayout.ts +0 -67
  352. package/src/editor/hooks/useEntryManager.test.ts +0 -588
  353. package/src/editor/hooks/useEntryManager.ts +0 -387
  354. package/src/editor/hooks/useGroupManager.test.ts +0 -277
  355. package/src/editor/hooks/useGroupManager.ts +0 -139
  356. package/src/editor/hooks/usePermissionManager.test.ts +0 -211
  357. package/src/editor/hooks/usePermissionManager.ts +0 -113
  358. package/src/editor/hooks/useReferenceResolution.ts +0 -248
  359. package/src/editor/hooks/useSchemaManager.test.ts +0 -370
  360. package/src/editor/hooks/useSchemaManager.ts +0 -310
  361. package/src/editor/hooks/useUserContext.tsx +0 -57
  362. package/src/editor/hooks/useUserMetadata.test.ts +0 -191
  363. package/src/editor/hooks/useUserMetadata.ts +0 -71
  364. package/src/editor/permission-manager/GroupSelector.tsx +0 -73
  365. package/src/editor/permission-manager/PermissionEditor.tsx +0 -321
  366. package/src/editor/permission-manager/PermissionLevelBadge.tsx +0 -53
  367. package/src/editor/permission-manager/PermissionTree.tsx +0 -237
  368. package/src/editor/permission-manager/UserSelector.tsx +0 -95
  369. package/src/editor/permission-manager/constants.tsx +0 -18
  370. package/src/editor/permission-manager/hooks/useGroupsAndUsers.ts +0 -153
  371. package/src/editor/permission-manager/hooks/usePermissionTree.ts +0 -200
  372. package/src/editor/permission-manager/index.tsx +0 -294
  373. package/src/editor/permission-manager/types.ts +0 -58
  374. package/src/editor/permission-manager/utils.ts +0 -179
  375. package/src/editor/preview-bridge.test.tsx +0 -50
  376. package/src/editor/preview-bridge.tsx +0 -294
  377. package/src/editor/schema-editor/CollectionEditor.test.tsx +0 -238
  378. package/src/editor/schema-editor/CollectionEditor.tsx +0 -520
  379. package/src/editor/schema-editor/EntryTypeEditor.test.tsx +0 -215
  380. package/src/editor/schema-editor/EntryTypeEditor.tsx +0 -367
  381. package/src/editor/schema-editor/index.ts +0 -19
  382. package/src/editor/setup-test-dom.ts +0 -10
  383. package/src/editor/test-setup.ts +0 -33
  384. package/src/editor/theme.tsx +0 -119
  385. package/src/editor/utils/env.ts +0 -39
  386. package/src/entry-schema-registry.test.ts +0 -281
  387. package/src/entry-schema-registry.ts +0 -121
  388. package/src/entry-schema.ts +0 -84
  389. package/src/git-manager.test.ts +0 -552
  390. package/src/git-manager.ts +0 -667
  391. package/src/github-service.test.ts +0 -312
  392. package/src/github-service.ts +0 -295
  393. package/src/http/handler.test.ts +0 -275
  394. package/src/http/handler.ts +0 -280
  395. package/src/http/index.ts +0 -11
  396. package/src/http/router.ts +0 -164
  397. package/src/http/types.ts +0 -44
  398. package/src/id.test.ts +0 -48
  399. package/src/id.ts +0 -22
  400. package/src/index.ts +0 -26
  401. package/src/operating-mode/__tests__/strategies.test.ts +0 -511
  402. package/src/operating-mode/client-safe-strategy.ts +0 -184
  403. package/src/operating-mode/client-unsafe-strategy.ts +0 -303
  404. package/src/operating-mode/client.ts +0 -13
  405. package/src/operating-mode/index.ts +0 -34
  406. package/src/operating-mode/types.ts +0 -186
  407. package/src/paths/__tests__/branch.test.ts +0 -53
  408. package/src/paths/__tests__/normalize.test.ts +0 -141
  409. package/src/paths/__tests__/resolve.test.ts +0 -207
  410. package/src/paths/__tests__/validation.test.ts +0 -61
  411. package/src/paths/branch.ts +0 -115
  412. package/src/paths/index.ts +0 -73
  413. package/src/paths/normalize-server.ts +0 -40
  414. package/src/paths/normalize.ts +0 -107
  415. package/src/paths/resolve.ts +0 -61
  416. package/src/paths/test-utils.ts +0 -37
  417. package/src/paths/types.ts +0 -68
  418. package/src/paths/validation.test.ts +0 -480
  419. package/src/paths/validation.ts +0 -391
  420. package/src/reference-resolver.test.ts +0 -107
  421. package/src/reference-resolver.ts +0 -157
  422. package/src/schema/index.ts +0 -29
  423. package/src/schema/meta-loader.ts +0 -366
  424. package/src/schema/resolver.ts +0 -83
  425. package/src/schema/schema-store-types.ts +0 -56
  426. package/src/schema/schema-store.test.ts +0 -816
  427. package/src/schema/schema-store.ts +0 -795
  428. package/src/schema/types.ts +0 -33
  429. package/src/schema-meta-loader.test.ts +0 -447
  430. package/src/server.ts +0 -15
  431. package/src/services.test.ts +0 -559
  432. package/src/services.ts +0 -373
  433. package/src/settings-branch-utils.ts +0 -53
  434. package/src/settings-workspace.ts +0 -156
  435. package/src/task-queue/README.md +0 -144
  436. package/src/task-queue/index.ts +0 -14
  437. package/src/task-queue/task-queue.test.ts +0 -524
  438. package/src/task-queue/task-queue.ts +0 -514
  439. package/src/task-queue/types.ts +0 -41
  440. package/src/test-utils/api-test-helpers.ts +0 -445
  441. package/src/test-utils/console-spy.test.ts +0 -14
  442. package/src/test-utils/console-spy.ts +0 -125
  443. package/src/test-utils/git-helpers.ts +0 -31
  444. package/src/test-utils/index.ts +0 -4
  445. package/src/types.ts +0 -54
  446. package/src/user.ts +0 -118
  447. package/src/utils/debug.test.ts +0 -114
  448. package/src/utils/debug.ts +0 -127
  449. package/src/utils/error.test.ts +0 -92
  450. package/src/utils/error.ts +0 -83
  451. package/src/utils/format.ts +0 -12
  452. package/src/validation/__tests__/field-traversal.test.ts +0 -263
  453. package/src/validation/deletion-checker.ts +0 -234
  454. package/src/validation/field-traversal.ts +0 -146
  455. package/src/validation/reference-validator.ts +0 -168
  456. package/src/worker/cms-worker-rebase.test.ts +0 -473
  457. package/src/worker/cms-worker.ts +0 -777
  458. package/src/worker/integration.test.ts +0 -289
  459. package/src/worker/task-queue-config.ts +0 -25
  460. package/src/worker/task-queue.test.ts +0 -452
  461. package/src/worker/task-queue.ts +0 -58
  462. /package/{src/cli/templates → dist/cli/template-files}/Dockerfile.cms.template +0 -0
  463. /package/{src/cli/templates → dist/cli/template-files}/canopycms.config.ts.template +0 -0
  464. /package/{src/cli/templates → dist/cli/template-files}/deploy-cms.yml.template +0 -0
  465. /package/{src/cli/templates → dist/cli/template-files}/edit-page.tsx.template +0 -0
  466. /package/{src/cli/templates → dist/cli/template-files}/route.ts.template +0 -0
  467. /package/{src/cli/templates → dist/cli/template-files}/schemas.ts.template +0 -0
@@ -1,479 +0,0 @@
1
- import fs from 'node:fs/promises'
2
- import path from 'node:path'
3
-
4
- import { isValidId } from './id'
5
- import { isNotFoundError } from './utils/error'
6
- import { type LogicalPath, type PhysicalPath, type EntrySlug, type ContentId } from './paths'
7
-
8
- /** Logical path representing entries stored at the branch root (no parent collection). Rare in practice. */
9
- const EMPTY_LOGICAL_PATH = '' as LogicalPath
10
-
11
- /**
12
- * Strips embedded IDs from each physical path segment to produce a logical path.
13
- * e.g. "content/posts.a1b2c3d4e5f6" → "content/posts"
14
- * This is a module-private helper for internal path conversion only.
15
- */
16
- function toLogicalCollectionPath(physicalPath: string): LogicalPath {
17
- if (physicalPath === '.') return EMPTY_LOGICAL_PATH
18
- // extractSlugFromFilename strips the ID (and extension) from each segment
19
- return physicalPath
20
- .split('/')
21
- .map((seg) => extractSlugFromFilename(seg))
22
- .join('/') as LogicalPath
23
- }
24
-
25
- export interface IdLocation {
26
- id: ContentId
27
- type: 'entry' | 'collection'
28
- relativePath: PhysicalPath // e.g. 'content/posts/dune.a1b2c3d4e5f6.json'
29
- collection?: LogicalPath // e.g. 'content/posts' (for entries only) — always logical, never physical
30
- slug?: EntrySlug // e.g. 'dune' (for entries only)
31
- }
32
-
33
- /**
34
- * ContentIdIndex manages the bidirectional mapping between content IDs and file paths.
35
- *
36
- * IDs are embedded in filenames using the patterns:
37
- * - Entries: `{type}.{slug}.{12-char-id}.{ext}` (e.g., `post.dune.a1b2c3d4e5f6.json`)
38
- * - Collection directories: `{slug}.{12-char-id}/` (e.g., `posts.a1b2c3d4e5f6/`)
39
- *
40
- * This class builds an in-memory index by scanning filenames recursively, providing O(1) lookups
41
- * in both directions (ID→path and path→ID).
42
- *
43
- * The index is built lazily on first access to optimize Lambda cold starts.
44
- *
45
- * ## Multi-Process Consistency
46
- *
47
- * This class is NOT thread-safe. In multi-process environments (e.g., multiple Lambda
48
- * instances or server processes), each process maintains its own in-memory index.
49
- *
50
- * **Consistency guarantees:**
51
- * - Filenames on the filesystem are the source of truth
52
- * - Each process discovers the same filenames when building its index
53
- * - Write operations that change filenames are atomic (rename is atomic)
54
- * - Read operations always reflect current filesystem state after index rebuild
55
- *
56
- * **Race condition handling:**
57
- * - Multiple processes creating entries simultaneously: Each generates a unique ID,
58
- * collisions detected during index build (fail fast)
59
- * - One process writes, another reads: Reader's stale index might miss new IDs until
60
- * next rebuild. This is acceptable - eventual consistency.
61
- * - Index drift: Rare, but processes can rebuild index if they detect missing IDs
62
- *
63
- * For most use cases (CMS with human editors), race conditions are unlikely and
64
- * eventual consistency is sufficient.
65
- */
66
- export class ContentIdIndex {
67
- private idToLocation: Map<string, IdLocation> = new Map()
68
- private pathToId: Map<string, string> = new Map()
69
- private byCollection: Map<string, Set<string>> = new Map()
70
- private root: string
71
-
72
- constructor(root: string) {
73
- this.root = path.resolve(root)
74
- }
75
-
76
- /**
77
- * Build index by scanning filenames recursively.
78
- * Throws if duplicate IDs found (collision detection).
79
- */
80
- async buildFromFilenames(startPath: string = ''): Promise<void> {
81
- await this.scanDirectory(startPath)
82
- }
83
-
84
- private async scanDirectory(relativePath: string): Promise<void> {
85
- const absoluteDir = path.join(this.root, relativePath)
86
-
87
- try {
88
- const entries = await fs.readdir(absoluteDir, { withFileTypes: true })
89
-
90
- for (const entry of entries) {
91
- // Skip hidden files and directories (including _ids_)
92
- if (entry.name.startsWith('.') || entry.name === '_ids_') {
93
- continue
94
- }
95
-
96
- const fullRelativePath = path.join(relativePath, entry.name)
97
- const id = extractIdFromFilename(entry.name)
98
-
99
- if (id) {
100
- // Collision detection
101
- if (this.idToLocation.has(id)) {
102
- const existing = this.idToLocation.get(id)!
103
- throw new Error(
104
- `ID collision detected: ${id}\n` +
105
- ` File 1: ${existing.relativePath}\n` +
106
- ` File 2: ${fullRelativePath}`,
107
- )
108
- }
109
-
110
- const location: IdLocation = {
111
- id, // already ContentId from extractIdFromFilename
112
- type: entry.isDirectory() ? 'collection' : 'entry',
113
- relativePath: fullRelativePath as PhysicalPath, // filesystem path with embedded IDs
114
- }
115
-
116
- // Extract slug and collection for entries
117
- if (!entry.isDirectory()) {
118
- const slug = extractSlugFromFilename(entry.name)
119
- // Convert physical collection path to logical by stripping embedded IDs from each segment
120
- // e.g., "content/posts.a1b2c3d4e5f6" → "content/posts"
121
- const physicalCollection = path.dirname(fullRelativePath)
122
- const collectionPath = toLogicalCollectionPath(physicalCollection)
123
- location.slug = slug as EntrySlug // slug extracted from validated filename
124
- location.collection = collectionPath
125
-
126
- // Add to collection index
127
- if (!this.byCollection.has(collectionPath)) {
128
- this.byCollection.set(collectionPath, new Set())
129
- }
130
- this.byCollection.get(collectionPath)!.add(id)
131
- }
132
-
133
- this.idToLocation.set(id, location)
134
- this.pathToId.set(fullRelativePath, id)
135
- }
136
-
137
- // Recurse into directories
138
- if (entry.isDirectory()) {
139
- await this.scanDirectory(fullRelativePath)
140
- }
141
- }
142
- } catch (err) {
143
- // Directory might not exist yet
144
- if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
145
- throw err
146
- }
147
- }
148
- }
149
-
150
- /**
151
- * Forward lookup: ID → location (O(1))
152
- */
153
- findById(id: string): IdLocation | null {
154
- return this.idToLocation.get(id) || null
155
- }
156
-
157
- /**
158
- * Reverse lookup: path → ID (O(1))
159
- */
160
- findByPath(relativePath: PhysicalPath): ContentId | null {
161
- return (this.pathToId.get(relativePath) as ContentId | undefined) || null
162
- }
163
-
164
- /**
165
- * Get all ID locations in the index.
166
- * Useful for validation and checking references.
167
- */
168
- getAllLocations(): IdLocation[] {
169
- return Array.from(this.idToLocation.values())
170
- }
171
-
172
- /**
173
- * Get all entries in a collection by collection path.
174
- *
175
- * Performance: O(1) + O(m) where m is the number of entries in the collection.
176
- *
177
- * @param collectionPath - The collection path (e.g., "content/posts")
178
- * @returns Array of IdLocation objects for entries in the collection
179
- */
180
- getEntriesInCollection(collectionPath: LogicalPath): IdLocation[] {
181
- const idSet = this.byCollection.get(collectionPath)
182
- if (!idSet) {
183
- return []
184
- }
185
-
186
- const locations: IdLocation[] = []
187
- for (const id of idSet) {
188
- const location = this.idToLocation.get(id)
189
- if (location) {
190
- locations.push(location)
191
- }
192
- }
193
-
194
- return locations
195
- }
196
-
197
- /**
198
- * Add a new entry or collection to the index.
199
- * Note: This only updates the in-memory index. The file with embedded ID
200
- * must already exist on disk (created by ContentStore).
201
- */
202
- add(location: Omit<IdLocation, 'id'>): void {
203
- const id = extractIdFromFilename(path.basename(location.relativePath))
204
- if (!id) {
205
- throw new Error(`Cannot add location without ID in filename: ${location.relativePath}`)
206
- }
207
-
208
- // Collision detection
209
- if (this.idToLocation.has(id)) {
210
- const existing = this.idToLocation.get(id)!
211
- throw new Error(
212
- `ID collision detected: ${id}\n` +
213
- ` File 1: ${existing.relativePath}\n` +
214
- ` File 2: ${location.relativePath}`,
215
- )
216
- }
217
-
218
- const fullLocation: IdLocation = {
219
- ...location,
220
- id, // already ContentId from extractIdFromFilename
221
- }
222
- this.idToLocation.set(id, fullLocation)
223
- this.pathToId.set(location.relativePath, id)
224
-
225
- // Add to collection index if it's an entry
226
- if (fullLocation.type === 'entry' && fullLocation.collection) {
227
- if (!this.byCollection.has(fullLocation.collection)) {
228
- this.byCollection.set(fullLocation.collection, new Set())
229
- }
230
- this.byCollection.get(fullLocation.collection)!.add(id)
231
- }
232
- }
233
-
234
- /**
235
- * Remove an entry or collection from the index by ID.
236
- * Note: This only updates the in-memory index. The file must be deleted separately.
237
- */
238
- remove(id: ContentId): void {
239
- const location = this.idToLocation.get(id)
240
- if (!location) return
241
-
242
- // Remove from collection index if it's an entry
243
- if (location.type === 'entry' && location.collection) {
244
- const idSet = this.byCollection.get(location.collection)
245
- if (idSet) {
246
- idSet.delete(id)
247
- // Clean up empty Sets to prevent memory leaks
248
- if (idSet.size === 0) {
249
- this.byCollection.delete(location.collection)
250
- }
251
- }
252
- }
253
-
254
- this.idToLocation.delete(id)
255
- this.pathToId.delete(location.relativePath)
256
- }
257
-
258
- /**
259
- * Update the path for an existing ID (e.g., after file rename/move).
260
- * This is used to keep the index in sync when files are renamed.
261
- */
262
- updatePath(id: ContentId, newRelativePath: PhysicalPath): void {
263
- const location = this.idToLocation.get(id)
264
- if (!location) {
265
- throw new Error(`Cannot update path for unknown ID: ${id}`)
266
- }
267
-
268
- // Remove old path mapping
269
- this.pathToId.delete(location.relativePath)
270
-
271
- // Update location
272
- location.relativePath = newRelativePath
273
-
274
- // Update slug and collection for entries
275
- if (location.type === 'entry') {
276
- const oldCollection = location.collection
277
- location.slug = extractSlugFromFilename(path.basename(newRelativePath)) as EntrySlug // from validated filename
278
- const physicalCollection = path.dirname(newRelativePath)
279
- location.collection = toLogicalCollectionPath(physicalCollection)
280
-
281
- // Update collection index if collection changed
282
- if (oldCollection !== location.collection) {
283
- // Remove from old collection
284
- if (oldCollection) {
285
- const oldSet = this.byCollection.get(oldCollection)
286
- if (oldSet) {
287
- oldSet.delete(id)
288
- if (oldSet.size === 0) {
289
- this.byCollection.delete(oldCollection)
290
- }
291
- }
292
- }
293
-
294
- // Add to new collection
295
- if (location.collection) {
296
- if (!this.byCollection.has(location.collection)) {
297
- this.byCollection.set(location.collection, new Set())
298
- }
299
- this.byCollection.get(location.collection)!.add(id)
300
- }
301
- }
302
- }
303
-
304
- // Add new path mapping
305
- this.pathToId.set(newRelativePath, id)
306
- }
307
- }
308
-
309
- /**
310
- * Extract ID from filename.
311
- * Returns null if filename doesn't contain an ID or is a metadata file.
312
- *
313
- * Pattern:
314
- * - Collection entry files: type.slug.id.ext → ID is parts[parts.length - 2] (e.g., "post.dune.a1b2c3d4e5f6.json")
315
- * - Collection directories: slug.id → ID is parts[1] (e.g., "posts.a1b2c3d4e5f6")
316
- * - Metadata files: .collection.json, .gitignore, etc. → null
317
- *
318
- * Edge cases:
319
- * - Slugs with dots: "post.my.page.a1b2c3d4e5f6.json" → extracts "a1b2c3d4e5f6"
320
- * - Hidden files with IDs: ".hidden.a1b2c3d4e5f6.json" → returns null (metadata)
321
- * - No ID present: "file.json" → returns null
322
- */
323
- export function extractIdFromFilename(filename: string): ContentId | null {
324
- // Skip metadata files (no IDs) - anything starting with dot is metadata
325
- // This includes .collection.json, .gitignore, and even .hidden.id.json
326
- if (filename.startsWith('.')) {
327
- return null
328
- }
329
-
330
- const parts = filename.split('.')
331
-
332
- // Files: type.slug.id.ext → need at least 3 parts
333
- // The ID is always the second-to-last part before the extension
334
- if (parts.length >= 3) {
335
- const candidate = parts[parts.length - 2]
336
- if (isValidId(candidate)) return candidate as ContentId
337
- }
338
-
339
- // Directories: slug.id → exactly 2 parts (slug and ID, no extension)
340
- if (parts.length === 2) {
341
- const candidate = parts[parts.length - 1]
342
- if (isValidId(candidate)) return candidate as ContentId
343
- }
344
-
345
- return null
346
- }
347
-
348
- /**
349
- * Resolve a logical collection path to its actual filesystem path with embedded IDs.
350
- * Recursively resolves each path segment to handle nested collections.
351
- *
352
- * Example:
353
- * Input: resolveCollectionPath(root, "content/docs/api")
354
- * Output: "/abs/path/to/content/docs.bChqT78gcaLd/api.meiuwxTSo7UN"
355
- *
356
- * @param root - Absolute path to the workspace root
357
- * @param logicalPath - Logical path from schema (e.g., "content/docs/api")
358
- * @returns Absolute filesystem path with embedded IDs, or null if path doesn't exist
359
- */
360
- export async function resolveCollectionPath(
361
- root: string,
362
- logicalPath: LogicalPath,
363
- ): Promise<string | null> {
364
- // Dynamic import: keep Node built-ins out of browser/edge bundles
365
- const fs = await import('node:fs/promises')
366
- const path = await import('node:path')
367
-
368
- const segments = logicalPath.split('/').filter(Boolean)
369
- let currentPath = root
370
-
371
- for (const segment of segments) {
372
- try {
373
- const entries = await fs.readdir(currentPath, { withFileTypes: true })
374
- const matchingDir = entries.find((entry) => {
375
- if (!entry.isDirectory()) return false
376
- // Extract logical name from directory (strips embedded ID)
377
- const logicalName = extractSlugFromFilename(entry.name)
378
- return logicalName === segment
379
- })
380
-
381
- if (matchingDir) {
382
- currentPath = path.join(currentPath, matchingDir.name)
383
- } else {
384
- // Directory not found - might not exist yet
385
- return null
386
- }
387
- } catch (err: unknown) {
388
- if (isNotFoundError(err)) return null
389
- throw err
390
- }
391
- }
392
-
393
- return currentPath
394
- }
395
-
396
- /**
397
- * Extract entry type name from filename.
398
- * For collection entry files with pattern type.slug.id.ext, returns the type (first part).
399
- *
400
- * Examples:
401
- * - "post.my-slug.a1b2c3d4e5f6.json" → "post"
402
- * - "article.test.a1b2c3d4e5f6.md" → "article"
403
- * - "posts.a1b2c3d4e5f6" → null (directory, not an entry file)
404
- *
405
- * @param filename - The filename to parse
406
- * @returns Entry type name or null if not a valid entry file
407
- */
408
- export function extractEntryTypeFromFilename(filename: string): string | null {
409
- if (filename.startsWith('.')) return null
410
-
411
- const parts = filename.split('.')
412
-
413
- // Need at least 4 parts for type.slug.id.ext
414
- if (parts.length >= 4) {
415
- const possibleId = parts[parts.length - 2]
416
- if (isValidId(possibleId)) {
417
- return parts[0] // Entry type is first part
418
- }
419
- }
420
-
421
- return null
422
- }
423
-
424
- /**
425
- * Extract slug from filename.
426
- *
427
- * Collection entries: type.slug.id.ext → slug is parts[1...-2] (between type and ID)
428
- * Directories: slug.id → slug is parts[0] (before ID)
429
- *
430
- * For collection entry files (4+ parts), automatically strips the first part (type) to extract just the slug.
431
- *
432
- * Examples:
433
- * - "post.my-slug.a1b2c3d4e5f6.json" → "my-slug" (4 parts)
434
- * - "post.my.page.a1b2c3d4e5f6.json" → "my.page" (dotted slug, 5 parts)
435
- * - "posts.a1b2c3d4e5f6" → "posts" (directory, 2 parts)
436
- *
437
- * @param filename - The filename to parse
438
- * @param entryTypeName - Optional entry type name for explicit type matching (e.g., "post")
439
- * If provided and matches first part, strips it from slug
440
- */
441
- export function extractSlugFromFilename(filename: string, entryTypeName?: string): string {
442
- const parts = filename.split('.')
443
-
444
- // Files: type.slug.id.ext (at least 3 parts)
445
- if (parts.length >= 3) {
446
- const possibleId = parts[parts.length - 2]
447
- if (isValidId(possibleId)) {
448
- // Get all parts before ID (excluding extension)
449
- let slugParts = parts.slice(0, parts.length - 2)
450
-
451
- // If entryTypeName is provided and matches the first part, strip it
452
- if (entryTypeName && slugParts.length > 1 && slugParts[0] === entryTypeName) {
453
- slugParts = slugParts.slice(1)
454
- }
455
- // Auto-detect: 4+ parts means type.slug.id.ext format
456
- else if (parts.length >= 4 && slugParts.length > 1) {
457
- // Strip first part (the type) to get just the slug
458
- slugParts = slugParts.slice(1)
459
- }
460
-
461
- return slugParts.join('.')
462
- }
463
- }
464
-
465
- // Directories: slug.id (exactly 2 parts)
466
- if (parts.length === 2) {
467
- const possibleId = parts[parts.length - 1]
468
- if (isValidId(possibleId)) {
469
- return parts[0]
470
- }
471
- }
472
-
473
- // No ID found, remove extension and return filename without extension
474
- if (parts.length > 1) {
475
- return parts.slice(0, -1).join('.')
476
- }
477
-
478
- return filename
479
- }