canopycms 0.0.68-int.98 → 0.1.0
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/CHANGELOG.md +2131 -0
- package/README.md +47 -63
- package/dist/ai/generate.d.ts +5 -0
- package/dist/ai/generate.js +244 -115
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/json-to-markdown.d.ts +21 -1
- package/dist/ai/json-to-markdown.js +120 -57
- package/dist/ai/references.d.ts +72 -0
- package/dist/ai/references.js +223 -0
- package/dist/ai/resolve-branch.js +9 -2
- package/dist/ai/to-plain-text.d.ts +17 -8
- package/dist/ai/to-plain-text.js +18 -15
- package/dist/ai/types.d.ts +84 -3
- package/dist/api/admin-branch-health.d.ts +24 -1
- package/dist/api/admin-branch-health.js +52 -20
- package/dist/api/admin.d.ts +23 -5
- package/dist/api/admin.js +36 -1
- package/dist/api/assets.js +88 -78
- package/dist/api/branch-create-window.d.ts +12 -0
- package/dist/api/branch-create-window.js +13 -0
- package/dist/api/branch-merge.d.ts +1 -1
- package/dist/api/branch-merge.js +1 -1
- package/dist/api/branch-review.d.ts +3 -3
- package/dist/api/branch-review.js +16 -7
- package/dist/api/branch-status.d.ts +16 -6
- package/dist/api/branch-status.js +57 -12
- package/dist/api/branch-withdraw.d.ts +2 -2
- package/dist/api/branch-withdraw.js +8 -3
- package/dist/api/branch.d.ts +25 -12
- package/dist/api/branch.js +164 -103
- package/dist/api/client.d.ts +78 -58
- package/dist/api/client.js +150 -117
- package/dist/api/comments.d.ts +12 -3
- package/dist/api/comments.js +118 -9
- package/dist/api/content.d.ts +9 -9
- package/dist/api/content.js +131 -22
- package/dist/api/entries-constants.d.ts +14 -3
- package/dist/api/entries-constants.js +14 -3
- package/dist/api/entries.d.ts +40 -2
- package/dist/api/entries.js +102 -6
- package/dist/api/github-sync.d.ts +19 -0
- package/dist/api/github-sync.js +50 -3
- package/dist/api/groups.d.ts +4 -4
- package/dist/api/groups.js +2 -1
- package/dist/api/guards.js +23 -3
- package/dist/api/index.d.ts +3 -1
- package/dist/api/index.js +1 -0
- package/dist/api/permissions.d.ts +21 -2
- package/dist/api/permissions.js +50 -3
- package/dist/api/request-deadline.d.ts +59 -0
- package/dist/api/request-deadline.js +73 -0
- package/dist/api/resolve-references.js +8 -7
- package/dist/api/route-builder.d.ts +14 -0
- package/dist/api/route-builder.js +14 -1
- package/dist/api/schema.d.ts +11 -9
- package/dist/api/schema.js +2 -0
- package/dist/api/settings-helpers.d.ts +5 -1
- package/dist/api/settings-helpers.js +10 -2
- package/dist/api/types.d.ts +18 -0
- package/dist/api/users-constants.d.ts +6 -0
- package/dist/api/users-constants.js +6 -0
- package/dist/assets/asset-url.d.ts +28 -16
- package/dist/assets/asset-url.js +51 -25
- package/dist/assets/finalize.js +3 -0
- package/dist/assets/index.d.ts +1 -1
- package/dist/assets/materialize.d.ts +153 -0
- package/dist/assets/materialize.js +402 -0
- package/dist/assets/store-local.d.ts +19 -5
- package/dist/assets/store-local.js +69 -10
- package/dist/assets/store-s3.d.ts +38 -7
- package/dist/assets/store-s3.js +128 -22
- package/dist/assets/transform-directives.d.ts +52 -13
- package/dist/assets/transform-directives.js +87 -27
- package/dist/assets/transform.d.ts +3 -3
- package/dist/assets/transform.js +13 -8
- package/dist/assets/types.d.ts +31 -4
- package/dist/auth/cache.d.ts +1 -1
- package/dist/auth/cache.js +1 -1
- package/dist/auth/caching-auth-plugin.d.ts +2 -0
- package/dist/auth/caching-auth-plugin.js +12 -2
- package/dist/auth/file-based-auth-cache.d.ts +8 -0
- package/dist/auth/file-based-auth-cache.js +18 -8
- package/dist/auth/person-name.d.ts +5 -0
- package/dist/auth/person-name.js +8 -0
- package/dist/auth/plugin.d.ts +10 -1
- package/dist/auth/types.d.ts +2 -0
- package/dist/auth/user-metadata-lookup.d.ts +21 -0
- package/dist/auth/user-metadata-lookup.js +116 -0
- package/dist/authorization/branch.d.ts +1 -1
- package/dist/authorization/branch.js +12 -13
- package/dist/authorization/groups/schema.d.ts +4 -4
- package/dist/authorization/helpers.d.ts +8 -0
- package/dist/authorization/helpers.js +8 -0
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.js +1 -1
- package/dist/authorization/protected-branch.d.ts +5 -4
- package/dist/authorization/protected-branch.js +7 -5
- package/dist/branch-health.d.ts +35 -8
- package/dist/branch-health.js +54 -18
- package/dist/branch-metadata-error.d.ts +27 -0
- package/dist/branch-metadata-error.js +23 -0
- package/dist/branch-metadata-file.d.ts +205 -24
- package/dist/branch-metadata-file.js +126 -25
- package/dist/branch-metadata.d.ts +45 -6
- package/dist/branch-metadata.js +142 -50
- package/dist/branch-provisioning.d.ts +167 -0
- package/dist/branch-provisioning.js +501 -0
- package/dist/branch-registry.d.ts +8 -0
- package/dist/branch-registry.js +61 -9
- package/dist/branch-schema-cache.d.ts +29 -12
- package/dist/branch-schema-cache.js +64 -21
- package/dist/branch-sparse.d.ts +23 -0
- package/dist/branch-sparse.js +118 -0
- package/dist/branch-workspace.d.ts +42 -3
- package/dist/branch-workspace.js +239 -100
- package/dist/build/asset-refs.d.ts +94 -0
- package/dist/build/asset-refs.js +267 -0
- package/dist/build/generate-ai-content.js +5 -0
- package/dist/build/inline-flight.d.ts +37 -0
- package/dist/build/inline-flight.js +142 -0
- package/dist/cli/asset-refs.d.ts +52 -0
- package/dist/cli/asset-refs.js +194 -0
- package/dist/cli/cli.d.ts +15 -1
- package/dist/cli/cli.js +8543 -3193
- package/dist/cli/configured-asset-store.d.ts +12 -0
- package/dist/cli/configured-asset-store.js +46 -0
- package/dist/cli/generate-ai-content.js +4244 -1072
- package/dist/cli/init.js +217 -126
- package/dist/cli/project-detect.d.ts +2 -0
- package/dist/cli/project-detect.js +2 -0
- package/dist/cli/template-files/Dockerfile.cms.template +13 -5
- package/dist/cli/template-files/cms-stack.ts.template +16 -13
- package/dist/client.d.ts +1 -2
- package/dist/client.js +1 -2
- package/dist/comment-store.d.ts +25 -0
- package/dist/comment-store.js +43 -8
- package/dist/config/flatten.js +2 -0
- package/dist/config/helpers.js +2 -2
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schemas/config.d.ts +12 -29
- package/dist/config/schemas/config.js +9 -12
- package/dist/config/schemas/field.d.ts +3 -0
- package/dist/config/schemas/field.js +58 -4
- package/dist/config/schemas/media.d.ts +4 -13
- package/dist/config/schemas/media.js +5 -8
- package/dist/config/schemas/url.d.ts +2 -20
- package/dist/config/schemas/url.js +2 -25
- package/dist/config/types.d.ts +116 -22
- package/dist/config/types.js +3 -9
- package/dist/config/validation.d.ts +25 -4
- package/dist/config/validation.js +116 -3
- package/dist/content-id-index.js +2 -2
- package/dist/content-index-generation.d.ts +1 -1
- package/dist/content-index-generation.js +1 -1
- package/dist/content-listing.d.ts +10 -1
- package/dist/content-listing.js +22 -5
- package/dist/content-reader.d.ts +9 -0
- package/dist/content-reader.js +16 -11
- package/dist/content-store.d.ts +75 -12
- package/dist/content-store.js +249 -86
- package/dist/content-tree.js +2 -2
- package/dist/context.js +5 -2
- package/dist/dangling-reference-log.d.ts +17 -0
- package/dist/dangling-reference-log.js +29 -0
- package/dist/dev-content-watcher.d.ts +1 -1
- package/dist/dev-content-watcher.js +1 -1
- package/dist/editor/BranchManager.d.ts +23 -7
- package/dist/editor/BranchManager.js +119 -54
- package/dist/editor/CanopyEditor.d.ts +1 -1
- package/dist/editor/CanopyEditor.js +1 -2
- package/dist/editor/CommentsPanel.d.ts +14 -0
- package/dist/editor/CommentsPanel.js +68 -43
- package/dist/editor/Editor.d.ts +11 -5
- package/dist/editor/Editor.js +891 -218
- package/dist/editor/EditorAuthGate.d.ts +7 -1
- package/dist/editor/EditorAuthGate.js +41 -9
- package/dist/editor/EntryNavigator.d.ts +22 -0
- package/dist/editor/EntryNavigator.js +353 -105
- package/dist/editor/FormHeader.d.ts +25 -0
- package/dist/editor/FormHeader.js +82 -0
- package/dist/editor/FormRenderer.d.ts +27 -3
- package/dist/editor/FormRenderer.js +171 -76
- package/dist/editor/PreviewFrame.d.ts +40 -0
- package/dist/editor/PreviewFrame.js +215 -0
- package/dist/editor/PreviewPane.d.ts +47 -0
- package/dist/editor/PreviewPane.js +147 -0
- package/dist/editor/PreviewToolbarTools.d.ts +22 -0
- package/dist/editor/PreviewToolbarTools.js +73 -0
- package/dist/editor/admin/SystemHealthPanel.d.ts +2 -1
- package/dist/editor/admin/SystemHealthPanel.js +163 -33
- package/dist/editor/admin/useSystemHealth.d.ts +18 -0
- package/dist/editor/admin/useSystemHealth.js +70 -1
- package/dist/editor/branch-status.d.ts +17 -0
- package/dist/editor/branch-status.js +29 -0
- package/dist/editor/canopy-path.d.ts +9 -6
- package/dist/editor/canopy-path.js +8 -11
- package/dist/editor/client-reference-resolver.d.ts +43 -16
- package/dist/editor/client-reference-resolver.js +155 -64
- package/dist/editor/comments/BranchComments.d.ts +1 -1
- package/dist/editor/comments/BranchComments.js +2 -2
- package/dist/editor/comments/CloseRefusedNotice.d.ts +4 -0
- package/dist/editor/comments/CloseRefusedNotice.js +7 -0
- package/dist/editor/comments/CommentThreadsPopover.d.ts +47 -0
- package/dist/editor/comments/CommentThreadsPopover.js +274 -0
- package/dist/editor/comments/CommentWriteAlert.d.ts +11 -0
- package/dist/editor/comments/CommentWriteAlert.js +13 -0
- package/dist/editor/comments/EntryComments.d.ts +10 -4
- package/dist/editor/comments/EntryComments.js +14 -17
- package/dist/editor/comments/FieldWrapper.d.ts +18 -4
- package/dist/editor/comments/FieldWrapper.js +62 -28
- package/dist/editor/comments/InlineCommentThread.d.ts +9 -2
- package/dist/editor/comments/InlineCommentThread.js +11 -47
- package/dist/editor/comments/ThreadCarousel.d.ts +1 -1
- package/dist/editor/comments/ThreadCarousel.js +18 -21
- package/dist/editor/comments/ThreadReplyControls.d.ts +28 -0
- package/dist/editor/comments/ThreadReplyControls.js +92 -0
- package/dist/editor/comments/field-comment-context.d.ts +14 -0
- package/dist/editor/comments/field-comment-context.js +14 -0
- package/dist/editor/comments/form-comments.d.ts +48 -0
- package/dist/editor/comments/form-comments.js +178 -0
- package/dist/editor/comments/item-anchor-copy.d.ts +6 -0
- package/dist/editor/comments/item-anchor-copy.js +6 -0
- package/dist/editor/comments/move-focus-if-unmoved.d.ts +6 -0
- package/dist/editor/comments/move-focus-if-unmoved.js +11 -0
- package/dist/editor/comments/popover-placement.d.ts +18 -0
- package/dist/editor/comments/popover-placement.js +58 -0
- package/dist/editor/comments/use-tracked-writes.d.ts +16 -0
- package/dist/editor/comments/use-tracked-writes.js +53 -0
- package/dist/editor/components/BranchAccessList.d.ts +15 -0
- package/dist/editor/components/BranchAccessList.js +52 -0
- package/dist/editor/components/BranchLockBanner.d.ts +22 -0
- package/dist/editor/components/BranchLockBanner.js +39 -0
- package/dist/editor/components/BranchPill.d.ts +32 -0
- package/dist/editor/components/BranchPill.js +33 -0
- package/dist/editor/components/BranchesDrawer.d.ts +11 -0
- package/dist/editor/components/BranchesDrawer.js +5 -0
- package/dist/editor/components/ConfirmDeleteModal.d.ts +6 -1
- package/dist/editor/components/ConfirmDeleteModal.js +3 -2
- package/dist/editor/components/DestructiveMenuItem.d.ts +7 -0
- package/dist/editor/components/DestructiveMenuItem.js +8 -0
- package/dist/editor/components/EditorCrashScreen.d.ts +17 -0
- package/dist/editor/components/EditorCrashScreen.js +22 -0
- package/dist/editor/components/EditorErrorBoundary.d.ts +38 -0
- package/dist/editor/components/EditorErrorBoundary.js +40 -0
- package/dist/editor/components/EditorHeader.d.ts +56 -106
- package/dist/editor/components/EditorHeader.js +130 -131
- package/dist/editor/components/EditorRail.d.ts +49 -0
- package/dist/editor/components/EditorRail.js +65 -0
- package/dist/editor/components/EntryBreadcrumb.d.ts +33 -0
- package/dist/editor/components/EntryBreadcrumb.js +56 -0
- package/dist/editor/components/EntryCreateModal.d.ts +12 -7
- package/dist/editor/components/EntryCreateModal.js +51 -57
- package/dist/editor/components/NoEditPermissionNotice.d.ts +6 -5
- package/dist/editor/components/NoEditPermissionNotice.js +5 -4
- package/dist/editor/components/QuickOpenPalette.d.ts +22 -0
- package/dist/editor/components/QuickOpenPalette.js +66 -0
- package/dist/editor/components/ReadOnlyDraftNotice.d.ts +11 -0
- package/dist/editor/components/ReadOnlyDraftNotice.js +12 -0
- package/dist/editor/components/ReasonedMenuItem.d.ts +15 -0
- package/dist/editor/components/ReasonedMenuItem.js +15 -0
- package/dist/editor/components/ReferencedByList.d.ts +11 -0
- package/dist/editor/components/ReferencedByList.js +28 -0
- package/dist/editor/components/RelativeTime.d.ts +10 -0
- package/dist/editor/components/RelativeTime.js +10 -0
- package/dist/editor/components/RenameEntryModal.d.ts +9 -1
- package/dist/editor/components/RenameEntryModal.js +19 -31
- package/dist/editor/components/RetryToastMessage.d.ts +9 -0
- package/dist/editor/components/RetryToastMessage.js +6 -0
- package/dist/editor/components/SaveAllResult.d.ts +25 -0
- package/dist/editor/components/SaveAllResult.js +86 -0
- package/dist/editor/components/SaveSplitButton.d.ts +30 -0
- package/dist/editor/components/SaveSplitButton.js +108 -0
- package/dist/editor/components/StagedChangesDrawer.d.ts +39 -0
- package/dist/editor/components/StagedChangesDrawer.js +92 -0
- package/dist/editor/components/UnavailableEntryNotice.d.ts +6 -0
- package/dist/editor/components/UnavailableEntryNotice.js +9 -0
- package/dist/editor/components/UnavailableTypeMessage.d.ts +6 -0
- package/dist/editor/components/UnavailableTypeMessage.js +9 -0
- package/dist/editor/components/UndoToastMessage.d.ts +18 -0
- package/dist/editor/components/UndoToastMessage.js +10 -0
- package/dist/editor/components/UserBadge.d.ts +2 -5
- package/dist/editor/components/UserBadge.js +62 -33
- package/dist/editor/components/ValidationSummary.d.ts +14 -0
- package/dist/editor/components/ValidationSummary.js +24 -0
- package/dist/editor/components/index.d.ts +2 -2
- package/dist/editor/components/index.js +2 -2
- package/dist/editor/context/ApiClientContext.d.ts +8 -2
- package/dist/editor/context/ApiClientContext.js +19 -8
- package/dist/editor/context/AssetContext.d.ts +13 -35
- package/dist/editor/context/AssetContext.js +12 -31
- package/dist/editor/context/EditorStateContext.d.ts +4 -4
- package/dist/editor/context/EditorStateContext.js +4 -4
- package/dist/editor/context/SWRProvider.d.ts +3 -3
- package/dist/editor/context/SiteMdxAllowContext.d.ts +4 -0
- package/dist/editor/context/SiteMdxAllowContext.js +7 -0
- package/dist/editor/context/index.d.ts +2 -1
- package/dist/editor/context/index.js +2 -1
- package/dist/editor/contrast.d.ts +19 -0
- package/dist/editor/contrast.js +41 -0
- package/dist/editor/copy.d.ts +18 -0
- package/dist/editor/copy.js +18 -0
- package/dist/editor/editor-config.js +16 -0
- package/dist/editor/editor-utils.d.ts +34 -8
- package/dist/editor/editor-utils.js +42 -20
- package/dist/editor/entry-search.d.ts +20 -0
- package/dist/editor/entry-search.js +34 -0
- package/dist/editor/field-breadcrumb.d.ts +12 -0
- package/dist/editor/field-breadcrumb.js +85 -0
- package/dist/editor/field-props.d.ts +86 -0
- package/dist/editor/field-props.js +27 -0
- package/dist/editor/field-target.d.ts +30 -0
- package/dist/editor/field-target.js +77 -0
- package/dist/editor/fields/BlockField.d.ts +12 -0
- package/dist/editor/fields/BlockField.js +89 -73
- package/dist/editor/fields/CodeField.d.ts +2 -0
- package/dist/editor/fields/CodeField.js +6 -2
- package/dist/editor/fields/DateTimeField.d.ts +4 -29
- package/dist/editor/fields/DateTimeField.js +79 -41
- package/dist/editor/fields/ExpandAllButton.d.ts +6 -0
- package/dist/editor/fields/ExpandAllButton.js +4 -0
- package/dist/editor/fields/FieldCrashFallback.d.ts +17 -0
- package/dist/editor/fields/FieldCrashFallback.js +30 -0
- package/dist/editor/fields/FieldLabel.d.ts +37 -0
- package/dist/editor/fields/FieldLabel.js +19 -0
- package/dist/editor/fields/ImageField.d.ts +4 -0
- package/dist/editor/fields/ImageField.js +29 -14
- package/dist/editor/fields/InlineGroupField.js +4 -3
- package/dist/editor/fields/ItemList.d.ts +42 -0
- package/dist/editor/fields/ItemList.js +130 -0
- package/dist/editor/fields/MarkdownField.d.ts +32 -0
- package/dist/editor/fields/MarkdownField.js +223 -46
- package/dist/editor/fields/MdxImageDialog.js +1 -1
- package/dist/editor/fields/NumberField.d.ts +2 -0
- package/dist/editor/fields/NumberField.js +8 -5
- package/dist/editor/fields/NumberListField.d.ts +2 -0
- package/dist/editor/fields/NumberListField.js +19 -16
- package/dist/editor/fields/ObjectField.d.ts +2 -7
- package/dist/editor/fields/ObjectField.js +15 -5
- package/dist/editor/fields/ObjectListField.d.ts +29 -0
- package/dist/editor/fields/ObjectListField.js +57 -0
- package/dist/editor/fields/ReferenceField.d.ts +2 -0
- package/dist/editor/fields/ReferenceField.js +34 -9
- package/dist/editor/fields/SelectField.d.ts +2 -0
- package/dist/editor/fields/SelectField.js +11 -2
- package/dist/editor/fields/StringListField.d.ts +4 -1
- package/dist/editor/fields/StringListField.js +22 -8
- package/dist/editor/fields/TextField.d.ts +2 -0
- package/dist/editor/fields/TextField.js +6 -2
- package/dist/editor/fields/ToggleField.d.ts +2 -0
- package/dist/editor/fields/ToggleField.js +8 -3
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +1 -1
- package/dist/editor/fields/entry-link/InsertEntryLink.js +1 -1
- package/dist/editor/fields/form-expansion.d.ts +9 -0
- package/dist/editor/fields/form-expansion.js +2 -0
- package/dist/editor/fields/item-expansion.d.ts +15 -0
- package/dist/editor/fields/item-expansion.js +60 -0
- package/dist/editor/fields/list-item-keys.d.ts +8 -0
- package/dist/editor/fields/list-item-keys.js +50 -0
- package/dist/editor/fields/list-item-title.d.ts +20 -0
- package/dist/editor/fields/list-item-title.js +85 -0
- package/dist/editor/fields/markdown-export-options.d.ts +2 -0
- package/dist/editor/fields/markdown-export-options.js +8 -0
- package/dist/editor/fields/markdown-fidelity-visitors.d.ts +11 -0
- package/dist/editor/fields/markdown-fidelity-visitors.js +160 -0
- package/dist/editor/fields/mdx-jsx-support.d.ts +5 -1
- package/dist/editor/fields/mdx-jsx-support.js +157 -69
- package/dist/editor/fields/rich-text-failures.d.ts +5 -0
- package/dist/editor/fields/rich-text-failures.js +26 -0
- package/dist/editor/fields/toolbar-wrap.d.ts +7 -0
- package/dist/editor/fields/toolbar-wrap.js +35 -0
- package/dist/editor/form-outline.d.ts +13 -0
- package/dist/editor/form-outline.js +70 -0
- package/dist/editor/group-manager/GroupCard.d.ts +4 -1
- package/dist/editor/group-manager/GroupCard.js +12 -3
- package/dist/editor/group-manager/GroupForm.js +1 -1
- package/dist/editor/group-manager/InternalGroupsTab.d.ts +2 -1
- package/dist/editor/group-manager/InternalGroupsTab.js +4 -4
- package/dist/editor/group-manager/MemberList.d.ts +2 -1
- package/dist/editor/group-manager/MemberList.js +15 -4
- package/dist/editor/group-manager/hooks/useGroupState.d.ts +5 -0
- package/dist/editor/group-manager/hooks/useGroupState.js +30 -7
- package/dist/editor/group-manager/index.js +34 -5
- package/dist/editor/group-manager/types.d.ts +5 -2
- package/dist/editor/hooks/create-branch-request.d.ts +20 -0
- package/dist/editor/hooks/create-branch-request.js +54 -0
- package/dist/editor/hooks/save-all.d.ts +68 -0
- package/dist/editor/hooks/save-all.js +61 -0
- package/dist/editor/hooks/useBranchActions.d.ts +11 -1
- package/dist/editor/hooks/useBranchActions.js +42 -19
- package/dist/editor/hooks/useBranchManager.d.ts +21 -0
- package/dist/editor/hooks/useBranchManager.js +321 -125
- package/dist/editor/hooks/useBranchesData.d.ts +8 -4
- package/dist/editor/hooks/useBranchesData.js +9 -5
- package/dist/editor/hooks/useCommentSystem.d.ts +14 -2
- package/dist/editor/hooks/useCommentSystem.js +79 -55
- package/dist/editor/hooks/useCommentsData.d.ts +11 -7
- package/dist/editor/hooks/useCommentsData.js +20 -19
- package/dist/editor/hooks/useDraftManager.d.ts +77 -3
- package/dist/editor/hooks/useDraftManager.js +887 -94
- package/dist/editor/hooks/useEditorLayout.d.ts +53 -7
- package/dist/editor/hooks/useEditorLayout.js +98 -20
- package/dist/editor/hooks/useEntriesData.d.ts +2 -1
- package/dist/editor/hooks/useEntriesData.js +18 -4
- package/dist/editor/hooks/useEntryManager.d.ts +41 -2
- package/dist/editor/hooks/useEntryManager.js +227 -41
- package/dist/editor/hooks/useGroupManager.js +13 -16
- package/dist/editor/hooks/usePermissionManager.js +14 -6
- package/dist/editor/hooks/usePreviewMarks.d.ts +21 -0
- package/dist/editor/hooks/usePreviewMarks.js +33 -0
- package/dist/editor/hooks/useReferenceResolution.d.ts +10 -3
- package/dist/editor/hooks/useReferenceResolution.js +34 -177
- package/dist/editor/hooks/useSchemaManager.d.ts +25 -6
- package/dist/editor/hooks/useSchemaManager.js +97 -39
- package/dist/editor/hooks/useUserMetadata.d.ts +14 -4
- package/dist/editor/hooks/useUserMetadata.js +76 -47
- package/dist/editor/hooks/user-metadata-batcher.d.ts +8 -0
- package/dist/editor/hooks/user-metadata-batcher.js +33 -0
- package/dist/editor/media/AssetCard.d.ts +6 -7
- package/dist/editor/media/AssetCard.js +24 -31
- package/dist/editor/media/AssetListRow.d.ts +16 -0
- package/dist/editor/media/AssetListRow.js +41 -0
- package/dist/editor/media/CropStep.js +6 -1
- package/dist/editor/media/MediaLibrary.d.ts +4 -3
- package/dist/editor/media/MediaLibrary.js +11 -4
- package/dist/editor/media/MediaLibraryBody.d.ts +3 -3
- package/dist/editor/media/MediaLibraryBody.js +195 -80
- package/dist/editor/media/MediaLibrarySkeleton.d.ts +6 -0
- package/dist/editor/media/MediaLibrarySkeleton.js +14 -0
- package/dist/editor/media/crop-math.d.ts +3 -4
- package/dist/editor/media/crop-math.js +11 -22
- package/dist/editor/media/editor-image-src.d.ts +8 -0
- package/dist/editor/media/editor-image-src.js +10 -0
- package/dist/editor/media/format-bytes.d.ts +2 -0
- package/dist/editor/media/format-bytes.js +23 -0
- package/dist/editor/media/media-library-prefs.d.ts +23 -0
- package/dist/editor/media/media-library-prefs.js +49 -0
- package/dist/editor/media/media-library-view.d.ts +34 -0
- package/dist/editor/media/media-library-view.js +40 -0
- package/dist/editor/media/useAssetLibrary.d.ts +30 -0
- package/dist/editor/media/useAssetLibrary.js +126 -0
- package/dist/editor/media/useStableAssetOrder.d.ts +11 -0
- package/dist/editor/media/useStableAssetOrder.js +37 -0
- package/dist/editor/media/useThumbnailFailure.d.ts +6 -0
- package/dist/editor/media/useThumbnailFailure.js +16 -0
- package/dist/editor/permission-manager/GroupSelector.js +2 -2
- package/dist/editor/permission-manager/PermissionEditor.d.ts +1 -1
- package/dist/editor/permission-manager/PermissionEditor.js +15 -4
- package/dist/editor/permission-manager/PermissionLevelBadge.js +1 -1
- package/dist/editor/permission-manager/PermissionTree.d.ts +1 -1
- package/dist/editor/permission-manager/UserSelector.d.ts +1 -1
- package/dist/editor/permission-manager/UserSelector.js +3 -3
- package/dist/editor/permission-manager/index.js +12 -3
- package/dist/editor/permission-manager/types.d.ts +5 -2
- package/dist/editor/platform.d.ts +3 -0
- package/dist/editor/platform.js +9 -0
- package/dist/editor/preview-asset-base.d.ts +9 -0
- package/dist/editor/preview-asset-base.js +17 -0
- package/dist/editor/preview-bridge.d.ts +51 -27
- package/dist/editor/preview-bridge.js +103 -144
- package/dist/editor/preview-marks.d.ts +15 -0
- package/dist/editor/preview-marks.js +74 -0
- package/dist/editor/preview-path.d.ts +12 -0
- package/dist/editor/preview-path.js +45 -1
- package/dist/editor/preview-scale.d.ts +27 -0
- package/dist/editor/preview-scale.js +34 -0
- package/dist/editor/raw-asset-base.d.ts +5 -0
- package/dist/editor/raw-asset-base.js +14 -0
- package/dist/editor/relative-time.d.ts +4 -4
- package/dist/editor/relative-time.js +16 -8
- package/dist/editor/schema-editor/CollectionEditor.d.ts +20 -3
- package/dist/editor/schema-editor/CollectionEditor.js +361 -62
- package/dist/editor/schema-editor/EntryTypeEditor.d.ts +5 -1
- package/dist/editor/schema-editor/EntryTypeEditor.js +11 -6
- package/dist/editor/schema-editor/collection-draft.d.ts +22 -0
- package/dist/editor/schema-editor/collection-draft.js +40 -0
- package/dist/editor/schema-editor/index.d.ts +1 -1
- package/dist/editor/schema-label.d.ts +10 -0
- package/dist/editor/schema-label.js +17 -0
- package/dist/editor/settings-conflict.d.ts +5 -0
- package/dist/editor/settings-conflict.js +8 -0
- package/dist/editor/shell/ActivityRail.d.ts +37 -0
- package/dist/editor/shell/ActivityRail.js +91 -0
- package/dist/editor/shell/EditorShell.d.ts +17 -0
- package/dist/editor/shell/EditorShell.js +31 -0
- package/dist/editor/shell/PaneLayout.d.ts +28 -0
- package/dist/editor/shell/PaneLayout.js +116 -0
- package/dist/editor/shell/SidePanelHost.d.ts +35 -0
- package/dist/editor/shell/SidePanelHost.js +184 -0
- package/dist/editor/shell/TopBar.d.ts +12 -0
- package/dist/editor/shell/TopBar.js +14 -0
- package/dist/editor/shell/host-chrome.d.ts +16 -0
- package/dist/editor/shell/host-chrome.js +69 -0
- package/dist/editor/slug.d.ts +16 -0
- package/dist/editor/slug.js +43 -0
- package/dist/editor/theme.d.ts +2 -1
- package/dist/editor/theme.js +314 -13
- package/dist/editor/unanswered.d.ts +17 -0
- package/dist/editor/unanswered.js +26 -0
- package/dist/editor/unavailable-entry-type.d.ts +20 -0
- package/dist/editor/unavailable-entry-type.js +28 -0
- package/dist/editor/undo-removal.d.ts +57 -0
- package/dist/editor/undo-removal.js +163 -0
- package/dist/editor/user-display.d.ts +4 -0
- package/dist/editor/user-display.js +5 -0
- package/dist/editor/utils/confirm-modal.d.ts +8 -0
- package/dist/editor/utils/confirm-modal.js +12 -0
- package/dist/editor/utils/editor-errors.d.ts +19 -0
- package/dist/editor/utils/editor-errors.js +32 -0
- package/dist/editor/utils/focus-return.d.ts +56 -0
- package/dist/editor/utils/focus-return.js +106 -0
- package/dist/entry-link-resolver.d.ts +11 -1
- package/dist/entry-link-resolver.js +65 -5
- package/dist/entry-schema-registry.d.ts +3 -3
- package/dist/entry-schema-registry.js +7 -4
- package/dist/entry-schema.d.ts +49 -3
- package/dist/entry-schema.js +18 -0
- package/dist/git-manager.d.ts +172 -10
- package/dist/git-manager.js +449 -107
- package/dist/github-service.d.ts +39 -2
- package/dist/github-service.js +101 -7
- package/dist/http/handler.js +74 -9
- package/dist/http/types.d.ts +2 -0
- package/dist/http/worker-not-ready.d.ts +9 -4
- package/dist/http/worker-not-ready.js +59 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/item-keys.d.ts +46 -0
- package/dist/item-keys.js +235 -0
- package/dist/operating-mode/editor-mode-check.d.ts +15 -0
- package/dist/operating-mode/editor-mode-check.js +24 -0
- package/dist/operating-mode/mode-env.d.ts +13 -14
- package/dist/operating-mode/mode-env.js +13 -14
- package/dist/operating-mode/types.d.ts +2 -2
- package/dist/paths/branch.d.ts +0 -1
- package/dist/paths/branch.js +1 -8
- package/dist/paths/index.d.ts +1 -1
- package/dist/paths/index.js +1 -1
- package/dist/paths/validation.js +0 -2
- package/dist/preview.d.ts +8 -0
- package/dist/preview.js +7 -0
- package/dist/reference-resolver.js +1 -0
- package/dist/resolve-canopy-user.d.ts +1 -1
- package/dist/resolve-canopy-user.js +1 -1
- package/dist/schema/meta-loader.d.ts +18 -8
- package/dist/schema/meta-loader.js +42 -9
- package/dist/schema/registry-fingerprint.d.ts +14 -0
- package/dist/schema/registry-fingerprint.js +63 -0
- package/dist/schema/resolver.d.ts +7 -4
- package/dist/schema/resolver.js +7 -6
- package/dist/schema/schema-store.d.ts +7 -10
- package/dist/schema/schema-store.js +13 -11
- package/dist/schema/schema-unavailable-error.d.ts +11 -0
- package/dist/schema/schema-unavailable-error.js +15 -0
- package/dist/schema/types.d.ts +22 -0
- package/dist/schema-registry-record.d.ts +35 -0
- package/dist/schema-registry-record.js +134 -0
- package/dist/server.d.ts +79 -9
- package/dist/server.js +62 -8
- package/dist/services.d.ts +33 -5
- package/dist/services.js +155 -37
- package/dist/settings-workspace.d.ts +23 -3
- package/dist/settings-workspace.js +159 -45
- package/dist/stamp-on-publish.d.ts +36 -0
- package/dist/stamp-on-publish.js +71 -0
- package/dist/static/index.d.ts +58 -5
- package/dist/static/index.js +133 -3
- package/dist/static/seo.d.ts +5 -5
- package/dist/static/seo.js +5 -5
- package/dist/submission-attribution.d.ts +8 -0
- package/dist/submission-attribution.js +22 -0
- package/dist/system-users.d.ts +12 -0
- package/dist/system-users.js +12 -0
- package/dist/task-queue/cms-task-queue.d.ts +1 -1
- package/dist/task-queue/cms-task-queue.js +1 -1
- package/dist/task-queue/index.d.ts +1 -1
- package/dist/task-queue/index.js +1 -1
- package/dist/task-queue/task-queue.d.ts +6 -0
- package/dist/task-queue/task-queue.js +29 -0
- package/dist/task-queue/worker-status.d.ts +35 -9
- package/dist/task-queue/worker-status.js +84 -17
- package/dist/types.d.ts +90 -9
- package/dist/url-collision.js +3 -3
- package/dist/url-exclusivity-fixtures.d.ts +8 -1
- package/dist/url-exclusivity-fixtures.js +11 -1
- package/dist/user.js +2 -1
- package/dist/utils/atomic-write.js +2 -1
- package/dist/utils/base-branch.d.ts +13 -0
- package/dist/utils/base-branch.js +23 -0
- package/dist/utils/content-serialize.d.ts +15 -7
- package/dist/utils/content-serialize.js +353 -51
- package/dist/utils/content-write-lock.d.ts +6 -1
- package/dist/utils/content-write-lock.js +21 -6
- package/dist/utils/debug.d.ts +1 -1
- package/dist/utils/debug.js +5 -3
- package/dist/utils/error.js +13 -2
- package/dist/utils/escape-text.d.ts +7 -0
- package/dist/utils/escape-text.js +27 -0
- package/dist/utils/fs.d.ts +12 -4
- package/dist/utils/fs.js +18 -5
- package/dist/utils/git.d.ts +21 -1
- package/dist/utils/git.js +63 -8
- package/dist/utils/json-source-splice.d.ts +14 -0
- package/dist/utils/json-source-splice.js +120 -0
- package/dist/utils/markdown-body-splice.d.ts +39 -0
- package/dist/utils/markdown-body-splice.js +421 -0
- package/dist/utils/occ-json-write.js +18 -12
- package/dist/utils/provision-log.d.ts +25 -0
- package/dist/utils/provision-log.js +49 -0
- package/dist/utils/provisioning-lock.d.ts +32 -1
- package/dist/utils/provisioning-lock.js +78 -32
- package/dist/utils/sanitize-href.d.ts +9 -23
- package/dist/utils/sanitize-href.js +14 -28
- package/dist/utils/title-field.d.ts +10 -0
- package/dist/utils/title-field.js +47 -0
- package/dist/utils/yaml-source-splice.d.ts +58 -0
- package/dist/utils/yaml-source-splice.js +515 -0
- package/dist/validation/block-structural-keys.d.ts +1 -1
- package/dist/validation/block-structural-keys.js +1 -1
- package/dist/validation/deletion-checker.d.ts +21 -29
- package/dist/validation/deletion-checker.js +41 -117
- package/dist/validation/entry-validator.d.ts +6 -10
- package/dist/validation/entry-validator.js +19 -26
- package/dist/validation/field-traversal.d.ts +22 -0
- package/dist/validation/field-traversal.js +39 -8
- package/dist/validation/markdown-safety.d.ts +68 -0
- package/dist/validation/markdown-safety.js +596 -0
- package/dist/validation/mdx-allowlist.d.ts +55 -0
- package/dist/validation/mdx-allowlist.js +183 -0
- package/dist/validation/reference-validator.d.ts +2 -0
- package/dist/validation/reference-validator.js +3 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/branch-policy.d.ts +124 -0
- package/dist/worker/branch-policy.js +243 -0
- package/dist/worker/bundle-header.d.ts +117 -0
- package/dist/worker/bundle-header.js +253 -0
- package/dist/worker/cms-worker.d.ts +236 -142
- package/dist/worker/cms-worker.js +772 -285
- package/dist/worker/gateway-egress.d.ts +43 -0
- package/dist/worker/gateway-egress.js +209 -0
- package/dist/worker/gateway-instance.d.ts +42 -0
- package/dist/worker/gateway-instance.js +129 -0
- package/dist/worker/git-process.d.ts +81 -0
- package/dist/worker/git-process.js +234 -0
- package/dist/worker/git-sync.d.ts +34 -17
- package/dist/worker/git-sync.js +394 -131
- package/dist/worker/github-auth.d.ts +9 -9
- package/dist/worker/github-auth.js +13 -15
- package/dist/worker/github-gateway-http.d.ts +62 -0
- package/dist/worker/github-gateway-http.js +977 -0
- package/dist/worker/github-gateway-wire.d.ts +590 -0
- package/dist/worker/github-gateway-wire.js +488 -0
- package/dist/worker/github-gateway.d.ts +238 -0
- package/dist/worker/github-gateway.js +726 -0
- package/dist/worker/github-mirror-upkeep.d.ts +75 -0
- package/dist/worker/github-mirror-upkeep.js +266 -0
- package/dist/worker/github-mirror.d.ts +364 -0
- package/dist/worker/github-mirror.js +1030 -0
- package/dist/worker/github-transfer.d.ts +56 -0
- package/dist/worker/github-transfer.js +444 -0
- package/dist/worker/history-rewrite.d.ts +4 -5
- package/dist/worker/history-rewrite.js +12 -17
- package/dist/worker/provisioned-workspace.d.ts +5 -5
- package/dist/worker/provisioned-workspace.js +5 -5
- package/dist/worker/rebase.d.ts +1 -1
- package/dist/worker/rebase.js +58 -54
- package/dist/worker/remote-git-maintenance.d.ts +3 -0
- package/dist/worker/remote-git-maintenance.js +12 -0
- package/dist/worker/schema-gate.d.ts +49 -0
- package/dist/worker/schema-gate.js +226 -0
- package/dist/worker/self-checks.d.ts +107 -0
- package/dist/worker/self-checks.js +358 -0
- package/dist/worker/shared-repo-git.d.ts +96 -0
- package/dist/worker/shared-repo-git.js +459 -0
- package/dist/worker/sparse-cone.d.ts +20 -0
- package/dist/worker/sparse-cone.js +136 -0
- package/dist/worker/stale-mirror.d.ts +82 -0
- package/dist/worker/stale-mirror.js +130 -0
- package/dist/worker/task-runner.d.ts +5 -3
- package/dist/worker/task-runner.js +287 -186
- package/dist/worker/worker-context.d.ts +36 -37
- package/package.json +35 -7
- package/dist/editor/EditorPanes.d.ts +0 -10
- package/dist/editor/EditorPanes.js +0 -98
- package/dist/editor/components/EditorFooter.d.ts +0 -11
- package/dist/editor/components/EditorFooter.js +0 -9
- package/dist/editor/components/EditorSidebar.d.ts +0 -67
- package/dist/editor/components/EditorSidebar.js +0 -22
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an MDX body may hold, as `markdown-safety.ts` enforces it and as config validation and
|
|
3
|
+
* the editor read it. Dependency-free, so config schemas and the client bundle can import it
|
|
4
|
+
* without the MDX parser.
|
|
5
|
+
*
|
|
6
|
+
* An `MdxAllowlist` only narrows the base policy: a tag outside `SAFE_HTML_TAGS`, a name that is
|
|
7
|
+
* not a component, and a prop the base policy refuses are config errors, and every base rule
|
|
8
|
+
* still runs on what the allowlist accepts.
|
|
9
|
+
*/
|
|
10
|
+
/** HTML tags an MDX body may use: content elements whose attributes carry no code. */
|
|
11
|
+
export const SAFE_HTML_TAGS = new Set([
|
|
12
|
+
'a',
|
|
13
|
+
'abbr',
|
|
14
|
+
'address',
|
|
15
|
+
'article',
|
|
16
|
+
'aside',
|
|
17
|
+
'audio',
|
|
18
|
+
'b',
|
|
19
|
+
'bdi',
|
|
20
|
+
'bdo',
|
|
21
|
+
'blockquote',
|
|
22
|
+
'br',
|
|
23
|
+
'caption',
|
|
24
|
+
'cite',
|
|
25
|
+
'code',
|
|
26
|
+
'col',
|
|
27
|
+
'colgroup',
|
|
28
|
+
'data',
|
|
29
|
+
'dd',
|
|
30
|
+
'del',
|
|
31
|
+
'details',
|
|
32
|
+
'dfn',
|
|
33
|
+
'div',
|
|
34
|
+
'dl',
|
|
35
|
+
'dt',
|
|
36
|
+
'em',
|
|
37
|
+
'figcaption',
|
|
38
|
+
'figure',
|
|
39
|
+
'footer',
|
|
40
|
+
'h1',
|
|
41
|
+
'h2',
|
|
42
|
+
'h3',
|
|
43
|
+
'h4',
|
|
44
|
+
'h5',
|
|
45
|
+
'h6',
|
|
46
|
+
'header',
|
|
47
|
+
'hgroup',
|
|
48
|
+
'hr',
|
|
49
|
+
'i',
|
|
50
|
+
'img',
|
|
51
|
+
'ins',
|
|
52
|
+
'kbd',
|
|
53
|
+
'li',
|
|
54
|
+
'main',
|
|
55
|
+
'mark',
|
|
56
|
+
'nav',
|
|
57
|
+
'ol',
|
|
58
|
+
'p',
|
|
59
|
+
'picture',
|
|
60
|
+
'pre',
|
|
61
|
+
'q',
|
|
62
|
+
'rp',
|
|
63
|
+
'rt',
|
|
64
|
+
'ruby',
|
|
65
|
+
's',
|
|
66
|
+
'samp',
|
|
67
|
+
'section',
|
|
68
|
+
'small',
|
|
69
|
+
'source',
|
|
70
|
+
'span',
|
|
71
|
+
'strong',
|
|
72
|
+
'sub',
|
|
73
|
+
'summary',
|
|
74
|
+
'sup',
|
|
75
|
+
'table',
|
|
76
|
+
'tbody',
|
|
77
|
+
'td',
|
|
78
|
+
'tfoot',
|
|
79
|
+
'th',
|
|
80
|
+
'thead',
|
|
81
|
+
'time',
|
|
82
|
+
'tr',
|
|
83
|
+
'track',
|
|
84
|
+
'u',
|
|
85
|
+
'ul',
|
|
86
|
+
'var',
|
|
87
|
+
'video',
|
|
88
|
+
'wbr',
|
|
89
|
+
]);
|
|
90
|
+
/**
|
|
91
|
+
* A JSX name MDX resolves from the site's components rather than rendering as an HTML tag. A name
|
|
92
|
+
* led by `_` or `$` could name one of MDX's own bindings, as could the two below.
|
|
93
|
+
*/
|
|
94
|
+
const COMPONENT_NAME = /^[A-Z][\w$]*$/;
|
|
95
|
+
const MDX_BINDINGS = new Set(['MDXContent', 'MDXLayout']);
|
|
96
|
+
export function isComponentName(name) {
|
|
97
|
+
return COMPONENT_NAME.test(name) && !MDX_BINDINGS.has(name);
|
|
98
|
+
}
|
|
99
|
+
/** Attribute names, lower-cased, that put markup or a document into the page. */
|
|
100
|
+
export const FORBIDDEN_ATTRIBUTES = new Set([
|
|
101
|
+
'dangerouslysetinnerhtml',
|
|
102
|
+
'srcdoc',
|
|
103
|
+
]);
|
|
104
|
+
/**
|
|
105
|
+
* A component prop the base policy always refuses: an event handler by React's convention
|
|
106
|
+
* (`onClick`, while `online` stays a plain prop), or one in `FORBIDDEN_ATTRIBUTES`.
|
|
107
|
+
*/
|
|
108
|
+
export function isRefusedComponentProp(name) {
|
|
109
|
+
return /^on[A-Z]/.test(name) || FORBIDDEN_ATTRIBUTES.has(name.toLowerCase());
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* A string two allowlists share only if they accept the same MDX. Two spellings of one allowlist
|
|
113
|
+
* (value order, the full tag set listed out) can differ, which only ever refuses keeping content.
|
|
114
|
+
*/
|
|
115
|
+
export function allowlistIdentity(allow) {
|
|
116
|
+
const components = allow.components === undefined
|
|
117
|
+
? null
|
|
118
|
+
: [...allow.components]
|
|
119
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
120
|
+
.map(([name, props]) => [
|
|
121
|
+
name,
|
|
122
|
+
props === undefined
|
|
123
|
+
? null
|
|
124
|
+
: [...props].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)),
|
|
125
|
+
]);
|
|
126
|
+
const htmlTags = allow.htmlTags === SAFE_HTML_TAGS ? null : [...allow.htmlTags].sort();
|
|
127
|
+
return JSON.stringify([components, htmlTags, allow.expressions, allow.fragments]);
|
|
128
|
+
}
|
|
129
|
+
/** Each key the field sets replaces the site's; a key neither sets keeps the base policy. */
|
|
130
|
+
export function resolveMdxAllowlist(field, site) {
|
|
131
|
+
const components = field?.components ?? site?.components;
|
|
132
|
+
const htmlTags = field?.htmlTags ?? site?.htmlTags;
|
|
133
|
+
return {
|
|
134
|
+
components: components === undefined
|
|
135
|
+
? undefined
|
|
136
|
+
: new Map(Object.entries(components).map(([name, { props }]) => [
|
|
137
|
+
name,
|
|
138
|
+
props === undefined ? undefined : new Map(Object.entries(props)),
|
|
139
|
+
])),
|
|
140
|
+
htmlTags: htmlTags === undefined ? SAFE_HTML_TAGS : new Set(htmlTags),
|
|
141
|
+
expressions: field?.expressions ?? site?.expressions ?? true,
|
|
142
|
+
fragments: field?.fragments ?? site?.fragments ?? true,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export function isMarkdownField(field) {
|
|
146
|
+
return field.type === 'markdown' || field.type === 'mdx';
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* The policy the server enforces and the editor follows, or undefined for an `executable` field. A
|
|
150
|
+
* field is MDX when typed `mdx` or set `renderAs: 'mdx'`. An entry's body (`bodyFormat` given, its
|
|
151
|
+
* field possibly undeclared) follows the entry instead: MDX in an `mdx` entry, and in an `md` entry
|
|
152
|
+
* only with `renderAs: 'mdx'`, since a site renders an `md` file as markdown.
|
|
153
|
+
*/
|
|
154
|
+
export function markdownPolicyOf(field, site, bodyFormat) {
|
|
155
|
+
if (field?.executable === true)
|
|
156
|
+
return undefined;
|
|
157
|
+
const mdx = bodyFormat === undefined
|
|
158
|
+
? field?.type === 'mdx' || field?.renderAs === 'mdx'
|
|
159
|
+
: bodyFormat === 'mdx' || field?.renderAs === 'mdx';
|
|
160
|
+
return { dialect: mdx ? 'mdx' : 'md', allow: resolveMdxAllowlist(field?.mdxAllow, site) };
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Why a markdown or mdx field's `renderAs`, `mdxAllow` and `executable` contradict each other, or
|
|
164
|
+
* undefined. An allowlist that cannot apply would look like protection it is not.
|
|
165
|
+
*/
|
|
166
|
+
export function markdownFieldOptionsError(field) {
|
|
167
|
+
const renderAs = field.renderAs;
|
|
168
|
+
if (renderAs !== undefined && renderAs !== 'mdx') {
|
|
169
|
+
return `Field "${field.name}": renderAs must be 'mdx'`;
|
|
170
|
+
}
|
|
171
|
+
if (renderAs !== undefined && field.type === 'mdx') {
|
|
172
|
+
return `Field "${field.name}": renderAs applies only to markdown fields`;
|
|
173
|
+
}
|
|
174
|
+
if (field.mdxAllow === undefined)
|
|
175
|
+
return undefined;
|
|
176
|
+
if (field.executable === true) {
|
|
177
|
+
return `Field "${field.name}": mdxAllow has no effect with executable: true, which turns the check off`;
|
|
178
|
+
}
|
|
179
|
+
if (field.type === 'markdown' && field.renderAs !== 'mdx') {
|
|
180
|
+
return `Field "${field.name}": mdxAllow applies to MDX; set renderAs: 'mdx' on a markdown field the site renders as MDX`;
|
|
181
|
+
}
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
@@ -54,6 +54,7 @@ export class ReferenceValidator {
|
|
|
54
54
|
fieldPath,
|
|
55
55
|
id: String(id),
|
|
56
56
|
error: 'Invalid content ID format',
|
|
57
|
+
...(typeof id === 'string' ? { dangling: true } : {}),
|
|
57
58
|
});
|
|
58
59
|
continue;
|
|
59
60
|
}
|
|
@@ -64,6 +65,7 @@ export class ReferenceValidator {
|
|
|
64
65
|
fieldPath,
|
|
65
66
|
id,
|
|
66
67
|
error: 'Referenced entry does not exist',
|
|
68
|
+
dangling: true,
|
|
67
69
|
});
|
|
68
70
|
continue;
|
|
69
71
|
}
|
|
@@ -73,6 +75,7 @@ export class ReferenceValidator {
|
|
|
73
75
|
fieldPath,
|
|
74
76
|
id,
|
|
75
77
|
error: 'ID points to a collection, not an entry',
|
|
78
|
+
dangling: true,
|
|
76
79
|
});
|
|
77
80
|
continue;
|
|
78
81
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CANOPYCMS_VERSION = "0.0
|
|
1
|
+
export declare const CANOPYCMS_VERSION = "0.1.0";
|
package/dist/version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// Generated by scripts/bump-version.mjs, its only writer. The package builds with plain
|
|
2
2
|
// tsc (rootDir: src), so src/ cannot import ../package.json; version.test.ts keeps the two equal.
|
|
3
|
-
export const CANOPYCMS_VERSION = '0.0
|
|
3
|
+
export const CANOPYCMS_VERSION = '0.1.0';
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How long GitHub's default branch, once read, is taken to be still the default.
|
|
3
|
+
* @internal Exported for tests.
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_BRANCH_TTL_MS: number;
|
|
6
|
+
/** The longest branch name the gateway takes, in characters. */
|
|
7
|
+
export declare const MAX_BRANCH_NAME_LENGTH = 255;
|
|
8
|
+
/**
|
|
9
|
+
* The longest pull request title the gateway sends, in UTF-16 code units.
|
|
10
|
+
* @internal Exported for tests.
|
|
11
|
+
*/
|
|
12
|
+
export declare const MAX_PULL_REQUEST_TITLE_LENGTH = 1024;
|
|
13
|
+
/**
|
|
14
|
+
* The longest pull request body the gateway sends: GitHub's own limit.
|
|
15
|
+
* @internal Exported for tests.
|
|
16
|
+
*/
|
|
17
|
+
export declare const MAX_PULL_REQUEST_BODY_LENGTH = 65536;
|
|
18
|
+
export type GatewayOperation = 'push' | 'delete' | 'pull-request';
|
|
19
|
+
export type RefusalReason = 'invalid' | 'protected' | 'settings' | 'not-a-commit' | 'too-long';
|
|
20
|
+
/**
|
|
21
|
+
* Something the gateway refuses to do for any caller. No CanopyCMS flow asks for it, so no retry
|
|
22
|
+
* can change the answer: the task runner fails such a task permanently, and a refusal never arms
|
|
23
|
+
* the credential re-read (`LocalGitHubGateway.credentialed`).
|
|
24
|
+
*/
|
|
25
|
+
export declare class GatewayRefusalError extends Error {
|
|
26
|
+
readonly operation: GatewayOperation;
|
|
27
|
+
readonly branch: string;
|
|
28
|
+
readonly reason: RefusalReason;
|
|
29
|
+
constructor(operation: GatewayOperation, branch: string, reason: RefusalReason, message: string);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Why `branch` is not a name the gateway takes, before git sees it, or null. Printable ASCII only,
|
|
33
|
+
* so no two names differ invisibly; no `"`, `%`, `{` or `}`, which reach URLs and log lines; no
|
|
34
|
+
* leading `-`; no leading `refs/`, `heads/`, `tags/` or `remotes/`, which git's ref lookup could
|
|
35
|
+
* read as some other ref than `refs/heads/<branch>`.
|
|
36
|
+
* `git check-ref-format --branch` runs after this (`assertPlainBranchName`).
|
|
37
|
+
*/
|
|
38
|
+
export declare function branchNameProblem(branch: string): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Why `pattern` cannot be a `protectedBranches` entry, or null. An entry is a branch name in which
|
|
41
|
+
* `*` matches any run of characters, `/` included; nothing else is a wildcard. A character no
|
|
42
|
+
* branch name can hold is refused rather than left to match nothing, so a list never protects
|
|
43
|
+
* less than it seems to.
|
|
44
|
+
* @internal Exported for tests.
|
|
45
|
+
*/
|
|
46
|
+
export declare function protectedPatternProblem(pattern: string): string | null;
|
|
47
|
+
/**
|
|
48
|
+
* Whether `name` matches `pattern`, where `*` matches any run of characters. Never a regex.
|
|
49
|
+
* @internal Exported for tests.
|
|
50
|
+
*/
|
|
51
|
+
export declare function matchesBranchPattern(pattern: string, name: string): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* The most `protectedBranches` entries a policy takes. The wire answer lists them plus the base
|
|
54
|
+
* branch (`describe()`), so its bound is one above this.
|
|
55
|
+
*/
|
|
56
|
+
export declare const MAX_PROTECTED_BRANCHES = 1024;
|
|
57
|
+
export interface BranchPolicyOptions {
|
|
58
|
+
/** The configured base branch (`CANOPYCMS_BASE_BRANCH`); never one read from the workspace. */
|
|
59
|
+
baseBranch?: string;
|
|
60
|
+
/** Further protected names and `*` globs (`CANOPYCMS_PROTECTED_BRANCHES`). */
|
|
61
|
+
protectedBranches?: readonly string[];
|
|
62
|
+
/** Test seam: the clock {@link DEFAULT_BRANCH_TTL_MS} is measured on. */
|
|
63
|
+
now?: () => number;
|
|
64
|
+
}
|
|
65
|
+
/** Reads GitHub's default branch: null for a repository with none. */
|
|
66
|
+
export type DefaultBranchReader = () => Promise<string | null>;
|
|
67
|
+
/**
|
|
68
|
+
* The protected set and the settings rules.
|
|
69
|
+
*
|
|
70
|
+
* A branch is protected when it is the configured base branch, GitHub's default branch or a
|
|
71
|
+
* `protectedBranches` entry, compared case-sensitively as GitHub compares refs. An exact entry
|
|
72
|
+
* also matches a name that sanitizes to the same workspace directory; a glob never matches a
|
|
73
|
+
* settings branch, whose plain push the worker needs. GitHub's default is re-read once
|
|
74
|
+
* {@link DEFAULT_BRANCH_TTL_MS} has passed since the read that set it, so a change of default
|
|
75
|
+
* takes up to that long to reach the set. A failed read is never cached: the operation fails.
|
|
76
|
+
* Reads are not shared between concurrent callers, because a push reads inside a mirror session
|
|
77
|
+
* and an operation that joined it from outside one would wait on that session.
|
|
78
|
+
*
|
|
79
|
+
* Settings branches are pushed plainly or not at all: no lease, no deletion, no pull request.
|
|
80
|
+
* One is a name with the reserved prefix, the task runner's own test (`isSettingsBranch`): branch
|
|
81
|
+
* creation refuses the prefix, while a configured settings name without it could be a content
|
|
82
|
+
* branch's.
|
|
83
|
+
*/
|
|
84
|
+
export declare class BranchPolicy {
|
|
85
|
+
private readonly exact;
|
|
86
|
+
private readonly globs;
|
|
87
|
+
private readonly now;
|
|
88
|
+
private githubDefault;
|
|
89
|
+
constructor(options?: BranchPolicyOptions);
|
|
90
|
+
/** The protected set as it stands: configured names and globs, and GitHub's default as last read. */
|
|
91
|
+
describe(): {
|
|
92
|
+
configured: string[];
|
|
93
|
+
githubDefault: string | null;
|
|
94
|
+
};
|
|
95
|
+
/** Whether `branch` is protected; GitHub's default is read only when nothing else matches. */
|
|
96
|
+
isProtected(branch: string, readDefault: DefaultBranchReader): Promise<boolean>;
|
|
97
|
+
/** Refuse a push to a protected branch, or a leased push to a settings branch. */
|
|
98
|
+
assertPushAllowed(branch: string, lease: string | undefined, readDefault: DefaultBranchReader, refuse: (reason: 'protected' | 'settings') => Error): Promise<void>;
|
|
99
|
+
/** Refuse to delete a protected branch or a settings branch. */
|
|
100
|
+
assertDeleteAllowed(branch: string, readDefault: DefaultBranchReader): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Refuse a pull request whose head is protected or a settings branch, or whose text is over its
|
|
103
|
+
* cap. The base is not restricted: a branch keeps the base it was created from after the
|
|
104
|
+
* adopter moves theirs, and a pull request merges nothing by itself.
|
|
105
|
+
*/
|
|
106
|
+
assertPullRequestAllowed(request: {
|
|
107
|
+
head: string;
|
|
108
|
+
title?: string;
|
|
109
|
+
body?: string;
|
|
110
|
+
}, readDefault: DefaultBranchReader): Promise<void>;
|
|
111
|
+
private isSettings;
|
|
112
|
+
private matchesConfigured;
|
|
113
|
+
private githubDefaultBranch;
|
|
114
|
+
/**
|
|
115
|
+
* Read GitHub's default branch now and keep it. A read that started before the one already kept
|
|
116
|
+
* never replaces it.
|
|
117
|
+
*/
|
|
118
|
+
recordGitHubDefault(readDefault: DefaultBranchReader): Promise<string | null>;
|
|
119
|
+
}
|
|
120
|
+
/** Refuse pull request text over its cap; `refusing` opens the message, `branch` names its head. */
|
|
121
|
+
export declare function assertPullRequestText(refusing: string, branch: string, text: {
|
|
122
|
+
title?: string;
|
|
123
|
+
body?: string;
|
|
124
|
+
}): void;
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The GitHub gateway's branch policy: what it never does to GitHub, whatever the worker asks. The
|
|
3
|
+
* task queue, remote.git and every branch's metadata are on the shared workspace, which the CMS
|
|
4
|
+
* Lambda can write, so nothing here takes a branch to protect from a request.
|
|
5
|
+
*/
|
|
6
|
+
import { RESERVED_SETTINGS_BRANCH_PREFIX, sanitizeBranchName } from '../paths/branch-name.js';
|
|
7
|
+
/**
|
|
8
|
+
* How long GitHub's default branch, once read, is taken to be still the default.
|
|
9
|
+
* @internal Exported for tests.
|
|
10
|
+
*/
|
|
11
|
+
export const DEFAULT_BRANCH_TTL_MS = 10 * 60_000;
|
|
12
|
+
/** The longest branch name the gateway takes, in characters. */
|
|
13
|
+
export const MAX_BRANCH_NAME_LENGTH = 255;
|
|
14
|
+
/**
|
|
15
|
+
* The longest pull request title the gateway sends, in UTF-16 code units.
|
|
16
|
+
* @internal Exported for tests.
|
|
17
|
+
*/
|
|
18
|
+
export const MAX_PULL_REQUEST_TITLE_LENGTH = 1024;
|
|
19
|
+
/**
|
|
20
|
+
* The longest pull request body the gateway sends: GitHub's own limit.
|
|
21
|
+
* @internal Exported for tests.
|
|
22
|
+
*/
|
|
23
|
+
export const MAX_PULL_REQUEST_BODY_LENGTH = 65_536;
|
|
24
|
+
/**
|
|
25
|
+
* Something the gateway refuses to do for any caller. No CanopyCMS flow asks for it, so no retry
|
|
26
|
+
* can change the answer: the task runner fails such a task permanently, and a refusal never arms
|
|
27
|
+
* the credential re-read (`LocalGitHubGateway.credentialed`).
|
|
28
|
+
*/
|
|
29
|
+
export class GatewayRefusalError extends Error {
|
|
30
|
+
constructor(operation, branch, reason, message) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.operation = operation;
|
|
33
|
+
this.branch = branch;
|
|
34
|
+
this.reason = reason;
|
|
35
|
+
this.name = 'GatewayRefusalError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const deleting = (branch) => `Refusing to delete ${JSON.stringify(branch)} on GitHub`;
|
|
39
|
+
const openingFrom = (head) => `Refusing to open a pull request from ${JSON.stringify(head)}`;
|
|
40
|
+
const PROTECTED_WHY = "it is protected (the base branch, GitHub's default branch, or a name protectedBranches " +
|
|
41
|
+
'lists), which the CanopyCMS worker never changes. Nothing in CanopyCMS queues this; find out ' +
|
|
42
|
+
'what wrote this task.';
|
|
43
|
+
/**
|
|
44
|
+
* Why `branch` is not a name the gateway takes, before git sees it, or null. Printable ASCII only,
|
|
45
|
+
* so no two names differ invisibly; no `"`, `%`, `{` or `}`, which reach URLs and log lines; no
|
|
46
|
+
* leading `-`; no leading `refs/`, `heads/`, `tags/` or `remotes/`, which git's ref lookup could
|
|
47
|
+
* read as some other ref than `refs/heads/<branch>`.
|
|
48
|
+
* `git check-ref-format --branch` runs after this (`assertPlainBranchName`).
|
|
49
|
+
*/
|
|
50
|
+
export function branchNameProblem(branch) {
|
|
51
|
+
if (branch.length === 0 || branch.length > MAX_BRANCH_NAME_LENGTH) {
|
|
52
|
+
return `a branch name is 1 to ${MAX_BRANCH_NAME_LENGTH} characters`;
|
|
53
|
+
}
|
|
54
|
+
if (!/^[\x21-\x7e]+$/.test(branch))
|
|
55
|
+
return 'it is not printable ASCII';
|
|
56
|
+
if (/["%{}]/.test(branch))
|
|
57
|
+
return 'it contains ", %, { or }';
|
|
58
|
+
if (branch.startsWith('-'))
|
|
59
|
+
return "it starts with '-'";
|
|
60
|
+
if (/^(?:refs|heads|tags|remotes)\//i.test(branch)) {
|
|
61
|
+
return "it starts with 'refs/', 'heads/', 'tags/' or 'remotes/'";
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Why `pattern` cannot be a `protectedBranches` entry, or null. An entry is a branch name in which
|
|
67
|
+
* `*` matches any run of characters, `/` included; nothing else is a wildcard. A character no
|
|
68
|
+
* branch name can hold is refused rather than left to match nothing, so a list never protects
|
|
69
|
+
* less than it seems to.
|
|
70
|
+
* @internal Exported for tests.
|
|
71
|
+
*/
|
|
72
|
+
export function protectedPatternProblem(pattern) {
|
|
73
|
+
const named = branchNameProblem(pattern.replace(/\*/g, 'x'));
|
|
74
|
+
if (named !== null)
|
|
75
|
+
return named;
|
|
76
|
+
if (/[~^:?[\\]/.test(pattern))
|
|
77
|
+
return 'only * is a wildcard, and ~ ^ : ? [ \\ are not in branch names';
|
|
78
|
+
if (pattern.includes('..') || pattern.includes('@{') || pattern.includes('//')) {
|
|
79
|
+
return "it contains '..', '@{' or '//'";
|
|
80
|
+
}
|
|
81
|
+
if (pattern.startsWith('/') || pattern.endsWith('/') || pattern.endsWith('.')) {
|
|
82
|
+
return "it starts or ends with '/', or ends with '.'";
|
|
83
|
+
}
|
|
84
|
+
if (pattern.startsWith(RESERVED_SETTINGS_BRANCH_PREFIX)) {
|
|
85
|
+
return pattern.includes('*')
|
|
86
|
+
? `a glob never matches a settings branch, so one starting ${RESERVED_SETTINGS_BRANCH_PREFIX} matches nothing`
|
|
87
|
+
: "a settings branch is pushed plainly every sync, so protecting it would stop this deployment's settings reaching GitHub";
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Whether `name` matches `pattern`, where `*` matches any run of characters. Never a regex.
|
|
93
|
+
* @internal Exported for tests.
|
|
94
|
+
*/
|
|
95
|
+
export function matchesBranchPattern(pattern, name) {
|
|
96
|
+
const parts = pattern.split('*');
|
|
97
|
+
const first = parts[0];
|
|
98
|
+
const last = parts[parts.length - 1];
|
|
99
|
+
if (parts.length === 1)
|
|
100
|
+
return pattern === name;
|
|
101
|
+
if (name.length < first.length + last.length)
|
|
102
|
+
return false;
|
|
103
|
+
if (!name.startsWith(first) || !name.endsWith(last))
|
|
104
|
+
return false;
|
|
105
|
+
let at = first.length;
|
|
106
|
+
const end = name.length - last.length;
|
|
107
|
+
for (const part of parts.slice(1, -1)) {
|
|
108
|
+
const found = name.indexOf(part, at);
|
|
109
|
+
if (found === -1 || found + part.length > end)
|
|
110
|
+
return false;
|
|
111
|
+
at = found + part.length;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The most `protectedBranches` entries a policy takes. The wire answer lists them plus the base
|
|
117
|
+
* branch (`describe()`), so its bound is one above this.
|
|
118
|
+
*/
|
|
119
|
+
export const MAX_PROTECTED_BRANCHES = 1024;
|
|
120
|
+
/**
|
|
121
|
+
* The protected set and the settings rules.
|
|
122
|
+
*
|
|
123
|
+
* A branch is protected when it is the configured base branch, GitHub's default branch or a
|
|
124
|
+
* `protectedBranches` entry, compared case-sensitively as GitHub compares refs. An exact entry
|
|
125
|
+
* also matches a name that sanitizes to the same workspace directory; a glob never matches a
|
|
126
|
+
* settings branch, whose plain push the worker needs. GitHub's default is re-read once
|
|
127
|
+
* {@link DEFAULT_BRANCH_TTL_MS} has passed since the read that set it, so a change of default
|
|
128
|
+
* takes up to that long to reach the set. A failed read is never cached: the operation fails.
|
|
129
|
+
* Reads are not shared between concurrent callers, because a push reads inside a mirror session
|
|
130
|
+
* and an operation that joined it from outside one would wait on that session.
|
|
131
|
+
*
|
|
132
|
+
* Settings branches are pushed plainly or not at all: no lease, no deletion, no pull request.
|
|
133
|
+
* One is a name with the reserved prefix, the task runner's own test (`isSettingsBranch`): branch
|
|
134
|
+
* creation refuses the prefix, while a configured settings name without it could be a content
|
|
135
|
+
* branch's.
|
|
136
|
+
*/
|
|
137
|
+
export class BranchPolicy {
|
|
138
|
+
constructor(options = {}) {
|
|
139
|
+
this.githubDefault = null;
|
|
140
|
+
this.now = options.now ?? (() => Date.now());
|
|
141
|
+
const entries = [...(options.protectedBranches ?? [])];
|
|
142
|
+
if (entries.length > MAX_PROTECTED_BRANCHES) {
|
|
143
|
+
throw new Error(`protectedBranches has ${entries.length} entries; the most it takes is ${MAX_PROTECTED_BRANCHES}`);
|
|
144
|
+
}
|
|
145
|
+
for (const entry of entries) {
|
|
146
|
+
const problem = protectedPatternProblem(entry);
|
|
147
|
+
if (problem !== null) {
|
|
148
|
+
throw new Error(`Invalid protectedBranches entry ${JSON.stringify(entry)}: ${problem}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (options.baseBranch !== undefined)
|
|
152
|
+
entries.push(options.baseBranch);
|
|
153
|
+
this.exact = entries.filter((entry) => !entry.includes('*'));
|
|
154
|
+
this.globs = entries.filter((entry) => entry.includes('*'));
|
|
155
|
+
}
|
|
156
|
+
/** The protected set as it stands: configured names and globs, and GitHub's default as last read. */
|
|
157
|
+
describe() {
|
|
158
|
+
return {
|
|
159
|
+
configured: [...this.exact, ...this.globs],
|
|
160
|
+
githubDefault: this.githubDefault?.name ?? null,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/** Whether `branch` is protected; GitHub's default is read only when nothing else matches. */
|
|
164
|
+
async isProtected(branch, readDefault) {
|
|
165
|
+
if (this.matchesConfigured(branch))
|
|
166
|
+
return true;
|
|
167
|
+
const githubDefault = await this.githubDefaultBranch(readDefault);
|
|
168
|
+
return githubDefault !== null && sameBranch(githubDefault, branch);
|
|
169
|
+
}
|
|
170
|
+
/** Refuse a push to a protected branch, or a leased push to a settings branch. */
|
|
171
|
+
async assertPushAllowed(branch, lease, readDefault, refuse) {
|
|
172
|
+
if (await this.isProtected(branch, readDefault))
|
|
173
|
+
throw refuse('protected');
|
|
174
|
+
if (lease !== undefined && this.isSettings(branch))
|
|
175
|
+
throw refuse('settings');
|
|
176
|
+
}
|
|
177
|
+
/** Refuse to delete a protected branch or a settings branch. */
|
|
178
|
+
async assertDeleteAllowed(branch, readDefault) {
|
|
179
|
+
if (this.isSettings(branch)) {
|
|
180
|
+
throw new GatewayRefusalError('delete', branch, 'settings', `${deleting(branch)}: it is a settings branch, which is never deleted`);
|
|
181
|
+
}
|
|
182
|
+
if (await this.isProtected(branch, readDefault)) {
|
|
183
|
+
throw new GatewayRefusalError('delete', branch, 'protected', `${deleting(branch)}: ${PROTECTED_WHY}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Refuse a pull request whose head is protected or a settings branch, or whose text is over its
|
|
188
|
+
* cap. The base is not restricted: a branch keeps the base it was created from after the
|
|
189
|
+
* adopter moves theirs, and a pull request merges nothing by itself.
|
|
190
|
+
*/
|
|
191
|
+
async assertPullRequestAllowed(request, readDefault) {
|
|
192
|
+
const { head } = request;
|
|
193
|
+
assertPullRequestText(openingFrom(head), head, request);
|
|
194
|
+
if (this.isSettings(head)) {
|
|
195
|
+
throw new GatewayRefusalError('pull-request', head, 'settings', `${openingFrom(head)}: it is a settings branch, which never gets one`);
|
|
196
|
+
}
|
|
197
|
+
if (await this.isProtected(head, readDefault)) {
|
|
198
|
+
throw new GatewayRefusalError('pull-request', head, 'protected', `${openingFrom(head)}: ${PROTECTED_WHY}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
isSettings(branch) {
|
|
202
|
+
return branch.startsWith(RESERVED_SETTINGS_BRANCH_PREFIX);
|
|
203
|
+
}
|
|
204
|
+
matchesConfigured(branch) {
|
|
205
|
+
return (this.exact.some((name) => sameBranch(name, branch)) ||
|
|
206
|
+
// A glob never takes in a settings branch, whose one allowed push (plain) the worker needs:
|
|
207
|
+
// `*-prod` would otherwise stop `canopycms-settings-prod` reaching GitHub.
|
|
208
|
+
(!this.isSettings(branch) && this.globs.some((glob) => matchesBranchPattern(glob, branch))));
|
|
209
|
+
}
|
|
210
|
+
async githubDefaultBranch(readDefault) {
|
|
211
|
+
const cached = this.githubDefault;
|
|
212
|
+
if (cached !== null && this.now() - cached.readAt < DEFAULT_BRANCH_TTL_MS)
|
|
213
|
+
return cached.name;
|
|
214
|
+
return this.recordGitHubDefault(readDefault);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Read GitHub's default branch now and keep it. A read that started before the one already kept
|
|
218
|
+
* never replaces it.
|
|
219
|
+
*/
|
|
220
|
+
async recordGitHubDefault(readDefault) {
|
|
221
|
+
const readAt = this.now();
|
|
222
|
+
const name = await readDefault();
|
|
223
|
+
if (this.githubDefault === null || readAt >= this.githubDefault.readAt) {
|
|
224
|
+
this.githubDefault = { name, readAt };
|
|
225
|
+
}
|
|
226
|
+
return name;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/** Refuse pull request text over its cap; `refusing` opens the message, `branch` names its head. */
|
|
230
|
+
export function assertPullRequestText(refusing, branch, text) {
|
|
231
|
+
const over = (text.title?.length ?? 0) > MAX_PULL_REQUEST_TITLE_LENGTH
|
|
232
|
+
? `its title is longer than ${MAX_PULL_REQUEST_TITLE_LENGTH} characters`
|
|
233
|
+
: (text.body?.length ?? 0) > MAX_PULL_REQUEST_BODY_LENGTH
|
|
234
|
+
? `its body is longer than ${MAX_PULL_REQUEST_BODY_LENGTH} characters`
|
|
235
|
+
: null;
|
|
236
|
+
if (over !== null) {
|
|
237
|
+
throw new GatewayRefusalError('pull-request', branch, 'too-long', `${refusing}: ${over}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/** Equal, or naming the same workspace directory. */
|
|
241
|
+
function sameBranch(a, b) {
|
|
242
|
+
return a === b || sanitizeBranchName(a) === sanitizeBranchName(b);
|
|
243
|
+
}
|