canopycms 0.0.61-int.75 → 0.0.62

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 (369) hide show
  1. package/dist/ai/handler.js +1 -1
  2. package/dist/ai/handler.js.map +1 -1
  3. package/dist/ai/json-to-markdown.js +1 -2
  4. package/dist/ai/json-to-markdown.js.map +1 -1
  5. package/dist/api/__test__/mock-client.d.ts +5 -1
  6. package/dist/api/__test__/mock-client.d.ts.map +1 -1
  7. package/dist/api/__test__/mock-client.js +9 -2
  8. package/dist/api/__test__/mock-client.js.map +1 -1
  9. package/dist/api/admin-branch-health.d.ts +36 -1
  10. package/dist/api/admin-branch-health.d.ts.map +1 -1
  11. package/dist/api/admin-branch-health.js +176 -2
  12. package/dist/api/admin-branch-health.js.map +1 -1
  13. package/dist/api/admin.d.ts +8 -1
  14. package/dist/api/admin.d.ts.map +1 -1
  15. package/dist/api/admin.js.map +1 -1
  16. package/dist/api/assets.d.ts.map +1 -1
  17. package/dist/api/assets.js +36 -4
  18. package/dist/api/assets.js.map +1 -1
  19. package/dist/api/branch-status.d.ts.map +1 -1
  20. package/dist/api/branch-status.js +56 -0
  21. package/dist/api/branch-status.js.map +1 -1
  22. package/dist/api/branch-withdraw.d.ts.map +1 -1
  23. package/dist/api/branch-withdraw.js +14 -3
  24. package/dist/api/branch-withdraw.js.map +1 -1
  25. package/dist/api/branch.d.ts +31 -2
  26. package/dist/api/branch.d.ts.map +1 -1
  27. package/dist/api/branch.js +268 -15
  28. package/dist/api/branch.js.map +1 -1
  29. package/dist/api/client.d.ts +5 -1
  30. package/dist/api/client.d.ts.map +1 -1
  31. package/dist/api/client.js +6 -0
  32. package/dist/api/client.js.map +1 -1
  33. package/dist/api/comments.d.ts +2 -2
  34. package/dist/api/content.d.ts +11 -5
  35. package/dist/api/content.d.ts.map +1 -1
  36. package/dist/api/content.js +91 -10
  37. package/dist/api/content.js.map +1 -1
  38. package/dist/api/entries.d.ts +10 -0
  39. package/dist/api/entries.d.ts.map +1 -1
  40. package/dist/api/entries.js +51 -24
  41. package/dist/api/entries.js.map +1 -1
  42. package/dist/api/guards.d.ts.map +1 -1
  43. package/dist/api/guards.js +12 -5
  44. package/dist/api/guards.js.map +1 -1
  45. package/dist/api/permissions.d.ts +2 -2
  46. package/dist/api/permissions.d.ts.map +1 -1
  47. package/dist/api/permissions.js +51 -3
  48. package/dist/api/permissions.js.map +1 -1
  49. package/dist/api/reference-options.d.ts.map +1 -1
  50. package/dist/api/reference-options.js +10 -17
  51. package/dist/api/reference-options.js.map +1 -1
  52. package/dist/api/resolve-references.d.ts.map +1 -1
  53. package/dist/api/resolve-references.js +3 -1
  54. package/dist/api/resolve-references.js.map +1 -1
  55. package/dist/api/schema.d.ts +4 -4
  56. package/dist/api/schema.d.ts.map +1 -1
  57. package/dist/api/schema.js +16 -15
  58. package/dist/api/schema.js.map +1 -1
  59. package/dist/api/settings-helpers.d.ts.map +1 -1
  60. package/dist/api/settings-helpers.js +6 -5
  61. package/dist/api/settings-helpers.js.map +1 -1
  62. package/dist/assets/pipeline.d.ts +11 -2
  63. package/dist/assets/pipeline.d.ts.map +1 -1
  64. package/dist/assets/pipeline.js +114 -2
  65. package/dist/assets/pipeline.js.map +1 -1
  66. package/dist/assets/transform-directives.d.ts +18 -0
  67. package/dist/assets/transform-directives.d.ts.map +1 -1
  68. package/dist/assets/transform-directives.js +18 -0
  69. package/dist/assets/transform-directives.js.map +1 -1
  70. package/dist/assets/transform.d.ts.map +1 -1
  71. package/dist/assets/transform.js +20 -16
  72. package/dist/assets/transform.js.map +1 -1
  73. package/dist/auth/types.d.ts +29 -0
  74. package/dist/auth/types.d.ts.map +1 -1
  75. package/dist/authorization/index.d.ts +1 -1
  76. package/dist/authorization/index.d.ts.map +1 -1
  77. package/dist/authorization/index.js +1 -1
  78. package/dist/authorization/index.js.map +1 -1
  79. package/dist/authorization/protected-branch.d.ts +75 -0
  80. package/dist/authorization/protected-branch.d.ts.map +1 -1
  81. package/dist/authorization/protected-branch.js +39 -0
  82. package/dist/authorization/protected-branch.js.map +1 -1
  83. package/dist/branch-health.d.ts +13 -0
  84. package/dist/branch-health.d.ts.map +1 -1
  85. package/dist/branch-health.js +23 -0
  86. package/dist/branch-health.js.map +1 -1
  87. package/dist/branch-registry.d.ts.map +1 -1
  88. package/dist/branch-registry.js +5 -1
  89. package/dist/branch-registry.js.map +1 -1
  90. package/dist/branch-schema-cache.d.ts.map +1 -1
  91. package/dist/branch-schema-cache.js +9 -0
  92. package/dist/branch-schema-cache.js.map +1 -1
  93. package/dist/build/generate-ai-content.js +1 -1
  94. package/dist/build/generate-ai-content.js.map +1 -1
  95. package/dist/cli/cli.js +2215 -1280
  96. package/dist/cli/generate-ai-content.js +1158 -585
  97. package/dist/cli/init.d.ts +8 -2
  98. package/dist/cli/init.d.ts.map +1 -1
  99. package/dist/cli/init.js +459 -152
  100. package/dist/cli/init.js.map +1 -1
  101. package/dist/cli/project-detect.d.ts +89 -0
  102. package/dist/cli/project-detect.d.ts.map +1 -0
  103. package/dist/cli/project-detect.js +240 -0
  104. package/dist/cli/project-detect.js.map +1 -0
  105. package/dist/cli/template-files/Dockerfile.cms.template +30 -7
  106. package/dist/cli/template-files/canopycms.config.ts.template +7 -0
  107. package/dist/cli/template-files/cdk-app.ts.template +82 -0
  108. package/dist/cli/template-files/cdk.json.template +9 -0
  109. package/dist/cli/template-files/cms-stack.ts.template +130 -0
  110. package/dist/cli/template-files/deploy-cms.yml.template +125 -13
  111. package/dist/cli/template-files/dockerignore.template +2 -1
  112. package/dist/cli/templates.d.ts +26 -2
  113. package/dist/cli/templates.d.ts.map +1 -1
  114. package/dist/cli/templates.js +36 -4
  115. package/dist/cli/templates.js.map +1 -1
  116. package/dist/client.d.ts +1 -0
  117. package/dist/client.d.ts.map +1 -1
  118. package/dist/client.js.map +1 -1
  119. package/dist/config/schemas/config.d.ts +2 -3
  120. package/dist/config/schemas/config.d.ts.map +1 -1
  121. package/dist/config/schemas/config.js +21 -1
  122. package/dist/config/schemas/config.js.map +1 -1
  123. package/dist/config/schemas/field.d.ts +15 -15
  124. package/dist/config/types.d.ts +2 -2
  125. package/dist/config/types.d.ts.map +1 -1
  126. package/dist/config/types.js +0 -1
  127. package/dist/config/types.js.map +1 -1
  128. package/dist/config/validation.d.ts +18 -0
  129. package/dist/config/validation.d.ts.map +1 -1
  130. package/dist/config/validation.js +36 -12
  131. package/dist/config/validation.js.map +1 -1
  132. package/dist/content-id-index.d.ts +97 -5
  133. package/dist/content-id-index.d.ts.map +1 -1
  134. package/dist/content-id-index.js +170 -18
  135. package/dist/content-id-index.js.map +1 -1
  136. package/dist/content-reader.js +1 -1
  137. package/dist/content-reader.js.map +1 -1
  138. package/dist/content-store.d.ts +92 -7
  139. package/dist/content-store.d.ts.map +1 -1
  140. package/dist/content-store.js +445 -259
  141. package/dist/content-store.js.map +1 -1
  142. package/dist/dev-content-watcher.d.ts.map +1 -1
  143. package/dist/dev-content-watcher.js +4 -1
  144. package/dist/dev-content-watcher.js.map +1 -1
  145. package/dist/editor/BranchManager.d.ts +15 -0
  146. package/dist/editor/BranchManager.d.ts.map +1 -1
  147. package/dist/editor/BranchManager.js +61 -15
  148. package/dist/editor/BranchManager.js.map +1 -1
  149. package/dist/editor/CanopyEditor.d.ts.map +1 -1
  150. package/dist/editor/CanopyEditor.js +3 -3
  151. package/dist/editor/CanopyEditor.js.map +1 -1
  152. package/dist/editor/CanopyEditorPage.d.ts +9 -1
  153. package/dist/editor/CanopyEditorPage.d.ts.map +1 -1
  154. package/dist/editor/CanopyEditorPage.js +9 -2
  155. package/dist/editor/CanopyEditorPage.js.map +1 -1
  156. package/dist/editor/Editor.d.ts +9 -1
  157. package/dist/editor/Editor.d.ts.map +1 -1
  158. package/dist/editor/Editor.js +156 -60
  159. package/dist/editor/Editor.js.map +1 -1
  160. package/dist/editor/FormRenderer.d.ts.map +1 -1
  161. package/dist/editor/FormRenderer.js +12 -0
  162. package/dist/editor/FormRenderer.js.map +1 -1
  163. package/dist/editor/admin/SystemHealthPanel.d.ts.map +1 -1
  164. package/dist/editor/admin/SystemHealthPanel.js +14 -9
  165. package/dist/editor/admin/SystemHealthPanel.js.map +1 -1
  166. package/dist/editor/components/EditorHeader.d.ts +6 -0
  167. package/dist/editor/components/EditorHeader.d.ts.map +1 -1
  168. package/dist/editor/components/EditorHeader.js +76 -23
  169. package/dist/editor/components/EditorHeader.js.map +1 -1
  170. package/dist/editor/components/EntryCreateModal.d.ts +9 -1
  171. package/dist/editor/components/EntryCreateModal.d.ts.map +1 -1
  172. package/dist/editor/components/EntryCreateModal.js +25 -7
  173. package/dist/editor/components/EntryCreateModal.js.map +1 -1
  174. package/dist/editor/context/SWRProvider.d.ts +31 -0
  175. package/dist/editor/context/SWRProvider.d.ts.map +1 -0
  176. package/dist/editor/context/SWRProvider.js +12 -0
  177. package/dist/editor/context/SWRProvider.js.map +1 -0
  178. package/dist/editor/context/index.d.ts +3 -0
  179. package/dist/editor/context/index.d.ts.map +1 -1
  180. package/dist/editor/context/index.js +3 -0
  181. package/dist/editor/context/index.js.map +1 -1
  182. package/dist/editor/editor-utils.d.ts.map +1 -1
  183. package/dist/editor/editor-utils.js +8 -2
  184. package/dist/editor/editor-utils.js.map +1 -1
  185. package/dist/editor/fields/DateTimeField.d.ts +46 -0
  186. package/dist/editor/fields/DateTimeField.d.ts.map +1 -0
  187. package/dist/editor/fields/DateTimeField.js +66 -0
  188. package/dist/editor/fields/DateTimeField.js.map +1 -0
  189. package/dist/editor/fields/ImageField.d.ts.map +1 -1
  190. package/dist/editor/fields/ImageField.js +27 -3
  191. package/dist/editor/fields/ImageField.js.map +1 -1
  192. package/dist/editor/fields/NumberField.d.ts +34 -0
  193. package/dist/editor/fields/NumberField.d.ts.map +1 -0
  194. package/dist/editor/fields/NumberField.js +53 -0
  195. package/dist/editor/fields/NumberField.js.map +1 -0
  196. package/dist/editor/fields/NumberListField.d.ts +25 -0
  197. package/dist/editor/fields/NumberListField.d.ts.map +1 -0
  198. package/dist/editor/fields/NumberListField.js +53 -0
  199. package/dist/editor/fields/NumberListField.js.map +1 -0
  200. package/dist/editor/fields/ReferenceField.d.ts.map +1 -1
  201. package/dist/editor/fields/ReferenceField.js +52 -31
  202. package/dist/editor/fields/ReferenceField.js.map +1 -1
  203. package/dist/editor/hooks/__test__/test-utils.d.ts +38 -3
  204. package/dist/editor/hooks/__test__/test-utils.d.ts.map +1 -1
  205. package/dist/editor/hooks/__test__/test-utils.js +50 -4
  206. package/dist/editor/hooks/__test__/test-utils.js.map +1 -1
  207. package/dist/editor/hooks/index.d.ts +4 -1
  208. package/dist/editor/hooks/index.d.ts.map +1 -1
  209. package/dist/editor/hooks/index.js +4 -1
  210. package/dist/editor/hooks/index.js.map +1 -1
  211. package/dist/editor/hooks/useBranchManager.d.ts +21 -1
  212. package/dist/editor/hooks/useBranchManager.d.ts.map +1 -1
  213. package/dist/editor/hooks/useBranchManager.js +183 -58
  214. package/dist/editor/hooks/useBranchManager.js.map +1 -1
  215. package/dist/editor/hooks/useBranchesData.d.ts +57 -0
  216. package/dist/editor/hooks/useBranchesData.d.ts.map +1 -0
  217. package/dist/editor/hooks/useBranchesData.js +69 -0
  218. package/dist/editor/hooks/useBranchesData.js.map +1 -0
  219. package/dist/editor/hooks/useCommentSystem.d.ts.map +1 -1
  220. package/dist/editor/hooks/useCommentSystem.js +24 -22
  221. package/dist/editor/hooks/useCommentSystem.js.map +1 -1
  222. package/dist/editor/hooks/useCommentsData.d.ts +29 -0
  223. package/dist/editor/hooks/useCommentsData.d.ts.map +1 -0
  224. package/dist/editor/hooks/useCommentsData.js +40 -0
  225. package/dist/editor/hooks/useCommentsData.js.map +1 -0
  226. package/dist/editor/hooks/useDraftManager.d.ts +8 -0
  227. package/dist/editor/hooks/useDraftManager.d.ts.map +1 -1
  228. package/dist/editor/hooks/useDraftManager.js +290 -36
  229. package/dist/editor/hooks/useDraftManager.js.map +1 -1
  230. package/dist/editor/hooks/useEntriesData.d.ts +35 -0
  231. package/dist/editor/hooks/useEntriesData.d.ts.map +1 -0
  232. package/dist/editor/hooks/useEntriesData.js +96 -0
  233. package/dist/editor/hooks/useEntriesData.js.map +1 -0
  234. package/dist/editor/hooks/useEntryManager.d.ts +29 -15
  235. package/dist/editor/hooks/useEntryManager.d.ts.map +1 -1
  236. package/dist/editor/hooks/useEntryManager.js +284 -119
  237. package/dist/editor/hooks/useEntryManager.js.map +1 -1
  238. package/dist/editor/hooks/usePermissionManager.d.ts +2 -2
  239. package/dist/editor/hooks/usePermissionManager.d.ts.map +1 -1
  240. package/dist/editor/hooks/usePermissionManager.js +11 -9
  241. package/dist/editor/hooks/usePermissionManager.js.map +1 -1
  242. package/dist/editor/hooks/useReferenceResolution.d.ts.map +1 -1
  243. package/dist/editor/hooks/useReferenceResolution.js +24 -1
  244. package/dist/editor/hooks/useReferenceResolution.js.map +1 -1
  245. package/dist/editor/media/MediaLibraryBody.d.ts.map +1 -1
  246. package/dist/editor/media/MediaLibraryBody.js +12 -2
  247. package/dist/editor/media/MediaLibraryBody.js.map +1 -1
  248. package/dist/editor/permission-manager/GroupSelector.d.ts.map +1 -1
  249. package/dist/editor/permission-manager/GroupSelector.js +7 -2
  250. package/dist/editor/permission-manager/GroupSelector.js.map +1 -1
  251. package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts +3 -3
  252. package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts.map +1 -1
  253. package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js +1 -0
  254. package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js.map +1 -1
  255. package/dist/editor/permission-manager/types.d.ts +6 -4
  256. package/dist/editor/permission-manager/types.d.ts.map +1 -1
  257. package/dist/editor/test-setup.js +8 -0
  258. package/dist/editor/test-setup.js.map +1 -1
  259. package/dist/editor/theme.d.ts +8 -8
  260. package/dist/git-manager.d.ts +175 -14
  261. package/dist/git-manager.d.ts.map +1 -1
  262. package/dist/git-manager.js +354 -39
  263. package/dist/git-manager.js.map +1 -1
  264. package/dist/github-service.d.ts.map +1 -1
  265. package/dist/github-service.js +13 -7
  266. package/dist/github-service.js.map +1 -1
  267. package/dist/http/handler.d.ts.map +1 -1
  268. package/dist/http/handler.js +78 -29
  269. package/dist/http/handler.js.map +1 -1
  270. package/dist/http/router.d.ts.map +1 -1
  271. package/dist/http/router.js +40 -3
  272. package/dist/http/router.js.map +1 -1
  273. package/dist/operating-mode/client-unsafe-strategy.d.ts.map +1 -1
  274. package/dist/operating-mode/client-unsafe-strategy.js +7 -8
  275. package/dist/operating-mode/client-unsafe-strategy.js.map +1 -1
  276. package/dist/operating-mode/deployment-name-fixtures.d.ts +29 -0
  277. package/dist/operating-mode/deployment-name-fixtures.d.ts.map +1 -0
  278. package/dist/operating-mode/deployment-name-fixtures.js +55 -0
  279. package/dist/operating-mode/deployment-name-fixtures.js.map +1 -0
  280. package/dist/operating-mode/deployment-name.d.ts +37 -0
  281. package/dist/operating-mode/deployment-name.d.ts.map +1 -0
  282. package/dist/operating-mode/deployment-name.js +86 -0
  283. package/dist/operating-mode/deployment-name.js.map +1 -0
  284. package/dist/operating-mode/index.d.ts +6 -1
  285. package/dist/operating-mode/index.d.ts.map +1 -1
  286. package/dist/operating-mode/index.js +10 -1
  287. package/dist/operating-mode/index.js.map +1 -1
  288. package/dist/operating-mode/mode-env.d.ts +58 -0
  289. package/dist/operating-mode/mode-env.d.ts.map +1 -0
  290. package/dist/operating-mode/mode-env.js +97 -0
  291. package/dist/operating-mode/mode-env.js.map +1 -0
  292. package/dist/operating-mode/types.d.ts +13 -3
  293. package/dist/operating-mode/types.d.ts.map +1 -1
  294. package/dist/paths/branch-name.d.ts +38 -0
  295. package/dist/paths/branch-name.d.ts.map +1 -1
  296. package/dist/paths/branch-name.js +46 -0
  297. package/dist/paths/branch-name.js.map +1 -1
  298. package/dist/paths/index.d.ts +1 -1
  299. package/dist/paths/index.d.ts.map +1 -1
  300. package/dist/paths/index.js +1 -1
  301. package/dist/paths/index.js.map +1 -1
  302. package/dist/reference-resolver.d.ts +6 -2
  303. package/dist/reference-resolver.d.ts.map +1 -1
  304. package/dist/reference-resolver.js +8 -1
  305. package/dist/reference-resolver.js.map +1 -1
  306. package/dist/resolve-canopy-user.d.ts +34 -0
  307. package/dist/resolve-canopy-user.d.ts.map +1 -0
  308. package/dist/resolve-canopy-user.js +55 -0
  309. package/dist/resolve-canopy-user.js.map +1 -0
  310. package/dist/schema/meta-loader.d.ts.map +1 -1
  311. package/dist/schema/meta-loader.js +10 -2
  312. package/dist/schema/meta-loader.js.map +1 -1
  313. package/dist/schema/schema-store.d.ts +64 -4
  314. package/dist/schema/schema-store.d.ts.map +1 -1
  315. package/dist/schema/schema-store.js +113 -30
  316. package/dist/schema/schema-store.js.map +1 -1
  317. package/dist/server.d.ts +9 -0
  318. package/dist/server.d.ts.map +1 -1
  319. package/dist/server.js +9 -0
  320. package/dist/server.js.map +1 -1
  321. package/dist/services.d.ts.map +1 -1
  322. package/dist/services.js +40 -6
  323. package/dist/services.js.map +1 -1
  324. package/dist/settings-workspace.d.ts +27 -2
  325. package/dist/settings-workspace.d.ts.map +1 -1
  326. package/dist/settings-workspace.js +142 -58
  327. package/dist/settings-workspace.js.map +1 -1
  328. package/dist/types.d.ts +73 -2
  329. package/dist/types.d.ts.map +1 -1
  330. package/dist/utils/content-write-lock.d.ts +127 -0
  331. package/dist/utils/content-write-lock.d.ts.map +1 -0
  332. package/dist/utils/content-write-lock.js +170 -0
  333. package/dist/utils/content-write-lock.js.map +1 -0
  334. package/dist/utils/debug.d.ts +11 -0
  335. package/dist/utils/debug.d.ts.map +1 -1
  336. package/dist/utils/debug.js +12 -1
  337. package/dist/utils/debug.js.map +1 -1
  338. package/dist/utils/error.d.ts +1 -1
  339. package/dist/utils/error.js +1 -1
  340. package/dist/utils/git.d.ts +54 -0
  341. package/dist/utils/git.d.ts.map +1 -1
  342. package/dist/utils/git.js +91 -0
  343. package/dist/utils/git.js.map +1 -1
  344. package/dist/utils/logger.d.ts +71 -0
  345. package/dist/utils/logger.d.ts.map +1 -0
  346. package/dist/utils/logger.js +85 -0
  347. package/dist/utils/logger.js.map +1 -0
  348. package/dist/utils/sanitize-href.d.ts +28 -3
  349. package/dist/utils/sanitize-href.d.ts.map +1 -1
  350. package/dist/utils/sanitize-href.js +64 -6
  351. package/dist/utils/sanitize-href.js.map +1 -1
  352. package/dist/validation/entry-link-validator.d.ts +1 -1
  353. package/dist/validation/entry-link-validator.js +3 -3
  354. package/dist/validation/entry-link-validator.js.map +1 -1
  355. package/dist/validation/entry-type-reference-validator.d.ts +33 -0
  356. package/dist/validation/entry-type-reference-validator.d.ts.map +1 -0
  357. package/dist/validation/entry-type-reference-validator.js +110 -0
  358. package/dist/validation/entry-type-reference-validator.js.map +1 -0
  359. package/dist/validation/entry-validator.js +1 -1
  360. package/dist/validation/entry-validator.js.map +1 -1
  361. package/dist/worker/cms-worker.d.ts +245 -3
  362. package/dist/worker/cms-worker.d.ts.map +1 -1
  363. package/dist/worker/cms-worker.js +1084 -253
  364. package/dist/worker/cms-worker.js.map +1 -1
  365. package/dist/worker/log.d.ts +61 -0
  366. package/dist/worker/log.d.ts.map +1 -0
  367. package/dist/worker/log.js +74 -0
  368. package/dist/worker/log.js.map +1 -0
  369. package/package.json +4 -2
