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
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from 'fs'
|
|
2
|
-
import { join } from 'pathe'
|
|
3
|
-
import { z } from 'zod'
|
|
4
|
-
import chokidar from 'chokidar'
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
ContentFormat,
|
|
8
|
-
CollectionConfig,
|
|
9
|
-
RootCollectionConfig,
|
|
10
|
-
EntryTypeConfig,
|
|
11
|
-
} from '../config'
|
|
12
|
-
import type { ContentId } from '../paths/types'
|
|
13
|
-
import type { EntrySchemaRegistry } from './types'
|
|
14
|
-
import { extractSlugFromFilename, extractIdFromFilename } from '../content-id-index'
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Zod schema for entry type metadata in .collection.json files.
|
|
18
|
-
* Each entry type has a name, format, and schema reference to the entry schema registry.
|
|
19
|
-
*/
|
|
20
|
-
const entryTypeMetaSchema = z.object({
|
|
21
|
-
name: z.string().min(1),
|
|
22
|
-
format: z.enum(['md', 'mdx', 'json']),
|
|
23
|
-
schema: z.string().min(1), // Entry schema registry key (validated at resolution time)
|
|
24
|
-
label: z.string().optional(),
|
|
25
|
-
default: z.boolean().optional(),
|
|
26
|
-
maxItems: z.number().int().positive().optional(),
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Zod schema for .collection.json files
|
|
31
|
-
*
|
|
32
|
-
* A collection folder can contain:
|
|
33
|
-
* - entries: Array of entry types with their own schemas
|
|
34
|
-
* - collections: Nested collections (discovered via their own .collection.json files)
|
|
35
|
-
*
|
|
36
|
-
* Note: We can't validate `schema` against entry schema registry keys at parse time because:
|
|
37
|
-
* 1. Entry schema registry is passed at runtime (not available during Zod schema definition)
|
|
38
|
-
* 2. Would create circular dependency (loader → services → config → loader)
|
|
39
|
-
*
|
|
40
|
-
* Validation of schema references happens in resolution functions with clear error messages.
|
|
41
|
-
*/
|
|
42
|
-
const collectionMetaSchema = z
|
|
43
|
-
.object({
|
|
44
|
-
name: z.string().min(1),
|
|
45
|
-
label: z.string().optional(),
|
|
46
|
-
entries: z.array(entryTypeMetaSchema).optional(),
|
|
47
|
-
order: z.array(z.string()), // Embedded IDs for ordering items (required)
|
|
48
|
-
})
|
|
49
|
-
.refine((data) => data.entries && data.entries.length > 0, {
|
|
50
|
-
message: 'Collection must have at least one entry type',
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Zod schema for root .collection.json file (content/.collection.json)
|
|
55
|
-
* Like other collections but no name/path (derived from contentRoot)
|
|
56
|
-
*/
|
|
57
|
-
const rootCollectionMetaSchema = z.object({
|
|
58
|
-
label: z.string().optional(),
|
|
59
|
-
entries: z.array(entryTypeMetaSchema).optional(),
|
|
60
|
-
order: z.array(z.string()).optional(), // Embedded IDs for ordering items
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
export type EntryTypeMeta = {
|
|
64
|
-
name: string
|
|
65
|
-
format: 'md' | 'mdx' | 'json'
|
|
66
|
-
schema: string // Entry schema registry key
|
|
67
|
-
label?: string
|
|
68
|
-
default?: boolean
|
|
69
|
-
maxItems?: number
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export type CollectionMeta = {
|
|
73
|
-
name: string
|
|
74
|
-
label?: string
|
|
75
|
-
entries?: EntryTypeMeta[]
|
|
76
|
-
order: string[] // Embedded IDs for ordering items (required)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export type RootCollectionMeta = {
|
|
80
|
-
label?: string
|
|
81
|
-
entries?: EntryTypeMeta[]
|
|
82
|
-
order?: string[] // Embedded IDs for ordering items
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Recursively scans a directory for .collection.json files.
|
|
87
|
-
*
|
|
88
|
-
* Discovery Rules:
|
|
89
|
-
* - Scans recursively from the base directory (content root)
|
|
90
|
-
* - Each directory can have at most ONE .collection.json file
|
|
91
|
-
* - Collection path is derived from the directory structure (e.g., "docs/api" for content/docs/api/)
|
|
92
|
-
* - Collection name comes from the "name" field in .collection.json, NOT the directory name
|
|
93
|
-
* - Directories without .collection.json are still scanned for nested collections
|
|
94
|
-
* - Invalid .collection.json files cause the entire scan to fail with a descriptive error
|
|
95
|
-
*
|
|
96
|
-
* @param baseDir - The directory to scan (absolute path)
|
|
97
|
-
* @param relativePath - Current path relative to content root (used for recursion)
|
|
98
|
-
* @returns Array of collection metadata with resolved paths
|
|
99
|
-
*/
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Strip embedded ID from a directory or file name.
|
|
103
|
-
* e.g., "docs.bChqT78gcaLd" -> "docs"
|
|
104
|
-
* e.g., "home.home.agfzDt2RLpSn.json" -> "home"
|
|
105
|
-
*/
|
|
106
|
-
function stripEmbeddedIdFromName(name: string): string {
|
|
107
|
-
// Use extractSlugFromFilename which handles the ID extraction logic
|
|
108
|
-
return extractSlugFromFilename(name)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async function scanForCollectionMeta(
|
|
112
|
-
baseDir: string,
|
|
113
|
-
relativePath: string = '',
|
|
114
|
-
): Promise<Array<CollectionMeta & { path: string; contentId?: ContentId }>> {
|
|
115
|
-
const collections: Array<CollectionMeta & { path: string; contentId?: ContentId }> = []
|
|
116
|
-
|
|
117
|
-
try {
|
|
118
|
-
const entries = await fs.readdir(baseDir, { withFileTypes: true })
|
|
119
|
-
|
|
120
|
-
for (const entry of entries) {
|
|
121
|
-
if (!entry.isDirectory()) continue
|
|
122
|
-
|
|
123
|
-
const folderName = entry.name
|
|
124
|
-
// Strip embedded ID from folder name for logical path
|
|
125
|
-
// e.g., "docs.bChqT78gcaLd" -> "docs"
|
|
126
|
-
const logicalName = stripEmbeddedIdFromName(folderName)
|
|
127
|
-
// Extract embedded ContentId from directory name (e.g., "posts.a1b2c3d4e5f6" → "a1b2c3d4e5f6")
|
|
128
|
-
const collectionContentId = extractIdFromFilename(folderName) ?? undefined
|
|
129
|
-
const folderPath = relativePath ? `${relativePath}/${logicalName}` : logicalName
|
|
130
|
-
const absolutePath = join(baseDir, folderName)
|
|
131
|
-
const metaPath = join(absolutePath, '.collection.json')
|
|
132
|
-
|
|
133
|
-
// Try to load collection meta file
|
|
134
|
-
try {
|
|
135
|
-
await fs.access(metaPath)
|
|
136
|
-
const content = await fs.readFile(metaPath, 'utf-8')
|
|
137
|
-
const parsed = JSON.parse(content)
|
|
138
|
-
|
|
139
|
-
// Validate with Zod
|
|
140
|
-
const meta = collectionMetaSchema.parse(parsed) as CollectionMeta
|
|
141
|
-
|
|
142
|
-
collections.push({
|
|
143
|
-
...meta,
|
|
144
|
-
path: folderPath, // Path derived from folder name
|
|
145
|
-
contentId: collectionContentId,
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
// Recursively scan for nested collection folders (they'll have their own .collection.json files)
|
|
149
|
-
const nestedCollections = await scanForCollectionMeta(absolutePath, folderPath)
|
|
150
|
-
collections.push(...nestedCollections)
|
|
151
|
-
} catch (err) {
|
|
152
|
-
if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
|
|
153
|
-
// File exists but is invalid
|
|
154
|
-
console.error(`Error loading ${metaPath}:`, err)
|
|
155
|
-
throw new Error(`Invalid .collection.json in ${folderPath}: ${(err as Error).message}`)
|
|
156
|
-
}
|
|
157
|
-
// No .collection.json - still scan subfolders in case they have collections
|
|
158
|
-
const nestedCollections = await scanForCollectionMeta(absolutePath, folderPath)
|
|
159
|
-
collections.push(...nestedCollections)
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return collections
|
|
164
|
-
} catch (err) {
|
|
165
|
-
if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
166
|
-
return []
|
|
167
|
-
}
|
|
168
|
-
throw err
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Loads all .collection.json meta files from contentRoot, including root.
|
|
174
|
-
*
|
|
175
|
-
* This function orchestrates the complete discovery process:
|
|
176
|
-
* 1. Attempts to load the root .collection.json (contentRoot/.collection.json) - optional
|
|
177
|
-
* 2. Recursively scans all subdirectories for .collection.json files
|
|
178
|
-
* 3. Returns both root configuration and nested collections
|
|
179
|
-
*
|
|
180
|
-
* Meta File Structure:
|
|
181
|
-
* - Root: contentRoot/.collection.json (optional, defines root-level entry types)
|
|
182
|
-
* - Collections: contentRoot/[path]/.collection.json (defines collection in that directory)
|
|
183
|
-
*
|
|
184
|
-
* @param contentRoot - Absolute path to the content directory
|
|
185
|
-
* @returns Object containing root meta (if exists) and array of collection metas with paths
|
|
186
|
-
* @throws Error if any .collection.json file is malformed or invalid
|
|
187
|
-
*/
|
|
188
|
-
export async function loadCollectionMetaFiles(contentRoot: string): Promise<{
|
|
189
|
-
root: RootCollectionMeta | null
|
|
190
|
-
collections: Array<CollectionMeta & { path: string; contentId?: ContentId }>
|
|
191
|
-
}> {
|
|
192
|
-
// Load root .collection.json (optional)
|
|
193
|
-
let root: RootCollectionMeta | null = null
|
|
194
|
-
const rootMetaPath = join(contentRoot, '.collection.json')
|
|
195
|
-
|
|
196
|
-
try {
|
|
197
|
-
await fs.access(rootMetaPath)
|
|
198
|
-
} catch (err) {
|
|
199
|
-
// No root .collection.json - that's okay
|
|
200
|
-
if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
201
|
-
// File doesn't exist, that's fine
|
|
202
|
-
} else {
|
|
203
|
-
throw err
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// If file exists, try to read and parse it
|
|
208
|
-
try {
|
|
209
|
-
const content = await fs.readFile(rootMetaPath, 'utf-8')
|
|
210
|
-
const parsed = JSON.parse(content)
|
|
211
|
-
root = rootCollectionMetaSchema.parse(parsed) as RootCollectionMeta
|
|
212
|
-
} catch (err) {
|
|
213
|
-
// Only handle errors if the file exists (not ENOENT)
|
|
214
|
-
const errno = (err as NodeJS.ErrnoException).code
|
|
215
|
-
if (errno !== 'ENOENT') {
|
|
216
|
-
throw new Error(`Invalid root .collection.json`)
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Scan for collection folders
|
|
221
|
-
const collections = await scanForCollectionMeta(contentRoot)
|
|
222
|
-
|
|
223
|
-
return { root, collections }
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Resolve schema references for entry types
|
|
228
|
-
*/
|
|
229
|
-
function resolveEntryTypes(
|
|
230
|
-
entryTypes: EntryTypeMeta[],
|
|
231
|
-
entrySchemaRegistry: EntrySchemaRegistry,
|
|
232
|
-
contextName: string,
|
|
233
|
-
): EntryTypeConfig[] {
|
|
234
|
-
return entryTypes.map((entryType) => {
|
|
235
|
-
const resolvedSchema = entrySchemaRegistry[entryType.schema]
|
|
236
|
-
if (!resolvedSchema) {
|
|
237
|
-
throw new Error(
|
|
238
|
-
`Schema reference "${entryType.schema}" in entry type "${entryType.name}" (${contextName}) not found in registry. ` +
|
|
239
|
-
`Available schemas: ${Object.keys(entrySchemaRegistry).join(', ')}`,
|
|
240
|
-
)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return {
|
|
244
|
-
name: entryType.name,
|
|
245
|
-
label: entryType.label,
|
|
246
|
-
format: entryType.format as ContentFormat,
|
|
247
|
-
schema: resolvedSchema,
|
|
248
|
-
schemaRef: entryType.schema,
|
|
249
|
-
default: entryType.default,
|
|
250
|
-
maxItems: entryType.maxItems,
|
|
251
|
-
}
|
|
252
|
-
})
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Resolve schema references for a single collection
|
|
257
|
-
*/
|
|
258
|
-
function resolveCollectionMeta(
|
|
259
|
-
meta: CollectionMeta & { path: string; contentId?: ContentId },
|
|
260
|
-
entrySchemaRegistry: EntrySchemaRegistry,
|
|
261
|
-
allCollections: Array<CollectionMeta & { path: string; contentId?: ContentId }>,
|
|
262
|
-
): CollectionConfig {
|
|
263
|
-
// Resolve entry types
|
|
264
|
-
const entries =
|
|
265
|
-
meta.entries && meta.entries.length > 0
|
|
266
|
-
? resolveEntryTypes(meta.entries, entrySchemaRegistry, `collection "${meta.name}"`)
|
|
267
|
-
: undefined
|
|
268
|
-
|
|
269
|
-
// Find nested collections (subfolders with .collection.json)
|
|
270
|
-
const nestedCollections = allCollections.filter((col) => {
|
|
271
|
-
return (
|
|
272
|
-
col.path.startsWith(`${meta.path}/`) &&
|
|
273
|
-
col.path.split('/').length === meta.path.split('/').length + 1
|
|
274
|
-
)
|
|
275
|
-
})
|
|
276
|
-
|
|
277
|
-
const collections =
|
|
278
|
-
nestedCollections.length > 0
|
|
279
|
-
? nestedCollections.map((nestedMeta) =>
|
|
280
|
-
resolveCollectionMeta(nestedMeta, entrySchemaRegistry, allCollections),
|
|
281
|
-
)
|
|
282
|
-
: undefined
|
|
283
|
-
|
|
284
|
-
return {
|
|
285
|
-
name: meta.name,
|
|
286
|
-
label: meta.label,
|
|
287
|
-
path: meta.path,
|
|
288
|
-
contentId: meta.contentId,
|
|
289
|
-
...(entries && { entries }),
|
|
290
|
-
...(meta.order && { order: meta.order }),
|
|
291
|
-
...(collections && { collections }),
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Resolve schema references for root collection and all collections.
|
|
297
|
-
*
|
|
298
|
-
* This function takes the loaded meta files (which contain string references like "postSchema")
|
|
299
|
-
* and resolves them to actual EntrySchema arrays from the entry schema registry.
|
|
300
|
-
*
|
|
301
|
-
* Resolution Process:
|
|
302
|
-
* 1. Root entry types: Resolve "schema" string to entry schema registry lookup
|
|
303
|
-
* 2. Top-level collections: Resolve recursively, building nested tree structure
|
|
304
|
-
* 3. Nested collections: Automatically grouped under their parent collections
|
|
305
|
-
*
|
|
306
|
-
* @param metaFiles - Loaded meta files from loadCollectionMetaFiles()
|
|
307
|
-
* @param entrySchemaRegistry - Map of schema names to EntrySchema arrays
|
|
308
|
-
* @returns Fully resolved root collection config ready for use by CanopyCMS
|
|
309
|
-
* @throws Error if any schema reference doesn't exist in registry (with helpful suggestions)
|
|
310
|
-
*/
|
|
311
|
-
export function resolveCollectionReferences(
|
|
312
|
-
metaFiles: {
|
|
313
|
-
root: RootCollectionMeta | null
|
|
314
|
-
collections: Array<CollectionMeta & { path: string; contentId?: ContentId }>
|
|
315
|
-
},
|
|
316
|
-
entrySchemaRegistry: EntrySchemaRegistry,
|
|
317
|
-
): RootCollectionConfig {
|
|
318
|
-
// Build result object dynamically to avoid readonly conflicts
|
|
319
|
-
const result: Record<string, unknown> = {}
|
|
320
|
-
|
|
321
|
-
// Pass through root label if present
|
|
322
|
-
if (metaFiles.root?.label) {
|
|
323
|
-
result.label = metaFiles.root.label
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Resolve root entry types
|
|
327
|
-
if (metaFiles.root?.entries && metaFiles.root.entries.length > 0) {
|
|
328
|
-
result.entries = resolveEntryTypes(
|
|
329
|
-
metaFiles.root.entries,
|
|
330
|
-
entrySchemaRegistry,
|
|
331
|
-
'root collection',
|
|
332
|
-
)
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Pass through root order array (embedded IDs for sorting)
|
|
336
|
-
if (metaFiles.root?.order) {
|
|
337
|
-
result.order = metaFiles.root.order
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// Resolve top-level collections (no slashes in path)
|
|
341
|
-
const topLevelCollections = metaFiles.collections.filter((meta) => !meta.path.includes('/'))
|
|
342
|
-
|
|
343
|
-
if (topLevelCollections.length > 0) {
|
|
344
|
-
result.collections = topLevelCollections.map((meta) =>
|
|
345
|
-
resolveCollectionMeta(meta, entrySchemaRegistry, metaFiles.collections),
|
|
346
|
-
)
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return result as RootCollectionConfig
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Watch for changes to .collection.json files
|
|
354
|
-
*/
|
|
355
|
-
export function watchCollectionMetaFiles(contentRoot: string, onChange: () => void): () => void {
|
|
356
|
-
const watcher = chokidar.watch(`${contentRoot}/**/.collection.json`, {
|
|
357
|
-
ignoreInitial: true,
|
|
358
|
-
})
|
|
359
|
-
|
|
360
|
-
watcher.on('add', onChange)
|
|
361
|
-
watcher.on('change', onChange)
|
|
362
|
-
watcher.on('unlink', onChange)
|
|
363
|
-
|
|
364
|
-
// Return cleanup function
|
|
365
|
-
return () => watcher.close()
|
|
366
|
-
}
|
package/src/schema/resolver.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Schema resolver for CanopyCMS.
|
|
3
|
-
*
|
|
4
|
-
* Loads and resolves schema from .collection.json files in the content directory.
|
|
5
|
-
* This is the single source of truth for collection structure.
|
|
6
|
-
*
|
|
7
|
-
* Field schemas are defined in the entry schema registry and referenced by name
|
|
8
|
-
* in .collection.json files for reusability and type safety.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { RootCollectionConfig } from '../config'
|
|
12
|
-
import type { EntrySchemaRegistry, SchemaResolutionResult, SchemaSourceInfo } from './types'
|
|
13
|
-
import { loadCollectionMetaFiles, resolveCollectionReferences } from './meta-loader'
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Resolve schema from .collection.json files.
|
|
17
|
-
*
|
|
18
|
-
* This is the primary entry point for loading schema configuration.
|
|
19
|
-
* It discovers all .collection.json files in the content directory
|
|
20
|
-
* and resolves schema references using the provided registry.
|
|
21
|
-
*
|
|
22
|
-
* @param contentRoot - Path to the content directory
|
|
23
|
-
* @param entrySchemaRegistry - Map of entry schema names to field definitions
|
|
24
|
-
* @returns Resolved schema configuration
|
|
25
|
-
* @throws Error if schema references cannot be resolved
|
|
26
|
-
*/
|
|
27
|
-
export async function resolveSchema(
|
|
28
|
-
contentRoot: string,
|
|
29
|
-
entrySchemaRegistry: EntrySchemaRegistry,
|
|
30
|
-
): Promise<SchemaResolutionResult> {
|
|
31
|
-
// Load all .collection.json meta files
|
|
32
|
-
const metaFiles = await loadCollectionMetaFiles(contentRoot)
|
|
33
|
-
|
|
34
|
-
// Build source info for debugging
|
|
35
|
-
const sources: SchemaSourceInfo[] = []
|
|
36
|
-
|
|
37
|
-
if (metaFiles.root) {
|
|
38
|
-
sources.push({
|
|
39
|
-
path: '.collection.json',
|
|
40
|
-
type: 'root',
|
|
41
|
-
collections: [],
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
for (const collection of metaFiles.collections) {
|
|
46
|
-
sources.push({
|
|
47
|
-
path: `${collection.path}/.collection.json`,
|
|
48
|
-
type: 'collection',
|
|
49
|
-
collections: [collection.name],
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Resolve schema references to actual field definitions
|
|
54
|
-
const schema = resolveCollectionReferences(metaFiles, entrySchemaRegistry)
|
|
55
|
-
|
|
56
|
-
return { schema, sources }
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Check if content root has any .collection.json files.
|
|
61
|
-
*
|
|
62
|
-
* @param contentRoot - Path to the content directory
|
|
63
|
-
* @returns true if at least one .collection.json file exists
|
|
64
|
-
*/
|
|
65
|
-
export async function hasSchemaFiles(contentRoot: string): Promise<boolean> {
|
|
66
|
-
const metaFiles = await loadCollectionMetaFiles(contentRoot)
|
|
67
|
-
return metaFiles.root !== null || metaFiles.collections.length > 0
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Validate schema completeness.
|
|
72
|
-
*
|
|
73
|
-
* Checks that the resolved schema has at least one collection or
|
|
74
|
-
* root entries definition.
|
|
75
|
-
*
|
|
76
|
-
* @param schema - Resolved schema to validate
|
|
77
|
-
* @returns true if schema is valid
|
|
78
|
-
*/
|
|
79
|
-
export function isValidSchema(schema: RootCollectionConfig): boolean {
|
|
80
|
-
const hasEntries = !!(schema.entries && schema.entries.length > 0)
|
|
81
|
-
const hasCollections = !!(schema.collections && schema.collections.length > 0)
|
|
82
|
-
return hasEntries || hasCollections
|
|
83
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Schema Store Types - Client-safe type definitions for schema CRUD operations.
|
|
3
|
-
*
|
|
4
|
-
* These types are separated from schema-store.ts to allow client-side code
|
|
5
|
-
* to import them without pulling in Node.js dependencies (fs, path).
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { ContentFormat } from '../config'
|
|
9
|
-
import type { LogicalPath } from '../paths/types'
|
|
10
|
-
|
|
11
|
-
// ============================================================================
|
|
12
|
-
// Input Types
|
|
13
|
-
// ============================================================================
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Input for creating a new collection
|
|
17
|
-
*/
|
|
18
|
-
export interface CreateCollectionInput {
|
|
19
|
-
name: string
|
|
20
|
-
label?: string
|
|
21
|
-
parentPath?: LogicalPath // Parent collection path (empty/undefined for root-level)
|
|
22
|
-
entries: CreateEntryTypeInput[]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Input for creating a new entry type
|
|
27
|
-
*/
|
|
28
|
-
export interface CreateEntryTypeInput {
|
|
29
|
-
name: string
|
|
30
|
-
label?: string
|
|
31
|
-
format: ContentFormat
|
|
32
|
-
schema: string // Entry schema registry key
|
|
33
|
-
default?: boolean
|
|
34
|
-
maxItems?: number
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Input for updating a collection
|
|
39
|
-
*/
|
|
40
|
-
export interface UpdateCollectionInput {
|
|
41
|
-
name?: string
|
|
42
|
-
label?: string
|
|
43
|
-
slug?: string // Directory name for renaming (e.g., "posts" in "posts.{id}/")
|
|
44
|
-
order?: string[] // Embedded IDs for ordering
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Input for updating an entry type
|
|
49
|
-
*/
|
|
50
|
-
export interface UpdateEntryTypeInput {
|
|
51
|
-
label?: string
|
|
52
|
-
format?: ContentFormat
|
|
53
|
-
schema?: string // Entry schema registry key
|
|
54
|
-
default?: boolean
|
|
55
|
-
maxItems?: number
|
|
56
|
-
}
|