canopycms 0.0.67-int.90 → 0.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -3
- package/dist/ai/generate.js +1 -27
- package/dist/ai/handler.d.ts +0 -4
- package/dist/ai/handler.js +0 -11
- package/dist/ai/index.d.ts +1 -8
- package/dist/ai/index.js +1 -8
- package/dist/ai/json-to-markdown.js +15 -58
- package/dist/ai/resolve-branch.d.ts +2 -7
- package/dist/ai/resolve-branch.js +2 -8
- package/dist/ai/strip-mdx.d.ts +5 -13
- package/dist/ai/strip-mdx.js +5 -17
- package/dist/ai/to-plain-text.d.ts +10 -28
- package/dist/ai/to-plain-text.js +10 -28
- package/dist/ai/transform-components.d.ts +2 -4
- package/dist/ai/transform-components.js +8 -19
- package/dist/ai/types.d.ts +5 -10
- package/dist/api/admin-branch-health.d.ts +4 -12
- package/dist/api/admin-branch-health.js +26 -66
- package/dist/api/admin.d.ts +4 -12
- package/dist/api/admin.js +10 -26
- package/dist/api/assets.d.ts +0 -25
- package/dist/api/assets.js +50 -91
- package/dist/api/branch-merge.d.ts +1 -1
- package/dist/api/branch-merge.js +0 -2
- package/dist/api/branch-review.d.ts +0 -8
- package/dist/api/branch-review.js +0 -13
- package/dist/api/branch-status.d.ts +0 -3
- package/dist/api/branch-status.js +8 -33
- package/dist/api/branch-withdraw.d.ts +0 -1
- package/dist/api/branch-withdraw.js +6 -9
- package/dist/api/branch.d.ts +7 -12
- package/dist/api/branch.js +7 -44
- package/dist/api/client.d.ts +71 -224
- package/dist/api/client.js +82 -233
- package/dist/api/comments.d.ts +2 -4
- package/dist/api/comments.js +0 -17
- package/dist/api/content.d.ts +0 -6
- package/dist/api/content.js +66 -142
- package/dist/api/entries-constants.d.ts +5 -9
- package/dist/api/entries-constants.js +5 -9
- package/dist/api/entries.d.ts +8 -13
- package/dist/api/entries.js +20 -51
- package/dist/api/github-sync.d.ts +2 -4
- package/dist/api/github-sync.js +4 -8
- package/dist/api/groups.d.ts +3 -0
- package/dist/api/groups.js +8 -21
- package/dist/api/guards.d.ts +4 -16
- package/dist/api/guards.js +3 -22
- package/dist/api/index.d.ts +4 -4
- package/dist/api/permissions.d.ts +2 -0
- package/dist/api/permissions.js +18 -40
- package/dist/api/reference-options.d.ts +0 -1
- package/dist/api/reference-options.js +3 -11
- package/dist/api/request-body-hash.d.ts +12 -23
- package/dist/api/request-body-hash.js +12 -23
- package/dist/api/resolve-references.d.ts +0 -1
- package/dist/api/resolve-references.js +13 -28
- package/dist/api/route-builder.d.ts +3 -7
- package/dist/api/route-builder.js +1 -1
- package/dist/api/routes.d.ts +12 -0
- package/dist/api/routes.js +47 -0
- package/dist/api/schema.d.ts +23 -33
- package/dist/api/schema.js +20 -74
- package/dist/api/settings-helpers.js +4 -5
- package/dist/api/types.d.ts +0 -5
- package/dist/api/user.js +0 -5
- package/dist/api/validators.d.ts +14 -52
- package/dist/api/validators.js +14 -52
- package/dist/assets/asset-prefixes.d.ts +4 -8
- package/dist/assets/asset-prefixes.js +4 -8
- package/dist/assets/asset-src.d.ts +5 -22
- package/dist/assets/asset-src.js +5 -21
- package/dist/assets/factory.d.ts +1 -2
- package/dist/assets/factory.js +1 -2
- package/dist/assets/finalize.d.ts +3 -1
- package/dist/assets/finalize.js +3 -1
- package/dist/assets/index.d.ts +3 -3
- package/dist/assets/index.js +1 -1
- package/dist/assets/keys.d.ts +5 -3
- package/dist/assets/keys.js +6 -3
- package/dist/assets/pipeline.d.ts +3 -2
- package/dist/assets/pipeline.js +22 -56
- package/dist/assets/sharp-loader.d.ts +2 -10
- package/dist/assets/sharp-loader.js +2 -10
- package/dist/assets/store-local.d.ts +1 -2
- package/dist/assets/store-local.js +1 -2
- package/dist/assets/store-s3.d.ts +3 -4
- package/dist/assets/svg-sanitizer.d.ts +6 -14
- package/dist/assets/svg-sanitizer.js +6 -14
- package/dist/assets/transform-directives.d.ts +3 -4
- package/dist/assets/transform-directives.js +1 -1
- package/dist/assets/transform.d.ts +19 -30
- package/dist/assets/transform.js +18 -31
- package/dist/auth/cache.d.ts +2 -3
- package/dist/auth/cache.js +2 -3
- package/dist/auth/caching-auth-plugin.d.ts +11 -22
- package/dist/auth/caching-auth-plugin.js +12 -14
- package/dist/auth/context-helpers.d.ts +6 -20
- package/dist/auth/context-helpers.js +5 -17
- package/dist/auth/file-based-auth-cache.d.ts +10 -21
- package/dist/auth/file-based-auth-cache.js +23 -51
- package/dist/auth/plugin.d.ts +29 -61
- package/dist/auth/plugin.js +9 -13
- package/dist/auth/types.d.ts +11 -20
- package/dist/authorization/branch.d.ts +30 -49
- package/dist/authorization/branch.js +16 -42
- package/dist/authorization/content.d.ts +11 -40
- package/dist/authorization/content.js +13 -45
- package/dist/authorization/groups/index.d.ts +0 -3
- package/dist/authorization/groups/index.js +0 -3
- package/dist/authorization/groups/loader.d.ts +14 -28
- package/dist/authorization/groups/loader.js +14 -38
- package/dist/authorization/groups/schema.d.ts +0 -6
- package/dist/authorization/groups/schema.js +4 -7
- package/dist/authorization/helpers.d.ts +9 -28
- package/dist/authorization/helpers.js +9 -28
- package/dist/authorization/index.d.ts +3 -25
- package/dist/authorization/index.js +3 -35
- package/dist/authorization/path.d.ts +6 -13
- package/dist/authorization/path.js +8 -25
- package/dist/authorization/permissions/index.d.ts +0 -3
- package/dist/authorization/permissions/index.js +0 -3
- package/dist/authorization/permissions/loader.d.ts +14 -27
- package/dist/authorization/permissions/loader.js +14 -32
- package/dist/authorization/permissions/schema.d.ts +1 -6
- package/dist/authorization/permissions/schema.js +6 -13
- package/dist/authorization/protected-branch.d.ts +36 -65
- package/dist/authorization/protected-branch.js +29 -41
- package/dist/authorization/settings-file-store.d.ts +38 -81
- package/dist/authorization/settings-file-store.js +38 -79
- package/dist/authorization/types.d.ts +4 -26
- package/dist/authorization/types.js +0 -6
- package/dist/authorization/validation.d.ts +1 -23
- package/dist/authorization/validation.js +1 -24
- package/dist/branch-health.d.ts +39 -67
- package/dist/branch-health.js +27 -43
- package/dist/branch-metadata-file.d.ts +16 -32
- package/dist/branch-metadata-file.js +13 -26
- package/dist/branch-metadata.d.ts +49 -80
- package/dist/branch-metadata.js +57 -87
- package/dist/branch-registry.d.ts +26 -64
- package/dist/branch-registry.js +44 -93
- package/dist/branch-schema-cache.d.ts +34 -124
- package/dist/branch-schema-cache.js +49 -155
- package/dist/branch-workspace.d.ts +4 -4
- package/dist/branch-workspace.js +15 -19
- package/dist/build/generate-ai-content.d.ts +1 -0
- package/dist/build/generate-ai-content.js +12 -25
- package/dist/build-canopy.d.ts +17 -27
- package/dist/build-canopy.js +16 -23
- package/dist/build-mode.d.ts +25 -27
- package/dist/build-mode.js +25 -29
- package/dist/cli/cli.d.ts +15 -26
- package/dist/cli/cli.js +601 -978
- package/dist/cli/generate-ai-content.js +351 -628
- package/dist/cli/github-app-manifest.d.ts +84 -0
- package/dist/cli/github-app-manifest.js +161 -0
- package/dist/cli/init-github-app.d.ts +110 -444
- package/dist/cli/init-github-app.js +236 -773
- package/dist/cli/init.js +39 -80
- package/dist/cli/migrate.d.ts +13 -10
- package/dist/cli/migrate.js +22 -30
- package/dist/cli/project-detect.d.ts +17 -31
- package/dist/cli/project-detect.js +31 -42
- package/dist/cli/project-root.d.ts +4 -11
- package/dist/cli/project-root.js +4 -11
- package/dist/cli/prompt.d.ts +10 -0
- package/dist/cli/prompt.js +67 -0
- package/dist/cli/sync.d.ts +0 -8
- package/dist/cli/sync.js +8 -28
- package/dist/cli/template-files/middleware.ts.template +15 -29
- package/dist/cli/templates.d.ts +2 -12
- package/dist/cli/templates.js +4 -4
- package/dist/client.d.ts +1 -1
- package/dist/comment-store.d.ts +32 -53
- package/dist/comment-store.js +32 -52
- package/dist/config/flatten.d.ts +0 -3
- package/dist/config/flatten.js +2 -12
- package/dist/config/helpers.js +2 -2
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +1 -4
- package/dist/config/schemas/collection.d.ts +0 -8
- package/dist/config/schemas/collection.js +0 -10
- package/dist/config/schemas/config.d.ts +6 -78
- package/dist/config/schemas/config.js +38 -54
- package/dist/config/schemas/field.d.ts +2 -242
- package/dist/config/schemas/field.js +9 -20
- package/dist/config/schemas/media.js +1 -1
- package/dist/config/schemas/permissions.js +0 -2
- package/dist/config/schemas/url.d.ts +5 -6
- package/dist/config/schemas/url.js +5 -6
- package/dist/config/types.d.ts +45 -33
- package/dist/config/types.js +0 -1
- package/dist/config.d.ts +1 -8
- package/dist/config.js +1 -9
- package/dist/content-id-index.d.ts +76 -188
- package/dist/content-id-index.js +79 -230
- package/dist/content-index-generation.d.ts +27 -48
- package/dist/content-index-generation.js +35 -84
- package/dist/content-index-registry.d.ts +15 -24
- package/dist/content-index-registry.js +5 -9
- package/dist/content-listing.d.ts +64 -107
- package/dist/content-listing.js +68 -118
- package/dist/content-reader.d.ts +20 -29
- package/dist/content-reader.js +10 -18
- package/dist/content-store.d.ts +210 -336
- package/dist/content-store.js +413 -657
- package/dist/content-tree.d.ts +44 -86
- package/dist/content-tree.js +26 -54
- package/dist/context.d.ts +67 -94
- package/dist/context.js +53 -72
- package/dist/dev-content-watcher.d.ts +18 -18
- package/dist/dev-content-watcher.js +41 -44
- package/dist/editor/BranchManager.d.ts +3 -6
- package/dist/editor/BranchManager.js +24 -44
- package/dist/editor/CanopyEditor.js +5 -2
- package/dist/editor/CommentsPanel.js +0 -2
- package/dist/editor/Editor.js +19 -76
- package/dist/editor/EditorAuthGate.d.ts +27 -0
- package/dist/editor/EditorAuthGate.js +140 -0
- package/dist/editor/EntryNavigator.js +0 -20
- package/dist/editor/FormRenderer.d.ts +1 -2
- package/dist/editor/FormRenderer.js +8 -23
- package/dist/editor/admin/SystemHealthPanel.js +20 -37
- package/dist/editor/admin/useSystemHealth.d.ts +2 -3
- package/dist/editor/admin/useSystemHealth.js +10 -12
- package/dist/editor/client-reference-resolver.d.ts +2 -5
- package/dist/editor/client-reference-resolver.js +2 -19
- package/dist/editor/comments/BranchComments.js +0 -4
- package/dist/editor/comments/EntryComments.js +0 -4
- package/dist/editor/comments/FieldWrapper.js +0 -4
- package/dist/editor/comments/InlineCommentThread.js +0 -2
- package/dist/editor/comments/ThreadCarousel.d.ts +0 -58
- package/dist/editor/comments/ThreadCarousel.js +0 -12
- package/dist/editor/components/EditorFooter.d.ts +0 -8
- package/dist/editor/components/EditorFooter.js +0 -5
- package/dist/editor/components/EditorHeader.d.ts +0 -31
- package/dist/editor/components/EditorHeader.js +21 -71
- package/dist/editor/components/EditorSidebar.d.ts +0 -19
- package/dist/editor/components/EditorSidebar.js +0 -16
- package/dist/editor/components/EntryCreateModal.d.ts +4 -4
- package/dist/editor/components/EntryCreateModal.js +7 -22
- package/dist/editor/components/RenameEntryModal.js +0 -4
- package/dist/editor/components/UserBadge.js +0 -10
- package/dist/editor/components/index.js +0 -2
- package/dist/editor/context/ApiClientContext.d.ts +8 -7
- package/dist/editor/context/ApiClientContext.js +39 -11
- package/dist/editor/context/AssetContext.d.ts +7 -17
- package/dist/editor/context/AssetContext.js +7 -17
- package/dist/editor/context/EditorIdentityContext.d.ts +13 -0
- package/dist/editor/context/EditorIdentityContext.js +7 -0
- package/dist/editor/context/EditorStateContext.d.ts +10 -41
- package/dist/editor/context/EditorStateContext.js +7 -23
- package/dist/editor/context/SWRProvider.d.ts +3 -6
- package/dist/editor/context/index.d.ts +1 -20
- package/dist/editor/context/index.js +1 -20
- package/dist/editor/editor-utils.d.ts +8 -47
- package/dist/editor/editor-utils.js +19 -72
- package/dist/editor/fields/BlockField.d.ts +2 -2
- package/dist/editor/fields/BlockField.js +1 -2
- package/dist/editor/fields/CodeField.d.ts +0 -1
- package/dist/editor/fields/CodeField.js +0 -1
- package/dist/editor/fields/DateTimeField.d.ts +15 -22
- package/dist/editor/fields/DateTimeField.js +17 -26
- package/dist/editor/fields/ImageField.d.ts +2 -2
- package/dist/editor/fields/ImageField.js +8 -14
- package/dist/editor/fields/InlineGroupField.d.ts +0 -1
- package/dist/editor/fields/InlineGroupField.js +0 -1
- package/dist/editor/fields/MarkdownField.d.ts +0 -1
- package/dist/editor/fields/MarkdownField.js +6 -11
- package/dist/editor/fields/MdxImageDialog.d.ts +1 -1
- package/dist/editor/fields/MdxImageDialog.js +0 -1
- package/dist/editor/fields/NumberField.d.ts +9 -19
- package/dist/editor/fields/NumberField.js +11 -22
- package/dist/editor/fields/NumberListField.d.ts +7 -10
- package/dist/editor/fields/NumberListField.js +7 -10
- package/dist/editor/fields/ObjectField.d.ts +5 -8
- package/dist/editor/fields/ObjectField.js +0 -1
- package/dist/editor/fields/ReferenceField.d.ts +1 -1
- package/dist/editor/fields/ReferenceField.js +11 -16
- package/dist/editor/fields/SelectField.d.ts +2 -2
- package/dist/editor/fields/SelectField.js +0 -1
- package/dist/editor/fields/StringListField.d.ts +0 -4
- package/dist/editor/fields/StringListField.js +4 -9
- package/dist/editor/fields/TextField.d.ts +0 -1
- package/dist/editor/fields/TextField.js +0 -1
- package/dist/editor/fields/ToggleField.d.ts +0 -1
- package/dist/editor/fields/ToggleField.js +0 -1
- package/dist/editor/fields/entry-link/EntryLinkContext.js +2 -4
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +0 -3
- package/dist/editor/fields/entry-link/InsertEntryLink.js +0 -4
- package/dist/editor/group-manager/ExternalGroupsTab.d.ts +0 -3
- package/dist/editor/group-manager/ExternalGroupsTab.js +0 -1
- package/dist/editor/group-manager/GroupCard.d.ts +0 -3
- package/dist/editor/group-manager/GroupForm.d.ts +0 -3
- package/dist/editor/group-manager/InternalGroupsTab.d.ts +0 -3
- package/dist/editor/group-manager/InternalGroupsTab.js +0 -2
- package/dist/editor/group-manager/MemberList.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useExternalGroupSearch.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useExternalGroupSearch.js +0 -3
- package/dist/editor/group-manager/hooks/useGroupState.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useGroupState.js +0 -5
- package/dist/editor/group-manager/hooks/useUserSearch.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useUserSearch.js +0 -3
- package/dist/editor/group-manager/index.d.ts +0 -6
- package/dist/editor/group-manager/index.js +0 -10
- package/dist/editor/group-manager/types.d.ts +2 -5
- package/dist/editor/group-manager/types.js +0 -3
- package/dist/editor/hooks/index.d.ts +6 -11
- package/dist/editor/hooks/index.js +6 -12
- package/dist/editor/hooks/useBranchActions.d.ts +0 -14
- package/dist/editor/hooks/useBranchActions.js +0 -22
- package/dist/editor/hooks/useBranchManager.d.ts +2 -48
- package/dist/editor/hooks/useBranchManager.js +4 -64
- package/dist/editor/hooks/useBranchesData.d.ts +7 -6
- package/dist/editor/hooks/useBranchesData.js +7 -6
- package/dist/editor/hooks/useCommentSystem.d.ts +0 -49
- package/dist/editor/hooks/useCommentSystem.js +1 -36
- package/dist/editor/hooks/useDraftManager.d.ts +2 -35
- package/dist/editor/hooks/useDraftManager.js +23 -64
- package/dist/editor/hooks/useEditorLayout.d.ts +0 -20
- package/dist/editor/hooks/useEditorLayout.js +0 -23
- package/dist/editor/hooks/useEntriesData.d.ts +1 -0
- package/dist/editor/hooks/useEntriesData.js +2 -3
- package/dist/editor/hooks/useEntryLinkResolution.d.ts +2 -2
- package/dist/editor/hooks/useEntryLinkResolution.js +2 -2
- package/dist/editor/hooks/useEntryManager.d.ts +2 -27
- package/dist/editor/hooks/useEntryManager.js +29 -78
- package/dist/editor/hooks/useGroupManager.d.ts +0 -21
- package/dist/editor/hooks/useGroupManager.js +0 -21
- package/dist/editor/hooks/usePermissionManager.d.ts +0 -20
- package/dist/editor/hooks/usePermissionManager.js +0 -20
- package/dist/editor/hooks/useReferenceResolution.d.ts +2 -33
- package/dist/editor/hooks/useReferenceResolution.js +1 -48
- package/dist/editor/hooks/useSchemaManager.d.ts +8 -27
- package/dist/editor/hooks/useSchemaManager.js +0 -19
- package/dist/editor/hooks/useUserContext.d.ts +2 -9
- package/dist/editor/hooks/useUserContext.js +10 -10
- package/dist/editor/hooks/useUserMetadata.d.ts +0 -2
- package/dist/editor/hooks/useUserMetadata.js +0 -3
- package/dist/editor/media/AssetCard.d.ts +0 -1
- package/dist/editor/media/AssetCard.js +1 -2
- package/dist/editor/media/CropStep.d.ts +0 -1
- package/dist/editor/media/CropStep.js +0 -1
- package/dist/editor/media/MediaLibrary.d.ts +1 -2
- package/dist/editor/media/MediaLibrary.js +1 -2
- package/dist/editor/media/MediaLibraryBody.d.ts +0 -1
- package/dist/editor/media/MediaLibraryBody.js +0 -1
- package/dist/editor/media/crop-math.d.ts +1 -1
- package/dist/editor/media/crop-math.js +1 -1
- package/dist/editor/permission-manager/GroupSelector.d.ts +0 -3
- package/dist/editor/permission-manager/PermissionEditor.d.ts +0 -4
- package/dist/editor/permission-manager/PermissionEditor.js +0 -1
- package/dist/editor/permission-manager/PermissionLevelBadge.d.ts +0 -7
- package/dist/editor/permission-manager/PermissionLevelBadge.js +0 -4
- package/dist/editor/permission-manager/PermissionTree.d.ts +0 -4
- package/dist/editor/permission-manager/UserSelector.d.ts +0 -3
- package/dist/editor/permission-manager/constants.d.ts +0 -3
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts +0 -3
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js +0 -10
- package/dist/editor/permission-manager/hooks/usePermissionTree.d.ts +0 -14
- package/dist/editor/permission-manager/hooks/usePermissionTree.js +0 -11
- package/dist/editor/permission-manager/index.d.ts +0 -7
- package/dist/editor/permission-manager/index.js +0 -16
- package/dist/editor/permission-manager/types.d.ts +2 -12
- package/dist/editor/permission-manager/types.js +0 -3
- package/dist/editor/permission-manager/utils.d.ts +0 -28
- package/dist/editor/permission-manager/utils.js +9 -23
- package/dist/editor/preview-bridge.d.ts +5 -1
- package/dist/editor/preview-bridge.js +4 -4
- package/dist/editor/schema-editor/CollectionEditor.d.ts +0 -5
- package/dist/editor/schema-editor/CollectionEditor.js +9 -31
- package/dist/editor/schema-editor/EntryTypeEditor.d.ts +0 -6
- package/dist/editor/schema-editor/EntryTypeEditor.js +3 -24
- package/dist/editor/schema-editor/index.d.ts +0 -7
- package/dist/editor/schema-editor/index.js +0 -7
- package/dist/editor/utils/env.d.ts +3 -18
- package/dist/editor/utils/env.js +6 -25
- package/dist/entry-link-resolver.d.ts +13 -35
- package/dist/entry-link-resolver.js +20 -53
- package/dist/entry-schema-registry.d.ts +20 -60
- package/dist/entry-schema-registry.js +20 -69
- package/dist/entry-schema.d.ts +118 -223
- package/dist/entry-schema.js +46 -91
- package/dist/git-manager.d.ts +101 -200
- package/dist/git-manager.js +211 -384
- package/dist/github-service.d.ts +34 -75
- package/dist/github-service.js +37 -91
- package/dist/http/handler.d.ts +6 -37
- package/dist/http/handler.js +65 -120
- package/dist/http/router.d.ts +15 -32
- package/dist/http/router.js +34 -99
- package/dist/http/types.d.ts +15 -40
- package/dist/http/types.js +3 -7
- package/dist/id.d.ts +4 -10
- package/dist/id.js +4 -10
- package/dist/index.js +6 -9
- package/dist/operating-mode/client-safe-strategy.d.ts +7 -14
- package/dist/operating-mode/client-safe-strategy.js +8 -28
- package/dist/operating-mode/client-unsafe-strategy.d.ts +6 -16
- package/dist/operating-mode/client-unsafe-strategy.js +9 -34
- package/dist/operating-mode/client.d.ts +3 -10
- package/dist/operating-mode/client.js +3 -8
- package/dist/operating-mode/deployment-name-fixtures.d.ts +14 -18
- package/dist/operating-mode/deployment-name-fixtures.js +14 -18
- package/dist/operating-mode/deployment-name.d.ts +19 -29
- package/dist/operating-mode/deployment-name.js +29 -47
- package/dist/operating-mode/index.d.ts +4 -25
- package/dist/operating-mode/index.js +9 -31
- package/dist/operating-mode/mode-env.d.ts +32 -54
- package/dist/operating-mode/mode-env.js +36 -58
- package/dist/operating-mode/types.d.ts +24 -72
- package/dist/operating-mode/types.js +1 -7
- package/dist/paths/branch-name.d.ts +30 -40
- package/dist/paths/branch-name.js +30 -40
- package/dist/paths/branch.d.ts +4 -18
- package/dist/paths/branch.js +6 -22
- package/dist/paths/index.d.ts +2 -13
- package/dist/paths/index.js +3 -23
- package/dist/paths/normalize-server.d.ts +3 -15
- package/dist/paths/normalize-server.js +3 -15
- package/dist/paths/normalize.d.ts +13 -33
- package/dist/paths/normalize.js +13 -33
- package/dist/paths/resolve.d.ts +4 -17
- package/dist/paths/resolve.js +4 -22
- package/dist/paths/types.d.ts +12 -34
- package/dist/paths/types.js +5 -7
- package/dist/paths/validation.d.ts +22 -119
- package/dist/paths/validation.js +30 -148
- package/dist/reference-resolver.d.ts +0 -13
- package/dist/reference-resolver.js +0 -18
- package/dist/resolve-canopy-user.d.ts +16 -18
- package/dist/resolve-canopy-user.js +17 -26
- package/dist/resource-generation.d.ts +16 -25
- package/dist/resource-generation.js +34 -97
- package/dist/schema/meta-loader.d.ts +2 -14
- package/dist/schema/meta-loader.js +15 -64
- package/dist/schema/resolver.d.ts +1 -4
- package/dist/schema/resolver.js +1 -6
- package/dist/schema/schema-store-types.d.ts +0 -12
- package/dist/schema/schema-store.d.ts +61 -138
- package/dist/schema/schema-store.js +85 -282
- package/dist/schema/types.d.ts +0 -4
- package/dist/server.d.ts +62 -93
- package/dist/server.js +63 -94
- package/dist/services.d.ts +23 -47
- package/dist/services.js +55 -98
- package/dist/settings-workspace.d.ts +17 -30
- package/dist/settings-workspace.js +51 -81
- package/dist/static/index.d.ts +26 -52
- package/dist/static/index.js +33 -67
- package/dist/{worker/task-queue.d.ts → task-queue/cms-task-queue.d.ts} +7 -9
- package/dist/task-queue/cms-task-queue.js +13 -0
- package/dist/task-queue/task-queue-config.d.ts +3 -0
- package/dist/{worker → task-queue}/task-queue-config.js +1 -6
- package/dist/task-queue/task-queue.d.ts +16 -22
- package/dist/task-queue/task-queue.js +20 -44
- package/dist/task-queue/types.d.ts +0 -1
- package/dist/task-queue/worker-status.d.ts +35 -0
- package/dist/task-queue/worker-status.js +40 -0
- package/dist/types.d.ts +40 -51
- package/dist/url-collision.d.ts +26 -40
- package/dist/url-collision.js +47 -63
- package/dist/url-exclusivity-fixtures.d.ts +15 -20
- package/dist/url-exclusivity-fixtures.js +14 -19
- package/dist/url-path-resolver.d.ts +8 -16
- package/dist/url-path-resolver.js +19 -29
- package/dist/user.d.ts +8 -21
- package/dist/user.js +10 -19
- package/dist/utils/async-mutex.js +4 -6
- package/dist/utils/atomic-write.d.ts +2 -11
- package/dist/utils/atomic-write.js +2 -11
- package/dist/utils/body-field.d.ts +8 -15
- package/dist/utils/body-field.js +8 -15
- package/dist/utils/content-serialize.d.ts +18 -24
- package/dist/utils/content-serialize.js +109 -160
- package/dist/utils/content-write-lock.d.ts +51 -106
- package/dist/utils/content-write-lock.js +66 -111
- package/dist/utils/debug.d.ts +7 -23
- package/dist/utils/debug.js +7 -23
- package/dist/utils/entry-url.d.ts +11 -23
- package/dist/utils/entry-url.js +11 -26
- package/dist/utils/error.d.ts +25 -90
- package/dist/utils/error.js +60 -147
- package/dist/utils/flatten-group-fields.d.ts +5 -7
- package/dist/utils/flatten-group-fields.js +5 -7
- package/dist/utils/format.d.ts +1 -5
- package/dist/utils/format.js +1 -5
- package/dist/utils/fs.d.ts +3 -4
- package/dist/utils/fs.js +3 -4
- package/dist/utils/git.d.ts +52 -83
- package/dist/utils/git.js +79 -125
- package/dist/utils/logger.d.ts +35 -50
- package/dist/utils/logger.js +35 -52
- package/dist/utils/provisioning-lock.d.ts +23 -35
- package/dist/utils/provisioning-lock.js +49 -69
- package/dist/utils/sanitize-href.d.ts +5 -10
- package/dist/utils/sanitize-href.js +8 -18
- package/dist/utils/title-field.d.ts +17 -20
- package/dist/utils/title-field.js +18 -27
- package/dist/utils/typed-filename.d.ts +20 -48
- package/dist/utils/typed-filename.js +25 -61
- package/dist/utils/url-prefix.d.ts +3 -3
- package/dist/utils/url-prefix.js +3 -3
- package/dist/validation/block-structural-keys.d.ts +16 -31
- package/dist/validation/block-structural-keys.js +19 -29
- package/dist/validation/deletion-checker.d.ts +0 -34
- package/dist/validation/deletion-checker.js +1 -43
- package/dist/validation/entry-link-validator.d.ts +6 -13
- package/dist/validation/entry-link-validator.js +4 -13
- package/dist/validation/entry-type-reference-validator.d.ts +13 -18
- package/dist/validation/entry-type-reference-validator.js +13 -18
- package/dist/validation/entry-validator.d.ts +13 -25
- package/dist/validation/entry-validator.js +15 -32
- package/dist/validation/field-traversal.d.ts +3 -30
- package/dist/validation/field-traversal.js +1 -32
- package/dist/validation/reference-validator.d.ts +5 -24
- package/dist/validation/reference-validator.js +5 -30
- package/dist/worker/cms-worker.d.ts +172 -232
- package/dist/worker/cms-worker.js +241 -333
- package/dist/worker/git-sync.d.ts +32 -133
- package/dist/worker/git-sync.js +129 -191
- package/dist/worker/github-auth.d.ts +13 -19
- package/dist/worker/github-auth.js +13 -19
- package/dist/worker/history-rewrite.d.ts +53 -66
- package/dist/worker/history-rewrite.js +54 -60
- package/dist/worker/log.d.ts +24 -41
- package/dist/worker/log.js +25 -42
- package/dist/worker/rebase.d.ts +20 -110
- package/dist/worker/rebase.js +279 -354
- package/dist/worker/task-runner.d.ts +32 -66
- package/dist/worker/task-runner.js +126 -162
- package/dist/worker/worker-context.d.ts +41 -81
- package/package.json +4 -4
- package/dist/cli/template-files/middleware-clerk.ts.template +0 -37
- package/dist/worker/task-queue-config.d.ts +0 -8
- package/dist/worker/task-queue.js +0 -19
- package/dist/worker/worker-status.d.ts +0 -47
- package/dist/worker/worker-status.js +0 -52
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { BranchContext, BranchMetadata } from './types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { BranchMetadataCorruptError, type BranchMetadataFile } from './branch-metadata-file.js';
|
|
3
3
|
import { type OperatingMode } from './operating-mode/index.js';
|
|
4
|
-
export {
|
|
4
|
+
export { BranchMetadataCorruptError, type BranchMetadataFile };
|
|
5
|
+
/** @internal Exported for tests. */
|
|
5
6
|
export declare class BranchMetadataConflictError extends Error {
|
|
6
7
|
constructor(message?: string);
|
|
7
8
|
}
|
|
@@ -9,28 +10,17 @@ export declare class BranchMetadataConflictError extends Error {
|
|
|
9
10
|
* Manages branch.json — branch status and access ACLs, both security-adjacent
|
|
10
11
|
* state — under `.canopy-meta/` in a branch workspace.
|
|
11
12
|
*
|
|
12
|
-
* save()
|
|
13
|
-
*
|
|
13
|
+
* save() runs under the same three-layer stack as {@link CommentStore}'s
|
|
14
|
+
* withMutation — see comment-store.ts, and `utils/occ-json-write.ts` for the
|
|
15
|
+
* guarantees of layers 2-3.
|
|
14
16
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* relies on a read-back that can be served from the writer's own local
|
|
23
|
-
* NFS dentry/attribute cache, so a foreign writer's rename can stay
|
|
24
|
-
* invisible for that cache's window (commonly 3-60s) and both writers
|
|
25
|
-
* conclude they won. A settle delay does not help — the cache window
|
|
26
|
-
* dwarfs any sleep worth paying — only server-enforced mutual exclusion
|
|
27
|
-
* does. Given branch.json carries status + ACLs, silently losing an
|
|
28
|
-
* update here is a correctness/security issue, not just a UX glitch.
|
|
29
|
-
* 3. {@link withOccRetry} around {@link writeOccJsonFile} - version/writeId
|
|
30
|
-
* based optimistic concurrency control. With layers 1-2 in place this is
|
|
31
|
-
* now a defense-in-depth backstop only, not the primary safety mechanism.
|
|
32
|
-
*
|
|
33
|
-
* See `utils/occ-json-write.ts` for full guarantee documentation of layers 2-3.
|
|
17
|
+
* Layer 2's server-enforced lock is the load-bearing one here. Rename-based OCC
|
|
18
|
+
* alone verifies by a read-back that can come from the writer's own NFS
|
|
19
|
+
* attribute cache, so for that cache's window (docs/concurrency.md) a foreign
|
|
20
|
+
* writer's rename stays invisible and both writers conclude they won; no settle
|
|
21
|
+
* delay closes it, since the window dwarfs any sleep worth paying. And because
|
|
22
|
+
* branch.json carries status and ACLs, a silently lost update is a
|
|
23
|
+
* correctness/security issue, not a UX glitch.
|
|
34
24
|
*/
|
|
35
25
|
export declare class BranchMetadataFileManager {
|
|
36
26
|
private readonly branchRoot;
|
|
@@ -38,94 +28,73 @@ export declare class BranchMetadataFileManager {
|
|
|
38
28
|
private readonly baseRoot;
|
|
39
29
|
private readonly settleMs;
|
|
40
30
|
private constructor();
|
|
41
|
-
/**
|
|
42
|
-
* Load branch metadata without requiring baseRoot.
|
|
43
|
-
* Use this for read-only access (e.g., in registry scanning or loadBranchContext).
|
|
44
|
-
*/
|
|
31
|
+
/** Read-only load, needing no baseRoot: registry scanning, loadBranchContext. */
|
|
45
32
|
static loadOnly(branchRoot: string): Promise<BranchMetadataFile | null>;
|
|
46
33
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
34
|
+
* An instance wired for registry invalidation. API handlers use this, so the
|
|
35
|
+
* registry cache is invalidated on update.
|
|
49
36
|
*/
|
|
50
37
|
static get(branchRoot: string, baseRoot: string, options?: {
|
|
51
38
|
settleMs?: number;
|
|
52
39
|
}): BranchMetadataFileManager;
|
|
53
40
|
private load;
|
|
54
41
|
/**
|
|
55
|
-
* Write branch.json via the shared OCC helper,
|
|
56
|
-
* default
|
|
42
|
+
* Write branch.json via the shared OCC helper, applying the schemaVersion
|
|
43
|
+
* default here since payload shaping is branch-metadata's concern.
|
|
57
44
|
*
|
|
58
|
-
* Throws the helper's raw {@link OccWriteConflictError}
|
|
59
|
-
* {@link withOccRetry} in save() recognizes and retries
|
|
60
|
-
* the public `BranchMetadataConflictError`
|
|
61
|
-
* boundary
|
|
62
|
-
* withOccRetry's default predicate miss it, since it only recognizes the
|
|
63
|
-
* raw error type).
|
|
45
|
+
* Throws the helper's raw {@link OccWriteConflictError}, which is what the
|
|
46
|
+
* surrounding {@link withOccRetry} in save() recognizes and retries;
|
|
47
|
+
* translating to the public `BranchMetadataConflictError` earlier than the
|
|
48
|
+
* save() boundary would make withOccRetry's predicate miss it.
|
|
64
49
|
*
|
|
65
|
-
* branch
|
|
66
|
-
*
|
|
50
|
+
* branch.json is written WITH a trailing newline (`trailingNewline: true`),
|
|
51
|
+
* unlike comments.json.
|
|
67
52
|
*/
|
|
68
53
|
private write;
|
|
69
54
|
/**
|
|
70
|
-
* Run a save cycle under the full lock + OCC-retry stack
|
|
71
|
-
*
|
|
72
|
-
* public `BranchMetadataConflictError`.
|
|
55
|
+
* Run a save cycle under the full lock + OCC-retry stack (class doc). A
|
|
56
|
+
* conflict surviving every retry surfaces as `BranchMetadataConflictError`.
|
|
73
57
|
*
|
|
74
|
-
*
|
|
75
|
-
* caller's branchContext can
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* a registry entry with no clone behind it. Checking BEFORE the lock stack
|
|
82
|
-
* (rather than after) fails fast without paying for a lock acquisition on
|
|
83
|
-
* a doomed save.
|
|
58
|
+
* The stat guards a phantom-resurrection race with branch deletion: a
|
|
59
|
+
* caller's branchContext can resolve BEFORE a concurrent deleteBranchHandler
|
|
60
|
+
* removes the branch directory, while the save reaches here after it, and
|
|
61
|
+
* write()'s `mkdir({recursive:true})` would then recreate `.canopy-meta/` and
|
|
62
|
+
* branch.json from defaults inside a tree nothing else refers to — a registry
|
|
63
|
+
* entry with no clone behind it. It runs BEFORE the lock stack so a doomed
|
|
64
|
+
* save fails fast instead of paying for a lock.
|
|
84
65
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* it cannot itself provide a wider guarantee than "the directory existed
|
|
91
|
-
* a moment ago."
|
|
66
|
+
* Accepted residual window: a save that passes the check can still race a
|
|
67
|
+
* `rm` that starts moments later and is mid-flight when the write lands.
|
|
68
|
+
* Closing that needs a tombstone OUTSIDE the tree being removed, and the
|
|
69
|
+
* lockfile taken next lives INSIDE `branchRoot`, so it can promise no more
|
|
70
|
+
* than "the directory existed a moment ago".
|
|
92
71
|
*/
|
|
93
72
|
save(incoming: BranchMetadataUpdate): Promise<BranchMetadataFile>;
|
|
94
|
-
/**
|
|
95
|
-
* Invalidates the registry cache so next list() call regenerates from branch.json files.
|
|
96
|
-
*/
|
|
73
|
+
/** Invalidate the registry cache so the next list() regenerates. */
|
|
97
74
|
private invalidateRegistry;
|
|
98
75
|
}
|
|
99
76
|
/**
|
|
100
|
-
* Fields
|
|
101
|
-
*
|
|
102
|
-
* - createdAt/updatedAt: Managed automatically
|
|
77
|
+
* Fields save() accepts. `createdBy` applies on creation only and is ignored
|
|
78
|
+
* once metadata exists; createdAt/updatedAt are managed here, not by callers.
|
|
103
79
|
*/
|
|
104
80
|
export interface BranchMetadataUpdate {
|
|
105
81
|
branch?: Partial<Omit<BranchMetadata, 'createdAt' | 'updatedAt'>>;
|
|
106
82
|
}
|
|
107
83
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* identical archived-branch metadata.
|
|
84
|
+
* The metadata update for archiving a branch whose PR merged. Shared by the
|
|
85
|
+
* worker's merge-poll (CmsWorker.pollMergeState) and the manual markAsMerged
|
|
86
|
+
* API (api/branch-merge.ts), so both produce identical metadata.
|
|
112
87
|
*
|
|
113
|
-
* Deliberately omits pullRequestNumber/pullRequestUrl: save()
|
|
114
|
-
*
|
|
115
|
-
*
|
|
88
|
+
* Deliberately omits pullRequestNumber/pullRequestUrl: save() keeps existing
|
|
89
|
+
* values for fields the incoming update omits, so the recorded PR number and
|
|
90
|
+
* URL survive untouched.
|
|
116
91
|
*/
|
|
117
92
|
export declare function buildMergedBranchUpdate(branchName: string, now?: Date): NonNullable<BranchMetadataUpdate['branch']>;
|
|
118
|
-
/**
|
|
119
|
-
* Get a BranchMetadataFileManager instance configured for registry invalidation.
|
|
120
|
-
* Use this in API handlers to ensure registry cache is invalidated on updates.
|
|
121
|
-
*/
|
|
93
|
+
/** {@link BranchMetadataFileManager.get} as a function. */
|
|
122
94
|
export declare const getBranchMetadataFileManager: (branchRoot: string, baseRoot: string, options?: {
|
|
123
95
|
settleMs?: number;
|
|
124
96
|
}) => BranchMetadataFileManager;
|
|
125
|
-
/**
|
|
126
|
-
* Load branch context from metadata file (source of truth).
|
|
127
|
-
* Returns null if the branch doesn't exist.
|
|
128
|
-
*/
|
|
97
|
+
/** Branch context from the metadata file, the source of truth. Null if absent. */
|
|
129
98
|
export declare const loadBranchContext: (options: {
|
|
130
99
|
branchName: string;
|
|
131
100
|
mode: OperatingMode;
|
package/dist/branch-metadata.js
CHANGED
|
@@ -6,11 +6,12 @@ import { resolveBranchPath } from './paths/index.js';
|
|
|
6
6
|
import { isNotFoundError } from './utils/error.js';
|
|
7
7
|
import { withLock } from './utils/async-mutex.js';
|
|
8
8
|
import { writeOccJsonFile, withOccRetry, withOccFileLock, OccWriteConflictError, } from './utils/occ-json-write.js';
|
|
9
|
-
// The file format
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
export {
|
|
9
|
+
// The file format lives in the leaf so branch-registry.ts can read branch.json
|
|
10
|
+
// without importing this module, which imports it back. Re-exported here so
|
|
11
|
+
// importers of these names do not have to move.
|
|
12
|
+
export { BranchMetadataCorruptError };
|
|
13
13
|
const CURRENT_SCHEMA_VERSION = 1;
|
|
14
|
+
/** @internal Exported for tests. */
|
|
14
15
|
export class BranchMetadataConflictError extends Error {
|
|
15
16
|
constructor(message = 'Concurrent modification detected in branch metadata') {
|
|
16
17
|
super(message);
|
|
@@ -21,28 +22,17 @@ export class BranchMetadataConflictError extends Error {
|
|
|
21
22
|
* Manages branch.json — branch status and access ACLs, both security-adjacent
|
|
22
23
|
* state — under `.canopy-meta/` in a branch workspace.
|
|
23
24
|
*
|
|
24
|
-
* save()
|
|
25
|
-
*
|
|
25
|
+
* save() runs under the same three-layer stack as {@link CommentStore}'s
|
|
26
|
+
* withMutation — see comment-store.ts, and `utils/occ-json-write.ts` for the
|
|
27
|
+
* guarantees of layers 2-3.
|
|
26
28
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* relies on a read-back that can be served from the writer's own local
|
|
35
|
-
* NFS dentry/attribute cache, so a foreign writer's rename can stay
|
|
36
|
-
* invisible for that cache's window (commonly 3-60s) and both writers
|
|
37
|
-
* conclude they won. A settle delay does not help — the cache window
|
|
38
|
-
* dwarfs any sleep worth paying — only server-enforced mutual exclusion
|
|
39
|
-
* does. Given branch.json carries status + ACLs, silently losing an
|
|
40
|
-
* update here is a correctness/security issue, not just a UX glitch.
|
|
41
|
-
* 3. {@link withOccRetry} around {@link writeOccJsonFile} - version/writeId
|
|
42
|
-
* based optimistic concurrency control. With layers 1-2 in place this is
|
|
43
|
-
* now a defense-in-depth backstop only, not the primary safety mechanism.
|
|
44
|
-
*
|
|
45
|
-
* See `utils/occ-json-write.ts` for full guarantee documentation of layers 2-3.
|
|
29
|
+
* Layer 2's server-enforced lock is the load-bearing one here. Rename-based OCC
|
|
30
|
+
* alone verifies by a read-back that can come from the writer's own NFS
|
|
31
|
+
* attribute cache, so for that cache's window (docs/concurrency.md) a foreign
|
|
32
|
+
* writer's rename stays invisible and both writers conclude they won; no settle
|
|
33
|
+
* delay closes it, since the window dwarfs any sleep worth paying. And because
|
|
34
|
+
* branch.json carries status and ACLs, a silently lost update is a
|
|
35
|
+
* correctness/security issue, not a UX glitch.
|
|
46
36
|
*/
|
|
47
37
|
export class BranchMetadataFileManager {
|
|
48
38
|
constructor(branchRoot, baseRoot, options) {
|
|
@@ -51,16 +41,13 @@ export class BranchMetadataFileManager {
|
|
|
51
41
|
this.baseRoot = baseRoot;
|
|
52
42
|
this.settleMs = options?.settleMs;
|
|
53
43
|
}
|
|
54
|
-
/**
|
|
55
|
-
* Load branch metadata without requiring baseRoot.
|
|
56
|
-
* Use this for read-only access (e.g., in registry scanning or loadBranchContext).
|
|
57
|
-
*/
|
|
44
|
+
/** Read-only load, needing no baseRoot: registry scanning, loadBranchContext. */
|
|
58
45
|
static async loadOnly(branchRoot) {
|
|
59
46
|
return readBranchMetadataFile(branchRoot);
|
|
60
47
|
}
|
|
61
48
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
49
|
+
* An instance wired for registry invalidation. API handlers use this, so the
|
|
50
|
+
* registry cache is invalidated on update.
|
|
64
51
|
*/
|
|
65
52
|
static get(branchRoot, baseRoot, options) {
|
|
66
53
|
return new BranchMetadataFileManager(branchRoot, baseRoot, options);
|
|
@@ -80,18 +67,16 @@ export class BranchMetadataFileManager {
|
|
|
80
67
|
}
|
|
81
68
|
}
|
|
82
69
|
/**
|
|
83
|
-
* Write branch.json via the shared OCC helper,
|
|
84
|
-
* default
|
|
70
|
+
* Write branch.json via the shared OCC helper, applying the schemaVersion
|
|
71
|
+
* default here since payload shaping is branch-metadata's concern.
|
|
85
72
|
*
|
|
86
|
-
* Throws the helper's raw {@link OccWriteConflictError}
|
|
87
|
-
* {@link withOccRetry} in save() recognizes and retries
|
|
88
|
-
* the public `BranchMetadataConflictError`
|
|
89
|
-
* boundary
|
|
90
|
-
* withOccRetry's default predicate miss it, since it only recognizes the
|
|
91
|
-
* raw error type).
|
|
73
|
+
* Throws the helper's raw {@link OccWriteConflictError}, which is what the
|
|
74
|
+
* surrounding {@link withOccRetry} in save() recognizes and retries;
|
|
75
|
+
* translating to the public `BranchMetadataConflictError` earlier than the
|
|
76
|
+
* save() boundary would make withOccRetry's predicate miss it.
|
|
92
77
|
*
|
|
93
|
-
* branch
|
|
94
|
-
*
|
|
78
|
+
* branch.json is written WITH a trailing newline (`trailingNewline: true`),
|
|
79
|
+
* unlike comments.json.
|
|
95
80
|
*/
|
|
96
81
|
async write(meta, expectedVersion) {
|
|
97
82
|
const payload = {
|
|
@@ -105,28 +90,22 @@ export class BranchMetadataFileManager {
|
|
|
105
90
|
});
|
|
106
91
|
}
|
|
107
92
|
/**
|
|
108
|
-
* Run a save cycle under the full lock + OCC-retry stack
|
|
109
|
-
*
|
|
110
|
-
* public `BranchMetadataConflictError`.
|
|
93
|
+
* Run a save cycle under the full lock + OCC-retry stack (class doc). A
|
|
94
|
+
* conflict surviving every retry surfaces as `BranchMetadataConflictError`.
|
|
111
95
|
*
|
|
112
|
-
*
|
|
113
|
-
* caller's branchContext can
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* a registry entry with no clone behind it. Checking BEFORE the lock stack
|
|
120
|
-
* (rather than after) fails fast without paying for a lock acquisition on
|
|
121
|
-
* a doomed save.
|
|
96
|
+
* The stat guards a phantom-resurrection race with branch deletion: a
|
|
97
|
+
* caller's branchContext can resolve BEFORE a concurrent deleteBranchHandler
|
|
98
|
+
* removes the branch directory, while the save reaches here after it, and
|
|
99
|
+
* write()'s `mkdir({recursive:true})` would then recreate `.canopy-meta/` and
|
|
100
|
+
* branch.json from defaults inside a tree nothing else refers to — a registry
|
|
101
|
+
* entry with no clone behind it. It runs BEFORE the lock stack so a doomed
|
|
102
|
+
* save fails fast instead of paying for a lock.
|
|
122
103
|
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* it cannot itself provide a wider guarantee than "the directory existed
|
|
129
|
-
* a moment ago."
|
|
104
|
+
* Accepted residual window: a save that passes the check can still race a
|
|
105
|
+
* `rm` that starts moments later and is mid-flight when the write lands.
|
|
106
|
+
* Closing that needs a tombstone OUTSIDE the tree being removed, and the
|
|
107
|
+
* lockfile taken next lives INSIDE `branchRoot`, so it can promise no more
|
|
108
|
+
* than "the directory existed a moment ago".
|
|
130
109
|
*/
|
|
131
110
|
async save(incoming) {
|
|
132
111
|
try {
|
|
@@ -167,9 +146,9 @@ export class BranchMetadataFileManager {
|
|
|
167
146
|
createdAt: existing?.branch.createdAt ?? defaults.createdAt,
|
|
168
147
|
// Fork point is recorded once at creation; later saves must not move it
|
|
169
148
|
baseBranch: existing?.branch.baseBranch ?? incoming.branch?.baseBranch,
|
|
170
|
-
// Always stamped fresh
|
|
171
|
-
// the
|
|
172
|
-
//
|
|
149
|
+
// Always stamped fresh; the spreads above would otherwise let
|
|
150
|
+
// the creation-time value win forever, freezing the timestamp
|
|
151
|
+
// the editor's Branches panel sorts and displays by
|
|
173
152
|
updatedAt: now,
|
|
174
153
|
},
|
|
175
154
|
};
|
|
@@ -185,31 +164,28 @@ export class BranchMetadataFileManager {
|
|
|
185
164
|
}
|
|
186
165
|
throw err;
|
|
187
166
|
}
|
|
188
|
-
// Registry invalidation AFTER releasing the lockfile
|
|
189
|
-
// requires the bump to land strictly after the branch.json write
|
|
190
|
-
// does
|
|
191
|
-
//
|
|
192
|
-
//
|
|
167
|
+
// Registry invalidation AFTER releasing the lockfile. The protocol only
|
|
168
|
+
// requires the bump to land strictly after the branch.json write, which it
|
|
169
|
+
// does, and the registry's eager regeneration is O(branch count) fs reads
|
|
170
|
+
// on EFS — holding the lock through it would stretch every save's critical
|
|
171
|
+
// section for no correctness gain.
|
|
193
172
|
await this.invalidateRegistry();
|
|
194
173
|
return saved;
|
|
195
174
|
}
|
|
196
|
-
/**
|
|
197
|
-
* Invalidates the registry cache so next list() call regenerates from branch.json files.
|
|
198
|
-
*/
|
|
175
|
+
/** Invalidate the registry cache so the next list() regenerates. */
|
|
199
176
|
async invalidateRegistry() {
|
|
200
177
|
const registry = new BranchRegistry(this.baseRoot);
|
|
201
178
|
await registry.invalidate();
|
|
202
179
|
}
|
|
203
180
|
}
|
|
204
181
|
/**
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
* identical archived-branch metadata.
|
|
182
|
+
* The metadata update for archiving a branch whose PR merged. Shared by the
|
|
183
|
+
* worker's merge-poll (CmsWorker.pollMergeState) and the manual markAsMerged
|
|
184
|
+
* API (api/branch-merge.ts), so both produce identical metadata.
|
|
209
185
|
*
|
|
210
|
-
* Deliberately omits pullRequestNumber/pullRequestUrl: save()
|
|
211
|
-
*
|
|
212
|
-
*
|
|
186
|
+
* Deliberately omits pullRequestNumber/pullRequestUrl: save() keeps existing
|
|
187
|
+
* values for fields the incoming update omits, so the recorded PR number and
|
|
188
|
+
* URL survive untouched.
|
|
213
189
|
*/
|
|
214
190
|
export function buildMergedBranchUpdate(branchName, now = new Date()) {
|
|
215
191
|
return {
|
|
@@ -219,17 +195,11 @@ export function buildMergedBranchUpdate(branchName, now = new Date()) {
|
|
|
219
195
|
mergedAt: now.toISOString(),
|
|
220
196
|
};
|
|
221
197
|
}
|
|
222
|
-
/**
|
|
223
|
-
* Get a BranchMetadataFileManager instance configured for registry invalidation.
|
|
224
|
-
* Use this in API handlers to ensure registry cache is invalidated on updates.
|
|
225
|
-
*/
|
|
198
|
+
/** {@link BranchMetadataFileManager.get} as a function. */
|
|
226
199
|
export const getBranchMetadataFileManager = (branchRoot, baseRoot, options) => {
|
|
227
200
|
return BranchMetadataFileManager.get(branchRoot, baseRoot, options);
|
|
228
201
|
};
|
|
229
|
-
/**
|
|
230
|
-
* Load branch context from metadata file (source of truth).
|
|
231
|
-
* Returns null if the branch doesn't exist.
|
|
232
|
-
*/
|
|
202
|
+
/** Branch context from the metadata file, the source of truth. Null if absent. */
|
|
233
203
|
export const loadBranchContext = async (options) => {
|
|
234
204
|
const { branchRoot, baseRoot } = resolveBranchPath({
|
|
235
205
|
branchName: options.branchName,
|
|
@@ -1,59 +1,28 @@
|
|
|
1
1
|
import type { BranchContext } from './types.js';
|
|
2
|
+
/** @internal Exported for tests. */
|
|
2
3
|
export interface BranchRegistrySnapshot {
|
|
3
4
|
version: number;
|
|
4
5
|
branches: BranchContext[];
|
|
5
6
|
/**
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* The marker token this snapshot was built against, or null when it was built
|
|
8
|
+
* before any bump on this root. Compared against the live marker (via
|
|
9
|
+
* isGenerationCurrent) to decide freshness.
|
|
9
10
|
*/
|
|
10
11
|
generation: string | null;
|
|
11
12
|
}
|
|
12
13
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
14
|
+
* A read-only `branches.json` cache for fast branch listing; the individual
|
|
15
|
+
* branch.json files are the source of truth.
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
+
* Freshness follows the generation-marker protocol owned by
|
|
18
|
+
* resource-generation.ts. This is that protocol's durable-snapshot consumer, so
|
|
19
|
+
* it carries both mitigations: invalidate() eager-regenerates on the mutating
|
|
20
|
+
* host right after its own bump, and get() has a throttled suspicious-miss
|
|
21
|
+
* backstop bounding how long a bad snapshot can hide a real branch.
|
|
17
22
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* via the generic on-disk generation marker in resource-generation.ts: every
|
|
22
|
-
* snapshot embeds the marker token it was built against, and every read
|
|
23
|
-
* cheaply re-checks the live marker before trusting the cached snapshot. See
|
|
24
|
-
* that module's doc comment for the full protocol and residual staleness
|
|
25
|
-
* windows (A/B/C/E).
|
|
26
|
-
*
|
|
27
|
-
* BranchRegistry is exactly the "durable snapshot consumer" case called out
|
|
28
|
-
* there: a regeneration whose scan is served from stale NFS dentry/attribute
|
|
29
|
-
* caches can record a FRESH token over STALE data (window E), and because the
|
|
30
|
-
* result is written to `branches.json`, that staleness becomes durable and
|
|
31
|
-
* shared with every other host that reads the marker - not just one process's
|
|
32
|
-
* memory. Two mitigations close the practical gap:
|
|
33
|
-
*
|
|
34
|
-
* - invalidate() eager-regenerates immediately after its own bump. The
|
|
35
|
-
* mutating host's own scan is necessarily coherent with the mutation it just
|
|
36
|
-
* made (no NFS round trip was needed to observe its own write), so this
|
|
37
|
-
* closes window (E) for the common case without waiting for some other host
|
|
38
|
-
* to lazily pull the change.
|
|
39
|
-
* - get() implements a suspicious-miss backstop: a branch that "should" exist
|
|
40
|
-
* but is absent from the cached snapshot forces one fresh regeneration
|
|
41
|
-
* (throttled), bounding how long a bad snapshot can hide a real branch.
|
|
42
|
-
*
|
|
43
|
-
* regenerate() also skips persisting a snapshot when the marker read itself
|
|
44
|
-
* fails (`{ ok: false }`, e.g. unreadable for a non-ENOENT reason): a snapshot
|
|
45
|
-
* embedding a token we cannot attribute to "matches this scan" would be
|
|
46
|
-
* indistinguishable from a correctly-attributed one to every future reader, so
|
|
47
|
-
* the safer behavior is to serve the fresh scan without writing it durably and
|
|
48
|
-
* let the next read retry the marker.
|
|
49
|
-
*
|
|
50
|
-
* Design:
|
|
51
|
-
* - list() returns the cached snapshot if its embedded generation token still
|
|
52
|
-
* matches the live marker, regenerates from branch.json files otherwise
|
|
53
|
-
* - invalidate() bumps the marker (durable, cross-process) and eager-regenerates
|
|
54
|
-
* - Concurrent regeneration within one process is deduped to a single scan
|
|
55
|
-
* (regenInFlight); across processes, regeneration is still safe since all
|
|
56
|
-
* processes produce identical output from the same branch.json files
|
|
23
|
+
* Concurrent regeneration within one process is deduped to a single scan
|
|
24
|
+
* (regenInFlight); across processes it needs no coordination, since every
|
|
25
|
+
* process produces identical output from the same branch.json files.
|
|
57
26
|
*/
|
|
58
27
|
export declare class BranchRegistry {
|
|
59
28
|
private readonly root;
|
|
@@ -71,35 +40,28 @@ export declare class BranchRegistry {
|
|
|
71
40
|
*/
|
|
72
41
|
list(): Promise<BranchContext[]>;
|
|
73
42
|
/**
|
|
74
|
-
* Returns a single branch by name
|
|
43
|
+
* Returns a single branch by name, from the cached snapshot when it is fresh.
|
|
75
44
|
*
|
|
76
|
-
* Suspicious-miss backstop:
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* genuinely-absent branch costs at most one extra scan per throttle window.
|
|
81
|
-
* This bounds durable window-E staleness for the "branch exists but
|
|
82
|
-
* snapshot predates it" direction; see the class doc comment.
|
|
45
|
+
* Suspicious-miss backstop: a `name` missing from the list is the signal that
|
|
46
|
+
* the snapshot may predate a branch that now exists, so force one fresh
|
|
47
|
+
* regeneration and re-search before giving up. Throttled per instance, so a
|
|
48
|
+
* genuinely-absent branch costs at most one extra scan per window.
|
|
83
49
|
*/
|
|
84
50
|
get(name: string): Promise<BranchContext | undefined>;
|
|
85
51
|
private shouldForceRefresh;
|
|
86
52
|
/**
|
|
87
|
-
* Marks the cache
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* closing window (E) early - the bump alone already restored correctness
|
|
93
|
-
* for every future reader. A failed eager regen therefore must not fail the
|
|
94
|
-
* caller's save/delete.
|
|
53
|
+
* Marks the cache stale for every process sharing this root by bumping the
|
|
54
|
+
* marker, then eager-regenerates on this host. The bump must succeed —
|
|
55
|
+
* swallowing that failure leaves the registry stale indefinitely with no
|
|
56
|
+
* backstop. A failed eager regen must NOT fail the caller's save/delete: the
|
|
57
|
+
* bump alone already restored correctness for every future reader.
|
|
95
58
|
*/
|
|
96
59
|
invalidate(): Promise<void>;
|
|
97
60
|
/**
|
|
98
61
|
* Scans branch directories and rebuilds the cache, deduping concurrent
|
|
99
62
|
* callers on this instance to a single underlying scan. Never loops waiting
|
|
100
|
-
* for the
|
|
101
|
-
* storm
|
|
102
|
-
* after a concurrent bump should call list() again after this resolves.
|
|
63
|
+
* for the embedded token to match the marker — that livelocks under a bump
|
|
64
|
+
* storm; a caller wanting the very latest state calls list() again.
|
|
103
65
|
*/
|
|
104
66
|
private regenerate;
|
|
105
67
|
private performRegenerate;
|