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
@@ -1 +1 @@
1
- {"version":3,"file":"ReferenceField.js","sourceRoot":"","sources":["../../../src/editor/fields/ReferenceField.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ReferenceField.js","sourceRoot":"","sources":["../../../src/editor/fields/ReferenceField.tsx"],"names":[],"mappings":"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"}
@@ -27,9 +27,25 @@ import { type MockApiClient } from '../../../api/__test__/mock-client';
27
27
  */
28
28
  export declare function setupMockApiClient(): Promise<MockApiClient>;
29
29
  /**
30
- * Create a wrapper component that provides the mock API client via context.
31
- *
32
- * Use this with renderHook to provide the ApiClientContext:
30
+ * Create a wrapper component that provides the mock API client via context,
31
+ * plus an SWR cache isolated to this wrapper instance.
32
+ *
33
+ * The isolated cache (`provider: () => new Map()`) matters: several hooks
34
+ * (useBranchManager, useEntryManager, useCommentSystem) now read through
35
+ * SWR-backed data hooks keyed by resource/branch (e.g. "canopy:branches",
36
+ * "canopy:entries:main"). Without a fresh cache per wrapper, tests across
37
+ * this file (and other hook test files in the same worker) would all share
38
+ * SWR's real global cache and collide on those keys -- a later test could
39
+ * see an earlier test's mocked response instead of its own. `dedupingInterval`
40
+ * matches the production `SWRProvider` (2000ms) rather than 0: the manager
41
+ * hooks' explicit reload functions (loadBranches, loadComments,
42
+ * refreshEntries) always issue a fresh, un-deduped fetch regardless of this
43
+ * value -- see their doc comments -- so a non-zero interval here doesn't
44
+ * risk masking a duplicate-request bug, and it's needed for dedup
45
+ * regression tests that mount under React.StrictMode to actually observe
46
+ * SWR's coalescing behavior.
47
+ *
48
+ * Use this with renderHook to provide both contexts:
33
49
  *
34
50
  * @example
35
51
  * ```ts
@@ -41,6 +57,25 @@ export declare function setupMockApiClient(): Promise<MockApiClient>;
41
57
  export declare function createApiClientWrapper(mockClient: MockApiClient): ({ children }: {
42
58
  children: React.ReactNode;
43
59
  }) => import("react/jsx-runtime").JSX.Element;
60
+ /**
61
+ * Like `createApiClientWrapper`, but the tree is additionally wrapped in
62
+ * `React.StrictMode`, which double-invokes effects (mount -> cleanup ->
63
+ * remount) in dev. Use this for dedup regression tests: without SWR's
64
+ * request deduplication, each fetch-on-load hook (useBranchManager,
65
+ * useEntryManager, useCommentSystem) fired its request twice under Strict
66
+ * Mode -- exactly the duplicate-request bug this SWR migration fixes.
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * const mockClient = await setupMockApiClient()
71
+ * const wrapper = createStrictModeApiClientWrapper(mockClient)
72
+ * const { result } = renderHook(() => useSomeHook(), { wrapper })
73
+ * // assert the mock fetch was called exactly once, not twice
74
+ * ```
75
+ */
76
+ export declare function createStrictModeApiClientWrapper(mockClient: MockApiClient): ({ children }: {
77
+ children: React.ReactNode;
78
+ }) => import("react/jsx-runtime").JSX.Element;
44
79
  /**
45
80
  * Setup mock window.location for tests that need to manipulate browser location.
46
81
  *
@@ -1 +1 @@
1
- {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../../../src/editor/hooks/__test__/test-utils.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,EAAE,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAA;AAG3F;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,aAAa,CAAC,CAKjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,aAAa,IACtC,cAAc;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,6CAGpE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,cAYjF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,KAAK,CAAC,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAa,GAiBlE,MAAM,CAAC,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG;IACtF,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CACF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAA;CAClB;;;;GAcP"}
1
+ {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../../../src/editor/hooks/__test__/test-utils.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,EAAE,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAEtC,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAA;AAG3F;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,aAAa,CAAC,CAKjE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,aAAa,IACtC,cAAc;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,6CAOpE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gCAAgC,CAAC,UAAU,EAAE,aAAa,IAE1C,cAAc;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,6CAO1E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,cAYjF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,KAAK,CAAC,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAa,GAiBlE,MAAM,CAAC,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG;IACtF,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CACF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAA;CAClB;;;;GAcP"}
@@ -1,5 +1,13 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Shared test utilities for hook tests.
4
+ *
5
+ * This file provides common setup patterns and helpers to reduce duplication
6
+ * across hook test files.
7
+ */
8
+ import React from 'react';
2
9
  import { vi } from 'vitest';
10
+ import { SWRConfig } from 'swr';
3
11
  import { createMockApiClient } from '../../../api/__test__/mock-client.js';
4
12
  import { ApiClientProvider } from '../../context/index.js';
5
13
  /**
@@ -27,9 +35,25 @@ export async function setupMockApiClient() {
27
35
  return mockClient;
28
36
  }
29
37
  /**
30
- * Create a wrapper component that provides the mock API client via context.
31
- *
32
- * Use this with renderHook to provide the ApiClientContext:
38
+ * Create a wrapper component that provides the mock API client via context,
39
+ * plus an SWR cache isolated to this wrapper instance.
40
+ *
41
+ * The isolated cache (`provider: () => new Map()`) matters: several hooks
42
+ * (useBranchManager, useEntryManager, useCommentSystem) now read through
43
+ * SWR-backed data hooks keyed by resource/branch (e.g. "canopy:branches",
44
+ * "canopy:entries:main"). Without a fresh cache per wrapper, tests across
45
+ * this file (and other hook test files in the same worker) would all share
46
+ * SWR's real global cache and collide on those keys -- a later test could
47
+ * see an earlier test's mocked response instead of its own. `dedupingInterval`
48
+ * matches the production `SWRProvider` (2000ms) rather than 0: the manager
49
+ * hooks' explicit reload functions (loadBranches, loadComments,
50
+ * refreshEntries) always issue a fresh, un-deduped fetch regardless of this
51
+ * value -- see their doc comments -- so a non-zero interval here doesn't
52
+ * risk masking a duplicate-request bug, and it's needed for dedup
53
+ * regression tests that mount under React.StrictMode to actually observe
54
+ * SWR's coalescing behavior.
55
+ *
56
+ * Use this with renderHook to provide both contexts:
33
57
  *
34
58
  * @example
35
59
  * ```ts
@@ -40,7 +64,29 @@ export async function setupMockApiClient() {
40
64
  */
41
65
  export function createApiClientWrapper(mockClient) {
42
66
  return function Wrapper({ children }) {
43
- return _jsx(ApiClientProvider, { client: mockClient, children: children });
67
+ return (_jsx(SWRConfig, { value: { provider: () => new Map(), dedupingInterval: 2000 }, children: _jsx(ApiClientProvider, { client: mockClient, children: children }) }));
68
+ };
69
+ }
70
+ /**
71
+ * Like `createApiClientWrapper`, but the tree is additionally wrapped in
72
+ * `React.StrictMode`, which double-invokes effects (mount -> cleanup ->
73
+ * remount) in dev. Use this for dedup regression tests: without SWR's
74
+ * request deduplication, each fetch-on-load hook (useBranchManager,
75
+ * useEntryManager, useCommentSystem) fired its request twice under Strict
76
+ * Mode -- exactly the duplicate-request bug this SWR migration fixes.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * const mockClient = await setupMockApiClient()
81
+ * const wrapper = createStrictModeApiClientWrapper(mockClient)
82
+ * const { result } = renderHook(() => useSomeHook(), { wrapper })
83
+ * // assert the mock fetch was called exactly once, not twice
84
+ * ```
85
+ */
86
+ export function createStrictModeApiClientWrapper(mockClient) {
87
+ const Inner = createApiClientWrapper(mockClient);
88
+ return function StrictWrapper({ children }) {
89
+ return (_jsx(React.StrictMode, { children: _jsx(Inner, { children: children }) }));
44
90
  };
45
91
  }
46
92
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../../../../src/editor/hooks/__test__/test-utils.tsx"],"names":[],"mappings":";AAQA,OAAO,EAAE,EAAE,EAAa,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAE,mBAAmB,EAAsB,MAAM,mCAAmC,CAAA;AAC3F,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEjD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAA;IACxD,MAAM,UAAU,GAAG,mBAAmB,EAAE,CAAA;IACxC,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,eAAe,CAAC,UAAiB,CAAC,CAAA;IAC7D,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAAyB;IAC9D,OAAO,SAAS,OAAO,CAAC,EAAE,QAAQ,EAAiC;QACjE,OAAO,KAAC,iBAAiB,IAAC,MAAM,EAAE,UAAiB,YAAG,QAAQ,GAAqB,CAAA;IACrF,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAA8C,EAAE;IAChF,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAoB,CAAA;IAEpD,OAAQ,MAAc,CAAC,QAAQ,CAC9B;IAAC,MAAc,CAAC,QAAQ,GAAG;QAC1B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,mBAAmB;QACzC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;KAC7B,CAAA;IAED,OAAO,GAAG,EAAE;QACV,CAAC;QAAC,MAAc,CAAC,QAAQ,GAAG,gBAAgB,CAAA;IAC9C,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;IAChC,MAAM,CAAC,OAAO,CAAC,YAAY,GAAG,gBAAgB,CAAA;IAC9C,OAAO,gBAAgB,CAAA;AACzB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAA8D,CAAC,OAAO,CAAC;IAEvE,MAAM,KAAK,GAAQ,EAAE,CAAA;IAErB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACxE,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACvC,CAAC;YAAC,GAAW,EAAE,WAAW,EAAE,CAAA;QAC9B,CAAC;IACH,CAAC,CAAA;IAED,OAAO;QACL,GAAG,KAAK;QACR,OAAO;KAGR,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,UAGI,EAAE;IAEN,MAAM,UAAU,GAAG,MAAM,kBAAkB,EAAE,CAAA;IAE7C,MAAM,eAAe,GAAG,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC3D,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,KAAK,KAAK,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;IAEnF,OAAO;QACL,UAAU;QACV,WAAW;QACX,OAAO,EAAE,GAAG,EAAE;YACZ,eAAe,EAAE,CAAA;QACnB,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../../../../src/editor/hooks/__test__/test-utils.tsx"],"names":[],"mappings":"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"}
@@ -1,8 +1,11 @@
1
1
  export * from './useEditorLayout';
2
2
  export { useBranchManager, type UseBranchManagerOptions } from './useBranchManager';
3
- export { useEntryManager } from './useEntryManager';
3
+ export { useEntryManager, listAllEntries } from './useEntryManager';
4
4
  export * from './useDraftManager';
5
5
  export { useCommentSystem } from './useCommentSystem';
6
+ export { useBranchesData, fetchBranches, BRANCHES_KEY, type BranchesData } from './useBranchesData';
7
+ export { fetchEntriesAndSchema, entriesKey, type EntriesData, type FetchEntriesParams, } from './useEntriesData';
8
+ export { useCommentsData, fetchComments, commentsKey, type CommentsData } from './useCommentsData';
6
9
  export { useGroupManager } from './useGroupManager';
7
10
  export { usePermissionManager } from './usePermissionManager';
8
11
  export { useBranchActions } from './useBranchActions';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/editor/hooks/index.ts"],"names":[],"mappings":"AAIA,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AACnF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAC5E,OAAO,EACL,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,KAAK,4BAA4B,GAClC,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/editor/hooks/index.ts"],"names":[],"mappings":"AAIA,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AACnF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACnE,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACnG,OAAO,EACL,qBAAqB,EACrB,UAAU,EACV,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAC5E,OAAO,EACL,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,KAAK,4BAA4B,GAClC,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAA"}
@@ -3,9 +3,12 @@
3
3
  // Note: resetApiClient functions are not exported - they're test-only utilities
4
4
  export * from './useEditorLayout.js';
5
5
  export { useBranchManager } from './useBranchManager.js';
6
- export { useEntryManager } from './useEntryManager.js';
6
+ export { useEntryManager, listAllEntries } from './useEntryManager.js';
7
7
  export * from './useDraftManager.js';
8
8
  export { useCommentSystem } from './useCommentSystem.js';
9
+ export { useBranchesData, fetchBranches, BRANCHES_KEY } from './useBranchesData.js';
10
+ export { fetchEntriesAndSchema, entriesKey, } from './useEntriesData.js';
11
+ export { useCommentsData, fetchComments, commentsKey } from './useCommentsData.js';
9
12
  export { useGroupManager } from './useGroupManager.js';
10
13
  export { usePermissionManager } from './usePermissionManager.js';
11
14
  export { useBranchActions } from './useBranchActions.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/editor/hooks/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,mCAAmC;AACnC,gFAAgF;AAEhF,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,gBAAgB,EAAgC,MAAM,oBAAoB,CAAA;AACnF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,cAAc,EAA6B,MAAM,kBAAkB,CAAA;AAC5E,OAAO,EACL,sBAAsB,GAGvB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,gBAAgB,GAGjB,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/editor/hooks/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,mCAAmC;AACnC,gFAAgF;AAEhF,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,gBAAgB,EAAgC,MAAM,oBAAoB,CAAA;AACnF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACnE,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAqB,MAAM,mBAAmB,CAAA;AACnG,OAAO,EACL,qBAAqB,EACrB,UAAU,GAGX,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAqB,MAAM,mBAAmB,CAAA;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,cAAc,EAA6B,MAAM,kBAAkB,CAAA;AAC5E,OAAO,EACL,sBAAsB,GAGvB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,gBAAgB,GAGjB,MAAM,oBAAoB,CAAA"}
@@ -20,6 +20,8 @@ export interface BranchSummary {
20
20
  mergedAt?: string;
21
21
  /** Sync status for async GitHub operations (used when Lambda has no internet) */
22
22
  syncStatus?: SyncStatus;
23
+ /** Short, sanitized reason the last GitHub sync task failed (set alongside syncStatus: 'sync-failed') */
24
+ syncFailureReason?: string;
23
25
  /** Whether this branch has unresolved merge conflicts with the base branch */
24
26
  conflictStatus?: ConflictStatus;
25
27
  /** ContentIds of entries where --theirs was applied during rebase; cleared on clean rebase */
@@ -27,6 +29,25 @@ export interface BranchSummary {
27
29
  commentCount: number;
28
30
  isProtected: boolean;
29
31
  readOnly: boolean;
32
+ /**
33
+ * Server-computed: content writes are rejected, because the branch is the
34
+ * read-only base branch OR its status is past 'editing'. `readOnly` still
35
+ * says WHICH, for banner copy.
36
+ */
37
+ writeBlocked: boolean;
38
+ /**
39
+ * Server-computed compound submit rule: true when the branch can never be
40
+ * submitted for review, for EITHER reason -- it is the protected base
41
+ * branch, or its workflow status has moved past 'editing'. Mirrors
42
+ * `writeBlocked`'s shape (a base-branch half + a status half, combined),
43
+ * except this one is built from `isProtected`/`submitBlocked` (both modes)
44
+ * rather than `readOnly` (prod-only) -- see
45
+ * `BranchWriteProtection.submitBlockedIncludingStatus` for why those two
46
+ * compounds are genuinely different predicates, not duplicates of each
47
+ * other. Consumed as-is by `BranchManager.tsx`'s `canSubmit`; do not
48
+ * re-derive the status/protection halves client-side.
49
+ */
50
+ submitBlocked: boolean;
30
51
  }
31
52
  export interface UseBranchManagerOptions {
32
53
  /**
@@ -52,7 +73,6 @@ export interface UseBranchManagerReturn {
52
73
  branches: BranchListItem[];
53
74
  branchSummaries: BranchSummary[];
54
75
  currentBranch: BranchListItem | undefined;
55
- branchStatus: string;
56
76
  handleSubmit: (branchName: string) => Promise<void>;
57
77
  handleWithdraw: (branchName: string) => Promise<void>;
58
78
  handleRequestChanges: (branchName: string) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"useBranchManager.d.ts","sourceRoot":"","sources":["../../../src/editor/hooks/useBranchManager.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAoDtD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;QAC3B,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;KAC7B,CAAA;IACD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iFAAiF;IACjF,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,8FAA8F;IAC9F,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,aAAa,EAAE,MAAM,CAAA;IAErB;;OAEG;IACH,aAAa,EAAE,aAAa,CAAA;IAE5B;;OAEG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAEhC;;OAEG;IACH,QAAQ,EAAE,aAAa,EAAE,CAAA;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,eAAe,EAAE,aAAa,EAAE,CAAA;IAChC,aAAa,EAAE,cAAc,GAAG,SAAS,CAAA;IACzC,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrD,oBAAoB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3D,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD,sBAAsB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3C,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,sBAAsB,CA0NzF"}
1
+ {"version":3,"file":"useBranchManager.d.ts","sourceRoot":"","sources":["../../../src/editor/hooks/useBranchManager.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AA0HtD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;QAC3B,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;KAC7B,CAAA;IACD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iFAAiF;IACjF,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,yGAAyG;IACzG,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,8FAA8F;IAC9F,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,YAAY,EAAE,OAAO,CAAA;IACrB;;;;;;;;;;;OAWG;IACH,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,aAAa,EAAE,MAAM,CAAA;IAErB;;OAEG;IACH,aAAa,EAAE,aAAa,CAAA;IAE5B;;OAEG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAEhC;;OAEG;IACH,QAAQ,EAAE,aAAa,EAAE,CAAA;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,eAAe,EAAE,aAAa,EAAE,CAAA;IAChC,aAAa,EAAE,cAAc,GAAG,SAAS,CAAA;IACzC,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrD,oBAAoB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3D,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD,sBAAsB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3C,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,sBAAsB,CA4RzF"}
@@ -1,39 +1,104 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useEffect, useMemo, useState } from 'react';
4
+ import { useSWRConfig } from 'swr';
4
5
  import { Text } from '@mantine/core';
5
6
  import { modals } from '@mantine/modals';
6
7
  import { notifications } from '@mantine/notifications';
7
8
  import { useApiClient } from '../context/index.js';
9
+ import { BRANCHES_KEY, fetchBranches, useBranchesData } from './useBranchesData.js';
8
10
  // branch-name, NOT branch or the '../../paths' barrel: both of those pull
9
11
  // node:fs/promises + node:path at the top level (path RESOLUTION helpers),
10
12
  // which breaks adopters' production `next build` of the editor bundle.
11
13
  // paths/branch-name.ts is the dependency-free home of sanitizeBranchName.
12
14
  import { sanitizeBranchName } from '../../paths/branch-name.js';
15
+ /**
16
+ * Wire a confirm modal's exits so exactly ONE of {confirmed, dismissed} runs,
17
+ * whichever happens first.
18
+ *
19
+ * Neither Mantine callback is the "user declined" signal on its own, in
20
+ * opposite directions: `onCancel` does NOT fire for an Escape or overlay
21
+ * dismissal (so a caller waiting on it alone waits forever), while `onClose`
22
+ * fires for EVERY exit including a confirm -- Mantine closes the modal right
23
+ * after calling `onConfirm`, and does not await it, so a bare `onClose`
24
+ * handler would settle the caller's promise before the confirmed work had
25
+ * even run. Claiming the first exit resolves both.
26
+ */
27
+ const confirmModalHandlers = (onConfirm, onDismiss) => {
28
+ let settled = false;
29
+ const claim = () => {
30
+ if (settled)
31
+ return false;
32
+ settled = true;
33
+ return true;
34
+ };
35
+ return {
36
+ onConfirm: () => {
37
+ // Not awaited by Mantine either way; the handlers below own their own
38
+ // error reporting, so nothing here can reject.
39
+ if (claim())
40
+ void onConfirm();
41
+ },
42
+ onCancel: () => {
43
+ if (claim())
44
+ onDismiss();
45
+ },
46
+ onClose: () => {
47
+ if (claim())
48
+ onDismiss();
49
+ },
50
+ };
51
+ };
13
52
  /**
14
53
  * Helper function to show confirmation modal for branch submit action.
15
54
  */
16
- const showSubmitConfirmation = (branchName, onConfirm, onCancel) => {
55
+ const showSubmitConfirmation = (branchName, onConfirm, onDismiss) => {
17
56
  modals.openConfirmModal({
18
57
  title: 'Submit Branch for Review',
19
58
  children: (_jsx(Text, { size: "sm", style: { whiteSpace: 'pre-line' }, children: `Are you sure you want to submit "${branchName}" for review?\n\nThis will:\n• Create a pull request for review\n• Change the branch status to "submitted"\n• Notify reviewers of pending changes` })),
20
59
  labels: { confirm: 'Submit Branch', cancel: 'Cancel' },
21
60
  confirmProps: { color: 'brand' },
22
- onCancel,
23
- onConfirm,
61
+ ...confirmModalHandlers(onConfirm, onDismiss),
24
62
  });
25
63
  };
26
64
  /**
27
65
  * Helper function to show confirmation modal for branch withdraw action.
28
66
  */
29
- const showWithdrawConfirmation = (branchName, onConfirm, onCancel) => {
67
+ const showWithdrawConfirmation = (branchName, onConfirm, onDismiss) => {
30
68
  modals.openConfirmModal({
31
69
  title: 'Withdraw Branch from Review',
32
70
  children: (_jsx(Text, { size: "sm", style: { whiteSpace: 'pre-line' }, children: `Are you sure you want to withdraw "${branchName}" from review?\n\nThis will:\n• Convert the pull request to a draft\n• Change the branch status back to "editing"\n• Remove from review queue` })),
33
71
  labels: { confirm: 'Withdraw Branch', cancel: 'Cancel' },
34
72
  confirmProps: { color: 'orange' },
35
- onCancel,
36
- onConfirm,
73
+ ...confirmModalHandlers(onConfirm, onDismiss),
74
+ });
75
+ };
76
+ /**
77
+ * Helper function to show confirmation modal for branch delete action.
78
+ *
79
+ * Unlike submit/withdraw (both reversible), delete is irreversible -- it
80
+ * unlinks branch.json, removes the clone, and removes the branch head from
81
+ * the local git mirror. Before this, `handleDelete` below called
82
+ * `apiClient.branches.delete` immediately on click with no confirmation
83
+ * anywhere in the chain (BranchManager.tsx's delete button calls `onDelete`
84
+ * directly), while submit and withdraw -- both reversible -- each went
85
+ * through this same `modals.openConfirmModal` pattern. This closes that gap;
86
+ * `color: 'red'` marks it as the destructive one, matching the button's own
87
+ * color in BranchManager.tsx.
88
+ */
89
+ const showDeleteConfirmation = (branchName, onConfirm, onDismiss) => {
90
+ modals.openConfirmModal({
91
+ title: 'Delete Branch',
92
+ children: (_jsx(Text, { size: "sm", style: { whiteSpace: 'pre-line' }, children: `Are you sure you want to delete "${branchName}"?\n\nThis will:\n• Permanently remove the branch and its clone\n• Discard any unsaved or unmerged changes\n\nThis cannot be undone.` })),
93
+ labels: { confirm: 'Delete Branch', cancel: 'Cancel' },
94
+ // data-testid is load-bearing, not decoration: the e2e helper
95
+ // (apps/test-app/e2e/fixtures/branch-page.ts's deleteBranch) already
96
+ // anticipated a delete confirmation and clicks
97
+ // [data-testid="confirm-delete-branch"] when it appears. Without this the
98
+ // modal opens, nothing dismisses it, and the branch never disappears --
99
+ // which is exactly how the e2e suite caught this confirmation being added.
100
+ confirmProps: { color: 'red', 'data-testid': 'confirm-delete-branch' },
101
+ ...confirmModalHandlers(onConfirm, onDismiss),
37
102
  });
38
103
  };
39
104
  /**
@@ -73,15 +138,51 @@ const showWithdrawConfirmation = (branchName, onConfirm, onCancel) => {
73
138
  */
74
139
  export function useBranchManager(options) {
75
140
  const apiClient = useApiClient();
141
+ const { mutate: globalMutate } = useSWRConfig();
76
142
  const [branchName, setBranchName] = useState(options.initialBranch);
77
- const [branches, setBranches] = useState([]);
143
+ // Automatic load, deduped by SWR (e.g. React Strict Mode's double effect
144
+ // invoke collapses to a single request). Not keyed by branchName -- the
145
+ // endpoint returns every branch regardless of which one is selected.
146
+ const { data: branchesData, error: branchesError, isValidating: branchesIsValidating, } = useBranchesData(apiClient);
147
+ const branches = useMemo(() => branchesData?.branches ?? [], [branchesData]);
148
+ // Adopt the server's default branch once data arrives, if nothing pinned one.
149
+ useEffect(() => {
150
+ if (!branchName && branchesData?.defaultBranch) {
151
+ setBranchName(branchesData.defaultBranch);
152
+ }
153
+ }, [branchesData, branchName]);
154
+ // Surface/clear the sticky error toast the same way loadBranches() used to.
155
+ useEffect(() => {
156
+ if (branchesError) {
157
+ console.error(branchesError);
158
+ const message = branchesError instanceof Error ? branchesError.message : 'Failed to load branches';
159
+ // Fixed id: retries update the existing toast instead of stacking; sticky
160
+ // because the editor cannot function without the branch list.
161
+ notifications.show({
162
+ id: 'canopy-branches-load-failed',
163
+ message,
164
+ color: 'red',
165
+ autoClose: false,
166
+ });
167
+ }
168
+ else if (branchesData) {
169
+ // A previous failure may have left the sticky error toast up; clear it
170
+ // now that loading succeeded (provisioning failures are often transient).
171
+ notifications.hide('canopy-branches-load-failed');
172
+ }
173
+ }, [branchesData, branchesError]);
174
+ // Mirrors the automatic load's in-flight state onto the shared busy flag,
175
+ // matching loadBranches()'s own setBusy bracket below for explicit reloads.
176
+ useEffect(() => {
177
+ options.setBusy(branchesIsValidating);
178
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- options is a new object every Editor.tsx render; only setBusy (a stable setState) matters here
179
+ }, [branchesIsValidating, options.setBusy]);
78
180
  // Exact match first; fall back to comparing sanitized forms so a legacy
79
181
  // deep-link carrying the raw, unsanitized name (e.g. "?branch=feature%2Fx"
80
182
  // from before a branch was created, or from an old bookmark) still
81
183
  // resolves to the branch the server actually persisted (e.g. "feature-x").
82
184
  const currentBranch = branches.find((b) => b.name === branchName) ??
83
185
  branches.find((b) => b.name === sanitizeBranchName(branchName));
84
- const branchStatus = currentBranch?.status ?? 'editing';
85
186
  // Compute branch summaries with comment counts
86
187
  const branchSummaries = useMemo(() => {
87
188
  return branches.map((b) => {
@@ -101,40 +202,44 @@ export function useBranchManager(options) {
101
202
  pullRequestState: b.pullRequestState,
102
203
  mergedAt: b.mergedAt,
103
204
  syncStatus: b.syncStatus,
205
+ syncFailureReason: b.syncFailureReason,
104
206
  conflictStatus: b.conflictStatus,
105
207
  conflictFiles: b.conflictFiles,
106
208
  commentCount: unresolvedCount,
107
- isProtected: b.isProtected ?? false,
209
+ // Fail CLOSED (`?? true`): these flags are optional on the wire (see
210
+ // BranchListItem's doc comment in api/branch.ts) so a version-skewed
211
+ // server, or a branches-list fetch that returned partial/legacy data,
212
+ // can omit them. `isProtected` gates `canDelete`/`isSystemBranch` in
213
+ // BranchManager.tsx and `submitBlocked` gates `canSubmit` -- both real
214
+ // mutating actions -- so "no answer" must render as "protected"/
215
+ // "blocked", the same fail-closed direction as `writeBlocked` below
216
+ // (see Editor.tsx's `branchContentLocked` for the full rationale, which
217
+ // applies identically here).
218
+ isProtected: b.isProtected ?? true,
219
+ // NOT flipped to `?? true`: `readOnly` only selects WHICH lock banner
220
+ // to show (base-branch read-only vs. status lock) once something is
221
+ // already known to be locked via `writeBlocked`/`submitBlocked` --
222
+ // it never gates a write by itself. Defaulting it true on missing data
223
+ // would mislabel a status lock as a base-branch lock (wrong banner
224
+ // copy), not under-lock anything, so `?? false` stays correct here.
108
225
  readOnly: b.readOnly ?? false,
226
+ writeBlocked: b.writeBlocked ?? true,
227
+ submitBlocked: b.submitBlocked ?? true,
109
228
  };
110
229
  });
111
230
  }, [branches, branchName, options.comments]);
231
+ // Explicit reload: always issues a fresh, independent fetch (raw call, not
232
+ // SWR's `mutate()` revalidate path) so callers requesting a reload right
233
+ // after mount aren't coalesced against the still-in-flight automatic load
234
+ // -- then writes the result into the shared cache so useBranchesData's
235
+ // bound hook (and anything else reading BRANCHES_KEY) picks it up.
236
+ // Side effects (default-branch adoption, error/success notifications) are
237
+ // driven by the effects above, which react to that same cache write.
112
238
  const loadBranches = async () => {
113
239
  options.setBusy(true);
114
240
  try {
115
- const result = await apiClient.branches.list();
116
- if (result.status === 404) {
117
- // No branch endpoint available; stay branchless. The branch dropdown
118
- // stays clickable so the user can open Manage Branches (which also
119
- // retries this load) and create or select a branch from there.
120
- setBranches([]);
121
- return;
122
- }
123
- if (!result.ok) {
124
- // Surface the server's reason (e.g. workspace provisioning failures
125
- // now arrive as 503s with the underlying git error)
126
- throw new Error(result.error ?? `Failed to load branches: ${result.status}`);
127
- }
128
- const list = result.data?.branches ?? [];
129
- setBranches(list);
130
- // A previous failure may have left the sticky error toast up; clear it
131
- // now that loading succeeded (provisioning failures are often transient).
132
- notifications.hide('canopy-branches-load-failed');
133
- // No branch pinned via URL or client config — adopt the server's
134
- // effective default (the detected active branch in dev mode).
135
- if (!branchName && result.data?.defaultBranch) {
136
- setBranchName(result.data.defaultBranch);
137
- }
241
+ const fresh = await fetchBranches(apiClient);
242
+ await globalMutate(BRANCHES_KEY, fresh, { revalidate: false });
138
243
  }
139
244
  catch (err) {
140
245
  console.error(err);
@@ -178,7 +283,13 @@ export function useBranchManager(options) {
178
283
  finally {
179
284
  options.setBusy(false);
180
285
  }
181
- }, () => reject(new Error('User cancelled submit')));
286
+ },
287
+ // Dismissal is not an error. Rejecting here meant clicking Cancel
288
+ // logged a console error at the only call site (Editor.tsx catches
289
+ // these into console.error), which is both noise and a trip hazard
290
+ // for the CI=1 stray-console gate. Settled once, by onCancel OR
291
+ // onClose, so an Escape/overlay dismissal can't leave this pending.
292
+ () => resolve());
182
293
  });
183
294
  };
184
295
  const handleWithdraw = async (branchNameToWithdraw) => {
@@ -204,7 +315,13 @@ export function useBranchManager(options) {
204
315
  finally {
205
316
  options.setBusy(false);
206
317
  }
207
- }, () => reject(new Error('User cancelled withdraw')));
318
+ },
319
+ // Dismissal is not an error. Rejecting here meant clicking Cancel
320
+ // logged a console error at the only call site (Editor.tsx catches
321
+ // these into console.error), which is both noise and a trip hazard
322
+ // for the CI=1 stray-console gate. Settled once, by onCancel OR
323
+ // onClose, so an Escape/overlay dismissal can't leave this pending.
324
+ () => resolve());
208
325
  });
