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/paths/resolve.js
CHANGED
|
@@ -2,40 +2,23 @@
|
|
|
2
2
|
* Path resolution utilities for converting between physical and logical paths.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
* Resolve a physical collection path
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* while logical paths are schema-defined (e.g., "content/authors").
|
|
9
|
-
*
|
|
10
|
-
* This function matches physical path segments to logical path segments,
|
|
11
|
-
* accounting for ID suffixes in physical paths.
|
|
12
|
-
*
|
|
13
|
-
* @param physicalPath - The physical filesystem path with embedded IDs
|
|
14
|
-
* @param schemaItems - Iterable of schema items to search
|
|
15
|
-
* @returns The matching logical path, or the physical path if no match found
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* // Match physical to logical
|
|
19
|
-
* resolveLogicalPath("content/authors.q52DCVPuH4ga", schemaItems)
|
|
20
|
-
* // Returns: "content/authors"
|
|
5
|
+
* Resolve a physical collection path (segments carry embedded IDs, e.g.
|
|
6
|
+
* "content/authors.q52DCVPuH4ga") to its schema-defined logical path
|
|
7
|
+
* ("content/authors"), or back to the physical path when nothing matches.
|
|
21
8
|
*
|
|
22
9
|
* @example
|
|
23
|
-
* // Nested collections
|
|
24
10
|
* resolveLogicalPath("content/docs.ABC/api.DEF", schemaItems)
|
|
25
11
|
* // Returns: "content/docs/api"
|
|
12
|
+
* @internal Exported for tests.
|
|
26
13
|
*/
|
|
27
14
|
export function resolveLogicalPath(physicalPath, schemaItems) {
|
|
28
15
|
const pathSegments = physicalPath.split('/');
|
|
29
16
|
for (const schemaItem of schemaItems) {
|
|
30
17
|
if (schemaItem.type === 'collection') {
|
|
31
18
|
const logicalSegments = schemaItem.logicalPath.split('/');
|
|
32
|
-
// Check if all logical segments match the corresponding physical segments
|
|
33
|
-
// (ignoring the ID part after the dot in directory names)
|
|
34
19
|
if (pathSegments.length === logicalSegments.length) {
|
|
35
20
|
const matches = logicalSegments.every((logicalSeg, i) => {
|
|
36
21
|
const physicalSeg = pathSegments[i];
|
|
37
|
-
// Physical segment might have ID: "authors.q52DCVPuH4ga"
|
|
38
|
-
// Logical segment: "authors"
|
|
39
22
|
// Match if identical OR if physical starts with logical + '.'
|
|
40
23
|
return physicalSeg === logicalSeg || physicalSeg.startsWith(logicalSeg + '.');
|
|
41
24
|
});
|
|
@@ -45,6 +28,5 @@ export function resolveLogicalPath(physicalPath, schemaItems) {
|
|
|
45
28
|
}
|
|
46
29
|
}
|
|
47
30
|
}
|
|
48
|
-
// Fallback: return the physical path if we can't find a match
|
|
49
31
|
return physicalPath;
|
|
50
32
|
}
|
package/dist/paths/types.d.ts
CHANGED
|
@@ -1,62 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* mixing logical paths (content/posts/my-post) with physical filesystem
|
|
6
|
-
* paths (content/posts/my-post.ABC123.mdx).
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* A logical content path without embedded IDs.
|
|
10
|
-
* Used in APIs, URLs, and user-facing contexts.
|
|
11
|
-
* Example: "content/posts/my-post"
|
|
2
|
+
* Branded path types. The brands exist to stop logical paths
|
|
3
|
+
* (content/posts/my-post) being passed where physical filesystem paths
|
|
4
|
+
* (content/posts/my-post.ABC123.mdx) are expected, and vice versa.
|
|
12
5
|
*/
|
|
6
|
+
/** A content path with no embedded IDs, as APIs and URLs carry it. */
|
|
13
7
|
export type LogicalPath = string & {
|
|
14
8
|
readonly __brand: 'LogicalPath';
|
|
15
9
|
};
|
|
16
|
-
/**
|
|
17
|
-
* A physical filesystem path that may contain embedded IDs.
|
|
18
|
-
* Used for actual file operations.
|
|
19
|
-
* Example: "content/posts/my-post.ABC123.mdx"
|
|
20
|
-
*/
|
|
10
|
+
/** A filesystem path, which may carry embedded IDs, as file operations need. */
|
|
21
11
|
export type PhysicalPath = string & {
|
|
22
12
|
readonly __brand: 'PhysicalPath';
|
|
23
13
|
};
|
|
24
|
-
/**
|
|
25
|
-
* A branch name that has been sanitized for filesystem use.
|
|
26
|
-
*/
|
|
14
|
+
/** A branch name already sanitized for filesystem use. */
|
|
27
15
|
export type SanitizedBranchName = string & {
|
|
28
16
|
readonly __brand: 'SanitizedBranchName';
|
|
29
17
|
};
|
|
30
|
-
/**
|
|
31
|
-
* A git branch name (before sanitization for filesystem use).
|
|
32
|
-
* Example: "feature/add-dark-mode" or "main"
|
|
33
|
-
*/
|
|
18
|
+
/** A git branch name, not yet sanitized: "feature/add-dark-mode", "main". */
|
|
34
19
|
export type BranchName = string & {
|
|
35
20
|
readonly __brand: 'BranchName';
|
|
36
21
|
};
|
|
37
22
|
/**
|
|
38
|
-
* A 12-character Base58
|
|
39
|
-
*
|
|
40
|
-
* Example: "bChqT78gcaLd"
|
|
23
|
+
* A 12-character Base58 content ID ("bChqT78gcaLd"), which uniquely identifies
|
|
24
|
+
* an entry or collection within a filename.
|
|
41
25
|
*/
|
|
42
26
|
export type ContentId = string & {
|
|
43
27
|
readonly __brand: 'ContentId';
|
|
44
28
|
};
|
|
45
29
|
/**
|
|
46
|
-
* Sentinel ContentId for the root content directory
|
|
47
|
-
*
|
|
30
|
+
* Sentinel ContentId for the root content directory, whose name carries no
|
|
31
|
+
* embedded ID. Underscores cannot collide with Base58 IDs, which exclude `_`.
|
|
48
32
|
*/
|
|
49
33
|
export declare const ROOT_COLLECTION_ID: ContentId;
|
|
50
|
-
/**
|
|
51
|
-
* A validated, lowercase slug used for collections and entries.
|
|
52
|
-
* Example: "posts", "my-first-post", "getting-started"
|
|
53
|
-
*/
|
|
34
|
+
/** A validated, lowercase collection or entry slug: "my-first-post". */
|
|
54
35
|
export type Slug = string & {
|
|
55
36
|
readonly __brand: 'Slug';
|
|
56
37
|
};
|
|
57
|
-
/**
|
|
58
|
-
* Path validation result.
|
|
59
|
-
*/
|
|
60
38
|
export interface PathValidationResult {
|
|
61
39
|
valid: boolean;
|
|
62
40
|
error?: string;
|
package/dist/paths/types.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* mixing logical paths (content/posts/my-post) with physical filesystem
|
|
6
|
-
* paths (content/posts/my-post.ABC123.mdx).
|
|
2
|
+
* Branded path types. The brands exist to stop logical paths
|
|
3
|
+
* (content/posts/my-post) being passed where physical filesystem paths
|
|
4
|
+
* (content/posts/my-post.ABC123.mdx) are expected, and vice versa.
|
|
7
5
|
*/
|
|
8
6
|
/**
|
|
9
|
-
* Sentinel ContentId for the root content directory
|
|
10
|
-
*
|
|
7
|
+
* Sentinel ContentId for the root content directory, whose name carries no
|
|
8
|
+
* embedded ID. Underscores cannot collide with Base58 IDs, which exclude `_`.
|
|
11
9
|
*/
|
|
12
10
|
export const ROOT_COLLECTION_ID = '__rootcoll__';
|
|
@@ -1,82 +1,40 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Path validation utilities.
|
|
3
|
-
*
|
|
4
|
-
* Security-focused validation for content paths and slugs.
|
|
5
|
-
*/
|
|
1
|
+
/** Security-focused validation for content paths, IDs, branch names and slugs. */
|
|
6
2
|
import type { LogicalPath, PhysicalPath, ContentId, BranchName, Slug } from './types.js';
|
|
7
3
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* @param path - The path to validate
|
|
11
|
-
* @param rootPath - The root directory (for traversal check)
|
|
12
|
-
* @returns Validation result
|
|
4
|
+
* Reject a content path that traverses, or that escapes `rootPath`.
|
|
5
|
+
* @internal Exported for tests.
|
|
13
6
|
*/
|
|
14
7
|
export declare function validateContentPath(path: string, rootPath: string): {
|
|
15
8
|
valid: boolean;
|
|
16
9
|
error?: string;
|
|
17
10
|
};
|
|
18
11
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* @param collectionPath - The collection path to validate
|
|
22
|
-
* @returns true if valid, false otherwise
|
|
12
|
+
* A collection path must be non-empty, traversal-free, and `[A-Za-z0-9_/-]+`.
|
|
13
|
+
* @internal Exported for tests.
|
|
23
14
|
*/
|
|
24
15
|
export declare function isValidCollectionPath(collectionPath: string): boolean;
|
|
25
16
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* @param input - The string to sanitize
|
|
29
|
-
* @returns Sanitized string safe for path use
|
|
17
|
+
* Strip the characters that make a string unsafe as a path component.
|
|
18
|
+
* @internal Exported for tests.
|
|
30
19
|
*/
|
|
31
20
|
export declare function sanitizeForPath(input: string): string;
|
|
32
21
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* Physical paths have segments with embedded 12-char IDs:
|
|
36
|
-
* - `post.my-slug.abc123def456.json` (entry file)
|
|
37
|
-
* - `posts.abc123def456` (collection directory)
|
|
38
|
-
*
|
|
39
|
-
* @param segment - A single path segment (no slashes)
|
|
40
|
-
* @returns true if segment contains embedded ID pattern
|
|
22
|
+
* Whether a single path segment (no slashes) carries an embedded content ID.
|
|
23
|
+
* @internal Exported for tests.
|
|
41
24
|
*/
|
|
42
25
|
export declare function hasEmbeddedContentId(segment: string): boolean;
|
|
43
26
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* Logical paths do not have embedded IDs:
|
|
50
|
-
* - `content/posts/hello` or `posts/hello`
|
|
51
|
-
*
|
|
52
|
-
* @param path - The path to check
|
|
53
|
-
* @returns true if any segment contains an embedded content ID
|
|
27
|
+
* Whether any segment carries an embedded content ID:
|
|
28
|
+
* `content/posts.abc123/post.hello.def456.json` does, `content/posts/hello`
|
|
29
|
+
* does not.
|
|
30
|
+
* @internal Exported for tests.
|
|
54
31
|
*/
|
|
55
32
|
export declare function looksLikePhysicalPath(path: string): boolean;
|
|
56
|
-
/**
|
|
57
|
-
* Check if a path appears to be a logical path (no embedded content IDs).
|
|
58
|
-
*
|
|
59
|
-
* @param path - The path to check
|
|
60
|
-
* @returns true if no segments contain embedded content IDs
|
|
61
|
-
*/
|
|
33
|
+
/** @internal Exported for tests. */
|
|
62
34
|
export declare function looksLikeLogicalPath(path: string): boolean;
|
|
63
35
|
/**
|
|
64
|
-
* Validate and cast
|
|
65
|
-
*
|
|
66
|
-
* Use this at API boundaries to validate incoming path strings
|
|
67
|
-
* and cast them to the branded LogicalPath type.
|
|
68
|
-
*
|
|
69
|
-
* @param path - The path string to validate
|
|
70
|
-
* @returns Object with success flag and either the typed path or an error
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```ts
|
|
74
|
-
* const result = parseLogicalPath(params.collectionPath)
|
|
75
|
-
* if (!result.ok) {
|
|
76
|
-
* return { ok: false, status: 400, error: result.error }
|
|
77
|
-
* }
|
|
78
|
-
* const collectionPath: LogicalPath = result.path
|
|
79
|
-
* ```
|
|
36
|
+
* Validate an incoming path string at an API boundary and cast it to the
|
|
37
|
+
* branded LogicalPath type.
|
|
80
38
|
*/
|
|
81
39
|
export declare function parseLogicalPath(path: string): {
|
|
82
40
|
ok: true;
|
|
@@ -86,13 +44,9 @@ export declare function parseLogicalPath(path: string): {
|
|
|
86
44
|
error: string;
|
|
87
45
|
};
|
|
88
46
|
/**
|
|
89
|
-
* Validate and cast
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* and cast them to the branded PhysicalPath type.
|
|
93
|
-
*
|
|
94
|
-
* @param path - The path string to validate
|
|
95
|
-
* @returns Object with success flag and either the typed path or an error
|
|
47
|
+
* Validate an incoming path string at an API boundary and cast it to the
|
|
48
|
+
* branded PhysicalPath type.
|
|
49
|
+
* @internal Exported for tests.
|
|
96
50
|
*/
|
|
97
51
|
export declare function parsePhysicalPath(path: string): {
|
|
98
52
|
ok: true;
|
|
@@ -101,29 +55,8 @@ export declare function parsePhysicalPath(path: string): {
|
|
|
101
55
|
ok: false;
|
|
102
56
|
error: string;
|
|
103
57
|
};
|
|
104
|
-
/**
|
|
105
|
-
* Check if a string is a valid 12-character content ID.
|
|
106
|
-
*
|
|
107
|
-
* @param id - The string to check
|
|
108
|
-
* @returns true if valid Base58 12-char ID
|
|
109
|
-
*/
|
|
110
58
|
export declare function isValidContentId(id: string): boolean;
|
|
111
|
-
/**
|
|
112
|
-
* Parse and validate a ContentId from a string.
|
|
113
|
-
* Validates Base58 format and 12-character length.
|
|
114
|
-
*
|
|
115
|
-
* @param id - The string to validate
|
|
116
|
-
* @returns Object with success flag and either the typed ID or an error
|
|
117
|
-
*
|
|
118
|
-
* @example
|
|
119
|
-
* ```ts
|
|
120
|
-
* const result = parseContentId(fileId)
|
|
121
|
-
* if (!result.ok) {
|
|
122
|
-
* throw new Error(result.error)
|
|
123
|
-
* }
|
|
124
|
-
* const contentId: ContentId = result.id
|
|
125
|
-
* ```
|
|
126
|
-
*/
|
|
59
|
+
/** Validate a string as a 12-character Base58 ContentId and cast it. */
|
|
127
60
|
export declare function parseContentId(id: string): {
|
|
128
61
|
ok: true;
|
|
129
62
|
id: ContentId;
|
|
@@ -131,22 +64,7 @@ export declare function parseContentId(id: string): {
|
|
|
131
64
|
ok: false;
|
|
132
65
|
error: string;
|
|
133
66
|
};
|
|
134
|
-
/**
|
|
135
|
-
* Parse and validate a BranchName.
|
|
136
|
-
* Checks git branch naming rules.
|
|
137
|
-
*
|
|
138
|
-
* @param name - The branch name to validate
|
|
139
|
-
* @returns Object with success flag and either the typed name or an error
|
|
140
|
-
*
|
|
141
|
-
* @example
|
|
142
|
-
* ```ts
|
|
143
|
-
* const result = parseBranchName(params.branch)
|
|
144
|
-
* if (!result.ok) {
|
|
145
|
-
* return { ok: false, status: 400, error: result.error }
|
|
146
|
-
* }
|
|
147
|
-
* const branchName: BranchName = result.name
|
|
148
|
-
* ```
|
|
149
|
-
*/
|
|
67
|
+
/** Validate a branch name against git's ref rules and cast it to BranchName. */
|
|
150
68
|
export declare function parseBranchName(name: string): {
|
|
151
69
|
ok: true;
|
|
152
70
|
name: BranchName;
|
|
@@ -154,22 +72,7 @@ export declare function parseBranchName(name: string): {
|
|
|
154
72
|
ok: false;
|
|
155
73
|
error: string;
|
|
156
74
|
};
|
|
157
|
-
/**
|
|
158
|
-
* Parse and validate a slug (collection or entry).
|
|
159
|
-
* Validates format and length constraints.
|
|
160
|
-
*
|
|
161
|
-
* @param slug - The slug to validate
|
|
162
|
-
* @returns Object with success flag and either the typed slug or an error
|
|
163
|
-
*
|
|
164
|
-
* @example
|
|
165
|
-
* ```ts
|
|
166
|
-
* const result = parseSlug(params.slug)
|
|
167
|
-
* if (!result.ok) {
|
|
168
|
-
* return { ok: false, status: 400, error: result.error }
|
|
169
|
-
* }
|
|
170
|
-
* const slug: Slug = result.slug
|
|
171
|
-
* ```
|
|
172
|
-
*/
|
|
75
|
+
/** Validate a collection or entry slug and cast it to Slug. */
|
|
173
76
|
export declare function parseSlug(slug: string): {
|
|
174
77
|
ok: true;
|
|
175
78
|
slug: Slug;
|
package/dist/paths/validation.js
CHANGED
|
@@ -1,41 +1,25 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Path validation utilities.
|
|
3
|
-
*
|
|
4
|
-
* Security-focused validation for content paths and slugs.
|
|
5
|
-
*/
|
|
1
|
+
/** Security-focused validation for content paths, IDs, branch names and slugs. */
|
|
6
2
|
import { normalizeFilesystemPath, hasTraversalSequence } from './normalize.js';
|
|
7
|
-
/**
|
|
8
|
-
* Base58 alphabet used for content IDs (excludes ambiguous: 0, O, I, l)
|
|
9
|
-
*/
|
|
3
|
+
/** Base58 alphabet for content IDs: excludes the ambiguous 0, O, I and l. */
|
|
10
4
|
const BASE58_PATTERN = '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]';
|
|
11
|
-
/**
|
|
12
|
-
* Pattern matching exactly a 12-character content ID
|
|
13
|
-
*/
|
|
14
5
|
const CONTENT_ID_PATTERN = new RegExp(`^${BASE58_PATTERN}{12}$`);
|
|
15
6
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* - `post.my-slug.abc123def456.json` (entry)
|
|
19
|
-
* - `posts.abc123def456` (collection directory)
|
|
7
|
+
* A physical path segment carries an embedded ID: `posts.abc123def456` for a
|
|
8
|
+
* collection directory, `post.my-slug.abc123def456.json` for an entry file.
|
|
20
9
|
*/
|
|
21
10
|
const PHYSICAL_SEGMENT_PATTERN = new RegExp(`\\.${BASE58_PATTERN}{12}(?:\\.[a-z]+)?$`);
|
|
22
11
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* @param path - The path to validate
|
|
26
|
-
* @param rootPath - The root directory (for traversal check)
|
|
27
|
-
* @returns Validation result
|
|
12
|
+
* Reject a content path that traverses, or that escapes `rootPath`.
|
|
13
|
+
* @internal Exported for tests.
|
|
28
14
|
*/
|
|
29
15
|
export function validateContentPath(path, rootPath) {
|
|
30
16
|
const normalized = normalizeFilesystemPath(path);
|
|
31
|
-
// Check for traversal sequences
|
|
32
17
|
if (hasTraversalSequence(normalized)) {
|
|
33
18
|
return { valid: false, error: 'Path contains traversal sequence' };
|
|
34
19
|
}
|
|
35
|
-
// Check path doesn't escape root
|
|
36
20
|
const normalizedRoot = normalizeFilesystemPath(rootPath);
|
|
37
21
|
if (!normalized.startsWith(normalizedRoot) && normalized !== normalizedRoot) {
|
|
38
|
-
//
|
|
22
|
+
// Not already rooted: re-check as a path relative to the root.
|
|
39
23
|
const normalizedPath = `${normalizedRoot}/${normalized}`;
|
|
40
24
|
if (hasTraversalSequence(normalizedPath)) {
|
|
41
25
|
return { valid: false, error: 'Path escapes root directory' };
|
|
@@ -44,29 +28,23 @@ export function validateContentPath(path, rootPath) {
|
|
|
44
28
|
return { valid: true };
|
|
45
29
|
}
|
|
46
30
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* @param collectionPath - The collection path to validate
|
|
50
|
-
* @returns true if valid, false otherwise
|
|
31
|
+
* A collection path must be non-empty, traversal-free, and `[A-Za-z0-9_/-]+`.
|
|
32
|
+
* @internal Exported for tests.
|
|
51
33
|
*/
|
|
52
34
|
export function isValidCollectionPath(collectionPath) {
|
|
53
35
|
if (!collectionPath || collectionPath.length === 0) {
|
|
54
36
|
return false;
|
|
55
37
|
}
|
|
56
|
-
// Normalize and check for traversal
|
|
57
38
|
const normalized = normalizeFilesystemPath(collectionPath);
|
|
58
39
|
if (hasTraversalSequence(normalized)) {
|
|
59
40
|
return false;
|
|
60
41
|
}
|
|
61
|
-
// Collection paths should only contain alphanumeric, hyphens, underscores, and forward slashes
|
|
62
42
|
const validPattern = /^[a-zA-Z0-9_/-]+$/;
|
|
63
43
|
return validPattern.test(normalized);
|
|
64
44
|
}
|
|
65
45
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* @param input - The string to sanitize
|
|
69
|
-
* @returns Sanitized string safe for path use
|
|
46
|
+
* Strip the characters that make a string unsafe as a path component.
|
|
47
|
+
* @internal Exported for tests.
|
|
70
48
|
*/
|
|
71
49
|
export function sanitizeForPath(input) {
|
|
72
50
|
return input
|
|
@@ -76,73 +54,39 @@ export function sanitizeForPath(input) {
|
|
|
76
54
|
.trim();
|
|
77
55
|
}
|
|
78
56
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* Physical paths have segments with embedded 12-char IDs:
|
|
82
|
-
* - `post.my-slug.abc123def456.json` (entry file)
|
|
83
|
-
* - `posts.abc123def456` (collection directory)
|
|
84
|
-
*
|
|
85
|
-
* @param segment - A single path segment (no slashes)
|
|
86
|
-
* @returns true if segment contains embedded ID pattern
|
|
57
|
+
* Whether a single path segment (no slashes) carries an embedded content ID.
|
|
58
|
+
* @internal Exported for tests.
|
|
87
59
|
*/
|
|
88
60
|
export function hasEmbeddedContentId(segment) {
|
|
89
61
|
return PHYSICAL_SEGMENT_PATTERN.test(segment);
|
|
90
62
|
}
|
|
91
63
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* Logical paths do not have embedded IDs:
|
|
98
|
-
* - `content/posts/hello` or `posts/hello`
|
|
99
|
-
*
|
|
100
|
-
* @param path - The path to check
|
|
101
|
-
* @returns true if any segment contains an embedded content ID
|
|
64
|
+
* Whether any segment carries an embedded content ID:
|
|
65
|
+
* `content/posts.abc123/post.hello.def456.json` does, `content/posts/hello`
|
|
66
|
+
* does not.
|
|
67
|
+
* @internal Exported for tests.
|
|
102
68
|
*/
|
|
103
69
|
export function looksLikePhysicalPath(path) {
|
|
104
70
|
const segments = path.split('/');
|
|
105
71
|
return segments.some(hasEmbeddedContentId);
|
|
106
72
|
}
|
|
107
|
-
/**
|
|
108
|
-
* Check if a path appears to be a logical path (no embedded content IDs).
|
|
109
|
-
*
|
|
110
|
-
* @param path - The path to check
|
|
111
|
-
* @returns true if no segments contain embedded content IDs
|
|
112
|
-
*/
|
|
73
|
+
/** @internal Exported for tests. */
|
|
113
74
|
export function looksLikeLogicalPath(path) {
|
|
114
75
|
return !looksLikePhysicalPath(path);
|
|
115
76
|
}
|
|
116
77
|
/**
|
|
117
|
-
* Validate and cast
|
|
118
|
-
*
|
|
119
|
-
* Use this at API boundaries to validate incoming path strings
|
|
120
|
-
* and cast them to the branded LogicalPath type.
|
|
121
|
-
*
|
|
122
|
-
* @param path - The path string to validate
|
|
123
|
-
* @returns Object with success flag and either the typed path or an error
|
|
124
|
-
*
|
|
125
|
-
* @example
|
|
126
|
-
* ```ts
|
|
127
|
-
* const result = parseLogicalPath(params.collectionPath)
|
|
128
|
-
* if (!result.ok) {
|
|
129
|
-
* return { ok: false, status: 400, error: result.error }
|
|
130
|
-
* }
|
|
131
|
-
* const collectionPath: LogicalPath = result.path
|
|
132
|
-
* ```
|
|
78
|
+
* Validate an incoming path string at an API boundary and cast it to the
|
|
79
|
+
* branded LogicalPath type.
|
|
133
80
|
*/
|
|
134
81
|
export function parseLogicalPath(path) {
|
|
135
|
-
// Basic validation
|
|
136
82
|
if (!path || typeof path !== 'string') {
|
|
137
83
|
return { ok: false, error: 'Path is required' };
|
|
138
84
|
}
|
|
139
|
-
//
|
|
85
|
+
// One separator in the branded value, as in parsePermissionPath.
|
|
140
86
|
const normalized = path.replace(/\\/g, '/');
|
|
141
|
-
// Security check
|
|
142
87
|
if (hasTraversalSequence(normalized)) {
|
|
143
88
|
return { ok: false, error: 'Path contains traversal sequence' };
|
|
144
89
|
}
|
|
145
|
-
// Check it's not a physical path
|
|
146
90
|
if (looksLikePhysicalPath(normalized)) {
|
|
147
91
|
return {
|
|
148
92
|
ok: false,
|
|
@@ -152,26 +96,19 @@ export function parseLogicalPath(path) {
|
|
|
152
96
|
return { ok: true, path: normalized };
|
|
153
97
|
}
|
|
154
98
|
/**
|
|
155
|
-
* Validate and cast
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
* and cast them to the branded PhysicalPath type.
|
|
159
|
-
*
|
|
160
|
-
* @param path - The path string to validate
|
|
161
|
-
* @returns Object with success flag and either the typed path or an error
|
|
99
|
+
* Validate an incoming path string at an API boundary and cast it to the
|
|
100
|
+
* branded PhysicalPath type.
|
|
101
|
+
* @internal Exported for tests.
|
|
162
102
|
*/
|
|
163
103
|
export function parsePhysicalPath(path) {
|
|
164
|
-
// Basic validation
|
|
165
104
|
if (!path || typeof path !== 'string') {
|
|
166
105
|
return { ok: false, error: 'Path is required' };
|
|
167
106
|
}
|
|
168
|
-
//
|
|
107
|
+
// One separator in the branded value, as in parseLogicalPath.
|
|
169
108
|
const normalized = path.replace(/\\/g, '/');
|
|
170
|
-
// Security check
|
|
171
109
|
if (hasTraversalSequence(normalized)) {
|
|
172
110
|
return { ok: false, error: 'Path contains traversal sequence' };
|
|
173
111
|
}
|
|
174
|
-
// Check it looks like a physical path
|
|
175
112
|
if (!looksLikePhysicalPath(normalized)) {
|
|
176
113
|
return {
|
|
177
114
|
ok: false,
|
|
@@ -180,31 +117,10 @@ export function parsePhysicalPath(path) {
|
|
|
180
117
|
}
|
|
181
118
|
return { ok: true, path: normalized };
|
|
182
119
|
}
|
|
183
|
-
/**
|
|
184
|
-
* Check if a string is a valid 12-character content ID.
|
|
185
|
-
*
|
|
186
|
-
* @param id - The string to check
|
|
187
|
-
* @returns true if valid Base58 12-char ID
|
|
188
|
-
*/
|
|
189
120
|
export function isValidContentId(id) {
|
|
190
121
|
return CONTENT_ID_PATTERN.test(id);
|
|
191
122
|
}
|
|
192
|
-
/**
|
|
193
|
-
* Parse and validate a ContentId from a string.
|
|
194
|
-
* Validates Base58 format and 12-character length.
|
|
195
|
-
*
|
|
196
|
-
* @param id - The string to validate
|
|
197
|
-
* @returns Object with success flag and either the typed ID or an error
|
|
198
|
-
*
|
|
199
|
-
* @example
|
|
200
|
-
* ```ts
|
|
201
|
-
* const result = parseContentId(fileId)
|
|
202
|
-
* if (!result.ok) {
|
|
203
|
-
* throw new Error(result.error)
|
|
204
|
-
* }
|
|
205
|
-
* const contentId: ContentId = result.id
|
|
206
|
-
* ```
|
|
207
|
-
*/
|
|
123
|
+
/** Validate a string as a 12-character Base58 ContentId and cast it. */
|
|
208
124
|
export function parseContentId(id) {
|
|
209
125
|
if (!id || typeof id !== 'string') {
|
|
210
126
|
return { ok: false, error: 'Content ID is required' };
|
|
@@ -217,22 +133,7 @@ export function parseContentId(id) {
|
|
|
217
133
|
}
|
|
218
134
|
return { ok: true, id: id };
|
|
219
135
|
}
|
|
220
|
-
/**
|
|
221
|
-
* Parse and validate a BranchName.
|
|
222
|
-
* Checks git branch naming rules.
|
|
223
|
-
*
|
|
224
|
-
* @param name - The branch name to validate
|
|
225
|
-
* @returns Object with success flag and either the typed name or an error
|
|
226
|
-
*
|
|
227
|
-
* @example
|
|
228
|
-
* ```ts
|
|
229
|
-
* const result = parseBranchName(params.branch)
|
|
230
|
-
* if (!result.ok) {
|
|
231
|
-
* return { ok: false, status: 400, error: result.error }
|
|
232
|
-
* }
|
|
233
|
-
* const branchName: BranchName = result.name
|
|
234
|
-
* ```
|
|
235
|
-
*/
|
|
136
|
+
/** Validate a branch name against git's ref rules and cast it to BranchName. */
|
|
236
137
|
export function parseBranchName(name) {
|
|
237
138
|
if (!name || typeof name !== 'string') {
|
|
238
139
|
return { ok: false, error: 'Branch name is required' };
|
|
@@ -241,7 +142,6 @@ export function parseBranchName(name) {
|
|
|
241
142
|
if (name.length > 250) {
|
|
242
143
|
return { ok: false, error: 'Branch name too long (max 250 characters)' };
|
|
243
144
|
}
|
|
244
|
-
// Git branch name rules
|
|
245
145
|
if (name.includes('..')) {
|
|
246
146
|
return { ok: false, error: 'Branch name cannot contain ".."' };
|
|
247
147
|
}
|
|
@@ -257,16 +157,14 @@ export function parseBranchName(name) {
|
|
|
257
157
|
if (name.startsWith('-')) {
|
|
258
158
|
return { ok: false, error: 'Branch name cannot start with "-"' };
|
|
259
159
|
}
|
|
260
|
-
// Additional git restrictions
|
|
261
160
|
if (name.startsWith('.') || name.endsWith('.')) {
|
|
262
161
|
return { ok: false, error: 'Branch name cannot start or end with a dot' };
|
|
263
162
|
}
|
|
264
163
|
if (name.includes('@{')) {
|
|
265
164
|
return { ok: false, error: 'Branch name cannot contain "@{"' };
|
|
266
165
|
}
|
|
267
|
-
// Bare
|
|
268
|
-
//
|
|
269
|
-
// contain these as a substring, e.g. "release-HEAD" or "HEADer").
|
|
166
|
+
// Bare "HEAD" and "@" are ambiguous shorthand for the current ref, not real
|
|
167
|
+
// branch names. Names merely containing them ("release-HEAD") stay legal.
|
|
270
168
|
if (name === 'HEAD' || name === '@') {
|
|
271
169
|
return { ok: false, error: 'Branch name cannot be the reserved ref "HEAD" or "@"' };
|
|
272
170
|
}
|
|
@@ -280,22 +178,7 @@ export function parseBranchName(name) {
|
|
|
280
178
|
}
|
|
281
179
|
return { ok: true, name: name };
|
|
282
180
|
}
|
|
283
|
-
/**
|
|
284
|
-
* Parse and validate a slug (collection or entry).
|
|
285
|
-
* Validates format and length constraints.
|
|
286
|
-
*
|
|
287
|
-
* @param slug - The slug to validate
|
|
288
|
-
* @returns Object with success flag and either the typed slug or an error
|
|
289
|
-
*
|
|
290
|
-
* @example
|
|
291
|
-
* ```ts
|
|
292
|
-
* const result = parseSlug(params.slug)
|
|
293
|
-
* if (!result.ok) {
|
|
294
|
-
* return { ok: false, status: 400, error: result.error }
|
|
295
|
-
* }
|
|
296
|
-
* const slug: Slug = result.slug
|
|
297
|
-
* ```
|
|
298
|
-
*/
|
|
181
|
+
/** Validate a collection or entry slug and cast it to Slug. */
|
|
299
182
|
export function parseSlug(slug) {
|
|
300
183
|
if (!slug) {
|
|
301
184
|
return {
|
|
@@ -307,7 +190,6 @@ export function parseSlug(slug) {
|
|
|
307
190
|
if (slug.length > 64) {
|
|
308
191
|
return { ok: false, error: 'Slug too long (max 64 characters)' };
|
|
309
192
|
}
|
|
310
|
-
// Check for path separators and traversal
|
|
311
193
|
if (slug.includes('/') || slug.includes('\\')) {
|
|
312
194
|
return {
|
|
313
195
|
ok: false,
|