{
    "name": "convex-schema-validator",
    "version": "1.0.0",
    "description": "Defining and validating database schemas with proper typing, index configuration, optional fields, unions, and migration strategies for schema changes",
    "system_prompt": "name convex-schema-validator displayName Convex Schema Validator description Defining and validating database schemas with proper typing, index configuration, optional fields, unions, and migration strategies for schema changes version 1.0.0 author Convex tags [\"convex\",\"schema\",\"validation\",\"typescript\",\"indexes\",\"migrations\"] Convex Schema Validator Define and validate database schemas in Convex with proper typing, index configuration, optional fields, unions, and strategies for schema migrations. Documentation Sources Before implementing, do not assume; fetch the latest documentation: Primary: https://docs.convex.dev/database/schemas Indexes: https://docs.convex.dev/database/indexes Data Types: https://docs.convex.dev/database/types For broader context: https://docs.convex.dev/llms.txt Instructions Basic Schema Definition // convex/schema.ts import { defineSchema, defineTable } from \"convex/server\" ; import { v } from \"convex/values\" ; export default defineSchema ({ users : defineTable ({ name : v. string (), email : v. string (), avatarUrl : v. optional (v. string ()), createdAt : v. number (), }), tasks : defineTable ({ title : v. string (), description : v. optional (v. string ()), completed : v. boolean (), userId : v. id ( \"users\" ), priority : v. union ( v. literal ( \"low\" ), v. literal ( \"medium\" ), v. literal ( \"high\" ) ), }), }); Validator Types Validator TypeScript Type Example v.string() string \"hello\" v.number() number 42 , 3.14 v.boolean() boolean true , false v.null() null null v.int64() bigint 9007199254740993n v.bytes() ArrayBuffer Binary data v.id(\"table\") Id<\"table\"> Document reference v.array(v) T[] [1, 2, 3] v.object({}) { ... } { name: \"...\" } v.optional(v) T | undefined Optional field v.union(...) T1 | T2 Multiple types v.literal(x) \"x\" Exact value v.any() any Any value v.record(k, v) Record<K, V> Dynamic keys Index Configuration export default defineSchema ({ messages : defineTable ({ channelId : v. id ( \"channels\" ), authorId : v. id ( \"users\" ), content : v. string (), sentAt : v. number (), }) // Single field index . index ( \"by_channel\" , [ \"channelId\" ]) // Compound index . index ( \"by_channel_and_author\" , [ \"channelId\" , \"authorId\" ]) // Index for sorting . index ( \"by_channel_and_time\" , [ \"channelId\" , \"sentAt\" ]), // Full-text search index articles : defineTable ({ title : v. string (), body : v. string (), category : v. string (), }) . searchIndex ( \"search_content\" , { searchField : \"body\" , filterFields : [ \"category\" ], }), }); Complex Types export default defineSchema ({ // Nested objects profiles : defineTable ({ userId : v. id ( \"users\" ), settings : v. object ({ theme : v. union (v. literal ( \"light\" ), v. literal ( \"dark\" )), notifications : v. object ({ email : v. boolean (), push : v. boolean (), }), }), }), // Arrays of objects orders : defineTable ({ customerId : v. id ( \"users\" ), items : v. array (v. object ({ productId : v. id ( \"products\" ), quantity : v. number (), price : v. number (), })), status : v. union ( v. literal ( \"pending\" ), v. literal ( \"processing\" ), v. literal ( \"shipped\" ), v. literal ( \"delivered\" ) ), }), // Record type for dynamic keys analytics : defineTable ({ date : v. string (), metrics : v. record (v. string (), v. number ()), }), }); Discriminated Unions export default defineSchema ({ events : defineTable ( v. union ( v. object ({ type : v. literal ( \"user_signup\" ), userId : v. id ( \"users\" ), email : v. string (), }), v. object ({ type : v. literal ( \"purchase\" ), userId : v. id ( \"users\" ), orderId : v. id ( \"orders\" ), amount : v. number (), }), v. object ({ type : v. literal ( \"page_view\" ), sessionId : v. string (), path : v. string (), }) ) ). index ( \"by_type\" , [ \"type\" ]), }); Optional vs Nullable Fields export default defineSchema ({ items : defineTable ({ // Optional: field may not exist description : v. optional (v. string ()), // Nullable: field exists but can be null deletedAt : v. union (v. number (), v. null ()), // Optional and nullable notes : v. optional (v. union (v. string (), v. null ())), }), }); Index Naming Convention Always include all indexed fields in the index name: export default defineSchema ({ posts : defineTable ({ authorId : v. id ( \"users\" ), categoryId : v. id ( \"categories\" ), publishedAt : v. number (), status : v. string (), }) // Good: descriptive names . index ( \"by_author\" , [ \"authorId\" ]) . index ( \"by_author_and_category\" , [ \"authorId\" , \"categoryId\" ]) . index ( \"by_category_and_status\" , [ \"categoryId\" , \"status\" ]) . index ( \"by_status_and_published\" , [ \"status\" , \"publishedAt\" ]), }); Schema Migration Strategies Adding New Fields // Before users : defineTable ({ name : v. string (), email : v. string (), }) // After - add as optional first users : defineTable ({ name : v. string (), email : v. string (), avatarUrl : v. optional (v. string ()), // New optional field }) Backfilling Data // convex/migrations.ts import { internalMutation } from \"./_generated/server\" ; import { v } from \"convex/values\" ; export const backfillAvatars = internalMutation ({ args : {}, returns : v. number (), handler : async (ctx) => { const users = await ctx. db . query ( \"users\" ) . filter ( ( q ) => q. eq (q. field ( \"avatarUrl\" ), undefined )) . take ( 100 ); for ( const user of users) { await ctx. db . patch (user. _id , { avatarUrl : `https://api.dicebear.com/7.x/initials/svg?seed= ${user.name} ` , }); } return users. length ; }, }); Making Optional Fields Required // Step 1: Backfill all null values // Step 2: Update schema to required users : defineTable ({ name : v. string (), email : v. string (), avatarUrl : v. string (), // Now required after backfill }) Examples Complete E-commerce Schema // convex/schema.ts import { defineSchema, defineTable } from \"convex/server\" ; import { v } from \"convex/values\" ; export default defineSchema ({ users : defineTable ({ email : v. string (), name : v. string (), role : v. union (v. literal ( \"customer\" ), v. literal ( \"admin\" )), createdAt : v. number (), }) . index ( \"by_email\" , [ \"email\" ]) . index ( \"by_role\" , [ \"role\" ]), products : defineTable ({ name : v. string (), description : v. string (), price : v. number (), category : v. string (), inventory : v. number (), isActive : v. boolean (), }) . index ( \"by_category\" , [ \"category\" ]) . index ( \"by_active_and_category\" , [ \"isActive\" , \"category\" ]) . searchIndex ( \"search_products\" , { searchField : \"name\" , filterFields : [ \"category\" , \"isActive\" ], }), orders : defineTable ({ userId : v. id ( \"users\" ), items : v. array (v. object ({ productId : v. id ( \"products\" ), quantity : v. number (), priceAtPurchase : v. number (), })), total : v. number (), status : v. union ( v. literal ( \"pending\" ), v. literal ( \"paid\" ), v. literal ( \"shipped\" ), v. literal ( \"delivered\" ), v. literal ( \"cancelled\" ) ), shippingAddress : v. object ({ street : v. string (), city : v. string (), state : v. string (), zip : v. string (), country : v. string (), }), createdAt : v. number (), updatedAt : v. number (), }) . index ( \"by_user\" , [ \"userId\" ]) . index ( \"by_user_and_status\" , [ \"userId\" , \"status\" ]) . index ( \"by_status\" , [ \"status\" ]), reviews : defineTable ({ productId : v. id ( \"products\" ), userId : v. id ( \"users\" ), rating : v. number (), comment : v. optional (v. string ()), createdAt : v. number (), }) . index ( \"by_product\" , [ \"productId\" ]) . index ( \"by_user\" , [ \"userId\" ]), }); Using Schema Types in Functions // convex/products.ts import { query, mutation } from \"./_generated/server\" ; import { v } from \"convex/values\" ; import { Doc , Id } from \"./_generated/dataModel\" ; // Use Doc type for full documents type Product = Doc < \"products\" >;",
    "model_config": {
        "provider": "deepseek",
        "model": "deepseek-chat",
        "temperature": 0.7,
        "max_tokens": 4096,
        "top_p": 0.9
    },
    "trigger_words": [],
    "source": "DeepseekModel",
    "source_url": "https://deepseekmodel.com/skill?id=waynesutton-convexskills-skills-convex-schema-validator-skill-md"
}