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/user.ts
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import type { CanopyUserId, CanopyGroupId } from './types'
|
|
2
|
-
import type { AuthenticationResult } from './auth/types'
|
|
3
|
-
// Import from client-safe subpaths to avoid pulling in server-only loader code
|
|
4
|
-
import { RESERVED_GROUPS } from './authorization/helpers'
|
|
5
|
-
import type { InternalGroup } from './authorization/groups/schema'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Anonymous user - explicitly marked for public/unauthenticated access
|
|
9
|
-
*/
|
|
10
|
-
export interface AnonymousUser {
|
|
11
|
-
type: 'anonymous'
|
|
12
|
-
userId: 'anonymous'
|
|
13
|
-
groups: readonly []
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Authenticated user - verified identity from auth provider
|
|
18
|
-
*/
|
|
19
|
-
export interface AuthenticatedUser {
|
|
20
|
-
type: 'authenticated'
|
|
21
|
-
userId: CanopyUserId
|
|
22
|
-
groups: CanopyGroupId[]
|
|
23
|
-
email?: string
|
|
24
|
-
name?: string
|
|
25
|
-
avatarUrl?: string
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Unified user type for all CanopyCMS operations
|
|
30
|
-
*/
|
|
31
|
-
export type CanopyUser = AnonymousUser | AuthenticatedUser
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Branded ANONYMOUS_USER constant - use this for intentional anonymous access.
|
|
35
|
-
* Callers must explicitly pass this to indicate anonymous access is intended.
|
|
36
|
-
*/
|
|
37
|
-
export const ANONYMOUS_USER: AnonymousUser = Object.freeze({
|
|
38
|
-
type: 'anonymous',
|
|
39
|
-
userId: 'anonymous',
|
|
40
|
-
groups: [] as const,
|
|
41
|
-
}) as AnonymousUser
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Type guard for anonymous user
|
|
45
|
-
*/
|
|
46
|
-
export const isAnonymousUser = (user: CanopyUser): user is AnonymousUser =>
|
|
47
|
-
user.type === 'anonymous'
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Type guard for authenticated user
|
|
51
|
-
*/
|
|
52
|
-
export const isAuthenticatedUser = (user: CanopyUser): user is AuthenticatedUser =>
|
|
53
|
-
user.type === 'authenticated'
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Create an authenticated user from auth provider data
|
|
57
|
-
*/
|
|
58
|
-
export const createAuthenticatedUser = (data: {
|
|
59
|
-
userId: CanopyUserId
|
|
60
|
-
groups?: CanopyGroupId[]
|
|
61
|
-
email?: string
|
|
62
|
-
name?: string
|
|
63
|
-
avatarUrl?: string
|
|
64
|
-
}): AuthenticatedUser => ({
|
|
65
|
-
type: 'authenticated',
|
|
66
|
-
userId: data.userId,
|
|
67
|
-
groups: data.groups ?? [],
|
|
68
|
-
email: data.email,
|
|
69
|
-
name: data.name,
|
|
70
|
-
avatarUrl: data.avatarUrl,
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Convert authentication result to CanopyUser.
|
|
75
|
-
* Applies bootstrap admin groups, merges internal groups, and returns ANONYMOUS_USER if not authenticated.
|
|
76
|
-
*
|
|
77
|
-
* This is the SINGLE source of truth for converting external auth to CanopyUser.
|
|
78
|
-
*
|
|
79
|
-
* @param authResult - Result from auth plugin's authenticate() method
|
|
80
|
-
* @param bootstrapAdminIds - Set of user IDs that should always be admins
|
|
81
|
-
* @param internalGroups - Optional internal groups from .canopycms/groups.json (loaded by caller)
|
|
82
|
-
* @returns CanopyUser (either authenticated with groups or ANONYMOUS_USER)
|
|
83
|
-
*/
|
|
84
|
-
export function authResultToCanopyUser(
|
|
85
|
-
authResult: AuthenticationResult,
|
|
86
|
-
bootstrapAdminIds: Set<string>,
|
|
87
|
-
internalGroups?: InternalGroup[],
|
|
88
|
-
): CanopyUser {
|
|
89
|
-
if (!authResult.success || !authResult.user) {
|
|
90
|
-
return ANONYMOUS_USER
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Step 1: Start with external groups from auth provider
|
|
94
|
-
const groups = [...(authResult.user.externalGroups ?? [])]
|
|
95
|
-
|
|
96
|
-
// Step 2: Add Admins group if user is in bootstrap admin list
|
|
97
|
-
if (bootstrapAdminIds.has(authResult.user.userId) && !groups.includes(RESERVED_GROUPS.ADMINS)) {
|
|
98
|
-
groups.push(RESERVED_GROUPS.ADMINS)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Step 3: Merge internal groups from .canopycms/groups.json
|
|
102
|
-
if (internalGroups) {
|
|
103
|
-
for (const group of internalGroups) {
|
|
104
|
-
if (group.members.includes(authResult.user.userId) && !groups.includes(group.id)) {
|
|
105
|
-
groups.push(group.id)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
type: 'authenticated',
|
|
112
|
-
userId: authResult.user.userId,
|
|
113
|
-
email: authResult.user.email,
|
|
114
|
-
name: authResult.user.name,
|
|
115
|
-
avatarUrl: authResult.user.avatarUrl,
|
|
116
|
-
groups,
|
|
117
|
-
}
|
|
118
|
-
}
|
package/src/utils/debug.test.ts
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
2
|
-
import { createDebugLogger } from './debug'
|
|
3
|
-
|
|
4
|
-
describe('DebugLogger', () => {
|
|
5
|
-
let originalEnv: string | undefined
|
|
6
|
-
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
// Save original env var
|
|
9
|
-
originalEnv = process.env.CANOPYCMS_DEBUG
|
|
10
|
-
// Mock console methods
|
|
11
|
-
vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
12
|
-
vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
13
|
-
vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
afterEach(() => {
|
|
17
|
-
// Restore env var
|
|
18
|
-
if (originalEnv === undefined) {
|
|
19
|
-
delete process.env.CANOPYCMS_DEBUG
|
|
20
|
-
} else {
|
|
21
|
-
process.env.CANOPYCMS_DEBUG = originalEnv
|
|
22
|
-
}
|
|
23
|
-
vi.restoreAllMocks()
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('respects enabled option', () => {
|
|
27
|
-
const logger = createDebugLogger({ enabled: true })
|
|
28
|
-
logger.debug('test', 'message')
|
|
29
|
-
|
|
30
|
-
expect(console.log).toHaveBeenCalledOnce()
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('respects disabled option', () => {
|
|
34
|
-
const logger = createDebugLogger({ enabled: false })
|
|
35
|
-
logger.debug('test', 'message')
|
|
36
|
-
|
|
37
|
-
expect(console.log).not.toHaveBeenCalled()
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('checks CANOPYCMS_DEBUG env var at call time, not construction time', () => {
|
|
41
|
-
// Create logger before env var is set
|
|
42
|
-
const logger = createDebugLogger()
|
|
43
|
-
|
|
44
|
-
// Initially disabled
|
|
45
|
-
logger.debug('test', 'message 1')
|
|
46
|
-
expect(console.log).not.toHaveBeenCalled()
|
|
47
|
-
|
|
48
|
-
// Enable via env var AFTER logger was created
|
|
49
|
-
process.env.CANOPYCMS_DEBUG = 'true'
|
|
50
|
-
|
|
51
|
-
// Should now be enabled
|
|
52
|
-
logger.debug('test', 'message 2')
|
|
53
|
-
expect(console.log).toHaveBeenCalledOnce()
|
|
54
|
-
|
|
55
|
-
// Disable again
|
|
56
|
-
process.env.CANOPYCMS_DEBUG = 'false'
|
|
57
|
-
|
|
58
|
-
// Should be disabled
|
|
59
|
-
logger.debug('test', 'message 3')
|
|
60
|
-
expect(console.log).toHaveBeenCalledOnce() // Still only called once
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('explicit enabled option overrides env var', () => {
|
|
64
|
-
process.env.CANOPYCMS_DEBUG = 'true'
|
|
65
|
-
|
|
66
|
-
const logger = createDebugLogger({ enabled: false })
|
|
67
|
-
logger.debug('test', 'message')
|
|
68
|
-
|
|
69
|
-
expect(console.log).not.toHaveBeenCalled()
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it('respects minLevel option', () => {
|
|
73
|
-
const logger = createDebugLogger({ enabled: true, minLevel: 'WARN' })
|
|
74
|
-
|
|
75
|
-
logger.debug('test', 'debug message')
|
|
76
|
-
expect(console.log).not.toHaveBeenCalled()
|
|
77
|
-
|
|
78
|
-
logger.info('test', 'info message')
|
|
79
|
-
expect(console.log).not.toHaveBeenCalled()
|
|
80
|
-
|
|
81
|
-
logger.warn('test', 'warn message')
|
|
82
|
-
expect(console.warn).toHaveBeenCalledOnce()
|
|
83
|
-
|
|
84
|
-
logger.error('test', 'error message')
|
|
85
|
-
expect(console.error).toHaveBeenCalledOnce()
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
it('formats messages correctly', () => {
|
|
89
|
-
const logger = createDebugLogger({ enabled: true, prefix: 'TestPrefix' })
|
|
90
|
-
logger.debug('category', 'test message', { foo: 'bar' })
|
|
91
|
-
|
|
92
|
-
const call = vi.mocked(console.log).mock.calls[0]
|
|
93
|
-
expect(call[0]).toContain('[TestPrefix:category]')
|
|
94
|
-
expect(call[0]).toContain('[DEBUG]')
|
|
95
|
-
expect(call[0]).toContain('test message')
|
|
96
|
-
expect(call[1]).toEqual({ foo: 'bar' })
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
it('throws on error when throwOnError is true', () => {
|
|
100
|
-
const logger = createDebugLogger({ enabled: true, throwOnError: true })
|
|
101
|
-
|
|
102
|
-
expect(() => {
|
|
103
|
-
logger.error('test', 'error message')
|
|
104
|
-
}).toThrow('error message')
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
it('does not throw on error when throwOnError is false', () => {
|
|
108
|
-
const logger = createDebugLogger({ enabled: true, throwOnError: false })
|
|
109
|
-
|
|
110
|
-
expect(() => {
|
|
111
|
-
logger.error('test', 'error message')
|
|
112
|
-
}).not.toThrow()
|
|
113
|
-
})
|
|
114
|
-
})
|
package/src/utils/debug.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
export type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'
|
|
2
|
-
|
|
3
|
-
export interface DebugOptions {
|
|
4
|
-
/** Enable/disable logging. Defaults to CANOPYCMS_DEBUG env var */
|
|
5
|
-
enabled?: boolean
|
|
6
|
-
/** Minimum log level to display. Defaults to DEBUG */
|
|
7
|
-
minLevel?: LogLevel
|
|
8
|
-
/** Prefix for all log messages. Defaults to 'CanopyCMS' */
|
|
9
|
-
prefix?: string
|
|
10
|
-
/** Throw an error when logger.error() is called. Defaults to false */
|
|
11
|
-
throwOnError?: boolean
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const LOG_LEVELS: Record<LogLevel, number> = {
|
|
15
|
-
DEBUG: 0,
|
|
16
|
-
INFO: 1,
|
|
17
|
-
WARN: 2,
|
|
18
|
-
ERROR: 3,
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class DebugLogger {
|
|
22
|
-
private options: DebugOptions
|
|
23
|
-
private timers: Map<string, number> = new Map()
|
|
24
|
-
|
|
25
|
-
constructor(options: DebugOptions = {}) {
|
|
26
|
-
this.options = options
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
private shouldLog(level: LogLevel): boolean {
|
|
30
|
-
// Check enabled at call time to support runtime env var changes
|
|
31
|
-
const enabled = this.options.enabled ?? process.env.CANOPYCMS_DEBUG === 'true'
|
|
32
|
-
if (!enabled) return false
|
|
33
|
-
|
|
34
|
-
const minLevel = this.options.minLevel ?? 'DEBUG'
|
|
35
|
-
return LOG_LEVELS[level] >= LOG_LEVELS[minLevel]
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
private formatMessage(level: LogLevel, category: string, message: string): string {
|
|
39
|
-
const timestamp = new Date().toISOString()
|
|
40
|
-
const prefix = this.options.prefix ?? 'CanopyCMS'
|
|
41
|
-
return `[${timestamp}] [${prefix}:${category}] [${level}] ${message}`
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
debug(category: string, message: string, data?: unknown) {
|
|
45
|
-
if (this.shouldLog('DEBUG')) {
|
|
46
|
-
console.log(this.formatMessage('DEBUG', category, message), data ?? '')
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
info(category: string, message: string, data?: unknown) {
|
|
51
|
-
if (this.shouldLog('INFO')) {
|
|
52
|
-
console.log(this.formatMessage('INFO', category, message), data ?? '')
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
warn(category: string, message: string, data?: unknown) {
|
|
57
|
-
if (this.shouldLog('WARN')) {
|
|
58
|
-
console.warn(this.formatMessage('WARN', category, message), data ?? '')
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
error(category: string, message: string, data?: unknown) {
|
|
63
|
-
const msg = this.formatMessage('ERROR', category, message)
|
|
64
|
-
|
|
65
|
-
if (this.shouldLog('ERROR')) {
|
|
66
|
-
console.error(msg, data ?? '')
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const throwOnError = this.options.throwOnError ?? false
|
|
70
|
-
if (throwOnError) {
|
|
71
|
-
const errorMsg = data ? `${message}: ${JSON.stringify(data)}` : message
|
|
72
|
-
throw new Error(errorMsg)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Start timing an operation
|
|
78
|
-
*/
|
|
79
|
-
time(label: string) {
|
|
80
|
-
this.timers.set(label, Date.now())
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* End timing an operation and log the duration
|
|
85
|
-
*/
|
|
86
|
-
timeEnd(category: string, label: string) {
|
|
87
|
-
const start = this.timers.get(label)
|
|
88
|
-
if (start === undefined) {
|
|
89
|
-
this.warn(category, `Timer '${label}' does not exist`)
|
|
90
|
-
return
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const duration = Date.now() - start
|
|
94
|
-
this.timers.delete(label)
|
|
95
|
-
this.debug(category, `${label} completed`, { durationMs: duration })
|
|
96
|
-
return duration
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Wrap an async function with automatic timing
|
|
101
|
-
*/
|
|
102
|
-
async timed<T>(category: string, label: string, fn: () => Promise<T>): Promise<T> {
|
|
103
|
-
this.time(label)
|
|
104
|
-
try {
|
|
105
|
-
return await fn()
|
|
106
|
-
} finally {
|
|
107
|
-
this.timeEnd(category, label)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Create a debug logger instance
|
|
114
|
-
*/
|
|
115
|
-
export function createDebugLogger(options?: DebugOptions): DebugLogger {
|
|
116
|
-
return new DebugLogger(options)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Default logger for test infrastructure (E2E tests)
|
|
121
|
-
* Enabled via E2E_DEBUG=true
|
|
122
|
-
*/
|
|
123
|
-
export const testLogger = createDebugLogger({
|
|
124
|
-
enabled: process.env.E2E_DEBUG === 'true',
|
|
125
|
-
prefix: 'E2E',
|
|
126
|
-
throwOnError: false,
|
|
127
|
-
})
|
package/src/utils/error.test.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest'
|
|
2
|
-
import { getErrorMessage, isNodeError, isNotFoundError, isPermissionError } from './error'
|
|
3
|
-
|
|
4
|
-
describe('error utilities', () => {
|
|
5
|
-
describe('getErrorMessage', () => {
|
|
6
|
-
it('extracts message from Error instances', () => {
|
|
7
|
-
const err = new Error('Something went wrong')
|
|
8
|
-
expect(getErrorMessage(err)).toBe('Something went wrong')
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
it('returns string errors as-is', () => {
|
|
12
|
-
expect(getErrorMessage('Plain string error')).toBe('Plain string error')
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('converts numbers to strings', () => {
|
|
16
|
-
expect(getErrorMessage(404)).toBe('404')
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('converts null to string', () => {
|
|
20
|
-
expect(getErrorMessage(null)).toBe('null')
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
it('converts undefined to string', () => {
|
|
24
|
-
expect(getErrorMessage(undefined)).toBe('undefined')
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('converts objects to string', () => {
|
|
28
|
-
expect(getErrorMessage({ code: 'ERR' })).toBe('[object Object]')
|
|
29
|
-
})
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
describe('isNodeError', () => {
|
|
33
|
-
it('returns true for errors with code property', () => {
|
|
34
|
-
const err = Object.assign(new Error('Not found'), { code: 'ENOENT' })
|
|
35
|
-
expect(isNodeError(err)).toBe(true)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('returns false for plain Error without code', () => {
|
|
39
|
-
const err = new Error('Plain error')
|
|
40
|
-
expect(isNodeError(err)).toBe(false)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
it('returns false for non-Error objects with code', () => {
|
|
44
|
-
const err = { code: 'ENOENT', message: 'Not found' }
|
|
45
|
-
expect(isNodeError(err)).toBe(false)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it('returns false for strings', () => {
|
|
49
|
-
expect(isNodeError('ENOENT')).toBe(false)
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it('returns false for null', () => {
|
|
53
|
-
expect(isNodeError(null)).toBe(false)
|
|
54
|
-
})
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
describe('isNotFoundError', () => {
|
|
58
|
-
it('returns true for ENOENT errors', () => {
|
|
59
|
-
const err = Object.assign(new Error('Not found'), { code: 'ENOENT' })
|
|
60
|
-
expect(isNotFoundError(err)).toBe(true)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('returns false for other error codes', () => {
|
|
64
|
-
const err = Object.assign(new Error('Permission denied'), {
|
|
65
|
-
code: 'EACCES',
|
|
66
|
-
})
|
|
67
|
-
expect(isNotFoundError(err)).toBe(false)
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
it('returns false for errors without code', () => {
|
|
71
|
-
expect(isNotFoundError(new Error('Not found'))).toBe(false)
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
describe('isPermissionError', () => {
|
|
76
|
-
it('returns true for EACCES errors', () => {
|
|
77
|
-
const err = Object.assign(new Error('Permission denied'), {
|
|
78
|
-
code: 'EACCES',
|
|
79
|
-
})
|
|
80
|
-
expect(isPermissionError(err)).toBe(true)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('returns false for other error codes', () => {
|
|
84
|
-
const err = Object.assign(new Error('Not found'), { code: 'ENOENT' })
|
|
85
|
-
expect(isPermissionError(err)).toBe(false)
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
it('returns false for errors without code', () => {
|
|
89
|
-
expect(isPermissionError(new Error('Permission denied'))).toBe(false)
|
|
90
|
-
})
|
|
91
|
-
})
|
|
92
|
-
})
|
package/src/utils/error.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Error handling utilities for type-safe error handling.
|
|
3
|
-
*
|
|
4
|
-
* These utilities help convert `catch (err: unknown)` to usable error information
|
|
5
|
-
* without using `any` types.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Extract a message string from an unknown error value.
|
|
10
|
-
*
|
|
11
|
-
* @param err - The caught error (unknown type)
|
|
12
|
-
* @returns A string message suitable for logging or user display
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```ts
|
|
16
|
-
* try {
|
|
17
|
-
* await riskyOperation()
|
|
18
|
-
* } catch (err: unknown) {
|
|
19
|
-
* console.error('Operation failed:', getErrorMessage(err))
|
|
20
|
-
* }
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
export function getErrorMessage(err: unknown): string {
|
|
24
|
-
if (err instanceof Error) {
|
|
25
|
-
return err.message
|
|
26
|
-
}
|
|
27
|
-
if (typeof err === 'string') {
|
|
28
|
-
return err
|
|
29
|
-
}
|
|
30
|
-
return String(err)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Type guard to check if an error is a Node.js system error with a code property.
|
|
35
|
-
*
|
|
36
|
-
* @param err - The caught error (unknown type)
|
|
37
|
-
* @returns True if the error has a `code` property (like ENOENT, EACCES, etc.)
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```ts
|
|
41
|
-
* try {
|
|
42
|
-
* await fs.readFile(path)
|
|
43
|
-
* } catch (err: unknown) {
|
|
44
|
-
* if (isNodeError(err) && err.code === 'ENOENT') {
|
|
45
|
-
* return null // File not found is expected
|
|
46
|
-
* }
|
|
47
|
-
* throw err
|
|
48
|
-
* }
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
export function isNodeError(err: unknown): err is NodeJS.ErrnoException {
|
|
52
|
-
return err instanceof Error && 'code' in err
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Check if an error indicates a "file not found" condition.
|
|
57
|
-
*
|
|
58
|
-
* @param err - The caught error (unknown type)
|
|
59
|
-
* @returns True if the error is ENOENT (file/directory not found)
|
|
60
|
-
*/
|
|
61
|
-
export function isNotFoundError(err: unknown): boolean {
|
|
62
|
-
return isNodeError(err) && err.code === 'ENOENT'
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Check if an error indicates a "permission denied" condition.
|
|
67
|
-
*
|
|
68
|
-
* @param err - The caught error (unknown type)
|
|
69
|
-
* @returns True if the error is EACCES (permission denied)
|
|
70
|
-
*/
|
|
71
|
-
export function isPermissionError(err: unknown): boolean {
|
|
72
|
-
return isNodeError(err) && err.code === 'EACCES'
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Check if an error indicates a "file already exists" condition.
|
|
77
|
-
*
|
|
78
|
-
* @param err - The caught error (unknown type)
|
|
79
|
-
* @returns True if the error is EEXIST (file already exists)
|
|
80
|
-
*/
|
|
81
|
-
export function isFileExistsError(err: unknown): boolean {
|
|
82
|
-
return isNodeError(err) && err.code === 'EEXIST'
|
|
83
|
-
}
|
package/src/utils/format.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { ContentFormat } from '../config'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Get the file extension for a content format
|
|
5
|
-
* @param format - The content format (md, mdx, json)
|
|
6
|
-
* @returns The file extension including the dot (e.g., '.md', '.json')
|
|
7
|
-
*/
|
|
8
|
-
export const getFormatExtension = (format: ContentFormat): string => {
|
|
9
|
-
if (format === 'md') return '.md'
|
|
10
|
-
if (format === 'mdx') return '.mdx'
|
|
11
|
-
return '.json'
|
|
12
|
-
}
|