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-listing.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared content-listing utilities used by both the entries API and the content tree builder.
|
|
3
|
-
*
|
|
4
|
-
* Extracted from api/entries.ts to avoid duplication.
|
|
5
3
|
*/
|
|
6
4
|
import fs from 'node:fs/promises';
|
|
7
5
|
import path from 'node:path';
|
|
@@ -17,10 +15,7 @@ import { createDebugLogger } from './utils/debug.js';
|
|
|
17
15
|
import { ContentStore, ContentStoreError, createReferenceResolveCache, } from './content-store.js';
|
|
18
16
|
import { isBuildMode } from './build-mode.js';
|
|
19
17
|
const log = createDebugLogger({ prefix: 'ContentListing' });
|
|
20
|
-
/**
|
|
21
|
-
* Validate and normalize a path relative to root.
|
|
22
|
-
* Throws ContentStoreError on traversal attempt.
|
|
23
|
-
*/
|
|
18
|
+
/** Validate and normalize `target` under `root`; throws ContentStoreError on a traversal. */
|
|
24
19
|
const normalizePath = (root, target) => {
|
|
25
20
|
const result = validateAndNormalizePath(root, target);
|
|
26
21
|
if (!result.valid) {
|
|
@@ -29,13 +24,11 @@ const normalizePath = (root, target) => {
|
|
|
29
24
|
return result.normalizedPath;
|
|
30
25
|
};
|
|
31
26
|
/**
|
|
32
|
-
* Read entry data from a file.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* For json: returns the parsed JSON object.
|
|
36
|
-
* Returns an empty object on read/parse failure.
|
|
27
|
+
* Read entry data from a file. For md/mdx: frontmatter fields plus the body content under
|
|
28
|
+
* `bodyFieldName` (defaults to `'body'`); for json/yaml, the parsed object. Returns an empty
|
|
29
|
+
* object on read/parse failure.
|
|
37
30
|
*/
|
|
38
|
-
|
|
31
|
+
const readEntryData = async (filePath, format, bodyFieldName = 'body') => {
|
|
39
32
|
try {
|
|
40
33
|
const raw = await fs.readFile(filePath, 'utf8');
|
|
41
34
|
if (format === 'json') {
|
|
@@ -51,13 +44,10 @@ export const readEntryData = async (filePath, format, bodyFieldName = 'body') =>
|
|
|
51
44
|
// Copy before writing the body in. gray-matter keeps a PROCESS-GLOBAL cache keyed by file
|
|
52
45
|
// content and hands every caller the same `data` object instance, so mutating it in place
|
|
53
46
|
// wrote the body into a shared object that later, unrelated `matter()` calls then saw as
|
|
54
|
-
// frontmatter
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
// listing and WITHOUT it on one scoped past its own collection: the same entry, two shapes,
|
|
59
|
-
// decided by unrelated scoping. Regression coverage lives with the reference-resolution
|
|
60
|
-
// tests in content-listing.test.ts.
|
|
47
|
+
// frontmatter: listing a collection containing an md entry poisoned the cache, and a
|
|
48
|
+
// reference resolution to that same entry (through `ContentStore.read()`, whose md branch
|
|
49
|
+
// calls `matter()` again) returned the body as a frontmatter field -- one entry with two
|
|
50
|
+
// shapes, decided by unrelated listing scope.
|
|
61
51
|
const data = { ...(parsed.data ?? {}) };
|
|
62
52
|
if (parsed.content) {
|
|
63
53
|
data[bodyFieldName] = parsed.content;
|
|
@@ -71,30 +61,25 @@ export const readEntryData = async (filePath, format, bodyFieldName = 'body') =>
|
|
|
71
61
|
return {};
|
|
72
62
|
}
|
|
73
63
|
};
|
|
74
|
-
// `parseTypedFilename`
|
|
75
|
-
//
|
|
76
|
-
//
|
|
64
|
+
// `parseTypedFilename` lives in utils/typed-filename.ts so dependency-light modules can use it
|
|
65
|
+
// without importing this one (which pulls in ContentStore). Re-exported here because callers --
|
|
66
|
+
// and `canopycms/server` -- import it from here.
|
|
77
67
|
export { parseTypedFilename } from './utils/typed-filename.js';
|
|
78
68
|
import { parseTypedFilename } from './utils/typed-filename.js';
|
|
79
|
-
// ---------------------------------------------------------------------------
|
|
80
|
-
// Reference resolution for batch listings
|
|
81
|
-
// ---------------------------------------------------------------------------
|
|
82
69
|
/**
|
|
83
70
|
* Build the `ContentStore` + shared cache that a batch listing resolves references through.
|
|
84
71
|
*
|
|
85
72
|
* Unrelated to the `ReferenceResolver` class in reference-resolver.ts despite the adjacent
|
|
86
|
-
* name — that one resolves an id to a human-readable
|
|
87
|
-
* resolves a reference to the referenced entry's *data* for server-side listings.
|
|
73
|
+
* name — that one resolves an id to a human-readable display label for the editor UI.
|
|
88
74
|
*
|
|
89
|
-
* Constructed lazily by each listing surface, and ONLY when the caller opted in
|
|
75
|
+
* Constructed lazily by each listing surface, and ONLY when the caller opted in: a store
|
|
90
76
|
* builds a ContentId index on first use, which is a full scan of the content tree, and the
|
|
91
77
|
* default (`resolveReferences` off) must stay a pure filesystem walk with no index at all.
|
|
92
78
|
*
|
|
93
|
-
* One store and one cache per listing
|
|
79
|
+
* One store and one cache per listing CALL, not per collection: the cache is the reason a
|
|
94
80
|
* shared block referenced from 40 pages costs one read instead of 40, so it has to span the
|
|
95
|
-
* whole batch.
|
|
96
|
-
* `
|
|
97
|
-
* `WeakRef` + a `FinalizationRegistry` precisely so short-lived instances stay collectable.
|
|
81
|
+
* whole batch. content-index-registry.ts holds stores through `WeakRef` + a
|
|
82
|
+
* `FinalizationRegistry`, so these short-lived instances stay collectable.
|
|
98
83
|
*/
|
|
99
84
|
export const createReferenceResolver = (branchRoot, flatSchema, contentRootName) => ({
|
|
100
85
|
store: new ContentStore(branchRoot, flatSchema, { contentRootName }),
|
|
@@ -118,46 +103,33 @@ export const resolveCollectionItemReferences = async (items, collection, resolve
|
|
|
118
103
|
};
|
|
119
104
|
}));
|
|
120
105
|
/**
|
|
121
|
-
* List all content entries as a flat array
|
|
106
|
+
* List all content entries as a flat array: walks the schema to discover collections, reads
|
|
107
|
+
* entries from each, and returns a flat list suitable for generateStaticParams, search
|
|
108
|
+
* indexing, sitemaps, etc.
|
|
122
109
|
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
110
|
+
* Build-time-only failure: a file with a recognized content extension sitting in a collection
|
|
111
|
+
* directory that *looks like an attempted entry* (see `looksLikeMalformedEntry`) but does not
|
|
112
|
+
* match `{type}.{slug}.{id}.{ext}` is silently dropped by default. That is exactly the
|
|
113
|
+
* silent-page-loss static generation must not have -- a schema rename without a matching file
|
|
114
|
+
* rename, or an entry type declared in one collection but not another, would vanish a page with
|
|
115
|
+
* zero build output -- so when `isBuildMode()` is true any such file throws instead
|
|
116
|
+
* (`static/index.ts`'s `assertBuildEntriesValid` is the sibling schema-validity guard).
|
|
117
|
+
* Outside build mode (admin UI, content tree, `next dev`) it is still skipped, since a fresh
|
|
118
|
+
* scaffold or mid-rename file legitimately exists there.
|
|
125
119
|
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* `looksLikeMalformedEntry` below) but doesn't match `{type}.{slug}.{id}.{ext}` is, by default,
|
|
129
|
-
* silently dropped (see `listCollectionEntries`'s debug-gated warning). That is exactly the
|
|
130
|
-
* silent-page-loss failure mode static generation must not have — a schema rename without a
|
|
131
|
-
* matching file rename, or an entry type declared in one collection but not another, would
|
|
132
|
-
* otherwise vanish a page with zero build output. So when `isBuildMode()` is true, any such file
|
|
133
|
-
* turns the listing into a thrown error instead (see `findInvalidEntries`/`assertBuildEntriesValid`
|
|
134
|
-
* in `static/index.ts` for the sibling schema-validity guard this mirrors). Outside build mode
|
|
135
|
-
* (admin UI, content tree, `next dev`) the file is still just skipped, since a fresh scaffold or
|
|
136
|
-
* mid-rename file legitimately exists there.
|
|
137
|
-
*
|
|
138
|
-
* A file that was never entry-shaped to begin with — a `README.md`, or a colocated sibling
|
|
139
|
-
* artifact named `{contentId}.suffix.ext` per the `entryTransforms`/`readSibling` convention
|
|
140
|
-
* documented in the README — is not this guard's failure mode and never throws, in or out of
|
|
141
|
-
* build mode. See `looksLikeMalformedEntry` for the exact shape test.
|
|
142
|
-
*
|
|
143
|
-
* @param branchRoot - Absolute path to the branch workspace root
|
|
144
|
-
* @param flatSchema - Flattened schema items (from flattenSchema)
|
|
145
|
-
* @param contentRootName - The content root name (e.g. "content")
|
|
146
|
-
* @param options - Listing options (extract, filter, rootPath, sort, resolveReferences)
|
|
147
|
-
* @param visibility - Internal path-ACL predicate; see `ContentVisibilityOptions`
|
|
120
|
+
* A file that was never entry-shaped -- a `README.md`, or a colocated sibling artifact named
|
|
121
|
+
* `{contentId}.suffix.ext` per the `entryTransforms`/`readSibling` convention -- never throws.
|
|
148
122
|
*/
|
|
149
123
|
export async function listEntries(branchRoot, flatSchema, contentRootName, options, visibility) {
|
|
150
124
|
const rootPath = options?.rootPath ?? contentRootName;
|
|
151
125
|
const extract = options?.extract;
|
|
152
126
|
const filter = options?.filter;
|
|
153
127
|
const customSort = options?.sort;
|
|
154
|
-
// Find all collections under rootPath
|
|
155
128
|
const collections = flatSchema.filter((item) => item.type === 'collection' &&
|
|
156
129
|
item.entries !== undefined &&
|
|
157
130
|
(item.logicalPath === rootPath || item.logicalPath.startsWith(`${rootPath}/`)));
|
|
158
|
-
// List entries from all collections in parallel.
|
|
159
|
-
//
|
|
160
|
-
// data never reaches `extract` (let alone the returned items).
|
|
131
|
+
// List entries from all collections in parallel. The visibility predicate is applied here,
|
|
132
|
+
// before the map below, so a denied entry's data never reaches `extract`.
|
|
161
133
|
const shouldInclude = visibility?.shouldInclude;
|
|
162
134
|
const skippedFiles = [];
|
|
163
135
|
// One store + cache for the whole call, or nothing at all when the caller did not opt in.
|
|
@@ -176,10 +148,9 @@ export async function listEntries(branchRoot, flatSchema, contentRootName, optio
|
|
|
176
148
|
: visible;
|
|
177
149
|
return resolved.map((entry) => ({ entry, collection }));
|
|
178
150
|
}));
|
|
179
|
-
// Build-time only: fail loudly rather than silently shipping a build with a page missing
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
// `looksLikeMalformedEntry` and `listCollectionEntries`.
|
|
151
|
+
// Build-time only: fail loudly rather than silently shipping a build with a page missing --
|
|
152
|
+
// see this function's doc comment. Only files that structurally look like a malformed entry
|
|
153
|
+
// reach `skippedFiles` (see `looksLikeMalformedEntry`).
|
|
183
154
|
if (isBuildMode() && skippedFiles.length > 0) {
|
|
184
155
|
const lines = skippedFiles.map(({ filename, collectionPath }) => ` - ${collectionPath}/${filename}`);
|
|
185
156
|
throw new Error(`CanopyCMS static build: found ${skippedFiles.length} file(s) that look like malformed ` +
|
|
@@ -193,26 +164,22 @@ export async function listEntries(branchRoot, flatSchema, contentRootName, optio
|
|
|
193
164
|
'segments (id.suffix.ext) so it is never mistaken for an entry attempt. Otherwise rename ' +
|
|
194
165
|
'or move the file, or fix the schema, then rebuild.');
|
|
195
166
|
}
|
|
196
|
-
// Flatten and map to ListEntriesItem
|
|
197
167
|
const contentPrefix = contentRootName ? `${contentRootName}/` : '';
|
|
198
168
|
const items = [];
|
|
199
169
|
for (const results of collectionResults) {
|
|
200
170
|
for (const { entry, collection } of results) {
|
|
201
|
-
// Compute pathSegments: strip content root prefix, split on /
|
|
202
171
|
const pathWithoutRoot = entry.logicalPath.startsWith(contentPrefix)
|
|
203
172
|
? entry.logicalPath.slice(contentPrefix.length)
|
|
204
173
|
: entry.logicalPath;
|
|
205
174
|
const pathSegments = pathWithoutRoot.split('/').filter(Boolean);
|
|
206
|
-
// Compute urlPath (
|
|
207
|
-
// the SHARED rule rather than a local copy
|
|
208
|
-
//
|
|
209
|
-
// this listing does, so the two must not be free to drift apart.
|
|
175
|
+
// Compute urlPath (collapsing an `index` entry to its parent collection path) through
|
|
176
|
+
// the SHARED rule rather than a local copy: a resolved reference carries a `urlPath`
|
|
177
|
+
// that must address the same entry this listing does, so the two must not drift apart.
|
|
210
178
|
//
|
|
211
|
-
// One deliberate copy of
|
|
212
|
-
//
|
|
213
|
-
// `computeEntryUrl` does not model.
|
|
179
|
+
// One deliberate copy of the rule remains: `content-tree.ts`'s `defaultBuildPath`,
|
|
180
|
+
// exported for adopters to extend and also handling the collection case
|
|
181
|
+
// `computeEntryUrl` does not model. Folding it in is tracked in
|
|
214
182
|
// `.claude/future-tasks/default-build-path-url-rule-copy.md`.
|
|
215
|
-
// `content-listing.test.ts` pins the listing-vs-resolved-reference agreement.
|
|
216
183
|
const urlPath = computeEntryUrl(entry.collectionPath, entry.slug, contentRootName);
|
|
217
184
|
const raw = entry.data;
|
|
218
185
|
const meta = {
|
|
@@ -249,15 +216,9 @@ export async function listEntries(branchRoot, flatSchema, contentRootName, optio
|
|
|
249
216
|
}
|
|
250
217
|
return items;
|
|
251
218
|
}
|
|
252
|
-
// ---------------------------------------------------------------------------
|
|
253
|
-
// Shared utilities
|
|
254
|
-
// ---------------------------------------------------------------------------
|
|
255
219
|
/**
|
|
256
|
-
* Sort items by a content ID order array
|
|
257
|
-
*
|
|
258
|
-
* sorted by the provided fallback key.
|
|
259
|
-
*
|
|
260
|
-
* Note: sorts the array in-place and returns it.
|
|
220
|
+
* Sort items by a content ID order array: items in `order` come first, in that order, then
|
|
221
|
+
* the rest sorted by `fallbackKey`. Sorts the array in place and returns it.
|
|
261
222
|
*/
|
|
262
223
|
export const sortByOrder = (items, order, fallbackKey) => {
|
|
263
224
|
if (!order || order.length === 0) {
|
|
@@ -278,32 +239,26 @@ export const sortByOrder = (items, order, fallbackKey) => {
|
|
|
278
239
|
});
|
|
279
240
|
};
|
|
280
241
|
/**
|
|
281
|
-
* True when a content-extension filename structurally resembles an attempted entry — as
|
|
282
|
-
* to a file that was never entry-shaped to begin with.
|
|
242
|
+
* True when a content-extension filename structurally resembles an attempted entry — as
|
|
243
|
+
* opposed to a file that was never entry-shaped to begin with.
|
|
283
244
|
*
|
|
284
|
-
* A successfully-parsed entry always has at least 4 dot-separated segments
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
* on its face — a wrong-length or invalid-Base58 ID, most often (`post.hello-world.BADID.md`).
|
|
245
|
+
* A successfully-parsed entry always has at least 4 dot-separated segments (type, slug, id,
|
|
246
|
+
* ext), so a 4+-segment file that still failed to parse is malformed on its face -- usually a
|
|
247
|
+
* wrong-length or invalid-Base58 ID (`post.hello-world.BADID.md`).
|
|
288
248
|
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
* bare `README.md` (2 segments, and "README" is essentially never a configured entry type name)
|
|
299
|
-
* and an entry's colocated sibling artifact named `{contentId}.suffix.ext` per the
|
|
300
|
-
* `entryTransforms`/`readSibling` convention documented in the README (3 segments, e.g.
|
|
301
|
-
* `5NVkkrB1MJUv.profile.json` — a content ID is never itself an entry type name, so the same
|
|
302
|
-
* "first segment matches a known type" test correctly leaves it unflagged).
|
|
249
|
+
* A 3-segment file whose FIRST segment matches a real entry type name in this collection
|
|
250
|
+
* counts too, which catches the more common accident of losing the ID segment entirely
|
|
251
|
+
* (`post.hello-world.md`): `parseTypedFilename` needs type+slug+id after the extension, so 3
|
|
252
|
+
* total segments leave only 2 -- `type.slug` with no id, or `type.id` with no slug, a lost
|
|
253
|
+
* segment rather than a coincidence. That leaves the two "never an entry" cases alone: a bare
|
|
254
|
+
* `README.md` (2 segments, and "README" is essentially never a configured entry type name) and
|
|
255
|
+
* an entry's colocated sibling artifact `{contentId}.suffix.ext` per the
|
|
256
|
+
* `entryTransforms`/`readSibling` convention (3 segments, but a content ID is never a type
|
|
257
|
+
* name).
|
|
303
258
|
*
|
|
304
|
-
* Dot-prefixed (hidden files, editor swap/backup files) and underscore-prefixed (
|
|
305
|
-
*
|
|
306
|
-
*
|
|
259
|
+
* Dot-prefixed (hidden files, editor swap/backup files) and underscore-prefixed (an adopter
|
|
260
|
+
* convention for "not an entry") names are excluded outright at any segment count, matching
|
|
261
|
+
* `parseTypedFilename`'s own dotfile rejection.
|
|
307
262
|
*/
|
|
308
263
|
const looksLikeMalformedEntry = (filename, entryTypes) => {
|
|
309
264
|
if (filename.startsWith('.') || filename.startsWith('_'))
|
|
@@ -314,24 +269,20 @@ const looksLikeMalformedEntry = (filename, entryTypes) => {
|
|
|
314
269
|
return segments.length === 3 && entryTypes.some((e) => e.name === segments[0]);
|
|
315
270
|
};
|
|
316
271
|
/**
|
|
317
|
-
* List all entries in a collection directory.
|
|
318
|
-
* Reads each entry's data (frontmatter or JSON).
|
|
272
|
+
* List all entries in a collection directory, reading each entry's data.
|
|
319
273
|
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
* exact prior behavior. `listEntries` below uses this to turn the skip into a hard build-time
|
|
327
|
-
* failure instead of a silent one.
|
|
274
|
+
* `onSkip` is called for every file that has a recognized content extension, does NOT match
|
|
275
|
+
* the `{type}.{slug}.{id}.{ext}` grammar (see `parseTypedFilename`), AND structurally looks
|
|
276
|
+
* like an attempted entry (see `looksLikeMalformedEntry`). A file that was never entry-shaped
|
|
277
|
+
* -- a `README.md`, a colocated sibling artifact -- is always dropped with a debug-gated
|
|
278
|
+
* `log.warn` and never passed to `onSkip`. Optional and purely diagnostic: `listEntries` uses
|
|
279
|
+
* it to turn the skip into a hard build-time failure instead of a silent one.
|
|
328
280
|
*/
|
|
329
281
|
export const listCollectionEntries = async (root, collection, onSkip) => {
|
|
330
282
|
if (collection.type !== 'collection' || !collection.entries) {
|
|
331
283
|
return [];
|
|
332
284
|
}
|
|
333
285
|
const entryTypes = collection.entries;
|
|
334
|
-
// Build a map of extension to entry types for efficient lookup
|
|
335
286
|
const extToTypes = new Map();
|
|
336
287
|
for (const entryType of entryTypes) {
|
|
337
288
|
const ext = getFormatExtension(entryType.format);
|
|
@@ -340,7 +291,6 @@ export const listCollectionEntries = async (root, collection, onSkip) => {
|
|
|
340
291
|
extToTypes.set(ext, existing);
|
|
341
292
|
}
|
|
342
293
|
const validExts = Array.from(extToTypes.keys());
|
|
343
|
-
// Resolve the full collection path with embedded IDs
|
|
344
294
|
const collectionRoot = await resolveCollectionPath(root, collection.logicalPath);
|
|
345
295
|
if (!collectionRoot) {
|
|
346
296
|
return [];
|
package/dist/content-reader.d.ts
CHANGED
|
@@ -31,18 +31,16 @@ export interface ReadContentInput {
|
|
|
31
31
|
*
|
|
32
32
|
* 1. `entryPath` must be a COLLECTION. A published URL is `/<collectionSegments>/<slug>` (or
|
|
33
33
|
* the collapsed collection path, for an index entry), so its non-slug segments are always
|
|
34
|
-
* collection names. An `entryPath`
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* forward surface emits.
|
|
34
|
+
* collection names. An `entryPath` resolving to an entry-TYPE item would be delegated by
|
|
35
|
+
* `ContentStore.buildPaths` to the parent collection, answering at URLs no forward surface
|
|
36
|
+
* emits.
|
|
38
37
|
* 2. The resolved entry's type must be one its collection declares, matching the
|
|
39
38
|
* `parseTypedFilename(filename, collection.entries)` check `listEntries` applies. A legacy
|
|
40
39
|
* untyped file has no type token to fail on -- see `declaresEntryType`.
|
|
41
40
|
*
|
|
42
|
-
* Set by `readByUrlPath` and nothing else
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* only make a read stricter, never looser.
|
|
41
|
+
* Set by `readByUrlPath` and nothing else: `read({ entryPath: 'content/home' })` and direct
|
|
42
|
+
* `ContentStore` use keep the entry-type delegation, a supported API and the only way to
|
|
43
|
+
* address a singleton structurally. Misusing this flag can only make a read stricter.
|
|
46
44
|
*/
|
|
47
45
|
urlAddressableOnly?: boolean;
|
|
48
46
|
}
|
|
@@ -53,35 +51,28 @@ export interface ReadContentInput {
|
|
|
53
51
|
*/
|
|
54
52
|
export interface ContentReadMeta {
|
|
55
53
|
/**
|
|
56
|
-
* Absolute filesystem path to the resolved entry file.
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* name).
|
|
54
|
+
* Absolute filesystem path to the resolved entry file. **Server-only**: do not serialize it
|
|
55
|
+
* to the client or embed it in public output, as it reveals the deployment's filesystem
|
|
56
|
+
* layout (home dir / EFS mount / branch name).
|
|
60
57
|
*/
|
|
61
58
|
physicalPath: PhysicalPath;
|
|
62
59
|
/**
|
|
63
60
|
* The resolved entry type name, read from the entry's own filename
|
|
64
|
-
* (`{type}.{slug}.{id}.{ext}`) -- immutable once the file is created, and
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* the
|
|
68
|
-
*
|
|
69
|
-
* created, or if the file was hand-authored with an unrecognized type
|
|
70
|
-
* token.
|
|
61
|
+
* (`{type}.{slug}.{id}.{ext}`) -- immutable once the file is created, and NOT re-validated
|
|
62
|
+
* against the collection's current `entries` config on every read. So it is usually, but not
|
|
63
|
+
* guaranteed to be, a key in that config: it diverges when an entry type was renamed or
|
|
64
|
+
* removed from the schema after files using the old name were created, or when the file was
|
|
65
|
+
* hand-authored with an unrecognized type token.
|
|
71
66
|
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* the file actually is. `entryId` being `undefined` (below) is the signal
|
|
76
|
-
* that this happened: when `entryId` is `undefined`, `entryType` is
|
|
77
|
-
* inferred rather than read.
|
|
67
|
+
* A legacy entry file (`{slug}.{ext}`) records no type at all, so this falls back to the
|
|
68
|
+
* collection's DEFAULT entry type, which may not be what the file is. `entryId` being
|
|
69
|
+
* `undefined` is the signal that this happened.
|
|
78
70
|
*/
|
|
79
71
|
entryType: string;
|
|
80
72
|
/**
|
|
81
|
-
* The entry's 12-char Base58 content ID, when the resolved file carries one.
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* `entryType` caveat above for what that implies about it.
|
|
73
|
+
* The entry's 12-char Base58 content ID, when the resolved file carries one. Undefined only
|
|
74
|
+
* for legacy entry files predating embedded-ID filenames (`{slug}.{ext}` rather than
|
|
75
|
+
* `{type}.{slug}.{id}.{ext}`) -- see the `entryType` caveat above for what that implies.
|
|
85
76
|
*/
|
|
86
77
|
entryId?: ContentId;
|
|
87
78
|
}
|
package/dist/content-reader.js
CHANGED
|
@@ -63,7 +63,6 @@ export const createContentReader = (options) => {
|
|
|
63
63
|
const resolveStore = async (branchName) => {
|
|
64
64
|
const context = await resolveBranchContext(branchName);
|
|
65
65
|
const { branchRoot } = resolveBranchPaths(context, operatingMode, basePathOverride);
|
|
66
|
-
// Load per-branch schema dynamically
|
|
67
66
|
const branchSchemaCache = services.branchSchemaCache;
|
|
68
67
|
const contentRootName = services.config.contentRoot || 'content';
|
|
69
68
|
const { flatSchema: branchFlatSchema } = await branchSchemaCache.getSchema(branchRoot, services.entrySchemaRegistry, contentRootName);
|
|
@@ -86,24 +85,22 @@ export const createContentReader = (options) => {
|
|
|
86
85
|
.filter(Boolean)
|
|
87
86
|
.map((segment) => encodeURIComponent(segment))
|
|
88
87
|
.join('/');
|
|
89
|
-
// Build preview paths using simple path construction
|
|
90
88
|
const contentRoot = trimSlashes(services.config.contentRoot ?? 'content');
|
|
91
89
|
// The `val === contentRoot` branch matters as much as the prefix one: a root-level entry's
|
|
92
|
-
// collectionPath IS the content root, which does not start with `${contentRoot}/`, so
|
|
93
|
-
// it the root index
|
|
94
|
-
// that resolve to nothing.
|
|
90
|
+
// collectionPath IS the content root, which does not start with `${contentRoot}/`, so
|
|
91
|
+
// without it the root index reports `path: '/content'` (and a root entry `/content/about`)
|
|
92
|
+
// -- paths that resolve to nothing.
|
|
95
93
|
//
|
|
96
94
|
// Both branches stay guarded on `contentRoot` so an empty one passes the value through
|
|
97
95
|
// unchanged, exactly as `computeEntryUrl` does. Unreachable today (`contentRootSchema` is
|
|
98
96
|
// `relativePathSchema.default('content')` with `.min(1)`), but a blanket short-circuit would
|
|
99
|
-
// be the WRONG answer if it ever were reachable
|
|
97
|
+
// be the WRONG answer if it ever were reachable: it would flatten every entry to root.
|
|
100
98
|
const stripRoot = (val) => contentRoot && val === contentRoot
|
|
101
99
|
? ''
|
|
102
100
|
: contentRoot && val.startsWith(`${contentRoot}/`)
|
|
103
101
|
? val.slice(contentRoot.length + 1)
|
|
104
102
|
: val;
|
|
105
103
|
const buildEntryPath = (opts) => {
|
|
106
|
-
// Construct preview path from collectionPath
|
|
107
104
|
const stripped = stripRoot(opts.collectionPath);
|
|
108
105
|
const base = stripped ? `/${stripped}` : '/';
|
|
109
106
|
const appendBranch = (url) => opts.branch
|
|
@@ -136,21 +133,18 @@ export const createContentReader = (options) => {
|
|
|
136
133
|
// for server-side colocated-artifact reads (e.g. a sibling profile.json). Already
|
|
137
134
|
// computed here for permission checks; just carried through.
|
|
138
135
|
let physicalPath;
|
|
139
|
-
// Entry type + content ID
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
// separate listEntries lookup or filename parse.
|
|
136
|
+
// Entry type + content ID come out of path resolution (buildPaths() derives both from the
|
|
137
|
+
// schema item / filename), surfaced on read() / readByUrlPath() so callers can route or
|
|
138
|
+
// key by them without a separate listEntries lookup or filename parse.
|
|
143
139
|
let entryType;
|
|
144
140
|
let entryId;
|
|
145
141
|
try {
|
|
146
142
|
const resolved = await store.resolveDocumentPath(entryPath, slug ?? '');
|
|
147
143
|
relativePath = resolved.relativePath;
|
|
148
144
|
physicalPath = resolved.absolutePath;
|
|
149
|
-
// resolveDocumentPath() always sets entryTypeName for a valid schema item
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
// is needed here — id is the one field that can be legitimately absent,
|
|
153
|
-
// for legacy entry files without an embedded ID (see ContentReadMeta).
|
|
145
|
+
// resolveDocumentPath() always sets entryTypeName for a valid schema item, so no
|
|
146
|
+
// further fallback is needed here; `id` is the one field that can be legitimately
|
|
147
|
+
// absent, for legacy entry files without an embedded ID (see ContentReadMeta).
|
|
154
148
|
entryType = resolved.entryTypeName;
|
|
155
149
|
entryId = resolved.id;
|
|
156
150
|
}
|
|
@@ -216,9 +210,7 @@ export const createContentReader = (options) => {
|
|
|
216
210
|
const rawData = docRecord.data;
|
|
217
211
|
const body = docRecord.body;
|
|
218
212
|
const bodyFieldName = docRecord.bodyFieldName ?? 'body';
|
|
219
|
-
// Merge body into data first, then resolve entry links across all fields
|
|
220
213
|
let data = (body != null ? { ...rawData, [bodyFieldName]: body } : rawData);
|
|
221
|
-
// Resolve entry:ID links in all string values (body + nested markdown fields)
|
|
222
214
|
if (input.resolveEntryLinks ?? true) {
|
|
223
215
|
const idIndex = await store.idIndex();
|
|
224
216
|
data = resolveEntryLinksInData(data, idIndex, contentRoot, services.config.entryLinkUrl);
|