package/dist/cli/init.js CHANGED
@@ -9,6 +9,18 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
+ // dist/utils/logger.js
13
+ function canopyLogWarn(...args) {
14
+ active.warn(...args);
15
+ }
16
+ var active;
17
+ var init_logger = __esm({
18
+ "dist/utils/logger.js"() {
19
+ "use strict";
20
+ active = console;
21
+ }
22
+ });
23
+
12
24
  // dist/config/types.js
13
25
  var primitiveFieldTypes, fieldTypes;
14
26
  var init_types = __esm({
@@ -19,7 +31,6 @@ var init_types = __esm({
19
31
  "number",
20
32
  "boolean",
21
33
  "datetime",
22
- "rich-text",
23
34
  "markdown",
24
35
  "mdx",
25
36
  "code"
@@ -267,6 +278,16 @@ var init_config = __esm({
267
278
  allowNetworkRemoteInProd: z4.boolean().optional(),
268
279
  settingsBranch: z4.string().optional(),
269
280
  autoCreateSettingsPR: z4.boolean().optional(),
281
+ // Deliberately `deploymentNameSchema.optional()`, NOT `deploymentNameSchema` alone.
282
+ // deploymentNameSchema.default('prod') would make `parse(undefined)` resolve to
283
+ // the literal 'prod' instead of staying `undefined` — collapsing the
284
+ // env > config > modeDefault precedence chain that resolveDeploymentName
285
+ // (operating-mode/deployment-name.ts) implements: config would then always
286
+ // "win" over modeDefault (masking dev's real default of 'local'), and the env
287
+ // var would just be racing config's baked-in 'prod' instead of a true absence.
288
+ // `.optional()` here is what keeps an omitted deploymentName reaching
289
+ // resolveDeploymentName as `undefined`, so it can fall through to modeDefault.
290
+ // Do not "fix" this by removing `.optional()`.
270
291
  deploymentName: deploymentNameSchema.optional(),
271
292
  contentRoot: contentRootSchema.default("content"),
272
293
  sourceRoot: sourceRootSchema.optional(),
@@ -323,12 +344,21 @@ var init_flatten = __esm({
323
344
  }
324
345
  });
325
346
 
347
+ // dist/operating-mode/mode-env.js
348
+ var init_mode_env = __esm({
349
+ "dist/operating-mode/mode-env.js"() {
350
+ "use strict";
351
+ init_logger();
352
+ }
353
+ });
354
+
326
355
  // dist/config/validation.js
327
356
  var init_validation = __esm({
328
357
  "dist/config/validation.js"() {
329
358
  "use strict";
330
359
  init_config();
331
360
  init_flatten();
361
+ init_mode_env();
332
362
  }
333
363
  });
334
364
 
@@ -356,14 +386,59 @@ var init_config2 = __esm({
356
386
  }
357
387
  });
358
388
 
389
+ // dist/utils/error.js
390
+ function getErrorMessage(err) {
391
+ if (err instanceof Error) {
392
+ return err.message;
393
+ }
394
+ if (typeof err === "string") {
395
+ return err;
396
+ }
397
+ return String(err);
398
+ }
399
+ function isNodeError(err) {
400
+ return err instanceof Error && "code" in err;
401
+ }
402
+ function isNotFoundError(err) {
403
+ return isNodeError(err) && err.code === "ENOENT";
404
+ }
405
+ var init_error = __esm({
406
+ "dist/utils/error.js"() {
407
+ "use strict";
408
+ }
409
+ });
410
+
411
+ // dist/utils/fs.js
412
+ import fs from "node:fs/promises";
413
+ async function filePathExists(filePath) {
414
+ try {
415
+ await fs.stat(filePath);
416
+ return true;
417
+ } catch (err) {
418
+ if (isNotFoundError(err))
419
+ return false;
420
+ throw err;
421
+ }
422
+ }
423
+ var init_fs = __esm({
424
+ "dist/utils/fs.js"() {
425
+ "use strict";
426
+ init_error();
427
+ }
428
+ });
429
+
359
430
  // dist/cli/templates.js
360
431
  var templates_exports = {};
361
432
  __export(templates_exports, {
433
+ SCAFFOLD_STACK_NAME: () => SCAFFOLD_STACK_NAME,
362
434
  aiConfig: () => aiConfig,
363
435
  aiRoute: () => aiRoute,
364
436
  apiRoute: () => apiRoute,
365
437
  canopyCmsConfig: () => canopyCmsConfig,
366
438
  canopyContext: () => canopyContext,
439
+ cdkApp: () => cdkApp,
440
+ cdkJson: () => cdkJson,
441
+ cmsStack: () => cmsStack,
367
442
  dockerfileCms: () => dockerfileCms,
368
443
  dockerignore: () => dockerignore,
369
444
  editPage: () => editPage,
@@ -427,21 +502,205 @@ async function nextConfig(options) {
427
502
  const templateName = options.staticBuild ? "next.config-static.ts.template" : "next.config.ts.template";
428
503
  return readTemplate(templateName);
429
504
  }
430
- async function dockerfileCms() {
431
- return readTemplate("Dockerfile.cms.template");
505
+ async function dockerfileCms(options) {
506
+ const template = await readTemplate("Dockerfile.cms.template");
507
+ return template.replace("{{DOCKER_COPY}}", options.copy).replace("{{DOCKER_INSTALL}}", options.install).replace("{{DOCKER_BUILD}}", options.build);
432
508
  }
433
509
  async function dockerignore() {
434
510
  return readTemplate("dockerignore.template");
435
511
  }
436
- async function githubWorkflowCms() {
437
- return readTemplate("deploy-cms.yml.template");
512
+ async function githubWorkflowCms(options) {
513
+ const template = await readTemplate("deploy-cms.yml.template");
514
+ return template.replace("{{DEFAULT_BRANCH}}", options.defaultBranch).replace("{{LOCKFILE}}", options.lockfile).replace("{{CI_INSTALL}}", options.ciInstall).replaceAll("{{ADD_DEV}}", options.addDev).replace("{{STACK_NAME}}", SCAFFOLD_STACK_NAME);
515
+ }
516
+ async function cdkJson() {
517
+ return readTemplate("cdk.json.template");
518
+ }
519
+ async function cdkApp(options) {
520
+ const template = await readTemplate("cdk-app.ts.template");
521
+ return template.replace("{{STACK_NAME}}", SCAFFOLD_STACK_NAME).replace("{{GITHUB_OWNER}}", options.githubOwner).replace("{{GITHUB_REPO}}", options.githubRepo);
438
522
  }
439
- var __dirname, TEMPLATES_DIR;
523
+ async function cmsStack() {
524
+ return readTemplate("cms-stack.ts.template");
525
+ }
526
+ var __dirname, TEMPLATES_DIR, SCAFFOLD_STACK_NAME;
440
527
  var init_templates = __esm({
441
528
  "dist/cli/templates.js"() {
442
529
  "use strict";
443
530
  __dirname = path2.dirname(fileURLToPath(import.meta.url));
444
531
  TEMPLATES_DIR = path2.join(__dirname, "template-files");
532
+ SCAFFOLD_STACK_NAME = "CanopyCms";
533
+ }
534
+ });
535
+
536
+ // dist/cli/project-detect.js
537
+ var project_detect_exports = {};
538
+ __export(project_detect_exports, {
539
+ CDK_DEPENDENCIES: () => CDK_DEPENDENCIES,
540
+ commandsFor: () => commandsFor,
541
+ detectDefaultBranch: () => detectDefaultBranch,
542
+ detectGitHubRepo: () => detectGitHubRepo,
543
+ detectPackageManager: () => detectPackageManager,
544
+ missingCdkDependencies: () => missingCdkDependencies,
545
+ readPackageJson: () => readPackageJson
546
+ });
547
+ import fs3 from "node:fs/promises";
548
+ import path3 from "node:path";
549
+ import { simpleGit } from "simple-git";
550
+ function commandsFor(manager) {
551
+ return COMMANDS[manager];
552
+ }
553
+ async function detectPackageManager(projectDir) {
554
+ for (const dir of await workspaceSearchPath(projectDir)) {
555
+ const declared = await readDeclaredPackageManager(dir);
556
+ if (declared)
557
+ return declared;
558
+ if (await filePathExists(path3.join(dir, "pnpm-lock.yaml")))
559
+ return "pnpm";
560
+ if (await filePathExists(path3.join(dir, "yarn.lock"))) {
561
+ return await isYarnBerryLockfile(dir) ? "yarn-berry" : "yarn";
562
+ }
563
+ }
564
+ return "npm";
565
+ }
566
+ async function workspaceSearchPath(projectDir) {
567
+ const start = path3.resolve(projectDir);
568
+ const dirs = [start];
569
+ if (!await filePathExists(path3.join(start, "package.json")))
570
+ return dirs;
571
+ let dir = start;
572
+ for (let depth = 0; depth < MAX_WORKSPACE_DEPTH; depth++) {
573
+ if (await filePathExists(path3.join(dir, ".git")))
574
+ break;
575
+ const parent = path3.dirname(dir);
576
+ if (parent === dir)
577
+ break;
578
+ dir = parent;
579
+ dirs.push(dir);
580
+ }
581
+ return dirs;
582
+ }
583
+ async function readDeclaredPackageManager(projectDir) {
584
+ const pkg = await readPackageJson(projectDir);
585
+ const declared = pkg?.["packageManager"];
586
+ if (typeof declared !== "string")
587
+ return null;
588
+ if (declared.startsWith("pnpm@"))
589
+ return "pnpm";
590
+ if (declared.startsWith("npm@"))
591
+ return "npm";
592
+ if (declared.startsWith("yarn@")) {
593
+ const major = Number.parseInt(declared.slice("yarn@".length), 10);
594
+ if (Number.isFinite(major) && major >= 2)
595
+ return "yarn-berry";
596
+ if (Number.isFinite(major))
597
+ return "yarn";
598
+ return await isYarnBerryLockfile(projectDir) ? "yarn-berry" : "yarn";
599
+ }
600
+ return null;
601
+ }
602
+ async function isYarnBerryLockfile(projectDir) {
603
+ try {
604
+ const content = await fs3.readFile(path3.join(projectDir, "yarn.lock"), "utf-8");
605
+ return content.includes("__metadata:");
606
+ } catch {
607
+ return false;
608
+ }
609
+ }
610
+ async function detectDefaultBranch(projectDir) {
611
+ const head = await gitRaw(projectDir, ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"]);
612
+ if (!head)
613
+ return "main";
614
+ const slash = head.indexOf("/");
615
+ const branch = slash === -1 ? head : head.slice(slash + 1);
616
+ return branch || "main";
617
+ }
618
+ async function detectGitHubRepo(projectDir) {
619
+ const url = await gitRaw(projectDir, ["remote", "get-url", "origin"]);
620
+ if (!url)
621
+ return null;
622
+ const match = /github\.com[:/]+([^/]+)\/(.+?)(?:\.git)?\/?$/.exec(url);
623
+ if (!match)
624
+ return null;
625
+ return { owner: match[1], repo: match[2] };
626
+ }
627
+ async function gitRaw(projectDir, args) {
628
+ try {
629
+ const output = await simpleGit({ baseDir: projectDir }).raw(args);
630
+ const trimmed = output.trim();
631
+ return trimmed.length > 0 ? trimmed : null;
632
+ } catch {
633
+ return null;
634
+ }
635
+ }
636
+ async function readPackageJson(projectDir) {
637
+ try {
638
+ const raw = await fs3.readFile(path3.join(projectDir, "package.json"), "utf-8");
639
+ const parsed = JSON.parse(raw);
640
+ return typeof parsed === "object" && parsed !== null ? parsed : null;
641
+ } catch {
642
+ return null;
643
+ }
644
+ }
645
+ async function missingCdkDependencies(projectDir) {
646
+ const pkg = await readPackageJson(projectDir);
647
+ const declared = /* @__PURE__ */ new Set();
648
+ for (const field of ["dependencies", "devDependencies", "peerDependencies"]) {
649
+ const section = pkg?.[field];
650
+ if (typeof section === "object" && section !== null) {
651
+ for (const name of Object.keys(section))
652
+ declared.add(name);
653
+ }
654
+ }
655
+ return CDK_DEPENDENCIES.filter((name) => !declared.has(name));
656
+ }
657
+ var COMMANDS, MAX_WORKSPACE_DEPTH, CDK_DEPENDENCIES;
658
+ var init_project_detect = __esm({
659
+ "dist/cli/project-detect.js"() {
660
+ "use strict";
661
+ init_fs();
662
+ COMMANDS = {
663
+ npm: {
664
+ lockfile: "package-lock.json",
665
+ ciInstall: "npm ci",
666
+ dockerCopy: "COPY package*.json ./",
667
+ dockerInstall: "RUN npm ci",
668
+ build: "npm run build",
669
+ addDev: "npm install --save-dev"
670
+ },
671
+ pnpm: {
672
+ lockfile: "pnpm-lock.yaml",
673
+ ciInstall: "corepack enable && pnpm install --frozen-lockfile",
674
+ dockerCopy: "COPY package.json pnpm-lock.yaml ./",
675
+ dockerInstall: "RUN corepack enable && pnpm install --frozen-lockfile",
676
+ build: "pnpm run build",
677
+ addDev: "pnpm add -D"
678
+ },
679
+ yarn: {
680
+ lockfile: "yarn.lock",
681
+ ciInstall: "corepack enable && yarn install --frozen-lockfile",
682
+ dockerCopy: "COPY package.json yarn.lock ./",
683
+ dockerInstall: "RUN corepack enable && yarn install --frozen-lockfile",
684
+ build: "yarn build",
685
+ addDev: "yarn add -D"
686
+ },
687
+ "yarn-berry": {
688
+ lockfile: "yarn.lock",
689
+ ciInstall: "corepack enable && yarn install --immutable",
690
+ dockerCopy: "COPY package.json yarn.lock .yarnrc.yml ./",
691
+ dockerInstall: "RUN corepack enable && yarn install --immutable",
692
+ build: "yarn build",
693
+ addDev: "yarn add -D"
694
+ }
695
+ };
696
+ MAX_WORKSPACE_DEPTH = 8;
697
+ CDK_DEPENDENCIES = [
698
+ "canopycms-cdk",
699
+ "aws-cdk-lib",
700
+ "constructs",
701
+ "tsx",
702
+ "aws-cdk"
703
+ ];
445
704
  }
446
705
  });
447
706
 
@@ -450,15 +709,15 @@ var task_queue_config_exports = {};
450
709
  __export(task_queue_config_exports, {
451
710
  getTaskQueueDir: () => getTaskQueueDir
452
711
  });
453
- import path3 from "node:path";
712
+ import path4 from "node:path";
454
713
  function getTaskQueueDir(config) {
455
714
  switch (config.mode) {
456
715
  case "prod": {
457
716
  const workspace = process.env.CANOPYCMS_WORKSPACE_ROOT ?? DEFAULT_PROD_WORKSPACE;
458
- return path3.join(path3.resolve(workspace), ".tasks");
717
+ return path4.join(path4.resolve(workspace), ".tasks");
459
718
  }
460
719
  case "dev": {
461
- return path3.join(process.cwd(), ".canopy-dev", ".tasks");
720
+ return path4.join(process.cwd(), ".canopy-dev", ".tasks");
462
721
  }
463
722
  }
464
723
  }
@@ -495,10 +754,21 @@ var init_debug = __esm({
495
754
  const minLevel = this.options.minLevel ?? "DEBUG";
496
755
  return LOG_LEVELS[level] >= LOG_LEVELS[minLevel];
497
756
  }
757
+ /**
758
+ * The ISO-8601 timestamp leads the line BARE - not wrapped in brackets as it
759
+ * once was. `CANOPYCMS_DEBUG=true` can be set on the EC2 worker, whose stdout
760
+ * appends to /var/log/canopy-worker/worker.log; the CloudWatch agent's
761
+ * `multi_line_start_pattern` matches the timestamp at the START of a line
762
+ * (see worker/log.ts's INVARIANT and cms-service.ts's agent config), so a
763
+ * leading `[` meant every debug line was silently folded into the previous
764
+ * event instead of starting its own. The bracketed `[prefix:category]` and
765
+ * `[level]` fields still follow, so the human-readable shape is unchanged
766
+ * apart from those two characters.
767
+ */
498
768
  formatMessage(level, category, message) {
499
769
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
500
770
  const prefix = this.options.prefix ?? "CanopyCMS";
501
- return `[${timestamp}] [${prefix}:${category}] [${level}] ${message}`;
771
+ return `${timestamp} [${prefix}:${category}] [${level}] ${message}`;
502
772
  }
503
773
  debug(category, message, data) {
504
774
  if (this.shouldLog("DEBUG")) {
@@ -567,17 +837,17 @@ var init_debug = __esm({
567
837
  });
568
838
 
569
839
  // dist/utils/atomic-write.js
570
- import fs3 from "node:fs/promises";
571
- import path4 from "node:path";
840
+ import fs4 from "node:fs/promises";
841
+ import path5 from "node:path";
572
842
  async function atomicWriteFile(filePath, content) {
573
- const dir = path4.dirname(filePath);
574
- await fs3.mkdir(dir, { recursive: true });
843
+ const dir = path5.dirname(filePath);
844
+ await fs4.mkdir(dir, { recursive: true });
575
845
  const tempPath = `${filePath}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
576
- await fs3.writeFile(tempPath, content, typeof content === "string" ? "utf-8" : void 0);
846
+ await fs4.writeFile(tempPath, content, typeof content === "string" ? "utf-8" : void 0);
577
847
  try {
578
- await fs3.rename(tempPath, filePath);
848
+ await fs4.rename(tempPath, filePath);
579
849
  } catch (err) {
580
- await fs3.unlink(tempPath).catch(() => {
850
+ await fs4.unlink(tempPath).catch(() => {
581
851
  });
582
852
  throw err;
583
853
  }
@@ -589,15 +859,15 @@ var init_atomic_write = __esm({
589
859
  });
590
860
 
591
861
  // dist/task-queue/task-queue.js
592
- import fs4 from "node:fs/promises";
593
- import path5 from "node:path";
862
+ import fs5 from "node:fs/promises";
863
+ import path6 from "node:path";
594
864
  import crypto from "node:crypto";
595
865
  function isNotFoundError2(err) {
596
866
  return err instanceof Error && "code" in err && err.code === "ENOENT";
597
867
  }
598
868
  async function enqueueTask(taskDir, task, logger = nullLogger) {
599
869
  const id = crypto.randomUUID();
600
- const pendingDir = path5.join(taskDir, "pending");
870
+ const pendingDir = path6.join(taskDir, "pending");
601
871
  const queuedTask = {
602
872
  id,
603
873
  action: task.action,
@@ -607,17 +877,17 @@ async function enqueueTask(taskDir, task, logger = nullLogger) {
607
877
  retryCount: 0,
608
878
  maxRetries: task.maxRetries ?? DEFAULT_MAX_RETRIES
609
879
  };
610
- const filePath = path5.join(pendingDir, `${id}.json`);
880
+ const filePath = path6.join(pendingDir, `${id}.json`);
611
881
  await atomicWriteFile(filePath, JSON.stringify(queuedTask, null, 2));
612
882
  logger.debug("Enqueued task", { id, action: task.action });
613
883
  return id;
614
884
  }
615
885
  async function dequeueTask(taskDir, logger = nullLogger) {
616
- const pendingDir = path5.join(taskDir, "pending");
617
- const processingDir = path5.join(taskDir, "processing");
886
+ const pendingDir = path6.join(taskDir, "pending");
887
+ const processingDir = path6.join(taskDir, "processing");
618
888
  let files;
619
889
  try {
620
- files = await fs4.readdir(pendingDir);
890
+ files = await fs5.readdir(pendingDir);
621
891
  } catch {
622
892
  return null;
623
893
  }
@@ -628,7 +898,7 @@ async function dequeueTask(taskDir, logger = nullLogger) {
628
898
  const tasks = [];
629
899
  for (const fileName of jsonFiles) {
630
900
  try {
631
- const content = await fs4.readFile(path5.join(pendingDir, fileName), "utf-8");
901
+ const content = await fs5.readFile(path6.join(pendingDir, fileName), "utf-8");
632
902
  const task = parseTaskJson(content);
633
903
  if (!task) {
634
904
  await moveToCorrupt(taskDir, pendingDir, fileName, "Invalid JSON", logger);
@@ -649,17 +919,17 @@ async function dequeueTask(taskDir, logger = nullLogger) {
649
919
  tasks.sort((a, b) => a.task.createdAt.localeCompare(b.task.createdAt) || a.task.id.localeCompare(b.task.id));
650
920
  for (const { fileName, task } of tasks) {
651
921
  if (await taskExistsIn(taskDir, task.id, ["completed", "failed"])) {
652
- await fs4.unlink(path5.join(pendingDir, fileName)).catch(() => {
922
+ await fs5.unlink(path6.join(pendingDir, fileName)).catch(() => {
653
923
  });
654
924
  logger.debug("Skipped already-finished task", { id: task.id });
655
925
  continue;
656
926
  }
657
- const sourcePath = path5.join(pendingDir, fileName);
658
- const destPath = path5.join(processingDir, fileName);
927
+ const sourcePath = path6.join(pendingDir, fileName);
928
+ const destPath = path6.join(processingDir, fileName);
659
929
  try {
660
930
  task.status = "processing";
661
931
  await atomicWriteFile(destPath, JSON.stringify(task, null, 2));
662
- await fs4.unlink(sourcePath);
932
+ await fs5.unlink(sourcePath);
663
933
  logger.debug("Dequeued task", { id: task.id, action: task.action });
664
934
  return task;
665
935
  } catch (err) {
@@ -671,16 +941,16 @@ async function dequeueTask(taskDir, logger = nullLogger) {
671
941
  return null;
672
942
  }
673
943
  async function completeTask(taskDir, taskId, result, logger = nullLogger) {
674
- const processingPath = path5.join(taskDir, "processing", `${taskId}.json`);
675
- const completedDir = path5.join(taskDir, "completed");
676
- const completedPath = path5.join(completedDir, `${taskId}.json`);
944
+ const processingPath = path6.join(taskDir, "processing", `${taskId}.json`);
945
+ const completedDir = path6.join(taskDir, "completed");
946
+ const completedPath = path6.join(completedDir, `${taskId}.json`);
677
947
  let task;
678
948
  try {
679
- const content = await fs4.readFile(processingPath, "utf-8");
949
+ const content = await fs5.readFile(processingPath, "utf-8");
680
950
  const parsed = parseTaskJson(content);
681
951
  if (!parsed) {
682
952
  logger.debug("Corrupt task file in processing, removing", { id: taskId });
683
- await fs4.unlink(processingPath).catch(() => {
953
+ await fs5.unlink(processingPath).catch(() => {
684
954
  });
685
955
  return;
686
956
  }
@@ -694,21 +964,21 @@ async function completeTask(taskDir, taskId, result, logger = nullLogger) {
694
964
  task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
695
965
  task.result = result;
696
966
  await atomicWriteFile(completedPath, JSON.stringify(task, null, 2));
697
- await fs4.unlink(processingPath).catch(() => {
967
+ await fs5.unlink(processingPath).catch(() => {
698
968
  });
699
969
  logger.debug("Completed task", { id: taskId });
700
970
  }
701
971
  async function failTask(taskDir, taskId, error, logger = nullLogger) {
702
- const processingPath = path5.join(taskDir, "processing", `${taskId}.json`);
703
- const failedDir = path5.join(taskDir, "failed");
704
- const failedPath = path5.join(failedDir, `${taskId}.json`);
972
+ const processingPath = path6.join(taskDir, "processing", `${taskId}.json`);
973
+ const failedDir = path6.join(taskDir, "failed");
974
+ const failedPath = path6.join(failedDir, `${taskId}.json`);
705
975
  let task;
706
976
  try {
707
- const content = await fs4.readFile(processingPath, "utf-8");
977
+ const content = await fs5.readFile(processingPath, "utf-8");
708
978
  const parsed = parseTaskJson(content);
709
979
  if (!parsed) {
710
980
  logger.debug("Corrupt task file in processing, removing", { id: taskId });
711
- await fs4.unlink(processingPath).catch(() => {
981
+ await fs5.unlink(processingPath).catch(() => {
712
982
  });
713
983
  return;
714
984
  }
@@ -722,21 +992,21 @@ async function failTask(taskDir, taskId, error, logger = nullLogger) {
722
992
  task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
723
993
  task.error = error;
724
994
  await atomicWriteFile(failedPath, JSON.stringify(task, null, 2));
725
- await fs4.unlink(processingPath).catch(() => {
995
+ await fs5.unlink(processingPath).catch(() => {
726
996
  });
727
997
  logger.debug("Failed task", { id: taskId, error });
728
998
  }
729
999
  async function retryTask(taskDir, taskId, error, logger = nullLogger) {
730
- const processingPath = path5.join(taskDir, "processing", `${taskId}.json`);
731
- const pendingDir = path5.join(taskDir, "pending");
732
- const pendingPath = path5.join(pendingDir, `${taskId}.json`);
1000
+ const processingPath = path6.join(taskDir, "processing", `${taskId}.json`);
1001
+ const pendingDir = path6.join(taskDir, "pending");
1002
+ const pendingPath = path6.join(pendingDir, `${taskId}.json`);
733
1003
  let task;
734
1004
  try {
735
- const content = await fs4.readFile(processingPath, "utf-8");
1005
+ const content = await fs5.readFile(processingPath, "utf-8");
736
1006
  const parsed = parseTaskJson(content);
737
1007
  if (!parsed) {
738
1008
  logger.debug("Corrupt task file in processing, removing", { id: taskId });
739
- await fs4.unlink(processingPath).catch(() => {
1009
+ await fs5.unlink(processingPath).catch(() => {
740
1010
  });
741
1011
  return;
742
1012
  }
@@ -753,15 +1023,15 @@ async function retryTask(taskDir, taskId, error, logger = nullLogger) {
753
1023
  task.retryAfter = new Date(Date.now() + backoffMs).toISOString();
754
1024
  task.error = error;
755
1025
  await atomicWriteFile(pendingPath, JSON.stringify(task, null, 2));
756
- await fs4.unlink(processingPath).catch(() => {
1026
+ await fs5.unlink(processingPath).catch(() => {
757
1027
  });
758
1028
  logger.debug("Retrying task", { id: taskId, retryCount, backoffMs });
759
1029
  }
760
1030
  async function requeueFailedTask(taskDir, taskId, logger = nullLogger) {
761
- const failedPath = path5.join(taskDir, "failed", `${taskId}.json`);
1031
+ const failedPath = path6.join(taskDir, "failed", `${taskId}.json`);
762
1032
  let content;
763
1033
  try {
764
- content = await fs4.readFile(failedPath, "utf-8");
1034
+ content = await fs5.readFile(failedPath, "utf-8");
765
1035
  } catch (err) {
766
1036
  if (isNotFoundError2(err))
767
1037
  return { error: "not-found" };
@@ -780,37 +1050,37 @@ async function requeueFailedTask(taskDir, taskId, logger = nullLogger) {
780
1050
  retryCount: 0,
781
1051
  maxRetries: original.maxRetries
782
1052
  };
783
- const pendingPath = path5.join(taskDir, "pending", `${newTaskId}.json`);
1053
+ const pendingPath = path6.join(taskDir, "pending", `${newTaskId}.json`);
784
1054
  await atomicWriteFile(pendingPath, JSON.stringify(newTask, null, 2));
785
- await fs4.unlink(failedPath).catch(() => {
1055
+ await fs5.unlink(failedPath).catch(() => {
786
1056
  });
787
1057
  logger.debug("Requeued failed task", { originalId: taskId, newTaskId });
788
1058
  return { newTaskId };
789
1059
  }
790
1060
  async function recoverOrphanedTasks(taskDir, maxAgeMs = 5 * 6e4, logger = nullLogger) {
791
- const processingDir = path5.join(taskDir, "processing");
792
- const pendingDir = path5.join(taskDir, "pending");
1061
+ const processingDir = path6.join(taskDir, "processing");
1062
+ const pendingDir = path6.join(taskDir, "pending");
793
1063
  let files;
794
1064
  try {
795
- files = await fs4.readdir(processingDir);
1065
+ files = await fs5.readdir(processingDir);
796
1066
  } catch {
797
1067
  return 0;
798
1068
  }
799
1069
  const now = Date.now();
800
1070
  let recovered = 0;
801
1071
  for (const fileName of files.filter((f) => f.endsWith(".json"))) {
802
- const filePath = path5.join(processingDir, fileName);
1072
+ const filePath = path6.join(processingDir, fileName);
803
1073
  try {
804
- const stat = await fs4.stat(filePath);
1074
+ const stat = await fs5.stat(filePath);
805
1075
  if (now - stat.mtimeMs >= maxAgeMs) {
806
- const content = await fs4.readFile(filePath, "utf-8");
1076
+ const content = await fs5.readFile(filePath, "utf-8");
807
1077
  const task = parseTaskJson(content);
808
1078
  if (!task) {
809
1079
  await moveToCorrupt(taskDir, processingDir, fileName, "Invalid JSON during recovery", logger);
810
1080
  continue;
811
1081
  }
812
1082
  if (await taskExistsIn(taskDir, task.id, ["completed", "failed"])) {
813
- await fs4.unlink(filePath).catch(() => {
1083
+ await fs5.unlink(filePath).catch(() => {
814
1084
  });
815
1085
  logger.debug("Cleaned up orphaned task (already finished)", {
816
1086
  id: task.id
@@ -818,8 +1088,8 @@ async function recoverOrphanedTasks(taskDir, maxAgeMs = 5 * 6e4, logger = nullLo
818
1088
  continue;
819
1089
  }
820
1090
  task.status = "pending";
821
- await atomicWriteFile(path5.join(pendingDir, fileName), JSON.stringify(task, null, 2));
822
- await fs4.unlink(filePath);
1091
+ await atomicWriteFile(path6.join(pendingDir, fileName), JSON.stringify(task, null, 2));
1092
+ await fs5.unlink(filePath);
823
1093
  logger.debug("Recovered orphaned task", {
824
1094
  id: task.id,
825
1095
  action: task.action
@@ -838,19 +1108,19 @@ async function cleanupOldTasks(taskDir, maxAgeMs = 30 * 24 * 60 * 6e4, logger =
838
1108
  const now = Date.now();
839
1109
  let cleaned = 0;
840
1110
  for (const subdir of ["completed", "failed"]) {
841
- const dir = path5.join(taskDir, subdir);
1111
+ const dir = path6.join(taskDir, subdir);
842
1112
  let files;
843
1113
  try {
844
- files = await fs4.readdir(dir);
1114
+ files = await fs5.readdir(dir);
845
1115
  } catch {
846
1116
  continue;
847
1117
  }
848
1118
  for (const fileName of files.filter((f) => f.endsWith(".json"))) {
849
1119
  try {
850
- const filePath = path5.join(dir, fileName);
851
- const stat = await fs4.stat(filePath);
1120
+ const filePath = path6.join(dir, fileName);
1121
+ const stat = await fs5.stat(filePath);
852
1122
  if (now - stat.mtimeMs >= maxAgeMs) {
853
- await fs4.unlink(filePath);
1123
+ await fs5.unlink(filePath);
854
1124
  cleaned++;
855
1125
  }
856
1126
  } catch {
@@ -864,9 +1134,9 @@ async function cleanupOldTasks(taskDir, maxAgeMs = 30 * 24 * 60 * 6e4, logger =
864
1134
  }
865
1135
  async function getTask(taskDir, taskId) {
866
1136
  for (const subdir of ["completed", "failed", "processing", "pending"]) {
867
- const filePath = path5.join(taskDir, subdir, `${taskId}.json`);
1137
+ const filePath = path6.join(taskDir, subdir, `${taskId}.json`);
868
1138
  try {
869
- const content = await fs4.readFile(filePath, "utf-8");
1139
+ const content = await fs5.readFile(filePath, "utf-8");
870
1140
  return parseTaskJson(content);
871
1141
  } catch {
872
1142
  continue;
@@ -875,10 +1145,10 @@ async function getTask(taskDir, taskId) {
875
1145
  return null;
876
1146
  }
877
1147
  async function listTasks(taskDir, status, limit = 100) {
878
- const dir = path5.join(taskDir, status);
1148
+ const dir = path6.join(taskDir, status);
879
1149
  let files;
880
1150
  try {
881
- files = await fs4.readdir(dir);
1151
+ files = await fs5.readdir(dir);
882
1152
  } catch {
883
1153
  return [];
884
1154
  }
@@ -887,7 +1157,7 @@ async function listTasks(taskDir, status, limit = 100) {
887
1157
  if (tasks.length >= limit)
888
1158
  break;
889
1159
  try {
890
- const content = await fs4.readFile(path5.join(dir, fileName), "utf-8");
1160
+ const content = await fs5.readFile(path6.join(dir, fileName), "utf-8");
891
1161
  const task = parseTaskJson(content);
892
1162
  if (task)
893
1163
  tasks.push(task);
@@ -907,9 +1177,9 @@ async function getQueueStats(taskDir) {
907
1177
  corrupt: 0
908
1178
  };
909
1179
  for (const status of ["pending", "processing", "completed", "failed", "corrupt"]) {
910
- const dir = path5.join(taskDir, status);
1180
+ const dir = path6.join(taskDir, status);
911
1181
  try {
912
- const files = await fs4.readdir(dir);
1182
+ const files = await fs5.readdir(dir);
913
1183
  stats[status] = files.filter((f) => f.endsWith(".json")).length;
914
1184
  } catch {
915
1185
  }
@@ -917,10 +1187,10 @@ async function getQueueStats(taskDir) {
917
1187
  return stats;
918
1188
  }
919
1189
  async function listCorruptTaskFiles(taskDir, limit = 50, logger = nullLogger) {
920
- const corruptDir = path5.join(taskDir, "corrupt");
1190
+ const corruptDir = path6.join(taskDir, "corrupt");
921
1191
  let files;
922
1192
  try {
923
- files = await fs4.readdir(corruptDir);
1193
+ files = await fs5.readdir(corruptDir);
924
1194
  } catch (err) {
925
1195
  if (isNotFoundError2(err))
926
1196
  return [];
@@ -928,9 +1198,9 @@ async function listCorruptTaskFiles(taskDir, limit = 50, logger = nullLogger) {
928
1198
  }
929
1199
  const entries = [];
930
1200
  for (const fileName of files.filter((f) => f.endsWith(".json"))) {
931
- const filePath = path5.join(corruptDir, fileName);
1201
+ const filePath = path6.join(corruptDir, fileName);
932
1202
  try {
933
- const stat = await fs4.stat(filePath);
1203
+ const stat = await fs5.stat(filePath);
934
1204
  entries.push({
935
1205
  fileName,
936
1206
  size: stat.size,
@@ -947,7 +1217,7 @@ async function listCorruptTaskFiles(taskDir, limit = 50, logger = nullLogger) {
947
1217
  return entries.slice(0, limit);
948
1218
  }
949
1219
  async function readSnippet(filePath, maxBytes) {
950
- const handle = await fs4.open(filePath, "r");
1220
+ const handle = await fs5.open(filePath, "r");
951
1221
  try {
952
1222
  const buffer = Buffer.alloc(maxBytes);
953
1223
  const { bytesRead } = await handle.read(buffer, 0, maxBytes, 0);
@@ -970,7 +1240,7 @@ function parseTaskJson(content) {
970
1240
  async function taskExistsIn(taskDir, taskId, subdirs) {
971
1241
  for (const subdir of subdirs) {
972
1242
  try {
973
- await fs4.stat(path5.join(taskDir, subdir, `${taskId}.json`));
1243
+ await fs5.stat(path6.join(taskDir, subdir, `${taskId}.json`));
974
1244
  return true;
975
1245
  } catch {
976
1246
  }
@@ -978,13 +1248,13 @@ async function taskExistsIn(taskDir, taskId, subdirs) {
978
1248
  return false;
979
1249
  }
980
1250
  async function moveToCorrupt(taskDir, sourceDir, fileName, reason, logger) {
981
- const corruptDir = path5.join(taskDir, "corrupt");
1251
+ const corruptDir = path6.join(taskDir, "corrupt");
982
1252
  try {
983
- await fs4.mkdir(corruptDir, { recursive: true });
984
- await fs4.rename(path5.join(sourceDir, fileName), path5.join(corruptDir, fileName));
1253
+ await fs5.mkdir(corruptDir, { recursive: true });
1254
+ await fs5.rename(path6.join(sourceDir, fileName), path6.join(corruptDir, fileName));
985
1255
  logger.debug("Moved corrupt task file", { fileName, reason });
986
1256
  } catch {
987
- await fs4.unlink(path5.join(sourceDir, fileName)).catch(() => {
1257
+ await fs5.unlink(path6.join(sourceDir, fileName)).catch(() => {
988
1258
  });
989
1259
  }
990
1260
  }
@@ -1041,8 +1311,8 @@ var init_task_queue3 = __esm({
1041
1311
  });
1042
1312
 
1043
1313
  // dist/cli/init.js
1044
- import fs5 from "node:fs/promises";
1045
- import path6 from "node:path";
1314
+ import fs6 from "node:fs/promises";
1315
+ import path7 from "node:path";
1046
1316
  import * as p from "@clack/prompts";
1047
1317
  import { createJiti } from "jiti";
1048
1318
 
@@ -1112,6 +1382,28 @@ var DevClientSafeStrategy = class {
1112
1382
 
1113
1383
  // dist/operating-mode/client-unsafe-strategy.js
1114
1384
  import path from "node:path";
1385
+
1386
+ // dist/operating-mode/deployment-name.js
1387
+ init_logger();
1388
+ var warned = false;
1389
+ var VALID_DEPLOYMENT_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
1390
+ var isValidDeploymentName = (name) => VALID_DEPLOYMENT_NAME.test(name) && !name.includes("..") && !name.endsWith(".") && !name.endsWith(".lock");
1391
+ function resolveDeploymentName(config, modeDefault) {
1392
+ const envValue = process.env.CANOPYCMS_DEPLOYMENT_NAME?.trim();
1393
+ const configValue = config.deploymentName;
1394
+ if (envValue && configValue && envValue !== configValue && !warned) {
1395
+ canopyLogWarn(`CanopyCMS: CANOPYCMS_DEPLOYMENT_NAME ("${envValue}") differs from config.deploymentName ("${configValue}") \u2014 using the env var (infra-stamped env wins over shared-repo config by design; see resolveDeploymentName's doc comment). Update config.deploymentName to match if this mismatch was unintentional.`);
1396
+ warned = true;
1397
+ }
1398
+ const resolved = envValue || configValue || modeDefault;
1399
+ if (!isValidDeploymentName(resolved)) {
1400
+ const source = envValue ? "CANOPYCMS_DEPLOYMENT_NAME" : configValue ? "config.deploymentName" : "the mode default";
1401
+ throw new Error(`CanopyCMS: invalid deploymentName ${JSON.stringify(resolved)} (from ${source}). It is interpolated into the settings branch name (canopycms-settings-<deploymentName>), so it must start with a letter or digit, contain only letters, digits, '.', '_' or '-', and must not contain '..' or end with '.' or '.lock'.`);
1402
+ }
1403
+ return resolved;
1404
+ }
1405
+
1406
+ // dist/operating-mode/client-unsafe-strategy.js
1115
1407
  init_config2();
1116
1408
  var ProdStrategy = class extends ProdClientSafeStrategy {
1117
1409
  // All client-safe methods inherited automatically from ProdClientSafeStrategy:
@@ -1122,8 +1414,8 @@ var ProdStrategy = class extends ProdClientSafeStrategy {
1122
1414
  getWorkspaceRoot(_sourceRoot) {
1123
1415
  return path.resolve(process.env.CANOPYCMS_WORKSPACE_ROOT ?? DEFAULT_PROD_WORKSPACE);
1124
1416
  }
1125
- getContentRoot(sourceRoot) {
1126
- return path.resolve(sourceRoot ?? process.cwd(), "content");
1417
+ getContentRoot(contentRoot, sourceRoot) {
1418
+ return path.resolve(sourceRoot ?? process.cwd(), contentRoot);
1127
1419
  }
1128
1420
  getContentBranchesRoot(sourceRoot) {
1129
1421
  return path.join(this.getWorkspaceRoot(sourceRoot), "content-branches");
@@ -1154,8 +1446,7 @@ var ProdStrategy = class extends ProdClientSafeStrategy {
1154
1446
  getSettingsBranchName(config) {
1155
1447
  if (config.settingsBranch)
1156
1448
  return config.settingsBranch;
1157
- const deploymentName = config.deploymentName ?? "prod";
1158
- return `canopycms-settings-${deploymentName}`;
1449
+ return `canopycms-settings-${resolveDeploymentName(config, "prod")}`;
1159
1450
  }
1160
1451
  getSettingsRoot(sourceRoot) {
1161
1452
  return path.join(this.getWorkspaceRoot(sourceRoot), "settings");
@@ -1177,8 +1468,8 @@ var DevStrategy = class extends DevClientSafeStrategy {
1177
1468
  getWorkspaceRoot(sourceRoot) {
1178
1469
  return path.resolve(sourceRoot ?? process.cwd(), ".canopy-dev");
1179
1470
  }
1180
- getContentRoot(sourceRoot) {
1181
- return path.resolve(sourceRoot ?? process.cwd(), "content");
1471
+ getContentRoot(contentRoot, sourceRoot) {
1472
+ return path.resolve(sourceRoot ?? process.cwd(), contentRoot);
1182
1473
  }
1183
1474
  getContentBranchesRoot(sourceRoot) {
1184
1475
  return path.join(this.getWorkspaceRoot(sourceRoot), "content-branches");
@@ -1208,8 +1499,7 @@ var DevStrategy = class extends DevClientSafeStrategy {
1208
1499
  getSettingsBranchName(config) {
1209
1500
  if (config.settingsBranch)
1210
1501
  return config.settingsBranch;
1211
- const deploymentName = config.deploymentName ?? "local";
1212
- return `canopycms-settings-${deploymentName}`;
1502
+ return `canopycms-settings-${resolveDeploymentName(config, "local")}`;
1213
1503
  }
1214
1504
  getSettingsRoot(sourceRoot) {
1215
1505
  return path.join(this.getWorkspaceRoot(sourceRoot), "settings");
@@ -1245,6 +1535,9 @@ function operatingStrategy(mode) {
1245
1535
  return strategy;
1246
1536
  }
1247
1537
 
1538
+ // dist/operating-mode/index.js
1539
+ init_mode_env();
1540
+
1248
1541
  // dist/auth/plugin.js
1249
1542
  function assertAuthPluginAllowedForMode(plugin, mode) {
1250
1543
  if (mode === "prod" && plugin.verifiesCredentials !== true) {
@@ -1252,41 +1545,11 @@ function assertAuthPluginAllowedForMode(plugin, mode) {
1252
1545
  }
1253
1546
  }
1254
1547
 
1255
- // dist/utils/fs.js
1256
- import fs from "node:fs/promises";
1257
-
1258
- // dist/utils/error.js
1259
- function getErrorMessage(err) {
1260
- if (err instanceof Error) {
1261
- return err.message;
1262
- }
1263
- if (typeof err === "string") {
1264
- return err;
1265
- }
1266
- return String(err);
1267
- }
1268
- function isNodeError(err) {
1269
- return err instanceof Error && "code" in err;
1270
- }
1271
- function isNotFoundError(err) {
1272
- return isNodeError(err) && err.code === "ENOENT";
1273
- }
1274
-
1275
- // dist/utils/fs.js
1276
- async function filePathExists(filePath) {
1277
- try {
1278
- await fs.stat(filePath);
1279
- return true;
1280
- } catch (err) {
1281
- if (isNotFoundError(err))
1282
- return false;
1283
- throw err;
1284
- }
1285
- }
1286
-
1287
1548
  // dist/cli/init.js
1549
+ init_fs();
1550
+ init_error();
1288
1551
  async function writeFile(filePath, content, options) {
1289
- const relativePath = path6.relative(process.cwd(), filePath);
1552
+ const relativePath = path7.relative(process.cwd(), filePath);
1290
1553
  if (await filePathExists(filePath)) {
1291
1554
  if (options.force) {
1292
1555
  } else if (options.nonInteractive) {
@@ -1303,8 +1566,8 @@ async function writeFile(filePath, content, options) {
1303
1566
  }
1304
1567
  }
1305
1568
  }
1306
- await fs5.mkdir(path6.dirname(filePath), { recursive: true });
1307
- await fs5.writeFile(filePath, content, "utf-8");
1569
+ await fs6.mkdir(path7.dirname(filePath), { recursive: true });
1570
+ await fs6.writeFile(filePath, content, "utf-8");
1308
1571
  p.log.success(`created: ${relativePath}`);
1309
1572
  return true;
1310
1573
  }
@@ -1356,24 +1619,24 @@ async function init(options) {
1356
1619
  }
1357
1620
  const serverPageExt = staticBuild ? "page.server.tsx" : "page.tsx";
1358
1621
  const serverRouteExt = staticBuild ? "route.server.ts" : "route.ts";
1359
- await writeFile(path6.join(projectDir, "canopycms.config.ts"), await canopyCmsConfig2({ mode, staticBuild }), writeOpts);
1360
- await writeFile(path6.join(projectDir, appDir, "lib/canopy.ts"), await canopyContext2({ configImport: configImportPath(appDir, 1), authProvider }), writeOpts);
1361
- await writeFile(path6.join(projectDir, appDir, "schemas.ts"), await schemasTemplate2(), writeOpts);
1362
- await writeFile(path6.join(projectDir, appDir, `api/canopycms/[...canopycms]/${serverRouteExt}`), await apiRoute2({
1622
+ await writeFile(path7.join(projectDir, "canopycms.config.ts"), await canopyCmsConfig2({ mode, staticBuild }), writeOpts);
1623
+ await writeFile(path7.join(projectDir, appDir, "lib/canopy.ts"), await canopyContext2({ configImport: configImportPath(appDir, 1), authProvider }), writeOpts);
1624
+ await writeFile(path7.join(projectDir, appDir, "schemas.ts"), await schemasTemplate2(), writeOpts);
1625
+ await writeFile(path7.join(projectDir, appDir, `api/canopycms/[...canopycms]/${serverRouteExt}`), await apiRoute2({
1363
1626
  canopyImport: "../".repeat(3) + "lib/canopy"
1364
1627
  }), writeOpts);
1365
- await writeFile(path6.join(projectDir, appDir, `edit/${serverPageExt}`), await editPage2({ configImport: configImportPath(appDir, 1), authProvider }), writeOpts);
1628
+ await writeFile(path7.join(projectDir, appDir, `edit/${serverPageExt}`), await editPage2({ configImport: configImportPath(appDir, 1), authProvider }), writeOpts);
1366
1629
  if (ai) {
1367
- await writeFile(path6.join(projectDir, appDir, "ai/config.ts"), await aiConfig2(), writeOpts);
1368
- await writeFile(path6.join(projectDir, appDir, `ai/[...path]/${serverRouteExt}`), await aiRoute2({ configImport: configImportPath(appDir, 2) }), writeOpts);
1630
+ await writeFile(path7.join(projectDir, appDir, "ai/config.ts"), await aiConfig2(), writeOpts);
1631
+ await writeFile(path7.join(projectDir, appDir, `ai/[...path]/${serverRouteExt}`), await aiRoute2({ configImport: configImportPath(appDir, 2) }), writeOpts);
1369
1632
  }
1370
- await writeFile(path6.join(projectDir, "next.config.ts"), await nextConfig2({ staticBuild }), writeOpts);
1371
- await writeFile(path6.join(projectDir, "middleware.ts"), await middleware2({ authProvider }), writeOpts);
1372
- const gitignorePath = path6.join(projectDir, ".gitignore");
1633
+ await writeFile(path7.join(projectDir, "next.config.ts"), await nextConfig2({ staticBuild }), writeOpts);
1634
+ await writeFile(path7.join(projectDir, "middleware.ts"), await middleware2({ authProvider }), writeOpts);
1635
+ const gitignorePath = path7.join(projectDir, ".gitignore");
1373
1636
  if (await filePathExists(gitignorePath)) {
1374
- const content = await fs5.readFile(gitignorePath, "utf-8");
1637
+ const content = await fs6.readFile(gitignorePath, "utf-8");
1375
1638
  if (!content.includes(".canopy-dev")) {
1376
- await fs5.appendFile(gitignorePath, "\n# CanopyCMS\n.canopy-dev/\n");
1639
+ await fs6.appendFile(gitignorePath, "\n# CanopyCMS\n.canopy-dev/\n");
1377
1640
  p.log.success("updated: .gitignore");
1378
1641
  }
1379
1642
  }
@@ -1398,34 +1661,78 @@ async function init(options) {
1398
1661
  async function initDeployAws(options) {
1399
1662
  const { projectDir, force, nonInteractive } = options;
1400
1663
  const writeOpts = { force, nonInteractive };
1401
- const { dockerfileCms: dockerfileCms2, dockerignore: dockerignore2, githubWorkflowCms: githubWorkflowCms2 } = await Promise.resolve().then(() => (init_templates(), templates_exports));
1664
+ const { dockerfileCms: dockerfileCms2, dockerignore: dockerignore2, githubWorkflowCms: githubWorkflowCms2, cdkJson: cdkJson2, cdkApp: cdkApp2, cmsStack: cmsStack2 } = await Promise.resolve().then(() => (init_templates(), templates_exports));
1665
+ const { detectPackageManager: detectPackageManager2, detectDefaultBranch: detectDefaultBranch2, detectGitHubRepo: detectGitHubRepo2, commandsFor: commandsFor2, missingCdkDependencies: missingCdkDependencies2, CDK_DEPENDENCIES: CDK_DEPENDENCIES2 } = await Promise.resolve().then(() => (init_project_detect(), project_detect_exports));
1402
1666
  p.intro("CanopyCMS init-deploy aws");
1403
- await writeFile(path6.join(projectDir, "Dockerfile.cms"), await dockerfileCms2(), writeOpts);
1404
- const dockerignoreWritten = await writeFile(path6.join(projectDir, ".dockerignore"), await dockerignore2(), writeOpts);
1667
+ const packageManager = await detectPackageManager2(projectDir);
1668
+ const pm = commandsFor2(packageManager);
1669
+ const defaultBranch = await detectDefaultBranch2(projectDir);
1670
+ const repo = await detectGitHubRepo2(projectDir);
1671
+ await writeFile(path7.join(projectDir, "Dockerfile.cms"), await dockerfileCms2({ copy: pm.dockerCopy, install: pm.dockerInstall, build: pm.build }), writeOpts);
1672
+ const dockerignoreWritten = await writeFile(path7.join(projectDir, ".dockerignore"), await dockerignore2(), writeOpts);
1405
1673
  if (!dockerignoreWritten) {
1406
- p.log.warn("Existing .dockerignore kept \u2014 verify it excludes .env* (secrets would otherwise enter the build context) and does NOT exclude vendor/ (needed for `npm ci` with file: deps).");
1674
+ p.log.warn("Existing .dockerignore kept \u2014 verify it excludes .env* (secrets would otherwise enter the build context) and does NOT exclude vendor/ (needed by the Dockerfile.cms install step with file: deps).");
1407
1675
  }
1408
- await writeFile(path6.join(projectDir, ".github/workflows/deploy-cms.yml"), await githubWorkflowCms2(), writeOpts);
1409
- const nextConfigPath = path6.join(projectDir, "next.config.ts");
1410
- const nextConfigMjsPath = path6.join(projectDir, "next.config.mjs");
1676
+ await writeFile(path7.join(projectDir, ".github/workflows/deploy-cms.yml"), await githubWorkflowCms2({
1677
+ defaultBranch,
1678
+ lockfile: pm.lockfile,
1679
+ ciInstall: pm.ciInstall,
1680
+ addDev: pm.addDev
1681
+ }), writeOpts);
1682
+ const cdkJsonPath = path7.join(projectDir, "cdk.json");
1683
+ const existingCdkJson = await filePathExists(cdkJsonPath) ? await fs6.readFile(cdkJsonPath, "utf-8") : null;
1684
+ const cdkJsonWritten = await writeFile(cdkJsonPath, await cdkJson2(), writeOpts);
1685
+ await writeFile(path7.join(projectDir, "infrastructure/bin/app.ts"), await cdkApp2({
1686
+ githubOwner: repo?.owner ?? "your-org",
1687
+ githubRepo: repo?.repo ?? "your-docs-site"
1688
+ }), writeOpts);
1689
+ await writeFile(path7.join(projectDir, "infrastructure/lib/cms-stack.ts"), await cmsStack2(), writeOpts);
1690
+ if (!cdkJsonWritten && existingCdkJson && !existingCdkJson.includes("infrastructure/bin/app.ts")) {
1691
+ p.log.warn("Existing cdk.json kept, and it does not point at infrastructure/bin/app.ts \u2014 the scaffolded CDK app will not be deployed. Either wire CmsStack into your own app entry point, or re-run with --force to replace cdk.json.");
1692
+ }
1693
+ const nextConfigPath = path7.join(projectDir, "next.config.ts");
1694
+ const nextConfigMjsPath = path7.join(projectDir, "next.config.mjs");
1411
1695
  const configPath = await filePathExists(nextConfigPath) ? nextConfigPath : await filePathExists(nextConfigMjsPath) ? nextConfigMjsPath : null;
1412
1696
  if (configPath) {
1413
- const content = await fs5.readFile(configPath, "utf-8");
1697
+ const content = await fs6.readFile(configPath, "utf-8");
1414
1698
  if (!content.includes("CANOPY_BUILD")) {
1415
1699
  p.note([
1416
- `Add dual build support to ${path6.basename(configPath)}:`,
1700
+ `Add dual build support to ${path7.basename(configPath)}:`,
1417
1701
  "",
1418
1702
  " output: process.env.CANOPY_BUILD === 'cms' ? 'standalone' : 'export',"
1419
1703
  ].join("\n"), "Manual step");
1420
1704
  }
1421
1705
  }
1422
- p.note("CDK constructs are available via the canopycms-cdk package.\nSee the deployment plan for CDK stack setup.", "AWS deployment");
1706
+ if (packageManager === "yarn" || packageManager === "yarn-berry") {
1707
+ p.log.warn(`Yarn detected (${packageManager === "yarn-berry" ? "Berry" : "classic"}). The generated install lines are a best effort and are not exercised by CanopyCMS tests \u2014 review them in Dockerfile.cms and .github/workflows/deploy-cms.yml.` + (packageManager === "yarn-berry" ? " Berry additionally requires nodeLinker: node-modules; PnP is incompatible with Next.js standalone output, which the CMS image's runner stage copies." : ""));
1708
+ }
1709
+ const missing = await missingCdkDependencies2(projectDir);
1710
+ if (missing.length > 0) {
1711
+ p.log.warn(`Not installed: ${missing.join(", ")}. cdk.json runs \`node --import tsx infrastructure/bin/app.ts\`, so the deploy fails without them:
1712
+ ${pm.addDev} ${CDK_DEPENDENCIES2.join(" ")}`);
1713
+ }
1714
+ p.note([
1715
+ "1. Install the CDK dependencies (if you have not already):",
1716
+ ` ${pm.addDev} ${CDK_DEPENDENCIES2.join(" ")}`,
1717
+ "",
1718
+ "2. Fill in infrastructure/lib/cms-stack.ts and infrastructure/bin/app.ts",
1719
+ ` (worker repo currently set to ${repo ? `${repo.owner}/${repo.repo}` : "your-org/your-docs-site"})`,
1720
+ "",
1721
+ "3. Bootstrap CDK in the target account/region: cdk bootstrap",
1722
+ "",
1723
+ "4. Set the repository secrets and variables listed at the top of",
1724
+ " .github/workflows/deploy-cms.yml \u2014 the deploy fails at synth without them.",
1725
+ "",
1726
+ `Deploys trigger on pushes to '${defaultBranch}'; edit the workflow to change that.`,
1727
+ "",
1728
+ "Full walkthrough: docs/deploying-to-aws.md"
1729
+ ].join("\n"), "AWS deployment");
1423
1730
  p.outro("Done!");
1424
1731
  }
1425
1732
  async function detectMode(projectDir) {
1426
- const cfgPath = path6.join(projectDir, "canopycms.config.ts");
1733
+ const cfgPath = path7.join(projectDir, "canopycms.config.ts");
1427
1734
  try {
1428
- await fs5.stat(cfgPath);
1735
+ await fs6.stat(cfgPath);
1429
1736
  } catch (err) {
1430
1737
  if (isNotFoundError(err))
1431
1738
  return "dev";
@@ -1456,7 +1763,7 @@ async function workerRunOnce(options) {
1456
1763
  assertAuthPluginAllowedForMode(options.authPlugin, mode);
1457
1764
  }
1458
1765
  const taskDir = getTaskQueueDir2({ mode });
1459
- const cachePath = process.env.CANOPY_AUTH_CACHE_PATH ?? path6.join(operatingStrategy(mode).getWorkspaceRoot(options.projectDir), ".cache");
1766
+ const cachePath = process.env.CANOPY_AUTH_CACHE_PATH ?? path7.join(operatingStrategy(mode).getWorkspaceRoot(options.projectDir), ".cache");
1460
1767
  let refreshAuthCache;
1461
1768
  const authMode = process.env.CANOPY_AUTH_MODE || "dev";
1462
1769
  if (options.authPlugin?.createCacheRefresher) {