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
|
@@ -4,49 +4,31 @@
|
|
|
4
4
|
*
|
|
5
5
|
* This is deliberately a *different* transform from `stripMdxImports`
|
|
6
6
|
* (strip-mdx.ts): that one is tuned for AI/RAG consumption and intentionally
|
|
7
|
-
* leaves JSX components intact
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* exists: a hand-rolled plaintext stripper that treats a paired component
|
|
13
|
-
* like `<Callout>...</Callout>` as one opaque unit and deletes it wholesale
|
|
14
|
-
* silently drops every word inside it from the search index. `toPlainText`
|
|
15
|
-
* strips the `<Callout>`/`</Callout>` delimiters but keeps the sentence
|
|
16
|
-
* between them.
|
|
7
|
+
* leaves JSX components intact. `toPlainText` has the opposite goal — it
|
|
8
|
+
* removes ALL markup (JSX tags, JSX expressions, markdown syntax) and keeps
|
|
9
|
+
* only the prose, so **paired custom components lose their tags but keep
|
|
10
|
+
* their children's text**: deleting a `<Callout>...</Callout>` wholesale
|
|
11
|
+
* would silently drop every word inside it from the search index.
|
|
17
12
|
*
|
|
18
13
|
* Pipeline (each step operates on the previous step's output):
|
|
19
14
|
* 1. Strip YAML frontmatter (via `gray-matter`, the same parser
|
|
20
15
|
* `content-store.ts` uses for `.md`/`.mdx` bodies).
|
|
21
16
|
* 2. Strip `import`/`export` statements (via `stripMdxImports`), which also
|
|
22
17
|
* protects fenced code blocks from every later step.
|
|
23
|
-
* 3. Mask fenced code blocks and inline code spans, capturing their content
|
|
24
|
-
*
|
|
25
|
-
* 4. Strip JSX/HTML tags — opening, closing, and self-closing — leaving
|
|
26
|
-
* whatever text sits between them in place. This is a single global
|
|
27
|
-
* replace, not a matched-pair walk: because we never need the tag name or
|
|
28
|
-
* the children as a unit (unlike `applyComponentTransforms`, which calls
|
|
29
|
-
* an adopter transform per component), deleting every tag occurrence and
|
|
30
|
-
* leaving the surrounding text untouched handles nesting for free.
|
|
18
|
+
* 3. Mask fenced code blocks and inline code spans, capturing their content.
|
|
19
|
+
* 4. Strip JSX/HTML tags via a single global replace (see `TAG_RE` below).
|
|
31
20
|
* 5. Strip JSX expressions (`{...}`, including nested braces) — these are
|
|
32
21
|
* code, not prose.
|
|
33
|
-
* 6. Strip common Markdown syntax
|
|
34
|
-
* (keep the link text, drop the URL), images (keep alt text), blockquote
|
|
35
|
-
* markers, list markers, and thematic breaks.
|
|
22
|
+
* 6. Strip common Markdown syntax (see `stripMarkdownSyntax` below).
|
|
36
23
|
* 7. Restore the masked code from step 3 as plain text.
|
|
37
24
|
* 8. Collapse whitespace: trim each line, collapse runs of blank lines,
|
|
38
|
-
* trim the result. Paragraph breaks (single blank lines) are preserved
|
|
39
|
-
* this does not flatten the output to one line.
|
|
25
|
+
* trim the result. Paragraph breaks (single blank lines) are preserved.
|
|
40
26
|
*/
|
|
41
27
|
/**
|
|
42
28
|
* Convert MDX/Markdown body content to plain prose text.
|
|
43
29
|
*
|
|
44
30
|
* See the module doc above for the full pipeline and why this exists as a
|
|
45
|
-
* distinct transform from `stripMdxImports`.
|
|
46
|
-
* fences, inline code, JSX tags/expressions, and Markdown syntax are all
|
|
47
|
-
* stripped down to their human-readable text — code content and link/image
|
|
48
|
-
* text are kept, everything else is discarded. Paired custom components
|
|
49
|
-
* lose only their tags; the prose between them survives.
|
|
31
|
+
* distinct transform from `stripMdxImports`.
|
|
50
32
|
*
|
|
51
33
|
* HTML/MDX comments (`<!-- ... -->`) are removed along with their contents:
|
|
52
34
|
* an authoring note is text the author marked as not-for-readers, so it does
|
package/dist/ai/to-plain-text.js
CHANGED
|
@@ -4,39 +4,25 @@
|
|
|
4
4
|
*
|
|
5
5
|
* This is deliberately a *different* transform from `stripMdxImports`
|
|
6
6
|
* (strip-mdx.ts): that one is tuned for AI/RAG consumption and intentionally
|
|
7
|
-
* leaves JSX components intact
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* exists: a hand-rolled plaintext stripper that treats a paired component
|
|
13
|
-
* like `<Callout>...</Callout>` as one opaque unit and deletes it wholesale
|
|
14
|
-
* silently drops every word inside it from the search index. `toPlainText`
|
|
15
|
-
* strips the `<Callout>`/`</Callout>` delimiters but keeps the sentence
|
|
16
|
-
* between them.
|
|
7
|
+
* leaves JSX components intact. `toPlainText` has the opposite goal — it
|
|
8
|
+
* removes ALL markup (JSX tags, JSX expressions, markdown syntax) and keeps
|
|
9
|
+
* only the prose, so **paired custom components lose their tags but keep
|
|
10
|
+
* their children's text**: deleting a `<Callout>...</Callout>` wholesale
|
|
11
|
+
* would silently drop every word inside it from the search index.
|
|
17
12
|
*
|
|
18
13
|
* Pipeline (each step operates on the previous step's output):
|
|
19
14
|
* 1. Strip YAML frontmatter (via `gray-matter`, the same parser
|
|
20
15
|
* `content-store.ts` uses for `.md`/`.mdx` bodies).
|
|
21
16
|
* 2. Strip `import`/`export` statements (via `stripMdxImports`), which also
|
|
22
17
|
* protects fenced code blocks from every later step.
|
|
23
|
-
* 3. Mask fenced code blocks and inline code spans, capturing their content
|
|
24
|
-
*
|
|
25
|
-
* 4. Strip JSX/HTML tags — opening, closing, and self-closing — leaving
|
|
26
|
-
* whatever text sits between them in place. This is a single global
|
|
27
|
-
* replace, not a matched-pair walk: because we never need the tag name or
|
|
28
|
-
* the children as a unit (unlike `applyComponentTransforms`, which calls
|
|
29
|
-
* an adopter transform per component), deleting every tag occurrence and
|
|
30
|
-
* leaving the surrounding text untouched handles nesting for free.
|
|
18
|
+
* 3. Mask fenced code blocks and inline code spans, capturing their content.
|
|
19
|
+
* 4. Strip JSX/HTML tags via a single global replace (see `TAG_RE` below).
|
|
31
20
|
* 5. Strip JSX expressions (`{...}`, including nested braces) — these are
|
|
32
21
|
* code, not prose.
|
|
33
|
-
* 6. Strip common Markdown syntax
|
|
34
|
-
* (keep the link text, drop the URL), images (keep alt text), blockquote
|
|
35
|
-
* markers, list markers, and thematic breaks.
|
|
22
|
+
* 6. Strip common Markdown syntax (see `stripMarkdownSyntax` below).
|
|
36
23
|
* 7. Restore the masked code from step 3 as plain text.
|
|
37
24
|
* 8. Collapse whitespace: trim each line, collapse runs of blank lines,
|
|
38
|
-
* trim the result. Paragraph breaks (single blank lines) are preserved
|
|
39
|
-
* this does not flatten the output to one line.
|
|
25
|
+
* trim the result. Paragraph breaks (single blank lines) are preserved.
|
|
40
26
|
*/
|
|
41
27
|
import matter from 'gray-matter';
|
|
42
28
|
import { stripMdxImports } from './strip-mdx.js';
|
|
@@ -271,11 +257,7 @@ function collapseWhitespace(text) {
|
|
|
271
257
|
* Convert MDX/Markdown body content to plain prose text.
|
|
272
258
|
*
|
|
273
259
|
* See the module doc above for the full pipeline and why this exists as a
|
|
274
|
-
* distinct transform from `stripMdxImports`.
|
|
275
|
-
* fences, inline code, JSX tags/expressions, and Markdown syntax are all
|
|
276
|
-
* stripped down to their human-readable text — code content and link/image
|
|
277
|
-
* text are kept, everything else is discarded. Paired custom components
|
|
278
|
-
* lose only their tags; the prose between them survives.
|
|
260
|
+
* distinct transform from `stripMdxImports`.
|
|
279
261
|
*
|
|
280
262
|
* HTML/MDX comments (`<!-- ... -->`) are removed along with their contents:
|
|
281
263
|
* an authoring note is text the author marked as not-for-readers, so it does
|
|
@@ -14,13 +14,11 @@ import type { ComponentProps, ComponentTransforms } from './types.js';
|
|
|
14
14
|
* Parse JSX attribute string into a props object.
|
|
15
15
|
*
|
|
16
16
|
* Handles: `key="value"`, `key='value'`, `key={expr}`, and boolean `key` (→ "true").
|
|
17
|
+
* @internal Exported for tests.
|
|
17
18
|
*/
|
|
18
19
|
export declare function parseComponentProps(attrString: string): ComponentProps;
|
|
19
20
|
/**
|
|
20
|
-
* Apply component transforms to a body string.
|
|
21
|
-
*
|
|
22
21
|
* For each registered component name, finds JSX tags in the body and calls
|
|
23
|
-
* the corresponding transform function.
|
|
24
|
-
* handle nesting (inner components first, outer on subsequent passes).
|
|
22
|
+
* the corresponding transform function.
|
|
25
23
|
*/
|
|
26
24
|
export declare function applyComponentTransforms(body: string, transforms: ComponentTransforms): string;
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
* Parse JSX attribute string into a props object.
|
|
14
14
|
*
|
|
15
15
|
* Handles: `key="value"`, `key='value'`, `key={expr}`, and boolean `key` (→ "true").
|
|
16
|
+
* @internal Exported for tests.
|
|
16
17
|
*/
|
|
17
18
|
export function parseComponentProps(attrString) {
|
|
18
19
|
const props = {};
|
|
19
20
|
if (!attrString)
|
|
20
21
|
return props;
|
|
21
|
-
// Match attribute patterns: name="value", name='value', name={expr}, or bare name
|
|
22
22
|
// eslint-disable-next-line security/detect-unsafe-regex
|
|
23
23
|
const attrRegex = /(\w+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|\{([^}]*)\}))?/g;
|
|
24
24
|
let match;
|
|
@@ -30,10 +30,6 @@ export function parseComponentProps(attrString) {
|
|
|
30
30
|
}
|
|
31
31
|
return props;
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Mask fenced code blocks so component transforms don't touch them.
|
|
35
|
-
* Returns the masked string and a restore function.
|
|
36
|
-
*/
|
|
37
33
|
/** Regex fragment matching JSX attribute content, skipping quoted strings containing '>'. */
|
|
38
34
|
const ATTR_CONTENT = `(?:[^>"']|"[^"]*"|'[^']*')*`;
|
|
39
35
|
const BLOCK_PREFIX = '<<CODEBLOCK';
|
|
@@ -50,12 +46,12 @@ function isFenceCloseLine(line, marker) {
|
|
|
50
46
|
}
|
|
51
47
|
/**
|
|
52
48
|
* Mask fenced code blocks (` ``` `/`~~~`), capturing each block's raw text (fence lines
|
|
53
|
-
* included)
|
|
49
|
+
* included).
|
|
54
50
|
*
|
|
55
|
-
* A hand-rolled line scan, not
|
|
56
|
-
* ~530KB of body text with many unclosed
|
|
57
|
-
*
|
|
58
|
-
*
|
|
51
|
+
* A hand-rolled line scan, not a lazy regex like `/^(```|~~~).*\n[\s\S]*?\n\1\s*$/gm`: that
|
|
52
|
+
* shape is a polynomial-ReDoS hazard (measured ~9s on ~530KB of body text with many unclosed
|
|
53
|
+
* fence openers — an ordinary authoring accident, not a crafted payload; see
|
|
54
|
+
* `ai/to-plain-text.ts`'s identical fix). The lazy `[\s\S]*?` has no bound on how far it
|
|
59
55
|
* must scan looking for a closing `\1` that, for an unclosed fence, never arrives — it exhausts
|
|
60
56
|
* to the end of the string before giving up on that starting line, and `/gm` retries the same
|
|
61
57
|
* exhaustive scan at every subsequent fence-opener line.
|
|
@@ -118,9 +114,8 @@ function maskFencedCodeBlocks(body, blocks) {
|
|
|
118
114
|
function maskCodeBlocks(body) {
|
|
119
115
|
const blocks = [];
|
|
120
116
|
const inlines = [];
|
|
121
|
-
// 1. Mask fenced code blocks
|
|
122
117
|
let masked = maskFencedCodeBlocks(body, blocks);
|
|
123
|
-
//
|
|
118
|
+
// Mask inline code spans (double-backtick first, then single-backtick)
|
|
124
119
|
masked = masked.replace(/``[^`]+``|`[^`]+`/g, (span) => {
|
|
125
120
|
const idx = inlines.length;
|
|
126
121
|
inlines.push(span);
|
|
@@ -137,17 +132,13 @@ function maskCodeBlocks(body) {
|
|
|
137
132
|
};
|
|
138
133
|
}
|
|
139
134
|
/**
|
|
140
|
-
* Apply component transforms to a body string.
|
|
141
|
-
*
|
|
142
135
|
* For each registered component name, finds JSX tags in the body and calls
|
|
143
|
-
* the corresponding transform function.
|
|
144
|
-
* handle nesting (inner components first, outer on subsequent passes).
|
|
136
|
+
* the corresponding transform function.
|
|
145
137
|
*/
|
|
146
138
|
export function applyComponentTransforms(body, transforms) {
|
|
147
139
|
const names = Object.keys(transforms);
|
|
148
140
|
if (names.length === 0)
|
|
149
141
|
return body;
|
|
150
|
-
// Mask code blocks to protect them from transformation
|
|
151
142
|
const { masked, restore } = maskCodeBlocks(body);
|
|
152
143
|
let result = masked;
|
|
153
144
|
const MAX_PASSES = 10;
|
|
@@ -175,7 +166,6 @@ export function applyComponentTransforms(body, transforms) {
|
|
|
175
166
|
const openStart = openMatch.index;
|
|
176
167
|
const openEnd = openStart + openMatch[0].length;
|
|
177
168
|
const attrStr = openMatch[1]?.trim() ?? '';
|
|
178
|
-
// Find matching close tag, accounting for nesting
|
|
179
169
|
const closeTag = `</${name}>`;
|
|
180
170
|
const closeIdx = findMatchingClose(result, openEnd, name, closeTag);
|
|
181
171
|
if (closeIdx === -1)
|
|
@@ -207,7 +197,6 @@ export function applyComponentTransforms(body, transforms) {
|
|
|
207
197
|
function findMatchingClose(body, startFrom, name, closeTag) {
|
|
208
198
|
let depth = 1;
|
|
209
199
|
const pos = startFrom;
|
|
210
|
-
// Regex to find either an opening or closing tag for this component
|
|
211
200
|
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
212
201
|
const tagRegex = new RegExp(`<${escapeRegex(name)}(?:\\s${ATTR_CONTENT})?>|<${escapeRegex(name)}(?:\\s${ATTR_CONTENT})?\\s*/>|${escapeRegex(closeTag)}`, 'g');
|
|
213
202
|
tagRegex.lastIndex = pos;
|
package/dist/ai/types.d.ts
CHANGED
|
@@ -216,16 +216,11 @@ export interface AIManifestBundle {
|
|
|
216
216
|
/** Top-level manifest for AI content */
|
|
217
217
|
export interface AIManifest {
|
|
218
218
|
/**
|
|
219
|
-
* When this content was generated, ISO-8601.
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
* under build-once-promote one artifact is built once and may be served months later, so a
|
|
225
|
-
* build clock describes the runner that produced it rather than the content, and anything
|
|
226
|
-
* reading it as "how fresh is this?" is misled by design. An adopter who has declared a build
|
|
227
|
-
* id has told us the date is not the identifying fact, so it is omitted rather than filled in
|
|
228
|
-
* with something arbitrary. Present unconditionally when neither env var is set.
|
|
219
|
+
* When this content was generated, ISO-8601. Absent when the manifest carries a `buildId`
|
|
220
|
+
* and no usable `SOURCE_DATE_EPOCH` (unset, blank, or malformed values are never replaced
|
|
221
|
+
* with a live clock): under build-once-promote a build clock describes the runner, not the
|
|
222
|
+
* content, and is misleading read as freshness once `buildId` says the artifact — not the
|
|
223
|
+
* date — is the identifying fact. Present unconditionally when neither env var is set.
|
|
229
224
|
*/
|
|
230
225
|
generated?: string;
|
|
231
226
|
/**
|
|
@@ -19,13 +19,13 @@ export interface BranchHealthData {
|
|
|
19
19
|
}
|
|
20
20
|
/** Response type for GET /admin/branch-health */
|
|
21
21
|
export type BranchHealthResponse = ApiResponse<BranchHealthData>;
|
|
22
|
-
|
|
22
|
+
interface PurgeBranchDirData {
|
|
23
23
|
/** The dot-prefixed name the directory was renamed to, e.g. `.trash-foo-20260101T000000Z`. */
|
|
24
24
|
trashedAs: string;
|
|
25
25
|
}
|
|
26
26
|
/** Response type for POST /admin/branch-dirs/:dirName/purge */
|
|
27
27
|
export type PurgeBranchDirResponse = ApiResponse<PurgeBranchDirData>;
|
|
28
|
-
|
|
28
|
+
interface RepairBranchDirData {
|
|
29
29
|
branch: BranchMetadata;
|
|
30
30
|
/** The archived corrupt file's name, e.g. `branch.json.corrupt-20260101T000000Z`. */
|
|
31
31
|
archivedAs: string;
|
|
@@ -48,26 +48,18 @@ export interface RepairBranchDirData {
|
|
|
48
48
|
}
|
|
49
49
|
/** Response type for POST /admin/branch-dirs/:dirName/repair-metadata */
|
|
50
50
|
export type RepairBranchDirResponse = ApiResponse<RepairBranchDirData>;
|
|
51
|
-
|
|
51
|
+
interface RepairedContentDuplicate {
|
|
52
52
|
id: string;
|
|
53
53
|
/** The path that was kept (the deterministic winner) -- untouched by this repair. */
|
|
54
54
|
keptPath: string;
|
|
55
55
|
/** Archived names the quarantined duplicate(s) were renamed to, dot-prefixed so future scans skip them. */
|
|
56
56
|
archivedAs: string[];
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
interface RepairContentDuplicatesData {
|
|
59
59
|
resolved: RepairedContentDuplicate[];
|
|
60
60
|
}
|
|
61
61
|
/** Response type for POST /admin/branch-dirs/:dirName/repair-content-duplicates */
|
|
62
62
|
export type RepairContentDuplicatesResponse = ApiResponse<RepairContentDuplicatesData>;
|
|
63
|
-
declare const branchDirParamsSchema: z.ZodObject<{
|
|
64
|
-
dirName: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
65
|
-
}, "strip", z.ZodTypeAny, {
|
|
66
|
-
dirName: string;
|
|
67
|
-
}, {
|
|
68
|
-
dirName: string;
|
|
69
|
-
}>;
|
|
70
|
-
export type BranchDirParams = z.infer<typeof branchDirParamsSchema>;
|
|
71
63
|
/**
|
|
72
64
|
* Exported routes, merged into ADMIN_ROUTES in admin.ts for a single
|
|
73
65
|
* router/generate-client import.
|
|
@@ -15,7 +15,7 @@ import { z } from 'zod';
|
|
|
15
15
|
import { simpleGit } from 'simple-git';
|
|
16
16
|
import { BranchMetadataFileManager, getBranchMetadataFileManager } from '../branch-metadata.js';
|
|
17
17
|
// Same constants the reader uses, rather than a second copy of the two string
|
|
18
|
-
// literals
|
|
18
|
+
// literals.
|
|
19
19
|
import { BRANCH_META_DIR, BRANCH_META_FILE } from '../branch-metadata-file.js';
|
|
20
20
|
import { scanBranchHealth } from '../branch-health.js';
|
|
21
21
|
import { ContentIdIndex } from '../content-id-index.js';
|
|
@@ -26,16 +26,10 @@ import { tryAcquireProvisioningLock } from '../utils/provisioning-lock.js';
|
|
|
26
26
|
import { withContentWriteLock, ContentWriteLockBusyError, DEFAULT_CONTENT_WRITE_LOCK_WAIT_MS, } from '../utils/content-write-lock.js';
|
|
27
27
|
import { getErrorMessage, isNodeError, isNotFoundError } from '../utils/error.js';
|
|
28
28
|
import { defineEndpoint } from './route-builder.js';
|
|
29
|
-
// ============================================================================
|
|
30
|
-
// Constants
|
|
31
|
-
// ============================================================================
|
|
32
29
|
/** [H1] A fresh (< 5 min old) init lock blocks purge -- provisioning may be running. */
|
|
33
30
|
const PROVISIONING_LOCK_FRESH_MS = 5 * 60_000;
|
|
34
31
|
/** An orphan dir younger than this may still be a clone in progress; corrupt dirs are exempt. */
|
|
35
32
|
const ORPHAN_YOUTH_THRESHOLD_MS = 15 * 60_000;
|
|
36
|
-
// ============================================================================
|
|
37
|
-
// Zod schemas
|
|
38
|
-
// ============================================================================
|
|
39
33
|
// Mirrors deleteTaskHandler's fileName pattern in admin.ts: conservative
|
|
40
34
|
// charset plus explicit traversal/dot-prefix refinements (the regex alone
|
|
41
35
|
// technically excludes '/' already, but the refinements keep intent explicit
|
|
@@ -46,9 +40,6 @@ const dirNameSchema = z
|
|
|
46
40
|
.refine((v) => !v.includes('..'), { message: 'dirName must not contain ..' })
|
|
47
41
|
.refine((v) => !v.startsWith('.'), { message: 'dirName must not be dot-prefixed' });
|
|
48
42
|
const branchDirParamsSchema = z.object({ dirName: dirNameSchema });
|
|
49
|
-
// ============================================================================
|
|
50
|
-
// Shared helpers
|
|
51
|
-
// ============================================================================
|
|
52
43
|
/** Compact UTC stamp for trash/archive names: `YYYYMMDDTHHMMSSZ` (no colons -- portability). */
|
|
53
44
|
function formatTrashStamp(date) {
|
|
54
45
|
return date
|
|
@@ -77,9 +68,6 @@ class RepairPreconditionError extends Error {
|
|
|
77
68
|
this.status = status;
|
|
78
69
|
}
|
|
79
70
|
}
|
|
80
|
-
// ============================================================================
|
|
81
|
-
// Handlers
|
|
82
|
-
// ============================================================================
|
|
83
71
|
const getBranchHealthHandler = async (_gc, ctx, _req) => {
|
|
84
72
|
// Same derivation services.ts uses to construct the BranchRegistry --
|
|
85
73
|
// admin handlers must agree with it or the scan silently looks at the
|
|
@@ -105,7 +93,7 @@ const getBranchHealthHandler = async (_gc, ctx, _req) => {
|
|
|
105
93
|
* sweeps trash older than 30 days, see cleanupTrashedBranchDirs in
|
|
106
94
|
* worker/rebase.ts).
|
|
107
95
|
*
|
|
108
|
-
* Safety rails
|
|
96
|
+
* Safety rails:
|
|
109
97
|
* - [always] the base branch directory can never be purged.
|
|
110
98
|
* - Server re-derives live/corrupt/orphan state itself -- never trusts the
|
|
111
99
|
* client's view of the world.
|
|
@@ -131,7 +119,7 @@ const purgeBranchDirHandler = async (_gc, ctx, _req, params) => {
|
|
|
131
119
|
if (!dirPath) {
|
|
132
120
|
return { ok: false, status: 400, error: 'Invalid directory name' };
|
|
133
121
|
}
|
|
134
|
-
//
|
|
122
|
+
// The directory must actually exist -- otherwise
|
|
135
123
|
// withOccFileLock's `mkdir -p` below would CREATE it, and purge would
|
|
136
124
|
// "succeed" with a phantom `.trash-*` entry for a directory that was
|
|
137
125
|
// never there. Must run before anything below treats "no branch.json" as
|
|
@@ -238,50 +226,29 @@ const purgeBranchDirHandler = async (_gc, ctx, _req, params) => {
|
|
|
238
226
|
};
|
|
239
227
|
/**
|
|
240
228
|
* Repair a corrupt branch.json by archiving it (forensics preserved as
|
|
241
|
-
* `branch.json.corrupt-{STAMP}
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
* -- a corrupt BASE branch.json is exactly the degraded-service scenario
|
|
245
|
-
* this handler exists to fix.
|
|
229
|
+
* `branch.json.corrupt-{STAMP}`) and recreating defaults via save(). Unlike
|
|
230
|
+
* purge, the base branch IS a valid target -- a corrupt BASE branch.json is
|
|
231
|
+
* exactly the degraded-service scenario this handler exists to fix.
|
|
246
232
|
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
* (
|
|
250
|
-
*
|
|
233
|
+
* Lock sequence: withOccFileLock is NOT reentrant and save() takes its own
|
|
234
|
+
* hold, so the archive rename must complete and the lock must be RELEASED
|
|
235
|
+
* before save() runs, or save() would deadlock against itself. The
|
|
236
|
+
* provisioning lock stays held across the whole archive+save sequence, same
|
|
237
|
+
* order as purge (provisioning -> branch.json) so the two operations can
|
|
238
|
+
* never deadlock each other; without that hold, a concurrent purge could
|
|
239
|
+
* trash the directory mid-sequence and have save() resurrect a
|
|
240
|
+
* metadata-only ghost of it.
|
|
251
241
|
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* save()'s defaults-merge sees no existing record once branch.json is
|
|
264
|
-
* archived out of the way, so a `submitted` (write-locked) branch comes back
|
|
265
|
-
* `editing` (unlocked), `access` ACLs are dropped to `{}`, and `createdBy`
|
|
266
|
-
* becomes the ADMIN RUNNING THIS REPAIR, not the branch's real creator. This
|
|
267
|
-
* handler deliberately does NOT attempt to recover those three fields from
|
|
268
|
-
* the corrupt file, even though it is sometimes technically "partially
|
|
269
|
-
* parseable" (e.g. valid JSON with a truncated tail, or a stray character
|
|
270
|
-
* breaking otherwise-valid JSON): branch.json is written via
|
|
271
|
-
* `writeOccJsonFile`, which is atomic (temp-file + rename/link, see
|
|
272
|
-
* utils/occ-json-write.ts), so a genuinely corrupt file on disk is not
|
|
273
|
-
* ordinary truncated-write debris -- it got that way some other, less
|
|
274
|
-
* predictable way. `status`/`access` are security-adjacent (branch
|
|
275
|
-
* protection and per-path ACLs); silently reinstating a best-effort guess
|
|
276
|
-
* parsed out of a file that failed strict JSON.parse risks resurrecting
|
|
277
|
-
* WRONG security state with no human review, which is worse than a clean,
|
|
278
|
-
* clearly-reported reset. The archived file (`archivedAs`) is preserved
|
|
279
|
-
* precisely so a human CAN recover the real values with full context (open
|
|
280
|
-
* it, cross-check the GitHub PR, ask the editor) -- that is the safe
|
|
281
|
-
* recovery path, not automation. What was missing before this fix was any
|
|
282
|
-
* signal that a reset happened at all; the `reset` field on the response
|
|
283
|
-
* closes that gap by always reporting the (new, defaulted) values for these
|
|
284
|
-
* three fields, so the admin knows to re-apply the ACL and re-submit.
|
|
242
|
+
* Reset, not recovered: save()'s defaults-merge sees no existing record once
|
|
243
|
+
* branch.json is archived, so `status`/`access`/`createdBy` reset to
|
|
244
|
+
* `editing`/`{}`/the admin running this repair, even when the corrupt file
|
|
245
|
+
* is partially parseable. `status`/`access` are security-adjacent, and a
|
|
246
|
+
* genuinely corrupt branch.json (writes are atomic, so it didn't get that
|
|
247
|
+
* way from an ordinary truncated write) is not safe to best-effort-parse: a
|
|
248
|
+
* wrong guess with no human review is worse than a clean reset. The archived
|
|
249
|
+
* file lets a human recover the real values with full context instead. The
|
|
250
|
+
* response's `reset` field reports that a reset happened, so an admin never
|
|
251
|
+
* mistakes the new defaults for recovered data.
|
|
285
252
|
*/
|
|
286
253
|
const repairBranchDirHandler = async (_gc, ctx, req, params) => {
|
|
287
254
|
const baseRoot = getDefaultBranchBase(ctx.services.config.mode);
|
|
@@ -289,7 +256,7 @@ const repairBranchDirHandler = async (_gc, ctx, req, params) => {
|
|
|
289
256
|
if (!dirPath) {
|
|
290
257
|
return { ok: false, status: 400, error: 'Invalid directory name' };
|
|
291
258
|
}
|
|
292
|
-
//
|
|
259
|
+
// Same stat guard as purge: the directory must actually
|
|
293
260
|
// exist, otherwise withOccFileLock's `mkdir -p` below would CREATE it.
|
|
294
261
|
const dirExists = await fs
|
|
295
262
|
.stat(dirPath)
|
|
@@ -522,12 +489,8 @@ const repairContentDuplicatesHandler = async (_gc, ctx, _req, params) => {
|
|
|
522
489
|
};
|
|
523
490
|
}
|
|
524
491
|
};
|
|
525
|
-
// ============================================================================
|
|
526
|
-
// Route definitions
|
|
527
|
-
// ============================================================================
|
|
528
492
|
/**
|
|
529
493
|
* Branch directory health scan (healthy/corrupt-metadata/orphan)
|
|
530
|
-
* GET /admin/branch-health
|
|
531
494
|
*/
|
|
532
495
|
const getBranchHealth = defineEndpoint({
|
|
533
496
|
namespace: 'admin',
|
|
@@ -542,7 +505,6 @@ const getBranchHealth = defineEndpoint({
|
|
|
542
505
|
});
|
|
543
506
|
/**
|
|
544
507
|
* Purge a corrupt-metadata or orphan branch directory (reversible trash-rename)
|
|
545
|
-
* POST /admin/branch-dirs/:dirName/purge
|
|
546
508
|
*/
|
|
547
509
|
const purgeBranchDir = defineEndpoint({
|
|
548
510
|
namespace: 'admin',
|
|
@@ -558,7 +520,6 @@ const purgeBranchDir = defineEndpoint({
|
|
|
558
520
|
});
|
|
559
521
|
/**
|
|
560
522
|
* Repair a corrupt branch.json by archiving it and recreating defaults
|
|
561
|
-
* POST /admin/branch-dirs/:dirName/repair-metadata
|
|
562
523
|
*/
|
|
563
524
|
const repairBranchDir = defineEndpoint({
|
|
564
525
|
namespace: 'admin',
|
|
@@ -586,9 +547,8 @@ const repairBranchDir = defineEndpoint({
|
|
|
586
547
|
/**
|
|
587
548
|
* Repair duplicate content IDs in a healthy branch's content tree by
|
|
588
549
|
* archiving the quarantined (losing) file(s) with a dot-prefixed name --
|
|
589
|
-
* see
|
|
550
|
+
* see the `ContentIdIndex` class doc and
|
|
590
551
|
* repairContentDuplicatesHandler's doc comment.
|
|
591
|
-
* POST /admin/branch-dirs/:dirName/repair-content-duplicates
|
|
592
552
|
*/
|
|
593
553
|
const repairContentDuplicates = defineEndpoint({
|
|
594
554
|
namespace: 'admin',
|
package/dist/api/admin.d.ts
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
import type { ApiResponse } from './types.js';
|
|
10
|
-
import type { Task, QueueStats, CorruptTaskFile } from '../
|
|
10
|
+
import type { Task, QueueStats, CorruptTaskFile } from '../task-queue/cms-task-queue.js';
|
|
11
11
|
import type { WorkerStatusReport } from '../types.js';
|
|
12
12
|
import type { OperatingMode } from '../operating-mode/index.js';
|
|
13
13
|
export type { BranchHealthResponse, PurgeBranchDirResponse, RepairBranchDirResponse, RepairContentDuplicatesResponse, } from './admin-branch-health.js';
|
|
14
|
-
|
|
14
|
+
type WorkerLivenessState = 'alive' | 'stale' | 'absent';
|
|
15
15
|
export interface WorkerLiveness {
|
|
16
16
|
/**
|
|
17
17
|
* 'absent' — the lock dir is removed on clean release, so this also covers
|
|
@@ -40,12 +40,12 @@ export interface AdminTasksData {
|
|
|
40
40
|
}
|
|
41
41
|
/** Response type for GET /admin/tasks/:status */
|
|
42
42
|
export type AdminTasksResponse = ApiResponse<AdminTasksData>;
|
|
43
|
-
|
|
43
|
+
interface AdminRetryTaskData {
|
|
44
44
|
newTaskId: string;
|
|
45
45
|
}
|
|
46
46
|
/** Response type for POST /admin/tasks/:taskId/retry */
|
|
47
47
|
export type AdminRetryTaskResponse = ApiResponse<AdminRetryTaskData>;
|
|
48
|
-
|
|
48
|
+
interface AdminDeleteTaskData {
|
|
49
49
|
deleted: true;
|
|
50
50
|
}
|
|
51
51
|
/** Response type for DELETE /admin/tasks/:status/:fileName */
|
|
@@ -61,14 +61,6 @@ declare const listAdminTasksParamsSchema: z.ZodObject<{
|
|
|
61
61
|
limit?: number | undefined;
|
|
62
62
|
}>;
|
|
63
63
|
export type ListAdminTasksParams = z.infer<typeof listAdminTasksParamsSchema>;
|
|
64
|
-
declare const retryTaskParamsSchema: z.ZodObject<{
|
|
65
|
-
taskId: z.ZodString;
|
|
66
|
-
}, "strip", z.ZodTypeAny, {
|
|
67
|
-
taskId: string;
|
|
68
|
-
}, {
|
|
69
|
-
taskId: string;
|
|
70
|
-
}>;
|
|
71
|
-
export type RetryTaskParams = z.infer<typeof retryTaskParamsSchema>;
|
|
72
64
|
declare const deleteTaskParamsSchema: z.ZodObject<{
|
|
73
65
|
status: z.ZodEnum<["pending", "failed", "corrupt"]>;
|
|
74
66
|
fileName: z.ZodEffects<z.ZodString, string, string>;
|
package/dist/api/admin.js
CHANGED
|
@@ -8,23 +8,20 @@
|
|
|
8
8
|
import fs from 'node:fs/promises';
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { z } from 'zod';
|
|
11
|
-
import { getQueueStats, listTasks, listCorruptTaskFiles, requeueFailedTask, } from '../
|
|
12
|
-
import { getTaskQueueDir } from '../
|
|
13
|
-
import { WORKER_STATUS_FILE } from '../
|
|
11
|
+
import { getQueueStats, listTasks, listCorruptTaskFiles, requeueFailedTask, } from '../task-queue/cms-task-queue.js';
|
|
12
|
+
import { getTaskQueueDir } from '../task-queue/task-queue-config.js';
|
|
13
|
+
import { WORKER_STATUS_FILE } from '../task-queue/worker-status.js';
|
|
14
14
|
import { defineEndpoint } from './route-builder.js';
|
|
15
15
|
import { getErrorMessage, isNotFoundError } from '../utils/error.js';
|
|
16
16
|
import { ADMIN_BRANCH_HEALTH_ROUTES } from './admin-branch-health.js';
|
|
17
|
-
// ============================================================================
|
|
18
|
-
// Worker lock liveness
|
|
19
|
-
// ============================================================================
|
|
20
17
|
/**
|
|
21
|
-
* 60_000 = DEFAULT_LOCK_STALE_MS in worker/cms-worker.ts, hardcoded
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* freshly-refreshed heartbeat
|
|
27
|
-
*
|
|
18
|
+
* 60_000 = DEFAULT_LOCK_STALE_MS in worker/cms-worker.ts, hardcoded rather
|
|
19
|
+
* than threaded through config: an adopter who overrides `lockStaleMs` skews
|
|
20
|
+
* this classification (the endpoint doesn't know the worker's actual
|
|
21
|
+
* config). +90_000 absorbs the EFS/NFS attribute-cache staleness window (see
|
|
22
|
+
* docs/concurrency.md's "Residual staleness windows" (A)), large enough that
|
|
23
|
+
* a freshly-refreshed heartbeat won't misreport as stale to a reader on a
|
|
24
|
+
* different host.
|
|
28
25
|
*/
|
|
29
26
|
const LIVENESS_THRESHOLD_MS = 60_000 + 90_000;
|
|
30
27
|
const DEFAULT_ADMIN_TASKS_LIMIT = 50;
|
|
@@ -103,9 +100,6 @@ async function getOldestPendingAgeMs(taskDir) {
|
|
|
103
100
|
}
|
|
104
101
|
return oldestMtimeMs === undefined ? undefined : Math.max(0, Date.now() - oldestMtimeMs);
|
|
105
102
|
}
|
|
106
|
-
// ============================================================================
|
|
107
|
-
// Zod Schemas for Validation
|
|
108
|
-
// ============================================================================
|
|
109
103
|
const adminTaskStatusSchema = z.enum(['pending', 'processing', 'completed', 'failed', 'corrupt']);
|
|
110
104
|
const listAdminTasksParamsSchema = z.object({
|
|
111
105
|
status: adminTaskStatusSchema,
|
|
@@ -129,9 +123,6 @@ const deleteTaskParamsSchema = z.object({
|
|
|
129
123
|
.regex(/^[A-Za-z0-9._-]{1,120}\.json$/)
|
|
130
124
|
.refine((v) => !v.includes('..'), { message: 'fileName must not contain ..' }),
|
|
131
125
|
});
|
|
132
|
-
// ============================================================================
|
|
133
|
-
// Handlers
|
|
134
|
-
// ============================================================================
|
|
135
126
|
const getAdminStatusHandler = async (_gc, ctx, _req) => {
|
|
136
127
|
const taskDir = getTaskQueueDir(ctx.services.config);
|
|
137
128
|
try {
|
|
@@ -248,12 +239,8 @@ const deleteTaskHandler = async (_gc, ctx, _req, params) => {
|
|
|
248
239
|
return { ok: false, status: 500, error: getErrorMessage(err) };
|
|
249
240
|
}
|
|
250
241
|
};
|
|
251
|
-
// ============================================================================
|
|
252
|
-
// Route Definitions with defineEndpoint
|
|
253
|
-
// ============================================================================
|
|
254
242
|
/**
|
|
255
243
|
* Task queue stats + worker liveness snapshot
|
|
256
|
-
* GET /admin/status
|
|
257
244
|
*/
|
|
258
245
|
const getAdminStatus = defineEndpoint({
|
|
259
246
|
namespace: 'admin',
|
|
@@ -274,7 +261,6 @@ const getAdminStatus = defineEndpoint({
|
|
|
274
261
|
});
|
|
275
262
|
/**
|
|
276
263
|
* List task files for a given status (or quarantined corrupt/ files)
|
|
277
|
-
* GET /admin/tasks/:status
|
|
278
264
|
*/
|
|
279
265
|
const listAdminTasks = defineEndpoint({
|
|
280
266
|
namespace: 'admin',
|
|
@@ -290,7 +276,6 @@ const listAdminTasks = defineEndpoint({
|
|
|
290
276
|
});
|
|
291
277
|
/**
|
|
292
278
|
* Requeue a failed task as a fresh pending task
|
|
293
|
-
* POST /admin/tasks/:taskId/retry
|
|
294
279
|
*/
|
|
295
280
|
const retryTask = defineEndpoint({
|
|
296
281
|
namespace: 'admin',
|
|
@@ -306,7 +291,6 @@ const retryTask = defineEndpoint({
|
|
|
306
291
|
});
|
|
307
292
|
/**
|
|
308
293
|
* Delete a task file from pending/, failed/, or corrupt/
|
|
309
|
-
* DELETE /admin/tasks/:status/:fileName
|
|
310
294
|
*/
|
|
311
295
|
const deleteTask = defineEndpoint({
|
|
312
296
|
namespace: 'admin',
|