convex-cms 0.0.1
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/cli/commands/admin.d.ts +16 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +88 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +18 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils/detectConvexUrl.d.ts +13 -0
- package/dist/cli/utils/detectConvexUrl.d.ts.map +1 -0
- package/dist/cli/utils/detectConvexUrl.js +48 -0
- package/dist/cli/utils/detectConvexUrl.js.map +1 -0
- package/dist/cli/utils/openBrowser.d.ts +7 -0
- package/dist/cli/utils/openBrowser.d.ts.map +1 -0
- package/dist/cli/utils/openBrowser.js +17 -0
- package/dist/cli/utils/openBrowser.js.map +1 -0
- package/dist/client/admin-config.d.ts +126 -0
- package/dist/client/admin-config.d.ts.map +1 -0
- package/dist/client/admin-config.js +117 -0
- package/dist/client/admin-config.js.map +1 -0
- package/dist/client/adminApi.d.ts +2273 -0
- package/dist/client/adminApi.d.ts.map +1 -0
- package/dist/client/adminApi.js +716 -0
- package/dist/client/adminApi.js.map +1 -0
- package/dist/client/agentTools.d.ts +933 -0
- package/dist/client/agentTools.d.ts.map +1 -0
- package/dist/client/agentTools.js +1004 -0
- package/dist/client/agentTools.js.map +1 -0
- package/dist/client/argTypes.d.ts +212 -0
- package/dist/client/argTypes.d.ts.map +1 -0
- package/dist/client/argTypes.js +5 -0
- package/dist/client/argTypes.js.map +1 -0
- package/dist/client/field-types.d.ts +55 -0
- package/dist/client/field-types.d.ts.map +1 -0
- package/dist/client/field-types.js +152 -0
- package/dist/client/field-types.js.map +1 -0
- package/dist/client/index.d.ts +189 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +668 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/queryBuilder.d.ts +765 -0
- package/dist/client/queryBuilder.d.ts.map +1 -0
- package/dist/client/queryBuilder.js +970 -0
- package/dist/client/queryBuilder.js.map +1 -0
- package/dist/client/schema/codegen.d.ts +128 -0
- package/dist/client/schema/codegen.d.ts.map +1 -0
- package/dist/client/schema/codegen.js +318 -0
- package/dist/client/schema/codegen.js.map +1 -0
- package/dist/client/schema/defineContentType.d.ts +221 -0
- package/dist/client/schema/defineContentType.d.ts.map +1 -0
- package/dist/client/schema/defineContentType.js +380 -0
- package/dist/client/schema/defineContentType.js.map +1 -0
- package/dist/client/schema/index.d.ts +85 -0
- package/dist/client/schema/index.d.ts.map +1 -0
- package/dist/client/schema/index.js +92 -0
- package/dist/client/schema/index.js.map +1 -0
- package/dist/client/schema/schemaDrift.d.ts +199 -0
- package/dist/client/schema/schemaDrift.d.ts.map +1 -0
- package/dist/client/schema/schemaDrift.js +340 -0
- package/dist/client/schema/schemaDrift.js.map +1 -0
- package/dist/client/schema/typedClient.d.ts +401 -0
- package/dist/client/schema/typedClient.d.ts.map +1 -0
- package/dist/client/schema/typedClient.js +269 -0
- package/dist/client/schema/typedClient.js.map +1 -0
- package/dist/client/schema/types.d.ts +477 -0
- package/dist/client/schema/types.d.ts.map +1 -0
- package/dist/client/schema/types.js +39 -0
- package/dist/client/schema/types.js.map +1 -0
- package/dist/client/types.d.ts +449 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +149 -0
- package/dist/client/types.js.map +1 -0
- package/dist/client/workflows.d.ts +51 -0
- package/dist/client/workflows.d.ts.map +1 -0
- package/dist/client/workflows.js +103 -0
- package/dist/client/workflows.js.map +1 -0
- package/dist/client/wrapper.d.ts +2198 -0
- package/dist/client/wrapper.d.ts.map +1 -0
- package/dist/client/wrapper.js +2651 -0
- package/dist/client/wrapper.js.map +1 -0
- package/dist/component/_generated/api.d.ts +124 -0
- package/dist/component/_generated/api.d.ts.map +1 -0
- package/dist/component/_generated/api.js +31 -0
- package/dist/component/_generated/api.js.map +1 -0
- package/dist/component/_generated/component.d.ts +4321 -0
- package/dist/component/_generated/component.d.ts.map +1 -0
- package/dist/component/_generated/component.js +11 -0
- package/dist/component/_generated/component.js.map +1 -0
- package/dist/component/_generated/dataModel.d.ts +46 -0
- package/dist/component/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/_generated/dataModel.js +11 -0
- package/dist/component/_generated/dataModel.js.map +1 -0
- package/dist/component/_generated/server.d.ts +121 -0
- package/dist/component/_generated/server.d.ts.map +1 -0
- package/dist/component/_generated/server.js +78 -0
- package/dist/component/_generated/server.js.map +1 -0
- package/dist/component/auditLog.d.ts +410 -0
- package/dist/component/auditLog.d.ts.map +1 -0
- package/dist/component/auditLog.js +607 -0
- package/dist/component/auditLog.js.map +1 -0
- package/dist/component/authorization.d.ts +323 -0
- package/dist/component/authorization.d.ts.map +1 -0
- package/dist/component/authorization.js +464 -0
- package/dist/component/authorization.js.map +1 -0
- package/dist/component/authorizationHooks.d.ts +184 -0
- package/dist/component/authorizationHooks.d.ts.map +1 -0
- package/dist/component/authorizationHooks.js +521 -0
- package/dist/component/authorizationHooks.js.map +1 -0
- package/dist/component/bulkOperations.d.ts +200 -0
- package/dist/component/bulkOperations.d.ts.map +1 -0
- package/dist/component/bulkOperations.js +568 -0
- package/dist/component/bulkOperations.js.map +1 -0
- package/dist/component/contentEntries.d.ts +719 -0
- package/dist/component/contentEntries.d.ts.map +1 -0
- package/dist/component/contentEntries.js +1617 -0
- package/dist/component/contentEntries.js.map +1 -0
- package/dist/component/contentEntryMutations.d.ts +505 -0
- package/dist/component/contentEntryMutations.d.ts.map +1 -0
- package/dist/component/contentEntryMutations.js +1009 -0
- package/dist/component/contentEntryMutations.js.map +1 -0
- package/dist/component/contentEntryValidation.d.ts +115 -0
- package/dist/component/contentEntryValidation.d.ts.map +1 -0
- package/dist/component/contentEntryValidation.js +546 -0
- package/dist/component/contentEntryValidation.js.map +1 -0
- package/dist/component/contentLock.d.ts +328 -0
- package/dist/component/contentLock.d.ts.map +1 -0
- package/dist/component/contentLock.js +471 -0
- package/dist/component/contentLock.js.map +1 -0
- package/dist/component/contentTypeMigration.d.ts +411 -0
- package/dist/component/contentTypeMigration.d.ts.map +1 -0
- package/dist/component/contentTypeMigration.js +805 -0
- package/dist/component/contentTypeMigration.js.map +1 -0
- package/dist/component/contentTypeMutations.d.ts +975 -0
- package/dist/component/contentTypeMutations.d.ts.map +1 -0
- package/dist/component/contentTypeMutations.js +768 -0
- package/dist/component/contentTypeMutations.js.map +1 -0
- package/dist/component/contentTypes.d.ts +538 -0
- package/dist/component/contentTypes.d.ts.map +1 -0
- package/dist/component/contentTypes.js +304 -0
- package/dist/component/contentTypes.js.map +1 -0
- package/dist/component/convex.config.d.ts +42 -0
- package/dist/component/convex.config.d.ts.map +1 -0
- package/dist/component/convex.config.js +43 -0
- package/dist/component/convex.config.js.map +1 -0
- package/dist/component/documentTypes.d.ts +186 -0
- package/dist/component/documentTypes.d.ts.map +1 -0
- package/dist/component/documentTypes.js +23 -0
- package/dist/component/documentTypes.js.map +1 -0
- package/dist/component/eventEmitter.d.ts +281 -0
- package/dist/component/eventEmitter.d.ts.map +1 -0
- package/dist/component/eventEmitter.js +300 -0
- package/dist/component/eventEmitter.js.map +1 -0
- package/dist/component/exportImport.d.ts +1120 -0
- package/dist/component/exportImport.d.ts.map +1 -0
- package/dist/component/exportImport.js +931 -0
- package/dist/component/exportImport.js.map +1 -0
- package/dist/component/index.d.ts +28 -0
- package/dist/component/index.d.ts.map +1 -0
- package/dist/component/index.js +142 -0
- package/dist/component/index.js.map +1 -0
- package/dist/component/lib/deepReferenceResolver.d.ts +252 -0
- package/dist/component/lib/deepReferenceResolver.d.ts.map +1 -0
- package/dist/component/lib/deepReferenceResolver.js +601 -0
- package/dist/component/lib/deepReferenceResolver.js.map +1 -0
- package/dist/component/lib/errors.d.ts +306 -0
- package/dist/component/lib/errors.d.ts.map +1 -0
- package/dist/component/lib/errors.js +407 -0
- package/dist/component/lib/errors.js.map +1 -0
- package/dist/component/lib/index.d.ts +10 -0
- package/dist/component/lib/index.d.ts.map +1 -0
- package/dist/component/lib/index.js +33 -0
- package/dist/component/lib/index.js.map +1 -0
- package/dist/component/lib/mediaReferenceResolver.d.ts +217 -0
- package/dist/component/lib/mediaReferenceResolver.d.ts.map +1 -0
- package/dist/component/lib/mediaReferenceResolver.js +326 -0
- package/dist/component/lib/mediaReferenceResolver.js.map +1 -0
- package/dist/component/lib/metadataExtractor.d.ts +245 -0
- package/dist/component/lib/metadataExtractor.d.ts.map +1 -0
- package/dist/component/lib/metadataExtractor.js +548 -0
- package/dist/component/lib/metadataExtractor.js.map +1 -0
- package/dist/component/lib/mutationAuth.d.ts +95 -0
- package/dist/component/lib/mutationAuth.d.ts.map +1 -0
- package/dist/component/lib/mutationAuth.js +146 -0
- package/dist/component/lib/mutationAuth.js.map +1 -0
- package/dist/component/lib/queries.d.ts +17 -0
- package/dist/component/lib/queries.d.ts.map +1 -0
- package/dist/component/lib/queries.js +49 -0
- package/dist/component/lib/queries.js.map +1 -0
- package/dist/component/lib/ragContentChunker.d.ts +423 -0
- package/dist/component/lib/ragContentChunker.d.ts.map +1 -0
- package/dist/component/lib/ragContentChunker.js +897 -0
- package/dist/component/lib/ragContentChunker.js.map +1 -0
- package/dist/component/lib/referenceResolver.d.ts +175 -0
- package/dist/component/lib/referenceResolver.d.ts.map +1 -0
- package/dist/component/lib/referenceResolver.js +293 -0
- package/dist/component/lib/referenceResolver.js.map +1 -0
- package/dist/component/lib/slugGenerator.d.ts +71 -0
- package/dist/component/lib/slugGenerator.d.ts.map +1 -0
- package/dist/component/lib/slugGenerator.js +207 -0
- package/dist/component/lib/slugGenerator.js.map +1 -0
- package/dist/component/lib/slugUniqueness.d.ts +131 -0
- package/dist/component/lib/slugUniqueness.d.ts.map +1 -0
- package/dist/component/lib/slugUniqueness.js +229 -0
- package/dist/component/lib/slugUniqueness.js.map +1 -0
- package/dist/component/lib/softDelete.d.ts +18 -0
- package/dist/component/lib/softDelete.d.ts.map +1 -0
- package/dist/component/lib/softDelete.js +29 -0
- package/dist/component/lib/softDelete.js.map +1 -0
- package/dist/component/localeFallbackChain.d.ts +410 -0
- package/dist/component/localeFallbackChain.d.ts.map +1 -0
- package/dist/component/localeFallbackChain.js +467 -0
- package/dist/component/localeFallbackChain.js.map +1 -0
- package/dist/component/localeFields.d.ts +508 -0
- package/dist/component/localeFields.d.ts.map +1 -0
- package/dist/component/localeFields.js +592 -0
- package/dist/component/localeFields.js.map +1 -0
- package/dist/component/mediaAssetMutations.d.ts +235 -0
- package/dist/component/mediaAssetMutations.d.ts.map +1 -0
- package/dist/component/mediaAssetMutations.js +558 -0
- package/dist/component/mediaAssetMutations.js.map +1 -0
- package/dist/component/mediaAssets.d.ts +168 -0
- package/dist/component/mediaAssets.d.ts.map +1 -0
- package/dist/component/mediaAssets.js +618 -0
- package/dist/component/mediaAssets.js.map +1 -0
- package/dist/component/mediaFolderMutations.d.ts +642 -0
- package/dist/component/mediaFolderMutations.d.ts.map +1 -0
- package/dist/component/mediaFolderMutations.js +849 -0
- package/dist/component/mediaFolderMutations.js.map +1 -0
- package/dist/component/mediaUploadMutations.d.ts +136 -0
- package/dist/component/mediaUploadMutations.d.ts.map +1 -0
- package/dist/component/mediaUploadMutations.js +205 -0
- package/dist/component/mediaUploadMutations.js.map +1 -0
- package/dist/component/mediaVariantMutations.d.ts +468 -0
- package/dist/component/mediaVariantMutations.d.ts.map +1 -0
- package/dist/component/mediaVariantMutations.js +737 -0
- package/dist/component/mediaVariantMutations.js.map +1 -0
- package/dist/component/mediaVariants.d.ts +525 -0
- package/dist/component/mediaVariants.d.ts.map +1 -0
- package/dist/component/mediaVariants.js +661 -0
- package/dist/component/mediaVariants.js.map +1 -0
- package/dist/component/ragContentIndexer.d.ts +595 -0
- package/dist/component/ragContentIndexer.d.ts.map +1 -0
- package/dist/component/ragContentIndexer.js +794 -0
- package/dist/component/ragContentIndexer.js.map +1 -0
- package/dist/component/rateLimitHooks.d.ts +266 -0
- package/dist/component/rateLimitHooks.d.ts.map +1 -0
- package/dist/component/rateLimitHooks.js +412 -0
- package/dist/component/rateLimitHooks.js.map +1 -0
- package/dist/component/roles.d.ts +649 -0
- package/dist/component/roles.d.ts.map +1 -0
- package/dist/component/roles.js +884 -0
- package/dist/component/roles.js.map +1 -0
- package/dist/component/scheduledPublish.d.ts +182 -0
- package/dist/component/scheduledPublish.d.ts.map +1 -0
- package/dist/component/scheduledPublish.js +304 -0
- package/dist/component/scheduledPublish.js.map +1 -0
- package/dist/component/schema.d.ts +4114 -0
- package/dist/component/schema.d.ts.map +1 -0
- package/dist/component/schema.js +469 -0
- package/dist/component/schema.js.map +1 -0
- package/dist/component/taxonomies.d.ts +476 -0
- package/dist/component/taxonomies.d.ts.map +1 -0
- package/dist/component/taxonomies.js +785 -0
- package/dist/component/taxonomies.js.map +1 -0
- package/dist/component/taxonomyMutations.d.ts +206 -0
- package/dist/component/taxonomyMutations.d.ts.map +1 -0
- package/dist/component/taxonomyMutations.js +1001 -0
- package/dist/component/taxonomyMutations.js.map +1 -0
- package/dist/component/trash.d.ts +265 -0
- package/dist/component/trash.d.ts.map +1 -0
- package/dist/component/trash.js +621 -0
- package/dist/component/trash.js.map +1 -0
- package/dist/component/types.d.ts +4 -0
- package/dist/component/types.d.ts.map +1 -0
- package/dist/component/types.js +2 -0
- package/dist/component/types.js.map +1 -0
- package/dist/component/userContext.d.ts +508 -0
- package/dist/component/userContext.d.ts.map +1 -0
- package/dist/component/userContext.js +615 -0
- package/dist/component/userContext.js.map +1 -0
- package/dist/component/validation.d.ts +387 -0
- package/dist/component/validation.d.ts.map +1 -0
- package/dist/component/validation.js +1052 -0
- package/dist/component/validation.js.map +1 -0
- package/dist/component/validators.d.ts +4645 -0
- package/dist/component/validators.d.ts.map +1 -0
- package/dist/component/validators.js +641 -0
- package/dist/component/validators.js.map +1 -0
- package/dist/component/versionMutations.d.ts +216 -0
- package/dist/component/versionMutations.d.ts.map +1 -0
- package/dist/component/versionMutations.js +321 -0
- package/dist/component/versionMutations.js.map +1 -0
- package/dist/component/webhookTrigger.d.ts +770 -0
- package/dist/component/webhookTrigger.d.ts.map +1 -0
- package/dist/component/webhookTrigger.js +1413 -0
- package/dist/component/webhookTrigger.js.map +1 -0
- package/dist/react/index.d.ts +316 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +558 -0
- package/dist/react/index.js.map +1 -0
- package/dist/test.d.ts +2230 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +1107 -0
- package/dist/test.js.map +1 -0
- package/package.json +95 -0
- package/src/cli/commands/admin.ts +104 -0
- package/src/cli/index.ts +21 -0
- package/src/cli/utils/detectConvexUrl.ts +54 -0
- package/src/cli/utils/openBrowser.ts +16 -0
- package/src/client/admin-config.ts +138 -0
- package/src/client/adminApi.ts +942 -0
- package/src/client/agentTools.ts +1311 -0
- package/src/client/argTypes.ts +316 -0
- package/src/client/field-types.ts +187 -0
- package/src/client/index.ts +1301 -0
- package/src/client/queryBuilder.ts +1100 -0
- package/src/client/schema/codegen.ts +500 -0
- package/src/client/schema/defineContentType.ts +501 -0
- package/src/client/schema/index.ts +169 -0
- package/src/client/schema/schemaDrift.ts +574 -0
- package/src/client/schema/typedClient.ts +688 -0
- package/src/client/schema/types.ts +666 -0
- package/src/client/types.ts +723 -0
- package/src/client/workflows.ts +141 -0
- package/src/client/wrapper.ts +4304 -0
- package/src/component/_generated/api.ts +140 -0
- package/src/component/_generated/component.ts +5029 -0
- package/src/component/_generated/dataModel.ts +60 -0
- package/src/component/_generated/server.ts +156 -0
- package/src/component/authorization.ts +647 -0
- package/src/component/authorizationHooks.ts +668 -0
- package/src/component/bulkOperations.ts +687 -0
- package/src/component/contentEntries.ts +1976 -0
- package/src/component/contentEntryMutations.ts +1223 -0
- package/src/component/contentEntryValidation.ts +707 -0
- package/src/component/contentLock.ts +550 -0
- package/src/component/contentTypeMigration.ts +1064 -0
- package/src/component/contentTypeMutations.ts +969 -0
- package/src/component/contentTypes.ts +346 -0
- package/src/component/convex.config.ts +44 -0
- package/src/component/documentTypes.ts +240 -0
- package/src/component/eventEmitter.ts +485 -0
- package/src/component/exportImport.ts +1169 -0
- package/src/component/index.ts +491 -0
- package/src/component/lib/deepReferenceResolver.ts +999 -0
- package/src/component/lib/errors.ts +816 -0
- package/src/component/lib/index.ts +145 -0
- package/src/component/lib/mediaReferenceResolver.ts +495 -0
- package/src/component/lib/metadataExtractor.ts +792 -0
- package/src/component/lib/mutationAuth.ts +199 -0
- package/src/component/lib/queries.ts +79 -0
- package/src/component/lib/ragContentChunker.ts +1371 -0
- package/src/component/lib/referenceResolver.ts +430 -0
- package/src/component/lib/slugGenerator.ts +262 -0
- package/src/component/lib/slugUniqueness.ts +333 -0
- package/src/component/lib/softDelete.ts +44 -0
- package/src/component/localeFallbackChain.ts +673 -0
- package/src/component/localeFields.ts +896 -0
- package/src/component/mediaAssetMutations.ts +725 -0
- package/src/component/mediaAssets.ts +932 -0
- package/src/component/mediaFolderMutations.ts +1046 -0
- package/src/component/mediaUploadMutations.ts +224 -0
- package/src/component/mediaVariantMutations.ts +900 -0
- package/src/component/mediaVariants.ts +793 -0
- package/src/component/ragContentIndexer.ts +1067 -0
- package/src/component/rateLimitHooks.ts +572 -0
- package/src/component/roles.ts +1360 -0
- package/src/component/scheduledPublish.ts +358 -0
- package/src/component/schema.ts +617 -0
- package/src/component/taxonomies.ts +949 -0
- package/src/component/taxonomyMutations.ts +1210 -0
- package/src/component/trash.ts +724 -0
- package/src/component/userContext.ts +898 -0
- package/src/component/validation.ts +1388 -0
- package/src/component/validators.ts +949 -0
- package/src/component/versionMutations.ts +392 -0
- package/src/component/webhookTrigger.ts +1922 -0
- package/src/react/index.ts +898 -0
- package/src/test.ts +1580 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Type Schema Definition
|
|
3
|
+
*
|
|
4
|
+
* The `defineContentType` function creates type-safe content type definitions
|
|
5
|
+
* using Convex validators. Types are automatically inferred via Convex's
|
|
6
|
+
* native `Infer<typeof validator>` pattern.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { v } from "convex/values";
|
|
11
|
+
* import { defineContentType } from "@convex-cms/core";
|
|
12
|
+
*
|
|
13
|
+
* export const blogPost = defineContentType({
|
|
14
|
+
* name: "blog_post",
|
|
15
|
+
* validator: v.object({
|
|
16
|
+
* title: v.string(),
|
|
17
|
+
* slug: v.string(),
|
|
18
|
+
* content: v.string(),
|
|
19
|
+
* author: v.id("contentEntries"),
|
|
20
|
+
* category: v.optional(v.union(v.literal("tech"), v.literal("news"))),
|
|
21
|
+
* publishedAt: v.optional(v.number()),
|
|
22
|
+
* }),
|
|
23
|
+
* meta: {
|
|
24
|
+
* displayName: "Blog Post",
|
|
25
|
+
* titleField: "title",
|
|
26
|
+
* slugField: "slug",
|
|
27
|
+
* fields: {
|
|
28
|
+
* title: { label: "Title", maxLength: 200 },
|
|
29
|
+
* content: { label: "Content", renderAs: "richText", searchable: true },
|
|
30
|
+
* author: { label: "Author", renderAs: "reference" },
|
|
31
|
+
* category: { label: "Category", renderAs: "select" },
|
|
32
|
+
* },
|
|
33
|
+
* },
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import type { Validator } from "convex/values";
|
|
39
|
+
import type {
|
|
40
|
+
ContentTypeConfig,
|
|
41
|
+
ContentTypeDefinition,
|
|
42
|
+
ContentTypeMeta,
|
|
43
|
+
FieldMeta,
|
|
44
|
+
} from "./types.js";
|
|
45
|
+
|
|
46
|
+
// =============================================================================
|
|
47
|
+
// Content Type Name Validation
|
|
48
|
+
// =============================================================================
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Pattern for valid content type names.
|
|
52
|
+
* - Lowercase letters, numbers, and underscores only
|
|
53
|
+
* - Must start with a letter
|
|
54
|
+
* - 1-50 characters
|
|
55
|
+
*/
|
|
56
|
+
const CONTENT_TYPE_NAME_PATTERN = /^[a-z][a-z0-9_]{0,49}$/;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Validates a content type name.
|
|
60
|
+
*
|
|
61
|
+
* @param name - The name to validate
|
|
62
|
+
* @throws Error if the name is invalid
|
|
63
|
+
*/
|
|
64
|
+
function validateContentTypeName(name: string): void {
|
|
65
|
+
if (!name) {
|
|
66
|
+
throw new Error("Content type name is required");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!CONTENT_TYPE_NAME_PATTERN.test(name)) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Invalid content type name "${name}". ` +
|
|
72
|
+
"Names must start with a lowercase letter and contain only " +
|
|
73
|
+
"lowercase letters, numbers, and underscores (1-50 characters)."
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// =============================================================================
|
|
79
|
+
// Define Content Type
|
|
80
|
+
// =============================================================================
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Creates a type-safe content type definition.
|
|
84
|
+
*
|
|
85
|
+
* This function accepts a Convex validator and CMS metadata, returning a
|
|
86
|
+
* definition object that can be used for:
|
|
87
|
+
* 1. **Type inference**: `Infer<typeof definition.validator>` gives the data type
|
|
88
|
+
* 2. **Runtime validation**: The validator is used to validate content at runtime
|
|
89
|
+
* 3. **Admin UI configuration**: Metadata provides display hints and field labels
|
|
90
|
+
*
|
|
91
|
+
* ## Why Convex Validators?
|
|
92
|
+
*
|
|
93
|
+
* Using Convex validators directly (instead of custom schema builders) provides:
|
|
94
|
+
* - **Native type inference** via `Infer<typeof>` - no custom type machinery
|
|
95
|
+
* - **Familiarity** - same validators used in Convex functions
|
|
96
|
+
* - **Full power** - supports unions, literals, nested objects, arrays, IDs
|
|
97
|
+
* - **Maintenance-free** - types are maintained by Convex
|
|
98
|
+
*
|
|
99
|
+
* ## Example: Basic Blog Post
|
|
100
|
+
*
|
|
101
|
+
* ```typescript
|
|
102
|
+
* import { v, Infer } from "convex/values";
|
|
103
|
+
* import { defineContentType } from "@convex-cms/core";
|
|
104
|
+
*
|
|
105
|
+
* export const blogPost = defineContentType({
|
|
106
|
+
* name: "blog_post",
|
|
107
|
+
* validator: v.object({
|
|
108
|
+
* title: v.string(),
|
|
109
|
+
* content: v.string(),
|
|
110
|
+
* publishedAt: v.optional(v.number()),
|
|
111
|
+
* }),
|
|
112
|
+
* meta: {
|
|
113
|
+
* displayName: "Blog Post",
|
|
114
|
+
* titleField: "title",
|
|
115
|
+
* },
|
|
116
|
+
* });
|
|
117
|
+
*
|
|
118
|
+
* // Type is automatically inferred
|
|
119
|
+
* type BlogPostData = Infer<typeof blogPost.validator>;
|
|
120
|
+
* // { title: string; content: string; publishedAt?: number }
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
* ## Example: Product with Variants
|
|
124
|
+
*
|
|
125
|
+
* ```typescript
|
|
126
|
+
* export const product = defineContentType({
|
|
127
|
+
* name: "product",
|
|
128
|
+
* validator: v.object({
|
|
129
|
+
* name: v.string(),
|
|
130
|
+
* price: v.number(),
|
|
131
|
+
* description: v.optional(v.string()),
|
|
132
|
+
* variants: v.array(v.object({
|
|
133
|
+
* sku: v.string(),
|
|
134
|
+
* name: v.string(),
|
|
135
|
+
* price: v.number(),
|
|
136
|
+
* attributes: v.record(v.string(), v.string()),
|
|
137
|
+
* })),
|
|
138
|
+
* seo: v.optional(v.object({
|
|
139
|
+
* title: v.string(),
|
|
140
|
+
* description: v.string(),
|
|
141
|
+
* keywords: v.array(v.string()),
|
|
142
|
+
* })),
|
|
143
|
+
* }),
|
|
144
|
+
* meta: {
|
|
145
|
+
* displayName: "Product",
|
|
146
|
+
* titleField: "name",
|
|
147
|
+
* fields: {
|
|
148
|
+
* name: { label: "Product Name", searchable: true },
|
|
149
|
+
* price: { label: "Base Price" },
|
|
150
|
+
* variants: { label: "Variants", renderAs: "json" },
|
|
151
|
+
* seo: { label: "SEO Settings", renderAs: "json" },
|
|
152
|
+
* },
|
|
153
|
+
* },
|
|
154
|
+
* });
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* @param config - The content type configuration
|
|
158
|
+
* @returns A frozen content type definition object
|
|
159
|
+
*
|
|
160
|
+
* @typeParam TName - The literal string type of the content type name
|
|
161
|
+
* @typeParam TValidator - The Convex validator type
|
|
162
|
+
*/
|
|
163
|
+
export function defineContentType<
|
|
164
|
+
const TName extends string,
|
|
165
|
+
TValidator extends Validator<Record<string, unknown>, "required", string>
|
|
166
|
+
>(
|
|
167
|
+
config: ContentTypeConfig<TValidator> & { name: TName }
|
|
168
|
+
): ContentTypeDefinition<TName, TValidator> {
|
|
169
|
+
// Validate the content type name at definition time
|
|
170
|
+
validateContentTypeName(config.name);
|
|
171
|
+
|
|
172
|
+
// Create the definition object
|
|
173
|
+
const definition: ContentTypeDefinition<TName, TValidator> = {
|
|
174
|
+
name: config.name,
|
|
175
|
+
validator: config.validator,
|
|
176
|
+
meta: config.meta as ContentTypeMeta,
|
|
177
|
+
_type: "content_type_definition",
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// Freeze to prevent accidental mutation
|
|
181
|
+
return Object.freeze(definition);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// =============================================================================
|
|
185
|
+
// Schema Collection Utilities
|
|
186
|
+
// =============================================================================
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Creates a content schema from multiple content type definitions.
|
|
190
|
+
*
|
|
191
|
+
* This is a convenience function that validates the schema and provides
|
|
192
|
+
* runtime utilities for working with multiple content types.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```typescript
|
|
196
|
+
* import { createContentSchema } from "@convex-cms/core";
|
|
197
|
+
*
|
|
198
|
+
* export const contentSchema = createContentSchema({
|
|
199
|
+
* blogPost,
|
|
200
|
+
* author,
|
|
201
|
+
* product,
|
|
202
|
+
* });
|
|
203
|
+
*
|
|
204
|
+
* // Get a specific definition
|
|
205
|
+
* const blogDef = contentSchema.getDefinition("blog_post");
|
|
206
|
+
*
|
|
207
|
+
* // List all content type names
|
|
208
|
+
* const names = contentSchema.getContentTypeNames();
|
|
209
|
+
* // ["blog_post", "author", "product"]
|
|
210
|
+
* ```
|
|
211
|
+
*
|
|
212
|
+
* @param definitions - An object containing content type definitions
|
|
213
|
+
* @returns A schema object with utility methods
|
|
214
|
+
*/
|
|
215
|
+
export function createContentSchema<
|
|
216
|
+
T extends Record<string, ContentTypeDefinition>
|
|
217
|
+
>(definitions: T): ContentSchemaInstance<T> {
|
|
218
|
+
// Build a map of name -> definition for quick lookup
|
|
219
|
+
const byName = new Map<string, ContentTypeDefinition>();
|
|
220
|
+
const names: string[] = [];
|
|
221
|
+
|
|
222
|
+
for (const [_key, def] of Object.entries(definitions)) {
|
|
223
|
+
if (byName.has(def.name)) {
|
|
224
|
+
throw new Error(
|
|
225
|
+
`Duplicate content type name "${def.name}" in schema. ` +
|
|
226
|
+
`Content type names must be unique.`
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
byName.set(def.name, def);
|
|
230
|
+
names.push(def.name);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return Object.freeze({
|
|
234
|
+
definitions,
|
|
235
|
+
|
|
236
|
+
getDefinition(name: string): ContentTypeDefinition | undefined {
|
|
237
|
+
return byName.get(name);
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
getContentTypeNames(): string[] {
|
|
241
|
+
return [...names];
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
hasContentType(name: string): boolean {
|
|
245
|
+
return byName.has(name);
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
getDefinitionByKey<K extends keyof T>(key: K): T[K] {
|
|
249
|
+
return definitions[key];
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* A content schema instance with utility methods.
|
|
256
|
+
*/
|
|
257
|
+
export interface ContentSchemaInstance<
|
|
258
|
+
T extends Record<string, ContentTypeDefinition>
|
|
259
|
+
> {
|
|
260
|
+
/**
|
|
261
|
+
* The raw definitions object.
|
|
262
|
+
*/
|
|
263
|
+
readonly definitions: T;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Get a content type definition by its name.
|
|
267
|
+
*
|
|
268
|
+
* @param name - The content type name (e.g., "blog_post")
|
|
269
|
+
* @returns The definition or undefined if not found
|
|
270
|
+
*/
|
|
271
|
+
getDefinition(name: string): ContentTypeDefinition | undefined;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Get all content type names in the schema.
|
|
275
|
+
*
|
|
276
|
+
* @returns Array of content type names
|
|
277
|
+
*/
|
|
278
|
+
getContentTypeNames(): string[];
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Check if a content type exists in the schema.
|
|
282
|
+
*
|
|
283
|
+
* @param name - The content type name to check
|
|
284
|
+
* @returns true if the content type exists
|
|
285
|
+
*/
|
|
286
|
+
hasContentType(name: string): boolean;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Get a content type definition by its key in the definitions object.
|
|
290
|
+
*
|
|
291
|
+
* @param key - The key used in the definitions object
|
|
292
|
+
* @returns The definition
|
|
293
|
+
*/
|
|
294
|
+
getDefinitionByKey<K extends keyof T>(key: K): T[K];
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// =============================================================================
|
|
298
|
+
// Schema to Field Definitions Converter
|
|
299
|
+
// =============================================================================
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Field definition format expected by the CMS database.
|
|
303
|
+
* This is the format stored in contentTypes.fields.
|
|
304
|
+
*/
|
|
305
|
+
export interface DatabaseFieldDefinition {
|
|
306
|
+
name: string;
|
|
307
|
+
label: string;
|
|
308
|
+
type: string;
|
|
309
|
+
required: boolean;
|
|
310
|
+
searchable?: boolean;
|
|
311
|
+
localized?: boolean;
|
|
312
|
+
description?: string;
|
|
313
|
+
defaultValue?: unknown;
|
|
314
|
+
options?: Record<string, unknown>;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Converts a content type definition to the database field format.
|
|
319
|
+
*
|
|
320
|
+
* This bridges the gap between the code-defined schema and the
|
|
321
|
+
* database format used by the CMS component.
|
|
322
|
+
*
|
|
323
|
+
* @param definition - The content type definition
|
|
324
|
+
* @returns An array of field definitions for the database
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```typescript
|
|
328
|
+
* const fields = toFieldDefinitions(blogPost);
|
|
329
|
+
* // [
|
|
330
|
+
* // { name: "title", label: "Title", type: "text", required: true, ... },
|
|
331
|
+
* // { name: "content", label: "Content", type: "richText", required: true, ... },
|
|
332
|
+
* // ]
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
335
|
+
export function toFieldDefinitions(
|
|
336
|
+
definition: ContentTypeDefinition
|
|
337
|
+
): DatabaseFieldDefinition[] {
|
|
338
|
+
// Extract field information from the validator
|
|
339
|
+
// This requires introspecting the validator structure
|
|
340
|
+
const validatorFields = extractValidatorFields(definition.validator);
|
|
341
|
+
const fieldMeta = definition.meta.fields || {};
|
|
342
|
+
|
|
343
|
+
return validatorFields.map((field) => {
|
|
344
|
+
const meta = fieldMeta[field.name as keyof typeof fieldMeta] || {};
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
name: field.name,
|
|
348
|
+
label: meta.label || field.name,
|
|
349
|
+
type: meta.renderAs || inferFieldType(field.validatorType),
|
|
350
|
+
required: field.required,
|
|
351
|
+
searchable: meta.searchable,
|
|
352
|
+
localized: meta.localized,
|
|
353
|
+
description: meta.description,
|
|
354
|
+
options: buildFieldOptions(field, meta),
|
|
355
|
+
};
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Field information extracted from a validator.
|
|
361
|
+
*/
|
|
362
|
+
interface ExtractedField {
|
|
363
|
+
name: string;
|
|
364
|
+
validatorType: string;
|
|
365
|
+
required: boolean;
|
|
366
|
+
innerValidator?: unknown;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Extract field information from a Convex object validator.
|
|
371
|
+
*
|
|
372
|
+
* @internal
|
|
373
|
+
*/
|
|
374
|
+
function extractValidatorFields(
|
|
375
|
+
validator: Validator<Record<string, unknown>, "required", string>
|
|
376
|
+
): ExtractedField[] {
|
|
377
|
+
const fields: ExtractedField[] = [];
|
|
378
|
+
|
|
379
|
+
// Convex validators have internal structure we can introspect
|
|
380
|
+
// The validator has a `fields` property for object validators
|
|
381
|
+
const validatorAny = validator as unknown as {
|
|
382
|
+
fieldPaths?: Record<string, unknown>;
|
|
383
|
+
type?: string;
|
|
384
|
+
kind?: string;
|
|
385
|
+
fields?: Record<
|
|
386
|
+
string,
|
|
387
|
+
{ fieldPath: string; validator: { isOptional?: string; type?: string; kind?: string } }
|
|
388
|
+
>;
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
// Try to access the validator's internal field definitions
|
|
392
|
+
if (validatorAny.fields) {
|
|
393
|
+
for (const [name, fieldInfo] of Object.entries(validatorAny.fields)) {
|
|
394
|
+
const innerValidator = fieldInfo.validator;
|
|
395
|
+
const isOptional = innerValidator?.isOptional === "optional";
|
|
396
|
+
|
|
397
|
+
fields.push({
|
|
398
|
+
name,
|
|
399
|
+
validatorType: innerValidator?.type || innerValidator?.kind || "unknown",
|
|
400
|
+
required: !isOptional,
|
|
401
|
+
innerValidator,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return fields;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Infer a CMS field type from a Convex validator type.
|
|
411
|
+
*
|
|
412
|
+
* @internal
|
|
413
|
+
*/
|
|
414
|
+
function inferFieldType(validatorType: string): string {
|
|
415
|
+
const typeMap: Record<string, string> = {
|
|
416
|
+
string: "text",
|
|
417
|
+
number: "number",
|
|
418
|
+
boolean: "boolean",
|
|
419
|
+
id: "reference",
|
|
420
|
+
array: "json",
|
|
421
|
+
object: "json",
|
|
422
|
+
union: "select",
|
|
423
|
+
literal: "select",
|
|
424
|
+
bytes: "media",
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
return typeMap[validatorType] || "text";
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Build field options from extracted field info and metadata.
|
|
432
|
+
*
|
|
433
|
+
* This function maps all FieldMeta options to the database field options format.
|
|
434
|
+
* The options object is stored in contentTypes.fields[].options and is used
|
|
435
|
+
* for validation and UI rendering.
|
|
436
|
+
*
|
|
437
|
+
* @internal
|
|
438
|
+
*/
|
|
439
|
+
function buildFieldOptions(
|
|
440
|
+
field: ExtractedField,
|
|
441
|
+
meta: FieldMeta
|
|
442
|
+
): Record<string, unknown> | undefined {
|
|
443
|
+
const options: Record<string, unknown> = {};
|
|
444
|
+
|
|
445
|
+
// ==========================================================================
|
|
446
|
+
// Text Field Options
|
|
447
|
+
// ==========================================================================
|
|
448
|
+
if (meta.minLength !== undefined) options.minLength = meta.minLength;
|
|
449
|
+
if (meta.maxLength !== undefined) options.maxLength = meta.maxLength;
|
|
450
|
+
if (meta.pattern !== undefined) options.pattern = meta.pattern;
|
|
451
|
+
// Note: patternMessage and multiline are UI hints, not stored in component schema
|
|
452
|
+
// They could be stored in a separate UI hints field if needed
|
|
453
|
+
|
|
454
|
+
// ==========================================================================
|
|
455
|
+
// Number Field Options
|
|
456
|
+
// ==========================================================================
|
|
457
|
+
if (meta.min !== undefined) options.min = meta.min;
|
|
458
|
+
if (meta.max !== undefined) options.max = meta.max;
|
|
459
|
+
if (meta.step !== undefined) options.step = meta.step;
|
|
460
|
+
if (meta.precision !== undefined) options.precision = meta.precision;
|
|
461
|
+
// Note: prefix/suffix are UI hints, not stored in component schema
|
|
462
|
+
|
|
463
|
+
// ==========================================================================
|
|
464
|
+
// Reference Field Options
|
|
465
|
+
// ==========================================================================
|
|
466
|
+
if (meta.allowedContentTypes !== undefined) options.allowedContentTypes = meta.allowedContentTypes;
|
|
467
|
+
if (meta.multiple !== undefined) options.multiple = meta.multiple;
|
|
468
|
+
if (meta.minItems !== undefined) options.minItems = meta.minItems;
|
|
469
|
+
// Note: maxItems maps to minItems in the component (for validation purposes)
|
|
470
|
+
// The component schema has minItems but not maxItems - we'll add it anyway
|
|
471
|
+
// for forward compatibility
|
|
472
|
+
|
|
473
|
+
// ==========================================================================
|
|
474
|
+
// Media Field Options
|
|
475
|
+
// ==========================================================================
|
|
476
|
+
if (meta.allowedMimeTypes !== undefined) options.allowedMimeTypes = meta.allowedMimeTypes;
|
|
477
|
+
if (meta.maxFileSize !== undefined) options.maxFileSize = meta.maxFileSize;
|
|
478
|
+
|
|
479
|
+
// ==========================================================================
|
|
480
|
+
// Select/MultiSelect Field Options
|
|
481
|
+
// ==========================================================================
|
|
482
|
+
if (meta.options !== undefined) options.options = meta.options;
|
|
483
|
+
// Note: minSelections/maxSelections could be mapped to minItems/maxItems
|
|
484
|
+
|
|
485
|
+
// ==========================================================================
|
|
486
|
+
// Rich Text Field Options
|
|
487
|
+
// ==========================================================================
|
|
488
|
+
if (meta.allowedBlocks !== undefined) options.allowedBlocks = meta.allowedBlocks;
|
|
489
|
+
if (meta.allowedMarks !== undefined) options.allowedMarks = meta.allowedMarks;
|
|
490
|
+
|
|
491
|
+
// ==========================================================================
|
|
492
|
+
// Taxonomy Field Options (tags/category)
|
|
493
|
+
// ==========================================================================
|
|
494
|
+
if (meta.taxonomyId !== undefined) options.taxonomyId = meta.taxonomyId;
|
|
495
|
+
if (meta.allowCreate !== undefined) options.allowCreate = meta.allowCreate;
|
|
496
|
+
if (meta.maxTags !== undefined) options.maxTags = meta.maxTags;
|
|
497
|
+
if (meta.minTags !== undefined) options.minTags = meta.minTags;
|
|
498
|
+
if (meta.allowMultiple !== undefined) options.allowMultiple = meta.allowMultiple;
|
|
499
|
+
|
|
500
|
+
return Object.keys(options).length > 0 ? options : undefined;
|
|
501
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code-Only Schema System
|
|
3
|
+
*
|
|
4
|
+
* This module provides type-safe content type definitions using Convex validators.
|
|
5
|
+
* Types are automatically inferred via Convex's native `Infer<typeof validator>` pattern.
|
|
6
|
+
*
|
|
7
|
+
* ## Quick Start
|
|
8
|
+
*
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { v, Infer } from "convex/values";
|
|
11
|
+
* import { defineContentType, InferContentType } from "@convex-cms/core";
|
|
12
|
+
*
|
|
13
|
+
* // Define a content type with a Convex validator
|
|
14
|
+
* export const blogPost = defineContentType({
|
|
15
|
+
* name: "blog_post",
|
|
16
|
+
* validator: v.object({
|
|
17
|
+
* title: v.string(),
|
|
18
|
+
* content: v.string(),
|
|
19
|
+
* publishedAt: v.optional(v.number()),
|
|
20
|
+
* }),
|
|
21
|
+
* meta: {
|
|
22
|
+
* displayName: "Blog Post",
|
|
23
|
+
* titleField: "title",
|
|
24
|
+
* },
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* // Type is automatically inferred
|
|
28
|
+
* type BlogPostData = InferContentType<typeof blogPost>;
|
|
29
|
+
* // { title: string; content: string; publishedAt?: number }
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* ## Creating a Schema
|
|
33
|
+
*
|
|
34
|
+
* ```typescript
|
|
35
|
+
* import { createContentSchema, InferSchema } from "@convex-cms/core";
|
|
36
|
+
*
|
|
37
|
+
* // Combine multiple content types into a schema
|
|
38
|
+
* export const contentSchema = createContentSchema({
|
|
39
|
+
* blogPost,
|
|
40
|
+
* author,
|
|
41
|
+
* product,
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* // Infer all types at once
|
|
45
|
+
* export type ContentTypes = InferSchema<typeof contentSchema.definitions>;
|
|
46
|
+
* // {
|
|
47
|
+
* // blog_post: { title: string; content: string; ... };
|
|
48
|
+
* // author: { name: string; bio?: string; ... };
|
|
49
|
+
* // product: { name: string; price: number; ... };
|
|
50
|
+
* // }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* ## Using with CMS Client
|
|
54
|
+
*
|
|
55
|
+
* ```typescript
|
|
56
|
+
* import { createCmsClient } from "@convex-cms/core";
|
|
57
|
+
* import { components } from "./_generated/api";
|
|
58
|
+
* import { contentSchema } from "./schema";
|
|
59
|
+
*
|
|
60
|
+
* // Create a schema-aware CMS client
|
|
61
|
+
* export const cms = createCmsClient(components.convexCms, {
|
|
62
|
+
* schema: contentSchema,
|
|
63
|
+
* // ... other options
|
|
64
|
+
* });
|
|
65
|
+
*
|
|
66
|
+
* // Now get() returns typed data
|
|
67
|
+
* const post = await cms.contentEntries.get<"blog_post">(ctx, id);
|
|
68
|
+
* post.data.title // ✅ string - fully typed
|
|
69
|
+
* post.data.typo // ❌ Error: Property 'typo' does not exist
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @module
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
// =============================================================================
|
|
76
|
+
// Core Functions
|
|
77
|
+
// =============================================================================
|
|
78
|
+
|
|
79
|
+
export { defineContentType, createContentSchema, toFieldDefinitions } from "./defineContentType.js";
|
|
80
|
+
|
|
81
|
+
// =============================================================================
|
|
82
|
+
// Types
|
|
83
|
+
// =============================================================================
|
|
84
|
+
|
|
85
|
+
// Core definition types
|
|
86
|
+
export type {
|
|
87
|
+
ContentTypeConfig,
|
|
88
|
+
ContentTypeDefinition,
|
|
89
|
+
ContentTypeMeta,
|
|
90
|
+
FieldMeta,
|
|
91
|
+
FieldRenderAs,
|
|
92
|
+
} from "./types.js";
|
|
93
|
+
|
|
94
|
+
// Type inference utilities
|
|
95
|
+
export type {
|
|
96
|
+
InferContentType,
|
|
97
|
+
InferSchema,
|
|
98
|
+
ContentSchema,
|
|
99
|
+
SchemaContentTypeNames,
|
|
100
|
+
SchemaContentType,
|
|
101
|
+
ContentTypeFieldNames,
|
|
102
|
+
} from "./types.js";
|
|
103
|
+
|
|
104
|
+
// Schema instance type
|
|
105
|
+
export type { ContentSchemaInstance, DatabaseFieldDefinition } from "./defineContentType.js";
|
|
106
|
+
|
|
107
|
+
// Runtime utilities
|
|
108
|
+
export { isContentTypeDefinition } from "./types.js";
|
|
109
|
+
|
|
110
|
+
// =============================================================================
|
|
111
|
+
// Typed Client Factory
|
|
112
|
+
// =============================================================================
|
|
113
|
+
|
|
114
|
+
export { createTypedCmsClient, TypedContentEntriesApiImpl } from "./typedClient.js";
|
|
115
|
+
|
|
116
|
+
// =============================================================================
|
|
117
|
+
// Schema Drift Detection
|
|
118
|
+
// =============================================================================
|
|
119
|
+
|
|
120
|
+
export {
|
|
121
|
+
detectSchemaDrift,
|
|
122
|
+
formatDriftReport,
|
|
123
|
+
hasErrors,
|
|
124
|
+
filterReportByContentTypes,
|
|
125
|
+
} from "./schemaDrift.js";
|
|
126
|
+
|
|
127
|
+
export type {
|
|
128
|
+
DriftSeverity,
|
|
129
|
+
DriftType,
|
|
130
|
+
DriftIssue,
|
|
131
|
+
DriftSummary,
|
|
132
|
+
SchemaDriftReport,
|
|
133
|
+
DetectDriftOptions,
|
|
134
|
+
} from "./schemaDrift.js";
|
|
135
|
+
|
|
136
|
+
// =============================================================================
|
|
137
|
+
// Type Code Generation
|
|
138
|
+
// =============================================================================
|
|
139
|
+
|
|
140
|
+
export {
|
|
141
|
+
generateTypesFromDatabase,
|
|
142
|
+
generateTypesFromDefinitions,
|
|
143
|
+
validateGeneratedCode,
|
|
144
|
+
} from "./codegen.js";
|
|
145
|
+
|
|
146
|
+
export type {
|
|
147
|
+
CodegenOptions,
|
|
148
|
+
CodegenResult,
|
|
149
|
+
} from "./codegen.js";
|
|
150
|
+
|
|
151
|
+
// =============================================================================
|
|
152
|
+
// Typed Client Types
|
|
153
|
+
// =============================================================================
|
|
154
|
+
|
|
155
|
+
// Typed content entry types
|
|
156
|
+
export type {
|
|
157
|
+
TypedContentEntry,
|
|
158
|
+
TypedPaginationResult,
|
|
159
|
+
TypedContentEntriesApi,
|
|
160
|
+
TypedCreateEntryOptions,
|
|
161
|
+
TypedUpdateEntryOptions,
|
|
162
|
+
TypedListEntriesOptions,
|
|
163
|
+
SchemaDataType,
|
|
164
|
+
ValidContentTypeName,
|
|
165
|
+
HasContentType,
|
|
166
|
+
GetContentTypeDefinition,
|
|
167
|
+
TypedCmsClientConfig,
|
|
168
|
+
TypedCmsClient,
|
|
169
|
+
} from "./typedClient.js";
|