canopycms 0.0.67-int.90 → 0.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -3
- package/dist/ai/generate.js +1 -27
- package/dist/ai/handler.d.ts +0 -4
- package/dist/ai/handler.js +0 -11
- package/dist/ai/index.d.ts +1 -8
- package/dist/ai/index.js +1 -8
- package/dist/ai/json-to-markdown.js +15 -58
- package/dist/ai/resolve-branch.d.ts +2 -7
- package/dist/ai/resolve-branch.js +2 -8
- package/dist/ai/strip-mdx.d.ts +5 -13
- package/dist/ai/strip-mdx.js +5 -17
- package/dist/ai/to-plain-text.d.ts +10 -28
- package/dist/ai/to-plain-text.js +10 -28
- package/dist/ai/transform-components.d.ts +2 -4
- package/dist/ai/transform-components.js +8 -19
- package/dist/ai/types.d.ts +5 -10
- package/dist/api/admin-branch-health.d.ts +4 -12
- package/dist/api/admin-branch-health.js +26 -66
- package/dist/api/admin.d.ts +4 -12
- package/dist/api/admin.js +10 -26
- package/dist/api/assets.d.ts +0 -25
- package/dist/api/assets.js +50 -91
- package/dist/api/branch-merge.d.ts +1 -1
- package/dist/api/branch-merge.js +0 -2
- package/dist/api/branch-review.d.ts +0 -8
- package/dist/api/branch-review.js +0 -13
- package/dist/api/branch-status.d.ts +0 -3
- package/dist/api/branch-status.js +8 -33
- package/dist/api/branch-withdraw.d.ts +0 -1
- package/dist/api/branch-withdraw.js +6 -9
- package/dist/api/branch.d.ts +7 -12
- package/dist/api/branch.js +7 -44
- package/dist/api/client.d.ts +71 -224
- package/dist/api/client.js +82 -233
- package/dist/api/comments.d.ts +2 -4
- package/dist/api/comments.js +0 -17
- package/dist/api/content.d.ts +0 -6
- package/dist/api/content.js +66 -142
- package/dist/api/entries-constants.d.ts +5 -9
- package/dist/api/entries-constants.js +5 -9
- package/dist/api/entries.d.ts +8 -13
- package/dist/api/entries.js +20 -51
- package/dist/api/github-sync.d.ts +2 -4
- package/dist/api/github-sync.js +4 -8
- package/dist/api/groups.d.ts +3 -0
- package/dist/api/groups.js +8 -21
- package/dist/api/guards.d.ts +4 -16
- package/dist/api/guards.js +3 -22
- package/dist/api/index.d.ts +4 -4
- package/dist/api/permissions.d.ts +2 -0
- package/dist/api/permissions.js +18 -40
- package/dist/api/reference-options.d.ts +0 -1
- package/dist/api/reference-options.js +3 -11
- package/dist/api/request-body-hash.d.ts +12 -23
- package/dist/api/request-body-hash.js +12 -23
- package/dist/api/resolve-references.d.ts +0 -1
- package/dist/api/resolve-references.js +13 -28
- package/dist/api/route-builder.d.ts +3 -7
- package/dist/api/route-builder.js +1 -1
- package/dist/api/routes.d.ts +12 -0
- package/dist/api/routes.js +47 -0
- package/dist/api/schema.d.ts +23 -33
- package/dist/api/schema.js +20 -74
- package/dist/api/settings-helpers.js +4 -5
- package/dist/api/types.d.ts +0 -5
- package/dist/api/user.js +0 -5
- package/dist/api/validators.d.ts +14 -52
- package/dist/api/validators.js +14 -52
- package/dist/assets/asset-prefixes.d.ts +4 -8
- package/dist/assets/asset-prefixes.js +4 -8
- package/dist/assets/asset-src.d.ts +5 -22
- package/dist/assets/asset-src.js +5 -21
- package/dist/assets/factory.d.ts +1 -2
- package/dist/assets/factory.js +1 -2
- package/dist/assets/finalize.d.ts +3 -1
- package/dist/assets/finalize.js +3 -1
- package/dist/assets/index.d.ts +3 -3
- package/dist/assets/index.js +1 -1
- package/dist/assets/keys.d.ts +5 -3
- package/dist/assets/keys.js +6 -3
- package/dist/assets/pipeline.d.ts +3 -2
- package/dist/assets/pipeline.js +22 -56
- package/dist/assets/sharp-loader.d.ts +2 -10
- package/dist/assets/sharp-loader.js +2 -10
- package/dist/assets/store-local.d.ts +1 -2
- package/dist/assets/store-local.js +1 -2
- package/dist/assets/store-s3.d.ts +3 -4
- package/dist/assets/svg-sanitizer.d.ts +6 -14
- package/dist/assets/svg-sanitizer.js +6 -14
- package/dist/assets/transform-directives.d.ts +3 -4
- package/dist/assets/transform-directives.js +1 -1
- package/dist/assets/transform.d.ts +19 -30
- package/dist/assets/transform.js +18 -31
- package/dist/auth/cache.d.ts +2 -3
- package/dist/auth/cache.js +2 -3
- package/dist/auth/caching-auth-plugin.d.ts +11 -22
- package/dist/auth/caching-auth-plugin.js +12 -14
- package/dist/auth/context-helpers.d.ts +6 -20
- package/dist/auth/context-helpers.js +5 -17
- package/dist/auth/file-based-auth-cache.d.ts +10 -21
- package/dist/auth/file-based-auth-cache.js +23 -51
- package/dist/auth/plugin.d.ts +29 -61
- package/dist/auth/plugin.js +9 -13
- package/dist/auth/types.d.ts +11 -20
- package/dist/authorization/branch.d.ts +30 -49
- package/dist/authorization/branch.js +16 -42
- package/dist/authorization/content.d.ts +11 -40
- package/dist/authorization/content.js +13 -45
- package/dist/authorization/groups/index.d.ts +0 -3
- package/dist/authorization/groups/index.js +0 -3
- package/dist/authorization/groups/loader.d.ts +14 -28
- package/dist/authorization/groups/loader.js +14 -38
- package/dist/authorization/groups/schema.d.ts +0 -6
- package/dist/authorization/groups/schema.js +4 -7
- package/dist/authorization/helpers.d.ts +9 -28
- package/dist/authorization/helpers.js +9 -28
- package/dist/authorization/index.d.ts +3 -25
- package/dist/authorization/index.js +3 -35
- package/dist/authorization/path.d.ts +6 -13
- package/dist/authorization/path.js +8 -25
- package/dist/authorization/permissions/index.d.ts +0 -3
- package/dist/authorization/permissions/index.js +0 -3
- package/dist/authorization/permissions/loader.d.ts +14 -27
- package/dist/authorization/permissions/loader.js +14 -32
- package/dist/authorization/permissions/schema.d.ts +1 -6
- package/dist/authorization/permissions/schema.js +6 -13
- package/dist/authorization/protected-branch.d.ts +36 -65
- package/dist/authorization/protected-branch.js +29 -41
- package/dist/authorization/settings-file-store.d.ts +38 -81
- package/dist/authorization/settings-file-store.js +38 -79
- package/dist/authorization/types.d.ts +4 -26
- package/dist/authorization/types.js +0 -6
- package/dist/authorization/validation.d.ts +1 -23
- package/dist/authorization/validation.js +1 -24
- package/dist/branch-health.d.ts +39 -67
- package/dist/branch-health.js +27 -43
- package/dist/branch-metadata-file.d.ts +16 -32
- package/dist/branch-metadata-file.js +13 -26
- package/dist/branch-metadata.d.ts +49 -80
- package/dist/branch-metadata.js +57 -87
- package/dist/branch-registry.d.ts +26 -64
- package/dist/branch-registry.js +44 -93
- package/dist/branch-schema-cache.d.ts +34 -124
- package/dist/branch-schema-cache.js +49 -155
- package/dist/branch-workspace.d.ts +4 -4
- package/dist/branch-workspace.js +15 -19
- package/dist/build/generate-ai-content.d.ts +1 -0
- package/dist/build/generate-ai-content.js +12 -25
- package/dist/build-canopy.d.ts +17 -27
- package/dist/build-canopy.js +16 -23
- package/dist/build-mode.d.ts +25 -27
- package/dist/build-mode.js +25 -29
- package/dist/cli/cli.d.ts +15 -26
- package/dist/cli/cli.js +601 -978
- package/dist/cli/generate-ai-content.js +351 -628
- package/dist/cli/github-app-manifest.d.ts +84 -0
- package/dist/cli/github-app-manifest.js +161 -0
- package/dist/cli/init-github-app.d.ts +110 -444
- package/dist/cli/init-github-app.js +236 -773
- package/dist/cli/init.js +39 -80
- package/dist/cli/migrate.d.ts +13 -10
- package/dist/cli/migrate.js +22 -30
- package/dist/cli/project-detect.d.ts +17 -31
- package/dist/cli/project-detect.js +31 -42
- package/dist/cli/project-root.d.ts +4 -11
- package/dist/cli/project-root.js +4 -11
- package/dist/cli/prompt.d.ts +10 -0
- package/dist/cli/prompt.js +67 -0
- package/dist/cli/sync.d.ts +0 -8
- package/dist/cli/sync.js +8 -28
- package/dist/cli/template-files/middleware.ts.template +15 -29
- package/dist/cli/templates.d.ts +2 -12
- package/dist/cli/templates.js +4 -4
- package/dist/client.d.ts +1 -1
- package/dist/comment-store.d.ts +32 -53
- package/dist/comment-store.js +32 -52
- package/dist/config/flatten.d.ts +0 -3
- package/dist/config/flatten.js +2 -12
- package/dist/config/helpers.js +2 -2
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +1 -4
- package/dist/config/schemas/collection.d.ts +0 -8
- package/dist/config/schemas/collection.js +0 -10
- package/dist/config/schemas/config.d.ts +6 -78
- package/dist/config/schemas/config.js +38 -54
- package/dist/config/schemas/field.d.ts +2 -242
- package/dist/config/schemas/field.js +9 -20
- package/dist/config/schemas/media.js +1 -1
- package/dist/config/schemas/permissions.js +0 -2
- package/dist/config/schemas/url.d.ts +5 -6
- package/dist/config/schemas/url.js +5 -6
- package/dist/config/types.d.ts +45 -33
- package/dist/config/types.js +0 -1
- package/dist/config.d.ts +1 -8
- package/dist/config.js +1 -9
- package/dist/content-id-index.d.ts +76 -188
- package/dist/content-id-index.js +79 -230
- package/dist/content-index-generation.d.ts +27 -48
- package/dist/content-index-generation.js +35 -84
- package/dist/content-index-registry.d.ts +15 -24
- package/dist/content-index-registry.js +5 -9
- package/dist/content-listing.d.ts +64 -107
- package/dist/content-listing.js +68 -118
- package/dist/content-reader.d.ts +20 -29
- package/dist/content-reader.js +10 -18
- package/dist/content-store.d.ts +210 -336
- package/dist/content-store.js +413 -657
- package/dist/content-tree.d.ts +44 -86
- package/dist/content-tree.js +26 -54
- package/dist/context.d.ts +67 -94
- package/dist/context.js +53 -72
- package/dist/dev-content-watcher.d.ts +18 -18
- package/dist/dev-content-watcher.js +41 -44
- package/dist/editor/BranchManager.d.ts +3 -6
- package/dist/editor/BranchManager.js +24 -44
- package/dist/editor/CanopyEditor.js +5 -2
- package/dist/editor/CommentsPanel.js +0 -2
- package/dist/editor/Editor.js +19 -76
- package/dist/editor/EditorAuthGate.d.ts +27 -0
- package/dist/editor/EditorAuthGate.js +140 -0
- package/dist/editor/EntryNavigator.js +0 -20
- package/dist/editor/FormRenderer.d.ts +1 -2
- package/dist/editor/FormRenderer.js +8 -23
- package/dist/editor/admin/SystemHealthPanel.js +20 -37
- package/dist/editor/admin/useSystemHealth.d.ts +2 -3
- package/dist/editor/admin/useSystemHealth.js +10 -12
- package/dist/editor/client-reference-resolver.d.ts +2 -5
- package/dist/editor/client-reference-resolver.js +2 -19
- package/dist/editor/comments/BranchComments.js +0 -4
- package/dist/editor/comments/EntryComments.js +0 -4
- package/dist/editor/comments/FieldWrapper.js +0 -4
- package/dist/editor/comments/InlineCommentThread.js +0 -2
- package/dist/editor/comments/ThreadCarousel.d.ts +0 -58
- package/dist/editor/comments/ThreadCarousel.js +0 -12
- package/dist/editor/components/EditorFooter.d.ts +0 -8
- package/dist/editor/components/EditorFooter.js +0 -5
- package/dist/editor/components/EditorHeader.d.ts +0 -31
- package/dist/editor/components/EditorHeader.js +21 -71
- package/dist/editor/components/EditorSidebar.d.ts +0 -19
- package/dist/editor/components/EditorSidebar.js +0 -16
- package/dist/editor/components/EntryCreateModal.d.ts +4 -4
- package/dist/editor/components/EntryCreateModal.js +7 -22
- package/dist/editor/components/RenameEntryModal.js +0 -4
- package/dist/editor/components/UserBadge.js +0 -10
- package/dist/editor/components/index.js +0 -2
- package/dist/editor/context/ApiClientContext.d.ts +8 -7
- package/dist/editor/context/ApiClientContext.js +39 -11
- package/dist/editor/context/AssetContext.d.ts +7 -17
- package/dist/editor/context/AssetContext.js +7 -17
- package/dist/editor/context/EditorIdentityContext.d.ts +13 -0
- package/dist/editor/context/EditorIdentityContext.js +7 -0
- package/dist/editor/context/EditorStateContext.d.ts +10 -41
- package/dist/editor/context/EditorStateContext.js +7 -23
- package/dist/editor/context/SWRProvider.d.ts +3 -6
- package/dist/editor/context/index.d.ts +1 -20
- package/dist/editor/context/index.js +1 -20
- package/dist/editor/editor-utils.d.ts +8 -47
- package/dist/editor/editor-utils.js +19 -72
- package/dist/editor/fields/BlockField.d.ts +2 -2
- package/dist/editor/fields/BlockField.js +1 -2
- package/dist/editor/fields/CodeField.d.ts +0 -1
- package/dist/editor/fields/CodeField.js +0 -1
- package/dist/editor/fields/DateTimeField.d.ts +15 -22
- package/dist/editor/fields/DateTimeField.js +17 -26
- package/dist/editor/fields/ImageField.d.ts +2 -2
- package/dist/editor/fields/ImageField.js +8 -14
- package/dist/editor/fields/InlineGroupField.d.ts +0 -1
- package/dist/editor/fields/InlineGroupField.js +0 -1
- package/dist/editor/fields/MarkdownField.d.ts +0 -1
- package/dist/editor/fields/MarkdownField.js +6 -11
- package/dist/editor/fields/MdxImageDialog.d.ts +1 -1
- package/dist/editor/fields/MdxImageDialog.js +0 -1
- package/dist/editor/fields/NumberField.d.ts +9 -19
- package/dist/editor/fields/NumberField.js +11 -22
- package/dist/editor/fields/NumberListField.d.ts +7 -10
- package/dist/editor/fields/NumberListField.js +7 -10
- package/dist/editor/fields/ObjectField.d.ts +5 -8
- package/dist/editor/fields/ObjectField.js +0 -1
- package/dist/editor/fields/ReferenceField.d.ts +1 -1
- package/dist/editor/fields/ReferenceField.js +11 -16
- package/dist/editor/fields/SelectField.d.ts +2 -2
- package/dist/editor/fields/SelectField.js +0 -1
- package/dist/editor/fields/StringListField.d.ts +0 -4
- package/dist/editor/fields/StringListField.js +4 -9
- package/dist/editor/fields/TextField.d.ts +0 -1
- package/dist/editor/fields/TextField.js +0 -1
- package/dist/editor/fields/ToggleField.d.ts +0 -1
- package/dist/editor/fields/ToggleField.js +0 -1
- package/dist/editor/fields/entry-link/EntryLinkContext.js +2 -4
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +0 -3
- package/dist/editor/fields/entry-link/InsertEntryLink.js +0 -4
- package/dist/editor/group-manager/ExternalGroupsTab.d.ts +0 -3
- package/dist/editor/group-manager/ExternalGroupsTab.js +0 -1
- package/dist/editor/group-manager/GroupCard.d.ts +0 -3
- package/dist/editor/group-manager/GroupForm.d.ts +0 -3
- package/dist/editor/group-manager/InternalGroupsTab.d.ts +0 -3
- package/dist/editor/group-manager/InternalGroupsTab.js +0 -2
- package/dist/editor/group-manager/MemberList.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useExternalGroupSearch.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useExternalGroupSearch.js +0 -3
- package/dist/editor/group-manager/hooks/useGroupState.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useGroupState.js +0 -5
- package/dist/editor/group-manager/hooks/useUserSearch.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useUserSearch.js +0 -3
- package/dist/editor/group-manager/index.d.ts +0 -6
- package/dist/editor/group-manager/index.js +0 -10
- package/dist/editor/group-manager/types.d.ts +2 -5
- package/dist/editor/group-manager/types.js +0 -3
- package/dist/editor/hooks/index.d.ts +6 -11
- package/dist/editor/hooks/index.js +6 -12
- package/dist/editor/hooks/useBranchActions.d.ts +0 -14
- package/dist/editor/hooks/useBranchActions.js +0 -22
- package/dist/editor/hooks/useBranchManager.d.ts +2 -48
- package/dist/editor/hooks/useBranchManager.js +4 -64
- package/dist/editor/hooks/useBranchesData.d.ts +7 -6
- package/dist/editor/hooks/useBranchesData.js +7 -6
- package/dist/editor/hooks/useCommentSystem.d.ts +0 -49
- package/dist/editor/hooks/useCommentSystem.js +1 -36
- package/dist/editor/hooks/useDraftManager.d.ts +2 -35
- package/dist/editor/hooks/useDraftManager.js +23 -64
- package/dist/editor/hooks/useEditorLayout.d.ts +0 -20
- package/dist/editor/hooks/useEditorLayout.js +0 -23
- package/dist/editor/hooks/useEntriesData.d.ts +1 -0
- package/dist/editor/hooks/useEntriesData.js +2 -3
- package/dist/editor/hooks/useEntryLinkResolution.d.ts +2 -2
- package/dist/editor/hooks/useEntryLinkResolution.js +2 -2
- package/dist/editor/hooks/useEntryManager.d.ts +2 -27
- package/dist/editor/hooks/useEntryManager.js +29 -78
- package/dist/editor/hooks/useGroupManager.d.ts +0 -21
- package/dist/editor/hooks/useGroupManager.js +0 -21
- package/dist/editor/hooks/usePermissionManager.d.ts +0 -20
- package/dist/editor/hooks/usePermissionManager.js +0 -20
- package/dist/editor/hooks/useReferenceResolution.d.ts +2 -33
- package/dist/editor/hooks/useReferenceResolution.js +1 -48
- package/dist/editor/hooks/useSchemaManager.d.ts +8 -27
- package/dist/editor/hooks/useSchemaManager.js +0 -19
- package/dist/editor/hooks/useUserContext.d.ts +2 -9
- package/dist/editor/hooks/useUserContext.js +10 -10
- package/dist/editor/hooks/useUserMetadata.d.ts +0 -2
- package/dist/editor/hooks/useUserMetadata.js +0 -3
- package/dist/editor/media/AssetCard.d.ts +0 -1
- package/dist/editor/media/AssetCard.js +1 -2
- package/dist/editor/media/CropStep.d.ts +0 -1
- package/dist/editor/media/CropStep.js +0 -1
- package/dist/editor/media/MediaLibrary.d.ts +1 -2
- package/dist/editor/media/MediaLibrary.js +1 -2
- package/dist/editor/media/MediaLibraryBody.d.ts +0 -1
- package/dist/editor/media/MediaLibraryBody.js +0 -1
- package/dist/editor/media/crop-math.d.ts +1 -1
- package/dist/editor/media/crop-math.js +1 -1
- package/dist/editor/permission-manager/GroupSelector.d.ts +0 -3
- package/dist/editor/permission-manager/PermissionEditor.d.ts +0 -4
- package/dist/editor/permission-manager/PermissionEditor.js +0 -1
- package/dist/editor/permission-manager/PermissionLevelBadge.d.ts +0 -7
- package/dist/editor/permission-manager/PermissionLevelBadge.js +0 -4
- package/dist/editor/permission-manager/PermissionTree.d.ts +0 -4
- package/dist/editor/permission-manager/UserSelector.d.ts +0 -3
- package/dist/editor/permission-manager/constants.d.ts +0 -3
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts +0 -3
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js +0 -10
- package/dist/editor/permission-manager/hooks/usePermissionTree.d.ts +0 -14
- package/dist/editor/permission-manager/hooks/usePermissionTree.js +0 -11
- package/dist/editor/permission-manager/index.d.ts +0 -7
- package/dist/editor/permission-manager/index.js +0 -16
- package/dist/editor/permission-manager/types.d.ts +2 -12
- package/dist/editor/permission-manager/types.js +0 -3
- package/dist/editor/permission-manager/utils.d.ts +0 -28
- package/dist/editor/permission-manager/utils.js +9 -23
- package/dist/editor/preview-bridge.d.ts +5 -1
- package/dist/editor/preview-bridge.js +4 -4
- package/dist/editor/schema-editor/CollectionEditor.d.ts +0 -5
- package/dist/editor/schema-editor/CollectionEditor.js +9 -31
- package/dist/editor/schema-editor/EntryTypeEditor.d.ts +0 -6
- package/dist/editor/schema-editor/EntryTypeEditor.js +3 -24
- package/dist/editor/schema-editor/index.d.ts +0 -7
- package/dist/editor/schema-editor/index.js +0 -7
- package/dist/editor/utils/env.d.ts +3 -18
- package/dist/editor/utils/env.js +6 -25
- package/dist/entry-link-resolver.d.ts +13 -35
- package/dist/entry-link-resolver.js +20 -53
- package/dist/entry-schema-registry.d.ts +20 -60
- package/dist/entry-schema-registry.js +20 -69
- package/dist/entry-schema.d.ts +118 -223
- package/dist/entry-schema.js +46 -91
- package/dist/git-manager.d.ts +101 -200
- package/dist/git-manager.js +211 -384
- package/dist/github-service.d.ts +34 -75
- package/dist/github-service.js +37 -91
- package/dist/http/handler.d.ts +6 -37
- package/dist/http/handler.js +65 -120
- package/dist/http/router.d.ts +15 -32
- package/dist/http/router.js +34 -99
- package/dist/http/types.d.ts +15 -40
- package/dist/http/types.js +3 -7
- package/dist/id.d.ts +4 -10
- package/dist/id.js +4 -10
- package/dist/index.js +6 -9
- package/dist/operating-mode/client-safe-strategy.d.ts +7 -14
- package/dist/operating-mode/client-safe-strategy.js +8 -28
- package/dist/operating-mode/client-unsafe-strategy.d.ts +6 -16
- package/dist/operating-mode/client-unsafe-strategy.js +9 -34
- package/dist/operating-mode/client.d.ts +3 -10
- package/dist/operating-mode/client.js +3 -8
- package/dist/operating-mode/deployment-name-fixtures.d.ts +14 -18
- package/dist/operating-mode/deployment-name-fixtures.js +14 -18
- package/dist/operating-mode/deployment-name.d.ts +19 -29
- package/dist/operating-mode/deployment-name.js +29 -47
- package/dist/operating-mode/index.d.ts +4 -25
- package/dist/operating-mode/index.js +9 -31
- package/dist/operating-mode/mode-env.d.ts +32 -54
- package/dist/operating-mode/mode-env.js +36 -58
- package/dist/operating-mode/types.d.ts +24 -72
- package/dist/operating-mode/types.js +1 -7
- package/dist/paths/branch-name.d.ts +30 -40
- package/dist/paths/branch-name.js +30 -40
- package/dist/paths/branch.d.ts +4 -18
- package/dist/paths/branch.js +6 -22
- package/dist/paths/index.d.ts +2 -13
- package/dist/paths/index.js +3 -23
- package/dist/paths/normalize-server.d.ts +3 -15
- package/dist/paths/normalize-server.js +3 -15
- package/dist/paths/normalize.d.ts +13 -33
- package/dist/paths/normalize.js +13 -33
- package/dist/paths/resolve.d.ts +4 -17
- package/dist/paths/resolve.js +4 -22
- package/dist/paths/types.d.ts +12 -34
- package/dist/paths/types.js +5 -7
- package/dist/paths/validation.d.ts +22 -119
- package/dist/paths/validation.js +30 -148
- package/dist/reference-resolver.d.ts +0 -13
- package/dist/reference-resolver.js +0 -18
- package/dist/resolve-canopy-user.d.ts +16 -18
- package/dist/resolve-canopy-user.js +17 -26
- package/dist/resource-generation.d.ts +16 -25
- package/dist/resource-generation.js +34 -97
- package/dist/schema/meta-loader.d.ts +2 -14
- package/dist/schema/meta-loader.js +15 -64
- package/dist/schema/resolver.d.ts +1 -4
- package/dist/schema/resolver.js +1 -6
- package/dist/schema/schema-store-types.d.ts +0 -12
- package/dist/schema/schema-store.d.ts +61 -138
- package/dist/schema/schema-store.js +85 -282
- package/dist/schema/types.d.ts +0 -4
- package/dist/server.d.ts +62 -93
- package/dist/server.js +63 -94
- package/dist/services.d.ts +23 -47
- package/dist/services.js +55 -98
- package/dist/settings-workspace.d.ts +17 -30
- package/dist/settings-workspace.js +51 -81
- package/dist/static/index.d.ts +26 -52
- package/dist/static/index.js +33 -67
- package/dist/{worker/task-queue.d.ts → task-queue/cms-task-queue.d.ts} +7 -9
- package/dist/task-queue/cms-task-queue.js +13 -0
- package/dist/task-queue/task-queue-config.d.ts +3 -0
- package/dist/{worker → task-queue}/task-queue-config.js +1 -6
- package/dist/task-queue/task-queue.d.ts +16 -22
- package/dist/task-queue/task-queue.js +20 -44
- package/dist/task-queue/types.d.ts +0 -1
- package/dist/task-queue/worker-status.d.ts +35 -0
- package/dist/task-queue/worker-status.js +40 -0
- package/dist/types.d.ts +40 -51
- package/dist/url-collision.d.ts +26 -40
- package/dist/url-collision.js +47 -63
- package/dist/url-exclusivity-fixtures.d.ts +15 -20
- package/dist/url-exclusivity-fixtures.js +14 -19
- package/dist/url-path-resolver.d.ts +8 -16
- package/dist/url-path-resolver.js +19 -29
- package/dist/user.d.ts +8 -21
- package/dist/user.js +10 -19
- package/dist/utils/async-mutex.js +4 -6
- package/dist/utils/atomic-write.d.ts +2 -11
- package/dist/utils/atomic-write.js +2 -11
- package/dist/utils/body-field.d.ts +8 -15
- package/dist/utils/body-field.js +8 -15
- package/dist/utils/content-serialize.d.ts +18 -24
- package/dist/utils/content-serialize.js +109 -160
- package/dist/utils/content-write-lock.d.ts +51 -106
- package/dist/utils/content-write-lock.js +66 -111
- package/dist/utils/debug.d.ts +7 -23
- package/dist/utils/debug.js +7 -23
- package/dist/utils/entry-url.d.ts +11 -23
- package/dist/utils/entry-url.js +11 -26
- package/dist/utils/error.d.ts +25 -90
- package/dist/utils/error.js +60 -147
- package/dist/utils/flatten-group-fields.d.ts +5 -7
- package/dist/utils/flatten-group-fields.js +5 -7
- package/dist/utils/format.d.ts +1 -5
- package/dist/utils/format.js +1 -5
- package/dist/utils/fs.d.ts +3 -4
- package/dist/utils/fs.js +3 -4
- package/dist/utils/git.d.ts +52 -83
- package/dist/utils/git.js +79 -125
- package/dist/utils/logger.d.ts +35 -50
- package/dist/utils/logger.js +35 -52
- package/dist/utils/provisioning-lock.d.ts +23 -35
- package/dist/utils/provisioning-lock.js +49 -69
- package/dist/utils/sanitize-href.d.ts +5 -10
- package/dist/utils/sanitize-href.js +8 -18
- package/dist/utils/title-field.d.ts +17 -20
- package/dist/utils/title-field.js +18 -27
- package/dist/utils/typed-filename.d.ts +20 -48
- package/dist/utils/typed-filename.js +25 -61
- package/dist/utils/url-prefix.d.ts +3 -3
- package/dist/utils/url-prefix.js +3 -3
- package/dist/validation/block-structural-keys.d.ts +16 -31
- package/dist/validation/block-structural-keys.js +19 -29
- package/dist/validation/deletion-checker.d.ts +0 -34
- package/dist/validation/deletion-checker.js +1 -43
- package/dist/validation/entry-link-validator.d.ts +6 -13
- package/dist/validation/entry-link-validator.js +4 -13
- package/dist/validation/entry-type-reference-validator.d.ts +13 -18
- package/dist/validation/entry-type-reference-validator.js +13 -18
- package/dist/validation/entry-validator.d.ts +13 -25
- package/dist/validation/entry-validator.js +15 -32
- package/dist/validation/field-traversal.d.ts +3 -30
- package/dist/validation/field-traversal.js +1 -32
- package/dist/validation/reference-validator.d.ts +5 -24
- package/dist/validation/reference-validator.js +5 -30
- package/dist/worker/cms-worker.d.ts +172 -232
- package/dist/worker/cms-worker.js +241 -333
- package/dist/worker/git-sync.d.ts +32 -133
- package/dist/worker/git-sync.js +129 -191
- package/dist/worker/github-auth.d.ts +13 -19
- package/dist/worker/github-auth.js +13 -19
- package/dist/worker/history-rewrite.d.ts +53 -66
- package/dist/worker/history-rewrite.js +54 -60
- package/dist/worker/log.d.ts +24 -41
- package/dist/worker/log.js +25 -42
- package/dist/worker/rebase.d.ts +20 -110
- package/dist/worker/rebase.js +279 -354
- package/dist/worker/task-runner.d.ts +32 -66
- package/dist/worker/task-runner.js +126 -162
- package/dist/worker/worker-context.d.ts +41 -81
- package/package.json +4 -4
- package/dist/cli/template-files/middleware-clerk.ts.template +0 -37
- package/dist/worker/task-queue-config.d.ts +0 -8
- package/dist/worker/task-queue.js +0 -19
- package/dist/worker/worker-status.d.ts +0 -47
- package/dist/worker/worker-status.js +0 -52
|
@@ -26,17 +26,11 @@ const entryTypeMetaSchema = z.object({
|
|
|
26
26
|
maxItems: z.number().int().positive().optional(),
|
|
27
27
|
});
|
|
28
28
|
/**
|
|
29
|
-
* Zod schema for .collection.json files
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* Note: We can't validate `schema` against entry schema registry keys at parse time because:
|
|
36
|
-
* 1. Entry schema registry is passed at runtime (not available during Zod schema definition)
|
|
37
|
-
* 2. Would create circular dependency (loader → services → config → loader)
|
|
38
|
-
*
|
|
39
|
-
* Validation of schema references happens in resolution functions with clear error messages.
|
|
29
|
+
* Zod schema for .collection.json files. `schema` can't be validated against
|
|
30
|
+
* the entry schema registry here — the registry is only available at
|
|
31
|
+
* runtime, and checking at parse time would create a loader → services →
|
|
32
|
+
* config → loader circular dependency — so schema references are checked in
|
|
33
|
+
* the resolution functions instead, with clear error messages.
|
|
40
34
|
*/
|
|
41
35
|
const collectionMetaSchema = z
|
|
42
36
|
.object({
|
|
@@ -58,31 +52,21 @@ const rootCollectionMetaSchema = z.object({
|
|
|
58
52
|
entries: z.array(entryTypeMetaSchema).optional(),
|
|
59
53
|
order: z.array(z.string()).optional(), // Embedded IDs for ordering items
|
|
60
54
|
});
|
|
55
|
+
/** Extracts the slug only — e.g. "post.hello-world.{id}.md" -> "hello-world" (the entry-type prefix and extension are dropped too, not just the ID). */
|
|
56
|
+
function stripEmbeddedIdFromName(name) {
|
|
57
|
+
return extractSlugFromFilename(name);
|
|
58
|
+
}
|
|
61
59
|
/**
|
|
62
|
-
* Recursively scans a directory for .collection.json files.
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* - Collection path is derived from the directory structure (e.g., "docs/api" for content/docs/api/)
|
|
68
|
-
* - Collection name comes from the "name" field in .collection.json, NOT the directory name
|
|
69
|
-
* - Directories without .collection.json are still scanned for nested collections
|
|
70
|
-
* - Invalid .collection.json files cause the entire scan to fail with a descriptive error
|
|
60
|
+
* Recursively scans a directory for .collection.json files. Each directory
|
|
61
|
+
* has at most one; a directory without one is still scanned for nested
|
|
62
|
+
* collections beneath it. A collection's name comes from `.collection.json`'s
|
|
63
|
+
* "name" field, not the directory name. An invalid file fails the whole scan
|
|
64
|
+
* with a descriptive error.
|
|
71
65
|
*
|
|
72
66
|
* @param baseDir - The directory to scan (absolute path)
|
|
73
67
|
* @param relativePath - Current path relative to content root (used for recursion)
|
|
74
68
|
* @returns Array of collection metadata with resolved paths
|
|
75
69
|
*/
|
|
76
|
-
/**
|
|
77
|
-
* Strip embedded ID from a directory or file name, leaving the slug.
|
|
78
|
-
* e.g., "docs.bChqT78gcaLd" -> "docs"
|
|
79
|
-
* e.g., "post.hello-world.vh2WdhwAFiSL.md" -> "hello-world" (the SLUG, not the entry type)
|
|
80
|
-
* e.g., "home.index.agfzDt2RLpSn.json" -> "index"
|
|
81
|
-
*/
|
|
82
|
-
function stripEmbeddedIdFromName(name) {
|
|
83
|
-
// Use extractSlugFromFilename which handles the ID extraction logic
|
|
84
|
-
return extractSlugFromFilename(name);
|
|
85
|
-
}
|
|
86
70
|
async function scanForCollectionMeta(baseDir, relativePath = '') {
|
|
87
71
|
const collections = [];
|
|
88
72
|
try {
|
|
@@ -91,27 +75,22 @@ async function scanForCollectionMeta(baseDir, relativePath = '') {
|
|
|
91
75
|
if (!entry.isDirectory())
|
|
92
76
|
continue;
|
|
93
77
|
const folderName = entry.name;
|
|
94
|
-
// Strip embedded ID from folder name for logical path
|
|
95
|
-
// e.g., "docs.bChqT78gcaLd" -> "docs"
|
|
96
78
|
const logicalName = stripEmbeddedIdFromName(folderName);
|
|
97
79
|
// Extract embedded ContentId from directory name (e.g., "posts.a1b2c3d4e5f6" → "a1b2c3d4e5f6")
|
|
98
80
|
const collectionContentId = extractIdFromFilename(folderName) ?? undefined;
|
|
99
81
|
const folderPath = relativePath ? `${relativePath}/${logicalName}` : logicalName;
|
|
100
82
|
const absolutePath = join(baseDir, folderName);
|
|
101
83
|
const metaPath = join(absolutePath, '.collection.json');
|
|
102
|
-
// Try to load collection meta file
|
|
103
84
|
try {
|
|
104
85
|
await fs.access(metaPath);
|
|
105
86
|
const content = await fs.readFile(metaPath, 'utf-8');
|
|
106
87
|
const parsed = JSON.parse(content);
|
|
107
|
-
// Validate with Zod
|
|
108
88
|
const meta = collectionMetaSchema.parse(parsed);
|
|
109
89
|
collections.push({
|
|
110
90
|
...meta,
|
|
111
|
-
path: folderPath,
|
|
91
|
+
path: folderPath,
|
|
112
92
|
contentId: collectionContentId,
|
|
113
93
|
});
|
|
114
|
-
// Recursively scan for nested collection folders (they'll have their own .collection.json files)
|
|
115
94
|
const nestedCollections = await scanForCollectionMeta(absolutePath, folderPath);
|
|
116
95
|
collections.push(...nestedCollections);
|
|
117
96
|
}
|
|
@@ -138,11 +117,6 @@ async function scanForCollectionMeta(baseDir, relativePath = '') {
|
|
|
138
117
|
/**
|
|
139
118
|
* Loads all .collection.json meta files from contentRoot, including root.
|
|
140
119
|
*
|
|
141
|
-
* This function orchestrates the complete discovery process:
|
|
142
|
-
* 1. Attempts to load the root .collection.json (contentRoot/.collection.json) - optional
|
|
143
|
-
* 2. Recursively scans all subdirectories for .collection.json files
|
|
144
|
-
* 3. Returns both root configuration and nested collections
|
|
145
|
-
*
|
|
146
120
|
* Meta File Structure:
|
|
147
121
|
* - Root: contentRoot/.collection.json (optional, defines root-level entry types)
|
|
148
122
|
* - Collections: contentRoot/[path]/.collection.json (defines collection in that directory)
|
|
@@ -152,14 +126,12 @@ async function scanForCollectionMeta(baseDir, relativePath = '') {
|
|
|
152
126
|
* @throws Error if any .collection.json file is malformed or invalid
|
|
153
127
|
*/
|
|
154
128
|
export async function loadCollectionMetaFiles(contentRoot) {
|
|
155
|
-
// Load root .collection.json (optional)
|
|
156
129
|
let root = null;
|
|
157
130
|
const rootMetaPath = join(contentRoot, '.collection.json');
|
|
158
131
|
try {
|
|
159
132
|
await fs.access(rootMetaPath);
|
|
160
133
|
}
|
|
161
134
|
catch (err) {
|
|
162
|
-
// No root .collection.json - that's okay
|
|
163
135
|
if (err.code === 'ENOENT') {
|
|
164
136
|
// File doesn't exist, that's fine
|
|
165
137
|
}
|
|
@@ -167,7 +139,6 @@ export async function loadCollectionMetaFiles(contentRoot) {
|
|
|
167
139
|
throw err;
|
|
168
140
|
}
|
|
169
141
|
}
|
|
170
|
-
// If file exists, try to read and parse it
|
|
171
142
|
try {
|
|
172
143
|
const content = await fs.readFile(rootMetaPath, 'utf-8');
|
|
173
144
|
const parsed = JSON.parse(content);
|
|
@@ -180,13 +151,9 @@ export async function loadCollectionMetaFiles(contentRoot) {
|
|
|
180
151
|
throw new Error(`Invalid root .collection.json`);
|
|
181
152
|
}
|
|
182
153
|
}
|
|
183
|
-
// Scan for collection folders
|
|
184
154
|
const collections = await scanForCollectionMeta(contentRoot);
|
|
185
155
|
return { root, collections };
|
|
186
156
|
}
|
|
187
|
-
/**
|
|
188
|
-
* Resolve schema references for entry types
|
|
189
|
-
*/
|
|
190
157
|
function resolveEntryTypes(entryTypes, entrySchemaRegistry, contextName) {
|
|
191
158
|
return entryTypes.map((entryType) => {
|
|
192
159
|
const resolvedSchema = entrySchemaRegistry[entryType.schema];
|
|
@@ -208,11 +175,7 @@ function resolveEntryTypes(entryTypes, entrySchemaRegistry, contextName) {
|
|
|
208
175
|
};
|
|
209
176
|
});
|
|
210
177
|
}
|
|
211
|
-
/**
|
|
212
|
-
* Resolve schema references for a single collection
|
|
213
|
-
*/
|
|
214
178
|
function resolveCollectionMeta(meta, entrySchemaRegistry, allCollections) {
|
|
215
|
-
// Resolve entry types
|
|
216
179
|
const entries = meta.entries && meta.entries.length > 0
|
|
217
180
|
? resolveEntryTypes(meta.entries, entrySchemaRegistry, `collection "${meta.name}"`)
|
|
218
181
|
: undefined;
|
|
@@ -240,11 +203,6 @@ function resolveCollectionMeta(meta, entrySchemaRegistry, allCollections) {
|
|
|
240
203
|
* This function takes the loaded meta files (which contain string references like "postSchema")
|
|
241
204
|
* and resolves them to actual EntrySchema arrays from the entry schema registry.
|
|
242
205
|
*
|
|
243
|
-
* Resolution Process:
|
|
244
|
-
* 1. Root entry types: Resolve "schema" string to entry schema registry lookup
|
|
245
|
-
* 2. Top-level collections: Resolve recursively, building nested tree structure
|
|
246
|
-
* 3. Nested collections: Automatically grouped under their parent collections
|
|
247
|
-
*
|
|
248
206
|
* @param metaFiles - Loaded meta files from loadCollectionMetaFiles()
|
|
249
207
|
* @param entrySchemaRegistry - Map of schema names to EntrySchema arrays
|
|
250
208
|
* @returns Fully resolved root collection config ready for use by CanopyCMS
|
|
@@ -253,15 +211,12 @@ function resolveCollectionMeta(meta, entrySchemaRegistry, allCollections) {
|
|
|
253
211
|
export function resolveCollectionReferences(metaFiles, entrySchemaRegistry) {
|
|
254
212
|
// Build result object dynamically to avoid readonly conflicts
|
|
255
213
|
const result = {};
|
|
256
|
-
// Pass through root label if present
|
|
257
214
|
if (metaFiles.root?.label) {
|
|
258
215
|
result.label = metaFiles.root.label;
|
|
259
216
|
}
|
|
260
|
-
// Resolve root entry types
|
|
261
217
|
if (metaFiles.root?.entries && metaFiles.root.entries.length > 0) {
|
|
262
218
|
result.entries = resolveEntryTypes(metaFiles.root.entries, entrySchemaRegistry, 'root collection');
|
|
263
219
|
}
|
|
264
|
-
// Pass through root order array (embedded IDs for sorting)
|
|
265
220
|
if (metaFiles.root?.order) {
|
|
266
221
|
result.order = metaFiles.root.order;
|
|
267
222
|
}
|
|
@@ -272,9 +227,6 @@ export function resolveCollectionReferences(metaFiles, entrySchemaRegistry) {
|
|
|
272
227
|
}
|
|
273
228
|
return result;
|
|
274
229
|
}
|
|
275
|
-
/**
|
|
276
|
-
* Watch for changes to .collection.json files
|
|
277
|
-
*/
|
|
278
230
|
export function watchCollectionMetaFiles(contentRoot, onChange) {
|
|
279
231
|
const watcher = chokidar.watch(`${contentRoot}/**/.collection.json`, {
|
|
280
232
|
ignoreInitial: true,
|
|
@@ -284,6 +236,5 @@ export function watchCollectionMetaFiles(contentRoot, onChange) {
|
|
|
284
236
|
watcher.on('unlink', onChange);
|
|
285
237
|
// Handle watcher errors (e.g. inotify ENOSPC/EMFILE) so an unhandled 'error' event can't crash dev.
|
|
286
238
|
watcher.on('error', (err) => canopyLogWarn(`CanopyCMS: .collection.json watcher error: ${getErrorMessage(err)}`));
|
|
287
|
-
// Return cleanup function
|
|
288
239
|
return () => watcher.close();
|
|
289
240
|
}
|
|
@@ -12,10 +12,6 @@ import type { EntrySchemaRegistry, SchemaResolutionResult } from './types.js';
|
|
|
12
12
|
/**
|
|
13
13
|
* Resolve schema from .collection.json files.
|
|
14
14
|
*
|
|
15
|
-
* This is the primary entry point for loading schema configuration.
|
|
16
|
-
* It discovers all .collection.json files in the content directory
|
|
17
|
-
* and resolves schema references using the provided registry.
|
|
18
|
-
*
|
|
19
15
|
* @param contentRoot - Path to the content directory
|
|
20
16
|
* @param entrySchemaRegistry - Map of entry schema names to field definitions
|
|
21
17
|
* @returns Resolved schema configuration
|
|
@@ -27,6 +23,7 @@ export declare function resolveSchema(contentRoot: string, entrySchemaRegistry:
|
|
|
27
23
|
*
|
|
28
24
|
* @param contentRoot - Path to the content directory
|
|
29
25
|
* @returns true if at least one .collection.json file exists
|
|
26
|
+
* @internal No importer; deletion candidate in knip-no-importer-deletion-candidates.md.
|
|
30
27
|
*/
|
|
31
28
|
export declare function hasSchemaFiles(contentRoot: string): Promise<boolean>;
|
|
32
29
|
/**
|
package/dist/schema/resolver.js
CHANGED
|
@@ -11,17 +11,12 @@ import { loadCollectionMetaFiles, resolveCollectionReferences } from './meta-loa
|
|
|
11
11
|
/**
|
|
12
12
|
* Resolve schema from .collection.json files.
|
|
13
13
|
*
|
|
14
|
-
* This is the primary entry point for loading schema configuration.
|
|
15
|
-
* It discovers all .collection.json files in the content directory
|
|
16
|
-
* and resolves schema references using the provided registry.
|
|
17
|
-
*
|
|
18
14
|
* @param contentRoot - Path to the content directory
|
|
19
15
|
* @param entrySchemaRegistry - Map of entry schema names to field definitions
|
|
20
16
|
* @returns Resolved schema configuration
|
|
21
17
|
* @throws Error if schema references cannot be resolved
|
|
22
18
|
*/
|
|
23
19
|
export async function resolveSchema(contentRoot, entrySchemaRegistry) {
|
|
24
|
-
// Load all .collection.json meta files
|
|
25
20
|
const metaFiles = await loadCollectionMetaFiles(contentRoot);
|
|
26
21
|
// Build source info for debugging
|
|
27
22
|
const sources = [];
|
|
@@ -39,7 +34,6 @@ export async function resolveSchema(contentRoot, entrySchemaRegistry) {
|
|
|
39
34
|
collections: [collection.name],
|
|
40
35
|
});
|
|
41
36
|
}
|
|
42
|
-
// Resolve schema references to actual field definitions
|
|
43
37
|
const schema = resolveCollectionReferences(metaFiles, entrySchemaRegistry);
|
|
44
38
|
return { schema, sources };
|
|
45
39
|
}
|
|
@@ -48,6 +42,7 @@ export async function resolveSchema(contentRoot, entrySchemaRegistry) {
|
|
|
48
42
|
*
|
|
49
43
|
* @param contentRoot - Path to the content directory
|
|
50
44
|
* @returns true if at least one .collection.json file exists
|
|
45
|
+
* @internal No importer; deletion candidate in knip-no-importer-deletion-candidates.md.
|
|
51
46
|
*/
|
|
52
47
|
export async function hasSchemaFiles(contentRoot) {
|
|
53
48
|
const metaFiles = await loadCollectionMetaFiles(contentRoot);
|
|
@@ -6,18 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { ContentFormat } from '../config/index.js';
|
|
8
8
|
import type { LogicalPath } from '../paths/types.js';
|
|
9
|
-
/**
|
|
10
|
-
* Input for creating a new collection
|
|
11
|
-
*/
|
|
12
9
|
export interface CreateCollectionInput {
|
|
13
10
|
name: string;
|
|
14
11
|
label?: string;
|
|
15
12
|
parentPath?: LogicalPath;
|
|
16
13
|
entries: CreateEntryTypeInput[];
|
|
17
14
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Input for creating a new entry type
|
|
20
|
-
*/
|
|
21
15
|
export interface CreateEntryTypeInput {
|
|
22
16
|
name: string;
|
|
23
17
|
label?: string;
|
|
@@ -26,18 +20,12 @@ export interface CreateEntryTypeInput {
|
|
|
26
20
|
default?: boolean;
|
|
27
21
|
maxItems?: number;
|
|
28
22
|
}
|
|
29
|
-
/**
|
|
30
|
-
* Input for updating a collection
|
|
31
|
-
*/
|
|
32
23
|
export interface UpdateCollectionInput {
|
|
33
24
|
name?: string;
|
|
34
25
|
label?: string;
|
|
35
26
|
slug?: string;
|
|
36
27
|
order?: string[];
|
|
37
28
|
}
|
|
38
|
-
/**
|
|
39
|
-
* Input for updating an entry type
|
|
40
|
-
*/
|
|
41
29
|
export interface UpdateEntryTypeInput {
|
|
42
30
|
label?: string;
|
|
43
31
|
format?: ContentFormat;
|
|
@@ -1,47 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Schema Store - handles reading and writing .collection.json files.
|
|
3
|
-
*
|
|
4
|
-
* This module provides CRUD operations for collection schema metadata:
|
|
5
|
-
* - Create/update/delete collections
|
|
6
|
-
* - Add/update/remove entry types
|
|
7
|
-
* - Update ordering of items within collections
|
|
8
|
-
*
|
|
9
3
|
* All mutations are branch-specific (like content edits).
|
|
10
4
|
*
|
|
11
5
|
* ## Concurrency
|
|
12
6
|
*
|
|
13
|
-
* `.collection.json` is read-modify-written by every mutator below
|
|
14
|
-
* mutated cross-host
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
7
|
+
* `.collection.json` is read-modify-written by every mutator below and
|
|
8
|
+
* mutated cross-host — two warm Lambdas, or a Lambda + the EC2 worker, on
|
|
9
|
+
* EFS can both read the same pre-mutation file and clobber each other's
|
|
10
|
+
* write. This deviates from the standard 3-layer recipe in
|
|
11
|
+
* docs/concurrency.md: no OCC `version`/`writeId` field goes into
|
|
12
|
+
* `.collection.json` itself, and no lockfile lives in the content tree —
|
|
13
|
+
* both are adopter-visible, git-committed files, so a rebase would make a
|
|
14
|
+
* version counter meaningless and a crash-leftover lockfile would land in a
|
|
15
|
+
* commit an adopter reviews.
|
|
20
16
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
17
|
+
* Protection is instead layer 1 ({@link withLock}) + layer 3
|
|
18
|
+
* ({@link withOccFileLock}) on one COARSE per-branch SURROGATE lock path
|
|
19
|
+
* OUTSIDE the content tree (`{branchRoot}/.canopy-meta/schema`, see
|
|
20
|
+
* `withSchemaLock`), covering every schema mutation on the branch including
|
|
21
|
+
* multi-file ones. Layer 2 (OCC read-back) is skipped, since there's no
|
|
22
|
+
* version field to check; layer 4 (generation marker) guards the schema
|
|
23
|
+
* CACHE separately, not this write path.
|
|
27
24
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* meta AND the parent's). Layer 2 (OCC read-back) is skipped entirely since
|
|
34
|
-
* there is no version field to check; layer 4 (generation marker) is used
|
|
35
|
-
* separately, for the schema CACHE, not for this write path.
|
|
36
|
-
*
|
|
37
|
-
* Accepted residual: `deleteBranch` does NOT take this lock before its
|
|
38
|
-
* recursive `rm` — an in-flight schema write can race a concurrent branch
|
|
39
|
-
* deletion (the write's `rm`/rename can hit ENOTEMPTY or land in a
|
|
40
|
-
* half-deleted tree). This mirrors the same residual documented on
|
|
41
|
-
* `BranchMetadataFileManager.save()` in branch-metadata.ts and is not closed
|
|
42
|
-
* here either; see `withSchemaLock`'s doc comment for the phantom-guard that
|
|
43
|
-
* IS in place for the common ordering (branch already gone before this call
|
|
44
|
-
* ever starts).
|
|
25
|
+
* Accepted residual: `deleteBranch` does not take this lock before its
|
|
26
|
+
* recursive `rm`, so an in-flight write can race a concurrent branch
|
|
27
|
+
* deletion (mirrors the residual on `BranchMetadataFileManager.save()` in
|
|
28
|
+
* branch-metadata.ts) — see `withSchemaLock`'s doc for the phantom-guard
|
|
29
|
+
* covering the common ordering instead.
|
|
45
30
|
*/
|
|
46
31
|
import { z } from 'zod';
|
|
47
32
|
import type { ContentFormat } from '../config/index.js';
|
|
@@ -219,43 +204,35 @@ export declare class SchemaOps {
|
|
|
219
204
|
constructor(contentRoot: string, entrySchemaRegistry: EntrySchemaRegistry, services?: CanopyServices | undefined, branchRoot?: string);
|
|
220
205
|
/**
|
|
221
206
|
* Serialize an entire read-modify-write schema mutation behind the coarse
|
|
222
|
-
* per-branch surrogate lock described in the module doc comment
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* serialization.
|
|
228
|
-
* 2. {@link withOccFileLock} — server-enforced, cross-process/cross-host
|
|
229
|
-
* mutual exclusion (proper-lockfile, mkdir-based), immune to NFS client
|
|
230
|
-
* dentry/attribute caching.
|
|
207
|
+
* per-branch surrogate lock described in the module doc comment: layer 1
|
|
208
|
+
* ({@link withLock}, in-process FIFO mutex) wraps layer 3
|
|
209
|
+
* ({@link withOccFileLock}, cross-process/cross-host mkdir-based mutual
|
|
210
|
+
* exclusion, immune to NFS attribute caching), same structure as
|
|
211
|
+
* `BranchMetadataFileManager.save()` in branch-metadata.ts.
|
|
231
212
|
*
|
|
232
|
-
* NOT re-entrant
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
213
|
+
* NOT re-entrant — callers must never invoke this from inside a callback
|
|
214
|
+
* already running under it, or `withLock` deadlocks waiting on itself;
|
|
215
|
+
* that's why `updateOrderInner` calls `updateCollectionInner` directly
|
|
216
|
+
* instead of the public `updateCollection`.
|
|
236
217
|
*
|
|
237
218
|
* Phantom-resurrection guard: `branchRoot` can be removed by a concurrent
|
|
238
219
|
* `deleteBranch` between the caller resolving its BranchContext and this
|
|
239
|
-
* call
|
|
240
|
-
* `mkdir({recursive:true})`
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* that passes this check can still race a `deleteBranch` `rm` that starts
|
|
247
|
-
* moments later and is still mid-flight when this call's write lands,
|
|
248
|
-
* resurrecting the tree. `deleteBranch` does not take this lock at all
|
|
249
|
-
* (see the module doc comment), so that race is not closed here either.
|
|
220
|
+
* call's own lock acquisition, which would otherwise let
|
|
221
|
+
* `withOccFileLock`'s `mkdir({recursive:true})` silently recreate
|
|
222
|
+
* `.canopy-meta/` in an otherwise-deleted tree. Checking BEFORE the lock
|
|
223
|
+
* fails fast instead. Residual (accepted, same shape as
|
|
224
|
+
* branch-metadata.ts's): a call that passes this check can still race a
|
|
225
|
+
* `deleteBranch` `rm` starting moments later — not closed here either,
|
|
226
|
+
* since `deleteBranch` never takes this lock (see the module doc comment).
|
|
250
227
|
*
|
|
251
228
|
* Translation happens ONLY at this boundary: inner code always sees the
|
|
252
|
-
* raw {@link OccWriteConflictError} bubble up
|
|
253
|
-
* re-translates it itself).
|
|
229
|
+
* raw {@link OccWriteConflictError} bubble up here untranslated.
|
|
254
230
|
*/
|
|
255
231
|
private withSchemaLock;
|
|
256
232
|
/**
|
|
257
233
|
* Invalidate schema cache for this branch after mutations, then eagerly
|
|
258
|
-
* re-resolve on THIS host.
|
|
234
|
+
* re-resolve on THIS host. Every mutator calls this after `withSchemaLock`
|
|
235
|
+
* has returned, never inside the critical section.
|
|
259
236
|
*
|
|
260
237
|
* The eager re-resolve is the durable-snapshot window-E mitigation (see
|
|
261
238
|
* BranchSchemaCache's class docs): the mutating host's own scan is
|
|
@@ -296,92 +273,50 @@ export declare class SchemaOps {
|
|
|
296
273
|
private invalidateContentIdIndexes;
|
|
297
274
|
/**
|
|
298
275
|
* The single normalisation boundary for logical collection paths entering
|
|
299
|
-
* this class. Every public method that accepts
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
* (`CollectionEditor.tsx` passes `editingCollection.logicalPath` as-is),
|
|
307
|
-
* but `resolveCollectionPath(this.contentRoot, ...)` treats its second
|
|
308
|
-
* argument as relative to `this.contentRoot` — which already embeds the
|
|
309
|
-
* content-root segment(s). A prefixed path therefore resolved one level
|
|
310
|
-
* too deep and was reported as not found. `updateCollectionInner` used to
|
|
311
|
-
* strip the prefix itself (the only mutator that did); that bespoke strip
|
|
312
|
-
* is gone now that every entry point normalises here instead.
|
|
276
|
+
* this class. Every public method that accepts one calls this exactly
|
|
277
|
+
* once, before touching the path: `flattenSchema` (branch-schema-cache.ts)
|
|
278
|
+
* produces content-root-prefixed logical paths (e.g. "content/posts") that
|
|
279
|
+
* the editor round-trips straight back into every mutator, but
|
|
280
|
+
* `resolveCollectionPath` treats its path argument as already relative to
|
|
281
|
+
* `this.contentRoot` — without stripping, a prefixed path resolves one
|
|
282
|
+
* level too deep and is reported as not found.
|
|
313
283
|
*
|
|
314
|
-
*
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
* no trailing segment): that has no trailing "/" to match, so it passes
|
|
322
|
-
* through unchanged and the `=== this.contentRootName` checks in
|
|
284
|
+
* Strips ONE leading `"{contentRootName}/"` if present — exact string
|
|
285
|
+
* match against the full, possibly multi-segment, `contentRootName`, never
|
|
286
|
+
* `path.basename()` (which would break a root like "cms/content") —
|
|
287
|
+
* otherwise returns the path unchanged, so both prefixed and unprefixed
|
|
288
|
+
* callers work. Leaves the bare root-collection sentinel
|
|
289
|
+
* (`collectionPath === this.contentRootName`) untouched: it has no
|
|
290
|
+
* trailing "/" to strip, so the `=== this.contentRootName` checks in
|
|
323
291
|
* `updateCollectionInner`/`updateOrderInner` keep working.
|
|
324
292
|
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
* collection — so a second call mutates a DIFFERENT collection rather than
|
|
332
|
-
* reporting not-found. Every entry point calls this exactly once today, so
|
|
333
|
-
* the ambiguity is unreachable; removing it needs the editor to send an
|
|
334
|
-
* unambiguously-scoped path, tracked in
|
|
335
|
-
* .claude/future-tasks/collection-path-content-root-ambiguity.md.
|
|
336
|
-
*
|
|
337
|
-
* A future public method that accepts a logical collection path must call
|
|
338
|
-
* this first, and only once, the same way every existing one does — that is
|
|
339
|
-
* the "safe by construction" contract this boundary is meant to provide.
|
|
293
|
+
* NOT idempotent — a sub-collection literally named after the content
|
|
294
|
+
* root can re-normalise to the ROOT collection on a second call, mutating
|
|
295
|
+
* the wrong one instead of reporting not-found. Every entry point calls
|
|
296
|
+
* this exactly once today, so the ambiguity is unreachable; see
|
|
297
|
+
* .claude/future-tasks/collection-path-content-root-ambiguity.md. A future
|
|
298
|
+
* method that accepts a logical collection path must do the same.
|
|
340
299
|
*/
|
|
341
300
|
private normalizeCollectionPath;
|
|
342
|
-
/**
|
|
343
|
-
* Validate that a schema reference exists in the registry
|
|
344
|
-
*/
|
|
345
301
|
validateSchemaReference(schemaKey: string): boolean;
|
|
346
|
-
/**
|
|
347
|
-
* Validate all schema references in entry types
|
|
348
|
-
*/
|
|
349
302
|
private validateEntryTypeSchemas;
|
|
350
303
|
/**
|
|
351
304
|
* Validate path to prevent traversal attacks
|
|
352
305
|
*/
|
|
353
306
|
private validatePath;
|
|
354
|
-
/**
|
|
355
|
-
* Read a collection's .collection.json file
|
|
356
|
-
*/
|
|
357
307
|
readCollectionMeta(collectionPath: LogicalPath): Promise<CollectionMetaFile | null>;
|
|
358
|
-
/**
|
|
359
|
-
* Read root collection meta (content/.collection.json)
|
|
360
|
-
*/
|
|
361
308
|
readRootCollectionMeta(): Promise<RootCollectionMetaFile | null>;
|
|
362
309
|
/**
|
|
363
310
|
* Check if a collection is empty (has no content files or child collections)
|
|
364
311
|
*/
|
|
365
312
|
isCollectionEmpty(collectionPath: LogicalPath): Promise<boolean>;
|
|
366
|
-
/**
|
|
367
|
-
* Write a collection's .collection.json file
|
|
368
|
-
*/
|
|
369
313
|
private writeCollectionMeta;
|
|
370
|
-
/**
|
|
371
|
-
* Write root collection meta
|
|
372
|
-
*/
|
|
373
314
|
private writeRootCollectionMeta;
|
|
374
|
-
/**
|
|
375
|
-
* Create a new collection
|
|
376
|
-
*/
|
|
377
315
|
createCollection(input: CreateCollectionInput): Promise<{
|
|
378
316
|
collectionPath: LogicalPath;
|
|
379
317
|
contentId: ContentId;
|
|
380
318
|
}>;
|
|
381
319
|
private createCollectionInner;
|
|
382
|
-
/**
|
|
383
|
-
* Update a collection's metadata
|
|
384
|
-
*/
|
|
385
320
|
updateCollection(collectionPath: LogicalPath, updates: UpdateCollectionInput): Promise<void>;
|
|
386
321
|
/**
|
|
387
322
|
* Body of updateCollection, holding the schema lock for its full
|
|
@@ -401,24 +336,15 @@ export declare class SchemaOps {
|
|
|
401
336
|
*/
|
|
402
337
|
deleteCollection(collectionPath: LogicalPath): Promise<void>;
|
|
403
338
|
private deleteCollectionInner;
|
|
404
|
-
/**
|
|
405
|
-
* Add an entry type to a collection
|
|
406
|
-
*/
|
|
407
339
|
addEntryType(collectionPath: LogicalPath, entryType: CreateEntryTypeInput): Promise<void>;
|
|
408
340
|
private addEntryTypeInner;
|
|
409
|
-
/**
|
|
410
|
-
* Update an entry type in a collection
|
|
411
|
-
*/
|
|
412
341
|
updateEntryType(collectionPath: LogicalPath, entryTypeName: string, updates: UpdateEntryTypeInput): Promise<void>;
|
|
413
342
|
private updateEntryTypeInner;
|
|
414
|
-
/**
|
|
415
|
-
* Remove an entry type from a collection
|
|
416
|
-
*/
|
|
417
343
|
removeEntryType(collectionPath: LogicalPath, entryTypeName: string): Promise<void>;
|
|
418
344
|
private removeEntryTypeInner;
|
|
419
345
|
/**
|
|
420
346
|
* Count the number of entries using a specific entry type in a collection.
|
|
421
|
-
*
|
|
347
|
+
* Prevents breaking changes to entry types that have existing content.
|
|
422
348
|
*
|
|
423
349
|
* @param collectionPath - Logical path to the collection (e.g., "content/posts")
|
|
424
350
|
* @param entryTypeName - Name of the entry type to count
|
|
@@ -433,9 +359,6 @@ export declare class SchemaOps {
|
|
|
433
359
|
* ```
|
|
434
360
|
*/
|
|
435
361
|
countEntriesUsingType(collectionPath: LogicalPath, entryTypeName: string): Promise<number>;
|
|
436
|
-
/**
|
|
437
|
-
* Update the order of items in a collection
|
|
438
|
-
*/
|
|
439
362
|
updateOrder(collectionPath: LogicalPath, order: string[]): Promise<void>;
|
|
440
363
|
private updateOrderInner;
|
|
441
364
|
}
|