canopycms 0.0.63 → 0.0.65
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 +7 -8
- package/dist/ai/index.js +0 -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 +4 -1
- package/dist/ai/to-plain-text.js +47 -1
- package/dist/ai/transform-components.d.ts +1 -2
- package/dist/ai/transform-components.js +0 -1
- 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 +9 -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 +14 -3
- 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 +4 -5
- package/dist/authorization/branch.js +0 -1
- 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 +6 -7
- 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 +22 -3
- package/dist/branch-health.js +6 -2
- 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 +5 -6
- package/dist/build-canopy.js +0 -1
- package/dist/build-mode.d.ts +1 -2
- package/dist/build-mode.js +0 -1
- package/dist/cli/cli.d.ts +18 -2
- package/dist/cli/cli.js +1172 -490
- package/dist/cli/generate-ai-content.d.ts +0 -1
- package/dist/cli/generate-ai-content.js +1000 -360
- package/dist/cli/init.d.ts +1 -2
- package/dist/cli/init.js +43 -6
- 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/Dockerfile.cms.template +8 -2
- package/dist/cli/template-files/cms-stack.ts.template +33 -6
- package/dist/cli/template-files/deploy-cms.yml.template +29 -14
- 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 +75 -59
- package/dist/content-listing.js +76 -83
- package/dist/content-reader.d.ts +4 -5
- package/dist/content-reader.js +22 -3
- package/dist/content-store.d.ts +137 -6
- package/dist/content-store.js +294 -22
- package/dist/content-tree.d.ts +15 -5
- package/dist/content-tree.js +27 -8
- package/dist/context.d.ts +9 -6
- package/dist/context.js +0 -1
- package/dist/dev-content-watcher.d.ts +12 -3
- package/dist/dev-content-watcher.js +120 -30
- 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 +114 -3
- package/dist/entry-schema.js +46 -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 -18
- package/dist/index.js +0 -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 +54 -45
- package/dist/server.js +11 -3
- package/dist/services.d.ts +10 -11
- package/dist/services.js +0 -1
- package/dist/settings-workspace.d.ts +12 -15
- package/dist/settings-workspace.js +10 -13
- package/dist/static/index.d.ts +164 -6
- package/dist/static/index.js +242 -7
- package/dist/static/seo.d.ts +8 -30
- package/dist/static/seo.js +19 -46
- 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 +10 -2
- 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 +18 -2
- package/dist/utils/git.js +61 -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 +2 -3
- package/dist/utils/sanitize-href.js +2 -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 +31 -2
- package/dist/worker/cms-worker.js +321 -13
- 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 +3 -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/to-plain-text.d.ts.map +0 -1
- package/dist/ai/to-plain-text.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-canopy.d.ts.map +0 -1
- package/dist/build-canopy.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/static/seo.d.ts.map +0 -1
- package/dist/static/seo.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
package/dist/content-store.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import matter from 'gray-matter';
|
|
4
|
-
import { parse as yamlParse
|
|
4
|
+
import { parse as yamlParse } from 'yaml';
|
|
5
5
|
import { atomicWriteFile } from './utils/atomic-write.js';
|
|
6
|
+
import { serializeFrontmatter, serializeYaml } from './utils/content-serialize.js';
|
|
6
7
|
import { withLock } from './utils/async-mutex.js';
|
|
7
8
|
import { ContentWriteLockBusyError, DEFAULT_CONTENT_WRITE_LOCK_WAIT_MS, withContentWriteLock, } from './utils/content-write-lock.js';
|
|
8
9
|
import { findBodyFieldName } from './utils/body-field.js';
|
|
10
|
+
import { buildResolvedReference } from './entry-schema.js';
|
|
11
|
+
import { computeEntryUrl } from './utils/entry-url.js';
|
|
12
|
+
import { findUrlPathClaimant } from './url-collision.js';
|
|
9
13
|
import { ContentIdIndex, extractIdFromFilename, extractSlugFromFilename, extractEntryTypeFromFilename, resolveCollectionPath, } from './content-id-index.js';
|
|
10
14
|
import { registerContentIndexForInvalidation } from './content-index-registry.js';
|
|
11
15
|
import { bumpContentIndexGeneration, readContentIndexGeneration } from './content-index-generation.js';
|
|
12
16
|
import { generateId } from './id.js';
|
|
13
17
|
import { isNodeError } from './utils/error.js';
|
|
14
|
-
import { filePathExists } from './utils/fs.js';
|
|
18
|
+
import { filePathExists, readFileIfExists } from './utils/fs.js';
|
|
15
19
|
import { asRecord, getFormatExtension } from './utils/format.js';
|
|
16
|
-
import { normalizeFilesystemPath, } from './paths/index.js';
|
|
20
|
+
import { normalizeFilesystemPath, parseSlug, } from './paths/index.js';
|
|
17
21
|
/**
|
|
18
22
|
* Acquire multiple lock keys (via withLock) in a canonical (sorted) order
|
|
19
23
|
* before running `fn`, to rule out AB-BA deadlocks between callers that need
|
|
@@ -107,6 +111,27 @@ export class DuplicateContentIdError extends ContentConflictError {
|
|
|
107
111
|
this.paths = sorted;
|
|
108
112
|
}
|
|
109
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Thrown when a create or rename would give a SECOND entry a `urlPath` another entry already
|
|
116
|
+
* holds -- the write-boundary half of the invariant `assertNoDuplicateUrlPaths` enforces at build
|
|
117
|
+
* time (see url-collision.ts for which shapes count and, just as importantly, which do not).
|
|
118
|
+
*
|
|
119
|
+
* Why refuse rather than write: only one of the two entries can be served at that URL, so the
|
|
120
|
+
* other silently has no route anywhere. Allowing the write trades a clear error now for a page
|
|
121
|
+
* that quietly does not exist later -- and, because the loser is picked by resolver precedence
|
|
122
|
+
* rather than by the author, not necessarily the page they were editing.
|
|
123
|
+
*
|
|
124
|
+
* A `ContentConflictError` subclass so every existing 409 mapping keeps working; the distinct
|
|
125
|
+
* type exists so the API can surface THIS message rather than the generic "modified by another
|
|
126
|
+
* editor", which would send the editor into a reload-and-retry loop that cannot succeed.
|
|
127
|
+
*/
|
|
128
|
+
export class UrlPathConflictError extends ContentConflictError {
|
|
129
|
+
constructor(message, conflictingPath) {
|
|
130
|
+
super(message);
|
|
131
|
+
this.name = 'UrlPathConflictError';
|
|
132
|
+
this.conflictingPath = conflictingPath;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
110
135
|
/**
|
|
111
136
|
* Get the default entry type from a collection's entries array.
|
|
112
137
|
* Returns the entry marked as default, or the first one, or undefined if no entries.
|
|
@@ -119,6 +144,13 @@ export function getDefaultEntryType(entries) {
|
|
|
119
144
|
/**
|
|
120
145
|
* Validates that a slug doesn't contain slashes or backslashes.
|
|
121
146
|
* Slugs must be simple filenames (last path segment only).
|
|
147
|
+
*
|
|
148
|
+
* Deliberately WEAKER than `parseSlug`, and deliberately not merged with it: this runs on every
|
|
149
|
+
* resolution, reads included (`buildPaths`), so it can only enforce what must be true of content
|
|
150
|
+
* that already exists on disk -- i.e. path safety. Content whose slug predates CanopyCMS, or was
|
|
151
|
+
* hand-authored, or came in over git, has to stay readable. `parseSlug`'s stricter URL-addressable
|
|
152
|
+
* rule is enforced only where a NEW filename is minted (see the [SLUG] guards in `write()` and
|
|
153
|
+
* `renameEntry()`); applying it here would convert a build-time failure into unreachable data.
|
|
122
154
|
*/
|
|
123
155
|
function validateSlug(slug) {
|
|
124
156
|
if (slug.includes('/')) {
|
|
@@ -136,6 +168,8 @@ const DEFAULT_INDEX_FRESHNESS_INTERVAL_MS = 1000;
|
|
|
136
168
|
const FORCED_REFRESH_MIN_INTERVAL_MS = 5000;
|
|
137
169
|
/** Internal sentinel: a lookup result that suggests this store's index is stale. */
|
|
138
170
|
const STALE_LOOKUP = Symbol('stale-index-lookup');
|
|
171
|
+
/** Create a cache for one batch of reference resolution. See {@link ReferenceResolveCache}. */
|
|
172
|
+
export const createReferenceResolveCache = () => new Map();
|
|
139
173
|
export class ContentStore {
|
|
140
174
|
constructor(root, flatSchema, options = {}) {
|
|
141
175
|
/** Bumped by invalidateIndex(); when it differs from loadedIndexGeneration the index is stale. */
|
|
@@ -420,6 +454,32 @@ export class ContentStore {
|
|
|
420
454
|
return this.createLockKey(schemaItem, slug);
|
|
421
455
|
return prePass.id ? this.idLockKey(prePass.id) : prePass.absolutePath;
|
|
422
456
|
}
|
|
457
|
+
/**
|
|
458
|
+
* Refuse a create/rename that would give a second entry a `urlPath` another entry already
|
|
459
|
+
* holds. See url-collision.ts for the two shapes that count, and the legitimate
|
|
460
|
+
* landing-page-beside-a-collection shape that deliberately does not.
|
|
461
|
+
*
|
|
462
|
+
* @param collectionDir Absolute physical directory the entry will live in.
|
|
463
|
+
* @param slug The entry's slug, as it will be written.
|
|
464
|
+
*/
|
|
465
|
+
async assertUrlPathAvailable(collectionDir, slug) {
|
|
466
|
+
const claimant = await findUrlPathClaimant({
|
|
467
|
+
collectionDir,
|
|
468
|
+
slug,
|
|
469
|
+
contentRoot: path.resolve(this.root, this.contentRootName),
|
|
470
|
+
});
|
|
471
|
+
if (!claimant)
|
|
472
|
+
return;
|
|
473
|
+
const relative = path.relative(this.root, claimant.physicalPath);
|
|
474
|
+
const message = claimant.kind === 'sibling-collection-index'
|
|
475
|
+
? `An entry with slug "${slug}" would share a URL with the index entry of the ` +
|
|
476
|
+
`"${claimant.name}" collection beside it ("${relative}"), and only one of them could ` +
|
|
477
|
+
`be served there. Rename this entry, or remove that collection's index entry.`
|
|
478
|
+
: `An index entry here would share a URL with the "${claimant.name}" entry in the parent ` +
|
|
479
|
+
`collection ("${relative}"), and only one of them could be served there. Rename that ` +
|
|
480
|
+
`entry, or give this collection's landing page a different slug.`;
|
|
481
|
+
throw new UrlPathConflictError(message, claimant.physicalPath);
|
|
482
|
+
}
|
|
423
483
|
/**
|
|
424
484
|
* Build absolute and relative paths with security validation.
|
|
425
485
|
* All entries use the unified filename pattern: {type}.{slug}.{id}.{ext}
|
|
@@ -773,6 +833,54 @@ export class ContentStore {
|
|
|
773
833
|
}
|
|
774
834
|
}
|
|
775
835
|
}
|
|
836
|
+
// [URL] Contested-URL guard, create only: an ordinary save cannot contest a URL it
|
|
837
|
+
// already holds, and blocking it would trap the author in an entry they can no longer
|
|
838
|
+
// edit.
|
|
839
|
+
//
|
|
840
|
+
// Keyed on whether the target file actually EXISTS, not on `inLock.existed`. That flag
|
|
841
|
+
// is `foundExisting || Boolean(options.existingId)`, and the `existingId` half is a
|
|
842
|
+
// caller ASSERTION rather than disk truth -- so an id-addressed write recreating an
|
|
843
|
+
// entry that was deleted out from under it (git, another process) would skip the guard
|
|
844
|
+
// while in fact creating one.
|
|
845
|
+
//
|
|
846
|
+
// The slug is read back off the filename `buildPaths` actually chose, never the
|
|
847
|
+
// caller's raw argument: `buildPaths` strips leading slashes and lowercases, and for
|
|
848
|
+
// the entry-type delegation shape substitutes the type name for an empty slug. Checking
|
|
849
|
+
// the raw value let `write(collection, '/guides', ...)` sail past a `guides` claimant.
|
|
850
|
+
//
|
|
851
|
+
// Serialization comes from `withContentWriteExclusion` (the branch-wide, cross-host
|
|
852
|
+
// content-write lock wrapping this whole reclassification loop), NOT from the per-entry
|
|
853
|
+
// lock: the two halves of a contested pair live in DIFFERENT collections and so take
|
|
854
|
+
// different entry-lock keys. The branch lock is what makes check-then-write atomic
|
|
855
|
+
// against the other half landing concurrently.
|
|
856
|
+
if (!(await filePathExists(absolutePath))) {
|
|
857
|
+
const chosenSlug = extractSlugFromFilename(path.basename(absolutePath));
|
|
858
|
+
// [SLUG] Routability guard, create only. `validateSlug` above (in buildPaths) is the
|
|
859
|
+
// path-traversal check -- it only rejects `/` and `\`, and it has to stay that weak
|
|
860
|
+
// because it also runs on every READ. So the filename grammar accepts slugs that
|
|
861
|
+
// `parseSlug` does not (a dot, an underscore, a leading hyphen), and `readByUrlPath`
|
|
862
|
+
// runs every URL candidate through `parseSlug` before trying a read -- meaning such
|
|
863
|
+
// an entry writes fine, builds fine, gets a `generateStaticParams` entry and a
|
|
864
|
+
// sitemap `<loc>`, and then 404s on every actual visit. `assertRoutableSlugs`
|
|
865
|
+
// (static/index.ts) now fails the whole production build over it.
|
|
866
|
+
//
|
|
867
|
+
// Refuse at the moment the unroutable entry is CREATED, so the failure lands on the
|
|
868
|
+
// caller that caused it rather than on whoever builds next. Create-only, keyed on the
|
|
869
|
+
// target file not existing, for exactly the reason the [URL] guard below is: content
|
|
870
|
+
// that already has a non-conforming slug (hand-authored, imported, or predating this
|
|
871
|
+
// guard) must stay editable -- and must stay renameable, which is the only way out.
|
|
872
|
+
// Tightening the read path instead would turn a red build into unreachable data.
|
|
873
|
+
//
|
|
874
|
+
// Checked against the slug `buildPaths` actually chose, not the caller's raw
|
|
875
|
+
// argument: buildPaths lowercases, strips leading slashes, and substitutes the entry
|
|
876
|
+
// type's name for an empty slug (the singleton shape, e.g. write('content/home', '')).
|
|
877
|
+
const routable = parseSlug(chosenSlug);
|
|
878
|
+
if (!routable.ok) {
|
|
879
|
+
throw new ContentStoreError(`Cannot create entry "${chosenSlug}": ${routable.error}. An entry whose slug is ` +
|
|
880
|
+
'not addressable as a URL segment would build and then 404 on every visit.', 'VALIDATION');
|
|
881
|
+
}
|
|
882
|
+
await this.assertUrlPathAvailable(path.dirname(absolutePath), chosenSlug);
|
|
883
|
+
}
|
|
776
884
|
await fs.mkdir(path.dirname(absolutePath), { recursive: true });
|
|
777
885
|
// OCC: undefined means no opinion (skip entirely, back-compat blind
|
|
778
886
|
// write). A number means "must match this mtime" (stale-write
|
|
@@ -846,16 +954,36 @@ export class ContentStore {
|
|
|
846
954
|
throw new ContentConflictError();
|
|
847
955
|
}
|
|
848
956
|
}
|
|
957
|
+
// Comment preservation: re-serialise onto the file's OWN parsed document rather than
|
|
958
|
+
// a fresh one, so nodes the payload did not change -- and the comments attached to
|
|
959
|
+
// them -- survive the write. Without this every editor save silently deleted every
|
|
960
|
+
// comment in the file (JSON has no comment syntax, so it is unaffected and skips the
|
|
961
|
+
// read). See utils/content-serialize.ts.
|
|
962
|
+
//
|
|
963
|
+
// This makes the write a genuine read-modify-write of the content file, so WHERE the
|
|
964
|
+
// read happens matters: it is inside withLock(lockKey), inside
|
|
965
|
+
// withContentWriteExclusion ([SYNC-C1]), and after the expectedVersion stat above --
|
|
966
|
+
// so the bytes read here are the bytes that OCC check validated, and no rebase can be
|
|
967
|
+
// running against this branch. Do not hoist it out of the critical section.
|
|
968
|
+
//
|
|
969
|
+
// INVARIANT, and the one case that does NOT preserve comments: this reads the path
|
|
970
|
+
// being WRITTEN. A relocating write -- one where the ID resolves to a different
|
|
971
|
+
// relativePath, so the block below unlinks `staleOldAbsPath` -- finds nothing at the
|
|
972
|
+
// new path and falls back to a plain stringify, losing the old file's comments. Latent
|
|
973
|
+
// today: the editor renames through renameEntry(), which link()s the bytes across
|
|
974
|
+
// intact, and no caller passes `existingId`. If a relocating write ever becomes
|
|
975
|
+
// reachable, read the ID's current path here instead of `absolutePath`.
|
|
976
|
+
const existingRaw = input.format === 'json' ? undefined : await readFileIfExists(absolutePath);
|
|
849
977
|
// Serialize content string
|
|
850
978
|
let content;
|
|
851
979
|
if (input.format === 'json') {
|
|
852
980
|
content = `${JSON.stringify(input.data ?? {}, null, 2)}\n`;
|
|
853
981
|
}
|
|
854
982
|
else if (input.format === 'yaml') {
|
|
855
|
-
content =
|
|
983
|
+
content = serializeYaml(input.data ?? {}, existingRaw);
|
|
856
984
|
}
|
|
857
985
|
else {
|
|
858
|
-
content =
|
|
986
|
+
content = serializeFrontmatter(input.body, input.data ?? {}, existingRaw);
|
|
859
987
|
}
|
|
860
988
|
await atomicWriteFile(absolutePath, content);
|
|
861
989
|
// Update the ID index after a successful write. Look up and mutate the
|
|
@@ -1114,7 +1242,7 @@ export class ContentStore {
|
|
|
1114
1242
|
// Warm the index outside the lock (a full scan must not hold the entry lock)
|
|
1115
1243
|
await this.idIndex();
|
|
1116
1244
|
const collection = this.assertCollection(collectionPath);
|
|
1117
|
-
//
|
|
1245
|
+
// Path-traversal check (rejects separators only).
|
|
1118
1246
|
validateSlug(newSlug);
|
|
1119
1247
|
const safeNewSlug = newSlug.replace(/^\/+/, '');
|
|
1120
1248
|
if (!safeNewSlug) {
|
|
@@ -1124,6 +1252,21 @@ export class ContentStore {
|
|
|
1124
1252
|
if (currentSlug === safeNewSlug) {
|
|
1125
1253
|
return { newPath: `${collectionPath}/${currentSlug}` };
|
|
1126
1254
|
}
|
|
1255
|
+
// [SLUG] Routability check, run here rather than trusted from the caller. The `Slug` branded
|
|
1256
|
+
// type does NOT guarantee it: `ContentStore.resolvePath` casts a raw path segment to `Slug`
|
|
1257
|
+
// with only `.toLowerCase()`, and tests/callers reach for `unsafeAsSlug`. The API's
|
|
1258
|
+
// `slugSchema` does run `parseSlug` on `newSlug`, but that is one caller of an exported
|
|
1259
|
+
// method -- and a rename mints a new filename, so it is a write that can create an
|
|
1260
|
+
// unroutable entry just as a create can. See write()'s [SLUG] guard for what goes wrong.
|
|
1261
|
+
//
|
|
1262
|
+
// Deliberately AFTER the no-op short-circuit above: a rename to the slug the entry already
|
|
1263
|
+
// has mints nothing, so refusing it would only take an existing non-conforming entry and
|
|
1264
|
+
// make one more operation on it fail, for no gain.
|
|
1265
|
+
const routable = parseSlug(safeNewSlug);
|
|
1266
|
+
if (!routable.ok) {
|
|
1267
|
+
throw new ContentStoreError(`Cannot rename to "${safeNewSlug}": ${routable.error}. An entry whose slug is not ` +
|
|
1268
|
+
'addressable as a URL segment would build and then 404 on every visit.', 'VALIDATION');
|
|
1269
|
+
}
|
|
1127
1270
|
// Pre-pass: classify via a directory scan (local ground truth, not the
|
|
1128
1271
|
// index) and pick the source entry's stable lock key.
|
|
1129
1272
|
const prePass = await this.buildPaths(collection, currentSlug);
|
|
@@ -1214,6 +1357,16 @@ export class ContentStore {
|
|
|
1214
1357
|
throw err;
|
|
1215
1358
|
// Ignore filesystem errors (e.g. ENOENT if parent dir doesn't exist)
|
|
1216
1359
|
}
|
|
1360
|
+
// [URL] Contested-URL guard. A rename moves the entry to a NEW url, so the same
|
|
1361
|
+
// check a create gets applies here -- including the index direction, since renaming
|
|
1362
|
+
// an entry TO `index` is how an existing collection acquires a landing page.
|
|
1363
|
+
//
|
|
1364
|
+
// Runs AFTER the same-slug scan above, deliberately. In an already-contested tree
|
|
1365
|
+
// both refusals apply, and the same-slug one is the more immediate and more
|
|
1366
|
+
// actionable of the two -- reporting the URL conflict first sent the author to fix
|
|
1367
|
+
// the other claimant, only to hit the same-slug refusal on the retry. Still before
|
|
1368
|
+
// link(), so either refusal leaves the tree untouched.
|
|
1369
|
+
await this.assertUrlPathAvailable(parentDir, safeNewSlug);
|
|
1217
1370
|
// Use link()+unlink() instead of rename() so a concurrent cross-process rename to the
|
|
1218
1371
|
// exact same destination path fails with EEXIST rather than silently overwriting.
|
|
1219
1372
|
//
|
|
@@ -1321,29 +1474,57 @@ export class ContentStore {
|
|
|
1321
1474
|
}
|
|
1322
1475
|
return entries;
|
|
1323
1476
|
}
|
|
1477
|
+
/**
|
|
1478
|
+
* Resolve every `reference` field in `data` against `fields`, returning a copy.
|
|
1479
|
+
*
|
|
1480
|
+
* This is what `read()` applies automatically (unless `resolveReferences: false`), exposed
|
|
1481
|
+
* so BATCH surfaces can opt into the same resolution without duplicating the walk: the
|
|
1482
|
+
* listing primitives in content-listing.ts and content-tree.ts read entry files straight
|
|
1483
|
+
* off disk and never touch this store, so before this existed a `reference` field reached
|
|
1484
|
+
* `listEntries()`/`buildContentTree()` callers as a bare id string or `null`.
|
|
1485
|
+
*
|
|
1486
|
+
* Pass one {@link ReferenceResolveCache} across a whole batch so a target referenced by
|
|
1487
|
+
* many entries is read once rather than once per referencing entry. Omit `cache` and the
|
|
1488
|
+
* behavior is exactly what `read()` has always done, unmemoized.
|
|
1489
|
+
*
|
|
1490
|
+
* **Path ACLs are not consulted for the targets.** Resolution goes through this store's
|
|
1491
|
+
* own `read()`, below the per-entry permission check in content-reader.ts — so a resolved
|
|
1492
|
+
* target may be an entry the caller could not `read()` directly. That is pre-existing
|
|
1493
|
+
* `read()` behavior, matched here on purpose so one rule covers both; see the
|
|
1494
|
+
* `resolveReferences` option in content-listing.ts for the note adopters see.
|
|
1495
|
+
*/
|
|
1496
|
+
async resolveReferences(data, fields, cache) {
|
|
1497
|
+
return this.resolveReferencesInData(data, fields, cache);
|
|
1498
|
+
}
|
|
1324
1499
|
/**
|
|
1325
1500
|
* Recursively resolve reference fields in data.
|
|
1326
1501
|
* This traverses objects, arrays, and blocks to find and resolve all reference fields.
|
|
1327
1502
|
*/
|
|
1328
|
-
async resolveReferencesInData(data, fields) {
|
|
1503
|
+
async resolveReferencesInData(data, fields, cache) {
|
|
1329
1504
|
const resolved = { ...data };
|
|
1330
1505
|
const idIndex = await this.idIndex();
|
|
1331
1506
|
for (const field of fields) {
|
|
1332
1507
|
// Inline groups are transparent — recurse into their children at the same data level
|
|
1333
1508
|
if (field.type === 'group') {
|
|
1334
|
-
const groupResolved = await this.resolveReferencesInData(resolved, field.fields);
|
|
1509
|
+
const groupResolved = await this.resolveReferencesInData(resolved, field.fields, cache);
|
|
1335
1510
|
Object.assign(resolved, groupResolved);
|
|
1336
1511
|
continue;
|
|
1337
1512
|
}
|
|
1338
1513
|
const value = data[field.name];
|
|
1339
1514
|
if (field.type === 'reference') {
|
|
1515
|
+
// Whether this reference EMBEDS its target (wants the target's body) or merely LINKS
|
|
1516
|
+
// to it is a property of the field, declared once in the schema -- not of the call,
|
|
1517
|
+
// which routinely contains both kinds at once. See ReferenceFieldConfig.includeBody.
|
|
1518
|
+
const includeBody = field.includeBody === true;
|
|
1340
1519
|
// Single reference
|
|
1341
1520
|
if (typeof value === 'string' && value) {
|
|
1342
|
-
resolved[field.name] = await this.resolveSingleReference(value, idIndex);
|
|
1521
|
+
resolved[field.name] = await this.resolveSingleReference(value, idIndex, includeBody, cache);
|
|
1343
1522
|
}
|
|
1344
1523
|
// Array of references (list: true)
|
|
1345
1524
|
else if (field.list && Array.isArray(value)) {
|
|
1346
|
-
resolved[field.name] = await Promise.all(value.map((id) => typeof id === 'string'
|
|
1525
|
+
resolved[field.name] = await Promise.all(value.map((id) => typeof id === 'string'
|
|
1526
|
+
? this.resolveSingleReference(id, idIndex, includeBody, cache)
|
|
1527
|
+
: null));
|
|
1347
1528
|
}
|
|
1348
1529
|
}
|
|
1349
1530
|
// Recursively handle nested objects
|
|
@@ -1353,11 +1534,11 @@ export class ContentStore {
|
|
|
1353
1534
|
continue;
|
|
1354
1535
|
if (objectField.list && Array.isArray(value)) {
|
|
1355
1536
|
resolved[field.name] = await Promise.all(value.map((item) => typeof item === 'object' && item !== null
|
|
1356
|
-
? this.resolveReferencesInData(item, objectField.fields)
|
|
1537
|
+
? this.resolveReferencesInData(item, objectField.fields, cache)
|
|
1357
1538
|
: item));
|
|
1358
1539
|
}
|
|
1359
1540
|
else if (typeof value === 'object') {
|
|
1360
|
-
resolved[field.name] = await this.resolveReferencesInData(value, objectField.fields);
|
|
1541
|
+
resolved[field.name] = await this.resolveReferencesInData(value, objectField.fields, cache);
|
|
1361
1542
|
}
|
|
1362
1543
|
}
|
|
1363
1544
|
// Recursively handle blocks
|
|
@@ -1372,7 +1553,7 @@ export class ContentStore {
|
|
|
1372
1553
|
return block;
|
|
1373
1554
|
return {
|
|
1374
1555
|
...b,
|
|
1375
|
-
value: await this.resolveReferencesInData(b.value, template.fields),
|
|
1556
|
+
value: await this.resolveReferencesInData(b.value, template.fields, cache),
|
|
1376
1557
|
};
|
|
1377
1558
|
}));
|
|
1378
1559
|
}
|
|
@@ -1380,7 +1561,68 @@ export class ContentStore {
|
|
|
1380
1561
|
return resolved;
|
|
1381
1562
|
}
|
|
1382
1563
|
/**
|
|
1383
|
-
* Resolve a single reference ID to full entry data
|
|
1564
|
+
* Resolve a single reference ID to full entry data, memoized when a batch cache is
|
|
1565
|
+
* supplied. Without a cache this is a straight pass-through to the uncached path, so
|
|
1566
|
+
* `read()` behaves exactly as it always has.
|
|
1567
|
+
*
|
|
1568
|
+
* Every occurrence gets its OWN deep copy, even on a cache hit. Without that, the memo
|
|
1569
|
+
* would hand one shared object to all 40 entries referencing the same block — a mutation
|
|
1570
|
+
* in one caller's `extract` (truncating a body for a search index, deleting a field) would
|
|
1571
|
+
* silently rewrite it for every sibling, and both `list: true` elements of `[id, id]` would
|
|
1572
|
+
* be the same instance. The copy is what keeps the cache a pure performance optimization
|
|
1573
|
+
* instead of a semantic change.
|
|
1574
|
+
*
|
|
1575
|
+
* Note the uncached path is NOT the clean baseline it looks like. For a json/yaml target it
|
|
1576
|
+
* genuinely reparses fresh per occurrence, but for md/mdx gray-matter serves `data` from a
|
|
1577
|
+
* process-global content-keyed cache, so `resolveSingleReferenceOnce`'s top-level spread
|
|
1578
|
+
* severs exactly one level and NESTED frontmatter objects alias across occurrences, calls and
|
|
1579
|
+
* requests. That is pre-existing `read()` behavior and out of scope here — deliberately, since
|
|
1580
|
+
* touching it would change `read()` — but it means the cached path is the safer of the two,
|
|
1581
|
+
* not a relaxation of a guarantee the uncached one provides. See
|
|
1582
|
+
* `.claude/future-tasks/graymatter-cache-shared-frontmatter.md`.
|
|
1583
|
+
*
|
|
1584
|
+
* What the copy costs, measured rather than assumed (2000 occurrences of one target, local
|
|
1585
|
+
* disk, so every read hits the page cache — the friendliest possible case for NOT caching):
|
|
1586
|
+
* a snippet-sized target is ~63x cheaper to clone than to re-read-and-parse, while a 265KB
|
|
1587
|
+
* JSON target is ~0.8x, i.e. cloning is marginally SLOWER than reparsing it. So the win is
|
|
1588
|
+
* large in the case this exists for and roughly a wash at the pathological end, never a
|
|
1589
|
+
* blow-up. Two things keep the bad end narrow: an md/mdx target resolves to its FRONTMATTER
|
|
1590
|
+
* only *unless the field sets `includeBody`* (`read()` puts the body on `doc.body`, which
|
|
1591
|
+
* `resolveSingleReferenceOnce` spreads in only for an embedding field), so by default body
|
|
1592
|
+
* size is irrelevant no matter how long the document and only a genuinely huge JSON/YAML
|
|
1593
|
+
* target reaches the wash. **`includeBody: true` is the case that CAN reach it on markdown**:
|
|
1594
|
+
* the body then sits inside the memoized object and is cloned once per referencing entry, so
|
|
1595
|
+
* a long document embedded by many pages pays that repeatedly — the reason `includeBody`
|
|
1596
|
+
* exists as an opt-in per field rather than as resolution's default. And in the deployment this
|
|
1597
|
+
* targets, content lives on EFS/NFS where the syscall the memo removes dominates parse and
|
|
1598
|
+
* clone alike, which the local-disk numbers above understate badly. Correctness is the
|
|
1599
|
+
* reason for the copy regardless; the numbers are here so nobody has to re-derive them
|
|
1600
|
+
* before touching this.
|
|
1601
|
+
*/
|
|
1602
|
+
resolveSingleReference(id, idIndex, includeBody, cache) {
|
|
1603
|
+
if (!cache)
|
|
1604
|
+
return this.resolveSingleReferenceUncached(id, idIndex, includeBody);
|
|
1605
|
+
// The key carries `includeBody`, not just the id: two fields can reference the SAME target
|
|
1606
|
+
// with different settings, and sharing one entry between them would make the shape depend
|
|
1607
|
+
// on which field the walk reached first -- the traversal-order nondeterminism the
|
|
1608
|
+
// per-occurrence copy already exists to prevent.
|
|
1609
|
+
const key = includeBody ? `${id}:body` : id;
|
|
1610
|
+
let pending = cache.get(key);
|
|
1611
|
+
if (!pending) {
|
|
1612
|
+
// Store the in-flight promise, and do it with no `await` in between: the whole point is
|
|
1613
|
+
// that concurrent lookups from one Promise.all batch find it and collapse onto a single
|
|
1614
|
+
// read. Memoizing the promise also keeps the self-healing retry below shared rather than
|
|
1615
|
+
// repeated — see ReferenceResolveCache for why misses are cached too.
|
|
1616
|
+
pending = this.resolveSingleReferenceUncached(id, idIndex, includeBody);
|
|
1617
|
+
cache.set(key, pending);
|
|
1618
|
+
}
|
|
1619
|
+
// The cached promise always has this handler attached, so it is never an unhandled
|
|
1620
|
+
// rejection; entry data is plain parsed JSON/YAML/frontmatter, so it is always cloneable
|
|
1621
|
+
// (verified against real parser output incl. `!!timestamp` Dates — the sole shape not
|
|
1622
|
+
// preserved exactly is a `!!binary` Buffer, which clones to a plain Uint8Array).
|
|
1623
|
+
return pending.then((resolved) => (resolved === null ? null : structuredClone(resolved)));
|
|
1624
|
+
}
|
|
1625
|
+
/**
|
|
1384
1626
|
* Returns null if the reference is invalid or missing.
|
|
1385
1627
|
* Includes id, slug, and collection fields for debugging.
|
|
1386
1628
|
*
|
|
@@ -1394,9 +1636,14 @@ export class ContentStore {
|
|
|
1394
1636
|
* idIndex() dedupes concurrent builds — so a sibling call that wins the
|
|
1395
1637
|
* throttle and rebuilds heals every other miss in the same batch, not just
|
|
1396
1638
|
* the first.
|
|
1639
|
+
*
|
|
1640
|
+
* A {@link ReferenceResolveCache} sits ABOVE this, never inside it, so every
|
|
1641
|
+
* distinct id still runs the full refresh-and-retry above. What a cache changes
|
|
1642
|
+
* is only that repeats of the SAME id in one batch share that one attempt's
|
|
1643
|
+
* outcome instead of each getting an independent throw of the dice.
|
|
1397
1644
|
*/
|
|
1398
|
-
async
|
|
1399
|
-
const first = await this.resolveSingleReferenceOnce(id, idIndex);
|
|
1645
|
+
async resolveSingleReferenceUncached(id, idIndex, includeBody) {
|
|
1646
|
+
const first = await this.resolveSingleReferenceOnce(id, idIndex, includeBody);
|
|
1400
1647
|
if (first !== STALE_LOOKUP)
|
|
1401
1648
|
return first;
|
|
1402
1649
|
// Force a rebuild (throttled). Even when this caller loses the throttle,
|
|
@@ -1404,10 +1651,10 @@ export class ContentStore {
|
|
|
1404
1651
|
// won it and invalidated/rebuilt (idIndex() dedupes in-flight builds), so
|
|
1405
1652
|
// every miss in a Promise.all batch heals, not just the first.
|
|
1406
1653
|
await this.refreshIndexForSuspiciousLookup();
|
|
1407
|
-
const second = await this.resolveSingleReferenceOnce(id, await this.idIndex());
|
|
1654
|
+
const second = await this.resolveSingleReferenceOnce(id, await this.idIndex(), includeBody);
|
|
1408
1655
|
return second === STALE_LOOKUP ? null : second;
|
|
1409
1656
|
}
|
|
1410
|
-
async resolveSingleReferenceOnce(id, idIndex) {
|
|
1657
|
+
async resolveSingleReferenceOnce(id, idIndex, includeBody) {
|
|
1411
1658
|
try {
|
|
1412
1659
|
const location = idIndex.findById(id);
|
|
1413
1660
|
if (!location)
|
|
@@ -1419,12 +1666,38 @@ export class ContentStore {
|
|
|
1419
1666
|
const doc = await this.read(location.collection, location.slug, {
|
|
1420
1667
|
resolveReferences: false,
|
|
1421
1668
|
});
|
|
1422
|
-
|
|
1669
|
+
// `urlPath` is what makes a resolved reference linkable. Without it, a page rendering
|
|
1670
|
+
// "see also: <Target>" as a real anchor had no way to get an href from the resolution
|
|
1671
|
+
// it had already paid for — one adopter ran a SECOND full listEntries pass over the
|
|
1672
|
+
// whole tree purely to build a contentId -> url table, and set `resolveReferences:
|
|
1673
|
+
// false` on pages where paying for both was worse than hand-rolling it.
|
|
1674
|
+
//
|
|
1675
|
+
// Deliberately `computeEntryUrl` (utils/entry-url.ts), the same forward
|
|
1676
|
+
// collection+slug -> url rule `listEntries` publishes as `item.urlPath` and
|
|
1677
|
+
// `entry-link-resolver.ts` already uses for `entry:ID` links — NOT the reverse
|
|
1678
|
+
// url -> entry resolver in url-path-resolver.ts. The two agree today (the reverse
|
|
1679
|
+
// resolver was taught to skip its direct-entry candidate for a literal `index` slug,
|
|
1680
|
+
// precisely so it stops answering at URLs this rule never emits — see
|
|
1681
|
+
// .claude/future-tasks/resolved/url-resolver-index-entry-extra-url.md), but the
|
|
1682
|
+
// direction still matters: this is the surface that DEFINES an entry's URL, and
|
|
1683
|
+
// sourcing it from the resolver that consumes that definition would invert the
|
|
1684
|
+
// dependency and let any future divergence propagate into every resolved reference.
|
|
1685
|
+
//
|
|
1686
|
+
// The assembly itself — data, then the embedded body, then the reserved metadata — is
|
|
1687
|
+
// `buildResolvedReference`'s job rather than this function's, because the editor's
|
|
1688
|
+
// live-preview endpoint (api/resolve-references.ts) builds the same object and the two
|
|
1689
|
+
// had already drifted. That doc comment carries the reasoning for the ordering.
|
|
1690
|
+
//
|
|
1691
|
+
// `'body' in doc` is what narrows the ContentDocument union to its markdown variant, so
|
|
1692
|
+
// `doc.body`/`doc.bodyFieldName` are reachable at all — a type guard, not a redundant
|
|
1693
|
+
// runtime check. Only a field that asked to EMBED its target passes a body at all.
|
|
1694
|
+
const bodyForEmbed = includeBody && 'body' in doc ? { fieldName: doc.bodyFieldName, value: doc.body } : undefined;
|
|
1695
|
+
return buildResolvedReference(doc.data, {
|
|
1423
1696
|
id,
|
|
1424
1697
|
slug: location.slug,
|
|
1425
1698
|
collection: location.collection,
|
|
1426
|
-
|
|
1427
|
-
};
|
|
1699
|
+
urlPath: computeEntryUrl(location.collection, location.slug, this.contentRootName),
|
|
1700
|
+
}, bodyForEmbed);
|
|
1428
1701
|
}
|
|
1429
1702
|
catch (error) {
|
|
1430
1703
|
// Index hit but the file is gone — the typical symptom of an external
|
|
@@ -1436,4 +1709,3 @@ export class ContentStore {
|
|
|
1436
1709
|
}
|
|
1437
1710
|
}
|
|
1438
1711
|
}
|
|
1439
|
-
//# sourceMappingURL=content-store.js.map
|
package/dist/content-tree.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* metadata, entry metadata). Display concerns like labels are left to the
|
|
9
9
|
* adopter via the `extract` callback.
|
|
10
10
|
*/
|
|
11
|
-
import type { FlatSchemaItem, ContentFormat } from './config';
|
|
11
|
+
import type { FlatSchemaItem, ContentFormat } from './config/index.js';
|
|
12
12
|
/**
|
|
13
13
|
* Adopter-supplied registry mapping entry type names (as they appear in
|
|
14
14
|
* filenames: `partner.index.yaml` → `'partner'`) to their data shapes.
|
|
@@ -86,8 +86,8 @@ export interface ContentTreeExtractMeta<TEntryTypes = DefaultEntryTypes> {
|
|
|
86
86
|
};
|
|
87
87
|
}[keyof TEntryTypes & string];
|
|
88
88
|
}
|
|
89
|
-
import type { LogicalPath, ContentId, Slug } from './paths/types';
|
|
90
|
-
import { type ContentVisibilityOptions } from './content-listing';
|
|
89
|
+
import type { LogicalPath, ContentId, Slug } from './paths/types.js';
|
|
90
|
+
import { type ContentVisibilityOptions } from './content-listing.js';
|
|
91
91
|
export interface ContentTreeNode<T = unknown> {
|
|
92
92
|
/** URL path, e.g. "/docs/getting-started". Computed by buildPath option. */
|
|
93
93
|
path: string;
|
|
@@ -162,13 +162,24 @@ export interface BuildContentTreeOptions<T = unknown, TEntryTypes = DefaultEntry
|
|
|
162
162
|
sort?: (a: ContentTreeNode<T>, b: ContentTreeNode<T>) => number;
|
|
163
163
|
/** Max depth to traverse. Default: unlimited. */
|
|
164
164
|
maxDepth?: number;
|
|
165
|
+
/**
|
|
166
|
+
* Resolve `reference` fields to the referenced entry's data, the way
|
|
167
|
+
* `read()`/`readByUrlPath()` do. Applies to both entry nodes and the `meta.indexEntry`
|
|
168
|
+
* handed to a collection's `extract`. Off leaves them as the bare id string, or `null`.
|
|
169
|
+
*
|
|
170
|
+
* Same flag, same default (`false`) and same reasoning as `listEntries`' option — see
|
|
171
|
+
* `ListEntriesOptions.resolveReferences` in content-listing.ts for why the default is
|
|
172
|
+
* opt-in rather than matching `read()`, what it costs, and why path ACLs are not applied
|
|
173
|
+
* to the resolved targets.
|
|
174
|
+
*/
|
|
175
|
+
resolveReferences?: boolean;
|
|
165
176
|
}
|
|
166
177
|
/**
|
|
167
178
|
* Default path builder: strips the content root prefix, lowercases, and prepends /.
|
|
168
179
|
* All URL paths are lowercased unconditionally for consistency with slug normalization.
|
|
169
180
|
* Adopters with case-sensitive slugs (e.g., "API-Reference") will get lowercased URLs.
|
|
170
181
|
*
|
|
171
|
-
* Index entries (slug 'index') are collapsed to their parent collection path,
|
|
182
|
+
* Index entries (slug 'index', any case) are collapsed to their parent collection path,
|
|
172
183
|
* matching the URL convention used by readByUrlPath and listEntries.
|
|
173
184
|
*
|
|
174
185
|
* Exported (also re-exported from `canopycms/server`) so adopters who want to
|
|
@@ -187,4 +198,3 @@ export declare const defaultBuildPath: (logicalPath: LogicalPath, contentRootNam
|
|
|
187
198
|
* @param visibility - Internal path-ACL predicate; see `ContentVisibilityOptions`
|
|
188
199
|
*/
|
|
189
200
|
export declare function buildContentTree<T = unknown, TEntryTypes = DefaultEntryTypes>(branchRoot: string, flatSchema: FlatSchemaItem[], contentRootName: string, options?: BuildContentTreeOptions<T, TEntryTypes>, visibility?: ContentVisibilityOptions): Promise<ContentTreeNode<T>[]>;
|
|
190
|
-
//# sourceMappingURL=content-tree.d.ts.map
|
package/dist/content-tree.js
CHANGED
|
@@ -8,7 +8,11 @@
|
|
|
8
8
|
* metadata, entry metadata). Display concerns like labels are left to the
|
|
9
9
|
* adopter via the `extract` callback.
|
|
10
10
|
*/
|
|
11
|
-
import {
|
|
11
|
+
import { isIndexSlug } from './utils/entry-url.js';
|
|
12
|
+
import { createReferenceResolver, listCollectionEntries, resolveCollectionItemReferences, sortByOrder, } from './content-listing.js';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Internal helpers
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
12
16
|
/** Group flat schema items by parentPath for O(1) child lookup. */
|
|
13
17
|
const groupByParent = (flat) => {
|
|
14
18
|
const map = new Map();
|
|
@@ -27,7 +31,7 @@ const groupByParent = (flat) => {
|
|
|
27
31
|
* All URL paths are lowercased unconditionally for consistency with slug normalization.
|
|
28
32
|
* Adopters with case-sensitive slugs (e.g., "API-Reference") will get lowercased URLs.
|
|
29
33
|
*
|
|
30
|
-
* Index entries (slug 'index') are collapsed to their parent collection path,
|
|
34
|
+
* Index entries (slug 'index', any case) are collapsed to their parent collection path,
|
|
31
35
|
* matching the URL convention used by readByUrlPath and listEntries.
|
|
32
36
|
*
|
|
33
37
|
* Exported (also re-exported from `canopycms/server`) so adopters who want to
|
|
@@ -40,11 +44,18 @@ export const defaultBuildPath = (logicalPath, contentRootName, kind) => {
|
|
|
40
44
|
const stripped = prefix && logicalPath.startsWith(prefix) ? logicalPath.slice(prefix.length) : logicalPath;
|
|
41
45
|
// Collapse index entries: content/guides/index → /guides (not /guides/index)
|
|
42
46
|
// Only for entries — a collection named "index" should keep its path.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
//
|
|
48
|
+
// The index test runs on the LAST SEGMENT through the shared `isIndexSlug`, so it is
|
|
49
|
+
// case-insensitive and agrees with `computeEntryUrl`. A string `endsWith('/index')` test
|
|
50
|
+
// did not: for an adopter-supplied `content/docs/Index` this said `/docs/index` while
|
|
51
|
+
// `computeEntryUrl` said `/docs`, and `/docs/index` is the one that does NOT round-trip.
|
|
52
|
+
const lastSlash = stripped.lastIndexOf('/');
|
|
53
|
+
const lastSegment = lastSlash === -1 ? stripped : stripped.slice(lastSlash + 1);
|
|
54
|
+
const collapsed = kind === 'entry' && isIndexSlug(lastSegment)
|
|
55
|
+
? lastSlash === -1
|
|
46
56
|
? ''
|
|
47
|
-
: stripped
|
|
57
|
+
: stripped.slice(0, lastSlash)
|
|
58
|
+
: stripped;
|
|
48
59
|
const urlPath = collapsed ? `/${collapsed}` : '/';
|
|
49
60
|
return urlPath.toLowerCase();
|
|
50
61
|
};
|
|
@@ -74,9 +85,18 @@ export async function buildContentTree(branchRoot, flatSchema, contentRootName,
|
|
|
74
85
|
* even though no node for it is ever emitted.
|
|
75
86
|
*/
|
|
76
87
|
const shouldInclude = visibility?.shouldInclude;
|
|
88
|
+
// One store + cache for the whole recursive walk, so a block shared across collections is
|
|
89
|
+
// read once for the entire tree rather than once per collection. Null unless opted in —
|
|
90
|
+
// see the `resolveReferences` option above.
|
|
91
|
+
const resolver = options?.resolveReferences
|
|
92
|
+
? createReferenceResolver(branchRoot, flatSchema, contentRootName)
|
|
93
|
+
: null;
|
|
77
94
|
const listVisibleEntries = async (collection) => {
|
|
78
95
|
const entries = await listCollectionEntries(branchRoot, collection);
|
|
79
|
-
|
|
96
|
+
const visible = shouldInclude ? entries.filter((e) => shouldInclude(e.physicalPath)) : entries;
|
|
97
|
+
// Resolved here rather than at the two node-building sites so BOTH inherit it — the same
|
|
98
|
+
// reason the ACL filter lives here. A denied entry is filtered above and never resolved.
|
|
99
|
+
return resolver ? resolveCollectionItemReferences(visible, collection, resolver) : visible;
|
|
80
100
|
};
|
|
81
101
|
// Find the starting collection(s)
|
|
82
102
|
const rootPath = options?.rootPath ?? contentRootName;
|
|
@@ -209,4 +229,3 @@ function interleaveChildren(collectionNodes, entryNodes, order, customSort) {
|
|
|
209
229
|
}
|
|
210
230
|
return sortByOrder(all, order, (item) => item.kind === 'collection' ? (item.collection?.name ?? '') : (item.entry?.slug ?? ''));
|
|
211
231
|
}
|
|
212
|
-
//# sourceMappingURL=content-tree.js.map
|
package/dist/context.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { CanopyUser } from './user';
|
|
2
|
-
import type { CanopyServices } from './services';
|
|
3
|
-
import type { ContentReadMeta } from './content-reader';
|
|
4
|
-
import { type BuildContentTreeOptions, type ContentTreeNode, type DefaultEntryTypes } from './content-tree';
|
|
5
|
-
import { type ListEntriesOptions, type ListEntriesItem } from './content-listing';
|
|
1
|
+
import type { CanopyUser } from './user.js';
|
|
2
|
+
import type { CanopyServices } from './services.js';
|
|
3
|
+
import type { ContentReadMeta } from './content-reader.js';
|
|
4
|
+
import { type BuildContentTreeOptions, type ContentTreeNode, type DefaultEntryTypes } from './content-tree.js';
|
|
5
|
+
import { type ListEntriesOptions, type ListEntriesItem } from './content-listing.js';
|
|
6
6
|
export interface CanopyContextOptions {
|
|
7
7
|
services: CanopyServices;
|
|
8
8
|
/**
|
|
@@ -78,6 +78,10 @@ export interface CanopyBuildContext {
|
|
|
78
78
|
* Tries direct entry match first (last segment = slug, rest = collection path),
|
|
79
79
|
* then falls back to index entry (full path = collection, slug = 'index').
|
|
80
80
|
* Root path '/' resolves to the content root's index entry.
|
|
81
|
+
*
|
|
82
|
+
* The direct-entry attempt is SKIPPED when the last segment is an index slug (any case), so
|
|
83
|
+
* `/x/index` returns null rather than a second URL for the entry that already answers at `/x`.
|
|
84
|
+
* A collection literally named `index` is unaffected — the fallback resolves it.
|
|
81
85
|
* Returns null if no content matches the path — including collection URLs that have no
|
|
82
86
|
* index entry (use buildContentTree for those) and non-entry/invalid paths such as
|
|
83
87
|
* `/favicon.ico` or Next internals (the slug validator rejects them, treated as a miss).
|
|
@@ -141,4 +145,3 @@ export declare function createCanopyContext(options: CanopyContextOptions): {
|
|
|
141
145
|
getContext: () => Promise<CanopyContext>;
|
|
142
146
|
services: CanopyServices;
|
|
143
147
|
};
|
|
144
|
-
//# sourceMappingURL=context.d.ts.map
|
package/dist/context.js
CHANGED