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.
- package/dist/ai/handler.js +1 -1
- package/dist/ai/handler.js.map +1 -1
- package/dist/ai/json-to-markdown.js +1 -2
- package/dist/ai/json-to-markdown.js.map +1 -1
- package/dist/api/__test__/mock-client.d.ts +5 -1
- package/dist/api/__test__/mock-client.d.ts.map +1 -1
- package/dist/api/__test__/mock-client.js +9 -2
- package/dist/api/__test__/mock-client.js.map +1 -1
- package/dist/api/admin-branch-health.d.ts +36 -1
- package/dist/api/admin-branch-health.d.ts.map +1 -1
- package/dist/api/admin-branch-health.js +176 -2
- package/dist/api/admin-branch-health.js.map +1 -1
- package/dist/api/admin.d.ts +8 -1
- package/dist/api/admin.d.ts.map +1 -1
- package/dist/api/admin.js.map +1 -1
- package/dist/api/assets.d.ts.map +1 -1
- package/dist/api/assets.js +36 -4
- package/dist/api/assets.js.map +1 -1
- package/dist/api/branch-status.d.ts.map +1 -1
- package/dist/api/branch-status.js +56 -0
- package/dist/api/branch-status.js.map +1 -1
- package/dist/api/branch-withdraw.d.ts.map +1 -1
- package/dist/api/branch-withdraw.js +14 -3
- package/dist/api/branch-withdraw.js.map +1 -1
- package/dist/api/branch.d.ts +31 -2
- package/dist/api/branch.d.ts.map +1 -1
- package/dist/api/branch.js +268 -15
- package/dist/api/branch.js.map +1 -1
- package/dist/api/client.d.ts +5 -1
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +6 -0
- package/dist/api/client.js.map +1 -1
- package/dist/api/comments.d.ts +2 -2
- package/dist/api/content.d.ts +11 -5
- package/dist/api/content.d.ts.map +1 -1
- package/dist/api/content.js +91 -10
- package/dist/api/content.js.map +1 -1
- package/dist/api/entries.d.ts +10 -0
- package/dist/api/entries.d.ts.map +1 -1
- package/dist/api/entries.js +51 -24
- package/dist/api/entries.js.map +1 -1
- package/dist/api/guards.d.ts.map +1 -1
- package/dist/api/guards.js +12 -5
- package/dist/api/guards.js.map +1 -1
- package/dist/api/permissions.d.ts +2 -2
- package/dist/api/permissions.d.ts.map +1 -1
- package/dist/api/permissions.js +51 -3
- package/dist/api/permissions.js.map +1 -1
- package/dist/api/reference-options.d.ts.map +1 -1
- package/dist/api/reference-options.js +10 -17
- package/dist/api/reference-options.js.map +1 -1
- package/dist/api/resolve-references.d.ts.map +1 -1
- package/dist/api/resolve-references.js +3 -1
- package/dist/api/resolve-references.js.map +1 -1
- package/dist/api/schema.d.ts +4 -4
- package/dist/api/schema.d.ts.map +1 -1
- package/dist/api/schema.js +16 -15
- package/dist/api/schema.js.map +1 -1
- package/dist/api/settings-helpers.d.ts.map +1 -1
- package/dist/api/settings-helpers.js +6 -5
- package/dist/api/settings-helpers.js.map +1 -1
- package/dist/assets/pipeline.d.ts +11 -2
- package/dist/assets/pipeline.d.ts.map +1 -1
- package/dist/assets/pipeline.js +114 -2
- package/dist/assets/pipeline.js.map +1 -1
- package/dist/assets/transform-directives.d.ts +18 -0
- package/dist/assets/transform-directives.d.ts.map +1 -1
- package/dist/assets/transform-directives.js +18 -0
- package/dist/assets/transform-directives.js.map +1 -1
- package/dist/assets/transform.d.ts.map +1 -1
- package/dist/assets/transform.js +20 -16
- package/dist/assets/transform.js.map +1 -1
- package/dist/auth/types.d.ts +29 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.d.ts.map +1 -1
- package/dist/authorization/index.js +1 -1
- package/dist/authorization/index.js.map +1 -1
- package/dist/authorization/protected-branch.d.ts +75 -0
- package/dist/authorization/protected-branch.d.ts.map +1 -1
- package/dist/authorization/protected-branch.js +39 -0
- package/dist/authorization/protected-branch.js.map +1 -1
- package/dist/branch-health.d.ts +13 -0
- package/dist/branch-health.d.ts.map +1 -1
- package/dist/branch-health.js +23 -0
- package/dist/branch-health.js.map +1 -1
- package/dist/branch-registry.d.ts.map +1 -1
- package/dist/branch-registry.js +5 -1
- package/dist/branch-registry.js.map +1 -1
- package/dist/branch-schema-cache.d.ts.map +1 -1
- package/dist/branch-schema-cache.js +9 -0
- package/dist/branch-schema-cache.js.map +1 -1
- package/dist/build/generate-ai-content.js +1 -1
- package/dist/build/generate-ai-content.js.map +1 -1
- package/dist/cli/cli.js +2215 -1280
- package/dist/cli/generate-ai-content.js +1158 -585
- package/dist/cli/init.d.ts +8 -2
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +459 -152
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/project-detect.d.ts +89 -0
- package/dist/cli/project-detect.d.ts.map +1 -0
- package/dist/cli/project-detect.js +240 -0
- package/dist/cli/project-detect.js.map +1 -0
- package/dist/cli/template-files/Dockerfile.cms.template +30 -7
- package/dist/cli/template-files/canopycms.config.ts.template +7 -0
- package/dist/cli/template-files/cdk-app.ts.template +82 -0
- package/dist/cli/template-files/cdk.json.template +9 -0
- package/dist/cli/template-files/cms-stack.ts.template +130 -0
- package/dist/cli/template-files/deploy-cms.yml.template +125 -13
- package/dist/cli/template-files/dockerignore.template +2 -1
- package/dist/cli/templates.d.ts +26 -2
- package/dist/cli/templates.d.ts.map +1 -1
- package/dist/cli/templates.js +36 -4
- package/dist/cli/templates.js.map +1 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/config/schemas/config.d.ts +2 -3
- package/dist/config/schemas/config.d.ts.map +1 -1
- package/dist/config/schemas/config.js +21 -1
- package/dist/config/schemas/config.js.map +1 -1
- package/dist/config/schemas/field.d.ts +15 -15
- package/dist/config/types.d.ts +2 -2
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +0 -1
- package/dist/config/types.js.map +1 -1
- package/dist/config/validation.d.ts +18 -0
- package/dist/config/validation.d.ts.map +1 -1
- package/dist/config/validation.js +36 -12
- package/dist/config/validation.js.map +1 -1
- package/dist/content-id-index.d.ts +97 -5
- package/dist/content-id-index.d.ts.map +1 -1
- package/dist/content-id-index.js +170 -18
- package/dist/content-id-index.js.map +1 -1
- package/dist/content-reader.js +1 -1
- package/dist/content-reader.js.map +1 -1
- package/dist/content-store.d.ts +92 -7
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +445 -259
- package/dist/content-store.js.map +1 -1
- package/dist/dev-content-watcher.d.ts.map +1 -1
- package/dist/dev-content-watcher.js +4 -1
- package/dist/dev-content-watcher.js.map +1 -1
- package/dist/editor/BranchManager.d.ts +15 -0
- package/dist/editor/BranchManager.d.ts.map +1 -1
- package/dist/editor/BranchManager.js +61 -15
- package/dist/editor/BranchManager.js.map +1 -1
- package/dist/editor/CanopyEditor.d.ts.map +1 -1
- package/dist/editor/CanopyEditor.js +3 -3
- package/dist/editor/CanopyEditor.js.map +1 -1
- package/dist/editor/CanopyEditorPage.d.ts +9 -1
- package/dist/editor/CanopyEditorPage.d.ts.map +1 -1
- package/dist/editor/CanopyEditorPage.js +9 -2
- package/dist/editor/CanopyEditorPage.js.map +1 -1
- package/dist/editor/Editor.d.ts +9 -1
- package/dist/editor/Editor.d.ts.map +1 -1
- package/dist/editor/Editor.js +156 -60
- package/dist/editor/Editor.js.map +1 -1
- package/dist/editor/FormRenderer.d.ts.map +1 -1
- package/dist/editor/FormRenderer.js +12 -0
- package/dist/editor/FormRenderer.js.map +1 -1
- package/dist/editor/admin/SystemHealthPanel.d.ts.map +1 -1
- package/dist/editor/admin/SystemHealthPanel.js +14 -9
- package/dist/editor/admin/SystemHealthPanel.js.map +1 -1
- package/dist/editor/components/EditorHeader.d.ts +6 -0
- package/dist/editor/components/EditorHeader.d.ts.map +1 -1
- package/dist/editor/components/EditorHeader.js +76 -23
- package/dist/editor/components/EditorHeader.js.map +1 -1
- package/dist/editor/components/EntryCreateModal.d.ts +9 -1
- package/dist/editor/components/EntryCreateModal.d.ts.map +1 -1
- package/dist/editor/components/EntryCreateModal.js +25 -7
- package/dist/editor/components/EntryCreateModal.js.map +1 -1
- package/dist/editor/context/SWRProvider.d.ts +31 -0
- package/dist/editor/context/SWRProvider.d.ts.map +1 -0
- package/dist/editor/context/SWRProvider.js +12 -0
- package/dist/editor/context/SWRProvider.js.map +1 -0
- package/dist/editor/context/index.d.ts +3 -0
- package/dist/editor/context/index.d.ts.map +1 -1
- package/dist/editor/context/index.js +3 -0
- package/dist/editor/context/index.js.map +1 -1
- package/dist/editor/editor-utils.d.ts.map +1 -1
- package/dist/editor/editor-utils.js +8 -2
- package/dist/editor/editor-utils.js.map +1 -1
- package/dist/editor/fields/DateTimeField.d.ts +46 -0
- package/dist/editor/fields/DateTimeField.d.ts.map +1 -0
- package/dist/editor/fields/DateTimeField.js +66 -0
- package/dist/editor/fields/DateTimeField.js.map +1 -0
- package/dist/editor/fields/ImageField.d.ts.map +1 -1
- package/dist/editor/fields/ImageField.js +27 -3
- package/dist/editor/fields/ImageField.js.map +1 -1
- package/dist/editor/fields/NumberField.d.ts +34 -0
- package/dist/editor/fields/NumberField.d.ts.map +1 -0
- package/dist/editor/fields/NumberField.js +53 -0
- package/dist/editor/fields/NumberField.js.map +1 -0
- package/dist/editor/fields/NumberListField.d.ts +25 -0
- package/dist/editor/fields/NumberListField.d.ts.map +1 -0
- package/dist/editor/fields/NumberListField.js +53 -0
- package/dist/editor/fields/NumberListField.js.map +1 -0
- package/dist/editor/fields/ReferenceField.d.ts.map +1 -1
- package/dist/editor/fields/ReferenceField.js +52 -31
- package/dist/editor/fields/ReferenceField.js.map +1 -1
- package/dist/editor/hooks/__test__/test-utils.d.ts +38 -3
- package/dist/editor/hooks/__test__/test-utils.d.ts.map +1 -1
- package/dist/editor/hooks/__test__/test-utils.js +50 -4
- package/dist/editor/hooks/__test__/test-utils.js.map +1 -1
- package/dist/editor/hooks/index.d.ts +4 -1
- package/dist/editor/hooks/index.d.ts.map +1 -1
- package/dist/editor/hooks/index.js +4 -1
- package/dist/editor/hooks/index.js.map +1 -1
- package/dist/editor/hooks/useBranchManager.d.ts +21 -1
- package/dist/editor/hooks/useBranchManager.d.ts.map +1 -1
- package/dist/editor/hooks/useBranchManager.js +183 -58
- package/dist/editor/hooks/useBranchManager.js.map +1 -1
- package/dist/editor/hooks/useBranchesData.d.ts +57 -0
- package/dist/editor/hooks/useBranchesData.d.ts.map +1 -0
- package/dist/editor/hooks/useBranchesData.js +69 -0
- package/dist/editor/hooks/useBranchesData.js.map +1 -0
- package/dist/editor/hooks/useCommentSystem.d.ts.map +1 -1
- package/dist/editor/hooks/useCommentSystem.js +24 -22
- package/dist/editor/hooks/useCommentSystem.js.map +1 -1
- package/dist/editor/hooks/useCommentsData.d.ts +29 -0
- package/dist/editor/hooks/useCommentsData.d.ts.map +1 -0
- package/dist/editor/hooks/useCommentsData.js +40 -0
- package/dist/editor/hooks/useCommentsData.js.map +1 -0
- package/dist/editor/hooks/useDraftManager.d.ts +8 -0
- package/dist/editor/hooks/useDraftManager.d.ts.map +1 -1
- package/dist/editor/hooks/useDraftManager.js +290 -36
- package/dist/editor/hooks/useDraftManager.js.map +1 -1
- package/dist/editor/hooks/useEntriesData.d.ts +35 -0
- package/dist/editor/hooks/useEntriesData.d.ts.map +1 -0
- package/dist/editor/hooks/useEntriesData.js +96 -0
- package/dist/editor/hooks/useEntriesData.js.map +1 -0
- package/dist/editor/hooks/useEntryManager.d.ts +29 -15
- package/dist/editor/hooks/useEntryManager.d.ts.map +1 -1
- package/dist/editor/hooks/useEntryManager.js +284 -119
- package/dist/editor/hooks/useEntryManager.js.map +1 -1
- package/dist/editor/hooks/usePermissionManager.d.ts +2 -2
- package/dist/editor/hooks/usePermissionManager.d.ts.map +1 -1
- package/dist/editor/hooks/usePermissionManager.js +11 -9
- package/dist/editor/hooks/usePermissionManager.js.map +1 -1
- package/dist/editor/hooks/useReferenceResolution.d.ts.map +1 -1
- package/dist/editor/hooks/useReferenceResolution.js +24 -1
- package/dist/editor/hooks/useReferenceResolution.js.map +1 -1
- package/dist/editor/media/MediaLibraryBody.d.ts.map +1 -1
- package/dist/editor/media/MediaLibraryBody.js +12 -2
- package/dist/editor/media/MediaLibraryBody.js.map +1 -1
- package/dist/editor/permission-manager/GroupSelector.d.ts.map +1 -1
- package/dist/editor/permission-manager/GroupSelector.js +7 -2
- package/dist/editor/permission-manager/GroupSelector.js.map +1 -1
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts +3 -3
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts.map +1 -1
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js +1 -0
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js.map +1 -1
- package/dist/editor/permission-manager/types.d.ts +6 -4
- package/dist/editor/permission-manager/types.d.ts.map +1 -1
- package/dist/editor/test-setup.js +8 -0
- package/dist/editor/test-setup.js.map +1 -1
- package/dist/editor/theme.d.ts +8 -8
- package/dist/git-manager.d.ts +175 -14
- package/dist/git-manager.d.ts.map +1 -1
- package/dist/git-manager.js +354 -39
- package/dist/git-manager.js.map +1 -1
- package/dist/github-service.d.ts.map +1 -1
- package/dist/github-service.js +13 -7
- package/dist/github-service.js.map +1 -1
- package/dist/http/handler.d.ts.map +1 -1
- package/dist/http/handler.js +78 -29
- package/dist/http/handler.js.map +1 -1
- package/dist/http/router.d.ts.map +1 -1
- package/dist/http/router.js +40 -3
- package/dist/http/router.js.map +1 -1
- package/dist/operating-mode/client-unsafe-strategy.d.ts.map +1 -1
- package/dist/operating-mode/client-unsafe-strategy.js +7 -8
- package/dist/operating-mode/client-unsafe-strategy.js.map +1 -1
- package/dist/operating-mode/deployment-name-fixtures.d.ts +29 -0
- package/dist/operating-mode/deployment-name-fixtures.d.ts.map +1 -0
- package/dist/operating-mode/deployment-name-fixtures.js +55 -0
- package/dist/operating-mode/deployment-name-fixtures.js.map +1 -0
- package/dist/operating-mode/deployment-name.d.ts +37 -0
- package/dist/operating-mode/deployment-name.d.ts.map +1 -0
- package/dist/operating-mode/deployment-name.js +86 -0
- package/dist/operating-mode/deployment-name.js.map +1 -0
- package/dist/operating-mode/index.d.ts +6 -1
- package/dist/operating-mode/index.d.ts.map +1 -1
- package/dist/operating-mode/index.js +10 -1
- package/dist/operating-mode/index.js.map +1 -1
- package/dist/operating-mode/mode-env.d.ts +58 -0
- package/dist/operating-mode/mode-env.d.ts.map +1 -0
- package/dist/operating-mode/mode-env.js +97 -0
- package/dist/operating-mode/mode-env.js.map +1 -0
- package/dist/operating-mode/types.d.ts +13 -3
- package/dist/operating-mode/types.d.ts.map +1 -1
- package/dist/paths/branch-name.d.ts +38 -0
- package/dist/paths/branch-name.d.ts.map +1 -1
- package/dist/paths/branch-name.js +46 -0
- package/dist/paths/branch-name.js.map +1 -1
- package/dist/paths/index.d.ts +1 -1
- package/dist/paths/index.d.ts.map +1 -1
- package/dist/paths/index.js +1 -1
- package/dist/paths/index.js.map +1 -1
- package/dist/reference-resolver.d.ts +6 -2
- package/dist/reference-resolver.d.ts.map +1 -1
- package/dist/reference-resolver.js +8 -1
- package/dist/reference-resolver.js.map +1 -1
- package/dist/resolve-canopy-user.d.ts +34 -0
- package/dist/resolve-canopy-user.d.ts.map +1 -0
- package/dist/resolve-canopy-user.js +55 -0
- package/dist/resolve-canopy-user.js.map +1 -0
- package/dist/schema/meta-loader.d.ts.map +1 -1
- package/dist/schema/meta-loader.js +10 -2
- package/dist/schema/meta-loader.js.map +1 -1
- package/dist/schema/schema-store.d.ts +64 -4
- package/dist/schema/schema-store.d.ts.map +1 -1
- package/dist/schema/schema-store.js +113 -30
- package/dist/schema/schema-store.js.map +1 -1
- package/dist/server.d.ts +9 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +9 -0
- package/dist/server.js.map +1 -1
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +40 -6
- package/dist/services.js.map +1 -1
- package/dist/settings-workspace.d.ts +27 -2
- package/dist/settings-workspace.d.ts.map +1 -1
- package/dist/settings-workspace.js +142 -58
- package/dist/settings-workspace.js.map +1 -1
- package/dist/types.d.ts +73 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/content-write-lock.d.ts +127 -0
- package/dist/utils/content-write-lock.d.ts.map +1 -0
- package/dist/utils/content-write-lock.js +170 -0
- package/dist/utils/content-write-lock.js.map +1 -0
- package/dist/utils/debug.d.ts +11 -0
- package/dist/utils/debug.d.ts.map +1 -1
- package/dist/utils/debug.js +12 -1
- package/dist/utils/debug.js.map +1 -1
- package/dist/utils/error.d.ts +1 -1
- package/dist/utils/error.js +1 -1
- package/dist/utils/git.d.ts +54 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +91 -0
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/logger.d.ts +71 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +85 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/sanitize-href.d.ts +28 -3
- package/dist/utils/sanitize-href.d.ts.map +1 -1
- package/dist/utils/sanitize-href.js +64 -6
- package/dist/utils/sanitize-href.js.map +1 -1
- package/dist/validation/entry-link-validator.d.ts +1 -1
- package/dist/validation/entry-link-validator.js +3 -3
- package/dist/validation/entry-link-validator.js.map +1 -1
- package/dist/validation/entry-type-reference-validator.d.ts +33 -0
- package/dist/validation/entry-type-reference-validator.d.ts.map +1 -0
- package/dist/validation/entry-type-reference-validator.js +110 -0
- package/dist/validation/entry-type-reference-validator.js.map +1 -0
- package/dist/validation/entry-validator.js +1 -1
- package/dist/validation/entry-validator.js.map +1 -1
- package/dist/worker/cms-worker.d.ts +245 -3
- package/dist/worker/cms-worker.d.ts.map +1 -1
- package/dist/worker/cms-worker.js +1084 -253
- package/dist/worker/cms-worker.js.map +1 -1
- package/dist/worker/log.d.ts +61 -0
- package/dist/worker/log.d.ts.map +1 -0
- package/dist/worker/log.js +74 -0
- package/dist/worker/log.js.map +1 -0
- package/package.json +4 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReferenceField.js","sourceRoot":"","sources":["../../../src/editor/fields/ReferenceField.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAc,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACvF,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAqBnD,MAAM,CAAC,MAAM,cAAc,GAAkC,CAAC,EAC5D,EAAE,EACF,KAAK,EACL,OAAO,EAAE,aAAa,EACtB,WAAW,EACX,UAAU,EACV,YAAY,GAAG,OAAO,EACtB,MAAM,GAAG,MAAM,EACf,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,eAAe,GAChB,EAAE,EAAE;IACH,MAAM,cAAc,GAAG,CAAC,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,CAAA;IAC9D,MAAM,aAAa,GAAG,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,CAAA;IAC3D,MAAM,UAAU,GAAG,CAAC,aAAa,IAAI,CAAC,cAAc,IAAI,aAAa,CAAC,CAAA;IACtE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAoB,aAAa,IAAI,EAAE,CAAC,CAAA;IAC9E,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAA;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAA;IACvD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IAE/C,sEAAsE;IACtE,MAAM,SAAS,GAAG,CAAC,GAAY,EAAU,EAAE;QACzC,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAA;QACvC,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,IAAI,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,EAAE,CAAA;QAC9F,OAAO,EAAE,CAAA;IACX,CAAC,CAAA;IAED,MAAM,eAAe,GAAG,QAAQ;QAC9B,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YACpB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;YACtB,CAAC,CAAC,EAAE;QACN,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IACpB,MAAM,WAAW,GAAG,KAAK,EAAE,CAAA;IAC3B,MAAM,OAAO,GAAG,EAAE,IAAI,WAAW,CAAA;IAEjC,+DAA+D;IAC/D,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IACpD,MAAM,QAAQ,GAAG,UAAU;QACzB,CAAC,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,YAAY,IAAI,MAAM,EAAE;QAC5F,CAAC,CAAC,EAAE,CAAA;IACN,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC9B,eAAe,CAAC,QAAQ,CAAC,CAAA;QACzB,IAAI,UAAU,EAAE,CAAC;YACf,UAAU,CAAC,IAAI,CAAC,CAAA;YAChB,QAAQ,CAAC,IAAI,CAAC,CAAA;QAChB,CAAC;IACH,CAAC;IAED,
|
|
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
|
-
*
|
|
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;
|
|
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
|
-
*
|
|
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":";
|
|
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;
|
|
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;
|
|
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":"
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
116
|
-
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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,
|