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
|
@@ -2,9 +2,6 @@ import type { OperatingMode } from '../../operating-mode/index.js';
|
|
|
2
2
|
import type { BranchStatus } from '../../types.js';
|
|
3
3
|
import type { EditorEntry } from '../Editor.js';
|
|
4
4
|
import type { LogicalPath } from '../../paths/types.js';
|
|
5
|
-
/**
|
|
6
|
-
* Props for the EditorHeader component.
|
|
7
|
-
*/
|
|
8
5
|
export interface EditorHeaderProps {
|
|
9
6
|
/**
|
|
10
7
|
* Site title displayed in the top-left.
|
|
@@ -150,33 +147,5 @@ export interface EditorHeaderProps {
|
|
|
150
147
|
/**
|
|
151
148
|
* Header component for the Editor.
|
|
152
149
|
* Contains site info, file navigation, breadcrumbs, branch selector, comments button, and action buttons.
|
|
153
|
-
*
|
|
154
|
-
* @example
|
|
155
|
-
* ```tsx
|
|
156
|
-
* <EditorHeader
|
|
157
|
-
* siteTitle="My Site"
|
|
158
|
-
* siteSubtitle="CMS"
|
|
159
|
-
* headerTitle="Edit Content"
|
|
160
|
-
* currentEntry={currentEntry}
|
|
161
|
-
* branchName="main"
|
|
162
|
-
* operatingMode="collaboration"
|
|
163
|
-
* busy={false}
|
|
164
|
-
* breadcrumbSegments={['Posts', 'My Post']}
|
|
165
|
-
* editedFiles={[]}
|
|
166
|
-
* modifiedCount={0}
|
|
167
|
-
* unresolvedCommentCount={0}
|
|
168
|
-
* comments={[]}
|
|
169
|
-
* onNavigatorOpen={() => setNavigatorOpen(true)}
|
|
170
|
-
* onFileReload={handleReload}
|
|
171
|
-
* onFileDiscardDraft={handleDiscardFileDraft}
|
|
172
|
-
* onEntrySelect={setSelectedId}
|
|
173
|
-
* onBranchReloadData={handleReloadBranchData}
|
|
174
|
-
* onBranchDiscardDrafts={handleDiscardDrafts}
|
|
175
|
-
* onBranchManagerOpen={() => setBranchManagerOpen(true)}
|
|
176
|
-
* onCommentsPanelOpen={() => setCommentsPanelOpen(true)}
|
|
177
|
-
* onSave={handleSave}
|
|
178
|
-
* onSubmit={() => handleSubmit(branchName)}
|
|
179
|
-
* />
|
|
180
|
-
* ```
|
|
181
150
|
*/
|
|
182
151
|
export declare const EditorHeader: import("react").ForwardRefExoticComponent<EditorHeaderProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -20,60 +20,20 @@ const getStatusColor = (status) => {
|
|
|
20
20
|
/**
|
|
21
21
|
* Header component for the Editor.
|
|
22
22
|
* Contains site info, file navigation, breadcrumbs, branch selector, comments button, and action buttons.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* ```tsx
|
|
26
|
-
* <EditorHeader
|
|
27
|
-
* siteTitle="My Site"
|
|
28
|
-
* siteSubtitle="CMS"
|
|
29
|
-
* headerTitle="Edit Content"
|
|
30
|
-
* currentEntry={currentEntry}
|
|
31
|
-
* branchName="main"
|
|
32
|
-
* operatingMode="collaboration"
|
|
33
|
-
* busy={false}
|
|
34
|
-
* breadcrumbSegments={['Posts', 'My Post']}
|
|
35
|
-
* editedFiles={[]}
|
|
36
|
-
* modifiedCount={0}
|
|
37
|
-
* unresolvedCommentCount={0}
|
|
38
|
-
* comments={[]}
|
|
39
|
-
* onNavigatorOpen={() => setNavigatorOpen(true)}
|
|
40
|
-
* onFileReload={handleReload}
|
|
41
|
-
* onFileDiscardDraft={handleDiscardFileDraft}
|
|
42
|
-
* onEntrySelect={setSelectedId}
|
|
43
|
-
* onBranchReloadData={handleReloadBranchData}
|
|
44
|
-
* onBranchDiscardDrafts={handleDiscardDrafts}
|
|
45
|
-
* onBranchManagerOpen={() => setBranchManagerOpen(true)}
|
|
46
|
-
* onCommentsPanelOpen={() => setCommentsPanelOpen(true)}
|
|
47
|
-
* onSave={handleSave}
|
|
48
|
-
* onSubmit={() => handleSubmit(branchName)}
|
|
49
|
-
* />
|
|
50
|
-
* ```
|
|
51
23
|
*/
|
|
52
24
|
export const EditorHeader = forwardRef(function EditorHeader({ siteTitle, siteSubtitle, headerTitle, currentEntry, branchName, operatingMode, busy, breadcrumbSegments, editedFiles, modifiedCount, unresolvedCommentCount: _, comments, onNavigatorOpen, onFileReload, onFileDiscardDraft, onEntrySelect, onBranchReloadData, onBranchDiscardDrafts, onBranchManagerOpen, onCommentsPanelOpen, onSave, onSubmit, hasUnsavedChanges, branchStatus, onWithdraw, userContext, branchCreatedBy, branchAccess, branchIsProtected = false, branchReadOnly = false, branchWriteBlocked = false, }, ref) {
|
|
53
|
-
// `branchWriteBlocked` is the server's own answer (getBranchProtection,
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
25
|
+
// `branchWriteBlocked` is the server's own answer (getBranchProtection), so
|
|
26
|
+
// Save is never enabled for a write the API would reject; a client-side
|
|
27
|
+
// derivation could drift from it. `branchReadOnly` only picks which banner
|
|
28
|
+
// to show -- base-branch read-only takes precedence over a workflow status
|
|
29
|
+
// lock.
|
|
58
30
|
const statusLocked = branchWriteBlocked && !branchReadOnly;
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
// where the status IS known ('editing') and the copy would assert a status
|
|
66
|
-
// lock the status plainly contradicts. So: locked, but say why honestly.
|
|
67
|
-
//
|
|
68
|
-
// Provably behavior-neutral for supported deployments: writeBlocked =
|
|
69
|
-
// readOnly || status !== 'editing', so when status === 'editing' that
|
|
70
|
-
// reduces to writeBlocked === readOnly. statusLocked = branchWriteBlocked
|
|
71
|
-
// && !branchReadOnly, so the new 'editing' arm below would require
|
|
72
|
-
// readOnly && !readOnly -- impossible. It is unreachable against any
|
|
73
|
-
// current server and only changes what renders under version skew (an old
|
|
74
|
-
// server that omits writeBlocked while still sending status: 'editing'),
|
|
75
|
-
// where it replaces the self-contradicting "Branch is editing — content is
|
|
76
|
-
// read-only" with the honest data-unavailable copy.
|
|
31
|
+
// Covers two cases where `branchStatus` can't be trusted to describe the lock
|
|
32
|
+
// honestly: branch data still loading (`branchStatus` is undefined, so the
|
|
33
|
+
// banner would otherwise interpolate "Branch is undefined...") and version
|
|
34
|
+
// skew (an old server omits `branchWriteBlocked` while still reporting
|
|
35
|
+
// status: 'editing', which would otherwise assert a lock the status
|
|
36
|
+
// contradicts). In both cases the banner says data is unavailable instead.
|
|
77
37
|
const branchDataUnavailable = statusLocked && (branchStatus === undefined || branchStatus === 'editing');
|
|
78
38
|
return (_jsx(Paper, { ref: ref, shadow: "md", withBorder: true, radius: 0, px: 0, py: 0, style: {
|
|
79
39
|
position: 'fixed',
|
|
@@ -134,11 +94,11 @@ export const EditorHeader = forwardRef(function EditorHeader({ siteTitle, siteSu
|
|
|
134
94
|
// wrongly stuck in 'submitted'.
|
|
135
95
|
if (branchIsProtected && !isWithdrawable)
|
|
136
96
|
return null;
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
// base branch
|
|
140
|
-
//
|
|
141
|
-
//
|
|
97
|
+
// Who may submit/withdraw: creator, ACL access, the system branch, or an
|
|
98
|
+
// admin/reviewer -- Admins/Reviewers must be able to withdraw a protected
|
|
99
|
+
// base branch stuck in 'submitted' even without ACL access. Mirrors the
|
|
100
|
+
// server's canPerformWorkflowAction (BranchManager.tsx), which is the
|
|
101
|
+
// actual enforcer; this only decides whether to show the control disabled.
|
|
142
102
|
const userIsCreator = userContext?.userId === branchCreatedBy;
|
|
143
103
|
const isSystemBranch = branchCreatedBy === 'canopycms-system' && !branchIsProtected;
|
|
144
104
|
const userInACL = userContext &&
|
|
@@ -154,21 +114,11 @@ export const EditorHeader = forwardRef(function EditorHeader({ siteTitle, siteSu
|
|
|
154
114
|
const statusHasAction = isEditing || isWithdrawable;
|
|
155
115
|
const canPerformAction = userHasPermission && statusHasAction;
|
|
156
116
|
return (_jsx(Tooltip, { label:
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
//
|
|
163
|
-
// Latent rather than live TODAY, and only by accident:
|
|
164
|
-
// Editor.tsx passes `branchIsProtected={... ?? true}` since
|
|
165
|
-
// the fail-closed change, so in that same window the early
|
|
166
|
-
// return above (`branchIsProtected && !isWithdrawable`)
|
|
167
|
-
// unmounts this button before the tooltip can render. That
|
|
168
|
-
// is one guard away from being user-visible -- relax the
|
|
169
|
-
// `?? true`, or pass `branchIsProtected={false}` from
|
|
170
|
-
// anywhere, and the copy is live. Guarding it here rather
|
|
171
|
-
// than relying on an unrelated condition to keep hiding it.
|
|
117
|
+
// No branch data (`branchStatus === undefined`) must not be
|
|
118
|
+
// interpolated raw into this label. Guarded explicitly here rather
|
|
119
|
+
// than left to the early return above, which hides this button
|
|
120
|
+
// today only as a side effect of `branchIsProtected`'s `?? true`
|
|
121
|
+
// default -- not a guarantee this arm stays unreachable.
|
|
172
122
|
branchStatus === undefined
|
|
173
123
|
? 'Branch data could not be loaded, so no submit or withdraw action is available'
|
|
174
124
|
: !statusHasAction
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import type { PaneLayout } from '../EditorPanes.js';
|
|
2
|
-
/**
|
|
3
|
-
* Props for the EditorSidebar component.
|
|
4
|
-
*/
|
|
5
2
|
export interface EditorSidebarProps {
|
|
6
3
|
/**
|
|
7
4
|
* Current layout mode (side or stacked).
|
|
@@ -66,21 +63,5 @@ export interface EditorSidebarProps {
|
|
|
66
63
|
/**
|
|
67
64
|
* Sidebar component for the Editor.
|
|
68
65
|
* Contains layout toggle, highlight toggle, settings menu, account button, and logout button.
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* ```tsx
|
|
72
|
-
* <EditorSidebar
|
|
73
|
-
* layout={layout}
|
|
74
|
-
* highlightEnabled={highlightEnabled}
|
|
75
|
-
* sidebarWidth={60}
|
|
76
|
-
* headerHeight={60}
|
|
77
|
-
* footerHeight={40}
|
|
78
|
-
* onLayoutChange={setLayout}
|
|
79
|
-
* onHighlightToggle={() => setHighlightEnabled(!highlightEnabled)}
|
|
80
|
-
* onPermissionManagerOpen={() => setPermissionManagerOpen(true)}
|
|
81
|
-
* onGroupManagerOpen={() => setGroupManagerOpen(true)}
|
|
82
|
-
* onMediaLibraryOpen={() => setMediaLibraryOpen(true)}
|
|
83
|
-
* />
|
|
84
|
-
* ```
|
|
85
66
|
*/
|
|
86
67
|
export declare function EditorSidebar({ layout, highlightEnabled, sidebarWidth, headerHeight, footerHeight, onLayoutChange, onHighlightToggle, onPermissionManagerOpen, onGroupManagerOpen, onMediaLibraryOpen, onSystemHealthOpen, AccountComponent, onAccountClick, onLogoutClick, }: EditorSidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -4,22 +4,6 @@ import { IconUserCircle, IconLogout, IconPhoto, IconSettings, IconLayoutColumns,
|
|
|
4
4
|
/**
|
|
5
5
|
* Sidebar component for the Editor.
|
|
6
6
|
* Contains layout toggle, highlight toggle, settings menu, account button, and logout button.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```tsx
|
|
10
|
-
* <EditorSidebar
|
|
11
|
-
* layout={layout}
|
|
12
|
-
* highlightEnabled={highlightEnabled}
|
|
13
|
-
* sidebarWidth={60}
|
|
14
|
-
* headerHeight={60}
|
|
15
|
-
* footerHeight={40}
|
|
16
|
-
* onLayoutChange={setLayout}
|
|
17
|
-
* onHighlightToggle={() => setHighlightEnabled(!highlightEnabled)}
|
|
18
|
-
* onPermissionManagerOpen={() => setPermissionManagerOpen(true)}
|
|
19
|
-
* onGroupManagerOpen={() => setGroupManagerOpen(true)}
|
|
20
|
-
* onMediaLibraryOpen={() => setMediaLibraryOpen(true)}
|
|
21
|
-
* />
|
|
22
|
-
* ```
|
|
23
7
|
*/
|
|
24
8
|
export function EditorSidebar({ layout, highlightEnabled, sidebarWidth, headerHeight, footerHeight, onLayoutChange, onHighlightToggle, onPermissionManagerOpen, onGroupManagerOpen, onMediaLibraryOpen, onSystemHealthOpen, AccountComponent, onAccountClick, onLogoutClick, }) {
|
|
25
9
|
return (_jsxs(Paper, { withBorder: true, shadow: "sm", radius: 0, style: {
|
|
@@ -24,10 +24,10 @@ export interface EntryCreateModalProps {
|
|
|
24
24
|
error?: string | null;
|
|
25
25
|
/**
|
|
26
26
|
* Slugs already taken in the target collection (from the already-loaded
|
|
27
|
-
* entries list).
|
|
28
|
-
* clear message
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* entries list). Lets the client flag an obvious collision early with a
|
|
28
|
+
* clear message; the server is still the authority, and without this
|
|
29
|
+
* check an entry type with no required fields would silently succeed via
|
|
30
|
+
* an update path instead of erroring.
|
|
31
31
|
*/
|
|
32
32
|
existingSlugs?: Set<string>;
|
|
33
33
|
}
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
/**
|
|
4
|
-
* EntryCreateModal - Modal for creating new entries.
|
|
5
|
-
*
|
|
6
|
-
* Replaces window.prompt with a proper UI for:
|
|
7
|
-
* - Selecting entry type (if multiple types available)
|
|
8
|
-
* - Entering slug for new entry
|
|
9
|
-
* - Validation and error handling
|
|
10
|
-
*/
|
|
3
|
+
/** Modal for creating a new entry: replaces window.prompt with entry-type selection, slug entry, and validation. */
|
|
11
4
|
import { useState, useEffect, useRef } from 'react';
|
|
12
5
|
import { Modal, Stack, TextInput, Group, Button, Alert, Text, Select } from '@mantine/core';
|
|
13
6
|
import { IconAlertCircle } from '@tabler/icons-react';
|
|
@@ -15,31 +8,23 @@ import { parseSlug } from '../../paths/validation.js';
|
|
|
15
8
|
/** Slug the form is seeded with each time the modal opens. */
|
|
16
9
|
const DEFAULT_SLUG = 'untitled';
|
|
17
10
|
export function EntryCreateModal({ isOpen, collectionLabel, entryTypes, selectedEntryTypeName, onCreate, onClose, isCreating = false, error = null, existingSlugs, }) {
|
|
18
|
-
// Helper to get default or first entry type
|
|
19
11
|
const getDefaultEntryTypeName = () => {
|
|
20
12
|
if (selectedEntryTypeName)
|
|
21
13
|
return selectedEntryTypeName;
|
|
22
14
|
if (entryTypes.length === 1)
|
|
23
15
|
return entryTypes[0].name;
|
|
24
|
-
// Find entry type marked as default
|
|
25
16
|
const defaultType = entryTypes.find((et) => et.default);
|
|
26
17
|
return defaultType?.name || entryTypes[0]?.name || '';
|
|
27
18
|
};
|
|
28
19
|
const [slug, setSlug] = useState(DEFAULT_SLUG);
|
|
29
20
|
const [entryTypeName, setEntryTypeName] = useState(getDefaultEntryTypeName());
|
|
30
21
|
const [validationError, setValidationError] = useState(null);
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
// silently discarded what the user had typed or selected. The entry was then
|
|
38
|
-
// written to disk under the default slug with no error surfaced.
|
|
39
|
-
//
|
|
40
|
-
// Seeding is a lifecycle event, not a derivation of the current props, so the
|
|
41
|
-
// narrow dep array is the point. Do not "fix" it by adding the props read
|
|
42
|
-
// below (`entryTypes`, `selectedEntryTypeName`) back in.
|
|
22
|
+
// Seeds the form once per open, on the closed -> open transition. Keys on
|
|
23
|
+
// `isOpen` alone, not on `entryTypes`/`selectedEntryTypeName`: `entryTypes`
|
|
24
|
+
// is an array callers build inline, a fresh identity on every parent
|
|
25
|
+
// render, so keying on it would silently reset the form on every
|
|
26
|
+
// re-render while the modal is open. Do not add those props back to the
|
|
27
|
+
// dep array below.
|
|
43
28
|
const wasOpenRef = useRef(false);
|
|
44
29
|
useEffect(() => {
|
|
45
30
|
if (isOpen && !wasOpenRef.current) {
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
|
-
* RenameEntryModal - Modal for renaming entry slugs.
|
|
5
|
-
*
|
|
6
4
|
* Allows changing the slug (middle segment) of an entry filename.
|
|
7
5
|
* The content ID is preserved, so drafts and references remain intact.
|
|
8
6
|
*/
|
|
@@ -23,7 +21,6 @@ export function RenameEntryModal({ isOpen, entryLabel, currentSlug, onSave, onCl
|
|
|
23
21
|
setValidationError(null);
|
|
24
22
|
}
|
|
25
23
|
}
|
|
26
|
-
// Validate slug format
|
|
27
24
|
const validateSlug = (slug) => {
|
|
28
25
|
if (!slug.trim()) {
|
|
29
26
|
return 'Slug cannot be empty';
|
|
@@ -31,7 +28,6 @@ export function RenameEntryModal({ isOpen, entryLabel, currentSlug, onSave, onCl
|
|
|
31
28
|
if (slug.includes('/')) {
|
|
32
29
|
return 'Slug cannot contain slashes';
|
|
33
30
|
}
|
|
34
|
-
// Simple validation - lowercase, alphanumeric + hyphens
|
|
35
31
|
if (!/^[a-z0-9][-a-z0-9]*$/.test(slug)) {
|
|
36
32
|
return 'Slug must start with letter/number and contain only lowercase letters, numbers, and hyphens';
|
|
37
33
|
}
|
|
@@ -5,39 +5,32 @@ import { useUserMetadata } from '../hooks/useUserMetadata.js';
|
|
|
5
5
|
export const UserBadge = ({ userId, getUserMetadata, variant = 'avatar-name', showEmailTooltip = true, onRemove, color, size = 'sm', badgeVariant = 'filled', showBadge = false, loading: loadingOverride, cachedUser, }) => {
|
|
6
6
|
const { userMetadata, isLoading, error } = useUserMetadata(userId, getUserMetadata, cachedUser);
|
|
7
7
|
const loading = loadingOverride ?? isLoading;
|
|
8
|
-
// Avatar size mapping
|
|
9
8
|
const avatarSize = {
|
|
10
9
|
xs: 16,
|
|
11
10
|
sm: 20,
|
|
12
11
|
md: 24,
|
|
13
12
|
lg: 32,
|
|
14
13
|
}[size];
|
|
15
|
-
// Text size mapping
|
|
16
14
|
const textSize = {
|
|
17
15
|
xs: 'xs',
|
|
18
16
|
sm: 'sm',
|
|
19
17
|
md: 'sm',
|
|
20
18
|
lg: 'md',
|
|
21
19
|
}[size];
|
|
22
|
-
// Loading state
|
|
23
20
|
if (loading) {
|
|
24
21
|
return (_jsxs(Group, { gap: 4, children: [_jsx(Skeleton, { circle: true, height: avatarSize, width: avatarSize }), variant !== 'avatar-only' && _jsx(Skeleton, { height: 12, width: 60 })] }));
|
|
25
22
|
}
|
|
26
|
-
// Error or missing user - fallback to userId
|
|
27
23
|
if (error || !userMetadata) {
|
|
28
24
|
const content = (_jsxs(Group, { gap: 4, children: [_jsx(Avatar, { size: avatarSize, color: "gray" }), variant !== 'avatar-only' && (_jsx(Text, { size: textSize, c: "dimmed", children: userId }))] }));
|
|
29
25
|
return showEmailTooltip ? (_jsx(Tooltip, { label: error ? 'Error loading user' : 'User not found', children: content })) : (content);
|
|
30
26
|
}
|
|
31
|
-
// Generate initials from name
|
|
32
27
|
const getInitials = (name) => {
|
|
33
28
|
const parts = name.trim().split(/\s+/);
|
|
34
29
|
if (parts.length === 1)
|
|
35
30
|
return parts[0].charAt(0).toUpperCase();
|
|
36
31
|
return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
|
|
37
32
|
};
|
|
38
|
-
// Render avatar
|
|
39
33
|
const renderAvatar = () => {
|
|
40
|
-
// Special case: anonymous user
|
|
41
34
|
if (userId === 'anonymous') {
|
|
42
35
|
return (_jsx(Avatar, { size: avatarSize, color: "orange", children: _jsx(IconUserOff, { size: avatarSize * 0.6 }) }));
|
|
43
36
|
}
|
|
@@ -61,7 +54,6 @@ export const UserBadge = ({ userId, getUserMetadata, variant = 'avatar-name', sh
|
|
|
61
54
|
}
|
|
62
55
|
return (_jsx(Avatar, { src: userMetadata.avatarUrl, size: avatarSize, color: avatarColor, style: avatarStyles, children: !userMetadata.avatarUrl && getInitials(userMetadata.name) }));
|
|
63
56
|
};
|
|
64
|
-
// Render content based on variant
|
|
65
57
|
const renderContent = () => {
|
|
66
58
|
const avatar = renderAvatar();
|
|
67
59
|
switch (variant) {
|
|
@@ -75,7 +67,6 @@ export const UserBadge = ({ userId, getUserMetadata, variant = 'avatar-name', sh
|
|
|
75
67
|
}
|
|
76
68
|
};
|
|
77
69
|
const content = renderContent();
|
|
78
|
-
// If onRemove or showBadge, wrap the content in a Badge
|
|
79
70
|
if (onRemove || showBadge) {
|
|
80
71
|
const badgeContent = (_jsx(Badge, { variant: badgeVariant, color: color, pr: onRemove ? 3 : 8, pl: 4, rightSection: onRemove ? (_jsx(ActionIcon, { size: "xs", radius: "xl", variant: "transparent", onClick: () => onRemove(userId), "aria-label": "Remove user", style: { color: 'white' }, children: _jsx(IconX, { size: 12, stroke: 2.5 }) })) : undefined, styles: {
|
|
81
72
|
label: {
|
|
@@ -87,6 +78,5 @@ export const UserBadge = ({ userId, getUserMetadata, variant = 'avatar-name', sh
|
|
|
87
78
|
}, children: content }));
|
|
88
79
|
return showEmailTooltip && variant !== 'full' ? (_jsx(Tooltip, { label: userMetadata.email, children: badgeContent })) : (badgeContent);
|
|
89
80
|
}
|
|
90
|
-
// No badge wrapper - just wrap with tooltip if needed
|
|
91
81
|
return showEmailTooltip && variant !== 'full' ? (_jsx(Tooltip, { label: userMetadata.email, children: content })) : (content);
|
|
92
82
|
};
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* API
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* pattern that was duplicated across 6 hooks. This enables:
|
|
6
|
-
* - Clean testing via provider (no more resetApiClient() hacks)
|
|
7
|
-
* - Explicit dependency
|
|
8
|
-
* - No global mutable state
|
|
2
|
+
* Provides the API client via context-based dependency injection rather than
|
|
3
|
+
* a module-global singleton, so tests can inject a mock client through the
|
|
4
|
+
* provider instead of resetting global state between tests.
|
|
9
5
|
*/
|
|
10
6
|
import React from 'react';
|
|
11
7
|
import { createApiClient } from '../../api/index.js';
|
|
@@ -27,6 +23,11 @@ export interface ApiClientProviderProps {
|
|
|
27
23
|
* Use the client prop to inject a mock client for testing.
|
|
28
24
|
*/
|
|
29
25
|
export declare function ApiClientProvider({ children, client, basePath }: ApiClientProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* Subscribe to every 401 the provider's client receives, from any request. `listener` should be
|
|
28
|
+
* stable (e.g. from `useCallback`): a new function re-subscribes. No-op outside a provider.
|
|
29
|
+
*/
|
|
30
|
+
export declare function useOnUnauthorized(listener: () => void): void;
|
|
30
31
|
/**
|
|
31
32
|
* Hook to access the API client.
|
|
32
33
|
* Must be used within an ApiClientProvider.
|
|
@@ -1,31 +1,59 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
|
-
* API
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* pattern that was duplicated across 6 hooks. This enables:
|
|
8
|
-
* - Clean testing via provider (no more resetApiClient() hacks)
|
|
9
|
-
* - Explicit dependency
|
|
10
|
-
* - No global mutable state
|
|
4
|
+
* Provides the API client via context-based dependency injection rather than
|
|
5
|
+
* a module-global singleton, so tests can inject a mock client through the
|
|
6
|
+
* provider instead of resetting global state between tests.
|
|
11
7
|
*/
|
|
12
|
-
import { createContext, useContext, useMemo } from 'react';
|
|
8
|
+
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
|
13
9
|
import { createApiClient } from '../../api/index.js';
|
|
14
10
|
import { joinUrlPrefix } from '../../utils/url-prefix.js';
|
|
15
11
|
const ApiClientContext = createContext(null);
|
|
12
|
+
function createUnauthorizedSignal() {
|
|
13
|
+
const listeners = new Set();
|
|
14
|
+
return {
|
|
15
|
+
emit: () => {
|
|
16
|
+
for (const listener of [...listeners])
|
|
17
|
+
listener();
|
|
18
|
+
},
|
|
19
|
+
subscribe: (listener) => {
|
|
20
|
+
listeners.add(listener);
|
|
21
|
+
return () => {
|
|
22
|
+
listeners.delete(listener);
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const UnauthorizedSignalContext = createContext(null);
|
|
16
28
|
/**
|
|
17
29
|
* Provider that creates and provides the API client.
|
|
18
30
|
* Use the client prop to inject a mock client for testing.
|
|
19
31
|
*/
|
|
20
32
|
export function ApiClientProvider({ children, client, basePath }) {
|
|
33
|
+
const [unauthorized] = useState(createUnauthorizedSignal);
|
|
21
34
|
// Memoized on identity, not just for cost: several consumers now list the client in their
|
|
22
35
|
// effect deps (useUserContext, useReferenceResolution, ReferenceField), so a fresh client each
|
|
23
36
|
// render would turn those one-shot fetches into a loop. A caller injecting an inline
|
|
24
37
|
// `client={createApiClient()}` would reintroduce exactly that.
|
|
38
|
+
//
|
|
39
|
+
// Only a client built HERE reports 401s to `useOnUnauthorized`; an injected `client` is used
|
|
40
|
+
// as-is, so its 401s reach the auth gate only through the gate's own whoami result.
|
|
25
41
|
const apiClient = useMemo(() => {
|
|
26
|
-
return client ??
|
|
27
|
-
|
|
28
|
-
|
|
42
|
+
return (client ??
|
|
43
|
+
createApiClient({
|
|
44
|
+
baseUrl: joinUrlPrefix(basePath, '/api/canopycms'),
|
|
45
|
+
onUnauthorized: unauthorized.emit,
|
|
46
|
+
}));
|
|
47
|
+
}, [client, basePath, unauthorized]);
|
|
48
|
+
return (_jsx(UnauthorizedSignalContext.Provider, { value: unauthorized, children: _jsx(ApiClientContext.Provider, { value: apiClient, children: children }) }));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Subscribe to every 401 the provider's client receives, from any request. `listener` should be
|
|
52
|
+
* stable (e.g. from `useCallback`): a new function re-subscribes. No-op outside a provider.
|
|
53
|
+
*/
|
|
54
|
+
export function useOnUnauthorized(listener) {
|
|
55
|
+
const signal = useContext(UnauthorizedSignalContext);
|
|
56
|
+
useEffect(() => signal?.subscribe(listener), [signal, listener]);
|
|
29
57
|
}
|
|
30
58
|
/**
|
|
31
59
|
* Hook to access the API client.
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Asset Context
|
|
3
|
-
*
|
|
4
2
|
* Carries `media.publicBaseUrl` (see CanopyClientConfig.assetBaseUrl) down to
|
|
5
3
|
* every asset-URL-building component - MediaLibrary, ImageField, and the MDX
|
|
6
4
|
* image dialog. A context (rather than a prop) because the MDX dialog is
|
|
@@ -31,23 +29,15 @@ export interface AssetContextProviderProps extends AssetContextValue {
|
|
|
31
29
|
* full, and a deployment `basePath` cannot apply on top of it. Where the two differ is topology,
|
|
32
30
|
* not precedence - see the asset-mount table in the README.
|
|
33
31
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* bare path, leaving the editor's thumbnails, previews and crop images root-relative — and 404 —
|
|
37
|
-
* on a basePath deployment where Next serves `/assets`. That constraint was lifted when
|
|
38
|
-
* `publicBaseUrl` moved to `assetMountUrlSchema`, which accepts a site-relative path: an adopter
|
|
39
|
-
* can now simply set `publicBaseUrl: '/preview-123'`. The fallback is kept only so that existing
|
|
40
|
-
* basePath deployments do not break on upgrade, which makes removing it a deliberate decision
|
|
41
|
-
* rather than a cleanup - it is option 1 of
|
|
32
|
+
* The fallback is kept only so that existing basePath deployments do not break on upgrade,
|
|
33
|
+
* which makes removing it a deliberate decision rather than a cleanup - it is option 1 of
|
|
42
34
|
* `.claude/future-tasks/editor-asset-mount-topology.md`, still open.
|
|
43
35
|
*
|
|
44
|
-
* KNOWN LIMITATION:
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* obvious: set `media.publicBaseUrl` to the distribution origin, which takes precedence here.
|
|
50
|
-
* Tracked in `.claude/future-tasks/editor-asset-mount-topology.md`.
|
|
36
|
+
* KNOWN LIMITATION: on a CloudFront/CDK deployment, a basePath does NOT move the asset
|
|
37
|
+
* space (behaviors are anchored at the distribution root), so this fallback prefixes
|
|
38
|
+
* wrongly — requests still resolve, via `withCanopy`'s auto-prefixed `/assets/:path*`
|
|
39
|
+
* rewrite, but bypass the CDN cache and the dedicated transform Lambda. Workaround: set
|
|
40
|
+
* `media.publicBaseUrl` to the distribution origin instead, which takes precedence here.
|
|
51
41
|
*/
|
|
52
42
|
export declare function AssetContextProvider({ baseUrl, basePath, children }: AssetContextProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
53
43
|
/** Safe to call outside a provider - returns `{ baseUrl: undefined }` (root-relative URLs). */
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
|
-
* Asset Context
|
|
5
|
-
*
|
|
6
4
|
* Carries `media.publicBaseUrl` (see CanopyClientConfig.assetBaseUrl) down to
|
|
7
5
|
* every asset-URL-building component - MediaLibrary, ImageField, and the MDX
|
|
8
6
|
* image dialog. A context (rather than a prop) because the MDX dialog is
|
|
@@ -22,23 +20,15 @@ const AssetContext = createContext({});
|
|
|
22
20
|
* full, and a deployment `basePath` cannot apply on top of it. Where the two differ is topology,
|
|
23
21
|
* not precedence - see the asset-mount table in the README.
|
|
24
22
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* bare path, leaving the editor's thumbnails, previews and crop images root-relative — and 404 —
|
|
28
|
-
* on a basePath deployment where Next serves `/assets`. That constraint was lifted when
|
|
29
|
-
* `publicBaseUrl` moved to `assetMountUrlSchema`, which accepts a site-relative path: an adopter
|
|
30
|
-
* can now simply set `publicBaseUrl: '/preview-123'`. The fallback is kept only so that existing
|
|
31
|
-
* basePath deployments do not break on upgrade, which makes removing it a deliberate decision
|
|
32
|
-
* rather than a cleanup - it is option 1 of
|
|
23
|
+
* The fallback is kept only so that existing basePath deployments do not break on upgrade,
|
|
24
|
+
* which makes removing it a deliberate decision rather than a cleanup - it is option 1 of
|
|
33
25
|
* `.claude/future-tasks/editor-asset-mount-topology.md`, still open.
|
|
34
26
|
*
|
|
35
|
-
* KNOWN LIMITATION:
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* obvious: set `media.publicBaseUrl` to the distribution origin, which takes precedence here.
|
|
41
|
-
* Tracked in `.claude/future-tasks/editor-asset-mount-topology.md`.
|
|
27
|
+
* KNOWN LIMITATION: on a CloudFront/CDK deployment, a basePath does NOT move the asset
|
|
28
|
+
* space (behaviors are anchored at the distribution root), so this fallback prefixes
|
|
29
|
+
* wrongly — requests still resolve, via `withCanopy`'s auto-prefixed `/assets/:path*`
|
|
30
|
+
* rewrite, but bypass the CDN cache and the dedicated transform Lambda. Workaround: set
|
|
31
|
+
* `media.publicBaseUrl` to the distribution origin instead, which takes precedence here.
|
|
42
32
|
*/
|
|
43
33
|
export function AssetContextProvider({ baseUrl, basePath, children }) {
|
|
44
34
|
const resolved = baseUrl ?? basePath;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { UserContext } from '../BranchManager.js';
|
|
2
|
+
/**
|
|
3
|
+
* The identity `EditorAuthGate` resolved for the editor below it. Present only inside the gate;
|
|
4
|
+
* `useUserContext` reads it so the editor shares the gate's one `whoami` instead of issuing its
|
|
5
|
+
* own.
|
|
6
|
+
*/
|
|
7
|
+
export interface EditorIdentity {
|
|
8
|
+
/** The server-accepted identity; the gate mounts the editor only once it has one. */
|
|
9
|
+
user: UserContext;
|
|
10
|
+
}
|
|
11
|
+
export declare const EditorIdentityContext: import("react").Context<EditorIdentity | null>;
|
|
12
|
+
/** The gate's resolved identity, or null outside an `EditorAuthGate`. */
|
|
13
|
+
export declare function useEditorIdentity(): EditorIdentity | null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
export const EditorIdentityContext = createContext(null);
|
|
4
|
+
/** The gate's resolved identity, or null outside an `EditorAuthGate`. */
|
|
5
|
+
export function useEditorIdentity() {
|
|
6
|
+
return useContext(EditorIdentityContext);
|
|
7
|
+
}
|