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
package/dist/worker/git-sync.js
CHANGED
|
@@ -9,8 +9,8 @@ import { getErrorMessage, isNodeError, redactCredentials } from '../utils/error.
|
|
|
9
9
|
import { isNonFastForwardRejection } from '../utils/git.js';
|
|
10
10
|
import { hasPendingHistoryRewrite } from './history-rewrite.js';
|
|
11
11
|
import { runRebaseCycle } from './rebase.js';
|
|
12
|
-
import { cleanupOldTasks } from '
|
|
13
|
-
import { writeWorkerStatus } from '
|
|
12
|
+
import { cleanupOldTasks } from '../task-queue/cms-task-queue.js';
|
|
13
|
+
import { writeWorkerStatus } from '../task-queue/worker-status.js';
|
|
14
14
|
import { workerLog, workerLogError, workerLogWarn } from './log.js';
|
|
15
15
|
/**
|
|
16
16
|
* [C1] Retention window for `.trash-*` branch directories left behind by the
|
|
@@ -37,22 +37,17 @@ function parseTrashStamp(stamp) {
|
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
39
|
* Push THIS deployment's own settings branch (`ensureSettingsBranch()`) from
|
|
40
|
-
* remote.git to GitHub. Non-fatal: a no-op push for an up-to-date branch
|
|
41
|
-
*
|
|
40
|
+
* remote.git to GitHub. Non-fatal: a no-op push for an up-to-date branch just
|
|
41
|
+
* succeeds quietly.
|
|
42
42
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* local head here too. Pushing it would be this deployment shipping
|
|
49
|
-
* settings state it doesn't own.
|
|
43
|
+
* Narrowed to that ONE branch, never every local `canopycms-settings-*`:
|
|
44
|
+
* `reconcileTrackedBranches` creates local heads for branches that exist on
|
|
45
|
+
* GitHub, so ANOTHER deployment's settings branch (sharing this GitHub repo)
|
|
46
|
+
* can legitimately show up as a local head here. Pushing it would be this
|
|
47
|
+
* deployment shipping settings state it does not own.
|
|
50
48
|
*/
|
|
51
49
|
export async function pushSettingsBranches(ctx, git, trackedNames) {
|
|
52
50
|
try {
|
|
53
|
-
// Resolved once here rather than at each use below: ensureSettingsBranch()
|
|
54
|
-
// is idempotent, but a local reads better and keeps the eight references
|
|
55
|
-
// in this method obviously talking about one value.
|
|
56
51
|
const settingsBranch = ctx.ensureSettingsBranch();
|
|
57
52
|
const branches = await git.branch();
|
|
58
53
|
const settingsBranches = branches.all.filter((b) => b.startsWith(RESERVED_SETTINGS_BRANCH_PREFIX));
|
|
@@ -66,19 +61,17 @@ export async function pushSettingsBranches(ctx, git, trackedNames) {
|
|
|
66
61
|
// Check the full branch list, not the `canopycms-settings-*` subset: an
|
|
67
62
|
// adopter-supplied `settingsBranch` override need not carry that prefix.
|
|
68
63
|
const ownBranchMissing = !branches.all.includes(settingsBranch);
|
|
69
|
-
// [SYNC-M3] A settings branch
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
// "owned-branch-absent" test alone would fire on every deployment that
|
|
77
|
-
// simply has not had a settings edit yet.
|
|
64
|
+
// [SYNC-M3] A settings branch in remote.git but absent from GitHub's
|
|
65
|
+
// tracking refs was pushed here LOCALLY (only this deployment's own API
|
|
66
|
+
// writes to remote.git) and has never reached GitHub. That absence is the
|
|
67
|
+
// discriminating signature: in the SUPPORTED two-deployments-one-repo case
|
|
68
|
+
// the foreign branch arrives through the GitHub fetch and so always has a
|
|
69
|
+
// tracking ref, while an "owned-branch-absent" test alone would fire on
|
|
70
|
+
// every deployment that has simply had no settings edit yet.
|
|
78
71
|
//
|
|
79
|
-
// With this deployment's own branch also missing, the API and this
|
|
80
|
-
//
|
|
81
|
-
//
|
|
72
|
+
// With this deployment's own branch also missing, the API and this worker
|
|
73
|
+
// have resolved different deploymentNames, and every settings change the
|
|
74
|
+
// API commits is stranded in remote.git forever.
|
|
82
75
|
const strandedLocal = foreign.filter((b) => !trackedNames.has(b));
|
|
83
76
|
if (strandedLocal.length > 0) {
|
|
84
77
|
workerLogWarn(ownBranchMissing
|
|
@@ -97,25 +90,20 @@ export async function pushSettingsBranches(ctx, git, trackedNames) {
|
|
|
97
90
|
return;
|
|
98
91
|
}
|
|
99
92
|
try {
|
|
100
|
-
// Resolved in place
|
|
101
|
-
//
|
|
102
|
-
// resolution
|
|
103
|
-
//
|
|
104
|
-
// calls directly through the instance against an inline type naming it
|
|
105
|
-
// (see the `PushSettingsBranchesInternals` suite).
|
|
93
|
+
// Resolved in place, not hoisted: this is the only push in the function,
|
|
94
|
+
// so there is no second call to keep consistent, and hoisting would move
|
|
95
|
+
// the resolution out to syncGit and change this signature -- which
|
|
96
|
+
// cms-worker.test.ts pins by calling the method through the instance.
|
|
106
97
|
await git.push(await ctx.buildGitHubUrl(), settingsBranch);
|
|
107
98
|
workerLog(`Pushed settings branch ${settingsBranch} to GitHub`);
|
|
108
99
|
}
|
|
109
100
|
catch (err) {
|
|
110
|
-
// Non-fatal: branch may already be up
|
|
111
|
-
// task to throw a PermanentTaskError into (unlike pushBranchToGitHub)
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
// GitHub (an actual settings-branch name collision, not just the
|
|
117
|
-
// "foreign branch found locally" case warned about above), so make
|
|
118
|
-
// that explicit instead of a generic "push failed" line.
|
|
101
|
+
// Non-fatal: the branch may already be up to date, and this call site has
|
|
102
|
+
// no task to throw a PermanentTaskError into (unlike pushBranchToGitHub).
|
|
103
|
+
// A non-fast-forward rejection here still gets its own wording: it means
|
|
104
|
+
// another deployment's worker already pushed ITS OWN state to this
|
|
105
|
+
// settings-branch name on GitHub -- an actual collision, not just the
|
|
106
|
+
// "foreign branch found locally" case warned about above.
|
|
119
107
|
const message = getErrorMessage(err);
|
|
120
108
|
if (isNonFastForwardRejection(message)) {
|
|
121
109
|
workerLogWarn(`Settings push for ${settingsBranch} was rejected (non-fast-forward): another ` +
|
|
@@ -135,49 +123,32 @@ export async function pushSettingsBranches(ctx, git, trackedNames) {
|
|
|
135
123
|
}
|
|
136
124
|
/**
|
|
137
125
|
* Bring `refs/heads/*` in `remote.git` toward what was just fetched into
|
|
138
|
-
* `GITHUB_TRACKING_REF_PREFIX` -- WITHOUT ever force-rewinding or deleting
|
|
139
|
-
*
|
|
140
|
-
* `+refs/heads/*:refs/heads/*` fetch refspec
|
|
141
|
-
* destructively) as part of the fetch itself; see
|
|
142
|
-
* `GITHUB_TRACKING_REF_PREFIX`'s doc comment for the two failure modes
|
|
143
|
-
* that refspec caused.
|
|
126
|
+
* `GITHUB_TRACKING_REF_PREFIX` -- WITHOUT ever force-rewinding or deleting a
|
|
127
|
+
* local head (see that constant's doc comment for the two failure modes a
|
|
128
|
+
* `+refs/heads/*:refs/heads/*` fetch refspec causes).
|
|
144
129
|
*
|
|
145
|
-
* Per tracked branch:
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
* old refspec used to destroy.
|
|
155
|
-
* - neither is an ancestor of the other (diverged) -> LEAVE IT ALONE and
|
|
156
|
-
* count/log it. A real collision (e.g. another deployment moved the
|
|
157
|
-
* same branch name on GitHub); the next push attempt will be rejected
|
|
158
|
-
* non-fast-forward, which is the correct, visible outcome -- this
|
|
159
|
-
* method must never silently pick a winner. The one expected, benign
|
|
160
|
-
* form of this -- our own rebase loop having published a rewrite into
|
|
161
|
-
* remote.git with the GitHub push still queued -- is split out into the
|
|
162
|
-
* `rewritten` bucket so the collision warning stays meaningful.
|
|
130
|
+
* Per tracked branch: no local `refs/heads/<name>` -> create it at the tracked
|
|
131
|
+
* commit; local behind -> fast-forward; equal -> nothing to do; local AHEAD ->
|
|
132
|
+
* LEAVE IT ALONE, since that is unpushed editor/settings work the queued push
|
|
133
|
+
* task (or pushSettingsBranches) ships; diverged -> LEAVE IT ALONE, count and
|
|
134
|
+
* log it. Divergence is a real collision (another deployment moved the same
|
|
135
|
+
* branch name on GitHub) and the next push is rejected non-fast-forward, the
|
|
136
|
+
* correct visible outcome -- this must never silently pick a winner. The one
|
|
137
|
+
* benign form, our own rebase loop having published a rewrite with the GitHub
|
|
138
|
+
* push still queued, is split into `rewritten` so that warning stays meaningful.
|
|
163
139
|
*
|
|
164
|
-
* Never deletes a local head: a branch removed on GitHub simply stops
|
|
165
|
-
*
|
|
166
|
-
*
|
|
140
|
+
* Never deletes a local head: a branch removed on GitHub simply stops being
|
|
141
|
+
* tracked here; the local ref persists until removed through its own explicit
|
|
142
|
+
* path, which the sync loop must not be.
|
|
167
143
|
*
|
|
168
|
-
* `remote.git` is bare
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* this runs. Every `update-ref` below passes the expected old value (the
|
|
175
|
-
* all-zeros OID for "must not exist yet" on creation, the previously-read
|
|
176
|
-
* SHA for the fast-forward case) so a concurrent Lambda write landing in
|
|
177
|
-
* the gap between the read and the write loses the ref update instead of
|
|
178
|
-
* being silently clobbered -- the branch is simply revisited next cycle.
|
|
144
|
+
* Concurrency: `remote.git` is bare and on EFS, and the Lambda pushes into it
|
|
145
|
+
* while this runs. Every `update-ref` below passes the expected old value (the
|
|
146
|
+
* all-zeros OID for "must not exist yet" on creation, the just-read SHA for a
|
|
147
|
+
* fast-forward), so a concurrent Lambda write landing between the read and the
|
|
148
|
+
* write loses the ref update instead of silently clobbering it -- that branch
|
|
149
|
+
* is simply revisited next cycle.
|
|
179
150
|
*/
|
|
180
|
-
|
|
151
|
+
async function reconcileTrackedBranches(ctx, git) {
|
|
181
152
|
const GIT_ZERO_OID = '0000000000000000000000000000000000000000';
|
|
182
153
|
const created = [];
|
|
183
154
|
const fastForwarded = [];
|
|
@@ -186,7 +157,7 @@ export async function reconcileTrackedBranches(ctx, git) {
|
|
|
186
157
|
const rewritten = [];
|
|
187
158
|
// One invocation enumerates both namespaces: refs/heads/<name> (what the
|
|
188
159
|
// Lambda pushes into and branch clones read from) and
|
|
189
|
-
// GITHUB_TRACKING_REF_PREFIX<name> (GitHub's tip
|
|
160
|
+
// GITHUB_TRACKING_REF_PREFIX<name> (GitHub's tip).
|
|
190
161
|
const raw = await git.raw([
|
|
191
162
|
'for-each-ref',
|
|
192
163
|
'--format=%(refname) %(objectname)',
|
|
@@ -212,9 +183,9 @@ export async function reconcileTrackedBranches(ctx, git) {
|
|
|
212
183
|
const localRef = `refs/heads/${name}`;
|
|
213
184
|
if (!localSha) {
|
|
214
185
|
try {
|
|
215
|
-
//
|
|
216
|
-
// against a concurrent Lambda push creating this exact branch
|
|
217
|
-
//
|
|
186
|
+
// The zero old-value asserts the ref does not already exist, guarding
|
|
187
|
+
// against a concurrent Lambda push creating this exact branch name
|
|
188
|
+
// between the for-each-ref read above and this update.
|
|
218
189
|
await git.raw(['update-ref', localRef, trackedSha, GIT_ZERO_OID]);
|
|
219
190
|
created.push(name);
|
|
220
191
|
}
|
|
@@ -225,30 +196,26 @@ export async function reconcileTrackedBranches(ctx, git) {
|
|
|
225
196
|
}
|
|
226
197
|
if (localSha === trackedSha)
|
|
227
198
|
continue; // nothing to do
|
|
228
|
-
// [SYNC-M2] Everything below is per-branch best-effort
|
|
229
|
-
//
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
//
|
|
233
|
-
//
|
|
234
|
-
// rebaseActiveBranches() entirely. Nothing self-healed, so it recurred
|
|
235
|
-
// every cycle. One unreadable ref must cost its own branch, not the
|
|
236
|
-
// whole sync cycle.
|
|
199
|
+
// [SYNC-M2] Everything below is per-branch best-effort: one unreadable ref
|
|
200
|
+
// must cost its own branch, not the whole sync cycle. A ref pointing at a
|
|
201
|
+
// missing or partially written object is plausible on EFS with the Lambda
|
|
202
|
+
// writing concurrently, and an unguarded throw here escapes syncGit()'s try
|
|
203
|
+
// -- skipping pushSettingsBranches(), refreshBaseBranchWorkspace() and the
|
|
204
|
+
// rebase cycle, with nothing to self-heal it on the next pass.
|
|
237
205
|
try {
|
|
238
|
-
//
|
|
239
|
-
//
|
|
240
|
-
//
|
|
241
|
-
//
|
|
242
|
-
// a non-zero exit for the common "not an ancestor" case).
|
|
206
|
+
// Commits unique to each side in one call: left = local's (ahead), right
|
|
207
|
+
// = tracked's (behind). Exits 0 regardless of ancestry direction, unlike
|
|
208
|
+
// `merge-base --is-ancestor`, whose non-zero exit for the common "not an
|
|
209
|
+
// ancestor" case simple-git would throw on.
|
|
243
210
|
const counts = (await git.raw(['rev-list', '--left-right', '--count', `${localSha}...${trackedSha}`])).trim();
|
|
244
211
|
const [leftStr, rightStr] = counts.split(/\s+/);
|
|
245
212
|
const localAheadCount = parseInt(leftStr, 10);
|
|
246
213
|
const localBehindCount = parseInt(rightStr, 10);
|
|
247
214
|
if (!Number.isInteger(localAheadCount) || !Number.isInteger(localBehindCount)) {
|
|
248
|
-
// Unparseable output means
|
|
249
|
-
//
|
|
250
|
-
// warn operators about a
|
|
251
|
-
//
|
|
215
|
+
// Unparseable output means this branch could not be read, NOT that it
|
|
216
|
+
// diverged: falling through to the `diverged` bucket (parseInt yields
|
|
217
|
+
// NaN, which fails both comparisons) would warn operators about a
|
|
218
|
+
// cross-deployment collision that never happened.
|
|
252
219
|
workerLogWarn(` Tracked-branch reconcile: skipping ${name}: unparseable rev-list output ${JSON.stringify(counts)}`);
|
|
253
220
|
continue;
|
|
254
221
|
}
|
|
@@ -264,15 +231,14 @@ export async function reconcileTrackedBranches(ctx, git) {
|
|
|
264
231
|
}
|
|
265
232
|
}
|
|
266
233
|
else if (localBehindCount === 0 && localAheadCount > 0) {
|
|
267
|
-
// Unpushed local work
|
|
268
|
-
// used to force-rewind or delete. Leave it.
|
|
234
|
+
// Unpushed local work. Leave it.
|
|
269
235
|
ahead.push(name);
|
|
270
236
|
}
|
|
271
237
|
else if (await hasPendingHistoryRewrite(ctx, name)) {
|
|
272
|
-
// [SYNC-H1] Our own rebase published a rewrite into remote.git and
|
|
273
|
-
//
|
|
274
|
-
//
|
|
275
|
-
//
|
|
238
|
+
// [SYNC-H1] Our own rebase published a rewrite into remote.git and the
|
|
239
|
+
// GitHub push has not landed yet. Ref-level this is identical to a
|
|
240
|
+
// collision, but expected and self-resolving, so it must not fire the
|
|
241
|
+
// collision warning below.
|
|
276
242
|
rewritten.push(name);
|
|
277
243
|
}
|
|
278
244
|
else {
|
|
@@ -291,10 +257,9 @@ export async function reconcileTrackedBranches(ctx, git) {
|
|
|
291
257
|
if (rewritten.length > 0) {
|
|
292
258
|
workerLog(` Tracked-branch reconcile: ${rewritten.length} branch(es) rebased locally with the GitHub push still pending: ${rewritten.join(', ')}`);
|
|
293
259
|
}
|
|
294
|
-
// trackedNames is returned alongside the summary
|
|
295
|
-
// it
|
|
296
|
-
// branch
|
|
297
|
-
// branch on GitHub and would bloat worker-status.json for no reader.
|
|
260
|
+
// trackedNames is returned alongside the summary rather than folded into it:
|
|
261
|
+
// it is a working set for pushSettingsBranches' stranded-branch check, and
|
|
262
|
+
// listing every branch on GitHub would bloat worker-status.json for no reader.
|
|
298
263
|
return {
|
|
299
264
|
summary: { created, fastForwarded, ahead, diverged, rewritten },
|
|
300
265
|
trackedNames: new Set(tracked.keys()),
|
|
@@ -312,24 +277,21 @@ export async function syncGit(ctx) {
|
|
|
312
277
|
// is inactivity-based, so a slow-but-flowing transfer is unaffected.
|
|
313
278
|
timeout: { block: ctx.taskTimeoutMs },
|
|
314
279
|
});
|
|
315
|
-
//
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
// env for the same reason: the fetch and push here reach GitHub.
|
|
280
|
+
// gitNetworkChildEnv because the fetch and push here reach GitHub, and
|
|
281
|
+
// because pushSettingsBranches(git) below needs its stable-English guarantee
|
|
282
|
+
// to classify a rejected settings-branch push.
|
|
319
283
|
git.env(gitNetworkChildEnv());
|
|
320
|
-
//
|
|
321
|
-
//
|
|
322
|
-
//
|
|
323
|
-
//
|
|
324
|
-
//
|
|
325
|
-
// on a failed one. On failure we rethrow so scheduleLoop's existing
|
|
284
|
+
// The whole cycle is wrapped so both outcomes -- success and hard failure
|
|
285
|
+
// (e.g. the fetch throwing against a poisoned remote.git) -- record a
|
|
286
|
+
// worker-status.json snapshot. The status write itself is always best-effort
|
|
287
|
+
// (.catch below): it must never turn a successful cycle into a failure, nor
|
|
288
|
+
// mask the real error on a failed one. Failures rethrow, so scheduleLoop's
|
|
326
289
|
// per-cycle catch stays the loud path.
|
|
327
290
|
try {
|
|
328
|
-
//
|
|
329
|
-
//
|
|
330
|
-
//
|
|
331
|
-
//
|
|
332
|
-
// simple-git's fetch() with a URL doesn't support --prune directly.
|
|
291
|
+
// Direct URL (no named remote), into the GITHUB_TRACKING_REF_PREFIX
|
|
292
|
+
// remote-tracking namespace rather than refs/heads/* -- see that constant's
|
|
293
|
+
// doc comment for the destructive-fetch bug this avoids. Raw git, because
|
|
294
|
+
// simple-git's fetch() with a URL does not support --prune.
|
|
333
295
|
await git.raw([
|
|
334
296
|
'fetch',
|
|
335
297
|
await ctx.buildGitHubUrl(),
|
|
@@ -337,9 +299,6 @@ export async function syncGit(ctx) {
|
|
|
337
299
|
`+refs/heads/*:${GITHUB_TRACKING_REF_PREFIX}*`,
|
|
338
300
|
]);
|
|
339
301
|
workerLog('Fetched from GitHub');
|
|
340
|
-
// Bring refs/heads/* toward what was just fetched, WITHOUT ever
|
|
341
|
-
// force-rewinding or deleting a local head -- see
|
|
342
|
-
// reconcileTrackedBranches()'s doc comment.
|
|
343
302
|
const { summary: trackedSummary, trackedNames } = await reconcileTrackedBranches(ctx, git);
|
|
344
303
|
// Push settings branches to GitHub (belt-and-suspenders for task queue).
|
|
345
304
|
// Ensures settings reach GitHub even if a task queue entry is lost.
|
|
@@ -349,12 +308,11 @@ export async function syncGit(ctx) {
|
|
|
349
308
|
await pushSettingsBranches(ctx, git, trackedNames);
|
|
350
309
|
await refreshBaseBranchWorkspace(ctx);
|
|
351
310
|
const rebaseSummary = await runRebaseCycle(ctx);
|
|
352
|
-
// Periodically clean up old completed/failed tasks
|
|
353
311
|
await cleanupOldTasks(ctx.taskDir, undefined, ctx.log);
|
|
354
|
-
// [C1] Sweep branch directories the admin purge action trashed more
|
|
355
|
-
//
|
|
356
|
-
//
|
|
357
|
-
//
|
|
312
|
+
// [C1] Sweep branch directories the admin purge action trashed more than
|
|
313
|
+
// TRASH_RETENTION_MS ago. Worker-only by design: purge itself never deletes
|
|
314
|
+
// anything (it stays reversible), and this is the sole place removal
|
|
315
|
+
// actually happens.
|
|
358
316
|
const trashRemoved = await cleanupTrashedBranchDirs(ctx);
|
|
359
317
|
if (trashRemoved > 0) {
|
|
360
318
|
workerLog(`Removed ${trashRemoved} expired trashed branch dir(s)`);
|
|
@@ -386,14 +344,12 @@ export async function syncGit(ctx) {
|
|
|
386
344
|
}
|
|
387
345
|
}
|
|
388
346
|
/**
|
|
389
|
-
* [C1] Remove `.trash-*` branch directories (created by the admin purge
|
|
390
|
-
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
* naming scheme, so an unparseable name is unexpected and worth a human
|
|
396
|
-
* looking rather than a silent skip.
|
|
347
|
+
* [C1] Remove `.trash-*` branch directories (created by the admin purge action,
|
|
348
|
+
* api/admin-branch-health.ts) whose name-embedded stamp is older than
|
|
349
|
+
* {@link TRASH_RETENTION_MS}. A name that doesn't match `.trash-{dirName}-
|
|
350
|
+
* {STAMP}`, or whose stamp fails to parse, is left alone and logged once per
|
|
351
|
+
* cycle: purge is the only writer of this naming scheme, so an unparseable name
|
|
352
|
+
* is unexpected and worth a human looking rather than a silent skip.
|
|
397
353
|
*/
|
|
398
354
|
export async function cleanupTrashedBranchDirs(ctx) {
|
|
399
355
|
let entries;
|
|
@@ -439,24 +395,17 @@ export async function cleanupTrashedBranchDirs(ctx) {
|
|
|
439
395
|
}
|
|
440
396
|
/**
|
|
441
397
|
* Fast-forward the base branch's own working-tree clone
|
|
442
|
-
* (content-branches/<baseBranch>) to match origin/<baseBranch
|
|
398
|
+
* (content-branches/<baseBranch>) to match origin/<baseBranch>, every sync
|
|
399
|
+
* cycle, so the drift window is bounded by gitSyncInterval.
|
|
443
400
|
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
* paths -- a dirty tree, a missing .git -- are silent, which is the
|
|
449
|
-
* suspected live failure mode: a wedged base clone with no diagnosable
|
|
450
|
-
* signal in the logs. This dedicated step makes the refresh explicit,
|
|
451
|
-
* ff-only, and loud, so a stuck base view (an editor forking a new branch
|
|
452
|
-
* "from base" that's actually a stale snapshot) is diagnosable from logs.
|
|
453
|
-
* This runs every sync cycle so the drift window is bounded by
|
|
454
|
-
* gitSyncInterval.
|
|
401
|
+
* A dedicated, explicit and LOUD step rather than a side effect of the rebase
|
|
402
|
+
* loop, whose skip paths (a dirty tree, a missing .git) are silent: a wedged
|
|
403
|
+
* base clone otherwise leaves no diagnosable signal, and an editor forking a
|
|
404
|
+
* new branch "from base" silently gets a stale snapshot.
|
|
455
405
|
*
|
|
456
406
|
* ff-only on purpose: this clone must stay a linear mirror of
|
|
457
|
-
* origin/<baseBranch>, so a merge that isn't a fast-forward (diverged
|
|
458
|
-
*
|
|
459
|
-
* untouched rather than force-resolved.
|
|
407
|
+
* origin/<baseBranch>, so a merge that isn't a fast-forward (diverged local
|
|
408
|
+
* history) is left untouched rather than force-resolved.
|
|
460
409
|
*/
|
|
461
410
|
export async function refreshBaseBranchWorkspace(ctx) {
|
|
462
411
|
// Sanitized name for the workspace directory (a base branch containing
|
|
@@ -478,28 +427,22 @@ export async function refreshBaseBranchWorkspace(ctx) {
|
|
|
478
427
|
const baseGit = simpleGit({
|
|
479
428
|
baseDir: basePath,
|
|
480
429
|
// Keep git non-interactive during the merge so it never blocks on an
|
|
481
|
-
// editor. simple-git >=3.32
|
|
482
|
-
//
|
|
483
|
-
//
|
|
484
|
-
// allowUnsafeEditor carries no injection risk (same as the rebase
|
|
485
|
-
// loop's git config below).
|
|
430
|
+
// editor. simple-git >=3.32 requires opting in to set core.editor; the
|
|
431
|
+
// value is a hardcoded literal ("true", the shell no-op), not user input,
|
|
432
|
+
// so allowUnsafeEditor carries no injection risk here.
|
|
486
433
|
config: ['core.editor=true'],
|
|
487
434
|
unsafe: { allowUnsafeEditor: true },
|
|
488
|
-
// DEP-H1: a hung fetch/merge against this EFS-backed clone would
|
|
489
|
-
//
|
|
490
|
-
//
|
|
491
|
-
// slow-but-flowing transfer is unaffected -- same as syncGit()'s
|
|
492
|
-
// remote handle.
|
|
435
|
+
// DEP-H1: a hung fetch/merge against this EFS-backed clone would stall
|
|
436
|
+
// the sync loop forever (scheduleLoop only reschedules after completion).
|
|
437
|
+
// Inactivity-based, so a slow-but-flowing transfer is unaffected.
|
|
493
438
|
timeout: { block: ctx.taskTimeoutMs },
|
|
494
439
|
});
|
|
495
|
-
// Nothing makes this clone read-only
|
|
496
|
-
//
|
|
497
|
-
//
|
|
498
|
-
//
|
|
499
|
-
//
|
|
500
|
-
//
|
|
501
|
-
// incoming content, the --ff-only merge below refuses on its own and
|
|
502
|
-
// that failure is already logged loudly.
|
|
440
|
+
// Nothing makes this clone read-only, and a direct edit here wedges every
|
|
441
|
+
// editor's view of the base branch until an operator intervenes, so a dirty
|
|
442
|
+
// tree is loud, not a quiet skip. Only TRACKED changes block the refresh: a
|
|
443
|
+
// stray untracked file must not wedge the fast-forward forever, and if one
|
|
444
|
+
// would collide with incoming content the --ff-only merge below refuses on
|
|
445
|
+
// its own and that failure is already logged loudly.
|
|
503
446
|
const status = await baseGit.status();
|
|
504
447
|
const trackedDirty = status.files.filter((f) => f.index !== '?' || f.working_dir !== '?');
|
|
505
448
|
if (trackedDirty.length > 0) {
|
|
@@ -510,16 +453,12 @@ export async function refreshBaseBranchWorkspace(ctx) {
|
|
|
510
453
|
// against origin/<baseBranch>, not filesystem paths, so they must use
|
|
511
454
|
// the same name GitHub knows the branch by.
|
|
512
455
|
await baseGit.fetch('origin', ctx.baseBranch);
|
|
513
|
-
//
|
|
514
|
-
//
|
|
515
|
-
//
|
|
516
|
-
//
|
|
517
|
-
//
|
|
518
|
-
//
|
|
519
|
-
// they were cloned from — for any other base branch, origin/<base>
|
|
520
|
-
// simply never exists and rev-list dies with "ambiguous argument".
|
|
521
|
-
// Pin FETCH_HEAD to a SHA immediately: FETCH_HEAD is one shared mutable
|
|
522
|
-
// file per repo, silently repointed by ANY other fetch in this clone.
|
|
456
|
+
// rev-list, not status.behind, which needs an upstream tracking branch that
|
|
457
|
+
// is not guaranteed here. Against the just-fetched tip rather than
|
|
458
|
+
// origin/<base>: workspaces are cloned --single-branch (git-manager.ts), so
|
|
459
|
+
// for any other base branch origin/<base> never exists and rev-list dies
|
|
460
|
+
// with "ambiguous argument". Pin FETCH_HEAD to a SHA immediately -- it is
|
|
461
|
+
// one shared mutable file per repo, silently repointed by any other fetch.
|
|
523
462
|
const fetchedTip = (await baseGit.revparse(['FETCH_HEAD'])).trim();
|
|
524
463
|
const behindCount = parseInt((await baseGit.raw(['rev-list', '--count', `HEAD..${fetchedTip}`])).trim(), 10);
|
|
525
464
|
if (behindCount > 0) {
|
|
@@ -533,11 +472,10 @@ export async function refreshBaseBranchWorkspace(ctx) {
|
|
|
533
472
|
await invalidateBranchContentCaches(basePath);
|
|
534
473
|
}
|
|
535
474
|
// Hygiene: conflictStatus/conflictFiles are meaningless for the base
|
|
536
|
-
// branch's own metadata
|
|
537
|
-
//
|
|
538
|
-
//
|
|
539
|
-
//
|
|
540
|
-
// so skip it when there's nothing to clear.
|
|
475
|
+
// branch's own metadata, which is excluded from the rebase loop's
|
|
476
|
+
// conflict-resolution pass. Guarded on already-clean, like that loop:
|
|
477
|
+
// save() eager-regenerates the branch registry (O(branch count) EFS reads),
|
|
478
|
+
// so skip it when there is nothing to clear.
|
|
541
479
|
const currentMeta = await BranchMetadataFileManager.loadOnly(basePath);
|
|
542
480
|
const conflictStatus = currentMeta?.branch.conflictStatus;
|
|
543
481
|
const conflictFiles = currentMeta?.branch.conflictFiles;
|
|
@@ -192,6 +192,7 @@ export declare function resolveWorkerGitHubAuth(config: GitHubAuthConfig): Resol
|
|
|
192
192
|
* A named class rather than a bare Error because `isTransientAuthFailure`
|
|
193
193
|
* below has to recognise it: a timeout carries no HTTP status, and the
|
|
194
194
|
* fail-closed rule there would otherwise read "slow network" as "wrong key".
|
|
195
|
+
* @internal Exported for tests.
|
|
195
196
|
*/
|
|
196
197
|
export declare class MintTimeoutError extends Error {
|
|
197
198
|
constructor(timeoutMs: number);
|
|
@@ -244,25 +245,18 @@ export declare function isTransientAuthFailure(err: unknown): boolean;
|
|
|
244
245
|
* is configured, naming the key — rather than surfacing later as an opaque
|
|
245
246
|
* JWT signing failure.
|
|
246
247
|
*
|
|
247
|
-
* The PKCS#1 → PKCS#8 conversion is INSURANCE, not a fix for a current
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
* -
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
* - Per their published package.json files (neither is installed here),
|
|
260
|
-
* `@octokit/auth-app@7` moves to `universal-github-app-jwt@2`, which is
|
|
261
|
-
* WebCrypto-only and converts PKCS#1 solely under the **`node` condition of
|
|
262
|
-
* its `imports` map** (`"#crypto"` → `lib/crypto-node.js`); the `default`
|
|
263
|
-
* sibling's `convertPrivateKey` is a literal no-op, and the key throws.
|
|
264
|
-
*
|
|
265
|
-
* So a bundler flag or a dependency bump can turn a working key into a boot
|
|
248
|
+
* The PKCS#1 → PKCS#8 conversion is INSURANCE, not a fix for a current failure.
|
|
249
|
+
* GitHub issues App keys as PKCS#1 (`-----BEGIN RSA PRIVATE KEY-----`), and
|
|
250
|
+
* whether that is accepted depends on which build of `universal-github-app-jwt`
|
|
251
|
+
* a bundler resolves, never on the key: at the pin we install
|
|
252
|
+
* (`@octokit/auth-app@6` → `universal-github-app-jwt@1.2.0`, no `exports`
|
|
253
|
+
* field) the worker's `esbuild --platform=node --format=esm` reaches `main` →
|
|
254
|
+
* the `dist-node` build, which signs via `jsonwebtoken` and takes PKCS#1; that
|
|
255
|
+
* same package's `module`/`browser` entry is a WebCrypto build that rejects it;
|
|
256
|
+
* and `universal-github-app-jwt@2` (what `@octokit/auth-app@7` pulls in) is
|
|
257
|
+
* WebCrypto-only, converting PKCS#1 solely under the `node` condition of its
|
|
258
|
+
* `imports` map, its `default` sibling's `convertPrivateKey` being a no-op. So
|
|
259
|
+
* a bundler flag or a dependency bump can turn a working key into a boot
|
|
266
260
|
* failure without the key changing. Three lines here remove that coupling.
|
|
267
261
|
*/
|
|
268
262
|
export declare function normalizeGitHubAppPrivateKey(privateKey: string): string;
|
|
@@ -232,6 +232,7 @@ async function mintInstallationToken(app, timeoutMs) {
|
|
|
232
232
|
* A named class rather than a bare Error because `isTransientAuthFailure`
|
|
233
233
|
* below has to recognise it: a timeout carries no HTTP status, and the
|
|
234
234
|
* fail-closed rule there would otherwise read "slow network" as "wrong key".
|
|
235
|
+
* @internal Exported for tests.
|
|
235
236
|
*/
|
|
236
237
|
export class MintTimeoutError extends Error {
|
|
237
238
|
constructor(timeoutMs) {
|
|
@@ -343,25 +344,18 @@ function getHttpStatus(err) {
|
|
|
343
344
|
* is configured, naming the key — rather than surfacing later as an opaque
|
|
344
345
|
* JWT signing failure.
|
|
345
346
|
*
|
|
346
|
-
* The PKCS#1 → PKCS#8 conversion is INSURANCE, not a fix for a current
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
* -
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* - Per their published package.json files (neither is installed here),
|
|
359
|
-
* `@octokit/auth-app@7` moves to `universal-github-app-jwt@2`, which is
|
|
360
|
-
* WebCrypto-only and converts PKCS#1 solely under the **`node` condition of
|
|
361
|
-
* its `imports` map** (`"#crypto"` → `lib/crypto-node.js`); the `default`
|
|
362
|
-
* sibling's `convertPrivateKey` is a literal no-op, and the key throws.
|
|
363
|
-
*
|
|
364
|
-
* So a bundler flag or a dependency bump can turn a working key into a boot
|
|
347
|
+
* The PKCS#1 → PKCS#8 conversion is INSURANCE, not a fix for a current failure.
|
|
348
|
+
* GitHub issues App keys as PKCS#1 (`-----BEGIN RSA PRIVATE KEY-----`), and
|
|
349
|
+
* whether that is accepted depends on which build of `universal-github-app-jwt`
|
|
350
|
+
* a bundler resolves, never on the key: at the pin we install
|
|
351
|
+
* (`@octokit/auth-app@6` → `universal-github-app-jwt@1.2.0`, no `exports`
|
|
352
|
+
* field) the worker's `esbuild --platform=node --format=esm` reaches `main` →
|
|
353
|
+
* the `dist-node` build, which signs via `jsonwebtoken` and takes PKCS#1; that
|
|
354
|
+
* same package's `module`/`browser` entry is a WebCrypto build that rejects it;
|
|
355
|
+
* and `universal-github-app-jwt@2` (what `@octokit/auth-app@7` pulls in) is
|
|
356
|
+
* WebCrypto-only, converting PKCS#1 solely under the `node` condition of its
|
|
357
|
+
* `imports` map, its `default` sibling's `convertPrivateKey` being a no-op. So
|
|
358
|
+
* a bundler flag or a dependency bump can turn a working key into a boot
|
|
365
359
|
* failure without the key changing. Three lines here remove that coupling.
|
|
366
360
|
*/
|
|
367
361
|
export function normalizeGitHubAppPrivateKey(privateKey) {
|