209
326
  };
210
327
  const handleRequestChanges = async (branchNameForChanges) => {
@@ -226,33 +343,42 @@ export function useBranchManager(options) {
226
343
  }
227
344
  };
228
345
  const handleDelete = async (branchNameToDelete) => {
229
- options.setBusy(true);
230
- try {
231
- const result = await apiClient.branches.delete({
232
- branch: branchNameToDelete,
233
- });
234
- if (!result.ok) {
235
- throw new Error(result.error || 'Failed to delete branch');
236
- }
237
- notifications.show({ message: 'Branch deleted', color: 'green' });
238
- await loadBranches();
239
- }
240
- catch (err) {
241
- const message = err instanceof Error ? err.message : 'Failed to delete branch';
242
- notifications.show({ message, color: 'red' });
243
- }
244
- finally {
245
- options.setBusy(false);
246
- }
346
+ return new Promise((resolve) => {
347
+ showDeleteConfirmation(branchNameToDelete, async () => {
348
+ options.setBusy(true);
349
+ try {
350
+ const result = await apiClient.branches.delete({
351
+ branch: branchNameToDelete,
352
+ });
353
+ if (!result.ok) {
354
+ throw new Error(result.error || 'Failed to delete branch');
355
+ }
356
+ notifications.show({ message: 'Branch deleted', color: 'green' });
357
+ await loadBranches();
358
+ }
359
+ catch (err) {
360
+ const message = err instanceof Error ? err.message : 'Failed to delete branch';
361
+ notifications.show({ message, color: 'red' });
362
+ }
363
+ finally {
364
+ options.setBusy(false);
365
+ // Resolve regardless of API success/failure, matching the
366
+ // pre-confirmation behavior (errors were shown as a toast, not
367
+ // rethrown). Cancellation resolves too -- see below.
368
+ resolve();
369
+ }
370
+ },
371
+ // Dismissal is not an error. Rejecting here meant clicking Cancel
372
+ // logged a console error at the only call site (Editor.tsx catches
373
+ // these into console.error), which is both noise and a trip hazard
374
+ // for the CI=1 stray-console gate. Settled once, by onCancel OR
375
+ // onClose, so an Escape/overlay dismissal can't leave this pending.
376
+ () => resolve());
377
+ });
247
378
  };
248
379
  const handleReloadBranchData = async () => {
249
380
  await loadBranches();
250
381
  };
251
- // Load branches on mount and when branchName changes
252
- useEffect(() => {
253
- loadBranches().catch(console.error);
254
- // eslint-disable-next-line react-hooks/exhaustive-deps -- loadBranches would cause infinite loop
255
- }, [branchName]);
256
382
  // Sync branch to URL parameter
257
383
  useEffect(() => {
258
384
  if (typeof window === 'undefined')
@@ -272,7 +398,6 @@ export function useBranchManager(options) {
272
398
  branches,
273
399
  branchSummaries,
274
400
  currentBranch,
275
- branchStatus,
276
401
  handleSubmit,
277
402
  handleWithdraw,
278
403
  handleRequestChanges,