canopycms 0.0.62 → 0.0.64
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 +153 -19
- package/dist/ai/generate.d.ts +4 -5
- package/dist/ai/generate.js +0 -1
- package/dist/ai/handler.d.ts +3 -4
- package/dist/ai/handler.js +0 -1
- package/dist/ai/index.d.ts +15 -7
- package/dist/ai/index.js +9 -1
- package/dist/ai/json-to-markdown.d.ts +1 -2
- package/dist/ai/json-to-markdown.js +11 -2
- package/dist/ai/resolve-branch.d.ts +1 -2
- package/dist/ai/resolve-branch.js +0 -1
- package/dist/ai/strip-mdx.d.ts +0 -1
- package/dist/ai/strip-mdx.js +0 -1
- package/dist/ai/to-plain-text.d.ts +60 -0
- package/dist/ai/to-plain-text.js +301 -0
- package/dist/ai/transform-components.d.ts +1 -2
- package/dist/ai/transform-components.js +70 -6
- package/dist/ai/types.d.ts +1 -2
- package/dist/ai/types.js +0 -1
- package/dist/api/admin-branch-health.d.ts +7 -8
- package/dist/api/admin-branch-health.js +0 -1
- package/dist/api/admin.d.ts +16 -17
- package/dist/api/admin.js +0 -1
- package/dist/api/assets.d.ts +8 -9
- package/dist/api/assets.js +0 -1
- package/dist/api/branch-merge.d.ts +3 -4
- package/dist/api/branch-merge.js +0 -1
- package/dist/api/branch-review.d.ts +5 -6
- package/dist/api/branch-review.js +0 -1
- package/dist/api/branch-status.d.ts +15 -16
- package/dist/api/branch-status.js +0 -1
- package/dist/api/branch-withdraw.d.ts +3 -4
- package/dist/api/branch-withdraw.js +0 -1
- package/dist/api/branch.d.ts +13 -14
- package/dist/api/branch.js +0 -1
- package/dist/api/client.d.ts +14 -15
- package/dist/api/client.js +0 -1
- package/dist/api/comments.d.ts +11 -12
- package/dist/api/comments.js +0 -1
- package/dist/api/content.d.ts +22 -24
- package/dist/api/content.js +132 -18
- package/dist/api/entries-constants.d.ts +0 -1
- package/dist/api/entries-constants.js +0 -1
- package/dist/api/entries.d.ts +12 -13
- package/dist/api/entries.js +12 -2
- package/dist/api/github-sync.d.ts +2 -3
- package/dist/api/github-sync.js +0 -1
- package/dist/api/groups.d.ts +6 -7
- package/dist/api/groups.js +0 -1
- package/dist/api/guards.d.ts +2 -3
- package/dist/api/guards.js +0 -1
- package/dist/api/index.d.ts +18 -19
- package/dist/api/index.js +0 -1
- package/dist/api/permissions.d.ts +10 -11
- package/dist/api/permissions.js +0 -1
- package/dist/api/reference-options.d.ts +3 -4
- package/dist/api/reference-options.js +0 -1
- package/dist/api/request-body-hash.d.ts +0 -1
- package/dist/api/request-body-hash.js +0 -1
- package/dist/api/resolve-references.d.ts +6 -7
- package/dist/api/resolve-references.js +24 -6
- package/dist/api/route-builder.d.ts +2 -3
- package/dist/api/route-builder.js +0 -1
- package/dist/api/schema.d.ts +43 -44
- package/dist/api/schema.js +0 -1
- package/dist/api/settings-helpers.d.ts +2 -3
- package/dist/api/settings-helpers.js +0 -1
- package/dist/api/types.d.ts +6 -7
- package/dist/api/types.js +0 -1
- package/dist/api/user.d.ts +2 -3
- package/dist/api/user.js +0 -1
- package/dist/api/validators.d.ts +3 -4
- package/dist/api/validators.js +0 -1
- package/dist/assets/asset-prefixes.d.ts +1 -2
- package/dist/assets/asset-prefixes.js +0 -1
- package/dist/assets/asset-src.d.ts +17 -5
- package/dist/assets/asset-src.js +15 -3
- package/dist/assets/asset-url.d.ts +28 -7
- package/dist/assets/asset-url.js +20 -15
- package/dist/assets/factory.d.ts +2 -3
- package/dist/assets/factory.js +0 -2
- package/dist/assets/finalize.d.ts +2 -3
- package/dist/assets/finalize.js +0 -1
- package/dist/assets/index.d.ts +12 -13
- package/dist/assets/index.js +0 -1
- package/dist/assets/keys.d.ts +1 -2
- package/dist/assets/keys.js +0 -1
- package/dist/assets/pipeline.d.ts +1 -2
- package/dist/assets/pipeline.js +0 -1
- package/dist/assets/store-local.d.ts +1 -2
- package/dist/assets/store-local.js +0 -1
- package/dist/assets/store-s3.d.ts +2 -4
- package/dist/assets/store-s3.js +0 -1
- package/dist/assets/svg-sanitizer.d.ts +0 -1
- package/dist/assets/svg-sanitizer.js +0 -1
- package/dist/assets/transform-directives.d.ts +0 -1
- package/dist/assets/transform-directives.js +0 -1
- package/dist/assets/transform.d.ts +1 -2
- package/dist/assets/transform.js +0 -1
- package/dist/assets/types.d.ts +0 -1
- package/dist/assets/types.js +0 -1
- package/dist/auth/cache.d.ts +2 -3
- package/dist/auth/cache.js +0 -1
- package/dist/auth/caching-auth-plugin.d.ts +3 -4
- package/dist/auth/caching-auth-plugin.js +0 -1
- package/dist/auth/context-helpers.d.ts +1 -2
- package/dist/auth/context-helpers.js +0 -1
- package/dist/auth/file-based-auth-cache.d.ts +3 -4
- package/dist/auth/file-based-auth-cache.js +0 -1
- package/dist/auth/index.d.ts +6 -7
- package/dist/auth/index.js +0 -1
- package/dist/auth/plugin.d.ts +3 -4
- package/dist/auth/plugin.js +0 -1
- package/dist/auth/types.d.ts +1 -2
- package/dist/auth/types.js +0 -1
- package/dist/authorization/branch.d.ts +58 -7
- package/dist/authorization/branch.js +55 -10
- package/dist/authorization/content.d.ts +6 -7
- package/dist/authorization/content.js +0 -1
- package/dist/authorization/groups/index.d.ts +2 -3
- package/dist/authorization/groups/index.js +0 -1
- package/dist/authorization/groups/loader.d.ts +3 -4
- package/dist/authorization/groups/loader.js +0 -1
- package/dist/authorization/groups/schema.d.ts +1 -2
- package/dist/authorization/groups/schema.js +0 -1
- package/dist/authorization/helpers.d.ts +0 -1
- package/dist/authorization/helpers.js +0 -1
- package/dist/authorization/index.d.ts +11 -12
- package/dist/authorization/index.js +0 -1
- package/dist/authorization/path.d.ts +4 -5
- package/dist/authorization/path.js +0 -1
- package/dist/authorization/permissions/index.d.ts +2 -3
- package/dist/authorization/permissions/index.js +0 -1
- package/dist/authorization/permissions/loader.d.ts +4 -5
- package/dist/authorization/permissions/loader.js +0 -1
- package/dist/authorization/permissions/schema.d.ts +2 -3
- package/dist/authorization/permissions/schema.js +0 -1
- package/dist/authorization/protected-branch.d.ts +2 -3
- package/dist/authorization/protected-branch.js +0 -1
- package/dist/authorization/settings-file-store.d.ts +1 -2
- package/dist/authorization/settings-file-store.js +0 -1
- package/dist/authorization/types.d.ts +7 -8
- package/dist/authorization/types.js +0 -1
- package/dist/authorization/validation.d.ts +1 -2
- package/dist/authorization/validation.js +0 -1
- package/dist/branch-health.d.ts +2 -3
- package/dist/branch-health.js +0 -1
- package/dist/branch-metadata.d.ts +2 -3
- package/dist/branch-metadata.js +0 -1
- package/dist/branch-registry.d.ts +1 -2
- package/dist/branch-registry.js +0 -1
- package/dist/branch-schema-cache.d.ts +4 -5
- package/dist/branch-schema-cache.js +0 -1
- package/dist/branch-workspace.d.ts +4 -5
- package/dist/branch-workspace.js +0 -1
- package/dist/build/generate-ai-content.d.ts +21 -5
- package/dist/build/generate-ai-content.js +98 -6
- package/dist/build/index.d.ts +2 -3
- package/dist/build/index.js +0 -1
- package/dist/build-canopy.d.ts +48 -0
- package/dist/build-canopy.js +50 -0
- package/dist/build-mode.d.ts +1 -2
- package/dist/build-mode.js +0 -1
- package/dist/cli/cli.d.ts +1 -2
- package/dist/cli/cli.js +1192 -495
- package/dist/cli/generate-ai-content.d.ts +0 -1
- package/dist/cli/generate-ai-content.js +1062 -370
- package/dist/cli/init.d.ts +1 -2
- package/dist/cli/init.js +12 -2
- package/dist/cli/migrate.d.ts +5 -3
- package/dist/cli/migrate.js +5 -3
- package/dist/cli/project-detect.d.ts +5 -2
- package/dist/cli/project-detect.js +5 -1
- package/dist/cli/project-root.d.ts +0 -1
- package/dist/cli/project-root.js +0 -1
- package/dist/cli/sync.d.ts +0 -1
- package/dist/cli/sync.js +0 -1
- package/dist/cli/template-files/canopycms.config.ts.template +18 -1
- package/dist/cli/template-files/deploy-cms.yml.template +8 -6
- package/dist/cli/templates.d.ts +0 -1
- package/dist/cli/templates.js +0 -1
- package/dist/client.d.ts +13 -14
- package/dist/client.js +0 -1
- package/dist/comment-store.d.ts +0 -1
- package/dist/comment-store.js +0 -1
- package/dist/config/flatten.d.ts +1 -2
- package/dist/config/flatten.js +0 -1
- package/dist/config/helpers.d.ts +3 -4
- package/dist/config/helpers.js +2 -2
- package/dist/config/index.d.ts +10 -11
- package/dist/config/index.js +0 -1
- package/dist/config/schemas/collection.d.ts +0 -1
- package/dist/config/schemas/collection.js +0 -1
- package/dist/config/schemas/config.d.ts +7 -4
- package/dist/config/schemas/config.js +12 -1
- package/dist/config/schemas/field.d.ts +3 -1
- package/dist/config/schemas/field.js +5 -1
- package/dist/config/schemas/media.d.ts +0 -1
- package/dist/config/schemas/media.js +0 -1
- package/dist/config/schemas/permissions.d.ts +0 -1
- package/dist/config/schemas/permissions.js +0 -1
- package/dist/config/types.d.ts +55 -9
- package/dist/config/types.js +0 -1
- package/dist/config/validation.d.ts +1 -2
- package/dist/config/validation.js +0 -1
- package/dist/config.d.ts +2 -3
- package/dist/config.js +0 -1
- package/dist/content-id-index.d.ts +1 -2
- package/dist/content-id-index.js +0 -1
- package/dist/content-index-generation.d.ts +0 -1
- package/dist/content-index-generation.js +0 -1
- package/dist/content-index-registry.d.ts +0 -1
- package/dist/content-index-registry.js +0 -1
- package/dist/content-listing.d.ts +137 -16
- package/dist/content-listing.js +175 -41
- package/dist/content-reader.d.ts +44 -8
- package/dist/content-reader.js +39 -7
- package/dist/content-store.d.ts +147 -7
- package/dist/content-store.js +294 -22
- package/dist/content-tree.d.ts +44 -5
- package/dist/content-tree.js +47 -11
- package/dist/context.d.ts +38 -15
- package/dist/context.js +55 -5
- package/dist/dev-content-watcher.d.ts +2 -3
- package/dist/dev-content-watcher.js +0 -1
- package/dist/editor/BranchManager.d.ts +4 -5
- package/dist/editor/BranchManager.js +0 -1
- package/dist/editor/CanopyEditor.d.ts +2 -3
- package/dist/editor/CanopyEditor.js +1 -2
- package/dist/editor/CanopyEditorPage.d.ts +2 -3
- package/dist/editor/CanopyEditorPage.js +0 -1
- package/dist/editor/CommentsPanel.d.ts +2 -3
- package/dist/editor/CommentsPanel.js +0 -1
- package/dist/editor/Editor.d.ts +13 -8
- package/dist/editor/Editor.js +4 -5
- package/dist/editor/EditorPanes.d.ts +0 -1
- package/dist/editor/EditorPanes.js +0 -1
- package/dist/editor/EntryNavigator.d.ts +1 -2
- package/dist/editor/EntryNavigator.js +0 -1
- package/dist/editor/FormRenderer.d.ts +2 -3
- package/dist/editor/FormRenderer.js +22 -3
- package/dist/editor/GroupManager.d.ts +2 -3
- package/dist/editor/GroupManager.js +0 -1
- package/dist/editor/PermissionManager.d.ts +2 -3
- package/dist/editor/PermissionManager.js +0 -1
- package/dist/editor/admin/SystemHealthPanel.d.ts +0 -1
- package/dist/editor/admin/SystemHealthPanel.js +0 -1
- package/dist/editor/admin/useSystemHealth.d.ts +2 -3
- package/dist/editor/admin/useSystemHealth.js +0 -1
- package/dist/editor/canopy-path.d.ts +0 -1
- package/dist/editor/canopy-path.js +0 -1
- package/dist/editor/client-reference-resolver.d.ts +13 -4
- package/dist/editor/client-reference-resolver.js +18 -8
- package/dist/editor/comments/BranchComments.d.ts +2 -3
- package/dist/editor/comments/BranchComments.js +0 -1
- package/dist/editor/comments/EntryComments.d.ts +1 -2
- package/dist/editor/comments/EntryComments.js +0 -1
- package/dist/editor/comments/FieldWrapper.d.ts +1 -2
- package/dist/editor/comments/FieldWrapper.js +0 -1
- package/dist/editor/comments/InlineCommentThread.d.ts +2 -3
- package/dist/editor/comments/InlineCommentThread.js +0 -1
- package/dist/editor/comments/ThreadCarousel.d.ts +2 -3
- package/dist/editor/comments/ThreadCarousel.js +0 -1
- package/dist/editor/components/ConfirmDeleteModal.d.ts +0 -1
- package/dist/editor/components/ConfirmDeleteModal.js +0 -1
- package/dist/editor/components/EditorFooter.d.ts +0 -1
- package/dist/editor/components/EditorFooter.js +0 -1
- package/dist/editor/components/EditorHeader.d.ts +4 -5
- package/dist/editor/components/EditorHeader.js +0 -1
- package/dist/editor/components/EditorSidebar.d.ts +1 -2
- package/dist/editor/components/EditorSidebar.js +0 -1
- package/dist/editor/components/EntryCreateModal.d.ts +0 -1
- package/dist/editor/components/EntryCreateModal.js +21 -10
- package/dist/editor/components/RenameEntryModal.d.ts +0 -1
- package/dist/editor/components/RenameEntryModal.js +0 -1
- package/dist/editor/components/UserBadge.d.ts +2 -3
- package/dist/editor/components/UserBadge.js +0 -1
- package/dist/editor/components/index.d.ts +3 -4
- package/dist/editor/components/index.js +0 -1
- package/dist/editor/context/ApiClientContext.d.ts +9 -3
- package/dist/editor/context/ApiClientContext.js +8 -4
- package/dist/editor/context/AssetContext.d.ts +26 -2
- package/dist/editor/context/AssetContext.js +23 -3
- package/dist/editor/context/EditorStateContext.d.ts +1 -2
- package/dist/editor/context/EditorStateContext.js +0 -1
- package/dist/editor/context/SWRProvider.d.ts +0 -1
- package/dist/editor/context/SWRProvider.js +0 -1
- package/dist/editor/context/index.d.ts +4 -5
- package/dist/editor/context/index.js +0 -1
- package/dist/editor/editor-config.d.ts +2 -3
- package/dist/editor/editor-config.js +0 -1
- package/dist/editor/editor-utils.d.ts +22 -10
- package/dist/editor/editor-utils.js +41 -10
- package/dist/editor/fields/BlockField.d.ts +1 -2
- package/dist/editor/fields/BlockField.js +0 -1
- package/dist/editor/fields/CodeField.d.ts +0 -1
- package/dist/editor/fields/CodeField.js +0 -1
- package/dist/editor/fields/DateTimeField.d.ts +0 -1
- package/dist/editor/fields/DateTimeField.js +0 -1
- package/dist/editor/fields/ImageField.d.ts +1 -2
- package/dist/editor/fields/ImageField.js +0 -1
- package/dist/editor/fields/InlineGroupField.d.ts +2 -3
- package/dist/editor/fields/InlineGroupField.js +0 -1
- package/dist/editor/fields/MarkdownField.d.ts +0 -1
- package/dist/editor/fields/MarkdownField.js +0 -1
- package/dist/editor/fields/MdxImageDialog.d.ts +0 -1
- package/dist/editor/fields/MdxImageDialog.js +0 -1
- package/dist/editor/fields/NumberField.d.ts +0 -1
- package/dist/editor/fields/NumberField.js +0 -1
- package/dist/editor/fields/NumberListField.d.ts +0 -1
- package/dist/editor/fields/NumberListField.js +0 -1
- package/dist/editor/fields/ObjectField.d.ts +11 -2
- package/dist/editor/fields/ObjectField.js +3 -4
- package/dist/editor/fields/ReferenceField.d.ts +0 -1
- package/dist/editor/fields/ReferenceField.js +8 -3
- package/dist/editor/fields/SelectField.d.ts +0 -1
- package/dist/editor/fields/SelectField.js +0 -1
- package/dist/editor/fields/StringListField.d.ts +0 -1
- package/dist/editor/fields/StringListField.js +0 -1
- 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.d.ts +1 -2
- package/dist/editor/fields/entry-link/EntryLinkContext.js +0 -1
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +0 -1
- package/dist/editor/fields/entry-link/InsertEntryLink.js +0 -1
- package/dist/editor/fields/entry-link/index.d.ts +2 -3
- package/dist/editor/fields/entry-link/index.js +0 -1
- package/dist/editor/group-manager/ExternalGroupsTab.d.ts +1 -2
- package/dist/editor/group-manager/ExternalGroupsTab.js +0 -1
- package/dist/editor/group-manager/GroupCard.d.ts +1 -2
- package/dist/editor/group-manager/GroupCard.js +0 -1
- package/dist/editor/group-manager/GroupForm.d.ts +1 -2
- package/dist/editor/group-manager/GroupForm.js +0 -1
- package/dist/editor/group-manager/InternalGroupsTab.d.ts +1 -2
- package/dist/editor/group-manager/InternalGroupsTab.js +0 -1
- package/dist/editor/group-manager/MemberList.d.ts +1 -2
- package/dist/editor/group-manager/MemberList.js +0 -1
- package/dist/editor/group-manager/hooks/useExternalGroupSearch.d.ts +1 -2
- package/dist/editor/group-manager/hooks/useExternalGroupSearch.js +0 -1
- package/dist/editor/group-manager/hooks/useGroupState.d.ts +1 -2
- package/dist/editor/group-manager/hooks/useGroupState.js +0 -1
- package/dist/editor/group-manager/hooks/useUserSearch.d.ts +1 -2
- package/dist/editor/group-manager/hooks/useUserSearch.js +0 -1
- package/dist/editor/group-manager/index.d.ts +5 -6
- package/dist/editor/group-manager/index.js +0 -1
- package/dist/editor/group-manager/types.d.ts +4 -5
- package/dist/editor/group-manager/types.js +0 -1
- package/dist/editor/hooks/index.d.ts +14 -15
- package/dist/editor/hooks/index.js +0 -1
- package/dist/editor/hooks/useBranchActions.d.ts +0 -1
- package/dist/editor/hooks/useBranchActions.js +0 -1
- package/dist/editor/hooks/useBranchManager.d.ts +4 -5
- package/dist/editor/hooks/useBranchManager.js +0 -1
- package/dist/editor/hooks/useBranchesData.d.ts +2 -3
- package/dist/editor/hooks/useBranchesData.js +0 -1
- package/dist/editor/hooks/useCommentSystem.d.ts +2 -3
- package/dist/editor/hooks/useCommentSystem.js +0 -1
- package/dist/editor/hooks/useCommentsData.d.ts +2 -3
- package/dist/editor/hooks/useCommentsData.js +0 -1
- package/dist/editor/hooks/useDraftManager.d.ts +3 -4
- package/dist/editor/hooks/useDraftManager.js +0 -1
- package/dist/editor/hooks/useEditorLayout.d.ts +1 -2
- package/dist/editor/hooks/useEditorLayout.js +0 -1
- package/dist/editor/hooks/useEntriesData.d.ts +3 -5
- package/dist/editor/hooks/useEntriesData.js +0 -3
- package/dist/editor/hooks/useEntryLinkResolution.d.ts +2 -3
- package/dist/editor/hooks/useEntryLinkResolution.js +0 -1
- package/dist/editor/hooks/useEntryManager.d.ts +5 -7
- package/dist/editor/hooks/useEntryManager.js +8 -3
- package/dist/editor/hooks/useGroupManager.d.ts +2 -3
- package/dist/editor/hooks/useGroupManager.js +0 -1
- package/dist/editor/hooks/usePermissionManager.d.ts +2 -3
- package/dist/editor/hooks/usePermissionManager.js +0 -1
- package/dist/editor/hooks/useReferenceResolution.d.ts +1 -2
- package/dist/editor/hooks/useReferenceResolution.js +8 -3
- package/dist/editor/hooks/useSchemaManager.d.ts +2 -3
- package/dist/editor/hooks/useSchemaManager.js +0 -1
- package/dist/editor/hooks/useUserContext.d.ts +1 -2
- package/dist/editor/hooks/useUserContext.js +8 -3
- package/dist/editor/hooks/useUserMetadata.d.ts +2 -3
- package/dist/editor/hooks/useUserMetadata.js +0 -1
- package/dist/editor/media/AssetCard.d.ts +1 -2
- package/dist/editor/media/AssetCard.js +0 -1
- package/dist/editor/media/CropStep.d.ts +1 -2
- package/dist/editor/media/CropStep.js +0 -1
- package/dist/editor/media/MediaLibrary.d.ts +1 -2
- package/dist/editor/media/MediaLibrary.js +0 -1
- package/dist/editor/media/MediaLibraryBody.d.ts +1 -2
- package/dist/editor/media/MediaLibraryBody.js +0 -1
- package/dist/editor/media/crop-math.d.ts +1 -2
- package/dist/editor/media/crop-math.js +0 -1
- package/dist/editor/media/upload-asset.d.ts +2 -3
- package/dist/editor/media/upload-asset.js +0 -1
- package/dist/editor/media/upload-constants.d.ts +0 -1
- package/dist/editor/media/upload-constants.js +0 -1
- package/dist/editor/media/useAssetUpload.d.ts +1 -2
- package/dist/editor/media/useAssetUpload.js +0 -1
- package/dist/editor/media/xhr-upload.d.ts +0 -1
- package/dist/editor/media/xhr-upload.js +0 -1
- package/dist/editor/permission-manager/GroupSelector.d.ts +1 -2
- package/dist/editor/permission-manager/GroupSelector.js +0 -1
- package/dist/editor/permission-manager/PermissionEditor.d.ts +1 -2
- package/dist/editor/permission-manager/PermissionEditor.js +0 -1
- package/dist/editor/permission-manager/PermissionLevelBadge.d.ts +1 -2
- package/dist/editor/permission-manager/PermissionLevelBadge.js +0 -1
- package/dist/editor/permission-manager/PermissionTree.d.ts +1 -2
- package/dist/editor/permission-manager/PermissionTree.js +0 -1
- package/dist/editor/permission-manager/UserSelector.d.ts +1 -2
- package/dist/editor/permission-manager/UserSelector.js +0 -1
- package/dist/editor/permission-manager/constants.d.ts +1 -2
- package/dist/editor/permission-manager/constants.js +0 -1
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts +1 -2
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js +0 -1
- package/dist/editor/permission-manager/hooks/usePermissionTree.d.ts +2 -3
- package/dist/editor/permission-manager/hooks/usePermissionTree.js +0 -1
- package/dist/editor/permission-manager/index.d.ts +4 -5
- package/dist/editor/permission-manager/index.js +0 -1
- package/dist/editor/permission-manager/types.d.ts +3 -4
- package/dist/editor/permission-manager/types.js +0 -1
- package/dist/editor/permission-manager/utils.d.ts +2 -3
- package/dist/editor/permission-manager/utils.js +0 -1
- package/dist/editor/preview-bridge.d.ts +1 -2
- package/dist/editor/preview-bridge.js +0 -1
- package/dist/editor/relative-time.d.ts +0 -1
- package/dist/editor/relative-time.js +0 -1
- package/dist/editor/schema-editor/CollectionEditor.d.ts +4 -5
- package/dist/editor/schema-editor/CollectionEditor.js +0 -1
- package/dist/editor/schema-editor/EntryTypeEditor.d.ts +2 -3
- package/dist/editor/schema-editor/EntryTypeEditor.js +0 -1
- package/dist/editor/schema-editor/index.d.ts +2 -3
- package/dist/editor/schema-editor/index.js +0 -1
- package/dist/editor/theme.d.ts +0 -1
- package/dist/editor/theme.js +0 -1
- package/dist/editor/utils/env.d.ts +0 -1
- package/dist/editor/utils/env.js +0 -1
- package/dist/entry-link-resolver.d.ts +1 -2
- package/dist/entry-link-resolver.js +0 -1
- package/dist/entry-schema-registry.d.ts +3 -4
- package/dist/entry-schema-registry.js +6 -2
- package/dist/entry-schema.d.ts +342 -11
- package/dist/entry-schema.js +170 -1
- package/dist/git-manager.d.ts +1 -2
- package/dist/git-manager.js +0 -1
- package/dist/github-service.d.ts +1 -2
- package/dist/github-service.js +0 -1
- package/dist/http/handler.d.ts +6 -7
- package/dist/http/handler.js +0 -1
- package/dist/http/index.d.ts +6 -7
- package/dist/http/index.js +0 -1
- package/dist/http/router.d.ts +2 -3
- package/dist/http/router.js +0 -1
- package/dist/http/types.d.ts +0 -1
- package/dist/http/types.js +0 -1
- package/dist/id.d.ts +2 -3
- package/dist/id.js +0 -1
- package/dist/index.d.ts +17 -17
- package/dist/index.js +7 -1
- package/dist/operating-mode/client-safe-strategy.d.ts +1 -2
- package/dist/operating-mode/client-safe-strategy.js +0 -1
- package/dist/operating-mode/client-unsafe-strategy.d.ts +1 -2
- package/dist/operating-mode/client-unsafe-strategy.js +0 -1
- package/dist/operating-mode/client.d.ts +3 -4
- package/dist/operating-mode/client.js +0 -1
- package/dist/operating-mode/deployment-name-fixtures.d.ts +0 -1
- package/dist/operating-mode/deployment-name-fixtures.js +0 -1
- package/dist/operating-mode/deployment-name.d.ts +0 -1
- package/dist/operating-mode/deployment-name.js +0 -1
- package/dist/operating-mode/index.d.ts +5 -6
- package/dist/operating-mode/index.js +0 -1
- package/dist/operating-mode/mode-env.d.ts +1 -2
- package/dist/operating-mode/mode-env.js +0 -1
- package/dist/operating-mode/types.d.ts +2 -3
- package/dist/operating-mode/types.js +0 -1
- package/dist/paths/branch-name.d.ts +1 -2
- package/dist/paths/branch-name.js +0 -1
- package/dist/paths/branch.d.ts +3 -4
- package/dist/paths/branch.js +0 -1
- package/dist/paths/index.d.ts +8 -9
- package/dist/paths/index.js +0 -1
- package/dist/paths/normalize-server.d.ts +1 -2
- package/dist/paths/normalize-server.js +0 -1
- package/dist/paths/normalize.d.ts +1 -2
- package/dist/paths/normalize.js +0 -1
- package/dist/paths/resolve.d.ts +2 -3
- package/dist/paths/resolve.js +0 -1
- package/dist/paths/types.d.ts +0 -1
- package/dist/paths/types.js +0 -1
- package/dist/paths/validation.d.ts +1 -2
- package/dist/paths/validation.js +0 -1
- package/dist/reference-resolver.d.ts +3 -4
- package/dist/reference-resolver.js +0 -1
- package/dist/resolve-canopy-user.d.ts +3 -4
- package/dist/resolve-canopy-user.js +0 -1
- package/dist/resource-generation.d.ts +0 -1
- package/dist/resource-generation.js +0 -1
- package/dist/schema/index.d.ts +3 -4
- package/dist/schema/index.js +0 -1
- package/dist/schema/meta-loader.d.ts +3 -4
- package/dist/schema/meta-loader.js +3 -3
- package/dist/schema/resolver.d.ts +2 -3
- package/dist/schema/resolver.js +0 -1
- package/dist/schema/schema-store-types.d.ts +2 -3
- package/dist/schema/schema-store-types.js +0 -1
- package/dist/schema/schema-store.d.ts +6 -7
- package/dist/schema/schema-store.js +33 -1
- package/dist/schema/types.d.ts +1 -2
- package/dist/schema/types.js +0 -1
- package/dist/server.d.ts +97 -37
- package/dist/server.js +60 -3
- package/dist/services.d.ts +10 -12
- package/dist/services.js +2 -7
- package/dist/settings-workspace.d.ts +12 -15
- package/dist/settings-workspace.js +10 -13
- package/dist/static/index.d.ts +227 -9
- package/dist/static/index.js +302 -14
- package/dist/static/seo.d.ts +128 -0
- package/dist/static/seo.js +162 -0
- package/dist/sync-core.d.ts +0 -1
- package/dist/sync-core.js +0 -1
- package/dist/task-queue/index.d.ts +2 -3
- package/dist/task-queue/index.js +0 -1
- package/dist/task-queue/task-queue.d.ts +1 -2
- package/dist/task-queue/task-queue.js +0 -1
- package/dist/task-queue/types.d.ts +0 -1
- package/dist/task-queue/types.js +0 -1
- package/dist/types.d.ts +3 -4
- package/dist/types.js +0 -1
- package/dist/url-collision.d.ts +86 -0
- package/dist/url-collision.js +186 -0
- package/dist/url-path-resolver.d.ts +11 -2
- package/dist/url-path-resolver.js +37 -5
- package/dist/user.d.ts +3 -4
- package/dist/user.js +0 -1
- package/dist/utils/async-mutex.d.ts +0 -1
- package/dist/utils/async-mutex.js +0 -1
- package/dist/utils/atomic-write.d.ts +0 -1
- package/dist/utils/atomic-write.js +0 -1
- package/dist/utils/body-field.d.ts +12 -2
- package/dist/utils/body-field.js +17 -1
- package/dist/utils/content-serialize.d.ts +37 -0
- package/dist/utils/content-serialize.js +429 -0
- package/dist/utils/content-write-lock.d.ts +12 -16
- package/dist/utils/content-write-lock.js +38 -22
- package/dist/utils/debug.d.ts +0 -1
- package/dist/utils/debug.js +0 -1
- package/dist/utils/entry-url.d.ts +17 -1
- package/dist/utils/entry-url.js +21 -3
- package/dist/utils/error.d.ts +0 -1
- package/dist/utils/error.js +0 -1
- package/dist/utils/flatten-group-fields.d.ts +1 -2
- package/dist/utils/flatten-group-fields.js +0 -1
- package/dist/utils/format.d.ts +1 -2
- package/dist/utils/format.js +0 -1
- package/dist/utils/fs.d.ts +7 -1
- package/dist/utils/fs.js +16 -1
- package/dist/utils/git.d.ts +1 -2
- package/dist/utils/git.js +0 -1
- package/dist/utils/logger.d.ts +0 -1
- package/dist/utils/logger.js +0 -1
- package/dist/utils/occ-json-write.d.ts +0 -1
- package/dist/utils/occ-json-write.js +0 -1
- package/dist/utils/provisioning-lock.d.ts +17 -4
- package/dist/utils/provisioning-lock.js +94 -14
- package/dist/utils/sanitize-href.d.ts +46 -1
- package/dist/utils/sanitize-href.js +63 -3
- package/dist/utils/title-field.d.ts +1 -2
- package/dist/utils/title-field.js +0 -1
- package/dist/utils/typed-filename.d.ts +61 -0
- package/dist/utils/typed-filename.js +92 -0
- package/dist/utils/url-prefix.d.ts +121 -0
- package/dist/utils/url-prefix.js +158 -0
- package/dist/validation/block-structural-keys.d.ts +42 -0
- package/dist/validation/block-structural-keys.js +44 -0
- package/dist/validation/deletion-checker.d.ts +4 -5
- package/dist/validation/deletion-checker.js +0 -1
- package/dist/validation/entry-link-validator.d.ts +2 -3
- package/dist/validation/entry-link-validator.js +0 -1
- package/dist/validation/entry-type-reference-validator.d.ts +1 -2
- package/dist/validation/entry-type-reference-validator.js +0 -1
- package/dist/validation/entry-validator.d.ts +23 -2
- package/dist/validation/entry-validator.js +34 -2
- package/dist/validation/field-traversal.d.ts +28 -4
- package/dist/validation/field-traversal.js +24 -7
- package/dist/validation/reference-validator.d.ts +2 -3
- package/dist/validation/reference-validator.js +0 -1
- package/dist/worker/cms-worker.d.ts +9 -2
- package/dist/worker/cms-worker.js +59 -2
- package/dist/worker/log.d.ts +0 -1
- package/dist/worker/log.js +0 -1
- package/dist/worker/task-queue-config.d.ts +1 -2
- package/dist/worker/task-queue-config.js +0 -1
- package/dist/worker/task-queue.d.ts +3 -4
- package/dist/worker/task-queue.js +0 -1
- package/dist/worker/worker-status.d.ts +1 -2
- package/dist/worker/worker-status.js +0 -1
- package/package.json +2 -6
- package/dist/ai/generate.d.ts.map +0 -1
- package/dist/ai/generate.js.map +0 -1
- package/dist/ai/handler.d.ts.map +0 -1
- package/dist/ai/handler.js.map +0 -1
- package/dist/ai/index.d.ts.map +0 -1
- package/dist/ai/index.js.map +0 -1
- package/dist/ai/json-to-markdown.d.ts.map +0 -1
- package/dist/ai/json-to-markdown.js.map +0 -1
- package/dist/ai/resolve-branch.d.ts.map +0 -1
- package/dist/ai/resolve-branch.js.map +0 -1
- package/dist/ai/strip-mdx.d.ts.map +0 -1
- package/dist/ai/strip-mdx.js.map +0 -1
- package/dist/ai/transform-components.d.ts.map +0 -1
- package/dist/ai/transform-components.js.map +0 -1
- package/dist/ai/types.d.ts.map +0 -1
- package/dist/ai/types.js.map +0 -1
- package/dist/api/__test__/mock-client.d.ts +0 -231
- package/dist/api/__test__/mock-client.d.ts.map +0 -1
- package/dist/api/__test__/mock-client.js +0 -388
- package/dist/api/__test__/mock-client.js.map +0 -1
- package/dist/api/admin-branch-health.d.ts.map +0 -1
- package/dist/api/admin-branch-health.js.map +0 -1
- package/dist/api/admin.d.ts.map +0 -1
- package/dist/api/admin.js.map +0 -1
- package/dist/api/assets.d.ts.map +0 -1
- package/dist/api/assets.js.map +0 -1
- package/dist/api/branch-merge.d.ts.map +0 -1
- package/dist/api/branch-merge.js.map +0 -1
- package/dist/api/branch-review.d.ts.map +0 -1
- package/dist/api/branch-review.js.map +0 -1
- package/dist/api/branch-status.d.ts.map +0 -1
- package/dist/api/branch-status.js.map +0 -1
- package/dist/api/branch-withdraw.d.ts.map +0 -1
- package/dist/api/branch-withdraw.js.map +0 -1
- package/dist/api/branch.d.ts.map +0 -1
- package/dist/api/branch.js.map +0 -1
- package/dist/api/client.d.ts.map +0 -1
- package/dist/api/client.js.map +0 -1
- package/dist/api/comments.d.ts.map +0 -1
- package/dist/api/comments.js.map +0 -1
- package/dist/api/content.d.ts.map +0 -1
- package/dist/api/content.js.map +0 -1
- package/dist/api/entries-constants.d.ts.map +0 -1
- package/dist/api/entries-constants.js.map +0 -1
- package/dist/api/entries.d.ts.map +0 -1
- package/dist/api/entries.js.map +0 -1
- package/dist/api/github-sync.d.ts.map +0 -1
- package/dist/api/github-sync.js.map +0 -1
- package/dist/api/groups.d.ts.map +0 -1
- package/dist/api/groups.js.map +0 -1
- package/dist/api/guards.d.ts.map +0 -1
- package/dist/api/guards.js.map +0 -1
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js.map +0 -1
- package/dist/api/permissions.d.ts.map +0 -1
- package/dist/api/permissions.js.map +0 -1
- package/dist/api/reference-options.d.ts.map +0 -1
- package/dist/api/reference-options.js.map +0 -1
- package/dist/api/request-body-hash.d.ts.map +0 -1
- package/dist/api/request-body-hash.js.map +0 -1
- package/dist/api/resolve-references.d.ts.map +0 -1
- package/dist/api/resolve-references.js.map +0 -1
- package/dist/api/route-builder.d.ts.map +0 -1
- package/dist/api/route-builder.js.map +0 -1
- package/dist/api/schema.d.ts.map +0 -1
- package/dist/api/schema.js.map +0 -1
- package/dist/api/settings-helpers.d.ts.map +0 -1
- package/dist/api/settings-helpers.js.map +0 -1
- package/dist/api/types.d.ts.map +0 -1
- package/dist/api/types.js.map +0 -1
- package/dist/api/user.d.ts.map +0 -1
- package/dist/api/user.js.map +0 -1
- package/dist/api/validators.d.ts.map +0 -1
- package/dist/api/validators.js.map +0 -1
- package/dist/assets/asset-prefixes.d.ts.map +0 -1
- package/dist/assets/asset-prefixes.js.map +0 -1
- package/dist/assets/asset-src.d.ts.map +0 -1
- package/dist/assets/asset-src.js.map +0 -1
- package/dist/assets/asset-url.d.ts.map +0 -1
- package/dist/assets/asset-url.js.map +0 -1
- package/dist/assets/factory.d.ts.map +0 -1
- package/dist/assets/factory.js.map +0 -1
- package/dist/assets/finalize.d.ts.map +0 -1
- package/dist/assets/finalize.js.map +0 -1
- package/dist/assets/index.d.ts.map +0 -1
- package/dist/assets/index.js.map +0 -1
- package/dist/assets/keys.d.ts.map +0 -1
- package/dist/assets/keys.js.map +0 -1
- package/dist/assets/pipeline.d.ts.map +0 -1
- package/dist/assets/pipeline.js.map +0 -1
- package/dist/assets/store-local.d.ts.map +0 -1
- package/dist/assets/store-local.js.map +0 -1
- package/dist/assets/store-s3.d.ts.map +0 -1
- package/dist/assets/store-s3.js.map +0 -1
- package/dist/assets/svg-sanitizer.d.ts.map +0 -1
- package/dist/assets/svg-sanitizer.js.map +0 -1
- package/dist/assets/transform-directives.d.ts.map +0 -1
- package/dist/assets/transform-directives.js.map +0 -1
- package/dist/assets/transform.d.ts.map +0 -1
- package/dist/assets/transform.js.map +0 -1
- package/dist/assets/types.d.ts.map +0 -1
- package/dist/assets/types.js.map +0 -1
- package/dist/auth/cache.d.ts.map +0 -1
- package/dist/auth/cache.js.map +0 -1
- package/dist/auth/caching-auth-plugin.d.ts.map +0 -1
- package/dist/auth/caching-auth-plugin.js.map +0 -1
- package/dist/auth/context-helpers.d.ts.map +0 -1
- package/dist/auth/context-helpers.js.map +0 -1
- package/dist/auth/file-based-auth-cache.d.ts.map +0 -1
- package/dist/auth/file-based-auth-cache.js.map +0 -1
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/plugin.d.ts.map +0 -1
- package/dist/auth/plugin.js.map +0 -1
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/auth/types.js.map +0 -1
- package/dist/authorization/branch.d.ts.map +0 -1
- package/dist/authorization/branch.js.map +0 -1
- package/dist/authorization/content.d.ts.map +0 -1
- package/dist/authorization/content.js.map +0 -1
- package/dist/authorization/groups/index.d.ts.map +0 -1
- package/dist/authorization/groups/index.js.map +0 -1
- package/dist/authorization/groups/loader.d.ts.map +0 -1
- package/dist/authorization/groups/loader.js.map +0 -1
- package/dist/authorization/groups/schema.d.ts.map +0 -1
- package/dist/authorization/groups/schema.js.map +0 -1
- package/dist/authorization/helpers.d.ts.map +0 -1
- package/dist/authorization/helpers.js.map +0 -1
- package/dist/authorization/index.d.ts.map +0 -1
- package/dist/authorization/index.js.map +0 -1
- package/dist/authorization/path.d.ts.map +0 -1
- package/dist/authorization/path.js.map +0 -1
- package/dist/authorization/permissions/index.d.ts.map +0 -1
- package/dist/authorization/permissions/index.js.map +0 -1
- package/dist/authorization/permissions/loader.d.ts.map +0 -1
- package/dist/authorization/permissions/loader.js.map +0 -1
- package/dist/authorization/permissions/schema.d.ts.map +0 -1
- package/dist/authorization/permissions/schema.js.map +0 -1
- package/dist/authorization/protected-branch.d.ts.map +0 -1
- package/dist/authorization/protected-branch.js.map +0 -1
- package/dist/authorization/settings-file-store.d.ts.map +0 -1
- package/dist/authorization/settings-file-store.js.map +0 -1
- package/dist/authorization/test-utils.d.ts +0 -26
- package/dist/authorization/test-utils.d.ts.map +0 -1
- package/dist/authorization/test-utils.js +0 -23
- package/dist/authorization/test-utils.js.map +0 -1
- package/dist/authorization/types.d.ts.map +0 -1
- package/dist/authorization/types.js.map +0 -1
- package/dist/authorization/validation.d.ts.map +0 -1
- package/dist/authorization/validation.js.map +0 -1
- package/dist/branch-health.d.ts.map +0 -1
- package/dist/branch-health.js.map +0 -1
- package/dist/branch-metadata.d.ts.map +0 -1
- package/dist/branch-metadata.js.map +0 -1
- package/dist/branch-registry.d.ts.map +0 -1
- package/dist/branch-registry.js.map +0 -1
- package/dist/branch-schema-cache.d.ts.map +0 -1
- package/dist/branch-schema-cache.js.map +0 -1
- package/dist/branch-workspace.d.ts.map +0 -1
- package/dist/branch-workspace.js.map +0 -1
- package/dist/build/generate-ai-content.d.ts.map +0 -1
- package/dist/build/generate-ai-content.js.map +0 -1
- package/dist/build/index.d.ts.map +0 -1
- package/dist/build/index.js.map +0 -1
- package/dist/build-mode.d.ts.map +0 -1
- package/dist/build-mode.js.map +0 -1
- package/dist/cli/cli.d.ts.map +0 -1
- package/dist/cli/cli.js.map +0 -1
- package/dist/cli/generate-ai-content.d.ts.map +0 -1
- package/dist/cli/generate-ai-content.js.map +0 -1
- package/dist/cli/init.d.ts.map +0 -1
- package/dist/cli/init.js.map +0 -1
- package/dist/cli/migrate.d.ts.map +0 -1
- package/dist/cli/migrate.js.map +0 -1
- package/dist/cli/project-detect.d.ts.map +0 -1
- package/dist/cli/project-detect.js.map +0 -1
- package/dist/cli/project-root.d.ts.map +0 -1
- package/dist/cli/project-root.js.map +0 -1
- package/dist/cli/sync.d.ts.map +0 -1
- package/dist/cli/sync.js.map +0 -1
- package/dist/cli/templates.d.ts.map +0 -1
- package/dist/cli/templates.js.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/comment-store.d.ts.map +0 -1
- package/dist/comment-store.js.map +0 -1
- package/dist/config/flatten.d.ts.map +0 -1
- package/dist/config/flatten.js.map +0 -1
- package/dist/config/helpers.d.ts.map +0 -1
- package/dist/config/helpers.js.map +0 -1
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js.map +0 -1
- package/dist/config/schemas/collection.d.ts.map +0 -1
- package/dist/config/schemas/collection.js.map +0 -1
- package/dist/config/schemas/config.d.ts.map +0 -1
- package/dist/config/schemas/config.js.map +0 -1
- package/dist/config/schemas/field.d.ts.map +0 -1
- package/dist/config/schemas/field.js.map +0 -1
- package/dist/config/schemas/media.d.ts.map +0 -1
- package/dist/config/schemas/media.js.map +0 -1
- package/dist/config/schemas/permissions.d.ts.map +0 -1
- package/dist/config/schemas/permissions.js.map +0 -1
- package/dist/config/types.d.ts.map +0 -1
- package/dist/config/types.js.map +0 -1
- package/dist/config/validation.d.ts.map +0 -1
- package/dist/config/validation.js.map +0 -1
- package/dist/config-test.d.ts +0 -20
- package/dist/config-test.d.ts.map +0 -1
- package/dist/config-test.js +0 -49
- package/dist/config-test.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/content-id-index.d.ts.map +0 -1
- package/dist/content-id-index.js.map +0 -1
- package/dist/content-index-generation.d.ts.map +0 -1
- package/dist/content-index-generation.js.map +0 -1
- package/dist/content-index-registry.d.ts.map +0 -1
- package/dist/content-index-registry.js.map +0 -1
- package/dist/content-listing.d.ts.map +0 -1
- package/dist/content-listing.js.map +0 -1
- package/dist/content-reader.d.ts.map +0 -1
- package/dist/content-reader.js.map +0 -1
- package/dist/content-store.d.ts.map +0 -1
- package/dist/content-store.js.map +0 -1
- package/dist/content-tree.d.ts.map +0 -1
- package/dist/content-tree.js.map +0 -1
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js.map +0 -1
- package/dist/dev-content-watcher.d.ts.map +0 -1
- package/dist/dev-content-watcher.js.map +0 -1
- package/dist/editor/BranchManager.d.ts.map +0 -1
- package/dist/editor/BranchManager.js.map +0 -1
- package/dist/editor/CanopyEditor.d.ts.map +0 -1
- package/dist/editor/CanopyEditor.js.map +0 -1
- package/dist/editor/CanopyEditorPage.d.ts.map +0 -1
- package/dist/editor/CanopyEditorPage.js.map +0 -1
- package/dist/editor/CommentsPanel.d.ts.map +0 -1
- package/dist/editor/CommentsPanel.js.map +0 -1
- package/dist/editor/Editor.d.ts.map +0 -1
- package/dist/editor/Editor.js.map +0 -1
- package/dist/editor/EditorPanes.d.ts.map +0 -1
- package/dist/editor/EditorPanes.js.map +0 -1
- package/dist/editor/EntryNavigator.d.ts.map +0 -1
- package/dist/editor/EntryNavigator.js.map +0 -1
- package/dist/editor/FormRenderer.d.ts.map +0 -1
- package/dist/editor/FormRenderer.js.map +0 -1
- package/dist/editor/GroupManager.d.ts.map +0 -1
- package/dist/editor/GroupManager.js.map +0 -1
- package/dist/editor/PermissionManager.d.ts.map +0 -1
- package/dist/editor/PermissionManager.js.map +0 -1
- package/dist/editor/admin/SystemHealthPanel.d.ts.map +0 -1
- package/dist/editor/admin/SystemHealthPanel.js.map +0 -1
- package/dist/editor/admin/useSystemHealth.d.ts.map +0 -1
- package/dist/editor/admin/useSystemHealth.js.map +0 -1
- package/dist/editor/canopy-path.d.ts.map +0 -1
- package/dist/editor/canopy-path.js.map +0 -1
- package/dist/editor/client-reference-resolver.d.ts.map +0 -1
- package/dist/editor/client-reference-resolver.js.map +0 -1
- package/dist/editor/comments/BranchComments.d.ts.map +0 -1
- package/dist/editor/comments/BranchComments.js.map +0 -1
- package/dist/editor/comments/EntryComments.d.ts.map +0 -1
- package/dist/editor/comments/EntryComments.js.map +0 -1
- package/dist/editor/comments/FieldWrapper.d.ts.map +0 -1
- package/dist/editor/comments/FieldWrapper.js.map +0 -1
- package/dist/editor/comments/InlineCommentThread.d.ts.map +0 -1
- package/dist/editor/comments/InlineCommentThread.js.map +0 -1
- package/dist/editor/comments/ThreadCarousel.d.ts.map +0 -1
- package/dist/editor/comments/ThreadCarousel.js.map +0 -1
- package/dist/editor/components/ConfirmDeleteModal.d.ts.map +0 -1
- package/dist/editor/components/ConfirmDeleteModal.js.map +0 -1
- package/dist/editor/components/EditorFooter.d.ts.map +0 -1
- package/dist/editor/components/EditorFooter.js.map +0 -1
- package/dist/editor/components/EditorHeader.d.ts.map +0 -1
- package/dist/editor/components/EditorHeader.js.map +0 -1
- package/dist/editor/components/EditorSidebar.d.ts.map +0 -1
- package/dist/editor/components/EditorSidebar.js.map +0 -1
- package/dist/editor/components/EntryCreateModal.d.ts.map +0 -1
- package/dist/editor/components/EntryCreateModal.js.map +0 -1
- package/dist/editor/components/RenameEntryModal.d.ts.map +0 -1
- package/dist/editor/components/RenameEntryModal.js.map +0 -1
- package/dist/editor/components/UserBadge.d.ts.map +0 -1
- package/dist/editor/components/UserBadge.js.map +0 -1
- package/dist/editor/components/index.d.ts.map +0 -1
- package/dist/editor/components/index.js.map +0 -1
- package/dist/editor/context/ApiClientContext.d.ts.map +0 -1
- package/dist/editor/context/ApiClientContext.js.map +0 -1
- package/dist/editor/context/AssetContext.d.ts.map +0 -1
- package/dist/editor/context/AssetContext.js.map +0 -1
- package/dist/editor/context/EditorStateContext.d.ts.map +0 -1
- package/dist/editor/context/EditorStateContext.js.map +0 -1
- package/dist/editor/context/SWRProvider.d.ts.map +0 -1
- package/dist/editor/context/SWRProvider.js.map +0 -1
- package/dist/editor/context/index.d.ts.map +0 -1
- package/dist/editor/context/index.js.map +0 -1
- package/dist/editor/editor-config.d.ts.map +0 -1
- package/dist/editor/editor-config.js.map +0 -1
- package/dist/editor/editor-utils.d.ts.map +0 -1
- package/dist/editor/editor-utils.js.map +0 -1
- package/dist/editor/fields/BlockField.d.ts.map +0 -1
- package/dist/editor/fields/BlockField.js.map +0 -1
- package/dist/editor/fields/CodeField.d.ts.map +0 -1
- package/dist/editor/fields/CodeField.js.map +0 -1
- package/dist/editor/fields/DateTimeField.d.ts.map +0 -1
- package/dist/editor/fields/DateTimeField.js.map +0 -1
- package/dist/editor/fields/ImageField.d.ts.map +0 -1
- package/dist/editor/fields/ImageField.js.map +0 -1
- package/dist/editor/fields/InlineGroupField.d.ts.map +0 -1
- package/dist/editor/fields/InlineGroupField.js.map +0 -1
- package/dist/editor/fields/MarkdownField.d.ts.map +0 -1
- package/dist/editor/fields/MarkdownField.js.map +0 -1
- package/dist/editor/fields/MdxImageDialog.d.ts.map +0 -1
- package/dist/editor/fields/MdxImageDialog.js.map +0 -1
- package/dist/editor/fields/NumberField.d.ts.map +0 -1
- package/dist/editor/fields/NumberField.js.map +0 -1
- package/dist/editor/fields/NumberListField.d.ts.map +0 -1
- package/dist/editor/fields/NumberListField.js.map +0 -1
- package/dist/editor/fields/ObjectField.d.ts.map +0 -1
- package/dist/editor/fields/ObjectField.js.map +0 -1
- package/dist/editor/fields/ReferenceField.d.ts.map +0 -1
- package/dist/editor/fields/ReferenceField.js.map +0 -1
- package/dist/editor/fields/SelectField.d.ts.map +0 -1
- package/dist/editor/fields/SelectField.js.map +0 -1
- package/dist/editor/fields/StringListField.d.ts.map +0 -1
- package/dist/editor/fields/StringListField.js.map +0 -1
- package/dist/editor/fields/TextField.d.ts.map +0 -1
- package/dist/editor/fields/TextField.js.map +0 -1
- package/dist/editor/fields/ToggleField.d.ts.map +0 -1
- package/dist/editor/fields/ToggleField.js.map +0 -1
- package/dist/editor/fields/entry-link/EntryLinkContext.d.ts.map +0 -1
- package/dist/editor/fields/entry-link/EntryLinkContext.js.map +0 -1
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts.map +0 -1
- package/dist/editor/fields/entry-link/InsertEntryLink.js.map +0 -1
- package/dist/editor/fields/entry-link/index.d.ts.map +0 -1
- package/dist/editor/fields/entry-link/index.js.map +0 -1
- package/dist/editor/group-manager/ExternalGroupsTab.d.ts.map +0 -1
- package/dist/editor/group-manager/ExternalGroupsTab.js.map +0 -1
- package/dist/editor/group-manager/GroupCard.d.ts.map +0 -1
- package/dist/editor/group-manager/GroupCard.js.map +0 -1
- package/dist/editor/group-manager/GroupForm.d.ts.map +0 -1
- package/dist/editor/group-manager/GroupForm.js.map +0 -1
- package/dist/editor/group-manager/InternalGroupsTab.d.ts.map +0 -1
- package/dist/editor/group-manager/InternalGroupsTab.js.map +0 -1
- package/dist/editor/group-manager/MemberList.d.ts.map +0 -1
- package/dist/editor/group-manager/MemberList.js.map +0 -1
- package/dist/editor/group-manager/hooks/useExternalGroupSearch.d.ts.map +0 -1
- package/dist/editor/group-manager/hooks/useExternalGroupSearch.js.map +0 -1
- package/dist/editor/group-manager/hooks/useGroupState.d.ts.map +0 -1
- package/dist/editor/group-manager/hooks/useGroupState.js.map +0 -1
- package/dist/editor/group-manager/hooks/useUserSearch.d.ts.map +0 -1
- package/dist/editor/group-manager/hooks/useUserSearch.js.map +0 -1
- package/dist/editor/group-manager/index.d.ts.map +0 -1
- package/dist/editor/group-manager/index.js.map +0 -1
- package/dist/editor/group-manager/types.d.ts.map +0 -1
- package/dist/editor/group-manager/types.js.map +0 -1
- package/dist/editor/hooks/__test__/test-utils.d.ts +0 -164
- package/dist/editor/hooks/__test__/test-utils.d.ts.map +0 -1
- package/dist/editor/hooks/__test__/test-utils.js +0 -203
- package/dist/editor/hooks/__test__/test-utils.js.map +0 -1
- package/dist/editor/hooks/index.d.ts.map +0 -1
- package/dist/editor/hooks/index.js.map +0 -1
- package/dist/editor/hooks/useBranchActions.d.ts.map +0 -1
- package/dist/editor/hooks/useBranchActions.js.map +0 -1
- package/dist/editor/hooks/useBranchManager.d.ts.map +0 -1
- package/dist/editor/hooks/useBranchManager.js.map +0 -1
- package/dist/editor/hooks/useBranchesData.d.ts.map +0 -1
- package/dist/editor/hooks/useBranchesData.js.map +0 -1
- package/dist/editor/hooks/useCommentSystem.d.ts.map +0 -1
- package/dist/editor/hooks/useCommentSystem.js.map +0 -1
- package/dist/editor/hooks/useCommentsData.d.ts.map +0 -1
- package/dist/editor/hooks/useCommentsData.js.map +0 -1
- package/dist/editor/hooks/useDraftManager.d.ts.map +0 -1
- package/dist/editor/hooks/useDraftManager.js.map +0 -1
- package/dist/editor/hooks/useEditorLayout.d.ts.map +0 -1
- package/dist/editor/hooks/useEditorLayout.js.map +0 -1
- package/dist/editor/hooks/useEntriesData.d.ts.map +0 -1
- package/dist/editor/hooks/useEntriesData.js.map +0 -1
- package/dist/editor/hooks/useEntryLinkResolution.d.ts.map +0 -1
- package/dist/editor/hooks/useEntryLinkResolution.js.map +0 -1
- package/dist/editor/hooks/useEntryManager.d.ts.map +0 -1
- package/dist/editor/hooks/useEntryManager.js.map +0 -1
- package/dist/editor/hooks/useGroupManager.d.ts.map +0 -1
- package/dist/editor/hooks/useGroupManager.js.map +0 -1
- package/dist/editor/hooks/usePermissionManager.d.ts.map +0 -1
- package/dist/editor/hooks/usePermissionManager.js.map +0 -1
- package/dist/editor/hooks/useReferenceResolution.d.ts.map +0 -1
- package/dist/editor/hooks/useReferenceResolution.js.map +0 -1
- package/dist/editor/hooks/useSchemaManager.d.ts.map +0 -1
- package/dist/editor/hooks/useSchemaManager.js.map +0 -1
- package/dist/editor/hooks/useUserContext.d.ts.map +0 -1
- package/dist/editor/hooks/useUserContext.js.map +0 -1
- package/dist/editor/hooks/useUserMetadata.d.ts.map +0 -1
- package/dist/editor/hooks/useUserMetadata.js.map +0 -1
- package/dist/editor/media/AssetCard.d.ts.map +0 -1
- package/dist/editor/media/AssetCard.js.map +0 -1
- package/dist/editor/media/CropStep.d.ts.map +0 -1
- package/dist/editor/media/CropStep.js.map +0 -1
- package/dist/editor/media/MediaLibrary.d.ts.map +0 -1
- package/dist/editor/media/MediaLibrary.js.map +0 -1
- package/dist/editor/media/MediaLibraryBody.d.ts.map +0 -1
- package/dist/editor/media/MediaLibraryBody.js.map +0 -1
- package/dist/editor/media/crop-math.d.ts.map +0 -1
- package/dist/editor/media/crop-math.js.map +0 -1
- package/dist/editor/media/upload-asset.d.ts.map +0 -1
- package/dist/editor/media/upload-asset.js.map +0 -1
- package/dist/editor/media/upload-constants.d.ts.map +0 -1
- package/dist/editor/media/upload-constants.js.map +0 -1
- package/dist/editor/media/useAssetUpload.d.ts.map +0 -1
- package/dist/editor/media/useAssetUpload.js.map +0 -1
- package/dist/editor/media/xhr-upload.d.ts.map +0 -1
- package/dist/editor/media/xhr-upload.js.map +0 -1
- package/dist/editor/permission-manager/GroupSelector.d.ts.map +0 -1
- package/dist/editor/permission-manager/GroupSelector.js.map +0 -1
- package/dist/editor/permission-manager/PermissionEditor.d.ts.map +0 -1
- package/dist/editor/permission-manager/PermissionEditor.js.map +0 -1
- package/dist/editor/permission-manager/PermissionLevelBadge.d.ts.map +0 -1
- package/dist/editor/permission-manager/PermissionLevelBadge.js.map +0 -1
- package/dist/editor/permission-manager/PermissionTree.d.ts.map +0 -1
- package/dist/editor/permission-manager/PermissionTree.js.map +0 -1
- package/dist/editor/permission-manager/UserSelector.d.ts.map +0 -1
- package/dist/editor/permission-manager/UserSelector.js.map +0 -1
- package/dist/editor/permission-manager/constants.d.ts.map +0 -1
- package/dist/editor/permission-manager/constants.js.map +0 -1
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts.map +0 -1
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js.map +0 -1
- package/dist/editor/permission-manager/hooks/usePermissionTree.d.ts.map +0 -1
- package/dist/editor/permission-manager/hooks/usePermissionTree.js.map +0 -1
- package/dist/editor/permission-manager/index.d.ts.map +0 -1
- package/dist/editor/permission-manager/index.js.map +0 -1
- package/dist/editor/permission-manager/types.d.ts.map +0 -1
- package/dist/editor/permission-manager/types.js.map +0 -1
- package/dist/editor/permission-manager/utils.d.ts.map +0 -1
- package/dist/editor/permission-manager/utils.js.map +0 -1
- package/dist/editor/preview-bridge.d.ts.map +0 -1
- package/dist/editor/preview-bridge.js.map +0 -1
- package/dist/editor/relative-time.d.ts.map +0 -1
- package/dist/editor/relative-time.js.map +0 -1
- package/dist/editor/schema-editor/CollectionEditor.d.ts.map +0 -1
- package/dist/editor/schema-editor/CollectionEditor.js.map +0 -1
- package/dist/editor/schema-editor/EntryTypeEditor.d.ts.map +0 -1
- package/dist/editor/schema-editor/EntryTypeEditor.js.map +0 -1
- package/dist/editor/schema-editor/index.d.ts.map +0 -1
- package/dist/editor/schema-editor/index.js.map +0 -1
- package/dist/editor/setup-test-dom.d.ts +0 -1
- package/dist/editor/setup-test-dom.d.ts.map +0 -1
- package/dist/editor/setup-test-dom.js +0 -12
- package/dist/editor/setup-test-dom.js.map +0 -1
- package/dist/editor/test-setup.d.ts +0 -6
- package/dist/editor/test-setup.d.ts.map +0 -1
- package/dist/editor/test-setup.js +0 -42
- package/dist/editor/test-setup.js.map +0 -1
- package/dist/editor/theme.d.ts.map +0 -1
- package/dist/editor/theme.js.map +0 -1
- package/dist/editor/utils/env.d.ts.map +0 -1
- package/dist/editor/utils/env.js.map +0 -1
- package/dist/entry-link-resolver.d.ts.map +0 -1
- package/dist/entry-link-resolver.js.map +0 -1
- package/dist/entry-schema-registry.d.ts.map +0 -1
- package/dist/entry-schema-registry.js.map +0 -1
- package/dist/entry-schema.d.ts.map +0 -1
- package/dist/entry-schema.js.map +0 -1
- package/dist/git-manager.d.ts.map +0 -1
- package/dist/git-manager.js.map +0 -1
- package/dist/github-service.d.ts.map +0 -1
- package/dist/github-service.js.map +0 -1
- package/dist/http/handler.d.ts.map +0 -1
- package/dist/http/handler.js.map +0 -1
- package/dist/http/index.d.ts.map +0 -1
- package/dist/http/index.js.map +0 -1
- package/dist/http/router.d.ts.map +0 -1
- package/dist/http/router.js.map +0 -1
- package/dist/http/types.d.ts.map +0 -1
- package/dist/http/types.js.map +0 -1
- package/dist/id.d.ts.map +0 -1
- package/dist/id.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/operating-mode/client-safe-strategy.d.ts.map +0 -1
- package/dist/operating-mode/client-safe-strategy.js.map +0 -1
- package/dist/operating-mode/client-unsafe-strategy.d.ts.map +0 -1
- package/dist/operating-mode/client-unsafe-strategy.js.map +0 -1
- package/dist/operating-mode/client.d.ts.map +0 -1
- package/dist/operating-mode/client.js.map +0 -1
- package/dist/operating-mode/deployment-name-fixtures.d.ts.map +0 -1
- package/dist/operating-mode/deployment-name-fixtures.js.map +0 -1
- package/dist/operating-mode/deployment-name.d.ts.map +0 -1
- package/dist/operating-mode/deployment-name.js.map +0 -1
- package/dist/operating-mode/index.d.ts.map +0 -1
- package/dist/operating-mode/index.js.map +0 -1
- package/dist/operating-mode/mode-env.d.ts.map +0 -1
- package/dist/operating-mode/mode-env.js.map +0 -1
- package/dist/operating-mode/types.d.ts.map +0 -1
- package/dist/operating-mode/types.js.map +0 -1
- package/dist/paths/branch-name.d.ts.map +0 -1
- package/dist/paths/branch-name.js.map +0 -1
- package/dist/paths/branch.d.ts.map +0 -1
- package/dist/paths/branch.js.map +0 -1
- package/dist/paths/index.d.ts.map +0 -1
- package/dist/paths/index.js.map +0 -1
- package/dist/paths/normalize-server.d.ts.map +0 -1
- package/dist/paths/normalize-server.js.map +0 -1
- package/dist/paths/normalize.d.ts.map +0 -1
- package/dist/paths/normalize.js.map +0 -1
- package/dist/paths/resolve.d.ts.map +0 -1
- package/dist/paths/resolve.js.map +0 -1
- package/dist/paths/test-utils.d.ts +0 -22
- package/dist/paths/test-utils.d.ts.map +0 -1
- package/dist/paths/test-utils.js +0 -21
- package/dist/paths/test-utils.js.map +0 -1
- package/dist/paths/types.d.ts.map +0 -1
- package/dist/paths/types.js.map +0 -1
- package/dist/paths/validation.d.ts.map +0 -1
- package/dist/paths/validation.js.map +0 -1
- package/dist/reference-resolver.d.ts.map +0 -1
- package/dist/reference-resolver.js.map +0 -1
- package/dist/resolve-canopy-user.d.ts.map +0 -1
- package/dist/resolve-canopy-user.js.map +0 -1
- package/dist/resource-generation.d.ts.map +0 -1
- package/dist/resource-generation.js.map +0 -1
- package/dist/schema/index.d.ts.map +0 -1
- package/dist/schema/index.js.map +0 -1
- package/dist/schema/meta-loader.d.ts.map +0 -1
- package/dist/schema/meta-loader.js.map +0 -1
- package/dist/schema/resolver.d.ts.map +0 -1
- package/dist/schema/resolver.js.map +0 -1
- package/dist/schema/schema-store-types.d.ts.map +0 -1
- package/dist/schema/schema-store-types.js.map +0 -1
- package/dist/schema/schema-store.d.ts.map +0 -1
- package/dist/schema/schema-store.js.map +0 -1
- package/dist/schema/types.d.ts.map +0 -1
- package/dist/schema/types.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/services.d.ts.map +0 -1
- package/dist/services.js.map +0 -1
- package/dist/settings-workspace.d.ts.map +0 -1
- package/dist/settings-workspace.js.map +0 -1
- package/dist/static/index.d.ts.map +0 -1
- package/dist/static/index.js.map +0 -1
- package/dist/sync-core.d.ts.map +0 -1
- package/dist/sync-core.js.map +0 -1
- package/dist/task-queue/index.d.ts.map +0 -1
- package/dist/task-queue/index.js.map +0 -1
- package/dist/task-queue/task-queue.d.ts.map +0 -1
- package/dist/task-queue/task-queue.js.map +0 -1
- package/dist/task-queue/types.d.ts.map +0 -1
- package/dist/task-queue/types.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/url-path-resolver.d.ts.map +0 -1
- package/dist/url-path-resolver.js.map +0 -1
- package/dist/user.d.ts.map +0 -1
- package/dist/user.js.map +0 -1
- package/dist/utils/async-mutex.d.ts.map +0 -1
- package/dist/utils/async-mutex.js.map +0 -1
- package/dist/utils/atomic-write.d.ts.map +0 -1
- package/dist/utils/atomic-write.js.map +0 -1
- package/dist/utils/body-field.d.ts.map +0 -1
- package/dist/utils/body-field.js.map +0 -1
- package/dist/utils/content-write-lock.d.ts.map +0 -1
- package/dist/utils/content-write-lock.js.map +0 -1
- package/dist/utils/debug.d.ts.map +0 -1
- package/dist/utils/debug.js.map +0 -1
- package/dist/utils/entry-url.d.ts.map +0 -1
- package/dist/utils/entry-url.js.map +0 -1
- package/dist/utils/error.d.ts.map +0 -1
- package/dist/utils/error.js.map +0 -1
- package/dist/utils/flatten-group-fields.d.ts.map +0 -1
- package/dist/utils/flatten-group-fields.js.map +0 -1
- package/dist/utils/format.d.ts.map +0 -1
- package/dist/utils/format.js.map +0 -1
- package/dist/utils/fs.d.ts.map +0 -1
- package/dist/utils/fs.js.map +0 -1
- package/dist/utils/git.d.ts.map +0 -1
- package/dist/utils/git.js.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/occ-json-write.d.ts.map +0 -1
- package/dist/utils/occ-json-write.js.map +0 -1
- package/dist/utils/provisioning-lock.d.ts.map +0 -1
- package/dist/utils/provisioning-lock.js.map +0 -1
- package/dist/utils/sanitize-href.d.ts.map +0 -1
- package/dist/utils/sanitize-href.js.map +0 -1
- package/dist/utils/title-field.d.ts.map +0 -1
- package/dist/utils/title-field.js.map +0 -1
- package/dist/validation/deletion-checker.d.ts.map +0 -1
- package/dist/validation/deletion-checker.js.map +0 -1
- package/dist/validation/entry-link-validator.d.ts.map +0 -1
- package/dist/validation/entry-link-validator.js.map +0 -1
- package/dist/validation/entry-type-reference-validator.d.ts.map +0 -1
- package/dist/validation/entry-type-reference-validator.js.map +0 -1
- package/dist/validation/entry-validator.d.ts.map +0 -1
- package/dist/validation/entry-validator.js.map +0 -1
- package/dist/validation/field-traversal.d.ts.map +0 -1
- package/dist/validation/field-traversal.js.map +0 -1
- package/dist/validation/reference-validator.d.ts.map +0 -1
- package/dist/validation/reference-validator.js.map +0 -1
- package/dist/worker/cms-worker.d.ts.map +0 -1
- package/dist/worker/cms-worker.js.map +0 -1
- package/dist/worker/log.d.ts.map +0 -1
- package/dist/worker/log.js.map +0 -1
- package/dist/worker/task-queue-config.d.ts.map +0 -1
- package/dist/worker/task-queue-config.js.map +0 -1
- package/dist/worker/task-queue.d.ts.map +0 -1
- package/dist/worker/task-queue.js.map +0 -1
- package/dist/worker/worker-status.d.ts.map +0 -1
- package/dist/worker/worker-status.js.map +0 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic SEO field extraction and URL shaping.
|
|
3
|
+
*
|
|
4
|
+
* This module is pure: it maps an entry's raw data onto a neutral `SeoFields` shape and
|
|
5
|
+
* resolves URLs. Framework adapters (e.g. canopycms-next's `entryToMetadata`) turn that shape
|
|
6
|
+
* into their own metadata objects; nothing here imports a framework or a node built-in.
|
|
7
|
+
*
|
|
8
|
+
* The field names default to the recommended SEO field group — see `defineSeoFieldGroup` in
|
|
9
|
+
* entry-schema.ts, which builds a schema group from these same names so the schema side and
|
|
10
|
+
* the read side cannot drift.
|
|
11
|
+
*/
|
|
12
|
+
import { isAbsoluteUrl, stripTrailingSlashes } from '../utils/url-prefix.js';
|
|
13
|
+
/**
|
|
14
|
+
* Re-exported so this module's public surface (and `canopycms/server`'s, via `static/index.ts`)
|
|
15
|
+
* is unchanged by their move to `utils/url-prefix.ts` — where they now sit beside
|
|
16
|
+
* `joinUrlPrefix`, the shared join that `assets/asset-url.ts` also needs and that must not
|
|
17
|
+
* import anything under `static/`.
|
|
18
|
+
*/
|
|
19
|
+
export { isAbsoluteUrl, stripTrailingSlashes };
|
|
20
|
+
/** og:type values covered by the recommended group. */
|
|
21
|
+
export type SeoOgType = 'website' | 'article' | 'profile';
|
|
22
|
+
/** twitter:card values covered by the recommended group. */
|
|
23
|
+
export type SeoTwitterCard = 'summary' | 'summary_large_image';
|
|
24
|
+
/** The neutral, framework-agnostic SEO shape. */
|
|
25
|
+
export interface SeoFields {
|
|
26
|
+
title?: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
ogImage?: string;
|
|
29
|
+
ogType?: SeoOgType;
|
|
30
|
+
canonical?: string;
|
|
31
|
+
noindex?: boolean;
|
|
32
|
+
twitterCard?: SeoTwitterCard;
|
|
33
|
+
}
|
|
34
|
+
/** Entry field names backing each neutral field. */
|
|
35
|
+
export type SeoFieldNames = Record<keyof SeoFields, string>;
|
|
36
|
+
/**
|
|
37
|
+
* The recommended SEO field names. `defineSeoFieldGroup()` emits a schema group using exactly
|
|
38
|
+
* these names, so an adopter who uses both ends needs no configuration at all.
|
|
39
|
+
*/
|
|
40
|
+
export declare const DEFAULT_SEO_FIELD_NAMES: {
|
|
41
|
+
readonly title: "metaTitle";
|
|
42
|
+
readonly description: "metaDescription";
|
|
43
|
+
readonly ogImage: "ogImage";
|
|
44
|
+
readonly ogType: "ogType";
|
|
45
|
+
readonly canonical: "canonical";
|
|
46
|
+
readonly noindex: "noindex";
|
|
47
|
+
readonly twitterCard: "twitterCard";
|
|
48
|
+
};
|
|
49
|
+
export interface ExtractSeoFieldsOptions {
|
|
50
|
+
/** Per-field name overrides (e.g. `{ title: 'seoTitle' }`). */
|
|
51
|
+
fields?: Partial<SeoFieldNames>;
|
|
52
|
+
/**
|
|
53
|
+
* Read the fields from a nested object under this key instead of from flat entry fields.
|
|
54
|
+
* Pair with `defineSeoFieldGroup({ group: 'seo' })`, which nests the same fields under that
|
|
55
|
+
* key in the content file. Omit for the flat (inline-group) convention, which is the default
|
|
56
|
+
* on both ends.
|
|
57
|
+
*/
|
|
58
|
+
group?: string;
|
|
59
|
+
/** Used when the entry has no meta title (typically the entry's own title/heading). */
|
|
60
|
+
fallbackTitle?: string;
|
|
61
|
+
/** Used when the entry has no meta description. */
|
|
62
|
+
fallbackDescription?: string;
|
|
63
|
+
}
|
|
64
|
+
/** Just the parts of `ExtractSeoFieldsOptions` that locate the fields, with no fallbacks. */
|
|
65
|
+
export type SeoFieldLocation = Pick<ExtractSeoFieldsOptions, 'fields' | 'group'>;
|
|
66
|
+
/**
|
|
67
|
+
* Map an entry's SEO fields onto the neutral shape.
|
|
68
|
+
*
|
|
69
|
+
* Entry data is `unknown` — every read is guarded, unknown enum values are dropped rather than
|
|
70
|
+
* passed through, and non-object data (null, a string, an array) yields an all-undefined result
|
|
71
|
+
* rather than throwing.
|
|
72
|
+
*/
|
|
73
|
+
export declare function extractSeoFields(entryData: unknown, opts?: ExtractSeoFieldsOptions): SeoFields;
|
|
74
|
+
/**
|
|
75
|
+
* THE `noindex` predicate. Every surface that suppresses an entry must route through this one
|
|
76
|
+
* function rather than re-deriving the flag:
|
|
77
|
+
*
|
|
78
|
+
* - the page's own `robots: { index: false }` (canopycms-next's `entryToMetadata`), and
|
|
79
|
+
* - exclusion from the sitemap (canopycms-next's `generateContentSitemap`).
|
|
80
|
+
*
|
|
81
|
+
* Those two shipping from one predicate is the point of shipping them together. Where they were
|
|
82
|
+
* derived separately, a `noindex` entry stayed advertised in one surface while correctly absent
|
|
83
|
+
* from the other, and nothing warned.
|
|
84
|
+
*
|
|
85
|
+
* NOT applied to enumeration: `noindex` means "don't advertise this", not "don't build this".
|
|
86
|
+
* `collectRoutableEntries` and `generateStaticParams` must still emit the entry, so its URL
|
|
87
|
+
* resolves for anyone holding the link.
|
|
88
|
+
*/
|
|
89
|
+
export declare function isNoindexEntry(entryData: unknown, opts?: SeoFieldLocation): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Append a trailing slash to a site-relative path, matching a site that serves `/contact/`.
|
|
92
|
+
*
|
|
93
|
+
* Leaves the root (`/`) and file-like paths (a last segment containing a dot, e.g.
|
|
94
|
+
* `/blog/rss.xml`) alone, and never doubles an existing slash.
|
|
95
|
+
*
|
|
96
|
+
* A query string and/or fragment (`?page=2`, `#section`) is split off BEFORE the slash decision
|
|
97
|
+
* and placement, then reattached after — so `/blog?page=2` becomes `/blog/?page=2`, never
|
|
98
|
+
* `/blog?page=2/` (a literal trailing slash inside the query string, which is not what "serve
|
|
99
|
+
* with a trailing slash" means and breaks the URL).
|
|
100
|
+
*/
|
|
101
|
+
export declare function withTrailingSlash(path: string): string;
|
|
102
|
+
export interface ResolveSeoUrlOptions {
|
|
103
|
+
/** Site origin (e.g. `https://example.com`). Trailing slashes are stripped. */
|
|
104
|
+
siteUrl?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Emit site-relative paths with a trailing slash. CanopyCMS has no knowledge of your
|
|
107
|
+
* framework's routing config, so this must be stated explicitly — see the note on
|
|
108
|
+
* `generateContentSitemap`.
|
|
109
|
+
*/
|
|
110
|
+
trailingSlash?: boolean;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Resolve a possibly-relative URL for public emission (canonical tag, sitemap URL, OG image).
|
|
114
|
+
*
|
|
115
|
+
* ORDER MATTERS — the absolute check runs FIRST. An absolute or protocol-relative value is a
|
|
116
|
+
* deliberate off-site pointer (syndication, a partner-hosted copy, a CDN image) and passes
|
|
117
|
+
* through verbatim; only a site-relative path gets trailing-slash normalization and the site
|
|
118
|
+
* origin. Normalizing first turns `https://other.org/page` into
|
|
119
|
+
* `<siteUrl>/https://other.org/page/`.
|
|
120
|
+
*
|
|
121
|
+
* With no `siteUrl`, a site-relative path is returned still relative (normalized), which is
|
|
122
|
+
* what you want when the framework resolves relative metadata URLs itself.
|
|
123
|
+
*
|
|
124
|
+
* A NOT-absolute value is also run through `neutralizeImplicitOffOrigin` before normalization,
|
|
125
|
+
* so a WHATWG-backslash-equivalent spelling that `isAbsoluteUrl` correctly declines to call
|
|
126
|
+
* "absolute" (see its doc) can't still be read by a browser as protocol-relative once emitted.
|
|
127
|
+
*/
|
|
128
|
+
export declare function resolveSeoUrl(pathOrUrl: string, opts?: ResolveSeoUrlOptions): string;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic SEO field extraction and URL shaping.
|
|
3
|
+
*
|
|
4
|
+
* This module is pure: it maps an entry's raw data onto a neutral `SeoFields` shape and
|
|
5
|
+
* resolves URLs. Framework adapters (e.g. canopycms-next's `entryToMetadata`) turn that shape
|
|
6
|
+
* into their own metadata objects; nothing here imports a framework or a node built-in.
|
|
7
|
+
*
|
|
8
|
+
* The field names default to the recommended SEO field group — see `defineSeoFieldGroup` in
|
|
9
|
+
* entry-schema.ts, which builds a schema group from these same names so the schema side and
|
|
10
|
+
* the read side cannot drift.
|
|
11
|
+
*/
|
|
12
|
+
import { isAbsoluteUrl, joinUrlPrefix, stripTrailingSlashes, toSameOriginPath, } from '../utils/url-prefix.js';
|
|
13
|
+
/**
|
|
14
|
+
* Re-exported so this module's public surface (and `canopycms/server`'s, via `static/index.ts`)
|
|
15
|
+
* is unchanged by their move to `utils/url-prefix.ts` — where they now sit beside
|
|
16
|
+
* `joinUrlPrefix`, the shared join that `assets/asset-url.ts` also needs and that must not
|
|
17
|
+
* import anything under `static/`.
|
|
18
|
+
*/
|
|
19
|
+
export { isAbsoluteUrl, stripTrailingSlashes };
|
|
20
|
+
/**
|
|
21
|
+
* The recommended SEO field names. `defineSeoFieldGroup()` emits a schema group using exactly
|
|
22
|
+
* these names, so an adopter who uses both ends needs no configuration at all.
|
|
23
|
+
*/
|
|
24
|
+
export const DEFAULT_SEO_FIELD_NAMES = {
|
|
25
|
+
title: 'metaTitle',
|
|
26
|
+
description: 'metaDescription',
|
|
27
|
+
ogImage: 'ogImage',
|
|
28
|
+
ogType: 'ogType',
|
|
29
|
+
canonical: 'canonical',
|
|
30
|
+
noindex: 'noindex',
|
|
31
|
+
twitterCard: 'twitterCard',
|
|
32
|
+
};
|
|
33
|
+
const asRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
34
|
+
? value
|
|
35
|
+
: undefined;
|
|
36
|
+
/**
|
|
37
|
+
* A non-empty trimmed string, or undefined.
|
|
38
|
+
*
|
|
39
|
+
* Empty is treated as UNSET, deliberately: CanopyCMS writes optional fields present-but-empty
|
|
40
|
+
* rather than omitting them, so `metaTitle: ''` is what an untouched SEO group looks like on
|
|
41
|
+
* disk. Treating it as a value would let a blank field beat the fallback title on every entry
|
|
42
|
+
* whose author never opened the SEO section.
|
|
43
|
+
*/
|
|
44
|
+
const asText = (value) => {
|
|
45
|
+
if (typeof value !== 'string')
|
|
46
|
+
return undefined;
|
|
47
|
+
const trimmed = value.trim();
|
|
48
|
+
return trimmed === '' ? undefined : trimmed;
|
|
49
|
+
};
|
|
50
|
+
const asFlag = (value) => typeof value === 'boolean' ? value : undefined;
|
|
51
|
+
/**
|
|
52
|
+
* An image URL from either convention: a plain string field, or an `image` field, whose value
|
|
53
|
+
* is a structured `{ src, alt, ... }` object. Supporting both means switching the recommended
|
|
54
|
+
* `ogImage` field to `type: 'image'` doesn't silently drop every OG image.
|
|
55
|
+
*/
|
|
56
|
+
const asImageUrl = (value) => {
|
|
57
|
+
const text = asText(value);
|
|
58
|
+
if (text)
|
|
59
|
+
return text;
|
|
60
|
+
return asText(asRecord(value)?.src);
|
|
61
|
+
};
|
|
62
|
+
const asOgType = (value) => {
|
|
63
|
+
const text = asText(value);
|
|
64
|
+
return text === 'website' || text === 'article' || text === 'profile' ? text : undefined;
|
|
65
|
+
};
|
|
66
|
+
const asTwitterCard = (value) => {
|
|
67
|
+
const text = asText(value);
|
|
68
|
+
return text === 'summary' || text === 'summary_large_image' ? text : undefined;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Map an entry's SEO fields onto the neutral shape.
|
|
72
|
+
*
|
|
73
|
+
* Entry data is `unknown` — every read is guarded, unknown enum values are dropped rather than
|
|
74
|
+
* passed through, and non-object data (null, a string, an array) yields an all-undefined result
|
|
75
|
+
* rather than throwing.
|
|
76
|
+
*/
|
|
77
|
+
export function extractSeoFields(entryData, opts = {}) {
|
|
78
|
+
const names = { ...DEFAULT_SEO_FIELD_NAMES, ...opts.fields };
|
|
79
|
+
const entry = asRecord(entryData);
|
|
80
|
+
const source = opts.group ? asRecord(entry?.[opts.group]) : entry;
|
|
81
|
+
return {
|
|
82
|
+
title: asText(source?.[names.title]) ?? asText(opts.fallbackTitle),
|
|
83
|
+
description: asText(source?.[names.description]) ?? asText(opts.fallbackDescription),
|
|
84
|
+
ogImage: asImageUrl(source?.[names.ogImage]),
|
|
85
|
+
ogType: asOgType(source?.[names.ogType]),
|
|
86
|
+
canonical: asText(source?.[names.canonical]),
|
|
87
|
+
noindex: asFlag(source?.[names.noindex]),
|
|
88
|
+
twitterCard: asTwitterCard(source?.[names.twitterCard]),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* THE `noindex` predicate. Every surface that suppresses an entry must route through this one
|
|
93
|
+
* function rather than re-deriving the flag:
|
|
94
|
+
*
|
|
95
|
+
* - the page's own `robots: { index: false }` (canopycms-next's `entryToMetadata`), and
|
|
96
|
+
* - exclusion from the sitemap (canopycms-next's `generateContentSitemap`).
|
|
97
|
+
*
|
|
98
|
+
* Those two shipping from one predicate is the point of shipping them together. Where they were
|
|
99
|
+
* derived separately, a `noindex` entry stayed advertised in one surface while correctly absent
|
|
100
|
+
* from the other, and nothing warned.
|
|
101
|
+
*
|
|
102
|
+
* NOT applied to enumeration: `noindex` means "don't advertise this", not "don't build this".
|
|
103
|
+
* `collectRoutableEntries` and `generateStaticParams` must still emit the entry, so its URL
|
|
104
|
+
* resolves for anyone holding the link.
|
|
105
|
+
*/
|
|
106
|
+
export function isNoindexEntry(entryData, opts = {}) {
|
|
107
|
+
return extractSeoFields(entryData, opts).noindex === true;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Append a trailing slash to a site-relative path, matching a site that serves `/contact/`.
|
|
111
|
+
*
|
|
112
|
+
* Leaves the root (`/`) and file-like paths (a last segment containing a dot, e.g.
|
|
113
|
+
* `/blog/rss.xml`) alone, and never doubles an existing slash.
|
|
114
|
+
*
|
|
115
|
+
* A query string and/or fragment (`?page=2`, `#section`) is split off BEFORE the slash decision
|
|
116
|
+
* and placement, then reattached after — so `/blog?page=2` becomes `/blog/?page=2`, never
|
|
117
|
+
* `/blog?page=2/` (a literal trailing slash inside the query string, which is not what "serve
|
|
118
|
+
* with a trailing slash" means and breaks the URL).
|
|
119
|
+
*/
|
|
120
|
+
export function withTrailingSlash(path) {
|
|
121
|
+
const splitIndex = path.search(/[?#]/);
|
|
122
|
+
const base = splitIndex === -1 ? path : path.slice(0, splitIndex);
|
|
123
|
+
const suffix = splitIndex === -1 ? '' : path.slice(splitIndex);
|
|
124
|
+
const withLeading = base.startsWith('/') ? base : `/${base}`;
|
|
125
|
+
if (withLeading === '/' || withLeading.endsWith('/'))
|
|
126
|
+
return withLeading + suffix;
|
|
127
|
+
const lastSegment = withLeading.slice(withLeading.lastIndexOf('/') + 1);
|
|
128
|
+
if (lastSegment.includes('.'))
|
|
129
|
+
return withLeading + suffix;
|
|
130
|
+
return `${withLeading}/${suffix}`;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Resolve a possibly-relative URL for public emission (canonical tag, sitemap URL, OG image).
|
|
134
|
+
*
|
|
135
|
+
* ORDER MATTERS — the absolute check runs FIRST. An absolute or protocol-relative value is a
|
|
136
|
+
* deliberate off-site pointer (syndication, a partner-hosted copy, a CDN image) and passes
|
|
137
|
+
* through verbatim; only a site-relative path gets trailing-slash normalization and the site
|
|
138
|
+
* origin. Normalizing first turns `https://other.org/page` into
|
|
139
|
+
* `<siteUrl>/https://other.org/page/`.
|
|
140
|
+
*
|
|
141
|
+
* With no `siteUrl`, a site-relative path is returned still relative (normalized), which is
|
|
142
|
+
* what you want when the framework resolves relative metadata URLs itself.
|
|
143
|
+
*
|
|
144
|
+
* A NOT-absolute value is also run through `neutralizeImplicitOffOrigin` before normalization,
|
|
145
|
+
* so a WHATWG-backslash-equivalent spelling that `isAbsoluteUrl` correctly declines to call
|
|
146
|
+
* "absolute" (see its doc) can't still be read by a browser as protocol-relative once emitted.
|
|
147
|
+
*/
|
|
148
|
+
export function resolveSeoUrl(pathOrUrl, opts = {}) {
|
|
149
|
+
if (isAbsoluteUrl(pathOrUrl))
|
|
150
|
+
return pathOrUrl;
|
|
151
|
+
// Neutralize BEFORE the trailing-slash step, which is the order this has always run in:
|
|
152
|
+
// `withTrailingSlash` inspects the last path segment, and a backslash-equivalent spelling
|
|
153
|
+
// changes what that segment is.
|
|
154
|
+
//
|
|
155
|
+
// `toSameOriginPath`, not a bare `neutralizeImplicitOffOrigin`: neutralizing `/\evil.com//a`
|
|
156
|
+
// yields `//a`, and handing THAT to `joinUrlPrefix` means its absolute-URL check reads it as a
|
|
157
|
+
// protocol-relative pointer and returns it verbatim — dropping `siteUrl` and emitting an
|
|
158
|
+
// off-origin canonical. See `toSameOriginPath`'s doc.
|
|
159
|
+
const safePathOrUrl = toSameOriginPath(pathOrUrl);
|
|
160
|
+
const normalized = opts.trailingSlash ? withTrailingSlash(safePathOrUrl) : safePathOrUrl;
|
|
161
|
+
return joinUrlPrefix(opts.siteUrl, normalized);
|
|
162
|
+
}
|
package/dist/sync-core.d.ts
CHANGED
package/dist/sync-core.js
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
export type { Task, TaskStatus, QueueStats, TaskQueueLogger, CorruptTaskFile } from './types';
|
|
2
|
-
export { enqueueTask, dequeueTask, completeTask, failTask, retryTask, requeueFailedTask, recoverOrphanedTasks, cleanupOldTasks, getTask, listTasks, getQueueStats, listCorruptTaskFiles, } from './task-queue';
|
|
3
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1
|
+
export type { Task, TaskStatus, QueueStats, TaskQueueLogger, CorruptTaskFile } from './types.js';
|
|
2
|
+
export { enqueueTask, dequeueTask, completeTask, failTask, retryTask, requeueFailedTask, recoverOrphanedTasks, cleanupOldTasks, getTask, listTasks, getQueueStats, listCorruptTaskFiles, } from './task-queue.js';
|
package/dist/task-queue/index.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* processes — the worker lock (acquireLock) ensures only one consumer runs at
|
|
16
16
|
* a time. Do not run multiple dequeue consumers concurrently.
|
|
17
17
|
*/
|
|
18
|
-
import type { Task, TaskStatus, QueueStats, TaskQueueLogger, CorruptTaskFile } from './types';
|
|
18
|
+
import type { Task, TaskStatus, QueueStats, TaskQueueLogger, CorruptTaskFile } from './types.js';
|
|
19
19
|
/**
|
|
20
20
|
* Enqueue a task. Writes a JSON file to pending/{id}.json.
|
|
21
21
|
* Returns the generated task ID.
|
|
@@ -114,4 +114,3 @@ export declare function getQueueStats(taskDir: string): Promise<QueueStats>;
|
|
|
114
114
|
* dir (returns []). Sorted newest-mtime first, capped at `limit`.
|
|
115
115
|
*/
|
|
116
116
|
export declare function listCorruptTaskFiles(taskDir: string, limit?: number, logger?: TaskQueueLogger): Promise<CorruptTaskFile[]>;
|
|
117
|
-
//# sourceMappingURL=task-queue.d.ts.map
|
package/dist/task-queue/types.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ContentId } from './paths/types';
|
|
1
|
+
import type { ContentId } from './paths/types.js';
|
|
2
2
|
export type CanopyUserId = string;
|
|
3
3
|
export type CanopyGroupId = string;
|
|
4
4
|
/**
|
|
@@ -98,11 +98,11 @@ export interface BranchPaths {
|
|
|
98
98
|
export interface BranchContext extends BranchPaths {
|
|
99
99
|
branch: BranchMetadata;
|
|
100
100
|
/** Per-branch flattened schema (lazy-loaded via getBranchContext with loadSchema: true) */
|
|
101
|
-
flatSchema?: import('./config').FlatSchemaItem[];
|
|
101
|
+
flatSchema?: import('./config/index.js').FlatSchemaItem[];
|
|
102
102
|
}
|
|
103
103
|
/** BranchContext with guaranteed flatSchema (loaded via schema guard or loadSchema: true) */
|
|
104
104
|
export interface BranchContextWithSchema extends BranchContext {
|
|
105
|
-
flatSchema: import('./config').FlatSchemaItem[];
|
|
105
|
+
flatSchema: import('./config/index.js').FlatSchemaItem[];
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
108
|
* Wire shape of the worker's self-reported status file (worker-status.json,
|
|
@@ -170,4 +170,3 @@ export interface WorkerStatusReport {
|
|
|
170
170
|
phase: 'startup' | 'run';
|
|
171
171
|
};
|
|
172
172
|
}
|
|
173
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.js
CHANGED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The WRITE-BOUNDARY half of the invariant "no two entries may claim the same `urlPath`".
|
|
3
|
+
*
|
|
4
|
+
* The build-time half (`assertNoDuplicateUrlPaths`, static/index.ts) detects the state; this
|
|
5
|
+
* refuses to create it. Neither replaces the other: content is git-backed, so it also arrives by
|
|
6
|
+
* merge, by PR, by direct commit and by adopters retrofitting an existing repo — none of which
|
|
7
|
+
* pass through this boundary — while the build guard cannot help an editor who is about to author
|
|
8
|
+
* the collision right now.
|
|
9
|
+
*
|
|
10
|
+
* A SCHEMA edit alone can also create one, with no content write at all: `updateEntryType`
|
|
11
|
+
* changing a format changes the listing's `validExts`, which can flip a previously-unlisted
|
|
12
|
+
* `guide.index.{id}.json` into a published entry and so into a contested pair. Another reason
|
|
13
|
+
* neither half of this invariant subsumes the other.
|
|
14
|
+
*
|
|
15
|
+
* Deliberately formulated on `urlPath`, not on names. An entry whose slug matches a sibling
|
|
16
|
+
* collection is only a problem when that collection ALSO has an index entry:
|
|
17
|
+
*
|
|
18
|
+
* content/docs/page.guides.{id}.json + content/docs/guides.{id}/ (no index) -> fine.
|
|
19
|
+
* A landing page plus a folder of children. Both are reachable; nothing is contested.
|
|
20
|
+
*
|
|
21
|
+
* content/docs/page.guides.{id}.json + content/docs/guides.{id}/doc.index.{id}.md
|
|
22
|
+
* -> contested. Both compute /docs/guides, so exactly one of them is reachable and the
|
|
23
|
+
* other silently has no route.
|
|
24
|
+
*
|
|
25
|
+
* A name-collision rule would forbid the first, which is a shape adopters legitimately build.
|
|
26
|
+
*
|
|
27
|
+
* Everything here works on PHYSICAL directories, because that is what the write path holds when
|
|
28
|
+
* it needs the answer, and because the on-disk names carry the content IDs that logical paths
|
|
29
|
+
* hide (`guides.{id}/`, `doc.index.{id}.md`).
|
|
30
|
+
*
|
|
31
|
+
* SCOPE, and do not widen it by accident: this guards the URL an ENTRY claims -- the `urlPath`
|
|
32
|
+
* that `computeEntryUrl` derives and `listEntries` publishes. It is NOT "every URL the site
|
|
33
|
+
* serves", and the two are not the same set. A framework adapter can route an entry somewhere
|
|
34
|
+
* else — adopters add hand-written routes Canopy knows nothing about, and a framework adapter can
|
|
35
|
+
* rewrite a sitemap `<loc>` after enumeration (`generateContentSitemap`'s `pathFor` option, in
|
|
36
|
+
* `canopycms-next/src/static.ts`, does exactly that). Those URLs are
|
|
37
|
+
* invisible here by design -- there is no filesystem state to check them against at write time.
|
|
38
|
+
* A future change that tries to make this the authority on "the set of URLs this site claims"
|
|
39
|
+
* would be reaching past what the write boundary can actually see.
|
|
40
|
+
*/
|
|
41
|
+
/** One entry that already claims the `urlPath` a pending write would produce. */
|
|
42
|
+
export interface UrlPathClaimant {
|
|
43
|
+
/**
|
|
44
|
+
* Which of the two shapes was found. Callers word their own message from this, because the
|
|
45
|
+
* actionable advice differs: for `sibling-collection-index` the author should rename their new
|
|
46
|
+
* entry, for `parent-entry` they are adding the index entry that makes an existing pair
|
|
47
|
+
* contested.
|
|
48
|
+
*/
|
|
49
|
+
kind: 'sibling-collection-index' | 'parent-entry';
|
|
50
|
+
/** Absolute path of the file already claiming that URL. */
|
|
51
|
+
physicalPath: string;
|
|
52
|
+
/** The contested logical name — the sibling collection's name, or the parent entry's slug. */
|
|
53
|
+
name: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The index entry file directly inside `dir`, or null.
|
|
57
|
+
*
|
|
58
|
+
* Slug extraction is entry-type-agnostic (each candidate's own type is read out of its filename),
|
|
59
|
+
* so an index entry of ANY entry type counts — same reasoning as the existing same-slug guard,
|
|
60
|
+
* which is deliberately cross-type because the URL does not care what type serves it.
|
|
61
|
+
*/
|
|
62
|
+
export declare function findIndexEntryIn(dir: string): Promise<string | null>;
|
|
63
|
+
/** The entry file directly inside `dir` whose slug is `slug`, or null. */
|
|
64
|
+
export declare function findEntryBySlugIn(dir: string, slug: string): Promise<string | null>;
|
|
65
|
+
/**
|
|
66
|
+
* Would an entry at `collectionDir` with slug `slug` land on a `urlPath` some OTHER entry already
|
|
67
|
+
* claims? Returns the offender, or null when the write is clear.
|
|
68
|
+
*
|
|
69
|
+
* Only the cross-collection shapes are checked here. An entry colliding with another entry in the
|
|
70
|
+
* SAME collection is already refused upstream (`ContentStore.buildPaths` resolves a write by a
|
|
71
|
+
* type-agnostic slug scan, and the `expectedVersion: null` create-intent guard turns that into a
|
|
72
|
+
* conflict), so re-checking it would be duplicate work and a second source of truth.
|
|
73
|
+
*
|
|
74
|
+
* Two directory reads at worst, and only on create/rename — an ordinary save of an existing entry
|
|
75
|
+
* never calls this, because the entry's URL is not changing and the collision (if any) predates
|
|
76
|
+
* the write.
|
|
77
|
+
*
|
|
78
|
+
* @param contentRoot Absolute path of the content root. A root-level index entry claims `/`, which
|
|
79
|
+
* nothing above it can contest, so the `parent-entry` check stops here rather than walking out
|
|
80
|
+
* of the content tree.
|
|
81
|
+
*/
|
|
82
|
+
export declare function findUrlPathClaimant(opts: {
|
|
83
|
+
collectionDir: string;
|
|
84
|
+
slug: string;
|
|
85
|
+
contentRoot: string;
|
|
86
|
+
}): Promise<UrlPathClaimant | null>;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { extractSlugFromFilename } from './content-id-index.js';
|
|
4
|
+
import { isIndexSlug } from './utils/entry-url.js';
|
|
5
|
+
import { isNotFoundError } from './utils/error.js';
|
|
6
|
+
import { parseTypedFilename } from './utils/typed-filename.js';
|
|
7
|
+
/**
|
|
8
|
+
* Every extension `getFormatExtension` can return.
|
|
9
|
+
*
|
|
10
|
+
* Compared CASE-SENSITIVELY, deliberately, because `listCollectionEntries` compares
|
|
11
|
+
* case-sensitively (`d.name.endsWith(ext)` against lowercase extensions). Lowercasing here made
|
|
12
|
+
* the guard looser than the listing: a `doc.index.{id}.MD` file counted as a claimant while the
|
|
13
|
+
* listing skipped it silently — publishing no URL, tripping no build error, and blocking a write
|
|
14
|
+
* the build would have accepted.
|
|
15
|
+
*
|
|
16
|
+
* KNOWN RESIDUAL LOOSENESS, stated because the alternative is a comment that overclaims: the
|
|
17
|
+
* listing accepts only the extensions of a collection's OWN configured entry-type formats, while
|
|
18
|
+
* this accepts all four. A hand-authored `doc.index.{id}.json` inside an md-only collection
|
|
19
|
+
* therefore claims no URL yet still blocks a sibling write. Closing that means threading each
|
|
20
|
+
* collection's configured formats into a module that is deliberately schema-free, across three
|
|
21
|
+
* call sites, and going from a physical directory back to a schema item to do it — a change with
|
|
22
|
+
* more room to introduce a new defect than the narrow one it fixes. Tracked in
|
|
23
|
+
* .claude/future-tasks/url-collision-guard-superset-of-listing.md.
|
|
24
|
+
*
|
|
25
|
+
* A literal rather than derived: deriving it needs the `ContentFormat` union this module has no
|
|
26
|
+
* reason to import. `url-collision.test.ts` carries the drift tripwire — a compile-time
|
|
27
|
+
* exhaustiveness check plus a fixture per format — so adding a format fails there rather than
|
|
28
|
+
* silently under-blocking here.
|
|
29
|
+
*/
|
|
30
|
+
const CONTENT_EXTENSIONS = ['.md', '.mdx', '.json', '.yaml'];
|
|
31
|
+
/** Read a directory, treating "missing" as empty. Anything else is a real error and propagates. */
|
|
32
|
+
async function readDirSafe(dir) {
|
|
33
|
+
try {
|
|
34
|
+
return await fs.readdir(dir, { withFileTypes: true });
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (isNotFoundError(err))
|
|
38
|
+
return [];
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** The child directory of `dir` whose logical name is `name`, or null. */
|
|
43
|
+
async function findChildCollectionDir(dir, name) {
|
|
44
|
+
const wanted = name.toLowerCase();
|
|
45
|
+
for (const entry of await readDirSafe(dir)) {
|
|
46
|
+
if (!entry.isDirectory())
|
|
47
|
+
continue;
|
|
48
|
+
if (extractSlugFromFilename(entry.name) === wanted)
|
|
49
|
+
return path.join(dir, entry.name);
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The slug a file CLAIMS A URL AT, or null when the file claims none.
|
|
55
|
+
*
|
|
56
|
+
* This must recognise the set `listEntries` recognises, as closely as a schema-free module can,
|
|
57
|
+
* because the invariant is defined over the `urlPath`s `listEntries` publishes and the build-time
|
|
58
|
+
* half checks those. (One documented gap remains — see `CONTENT_EXTENSIONS`.) Hence
|
|
59
|
+
* `parseTypedFilename` — the same `{type}.{slug}.{id}.{ext}` grammar `listCollectionEntries` uses
|
|
60
|
+
* — rather than `extractSlugFromFilename`, which answers a different and much looser question
|
|
61
|
+
* ("what would I call this file?") and happily names a slug for things that are not entries.
|
|
62
|
+
*
|
|
63
|
+
* Getting this wrong OVER-BLOCKS, which is worse here than under-blocking: a hand-authored
|
|
64
|
+
* `index.md` with no content ID, an `index.md~` editor backup, or a colocated `guides.png` are all
|
|
65
|
+
* non-entries that claim no URL, so the build guard ignores them — but a looser scan counted them
|
|
66
|
+
* as claimants and refused a legitimate write, telling the author to "remove that collection's
|
|
67
|
+
* index entry" about a file Canopy does not consider an entry. That lands hardest on repos being
|
|
68
|
+
* retrofitted onto CanopyCMS, which is precisely the audience this guard's migration note
|
|
69
|
+
* addresses.
|
|
70
|
+
*
|
|
71
|
+
* Parsed structurally (no `entryTypes` list), which is the SECOND of three known ways this
|
|
72
|
+
* claimant set is a strict superset of the listing's — all of them over-blocks, all of them
|
|
73
|
+
* tracked together in .claude/future-tasks/url-collision-guard-superset-of-listing.md:
|
|
74
|
+
*
|
|
75
|
+
* 1. extension — see `CONTENT_EXTENSIONS` above;
|
|
76
|
+
* 2. entry TYPE — a file whose type is not in the collection's config is skipped by the
|
|
77
|
+
* listing but counted here. An earlier version of this comment dismissed that as "already
|
|
78
|
+
* reported by the listing's malformed-file guard". That is true only in BUILD mode; in the
|
|
79
|
+
* editor, where this guard actually runs, `listCollectionEntries` skips such a file with a
|
|
80
|
+
* debug-gated warning and nothing surfaces. Reached by the accident
|
|
81
|
+
* `looksLikeMalformedEntry` itself names as most common: renaming an entry type in
|
|
82
|
+
* `.collection.json` without renaming the files;
|
|
83
|
+
* 3. collection-hood — `findChildCollectionDir` matches any child directory by name, but a
|
|
84
|
+
* directory with no `.collection.json` is not a collection, so nothing inside it publishes
|
|
85
|
+
* a URL. Narrow (the file inside still needs valid entry grammar) but the same direction.
|
|
86
|
+
*
|
|
87
|
+
* All three need the same fix — the schema this module deliberately does not have — so they are
|
|
88
|
+
* one task, not three.
|
|
89
|
+
*/
|
|
90
|
+
function entrySlugOf(filename) {
|
|
91
|
+
// `parseTypedFilename` strips the extension without checking it, so an editor backup
|
|
92
|
+
// (`doc.index.{id}.md~`) parses exactly like the entry it shadows. `listCollectionEntries`
|
|
93
|
+
// additionally requires a CONFIGURED format extension, so it skips those -- and this must skip
|
|
94
|
+
// them too, or the guard refuses a write over a file the build guard never counted.
|
|
95
|
+
if (!CONTENT_EXTENSIONS.some((ext) => filename.endsWith(ext)))
|
|
96
|
+
return null;
|
|
97
|
+
return parseTypedFilename(filename)?.slug ?? null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The index entry file directly inside `dir`, or null.
|
|
101
|
+
*
|
|
102
|
+
* Slug extraction is entry-type-agnostic (each candidate's own type is read out of its filename),
|
|
103
|
+
* so an index entry of ANY entry type counts — same reasoning as the existing same-slug guard,
|
|
104
|
+
* which is deliberately cross-type because the URL does not care what type serves it.
|
|
105
|
+
*/
|
|
106
|
+
export async function findIndexEntryIn(dir) {
|
|
107
|
+
for (const entry of await readDirSafe(dir)) {
|
|
108
|
+
if (entry.isDirectory())
|
|
109
|
+
continue;
|
|
110
|
+
if (isIndexSlug(entrySlugOf(entry.name) ?? undefined))
|
|
111
|
+
return path.join(dir, entry.name);
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
/** The entry file directly inside `dir` whose slug is `slug`, or null. */
|
|
116
|
+
export async function findEntryBySlugIn(dir, slug) {
|
|
117
|
+
const wanted = slug.toLowerCase();
|
|
118
|
+
for (const entry of await readDirSafe(dir)) {
|
|
119
|
+
if (entry.isDirectory())
|
|
120
|
+
continue;
|
|
121
|
+
if (entrySlugOf(entry.name) === wanted)
|
|
122
|
+
return path.join(dir, entry.name);
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Would an entry at `collectionDir` with slug `slug` land on a `urlPath` some OTHER entry already
|
|
128
|
+
* claims? Returns the offender, or null when the write is clear.
|
|
129
|
+
*
|
|
130
|
+
* Only the cross-collection shapes are checked here. An entry colliding with another entry in the
|
|
131
|
+
* SAME collection is already refused upstream (`ContentStore.buildPaths` resolves a write by a
|
|
132
|
+
* type-agnostic slug scan, and the `expectedVersion: null` create-intent guard turns that into a
|
|
133
|
+
* conflict), so re-checking it would be duplicate work and a second source of truth.
|
|
134
|
+
*
|
|
135
|
+
* Two directory reads at worst, and only on create/rename — an ordinary save of an existing entry
|
|
136
|
+
* never calls this, because the entry's URL is not changing and the collision (if any) predates
|
|
137
|
+
* the write.
|
|
138
|
+
*
|
|
139
|
+
* @param contentRoot Absolute path of the content root. A root-level index entry claims `/`, which
|
|
140
|
+
* nothing above it can contest, so the `parent-entry` check stops here rather than walking out
|
|
141
|
+
* of the content tree.
|
|
142
|
+
*/
|
|
143
|
+
export async function findUrlPathClaimant(opts) {
|
|
144
|
+
const { collectionDir, slug, contentRoot } = opts;
|
|
145
|
+
if (isIndexSlug(slug)) {
|
|
146
|
+
// Adding an index entry collapses this collection onto its own path, which an entry sitting
|
|
147
|
+
// beside the collection in the PARENT may already hold.
|
|
148
|
+
const resolvedRoot = path.resolve(contentRoot);
|
|
149
|
+
if (path.resolve(collectionDir) === resolvedRoot)
|
|
150
|
+
return null; // a root index claims '/', uncontestable
|
|
151
|
+
const parentDir = path.dirname(collectionDir);
|
|
152
|
+
const ownName = extractSlugFromFilename(path.basename(collectionDir));
|
|
153
|
+
// A collection literally NAMED "index" collapses onto ITS OWN path (`<parentPath>/index`),
|
|
154
|
+
// not onto `<parentPath>` -- see `computeEntryUrl`. So the only thing that could contest it
|
|
155
|
+
// is another entry in the parent whose slug is ALSO the literal string "index" -- but per
|
|
156
|
+
// that same forward rule, such an entry IS the parent's own index/landing entry, which
|
|
157
|
+
// collapses onto `<parentPath>` itself, a different URL. Nothing in the parent can ever claim
|
|
158
|
+
// `<parentPath>/index`, so skip the lookup below rather than let it match the parent's own
|
|
159
|
+
// index entry and report a collision that does not exist. Without this, a collection named
|
|
160
|
+
// "index" could never have a landing page under any parent that has one of its own --
|
|
161
|
+
// ironic, since `resolveUrlPathCandidates`' candidate 2 was deliberately engineered to keep a
|
|
162
|
+
// collection named "index" addressable in the first place.
|
|
163
|
+
if (isIndexSlug(ownName))
|
|
164
|
+
return null;
|
|
165
|
+
const claimant = await findEntryBySlugIn(parentDir, ownName);
|
|
166
|
+
return claimant ? { kind: 'parent-entry', physicalPath: claimant, name: ownName } : null;
|
|
167
|
+
}
|
|
168
|
+
// A plain entry sits at the same URL as a same-named child collection's index entry.
|
|
169
|
+
//
|
|
170
|
+
// KNOWN DEPENDENCY: this resolves ONE child collection by name, and the index direction above
|
|
171
|
+
// likewise looks only for a parent ENTRY. Neither considers a second collection sharing the
|
|
172
|
+
// same name, because nothing currently stops one being created -- `createCollectionInner` does
|
|
173
|
+
// not check sibling names at all (tracked in collection-sibling-name-uniqueness.md). With two
|
|
174
|
+
// `guides.{id}` directories side by side you can write an index entry into each, and both
|
|
175
|
+
// writes pass this guard while two entries end up claiming one URL. The build guard still
|
|
176
|
+
// catches it. Fixing sibling-name uniqueness closes this without changing anything here --
|
|
177
|
+
// which is why that task is a prerequisite for this guard being complete, not an unrelated
|
|
178
|
+
// tidy-up.
|
|
179
|
+
const childDir = await findChildCollectionDir(collectionDir, slug);
|
|
180
|
+
if (!childDir)
|
|
181
|
+
return null;
|
|
182
|
+
const indexEntry = await findIndexEntryIn(childDir);
|
|
183
|
+
return indexEntry
|
|
184
|
+
? { kind: 'sibling-collection-index', physicalPath: indexEntry, name: slug }
|
|
185
|
+
: null;
|
|
186
|
+
}
|