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/api/content.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { z } from 'zod';
|
|
|
2
2
|
import type { ApiResponse } from './types.js';
|
|
3
3
|
import type { EntryValidationIssue } from '../config/index.js';
|
|
4
4
|
import { type Slug } from '../paths/index.js';
|
|
5
|
-
/** Response type for content read operations */
|
|
6
5
|
export type ContentReadResponse = ApiResponse<{
|
|
7
6
|
format: string;
|
|
8
7
|
data: Record<string, unknown>;
|
|
@@ -10,7 +9,6 @@ export type ContentReadResponse = ApiResponse<{
|
|
|
10
9
|
/** OCC version token: file mtime in ms. Pass back as `expectedVersion` on next write. */
|
|
11
10
|
version?: number;
|
|
12
11
|
}>;
|
|
13
|
-
/** Response type for content write operations */
|
|
14
12
|
export type ContentWriteResponse = ApiResponse<{
|
|
15
13
|
format: string;
|
|
16
14
|
data: Record<string, unknown>;
|
|
@@ -25,7 +23,6 @@ export type ContentWriteResponse = ApiResponse<{
|
|
|
25
23
|
*/
|
|
26
24
|
validationWarnings?: EntryValidationIssue[];
|
|
27
25
|
}>;
|
|
28
|
-
/** Response type for reference validation */
|
|
29
26
|
export type ReferenceValidationResponse = ApiResponse<{
|
|
30
27
|
valid: boolean;
|
|
31
28
|
errors?: Array<{
|
|
@@ -35,7 +32,6 @@ export type ReferenceValidationResponse = ApiResponse<{
|
|
|
35
32
|
error: string;
|
|
36
33
|
}>;
|
|
37
34
|
}>;
|
|
38
|
-
/** Response type for entry rename operations */
|
|
39
35
|
export type RenameEntryResponse = ApiResponse<{
|
|
40
36
|
newPath: string;
|
|
41
37
|
}>;
|
|
@@ -58,8 +54,6 @@ export interface ValidateReferencesBody {
|
|
|
58
54
|
export interface RenameEntryBody {
|
|
59
55
|
newSlug: string;
|
|
60
56
|
}
|
|
61
|
-
/** Response type for reference options - re-exported for convenience */
|
|
62
|
-
export type { ReferenceOptionsResponse } from './reference-options.js';
|
|
63
57
|
/**
|
|
64
58
|
* Exported routes for router registration
|
|
65
59
|
*/
|
package/dist/api/content.js
CHANGED
|
@@ -22,9 +22,7 @@ function parseApiPath(apiPath, contentRoot) {
|
|
|
22
22
|
* sentence rather than a wall of paths.
|
|
23
23
|
*/
|
|
24
24
|
const UNKNOWN_KEY_WARNING_LIMIT = 10;
|
|
25
|
-
|
|
26
|
-
// Zod Schemas for Validation
|
|
27
|
-
// ============================================================================
|
|
25
|
+
/** Re-exported for convenience. */
|
|
28
26
|
const readContentParamsSchema = z.object({
|
|
29
27
|
branch: branchNameSchema,
|
|
30
28
|
path: logicalPathSchema,
|
|
@@ -78,10 +76,8 @@ const readContentHandler = async (gc, ctx, req, params) => {
|
|
|
78
76
|
const store = new ContentStore(branchContext.branchRoot, flatSchema, {
|
|
79
77
|
contentRootName: ctx.services.config.contentRoot || 'content',
|
|
80
78
|
});
|
|
81
|
-
// Parse path segments: params.path is like "content/posts/hello"
|
|
82
79
|
const contentRoot = ctx.services.config.contentRoot || 'content';
|
|
83
80
|
const logicalPathSegments = parseApiPath(params.path, contentRoot);
|
|
84
|
-
// Use trivial path resolution
|
|
85
81
|
let schemaItem;
|
|
86
82
|
let slug;
|
|
87
83
|
let relativePath;
|
|
@@ -117,10 +113,8 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
|
|
|
117
113
|
const store = new ContentStore(branchContext.branchRoot, flatSchema, {
|
|
118
114
|
contentRootName: ctx.services.config.contentRoot || 'content',
|
|
119
115
|
});
|
|
120
|
-
// Parse path segments: params.path is like "content/posts/hello" or "posts/hello"
|
|
121
116
|
const contentRoot = ctx.services.config.contentRoot || 'content';
|
|
122
117
|
const logicalPathSegments = parseApiPath(params.path, contentRoot);
|
|
123
|
-
// Use trivial path resolution
|
|
124
118
|
let schemaItem;
|
|
125
119
|
let slug;
|
|
126
120
|
let relativePath;
|
|
@@ -139,21 +133,15 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
|
|
|
139
133
|
if (!access.allowed) {
|
|
140
134
|
return { ok: false, status: 403, error: 'Forbidden' };
|
|
141
135
|
}
|
|
142
|
-
//
|
|
143
|
-
//
|
|
136
|
+
// Authoritative schema validation at the write boundary (COMPOUND-2): the server re-checks
|
|
137
|
+
// required fields, type/format correctness, and non-empty required references (rules shared
|
|
138
|
+
// with the editor via validation/entry-validator), plus reference EXISTENCE and
|
|
139
|
+
// EntryTypeConfig.maxItems (SCH-H3) — so a direct API call can't bypass what the editor's form
|
|
140
|
+
// enforces client-side.
|
|
144
141
|
//
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
// plus reference EXISTENCE (server-only: reads the content ID index) and
|
|
149
|
-
// EntryTypeConfig.maxItems at the create boundary (SCH-H3).
|
|
150
|
-
//
|
|
151
|
-
// One narrow carve-out: the editor's create flow scaffolds a brand-new entry
|
|
152
|
-
// by writing entirely empty data (`{}` and an empty body) and only then lets
|
|
153
|
-
// the user fill the form — so a create scaffold (target file does not exist
|
|
154
|
-
// yet AND the payload is completely empty) skips field validation. Any write
|
|
155
|
-
// carrying actual data, and every write to an existing entry, is validated.
|
|
156
|
-
// ------------------------------------------------------------------
|
|
142
|
+
// Carve-out: a create scaffold (target doesn't exist yet, payload is entirely empty `{}`/no
|
|
143
|
+
// body) skips field validation, since the editor's create flow writes an empty scaffold before
|
|
144
|
+
// the user fills the form.
|
|
157
145
|
// Resolve the entry-type config the store will write with (mirrors ContentStore.write)
|
|
158
146
|
let entryTypeConfig;
|
|
159
147
|
let fields = [];
|
|
@@ -182,7 +170,7 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
|
|
|
182
170
|
// ContentStore.write() preserves it regardless of what's requested (see
|
|
183
171
|
// buildPaths in content-store.ts) — so resolving from params.entryType
|
|
184
172
|
// or the default here instead would let a direct API write validate a
|
|
185
|
-
// payload against the WRONG entry type's schema
|
|
173
|
+
// payload against the WRONG entry type's schema. The
|
|
186
174
|
// editor always sends the entry's real entryType, so this only changes
|
|
187
175
|
// behavior for non-editor callers.
|
|
188
176
|
const existingEntryType = await store.getExistingEntryType(schemaItem.logicalPath, slug);
|
|
@@ -212,19 +200,12 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
|
|
|
212
200
|
const isDataOnly = isDataOnlyFormat(body.format);
|
|
213
201
|
try {
|
|
214
202
|
const exists = await store.documentExists(schemaItem.logicalPath, slug);
|
|
215
|
-
// Create-intent guard
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
// before that validation (and the maxItems count below) even runs, so
|
|
222
|
-
// the error always names the real problem instead of a confusing
|
|
223
|
-
// "field is required" message or a bare conflict. store.write() also
|
|
224
|
-
// enforces this same guard itself, inside its per-entry lock against a
|
|
225
|
-
// fresh stat — that is the race-safe authoritative check; this early
|
|
226
|
-
// return is just a cheaper, clearer-messaged fast path for the common
|
|
227
|
-
// (non-racing) case.
|
|
203
|
+
// Create-intent guard: a create request (expectedVersion === null) against a slug that
|
|
204
|
+
// already has content must never silently overwrite it — short-circuit with 409 before field
|
|
205
|
+
// validation runs, so the error names the real problem instead of "field is required" or a
|
|
206
|
+
// bare conflict. store.write() re-enforces this itself inside its per-entry lock against a
|
|
207
|
+
// fresh stat (the race-safe authoritative check); this is just a cheaper fast path for the
|
|
208
|
+
// common case.
|
|
228
209
|
if (body.expectedVersion === null && exists) {
|
|
229
210
|
return {
|
|
230
211
|
ok: false,
|
|
@@ -232,18 +213,15 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
|
|
|
232
213
|
error: `An entry with slug "${slug}" already exists`,
|
|
233
214
|
};
|
|
234
215
|
}
|
|
235
|
-
// [SLUG] Create-only routability check
|
|
236
|
-
//
|
|
237
|
-
//
|
|
238
|
-
// `
|
|
239
|
-
//
|
|
240
|
-
//
|
|
241
|
-
// per-entry lock; this is the cheaper, clearer-messaged fast path — without it a create that
|
|
242
|
-
// is ALSO missing a required field reports the field, never the slug that is the real
|
|
243
|
-
// problem (same reasoning as the create-intent guard above).
|
|
216
|
+
// [SLUG] Create-only routability check: `writeContentParamsSchema.path`'s `parseLogicalPath`
|
|
217
|
+
// has no charset rule, and `ContentStore.resolvePath` only lowercases the slug — so this is
|
|
218
|
+
// the only place on the write chain that applies `parseSlug` (besides `renameEntry`'s
|
|
219
|
+
// `newSlug`). Without it, a non-routable slug like `my_post` would build and then 404 on
|
|
220
|
+
// every visit. `store.write()` re-enforces this inside its per-entry lock; this is the
|
|
221
|
+
// cheaper, clearer-messaged fast path.
|
|
244
222
|
//
|
|
245
|
-
// Create-only
|
|
246
|
-
//
|
|
223
|
+
// Create-only: an entry with an existing non-conforming slug must stay saveable and
|
|
224
|
+
// renameable, since renaming it is the only way to fix the build.
|
|
247
225
|
if (!exists) {
|
|
248
226
|
const routable = parseSlug(slug);
|
|
249
227
|
if (!routable.ok) {
|
|
@@ -255,11 +233,10 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
|
|
|
255
233
|
};
|
|
256
234
|
}
|
|
257
235
|
}
|
|
258
|
-
// SCH-H3: enforce maxItems server-side
|
|
259
|
-
//
|
|
260
|
-
//
|
|
261
|
-
//
|
|
262
|
-
// the guard's real target is the single-request direct-API bypass.
|
|
236
|
+
// SCH-H3: enforce maxItems server-side — the editor only gates its "Add" button, so a direct
|
|
237
|
+
// API create could otherwise exceed the cap. Best-effort under concurrency: count-then-create
|
|
238
|
+
// isn't atomic, so two simultaneous creates can still race past the cap; this guards the
|
|
239
|
+
// single-request bypass, not the race.
|
|
263
240
|
if (!exists && maxItems !== undefined && entryTypeName) {
|
|
264
241
|
const collectionPath = schemaItem.type === 'entry-type' ? schemaItem.parentPath : schemaItem.logicalPath;
|
|
265
242
|
const count = await store.countEntriesOfType(collectionPath, entryTypeName);
|
|
@@ -308,45 +285,24 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
|
|
|
308
285
|
// 'warning' issues are returned alongside the successful write.
|
|
309
286
|
let validationWarnings;
|
|
310
287
|
const validateEntry = ctx.services.config.validateEntry;
|
|
311
|
-
// Collapse resolved reference objects back to bare ID strings before
|
|
312
|
-
//
|
|
313
|
-
//
|
|
314
|
-
//
|
|
315
|
-
//
|
|
316
|
-
//
|
|
317
|
-
// unnormalized it lands in the content file verbatim — and because resolution only re-resolves
|
|
318
|
-
// a `typeof value === 'string'`, every later read passes the frozen snapshot through and every
|
|
319
|
-
// later save rewrites it. The reference is then permanently severed from its target: renaming
|
|
320
|
-
// or editing the target changes nothing, silently.
|
|
321
|
-
//
|
|
322
|
-
// The mechanism predates reference resolution reaching listings, but `includeBody` makes it
|
|
323
|
-
// materially worse — the snapshot now carries the target's entire prose — and `urlPath` adds a
|
|
324
|
-
// value that goes stale the moment the target is renamed. Normalizing here is schema-driven and
|
|
325
|
-
// idempotent: a payload that already holds ID strings is unchanged.
|
|
288
|
+
// Collapse resolved reference objects back to bare ID strings before persisting (the reference
|
|
289
|
+
// validator above gets its own copy). The editor's GET resolves references by default, so form
|
|
290
|
+
// state round-trips `{...target data, id, slug, collection, urlPath}` for each reference field;
|
|
291
|
+
// left unnormalized, a save would freeze that snapshot into the file (resolution only
|
|
292
|
+
// re-resolves plain ID strings), permanently severing the reference from its target. Idempotent:
|
|
293
|
+
// a payload that already holds ID strings is unchanged.
|
|
326
294
|
const normalizedData = body.data === undefined ? undefined : normalizeReferenceValues(fields, body.data);
|
|
327
|
-
//
|
|
328
|
-
//
|
|
329
|
-
//
|
|
330
|
-
//
|
|
331
|
-
//
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
335
|
-
//
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
//
|
|
339
|
-
// Run against normalizedData -- the shape that will actually be persisted -- so the report
|
|
340
|
-
// matches the bytes, and so a resolved reference collapsed back to an ID string cannot be
|
|
341
|
-
// mistaken for anything. A warning, never a rejection: the key is still written (with its
|
|
342
|
-
// comments, see utils/content-serialize.ts), it is just not editable and nothing reads it.
|
|
343
|
-
//
|
|
344
|
-
// ONE issue, not one per key. The editor joins every warning into a single non-auto-closing
|
|
345
|
-
// notification (useEntryManager.ts), so one-per-key repeated the same explanatory sentence
|
|
346
|
-
// once per stale key, on every save, for a condition that is permanent until someone edits the
|
|
347
|
-
// schema. The keys are listed in the message instead, capped so a schema-wide rename cannot
|
|
348
|
-
// produce an unreadable wall of text. Worded for who can actually act: an editor cannot remove
|
|
349
|
-
// a key the form does not render, and cannot change the schema.
|
|
295
|
+
// Computed before the validateEntry hook and the entry-link scan too, not just the write, so
|
|
296
|
+
// every consumer agrees on the same bytes — otherwise an adopter's hook could see a resolved
|
|
297
|
+
// object while the file got an ID string, depending on whether the post came from the editor.
|
|
298
|
+
// Keys with no counterpart in the schema: validateEntryData iterates the SCHEMA, so it can't
|
|
299
|
+
// catch the inverse — a renamed/reshaped field whose old key lingers on disk forever, silently
|
|
300
|
+
// read back as `undefined`. Checked against normalizedData (the bytes that will actually be
|
|
301
|
+
// persisted) so a resolved reference collapsed to an ID string isn't mistaken for a stray key.
|
|
302
|
+
// A warning, never a rejection: the key is kept in the file, just unread and uneditable — an
|
|
303
|
+
// editor can't remove a key the form doesn't render or change the schema. One issue listing all
|
|
304
|
+
// stale keys (capped), not one per key, since the editor renders warnings as a single
|
|
305
|
+
// notification (useEntryManager.ts).
|
|
350
306
|
if (normalizedData !== undefined) {
|
|
351
307
|
const unknownKeys = findUnknownKeys(fields, normalizedData);
|
|
352
308
|
if (unknownKeys.length > 0) {
|
|
@@ -420,8 +376,7 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
|
|
|
420
376
|
// Reuses the entry-type fields resolved above for schema validation. Folded into
|
|
421
377
|
// `validationWarnings` (not a separate `entryLinkWarnings` field) so the editor's one
|
|
422
378
|
// save-warnings notification (useEntryManager.ts) is the single place any save-time
|
|
423
|
-
// warning surfaces
|
|
424
|
-
// with no consumer anywhere in the editor, so it was silently discarded.
|
|
379
|
+
// warning surfaces.
|
|
425
380
|
const idIndex = await store.idIndex();
|
|
426
381
|
const linkValidation = validateEntryLinks(normalizedData ?? {}, fields, idIndex, body.body);
|
|
427
382
|
if (linkValidation.warnings.length > 0) {
|
|
@@ -436,39 +391,27 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
|
|
|
436
391
|
}
|
|
437
392
|
catch (err) {
|
|
438
393
|
if (err instanceof ContentConflictError) {
|
|
439
|
-
// [SYNC-C1] Not an editor
|
|
440
|
-
//
|
|
441
|
-
//
|
|
442
|
-
// lock compromised mid-write, where the write DID land but we can no
|
|
443
|
-
// longer prove it was exclusive. Each case carries its own message
|
|
444
|
-
// (retry vs. reload-then-decide), so pass it through -- checked first,
|
|
445
|
-
// since the generic branches below would otherwise blame another editor.
|
|
394
|
+
// [SYNC-C1] Not an editor collision: the branch is mid-rebase. Usually the write was
|
|
395
|
+
// refused outright, but a lock compromised mid-write can still land it — each case carries
|
|
396
|
+
// its own message, so pass `err.message` through rather than the generic conflict below.
|
|
446
397
|
if (err instanceof BranchSyncingError) {
|
|
447
398
|
return { ok: false, status: 409, error: err.message };
|
|
448
399
|
}
|
|
449
|
-
// [F1] Also not an editor
|
|
450
|
-
//
|
|
451
|
-
//
|
|
452
|
-
//
|
|
453
|
-
// to reload and retry, which cannot help and would have them hammering
|
|
454
|
-
// a save that stays refused until an admin runs repair-content-duplicates.
|
|
400
|
+
// [F1] Also not an editor collision: this content ID is quarantined on two files
|
|
401
|
+
// (ContentIdIndex's duplicate-ID detection). The generic message below would send the
|
|
402
|
+
// editor into a reload-and-retry loop that can't help until an admin runs
|
|
403
|
+
// repair-content-duplicates, so surface this error's own message instead.
|
|
455
404
|
if (err instanceof DuplicateContentIdError) {
|
|
456
405
|
return { ok: false, status: 409, error: err.message };
|
|
457
406
|
}
|
|
458
|
-
// [URL] Also not an editor
|
|
459
|
-
//
|
|
460
|
-
//
|
|
461
|
-
// exists is a DIFFERENT entry claiming the same URL -- a sibling
|
|
462
|
-
// collection's index entry, or the parent entry this index entry would
|
|
463
|
-
// collide with. Falling through would tell the editor to look for an
|
|
464
|
-
// entry that is not there, and discard the one message that names the
|
|
465
|
-
// actual offender and what to do about it.
|
|
407
|
+
// [URL] Also not an editor collision, and not a same-slug conflict either — a DIFFERENT
|
|
408
|
+
// entry (a sibling collection's index entry, or this one's parent) claims the same URL.
|
|
409
|
+
// Surface its own message rather than telling the editor to look for an entry that exists.
|
|
466
410
|
if (err instanceof UrlPathConflictError) {
|
|
467
411
|
return { ok: false, status: 409, error: err.message };
|
|
468
412
|
}
|
|
469
|
-
//
|
|
470
|
-
//
|
|
471
|
-
// between that check and store.write()'s in-lock stat.
|
|
413
|
+
// Race-safe fallback: the early `exists` check above catches the common case; this covers a
|
|
414
|
+
// collision that lands between that check and store.write()'s in-lock stat.
|
|
472
415
|
if (body.expectedVersion === null) {
|
|
473
416
|
return {
|
|
474
417
|
ok: false,
|
|
@@ -482,12 +425,9 @@ const writeContentHandler = async (gc, ctx, req, params, body) => {
|
|
|
482
425
|
error: 'Content conflict: entry was modified by another editor',
|
|
483
426
|
};
|
|
484
427
|
}
|
|
485
|
-
// C2: a ContentStoreError is
|
|
486
|
-
//
|
|
487
|
-
//
|
|
488
|
-
// as the client's mistake; rethrow so it surfaces as a 500 (see
|
|
489
|
-
// readContentHandler's store.read() catch above, which already follows
|
|
490
|
-
// this same pattern).
|
|
428
|
+
// C2: a ContentStoreError is an expected client fault (bad slug, validation, etc.) and keeps
|
|
429
|
+
// its 400. Anything else — ENOSPC, EACCES, a bug — is a genuine server fault and must not be
|
|
430
|
+
// mislabeled as the client's mistake; rethrow so it surfaces as a 500.
|
|
491
431
|
if (err instanceof ContentStoreError) {
|
|
492
432
|
return { ok: false, status: 400, error: sanitizeErrorMessage(err.message) };
|
|
493
433
|
}
|
|
@@ -500,7 +440,6 @@ const validateReferencesHandler = async (gc, ctx, req, params, body) => {
|
|
|
500
440
|
const store = new ContentStore(branchContext.branchRoot, flatSchema, {
|
|
501
441
|
contentRootName: ctx.services.config.contentRoot || 'content',
|
|
502
442
|
});
|
|
503
|
-
// Parse path segments to get collection/schema info
|
|
504
443
|
const contentRoot = ctx.services.config.contentRoot || 'content';
|
|
505
444
|
const logicalPathSegments = parseApiPath(params.path, contentRoot);
|
|
506
445
|
let schemaItem;
|
|
@@ -522,7 +461,6 @@ const validateReferencesHandler = async (gc, ctx, req, params, body) => {
|
|
|
522
461
|
}
|
|
523
462
|
// Get ID index (automatically loads if needed)
|
|
524
463
|
const idIndex = await store.idIndex();
|
|
525
|
-
// Resolve fields from entry type schema
|
|
526
464
|
let fields = [];
|
|
527
465
|
if (schemaItem.type === 'entry-type') {
|
|
528
466
|
fields = schemaItem.schema;
|
|
@@ -551,7 +489,6 @@ const validateReferencesHandler = async (gc, ctx, req, params, body) => {
|
|
|
551
489
|
}
|
|
552
490
|
fields = entryTypeConfig.schema || [];
|
|
553
491
|
}
|
|
554
|
-
// Validate references
|
|
555
492
|
const validator = new ReferenceValidator(idIndex, fields, (name) => store.resolveCollectionItem(name)?.logicalPath);
|
|
556
493
|
const result = await validator.validate(body.data);
|
|
557
494
|
return {
|
|
@@ -569,10 +506,8 @@ const renameEntryHandler = async (gc, ctx, req, params, body) => {
|
|
|
569
506
|
const store = new ContentStore(branchContext.branchRoot, flatSchema, {
|
|
570
507
|
contentRootName: ctx.services.config.contentRoot || 'content',
|
|
571
508
|
});
|
|
572
|
-
// Parse path segments
|
|
573
509
|
const contentRoot = ctx.services.config.contentRoot || 'content';
|
|
574
510
|
const logicalPathSegments = parseApiPath(params.path, contentRoot);
|
|
575
|
-
// Resolve to collection and slug
|
|
576
511
|
let schemaItem;
|
|
577
512
|
let currentSlug;
|
|
578
513
|
let relativePath;
|
|
@@ -587,25 +522,19 @@ const renameEntryHandler = async (gc, ctx, req, params, body) => {
|
|
|
587
522
|
const message = err instanceof ContentStoreError ? err.message : 'Invalid content request';
|
|
588
523
|
return { ok: false, status: 400, error: sanitizeErrorMessage(message) };
|
|
589
524
|
}
|
|
590
|
-
// Check edit permission on current path
|
|
591
525
|
const access = await ctx.services.checkContentAccess(branchContext, branchContext.branchRoot, relativePath, req.user, 'edit');
|
|
592
526
|
if (!access.allowed) {
|
|
593
527
|
return { ok: false, status: 403, error: 'Forbidden' };
|
|
594
528
|
}
|
|
595
|
-
// Rename the entry
|
|
596
529
|
try {
|
|
597
530
|
const result = await store.renameEntry(schemaItem.logicalPath, currentSlug, body.newSlug);
|
|
598
531
|
return { ok: true, status: 200, data: { newPath: result.newPath } };
|
|
599
532
|
}
|
|
600
533
|
catch (err) {
|
|
601
|
-
// [SYNC-C1]
|
|
602
|
-
// because the request was bad -- 409 + retry, never a 400.
|
|
534
|
+
// [SYNC-C1] Mid-rebase, not a bad request -- 409 + retry, never 400.
|
|
603
535
|
if (err instanceof ContentConflictError) {
|
|
604
|
-
// [URL] A contested-URL refusal
|
|
605
|
-
//
|
|
606
|
-
// here -- the rename stays refused until they pick a different slug or
|
|
607
|
-
// remove the other claimant -- which is exactly the loop
|
|
608
|
-
// UrlPathConflictError's doc comment exists to prevent.
|
|
536
|
+
// [URL] A contested-URL refusal needs its own message: the generic one below tells the
|
|
537
|
+
// editor to reload and retry, which can't succeed until they pick a different slug.
|
|
609
538
|
const passThrough = err instanceof BranchSyncingError || err instanceof UrlPathConflictError;
|
|
610
539
|
return {
|
|
611
540
|
ok: false,
|
|
@@ -613,19 +542,14 @@ const renameEntryHandler = async (gc, ctx, req, params, body) => {
|
|
|
613
542
|
error: passThrough ? err.message : 'Content conflict: entry was modified by another editor',
|
|
614
543
|
};
|
|
615
544
|
}
|
|
616
|
-
// C2: same
|
|
617
|
-
//
|
|
618
|
-
// genuine server fault and must surface as a 500, not get mislabeled as
|
|
619
|
-
// "Rename failed" (the client's mistake).
|
|
545
|
+
// C2: same rule as writeContentHandler's catch above (ContentStoreError -> 400, everything
|
|
546
|
+
// else -> 500).
|
|
620
547
|
if (err instanceof ContentStoreError) {
|
|
621
548
|
return { ok: false, status: 400, error: sanitizeErrorMessage(err.message) };
|
|
622
549
|
}
|
|
623
550
|
throw err;
|
|
624
551
|
}
|
|
625
552
|
};
|
|
626
|
-
// ============================================================================
|
|
627
|
-
// Route Definitions with defineEndpoint
|
|
628
|
-
// ============================================================================
|
|
629
553
|
/**
|
|
630
554
|
* Read content using path-based routing
|
|
631
555
|
* GET /:branch/content/:path*
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pagination constants for the entries list endpoint.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* browser bundle can import the page-size cap without pulling in `entries.ts`
|
|
6
|
-
* and its `node:fs`-backed transitive deps. `entries.ts` re-exports these for
|
|
7
|
-
* API-surface discoverability.
|
|
2
|
+
* Pagination constants for the entries list endpoint. Kept dependency-free (no server-only
|
|
3
|
+
* imports) so the editor's browser bundle can import the page-size cap without pulling in
|
|
4
|
+
* `entries.ts` and its `node:fs`-backed deps; `entries.ts` re-exports these for API discoverability.
|
|
8
5
|
*/
|
|
9
6
|
/**
|
|
10
|
-
* Maximum entries the list endpoint returns per request
|
|
11
|
-
*
|
|
12
|
-
* silently drift from the server's cap.
|
|
7
|
+
* Maximum entries the list endpoint returns per request; larger `limit` values are clamped to
|
|
8
|
+
* this so paginating clients never silently drift from the server's cap.
|
|
13
9
|
*/
|
|
14
10
|
export declare const MAX_ENTRIES_PER_PAGE = 200;
|
|
15
11
|
/** Default page size when a request omits `limit`. */
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pagination constants for the entries list endpoint.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* browser bundle can import the page-size cap without pulling in `entries.ts`
|
|
6
|
-
* and its `node:fs`-backed transitive deps. `entries.ts` re-exports these for
|
|
7
|
-
* API-surface discoverability.
|
|
2
|
+
* Pagination constants for the entries list endpoint. Kept dependency-free (no server-only
|
|
3
|
+
* imports) so the editor's browser bundle can import the page-size cap without pulling in
|
|
4
|
+
* `entries.ts` and its `node:fs`-backed deps; `entries.ts` re-exports these for API discoverability.
|
|
8
5
|
*/
|
|
9
6
|
/**
|
|
10
|
-
* Maximum entries the list endpoint returns per request
|
|
11
|
-
*
|
|
12
|
-
* silently drift from the server's cap.
|
|
7
|
+
* Maximum entries the list endpoint returns per request; larger `limit` values are clamped to
|
|
8
|
+
* this so paginating clients never silently drift from the server's cap.
|
|
13
9
|
*/
|
|
14
10
|
export const MAX_ENTRIES_PER_PAGE = 200;
|
|
15
11
|
/** Default page size when a request omits `limit`. */
|
package/dist/api/entries.d.ts
CHANGED
|
@@ -2,10 +2,10 @@ import { z } from 'zod';
|
|
|
2
2
|
import type { ContentFormat } from '../config/index.js';
|
|
3
3
|
import type { ApiResponse } from './types.js';
|
|
4
4
|
import type { LogicalPath, PhysicalPath, Slug, ContentId } from '../paths/types.js';
|
|
5
|
-
export { MAX_ENTRIES_PER_PAGE, DEFAULT_ENTRIES_LIMIT } from './entries-constants.js';
|
|
6
5
|
/**
|
|
7
6
|
* Summary of an entry type for client display.
|
|
8
7
|
* Simplified from EntryTypeConfig - doesn't include full field definitions.
|
|
8
|
+
* @internal No importer; deletion candidate in knip-no-importer-deletion-candidates.md.
|
|
9
9
|
*/
|
|
10
10
|
export interface EntryTypeSummary {
|
|
11
11
|
name: string;
|
|
@@ -28,6 +28,7 @@ export interface CollectionItem {
|
|
|
28
28
|
exists?: boolean;
|
|
29
29
|
canEdit?: boolean;
|
|
30
30
|
}
|
|
31
|
+
/** @internal No importer; deletion candidate in knip-no-importer-deletion-candidates.md. */
|
|
31
32
|
export interface ListEntriesParams {
|
|
32
33
|
branch: string;
|
|
33
34
|
collection?: LogicalPath;
|
|
@@ -49,6 +50,7 @@ export type EntriesResponse = ApiResponse<ListEntriesResponse>;
|
|
|
49
50
|
/**
|
|
50
51
|
* List entries for a branch
|
|
51
52
|
* GET /:branch/entries
|
|
53
|
+
* @internal Exported for tests.
|
|
52
54
|
*/
|
|
53
55
|
export declare const listEntries: import("./route-builder.js").RouteDefinition<z.ZodObject<{
|
|
54
56
|
branch: z.ZodType<import("../paths/index.js").BranchName, z.ZodTypeDef, import("../paths/index.js").BranchName>;
|
|
@@ -81,21 +83,14 @@ export type DeleteEntryResponse = ApiResponse<{
|
|
|
81
83
|
deleted: boolean;
|
|
82
84
|
contentId?: string;
|
|
83
85
|
/**
|
|
84
|
-
* Set when the entry
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* the same "warn, don't fail" precedent on the write path). The order
|
|
89
|
-
* array still contains the now-nonexistent id until a later schema
|
|
90
|
-
* mutation cleans it up.
|
|
86
|
+
* Set when the entry deleted successfully but the collection's order array couldn't be updated
|
|
87
|
+
* afterward (C6: best-effort hygiene after the delete, so its failure must not present as a
|
|
88
|
+
* failed delete — see content.ts's `validationWarnings`). The order array keeps the
|
|
89
|
+
* now-nonexistent id until the next schema mutation cleans it up.
|
|
91
90
|
*/
|
|
92
91
|
warning?: string;
|
|
93
92
|
}>;
|
|
94
|
-
/**
|
|
95
|
-
* Delete an entry
|
|
96
|
-
* DELETE /:branch/entries/...entryPath
|
|
97
|
-
* Note: Uses catch-all to support paths with slashes (e.g., content/posts/hello-world)
|
|
98
|
-
*/
|
|
93
|
+
/** @internal Exported for tests. */
|
|
99
94
|
export declare const deleteEntry: import("./route-builder.js").RouteDefinition<z.ZodObject<{
|
|
100
95
|
branch: z.ZodType<import("../paths/index.js").BranchName, z.ZodTypeDef, import("../paths/index.js").BranchName>;
|
|
101
96
|
entryPath: z.ZodType<LogicalPath, z.ZodTypeDef, LogicalPath>;
|