canopycms 0.0.0 → 0.0.2
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/dist/auth/plugin.d.ts +8 -0
- package/dist/auth/plugin.d.ts.map +1 -1
- package/dist/build-mode.d.ts +15 -5
- package/dist/build-mode.d.ts.map +1 -1
- package/dist/build-mode.js +18 -8
- package/dist/build-mode.js.map +1 -1
- package/dist/cli/init.d.ts +2 -2
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +37 -36
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/template-files/ai-config.ts.template +21 -0
- package/dist/cli/template-files/ai-route.ts.template +10 -0
- package/dist/cli/template-files/canopy.ts.template +24 -0
- package/dist/cli/templates.d.ts +5 -1
- package/dist/cli/templates.d.ts.map +1 -1
- package/dist/cli/templates.js +9 -2
- package/dist/cli/templates.js.map +1 -1
- package/dist/config/schemas/config.d.ts +4 -0
- package/dist/config/schemas/config.d.ts.map +1 -1
- package/dist/config/schemas/config.js +2 -0
- package/dist/config/schemas/config.js.map +1 -1
- package/dist/config/types.d.ts +5 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/content-reader.js +2 -2
- package/dist/content-reader.js.map +1 -1
- package/dist/context.js +5 -5
- package/dist/context.js.map +1 -1
- package/dist/operating-mode/client-unsafe-strategy.d.ts.map +1 -1
- package/dist/operating-mode/client-unsafe-strategy.js +15 -18
- package/dist/operating-mode/client-unsafe-strategy.js.map +1 -1
- package/dist/operating-mode/types.d.ts +8 -0
- package/dist/operating-mode/types.d.ts.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -1
- package/package.json +5 -4
- package/src/cli/init.ts +43 -38
- package/dist/__integration__/fixtures/content-seeds.d.ts +0 -43
- package/dist/__integration__/fixtures/content-seeds.d.ts.map +0 -1
- package/dist/__integration__/fixtures/content-seeds.js +0 -99
- package/dist/__integration__/fixtures/content-seeds.js.map +0 -1
- package/dist/__integration__/fixtures/schemas.d.ts +0 -12
- package/dist/__integration__/fixtures/schemas.d.ts.map +0 -1
- package/dist/__integration__/fixtures/schemas.js +0 -65
- package/dist/__integration__/fixtures/schemas.js.map +0 -1
- package/dist/__integration__/test-utils/api-client.d.ts +0 -123
- package/dist/__integration__/test-utils/api-client.d.ts.map +0 -1
- package/dist/__integration__/test-utils/api-client.js +0 -118
- package/dist/__integration__/test-utils/api-client.js.map +0 -1
- package/dist/__integration__/test-utils/multi-user.d.ts +0 -25
- package/dist/__integration__/test-utils/multi-user.d.ts.map +0 -1
- package/dist/__integration__/test-utils/multi-user.js +0 -105
- package/dist/__integration__/test-utils/multi-user.js.map +0 -1
- package/dist/__integration__/test-utils/test-workspace.d.ts +0 -25
- package/dist/__integration__/test-utils/test-workspace.d.ts.map +0 -1
- package/dist/__integration__/test-utils/test-workspace.js +0 -102
- package/dist/__integration__/test-utils/test-workspace.js.map +0 -1
- package/dist/editor/BranchManager.stories.d.ts +0 -8
- package/dist/editor/BranchManager.stories.d.ts.map +0 -1
- package/dist/editor/BranchManager.stories.js +0 -74
- package/dist/editor/BranchManager.stories.js.map +0 -1
- package/dist/editor/CanopyEditor.stories.d.ts +0 -7
- package/dist/editor/CanopyEditor.stories.d.ts.map +0 -1
- package/dist/editor/CanopyEditor.stories.js +0 -99
- package/dist/editor/CanopyEditor.stories.js.map +0 -1
- package/dist/editor/CommentsPanel.stories.d.ts +0 -10
- package/dist/editor/CommentsPanel.stories.d.ts.map +0 -1
- package/dist/editor/CommentsPanel.stories.js +0 -175
- package/dist/editor/CommentsPanel.stories.js.map +0 -1
- package/dist/editor/Editor.stories.d.ts +0 -7
- package/dist/editor/Editor.stories.d.ts.map +0 -1
- package/dist/editor/Editor.stories.js +0 -95
- package/dist/editor/Editor.stories.js.map +0 -1
- package/dist/editor/EditorPanes.stories.d.ts +0 -7
- package/dist/editor/EditorPanes.stories.d.ts.map +0 -1
- package/dist/editor/EditorPanes.stories.js +0 -116
- package/dist/editor/EditorPanes.stories.js.map +0 -1
- package/dist/editor/EntryNavigator.stories.d.ts +0 -8
- package/dist/editor/EntryNavigator.stories.d.ts.map +0 -1
- package/dist/editor/EntryNavigator.stories.js +0 -42
- package/dist/editor/EntryNavigator.stories.js.map +0 -1
- package/dist/editor/FormRenderer.stories.d.ts +0 -7
- package/dist/editor/FormRenderer.stories.d.ts.map +0 -1
- package/dist/editor/FormRenderer.stories.js +0 -115
- package/dist/editor/FormRenderer.stories.js.map +0 -1
- package/dist/editor/GroupManager.stories.d.ts +0 -19
- package/dist/editor/GroupManager.stories.d.ts.map +0 -1
- package/dist/editor/GroupManager.stories.js +0 -265
- package/dist/editor/GroupManager.stories.js.map +0 -1
- package/dist/editor/PermissionManager.stories.d.ts +0 -20
- package/dist/editor/PermissionManager.stories.d.ts.map +0 -1
- package/dist/editor/PermissionManager.stories.js +0 -506
- package/dist/editor/PermissionManager.stories.js.map +0 -1
- package/dist/editor/comments/FieldWrapper.stories.d.ts +0 -10
- package/dist/editor/comments/FieldWrapper.stories.d.ts.map +0 -1
- package/dist/editor/comments/FieldWrapper.stories.js +0 -173
- package/dist/editor/comments/FieldWrapper.stories.js.map +0 -1
- package/dist/editor/fields/BlockField.stories.d.ts +0 -7
- package/dist/editor/fields/BlockField.stories.d.ts.map +0 -1
- package/dist/editor/fields/BlockField.stories.js +0 -50
- package/dist/editor/fields/BlockField.stories.js.map +0 -1
- package/dist/editor/fields/fields.stories.d.ts +0 -8
- package/dist/editor/fields/fields.stories.d.ts.map +0 -1
- package/dist/editor/fields/fields.stories.js +0 -34
- package/dist/editor/fields/fields.stories.js.map +0 -1
- package/dist/test-utils/api-test-helpers.d.ts +0 -238
- package/dist/test-utils/api-test-helpers.d.ts.map +0 -1
- package/dist/test-utils/api-test-helpers.js +0 -347
- package/dist/test-utils/api-test-helpers.js.map +0 -1
- package/dist/test-utils/console-spy.d.ts +0 -56
- package/dist/test-utils/console-spy.d.ts.map +0 -1
- package/dist/test-utils/console-spy.js +0 -81
- package/dist/test-utils/console-spy.js.map +0 -1
- package/dist/test-utils/git-helpers.d.ts +0 -21
- package/dist/test-utils/git-helpers.d.ts.map +0 -1
- package/dist/test-utils/git-helpers.js +0 -23
- package/dist/test-utils/git-helpers.js.map +0 -1
- package/dist/test-utils/index.d.ts +0 -5
- package/dist/test-utils/index.d.ts.map +0 -1
- package/dist/test-utils/index.js +0 -4
- package/dist/test-utils/index.js.map +0 -1
- package/src/__integration__/errors/invalid-content.test.ts +0 -238
- package/src/__integration__/errors/permission-denied.test.ts +0 -220
- package/src/__integration__/fixtures/content-seeds.ts +0 -105
- package/src/__integration__/fixtures/schemas.ts +0 -67
- package/src/__integration__/initialization/prod-sim-init.test.ts +0 -139
- package/src/__integration__/permissions/path-permissions.test.ts +0 -314
- package/src/__integration__/permissions/role-permissions.test.ts +0 -354
- package/src/__integration__/permissions/settings-branch-isolation.test.ts +0 -317
- package/src/__integration__/settings/groups-api.test.ts +0 -403
- package/src/__integration__/test-utils/api-client.ts +0 -167
- package/src/__integration__/test-utils/multi-user.ts +0 -129
- package/src/__integration__/test-utils/test-workspace.ts +0 -130
- package/src/__integration__/user/user-context.test.ts +0 -174
- package/src/__integration__/validation/input-validation.test.ts +0 -166
- package/src/__integration__/workflows/api-editing-workflow.test.ts +0 -244
- package/src/__integration__/workflows/conflict-resolution.test.ts +0 -259
- package/src/__integration__/workflows/editing-workflow.test.ts +0 -205
- package/src/__integration__/workflows/review-workflow.test.ts +0 -260
- package/src/ai/__tests__/build.integration.test.ts +0 -224
- package/src/ai/__tests__/generate.integration.test.ts +0 -495
- package/src/ai/__tests__/handler.integration.test.ts +0 -212
- package/src/ai/__tests__/json-to-markdown.test.ts +0 -553
- package/src/ai/generate.ts +0 -410
- package/src/ai/handler.ts +0 -123
- package/src/ai/index.ts +0 -26
- package/src/ai/json-to-markdown.ts +0 -424
- package/src/ai/resolve-branch.ts +0 -34
- package/src/ai/types.ts +0 -160
- package/src/api/AGENTS.md +0 -81
- package/src/api/__test__/mock-client.ts +0 -404
- package/src/api/assets.test.ts +0 -140
- package/src/api/assets.ts +0 -154
- package/src/api/branch-merge.test.ts +0 -163
- package/src/api/branch-merge.ts +0 -113
- package/src/api/branch-review.test.ts +0 -297
- package/src/api/branch-review.ts +0 -136
- package/src/api/branch-status.test.ts +0 -85
- package/src/api/branch-status.ts +0 -153
- package/src/api/branch-withdraw.test.ts +0 -146
- package/src/api/branch-withdraw.ts +0 -81
- package/src/api/branch-workflow.integration.test.ts +0 -578
- package/src/api/branch.test.ts +0 -620
- package/src/api/branch.ts +0 -492
- package/src/api/client.test.ts +0 -349
- package/src/api/client.ts +0 -506
- package/src/api/comments.test.ts +0 -285
- package/src/api/comments.ts +0 -210
- package/src/api/content.test.ts +0 -345
- package/src/api/content.ts +0 -454
- package/src/api/entries.test.ts +0 -1339
- package/src/api/entries.ts +0 -650
- package/src/api/github-sync.ts +0 -144
- package/src/api/groups.test.ts +0 -1013
- package/src/api/groups.ts +0 -375
- package/src/api/guards.test.ts +0 -533
- package/src/api/guards.ts +0 -271
- package/src/api/index.ts +0 -87
- package/src/api/permissions.test.ts +0 -766
- package/src/api/permissions.ts +0 -334
- package/src/api/reference-options.ts +0 -118
- package/src/api/resolve-references.ts +0 -107
- package/src/api/route-builder.ts +0 -289
- package/src/api/schema.test.ts +0 -840
- package/src/api/schema.ts +0 -936
- package/src/api/security.test.ts +0 -233
- package/src/api/settings-helpers.ts +0 -84
- package/src/api/types.ts +0 -40
- package/src/api/user.test.ts +0 -127
- package/src/api/user.ts +0 -42
- package/src/api/validators.test.ts +0 -275
- package/src/api/validators.ts +0 -176
- package/src/asset-store.test.ts +0 -37
- package/src/asset-store.ts +0 -110
- package/src/auth/cache.ts +0 -7
- package/src/auth/caching-auth-plugin.test.ts +0 -154
- package/src/auth/caching-auth-plugin.ts +0 -109
- package/src/auth/context-helpers.ts +0 -75
- package/src/auth/file-based-auth-cache.test.ts +0 -257
- package/src/auth/file-based-auth-cache.ts +0 -279
- package/src/auth/index.ts +0 -12
- package/src/auth/plugin.ts +0 -51
- package/src/auth/types.ts +0 -38
- package/src/authorization/__tests__/branch.test.ts +0 -260
- package/src/authorization/__tests__/content.test.ts +0 -142
- package/src/authorization/__tests__/path.test.ts +0 -133
- package/src/authorization/__tests__/permissions-loader.test.ts +0 -200
- package/src/authorization/branch.ts +0 -94
- package/src/authorization/content.ts +0 -93
- package/src/authorization/groups/index.ts +0 -11
- package/src/authorization/groups/loader.ts +0 -127
- package/src/authorization/groups/schema.ts +0 -48
- package/src/authorization/helpers.ts +0 -48
- package/src/authorization/index.ts +0 -84
- package/src/authorization/path.ts +0 -112
- package/src/authorization/permissions/index.ts +0 -11
- package/src/authorization/permissions/loader.ts +0 -116
- package/src/authorization/permissions/schema.ts +0 -66
- package/src/authorization/test-utils.ts +0 -15
- package/src/authorization/types.ts +0 -66
- package/src/authorization/validation.test.ts +0 -100
- package/src/authorization/validation.ts +0 -62
- package/src/branch-metadata.test.ts +0 -168
- package/src/branch-metadata.ts +0 -166
- package/src/branch-registry.test.ts +0 -248
- package/src/branch-registry.ts +0 -152
- package/src/branch-schema-cache.test.ts +0 -275
- package/src/branch-schema-cache.ts +0 -189
- package/src/branch-workspace.test.ts +0 -183
- package/src/branch-workspace.ts +0 -124
- package/src/build/generate-ai-content.ts +0 -78
- package/src/build/index.ts +0 -8
- package/src/build-mode.ts +0 -27
- package/src/cli/generate-ai-content.ts +0 -100
- package/src/cli/init.test.ts +0 -240
- package/src/cli/templates/canopy.ts.template +0 -55
- package/src/cli/templates.ts +0 -47
- package/src/client.ts +0 -12
- package/src/comment-store.test.ts +0 -442
- package/src/comment-store.ts +0 -301
- package/src/config/__tests__/config.test.ts +0 -513
- package/src/config/flatten.ts +0 -174
- package/src/config/helpers.ts +0 -167
- package/src/config/index.ts +0 -86
- package/src/config/schemas/collection.ts +0 -67
- package/src/config/schemas/config.ts +0 -77
- package/src/config/schemas/field.ts +0 -108
- package/src/config/schemas/media.ts +0 -27
- package/src/config/schemas/permissions.ts +0 -21
- package/src/config/types.ts +0 -321
- package/src/config/validation.ts +0 -70
- package/src/config-test.ts +0 -65
- package/src/config.ts +0 -11
- package/src/content-id-index.test.ts +0 -512
- package/src/content-id-index.ts +0 -479
- package/src/content-reader.test.ts +0 -478
- package/src/content-reader.ts +0 -214
- package/src/content-store.test.ts +0 -1126
- package/src/content-store.ts +0 -793
- package/src/context.ts +0 -111
- package/src/editor/BranchManager.stories.tsx +0 -80
- package/src/editor/BranchManager.test.tsx +0 -324
- package/src/editor/BranchManager.tsx +0 -461
- package/src/editor/CanopyEditor.stories.tsx +0 -128
- package/src/editor/CanopyEditor.test.tsx +0 -81
- package/src/editor/CanopyEditor.tsx +0 -73
- package/src/editor/CanopyEditorPage.test.tsx +0 -59
- package/src/editor/CanopyEditorPage.tsx +0 -25
- package/src/editor/CommentsPanel.stories.tsx +0 -184
- package/src/editor/CommentsPanel.tsx +0 -338
- package/src/editor/Editor.integration.test.tsx +0 -227
- package/src/editor/Editor.stories.tsx +0 -119
- package/src/editor/Editor.tsx +0 -1221
- package/src/editor/EditorPanes.stories.tsx +0 -256
- package/src/editor/EditorPanes.test.tsx +0 -77
- package/src/editor/EditorPanes.tsx +0 -180
- package/src/editor/EntryNavigator.stories.tsx +0 -65
- package/src/editor/EntryNavigator.test.tsx +0 -598
- package/src/editor/EntryNavigator.tsx +0 -665
- package/src/editor/FormRenderer.stories.tsx +0 -212
- package/src/editor/FormRenderer.test.tsx +0 -194
- package/src/editor/FormRenderer.tsx +0 -432
- package/src/editor/GroupManager.stories.tsx +0 -301
- package/src/editor/GroupManager.test.tsx +0 -682
- package/src/editor/GroupManager.tsx +0 -9
- package/src/editor/PermissionManager.stories.tsx +0 -539
- package/src/editor/PermissionManager.test.tsx +0 -864
- package/src/editor/PermissionManager.tsx +0 -12
- package/src/editor/canopy-path.test.ts +0 -23
- package/src/editor/canopy-path.ts +0 -52
- package/src/editor/client-reference-resolver.ts +0 -118
- package/src/editor/comments/BranchComments.tsx +0 -93
- package/src/editor/comments/EntryComments.tsx +0 -94
- package/src/editor/comments/FieldWrapper.stories.tsx +0 -210
- package/src/editor/comments/FieldWrapper.tsx +0 -129
- package/src/editor/comments/InlineCommentThread.test.tsx +0 -384
- package/src/editor/comments/InlineCommentThread.tsx +0 -246
- package/src/editor/comments/ThreadCarousel.test.tsx +0 -393
- package/src/editor/comments/ThreadCarousel.tsx +0 -525
- package/src/editor/components/ConfirmDeleteModal.tsx +0 -49
- package/src/editor/components/EditorContext.tsx +0 -49
- package/src/editor/components/EditorFooter.tsx +0 -47
- package/src/editor/components/EditorHeader.tsx +0 -492
- package/src/editor/components/EditorSidebar.tsx +0 -193
- package/src/editor/components/EntryCreateModal.tsx +0 -193
- package/src/editor/components/RenameEntryModal.tsx +0 -152
- package/src/editor/components/UserBadge.test.tsx +0 -274
- package/src/editor/components/UserBadge.tsx +0 -240
- package/src/editor/components/index.ts +0 -6
- package/src/editor/context/ApiClientContext.tsx +0 -56
- package/src/editor/context/EditorStateContext.tsx +0 -221
- package/src/editor/context/index.ts +0 -40
- package/src/editor/editor-config.test.ts +0 -385
- package/src/editor/editor-config.ts +0 -94
- package/src/editor/editor-utils.test.ts +0 -772
- package/src/editor/editor-utils.ts +0 -303
- package/src/editor/env.ts +0 -4
- package/src/editor/fields/BlockField.stories.tsx +0 -79
- package/src/editor/fields/BlockField.tsx +0 -267
- package/src/editor/fields/CodeField.tsx +0 -41
- package/src/editor/fields/MarkdownField.tsx +0 -205
- package/src/editor/fields/ObjectField.tsx +0 -71
- package/src/editor/fields/ReferenceField.tsx +0 -138
- package/src/editor/fields/SelectField.tsx +0 -76
- package/src/editor/fields/TextField.tsx +0 -35
- package/src/editor/fields/ToggleField.tsx +0 -37
- package/src/editor/fields/fields.stories.tsx +0 -40
- package/src/editor/group-manager/ExternalGroupsTab.tsx +0 -114
- package/src/editor/group-manager/GroupCard.tsx +0 -102
- package/src/editor/group-manager/GroupForm.tsx +0 -66
- package/src/editor/group-manager/InternalGroupsTab.tsx +0 -147
- package/src/editor/group-manager/MemberList.tsx +0 -184
- package/src/editor/group-manager/hooks/useExternalGroupSearch.ts +0 -63
- package/src/editor/group-manager/hooks/useGroupState.ts +0 -134
- package/src/editor/group-manager/hooks/useUserSearch.ts +0 -84
- package/src/editor/group-manager/index.tsx +0 -210
- package/src/editor/group-manager/types.ts +0 -28
- package/src/editor/hooks/README.md +0 -26
- package/src/editor/hooks/__test__/test-utils.tsx +0 -183
- package/src/editor/hooks/index.ts +0 -23
- package/src/editor/hooks/useBranchActions.test.tsx +0 -267
- package/src/editor/hooks/useBranchActions.tsx +0 -121
- package/src/editor/hooks/useBranchManager.test.tsx +0 -391
- package/src/editor/hooks/useBranchManager.tsx +0 -326
- package/src/editor/hooks/useCommentSystem.test.ts +0 -615
- package/src/editor/hooks/useCommentSystem.ts +0 -347
- package/src/editor/hooks/useDraftManager.test.ts +0 -375
- package/src/editor/hooks/useDraftManager.ts +0 -259
- package/src/editor/hooks/useEditorLayout.test.ts +0 -147
- package/src/editor/hooks/useEditorLayout.ts +0 -67
- package/src/editor/hooks/useEntryManager.test.ts +0 -588
- package/src/editor/hooks/useEntryManager.ts +0 -387
- package/src/editor/hooks/useGroupManager.test.ts +0 -277
- package/src/editor/hooks/useGroupManager.ts +0 -139
- package/src/editor/hooks/usePermissionManager.test.ts +0 -211
- package/src/editor/hooks/usePermissionManager.ts +0 -113
- package/src/editor/hooks/useReferenceResolution.ts +0 -248
- package/src/editor/hooks/useSchemaManager.test.ts +0 -370
- package/src/editor/hooks/useSchemaManager.ts +0 -310
- package/src/editor/hooks/useUserContext.tsx +0 -57
- package/src/editor/hooks/useUserMetadata.test.ts +0 -191
- package/src/editor/hooks/useUserMetadata.ts +0 -71
- package/src/editor/permission-manager/GroupSelector.tsx +0 -73
- package/src/editor/permission-manager/PermissionEditor.tsx +0 -321
- package/src/editor/permission-manager/PermissionLevelBadge.tsx +0 -53
- package/src/editor/permission-manager/PermissionTree.tsx +0 -237
- package/src/editor/permission-manager/UserSelector.tsx +0 -95
- package/src/editor/permission-manager/constants.tsx +0 -18
- package/src/editor/permission-manager/hooks/useGroupsAndUsers.ts +0 -153
- package/src/editor/permission-manager/hooks/usePermissionTree.ts +0 -200
- package/src/editor/permission-manager/index.tsx +0 -294
- package/src/editor/permission-manager/types.ts +0 -58
- package/src/editor/permission-manager/utils.ts +0 -179
- package/src/editor/preview-bridge.test.tsx +0 -50
- package/src/editor/preview-bridge.tsx +0 -294
- package/src/editor/schema-editor/CollectionEditor.test.tsx +0 -238
- package/src/editor/schema-editor/CollectionEditor.tsx +0 -520
- package/src/editor/schema-editor/EntryTypeEditor.test.tsx +0 -215
- package/src/editor/schema-editor/EntryTypeEditor.tsx +0 -367
- package/src/editor/schema-editor/index.ts +0 -19
- package/src/editor/setup-test-dom.ts +0 -10
- package/src/editor/test-setup.ts +0 -33
- package/src/editor/theme.tsx +0 -119
- package/src/editor/utils/env.ts +0 -39
- package/src/entry-schema-registry.test.ts +0 -281
- package/src/entry-schema-registry.ts +0 -121
- package/src/entry-schema.ts +0 -84
- package/src/git-manager.test.ts +0 -552
- package/src/git-manager.ts +0 -667
- package/src/github-service.test.ts +0 -312
- package/src/github-service.ts +0 -295
- package/src/http/handler.test.ts +0 -275
- package/src/http/handler.ts +0 -280
- package/src/http/index.ts +0 -11
- package/src/http/router.ts +0 -164
- package/src/http/types.ts +0 -44
- package/src/id.test.ts +0 -48
- package/src/id.ts +0 -22
- package/src/index.ts +0 -26
- package/src/operating-mode/__tests__/strategies.test.ts +0 -511
- package/src/operating-mode/client-safe-strategy.ts +0 -184
- package/src/operating-mode/client-unsafe-strategy.ts +0 -303
- package/src/operating-mode/client.ts +0 -13
- package/src/operating-mode/index.ts +0 -34
- package/src/operating-mode/types.ts +0 -186
- package/src/paths/__tests__/branch.test.ts +0 -53
- package/src/paths/__tests__/normalize.test.ts +0 -141
- package/src/paths/__tests__/resolve.test.ts +0 -207
- package/src/paths/__tests__/validation.test.ts +0 -61
- package/src/paths/branch.ts +0 -115
- package/src/paths/index.ts +0 -73
- package/src/paths/normalize-server.ts +0 -40
- package/src/paths/normalize.ts +0 -107
- package/src/paths/resolve.ts +0 -61
- package/src/paths/test-utils.ts +0 -37
- package/src/paths/types.ts +0 -68
- package/src/paths/validation.test.ts +0 -480
- package/src/paths/validation.ts +0 -391
- package/src/reference-resolver.test.ts +0 -107
- package/src/reference-resolver.ts +0 -157
- package/src/schema/index.ts +0 -29
- package/src/schema/meta-loader.ts +0 -366
- package/src/schema/resolver.ts +0 -83
- package/src/schema/schema-store-types.ts +0 -56
- package/src/schema/schema-store.test.ts +0 -816
- package/src/schema/schema-store.ts +0 -795
- package/src/schema/types.ts +0 -33
- package/src/schema-meta-loader.test.ts +0 -447
- package/src/server.ts +0 -15
- package/src/services.test.ts +0 -559
- package/src/services.ts +0 -373
- package/src/settings-branch-utils.ts +0 -53
- package/src/settings-workspace.ts +0 -156
- package/src/task-queue/README.md +0 -144
- package/src/task-queue/index.ts +0 -14
- package/src/task-queue/task-queue.test.ts +0 -524
- package/src/task-queue/task-queue.ts +0 -514
- package/src/task-queue/types.ts +0 -41
- package/src/test-utils/api-test-helpers.ts +0 -445
- package/src/test-utils/console-spy.test.ts +0 -14
- package/src/test-utils/console-spy.ts +0 -125
- package/src/test-utils/git-helpers.ts +0 -31
- package/src/test-utils/index.ts +0 -4
- package/src/types.ts +0 -54
- package/src/user.ts +0 -118
- package/src/utils/debug.test.ts +0 -114
- package/src/utils/debug.ts +0 -127
- package/src/utils/error.test.ts +0 -92
- package/src/utils/error.ts +0 -83
- package/src/utils/format.ts +0 -12
- package/src/validation/__tests__/field-traversal.test.ts +0 -263
- package/src/validation/deletion-checker.ts +0 -234
- package/src/validation/field-traversal.ts +0 -146
- package/src/validation/reference-validator.ts +0 -168
- package/src/worker/cms-worker-rebase.test.ts +0 -473
- package/src/worker/cms-worker.ts +0 -777
- package/src/worker/integration.test.ts +0 -289
- package/src/worker/task-queue-config.ts +0 -25
- package/src/worker/task-queue.test.ts +0 -452
- package/src/worker/task-queue.ts +0 -58
- /package/{src/cli/templates → dist/cli/template-files}/Dockerfile.cms.template +0 -0
- /package/{src/cli/templates → dist/cli/template-files}/canopycms.config.ts.template +0 -0
- /package/{src/cli/templates → dist/cli/template-files}/deploy-cms.yml.template +0 -0
- /package/{src/cli/templates → dist/cli/template-files}/edit-page.tsx.template +0 -0
- /package/{src/cli/templates → dist/cli/template-files}/route.ts.template +0 -0
- /package/{src/cli/templates → dist/cli/template-files}/schemas.ts.template +0 -0
package/src/context.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import type { CanopyUser } from './user'
|
|
2
|
-
import type { CanopyServices } from './services'
|
|
3
|
-
import type { ReadContentInput } from './content-reader'
|
|
4
|
-
import { isBuildMode, BUILD_USER } from './build-mode'
|
|
5
|
-
import { createContentReader } from './content-reader'
|
|
6
|
-
import { createLogicalPath, parseSlug, type EntrySlug } from './paths'
|
|
7
|
-
|
|
8
|
-
export interface CanopyContextOptions {
|
|
9
|
-
services: CanopyServices
|
|
10
|
-
/**
|
|
11
|
-
* Extract the current user from framework-specific context.
|
|
12
|
-
* Should call authResultToCanopyUser() to apply bootstrap admin groups.
|
|
13
|
-
*
|
|
14
|
-
* Framework adapters provide this (e.g., from Next.js headers, Express req, etc.)
|
|
15
|
-
*/
|
|
16
|
-
extractUser: () => Promise<CanopyUser>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface CanopyContext {
|
|
20
|
-
/** Content reader with automatic auth context */
|
|
21
|
-
read: <T = unknown>(input: {
|
|
22
|
-
entryPath: string
|
|
23
|
-
slug?: string
|
|
24
|
-
branch?: string
|
|
25
|
-
resolveReferences?: boolean
|
|
26
|
-
}) => Promise<{ data: T; path: string }>
|
|
27
|
-
|
|
28
|
-
/** Underlying services */
|
|
29
|
-
services: CanopyServices
|
|
30
|
-
|
|
31
|
-
/** Current authenticated user */
|
|
32
|
-
user: CanopyUser
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Create a Canopy context that manages auth + content reading.
|
|
37
|
-
* Framework-agnostic - the adapter provides the extractUser function.
|
|
38
|
-
*
|
|
39
|
-
* User extractor should apply bootstrap admin groups (via authResultToCanopyUser).
|
|
40
|
-
*
|
|
41
|
-
* NOTE: This function is synchronous because in practice, services are always
|
|
42
|
-
* provided pre-created (async) by the framework adapter. The fallback path
|
|
43
|
-
* that creates services from config cannot work correctly since createCanopyServices
|
|
44
|
-
* is now async. Always pass services, not config.
|
|
45
|
-
*/
|
|
46
|
-
export function createCanopyContext(options: CanopyContextOptions) {
|
|
47
|
-
const services = options.services
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Get the current user.
|
|
51
|
-
* Returns BUILD_USER during static generation, otherwise delegates to adapter.
|
|
52
|
-
*/
|
|
53
|
-
const getUser = async (): Promise<CanopyUser> => {
|
|
54
|
-
// Build mode: static generation gets admin access
|
|
55
|
-
if (isBuildMode()) {
|
|
56
|
-
return BUILD_USER
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Runtime: delegate to adapter-provided user extractor
|
|
60
|
-
// (adapter should use authResultToCanopyUser to apply bootstrap admins)
|
|
61
|
-
return await options.extractUser()
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Get the context for the current request.
|
|
66
|
-
* Call this in server components/routes to get auth-aware reader.
|
|
67
|
-
*/
|
|
68
|
-
const getContext = async (): Promise<CanopyContext> => {
|
|
69
|
-
const user = await getUser()
|
|
70
|
-
|
|
71
|
-
// Create base content reader
|
|
72
|
-
const baseReader = createContentReader({ services })
|
|
73
|
-
|
|
74
|
-
// Wrap reader to inject user automatically, validating strings → branded types at this boundary
|
|
75
|
-
const read: CanopyContext['read'] = async <T = unknown>(input: {
|
|
76
|
-
entryPath: string
|
|
77
|
-
slug?: string
|
|
78
|
-
branch?: string
|
|
79
|
-
resolveReferences?: boolean
|
|
80
|
-
}) => {
|
|
81
|
-
const entryPath = createLogicalPath(input.entryPath)
|
|
82
|
-
let slug: EntrySlug | undefined
|
|
83
|
-
if (input.slug) {
|
|
84
|
-
const slugResult = parseSlug(input.slug, 'entry')
|
|
85
|
-
if (!slugResult.ok) {
|
|
86
|
-
throw new Error(`Invalid slug: ${slugResult.error}`)
|
|
87
|
-
}
|
|
88
|
-
slug = slugResult.slug as EntrySlug
|
|
89
|
-
}
|
|
90
|
-
const readInput: ReadContentInput = {
|
|
91
|
-
entryPath,
|
|
92
|
-
slug,
|
|
93
|
-
branch: input.branch,
|
|
94
|
-
user,
|
|
95
|
-
resolveReferences: input.resolveReferences ?? true,
|
|
96
|
-
}
|
|
97
|
-
return baseReader.read<T>(readInput)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return {
|
|
101
|
-
read,
|
|
102
|
-
services,
|
|
103
|
-
user,
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
getContext,
|
|
109
|
-
services,
|
|
110
|
-
}
|
|
111
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
-
|
|
3
|
-
import { BranchManager } from './BranchManager'
|
|
4
|
-
|
|
5
|
-
const meta: Meta<typeof BranchManager> = {
|
|
6
|
-
title: 'Editor/BranchManager',
|
|
7
|
-
component: BranchManager,
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default meta
|
|
11
|
-
type Story = StoryObj<typeof BranchManager>
|
|
12
|
-
|
|
13
|
-
export const Default: Story = {
|
|
14
|
-
args: {
|
|
15
|
-
branches: [
|
|
16
|
-
{
|
|
17
|
-
name: 'feature/landing',
|
|
18
|
-
status: 'editing',
|
|
19
|
-
updatedAt: 'today',
|
|
20
|
-
access: { users: ['alice'], groups: ['team-marketing'] },
|
|
21
|
-
commentCount: 3,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
name: 'feature/docs',
|
|
25
|
-
status: 'submitted',
|
|
26
|
-
updatedAt: 'yesterday',
|
|
27
|
-
access: { users: ['bob'] },
|
|
28
|
-
pullRequestUrl: 'https://github.com/owner/repo/pull/42',
|
|
29
|
-
pullRequestNumber: 42,
|
|
30
|
-
commentCount: 1,
|
|
31
|
-
},
|
|
32
|
-
],
|
|
33
|
-
onSelect: (name: string) => alert(`Open ${name}`),
|
|
34
|
-
onCreate: (branch) => alert(`Create branch: ${branch.name}`),
|
|
35
|
-
onSubmit: (name: string) => alert(`Submit ${name}`),
|
|
36
|
-
onWithdraw: (name: string) => alert(`Withdraw ${name}`),
|
|
37
|
-
onDelete: (name: string) => alert(`Delete ${name}`),
|
|
38
|
-
onRequestChanges: (name: string) => alert(`Request changes on ${name}`),
|
|
39
|
-
},
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const WithPullRequests: Story = {
|
|
43
|
-
args: {
|
|
44
|
-
branches: [
|
|
45
|
-
{
|
|
46
|
-
name: 'feature/new-homepage',
|
|
47
|
-
status: 'editing',
|
|
48
|
-
updatedAt: '2 hours ago',
|
|
49
|
-
createdBy: 'alice',
|
|
50
|
-
access: { users: ['alice'] },
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
name: 'feature/dark-mode',
|
|
54
|
-
status: 'submitted',
|
|
55
|
-
updatedAt: '1 day ago',
|
|
56
|
-
createdBy: 'bob',
|
|
57
|
-
access: { users: ['bob'] },
|
|
58
|
-
pullRequestUrl: 'https://github.com/owner/repo/pull/123',
|
|
59
|
-
pullRequestNumber: 123,
|
|
60
|
-
commentCount: 5,
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
name: 'fix/navigation-bug',
|
|
64
|
-
status: 'submitted',
|
|
65
|
-
updatedAt: '3 days ago',
|
|
66
|
-
createdBy: 'charlie',
|
|
67
|
-
access: { users: ['charlie'] },
|
|
68
|
-
pullRequestUrl: 'https://github.com/owner/repo/pull/118',
|
|
69
|
-
pullRequestNumber: 118,
|
|
70
|
-
commentCount: 0,
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
onSelect: (name: string) => console.log(`Open ${name}`),
|
|
74
|
-
onCreate: (branch) => console.log(`Create branch:`, branch),
|
|
75
|
-
onSubmit: (name: string) => console.log(`Submit ${name}`),
|
|
76
|
-
onWithdraw: (name: string) => console.log(`Withdraw ${name}`),
|
|
77
|
-
onDelete: (name: string) => console.log(`Delete ${name}`),
|
|
78
|
-
onRequestChanges: (name: string) => console.log(`Request changes on ${name}`),
|
|
79
|
-
},
|
|
80
|
-
}
|
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { cleanup, render, screen, waitFor } from '@testing-library/react'
|
|
3
|
-
import userEvent from '@testing-library/user-event'
|
|
4
|
-
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest'
|
|
5
|
-
import { BranchManager, getBranchPermissions } from './BranchManager'
|
|
6
|
-
import type { BranchSummary } from './BranchManager'
|
|
7
|
-
import { CanopyCMSProvider } from './theme'
|
|
8
|
-
import { RESERVED_GROUPS } from '../authorization'
|
|
9
|
-
|
|
10
|
-
const originalMatchMedia = window.matchMedia
|
|
11
|
-
|
|
12
|
-
beforeAll(() => {
|
|
13
|
-
if (!window.matchMedia) {
|
|
14
|
-
window.matchMedia = ((query: string) =>
|
|
15
|
-
({
|
|
16
|
-
matches: false,
|
|
17
|
-
media: query,
|
|
18
|
-
onchange: null,
|
|
19
|
-
addListener: () => {},
|
|
20
|
-
removeListener: () => {},
|
|
21
|
-
addEventListener: () => {},
|
|
22
|
-
removeEventListener: () => {},
|
|
23
|
-
dispatchEvent: () => false,
|
|
24
|
-
}) as MediaQueryList) as typeof window.matchMedia
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (!window.ResizeObserver) {
|
|
28
|
-
class ResizeObserver {
|
|
29
|
-
observe() {}
|
|
30
|
-
unobserve() {}
|
|
31
|
-
disconnect() {}
|
|
32
|
-
}
|
|
33
|
-
;(window as unknown as { ResizeObserver: typeof ResizeObserver }).ResizeObserver =
|
|
34
|
-
ResizeObserver as typeof ResizeObserver
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
afterAll(() => {
|
|
39
|
-
if (originalMatchMedia) {
|
|
40
|
-
window.matchMedia = originalMatchMedia
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
afterEach(() => {
|
|
45
|
-
cleanup()
|
|
46
|
-
vi.restoreAllMocks()
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
const renderBranchManager = (props: React.ComponentProps<typeof BranchManager>) => {
|
|
50
|
-
return render(
|
|
51
|
-
<CanopyCMSProvider>
|
|
52
|
-
<BranchManager {...props} />
|
|
53
|
-
</CanopyCMSProvider>,
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
describe('getBranchPermissions', () => {
|
|
58
|
-
it('returns all false when no user provided', () => {
|
|
59
|
-
const branch: BranchSummary = {
|
|
60
|
-
name: 'main',
|
|
61
|
-
status: 'editing',
|
|
62
|
-
createdBy: 'user1',
|
|
63
|
-
}
|
|
64
|
-
const perms = getBranchPermissions(branch, undefined)
|
|
65
|
-
expect(perms.canSubmit).toBe(false)
|
|
66
|
-
expect(perms.canWithdraw).toBe(false)
|
|
67
|
-
expect(perms.canDelete).toBe(false)
|
|
68
|
-
expect(perms.canRequestChanges).toBe(false)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('allows creator to submit editing branch', () => {
|
|
72
|
-
const branch: BranchSummary = {
|
|
73
|
-
name: 'main',
|
|
74
|
-
status: 'editing',
|
|
75
|
-
createdBy: 'user1',
|
|
76
|
-
}
|
|
77
|
-
const perms = getBranchPermissions(branch, { userId: 'user1', groups: [] })
|
|
78
|
-
expect(perms.canSubmit).toBe(true)
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
it('allows creator to withdraw submitted branch', () => {
|
|
82
|
-
const branch: BranchSummary = {
|
|
83
|
-
name: 'main',
|
|
84
|
-
status: 'submitted',
|
|
85
|
-
createdBy: 'user1',
|
|
86
|
-
}
|
|
87
|
-
const perms = getBranchPermissions(branch, { userId: 'user1', groups: [] })
|
|
88
|
-
expect(perms.canWithdraw).toBe(true)
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
it('allows admin to delete any branch', () => {
|
|
92
|
-
const branch: BranchSummary = {
|
|
93
|
-
name: 'main',
|
|
94
|
-
status: 'editing',
|
|
95
|
-
createdBy: 'other',
|
|
96
|
-
}
|
|
97
|
-
const perms = getBranchPermissions(branch, {
|
|
98
|
-
userId: 'admin',
|
|
99
|
-
groups: [RESERVED_GROUPS.ADMINS],
|
|
100
|
-
})
|
|
101
|
-
expect(perms.canDelete).toBe(true)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
it('blocks delete for submitted branches', () => {
|
|
105
|
-
const branch: BranchSummary = {
|
|
106
|
-
name: 'main',
|
|
107
|
-
status: 'submitted',
|
|
108
|
-
createdBy: 'user1',
|
|
109
|
-
}
|
|
110
|
-
const perms = getBranchPermissions(branch, { userId: 'user1', groups: [] })
|
|
111
|
-
expect(perms.canDelete).toBe(false)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
it('allows reviewer to request changes on submitted branch', () => {
|
|
115
|
-
const branch: BranchSummary = {
|
|
116
|
-
name: 'main',
|
|
117
|
-
status: 'submitted',
|
|
118
|
-
createdBy: 'other',
|
|
119
|
-
}
|
|
120
|
-
const perms = getBranchPermissions(branch, {
|
|
121
|
-
userId: 'reviewer',
|
|
122
|
-
groups: [RESERVED_GROUPS.REVIEWERS],
|
|
123
|
-
})
|
|
124
|
-
expect(perms.canRequestChanges).toBe(true)
|
|
125
|
-
})
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
describe('BranchManager', () => {
|
|
129
|
-
// Admin user can do everything
|
|
130
|
-
const adminUser = { userId: 'admin', groups: [RESERVED_GROUPS.ADMINS] }
|
|
131
|
-
// Creator user for testing branch operations
|
|
132
|
-
const creatorUser = { userId: 'user1', groups: [] }
|
|
133
|
-
|
|
134
|
-
const baseBranches: BranchSummary[] = [
|
|
135
|
-
{
|
|
136
|
-
name: 'main',
|
|
137
|
-
status: 'editing',
|
|
138
|
-
createdBy: 'user1',
|
|
139
|
-
updatedAt: '2024-01-01',
|
|
140
|
-
access: { users: ['user1'] },
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
name: 'feature/test',
|
|
144
|
-
status: 'submitted',
|
|
145
|
-
createdBy: 'user1',
|
|
146
|
-
updatedAt: '2024-01-02',
|
|
147
|
-
access: { users: ['user1'] },
|
|
148
|
-
pullRequestUrl: 'https://github.com/owner/repo/pull/1',
|
|
149
|
-
pullRequestNumber: 1,
|
|
150
|
-
commentCount: 3,
|
|
151
|
-
},
|
|
152
|
-
]
|
|
153
|
-
|
|
154
|
-
it('renders branch list', () => {
|
|
155
|
-
renderBranchManager({ branches: baseBranches, mode: 'prod' })
|
|
156
|
-
expect(screen.getByText('main')).toBeDefined()
|
|
157
|
-
expect(screen.getByText('feature/test')).toBeDefined()
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
it('shows PR status and link when present', () => {
|
|
161
|
-
renderBranchManager({ branches: baseBranches, mode: 'prod' })
|
|
162
|
-
const prBadge = screen.getByText(/PR #1/)
|
|
163
|
-
expect(prBadge).toBeDefined()
|
|
164
|
-
|
|
165
|
-
const prLink = screen.getByText('View PR')
|
|
166
|
-
expect(prLink).toBeDefined()
|
|
167
|
-
expect(prLink.getAttribute('href')).toBe('https://github.com/owner/repo/pull/1')
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
it('shows comment count badge when present', () => {
|
|
171
|
-
renderBranchManager({ branches: baseBranches, mode: 'prod' })
|
|
172
|
-
expect(screen.getByText(/3 comments/)).toBeDefined()
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
it('calls onSubmit when Submit button clicked', async () => {
|
|
176
|
-
const onSubmit = vi.fn()
|
|
177
|
-
// Use creator user so they can submit their own branch
|
|
178
|
-
renderBranchManager({
|
|
179
|
-
branches: baseBranches,
|
|
180
|
-
onSubmit,
|
|
181
|
-
user: creatorUser,
|
|
182
|
-
mode: 'prod',
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
const submitButton = screen.getByRole('button', { name: /submit/i })
|
|
186
|
-
await userEvent.click(submitButton)
|
|
187
|
-
|
|
188
|
-
expect(onSubmit).toHaveBeenCalledWith('main')
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
it('calls onWithdraw when Withdraw button clicked', async () => {
|
|
192
|
-
const onWithdraw = vi.fn()
|
|
193
|
-
// Use creator user so they can withdraw their own branch
|
|
194
|
-
renderBranchManager({
|
|
195
|
-
branches: baseBranches,
|
|
196
|
-
onWithdraw,
|
|
197
|
-
user: creatorUser,
|
|
198
|
-
mode: 'prod',
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
const withdrawButton = screen.getByRole('button', { name: /withdraw/i })
|
|
202
|
-
await userEvent.click(withdrawButton)
|
|
203
|
-
|
|
204
|
-
expect(onWithdraw).toHaveBeenCalledWith('feature/test')
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
it('shows create branch form when Create button clicked', async () => {
|
|
208
|
-
renderBranchManager({ branches: baseBranches, mode: 'prod' })
|
|
209
|
-
|
|
210
|
-
const createButton = screen.getByRole('button', {
|
|
211
|
-
name: /create new branch/i,
|
|
212
|
-
})
|
|
213
|
-
await userEvent.click(createButton)
|
|
214
|
-
|
|
215
|
-
await waitFor(() => {
|
|
216
|
-
expect(screen.getByLabelText(/branch name/i)).toBeDefined()
|
|
217
|
-
})
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
it('calls onCreate with branch details when form submitted', async () => {
|
|
221
|
-
const onCreate = vi.fn()
|
|
222
|
-
renderBranchManager({ branches: baseBranches, onCreate, mode: 'prod' })
|
|
223
|
-
|
|
224
|
-
// Open form
|
|
225
|
-
const createButton = screen.getByRole('button', {
|
|
226
|
-
name: /create new branch/i,
|
|
227
|
-
})
|
|
228
|
-
await userEvent.click(createButton)
|
|
229
|
-
|
|
230
|
-
// Fill form
|
|
231
|
-
const nameInput = await screen.findByLabelText(/branch name/i)
|
|
232
|
-
const titleInput = await screen.findByLabelText(/title/i)
|
|
233
|
-
const descriptionInput = await screen.findByLabelText(/description/i)
|
|
234
|
-
|
|
235
|
-
await userEvent.type(nameInput, 'feature/new-feature')
|
|
236
|
-
await userEvent.type(titleInput, 'New Feature')
|
|
237
|
-
await userEvent.type(descriptionInput, 'A great new feature')
|
|
238
|
-
|
|
239
|
-
// Submit form
|
|
240
|
-
const submitButton = screen.getByRole('button', {
|
|
241
|
-
name: /^create branch$/i,
|
|
242
|
-
})
|
|
243
|
-
await userEvent.click(submitButton)
|
|
244
|
-
|
|
245
|
-
expect(onCreate).toHaveBeenCalledWith({
|
|
246
|
-
name: 'feature/new-feature',
|
|
247
|
-
title: 'New Feature',
|
|
248
|
-
description: 'A great new feature',
|
|
249
|
-
})
|
|
250
|
-
})
|
|
251
|
-
|
|
252
|
-
it('disables create button when name is empty', async () => {
|
|
253
|
-
renderBranchManager({
|
|
254
|
-
branches: baseBranches,
|
|
255
|
-
onCreate: vi.fn(),
|
|
256
|
-
mode: 'prod',
|
|
257
|
-
})
|
|
258
|
-
|
|
259
|
-
// Open form
|
|
260
|
-
const createButton = screen.getByRole('button', {
|
|
261
|
-
name: /create new branch/i,
|
|
262
|
-
})
|
|
263
|
-
await userEvent.click(createButton)
|
|
264
|
-
|
|
265
|
-
// Submit button should be disabled with no name
|
|
266
|
-
const submitButton = await screen.findByRole('button', {
|
|
267
|
-
name: /^create branch$/i,
|
|
268
|
-
})
|
|
269
|
-
expect(submitButton.hasAttribute('disabled')).toBe(true)
|
|
270
|
-
|
|
271
|
-
// Type name
|
|
272
|
-
const nameInput = await screen.findByLabelText(/branch name/i)
|
|
273
|
-
await userEvent.type(nameInput, 'test')
|
|
274
|
-
|
|
275
|
-
// Submit button should be enabled
|
|
276
|
-
await waitFor(() => {
|
|
277
|
-
expect(submitButton.hasAttribute('disabled')).toBe(false)
|
|
278
|
-
})
|
|
279
|
-
})
|
|
280
|
-
|
|
281
|
-
it('hides create form in dev mode', () => {
|
|
282
|
-
renderBranchManager({ branches: baseBranches, mode: 'dev' })
|
|
283
|
-
|
|
284
|
-
const createButton = screen.queryByRole('button', {
|
|
285
|
-
name: /create new branch/i,
|
|
286
|
-
})
|
|
287
|
-
expect(createButton).toBeNull()
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
it('calls onRequestChanges when button clicked', async () => {
|
|
291
|
-
const onRequestChanges = vi.fn()
|
|
292
|
-
// Use admin user who can request changes on submitted branches
|
|
293
|
-
renderBranchManager({
|
|
294
|
-
branches: baseBranches,
|
|
295
|
-
onRequestChanges,
|
|
296
|
-
user: adminUser,
|
|
297
|
-
mode: 'prod',
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
const requestChangesButtons = screen.getAllByRole('button', {
|
|
301
|
-
name: /request changes/i,
|
|
302
|
-
})
|
|
303
|
-
// The second branch (feature/test) is submitted, so its button should be at index 1
|
|
304
|
-
await userEvent.click(requestChangesButtons[1])
|
|
305
|
-
|
|
306
|
-
expect(onRequestChanges).toHaveBeenCalledWith('feature/test')
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
it('calls onDelete when delete button clicked', async () => {
|
|
310
|
-
const onDelete = vi.fn()
|
|
311
|
-
// Use creator user so they can delete their own branch (main is editing, not submitted)
|
|
312
|
-
renderBranchManager({
|
|
313
|
-
branches: baseBranches,
|
|
314
|
-
onDelete,
|
|
315
|
-
user: creatorUser,
|
|
316
|
-
mode: 'prod',
|
|
317
|
-
})
|
|
318
|
-
|
|
319
|
-
const deleteButtons = screen.getAllByRole('button', { name: /delete/i })
|
|
320
|
-
await userEvent.click(deleteButtons[0])
|
|
321
|
-
|
|
322
|
-
expect(onDelete).toHaveBeenCalledWith('main')
|
|
323
|
-
})
|
|
324
|
-
})
|