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/content-tree.d.ts
CHANGED
|
@@ -1,55 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Content tree builder for adopters
|
|
2
|
+
* Content tree builder for adopters: walks the schema + filesystem and returns a tree of
|
|
3
|
+
* content nodes for navigation, sitemaps, search indexes, breadcrumbs.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Nodes carry Canopy's structural facts (logicalPath, contentId, collection
|
|
8
|
-
* metadata, entry metadata). Display concerns like labels are left to the
|
|
9
|
-
* adopter via the `extract` callback.
|
|
5
|
+
* Nodes carry Canopy's structural facts (logicalPath, contentId, collection metadata, entry
|
|
6
|
+
* metadata); display concerns like labels are left to the adopter's `extract` callback.
|
|
10
7
|
*/
|
|
11
8
|
import type { FlatSchemaItem, ContentFormat } from './config/index.js';
|
|
12
9
|
/**
|
|
13
|
-
* Adopter-supplied registry mapping entry type names (as they appear in
|
|
14
|
-
*
|
|
10
|
+
* Adopter-supplied registry mapping entry type names (as they appear in filenames:
|
|
11
|
+
* `partner.index.yaml` → `'partner'`) to their data shapes.
|
|
15
12
|
*
|
|
16
|
-
* Pair with `TypeFromEntrySchema<typeof yourSchema>` to derive shapes from
|
|
17
|
-
*
|
|
13
|
+
* Pair with `TypeFromEntrySchema<typeof yourSchema>` to derive shapes from schemas you have
|
|
14
|
+
* already defined — no redeclaration needed.
|
|
18
15
|
*
|
|
19
16
|
* @example
|
|
20
17
|
* ```ts
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* const partnerSchema = defineEntrySchema([
|
|
24
|
-
* { name: 'name', type: 'string', isTitle: true },
|
|
25
|
-
* { name: 'tagline', type: 'string' },
|
|
26
|
-
* ])
|
|
27
|
-
* const docSchema = defineEntrySchema([
|
|
28
|
-
* { name: 'title', type: 'string' },
|
|
29
|
-
* ])
|
|
30
|
-
*
|
|
18
|
+
* const partnerSchema = defineEntrySchema([{ name: 'name', type: 'string', isTitle: true }])
|
|
31
19
|
* interface MyEntries {
|
|
32
20
|
* partner: TypeFromEntrySchema<typeof partnerSchema>
|
|
33
|
-
* doc: TypeFromEntrySchema<typeof docSchema>
|
|
34
21
|
* }
|
|
35
22
|
*
|
|
36
|
-
* const canopy = await getCanopyForBuild()
|
|
37
23
|
* await canopy.buildContentTree<NavFields, MyEntries>({
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* return { name: '' }
|
|
44
|
-
* },
|
|
24
|
+
* // meta.indexEntry.data is narrowed to the partner shape
|
|
25
|
+
* extract: (data, meta) =>
|
|
26
|
+
* meta.kind === 'collection' && meta.indexEntry?.entryType === 'partner'
|
|
27
|
+
* ? { name: meta.indexEntry.data.name }
|
|
28
|
+
* : { name: '' },
|
|
45
29
|
* })
|
|
46
30
|
* ```
|
|
47
31
|
*/
|
|
48
32
|
export type EntryTypeMap = Record<string, object>;
|
|
49
33
|
/**
|
|
50
|
-
* Default TEntryTypes when an adopter hasn't supplied one.
|
|
51
|
-
*
|
|
52
|
-
* stays `Record<string, unknown>`, useful for unstructured access without
|
|
34
|
+
* Default TEntryTypes when an adopter hasn't supplied one. The index signature keeps
|
|
35
|
+
* `meta.indexEntry.data` as `Record<string, unknown>`, useful for unstructured access without
|
|
53
36
|
* opting in to the discriminated-union pattern. Exported so callers wrapping
|
|
54
37
|
* `buildContentTree` (e.g. CanopyBuildContext) share the same default.
|
|
55
38
|
*/
|
|
@@ -68,15 +51,14 @@ export interface ContentTreeExtractMeta<TEntryTypes = DefaultEntryTypes> {
|
|
|
68
51
|
/** Content format — present when kind is 'entry'. */
|
|
69
52
|
format?: ContentFormat;
|
|
70
53
|
/**
|
|
71
|
-
* The entry with slug 'index' inside a collection, when present
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* at the maxDepth cap (entries aren't loaded there).
|
|
54
|
+
* The entry with slug 'index' inside a collection, when present — the collection's
|
|
55
|
+
* "identity" under the directory-as-page pattern (a partner's metadata for
|
|
56
|
+
* /data-catalog/<partner>/, a section landing for /docs/<section>/). Populated only when
|
|
57
|
+
* kind === 'collection' AND such an entry exists; undefined for collections at the maxDepth
|
|
58
|
+
* cap, where entries are not loaded.
|
|
77
59
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
60
|
+
* With TEntryTypes supplied this is a discriminated union: narrow on `indexEntry.entryType`
|
|
61
|
+
* and `data` is typed accordingly.
|
|
80
62
|
*/
|
|
81
63
|
indexEntry?: {
|
|
82
64
|
[K in keyof TEntryTypes & string]: {
|
|
@@ -119,24 +101,18 @@ export interface BuildContentTreeOptions<T = unknown, TEntryTypes = DefaultEntry
|
|
|
119
101
|
/** Starting collection path. Defaults to content root. */
|
|
120
102
|
rootPath?: string;
|
|
121
103
|
/**
|
|
122
|
-
* Extract typed custom fields from each node's raw data.
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* Supply TEntryTypes to get narrowed access to `meta.indexEntry.data`
|
|
127
|
-
* via discriminated-union narrowing on `meta.indexEntry.entryType`.
|
|
104
|
+
* Extract typed custom fields from each node's raw data. For entries, data is frontmatter +
|
|
105
|
+
* body (md/mdx) or the parsed object; for collections it is `{ name, label }` from the
|
|
106
|
+
* schema. Supply TEntryTypes for narrowed access to `meta.indexEntry.data`.
|
|
128
107
|
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* side effects (logging, counters, populating an external index) will see
|
|
132
|
-
* those rejected nodes too.
|
|
108
|
+
* Must be a pure mapping: it may be invoked on entry nodes that `filter` later removes (the
|
|
109
|
+
* tree-walk extracts, then filters), so side effects see those rejected nodes too.
|
|
133
110
|
*/
|
|
134
111
|
extract?: (data: Record<string, unknown>, meta: ContentTreeExtractMeta<TEntryTypes>) => T;
|
|
135
112
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* or entry reads beneath the rejected node).
|
|
113
|
+
* Return false to exclude a node and its descendants. Runs after extract, so `fields` is
|
|
114
|
+
* available. Rejecting a collection short-circuits descendant traversal — no recursion into
|
|
115
|
+
* child collections, no entry reads beneath it.
|
|
140
116
|
*/
|
|
141
117
|
filter?: (node: ContentTreeNode<T>) => boolean;
|
|
142
118
|
/**
|
|
@@ -144,20 +120,11 @@ export interface BuildContentTreeOptions<T = unknown, TEntryTypes = DefaultEntry
|
|
|
144
120
|
* with it. To extend rather than replace the default behavior, call the exported
|
|
145
121
|
* `defaultBuildPath(logicalPath, contentRootName, kind)` from inside your
|
|
146
122
|
* function and post-process its result (see `canopycms/server`).
|
|
147
|
-
*
|
|
148
|
-
* Default behavior (`defaultBuildPath`):
|
|
149
|
-
* - Strips the `{contentRootName}/` prefix from `logicalPath`.
|
|
150
|
-
* - For entries: collapses an `index` slug to its parent collection's path
|
|
151
|
-
* (`content/guides/index` → `/guides`, not `/guides/index`); a collection
|
|
152
|
-
* literally named `index` is unaffected (only entries collapse).
|
|
153
|
-
* - Lowercases the entire result.
|
|
154
|
-
* - Prepends `/`; the content root's own index collapses to `/`.
|
|
155
123
|
*/
|
|
156
124
|
buildPath?: (logicalPath: LogicalPath, kind: 'collection' | 'entry') => string;
|
|
157
125
|
/**
|
|
158
|
-
* Custom sort for children at each level
|
|
159
|
-
*
|
|
160
|
-
* Runs after extract + filter, so `fields` is available.
|
|
126
|
+
* Custom sort for children at each level; replaces the default (order array → alphabetical)
|
|
127
|
+
* entirely. Runs after extract + filter, so `fields` is available.
|
|
161
128
|
*/
|
|
162
129
|
sort?: (a: ContentTreeNode<T>, b: ContentTreeNode<T>) => number;
|
|
163
130
|
/** Max depth to traverse. Default: unlimited. */
|
|
@@ -167,34 +134,25 @@ export interface BuildContentTreeOptions<T = unknown, TEntryTypes = DefaultEntry
|
|
|
167
134
|
* `read()`/`readByUrlPath()` do. Applies to both entry nodes and the `meta.indexEntry`
|
|
168
135
|
* handed to a collection's `extract`. Off leaves them as the bare id string, or `null`.
|
|
169
136
|
*
|
|
170
|
-
* Same flag, same default (`false`) and same reasoning as
|
|
171
|
-
* `ListEntriesOptions.resolveReferences` in content-listing.ts for why the default
|
|
172
|
-
* opt-in
|
|
173
|
-
* to the resolved targets.
|
|
137
|
+
* Same flag, same default (`false`) and same reasoning as
|
|
138
|
+
* `ListEntriesOptions.resolveReferences` in content-listing.ts — see it for why the default
|
|
139
|
+
* is opt-in, what it costs, and why path ACLs are not applied to the resolved targets.
|
|
174
140
|
*/
|
|
175
141
|
resolveReferences?: boolean;
|
|
176
142
|
}
|
|
177
143
|
/**
|
|
178
|
-
* Default path builder: strips the content root prefix,
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* matching the URL convention used by readByUrlPath and listEntries.
|
|
144
|
+
* Default path builder: strips the content root prefix, collapses index entries, lowercases,
|
|
145
|
+
* prepends `/`. Lowercasing is unconditional, for consistency with slug normalization, so an
|
|
146
|
+
* adopter with case-sensitive slugs ("API-Reference") gets lowercased URLs. Index entries
|
|
147
|
+
* (slug 'index', any case) collapse to their parent collection path, matching the convention
|
|
148
|
+
* readByUrlPath and listEntries use.
|
|
184
149
|
*
|
|
185
|
-
* Exported (
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* content-root-strip / index-collapse / lowercase logic verbatim.
|
|
150
|
+
* Exported (and re-exported from `canopycms/server`) so adopters who want to EXTEND this
|
|
151
|
+
* rather than replace it can call it from inside their own `buildPath` and post-process the
|
|
152
|
+
* result, instead of reimplementing strip / collapse / lowercase verbatim.
|
|
189
153
|
*/
|
|
190
154
|
export declare const defaultBuildPath: (logicalPath: LogicalPath, contentRootName: string, kind: "collection" | "entry") => string;
|
|
191
155
|
/**
|
|
192
156
|
* Build a content tree from a flattened schema and the filesystem.
|
|
193
|
-
*
|
|
194
|
-
* @param branchRoot - Absolute path to the branch workspace root
|
|
195
|
-
* @param flatSchema - Flattened schema items (from flattenSchema)
|
|
196
|
-
* @param contentRootName - The content root name (e.g. "content")
|
|
197
|
-
* @param options - Tree-building options
|
|
198
|
-
* @param visibility - Internal path-ACL predicate; see `ContentVisibilityOptions`
|
|
199
157
|
*/
|
|
200
158
|
export declare function buildContentTree<T = unknown, TEntryTypes = DefaultEntryTypes>(branchRoot: string, flatSchema: FlatSchemaItem[], contentRootName: string, options?: BuildContentTreeOptions<T, TEntryTypes>, visibility?: ContentVisibilityOptions): Promise<ContentTreeNode<T>[]>;
|
package/dist/content-tree.js
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Content tree builder for adopters
|
|
2
|
+
* Content tree builder for adopters: walks the schema + filesystem and returns a tree of
|
|
3
|
+
* content nodes for navigation, sitemaps, search indexes, breadcrumbs.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Nodes carry Canopy's structural facts (logicalPath, contentId, collection
|
|
8
|
-
* metadata, entry metadata). Display concerns like labels are left to the
|
|
9
|
-
* adopter via the `extract` callback.
|
|
5
|
+
* Nodes carry Canopy's structural facts (logicalPath, contentId, collection metadata, entry
|
|
6
|
+
* metadata); display concerns like labels are left to the adopter's `extract` callback.
|
|
10
7
|
*/
|
|
11
8
|
import { isIndexSlug } from './utils/entry-url.js';
|
|
12
9
|
import { createReferenceResolver, listCollectionEntries, resolveCollectionItemReferences, sortByOrder, } from './content-listing.js';
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
// Internal helpers
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
10
|
/** Group flat schema items by parentPath for O(1) child lookup. */
|
|
17
11
|
const groupByParent = (flat) => {
|
|
18
12
|
const map = new Map();
|
|
@@ -27,28 +21,24 @@ const groupByParent = (flat) => {
|
|
|
27
21
|
return map;
|
|
28
22
|
};
|
|
29
23
|
/**
|
|
30
|
-
* Default path builder: strips the content root prefix,
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* matching the URL convention used by readByUrlPath and listEntries.
|
|
24
|
+
* Default path builder: strips the content root prefix, collapses index entries, lowercases,
|
|
25
|
+
* prepends `/`. Lowercasing is unconditional, for consistency with slug normalization, so an
|
|
26
|
+
* adopter with case-sensitive slugs ("API-Reference") gets lowercased URLs. Index entries
|
|
27
|
+
* (slug 'index', any case) collapse to their parent collection path, matching the convention
|
|
28
|
+
* readByUrlPath and listEntries use.
|
|
36
29
|
*
|
|
37
|
-
* Exported (
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* content-root-strip / index-collapse / lowercase logic verbatim.
|
|
30
|
+
* Exported (and re-exported from `canopycms/server`) so adopters who want to EXTEND this
|
|
31
|
+
* rather than replace it can call it from inside their own `buildPath` and post-process the
|
|
32
|
+
* result, instead of reimplementing strip / collapse / lowercase verbatim.
|
|
41
33
|
*/
|
|
42
34
|
export const defaultBuildPath = (logicalPath, contentRootName, kind) => {
|
|
43
35
|
const prefix = contentRootName ? `${contentRootName}/` : '';
|
|
44
36
|
const stripped = prefix && logicalPath.startsWith(prefix) ? logicalPath.slice(prefix.length) : logicalPath;
|
|
45
|
-
// Collapse index entries: content/guides/index → /guides
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
// did not: for an adopter-supplied `content/docs/Index` this said `/docs/index` while
|
|
51
|
-
// `computeEntryUrl` said `/docs`, and `/docs/index` is the one that does NOT round-trip.
|
|
37
|
+
// Collapse index entries: content/guides/index → /guides. Entries only — a collection named
|
|
38
|
+
// "index" keeps its path. The test runs on the LAST SEGMENT through the shared
|
|
39
|
+
// `isIndexSlug`, so it is case-insensitive and agrees with `computeEntryUrl`; a string
|
|
40
|
+
// `endsWith('/index')` test disagreed for an adopter-supplied `content/docs/Index`, and
|
|
41
|
+
// `/docs/index` is the answer that does NOT round-trip.
|
|
52
42
|
const lastSlash = stripped.lastIndexOf('/');
|
|
53
43
|
const lastSegment = lastSlash === -1 ? stripped : stripped.slice(lastSlash + 1);
|
|
54
44
|
const collapsed = kind === 'entry' && isIndexSlug(lastSegment)
|
|
@@ -59,17 +49,8 @@ export const defaultBuildPath = (logicalPath, contentRootName, kind) => {
|
|
|
59
49
|
const urlPath = collapsed ? `/${collapsed}` : '/';
|
|
60
50
|
return urlPath.toLowerCase();
|
|
61
51
|
};
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
|
-
// Core builder
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
52
|
/**
|
|
66
53
|
* Build a content tree from a flattened schema and the filesystem.
|
|
67
|
-
*
|
|
68
|
-
* @param branchRoot - Absolute path to the branch workspace root
|
|
69
|
-
* @param flatSchema - Flattened schema items (from flattenSchema)
|
|
70
|
-
* @param contentRootName - The content root name (e.g. "content")
|
|
71
|
-
* @param options - Tree-building options
|
|
72
|
-
* @param visibility - Internal path-ACL predicate; see `ContentVisibilityOptions`
|
|
73
54
|
*/
|
|
74
55
|
export async function buildContentTree(branchRoot, flatSchema, contentRootName, options, visibility) {
|
|
75
56
|
const childrenByParent = groupByParent(flatSchema);
|
|
@@ -98,7 +79,6 @@ export async function buildContentTree(branchRoot, flatSchema, contentRootName,
|
|
|
98
79
|
// reason the ACL filter lives here. A denied entry is filtered above and never resolved.
|
|
99
80
|
return resolver ? resolveCollectionItemReferences(visible, collection, resolver) : visible;
|
|
100
81
|
};
|
|
101
|
-
// Find the starting collection(s)
|
|
102
82
|
const rootPath = options?.rootPath ?? contentRootName;
|
|
103
83
|
const rootCollection = flatSchema.find((item) => item.type === 'collection' && item.logicalPath === rootPath);
|
|
104
84
|
if (!rootCollection)
|
|
@@ -131,20 +111,16 @@ export async function buildContentTree(branchRoot, flatSchema, contentRootName,
|
|
|
131
111
|
return null;
|
|
132
112
|
return node;
|
|
133
113
|
}
|
|
134
|
-
// Load this collection's entries first (needed for indexEntry detection).
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
// descendant I/O — preserving the pre-existing "filter prunes whole subtree"
|
|
138
|
-
// optimization that the directory-as-page reorder would otherwise lose.
|
|
114
|
+
// Load this collection's entries first (needed for indexEntry detection). The
|
|
115
|
+
// child-collection recursion deliberately does NOT run in parallel with it: if `filter`
|
|
116
|
+
// rejects this collection, returning early short-circuits all descendant I/O.
|
|
139
117
|
const entries = await listVisibleEntries(collection);
|
|
140
|
-
// Surface the 'index' entry (when present) to extract via meta.
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
// The cast bridges runtime string keys to the parametric discriminated union;
|
|
147
|
-
// the adopter narrows on `indexEntry.entryType` to get the typed `data`.
|
|
118
|
+
// Surface the 'index' entry (when present) to extract via meta. 'index' is the same magic
|
|
119
|
+
// slug defaultBuildPath collapses /foo/index to /foo with. If a collection contains
|
|
120
|
+
// several slug==='index' entries (only reachable via hand-edited or merged content -- the
|
|
121
|
+
// write path forbids it), the first by filename order wins. The cast bridges runtime
|
|
122
|
+
// string keys to the parametric discriminated union; the adopter narrows on
|
|
123
|
+
// `indexEntry.entryType` to get the typed `data`.
|
|
148
124
|
const idx = entries.find((e) => e.slug === 'index');
|
|
149
125
|
const indexEntry = (idx ? { entryType: idx.entryType, format: idx.format, data: idx.data } : undefined);
|
|
150
126
|
if (extract) {
|
|
@@ -156,10 +132,8 @@ export async function buildContentTree(branchRoot, flatSchema, contentRootName,
|
|
|
156
132
|
}
|
|
157
133
|
if (filter && !filter(node))
|
|
158
134
|
return null;
|
|
159
|
-
// Now recurse into child collections (after filter has had a chance to prune)
|
|
160
135
|
const childCollections = childrenByParent.get(collection.logicalPath) ?? [];
|
|
161
136
|
const childCollectionNodes = await Promise.all(childCollections.map((child) => buildNode(child, depth + 1)));
|
|
162
|
-
// Build entry nodes
|
|
163
137
|
const entryNodes = [];
|
|
164
138
|
for (const entry of entries) {
|
|
165
139
|
const entryNode = buildEntryNode(entry, buildPath, extract);
|
|
@@ -167,7 +141,6 @@ export async function buildContentTree(branchRoot, flatSchema, contentRootName,
|
|
|
167
141
|
continue;
|
|
168
142
|
entryNodes.push(entryNode);
|
|
169
143
|
}
|
|
170
|
-
// Combine and interleave by order array (or custom sort)
|
|
171
144
|
const allChildren = interleaveChildren(childCollectionNodes.filter((n) => n !== null), entryNodes, collection.order, customSort);
|
|
172
145
|
// Prune empty collections (no children after filtering)
|
|
173
146
|
if (allChildren.length === 0)
|
|
@@ -177,7 +150,6 @@ export async function buildContentTree(branchRoot, flatSchema, contentRootName,
|
|
|
177
150
|
};
|
|
178
151
|
// Start from root's children (don't include the root collection itself)
|
|
179
152
|
const topLevelCollections = childrenByParent.get(rootCollection.logicalPath) ?? [];
|
|
180
|
-
// Also get entries directly in the root collection
|
|
181
153
|
const [collectionNodes, rootEntries] = await Promise.all([
|
|
182
154
|
Promise.all(topLevelCollections.map((child) => buildNode(child, 1))),
|
|
183
155
|
listVisibleEntries(rootCollection),
|
package/dist/context.d.ts
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
* layer where authorization is applied, so a read that bypasses it bypasses
|
|
8
8
|
* path ACLs.
|
|
9
9
|
*
|
|
10
|
-
* PHASE-AWARE: at build time (`isBuildMode`) or
|
|
11
|
-
* (`isDeployedStatic`) it authorizes as `STATIC_DEPLOY_USER`
|
|
12
|
-
* user (WHO)
|
|
13
|
-
*
|
|
10
|
+
* PHASE-AWARE: at build time (`isBuildMode`) or on a static deployment
|
|
11
|
+
* (`isDeployedStatic`) it authorizes as `STATIC_DEPLOY_USER` rather than a real
|
|
12
|
+
* user (WHO) and reads the working tree at `process.cwd()` rather than a branch
|
|
13
|
+
* workspace (WHERE: `readsFromCheckout`, applied inside
|
|
14
14
|
* `loadOrCreateBranchContext`), so a `branch` passed to a read selects nothing.
|
|
15
|
-
* Only request-time reads on a server deployment resolve a branch workspace
|
|
16
|
-
* in dev
|
|
15
|
+
* Only request-time reads on a server deployment resolve a branch workspace —
|
|
16
|
+
* in dev, the clone under `.canopy-dev/content-branches/`.
|
|
17
17
|
*
|
|
18
18
|
* The Next.js adapter wraps this in React `cache()` for per-request memoization
|
|
19
19
|
* (`canopycms-next/src/context-wrapper.ts`).
|
|
@@ -28,60 +28,60 @@ import { type ListEntriesOptions, type ListEntriesItem } from './content-listing
|
|
|
28
28
|
export interface CanopyContextOptions {
|
|
29
29
|
services: CanopyServices;
|
|
30
30
|
/**
|
|
31
|
-
* Extract the current user from framework-specific context
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* Framework adapters provide this (e.g., from Next.js headers, Express req, etc.)
|
|
31
|
+
* Extract the current user from framework-specific context — supplied by the
|
|
32
|
+
* framework adapter, and must call authResultToCanopyUser() so bootstrap
|
|
33
|
+
* admin groups are applied.
|
|
35
34
|
*/
|
|
36
35
|
extractUser: () => Promise<CanopyUser>;
|
|
37
36
|
}
|
|
38
37
|
/**
|
|
39
|
-
* Build-time context
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* ACL-enforced access use getCanopy() (CanopyContext) instead.
|
|
38
|
+
* Build-time context, from getCanopyForBuild(): reads the filesystem directly
|
|
39
|
+
* as a synthetic admin (STATIC_DEPLOY_USER), bypassing all branch and path
|
|
40
|
+
* ACLs. Use it for static generation — generateStaticParams, sitemap,
|
|
41
|
+
* build-time page rendering — and never to serve content at request time on a
|
|
42
|
+
* production `server` deployment; request-time, ACL-enforced access is
|
|
43
|
+
* getCanopy() (CanopyContext). Framework adapters throw on the read helpers
|
|
44
|
+
* there, though `services` stays a raw, unguarded escape hatch.
|
|
47
45
|
*
|
|
48
|
-
*
|
|
49
|
-
* scanning the whole collection.
|
|
46
|
+
* It carries read/readByUrlPath so build-time code can resolve a single entry
|
|
47
|
+
* by path or URL without scanning the whole collection.
|
|
50
48
|
*/
|
|
51
49
|
export interface CanopyBuildContext {
|
|
52
50
|
/**
|
|
53
|
-
* Build a content tree from the schema and filesystem entries.
|
|
51
|
+
* Build a content tree from the schema and filesystem entries. Supply
|
|
52
|
+
* TEntryTypes (entry type name → data shape, typically via
|
|
53
|
+
* `TypeFromEntrySchema<typeof yourSchema>`) for narrowed access to
|
|
54
|
+
* `meta.indexEntry.data` inside `extract`.
|
|
54
55
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* cannot `read` are omitted — from the emitted nodes AND from the `meta.indexEntry`
|
|
61
|
-
* handed to `extract`. Collections whose children are all filtered out are pruned.
|
|
62
|
-
* On the build context, and on static deployments, nothing is filtered (synthetic admin).
|
|
56
|
+
* Path ACLs: on the request-scoped context (`getCanopy()`), entries the user
|
|
57
|
+
* cannot `read` are omitted from the emitted nodes AND from the
|
|
58
|
+
* `meta.indexEntry` handed to `extract`, and a collection whose children are
|
|
59
|
+
* all filtered out is pruned. On the build context and on static deployments
|
|
60
|
+
* nothing is filtered — the synthetic admin sees everything.
|
|
63
61
|
*/
|
|
64
62
|
buildContentTree: <T = unknown, TEntryTypes = DefaultEntryTypes>(options?: BuildContentTreeOptions<T, TEntryTypes>) => Promise<ContentTreeNode<T>[]>;
|
|
65
63
|
/**
|
|
66
|
-
*
|
|
64
|
+
* Every content entry as a flat array.
|
|
67
65
|
*
|
|
68
|
-
* Path ACLs: on the request-scoped context (`getCanopy()`), entries the
|
|
69
|
-
* cannot `read` are omitted before `extract` runs
|
|
70
|
-
* deployments
|
|
66
|
+
* Path ACLs: on the request-scoped context (`getCanopy()`), entries the user
|
|
67
|
+
* cannot `read` are omitted before `extract` runs; on the build context and
|
|
68
|
+
* static deployments nothing is filtered.
|
|
71
69
|
*
|
|
72
|
-
* Branch: unlike `read`/`readByUrlPath
|
|
73
|
-
* `defaultActiveBranch ?? defaultBaseBranch ?? 'main'`. In `dev` that
|
|
74
|
-
* via `refreshActiveBranch()`; in `prod`
|
|
75
|
-
* base branch. See
|
|
70
|
+
* Branch: unlike `read`/`readByUrlPath` this takes no `branch` option, always
|
|
71
|
+
* listing `defaultActiveBranch ?? defaultBaseBranch ?? 'main'`. In `dev` that
|
|
72
|
+
* tracks git HEAD via `refreshActiveBranch()`; in `prod` the refresh is a
|
|
73
|
+
* no-op, so it always reads the base branch. See
|
|
74
|
+
* `.claude/future-tasks/context-listing-branch-pinning.md`.
|
|
76
75
|
*/
|
|
77
76
|
listEntries: <T = Record<string, unknown>>(options?: ListEntriesOptions<T>) => Promise<ListEntriesItem<T>[]>;
|
|
78
77
|
/**
|
|
79
|
-
* Content reader
|
|
78
|
+
* Content reader, with the auth context applied automatically (admin at build
|
|
79
|
+
* time).
|
|
80
80
|
*
|
|
81
|
-
* `meta.physicalPath` is the
|
|
82
|
-
*
|
|
83
|
-
* output,
|
|
84
|
-
* branch name).
|
|
81
|
+
* `meta.physicalPath` is the resolved entry file's absolute path, and is
|
|
82
|
+
* **server-only**: never serialize it to the client or embed it in public
|
|
83
|
+
* output, since it reveals the deployment's filesystem layout (home dir, EFS
|
|
84
|
+
* mount, branch name). It is for build-time reads of colocated artifacts, e.g.
|
|
85
85
|
* `fs.readFile(path.join(path.dirname(result.meta.physicalPath), 'profile.json'))`.
|
|
86
86
|
*/
|
|
87
87
|
read: <T = unknown>(input: {
|
|
@@ -95,56 +95,33 @@ export interface CanopyBuildContext {
|
|
|
95
95
|
meta: ContentReadMeta;
|
|
96
96
|
}>;
|
|
97
97
|
/**
|
|
98
|
-
* Read content by URL path, resolving the collection/entry split
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* Root path '/' resolves to the content root's index entry.
|
|
98
|
+
* Read content by URL path, resolving the collection/entry split itself: a
|
|
99
|
+
* direct entry match first (last segment = slug, rest = collection path),
|
|
100
|
+
* then the index entry (full path = collection, slug = 'index'). Both need a
|
|
101
|
+
* real collection for the collection part; root '/' is the content root's
|
|
102
|
+
* index entry.
|
|
104
103
|
*
|
|
105
|
-
* Resolves ONLY what `listEntries` publishes — `readByUrlPath(item.urlPath)`
|
|
106
|
-
* and no other spelling does
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* on-disk type token its collection does not declare (`listEntries` skips those too). A
|
|
111
|
-
* collection literally named `index` is unaffected — the index fallback resolves it.
|
|
104
|
+
* Resolves ONLY what `listEntries` publishes — `readByUrlPath(item.urlPath)`
|
|
105
|
+
* reaches the entry and no other spelling does; a collection literally named
|
|
106
|
+
* `index` still resolves, via the index fallback. `read({ entryPath })` is
|
|
107
|
+
* deliberately NOT narrowed this way: a schema path is a different question
|
|
108
|
+
* from a published URL, and reaches a singleton whose slug nobody knows.
|
|
112
109
|
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
110
|
+
* Null when nothing matches — a collection URL with no index entry (use
|
|
111
|
+
* buildContentTree), a non-entry path like `/favicon.ico` the slug validator
|
|
112
|
+
* rejects, or a path the user may not read, so a FORBIDDEN denial renders as
|
|
113
|
+
* a 404 via `notFound()` rather than a 500. Strict `read()` still throws.
|
|
116
114
|
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* still throws on permission errors.
|
|
123
|
-
*
|
|
124
|
-
* The result's `meta.physicalPath` is the absolute filesystem path to the resolved
|
|
125
|
-
* entry file. It is **server-only** — do not serialize it to the client or embed it
|
|
126
|
-
* in public output, as it reveals the deployment's filesystem layout (home dir / EFS
|
|
127
|
-
* mount / branch name). Intended for build-time reads of colocated artifacts.
|
|
128
|
-
*
|
|
129
|
-
* `meta.entryType` and `meta.entryId` are also resolved for free (path resolution
|
|
130
|
-
* already derives them) — useful for entry-type-based dispatch in a single
|
|
131
|
-
* catch-all route without a separate `listEntries` lookup or filename parse. See
|
|
132
|
-
* `ContentReadMeta` (content-reader.ts) before branching on `entryType` for a legacy
|
|
133
|
-
* file: `entryId === undefined` signals that `entryType` is a fallback, not a read.
|
|
115
|
+
* `meta.physicalPath` is **server-only**, for the reason given on `read`.
|
|
116
|
+
* `meta.entryType`/`entryId` come free with path resolution, so one catch-all
|
|
117
|
+
* route can dispatch on entry type with no extra lookup; check
|
|
118
|
+
* `ContentReadMeta` first — `entryId === undefined` marks `entryType` a
|
|
119
|
+
* fallback, not a read.
|
|
134
120
|
*
|
|
135
121
|
* @example
|
|
136
122
|
* ```ts
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* // URL / → reads content root + slug "index"
|
|
140
|
-
* const result = await canopy.readByUrlPath<DocContent>('/docs/guides/getting-started')
|
|
141
|
-
* if (result) {
|
|
142
|
-
* const { data, path } = result
|
|
143
|
-
* switch (result.meta.entryType) {
|
|
144
|
-
* case 'home': return <HomePage data={data} />
|
|
145
|
-
* default: return <DocView data={data} />
|
|
146
|
-
* }
|
|
147
|
-
* }
|
|
123
|
+
* const result = await canopy.readByUrlPath<DocContent>('/docs/guides/intro')
|
|
124
|
+
* if (result?.meta.entryType === 'home') return <HomePage data={result.data} />
|
|
148
125
|
* ```
|
|
149
126
|
*/
|
|
150
127
|
readByUrlPath: <T = unknown>(urlPath: string, options?: {
|
|
@@ -163,15 +140,11 @@ export interface CanopyContext extends CanopyBuildContext {
|
|
|
163
140
|
user: CanopyUser;
|
|
164
141
|
}
|
|
165
142
|
/**
|
|
166
|
-
* Create a Canopy context
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* User extractor should apply bootstrap admin groups (via authResultToCanopyUser).
|
|
143
|
+
* Create a Canopy context managing auth + content reading. Framework-agnostic:
|
|
144
|
+
* the adapter supplies extractUser.
|
|
170
145
|
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* that creates services from config cannot work correctly since createCanopyServices
|
|
174
|
-
* is now async. Always pass services, not config.
|
|
146
|
+
* Synchronous, and takes pre-created `services` rather than config — building
|
|
147
|
+
* services is async, so there is no working fallback path from config here.
|
|
175
148
|
*/
|
|
176
149
|
export declare function createCanopyContext(options: CanopyContextOptions): {
|
|
177
150
|
getContext: () => Promise<CanopyContext>;
|