@vexcms/core 0.0.8 → 0.0.9

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/media.ts","../src/errors/index.ts","../src/config/defineConfig.ts","../src/config/defineCollection.ts","../src/access/defineAccess.ts","../src/access/hasPermission.ts","../src/config/sanitizeConfig.ts","../src/config/isMediaCollection.ts","../src/config/findCollectionBySlug.ts","../src/fields/checkbox/config.ts","../src/utils.ts","../src/fields/checkbox/columnDef.ts","../src/valueTypes/processAdminOptions.ts","../src/fields/constants.ts","../src/fields/checkbox/schemaValueType.ts","../src/fields/number/config.ts","../src/fields/number/columnDef.ts","../src/fields/number/schemaValueType.ts","../src/fields/select/config.ts","../src/fields/select/columnDef.tsx","../src/fields/select/schemaValueType.ts","../src/fields/text/config.ts","../src/fields/text/columnDef.tsx","../src/fields/text/schemaValueType.ts","../src/fields/date/config.ts","../src/fields/date/columnDef.ts","../src/fields/date/schemaValueType.ts","../src/fields/imageUrl/config.ts","../src/fields/imageUrl/columnDef.tsx","../src/fields/imageUrl/schemaValueType.ts","../src/fields/relationship/config.ts","../src/fields/relationship/columnDef.ts","../src/fields/relationship/schemaValueType.ts","../src/fields/json/config.ts","../src/fields/json/columnDef.ts","../src/fields/json/schemaValueType.ts","../src/fields/richtext/config.ts","../src/fields/richtext/schemaValueType.ts","../src/fields/richtext/columnDef.ts","../src/fields/media/config.ts","../src/fields/media/schemaValueType.ts","../src/fields/array/config.ts","../src/fields/array/columnDef.ts","../src/fields/array/schemaValueType.ts","../src/fields/blocks/config.ts","../src/fields/blocks/schemaValueType.ts","../src/fields/blocks/columnDef.ts","../src/valueTypes/extract.ts","../src/valueTypes/indexes.ts","../src/valueTypes/searchIndexes.ts","../src/valueTypes/merge.ts","../src/valueTypes/slugs.ts","../src/valueTypes/generate.ts","../src/schema/extendTable.ts","../src/fields/media/columnDef.ts","../src/columns/generateColumns.ts","../src/formSchema/generateFormSchema.ts","../src/formSchema/generateFormDefaultValues.ts","../src/fields/ui/config.ts","../src/types/fields.ts","../src/blocks/defineBlock.ts","../src/typeGen/slugToInterfaceName.ts","../src/typeGen/fieldToTypeString.ts","../src/typeGen/generateVexTypes.ts","../src/versioning/constants.ts","../src/versioning/extractUserFields.ts","../src/livePreview/resolvePreviewURL.ts","../src/livePreview/shouldReloadURL.ts","../src/livePreview/constants.ts","../src/convex/previewSnapshot.ts","../src/convex/vexQuery.ts","../src/convex/model/collections.ts","../src/valueTypes/generateCollectionQueries.ts","../src/migrations/diffSchema.ts","../src/migrations/planMigration.ts"],"sourcesContent":["import type { VexField } from \"./fields\";\nimport type { VexCollection, CollectionAdminConfig } from \"./collections\";\n\n/**\n * Interface that file storage plugins must implement.\n * Each method operates on the storage provider (e.g., Convex file storage, S3, Cloudinary).\n */\nexport interface FileStorageAdapter {\n /** Identifier for the storage provider (e.g., \"convex\", \"s3\", \"cloudinary\"). */\n readonly name: string;\n\n /**\n * The Convex value type string for the storageId field in media collections.\n * Determines the schema type at generation time.\n *\n * - Convex adapter: `'v.id(\"_storage\")'` — typed reference to Convex file storage\n * - Generic adapters: `'v.string()'` — plain string for external storage URLs/IDs\n */\n readonly storageIdValueType: string;\n\n /**\n * Get a presigned upload URL from the storage provider.\n * Called by the admin panel before uploading a file.\n *\n * @returns A URL string that accepts file uploads via PUT/POST.\n */\n getUploadUrl: () => Promise<string>;\n\n /**\n * Resolve a storage ID to an accessible URL.\n *\n * @param props.storageId - The storage provider's file identifier.\n * @returns A URL string for accessing the file, or null if the file doesn't exist.\n */\n getUrl: (props: { storageId: string }) => Promise<string | null>;\n\n /**\n * Delete a file from the storage provider.\n *\n * @param props.storageId - The storage provider's file identifier.\n */\n deleteFile: (props: { storageId: string }) => Promise<void>;\n}\n\n/**\n * Fields that are auto-injected into every media collection and cannot be overridden.\n */\nexport const LOCKED_MEDIA_FIELDS = [\n \"storageId\",\n \"filename\",\n \"mimeType\",\n \"size\",\n] as const;\nexport type LockedMediaField = (typeof LOCKED_MEDIA_FIELDS)[number];\n\n/**\n * Fields that are auto-injected but CAN be overridden by the user.\n */\nexport const OVERRIDABLE_MEDIA_FIELDS = [\n \"url\",\n \"alt\",\n \"width\",\n \"height\",\n] as const;\nexport type OverridableMediaField = (typeof OVERRIDABLE_MEDIA_FIELDS)[number];\n\n/**\n * Keys of all default media fields auto-injected by `defineConfig()`.\n * Used as extra autocomplete keys in `CollectionAdminConfig` so that\n * `useAsTitle`, `defaultColumns`, etc. suggest both user fields and preset fields.\n */\nexport type DefaultMediaFieldKeys =\n | LockedMediaField\n | OverridableMediaField;\n\n/**\n * A media collection definition. Users create these as plain objects.\n * Default media fields (storageId, filename, mimeType, size, url, alt, width, height)\n * are injected automatically by `defineConfig()`.\n *\n * The `fields` record contains ONLY user-defined additional fields or overrides\n * of overridable defaults (url, alt, width, height).\n */\nexport interface VexMediaCollection<\n TFields extends Record<string, VexField> = any,\n TSlug extends string = string,\n> {\n readonly slug: TSlug;\n fields?: TFields;\n tableName?: string;\n labels?: { singular?: string; plural?: string };\n admin?: CollectionAdminConfig<TFields, DefaultMediaFieldKeys>;\n}\n\n/**\n * Default media fields injected into every media collection by defineConfig().\n * Returns a fresh record each call to avoid mutation across collections.\n */\nexport function getDefaultMediaFields(): Record<string, VexField> {\n return {\n storageId: {\n type: \"text\",\n required: true,\n defaultValue: \"\",\n label: \"Storage ID\",\n admin: { hidden: true },\n },\n filename: {\n type: \"text\",\n required: true,\n defaultValue: \"\",\n label: \"Filename\",\n admin: { readOnly: true },\n },\n mimeType: {\n type: \"text\",\n required: true,\n defaultValue: \"\",\n label: \"MIME Type\",\n index: \"by_mimeType\",\n admin: { readOnly: true },\n },\n size: {\n type: \"number\",\n required: true,\n defaultValue: 0,\n label: \"File Size (bytes)\",\n admin: { readOnly: true },\n },\n url: {\n type: \"text\",\n required: true,\n defaultValue: \"\",\n label: \"URL\",\n admin: { readOnly: true },\n },\n alt: { type: \"text\", label: \"Alt Text\" },\n width: { type: \"number\", label: \"Width (px)\" },\n height: { type: \"number\", label: \"Height (px)\" },\n };\n}\n\n/**\n * The resolved media configuration on VexConfig.\n */\nexport interface MediaConfig {\n collections: VexCollection[];\n storageAdapter: FileStorageAdapter;\n}\n\n/**\n * Client-safe media configuration with non-serializable parts stripped.\n * Used when passing config across RSC serialization boundaries (e.g., to client components).\n */\nexport interface ClientMediaConfig {\n collections: VexCollection[];\n}\n\n/**\n * Input shape for the `media` field on VexConfigInput.\n */\nexport interface MediaConfigInput {\n collections: VexMediaCollection[];\n storageAdapter: FileStorageAdapter;\n}\n","/**\n * Base error class for all Vex CMS errors.\n * Provides consistent error formatting with a [vex] prefix.\n */\nexport class VexError extends Error {\n constructor(message: string) {\n super(`[vex] ${message}`);\n this.name = \"VexError\";\n }\n}\n\n/**\n * Thrown when a duplicate table slug is detected during schema generation.\n * Includes both registrations so the user can identify the conflict.\n */\nexport class VexSlugConflictError extends VexError {\n constructor(\n public readonly slug: string,\n public readonly existingSource: string,\n public readonly existingLocation: string,\n public readonly newSource: string,\n public readonly newLocation: string,\n ) {\n super(\n `Duplicate table slug \"${slug}\":\\n` +\n ` - ${existingSource}: ${existingLocation}\\n` +\n ` - ${newSource}: ${newLocation}\\n` +\n `Rename one of these to resolve the conflict.`,\n );\n this.name = \"VexSlugConflictError\";\n }\n}\n\n/**\n * Thrown when a field fails validation during schema generation.\n * For example: required field with no defaultValue, or wrong defaultValue type.\n */\nexport class VexFieldValidationError extends VexError {\n constructor(\n public readonly collectionSlug: string,\n public readonly fieldName: string,\n public readonly detail: string,\n ) {\n super(`Field \"${fieldName}\" in collection \"${collectionSlug}\": ${detail}`);\n this.name = \"VexFieldValidationError\";\n }\n}\n\n/**\n * Thrown when auth configuration is invalid.\n * For example: userCollection not found in collections.\n */\nexport class VexAuthConfigError extends VexError {\n constructor(detail: string) {\n super(`Auth configuration error: ${detail}`);\n this.name = \"VexAuthConfigError\";\n }\n}\n\n/**\n * Thrown when media configuration is invalid.\n */\nexport class VexMediaConfigError extends VexError {\n constructor(detail: string) {\n super(`Media configuration error: ${detail}`);\n this.name = \"VexMediaConfigError\";\n }\n}\n\n/**\n * Thrown when access configuration is invalid.\n * For example: orgCollection provided without userOrgField.\n */\nexport class VexAccessConfigError extends VexError {\n constructor(detail: string) {\n super(`Access configuration error: ${detail}`);\n this.name = \"VexAccessConfigError\";\n }\n}\n\n/**\n * Thrown by `hasPermission` when `throwOnDenied` is true and the user\n * does not have permission for the requested action.\n *\n * Contains structured context about the denied access attempt so callers\n * can log, surface to users, or handle programmatically.\n */\nexport class VexAccessError extends VexError {\n constructor(\n public readonly resource: string,\n public readonly action: string,\n public readonly field?: string,\n ) {\n const target = field\n ? `field \"${field}\" on resource \"${resource}\"`\n : `resource \"${resource}\"`;\n super(`Access denied: ${action} on ${target}`);\n this.name = \"VexAccessError\";\n }\n}\n\n/**\n * Thrown when a block definition is invalid.\n * For example: reserved field name used, duplicate block slug.\n */\nexport class VexBlockValidationError extends VexError {\n constructor(\n public readonly blockSlug: string,\n public readonly detail: string,\n ) {\n super(`Block \"${blockSlug}\": ${detail}`);\n this.name = \"VexBlockValidationError\";\n }\n}\n","import type { VexConfig, VexConfigInput, VexCollection } from \"../types\";\nimport type { VexMediaCollection } from \"../types/media\";\nimport { getDefaultMediaFields, LOCKED_MEDIA_FIELDS } from \"../types/media\";\nimport { VexMediaConfigError } from \"../errors\";\n\nexport const BASE_VEX_CONFIG: Omit<VexConfig, \"auth\"> = {\n basePath: \"/admin\",\n globals: [],\n collections: [],\n admin: {\n meta: {\n titleSuffix: \"| Admin\",\n favicon: \"/favicon.ico\",\n },\n user: \"users\",\n sidebar: {\n hideGlobals: false,\n },\n onboarding: {\n disabled: false,\n },\n },\n schema: {\n outputPath: \"/convex/vex.schema.ts\",\n typesOutputPath: \"/convex/vex.types.ts\",\n autoMigrate: true,\n autoRemove: false,\n },\n};\n\n/**\n * Resolve a VexMediaCollection into a VexCollection by injecting\n * default media fields. Locked fields cannot be overridden by the user.\n * Overridable fields (url, alt, width, height) can be customized.\n */\nfunction resolveMediaCollection(props: {\n mediaCollection: VexMediaCollection;\n}): VexCollection {\n const defaults = getDefaultMediaFields();\n\n // Merge user fields, skipping locked fields\n if (props.mediaCollection.fields) {\n for (const [fieldName, field] of Object.entries(props.mediaCollection.fields) as [string, any][]) {\n if ((LOCKED_MEDIA_FIELDS as readonly string[]).includes(fieldName)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `[vex] Media collection \"${props.mediaCollection.slug}\": field \"${fieldName}\" is a system field and cannot be overridden`,\n );\n }\n continue;\n }\n defaults[fieldName] = field;\n }\n }\n\n // Build admin config with useAsTitle default\n const adminConfig: Record<string, unknown> = {\n ...props.mediaCollection.admin,\n useAsTitle: props.mediaCollection.admin?.useAsTitle ?? \"filename\",\n };\n\n return {\n slug: props.mediaCollection.slug,\n fields: defaults,\n tableName: props.mediaCollection.tableName,\n labels: props.mediaCollection.labels,\n admin: adminConfig as any,\n _isMedia: true,\n };\n}\n\nexport function defineConfig(vexConfig: VexConfigInput): VexConfig {\n const { media: mediaInput, ...restInput } = vexConfig;\n const config: VexConfig = {\n ...BASE_VEX_CONFIG,\n ...restInput,\n admin: {\n ...BASE_VEX_CONFIG.admin,\n ...vexConfig.admin,\n meta: {\n ...BASE_VEX_CONFIG.admin.meta,\n ...vexConfig.admin?.meta,\n },\n sidebar: {\n ...BASE_VEX_CONFIG.admin.sidebar,\n ...vexConfig.admin?.sidebar,\n },\n onboarding: {\n ...BASE_VEX_CONFIG.admin.onboarding,\n ...vexConfig.admin?.onboarding,\n },\n livePreview: vexConfig.admin?.livePreview,\n },\n schema: {\n ...BASE_VEX_CONFIG.schema,\n ...vexConfig.schema,\n },\n access: vexConfig.access,\n };\n\n // Handle media config\n if (mediaInput) {\n if (mediaInput.collections.length === 0) {\n config.media = undefined;\n } else if (!mediaInput.storageAdapter) {\n throw new VexMediaConfigError(\n \"media.storageAdapter is required when media.collections is non-empty\",\n );\n } else {\n config.media = {\n collections: mediaInput.collections.map((mc) =>\n resolveMediaCollection({ mediaCollection: mc }),\n ),\n storageAdapter: mediaInput.storageAdapter,\n };\n }\n } else {\n config.media = undefined;\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n // Validate collection slugs\n for (const collection of config.collections) {\n if (!/^[a-z][a-z0-9_]*$/.test(collection.slug)) {\n console.warn(\n `[vex] Collection slug \"${collection.slug}\" should be lowercase alphanumeric with underscores, starting with a letter`,\n );\n }\n if (collection.slug.startsWith(\"vex_\")) {\n console.warn(\n `[vex] Collection slug \"${collection.slug}\" uses reserved prefix \"vex_\"`,\n );\n }\n if (Object.keys(collection.fields).length === 0) {\n console.warn(`[vex] Collection \"${collection.slug}\" has no fields defined`);\n }\n }\n\n // Validate global slugs\n for (const global of config.globals) {\n if (!/^[a-z][a-z0-9_]*$/.test(global.slug)) {\n console.warn(\n `[vex] Global slug \"${global.slug}\" should be lowercase alphanumeric with underscores, starting with a letter`,\n );\n }\n if (global.slug.startsWith(\"vex_\")) {\n console.warn(`[vex] Global slug \"${global.slug}\" uses reserved prefix \"vex_\"`);\n }\n if (Object.keys(global.fields).length === 0) {\n console.warn(`[vex] Global \"${global.slug}\" has no fields defined`);\n }\n }\n\n // Check for duplicate slugs\n const slugs = config.collections.concat(config.globals as any[]).map((c) => c.slug);\n const duplicates = slugs.filter((slug, i) => slugs.indexOf(slug) !== i);\n if (duplicates.length > 0) {\n console.warn(\n `[vex] Duplicate collection slugs detected: ${duplicates.join(\", \")}`,\n );\n }\n }\n\n return config;\n}\n","import type { VexField, VexCollection } from \"../types\";\nimport type { VexAuthAdapter, AuthCollectionFieldKeys } from \"../types/auth\";\nimport type { CollectionAdminConfig, IndexConfig, SearchIndexConfig, VersionsConfig, VersioningFieldKeys } from \"../types/collections\";\nimport type { VexMediaCollection, DefaultMediaFieldKeys } from \"../types/media\";\n\n/**\n * Creates a VexCollection with full LSP autocomplete on field names,\n * `admin.useAsTitle`, `admin.defaultColumns`, index fields, etc.\n *\n * When `auth` is provided, auth field keys (e.g. \"email\", \"createdAt\") are\n * also included in autocomplete for admin config and indexes.\n *\n * @example\n * ```ts\n * // Without auth — autocomplete for own fields\n * export const posts = defineCollection({\n * slug: \"posts\",\n * fields: {\n * title: { type: \"text\", required: true },\n * status: { type: \"select\", options: [...] },\n * },\n * admin: { useAsTitle: \"title\" }, // autocomplete: \"title\" | \"status\"\n * });\n *\n * // With auth — autocomplete for own fields + auth fields\n * export const users = defineCollection({\n * slug: \"users\",\n * auth,\n * fields: {\n * name: { type: \"text\", required: true },\n * role: { type: \"select\", options: [...] },\n * },\n * admin: {\n * useAsTitle: \"name\", // autocomplete: \"name\" | \"role\" | \"email\" | \"createdAt\" | ...\n * defaultColumns: [\"name\", \"email\"], // same autocomplete\n * },\n * });\n * ```\n */\nexport function defineCollection<\n TFields extends Record<string, VexField>,\n TAuth extends VexAuthAdapter<any> | undefined = undefined,\n TSlug extends string = string,\n>(props: {\n readonly slug: TSlug;\n fields: TFields;\n auth?: TAuth;\n tableName?: string;\n labels?: { singular?: string; plural?: string };\n admin?: CollectionAdminConfig<\n TFields,\n VersioningFieldKeys | (TAuth extends VexAuthAdapter<any> ? AuthCollectionFieldKeys<TAuth, TSlug> : never)\n >;\n indexes?: IndexConfig<\n TFields,\n VersioningFieldKeys | (TAuth extends VexAuthAdapter<any> ? AuthCollectionFieldKeys<TAuth, TSlug> : never)\n >[];\n searchIndexes?: SearchIndexConfig<\n TFields,\n VersioningFieldKeys | (TAuth extends VexAuthAdapter<any> ? AuthCollectionFieldKeys<TAuth, TSlug> : never)\n >[];\n versions?: VersionsConfig;\n interfaceName?: string;\n}): VexCollection<\n TFields,\n VersioningFieldKeys | (TAuth extends VexAuthAdapter<any> ? AuthCollectionFieldKeys<TAuth, TSlug> : never),\n TSlug\n> {\n const { auth: _auth, ...rest } = props;\n return rest as VexCollection<\n TFields,\n VersioningFieldKeys | (TAuth extends VexAuthAdapter<any> ? AuthCollectionFieldKeys<TAuth, TSlug> : never),\n TSlug\n >;\n}\n\n/**\n * Creates a VexMediaCollection with full LSP autocomplete on field names\n * and `admin.useAsTitle`, `admin.defaultColumns`, etc.\n *\n * Default media fields (storageId, filename, mimeType, size, url, alt, width, height)\n * are injected automatically by `defineConfig()` — only define additional or\n * overridden fields here.\n *\n * @example\n * ```ts\n * export const media = defineMediaCollection({\n * slug: \"media\",\n * fields: {\n * caption: { type: \"text\" },\n * },\n * admin: { useAsTitle: \"filename\" }, // autocomplete: \"caption\" | default media field keys\n * });\n * ```\n */\nexport function defineMediaCollection<\n TFields extends Record<string, VexField> = Record<never, VexField>,\n TSlug extends string = string,\n>(props: {\n readonly slug: TSlug;\n fields?: TFields;\n tableName?: string;\n labels?: { singular?: string; plural?: string };\n admin?: CollectionAdminConfig<TFields, DefaultMediaFieldKeys>;\n}): VexMediaCollection<TFields, TSlug> {\n return props as VexMediaCollection<TFields, TSlug>;\n}\n","import type {\n VexAccessConfig,\n VexAccessInputBase,\n VexAccessInputWithOrg,\n} from \"./types\";\nimport type { VexCollection } from \"../types\";\nimport { VexAccessConfigError } from \"../errors\";\n\n/**\n * Define access permissions for the Vex CMS admin panel.\n *\n * This is a builder function (like `defineCollection`) that provides full\n * TypeScript inference for roles, resource slugs, field keys, user type,\n * and organization type.\n *\n * The function validates configuration in non-production and returns a\n * `VexAccessConfig` for passing to `defineConfig({ access: ... })`.\n *\n * @returns A `VexAccessConfig` for passing to `defineConfig({ access: ... })`.\n */\n\n// Overload: with organization (must come first — more specific)\nexport function defineAccess<\n const TRoles extends readonly string[],\n const TResources extends readonly any[],\n const TUserCollection extends VexCollection<any, any, any>,\n TUser = undefined,\n const TOrgCollection extends VexCollection<any, any, any> = never,\n TOrg = undefined,\n>(\n props: VexAccessInputWithOrg<TRoles, TResources, TUserCollection, TUser, TOrgCollection, TOrg>,\n): VexAccessConfig;\n\n// Overload: without organization\nexport function defineAccess<\n const TRoles extends readonly string[],\n const TResources extends readonly any[],\n const TUserCollection extends VexCollection<any, any, any>,\n TUser = undefined,\n>(\n props: VexAccessInputBase<TRoles, TResources, TUserCollection, TUser> & {\n orgCollection?: never;\n orgType?: never;\n userOrgField?: never;\n },\n): VexAccessConfig;\n\n// Implementation\nexport function defineAccess(props: {\n roles: readonly string[];\n adminRoles?: readonly string[];\n resources?: readonly any[];\n userCollection: { slug: string; fields?: Record<string, any> };\n userType?: unknown;\n orgCollection?: { slug: string };\n orgType?: unknown;\n userOrgField?: string;\n permissions: Record<string, any>;\n}): VexAccessConfig {\n // Validate org config coupling\n if (props.orgCollection && !props.userOrgField) {\n throw new VexAccessConfigError(\"orgCollection requires userOrgField\");\n }\n if (props.userOrgField && !props.orgCollection) {\n throw new VexAccessConfigError(\"userOrgField requires orgCollection\");\n }\n\n // Default adminRoles to all roles if not specified\n const adminRoles = props.adminRoles ?? props.roles;\n\n if (process.env.NODE_ENV !== \"production\") {\n // Validate userCollection has a slug\n if (!props.userCollection?.slug) {\n console.warn(\"[vex] defineAccess: userCollection must have a slug\");\n }\n\n // Validate orgCollection has a slug if provided\n if (props.orgCollection && !props.orgCollection.slug) {\n console.warn(\"[vex] defineAccess: orgCollection must have a slug\");\n }\n\n // Validate that permission resource slugs match resources (if resources provided)\n if (props.resources) {\n const resourceSlugs = new Set(\n props.resources.map((r: any) => r.slug),\n );\n for (const role of Object.keys(props.permissions)) {\n const rolePerms = props.permissions[role];\n if (!rolePerms) continue;\n for (const slug of Object.keys(rolePerms)) {\n if (!resourceSlugs.has(slug)) {\n console.warn(\n `[vex] defineAccess: permission resource \"${slug}\" not found in resources`,\n );\n }\n }\n }\n }\n\n // Validate that permission role keys match roles array\n const rolesSet = new Set(props.roles);\n for (const role of Object.keys(props.permissions)) {\n if (!rolesSet.has(role)) {\n console.warn(\n `[vex] defineAccess: permission role \"${role}\" not in roles array`,\n );\n }\n }\n\n // Validate adminRoles are a subset of roles\n if (props.adminRoles) {\n const rolesSetForAdmin = new Set(props.roles);\n for (const adminRole of props.adminRoles) {\n if (!rolesSetForAdmin.has(adminRole)) {\n console.warn(\n `[vex] defineAccess: adminRole \"${adminRole}\" not found in roles array`,\n );\n }\n }\n }\n\n // Validate userOrgField exists in user collection fields\n if (props.userOrgField && props.userCollection?.fields) {\n if (!(props.userOrgField in props.userCollection.fields)) {\n console.warn(\n `[vex] defineAccess: userOrgField \"${props.userOrgField}\" not found in user collection fields`,\n );\n }\n }\n }\n\n return {\n roles: props.roles,\n adminRoles,\n userCollection: props.userCollection.slug,\n orgCollection: props.orgCollection?.slug,\n userOrgField: props.userOrgField,\n permissions: props.permissions,\n };\n}\n","import type { AccessAction, VexAccessConfig, PermissionCheck, FieldPermissionResult } from \"./types\";\nimport { VexAccessError } from \"../errors\";\n\n/**\n * The result of resolving field permissions for a resource action.\n * Maps each field key to whether the action is allowed on that field.\n */\nexport type ResolvedFieldPermissions = Record<string, boolean>;\n\n/**\n * Resolve a permission check value (boolean, mode object, or function)\n * into a result for the requested fields.\n *\n * When `fields` is provided, returns a `Record<field, boolean>` for those fields.\n * When `fields` is omitted, returns a single `boolean` for overall action access.\n *\n * @param props.check - The permission check value to resolve\n * @param props.fields - Specific fields to check. When omitted, returns overall boolean.\n * @param props.data - The document data (for dynamic checks)\n * @param props.user - The user object (for dynamic checks)\n * @param props.organization - Optional organization object (for dynamic checks)\n * @returns Field permission map when fields provided, boolean when omitted\n */\nexport function resolvePermissionCheck(props: {\n check: PermissionCheck<string, any, any, any> | undefined;\n fields?: string[];\n data: Record<string, any>;\n user: Record<string, any>;\n organization?: Record<string, any>;\n}): ResolvedFieldPermissions | boolean {\n // Permissive default for missing actions\n if (props.check === undefined) {\n if (props.fields === undefined) return true;\n return Object.fromEntries(props.fields.map((k) => [k, true]));\n }\n\n // Resolve function checks\n let resolved: FieldPermissionResult<string>;\n if (typeof props.check === \"function\") {\n const callbackProps: any = props.organization !== undefined\n ? { data: props.data, user: props.user, organization: props.organization }\n : { data: props.data, user: props.user };\n resolved = props.check(callbackProps);\n } else {\n resolved = props.check;\n }\n\n // Handle undefined function return as deny-all\n if (resolved === undefined) {\n if (props.fields === undefined) return false;\n return Object.fromEntries(props.fields.map((k) => [k, false]));\n }\n\n // Boolean result\n if (typeof resolved === \"boolean\") {\n if (props.fields === undefined) return resolved;\n return Object.fromEntries(props.fields.map((k) => [k, resolved as boolean]));\n }\n\n // Mode object result — need fields to check against\n if (props.fields === undefined) {\n // No specific fields requested — for mode objects, we can't give a single boolean\n // without knowing what fields exist. Default to true (allow mode with fields means\n // \"some fields allowed\", deny mode with fields means \"some fields denied\").\n // Callers wanting field-level granularity must pass fields.\n if (resolved.mode === \"allow\") return resolved.fields.length > 0;\n if (resolved.mode === \"deny\") return resolved.fields.length === 0;\n return true;\n }\n\n if (resolved.mode === \"allow\") {\n const allowSet = new Set(resolved.fields);\n return Object.fromEntries(\n props.fields.map((k) => [k, allowSet.has(k)]),\n );\n }\n\n // mode === \"deny\"\n const denySet = new Set(resolved.fields);\n return Object.fromEntries(\n props.fields.map((k) => [k, !denySet.has(k)]),\n );\n}\n\n/**\n * Merge field permission maps from multiple roles using OR logic.\n * If any role grants access to a field, that field is allowed.\n * Allow always wins over deny in cross-role merges.\n *\n * When all entries are booleans (no fields mode), merges with OR logic on booleans.\n *\n * @param props.results - Array of resolved permission results (one per role)\n * @param props.fields - The specific fields being checked (when field-level)\n * @returns Merged result: Record<string, boolean> when fields provided, boolean otherwise\n */\nexport function mergeRolePermissions(props: {\n results: (ResolvedFieldPermissions | boolean)[];\n fields?: string[];\n}): ResolvedFieldPermissions | boolean {\n if (props.results.length === 0) {\n if (props.fields === undefined) return true;\n return Object.fromEntries(props.fields.map((k) => [k, true]));\n }\n\n // No fields — merge booleans with OR\n if (props.fields === undefined) {\n return props.results.some((r) => r === true);\n }\n\n // With fields — merge field maps with OR\n return Object.fromEntries(\n props.fields.map((k) => [\n k,\n props.results.some((r) =>\n typeof r === \"boolean\" ? r : (r[k] === true),\n ),\n ]),\n );\n}\n\n/**\n * Check permissions for a user on a resource action.\n *\n * Without `fields` param → returns `boolean` (overall action access)\n * With `fields` param → returns `Record<string, boolean>` for those specific fields\n *\n * @param props.access - The VexAccessConfig from defineAccess\n * @param props.user - The user object\n * @param props.userRoles - The user's role(s) as a string array\n * @param props.resource - The resource slug (collection or global slug)\n * @param props.action - The CRUD action to check\n * @param props.data - Document data for dynamic permission checks. Defaults to `{}`.\n * @param props.organization - Optional organization object for org-aware permission checks.\n * @param props.fields - Specific fields to check. When provided, returns Record<string, boolean>.\n * @param props.throwOnDenied - When true, throws VexAccessError instead of returning false. Default: false.\n * @returns `boolean` when fields is omitted, `Record<string, boolean>` when fields is provided\n * @throws {VexAccessError} When `throwOnDenied` is true and access is denied\n */\nexport function hasPermission(props: {\n access: VexAccessConfig | undefined;\n user: Record<string, any>;\n userRoles: string[];\n resource: string;\n action: AccessAction;\n data?: Record<string, any>;\n organization?: Record<string, any>;\n fields?: string[];\n throwOnDenied?: boolean;\n}): ResolvedFieldPermissions | boolean {\n // Permissive default when no access config\n if (props.access === undefined) {\n if (props.fields === undefined) return true;\n return Object.fromEntries(props.fields.map((k) => [k, true]));\n }\n\n // Deny all when no roles\n if (props.userRoles.length === 0) {\n if (props.throwOnDenied) {\n throw new VexAccessError(props.resource, props.action);\n }\n if (props.fields === undefined) return false;\n return Object.fromEntries(props.fields.map((k) => [k, false]));\n }\n\n // Filter to only known roles\n const knownRolesSet = new Set(props.access.roles);\n const knownRoles = props.userRoles.filter((r) => knownRolesSet.has(r));\n\n // All roles unknown → deny all\n if (knownRoles.length === 0) {\n if (props.throwOnDenied) {\n throw new VexAccessError(props.resource, props.action);\n }\n if (props.fields === undefined) return false;\n return Object.fromEntries(props.fields.map((k) => [k, false]));\n }\n\n // Resolve permissions for each known role\n const results: (ResolvedFieldPermissions | boolean)[] = [];\n const data = props.data ?? {};\n\n for (const role of knownRoles) {\n const rolePerms = props.access.permissions[role];\n if (rolePerms === undefined) {\n // Role has no permissions object → skip (contributes nothing)\n continue;\n }\n\n const resourcePerms = rolePerms[props.resource];\n if (resourcePerms === undefined) {\n // Role has no entry for this resource → permissive default\n results.push(true);\n continue;\n }\n\n // Boolean shorthand at resource level: true = all actions allowed, false = all denied\n if (typeof resourcePerms === \"boolean\") {\n results.push(resourcePerms);\n continue;\n }\n\n const actionCheck = resourcePerms[props.action];\n results.push(\n resolvePermissionCheck({\n check: actionCheck,\n fields: props.fields,\n data,\n user: props.user,\n organization: props.organization,\n }),\n );\n }\n\n // Merge all role results with OR logic\n const merged = mergeRolePermissions({\n results,\n fields: props.fields,\n });\n\n // Handle throwOnDenied\n if (props.throwOnDenied) {\n if (typeof merged === \"boolean\") {\n if (!merged) {\n throw new VexAccessError(props.resource, props.action);\n }\n } else {\n const deniedField = Object.entries(merged).find(([, v]) => v === false);\n if (deniedField) {\n throw new VexAccessError(props.resource, props.action, deniedField[0]);\n }\n }\n }\n\n return merged;\n}\n","import type { VexConfig, ClientVexConfig } from \"../types\";\n\n/**\n * Strip non-serializable values from VexConfig for safe passage across\n * RSC / JSON serialization boundaries (e.g., server layout → client component).\n *\n * Currently strips:\n * - `media.storageAdapter` (contains async functions — only needed at CLI / schema-gen time)\n * - `admin.livePreview.url` function values on collections (replaced with `null`)\n *\n * This function is the single place to extend when new non-serializable\n * properties are added to VexConfig in the future.\n */\nexport function sanitizeConfigForClient(config: VexConfig): ClientVexConfig {\n const { media, ...rest } = config;\n\n return {\n ...rest,\n collections: rest.collections.map((collection) => {\n if (!collection.admin?.livePreview) return collection;\n if (typeof collection.admin.livePreview.url === \"string\") return collection;\n\n // Strip function URL — replaced with null for RSC serialization.\n // The admin panel resolves function URLs at runtime via livePreviewConfigs prop.\n return {\n ...collection,\n admin: {\n ...collection.admin,\n livePreview: {\n ...collection.admin.livePreview,\n url: null as any,\n },\n },\n };\n }),\n media: media\n ? { collections: media.collections }\n : undefined,\n };\n}\n\n/**\n * Extracts a map of collection slug → original livePreview URL function for collections\n * that have function-based preview URLs. Pass this to admin components so they\n * can resolve preview URLs at runtime on the client.\n *\n * @returns Map of collection slug → { url } (only entries with function URLs)\n */\nexport function extractLivePreviewConfigs(config: VexConfig): Record<string, { url: (doc: { _id: string; [key: string]: any }) => string }> {\n const result: Record<string, { url: (doc: { _id: string; [key: string]: any }) => string }> = {};\n\n for (const collection of config.collections) {\n if (collection.admin?.livePreview && typeof collection.admin.livePreview.url === \"function\") {\n result[collection.slug] = { url: collection.admin.livePreview.url };\n }\n }\n\n return result;\n}\n","interface HasSlug {\n readonly slug: string;\n}\n\ninterface ConfigWithMedia {\n media?: {\n collections: HasSlug[];\n };\n}\n\n/**\n * Check whether a collection is a media collection.\n *\n * Compares the collection's slug against the slugs in `config.media.collections`.\n * Works with both `VexConfig` and `ClientVexConfig` (both have the `media?.collections` shape).\n *\n * @param props.collection - The collection to check\n * @param props.config - The Vex config (or client config) containing media configuration\n * @returns true if the collection's slug matches a media collection slug\n */\nexport function isMediaCollection(props: {\n collection: HasSlug;\n config: ConfigWithMedia;\n}): boolean {\n if (!props.config.media?.collections) return false;\n return props.config.media.collections.some(\n (mc) => mc.slug === props.collection.slug,\n );\n}\n","import type { VexField } from \"../types/fields\";\n\ninterface HasSlugAndFields {\n readonly slug: string;\n fields: Record<string, VexField>;\n}\n\ninterface ConfigShape {\n collections: HasSlugAndFields[];\n globals: HasSlugAndFields[];\n media?: {\n collections: HasSlugAndFields[];\n };\n}\n\nexport type CollectionKind = \"collection\" | \"media\" | \"global\";\n\nexport interface ResolvedCollectionMatch {\n slug: string;\n fields: Record<string, VexField>;\n kind: CollectionKind;\n}\n\n/**\n * Get all collections, media collections, and globals as a flat array.\n *\n * Each entry includes the `kind` discriminator so callers can switch on it.\n *\n * @param props.config - The resolved Vex config\n * @param props.excludeGlobals - Skip globals (default: false)\n */\nexport function getAllCollections(props: {\n config: ConfigShape;\n excludeGlobals?: boolean;\n}): ResolvedCollectionMatch[] {\n const { config, excludeGlobals = false } = props;\n const result: ResolvedCollectionMatch[] = [];\n\n for (const c of config.collections) {\n result.push({ slug: c.slug, fields: c.fields, kind: \"collection\" });\n }\n\n if (config.media?.collections) {\n for (const c of config.media.collections) {\n result.push({ slug: c.slug, fields: c.fields, kind: \"media\" });\n }\n }\n\n if (!excludeGlobals) {\n for (const g of config.globals) {\n result.push({ slug: g.slug, fields: g.fields, kind: \"global\" });\n }\n }\n\n return result;\n}\n\n/**\n * Find a collection, media collection, or global by slug across the entire config.\n *\n * Searches in order: collections → media collections → globals.\n * Returns the match with its fields and what kind it is, or null if not found.\n *\n * @param props.slug - The slug to search for\n * @param props.config - The resolved Vex config\n * @param props.excludeGlobals - Skip globals when searching (default: false)\n */\nexport function findCollectionBySlug(props: {\n slug: string;\n config: ConfigShape;\n excludeGlobals?: boolean;\n}): ResolvedCollectionMatch | null {\n return getAllCollections(props).find((c) => c.slug === props.slug) ?? null;\n}\n","import type { CheckboxFieldDef } from \"../../types\";\n\nexport function checkbox(options?: Omit<CheckboxFieldDef, \"type\">): CheckboxFieldDef {\n return {\n type: \"checkbox\",\n ...(options?.required && options?.defaultValue === undefined\n ? { defaultValue: false }\n : {}),\n ...options,\n };\n}\n","const MINOR_WORDS = new Set([\n \"a\",\n \"an\",\n \"and\",\n \"as\",\n // \"at\",\n \"but\",\n \"by\",\n \"for\",\n \"if\",\n \"in\",\n \"nor\",\n \"of\",\n \"on\",\n \"or\",\n \"so\",\n \"the\",\n \"to\",\n \"up\",\n \"yet\",\n]);\n\nexport function toTitleCase(input: string): string {\n const words = input\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .replace(/[_-]+/g, \" \")\n .trim()\n .split(/\\s+/);\n\n return words\n .map((word, i) => {\n const lower = word.toLowerCase();\n if (i > 0 && MINOR_WORDS.has(lower)) return lower;\n return lower.charAt(0).toUpperCase() + lower.slice(1);\n })\n .join(\" \");\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { CheckboxFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a checkbox (boolean) field.\n *\n * @param props.fieldKey - The field name (used as accessorKey)\n * @param props.field - The checkbox field definition\n * @returns A ColumnDef for the checkbox field\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: render \"Yes\" / \"No\" (React rendering with icons is handled by UI layer)\n */\nexport function checkboxColumnDef(props: {\n fieldKey: string;\n field: CheckboxFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n };\n}\n","import { VexFieldValidationError } from \"../errors\";\n\n/**\n * Validates a field's configuration and determines if it should be optional.\n * Called by each per-field valueType function before generating the valueType string.\n *\n * Checks:\n * 1. If required=true and defaultValue is undefined → throw VexFieldValidationError\n * 2. If defaultValue is provided, verify it matches the expected type → throw VexFieldValidationError\n *\n * @param props.field - The field to validate (only needs required and defaultValue)\n * @param props.collectionSlug - The collection slug (for error messages)\n * @param props.fieldName - The field name (for error messages)\n * @param props.expectedType - The expected typeof for defaultValue (e.g., \"string\", \"number\", \"boolean\")\n * @param props.valueType - The Convex value type string (e.g., \"v.string()\")\n * @param props.skipDefaultValidation - Skip defaultValue presence and type checks.\n */\nexport function processFieldValueTypeOptions(props: {\n field: { required?: boolean; defaultValue?: unknown };\n collectionSlug: string;\n fieldName: string;\n expectedType: string;\n valueType: string;\n skipDefaultValidation?: boolean;\n}): string {\n if (!props.field.required) {\n return `v.optional(${props.valueType})`;\n }\n\n if (!props.skipDefaultValidation) {\n if (props.field.defaultValue === undefined) {\n throw new VexFieldValidationError(\n props.collectionSlug,\n props.fieldName,\n \"No defaultValue Provided\",\n );\n }\n if (!(typeof props.field.defaultValue === props.expectedType)) {\n throw new VexFieldValidationError(\n props.collectionSlug,\n props.fieldName,\n `Invalid defaultValue Provided. Expected: ${props.expectedType}, Received: ${typeof props.field.defaultValue}`,\n );\n }\n }\n\n return props.valueType;\n}\n","export const TEXT_VALUETYPE = \"v.string()\" as const;\nexport const NUMBER_VALUETYPE = \"v.number()\" as const;\nexport const CHECKBOX_VALUETYPE = \"v.boolean()\" as const;\nexport const DATE_VALUETYPE = \"v.number()\" as const;\nexport const IMAGEURL_VALUETYPE = \"v.string()\" as const;\nexport const JSON_VALUETYPE = \"v.any()\" as const;\nexport const RICHTEXT_VALUETYPE = \"v.any()\" as const;\n\nexport type { Alignment } from \"../types/fields\";\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { CheckboxFieldDef } from \"../../types\";\nimport { CHECKBOX_VALUETYPE } from \"../constants\";\n\n/**\n * Converts checkbox field definition to a Convex value type string.\n *\n * @returns `\"v.boolean()\"` or `\"v.optional(v.boolean())\"`\n */\nexport function checkboxToValueTypeString(props: {\n field: CheckboxFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"boolean\",\n valueType: CHECKBOX_VALUETYPE,\n });\n}\n","import type { NumberFieldDef } from \"../../types\";\n\nexport function number(options?: Omit<NumberFieldDef, \"type\">): NumberFieldDef {\n return {\n type: \"number\",\n ...(options?.required && options?.defaultValue === undefined\n ? { defaultValue: 0 }\n : {}),\n ...options,\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { NumberFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a number field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: render the number directly\n */\nexport function numberColumnDef(props: {\n fieldKey: string;\n field: NumberFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"right\" },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { NumberFieldDef } from \"../../types\";\nimport { NUMBER_VALUETYPE } from \"../constants\";\n\n/**\n * Converts number field definition to a Convex value type string.\n *\n * @returns `\"v.number()\"` or `\"v.optional(v.number())\"`\n */\nexport function numberToValueTypeString(props: {\n field: NumberFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"number\",\n valueType: NUMBER_VALUETYPE,\n });\n}\n","import type { SelectFieldDef, SelectFieldSingle, SelectFieldMany } from \"../../types\";\n\nexport function select<T extends string = string>(\n options: Omit<SelectFieldMany<T>, \"type\">,\n): SelectFieldDef<T>;\nexport function select<T extends string = string>(\n options: Omit<SelectFieldSingle<T>, \"type\">,\n): SelectFieldDef<T>;\nexport function select<T extends string = string>(\n options: Omit<SelectFieldSingle<T>, \"type\"> | Omit<SelectFieldMany<T>, \"type\">,\n): SelectFieldDef<T> {\n return { type: \"select\", ...options } as SelectFieldDef<T>;\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { SelectFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Default hex colors rotated through when options don't specify a `badgeColor`.\n */\nconst DEFAULT_BADGE_COLORS = [\n \"#3b82f6\", // blue\n \"#22c55e\", // green\n \"#a855f7\", // purple\n \"#f59e0b\", // amber\n \"#f43f5e\", // rose\n \"#06b6d4\", // cyan\n \"#6366f1\", // indigo\n \"#14b8a6\", // teal\n \"#f97316\", // orange\n \"#d946ef\", // fuchsia\n] as const;\n\n/**\n * Builds a ColumnDef for a select field.\n *\n * @param props.fieldKey - The field name (used as accessorKey)\n * @param props.field - The select field definition (includes options for label lookup)\n * @returns A ColumnDef for the select field\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: renders option values as colored badges in a scrollable flex grid\n */\nexport function selectColumnDef(props: {\n fieldKey: string;\n field: SelectFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n const optionMap = new Map(\n props.field.options.map((opt, i) => [\n opt.value,\n {\n label: opt.label,\n color: opt.badgeColor ?? DEFAULT_BADGE_COLORS[i % DEFAULT_BADGE_COLORS.length],\n },\n ]),\n );\n\n return {\n accessorKey: props.fieldKey,\n header:\n (props.field.hasMany\n ? props.field.labels?.singular\n : props.field.label) ?? toTitleCase(props.fieldKey),\n meta: {\n align: props.field.admin?.cellAlignment ?? \"left\",\n noTruncate: true,\n },\n cell: (info) => {\n const raw = info.getValue();\n const values = Array.isArray(raw)\n ? (raw as string[])\n : raw != null\n ? [String(raw)]\n : [];\n\n if (values.length === 0) return null;\n\n return (\n <div className=\"flex flex-wrap gap-1 max-w-[240px] max-h-[60px] overflow-auto\">\n {values.map((v) => {\n const opt = optionMap.get(v);\n return (\n <span\n key={v}\n className=\"inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium text-white shrink-0\"\n style={{ backgroundColor: opt?.color }}\n >\n {opt?.label ?? v}\n </span>\n );\n })}\n </div>\n );\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { SelectFieldDef } from \"../../types\";\n\n/**\n * Converts select field definition to a Convex value type string.\n *\n * @returns One of (each may be wrapped in v.optional()):\n * - Single select: `'v.union(v.literal(\"draft\"),v.literal(\"published\"))'`\n * - Multi select (hasMany): `'v.array(v.union(v.literal(\"draft\"),v.literal(\"published\")))'`\n */\nexport function selectToValueTypeString(props: {\n field: SelectFieldDef<string>;\n collectionSlug: string;\n fieldName: string;\n}): string {\n const literals = props.field.options.map((o) => `v.literal(\"${o.value}\")`).join(\",\");\n\n if (props.field.hasMany) {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: props.field.options.length === 1\n ? `v.array(${literals})`\n : `v.array(v.union(${literals}))`,\n skipDefaultValidation: true,\n });\n }\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: `v.union(${literals})`,\n });\n}\n","import type { TextFieldDef } from \"../../types\";\n\nexport function text(options?: Omit<TextFieldDef, \"type\">): TextFieldDef {\n return {\n type: \"text\",\n ...(options?.required && options?.defaultValue === undefined\n ? { defaultValue: \"\" }\n : {}),\n ...options,\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { TextFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a text field.\n *\n * @param props.fieldKey - The field name (used as accessorKey)\n * @param props.field - The text field definition\n * @returns A ColumnDef for the text field\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? props.fieldKey (capitalize first letter of fieldKey as fallback)\n * - cell: render the value as a string, truncated to 80 characters with ellipsis if longer\n */\nexport function textColumnDef(props: {\n fieldKey: string;\n field: TextFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { TextFieldDef } from \"../../types\";\nimport { TEXT_VALUETYPE } from \"../constants\";\n\n/**\n * Converts text field definition to a Convex value type string.\n *\n * @returns `\"v.string()\"` or `\"v.optional(v.string())\"`\n *\n * minLength/maxLength are runtime validation concerns, not schema constraints.\n * The index property has no effect on the value type (handled by collectIndexes).\n */\nexport function textToValueTypeString(props: {\n field: TextFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: TEXT_VALUETYPE,\n });\n}\n","import type { DateFieldDef } from \"../../types\";\n\nexport function date(options?: Omit<DateFieldDef, \"type\">): DateFieldDef {\n return {\n type: \"date\",\n ...(options?.required && options?.defaultValue === undefined\n ? { defaultValue: 0 }\n : {}),\n ...options,\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { DateFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a date field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: formats epoch ms as a human-readable date string\n */\nexport function dateColumnDef(props: {\n fieldKey: string;\n field: DateFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: {\n align: props.field.admin?.cellAlignment ?? \"left\",\n },\n cell: (info) => {\n const value = info.getValue();\n if (value == null) return \"\";\n return new Date(value as number).toLocaleDateString();\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { DateFieldDef } from \"../../types\";\nimport { DATE_VALUETYPE } from \"../constants\";\n\n/**\n * Converts date field definition to a Convex value type string.\n *\n * @returns `\"v.number()\"` or `\"v.optional(v.number())\"`\n *\n * Dates are stored as epoch milliseconds (number).\n */\nexport function dateToValueTypeString(props: {\n field: DateFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"number\",\n valueType: DATE_VALUETYPE,\n });\n}\n","import type { ImageUrlFieldDef } from \"../../types\";\n\nexport function imageUrl(options?: Omit<ImageUrlFieldDef, \"type\">): ImageUrlFieldDef {\n return {\n type: \"imageUrl\",\n ...(options?.required && options?.defaultValue === undefined\n ? { defaultValue: \"\" }\n : {}),\n ...options,\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { ImageUrlFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for an imageUrl field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: renders an <img> thumbnail with fallback on error\n */\nexport function imageUrlColumnDef(props: {\n fieldKey: string;\n field: ImageUrlFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"center\" },\n cell: (info) => {\n const value = info.getValue();\n if (!value || typeof value !== \"string\") return \"\";\n const size = props.field.width ?? 28;\n const height = props.field.height ?? size;\n return (\n <img\n src={value}\n alt=\"\"\n width={size}\n height={height}\n className=\"rounded-full object-cover bg-muted\"\n style={{ width: size, height }}\n loading=\"lazy\"\n referrerPolicy=\"no-referrer\"\n onError={(e) => {\n (e.currentTarget as any).style.display = \"none\";\n }}\n />\n );\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { ImageUrlFieldDef } from \"../../types\";\nimport { IMAGEURL_VALUETYPE } from \"../constants\";\n\n/**\n * Converts imageUrl field definition to a Convex value type string.\n *\n * @returns `\"v.string()\"` or `\"v.optional(v.string())\"`\n *\n * Image URLs are stored as strings, same schema as text.\n */\nexport function imageUrlToValueTypeString(props: {\n field: ImageUrlFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: IMAGEURL_VALUETYPE,\n });\n}\n","import type { RelationshipFieldDef, RelationshipFieldSingle, RelationshipFieldMany } from \"../../types\";\n\nexport function relationship(\n options: Omit<RelationshipFieldMany, \"type\">,\n): RelationshipFieldDef;\nexport function relationship(\n options: Omit<RelationshipFieldSingle, \"type\">,\n): RelationshipFieldDef;\nexport function relationship(\n options: Omit<RelationshipFieldSingle, \"type\"> | Omit<RelationshipFieldMany, \"type\">,\n): RelationshipFieldDef {\n return { type: \"relationship\", ...options } as RelationshipFieldDef;\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { RelationshipFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a relationship field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - meta: includes relationship info (type, to) for DataTable to fetch related docs\n * - cell: shows raw ID (DataTable component resolves to useAsTitle at render time)\n */\nexport function relationshipColumnDef(props: {\n fieldKey: string;\n field: RelationshipFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: (props.field.hasMany ? props.field.labels?.singular : props.field.label) ?? toTitleCase(props.fieldKey),\n meta: { type: \"relationship\", to: props.field.to, align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (value == null) return \"\";\n if (Array.isArray(value)) return `${value.length} item${value.length === 1 ? \"\" : \"s\"}`;\n return String(value);\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { RelationshipFieldDef } from \"../../types\";\n\n/**\n * Converts relationship field definition to a Convex value type string.\n *\n * @returns\n * - hasMany + required: `v.array(v.id(\"tableName\"))`\n * - hasMany + !required: `v.optional(v.array(v.id(\"tableName\")))`\n * - !hasMany + required: `v.id(\"tableName\")`\n * - !hasMany + !required: `v.optional(v.id(\"tableName\"))`\n */\nexport function relationshipToValueTypeString(props: {\n field: RelationshipFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n const idType = `v.id(\"${props.field.to}\")`;\n const baseValueType = props.field.hasMany ? `v.array(${idType})` : idType;\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: baseValueType,\n skipDefaultValidation: true,\n });\n}\n","import type { JsonFieldDef } from \"../../types\";\n\nexport function json(options?: Omit<JsonFieldDef, \"type\">): JsonFieldDef {\n return {\n type: \"json\",\n ...options,\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { JsonFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a json field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: shows truncated JSON preview\n */\nexport function jsonColumnDef(props: {\n fieldKey: string;\n field: JsonFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (value == null) return \"\";\n const str = JSON.stringify(value);\n return str.length > 50 ? str.slice(0, 50) + \"...\" : str;\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { JsonFieldDef } from \"../../types\";\nimport { JSON_VALUETYPE } from \"../constants\";\n\n/**\n * Converts json field definition to a Convex value type string.\n *\n * @returns\n * - required: `\"v.any()\"`\n * - !required: `\"v.optional(v.any())\"`\n */\nexport function jsonToValueTypeString(props: {\n field: JsonFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: JSON_VALUETYPE,\n skipDefaultValidation: true,\n });\n}\n","import type { RichTextFieldDef } from \"../../types\";\n\n/**\n * Creates a rich text field definition.\n * Stores Plate/Slate JSON document as `v.any()` in Convex.\n *\n * @param options.label - Display label in admin form\n * @param options.required - Whether this field is required\n * @param options.editor - Per-field editor adapter override\n * @returns A RichTextFieldDef\n *\n * @example\n * ```ts\n * content: richtext({ label: \"Content\", required: true })\n * ```\n */\nexport function richtext(options?: Omit<RichTextFieldDef, \"type\">): RichTextFieldDef {\n return {\n type: \"richtext\",\n ...options,\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { RichTextFieldDef } from \"../../types\";\nimport { RICHTEXT_VALUETYPE } from \"../constants\";\n\n/**\n * Converts richtext field definition to a Convex value type string.\n *\n * @param props.field - The richtext field definition\n * @param props.collectionSlug - The collection this field belongs to\n * @param props.fieldName - The field key name\n * @returns\n * - required: `\"v.any()\"`\n * - !required: `\"v.optional(v.any())\"`\n */\nexport function richtextToValueTypeString(props: {\n field: RichTextFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: RICHTEXT_VALUETYPE,\n skipDefaultValidation: true,\n });\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { RichTextFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a richtext field.\n *\n * @param props.fieldKey - The field key name\n * @param props.field - The richtext field definition\n * @returns ColumnDef that shows \"Rich text\" or empty string in the data table\n */\nexport function richtextColumnDef(props: {\n fieldKey: string;\n field: RichTextFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (value == null) return \"\";\n if (Array.isArray(value) && value.length === 0) return \"\";\n return \"Rich text\";\n },\n };\n}\n","import type { UploadFieldDef, UploadFieldSingle, UploadFieldMany } from \"../../types\";\n\nexport function upload(\n options: Omit<UploadFieldMany, \"type\">,\n): UploadFieldDef;\nexport function upload(\n options: Omit<UploadFieldSingle, \"type\">,\n): UploadFieldDef;\nexport function upload(\n options: Omit<UploadFieldSingle, \"type\"> | Omit<UploadFieldMany, \"type\">,\n): UploadFieldDef {\n return { type: \"upload\", ...options } as UploadFieldDef;\n}\n","import type { UploadFieldDef } from \"../../types\";\nimport { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\n\n/**\n * Converts upload field definition to a Convex value type string.\n *\n * @returns\n * - hasMany + required: `v.array(v.id(\"mediaCollectionSlug\"))`\n * - hasMany + !required: `v.optional(v.array(v.id(\"mediaCollectionSlug\")))`\n * - !hasMany + required: `v.id(\"mediaCollectionSlug\")`\n * - !hasMany + !required: `v.optional(v.id(\"mediaCollectionSlug\"))`\n */\nexport function uploadToValueTypeString(props: {\n field: UploadFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n const idType = `v.id(\"${props.field.to}\")`;\n const baseValueType = props.field.hasMany ? `v.array(${idType})` : idType;\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: baseValueType,\n skipDefaultValidation: true,\n });\n}\n","import type { ArrayFieldDef } from \"../../types\";\n\nexport function array(options: Omit<ArrayFieldDef, \"type\">): ArrayFieldDef {\n return { type: \"array\", ...options };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { ArrayFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for an array field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: shows item count — \"no items\", \"1 item\", \"3 items\"\n */\nexport function arrayColumnDef(props: {\n fieldKey: string;\n field: ArrayFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (!Array.isArray(value) || value.length === 0) return \"no items\";\n if (value.length === 1) return \"1 item\";\n return `${value.length} items`;\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { ArrayFieldDef, VexField } from \"../../types\";\n\n/**\n * Converts array field definition to a Convex value type string.\n *\n * Uses callback injection to resolve the inner field type,\n * avoiding circular imports with fieldToValueType.\n *\n * @returns e.g. `\"v.array(v.string())\"` or `\"v.optional(v.array(v.string()))\"`\n */\nexport function arrayToValueTypeString(props: {\n field: ArrayFieldDef;\n collectionSlug: string;\n fieldName: string;\n resolveInnerField: (props: {\n field: VexField;\n collectionSlug: string;\n fieldName: string;\n }) => string;\n}): string {\n const innerValueType = props.resolveInnerField({\n field: props.field.field,\n collectionSlug: props.collectionSlug,\n fieldName: `${props.fieldName}[]`,\n });\n // Strip v.optional() from inner — array wrapping handles optionality\n const unwrapped = innerValueType.replace(/^v\\.optional\\((.+)\\)$/, \"$1\");\n const arrayType = `v.array(${unwrapped})`;\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: arrayType,\n skipDefaultValidation: true,\n });\n}\n","import type { BlocksFieldDef, BlockDef } from \"../../types\";\nimport { VexBlockValidationError } from \"../../errors\";\n\n/**\n * Create a blocks field that stores an ordered array of block instances.\n *\n * @param props.blocks - Array of BlockDef objects allowed in this field\n * @param props.labels - Optional singular/plural display labels\n * @param props.min - Minimum number of blocks\n * @param props.max - Maximum number of blocks\n * @returns A BlocksFieldDef\n *\n * @throws VexBlockValidationError if two blocks share the same slug\n *\n * @example\n * ```ts\n * content: blocks({\n * blocks: [heroBlock, ctaBlock, featureGridBlock],\n * })\n * ```\n */\nexport function blocks(props: {\n blocks: BlockDef[];\n labels?: BlocksFieldDef[\"labels\"];\n min?: number;\n max?: number;\n label?: string;\n description?: string;\n required?: boolean;\n admin?: BlocksFieldDef[\"admin\"];\n}): BlocksFieldDef {\n const seen = new Set<string>();\n for (const block of props.blocks) {\n if (seen.has(block.slug)) {\n throw new VexBlockValidationError(\n block.slug,\n `Duplicate block slug \"${block.slug}\" in blocks field. Each block in a blocks() field must have a unique slug.`,\n );\n }\n seen.add(block.slug);\n }\n\n return {\n type: \"blocks\",\n blocks: props.blocks,\n labels: props.labels,\n min: props.min,\n max: props.max,\n label: props.label,\n description: props.description,\n required: props.required,\n admin: props.admin,\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { BlocksFieldDef, VexField } from \"../../types\";\nimport { VexBlockValidationError } from \"../../errors\";\n\n/**\n * Converts a blocks field definition to a Convex value type string.\n *\n * Generates `v.array(v.union(v.object({...}), v.object({...})))` where each\n * v.object corresponds to a block type with `blockType: v.literal(\"slug\")`\n * as the discriminant, `_key: v.string()`, and each block field converted\n * to its Convex value type.\n *\n * @param props.field - The BlocksFieldDef\n * @param props.collectionSlug - Parent collection slug (for error messages)\n * @param props.fieldName - Field name on the parent collection (for error messages)\n * @param props.resolveInnerField - Callback to resolve inner field value types (avoids circular imports)\n * @param props.visitedBlockSlugs - Set of block slugs already being processed (cycle detection)\n * @returns Convex value type string, e.g. `\"v.array(v.union(v.object({...}), ...))\"`\n *\n * @throws VexBlockValidationError if a cycle is detected in nested blocks\n */\nexport function blocksToValueTypeString(props: {\n field: BlocksFieldDef;\n collectionSlug: string;\n fieldName: string;\n resolveInnerField: (props: {\n field: VexField;\n collectionSlug: string;\n fieldName: string;\n visitedBlockSlugs?: Set<string>;\n }) => string;\n visitedBlockSlugs?: Set<string>;\n}): string {\n const visited = props.visitedBlockSlugs ?? new Set<string>();\n\n if (props.field.blocks.length === 0) {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: \"v.array(v.any())\",\n skipDefaultValidation: true,\n });\n }\n\n const objectTypes: string[] = [];\n\n for (const block of props.field.blocks) {\n if (visited.has(block.slug)) {\n throw new VexBlockValidationError(\n block.slug,\n `Circular block reference detected: block \"${block.slug}\" references itself (directly or through a cycle).`,\n );\n }\n\n const blockVisited = new Set(visited);\n blockVisited.add(block.slug);\n\n const fieldEntries: string[] = [\n `blockType: v.literal(\"${block.slug}\")`,\n `blockName: v.optional(v.string())`,\n `_key: v.string()`,\n ];\n\n for (const [fieldName, field] of Object.entries(block.fields)) {\n const valueType = props.resolveInnerField({\n field: field as VexField,\n collectionSlug: props.collectionSlug,\n fieldName: `${props.fieldName}.${block.slug}.${fieldName}`,\n visitedBlockSlugs: blockVisited,\n });\n fieldEntries.push(`${fieldName}: ${valueType}`);\n }\n\n objectTypes.push(`v.object({${fieldEntries.join(\", \")}})`);\n }\n\n const innerType =\n objectTypes.length === 1\n ? objectTypes[0]\n : `v.union(${objectTypes.join(\", \")})`;\n\n const arrayType = `v.array(${innerType})`;\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: arrayType,\n skipDefaultValidation: true,\n });\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { BlocksFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a blocks field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: shows block count — \"no blocks\", \"1 block\", \"3 blocks\"\n * Uses field.labels if provided (e.g., \"1 section\", \"3 sections\").\n */\nexport function blocksColumnDef(props: {\n fieldKey: string;\n field: BlocksFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n const singular = props.field.labels?.singular ?? \"block\";\n const plural = props.field.labels?.plural ?? \"blocks\";\n\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (!Array.isArray(value) || value.length === 0) return `no ${plural}`;\n if (value.length === 1) return `1 ${singular}`;\n return `${value.length} ${plural}`;\n },\n };\n}\n","import { VexFieldValidationError } from \"../errors\";\nimport { checkboxToValueTypeString } from \"../fields/checkbox\";\nimport { numberToValueTypeString } from \"../fields/number\";\nimport { selectToValueTypeString } from \"../fields/select\";\nimport { textToValueTypeString } from \"../fields/text\";\nimport { dateToValueTypeString } from \"../fields/date\";\nimport { imageUrlToValueTypeString } from \"../fields/imageUrl\";\nimport { relationshipToValueTypeString } from \"../fields/relationship\";\nimport { jsonToValueTypeString } from \"../fields/json\";\nimport { richtextToValueTypeString } from \"../fields/richtext\";\nimport { uploadToValueTypeString } from \"../fields/media\";\nimport { arrayToValueTypeString } from \"../fields/array\";\nimport { blocksToValueTypeString } from \"../fields/blocks\";\nimport type { VexField } from \"../types\";\n\n/**\n * Converts a VexField to its Convex value type string representation.\n * Dispatches to the appropriate per-field function based on `type`.\n *\n * Each per-field function handles its own validation (via processFieldValueTypeOptions())\n * and its own v.optional() wrapping. This dispatcher just routes by type.\n */\nexport function fieldToValueType(props: {\n field: VexField;\n collectionSlug: string;\n fieldName: string;\n visitedBlockSlugs?: Set<string>;\n}): string {\n const { field, collectionSlug, fieldName } = props;\n switch (field.type) {\n case \"text\":\n return textToValueTypeString({ field, collectionSlug, fieldName });\n case \"number\":\n return numberToValueTypeString({ field, collectionSlug, fieldName });\n case \"checkbox\":\n return checkboxToValueTypeString({ field, collectionSlug, fieldName });\n case \"select\":\n return selectToValueTypeString({ field, collectionSlug, fieldName });\n case \"date\":\n return dateToValueTypeString({ field, collectionSlug, fieldName });\n case \"imageUrl\":\n return imageUrlToValueTypeString({ field, collectionSlug, fieldName });\n case \"relationship\":\n return relationshipToValueTypeString({ field, collectionSlug, fieldName });\n case \"upload\":\n return uploadToValueTypeString({ field, collectionSlug, fieldName });\n case \"json\":\n return jsonToValueTypeString({ field, collectionSlug, fieldName });\n case \"richtext\":\n return richtextToValueTypeString({ field, collectionSlug, fieldName });\n case \"array\":\n return arrayToValueTypeString({\n field,\n collectionSlug,\n fieldName,\n resolveInnerField: fieldToValueType,\n });\n case \"blocks\":\n return blocksToValueTypeString({\n field,\n collectionSlug,\n fieldName,\n resolveInnerField: (innerProps) =>\n fieldToValueType({\n field: innerProps.field,\n collectionSlug: innerProps.collectionSlug,\n fieldName: innerProps.fieldName,\n visitedBlockSlugs: innerProps.visitedBlockSlugs,\n }),\n visitedBlockSlugs: props.visitedBlockSlugs,\n });\n case \"ui\":\n throw new VexFieldValidationError(\n collectionSlug,\n fieldName,\n `UI field \"${fieldName}\" on collection \"${collectionSlug}\" has no database representation and should not be included in schema generation.`,\n );\n default:\n throw new VexFieldValidationError(\n collectionSlug,\n fieldName,\n `Unknown Field Type: ${(field as any).type}`,\n );\n }\n}\n","import { VexFieldValidationError } from \"../errors\";\nimport type {\n VexCollection,\n VexField,\n ResolvedIndex,\n} from \"../types\";\n\n/**\n * Collects all indexes for a collection from three sources:\n * 1. Per-field `index` property on individual fields\n * 2. Collection-level `indexes` array on the collection\n * 3. Auto-generated index for `admin.useAsTitle` field (for fast admin panel title queries)\n *\n * @param collection - The collection to extract indexes from\n * @returns Array of resolved indexes, deduplicated by name\n */\nexport function collectIndexes(props: { collection: VexCollection }): ResolvedIndex[] {\n const { collection } = props;\n const fieldIndexes = new Map<string, ResolvedIndex>();\n\n for (const [fieldKey, field] of Object.entries(collection.fields) as [string, VexField][]) {\n const indexName = field.index;\n if (indexName) {\n if (fieldIndexes.has(indexName)) {\n throw new VexFieldValidationError(\n collection.slug,\n fieldKey,\n `Duplicate Indexes detected: ${indexName}`,\n );\n }\n fieldIndexes.set(indexName, { name: indexName, fields: [fieldKey] });\n }\n }\n\n collection.indexes?.forEach((index) => {\n fieldIndexes.set(index.name, { name: index.name, fields: index.fields });\n });\n\n const useAsTitle = collection.admin?.useAsTitle as string;\n if (useAsTitle && useAsTitle !== \"_id\") {\n const autoName = `by_${useAsTitle}`;\n if (!fieldIndexes.has(autoName)) {\n fieldIndexes.set(autoName, { name: autoName, fields: [useAsTitle] });\n }\n }\n\n return Array.from(fieldIndexes.values());\n}\n","import { VexFieldValidationError } from \"../errors\";\nimport type {\n VexCollection,\n VexField,\n ResolvedSearchIndex,\n} from \"../types\";\n\n/**\n * Collects all search indexes for a collection from three sources:\n * 1. Per-field `searchIndex` property on individual fields\n * 2. Collection-level `searchIndexes` array on the collection\n * 3. Auto-generated search index for `admin.useAsTitle` field\n *\n * @param collection - The collection to extract search indexes from\n * @returns Array of resolved search indexes, deduplicated by name\n */\nexport function collectSearchIndexes(props: { collection: VexCollection }): ResolvedSearchIndex[] {\n const { collection } = props;\n const searchIndexes = new Map<string, ResolvedSearchIndex>();\n\n for (const [fieldKey, field] of Object.entries(collection.fields) as [string, VexField][]) {\n const searchIndex = field.searchIndex;\n if (searchIndex && searchIndex.name) {\n if (searchIndexes.has(searchIndex.name)) {\n throw new VexFieldValidationError(\n collection.slug,\n fieldKey,\n `Duplicate search index name: ${searchIndex.name}`,\n );\n }\n searchIndexes.set(searchIndex.name, {\n name: searchIndex.name,\n searchField: fieldKey,\n filterFields: searchIndex.filterFields,\n });\n }\n }\n\n collection.searchIndexes?.forEach((entry) => {\n searchIndexes.set(entry.name, {\n name: entry.name,\n searchField: entry.searchField,\n filterFields: entry.filterFields ?? [],\n });\n });\n\n const useAsTitle = collection.admin?.useAsTitle as string;\n if (useAsTitle && useAsTitle !== \"_id\") {\n const autoName = `search_${useAsTitle}`;\n const alreadyCovered = Array.from(searchIndexes.values()).some(\n (si) => si.searchField === useAsTitle,\n );\n if (!alreadyCovered && !searchIndexes.has(autoName)) {\n searchIndexes.set(autoName, {\n name: autoName,\n searchField: useAsTitle,\n filterFields: [],\n });\n }\n }\n\n return Array.from(searchIndexes.values());\n}\n","import type { VexField } from \"../types\";\nimport type { VexCollection } from \"../types\";\nimport type { ResolvedIndex, ResolvedSearchIndex } from \"../types\";\n\n/**\n * Result of merging an auth collection with a user collection.\n * Contains merged VexFields and metadata about field sources.\n */\nexport interface MergedCollectionResult {\n /**\n * The final merged field map.\n * Key is field name, value is the VexField object.\n * Auth fields win for schema generation; user admin config is preserved.\n */\n fields: Record<string, VexField>;\n\n /** Indexes from both auth and user collections (deduplicated by name). */\n indexes: ResolvedIndex[];\n\n /** Search indexes from the user collection. */\n searchIndexes: ResolvedSearchIndex[];\n\n /**\n * Fields that exist in both auth collection and user config.\n * The auth VexField wins for schema gen; user admin config wins for UI.\n */\n overlapping: string[];\n\n /** Fields that only exist in the auth collection (not in user's collection). */\n authOnly: string[];\n\n /** Fields that only exist in the user's collection (not from auth). */\n userOnly: string[];\n}\n\n/**\n * Merges an auth collection's fields with a user-defined collection's fields.\n *\n * Both sides are VexField records. For overlapping fields, the auth\n * VexField's schema properties are used (it controls the DB shape), but\n * the user's admin config (label, hidden, etc.) is preserved by copying\n * admin-related metadata from the user's field onto the auth field.\n *\n * @param authCollection - The auth collection with fully resolved fields\n * @param userCollection - The user's collection that matches this auth table by slug\n * @returns Merged collection result with combined fields and source tracking\n */\nexport function mergeAuthCollectionWithUserCollection(props: {\n authCollection: VexCollection;\n userCollection: VexCollection;\n}): MergedCollectionResult {\n const { authCollection, userCollection } = props;\n const fields: Record<string, VexField> = {};\n const overlapping: string[] = [];\n const authOnly: string[] = [];\n const userOnly: string[] = [];\n\n const authFields = authCollection.fields;\n const userFields = userCollection.fields;\n const authFieldKeys = Object.keys(authFields);\n const userFieldKeys = Object.keys(userFields);\n\n // Process auth fields\n for (const fieldKey of authFieldKeys) {\n if (userFieldKeys.includes(fieldKey)) {\n overlapping.push(fieldKey);\n // Auth field wins for schema, but user field wins for rendering.\n // Use user's field as base so type, label, admin, etc. are preserved,\n // then layer auth's schema-relevant props (required, defaultValue).\n const authField = authFields[fieldKey];\n const userField = userFields[fieldKey];\n fields[fieldKey] = {\n ...userField,\n required: authField.required,\n ...((authField as any).defaultValue !== undefined && { defaultValue: (authField as any).defaultValue }),\n } as VexField;\n } else {\n authOnly.push(fieldKey);\n fields[fieldKey] = authFields[fieldKey];\n }\n }\n\n // Process user-only fields\n for (const fieldKey of userFieldKeys) {\n if (authFieldKeys.includes(fieldKey)) continue;\n userOnly.push(fieldKey);\n fields[fieldKey] = userFields[fieldKey];\n }\n\n // Merge indexes (auth indexes first, user indexes added if name doesn't conflict)\n const indexes: ResolvedIndex[] = [];\n const indexNames = new Set<string>();\n\n // Auth collection indexes (from collection-level)\n for (const idx of authCollection.indexes ?? []) {\n indexes.push({ name: idx.name, fields: idx.fields as string[] });\n indexNames.add(idx.name);\n }\n\n // User collection indexes\n for (const idx of userCollection.indexes ?? []) {\n if (!indexNames.has(idx.name)) {\n indexes.push({ name: idx.name, fields: idx.fields as string[] });\n indexNames.add(idx.name);\n }\n }\n\n // Search indexes from user collection\n const searchIndexes: ResolvedSearchIndex[] = (\n userCollection.searchIndexes ?? []\n ).map((si) => ({\n name: si.name,\n searchField: si.searchField as string,\n filterFields: (si.filterFields ?? []) as string[],\n }));\n\n return { fields, indexes, searchIndexes, overlapping, authOnly, userOnly };\n}\n","import { VexSlugConflictError } from \"../errors\";\nimport type { VexConfig } from \"../types\";\n\n// =============================================================================\n// SLUG REGISTRY — tracks table slugs and validates uniqueness on register\n// =============================================================================\n\n/**\n * Where a slug was registered from.\n */\nexport const SLUG_SOURCES = {\n userCollection: \"user-collection\",\n userGlobal: \"user-global\",\n authTable: \"auth-table\",\n mediaCollection: \"media-collection\",\n system: \"system\",\n} as const;\nexport type SlugSource = (typeof SLUG_SOURCES)[keyof typeof SLUG_SOURCES];\n\n/**\n * A registered slug with its source information.\n */\nexport interface SlugRegistration {\n slug: string;\n source: SlugSource;\n /** Human-readable description of where this slug was defined */\n location: string;\n}\n\n/**\n * Registry that collects all table slugs and validates uniqueness.\n * Throws immediately on duplicate — fail fast during schema generation.\n */\nexport class SlugRegistry {\n private registrations = new Map<string, SlugRegistration>();\n\n /**\n * Register a slug with its source.\n * Throws VexSlugConflictError immediately if the slug is already registered,\n * UNLESS an auth table slug overlaps with a user collection slug — this is\n * expected behavior indicating the user wants to customize that auth table's\n * admin UI. In that case, the user collection's registration takes precedence\n * (it was registered first as \"user-collection\") and the auth table is\n * silently skipped in the registry. The merge happens during schema generation.\n *\n * @param props.slug - The table slug to register\n * @param props.source - Where this slug comes from (e.g., \"user-collection\", \"auth-table\")\n * @param props.location - Human-readable location for error messages (e.g., `collection \"posts\"`)\n *\n * Edge cases:\n * - Auth table slug matches user collection slug: NOT a conflict — skip\n * registration (user collection already registered, merge happens later)\n * - System table prefixed with \"vex_\" should not conflict with user tables\n * because defineCollection already warns about \"vex_\" prefix\n */\n register(props: {\n slug: string;\n source: SlugSource;\n location: string;\n }): void {\n const existing = this.registrations.get(props.slug);\n if (existing) {\n // Auth table overlapping with user collection is expected — it means\n // the user wants to customize that auth table. The user collection\n // registration takes precedence; merge happens during schema generation.\n if (\n (existing.source === \"user-collection\" &&\n props.source === \"auth-table\") ||\n (existing.source === \"auth-table\" && props.source === \"user-collection\")\n ) {\n // Keep the user-collection registration, skip the auth-table one\n if (props.source === \"user-collection\") {\n this.registrations.set(props.slug, {\n slug: props.slug,\n source: props.source,\n location: props.location,\n });\n }\n return;\n }\n throw new VexSlugConflictError(\n props.slug,\n existing.source,\n existing.location,\n props.source,\n props.location,\n );\n }\n this.registrations.set(props.slug, {\n slug: props.slug,\n source: props.source,\n location: props.location,\n });\n }\n\n /**\n * Get all registered slugs.\n */\n getAll(): SlugRegistration[] {\n return [...this.registrations.values()];\n }\n}\n\n/**\n * Populate a SlugRegistry from a VexConfig.\n *\n * Registers slugs from:\n * 1. User collections (source: \"user-collection\")\n * 2. User globals (source: \"user-global\")\n * 3. Auth tables (source: \"auth-table\") — including the user table\n * 4. System tables like vex_globals (source: \"system\")\n *\n * Each register() call throws immediately on duplicate slug, except\n * when an auth table slug matches a user collection slug — this is\n * expected behavior indicating the user wants to customize that auth\n * table's admin UI. The merge happens during schema generation.\n *\n * Edge cases:\n * - No globals: skip global registration\n * - Auth table slug matches user collection slug: NOT a conflict —\n * the user collection registration takes precedence, merge happens later\n */\nexport function buildSlugRegistry(props: { config: VexConfig }): SlugRegistry {\n const registry = new SlugRegistry();\n\n for (const collection of props.config.collections) {\n registry.register({\n slug: collection.slug,\n source: SLUG_SOURCES.userCollection,\n location: `Collection ${collection.slug}`,\n });\n }\n\n // Register media collection slugs\n if (props.config.media) {\n for (const collection of props.config.media.collections) {\n registry.register({\n slug: collection.slug,\n source: SLUG_SOURCES.mediaCollection,\n location: `Media Collection ${collection.slug}`,\n });\n }\n }\n\n for (const global of props.config.globals) {\n registry.register({\n slug: global.slug,\n source: SLUG_SOURCES.userGlobal,\n location: `Global ${global.slug}`,\n });\n }\n\n for (const collection of props.config.auth.collections) {\n registry.register({\n slug: collection.slug,\n source: SLUG_SOURCES.authTable,\n location: `Auth Table ${collection.slug}`,\n });\n }\n\n return registry;\n}\n","import type { ResolvedIndex, ResolvedSearchIndex, VexConfig, VexField } from \"../types\";\nimport { fieldToValueType } from \"./extract\";\nimport { collectIndexes } from \"./indexes\";\nimport { collectSearchIndexes } from \"./searchIndexes\";\nimport { mergeAuthCollectionWithUserCollection } from \"./merge\";\nimport { buildSlugRegistry } from \"./slugs\";\n\n/**\n * Generates the full TypeScript source content for `convex/vex.schema.ts`.\n *\n * This is the main entry point for schema generation. It:\n * 1. Validates all slugs are unique (via SlugRegistry)\n * 2. For each auth collection, checks if a matching user collection exists (by slug):\n * a. If yes: merges auth collection fields with user collection fields\n * b. If no matching collection: generates the auth collection as-is\n * 3. User collections that don't match any auth collection: generates from collection fields only\n * 4. Collects indexes from per-field `index` properties and collection-level `indexes`\n * 5. Generates defineTable() calls for each table with chained .index() calls\n * 6. Generates defineTable() calls for system tables (vex_globals if globals exist)\n *\n * All fields go through fieldToValueType() uniformly — no dual path for auth vs user.\n */\nexport function generateVexSchema(props: { config: VexConfig }): string {\n const config = props.config;\n buildSlugRegistry({ config });\n const authCollectionMap = new Map(\n config.auth.collections.map((c) => [c.slug, c]),\n );\n const mergedAuthSlugs = new Set<string>();\n\n const lines: string[] = [\n \"// ⚠️ AUTO-GENERATED BY VEX CMS — DO NOT EDIT ⚠️\",\n \"\",\n 'import { defineTable } from \"convex/server\";',\n 'import { v } from \"convex/values\";',\n ];\n\n if (config.collections.length > 0) {\n lines.push(\"\", \"/**\", \" * USER COLLECTIONS\", \" **/\");\n }\n\n for (const collection of config.collections) {\n const authCollection = authCollectionMap.get(collection.slug);\n const fields: { name: string; valueType: string }[] = [];\n const indexes: ResolvedIndex[] = collectIndexes({ collection });\n const searchIndexes: ResolvedSearchIndex[] = collectSearchIndexes({\n collection,\n });\n\n if (authCollection) {\n mergedAuthSlugs.add(authCollection.slug);\n const merged = mergeAuthCollectionWithUserCollection({\n authCollection,\n userCollection: collection,\n });\n\n // All merged fields go through fieldToValueType uniformly\n for (const [name, field] of Object.entries(merged.fields)) {\n if (field.type === \"ui\") continue; // UI fields have no database representation\n fields.push({\n name,\n valueType: fieldToValueType({\n field,\n collectionSlug: collection.slug,\n fieldName: name,\n }),\n });\n }\n\n // Add merged indexes (deduplicated)\n for (const index of merged.indexes) {\n if (indexes.find((ui) => ui.name === index.name)) continue;\n indexes.push(index);\n }\n\n // Add merged search indexes\n for (const si of merged.searchIndexes) {\n if (searchIndexes.find((existing) => existing.name === si.name))\n continue;\n searchIndexes.push(si);\n }\n } else {\n for (const [fieldName, field] of Object.entries(\n collection.fields,\n ) as [string, VexField][]) {\n if (field.type === \"ui\") continue; // UI fields have no database representation\n fields.push({\n name: fieldName,\n valueType: fieldToValueType({\n fieldName,\n field,\n collectionSlug: collection.slug,\n }),\n });\n }\n }\n\n lines.push(\n \"\",\n `export const ${collection.tableName ?? collection.slug} = defineTable({`,\n );\n for (const f of fields) {\n lines.push(` ${f.name}: ${f.valueType},`);\n }\n // vex_status on all user collections — defaults to \"published\"\n lines.push(` vex_status: v.optional(v.union(v.literal(\"draft\"), v.literal(\"published\"))),`);\n if (collection.versions?.drafts) {\n lines.push(` vex_version: v.optional(v.number()),`);\n lines.push(` vex_publishedAt: v.optional(v.number()),`);\n }\n lines.push(\"})\");\n for (const i of indexes) {\n const fieldList = i.fields.map((f) => `\"${f}\"`).join(\", \");\n lines.push(` .index(\"${i.name}\", [${fieldList}])`);\n }\n for (const si of searchIndexes) {\n const filterList =\n si.filterFields.length > 0\n ? `, filterFields: [${si.filterFields.map((f) => `\"${f}\"`).join(\", \")}]`\n : \"\";\n lines.push(\n ` .searchIndex(\"${si.name}\", { searchField: \"${si.searchField}\"${filterList} })`,\n );\n }\n }\n\n // --- MEDIA COLLECTIONS ---\n if (config.media && config.media.collections.length > 0) {\n lines.push(\"\", \"/**\", \" * MEDIA COLLECTIONS\", \" **/\");\n\n for (const mediaCollection of config.media.collections) {\n const fields: { name: string; valueType: string }[] = [];\n const indexes: ResolvedIndex[] = collectIndexes({ collection: mediaCollection });\n const searchIndexes: ResolvedSearchIndex[] = collectSearchIndexes({\n collection: mediaCollection,\n });\n\n for (const [fieldName, field] of Object.entries(\n mediaCollection.fields,\n ) as [string, VexField][]) {\n if (field.type === \"ui\") continue;\n if (fieldName === \"storageId\") {\n // Use adapter's storageIdValueType instead of fieldToValueType\n fields.push({\n name: fieldName,\n valueType: config.media.storageAdapter.storageIdValueType,\n });\n } else {\n fields.push({\n name: fieldName,\n valueType: fieldToValueType({\n fieldName,\n field,\n collectionSlug: mediaCollection.slug,\n }),\n });\n }\n }\n\n lines.push(\n \"\",\n `export const ${mediaCollection.tableName ?? mediaCollection.slug} = defineTable({`,\n );\n for (const f of fields) {\n lines.push(` ${f.name}: ${f.valueType},`);\n }\n lines.push(\"})\");\n for (const i of indexes) {\n const fieldList = i.fields.map((f) => `\"${f}\"`).join(\", \");\n lines.push(` .index(\"${i.name}\", [${fieldList}])`);\n }\n for (const si of searchIndexes) {\n const filterList =\n si.filterFields.length > 0\n ? `, filterFields: [${si.filterFields.map((f) => `\"${f}\"`).join(\", \")}]`\n : \"\";\n lines.push(\n ` .searchIndex(\"${si.name}\", { searchField: \"${si.searchField}\"${filterList} })`,\n );\n }\n }\n }\n\n const unmergedAuthCollections = config.auth.collections.filter(\n (c) => !mergedAuthSlugs.has(c.slug),\n );\n\n if (unmergedAuthCollections.length > 0) {\n lines.push(\"\", \"/**\", \" * AUTH TABLES\", \" **/\");\n }\n\n for (const authCollection of unmergedAuthCollections) {\n const indexes: ResolvedIndex[] = collectIndexes({\n collection: authCollection,\n });\n lines.push(\n \"\",\n `export const ${authCollection.tableName ?? authCollection.slug} = defineTable({`,\n );\n for (const [name, field] of Object.entries(authCollection.fields) as [string, VexField][]) {\n lines.push(\n ` ${name}: ${fieldToValueType({\n field,\n collectionSlug: authCollection.slug,\n fieldName: name,\n })},`,\n );\n }\n lines.push(\"})\");\n for (const i of indexes) {\n const fieldList = i.fields.map((f) => `\"${f}\"`).join(\", \");\n lines.push(` .index(\"${i.name}\", [${fieldList}])`);\n }\n }\n\n for (const global of config.globals) {\n const fields: { name: string; valueType: string }[] = [];\n const indexes: ResolvedIndex[] = collectIndexes({ collection: global });\n for (const [fieldName, field] of Object.entries(global.fields)) {\n fields.push({\n name: fieldName,\n valueType: fieldToValueType({\n fieldName,\n field,\n collectionSlug: global.slug,\n }),\n });\n }\n\n lines.push(\n \"\",\n `export const ${global.tableName ?? global.slug} = defineTable({`,\n );\n for (const f of fields) {\n lines.push(` ${f.name}: ${f.valueType},`);\n }\n lines.push(\"})\");\n for (const i of indexes) {\n const fieldList = i.fields.map((f) => `\"${f}\"`).join(\", \");\n lines.push(` .index(\"${i.name}\", [${fieldList}])`);\n }\n }\n\n // Always generate vex_versions so removing versioning from a collection\n // doesn't break schema.ts imports that reference vex_versions.\n {\n lines.push(\"\", \"/**\", \" * VEX SYSTEM TABLES\", \" **/\");\n lines.push(\"\");\n lines.push(\"export const vex_versions = defineTable({\");\n lines.push(\" collection: v.string(),\");\n lines.push(\" documentId: v.string(),\");\n lines.push(\" version: v.number(),\");\n lines.push(` status: v.union(v.literal(\"draft\"), v.literal(\"published\"), v.literal(\"autosave\"), v.literal(\"previewSnapshot\")),`);\n lines.push(\" snapshot: v.any(),\");\n lines.push(\" createdAt: v.number(),\");\n lines.push(\" createdBy: v.optional(v.string()),\");\n lines.push(\" isAutosave: v.boolean(),\");\n lines.push(\" restoredFrom: v.optional(v.number()),\");\n lines.push(\"})\");\n lines.push(` .index(\"by_document\", [\"collection\", \"documentId\"])`);\n lines.push(` .index(\"by_document_version\", [\"collection\", \"documentId\", \"version\"])`);\n lines.push(` .index(\"by_document_latest\", [\"collection\", \"documentId\", \"createdAt\"])`);\n lines.push(` .index(\"by_document_status\", [\"collection\", \"documentId\", \"status\"])`);\n lines.push(` .index(\"by_autosave\", [\"collection\", \"documentId\", \"isAutosave\"])`);\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","import { defineTable, type TableDefinition } from \"convex/server\";\nimport type { GenericValidator, ObjectType, VObject } from \"convex/values\";\n\ntype ExtractFields<T> =\n T extends TableDefinition<VObject<any, infer F>> ? F : never;\n\ntype ForbidExistingKeys<Existing, New> = {\n [K in keyof New]: K extends keyof Existing ? never : New[K];\n};\n\n/**\n * Compute the TableDefinition type that preserves field types.\n * Matches the second overload of defineTable:\n * defineTable(fields) → TableDefinition<VObject<ObjectType<Fields>, Fields>>\n */\ntype ExtendedTableDef<Fields extends Record<string, GenericValidator>> =\n TableDefinition<VObject<ObjectType<Fields>, Fields>>;\n\n/**\n * Extends a vex-generated table definition with additional fields,\n * preserving all indexes from the original table.\n *\n * Use this in your `convex/schema.ts` when you need to add custom\n * fields to a vex-managed table (e.g., adding a `body` field to posts).\n *\n * @param props.table - The table definition from vex.schema.ts\n * @param props.additionalFields - Additional Convex validator fields to add.\n * Keys that already exist on the table will cause a type error.\n * @returns A new TableDefinition with merged fields and original indexes.\n * You can chain additional `.index()` calls on the result.\n *\n * @example\n * ```ts\n * import { posts } from \"./vex.schema\";\n * import { extendTable } from \"@vexcms/core\";\n * import { v } from \"convex/values\";\n *\n * export default defineSchema({\n * posts: extendTable({\n * table: posts,\n * additionalFields: { body: v.optional(v.string()) },\n * }).index(\"by_status\", [\"status\"]),\n * });\n * ```\n */\nexport function extendTable<\n T extends TableDefinition<VObject<any, any>>,\n A extends Record<string, GenericValidator> = {},\n>(props: {\n table: T;\n additionalFields?: A & ForbidExistingKeys<ExtractFields<T>, A>;\n}): ExtendedTableDef<ExtractFields<T> & A> {\n const { validator } = props.table;\n\n let extended = defineTable({\n ...validator.fields,\n ...props.additionalFields,\n });\n\n // Use the public \" indexes\"() method (note: the method name has a leading space)\n for (const idx of props.table[\" indexes\"]()) {\n extended = extended.index(\n idx.indexDescriptor,\n idx.fields as [string, ...string[]],\n );\n }\n\n // searchIndexes and vectorIndexes are private — access via any cast\n const source = props.table as any;\n\n for (const idx of source.searchIndexes ?? []) {\n extended = extended.searchIndex(idx.indexDescriptor, {\n searchField: idx.searchField,\n filterFields: idx.filterFields,\n } as any);\n }\n\n for (const idx of source.vectorIndexes ?? []) {\n extended = extended.vectorIndex(idx.indexDescriptor, {\n vectorField: idx.vectorField,\n dimensions: idx.dimensions,\n filterFields: idx.filterFields,\n } as any);\n }\n\n return extended as ExtendedTableDef<ExtractFields<T> & A>;\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { UploadFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for an upload field.\n *\n * The cell renders the raw document ID by default. Consumers (e.g., admin-next)\n * can replace the cell renderer using the column meta to show a file preview.\n *\n * Meta includes `type: \"upload\"` and `to` (target collection slug) so that\n * the rendering layer can detect upload columns and provide custom rendering.\n */\nexport function uploadColumnDef(props: {\n fieldKey: string;\n field: UploadFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: (props.field.hasMany ? props.field.labels?.singular : props.field.label) ?? toTitleCase(props.fieldKey),\n meta: {\n type: \"upload\",\n to: props.field.to,\n noTruncate: true,\n },\n cell: (info) => {\n const value = info.getValue();\n if (!value || typeof value !== \"string\") return \"\";\n return value;\n },\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { VexAuthAdapter, VexCollection, VexField } from \"../types\";\nimport { textColumnDef } from \"../fields/text/columnDef\";\nimport { numberColumnDef } from \"../fields/number/columnDef\";\nimport { checkboxColumnDef } from \"../fields/checkbox/columnDef\";\nimport { selectColumnDef } from \"../fields/select/columnDef\";\nimport { dateColumnDef } from \"../fields/date/columnDef\";\nimport { imageUrlColumnDef } from \"../fields/imageUrl/columnDef\";\nimport { relationshipColumnDef } from \"../fields/relationship/columnDef\";\nimport { jsonColumnDef } from \"../fields/json/columnDef\";\nimport { richtextColumnDef } from \"../fields/richtext/columnDef\";\nimport { arrayColumnDef } from \"../fields/array/columnDef\";\nimport { uploadColumnDef } from \"../fields/media/columnDef\";\nimport { blocksColumnDef } from \"../fields/blocks/columnDef\";\nimport { toTitleCase } from \"../utils\";\n\n/**\n * Generates an array of ColumnDef objects from a VexCollection's field configs.\n *\n * @param props.collection - The collection to generate columns for\n * @param props.auth - Optional auth adapter. When provided, auth fields (e.g. createdAt)\n * get proper columnDef dispatch instead of falling back to plain text columns.\n * @returns Array of ColumnDef objects for use with @tanstack/react-table\n */\nexport function generateColumns(props: {\n collection: VexCollection;\n auth?: VexAuthAdapter;\n}): ColumnDef<Record<string, unknown>>[] {\n const { collection, auth } = props;\n const columns: ColumnDef<Record<string, unknown>>[] = [];\n const useAsTitle = collection.admin?.useAsTitle as string | undefined;\n const defaultColumns = collection.admin?.defaultColumns as\n | string[]\n | undefined;\n const fields = collection.fields;\n\n // Build a lookup of auth fields for this collection's slug\n const authFields: Record<string, VexField> = {};\n if (auth) {\n const authCollection = auth.collections.find(\n (c: VexCollection) => c.slug === collection.slug,\n );\n if (authCollection) {\n for (const [k, v] of Object.entries(authCollection.fields) as [\n string,\n VexField,\n ][]) {\n authFields[k] = v;\n }\n }\n }\n\n if (defaultColumns) {\n for (const fieldKey of defaultColumns) {\n if (fieldKey === \"_id\") {\n columns.push({ accessorKey: \"_id\", header: \"ID\" });\n continue;\n }\n\n const field = (fields[fieldKey] ?? authFields[fieldKey]) as\n | VexField\n | undefined;\n\n if (!field) {\n columns.push({ accessorKey: fieldKey, header: toTitleCase(fieldKey) });\n continue;\n }\n\n if (field.admin?.hidden) continue;\n if (field.type === \"ui\") continue;\n\n const col = buildColumnDef(fieldKey, field);\n\n if (useAsTitle && fieldKey === useAsTitle) {\n col.meta = { ...col.meta, isTitle: true };\n }\n\n // Attach custom Cell component to meta if present\n if (field.admin?.components?.Cell) {\n col.meta = {\n ...col.meta,\n customCell: field.admin.components.Cell,\n fieldDef: field,\n };\n }\n\n columns.push(col);\n }\n } else {\n columns.push({ accessorKey: \"_id\", header: \"ID\" });\n\n // Collect all field keys: user fields first, then auth-only fields\n const allFieldKeys = new Set(Object.keys(fields));\n for (const k of Object.keys(authFields)) {\n allFieldKeys.add(k);\n }\n\n for (const fieldKey of allFieldKeys) {\n const field = (fields[fieldKey] ?? authFields[fieldKey]) as VexField;\n if (field.admin?.hidden) continue;\n if (field.type === \"ui\") continue;\n\n const col = buildColumnDef(fieldKey, field);\n\n if (useAsTitle && fieldKey === useAsTitle) {\n col.meta = { ...col.meta, isTitle: true };\n }\n\n // Attach custom Cell component to meta if present\n if (field.admin?.components?.Cell) {\n col.meta = {\n ...col.meta,\n customCell: field.admin.components.Cell,\n fieldDef: field,\n };\n }\n\n columns.push(col);\n }\n }\n\n return columns;\n}\n\nfunction buildColumnDef(\n fieldKey: string,\n field: VexField,\n): ColumnDef<Record<string, unknown>> {\n switch (field.type) {\n case \"text\":\n return textColumnDef({ fieldKey, field });\n case \"number\":\n return numberColumnDef({ fieldKey, field });\n case \"checkbox\":\n return checkboxColumnDef({ fieldKey, field });\n case \"select\":\n return selectColumnDef({ fieldKey, field });\n case \"date\":\n return dateColumnDef({ fieldKey, field });\n case \"imageUrl\":\n return imageUrlColumnDef({ fieldKey, field });\n case \"relationship\":\n return relationshipColumnDef({ fieldKey, field });\n case \"json\":\n return jsonColumnDef({ fieldKey, field });\n case \"richtext\":\n return richtextColumnDef({ fieldKey, field });\n case \"array\":\n return arrayColumnDef({ fieldKey, field });\n case \"upload\":\n return uploadColumnDef({ fieldKey, field });\n case \"blocks\":\n return blocksColumnDef({ fieldKey, field });\n default:\n return {\n accessorKey: fieldKey,\n header: toTitleCase(fieldKey),\n };\n }\n}\n","import { z, type ZodTypeAny } from \"zod\";\nimport type { VexField } from \"../types\";\n\n/**\n * Generate a Zod schema from a collection's field definitions.\n * Used by both the client-side form (for validation on submit)\n * and the server-side mutation (for payload validation).\n *\n * @param props.fields - Record of field name → VexField from the collection\n * @returns A z.object() schema matching the collection's editable fields\n */\nexport function generateFormSchema(props: {\n fields: Record<string, VexField>;\n}): z.ZodObject<Record<string, ZodTypeAny>> {\n const shape: Record<string, ZodTypeAny> = {};\n\n for (const [fieldName, field] of Object.entries(props.fields)) {\n if (field.admin?.hidden) continue;\n if (field.type === \"ui\") continue;\n\n let validator = fieldMetaToZod({ field });\n\n if (!field.required) {\n validator = validator.optional();\n }\n\n shape[fieldName] = validator;\n }\n\n return z.object(shape);\n}\n\n/**\n * Convert a single field to its Zod validator.\n * Does NOT handle optional wrapping — that's done by the caller.\n *\n * @param props.field - The field definition (discriminated on `type`)\n * @returns The base Zod type for this field (always required)\n */\nexport function fieldMetaToZod(props: { field: VexField }): ZodTypeAny {\n switch (props.field.type) {\n case \"text\": {\n let schema = z.string();\n if (props.field.minLength != null) schema = schema.min(props.field.minLength);\n if (props.field.maxLength != null) schema = schema.max(props.field.maxLength);\n return schema;\n }\n\n case \"number\": {\n let schema = z.number();\n if (props.field.min != null) schema = schema.min(props.field.min);\n if (props.field.max != null) schema = schema.max(props.field.max);\n return schema;\n }\n\n case \"checkbox\":\n return z.boolean();\n\n case \"select\": {\n const values = props.field.options.map((o) => o.value);\n if (values.length === 0) return z.string();\n const enumSchema = z.enum(values as [string, ...string[]]);\n if (props.field.hasMany) {\n return z.array(enumSchema);\n }\n return enumSchema;\n }\n\n case \"date\":\n return z.number();\n\n case \"imageUrl\":\n return z.string().url().or(z.literal(\"\"));\n\n case \"relationship\": {\n if (props.field.hasMany) {\n return z.array(z.string());\n }\n return z.string();\n }\n\n case \"upload\": {\n if (props.field.hasMany) {\n return z.array(z.string());\n }\n return z.string();\n }\n\n case \"json\":\n return z.any();\n\n case \"richtext\":\n return z.any();\n\n case \"array\": {\n let schema = z.array(fieldMetaToZod({ field: props.field.field }));\n if (props.field.min != null) schema = schema.min(props.field.min);\n if (props.field.max != null) schema = schema.max(props.field.max);\n return schema;\n }\n\n case \"blocks\": {\n const blockSchemas = props.field.blocks.map((blockDef) => {\n const shape: Record<string, ZodTypeAny> = {\n blockType: z.literal(blockDef.slug),\n blockName: z.string().optional(),\n _key: z.string(),\n };\n for (const [fieldName, field] of Object.entries(blockDef.fields)) {\n let validator = fieldMetaToZod({ field: field as VexField });\n if (!(field as VexField).required) {\n validator = validator.optional();\n }\n shape[fieldName] = validator;\n }\n return z.object(shape);\n });\n\n if (blockSchemas.length === 0) {\n let schema = z.array(z.any());\n if (props.field.min != null) schema = schema.min(props.field.min);\n if (props.field.max != null) schema = schema.max(props.field.max);\n return schema;\n }\n\n const union =\n blockSchemas.length === 1\n ? blockSchemas[0]\n : z.discriminatedUnion(\n \"blockType\",\n blockSchemas as [z.ZodObject<any>, z.ZodObject<any>, ...z.ZodObject<any>[]],\n );\n\n let schema = z.array(union);\n if (props.field.min != null) schema = schema.min(props.field.min);\n if (props.field.max != null) schema = schema.max(props.field.max);\n return schema;\n }\n\n default:\n return z.any();\n }\n}\n","import type { VexField } from \"../types\";\n\n/**\n * Compute the zero-value for a field type (used as initial form value).\n */\nfunction getFormDefaultValue(props: { field: VexField }): unknown {\n switch (props.field.type) {\n case \"text\":\n return props.field.defaultValue ?? \"\";\n case \"number\":\n return props.field.defaultValue ?? 0;\n case \"checkbox\":\n return props.field.defaultValue ?? false;\n case \"select\":\n if (props.field.hasMany) {\n return props.field.defaultValue ? [props.field.defaultValue] : [];\n }\n return props.field.defaultValue ?? \"\";\n case \"date\":\n return props.field.defaultValue ?? 0;\n case \"imageUrl\":\n return props.field.defaultValue ?? \"\";\n case \"relationship\":\n return props.field.hasMany ? [] : \"\";\n case \"upload\":\n return props.field.hasMany ? [] : \"\";\n case \"json\":\n return {};\n case \"richtext\":\n return [];\n case \"array\":\n return [];\n case \"blocks\":\n return [];\n case \"ui\":\n return undefined;\n default:\n return undefined;\n }\n}\n\n/**\n * Generate default values for a create form from a collection's field definitions.\n * Skips hidden fields.\n *\n * @param props.fields - Record of field name -> VexField from the collection\n * @returns Record of field name -> default value for the create form\n */\nexport function generateFormDefaultValues(props: {\n fields: Record<string, VexField>;\n}): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [fieldName, field] of Object.entries(props.fields)) {\n if (field.admin?.hidden) continue;\n if (field.type === \"ui\") continue;\n result[fieldName] = getFormDefaultValue({ field });\n }\n\n return result;\n}\n","import type { UIFieldDef, FieldAdminConfig, FieldComponentProps } from \"../../types\";\nimport type { ComponentType } from \"react\";\n\n/**\n * Creates a UI field — a non-persisted field that renders a custom component.\n * UI fields are skipped during schema generation, form validation, and column generation.\n * They are useful for computed displays, action buttons, and embedded widgets.\n *\n * @param props.label - Display label for the field\n * @param props.admin - Admin config. components.Field is required.\n * @param props.description - Helper text displayed below the field\n * @returns A UIFieldDef\n *\n * @example\n * ```ts\n * import { ui } from \"@vexcms/core\";\n * import WordCount from \"~/components/admin/WordCount\";\n *\n * const collection = defineCollection({\n * slug: \"posts\",\n * fields: {\n * wordCount: ui({\n * label: \"Word Count\",\n * admin: {\n * components: { Field: WordCount },\n * position: \"sidebar\",\n * },\n * }),\n * },\n * });\n * ```\n */\nexport function ui(props: {\n label?: string;\n admin: FieldAdminConfig & {\n components: {\n Field: ComponentType<FieldComponentProps>;\n };\n };\n description?: string;\n}): UIFieldDef {\n return {\n type: \"ui\" as const,\n label: props.label,\n description: props.description,\n admin: props.admin,\n };\n}\n","// =============================================================================\n// FIELD TYPES — Object-based configuration\n// =============================================================================\n\nimport type { ComponentType } from \"react\";\n\n/** Content alignment for data table cells. */\nexport type Alignment = \"left\" | \"right\" | \"center\";\nexport type Labels = {\n singular: string;\n plural: string;\n};\n\n/**\n * Props passed to custom field components.\n * Custom components receive these props and use useVexField() for state.\n *\n * Use the generic parameter to narrow the field type for type-safe access\n * to field-specific properties like `options` on select fields.\n *\n * @example\n * ```tsx\n * // Generic — fieldDef has label, admin, description, required\n * function MyField({ name, fieldDef, readOnly }: FieldComponentProps) { ... }\n *\n * // Narrowed — fieldDef is TextFieldDef with maxLength, minLength, etc.\n * function MyTextField({ name, fieldDef }: FieldComponentProps<TextFieldDef>) { ... }\n * ```\n */\nexport interface FieldComponentProps<TField extends VexField = VexField> {\n /** The field key name (e.g., \"primaryColor\") */\n name: string;\n /** The VexField definition for this field */\n fieldDef: TField;\n /** Whether the field is read-only (from permissions or config) */\n readOnly: boolean;\n}\n\n/**\n * Props passed to custom cell components in the data table.\n */\nexport interface CellComponentProps<TField extends VexField = VexField> {\n /** The raw cell value from the document */\n value: unknown;\n /** The full row data (document) */\n row: Record<string, unknown>;\n /** The VexField definition for this column's field */\n fieldDef: TField;\n}\n\n/**\n * Admin panel configuration for individual fields.\n * Controls visibility, layout, and input behavior in the admin UI.\n */\nexport interface FieldAdminConfig {\n /**\n * Hide this field from the admin form.\n * Hidden fields are still stored in the database.\n *\n * Default: `false`\n */\n hidden?: boolean;\n /**\n * Make this field read-only in the admin form.\n * The value is displayed but cannot be edited.\n *\n * Default: `false`\n */\n readOnly?: boolean;\n /**\n * Position of the field in the form layout.\n *\n * - `\"main\"` — placed in the main content area\n * - `\"sidebar\"` — placed in the sidebar panel\n *\n * Default: `\"main\"`\n */\n position?: \"main\" | \"sidebar\";\n /**\n * Width of the field within its row.\n *\n * - `\"full\"` — spans the full width\n * - `\"half\"` — spans half the width (two fields per row)\n *\n * Default: `\"full\"`\n */\n width?: \"full\" | \"half\";\n /**\n * Placeholder text shown in the input when empty.\n */\n placeholder?: string;\n /**\n * Helper text displayed below the field input.\n * Use for additional context or formatting hints.\n */\n description?: string;\n /**\n * Content alignment in data table cells. 'left' | 'right' | 'center'\n */\n cellAlignment?: Alignment;\n /**\n * Custom components for this field.\n *\n * - `Field` replaces the entire field input in the edit form.\n * Only allowed on text, number, checkbox, and select fields.\n * The component receives FieldComponentProps and uses useVexField() for state.\n *\n * - `Cell` replaces the cell renderer in the data table list view.\n * Allowed on any field type.\n */\n components?: {\n Field?: ComponentType<FieldComponentProps>;\n Cell?: ComponentType<CellComponentProps>;\n };\n}\n\n// =============================================================================\n// BASE FIELD PROPERTIES (shared by all field types)\n// =============================================================================\n\n/**\n * Properties shared by all field types.\n * Each concrete field type extends this with its `type` discriminant\n * and type-specific options.\n */\ninterface BaseField {\n /** Display label for the field in the admin form. */\n label?: string;\n /** Description text shown below the field. */\n description?: string;\n /**\n * Whether this field is required.\n *\n * Default: `false`\n */\n required?: boolean;\n /** Admin UI configuration for this field. */\n admin?: FieldAdminConfig;\n /**\n * Create a database index on this field.\n * The string value becomes the index name in Convex.\n *\n * @example\n * ```ts\n * slug: { type: \"text\", index: \"by_slug\", required: true }\n * // Generates: .index(\"by_slug\", [\"slug\"])\n * ```\n */\n index?: string;\n /**\n * Create a full-text search index on this field.\n * The field this is defined on becomes the `searchField`.\n *\n * @example\n * ```ts\n * title: {\n * type: \"text\",\n * searchIndex: { name: \"search_title\", filterFields: [\"status\", \"author\"] },\n * }\n * // Generates: .searchIndex(\"search_title\", { searchField: \"title\", filterFields: [\"status\", \"author\"] })\n * ```\n */\n searchIndex?: {\n /** Search index name (must be unique within the collection). */\n name: string;\n /**\n * Fields to filter search results by.\n * String array — validated at runtime against collection field names.\n */\n filterFields: string[];\n };\n}\n\n// =============================================================================\n// CONCRETE FIELD TYPES\n// =============================================================================\n\n/** Text field definition. */\nexport interface TextFieldDef extends BaseField {\n readonly type: \"text\";\n /** Default value for new documents. */\n defaultValue?: string;\n /** Minimum character length. */\n minLength?: number;\n /** Maximum character length. */\n maxLength?: number;\n}\n\n/** Number field definition. */\nexport interface NumberFieldDef extends BaseField {\n readonly type: \"number\";\n /** Default value for new documents. */\n defaultValue?: number;\n /** Minimum allowed value. */\n min?: number;\n /** Maximum allowed value. */\n max?: number;\n /** Step increment for the input. */\n step?: number;\n}\n\n/** Checkbox field definition. */\nexport interface CheckboxFieldDef extends BaseField {\n readonly type: \"checkbox\";\n /** Default value for new documents. */\n defaultValue?: boolean;\n}\n\n/**\n * A single option in a select field.\n */\nexport interface SelectOption<T extends string = string> {\n /** The stored value. */\n readonly value: T;\n /** The display label shown in the dropdown. */\n readonly label: string;\n /** Optional badge color for the data table. Accepts a hex string (e.g. \"#3b82f6\"). */\n readonly badgeColor?: string;\n}\n\n/** Select field — single value variant. */\nexport interface SelectFieldSingle<T extends string = string> extends BaseField {\n readonly type: \"select\";\n /** The available options for this select field. */\n options: readonly SelectOption<T>[];\n /** Default value for new documents. */\n defaultValue?: T;\n hasMany?: false;\n}\n\n/** Select field — multi-value variant. */\nexport interface SelectFieldMany<T extends string = string> extends BaseField {\n readonly type: \"select\";\n /** The available options for this select field. */\n options: readonly SelectOption<T>[];\n /** Default value for new documents. */\n defaultValue?: T;\n /** Display labels for the field (singular/plural). */\n labels?: Labels;\n hasMany: true;\n}\n\n/** Select field definition with typed options. Discriminated on `hasMany`. */\nexport type SelectFieldDef<T extends string = string> =\n | SelectFieldSingle<T>\n | SelectFieldMany<T>;\n\n/** Date field definition. Stores epoch milliseconds. */\nexport interface DateFieldDef extends BaseField {\n readonly type: \"date\";\n /** Default value for new documents (epoch ms). */\n defaultValue?: number;\n}\n\n/** Image URL field definition. Stores a URL string, renders as thumbnail. */\nexport interface ImageUrlFieldDef extends BaseField {\n readonly type: \"imageUrl\";\n /** Default value for new documents. */\n defaultValue?: string;\n /** Width (px) of the image */\n width?: number;\n /** Height (px) of the image */\n height?: number;\n}\n\n/** Relationship field — single reference variant. */\nexport interface RelationshipFieldSingle extends BaseField {\n readonly type: \"relationship\";\n /** Target table name. */\n to: string;\n hasMany?: false;\n}\n\n/** Relationship field — multi-reference variant. */\nexport interface RelationshipFieldMany extends BaseField {\n readonly type: \"relationship\";\n /** Target table name. */\n to: string;\n /** Display labels for the field (singular/plural). */\n labels?: Labels;\n hasMany: true;\n}\n\n/** Relationship field definition. Discriminated on `hasMany`. */\nexport type RelationshipFieldDef = RelationshipFieldSingle | RelationshipFieldMany;\n\n/** Shared upload field properties. */\ninterface UploadFieldBase extends BaseField {\n readonly type: \"upload\";\n /** Target media collection slug. */\n to: string;\n /**\n * Accepted MIME types for file uploads.\n * Supports exact types (\"image/png\") and wildcards (\"image/*\").\n * When not set, all file types are accepted.\n */\n accept?: string[];\n /**\n * Maximum file size in bytes for uploads.\n * When not set, no size limit is enforced (beyond storage provider limits).\n */\n maxSize?: number;\n}\n\n/** Upload field — single reference variant. */\nexport interface UploadFieldSingle extends UploadFieldBase {\n hasMany?: false;\n}\n\n/** Upload field — multi-reference variant. */\nexport interface UploadFieldMany extends UploadFieldBase {\n /** Display labels for the field (singular/plural). */\n labels?: Labels;\n hasMany: true;\n}\n\n/**\n * Upload field definition. References a media collection document via `v.id()`.\n * Discriminated on `hasMany`.\n */\nexport type UploadFieldDef = UploadFieldSingle | UploadFieldMany;\n\n/** JSON field definition. Stores arbitrary data via `v.any()`. */\nexport interface JsonFieldDef extends BaseField {\n readonly type: \"json\";\n}\n\n/** Array field definition. Wraps an inner field in `v.array()`. */\nexport interface ArrayFieldDef extends BaseField {\n readonly type: \"array\";\n /** Display labels for the field (singular/plural). */\n labels?: Labels;\n /** The inner field type for array elements. */\n field: VexField;\n /** Minimum number of items. */\n min?: number;\n /** Maximum number of items. */\n max?: number;\n}\n\nimport type { VexEditorAdapter, RichTextDocument } from \"./editor\";\n\n/** Rich text field definition. Stores Plate/Slate JSON via `v.any()`. */\nexport interface RichTextFieldDef extends BaseField {\n readonly type: \"richtext\";\n /**\n * Editor adapter override for this specific field.\n * If not set, uses the global editor from `VexConfig.editor`.\n */\n editor?: VexEditorAdapter;\n /**\n * Media collection slug for image uploads.\n * When set, the editor can pick images from the specified media collection,\n * and paste/drop image uploads are auto-saved to this collection.\n * When not set, images can only be inserted by URL.\n */\n mediaCollection?: string;\n}\n\n/**\n * UI field definition. Non-persisted — renders a custom component only.\n * Skipped during schema generation, form validation, and column generation.\n * Requires admin.components.Field to be set.\n */\nexport interface UIFieldDef extends BaseField {\n readonly type: \"ui\";\n /**\n * Admin config — components.Field is required for ui fields.\n */\n admin: FieldAdminConfig & {\n components: {\n Field: ComponentType<FieldComponentProps>;\n };\n };\n}\n\n// =============================================================================\n// BLOCK TYPES\n// =============================================================================\n\n/**\n * Admin configuration specific to block definitions.\n */\nexport interface BlockAdminConfig {\n /** Icon identifier for the block picker UI (e.g., \"layout-template\"). */\n icon?: string;\n /** Custom admin components for this block (future — Spec 09b). */\n components?: {\n Editor?: ComponentType<any>;\n };\n}\n\n/**\n * A block definition created by `defineBlock()`.\n * Blocks are reusable field groups composed into ordered lists via the `blocks()` field type.\n *\n * @example\n * ```ts\n * const heroBlock = defineBlock({\n * slug: \"hero\",\n * label: \"Hero Section\",\n * fields: { heading: text({ required: true }), subheading: text() },\n * })\n * ```\n */\nexport interface BlockDef<TFields extends Record<string, VexField> = Record<string, VexField>> {\n /** Unique identifier for this block type. Used as the `blockType` discriminant in stored data. */\n readonly slug: string;\n /** Display label for the block in the admin picker. */\n label: string;\n /** Field definitions for this block's data shape. */\n fields: TFields;\n /** Admin UI configuration. */\n admin?: BlockAdminConfig;\n /**\n * TypeScript interface name used in generated `vex.types.ts`.\n * If not set, auto-generated from slug via PascalCase conversion.\n * @example \"HeroBlock\"\n */\n interfaceName?: string;\n}\n\n/** Reserved field names that cannot be used in block field definitions. */\nexport const RESERVED_BLOCK_FIELD_NAMES = [\"blockType\", \"blockName\", \"_key\"] as const;\n\n/** Blocks field definition. Stores an ordered array of block instances. */\nexport interface BlocksFieldDef extends BaseField {\n readonly type: \"blocks\";\n /** The block definitions allowed in this field. */\n blocks: BlockDef[];\n /** Display labels for the field (singular/plural). */\n labels?: Labels;\n /** Minimum number of blocks. */\n min?: number;\n /** Maximum number of blocks. */\n max?: number;\n}\n\n// =============================================================================\n// UTILITY TYPES\n// =============================================================================\n\n/**\n * Distributive version of `Omit` that preserves union branches.\n * Standard `Omit` collapses unions; this applies `Omit` to each branch individually.\n */\nexport type DistributiveOmit<T, K extends PropertyKey> = T extends unknown\n ? Omit<T, K>\n : never;\n\n// =============================================================================\n// DISCRIMINATED UNION\n// =============================================================================\n\n/**\n * Discriminated union of all field types. Switch on `field.type` to narrow.\n *\n * @example\n * ```ts\n * function handle(field: VexField) {\n * switch (field.type) {\n * case \"text\":\n * field.maxLength; // TextFieldDef ✓\n * break;\n * case \"select\":\n * field.options; // SelectFieldDef ✓\n * break;\n * }\n * }\n * ```\n */\nexport type VexField =\n | TextFieldDef\n | NumberFieldDef\n | CheckboxFieldDef\n | SelectFieldDef<string>\n | DateFieldDef\n | ImageUrlFieldDef\n | RelationshipFieldDef\n | UploadFieldDef\n | JsonFieldDef\n | ArrayFieldDef\n | RichTextFieldDef\n | UIFieldDef\n | BlocksFieldDef;\n\n// =============================================================================\n// TYPE INFERENCE\n// =============================================================================\n\n/**\n * Infer the TypeScript value type from a VexField.\n * Uses the `type` discriminant and field options to determine the type.\n */\nexport type InferFieldType<F extends VexField> = F extends { type: \"text\" }\n ? string\n : F extends { type: \"number\" }\n ? number\n : F extends { type: \"checkbox\" }\n ? boolean\n : F extends { type: \"select\"; hasMany: true }\n ? string[]\n : F extends { type: \"select\" }\n ? string\n : F extends { type: \"date\" }\n ? number\n : F extends { type: \"imageUrl\" }\n ? string\n : F extends { type: \"relationship\"; hasMany: true }\n ? string[]\n : F extends { type: \"relationship\" }\n ? string\n : F extends { type: \"upload\"; hasMany: true }\n ? string[]\n : F extends { type: \"upload\" }\n ? string\n : F extends { type: \"json\" }\n ? unknown\n : F extends { type: \"richtext\" }\n ? RichTextDocument\n : F extends { type: \"blocks\" }\n ? Array<InferBlockUnion<F>>\n : F extends { type: \"array\" }\n ? unknown[]\n : F extends { type: \"ui\" }\n ? never\n : never;\n\n/**\n * Infer the discriminated union type for a blocks field.\n * Each block becomes an object type with `blockType` literal + `_key` + its field types.\n */\nexport type InferBlockUnion<F extends VexField> = F extends BlocksFieldDef\n ? F[\"blocks\"][number] extends infer B\n ? B extends BlockDef<infer TFields>\n ? { blockType: B[\"slug\"]; blockName?: string; _key: string } & {\n [K in keyof TFields]: InferFieldType<TFields[K] & VexField>;\n }\n : never\n : never\n : never;\n\n/**\n * Infer the document type from a record of fields.\n *\n * @example\n * ```ts\n * type Doc = InferFieldsType<{\n * title: { type: \"text\"; required: true };\n * count: { type: \"number\" };\n * }>;\n * // { title: string; count: number }\n * ```\n */\nexport type InferFieldsType<F extends Record<string, VexField>> = {\n [K in keyof F]: InferFieldType<F[K] & VexField>;\n};\n","import type { BlockDef, VexField } from \"../types\";\nimport { RESERVED_BLOCK_FIELD_NAMES } from \"../types/fields\";\nimport { VexBlockValidationError } from \"../errors\";\n\n/**\n * Define a block type for use with the `blocks()` field.\n *\n * @param props.slug - Unique identifier for this block type\n * @param props.label - Display label for the admin picker\n * @param props.fields - Field definitions for this block's data shape\n * @param props.admin - Optional admin UI configuration (icon, custom components)\n * @returns A BlockDef object\n *\n * @throws VexBlockValidationError if slug is empty or contains invalid characters\n * @throws VexBlockValidationError if any field name is reserved (blockType, _key)\n *\n * @example\n * ```ts\n * const heroBlock = defineBlock({\n * slug: \"hero\",\n * label: \"Hero Section\",\n * fields: {\n * heading: text({ required: true }),\n * subheading: text(),\n * },\n * })\n * ```\n */\nexport function defineBlock<TFields extends Record<string, VexField>>(props: {\n slug: string;\n label: string;\n fields: TFields;\n admin?: BlockDef[\"admin\"];\n interfaceName?: string;\n}): BlockDef<TFields> {\n if (!props.slug || !/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(props.slug)) {\n throw new VexBlockValidationError(\n props.slug || \"(empty)\",\n `Invalid block slug \"${props.slug}\". Slugs must start with a letter and contain only letters, numbers, hyphens, and underscores.`,\n );\n }\n\n for (const fieldName of Object.keys(props.fields)) {\n if ((RESERVED_BLOCK_FIELD_NAMES as readonly string[]).includes(fieldName)) {\n throw new VexBlockValidationError(\n props.slug,\n `Field name \"${fieldName}\" is reserved in block definitions. Reserved names: ${RESERVED_BLOCK_FIELD_NAMES.join(\", \")}`,\n );\n }\n }\n\n return {\n slug: props.slug,\n label: props.label,\n fields: props.fields,\n admin: props.admin,\n interfaceName: props.interfaceName,\n };\n}\n","/**\n * Convert a slug string to a PascalCase interface name.\n *\n * @param props.slug - The slug to convert (e.g., \"blog-posts\", \"new_block\", \"media\")\n * @returns PascalCase string (e.g., \"BlogPosts\", \"NewBlock\", \"Media\")\n */\nexport function slugToInterfaceName(props: { slug: string }): string {\n return props.slug\n .replace(/[-_]+/g, \" \")\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .split(/\\s+/)\n .filter(Boolean)\n .map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1).toLowerCase())\n .join(\"\");\n}\n","import type { VexField } from \"../types\";\nimport { slugToInterfaceName } from \"./slugToInterfaceName\";\n\n/**\n * Convert a VexField to its TypeScript type string for generated interfaces.\n *\n * @param props.field - The field definition\n * @param props.blockInterfaceNames - Map of block slug → interface name (for blocks fields)\n * @returns TypeScript type string (e.g., \"string\", \"number\", \"'draft' | 'published'\", \"HeroBlock[]\")\n */\nexport function fieldToTypeString(props: {\n field: VexField;\n blockInterfaceNames?: Map<string, string>;\n}): string {\n switch (props.field.type) {\n case \"text\":\n return \"string\";\n case \"number\":\n return \"number\";\n case \"checkbox\":\n return \"boolean\";\n case \"date\":\n return \"number\";\n case \"imageUrl\":\n return \"string\";\n case \"json\":\n return \"Record<string, unknown>\";\n case \"richtext\":\n return \"RichTextDocument\";\n case \"ui\":\n return \"never\";\n\n case \"select\": {\n const values = props.field.options.map((o) => o.value);\n if (values.length === 0) return \"string\";\n const union = values.map((v) => `'${v}'`).join(\" | \");\n if (props.field.hasMany) {\n return `(${union})[]`;\n }\n return union;\n }\n\n case \"relationship\": {\n const idType = `Id<'${props.field.to}'>`;\n return props.field.hasMany ? `${idType}[]` : idType;\n }\n\n case \"upload\": {\n const idType = `Id<'${props.field.to}'>`;\n return props.field.hasMany ? `${idType}[]` : idType;\n }\n\n case \"array\": {\n const inner = fieldToTypeString({\n field: props.field.field,\n blockInterfaceNames: props.blockInterfaceNames,\n });\n const needsParens = inner.includes(\"|\");\n return needsParens ? `(${inner})[]` : `${inner}[]`;\n }\n\n case \"blocks\": {\n const names = props.field.blocks.map((b) => {\n if (props.blockInterfaceNames?.has(b.slug)) {\n return props.blockInterfaceNames.get(b.slug)!;\n }\n return b.interfaceName ?? slugToInterfaceName({ slug: b.slug });\n });\n if (names.length === 0) return \"unknown[]\";\n if (names.length === 1) return `${names[0]}[]`;\n return `(${names.join(\" | \")})[]`;\n }\n\n default:\n return \"unknown\";\n }\n}\n","import type { VexConfig, VexField, BlockDef } from \"../types\";\nimport { mergeAuthCollectionWithUserCollection } from \"../valueTypes/merge\";\nimport { LOCKED_MEDIA_FIELDS, OVERRIDABLE_MEDIA_FIELDS } from \"../types/media\";\nimport { fieldToTypeString } from \"./fieldToTypeString\";\nimport { slugToInterfaceName } from \"./slugToInterfaceName\";\nimport { VexError } from \"../errors\";\n\n/**\n * Generate the complete TypeScript source for `vex.types.ts`.\n *\n * @param props.config - The resolved VexConfig\n * @returns TypeScript source code string\n */\nexport function generateVexTypes(props: { config: VexConfig }): string {\n const config = props.config;\n const parts: string[] = [];\n\n // ── 1. Collect all blocks and build name maps ──\n\n const blocksBySlug = new Map<string, BlockDef>();\n const blockInterfaceNames = new Map<string, string>();\n\n function collectBlocks(fields: Record<string, VexField>) {\n for (const field of Object.values(fields)) {\n if (field.type === \"blocks\") {\n for (const block of field.blocks) {\n if (!blocksBySlug.has(block.slug)) {\n blocksBySlug.set(block.slug, block);\n collectBlocks(block.fields as Record<string, VexField>);\n }\n }\n }\n }\n }\n\n for (const col of config.collections) {\n collectBlocks(col.fields as Record<string, VexField>);\n }\n if (config.media?.collections) {\n for (const col of config.media.collections) {\n collectBlocks(col.fields as Record<string, VexField>);\n }\n }\n for (const g of config.globals) {\n collectBlocks(g.fields as Record<string, VexField>);\n }\n\n for (const [slug, block] of blocksBySlug) {\n blockInterfaceNames.set(\n slug,\n block.interfaceName ?? slugToInterfaceName({ slug }),\n );\n }\n\n // ── 2. Build collection & global name maps, check for duplicates ──\n\n const allNames = new Map<string, string>(); // name → source description\n\n function registerName(name: string, source: string) {\n if (allNames.has(name)) {\n throw new VexError(\n `Duplicate interface name \"${name}\" — used by ${allNames.get(name)} and ${source}. ` +\n `Set a unique \\`interfaceName\\` on one of them.`,\n );\n }\n allNames.set(name, source);\n }\n\n const collectionNames = new Map<string, string>(); // slug → interfaceName\n for (const col of config.collections) {\n const name = col.interfaceName ?? slugToInterfaceName({ slug: col.slug });\n registerName(name, `collection \"${col.slug}\"`);\n collectionNames.set(col.slug, name);\n }\n\n if (config.media?.collections) {\n for (const col of config.media.collections) {\n const name = col.interfaceName ?? slugToInterfaceName({ slug: col.slug });\n registerName(name, `media collection \"${col.slug}\"`);\n collectionNames.set(col.slug, name);\n }\n }\n\n // Auth-only collections (not matched to user collections)\n const authCollectionMap = new Map(\n config.auth.collections.map((c) => [c.slug, c]),\n );\n const userCollectionSlugs = new Set(config.collections.map((c) => c.slug));\n const mediaSlugs = new Set(\n (config.media?.collections ?? []).map((c) => c.slug),\n );\n for (const authCol of config.auth.collections) {\n if (!userCollectionSlugs.has(authCol.slug) && !mediaSlugs.has(authCol.slug)) {\n const name = authCol.interfaceName ?? slugToInterfaceName({ slug: authCol.slug });\n registerName(name, `auth collection \"${authCol.slug}\"`);\n collectionNames.set(authCol.slug, name);\n }\n }\n\n const globalNames = new Map<string, string>();\n for (const g of config.globals) {\n const name = g.interfaceName ?? slugToInterfaceName({ slug: g.slug });\n registerName(name, `global \"${g.slug}\"`);\n globalNames.set(g.slug, name);\n }\n\n for (const [slug, name] of blockInterfaceNames) {\n registerName(name, `block \"${slug}\"`);\n }\n\n // ── 3. Check if Id import is needed ──\n\n let needsIdImport = false;\n function checkForIdFields(fields: Record<string, VexField>) {\n for (const field of Object.values(fields)) {\n if (field.type === \"relationship\" || field.type === \"upload\") {\n needsIdImport = true;\n }\n }\n }\n for (const col of config.collections) {\n checkForIdFields(col.fields as Record<string, VexField>);\n }\n if (config.media?.collections) {\n for (const col of config.media.collections) {\n checkForIdFields(col.fields as Record<string, VexField>);\n }\n }\n for (const g of config.globals) {\n checkForIdFields(g.fields as Record<string, VexField>);\n }\n for (const block of blocksBySlug.values()) {\n checkForIdFields(block.fields as Record<string, VexField>);\n }\n // Collections always have _id which is Id<slug>, so always need it\n if (config.collections.length > 0 || (config.media?.collections?.length ?? 0) > 0 || config.globals.length > 0) {\n needsIdImport = true;\n }\n\n // Check if RichTextDocument import is needed\n let needsRichTextImport = false;\n function checkForRichTextFields(fields: Record<string, VexField>) {\n for (const field of Object.values(fields)) {\n if (field.type === \"richtext\") {\n needsRichTextImport = true;\n }\n }\n }\n for (const col of config.collections) {\n checkForRichTextFields(col.fields as Record<string, VexField>);\n }\n if (config.media?.collections) {\n for (const col of config.media.collections) {\n checkForRichTextFields(col.fields as Record<string, VexField>);\n }\n }\n for (const g of config.globals) {\n checkForRichTextFields(g.fields as Record<string, VexField>);\n }\n for (const block of blocksBySlug.values()) {\n checkForRichTextFields(block.fields as Record<string, VexField>);\n }\n\n // ── 4. File header ──\n\n parts.push(\"// ⚠️ AUTO-GENERATED BY VEX CMS — DO NOT EDIT ⚠️\");\n parts.push(\"\");\n if (needsIdImport) {\n parts.push(\"import type { Id } from './_generated/dataModel';\");\n }\n if (needsRichTextImport) {\n parts.push(\"import type { RichTextDocument } from '@vexcms/core';\");\n }\n if (needsIdImport || needsRichTextImport) {\n parts.push(\"\");\n }\n\n // ── 5. Block interfaces ──\n\n const sortedBlockSlugs = [...blocksBySlug.keys()].sort();\n for (const slug of sortedBlockSlugs) {\n const block = blocksBySlug.get(slug)!;\n const name = blockInterfaceNames.get(slug)!;\n parts.push(generateBlockInterface({ block, name, blockInterfaceNames }));\n parts.push(\"\");\n }\n\n // ── 6. Collection interfaces ──\n\n for (const col of config.collections) {\n const name = collectionNames.get(col.slug)!;\n const authCol = authCollectionMap.get(col.slug);\n let fields: Record<string, VexField>;\n\n if (authCol) {\n const merged = mergeAuthCollectionWithUserCollection({\n authCollection: authCol,\n userCollection: col,\n });\n fields = merged.fields;\n } else {\n fields = col.fields as Record<string, VexField>;\n }\n\n const isVersioned = !!(col as any).versions?.drafts;\n parts.push(\n generateCollectionInterface({\n name,\n slug: col.slug,\n fields,\n isVersioned,\n blockInterfaceNames,\n }),\n );\n parts.push(\"\");\n }\n\n // Auth-only collections\n for (const authCol of config.auth.collections) {\n if (userCollectionSlugs.has(authCol.slug) || mediaSlugs.has(authCol.slug)) continue;\n const name = collectionNames.get(authCol.slug)!;\n parts.push(\n generateCollectionInterface({\n name,\n slug: authCol.slug,\n fields: authCol.fields as Record<string, VexField>,\n isVersioned: false,\n blockInterfaceNames,\n }),\n );\n parts.push(\"\");\n }\n\n // Media collections\n if (config.media?.collections) {\n for (const col of config.media.collections) {\n const name = collectionNames.get(col.slug)!;\n parts.push(\n generateMediaCollectionInterface({\n name,\n slug: col.slug,\n userFields: col.fields as Record<string, VexField>,\n blockInterfaceNames,\n }),\n );\n parts.push(\"\");\n }\n }\n\n // ── 7. Global interfaces ──\n\n for (const g of config.globals) {\n const name = globalNames.get(g.slug)!;\n parts.push(\n generateGlobalInterface({\n name,\n slug: g.slug,\n fields: g.fields as Record<string, VexField>,\n blockInterfaceNames,\n }),\n );\n parts.push(\"\");\n }\n\n // ── 8. Barrel types ──\n\n if (collectionNames.size > 0) {\n const entries = [...collectionNames.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([slug, name]) => ` ${slug}: ${name};`)\n .join(\"\\n\");\n parts.push(`export interface VexCollectionTypes {\\n${entries}\\n}`);\n parts.push(\"\");\n }\n\n if (globalNames.size > 0) {\n const entries = [...globalNames.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([slug, name]) => ` ${slug}: ${name};`)\n .join(\"\\n\");\n parts.push(`export interface VexGlobalTypes {\\n${entries}\\n}`);\n parts.push(\"\");\n }\n\n return parts.join(\"\\n\");\n}\n\n// ── Helpers ──\n\nfunction generateBlockInterface(props: {\n block: BlockDef;\n name: string;\n blockInterfaceNames: Map<string, string>;\n}): string {\n const lines: string[] = [];\n lines.push(`export interface ${props.name} {`);\n lines.push(` blockType: '${props.block.slug}';`);\n lines.push(` blockName?: string;`);\n lines.push(` _key: string;`);\n\n for (const [fieldName, field] of Object.entries(props.block.fields)) {\n const f = field as VexField;\n if (f.type === \"ui\") continue;\n const label = f.label;\n if (label) lines.push(` /** ${label} */`);\n const optional = f.required ? \"\" : \"?\";\n const typeStr = fieldToTypeString({\n field: f,\n blockInterfaceNames: props.blockInterfaceNames,\n });\n lines.push(` ${fieldName}${optional}: ${typeStr};`);\n }\n\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nfunction generateCollectionInterface(props: {\n name: string;\n slug: string;\n fields: Record<string, VexField>;\n isVersioned: boolean;\n blockInterfaceNames: Map<string, string>;\n}): string {\n const lines: string[] = [];\n lines.push(`export interface ${props.name} {`);\n lines.push(` _id: Id<'${props.slug}'>;`);\n lines.push(` _creationTime: number;`);\n\n if (props.isVersioned) {\n lines.push(` vex_status?: 'draft' | 'published';`);\n lines.push(` vex_version?: number;`);\n lines.push(` vex_publishedAt?: number;`);\n }\n\n for (const [fieldName, field] of Object.entries(props.fields)) {\n const f = field as VexField;\n if (f.type === \"ui\") continue;\n const label = f.label;\n if (label) lines.push(` /** ${label} */`);\n const optional = f.required ? \"\" : \"?\";\n const typeStr = fieldToTypeString({\n field: f,\n blockInterfaceNames: props.blockInterfaceNames,\n });\n lines.push(` ${fieldName}${optional}: ${typeStr};`);\n }\n\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nfunction generateMediaCollectionInterface(props: {\n name: string;\n slug: string;\n userFields: Record<string, VexField>;\n blockInterfaceNames: Map<string, string>;\n}): string {\n const lines: string[] = [];\n lines.push(`export interface ${props.name} {`);\n lines.push(` _id: Id<'${props.slug}'>;`);\n lines.push(` _creationTime: number;`);\n\n // Locked fields\n lines.push(` storageId: string;`);\n lines.push(` filename: string;`);\n lines.push(` mimeType: string;`);\n lines.push(` size: number;`);\n\n // Overridable fields (optional unless user defines them)\n lines.push(` url?: string;`);\n lines.push(` width?: number;`);\n lines.push(` height?: number;`);\n\n // User-defined fields\n const lockedSet = new Set([...LOCKED_MEDIA_FIELDS, ...OVERRIDABLE_MEDIA_FIELDS]);\n for (const [fieldName, field] of Object.entries(props.userFields)) {\n if (lockedSet.has(fieldName as any)) continue;\n const f = field as VexField;\n if (f.type === \"ui\") continue;\n const label = f.label;\n if (label) lines.push(` /** ${label} */`);\n const optional = f.required ? \"\" : \"?\";\n const typeStr = fieldToTypeString({\n field: f,\n blockInterfaceNames: props.blockInterfaceNames,\n });\n lines.push(` ${fieldName}${optional}: ${typeStr};`);\n }\n\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nfunction generateGlobalInterface(props: {\n name: string;\n slug: string;\n fields: Record<string, VexField>;\n blockInterfaceNames: Map<string, string>;\n}): string {\n const lines: string[] = [];\n lines.push(`export interface ${props.name} {`);\n lines.push(` _id: Id<'vex_globals'>;`);\n lines.push(` _creationTime: number;`);\n lines.push(` vexGlobalSlug: '${props.slug}';`);\n\n for (const [fieldName, field] of Object.entries(props.fields)) {\n const f = field as VexField;\n if (f.type === \"ui\") continue;\n const label = f.label;\n if (label) lines.push(` /** ${label} */`);\n const optional = f.required ? \"\" : \"?\";\n const typeStr = fieldToTypeString({\n field: f,\n blockInterfaceNames: props.blockInterfaceNames,\n });\n lines.push(` ${fieldName}${optional}: ${typeStr};`);\n }\n\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n","/**\n * System field names injected into versioned collection schemas.\n * These are excluded from user-editable fields and version snapshots.\n */\nexport const VERSION_SYSTEM_FIELDS = [\n \"vex_status\",\n \"vex_version\",\n \"vex_publishedAt\",\n] as const;\n\n/**\n * All system fields (Convex built-in + versioning) to strip when\n * extracting user content from a document.\n */\nexport const ALL_SYSTEM_FIELDS = new Set([\n \"_id\",\n \"_creationTime\",\n ...VERSION_SYSTEM_FIELDS,\n]);\n\n/**\n * Default max versions to keep per document.\n */\nexport const DEFAULT_MAX_VERSIONS_PER_DOC = 100;\n\n/**\n * Default autosave interval in milliseconds.\n */\nexport const DEFAULT_AUTOSAVE_INTERVAL = 2000;\n","import { ALL_SYSTEM_FIELDS } from \"./constants\";\n\n/**\n * Extracts user-defined fields from a document, stripping all\n * system fields (_id, _creationTime, _status, _version, _publishedAt).\n *\n * Used to create version snapshots that contain only content fields.\n *\n * @param props.document - The full document including system fields\n * @returns A new object with only user-defined fields\n */\nexport function extractUserFields(props: {\n document: Record<string, unknown>;\n}): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props.document)) {\n if (!ALL_SYSTEM_FIELDS.has(key)) {\n result[key] = value;\n }\n }\n return result;\n}\n","import type { LivePreviewConfig } from \"../types/livePreview\";\n\n/**\n * Resolves the preview URL from a collection's live preview config.\n *\n * @param props.config - The collection's livePreview config\n * @param props.doc - The current document data (must include `_id`)\n * @param props.fallbackURL - URL to return if the function throws\n * @returns The resolved preview URL\n * @throws If the resolved URL is empty and no fallbackURL is provided\n */\nexport function resolvePreviewURL(props: {\n config: LivePreviewConfig;\n doc: { _id: string; [key: string]: any };\n fallbackURL?: string;\n}): string {\n if (typeof props.config.url === \"string\") {\n return props.config.url;\n }\n\n try {\n const result = props.config.url(props.doc);\n if (!result) {\n throw new Error(\n `Live preview URL resolved to empty string for document ${props.doc._id}`,\n );\n }\n return result;\n } catch (error) {\n if (props.fallbackURL !== undefined) {\n return props.fallbackURL;\n }\n throw error;\n }\n}\n","import type { LivePreviewConfig } from \"../types/livePreview\";\n\n/**\n * Determines if the preview iframe URL should be recomputed.\n *\n * @param props.config - The collection's livePreview config\n * @param props.changedFields - Set of field names that changed in the save\n * @returns true if the URL should be recomputed\n */\nexport function shouldReloadURL(props: {\n config: LivePreviewConfig;\n changedFields: string[];\n}): boolean {\n if (props.config.reloadOnFields === undefined) {\n return true;\n }\n\n if (props.config.reloadOnFields.length === 0) {\n return false;\n }\n\n return props.changedFields.some((field) =>\n props.config.reloadOnFields!.includes(field),\n );\n}\n","import type { LivePreviewBreakpoint } from \"../types/livePreview\";\n\nexport const DEFAULT_BREAKPOINTS: LivePreviewBreakpoint[] = [\n { label: \"Mobile\", width: 375, height: 667, icon: \"smartphone\" },\n { label: \"Tablet\", width: 768, height: 1024, icon: \"tablet\" },\n { label: \"Laptop\", width: 1280, height: 800, icon: \"laptop\" },\n { label: \"Desktop\", width: 1920, height: 1080, icon: \"monitor\" },\n];\n\n/**\n * Debounce interval for writing preview snapshots on form changes.\n */\nexport const PREVIEW_SNAPSHOT_DEBOUNCE_MS = 500;\n","import type { GenericMutationCtx, GenericQueryCtx, GenericDataModel } from \"convex/server\";\n\n/**\n * Upserts a preview snapshot for a document.\n * If a snapshot already exists for this collection+document, it is updated in place.\n * If not, a new entry is created.\n *\n * @param props.ctx - Convex mutation context\n * @param props.collection - Collection slug\n * @param props.documentId - Document ID\n * @param props.snapshot - Complete field snapshot from the form\n */\nexport async function upsertPreviewSnapshot<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>;\n collection: string;\n documentId: string;\n snapshot: Record<string, unknown>;\n}): Promise<void> {\n const existing = await (props.ctx.db as any)\n .query(\"vex_versions\")\n .withIndex(\"by_document_status\", (q: any) =>\n q\n .eq(\"collection\", props.collection)\n .eq(\"documentId\", props.documentId)\n .eq(\"status\", \"previewSnapshot\"),\n )\n .first();\n\n if (existing) {\n await (props.ctx.db as any).patch(existing._id, {\n snapshot: props.snapshot,\n createdAt: Date.now(),\n });\n } else {\n await (props.ctx.db as any).insert(\"vex_versions\", {\n collection: props.collection,\n documentId: props.documentId,\n version: 0,\n status: \"previewSnapshot\",\n snapshot: props.snapshot,\n createdAt: Date.now(),\n createdBy: undefined,\n isAutosave: false,\n restoredFrom: undefined,\n });\n }\n}\n\n/**\n * Deletes the preview snapshot for a document.\n * Called after a successful save to clean up transient state.\n *\n * @param props.ctx - Convex mutation context\n * @param props.collection - Collection slug\n * @param props.documentId - Document ID\n */\nexport async function deletePreviewSnapshot<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>;\n collection: string;\n documentId: string;\n}): Promise<void> {\n const entries = await (props.ctx.db as any)\n .query(\"vex_versions\")\n .withIndex(\"by_document_status\", (q: any) =>\n q\n .eq(\"collection\", props.collection)\n .eq(\"documentId\", props.documentId)\n .eq(\"status\", \"previewSnapshot\"),\n )\n .collect();\n\n for (const entry of entries) {\n await (props.ctx.db as any).delete(entry._id);\n }\n}\n\n/**\n * Gets the preview data for a document.\n *\n * Lookup order:\n * 1. Preview snapshot (transient, written by admin form on each change)\n * 2. Latest version from vex_versions (draft or published, excluding autosave/previewSnapshot)\n * 3. null (fall back to main document)\n *\n * @param props.ctx - Convex query context\n * @param props.collection - Collection slug\n * @param props.documentId - Document ID\n * @returns The snapshot data, or null if no preview/version exists\n */\nexport async function getPreviewSnapshot<DataModel extends GenericDataModel>(props: {\n ctx: GenericQueryCtx<DataModel>;\n collection: string;\n documentId: string;\n}): Promise<Record<string, unknown> | null> {\n // 1. Check for a transient preview snapshot (written by admin form edits)\n const previewEntry = await (props.ctx.db as any)\n .query(\"vex_versions\")\n .withIndex(\"by_document_status\", (q: any) =>\n q\n .eq(\"collection\", props.collection)\n .eq(\"documentId\", props.documentId)\n .eq(\"status\", \"previewSnapshot\"),\n )\n .first();\n\n if (previewEntry) {\n return previewEntry.snapshot as Record<string, unknown>;\n }\n\n // 2. Fall back to the latest version (draft or published)\n const allVersions = await (props.ctx.db as any)\n .query(\"vex_versions\")\n .withIndex(\"by_document\", (q: any) =>\n q.eq(\"collection\", props.collection).eq(\"documentId\", props.documentId),\n )\n .collect();\n\n let latestVersion: Record<string, unknown> | null = null;\n let maxVersion = -1;\n for (const v of allVersions) {\n if (v.status === \"previewSnapshot\" || v.status === \"autosave\") continue;\n const ver = v.version as number;\n if (ver > maxVersion) {\n maxVersion = ver;\n latestVersion = v;\n }\n }\n\n if (latestVersion) {\n return (latestVersion as any).snapshot as Record<string, unknown>;\n }\n\n // 3. No versions at all — caller will use the main document\n return null;\n}\n","import {\n queryGeneric,\n type QueryBuilder,\n type GenericQueryCtx,\n type GenericDataModel,\n type RegisteredQuery,\n} from \"convex/server\";\nimport { v, type ObjectType, type PropertyValidators } from \"convex/values\";\n\n/**\n * Drafts mode for vexQuery.\n * - \"snapshot\": Fetch the transient preview snapshot (written by admin on form changes)\n * - true: Fetch the latest draft version (from versioning system)\n * - false: Fetch published content only\n */\nexport type VexDraftsMode = \"snapshot\" | boolean;\n\n/**\n * Context passed to vexQuery handlers.\n * Extends the standard Convex QueryCtx with draft-awareness.\n */\nexport interface VexQueryCtx<DataModel extends GenericDataModel = GenericDataModel>\n extends GenericQueryCtx<DataModel> {\n /**\n * The resolved drafts mode.\n * - \"snapshot\": caller wants preview snapshot data\n * - true: caller wants latest draft version\n * - false: caller wants published content only\n *\n * Defaults to \"snapshot\" when not explicitly passed by the caller.\n */\n drafts: VexDraftsMode;\n}\n\nfunction wrapHandler<DataModel extends GenericDataModel, Args extends PropertyValidators, Output>(\n handler: (ctx: VexQueryCtx<DataModel>, args: ObjectType<Args>) => Output | Promise<Output>,\n) {\n return async (ctx: GenericQueryCtx<any>, args: any): Promise<Awaited<Output>> => {\n const { _vexDrafts, ...userArgs } = args;\n\n const drafts: VexDraftsMode = _vexDrafts !== undefined\n ? (_vexDrafts as VexDraftsMode)\n : \"snapshot\";\n\n const vexCtx = Object.assign(\n Object.create(Object.getPrototypeOf(ctx)),\n ctx,\n { drafts },\n ) as VexQueryCtx<DataModel>;\n\n return handler(vexCtx, userArgs as ObjectType<Args>) as Promise<Awaited<Output>>;\n };\n}\n\n/**\n * Create a typed vexQuery builder from your project's query builder.\n *\n * Call this once in your project to get a `vexQuery` function that\n * preserves full return type inference from your DataModel.\n *\n * @example\n * ```ts\n * // convex/vex/helpers.ts\n * import { createVexQuery } from \"@vexcms/core\";\n * import { query } from \"../_generated/server\";\n *\n * export const vexQuery = createVexQuery(query);\n * ```\n *\n * Then use it in your query files:\n * ```ts\n * // convex/pages.ts\n * import { vexQuery } from \"./vex/helpers\";\n * import { getPreviewSnapshot } from \"@vexcms/core\";\n *\n * export const getBySlug = vexQuery({\n * args: { slug: v.string() },\n * handler: async (ctx, args) => {\n * const page = await ctx.db\n * .query(\"pages\")\n * .withIndex(\"by_slug\", (q) => q.eq(\"slug\", args.slug))\n * .first();\n * if (!page) return null;\n * if (ctx.drafts === \"snapshot\") {\n * const snapshot = await getPreviewSnapshot({ ctx, collection: \"pages\", documentId: page._id });\n * if (snapshot) return { ...page, ...snapshot };\n * }\n * return page;\n * },\n * });\n * ```\n */\nexport function createVexQuery<DataModel extends GenericDataModel>(\n _queryBuilder: QueryBuilder<DataModel, \"public\">,\n) {\n return <Args extends PropertyValidators, Output>(props: {\n args: Args;\n handler: (\n ctx: VexQueryCtx<DataModel>,\n args: ObjectType<Args>,\n ) => Output | Promise<Output>;\n }): RegisteredQuery<\"public\", ObjectType<Args & { _vexDrafts: typeof v.optional<any> }>, Awaited<Output>> => {\n const mergedArgs = {\n ...props.args,\n _vexDrafts: v.optional(v.union(v.literal(\"snapshot\"), v.boolean())),\n };\n\n return queryGeneric({\n args: mergedArgs,\n handler: wrapHandler<DataModel, Args, Output>(props.handler),\n }) as RegisteredQuery<\"public\", ObjectType<Args & { _vexDrafts: typeof v.optional<any> }>, Awaited<Output>>;\n };\n}\n\n/**\n * Generic vexQuery for use without project-specific types.\n * Prefer `createVexQuery(query)` for full type inference.\n *\n * @deprecated Use `createVexQuery(query)` instead for proper return type inference.\n */\nexport function vexQuery<Args extends PropertyValidators, Output>(props: {\n args: Args;\n handler: (\n ctx: VexQueryCtx,\n args: ObjectType<Args>,\n ) => Output | Promise<Output>;\n}): RegisteredQuery<\"public\", ObjectType<Args & { _vexDrafts: typeof v.optional<any> }>, Awaited<Output>> {\n const mergedArgs = {\n ...props.args,\n _vexDrafts: v.optional(v.union(v.literal(\"snapshot\"), v.boolean())),\n };\n\n return queryGeneric({\n args: mergedArgs,\n handler: wrapHandler(props.handler),\n }) as RegisteredQuery<\"public\", ObjectType<Args & { _vexDrafts: typeof v.optional<any> }>, Awaited<Output>>;\n}\n","import type {\n GenericDataModel,\n GenericMutationCtx,\n GenericQueryCtx,\n PaginationOptions,\n TableNamesInDataModel,\n} from \"convex/server\"\n\nimport { ConvexError } from \"convex/values\"\nimport { generateFormSchema } from \"../../formSchema/generateFormSchema\"\nimport { getPreviewSnapshot } from \"../previewSnapshot\"\nimport type { VexField } from \"../../types\"\nimport type { CollectionKind } from \"../../config/findCollectionBySlug\"\n\nasync function resolveStorageUrl(\n ctx: { storage: { getUrl: (id: any) => Promise<string | null> } },\n doc: any,\n) {\n if (doc?.storageId && (!doc.url || doc.url === \"\")) {\n const url = await ctx.storage.getUrl(doc.storageId)\n if (url) return { ...doc, url }\n }\n return doc\n}\n\nexport async function listDocuments<DataModel extends GenericDataModel>(props: {\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n paginationOpts: PaginationOptions\n order?: \"asc\" | \"desc\"\n }\n ctx: GenericQueryCtx<DataModel>\n}) {\n const { args, ctx } = props\n const q = args.order === \"desc\"\n ? ctx.db.query(args.collectionSlug).order(\"desc\")\n : ctx.db.query(args.collectionSlug)\n const result = await q.paginate(args.paginationOpts)\n const resolvedPage = await Promise.all(\n result.page.map((doc: any) => resolveStorageUrl(ctx, doc)),\n )\n return { ...result, page: resolvedPage }\n}\n\nexport async function countDocuments<DataModel extends GenericDataModel>(props: {\n ctx: GenericQueryCtx<DataModel>\n args: { collectionSlug: TableNamesInDataModel<DataModel> }\n}): Promise<number> {\n return await (props.ctx.db.query(props.args.collectionSlug) as any).count()\n}\n\nexport async function getDocument<DataModel extends GenericDataModel>(props: {\n ctx: GenericQueryCtx<DataModel>\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n documentId: string\n /** When true, merges the transient preview snapshot (from admin live preview) */\n preview?: boolean\n }\n}) {\n const doc = await props.ctx.db.get(props.args.documentId as any)\n if (!doc) return null\n const resolved = await resolveStorageUrl(props.ctx, doc)\n\n // Merge preview snapshot when explicitly requested (live preview iframe).\n if (props.args.preview) {\n const snapshot = await getPreviewSnapshot<DataModel>({\n ctx: props.ctx,\n collection: props.args.collectionSlug as string,\n documentId: props.args.documentId,\n })\n if (snapshot) {\n return { ...resolved, ...snapshot }\n }\n }\n\n return resolved\n}\n\nexport async function updateDocument<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n documentId: string\n fields: Record<string, unknown>\n collectionFields: Record<string, VexField>\n }\n}) {\n const f = { ...props.args.fields }\n\n // Resolve the file URL from storageId when replacing a media file\n if (f.storageId && f.url === \"\") {\n const url = await props.ctx.storage.getUrl(f.storageId as any)\n if (url) f.url = url\n }\n\n const schema = generateFormSchema({\n fields: props.args.collectionFields,\n }).partial()\n\n const result = schema.safeParse(f)\n if (!result.success) {\n throw new ConvexError({\n message: \"Validation failed\",\n errors: result.error.flatten(),\n })\n }\n\n await props.ctx.db.patch(props.args.documentId as any, result.data as any)\n return props.args.documentId\n}\n\nexport async function createDocument<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n fields: Record<string, unknown>\n collectionFields: Record<string, VexField>\n kind: CollectionKind\n }\n}): Promise<string> {\n if (props.args.kind === \"global\") {\n const existing = await props.ctx.db.query(props.args.collectionSlug).first()\n if (existing) {\n throw new ConvexError(\n `Global \"${props.args.collectionSlug}\" already exists. Globals can only have one document.`,\n )\n }\n }\n\n const schema = generateFormSchema({\n fields: props.args.collectionFields,\n })\n\n const result = schema.safeParse(props.args.fields)\n if (!result.success) {\n throw new ConvexError({\n message: \"Validation failed\",\n errors: result.error.flatten(),\n })\n }\n\n const id = await props.ctx.db.insert(props.args.collectionSlug as any, result.data as any)\n return id as string\n}\n\nexport async function deleteDocument<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n documentId: string\n kind: CollectionKind\n }\n}): Promise<void> {\n if (props.args.kind === \"global\") {\n const existing = await props.ctx.db.get(props.args.documentId as any)\n if (!existing) {\n throw new ConvexError(\n `Global \"${props.args.collectionSlug}\" document not found. Cannot delete a non-existent global.`,\n )\n }\n }\n\n await props.ctx.db.delete(props.args.documentId as any)\n}\n\nexport async function bulkDeleteDocuments<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>\n args: {\n documentIds: string[]\n }\n}): Promise<{ deleted: number }> {\n for (const id of props.args.documentIds) {\n await props.ctx.db.delete(id as any)\n }\n return { deleted: props.args.documentIds.length }\n}\n\nexport async function searchDocuments<DataModel extends GenericDataModel>(props: {\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n searchIndexName: string\n searchField: string\n query: string\n }\n ctx: GenericQueryCtx<DataModel>\n}) {\n const { args, ctx } = props\n const docs = await (ctx.db.query(args.collectionSlug) as any)\n .withSearchIndex(args.searchIndexName, (q: any) => q.search(args.searchField, args.query))\n .take(50)\n return Promise.all(docs.map((doc: any) => resolveStorageUrl(ctx, doc)))\n}\n","import type { VexConfig, VexCollection } from \"../types\";\n\n/** Sentinel string placed at the top of every generated file. */\nexport const GENERATED_HEADER =\n \"// ⚠️ AUTO-GENERATED BY VEX CMS — DO NOT EDIT ⚠️\";\n\n/**\n * Relative import paths used inside generated files.\n * Computed by the CLI from cwd + convexDir; passed in so this function\n * stays pure and testable.\n */\nexport interface CollectionQueryImports {\n /** Import path for vex.config.ts from api/ dir. e.g. `\"../../../vex.config\"` */\n vexConfigFromApi: string;\n /** Import path for _generated/ from api/ dir. e.g. `\"../../_generated\"` */\n generatedDirFromApi: string;\n /** Import path for the user's auth helper from api/ dir. e.g. `\"../auth\"` */\n authFromApi: string;\n /** Import path for _generated/ from model/api/ dir. e.g. `\"../../../_generated\"` */\n generatedDirFromModel: string;\n}\n\n/**\n * Result of generating all collection files.\n * Keys are relative paths from the vex/ directory.\n * e.g. `\"api/articles.ts\"`, `\"model/api/articles.ts\"`, `\"api/index.ts\"`\n */\nexport type GeneratedFiles = Record<string, string>;\n\n/**\n * Generate typed Convex query/mutation files for all collections in `config`.\n *\n * Produces two files per collection:\n * - `model/api/{slug}.ts` — typed model functions (DB logic)\n * - `api/{slug}.ts` — Convex query/mutation exports (auth + RBAC + calls model)\n * Plus a barrel `api/index.ts`.\n */\nexport function generateCollectionQueries(props: {\n config: VexConfig;\n imports: CollectionQueryImports;\n}): GeneratedFiles {\n const { config, imports } = props;\n const result: GeneratedFiles = {};\n const slugs: string[] = [];\n\n // Regular collections\n for (const collection of config.collections) {\n const { apiFile, modelFile } = generateCollectionPair({\n collection,\n isMedia: false,\n imports,\n });\n result[`api/${collection.slug}.ts`] = apiFile;\n result[`model/api/${collection.slug}.ts`] = modelFile;\n slugs.push(collection.slug);\n }\n\n // Media collections\n if (config.media?.collections) {\n for (const collection of config.media.collections) {\n const { apiFile, modelFile } = generateCollectionPair({\n collection,\n isMedia: true,\n imports,\n });\n result[`api/${collection.slug}.ts`] = apiFile;\n result[`model/api/${collection.slug}.ts`] = modelFile;\n slugs.push(collection.slug);\n }\n }\n\n // Auth collections that opt in with generateApi: true\n if (config.auth?.collections) {\n for (const collection of config.auth.collections) {\n if (!collection.generateApi) continue;\n // Skip if already generated (user may have the same collection in config.collections)\n if (slugs.includes(collection.slug)) continue;\n const { apiFile, modelFile } = generateCollectionPair({\n collection,\n isMedia: false,\n imports,\n });\n result[`api/${collection.slug}.ts`] = apiFile;\n result[`model/api/${collection.slug}.ts`] = modelFile;\n slugs.push(collection.slug);\n }\n }\n\n // Barrel index\n result[\"api/index.ts\"] = generateIndexFile({ slugs });\n\n return result;\n}\n\n// ─── Per-collection pair generation ──────────────────────────────────────────\n\n/**\n * Generate both the model file and the API file for a single collection.\n */\nexport function generateCollectionPair(props: {\n collection: VexCollection;\n isMedia: boolean;\n imports: CollectionQueryImports;\n}): { apiFile: string; modelFile: string } {\n const { collection, isMedia, imports } = props;\n const slug = collection.slug;\n const tableName = collection.tableName ?? collection.slug;\n const firstSearchIndex = collection.searchIndexes?.[0] ?? null;\n\n const modelFile = generateModelFile({ slug, tableName, isMedia, firstSearchIndex, imports });\n const apiFile = generateApiFile({ slug, tableName, isMedia, firstSearchIndex, imports });\n\n return { apiFile, modelFile };\n}\n\n// ─── Model file generation ──────────────────────────────────────────────────\n\nexport function generateModelFile(props: {\n slug: string;\n tableName: string;\n isMedia: boolean;\n firstSearchIndex: { name: string; searchField: string } | null;\n imports: CollectionQueryImports;\n}): string {\n const { tableName, isMedia, firstSearchIndex, imports } = props;\n const parts: string[] = [];\n\n // Header + imports\n const coreImports = [\"getPreviewSnapshot\"];\n if (!isMedia) {\n coreImports.push(\"generateFormSchema\");\n }\n\n const coreTypeImports: string[] = [\"CollectionKind\"];\n if (!isMedia) {\n coreTypeImports.push(\"VexField\");\n }\n\n const coreTypeImportLine = coreTypeImports.length > 0\n ? `\\nimport type { ${coreTypeImports.join(\", \")} } from \"@vexcms/core\"`\n : \"\";\n\n const convexTypeImports = isMedia ? \"\" : `\\nimport type { WithoutSystemFields } from \"convex/server\"`;\n\n parts.push(`${GENERATED_HEADER}\nimport type { Doc, Id } from \"${imports.generatedDirFromModel}/dataModel\"\nimport type { QueryCtx, MutationCtx } from \"${imports.generatedDirFromModel}/server\"${convexTypeImports}\nimport { ConvexError } from \"convex/values\"\nimport { ${coreImports.join(\", \")} } from \"@vexcms/core\"${coreTypeImportLine}`);\n\n // getDocument\n parts.push(buildModelGetDocument({ tableName }));\n\n // listDocuments\n parts.push(buildModelListDocuments({ tableName }));\n\n // createDocument (not for media)\n if (!isMedia) {\n parts.push(buildModelCreateDocument({ tableName }));\n }\n\n // updateDocument (not for media)\n if (!isMedia) {\n parts.push(buildModelUpdateDocument({ tableName }));\n }\n\n // deleteDocument\n parts.push(buildModelDeleteDocument({ tableName }));\n\n // searchDocuments (only if search index)\n if (firstSearchIndex) {\n parts.push(buildModelSearchDocuments({\n tableName,\n searchIndexName: firstSearchIndex.name,\n searchField: firstSearchIndex.searchField as string,\n }));\n }\n\n return parts.join(\"\\n\\n\") + \"\\n\";\n}\n\nexport function buildModelGetDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export async function getDocument(props: {\n ctx: QueryCtx\n documentId: Id<\"${tableName}\">\n preview?: boolean\n}): Promise<Doc<\"${tableName}\"> | null> {\n const doc = await props.ctx.db.get(props.documentId)\n if (!doc) return null\n\n if (props.preview) {\n const snapshot = await getPreviewSnapshot({\n ctx: props.ctx,\n collection: \"${tableName}\",\n documentId: props.documentId,\n })\n if (snapshot) {\n return { ...doc, ...snapshot } as Doc<\"${tableName}\">\n }\n }\n\n return doc\n}`;\n}\n\nexport function buildModelListDocuments(props: { tableName: string }): string {\n const { tableName } = props;\n return `export async function listDocuments(props: {\n ctx: QueryCtx\n paginationOpts: { numItems: number; cursor: string | null }\n order?: \"asc\" | \"desc\"\n}) {\n const q = props.order === \"desc\"\n ? props.ctx.db.query(\"${tableName}\").order(\"desc\")\n : props.ctx.db.query(\"${tableName}\")\n return await q.paginate(props.paginationOpts)\n}`;\n}\n\nexport function buildModelCreateDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export async function createDocument(props: {\n collectionFields: Record<string, VexField>\n ctx: MutationCtx\n fields: unknown\n kind: CollectionKind\n}): Promise<Id<\"${tableName}\">> {\n if (props.kind === \"global\") {\n const existing = await props.ctx.db.query(\"${tableName}\").first()\n if (existing) {\n throw new ConvexError(\\`Global \"${tableName}\" already exists. Globals can only have one document.\\`)\n }\n }\n\n const schema = generateFormSchema({ fields: props.collectionFields })\n const parsed = schema.safeParse(props.fields)\n if (!parsed.success) {\n throw new ConvexError({ message: \"Validation failed\", errors: parsed.error.flatten() })\n }\n\n const data = { ...parsed.data }\n data.vex_status ??= \"published\"\n return await props.ctx.db.insert(\"${tableName}\", data as WithoutSystemFields<Doc<\"${tableName}\">>)\n}`;\n}\n\nexport function buildModelUpdateDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export async function updateDocument(props: {\n collectionFields: Record<string, VexField>\n ctx: MutationCtx\n documentId: Id<\"${tableName}\">\n fields: unknown\n}): Promise<Id<\"${tableName}\">> {\n const schema = generateFormSchema({ fields: props.collectionFields }).partial()\n const parsed = schema.safeParse(props.fields)\n if (!parsed.success) {\n throw new ConvexError({ message: \"Validation failed\", errors: parsed.error.flatten() })\n }\n\n await props.ctx.db.patch(props.documentId, parsed.data as Partial<Doc<\"${tableName}\">>)\n return props.documentId\n}`;\n}\n\nexport function buildModelDeleteDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export async function deleteDocument(props: {\n ctx: MutationCtx\n documentId: Id<\"${tableName}\">\n kind: CollectionKind\n}): Promise<void> {\n if (props.kind === \"global\") {\n const existing = await props.ctx.db.get(props.documentId)\n if (!existing) {\n throw new ConvexError(\\`Global \"${tableName}\" document not found. Cannot delete a non-existent global.\\`)\n }\n }\n\n await props.ctx.db.delete(props.documentId)\n}`;\n}\n\nexport function buildModelSearchDocuments(props: {\n tableName: string;\n searchIndexName: string;\n searchField: string;\n}): string {\n const { tableName, searchIndexName, searchField } = props;\n return `export async function searchDocuments(props: {\n ctx: QueryCtx\n query: string\n}): Promise<Doc<\"${tableName}\">[]> {\n return await props.ctx.db.query(\"${tableName}\")\n .withSearchIndex(\"${searchIndexName}\", (q) => q.search(\"${searchField}\", props.query))\n .take(50)\n}`;\n}\n\n// ─── API file generation ─────────────────────────────────────────────────────\n\nexport function generateApiFile(props: {\n slug: string;\n tableName: string;\n isMedia: boolean;\n firstSearchIndex: { name: string; searchField: string } | null;\n imports: CollectionQueryImports;\n}): string {\n const { slug, tableName, isMedia, firstSearchIndex, imports } = props;\n const parts: string[] = [];\n\n // Model imports\n const modelFns = [\n \"getDocument\",\n \"listDocuments\",\n ...(isMedia ? [] : [\"createDocument\", \"updateDocument\"]),\n \"deleteDocument\",\n ...(firstSearchIndex ? [\"searchDocuments\"] : []),\n ];\n\n parts.push(`${GENERATED_HEADER}\nimport { v } from \"convex/values\"\nimport { paginationOptsValidator } from \"convex/server\"\nimport { ConvexError } from \"convex/values\"\nimport { query, mutation } from \"${imports.generatedDirFromApi}/server\"\nimport type { QueryCtx, MutationCtx } from \"${imports.generatedDirFromApi}/server\"\nimport { hasPermission, findCollectionBySlug } from \"@vexcms/core\"\nimport { getUser } from \"${imports.authFromApi}\"\nimport vexConfig from \"${imports.vexConfigFromApi}\"\nimport { ${modelFns.join(\", \")} } from \"../model/api/${slug}\"`);\n\n // SLUG constant + requireAuth helper\n parts.push(`const SLUG = \"${slug}\" as const\n\nasync function requireAuth(ctx: QueryCtx | MutationCtx) {\n const auth = await getUser(ctx)\n if (!auth) throw new ConvexError(\"Not authenticated\")\n return auth\n}`);\n\n // getDocument\n parts.push(buildApiGetDocument({ tableName }));\n\n // listDocuments\n parts.push(buildApiListDocuments({ tableName }));\n\n // createDocument (not for media)\n if (!isMedia) {\n parts.push(buildApiCreateDocument({ slug, tableName }));\n }\n\n // updateDocument (not for media)\n if (!isMedia) {\n parts.push(buildApiUpdateDocument({ slug, tableName }));\n }\n\n // deleteDocument\n parts.push(buildApiDeleteDocument({ tableName }));\n\n // searchDocuments (only if search index)\n if (firstSearchIndex) {\n parts.push(buildApiSearchDocuments());\n }\n\n return parts.join(\"\\n\\n\") + \"\\n\";\n}\n\nexport function buildApiGetDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export const get = query({\n args: {\n id: v.id(\"${tableName}\"),\n _vexDrafts: v.optional(v.union(v.literal(\"snapshot\"), v.boolean())),\n },\n handler: async (ctx, args) => {\n const preview = (args._vexDrafts ?? \"snapshot\") === \"snapshot\"\n const doc = await getDocument({\n ctx,\n documentId: args.id,\n preview,\n })\n if (!doc) return null\n const auth = await getUser(ctx)\n if (auth) {\n const allowed = hasPermission({\n access: vexConfig.access,\n user: auth.user,\n userRoles: auth.roles,\n resource: SLUG,\n action: \"read\",\n data: doc,\n })\n if (!allowed) return null\n }\n return doc\n },\n})`;\n}\n\nexport function buildApiListDocuments(_props: { tableName: string }): string {\n return `export const list = query({\n args: {\n paginationOpts: paginationOptsValidator,\n order: v.optional(v.union(v.literal(\"asc\"), v.literal(\"desc\"))),\n },\n handler: async (ctx, args) => {\n const result = await listDocuments({\n ctx,\n paginationOpts: args.paginationOpts,\n order: args.order,\n })\n const auth = await getUser(ctx)\n if (!auth) return result\n const filteredPage = result.page.filter((doc) =>\n hasPermission({\n access: vexConfig.access,\n user: auth.user,\n userRoles: auth.roles,\n resource: SLUG,\n action: \"read\",\n data: doc,\n }) === true,\n )\n return { ...result, page: filteredPage }\n },\n})`;\n}\n\nexport function buildApiCreateDocument(_props: {\n slug: string;\n tableName: string;\n}): string {\n return `export const create = mutation({\n args: { fields: v.any() },\n handler: async (ctx, args) => {\n const { user, roles } = await requireAuth(ctx)\n hasPermission({\n access: vexConfig.access,\n user,\n userRoles: roles,\n resource: SLUG,\n action: \"create\",\n throwOnDenied: true,\n })\n const collection = findCollectionBySlug({ slug: SLUG, config: vexConfig })\n if (!collection) throw new ConvexError(\\`Collection \"\\${SLUG}\" not found in vex config\\`)\n return createDocument({\n collectionFields: collection.fields,\n ctx,\n fields: args.fields as unknown,\n kind: \"collection\",\n })\n },\n})`;\n}\n\nexport function buildApiUpdateDocument(props: {\n slug: string;\n tableName: string;\n}): string {\n const { tableName } = props;\n return `export const update = mutation({\n args: { id: v.id(\"${tableName}\"), fields: v.any() },\n handler: async (ctx, args) => {\n const { user, roles } = await requireAuth(ctx)\n hasPermission({\n access: vexConfig.access,\n user,\n userRoles: roles,\n resource: SLUG,\n action: \"update\",\n throwOnDenied: true,\n })\n const collection = findCollectionBySlug({ slug: SLUG, config: vexConfig })\n if (!collection) throw new ConvexError(\\`Collection \"\\${SLUG}\" not found in vex config\\`)\n return updateDocument({\n collectionFields: collection.fields,\n ctx,\n documentId: args.id,\n fields: args.fields,\n })\n },\n})`;\n}\n\nexport function buildApiDeleteDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export const remove = mutation({\n args: { id: v.id(\"${tableName}\") },\n handler: async (ctx, args) => {\n const { user, roles } = await requireAuth(ctx)\n hasPermission({\n access: vexConfig.access,\n user,\n userRoles: roles,\n resource: SLUG,\n action: \"delete\",\n throwOnDenied: true,\n })\n await deleteDocument({\n ctx,\n documentId: args.id,\n kind: \"collection\",\n })\n },\n})`;\n}\n\nexport function buildApiSearchDocuments(): string {\n return `export const search = query({\n args: { query: v.string() },\n handler: async (ctx, args) => {\n const results = await searchDocuments({\n ctx,\n query: args.query,\n })\n const auth = await getUser(ctx)\n if (!auth) return results\n return results.filter((doc) =>\n hasPermission({\n access: vexConfig.access,\n user: auth.user,\n userRoles: auth.roles,\n resource: SLUG,\n action: \"read\",\n data: doc,\n }) === true,\n )\n },\n})`;\n}\n\n// ─── Barrel index ────────────────────────────────────────────────────────────\n\n/**\n * Generate the barrel `index.ts` that namespace-re-exports all collection files.\n */\nexport function generateIndexFile(props: { slugs: string[] }): string {\n const sorted = [...props.slugs].sort();\n if (sorted.length === 0) {\n return GENERATED_HEADER + \"\\n\";\n }\n const exports = sorted\n .map((slug) => `export * as ${slug} from \"./${slug}\"`)\n .join(\"\\n\");\n return `${GENERATED_HEADER}\\n${exports}\\n`;\n}\n","// =============================================================================\n// SCHEMA DIFF — compares old vs new generated schema to detect migration needs\n// =============================================================================\n\nexport interface SchemaFieldInfo {\n /** Table name (export const name). */\n table: string;\n /** Field name within the table. */\n field: string;\n /** Full value type string, e.g. \"v.string()\" or \"v.optional(v.string())\". */\n valueType: string;\n /** Whether the field is wrapped in v.optional(...). */\n isOptional: boolean;\n}\n\nexport interface RemovedFieldInfo {\n /** Table name (export const name). */\n table: string;\n /** Field name that was removed. */\n field: string;\n /** The old value type string, e.g. \"v.string()\". */\n valueType: string;\n /** Whether the field was optional in the old schema. */\n wasOptional: boolean;\n}\n\nexport interface SchemaDiff {\n /** Fields that changed from optional → required (need backfill). */\n newRequired: SchemaFieldInfo[];\n /** Fields that are entirely new and required (need backfill). */\n addedRequired: SchemaFieldInfo[];\n /** Fields that are entirely new and optional (may need backfill if they have a defaultValue). */\n addedOptional: SchemaFieldInfo[];\n /** Fields that existed in old schema but are absent in new schema. */\n removedFields: RemovedFieldInfo[];\n /** All fields that need migration. */\n needsMigration: SchemaFieldInfo[];\n}\n\ninterface ParsedTable {\n name: string;\n fields: Map<string, { valueType: string; isOptional: boolean }>;\n}\n\n/**\n * Parse a generated vex schema string into a map of table → fields.\n *\n * Relies on the known output format of `generateVexSchema()`:\n * ```\n * export const <name> = defineTable({\n * field1: v.string(),\n * field2: v.optional(v.string()),\n * })\n * ```\n */\nfunction parseTables(schema: string): Map<string, ParsedTable> {\n const tables = new Map<string, ParsedTable>();\n if (!schema.trim()) return tables;\n\n // Match each `export const <name> = defineTable({ ... })`\n const tableRegex =\n /export\\s+const\\s+(\\w+)\\s*=\\s*defineTable\\(\\{([\\s\\S]*?)\\}\\)/g;\n\n let match: RegExpExecArray | null;\n while ((match = tableRegex.exec(schema)) !== null) {\n const name = match[1]!;\n const body = match[2]!;\n const fields = new Map<string, { valueType: string; isOptional: boolean }>();\n\n // Match field entries like ` fieldName: v.string(),` or ` fieldName: v.optional(v.string()),`\n // The value type can contain nested parens, so we use a greedy match up to the trailing comma\n const fieldRegex = /^\\s+(\\w+):\\s+(v\\..+?),?\\s*$/gm;\n let fieldMatch: RegExpExecArray | null;\n while ((fieldMatch = fieldRegex.exec(body)) !== null) {\n const fieldName = fieldMatch[1]!;\n const valueType = fieldMatch[2]!.replace(/,\\s*$/, \"\");\n const isOptional = valueType.startsWith(\"v.optional(\");\n fields.set(fieldName, { valueType, isOptional });\n }\n\n tables.set(name, { name, fields });\n }\n\n return tables;\n}\n\n/**\n * Compare two generated schema strings and return fields that need migration.\n *\n * A field needs migration when:\n * 1. It exists in the new schema but not the old, and is NOT optional → `addedRequired`\n * 2. It exists in the new schema but not the old, and IS optional → `addedOptional`\n * (planMigration decides whether to backfill based on defaultValue)\n * 3. It exists in both, was optional in old but is NOT optional in new → `newRequired`\n */\nexport function diffSchema(oldSchema: string, newSchema: string): SchemaDiff {\n const oldTables = parseTables(oldSchema);\n const newTables = parseTables(newSchema);\n\n const addedRequired: SchemaFieldInfo[] = [];\n const addedOptional: SchemaFieldInfo[] = [];\n const newRequired: SchemaFieldInfo[] = [];\n const removedFields: RemovedFieldInfo[] = [];\n\n for (const [tableName, newTable] of newTables) {\n const oldTable = oldTables.get(tableName);\n\n for (const [fieldName, newField] of newTable.fields) {\n const info: SchemaFieldInfo = {\n table: tableName,\n field: fieldName,\n valueType: newField.valueType,\n isOptional: newField.isOptional,\n };\n\n if (!oldTable) {\n // Entire table is new\n if (newField.isOptional) {\n addedOptional.push(info);\n } else {\n addedRequired.push(info);\n }\n } else {\n const oldField = oldTable.fields.get(fieldName);\n if (!oldField) {\n // Field is new\n if (newField.isOptional) {\n addedOptional.push(info);\n } else {\n addedRequired.push(info);\n }\n } else if (oldField.isOptional && !newField.isOptional) {\n // Field changed from optional → required\n newRequired.push(info);\n }\n }\n }\n }\n\n // Detect removed fields: fields that exist in old but not in new\n for (const [tableName, oldTable] of oldTables) {\n const newTable = newTables.get(tableName);\n if (!newTable) continue; // Entire table removed — not our concern here\n\n for (const [fieldName, oldField] of oldTable.fields) {\n if (!newTable.fields.has(fieldName)) {\n removedFields.push({\n table: tableName,\n field: fieldName,\n valueType: oldField.valueType,\n wasOptional: oldField.isOptional,\n });\n }\n }\n }\n\n return {\n addedRequired,\n addedOptional,\n newRequired,\n removedFields,\n needsMigration: [...addedRequired, ...addedOptional, ...newRequired],\n };\n}\n\n/**\n * Rewrite specific fields in a schema string to be `v.optional(...)`.\n *\n * Used to produce an interim schema where new required fields are temporarily\n * optional, allowing Convex to accept the schema before documents are backfilled.\n */\nexport function makeFieldsOptional(\n schema: string,\n fields: SchemaFieldInfo[],\n): string {\n let result = schema;\n\n for (const field of fields) {\n if (field.isOptional) continue; // Already optional\n\n // Match ` <fieldName>: <valueType>,` within the schema and wrap in v.optional(...)\n // The field line looks like: ` fieldName: v.string(),`\n const escaped = field.field.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = new RegExp(\n `(\\\\s+${escaped}:\\\\s+)(${field.valueType.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")})(,?)`,\n );\n result = result.replace(pattern, `$1v.optional($2)$3`);\n }\n\n return result;\n}\n\n/**\n * Re-insert removed fields into a schema string as `v.optional(...)`.\n *\n * Used to produce an interim schema that still accepts documents with the\n * removed field, so we can strip the field from documents before deploying\n * the final schema without the field.\n */\nexport function addRemovedFieldsAsOptional(\n schema: string,\n fields: RemovedFieldInfo[],\n): string {\n let result = schema;\n\n // Group removed fields by table for efficient insertion\n const byTable = new Map<string, RemovedFieldInfo[]>();\n for (const f of fields) {\n const list = byTable.get(f.table) ?? [];\n list.push(f);\n byTable.set(f.table, list);\n }\n\n for (const [tableName, tableFields] of byTable) {\n // Find the closing `})` of the defineTable for this table\n const tablePattern = new RegExp(\n `(export\\\\s+const\\\\s+${tableName}\\\\s*=\\\\s*defineTable\\\\(\\\\{[\\\\s\\\\S]*?)(\\\\}\\\\))`,\n );\n const tableMatch = result.match(tablePattern);\n if (!tableMatch) continue;\n\n // Build the extra field lines\n const extraLines = tableFields.map((f) => {\n const optionalType = f.wasOptional\n ? f.valueType\n : `v.optional(${f.valueType})`;\n return ` ${f.field}: ${optionalType},`;\n });\n\n // Insert the extra fields before the closing `})`\n result = result.replace(\n tablePattern,\n `$1${extraLines.join(\"\\n\")}\\n$2`,\n );\n }\n\n return result;\n}\n","// =============================================================================\n// MIGRATION PLAN — maps schema diff to concrete backfill operations\n// =============================================================================\n\nimport type { SchemaDiff } from \"./diffSchema\";\nimport type { VexConfig } from \"../types\";\nimport type { VexField } from \"../types/fields\";\n\nexport interface MigrationOp {\n /** The table name (as exported in the schema). */\n table: string;\n /** The field name to backfill. */\n field: string;\n /** The default value to set on existing documents. */\n defaultValue: unknown;\n}\n\n/**\n * Given a schema diff and the full Vex config, produce a list of\n * migration operations — one per field that needs backfilling.\n *\n * Fields are matched by looking up the collection whose table name\n * (or slug) matches the diff's table, then finding the field's\n * `defaultValue`.\n *\n * Auth-only fields (fields that come from the auth adapter, not from\n * user-defined collections) are skipped — auth manages its own data.\n */\nexport function planMigration(props: {\n diff: SchemaDiff;\n config: VexConfig;\n}): MigrationOp[] {\n const { diff, config } = props;\n\n if (diff.needsMigration.length === 0) return [];\n\n // Build a lookup: table export name → collection fields\n const tableFieldsMap = new Map<\n string,\n Record<string, VexField>\n >();\n\n for (const collection of config.collections) {\n tableFieldsMap.set(collection.slug, collection.fields);\n }\n\n for (const global of config.globals) {\n tableFieldsMap.set(global.slug, global.fields);\n }\n\n const ops: MigrationOp[] = [];\n\n for (const fieldInfo of diff.needsMigration) {\n const collectionFields = tableFieldsMap.get(fieldInfo.table);\n\n if (!collectionFields) {\n // Table not found in user collections — likely an auth-only table\n continue;\n }\n\n const field = collectionFields[fieldInfo.field] as VexField | undefined;\n if (!field) {\n // Field not found in collection config — likely an auth-managed field\n continue;\n }\n\n if (!field.required) {\n // Only migrate required fields — optional fields don't need backfill\n continue;\n }\n const defaultValue = (field as any).defaultValue;\n if (defaultValue === undefined) {\n // No defaultValue — skip (required fields enforce defaultValue at config time)\n continue;\n }\n\n ops.push({\n table: fieldInfo.table,\n field: fieldInfo.field,\n defaultValue,\n });\n }\n\n return ops;\n}\n"],"mappings":"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","names":["v","v","jsx","ui","v","schema","v","v"]}
1
+ {"version":3,"sources":["../src/types/media.ts","../src/errors/index.ts","../src/config/defineConfig.ts","../src/config/defineCollection.ts","../src/config/defineGlobal.ts","../src/access/defineAccess.ts","../src/access/hasPermission.ts","../src/access/checkAdminAccess.ts","../src/metadata/buildSiteMetadata.ts","../src/config/sanitizeConfig.ts","../src/config/isMediaCollection.ts","../src/config/findCollectionBySlug.ts","../src/fields/checkbox/config.ts","../src/utils.ts","../src/fields/checkbox/columnDef.ts","../src/valueTypes/processAdminOptions.ts","../src/fields/constants.ts","../src/fields/checkbox/schemaValueType.ts","../src/fields/number/config.ts","../src/fields/number/columnDef.ts","../src/fields/number/schemaValueType.ts","../src/fields/select/config.ts","../src/fields/select/columnDef.tsx","../src/fields/select/schemaValueType.ts","../src/fields/text/config.ts","../src/fields/text/columnDef.tsx","../src/fields/text/schemaValueType.ts","../src/fields/date/config.ts","../src/fields/date/columnDef.ts","../src/fields/date/schemaValueType.ts","../src/fields/imageUrl/config.ts","../src/fields/imageUrl/columnDef.tsx","../src/fields/imageUrl/schemaValueType.ts","../src/fields/relationship/config.ts","../src/fields/relationship/columnDef.ts","../src/fields/relationship/schemaValueType.ts","../src/fields/json/config.ts","../src/fields/json/columnDef.ts","../src/fields/json/schemaValueType.ts","../src/fields/object/config.ts","../src/fields/object/schemaValueType.ts","../src/fields/object/columnDef.ts","../src/fields/richtext/config.ts","../src/fields/richtext/schemaValueType.ts","../src/fields/richtext/columnDef.ts","../src/fields/media/config.ts","../src/fields/media/schemaValueType.ts","../src/fields/array/config.ts","../src/fields/array/columnDef.ts","../src/fields/array/schemaValueType.ts","../src/fields/blocks/config.ts","../src/fields/blocks/schemaValueType.ts","../src/fields/blocks/columnDef.ts","../src/fields/color/config.ts","../src/fields/color/schemaValueType.ts","../src/fields/color/columnDef.ts","../src/valueTypes/extract.ts","../src/valueTypes/indexes.ts","../src/valueTypes/searchIndexes.ts","../src/valueTypes/merge.ts","../src/valueTypes/slugs.ts","../src/valueTypes/generate.ts","../src/schema/extendTable.ts","../src/fields/media/columnDef.ts","../src/columns/generateColumns.ts","../src/formSchema/generateFormSchema.ts","../src/formSchema/generateFormDefaultValues.ts","../src/fields/ui/config.ts","../src/fields/tabs/config.ts","../src/types/fields.ts","../src/blocks/defineBlock.ts","../src/styles/presets.ts","../src/styles/blockStylesToTailwind.ts","../src/typeGen/slugToInterfaceName.ts","../src/typeGen/fieldToTypeString.ts","../src/typeGen/generateVexTypes.ts","../src/versioning/constants.ts","../src/versioning/extractUserFields.ts","../src/livePreview/resolvePreviewURL.ts","../src/livePreview/shouldReloadURL.ts","../src/livePreview/constants.ts","../src/convex/previewSnapshot.ts","../src/convex/vexQuery.ts","../src/convex/model/collections.ts","../src/valueTypes/generateCollectionQueries.ts","../src/migrations/diffSchema.ts","../src/migrations/planMigration.ts"],"sourcesContent":["import type { VexField } from \"./fields\";\nimport type { VexCollection, CollectionAdminConfig } from \"./collections\";\n\n/**\n * Interface that file storage plugins must implement.\n * Each method operates on the storage provider (e.g., Convex file storage, S3, Cloudinary).\n */\nexport interface FileStorageAdapter {\n /** Identifier for the storage provider (e.g., \"convex\", \"s3\", \"cloudinary\"). */\n readonly name: string;\n\n /**\n * The Convex value type string for the storageId field in media collections.\n * Determines the schema type at generation time.\n *\n * - Convex adapter: `'v.id(\"_storage\")'` — typed reference to Convex file storage\n * - Generic adapters: `'v.string()'` — plain string for external storage URLs/IDs\n */\n readonly storageIdValueType: string;\n\n /**\n * Get a presigned upload URL from the storage provider.\n * Called by the admin panel before uploading a file.\n *\n * @returns A URL string that accepts file uploads via PUT/POST.\n */\n getUploadUrl: () => Promise<string>;\n\n /**\n * Resolve a storage ID to an accessible URL.\n *\n * @param props.storageId - The storage provider's file identifier.\n * @returns A URL string for accessing the file, or null if the file doesn't exist.\n */\n getUrl: (props: { storageId: string }) => Promise<string | null>;\n\n /**\n * Delete a file from the storage provider.\n *\n * @param props.storageId - The storage provider's file identifier.\n */\n deleteFile: (props: { storageId: string }) => Promise<void>;\n}\n\n/**\n * Fields that are auto-injected into every media collection and cannot be overridden.\n */\nexport const LOCKED_MEDIA_FIELDS = [\n \"storageId\",\n \"filename\",\n \"mimeType\",\n \"size\",\n] as const;\nexport type LockedMediaField = (typeof LOCKED_MEDIA_FIELDS)[number];\n\n/**\n * Fields that are auto-injected but CAN be overridden by the user.\n */\nexport const OVERRIDABLE_MEDIA_FIELDS = [\n \"url\",\n \"alt\",\n \"width\",\n \"height\",\n] as const;\nexport type OverridableMediaField = (typeof OVERRIDABLE_MEDIA_FIELDS)[number];\n\n/**\n * Keys of all default media fields auto-injected by `defineConfig()`.\n * Used as extra autocomplete keys in `CollectionAdminConfig` so that\n * `useAsTitle`, `defaultColumns`, etc. suggest both user fields and preset fields.\n */\nexport type DefaultMediaFieldKeys =\n | LockedMediaField\n | OverridableMediaField;\n\n/**\n * A media collection definition. Users create these as plain objects.\n * Default media fields (storageId, filename, mimeType, size, url, alt, width, height)\n * are injected automatically by `defineConfig()`.\n *\n * The `fields` record contains ONLY user-defined additional fields or overrides\n * of overridable defaults (url, alt, width, height).\n */\nexport interface VexMediaCollection<\n TFields extends Record<string, VexField> = any,\n TSlug extends string = string,\n> {\n readonly slug: TSlug;\n fields?: TFields;\n tableName?: string;\n labels?: { singular?: string; plural?: string };\n admin?: CollectionAdminConfig<TFields, DefaultMediaFieldKeys>;\n}\n\n/**\n * Default media fields injected into every media collection by defineConfig().\n * Returns a fresh record each call to avoid mutation across collections.\n */\nexport function getDefaultMediaFields(): Record<string, VexField> {\n return {\n storageId: {\n type: \"text\",\n required: true,\n defaultValue: \"\",\n label: \"Storage ID\",\n admin: { hidden: true },\n },\n filename: {\n type: \"text\",\n required: true,\n defaultValue: \"\",\n label: \"Filename\",\n admin: { readOnly: true },\n },\n mimeType: {\n type: \"text\",\n required: true,\n defaultValue: \"\",\n label: \"MIME Type\",\n index: \"by_mimeType\",\n admin: { readOnly: true },\n },\n size: {\n type: \"number\",\n required: true,\n defaultValue: 0,\n label: \"File Size (bytes)\",\n admin: { readOnly: true },\n },\n url: {\n type: \"text\",\n required: true,\n defaultValue: \"\",\n label: \"URL\",\n admin: { readOnly: true },\n },\n alt: { type: \"text\", label: \"Alt Text\" },\n width: { type: \"number\", label: \"Width (px)\" },\n height: { type: \"number\", label: \"Height (px)\" },\n };\n}\n\n/**\n * The resolved media configuration on VexConfig.\n */\nexport interface MediaConfig {\n collections: VexCollection[];\n storageAdapter: FileStorageAdapter;\n}\n\n/**\n * Client-safe media configuration with non-serializable parts stripped.\n * Used when passing config across RSC serialization boundaries (e.g., to client components).\n */\nexport interface ClientMediaConfig {\n collections: VexCollection[];\n}\n\n/**\n * Input shape for the `media` field on VexConfigInput.\n */\nexport interface MediaConfigInput {\n collections: VexMediaCollection[];\n storageAdapter: FileStorageAdapter;\n}\n","/**\n * Base error class for all Vex CMS errors.\n * Provides consistent error formatting with a [vex] prefix.\n */\nexport class VexError extends Error {\n constructor(message: string) {\n super(`[vex] ${message}`);\n this.name = \"VexError\";\n }\n}\n\n/**\n * Thrown when a duplicate table slug is detected during schema generation.\n * Includes both registrations so the user can identify the conflict.\n */\nexport class VexSlugConflictError extends VexError {\n constructor(\n public readonly slug: string,\n public readonly existingSource: string,\n public readonly existingLocation: string,\n public readonly newSource: string,\n public readonly newLocation: string,\n ) {\n super(\n `Duplicate table slug \"${slug}\":\\n` +\n ` - ${existingSource}: ${existingLocation}\\n` +\n ` - ${newSource}: ${newLocation}\\n` +\n `Rename one of these to resolve the conflict.`,\n );\n this.name = \"VexSlugConflictError\";\n }\n}\n\n/**\n * Thrown when a field fails validation during schema generation.\n * For example: required field with no defaultValue, or wrong defaultValue type.\n */\nexport class VexFieldValidationError extends VexError {\n constructor(\n public readonly collectionSlug: string,\n public readonly fieldName: string,\n public readonly detail: string,\n ) {\n super(`Field \"${fieldName}\" in collection \"${collectionSlug}\": ${detail}`);\n this.name = \"VexFieldValidationError\";\n }\n}\n\n/**\n * Thrown when auth configuration is invalid.\n * For example: userCollection not found in collections.\n */\nexport class VexAuthConfigError extends VexError {\n constructor(detail: string) {\n super(`Auth configuration error: ${detail}`);\n this.name = \"VexAuthConfigError\";\n }\n}\n\n/**\n * Thrown when media configuration is invalid.\n */\nexport class VexMediaConfigError extends VexError {\n constructor(detail: string) {\n super(`Media configuration error: ${detail}`);\n this.name = \"VexMediaConfigError\";\n }\n}\n\n/**\n * Thrown when access configuration is invalid.\n * For example: orgCollection provided without userOrgField.\n */\nexport class VexAccessConfigError extends VexError {\n constructor(detail: string) {\n super(`Access configuration error: ${detail}`);\n this.name = \"VexAccessConfigError\";\n }\n}\n\n/**\n * Thrown by `hasPermission` when `throwOnDenied` is true and the user\n * does not have permission for the requested action.\n *\n * Contains structured context about the denied access attempt so callers\n * can log, surface to users, or handle programmatically.\n */\nexport class VexAccessError extends VexError {\n constructor(\n public readonly resource: string,\n public readonly action: string,\n public readonly field?: string,\n ) {\n const target = field\n ? `field \"${field}\" on resource \"${resource}\"`\n : `resource \"${resource}\"`;\n super(`Access denied: ${action} on ${target}`);\n this.name = \"VexAccessError\";\n }\n}\n\n/**\n * Thrown when a block definition is invalid.\n * For example: reserved field name used, duplicate block slug.\n */\nexport class VexBlockValidationError extends VexError {\n constructor(\n public readonly blockSlug: string,\n public readonly detail: string,\n ) {\n super(`Block \"${blockSlug}\": ${detail}`);\n this.name = \"VexBlockValidationError\";\n }\n}\n","import type { VexConfig, VexConfigInput, VexCollection } from \"../types\";\nimport type { VexMediaCollection } from \"../types/media\";\nimport { getDefaultMediaFields, LOCKED_MEDIA_FIELDS } from \"../types/media\";\nimport { VexMediaConfigError } from \"../errors\";\n\nexport const BASE_VEX_CONFIG: Omit<VexConfig, \"auth\"> = {\n basePath: \"/admin\",\n globals: [],\n collections: [],\n admin: {\n meta: {\n titleSuffix: \"| Admin\",\n favicon: \"/favicon.ico\",\n },\n user: \"users\",\n sidebar: {\n hideGlobals: false,\n },\n onboarding: {\n disabled: false,\n },\n },\n schema: {\n outputPath: \"/convex/vex.schema.ts\",\n typesOutputPath: \"/convex/vex.types.ts\",\n autoMigrate: true,\n autoRemove: false,\n },\n};\n\n/**\n * Resolve a VexMediaCollection into a VexCollection by injecting\n * default media fields. Locked fields cannot be overridden by the user.\n * Overridable fields (url, alt, width, height) can be customized.\n */\nfunction resolveMediaCollection(props: {\n mediaCollection: VexMediaCollection;\n}): VexCollection {\n const defaults = getDefaultMediaFields();\n\n // Merge user fields, skipping locked fields\n if (props.mediaCollection.fields) {\n for (const [fieldName, field] of Object.entries(props.mediaCollection.fields) as [string, any][]) {\n if ((LOCKED_MEDIA_FIELDS as readonly string[]).includes(fieldName)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `[vex] Media collection \"${props.mediaCollection.slug}\": field \"${fieldName}\" is a system field and cannot be overridden`,\n );\n }\n continue;\n }\n defaults[fieldName] = field;\n }\n }\n\n // Build admin config with useAsTitle default\n const adminConfig: Record<string, unknown> = {\n ...props.mediaCollection.admin,\n useAsTitle: props.mediaCollection.admin?.useAsTitle ?? \"filename\",\n };\n\n return {\n slug: props.mediaCollection.slug,\n fields: defaults,\n tableName: props.mediaCollection.tableName,\n labels: props.mediaCollection.labels,\n admin: adminConfig as any,\n _isMedia: true,\n };\n}\n\nexport function defineConfig(vexConfig: VexConfigInput): VexConfig {\n // Execute plugins sequentially — each transforms the config for the next\n let resolvedInput = vexConfig;\n if (vexConfig.plugins && vexConfig.plugins.length > 0) {\n for (const plugin of vexConfig.plugins) {\n resolvedInput = plugin(resolvedInput);\n }\n }\n // Remove plugins from the resolved config (they've already been applied)\n const { plugins: _plugins, ...inputWithoutPlugins } = resolvedInput;\n\n const { media: mediaInput, ...restInput } = inputWithoutPlugins;\n const resolved = inputWithoutPlugins;\n const config: VexConfig = {\n ...BASE_VEX_CONFIG,\n ...restInput,\n admin: {\n ...BASE_VEX_CONFIG.admin,\n ...resolved.admin,\n meta: {\n ...BASE_VEX_CONFIG.admin.meta,\n ...resolved.admin?.meta,\n },\n sidebar: {\n ...BASE_VEX_CONFIG.admin.sidebar,\n ...resolved.admin?.sidebar,\n },\n onboarding: {\n ...BASE_VEX_CONFIG.admin.onboarding,\n ...resolved.admin?.onboarding,\n },\n livePreview: resolved.admin?.livePreview,\n },\n schema: {\n ...BASE_VEX_CONFIG.schema,\n ...resolved.schema,\n },\n access: resolved.access,\n breakpoints: resolved.breakpoints,\n };\n\n // Handle media config\n if (mediaInput) {\n if (mediaInput.collections.length === 0) {\n config.media = undefined;\n } else if (!mediaInput.storageAdapter) {\n throw new VexMediaConfigError(\n \"media.storageAdapter is required when media.collections is non-empty\",\n );\n } else {\n config.media = {\n collections: mediaInput.collections.map((mc) =>\n resolveMediaCollection({ mediaCollection: mc }),\n ),\n storageAdapter: mediaInput.storageAdapter,\n };\n }\n } else {\n config.media = undefined;\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n // Validate collection slugs\n for (const collection of config.collections) {\n if (!/^[a-z][a-z0-9_]*$/.test(collection.slug)) {\n console.warn(\n `[vex] Collection slug \"${collection.slug}\" should be lowercase alphanumeric with underscores, starting with a letter`,\n );\n }\n if (collection.slug.startsWith(\"vex_\")) {\n console.warn(\n `[vex] Collection slug \"${collection.slug}\" uses reserved prefix \"vex_\"`,\n );\n }\n if (Object.keys(collection.fields).length === 0) {\n console.warn(`[vex] Collection \"${collection.slug}\" has no fields defined`);\n }\n }\n\n // Validate global slugs\n for (const global of config.globals) {\n if (!/^[a-z][a-z0-9_]*$/.test(global.slug)) {\n console.warn(\n `[vex] Global slug \"${global.slug}\" should be lowercase alphanumeric with underscores, starting with a letter`,\n );\n }\n if (global.slug.startsWith(\"vex_\")) {\n console.warn(`[vex] Global slug \"${global.slug}\" uses reserved prefix \"vex_\"`);\n }\n if (Object.keys(global.fields).length === 0) {\n console.warn(`[vex] Global \"${global.slug}\" has no fields defined`);\n }\n }\n\n // Check for duplicate slugs\n const slugs = config.collections.concat(config.globals as any[]).map((c) => c.slug);\n const duplicates = slugs.filter((slug, i) => slugs.indexOf(slug) !== i);\n if (duplicates.length > 0) {\n console.warn(\n `[vex] Duplicate collection slugs detected: ${duplicates.join(\", \")}`,\n );\n }\n }\n\n return config;\n}\n","import type { VexField, VexCollection } from \"../types\";\nimport type { VexAuthAdapter, AuthCollectionFieldKeys } from \"../types/auth\";\nimport type { CollectionAdminConfig, IndexConfig, SearchIndexConfig, VersionsConfig, VersioningFieldKeys } from \"../types/collections\";\nimport type { VexMediaCollection, DefaultMediaFieldKeys } from \"../types/media\";\n\n/**\n * Creates a VexCollection with full LSP autocomplete on field names,\n * `admin.useAsTitle`, `admin.defaultColumns`, index fields, etc.\n *\n * When `auth` is provided, auth field keys (e.g. \"email\", \"createdAt\") are\n * also included in autocomplete for admin config and indexes.\n *\n * @example\n * ```ts\n * // Without auth — autocomplete for own fields\n * export const posts = defineCollection({\n * slug: \"posts\",\n * fields: {\n * title: { type: \"text\", required: true },\n * status: { type: \"select\", options: [...] },\n * },\n * admin: { useAsTitle: \"title\" }, // autocomplete: \"title\" | \"status\"\n * });\n *\n * // With auth — autocomplete for own fields + auth fields\n * export const users = defineCollection({\n * slug: \"users\",\n * auth,\n * fields: {\n * name: { type: \"text\", required: true },\n * role: { type: \"select\", options: [...] },\n * },\n * admin: {\n * useAsTitle: \"name\", // autocomplete: \"name\" | \"role\" | \"email\" | \"createdAt\" | ...\n * defaultColumns: [\"name\", \"email\"], // same autocomplete\n * },\n * });\n * ```\n */\nexport function defineCollection<\n TFields extends Record<string, VexField>,\n TAuth extends VexAuthAdapter<any> | undefined = undefined,\n TSlug extends string = string,\n>(props: {\n readonly slug: TSlug;\n fields: TFields;\n auth?: TAuth;\n tableName?: string;\n labels?: { singular?: string; plural?: string };\n admin?: CollectionAdminConfig<\n TFields,\n VersioningFieldKeys | (TAuth extends VexAuthAdapter<any> ? AuthCollectionFieldKeys<TAuth, TSlug> : never)\n >;\n indexes?: IndexConfig<\n TFields,\n VersioningFieldKeys | (TAuth extends VexAuthAdapter<any> ? AuthCollectionFieldKeys<TAuth, TSlug> : never)\n >[];\n searchIndexes?: SearchIndexConfig<\n TFields,\n VersioningFieldKeys | (TAuth extends VexAuthAdapter<any> ? AuthCollectionFieldKeys<TAuth, TSlug> : never)\n >[];\n versions?: VersionsConfig;\n interfaceName?: string;\n}): VexCollection<\n TFields,\n VersioningFieldKeys | (TAuth extends VexAuthAdapter<any> ? AuthCollectionFieldKeys<TAuth, TSlug> : never),\n TSlug\n> {\n const { auth: _auth, ...rest } = props;\n return rest as VexCollection<\n TFields,\n VersioningFieldKeys | (TAuth extends VexAuthAdapter<any> ? AuthCollectionFieldKeys<TAuth, TSlug> : never),\n TSlug\n >;\n}\n\n/**\n * Creates a VexMediaCollection with full LSP autocomplete on field names\n * and `admin.useAsTitle`, `admin.defaultColumns`, etc.\n *\n * Default media fields (storageId, filename, mimeType, size, url, alt, width, height)\n * are injected automatically by `defineConfig()` — only define additional or\n * overridden fields here.\n *\n * @example\n * ```ts\n * export const media = defineMediaCollection({\n * slug: \"media\",\n * fields: {\n * caption: { type: \"text\" },\n * },\n * admin: { useAsTitle: \"filename\" }, // autocomplete: \"caption\" | default media field keys\n * });\n * ```\n */\nexport function defineMediaCollection<\n TFields extends Record<string, VexField> = Record<never, VexField>,\n TSlug extends string = string,\n>(props: {\n readonly slug: TSlug;\n fields?: TFields;\n tableName?: string;\n labels?: { singular?: string; plural?: string };\n admin?: CollectionAdminConfig<TFields, DefaultMediaFieldKeys>;\n}): VexMediaCollection<TFields, TSlug> {\n return props as VexMediaCollection<TFields, TSlug>;\n}\n","import type { VexField, VexGlobal, GlobalAdminConfig } from \"../types\";\nimport type { VersionsConfig } from \"../types/collections\";\n\n/**\n * Creates a VexGlobal with full LSP autocomplete on field names\n * and `admin.useAsTitle`, etc.\n *\n * A global is a singleton document — only one document exists per global.\n * The admin panel shows it as a single editable form, not a list.\n *\n * @example\n * ```ts\n * export const siteSettings = defineGlobal({\n * slug: \"site_settings\",\n * label: \"Site Settings\",\n * fields: {\n * siteName: text({ label: \"Site Name\", required: true }),\n * description: text({ label: \"Description\" }),\n * },\n * admin: { useAsTitle: \"siteName\" },\n * versions: { drafts: true },\n * });\n * ```\n */\nexport function defineGlobal<\n TFields extends Record<string, VexField>,\n TSlug extends string = string,\n>(props: {\n readonly slug: TSlug;\n fields: TFields;\n label?: string;\n tableName?: string;\n admin?: GlobalAdminConfig<TFields>;\n versions?: VersionsConfig;\n interfaceName?: string;\n}): VexGlobal<TFields, TSlug> {\n return props;\n}\n","import type {\n VexAccessConfig,\n VexAccessInputBase,\n VexAccessInputWithOrg,\n} from \"./types\";\nimport type { VexCollection } from \"../types\";\nimport { VexAccessConfigError } from \"../errors\";\n\n/**\n * Define access permissions for the Vex CMS admin panel.\n *\n * This is a builder function (like `defineCollection`) that provides full\n * TypeScript inference for roles, resource slugs, field keys, user type,\n * and organization type.\n *\n * The function validates configuration in non-production and returns a\n * `VexAccessConfig` for passing to `defineConfig({ access: ... })`.\n *\n * @returns A `VexAccessConfig` for passing to `defineConfig({ access: ... })`.\n */\n\n// Overload: with organization (must come first — more specific)\nexport function defineAccess<\n const TRoles extends readonly string[],\n const TResources extends readonly any[],\n const TUserCollection extends VexCollection<any, any, any>,\n TUser = undefined,\n const TOrgCollection extends VexCollection<any, any, any> = never,\n TOrg = undefined,\n>(\n props: VexAccessInputWithOrg<TRoles, TResources, TUserCollection, TUser, TOrgCollection, TOrg>,\n): VexAccessConfig;\n\n// Overload: without organization\nexport function defineAccess<\n const TRoles extends readonly string[],\n const TResources extends readonly any[],\n const TUserCollection extends VexCollection<any, any, any>,\n TUser = undefined,\n>(\n props: VexAccessInputBase<TRoles, TResources, TUserCollection, TUser> & {\n orgCollection?: never;\n orgType?: never;\n userOrgField?: never;\n },\n): VexAccessConfig;\n\n// Implementation\nexport function defineAccess(props: {\n roles: readonly string[];\n adminRoles?: readonly string[];\n resources?: readonly any[];\n userCollection: { slug: string; fields?: Record<string, any> };\n userType?: unknown;\n orgCollection?: { slug: string };\n orgType?: unknown;\n userOrgField?: string;\n permissions: Record<string, any>;\n}): VexAccessConfig {\n // Validate org config coupling\n if (props.orgCollection && !props.userOrgField) {\n throw new VexAccessConfigError(\"orgCollection requires userOrgField\");\n }\n if (props.userOrgField && !props.orgCollection) {\n throw new VexAccessConfigError(\"userOrgField requires orgCollection\");\n }\n\n // Default adminRoles to all roles if not specified\n const adminRoles = props.adminRoles ?? props.roles;\n\n if (process.env.NODE_ENV !== \"production\") {\n // Validate userCollection has a slug\n if (!props.userCollection?.slug) {\n console.warn(\"[vex] defineAccess: userCollection must have a slug\");\n }\n\n // Validate orgCollection has a slug if provided\n if (props.orgCollection && !props.orgCollection.slug) {\n console.warn(\"[vex] defineAccess: orgCollection must have a slug\");\n }\n\n // Validate that permission resource slugs match resources (if resources provided)\n if (props.resources) {\n const resourceSlugs = new Set(\n props.resources.map((r: any) => r.slug),\n );\n for (const role of Object.keys(props.permissions)) {\n const rolePerms = props.permissions[role];\n if (!rolePerms) continue;\n for (const slug of Object.keys(rolePerms)) {\n if (!resourceSlugs.has(slug)) {\n console.warn(\n `[vex] defineAccess: permission resource \"${slug}\" not found in resources`,\n );\n }\n }\n }\n }\n\n // Validate that permission role keys match roles array\n const rolesSet = new Set(props.roles);\n for (const role of Object.keys(props.permissions)) {\n if (!rolesSet.has(role)) {\n console.warn(\n `[vex] defineAccess: permission role \"${role}\" not in roles array`,\n );\n }\n }\n\n // Validate adminRoles are a subset of roles\n if (props.adminRoles) {\n const rolesSetForAdmin = new Set(props.roles);\n for (const adminRole of props.adminRoles) {\n if (!rolesSetForAdmin.has(adminRole)) {\n console.warn(\n `[vex] defineAccess: adminRole \"${adminRole}\" not found in roles array`,\n );\n }\n }\n }\n\n // Validate userOrgField exists in user collection fields\n if (props.userOrgField && props.userCollection?.fields) {\n if (!(props.userOrgField in props.userCollection.fields)) {\n console.warn(\n `[vex] defineAccess: userOrgField \"${props.userOrgField}\" not found in user collection fields`,\n );\n }\n }\n }\n\n return {\n roles: props.roles,\n adminRoles,\n userCollection: props.userCollection.slug,\n orgCollection: props.orgCollection?.slug,\n userOrgField: props.userOrgField,\n permissions: props.permissions,\n };\n}\n","import type { AccessAction, VexAccessConfig, PermissionCheck, FieldPermissionResult } from \"./types\";\nimport { VexAccessError } from \"../errors\";\n\n/**\n * The result of resolving field permissions for a resource action.\n * Maps each field key to whether the action is allowed on that field.\n */\nexport type ResolvedFieldPermissions = Record<string, boolean>;\n\n/**\n * Resolve a permission check value (boolean, mode object, or function)\n * into a result for the requested fields.\n *\n * When `fields` is provided, returns a `Record<field, boolean>` for those fields.\n * When `fields` is omitted, returns a single `boolean` for overall action access.\n *\n * @param props.check - The permission check value to resolve\n * @param props.fields - Specific fields to check. When omitted, returns overall boolean.\n * @param props.data - The document data (for dynamic checks)\n * @param props.user - The user object (for dynamic checks)\n * @param props.organization - Optional organization object (for dynamic checks)\n * @returns Field permission map when fields provided, boolean when omitted\n */\nexport function resolvePermissionCheck(props: {\n check: PermissionCheck<string, any, any, any> | undefined;\n fields?: string[];\n data: Record<string, any>;\n user: Record<string, any>;\n organization?: Record<string, any>;\n}): ResolvedFieldPermissions | boolean {\n // Permissive default for missing actions\n if (props.check === undefined) {\n if (props.fields === undefined) return true;\n return Object.fromEntries(props.fields.map((k) => [k, true]));\n }\n\n // Resolve function checks\n let resolved: FieldPermissionResult<string>;\n if (typeof props.check === \"function\") {\n const callbackProps: any = props.organization !== undefined\n ? { data: props.data, user: props.user, organization: props.organization }\n : { data: props.data, user: props.user };\n resolved = props.check(callbackProps);\n } else {\n resolved = props.check;\n }\n\n // Handle undefined function return as deny-all\n if (resolved === undefined) {\n if (props.fields === undefined) return false;\n return Object.fromEntries(props.fields.map((k) => [k, false]));\n }\n\n // Boolean result\n if (typeof resolved === \"boolean\") {\n if (props.fields === undefined) return resolved;\n return Object.fromEntries(props.fields.map((k) => [k, resolved as boolean]));\n }\n\n // Mode object result — need fields to check against\n if (props.fields === undefined) {\n // No specific fields requested — for mode objects, we can't give a single boolean\n // without knowing what fields exist. Default to true (allow mode with fields means\n // \"some fields allowed\", deny mode with fields means \"some fields denied\").\n // Callers wanting field-level granularity must pass fields.\n if (resolved.mode === \"allow\") return resolved.fields.length > 0;\n if (resolved.mode === \"deny\") return resolved.fields.length === 0;\n return true;\n }\n\n if (resolved.mode === \"allow\") {\n const allowSet = new Set(resolved.fields);\n return Object.fromEntries(\n props.fields.map((k) => [k, allowSet.has(k)]),\n );\n }\n\n // mode === \"deny\"\n const denySet = new Set(resolved.fields);\n return Object.fromEntries(\n props.fields.map((k) => [k, !denySet.has(k)]),\n );\n}\n\n/**\n * Merge field permission maps from multiple roles using OR logic.\n * If any role grants access to a field, that field is allowed.\n * Allow always wins over deny in cross-role merges.\n *\n * When all entries are booleans (no fields mode), merges with OR logic on booleans.\n *\n * @param props.results - Array of resolved permission results (one per role)\n * @param props.fields - The specific fields being checked (when field-level)\n * @returns Merged result: Record<string, boolean> when fields provided, boolean otherwise\n */\nexport function mergeRolePermissions(props: {\n results: (ResolvedFieldPermissions | boolean)[];\n fields?: string[];\n}): ResolvedFieldPermissions | boolean {\n if (props.results.length === 0) {\n if (props.fields === undefined) return true;\n return Object.fromEntries(props.fields.map((k) => [k, true]));\n }\n\n // No fields — merge booleans with OR\n if (props.fields === undefined) {\n return props.results.some((r) => r === true);\n }\n\n // With fields — merge field maps with OR\n return Object.fromEntries(\n props.fields.map((k) => [\n k,\n props.results.some((r) =>\n typeof r === \"boolean\" ? r : (r[k] === true),\n ),\n ]),\n );\n}\n\n/**\n * Check permissions for a user on a resource action.\n *\n * Without `fields` param → returns `boolean` (overall action access)\n * With `fields` param → returns `Record<string, boolean>` for those specific fields\n *\n * @param props.access - The VexAccessConfig from defineAccess\n * @param props.user - The user object\n * @param props.userRoles - The user's role(s) as a string array\n * @param props.resource - The resource slug (collection or global slug)\n * @param props.action - The CRUD action to check\n * @param props.data - Document data for dynamic permission checks. Defaults to `{}`.\n * @param props.organization - Optional organization object for org-aware permission checks.\n * @param props.fields - Specific fields to check. When provided, returns Record<string, boolean>.\n * @param props.throwOnDenied - When true, throws VexAccessError instead of returning false. Default: false.\n * @returns `boolean` when fields is omitted, `Record<string, boolean>` when fields is provided\n * @throws {VexAccessError} When `throwOnDenied` is true and access is denied\n */\nexport function hasPermission(props: {\n access: VexAccessConfig | undefined;\n user: Record<string, any>;\n userRoles: string[];\n resource: string;\n action: AccessAction;\n data?: Record<string, any>;\n organization?: Record<string, any>;\n fields?: string[];\n throwOnDenied?: boolean;\n}): ResolvedFieldPermissions | boolean {\n // Permissive default when no access config\n if (props.access === undefined) {\n if (props.fields === undefined) return true;\n return Object.fromEntries(props.fields.map((k) => [k, true]));\n }\n\n // Deny all when no roles\n if (props.userRoles.length === 0) {\n if (props.throwOnDenied) {\n throw new VexAccessError(props.resource, props.action);\n }\n if (props.fields === undefined) return false;\n return Object.fromEntries(props.fields.map((k) => [k, false]));\n }\n\n // Filter to only known roles\n const knownRolesSet = new Set(props.access.roles);\n const knownRoles = props.userRoles.filter((r) => knownRolesSet.has(r));\n\n // All roles unknown → deny all\n if (knownRoles.length === 0) {\n if (props.throwOnDenied) {\n throw new VexAccessError(props.resource, props.action);\n }\n if (props.fields === undefined) return false;\n return Object.fromEntries(props.fields.map((k) => [k, false]));\n }\n\n // Resolve permissions for each known role\n const results: (ResolvedFieldPermissions | boolean)[] = [];\n const data = props.data ?? {};\n\n for (const role of knownRoles) {\n const rolePerms = props.access.permissions[role];\n if (rolePerms === undefined) {\n // Role has no permissions object → skip (contributes nothing)\n continue;\n }\n\n const resourcePerms = rolePerms[props.resource];\n if (resourcePerms === undefined) {\n // Role has no entry for this resource → permissive default\n results.push(true);\n continue;\n }\n\n // Boolean shorthand at resource level: true = all actions allowed, false = all denied\n if (typeof resourcePerms === \"boolean\") {\n results.push(resourcePerms);\n continue;\n }\n\n const actionCheck = resourcePerms[props.action];\n results.push(\n resolvePermissionCheck({\n check: actionCheck,\n fields: props.fields,\n data,\n user: props.user,\n organization: props.organization,\n }),\n );\n }\n\n // Merge all role results with OR logic\n const merged = mergeRolePermissions({\n results,\n fields: props.fields,\n });\n\n // Handle throwOnDenied\n if (props.throwOnDenied) {\n if (typeof merged === \"boolean\") {\n if (!merged) {\n throw new VexAccessError(props.resource, props.action);\n }\n } else {\n const deniedField = Object.entries(merged).find(([, v]) => v === false);\n if (deniedField) {\n throw new VexAccessError(props.resource, props.action, deniedField[0]);\n }\n }\n }\n\n return merged;\n}\n","import type { VexAccessConfig } from \"./types\";\n\n/**\n * Check whether a user has access to the admin panel.\n *\n * Evaluates the `admin` permission on each of the user's roles.\n * If any role has `admin: true` (or a callback that returns true),\n * the user is granted access. Returns false if no role grants access\n * or if the access config is not defined.\n *\n * @param props.access - The VexAccessConfig from defineAccess\n * @param props.user - The user object (passed to dynamic permission callbacks)\n * @param props.userRoles - The user's role(s) as a string array\n * @param props.organization - Optional organization object (passed to callbacks if org support is configured)\n * @returns Whether the user can access the admin panel\n */\nexport function checkAdminAccess(props: {\n access: VexAccessConfig | undefined;\n user: Record<string, any>;\n userRoles: string[];\n organization?: Record<string, any>;\n}): boolean {\n // No access config — deny by default (admin should be explicitly granted)\n if (props.access === undefined) {\n return false;\n }\n\n // No roles — deny\n if (props.userRoles.length === 0) {\n return false;\n }\n\n const knownRolesSet = new Set(props.access.roles);\n\n for (const role of props.userRoles) {\n if (!knownRolesSet.has(role)) continue;\n\n const rolePerms = props.access.permissions[role];\n if (rolePerms === undefined) continue;\n\n const adminPerm = (rolePerms as Record<string, unknown>).admin;\n\n // Not specified — defaults to false\n if (adminPerm === undefined) continue;\n\n // Static boolean\n if (typeof adminPerm === \"boolean\") {\n if (adminPerm) return true;\n continue;\n }\n\n // Dynamic callback\n if (typeof adminPerm === \"function\") {\n const callbackProps: any = props.organization !== undefined\n ? { user: props.user, organization: props.organization }\n : { user: props.user };\n if (adminPerm(callbackProps)) return true;\n }\n }\n\n return false;\n}\n","/**\n * Framework-agnostic site metadata object.\n * Consumers (Next.js, TanStack Start, etc.) map this to their framework's metadata format.\n */\nexport interface SiteMetadata {\n title: string;\n description: string;\n ogImage?: string;\n twitterHandle?: string;\n}\n\n/**\n * Build site metadata by merging site-wide defaults with per-page overrides.\n *\n * Resolution order (per-page wins over site-wide):\n * - title: page.metaTitle → page.title → site.metaTitle → site.name → \"Untitled\"\n * - description: page.metaDescription → site.metaDescription → site.description → \"\"\n * - ogImage: page.ogImage → site.ogImage → undefined\n * - twitterHandle: site.twitterHandle → undefined\n *\n * @param props.site - Site settings fields (from globals)\n * @param props.page - Optional per-page overrides\n * @param props.titleSuffix - Optional suffix appended to title (e.g. \" | My Site\")\n * @returns Framework-agnostic metadata object\n */\nexport function buildSiteMetadata(props: {\n site: {\n name?: string;\n metaTitle?: string;\n metaDescription?: string;\n description?: string;\n ogImage?: string;\n twitterHandle?: string;\n };\n page?: {\n title?: string;\n metaTitle?: string;\n metaDescription?: string;\n ogImage?: string;\n };\n titleSuffix?: string;\n}): SiteMetadata {\n const title =\n props.page?.metaTitle ||\n props.page?.title ||\n props.site.metaTitle ||\n props.site.name ||\n \"Untitled\";\n\n const description =\n props.page?.metaDescription ||\n props.site.metaDescription ||\n props.site.description ||\n \"\";\n\n const ogImage = props.page?.ogImage || props.site.ogImage || undefined;\n\n const twitterHandle = props.site.twitterHandle || undefined;\n\n // Append title suffix if provided, unless:\n // - The title already ends with the suffix\n // - The title equals the site name (avoids \"My Site | My Site\" on home page)\n let finalTitle = title;\n if (\n props.titleSuffix &&\n !title.endsWith(props.titleSuffix) &&\n title !== props.site.name\n ) {\n finalTitle = title + props.titleSuffix;\n }\n\n return {\n title: finalTitle,\n description,\n ogImage,\n twitterHandle,\n };\n}\n","import type { VexConfig, ClientVexConfig } from \"../types\";\n\n/**\n * Strip non-serializable values from VexConfig for safe passage across\n * RSC / JSON serialization boundaries (e.g., server layout → client component).\n *\n * Currently strips:\n * - `media.storageAdapter` (contains async functions — only needed at CLI / schema-gen time)\n * - `admin.livePreview.url` function values on collections (replaced with `null`)\n *\n * This function is the single place to extend when new non-serializable\n * properties are added to VexConfig in the future.\n */\nexport function sanitizeConfigForClient(config: VexConfig): ClientVexConfig {\n const { media, ...rest } = config;\n\n return {\n ...rest,\n collections: rest.collections.map((collection) => {\n if (!collection.admin?.livePreview) return collection;\n if (typeof collection.admin.livePreview.url === \"string\") return collection;\n\n // Strip function URL — replaced with null for RSC serialization.\n // The admin panel resolves function URLs at runtime via livePreviewConfigs prop.\n return {\n ...collection,\n admin: {\n ...collection.admin,\n livePreview: {\n ...collection.admin.livePreview,\n url: null as any,\n },\n },\n };\n }),\n media: media\n ? { collections: media.collections }\n : undefined,\n };\n}\n\n/**\n * Extracts a map of collection slug → original livePreview URL function for collections\n * that have function-based preview URLs. Pass this to admin components so they\n * can resolve preview URLs at runtime on the client.\n *\n * @returns Map of collection slug → { url } (only entries with function URLs)\n */\nexport function extractLivePreviewConfigs(config: VexConfig): Record<string, { url: (doc: { _id: string; [key: string]: any }) => string }> {\n const result: Record<string, { url: (doc: { _id: string; [key: string]: any }) => string }> = {};\n\n for (const collection of config.collections) {\n if (collection.admin?.livePreview && typeof collection.admin.livePreview.url === \"function\") {\n result[collection.slug] = { url: collection.admin.livePreview.url };\n }\n }\n\n return result;\n}\n","interface HasSlug {\n readonly slug: string;\n}\n\ninterface ConfigWithMedia {\n media?: {\n collections: HasSlug[];\n };\n}\n\n/**\n * Check whether a collection is a media collection.\n *\n * Compares the collection's slug against the slugs in `config.media.collections`.\n * Works with both `VexConfig` and `ClientVexConfig` (both have the `media?.collections` shape).\n *\n * @param props.collection - The collection to check\n * @param props.config - The Vex config (or client config) containing media configuration\n * @returns true if the collection's slug matches a media collection slug\n */\nexport function isMediaCollection(props: {\n collection: HasSlug;\n config: ConfigWithMedia;\n}): boolean {\n if (!props.config.media?.collections) return false;\n return props.config.media.collections.some(\n (mc) => mc.slug === props.collection.slug,\n );\n}\n","import type { VexField } from \"../types/fields\";\n\ninterface HasSlugAndFields {\n readonly slug: string;\n fields: Record<string, VexField>;\n}\n\ninterface ConfigShape {\n collections: HasSlugAndFields[];\n globals: HasSlugAndFields[];\n media?: {\n collections: HasSlugAndFields[];\n };\n}\n\nexport type CollectionKind = \"collection\" | \"media\" | \"global\";\n\nexport interface ResolvedCollectionMatch {\n slug: string;\n fields: Record<string, VexField>;\n kind: CollectionKind;\n}\n\n/**\n * Get all collections, media collections, and globals as a flat array.\n *\n * Each entry includes the `kind` discriminator so callers can switch on it.\n *\n * @param props.config - The resolved Vex config\n * @param props.excludeGlobals - Skip globals (default: false)\n */\nexport function getAllCollections(props: {\n config: ConfigShape;\n excludeGlobals?: boolean;\n}): ResolvedCollectionMatch[] {\n const { config, excludeGlobals = false } = props;\n const result: ResolvedCollectionMatch[] = [];\n\n for (const c of config.collections) {\n result.push({ slug: c.slug, fields: c.fields, kind: \"collection\" });\n }\n\n if (config.media?.collections) {\n for (const c of config.media.collections) {\n result.push({ slug: c.slug, fields: c.fields, kind: \"media\" });\n }\n }\n\n if (!excludeGlobals) {\n for (const g of config.globals) {\n result.push({ slug: g.slug, fields: g.fields, kind: \"global\" });\n }\n }\n\n return result;\n}\n\n/**\n * Find a collection, media collection, or global by slug across the entire config.\n *\n * Searches in order: collections → media collections → globals.\n * Returns the match with its fields and what kind it is, or null if not found.\n *\n * @param props.slug - The slug to search for\n * @param props.config - The resolved Vex config\n * @param props.excludeGlobals - Skip globals when searching (default: false)\n */\nexport function findCollectionBySlug(props: {\n slug: string;\n config: ConfigShape;\n excludeGlobals?: boolean;\n}): ResolvedCollectionMatch | null {\n return getAllCollections(props).find((c) => c.slug === props.slug) ?? null;\n}\n","import type { CheckboxFieldDef } from \"../../types\";\n\nexport function checkbox(options?: Omit<CheckboxFieldDef, \"type\">): CheckboxFieldDef {\n return {\n type: \"checkbox\",\n ...(options?.required && options?.defaultValue === undefined\n ? { defaultValue: false }\n : {}),\n ...options,\n };\n}\n","const MINOR_WORDS = new Set([\n \"a\",\n \"an\",\n \"and\",\n \"as\",\n // \"at\",\n \"but\",\n \"by\",\n \"for\",\n \"if\",\n \"in\",\n \"nor\",\n \"of\",\n \"on\",\n \"or\",\n \"so\",\n \"the\",\n \"to\",\n \"up\",\n \"yet\",\n]);\n\nexport function toTitleCase(input: string): string {\n const words = input\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .replace(/[_-]+/g, \" \")\n .trim()\n .split(/\\s+/);\n\n return words\n .map((word, i) => {\n const lower = word.toLowerCase();\n if (i > 0 && MINOR_WORDS.has(lower)) return lower;\n return lower.charAt(0).toUpperCase() + lower.slice(1);\n })\n .join(\" \");\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { CheckboxFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a checkbox (boolean) field.\n *\n * @param props.fieldKey - The field name (used as accessorKey)\n * @param props.field - The checkbox field definition\n * @returns A ColumnDef for the checkbox field\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: render \"Yes\" / \"No\" (React rendering with icons is handled by UI layer)\n */\nexport function checkboxColumnDef(props: {\n fieldKey: string;\n field: CheckboxFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n };\n}\n","import { VexFieldValidationError } from \"../errors\";\n\n/**\n * Validates a field's configuration and determines if it should be optional.\n * Called by each per-field valueType function before generating the valueType string.\n *\n * Checks:\n * 1. If required=true and defaultValue is undefined → throw VexFieldValidationError\n * 2. If defaultValue is provided, verify it matches the expected type → throw VexFieldValidationError\n *\n * @param props.field - The field to validate (only needs required and defaultValue)\n * @param props.collectionSlug - The collection slug (for error messages)\n * @param props.fieldName - The field name (for error messages)\n * @param props.expectedType - The expected typeof for defaultValue (e.g., \"string\", \"number\", \"boolean\")\n * @param props.valueType - The Convex value type string (e.g., \"v.string()\")\n * @param props.skipDefaultValidation - Skip defaultValue presence and type checks.\n */\nexport function processFieldValueTypeOptions(props: {\n field: { required?: boolean; defaultValue?: unknown };\n collectionSlug: string;\n fieldName: string;\n expectedType: string;\n valueType: string;\n skipDefaultValidation?: boolean;\n}): string {\n if (!props.field.required) {\n return `v.optional(${props.valueType})`;\n }\n\n if (!props.skipDefaultValidation) {\n if (props.field.defaultValue === undefined) {\n throw new VexFieldValidationError(\n props.collectionSlug,\n props.fieldName,\n \"No defaultValue Provided\",\n );\n }\n if (!(typeof props.field.defaultValue === props.expectedType)) {\n throw new VexFieldValidationError(\n props.collectionSlug,\n props.fieldName,\n `Invalid defaultValue Provided. Expected: ${props.expectedType}, Received: ${typeof props.field.defaultValue}`,\n );\n }\n }\n\n return props.valueType;\n}\n","export const TEXT_VALUETYPE = \"v.string()\" as const;\nexport const NUMBER_VALUETYPE = \"v.number()\" as const;\nexport const CHECKBOX_VALUETYPE = \"v.boolean()\" as const;\nexport const DATE_VALUETYPE = \"v.number()\" as const;\nexport const IMAGEURL_VALUETYPE = \"v.string()\" as const;\nexport const JSON_VALUETYPE = \"v.any()\" as const;\nexport const RICHTEXT_VALUETYPE = \"v.any()\" as const;\n\nexport type { Alignment } from \"../types/fields\";\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { CheckboxFieldDef } from \"../../types\";\nimport { CHECKBOX_VALUETYPE } from \"../constants\";\n\n/**\n * Converts checkbox field definition to a Convex value type string.\n *\n * @returns `\"v.boolean()\"` or `\"v.optional(v.boolean())\"`\n */\nexport function checkboxToValueTypeString(props: {\n field: CheckboxFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"boolean\",\n valueType: CHECKBOX_VALUETYPE,\n });\n}\n","import type { NumberFieldDef } from \"../../types\";\n\nexport function number(options?: Omit<NumberFieldDef, \"type\">): NumberFieldDef {\n return {\n type: \"number\",\n ...(options?.required && options?.defaultValue === undefined\n ? { defaultValue: 0 }\n : {}),\n ...options,\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { NumberFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a number field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: render the number directly\n */\nexport function numberColumnDef(props: {\n fieldKey: string;\n field: NumberFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"right\" },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { NumberFieldDef } from \"../../types\";\nimport { NUMBER_VALUETYPE } from \"../constants\";\n\n/**\n * Converts number field definition to a Convex value type string.\n *\n * @returns `\"v.number()\"` or `\"v.optional(v.number())\"`\n */\nexport function numberToValueTypeString(props: {\n field: NumberFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"number\",\n valueType: NUMBER_VALUETYPE,\n });\n}\n","import type { SelectFieldDef, SelectFieldSingle, SelectFieldMany } from \"../../types\";\n\nexport function select<T extends string = string>(\n options: Omit<SelectFieldMany<T>, \"type\">,\n): SelectFieldDef<T>;\nexport function select<T extends string = string>(\n options: Omit<SelectFieldSingle<T>, \"type\">,\n): SelectFieldDef<T>;\nexport function select<T extends string = string>(\n options: Omit<SelectFieldSingle<T>, \"type\"> | Omit<SelectFieldMany<T>, \"type\">,\n): SelectFieldDef<T> {\n return { type: \"select\", ...options } as SelectFieldDef<T>;\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { SelectFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Default hex colors rotated through when options don't specify a `badgeColor`.\n */\nconst DEFAULT_BADGE_COLORS = [\n \"#3b82f6\", // blue\n \"#22c55e\", // green\n \"#a855f7\", // purple\n \"#f59e0b\", // amber\n \"#f43f5e\", // rose\n \"#06b6d4\", // cyan\n \"#6366f1\", // indigo\n \"#14b8a6\", // teal\n \"#f97316\", // orange\n \"#d946ef\", // fuchsia\n] as const;\n\n/**\n * Builds a ColumnDef for a select field.\n *\n * @param props.fieldKey - The field name (used as accessorKey)\n * @param props.field - The select field definition (includes options for label lookup)\n * @returns A ColumnDef for the select field\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: renders option values as colored badges in a scrollable flex grid\n */\nexport function selectColumnDef(props: {\n fieldKey: string;\n field: SelectFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n const optionMap = new Map(\n props.field.options.map((opt, i) => [\n opt.value,\n {\n label: opt.label,\n color: opt.badgeColor ?? DEFAULT_BADGE_COLORS[i % DEFAULT_BADGE_COLORS.length],\n },\n ]),\n );\n\n return {\n accessorKey: props.fieldKey,\n header:\n (props.field.hasMany\n ? props.field.labels?.singular\n : props.field.label) ?? toTitleCase(props.fieldKey),\n meta: {\n align: props.field.admin?.cellAlignment ?? \"left\",\n noTruncate: true,\n },\n cell: (info) => {\n const raw = info.getValue();\n const values = Array.isArray(raw)\n ? (raw as string[])\n : raw != null\n ? [String(raw)]\n : [];\n\n if (values.length === 0) return null;\n\n return (\n <div className=\"flex flex-wrap gap-1 max-w-[240px] max-h-[60px] overflow-auto\">\n {values.map((v) => {\n const opt = optionMap.get(v);\n return (\n <span\n key={v}\n className=\"inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium text-white shrink-0\"\n style={{ backgroundColor: opt?.color }}\n >\n {opt?.label ?? v}\n </span>\n );\n })}\n </div>\n );\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { SelectFieldDef } from \"../../types\";\n\n/**\n * Converts select field definition to a Convex value type string.\n *\n * @returns One of (each may be wrapped in v.optional()):\n * - Single select: `'v.union(v.literal(\"draft\"),v.literal(\"published\"))'`\n * - Multi select (hasMany): `'v.array(v.union(v.literal(\"draft\"),v.literal(\"published\")))'`\n */\nexport function selectToValueTypeString(props: {\n field: SelectFieldDef<string>;\n collectionSlug: string;\n fieldName: string;\n}): string {\n const literals = props.field.options.map((o) => `v.literal(\"${o.value}\")`).join(\",\");\n\n if (props.field.hasMany) {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: props.field.options.length === 1\n ? `v.array(${literals})`\n : `v.array(v.union(${literals}))`,\n skipDefaultValidation: true,\n });\n }\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: `v.union(${literals})`,\n });\n}\n","import type { TextFieldDef } from \"../../types\";\n\nexport function text(options?: Omit<TextFieldDef, \"type\">): TextFieldDef {\n return {\n type: \"text\",\n ...(options?.required && options?.defaultValue === undefined\n ? { defaultValue: \"\" }\n : {}),\n ...options,\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { TextFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a text field.\n *\n * @param props.fieldKey - The field name (used as accessorKey)\n * @param props.field - The text field definition\n * @returns A ColumnDef for the text field\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? props.fieldKey (capitalize first letter of fieldKey as fallback)\n * - cell: render the value as a string, truncated to 80 characters with ellipsis if longer\n */\nexport function textColumnDef(props: {\n fieldKey: string;\n field: TextFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { TextFieldDef } from \"../../types\";\nimport { TEXT_VALUETYPE } from \"../constants\";\n\n/**\n * Converts text field definition to a Convex value type string.\n *\n * @returns `\"v.string()\"` or `\"v.optional(v.string())\"`\n *\n * minLength/maxLength are runtime validation concerns, not schema constraints.\n * The index property has no effect on the value type (handled by collectIndexes).\n */\nexport function textToValueTypeString(props: {\n field: TextFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: TEXT_VALUETYPE,\n });\n}\n","import type { DateFieldDef } from \"../../types\";\n\nexport function date(options?: Omit<DateFieldDef, \"type\">): DateFieldDef {\n return {\n type: \"date\",\n ...(options?.required && options?.defaultValue === undefined\n ? { defaultValue: 0 }\n : {}),\n ...options,\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { DateFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a date field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: formats epoch ms as a human-readable date string\n */\nexport function dateColumnDef(props: {\n fieldKey: string;\n field: DateFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: {\n align: props.field.admin?.cellAlignment ?? \"left\",\n },\n cell: (info) => {\n const value = info.getValue();\n if (value == null) return \"\";\n return new Date(value as number).toLocaleDateString();\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { DateFieldDef } from \"../../types\";\nimport { DATE_VALUETYPE } from \"../constants\";\n\n/**\n * Converts date field definition to a Convex value type string.\n *\n * @returns `\"v.number()\"` or `\"v.optional(v.number())\"`\n *\n * Dates are stored as epoch milliseconds (number).\n */\nexport function dateToValueTypeString(props: {\n field: DateFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"number\",\n valueType: DATE_VALUETYPE,\n });\n}\n","import type { ImageUrlFieldDef } from \"../../types\";\n\nexport function imageUrl(options?: Omit<ImageUrlFieldDef, \"type\">): ImageUrlFieldDef {\n return {\n type: \"imageUrl\",\n ...(options?.required && options?.defaultValue === undefined\n ? { defaultValue: \"\" }\n : {}),\n ...options,\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { ImageUrlFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for an imageUrl field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: renders an <img> thumbnail with fallback on error\n */\nexport function imageUrlColumnDef(props: {\n fieldKey: string;\n field: ImageUrlFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"center\" },\n cell: (info) => {\n const value = info.getValue();\n if (!value || typeof value !== \"string\") return \"\";\n const size = props.field.width ?? 28;\n const height = props.field.height ?? size;\n return (\n <img\n src={value}\n alt=\"\"\n width={size}\n height={height}\n className=\"rounded-full object-cover bg-muted\"\n style={{ width: size, height }}\n loading=\"lazy\"\n referrerPolicy=\"no-referrer\"\n onError={(e) => {\n (e.currentTarget as any).style.display = \"none\";\n }}\n />\n );\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { ImageUrlFieldDef } from \"../../types\";\nimport { IMAGEURL_VALUETYPE } from \"../constants\";\n\n/**\n * Converts imageUrl field definition to a Convex value type string.\n *\n * @returns `\"v.string()\"` or `\"v.optional(v.string())\"`\n *\n * Image URLs are stored as strings, same schema as text.\n */\nexport function imageUrlToValueTypeString(props: {\n field: ImageUrlFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: IMAGEURL_VALUETYPE,\n });\n}\n","import type { RelationshipFieldDef, RelationshipFieldSingle, RelationshipFieldMany } from \"../../types\";\n\nexport function relationship(\n options: Omit<RelationshipFieldMany, \"type\">,\n): RelationshipFieldDef;\nexport function relationship(\n options: Omit<RelationshipFieldSingle, \"type\">,\n): RelationshipFieldDef;\nexport function relationship(\n options: Omit<RelationshipFieldSingle, \"type\"> | Omit<RelationshipFieldMany, \"type\">,\n): RelationshipFieldDef {\n return { type: \"relationship\", ...options } as RelationshipFieldDef;\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { RelationshipFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a relationship field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - meta: includes relationship info (type, to) for DataTable to fetch related docs\n * - cell: shows raw ID (DataTable component resolves to useAsTitle at render time)\n */\nexport function relationshipColumnDef(props: {\n fieldKey: string;\n field: RelationshipFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: (props.field.hasMany ? props.field.labels?.singular : props.field.label) ?? toTitleCase(props.fieldKey),\n meta: { type: \"relationship\", to: props.field.to, align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (value == null) return \"\";\n if (Array.isArray(value)) return `${value.length} item${value.length === 1 ? \"\" : \"s\"}`;\n return String(value);\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { RelationshipFieldDef } from \"../../types\";\n\n/**\n * Converts relationship field definition to a Convex value type string.\n *\n * @returns\n * - hasMany + required: `v.array(v.id(\"tableName\"))`\n * - hasMany + !required: `v.optional(v.array(v.id(\"tableName\")))`\n * - !hasMany + required: `v.id(\"tableName\")`\n * - !hasMany + !required: `v.optional(v.id(\"tableName\"))`\n */\nexport function relationshipToValueTypeString(props: {\n field: RelationshipFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n const idType = `v.id(\"${props.field.to}\")`;\n const baseValueType = props.field.hasMany ? `v.array(${idType})` : idType;\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: baseValueType,\n skipDefaultValidation: true,\n });\n}\n","import type { JsonFieldDef } from \"../../types\";\n\nexport function json(options?: Omit<JsonFieldDef, \"type\">): JsonFieldDef {\n return {\n type: \"json\",\n ...options,\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { JsonFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a json field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: shows truncated JSON preview\n */\nexport function jsonColumnDef(props: {\n fieldKey: string;\n field: JsonFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (value == null) return \"\";\n const str = JSON.stringify(value);\n return str.length > 50 ? str.slice(0, 50) + \"...\" : str;\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { JsonFieldDef } from \"../../types\";\nimport { JSON_VALUETYPE } from \"../constants\";\n\n/**\n * Converts json field definition to a Convex value type string.\n *\n * @returns\n * - required: `\"v.any()\"`\n * - !required: `\"v.optional(v.any())\"`\n */\nexport function jsonToValueTypeString(props: {\n field: JsonFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: JSON_VALUETYPE,\n skipDefaultValidation: true,\n });\n}\n","import type { ObjectFieldDef } from \"../../types\";\n\nexport function object(options: Omit<ObjectFieldDef, \"type\">): ObjectFieldDef {\n return { type: \"object\", ...options };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { ObjectFieldDef, VexField } from \"../../types\";\n\n/**\n * Converts an object field definition to a Convex value type string.\n *\n * Generates multi-line `v.object({...})` by resolving each sub-field's value type.\n * Each field is placed on its own line to avoid prettier reformatting issues.\n */\nexport function objectToValueTypeString(props: {\n field: ObjectFieldDef;\n collectionSlug: string;\n fieldName: string;\n resolveInnerField: (props: {\n field: VexField;\n collectionSlug: string;\n fieldName: string;\n visitedBlockSlugs?: Set<string>;\n }) => string;\n}): string {\n const fieldEntries: string[] = [];\n\n for (const [subFieldName, subField] of Object.entries(props.field.fields)) {\n const valueType = props.resolveInnerField({\n field: subField as VexField,\n collectionSlug: props.collectionSlug,\n fieldName: `${props.fieldName}.${subFieldName}`,\n });\n fieldEntries.push(`${subFieldName}: ${valueType}`);\n }\n\n const objectType = fieldEntries.length <= 2\n ? `v.object({ ${fieldEntries.join(\", \")} })`\n : `v.object({\\n${fieldEntries.map((e) => ` ${e},`).join(\"\\n\")}\\n})`;\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: objectType,\n skipDefaultValidation: true,\n });\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { ObjectFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for an object field.\n * Shows a truncated JSON preview in the table cell.\n */\nexport function objectColumnDef(props: {\n fieldKey: string;\n field: ObjectFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (value == null) return \"\";\n const str = JSON.stringify(value);\n return str.length > 50 ? str.slice(0, 50) + \"...\" : str;\n },\n };\n}\n","import type { RichTextFieldDef } from \"../../types\";\n\n/**\n * Creates a rich text field definition.\n * Stores Plate/Slate JSON document as `v.any()` in Convex.\n *\n * @param options.label - Display label in admin form\n * @param options.required - Whether this field is required\n * @param options.editor - Per-field editor adapter override\n * @returns A RichTextFieldDef\n *\n * @example\n * ```ts\n * content: richtext({ label: \"Content\", required: true })\n * ```\n */\nexport function richtext(options?: Omit<RichTextFieldDef, \"type\">): RichTextFieldDef {\n return {\n type: \"richtext\",\n ...options,\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { RichTextFieldDef } from \"../../types\";\nimport { RICHTEXT_VALUETYPE } from \"../constants\";\n\n/**\n * Converts richtext field definition to a Convex value type string.\n *\n * @param props.field - The richtext field definition\n * @param props.collectionSlug - The collection this field belongs to\n * @param props.fieldName - The field key name\n * @returns\n * - required: `\"v.any()\"`\n * - !required: `\"v.optional(v.any())\"`\n */\nexport function richtextToValueTypeString(props: {\n field: RichTextFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: RICHTEXT_VALUETYPE,\n skipDefaultValidation: true,\n });\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { RichTextFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a richtext field.\n *\n * @param props.fieldKey - The field key name\n * @param props.field - The richtext field definition\n * @returns ColumnDef that shows \"Rich text\" or empty string in the data table\n */\nexport function richtextColumnDef(props: {\n fieldKey: string;\n field: RichTextFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (value == null) return \"\";\n if (Array.isArray(value) && value.length === 0) return \"\";\n return \"Rich text\";\n },\n };\n}\n","import type { UploadFieldDef, UploadFieldSingle, UploadFieldMany } from \"../../types\";\n\nexport function upload(\n options: Omit<UploadFieldMany, \"type\">,\n): UploadFieldDef;\nexport function upload(\n options: Omit<UploadFieldSingle, \"type\">,\n): UploadFieldDef;\nexport function upload(\n options: Omit<UploadFieldSingle, \"type\"> | Omit<UploadFieldMany, \"type\">,\n): UploadFieldDef {\n return { type: \"upload\", ...options } as UploadFieldDef;\n}\n","import type { UploadFieldDef } from \"../../types\";\nimport { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\n\n/**\n * Converts upload field definition to a Convex value type string.\n *\n * @returns\n * - hasMany + required: `v.array(v.id(\"mediaCollectionSlug\"))`\n * - hasMany + !required: `v.optional(v.array(v.id(\"mediaCollectionSlug\")))`\n * - !hasMany + required: `v.id(\"mediaCollectionSlug\")`\n * - !hasMany + !required: `v.optional(v.id(\"mediaCollectionSlug\"))`\n */\nexport function uploadToValueTypeString(props: {\n field: UploadFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n const idType = `v.id(\"${props.field.to}\")`;\n const baseValueType = props.field.hasMany ? `v.array(${idType})` : idType;\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: baseValueType,\n skipDefaultValidation: true,\n });\n}\n","import type { ArrayFieldDef } from \"../../types\";\n\nexport function array(options: Omit<ArrayFieldDef, \"type\">): ArrayFieldDef {\n return { type: \"array\", ...options };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { ArrayFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for an array field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: shows item count — \"no items\", \"1 item\", \"3 items\"\n */\nexport function arrayColumnDef(props: {\n fieldKey: string;\n field: ArrayFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (!Array.isArray(value) || value.length === 0) return \"no items\";\n if (value.length === 1) return \"1 item\";\n return `${value.length} items`;\n },\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { ArrayFieldDef, VexField } from \"../../types\";\n\n/**\n * Converts array field definition to a Convex value type string.\n *\n * Uses callback injection to resolve the inner field type,\n * avoiding circular imports with fieldToValueType.\n *\n * @returns e.g. `\"v.array(v.string())\"` or `\"v.optional(v.array(v.string()))\"`\n */\nexport function arrayToValueTypeString(props: {\n field: ArrayFieldDef;\n collectionSlug: string;\n fieldName: string;\n resolveInnerField: (props: {\n field: VexField;\n collectionSlug: string;\n fieldName: string;\n }) => string;\n}): string {\n const innerValueType = props.resolveInnerField({\n field: props.field.items,\n collectionSlug: props.collectionSlug,\n fieldName: `${props.fieldName}[]`,\n });\n // Strip v.optional() from inner — array wrapping handles optionality\n // Use a function to find the matching closing paren for v.optional(\n let unwrapped = innerValueType;\n if (unwrapped.startsWith(\"v.optional(\")) {\n // Remove \"v.optional(\" prefix and matching \")\" suffix\n const inner = unwrapped.slice(\"v.optional(\".length);\n // Find the matching closing paren (last char should be \")\")\n if (inner.endsWith(\")\")) {\n unwrapped = inner.slice(0, -1);\n }\n }\n const arrayType = `v.array(${unwrapped})`;\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: arrayType,\n skipDefaultValidation: true,\n });\n}\n","import type { BlocksFieldDef, BlockDef } from \"../../types\";\nimport { VexBlockValidationError } from \"../../errors\";\n\n/**\n * Create a blocks field that stores an ordered array of block instances.\n *\n * @param props.blocks - Array of BlockDef objects allowed in this field\n * @param props.labels - Optional singular/plural display labels\n * @param props.min - Minimum number of blocks\n * @param props.max - Maximum number of blocks\n * @returns A BlocksFieldDef\n *\n * @throws VexBlockValidationError if two blocks share the same slug\n *\n * @example\n * ```ts\n * content: blocks({\n * blocks: [heroBlock, ctaBlock, featureGridBlock],\n * })\n * ```\n */\nexport function blocks(props: {\n blocks: BlockDef[];\n labels?: BlocksFieldDef[\"labels\"];\n min?: number;\n max?: number;\n label?: string;\n description?: string;\n required?: boolean;\n admin?: BlocksFieldDef[\"admin\"];\n}): BlocksFieldDef {\n const seen = new Set<string>();\n for (const block of props.blocks) {\n if (seen.has(block.slug)) {\n throw new VexBlockValidationError(\n block.slug,\n `Duplicate block slug \"${block.slug}\" in blocks field. Each block in a blocks() field must have a unique slug.`,\n );\n }\n seen.add(block.slug);\n }\n\n return {\n type: \"blocks\",\n blocks: props.blocks,\n labels: props.labels,\n min: props.min,\n max: props.max,\n label: props.label,\n description: props.description,\n required: props.required,\n admin: props.admin,\n };\n}\n","import { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\nimport type { BlocksFieldDef, VexField } from \"../../types\";\nimport { VexBlockValidationError } from \"../../errors\";\n\n/**\n * Converts a blocks field definition to a Convex value type string.\n *\n * Generates `v.array(v.union(v.object({...}), v.object({...})))` where each\n * v.object corresponds to a block type with `blockType: v.literal(\"slug\")`\n * as the discriminant, `_key: v.string()`, and each block field converted\n * to its Convex value type.\n *\n * @param props.field - The BlocksFieldDef\n * @param props.collectionSlug - Parent collection slug (for error messages)\n * @param props.fieldName - Field name on the parent collection (for error messages)\n * @param props.resolveInnerField - Callback to resolve inner field value types (avoids circular imports)\n * @param props.visitedBlockSlugs - Set of block slugs already being processed (cycle detection)\n * @returns Convex value type string, e.g. `\"v.array(v.union(v.object({...}), ...))\"`\n *\n * @throws VexBlockValidationError if a cycle is detected in nested blocks\n */\nexport function blocksToValueTypeString(props: {\n field: BlocksFieldDef;\n collectionSlug: string;\n fieldName: string;\n resolveInnerField: (props: {\n field: VexField;\n collectionSlug: string;\n fieldName: string;\n visitedBlockSlugs?: Set<string>;\n }) => string;\n visitedBlockSlugs?: Set<string>;\n}): string {\n const visited = props.visitedBlockSlugs ?? new Set<string>();\n\n if (props.field.blocks.length === 0) {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: \"v.array(v.any())\",\n skipDefaultValidation: true,\n });\n }\n\n const objectTypes: string[] = [];\n\n for (const block of props.field.blocks) {\n if (visited.has(block.slug)) {\n throw new VexBlockValidationError(\n block.slug,\n `Circular block reference detected: block \"${block.slug}\" references itself (directly or through a cycle).`,\n );\n }\n\n const blockVisited = new Set(visited);\n blockVisited.add(block.slug);\n\n const fieldEntries: string[] = [\n `blockType: v.literal(\"${block.slug}\")`,\n `blockName: v.optional(v.string())`,\n `blockStyles: v.optional(v.string())`,\n `_key: v.string()`,\n ];\n\n for (const [fieldName, field] of Object.entries(block.fields)) {\n const valueType = props.resolveInnerField({\n field: field as VexField,\n collectionSlug: props.collectionSlug,\n fieldName: `${props.fieldName}.${block.slug}.${fieldName}`,\n visitedBlockSlugs: blockVisited,\n });\n fieldEntries.push(`${fieldName}: ${valueType}`);\n }\n\n objectTypes.push(\n `v.object({\\n${fieldEntries.map((e) => ` ${e},`).join(\"\\n\")}\\n})`,\n );\n }\n\n const innerType =\n objectTypes.length === 1\n ? objectTypes[0]\n : `v.union(\\n${objectTypes.map((o) => ` ${o},`).join(\"\\n\")}\\n)`;\n\n const arrayType = `v.array(\\n${innerType}\\n)`;\n\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"object\",\n valueType: arrayType,\n skipDefaultValidation: true,\n });\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { BlocksFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for a blocks field.\n *\n * Behavior:\n * - accessorKey: props.fieldKey\n * - header: props.field.label ?? toTitleCase(props.fieldKey)\n * - cell: shows block count — \"no blocks\", \"1 block\", \"3 blocks\"\n * Uses field.labels if provided (e.g., \"1 section\", \"3 sections\").\n */\nexport function blocksColumnDef(props: {\n fieldKey: string;\n field: BlocksFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n const singular = props.field.labels?.singular ?? \"block\";\n const plural = props.field.labels?.plural ?? \"blocks\";\n\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? toTitleCase(props.fieldKey),\n meta: { align: props.field.admin?.cellAlignment ?? \"left\" },\n cell: (info) => {\n const value = info.getValue();\n if (!Array.isArray(value) || value.length === 0) return `no ${plural}`;\n if (value.length === 1) return `1 ${singular}`;\n return `${value.length} ${plural}`;\n },\n };\n}\n","import type { ColorFieldDef } from \"../../types/fields\";\n\n/**\n * Creates a color field definition.\n *\n * @param props - Color field configuration\n * @param props.label - Display label in admin panel\n * @param props.format - Output format: \"hex\" (default), \"hsl\", or \"oklch\"\n * @param props.themeColors - When true, shows theme CSS variable picker tab\n * @returns ColorFieldDef\n */\nexport function color(props?: Omit<ColorFieldDef, \"type\">): ColorFieldDef {\n return {\n ...props,\n type: \"color\" as const,\n };\n}\n","import type { ColorFieldDef } from \"../../types/fields\";\nimport { TEXT_VALUETYPE } from \"../constants\";\nimport { processFieldValueTypeOptions } from \"../../valueTypes/processAdminOptions\";\n\n/**\n * Convert a color field to its Convex schema value type string.\n * Color fields store strings (hex, hsl, or oklch) so they use v.string().\n */\nexport function colorToValueTypeString(props: {\n field: ColorFieldDef;\n collectionSlug: string;\n fieldName: string;\n}): string {\n return processFieldValueTypeOptions({\n field: props.field,\n collectionSlug: props.collectionSlug,\n fieldName: props.fieldName,\n expectedType: \"string\",\n valueType: TEXT_VALUETYPE,\n });\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { ColorFieldDef } from \"../../types/fields\";\n\n/**\n * Generate a column definition for a color field.\n * Shows the color value as text with a color swatch indicator.\n */\nexport function colorColumnDef(props: {\n fieldKey: string;\n field: ColorFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: props.field.label ?? props.fieldKey,\n size: 120,\n cell: (info) => {\n const value = info.getValue() as string | undefined;\n if (!value) return \"\";\n return value;\n },\n meta: {\n type: \"color\" as const,\n },\n };\n}\n","import { VexFieldValidationError } from \"../errors\";\nimport { checkboxToValueTypeString } from \"../fields/checkbox\";\nimport { numberToValueTypeString } from \"../fields/number\";\nimport { selectToValueTypeString } from \"../fields/select\";\nimport { textToValueTypeString } from \"../fields/text\";\nimport { dateToValueTypeString } from \"../fields/date\";\nimport { imageUrlToValueTypeString } from \"../fields/imageUrl\";\nimport { relationshipToValueTypeString } from \"../fields/relationship\";\nimport { jsonToValueTypeString } from \"../fields/json\";\nimport { objectToValueTypeString } from \"../fields/object\";\nimport { richtextToValueTypeString } from \"../fields/richtext\";\nimport { uploadToValueTypeString } from \"../fields/media\";\nimport { arrayToValueTypeString } from \"../fields/array\";\nimport { blocksToValueTypeString } from \"../fields/blocks\";\nimport { colorToValueTypeString } from \"../fields/color\";\nimport type { VexField } from \"../types\";\n\n/**\n * Converts a VexField to its Convex value type string representation.\n * Dispatches to the appropriate per-field function based on `type`.\n *\n * Each per-field function handles its own validation (via processFieldValueTypeOptions())\n * and its own v.optional() wrapping. This dispatcher just routes by type.\n */\nexport function fieldToValueType(props: {\n field: VexField;\n collectionSlug: string;\n fieldName: string;\n visitedBlockSlugs?: Set<string>;\n}): string {\n const { field, collectionSlug, fieldName } = props;\n switch (field.type) {\n case \"text\":\n return textToValueTypeString({ field, collectionSlug, fieldName });\n case \"number\":\n return numberToValueTypeString({ field, collectionSlug, fieldName });\n case \"checkbox\":\n return checkboxToValueTypeString({ field, collectionSlug, fieldName });\n case \"select\":\n return selectToValueTypeString({ field, collectionSlug, fieldName });\n case \"date\":\n return dateToValueTypeString({ field, collectionSlug, fieldName });\n case \"imageUrl\":\n return imageUrlToValueTypeString({ field, collectionSlug, fieldName });\n case \"relationship\":\n return relationshipToValueTypeString({ field, collectionSlug, fieldName });\n case \"upload\":\n return uploadToValueTypeString({ field, collectionSlug, fieldName });\n case \"json\":\n return jsonToValueTypeString({ field, collectionSlug, fieldName });\n case \"object\":\n return objectToValueTypeString({\n field,\n collectionSlug,\n fieldName,\n resolveInnerField: fieldToValueType,\n });\n case \"richtext\":\n return richtextToValueTypeString({ field, collectionSlug, fieldName });\n case \"array\":\n return arrayToValueTypeString({\n field,\n collectionSlug,\n fieldName,\n resolveInnerField: fieldToValueType,\n });\n case \"blocks\":\n return blocksToValueTypeString({\n field,\n collectionSlug,\n fieldName,\n resolveInnerField: (innerProps) =>\n fieldToValueType({\n field: innerProps.field,\n collectionSlug: innerProps.collectionSlug,\n fieldName: innerProps.fieldName,\n visitedBlockSlugs: innerProps.visitedBlockSlugs,\n }),\n visitedBlockSlugs: props.visitedBlockSlugs,\n });\n case \"color\":\n return colorToValueTypeString({ field, collectionSlug, fieldName });\n case \"tabs\":\n // Tabs are expanded by generate.ts's expandFields(), not here\n return \"v.any()\";\n case \"ui\":\n throw new VexFieldValidationError(\n collectionSlug,\n fieldName,\n `UI field \"${fieldName}\" on collection \"${collectionSlug}\" has no database representation and should not be included in schema generation.`,\n );\n default:\n throw new VexFieldValidationError(\n collectionSlug,\n fieldName,\n `Unknown Field Type: ${(field as any).type}`,\n );\n }\n}\n","import { VexFieldValidationError } from \"../errors\";\nimport type {\n VexCollection,\n VexField,\n ResolvedIndex,\n} from \"../types\";\n\n/**\n * Collects all indexes for a collection from three sources:\n * 1. Per-field `index` property on individual fields\n * 2. Collection-level `indexes` array on the collection\n * 3. Auto-generated index for `admin.useAsTitle` field (for fast admin panel title queries)\n *\n * @param collection - The collection to extract indexes from\n * @returns Array of resolved indexes, deduplicated by name\n */\nexport function collectIndexes(props: { collection: VexCollection }): ResolvedIndex[] {\n const { collection } = props;\n const fieldIndexes = new Map<string, ResolvedIndex>();\n\n for (const [fieldKey, field] of Object.entries(collection.fields) as [string, VexField][]) {\n const indexName = field.index;\n if (indexName) {\n if (fieldIndexes.has(indexName)) {\n throw new VexFieldValidationError(\n collection.slug,\n fieldKey,\n `Duplicate Indexes detected: ${indexName}`,\n );\n }\n fieldIndexes.set(indexName, { name: indexName, fields: [fieldKey] });\n }\n }\n\n collection.indexes?.forEach((index) => {\n fieldIndexes.set(index.name, { name: index.name, fields: index.fields });\n });\n\n const useAsTitle = collection.admin?.useAsTitle as string;\n if (useAsTitle && useAsTitle !== \"_id\") {\n const autoName = `by_${useAsTitle}`;\n if (!fieldIndexes.has(autoName)) {\n fieldIndexes.set(autoName, { name: autoName, fields: [useAsTitle] });\n }\n }\n\n return Array.from(fieldIndexes.values());\n}\n","import { VexFieldValidationError } from \"../errors\";\nimport type {\n VexCollection,\n VexField,\n ResolvedSearchIndex,\n} from \"../types\";\n\n/**\n * Collects all search indexes for a collection from three sources:\n * 1. Per-field `searchIndex` property on individual fields\n * 2. Collection-level `searchIndexes` array on the collection\n * 3. Auto-generated search index for `admin.useAsTitle` field\n *\n * @param collection - The collection to extract search indexes from\n * @returns Array of resolved search indexes, deduplicated by name\n */\nexport function collectSearchIndexes(props: { collection: VexCollection }): ResolvedSearchIndex[] {\n const { collection } = props;\n const searchIndexes = new Map<string, ResolvedSearchIndex>();\n\n for (const [fieldKey, field] of Object.entries(collection.fields) as [string, VexField][]) {\n const searchIndex = field.searchIndex;\n if (searchIndex && searchIndex.name) {\n if (searchIndexes.has(searchIndex.name)) {\n throw new VexFieldValidationError(\n collection.slug,\n fieldKey,\n `Duplicate search index name: ${searchIndex.name}`,\n );\n }\n searchIndexes.set(searchIndex.name, {\n name: searchIndex.name,\n searchField: fieldKey,\n filterFields: searchIndex.filterFields,\n });\n }\n }\n\n collection.searchIndexes?.forEach((entry) => {\n searchIndexes.set(entry.name, {\n name: entry.name,\n searchField: entry.searchField,\n filterFields: entry.filterFields ?? [],\n });\n });\n\n const useAsTitle = collection.admin?.useAsTitle as string;\n if (useAsTitle && useAsTitle !== \"_id\") {\n const autoName = `search_${useAsTitle}`;\n const alreadyCovered = Array.from(searchIndexes.values()).some(\n (si) => si.searchField === useAsTitle,\n );\n if (!alreadyCovered && !searchIndexes.has(autoName)) {\n searchIndexes.set(autoName, {\n name: autoName,\n searchField: useAsTitle,\n filterFields: [],\n });\n }\n }\n\n return Array.from(searchIndexes.values());\n}\n","import type { VexField } from \"../types\";\nimport type { VexCollection } from \"../types\";\nimport type { ResolvedIndex, ResolvedSearchIndex } from \"../types\";\n\n/**\n * Result of merging an auth collection with a user collection.\n * Contains merged VexFields and metadata about field sources.\n */\nexport interface MergedCollectionResult {\n /**\n * The final merged field map.\n * Key is field name, value is the VexField object.\n * Auth fields win for schema generation; user admin config is preserved.\n */\n fields: Record<string, VexField>;\n\n /** Indexes from both auth and user collections (deduplicated by name). */\n indexes: ResolvedIndex[];\n\n /** Search indexes from the user collection. */\n searchIndexes: ResolvedSearchIndex[];\n\n /**\n * Fields that exist in both auth collection and user config.\n * The auth VexField wins for schema gen; user admin config wins for UI.\n */\n overlapping: string[];\n\n /** Fields that only exist in the auth collection (not in user's collection). */\n authOnly: string[];\n\n /** Fields that only exist in the user's collection (not from auth). */\n userOnly: string[];\n}\n\n/**\n * Merges an auth collection's fields with a user-defined collection's fields.\n *\n * Both sides are VexField records. For overlapping fields, the auth\n * VexField's schema properties are used (it controls the DB shape), but\n * the user's admin config (label, hidden, etc.) is preserved by copying\n * admin-related metadata from the user's field onto the auth field.\n *\n * @param authCollection - The auth collection with fully resolved fields\n * @param userCollection - The user's collection that matches this auth table by slug\n * @returns Merged collection result with combined fields and source tracking\n */\nexport function mergeAuthCollectionWithUserCollection(props: {\n authCollection: VexCollection;\n userCollection: VexCollection;\n}): MergedCollectionResult {\n const { authCollection, userCollection } = props;\n const fields: Record<string, VexField> = {};\n const overlapping: string[] = [];\n const authOnly: string[] = [];\n const userOnly: string[] = [];\n\n const authFields = authCollection.fields;\n const userFields = userCollection.fields;\n const authFieldKeys = Object.keys(authFields);\n const userFieldKeys = Object.keys(userFields);\n\n // Process auth fields\n for (const fieldKey of authFieldKeys) {\n if (userFieldKeys.includes(fieldKey)) {\n overlapping.push(fieldKey);\n // Auth field wins for schema, but user field wins for rendering.\n // Use user's field as base so type, label, admin, etc. are preserved,\n // then layer auth's schema-relevant props (required, defaultValue).\n const authField = authFields[fieldKey];\n const userField = userFields[fieldKey];\n fields[fieldKey] = {\n ...userField,\n required: authField.required,\n ...((authField as any).defaultValue !== undefined && { defaultValue: (authField as any).defaultValue }),\n } as VexField;\n } else {\n authOnly.push(fieldKey);\n fields[fieldKey] = authFields[fieldKey];\n }\n }\n\n // Process user-only fields\n for (const fieldKey of userFieldKeys) {\n if (authFieldKeys.includes(fieldKey)) continue;\n userOnly.push(fieldKey);\n fields[fieldKey] = userFields[fieldKey];\n }\n\n // Merge indexes (auth indexes first, user indexes added if name doesn't conflict)\n const indexes: ResolvedIndex[] = [];\n const indexNames = new Set<string>();\n\n // Auth collection indexes (from collection-level)\n for (const idx of authCollection.indexes ?? []) {\n indexes.push({ name: idx.name, fields: idx.fields as string[] });\n indexNames.add(idx.name);\n }\n\n // User collection indexes\n for (const idx of userCollection.indexes ?? []) {\n if (!indexNames.has(idx.name)) {\n indexes.push({ name: idx.name, fields: idx.fields as string[] });\n indexNames.add(idx.name);\n }\n }\n\n // Search indexes from user collection\n const searchIndexes: ResolvedSearchIndex[] = (\n userCollection.searchIndexes ?? []\n ).map((si) => ({\n name: si.name,\n searchField: si.searchField as string,\n filterFields: (si.filterFields ?? []) as string[],\n }));\n\n return { fields, indexes, searchIndexes, overlapping, authOnly, userOnly };\n}\n","import { VexSlugConflictError } from \"../errors\";\nimport type { VexConfig } from \"../types\";\n\n// =============================================================================\n// SLUG REGISTRY — tracks table slugs and validates uniqueness on register\n// =============================================================================\n\n/**\n * Where a slug was registered from.\n */\nexport const SLUG_SOURCES = {\n userCollection: \"user-collection\",\n userGlobal: \"user-global\",\n authTable: \"auth-table\",\n mediaCollection: \"media-collection\",\n system: \"system\",\n} as const;\nexport type SlugSource = (typeof SLUG_SOURCES)[keyof typeof SLUG_SOURCES];\n\n/**\n * A registered slug with its source information.\n */\nexport interface SlugRegistration {\n slug: string;\n source: SlugSource;\n /** Human-readable description of where this slug was defined */\n location: string;\n}\n\n/**\n * Registry that collects all table slugs and validates uniqueness.\n * Throws immediately on duplicate — fail fast during schema generation.\n */\nexport class SlugRegistry {\n private registrations = new Map<string, SlugRegistration>();\n\n /**\n * Register a slug with its source.\n * Throws VexSlugConflictError immediately if the slug is already registered,\n * UNLESS an auth table slug overlaps with a user collection slug — this is\n * expected behavior indicating the user wants to customize that auth table's\n * admin UI. In that case, the user collection's registration takes precedence\n * (it was registered first as \"user-collection\") and the auth table is\n * silently skipped in the registry. The merge happens during schema generation.\n *\n * @param props.slug - The table slug to register\n * @param props.source - Where this slug comes from (e.g., \"user-collection\", \"auth-table\")\n * @param props.location - Human-readable location for error messages (e.g., `collection \"posts\"`)\n *\n * Edge cases:\n * - Auth table slug matches user collection slug: NOT a conflict — skip\n * registration (user collection already registered, merge happens later)\n * - System table prefixed with \"vex_\" should not conflict with user tables\n * because defineCollection already warns about \"vex_\" prefix\n */\n register(props: {\n slug: string;\n source: SlugSource;\n location: string;\n }): void {\n const existing = this.registrations.get(props.slug);\n if (existing) {\n // Auth table overlapping with user collection is expected — it means\n // the user wants to customize that auth table. The user collection\n // registration takes precedence; merge happens during schema generation.\n if (\n (existing.source === \"user-collection\" &&\n props.source === \"auth-table\") ||\n (existing.source === \"auth-table\" && props.source === \"user-collection\")\n ) {\n // Keep the user-collection registration, skip the auth-table one\n if (props.source === \"user-collection\") {\n this.registrations.set(props.slug, {\n slug: props.slug,\n source: props.source,\n location: props.location,\n });\n }\n return;\n }\n throw new VexSlugConflictError(\n props.slug,\n existing.source,\n existing.location,\n props.source,\n props.location,\n );\n }\n this.registrations.set(props.slug, {\n slug: props.slug,\n source: props.source,\n location: props.location,\n });\n }\n\n /**\n * Get all registered slugs.\n */\n getAll(): SlugRegistration[] {\n return [...this.registrations.values()];\n }\n}\n\n/**\n * Populate a SlugRegistry from a VexConfig.\n *\n * Registers slugs from:\n * 1. User collections (source: \"user-collection\")\n * 2. User globals (source: \"user-global\")\n * 3. Auth tables (source: \"auth-table\") — including the user table\n * 4. System tables like vex_globals (source: \"system\")\n *\n * Each register() call throws immediately on duplicate slug, except\n * when an auth table slug matches a user collection slug — this is\n * expected behavior indicating the user wants to customize that auth\n * table's admin UI. The merge happens during schema generation.\n *\n * Edge cases:\n * - No globals: skip global registration\n * - Auth table slug matches user collection slug: NOT a conflict —\n * the user collection registration takes precedence, merge happens later\n */\nexport function buildSlugRegistry(props: { config: VexConfig }): SlugRegistry {\n const registry = new SlugRegistry();\n\n for (const collection of props.config.collections) {\n registry.register({\n slug: collection.slug,\n source: SLUG_SOURCES.userCollection,\n location: `Collection ${collection.slug}`,\n });\n }\n\n // Register media collection slugs\n if (props.config.media) {\n for (const collection of props.config.media.collections) {\n registry.register({\n slug: collection.slug,\n source: SLUG_SOURCES.mediaCollection,\n location: `Media Collection ${collection.slug}`,\n });\n }\n }\n\n for (const global of props.config.globals) {\n registry.register({\n slug: global.slug,\n source: SLUG_SOURCES.userGlobal,\n location: `Global ${global.slug}`,\n });\n }\n\n for (const collection of props.config.auth.collections) {\n registry.register({\n slug: collection.slug,\n source: SLUG_SOURCES.authTable,\n location: `Auth Table ${collection.slug}`,\n });\n }\n\n return registry;\n}\n","import type { ResolvedIndex, ResolvedSearchIndex, VexConfig, VexField } from \"../types\";\nimport type { TabsFieldDef } from \"../types/fields\";\nimport { fieldToValueType } from \"./extract\";\nimport { collectIndexes } from \"./indexes\";\nimport { collectSearchIndexes } from \"./searchIndexes\";\nimport { mergeAuthCollectionWithUserCollection } from \"./merge\";\nimport { buildSlugRegistry } from \"./slugs\";\n\n/**\n * Expand a record of fields into flat name/valueType pairs,\n * handling tabs fields by expanding their sub-fields.\n * Each tab produces a v.optional(v.object({ ... })) entry keyed by its slug.\n */\nfunction expandFields(props: {\n fields: Record<string, VexField>;\n collectionSlug: string;\n}): { name: string; valueType: string }[] {\n const result: { name: string; valueType: string }[] = [];\n\n for (const [fieldName, field] of Object.entries(props.fields) as [string, VexField][]) {\n if (field.type === \"ui\") continue;\n\n if (field.type === \"tabs\") {\n const tabsField = field as TabsFieldDef;\n for (const tab of tabsField.tabs) {\n const innerFields: string[] = [];\n for (const [innerName, innerField] of Object.entries(tab.fields) as [string, VexField][]) {\n if (innerField.type === \"ui\") continue;\n const innerValueType = fieldToValueType({\n field: innerField,\n collectionSlug: props.collectionSlug,\n fieldName: innerName,\n });\n innerFields.push(`${innerName}: ${innerValueType}`);\n }\n if (innerFields.length > 0) {\n result.push({\n name: tab.slug,\n valueType: `v.optional(v.object({ ${innerFields.join(\", \")} }))`,\n });\n }\n }\n } else {\n result.push({\n name: fieldName,\n valueType: fieldToValueType({\n fieldName,\n field,\n collectionSlug: props.collectionSlug,\n }),\n });\n }\n }\n\n return result;\n}\n\n/**\n * Generates the full TypeScript source content for `convex/vex.schema.ts`.\n *\n * This is the main entry point for schema generation. It:\n * 1. Validates all slugs are unique (via SlugRegistry)\n * 2. For each auth collection, checks if a matching user collection exists (by slug):\n * a. If yes: merges auth collection fields with user collection fields\n * b. If no matching collection: generates the auth collection as-is\n * 3. User collections that don't match any auth collection: generates from collection fields only\n * 4. Collects indexes from per-field `index` properties and collection-level `indexes`\n * 5. Generates defineTable() calls for each table with chained .index() calls\n * 6. Generates defineTable() calls for system tables (vex_globals if globals exist)\n *\n * All fields go through fieldToValueType() uniformly — no dual path for auth vs user.\n */\nexport function generateVexSchema(props: { config: VexConfig }): string {\n const config = props.config;\n buildSlugRegistry({ config });\n const authCollectionMap = new Map(\n config.auth.collections.map((c) => [c.slug, c]),\n );\n const mergedAuthSlugs = new Set<string>();\n\n const lines: string[] = [\n \"// ⚠️ AUTO-GENERATED BY VEX CMS — DO NOT EDIT ⚠️\",\n \"\",\n 'import { defineTable } from \"convex/server\";',\n 'import { v } from \"convex/values\";',\n ];\n\n if (config.collections.length > 0) {\n lines.push(\"\", \"/**\", \" * USER COLLECTIONS\", \" **/\");\n }\n\n for (const collection of config.collections) {\n const authCollection = authCollectionMap.get(collection.slug);\n const fields: { name: string; valueType: string }[] = [];\n const indexes: ResolvedIndex[] = collectIndexes({ collection });\n const searchIndexes: ResolvedSearchIndex[] = collectSearchIndexes({\n collection,\n });\n\n if (authCollection) {\n mergedAuthSlugs.add(authCollection.slug);\n const merged = mergeAuthCollectionWithUserCollection({\n authCollection,\n userCollection: collection,\n });\n\n // All merged fields go through fieldToValueType uniformly\n for (const [name, field] of Object.entries(merged.fields)) {\n if (field.type === \"ui\") continue; // UI fields have no database representation\n fields.push({\n name,\n valueType: fieldToValueType({\n field,\n collectionSlug: collection.slug,\n fieldName: name,\n }),\n });\n }\n\n // Add merged indexes (deduplicated)\n for (const index of merged.indexes) {\n if (indexes.find((ui) => ui.name === index.name)) continue;\n indexes.push(index);\n }\n\n // Add merged search indexes\n for (const si of merged.searchIndexes) {\n if (searchIndexes.find((existing) => existing.name === si.name))\n continue;\n searchIndexes.push(si);\n }\n } else {\n fields.push(...expandFields({\n fields: collection.fields as Record<string, VexField>,\n collectionSlug: collection.slug,\n }));\n }\n\n lines.push(\n \"\",\n `export const ${collection.tableName ?? collection.slug} = defineTable({`,\n );\n for (const f of fields) {\n lines.push(` ${f.name}: ${f.valueType},`);\n }\n // vex_status on all user collections — defaults to \"published\"\n lines.push(` vex_status: v.optional(v.union(v.literal(\"draft\"), v.literal(\"published\"))),`);\n if (collection.versions?.drafts) {\n lines.push(` vex_version: v.optional(v.number()),`);\n lines.push(` vex_publishedAt: v.optional(v.number()),`);\n }\n lines.push(\"})\");\n for (const i of indexes) {\n const fieldList = i.fields.map((f) => `\"${f}\"`).join(\", \");\n lines.push(` .index(\"${i.name}\", [${fieldList}])`);\n }\n for (const si of searchIndexes) {\n const filterList =\n si.filterFields.length > 0\n ? `, filterFields: [${si.filterFields.map((f) => `\"${f}\"`).join(\", \")}]`\n : \"\";\n lines.push(\n ` .searchIndex(\"${si.name}\", { searchField: \"${si.searchField}\"${filterList} })`,\n );\n }\n }\n\n // --- MEDIA COLLECTIONS ---\n if (config.media && config.media.collections.length > 0) {\n lines.push(\"\", \"/**\", \" * MEDIA COLLECTIONS\", \" **/\");\n\n for (const mediaCollection of config.media.collections) {\n const fields: { name: string; valueType: string }[] = [];\n const indexes: ResolvedIndex[] = collectIndexes({ collection: mediaCollection });\n const searchIndexes: ResolvedSearchIndex[] = collectSearchIndexes({\n collection: mediaCollection,\n });\n\n for (const [fieldName, field] of Object.entries(\n mediaCollection.fields,\n ) as [string, VexField][]) {\n if (field.type === \"ui\") continue;\n if (fieldName === \"storageId\") {\n // Use adapter's storageIdValueType instead of fieldToValueType\n fields.push({\n name: fieldName,\n valueType: config.media.storageAdapter.storageIdValueType,\n });\n } else {\n fields.push({\n name: fieldName,\n valueType: fieldToValueType({\n fieldName,\n field,\n collectionSlug: mediaCollection.slug,\n }),\n });\n }\n }\n\n lines.push(\n \"\",\n `export const ${mediaCollection.tableName ?? mediaCollection.slug} = defineTable({`,\n );\n for (const f of fields) {\n lines.push(` ${f.name}: ${f.valueType},`);\n }\n lines.push(\"})\");\n for (const i of indexes) {\n const fieldList = i.fields.map((f) => `\"${f}\"`).join(\", \");\n lines.push(` .index(\"${i.name}\", [${fieldList}])`);\n }\n for (const si of searchIndexes) {\n const filterList =\n si.filterFields.length > 0\n ? `, filterFields: [${si.filterFields.map((f) => `\"${f}\"`).join(\", \")}]`\n : \"\";\n lines.push(\n ` .searchIndex(\"${si.name}\", { searchField: \"${si.searchField}\"${filterList} })`,\n );\n }\n }\n }\n\n const unmergedAuthCollections = config.auth.collections.filter(\n (c) => !mergedAuthSlugs.has(c.slug),\n );\n\n if (unmergedAuthCollections.length > 0) {\n lines.push(\"\", \"/**\", \" * AUTH TABLES\", \" **/\");\n }\n\n for (const authCollection of unmergedAuthCollections) {\n const indexes: ResolvedIndex[] = collectIndexes({\n collection: authCollection,\n });\n lines.push(\n \"\",\n `export const ${authCollection.tableName ?? authCollection.slug} = defineTable({`,\n );\n for (const [name, field] of Object.entries(authCollection.fields) as [string, VexField][]) {\n lines.push(\n ` ${name}: ${fieldToValueType({\n field,\n collectionSlug: authCollection.slug,\n fieldName: name,\n })},`,\n );\n }\n lines.push(\"})\");\n for (const i of indexes) {\n const fieldList = i.fields.map((f) => `\"${f}\"`).join(\", \");\n lines.push(` .index(\"${i.name}\", [${fieldList}])`);\n }\n }\n\n for (const global of config.globals) {\n const fields: { name: string; valueType: string }[] = [];\n const indexes: ResolvedIndex[] = collectIndexes({ collection: global });\n for (const [fieldName, field] of Object.entries(global.fields)) {\n fields.push({\n name: fieldName,\n valueType: fieldToValueType({\n fieldName,\n field,\n collectionSlug: global.slug,\n }),\n });\n }\n\n lines.push(\n \"\",\n `export const ${global.tableName ?? global.slug} = defineTable({`,\n );\n for (const f of fields) {\n lines.push(` ${f.name}: ${f.valueType},`);\n }\n // vex_status on all globals — defaults to \"published\"\n lines.push(` vex_status: v.optional(v.union(v.literal(\"draft\"), v.literal(\"published\"))),`);\n if ((global as any).versions?.drafts) {\n lines.push(` vex_version: v.optional(v.number()),`);\n lines.push(` vex_publishedAt: v.optional(v.number()),`);\n }\n lines.push(\"})\");\n for (const i of indexes) {\n const fieldList = i.fields.map((f) => `\"${f}\"`).join(\", \");\n lines.push(` .index(\"${i.name}\", [${fieldList}])`);\n }\n }\n\n // Always generate vex_versions so removing versioning from a collection\n // doesn't break schema.ts imports that reference vex_versions.\n {\n lines.push(\"\", \"/**\", \" * VEX SYSTEM TABLES\", \" **/\");\n lines.push(\"\");\n lines.push(\"export const vex_versions = defineTable({\");\n lines.push(\" collection: v.string(),\");\n lines.push(\" documentId: v.string(),\");\n lines.push(\" version: v.number(),\");\n lines.push(\" status: v.union(\");\n lines.push(` v.literal(\"draft\"),`);\n lines.push(` v.literal(\"published\"),`);\n lines.push(` v.literal(\"autosave\"),`);\n lines.push(` v.literal(\"previewSnapshot\"),`);\n lines.push(\" ),\");\n lines.push(\" snapshot: v.any(),\");\n lines.push(\" createdAt: v.number(),\");\n lines.push(\" createdBy: v.optional(v.string()),\");\n lines.push(\" isAutosave: v.boolean(),\");\n lines.push(\" restoredFrom: v.optional(v.number()),\");\n lines.push(\"})\");\n lines.push(` .index(\"by_document\", [\"collection\", \"documentId\"])`);\n lines.push(` .index(\"by_document_version\", [\"collection\", \"documentId\", \"version\"])`);\n lines.push(` .index(\"by_document_latest\", [\"collection\", \"documentId\", \"createdAt\"])`);\n lines.push(` .index(\"by_document_status\", [\"collection\", \"documentId\", \"status\"])`);\n lines.push(` .index(\"by_autosave\", [\"collection\", \"documentId\", \"isAutosave\"])`);\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","import { defineTable, type TableDefinition } from \"convex/server\";\nimport type { GenericValidator, ObjectType, VObject } from \"convex/values\";\n\ntype ExtractFields<T> =\n T extends TableDefinition<VObject<any, infer F>> ? F : never;\n\ntype ForbidExistingKeys<Existing, New> = {\n [K in keyof New]: K extends keyof Existing ? never : New[K];\n};\n\n/**\n * Compute the TableDefinition type that preserves field types.\n * Matches the second overload of defineTable:\n * defineTable(fields) → TableDefinition<VObject<ObjectType<Fields>, Fields>>\n */\ntype ExtendedTableDef<Fields extends Record<string, GenericValidator>> =\n TableDefinition<VObject<ObjectType<Fields>, Fields>>;\n\n/**\n * Extends a vex-generated table definition with additional fields,\n * preserving all indexes from the original table.\n *\n * Use this in your `convex/schema.ts` when you need to add custom\n * fields to a vex-managed table (e.g., adding a `body` field to posts).\n *\n * @param props.table - The table definition from vex.schema.ts\n * @param props.additionalFields - Additional Convex validator fields to add.\n * Keys that already exist on the table will cause a type error.\n * @returns A new TableDefinition with merged fields and original indexes.\n * You can chain additional `.index()` calls on the result.\n *\n * @example\n * ```ts\n * import { posts } from \"./vex.schema\";\n * import { extendTable } from \"@vexcms/core\";\n * import { v } from \"convex/values\";\n *\n * export default defineSchema({\n * posts: extendTable({\n * table: posts,\n * additionalFields: { body: v.optional(v.string()) },\n * }).index(\"by_status\", [\"status\"]),\n * });\n * ```\n */\nexport function extendTable<\n T extends TableDefinition<VObject<any, any>>,\n A extends Record<string, GenericValidator> = {},\n>(props: {\n table: T;\n additionalFields?: A & ForbidExistingKeys<ExtractFields<T>, A>;\n}): ExtendedTableDef<ExtractFields<T> & A> {\n const { validator } = props.table;\n\n let extended = defineTable({\n ...validator.fields,\n ...props.additionalFields,\n });\n\n // Use the public \" indexes\"() method (note: the method name has a leading space)\n for (const idx of props.table[\" indexes\"]()) {\n extended = extended.index(\n idx.indexDescriptor,\n idx.fields as [string, ...string[]],\n );\n }\n\n // searchIndexes and vectorIndexes are private — access via any cast\n const source = props.table as any;\n\n for (const idx of source.searchIndexes ?? []) {\n extended = extended.searchIndex(idx.indexDescriptor, {\n searchField: idx.searchField,\n filterFields: idx.filterFields,\n } as any);\n }\n\n for (const idx of source.vectorIndexes ?? []) {\n extended = extended.vectorIndex(idx.indexDescriptor, {\n vectorField: idx.vectorField,\n dimensions: idx.dimensions,\n filterFields: idx.filterFields,\n } as any);\n }\n\n return extended as ExtendedTableDef<ExtractFields<T> & A>;\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { UploadFieldDef } from \"../../types\";\nimport { toTitleCase } from \"../../utils\";\n\n/**\n * Builds a ColumnDef for an upload field.\n *\n * The cell renders the raw document ID by default. Consumers (e.g., admin-next)\n * can replace the cell renderer using the column meta to show a file preview.\n *\n * Meta includes `type: \"upload\"` and `to` (target collection slug) so that\n * the rendering layer can detect upload columns and provide custom rendering.\n */\nexport function uploadColumnDef(props: {\n fieldKey: string;\n field: UploadFieldDef;\n}): ColumnDef<Record<string, unknown>> {\n return {\n accessorKey: props.fieldKey,\n header: (props.field.hasMany ? props.field.labels?.singular : props.field.label) ?? toTitleCase(props.fieldKey),\n meta: {\n type: \"upload\",\n to: props.field.to,\n noTruncate: true,\n },\n cell: (info) => {\n const value = info.getValue();\n if (!value || typeof value !== \"string\") return \"\";\n return value;\n },\n };\n}\n","import type { ColumnDef } from \"@tanstack/react-table\";\nimport type { VexAuthAdapter, VexCollection, VexField } from \"../types\";\nimport { textColumnDef } from \"../fields/text/columnDef\";\nimport { numberColumnDef } from \"../fields/number/columnDef\";\nimport { checkboxColumnDef } from \"../fields/checkbox/columnDef\";\nimport { selectColumnDef } from \"../fields/select/columnDef\";\nimport { dateColumnDef } from \"../fields/date/columnDef\";\nimport { imageUrlColumnDef } from \"../fields/imageUrl/columnDef\";\nimport { relationshipColumnDef } from \"../fields/relationship/columnDef\";\nimport { jsonColumnDef } from \"../fields/json/columnDef\";\nimport { objectColumnDef } from \"../fields/object/columnDef\";\nimport { richtextColumnDef } from \"../fields/richtext/columnDef\";\nimport { arrayColumnDef } from \"../fields/array/columnDef\";\nimport { uploadColumnDef } from \"../fields/media/columnDef\";\nimport { blocksColumnDef } from \"../fields/blocks/columnDef\";\nimport { colorColumnDef } from \"../fields/color/columnDef\";\nimport { toTitleCase } from \"../utils\";\n\n/**\n * Generates an array of ColumnDef objects from a VexCollection's field configs.\n *\n * @param props.collection - The collection to generate columns for\n * @param props.auth - Optional auth adapter. When provided, auth fields (e.g. createdAt)\n * get proper columnDef dispatch instead of falling back to plain text columns.\n * @returns Array of ColumnDef objects for use with @tanstack/react-table\n */\nexport function generateColumns(props: {\n collection: VexCollection;\n auth?: VexAuthAdapter;\n}): ColumnDef<Record<string, unknown>>[] {\n const { collection, auth } = props;\n const columns: ColumnDef<Record<string, unknown>>[] = [];\n const useAsTitle = collection.admin?.useAsTitle as string | undefined;\n const defaultColumns = collection.admin?.defaultColumns as\n | string[]\n | undefined;\n const fields = collection.fields;\n\n // Build a lookup of auth fields for this collection's slug\n const authFields: Record<string, VexField> = {};\n if (auth) {\n const authCollection = auth.collections.find(\n (c: VexCollection) => c.slug === collection.slug,\n );\n if (authCollection) {\n for (const [k, v] of Object.entries(authCollection.fields) as [\n string,\n VexField,\n ][]) {\n authFields[k] = v;\n }\n }\n }\n\n if (defaultColumns) {\n for (const fieldKey of defaultColumns) {\n if (fieldKey === \"_id\") {\n columns.push({ accessorKey: \"_id\", header: \"ID\" });\n continue;\n }\n\n const field = (fields[fieldKey] ?? authFields[fieldKey]) as\n | VexField\n | undefined;\n\n if (!field) {\n columns.push({ accessorKey: fieldKey, header: toTitleCase(fieldKey) });\n continue;\n }\n\n if (field.admin?.hidden) continue;\n if (field.type === \"ui\" || field.type === \"tabs\") continue;\n\n const col = buildColumnDef(fieldKey, field);\n\n if (useAsTitle && fieldKey === useAsTitle) {\n col.meta = { ...col.meta, isTitle: true };\n }\n\n // Attach custom Cell component to meta if present\n if (field.admin?.components?.Cell) {\n col.meta = {\n ...col.meta,\n customCell: field.admin.components.Cell,\n fieldDef: field,\n };\n }\n\n columns.push(col);\n }\n } else {\n columns.push({ accessorKey: \"_id\", header: \"ID\" });\n\n // Collect all field keys: user fields first, then auth-only fields\n const allFieldKeys = new Set(Object.keys(fields));\n for (const k of Object.keys(authFields)) {\n allFieldKeys.add(k);\n }\n\n for (const fieldKey of allFieldKeys) {\n const field = (fields[fieldKey] ?? authFields[fieldKey]) as VexField;\n if (field.admin?.hidden) continue;\n if (field.type === \"ui\" || field.type === \"tabs\") continue;\n\n const col = buildColumnDef(fieldKey, field);\n\n if (useAsTitle && fieldKey === useAsTitle) {\n col.meta = { ...col.meta, isTitle: true };\n }\n\n // Attach custom Cell component to meta if present\n if (field.admin?.components?.Cell) {\n col.meta = {\n ...col.meta,\n customCell: field.admin.components.Cell,\n fieldDef: field,\n };\n }\n\n columns.push(col);\n }\n }\n\n return columns;\n}\n\nfunction buildColumnDef(\n fieldKey: string,\n field: VexField,\n): ColumnDef<Record<string, unknown>> {\n switch (field.type) {\n case \"text\":\n return textColumnDef({ fieldKey, field });\n case \"number\":\n return numberColumnDef({ fieldKey, field });\n case \"checkbox\":\n return checkboxColumnDef({ fieldKey, field });\n case \"select\":\n return selectColumnDef({ fieldKey, field });\n case \"date\":\n return dateColumnDef({ fieldKey, field });\n case \"imageUrl\":\n return imageUrlColumnDef({ fieldKey, field });\n case \"relationship\":\n return relationshipColumnDef({ fieldKey, field });\n case \"json\":\n return jsonColumnDef({ fieldKey, field });\n case \"object\":\n return objectColumnDef({ fieldKey, field });\n case \"richtext\":\n return richtextColumnDef({ fieldKey, field });\n case \"array\":\n return arrayColumnDef({ fieldKey, field });\n case \"upload\":\n return uploadColumnDef({ fieldKey, field });\n case \"blocks\":\n return blocksColumnDef({ fieldKey, field });\n case \"color\":\n return colorColumnDef({ fieldKey, field });\n default:\n return {\n accessorKey: fieldKey,\n header: toTitleCase(fieldKey),\n };\n }\n}\n","import { z, type ZodTypeAny } from \"zod\";\nimport type { VexField } from \"../types\";\n\n/**\n * Generate a Zod schema from a collection's field definitions.\n * Used by both the client-side form (for validation on submit)\n * and the server-side mutation (for payload validation).\n *\n * @param props.fields - Record of field name → VexField from the collection\n * @returns A z.object() schema matching the collection's editable fields\n */\nexport function generateFormSchema(props: {\n fields: Record<string, VexField>;\n}): z.ZodObject<Record<string, ZodTypeAny>> {\n const shape: Record<string, ZodTypeAny> = {};\n\n for (const [fieldName, field] of Object.entries(props.fields)) {\n if (field.admin?.hidden) continue;\n if (field.type === \"ui\") continue;\n\n // Tabs expand into slug-keyed z.object() entries\n if (field.type === \"tabs\") {\n for (const tab of field.tabs) {\n const tabFields: Record<string, ZodTypeAny> = {};\n for (const [subName, subField] of Object.entries(tab.fields)) {\n if (subField.type === \"ui\") continue;\n let subValidator = fieldMetaToZod({ field: subField });\n if (!subField.required) subValidator = subValidator.optional();\n tabFields[subName] = subValidator;\n }\n shape[tab.slug] = z.object(tabFields).optional();\n }\n continue;\n }\n\n let validator = fieldMetaToZod({ field });\n\n if (!field.required) {\n validator = validator.optional();\n }\n\n shape[fieldName] = validator;\n }\n\n return z.object(shape);\n}\n\n/**\n * Convert a single field to its Zod validator.\n * Does NOT handle optional wrapping — that's done by the caller.\n *\n * @param props.field - The field definition (discriminated on `type`)\n * @returns The base Zod type for this field (always required)\n */\nexport function fieldMetaToZod(props: { field: VexField }): ZodTypeAny {\n switch (props.field.type) {\n case \"text\": {\n let schema = z.string();\n if (props.field.minLength != null) schema = schema.min(props.field.minLength);\n if (props.field.maxLength != null) schema = schema.max(props.field.maxLength);\n return schema;\n }\n\n case \"number\": {\n let schema = z.number();\n if (props.field.min != null) schema = schema.min(props.field.min);\n if (props.field.max != null) schema = schema.max(props.field.max);\n return schema;\n }\n\n case \"checkbox\":\n return z.boolean();\n\n case \"select\": {\n const values = props.field.options.map((o) => o.value);\n if (values.length === 0) return z.string();\n const enumSchema = z.enum(values as [string, ...string[]]);\n if (props.field.hasMany) {\n return z.array(enumSchema);\n }\n return enumSchema;\n }\n\n case \"date\":\n return z.number();\n\n case \"imageUrl\":\n return z.string().url().or(z.literal(\"\"));\n\n case \"relationship\": {\n if (props.field.hasMany) {\n return z.array(z.string());\n }\n return z.string();\n }\n\n case \"upload\": {\n if (props.field.hasMany) {\n return z.array(z.string());\n }\n return z.string();\n }\n\n case \"json\":\n return z.any();\n\n case \"object\": {\n const shape: Record<string, ZodTypeAny> = {};\n for (const [subName, subField] of Object.entries(props.field.fields)) {\n let subValidator = fieldMetaToZod({ field: subField as VexField });\n if (!(subField as VexField).required) subValidator = subValidator.optional();\n shape[subName] = subValidator;\n }\n return z.object(shape);\n }\n\n case \"richtext\":\n return z.any();\n\n case \"color\":\n return z.string();\n\n case \"tabs\":\n // Tabs are expanded in generateFormSchema's loop, not here\n return z.any();\n\n case \"array\": {\n let schema = z.array(fieldMetaToZod({ field: props.field.items }));\n if (props.field.min != null) schema = schema.min(props.field.min);\n if (props.field.max != null) schema = schema.max(props.field.max);\n return schema;\n }\n\n case \"blocks\": {\n const blockSchemas = props.field.blocks.map((blockDef) => {\n const shape: Record<string, ZodTypeAny> = {\n blockType: z.literal(blockDef.slug),\n blockName: z.string().optional(),\n _key: z.string(),\n };\n for (const [fieldName, field] of Object.entries(blockDef.fields)) {\n let validator = fieldMetaToZod({ field: field as VexField });\n if (!(field as VexField).required) {\n validator = validator.optional();\n }\n shape[fieldName] = validator;\n }\n return z.object(shape);\n });\n\n if (blockSchemas.length === 0) {\n let schema = z.array(z.any());\n if (props.field.min != null) schema = schema.min(props.field.min);\n if (props.field.max != null) schema = schema.max(props.field.max);\n return schema;\n }\n\n const union =\n blockSchemas.length === 1\n ? blockSchemas[0]\n : z.discriminatedUnion(\n \"blockType\",\n blockSchemas as [z.ZodObject<any>, z.ZodObject<any>, ...z.ZodObject<any>[]],\n );\n\n let schema = z.array(union);\n if (props.field.min != null) schema = schema.min(props.field.min);\n if (props.field.max != null) schema = schema.max(props.field.max);\n return schema;\n }\n\n default:\n return z.any();\n }\n}\n","import type { VexField } from \"../types\";\n\n/**\n * Compute the zero-value for a field type (used as initial form value).\n */\nfunction getFormDefaultValue(props: { field: VexField }): unknown {\n switch (props.field.type) {\n case \"text\":\n return props.field.defaultValue ?? \"\";\n case \"number\":\n return props.field.defaultValue ?? 0;\n case \"checkbox\":\n return props.field.defaultValue ?? false;\n case \"select\":\n if (props.field.hasMany) {\n return props.field.defaultValue ? [props.field.defaultValue] : [];\n }\n return props.field.defaultValue ?? \"\";\n case \"date\":\n return props.field.defaultValue ?? 0;\n case \"imageUrl\":\n return props.field.defaultValue ?? \"\";\n case \"relationship\":\n return props.field.hasMany ? [] : undefined;\n case \"upload\":\n return props.field.hasMany ? [] : undefined;\n case \"json\":\n return {};\n case \"object\": {\n const defaults: Record<string, unknown> = {};\n for (const [subName, subField] of Object.entries(props.field.fields)) {\n defaults[subName] = getFormDefaultValue({ field: subField });\n }\n return defaults;\n }\n case \"richtext\":\n return [];\n case \"color\":\n return props.field.defaultValue ?? \"\";\n case \"tabs\":\n return {};\n case \"array\":\n return props.field.defaultValue ?? [];\n case \"blocks\":\n return [];\n case \"ui\":\n return undefined;\n default:\n return undefined;\n }\n}\n\n/**\n * Generate default values for a create form from a collection's field definitions.\n * Skips hidden fields.\n *\n * @param props.fields - Record of field name -> VexField from the collection\n * @returns Record of field name -> default value for the create form\n */\nexport function generateFormDefaultValues(props: {\n fields: Record<string, VexField>;\n}): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [fieldName, field] of Object.entries(props.fields)) {\n if (field.admin?.hidden) continue;\n if (field.type === \"ui\") continue;\n\n // Tabs expand into slug-keyed objects with sub-field defaults\n if (field.type === \"tabs\") {\n for (const tab of field.tabs) {\n const tabDefaults: Record<string, unknown> = {};\n for (const [subName, subField] of Object.entries(tab.fields)) {\n if (subField.type === \"ui\") continue;\n tabDefaults[subName] = getFormDefaultValue({ field: subField });\n }\n result[tab.slug] = tabDefaults;\n }\n continue;\n }\n\n result[fieldName] = getFormDefaultValue({ field });\n }\n\n return result;\n}\n","import type { UIFieldDef, FieldAdminConfig, FieldComponentProps } from \"../../types\";\nimport type { ComponentType } from \"react\";\n\n/**\n * Creates a UI field — a non-persisted field that renders a custom component.\n * UI fields are skipped during schema generation, form validation, and column generation.\n * They are useful for computed displays, action buttons, and embedded widgets.\n *\n * @param props.label - Display label for the field\n * @param props.admin - Admin config. components.Field is required.\n * @param props.description - Helper text displayed below the field\n * @returns A UIFieldDef\n *\n * @example\n * ```ts\n * import { ui } from \"@vexcms/core\";\n * import WordCount from \"~/components/admin/WordCount\";\n *\n * const collection = defineCollection({\n * slug: \"posts\",\n * fields: {\n * wordCount: ui({\n * label: \"Word Count\",\n * admin: {\n * components: { Field: WordCount },\n * position: \"sidebar\",\n * },\n * }),\n * },\n * });\n * ```\n */\nexport function ui(props: {\n label?: string;\n admin: FieldAdminConfig & {\n components: {\n Field: ComponentType<FieldComponentProps>;\n };\n };\n description?: string;\n}): UIFieldDef {\n return {\n type: \"ui\" as const,\n label: props.label,\n description: props.description,\n admin: props.admin,\n };\n}\n","import type { TabDef, TabsFieldDef } from \"../../types/fields\";\n\n/**\n * Creates a tabs field definition.\n * Groups fields into tabbed UI sections in the admin panel.\n *\n * Tabs with `slug` create nested objects in the document.\n * Tabs without `slug` flatten their fields onto the parent.\n *\n * @param props - Tabs field configuration\n * @param props.tabs - Array of tab definitions with label, optional slug, and fields\n * @returns TabsFieldDef with preserved tab slug and field type information\n */\nexport function tabs<const TTabs extends TabDef[]>(\n props: Omit<TabsFieldDef<TTabs>, \"type\">,\n): TabsFieldDef<TTabs> {\n return {\n ...props,\n type: \"tabs\" as const,\n };\n}\n","// =============================================================================\n// FIELD TYPES — Object-based configuration\n// =============================================================================\n\nimport type { ComponentType } from \"react\";\nimport type { StyleTier } from \"../styles/types\";\n\n/** Content alignment for data table cells. */\nexport type Alignment = \"left\" | \"right\" | \"center\";\nexport type Labels = {\n singular: string;\n plural: string;\n};\n\n/**\n * Props passed to custom field components.\n * Custom components receive these props and use useVexField() for state.\n *\n * Use the generic parameter to narrow the field type for type-safe access\n * to field-specific properties like `options` on select fields.\n *\n * @example\n * ```tsx\n * // Generic — fieldDef has label, admin, description, required\n * function MyField({ name, fieldDef, readOnly }: FieldComponentProps) { ... }\n *\n * // Narrowed — fieldDef is TextFieldDef with maxLength, minLength, etc.\n * function MyTextField({ name, fieldDef }: FieldComponentProps<TextFieldDef>) { ... }\n * ```\n */\nexport interface FieldComponentProps<TField extends VexField = VexField> {\n /** The field key name (e.g., \"primaryColor\") */\n name: string;\n /** The VexField definition for this field */\n fieldDef: TField;\n /** Whether the field is read-only (from permissions or config) */\n readOnly: boolean;\n}\n\n/**\n * Props passed to custom cell components in the data table.\n */\nexport interface CellComponentProps<TField extends VexField = VexField> {\n /** The raw cell value from the document */\n value: unknown;\n /** The full row data (document) */\n row: Record<string, unknown>;\n /** The VexField definition for this column's field */\n fieldDef: TField;\n}\n\n/**\n * Admin panel configuration for individual fields.\n * Controls visibility, layout, and input behavior in the admin UI.\n */\nexport interface FieldAdminConfig {\n /**\n * Hide this field from the admin form.\n * Hidden fields are still stored in the database.\n *\n * Default: `false`\n */\n hidden?: boolean;\n /**\n * Make this field read-only in the admin form.\n * The value is displayed but cannot be edited.\n *\n * Default: `false`\n */\n readOnly?: boolean;\n /**\n * Position of the field in the form layout.\n *\n * - `\"main\"` — placed in the main content area\n * - `\"sidebar\"` — placed in the sidebar panel\n *\n * Default: `\"main\"`\n */\n position?: \"main\" | \"sidebar\";\n /**\n * Width of the field within its row.\n *\n * - `\"full\"` — spans the full width\n * - `\"half\"` — spans half the width (two fields per row)\n *\n * Default: `\"full\"`\n */\n width?: \"full\" | \"half\";\n /**\n * Placeholder text shown in the input when empty.\n */\n placeholder?: string;\n /**\n * Helper text displayed below the field input.\n * Use for additional context or formatting hints.\n */\n description?: string;\n /**\n * Content alignment in data table cells. 'left' | 'right' | 'center'\n */\n cellAlignment?: Alignment;\n /**\n * Custom components for this field.\n *\n * - `Field` replaces the entire field input in the edit form.\n * Only allowed on text, number, checkbox, and select fields.\n * The component receives FieldComponentProps and uses useVexField() for state.\n *\n * - `Cell` replaces the cell renderer in the data table list view.\n * Allowed on any field type.\n */\n components?: {\n Field?: ComponentType<FieldComponentProps>;\n Cell?: ComponentType<CellComponentProps>;\n };\n}\n\n// =============================================================================\n// BASE FIELD PROPERTIES (shared by all field types)\n// =============================================================================\n\n/**\n * Properties shared by all field types.\n * Each concrete field type extends this with its `type` discriminant\n * and type-specific options.\n */\ninterface BaseField {\n /** Display label for the field in the admin form. */\n label?: string;\n /** Description text shown below the field. */\n description?: string;\n /**\n * Whether this field is required.\n *\n * Default: `false`\n */\n required?: boolean;\n /** Admin UI configuration for this field. */\n admin?: FieldAdminConfig;\n /**\n * Create a database index on this field.\n * The string value becomes the index name in Convex.\n *\n * @example\n * ```ts\n * slug: { type: \"text\", index: \"by_slug\", required: true }\n * // Generates: .index(\"by_slug\", [\"slug\"])\n * ```\n */\n index?: string;\n /**\n * Create a full-text search index on this field.\n * The field this is defined on becomes the `searchField`.\n *\n * @example\n * ```ts\n * title: {\n * type: \"text\",\n * searchIndex: { name: \"search_title\", filterFields: [\"status\", \"author\"] },\n * }\n * // Generates: .searchIndex(\"search_title\", { searchField: \"title\", filterFields: [\"status\", \"author\"] })\n * ```\n */\n searchIndex?: {\n /** Search index name (must be unique within the collection). */\n name: string;\n /**\n * Fields to filter search results by.\n * String array — validated at runtime against collection field names.\n */\n filterFields: string[];\n };\n}\n\n// =============================================================================\n// CONCRETE FIELD TYPES\n// =============================================================================\n\n/** Text field definition. */\nexport interface TextFieldDef extends BaseField {\n readonly type: \"text\";\n /** Default value for new documents. */\n defaultValue?: string;\n /** Minimum character length. */\n minLength?: number;\n /** Maximum character length. */\n maxLength?: number;\n}\n\n/** Number field definition. */\nexport interface NumberFieldDef extends BaseField {\n readonly type: \"number\";\n /** Default value for new documents. */\n defaultValue?: number;\n /** Minimum allowed value. */\n min?: number;\n /** Maximum allowed value. */\n max?: number;\n /** Step increment for the input. */\n step?: number;\n}\n\n/** Checkbox field definition. */\nexport interface CheckboxFieldDef extends BaseField {\n readonly type: \"checkbox\";\n /** Default value for new documents. */\n defaultValue?: boolean;\n}\n\n/**\n * A single option in a select field.\n */\nexport interface SelectOption<T extends string = string> {\n /** The stored value. */\n readonly value: T;\n /** The display label shown in the dropdown. */\n readonly label: string;\n /** Optional badge color for the data table. Accepts a hex string (e.g. \"#3b82f6\"). */\n readonly badgeColor?: string;\n}\n\n/** Select field — single value variant. */\nexport interface SelectFieldSingle<T extends string = string> extends BaseField {\n readonly type: \"select\";\n /** The available options for this select field. */\n options: readonly SelectOption<T>[];\n /** Default value for new documents. */\n defaultValue?: T;\n hasMany?: false;\n}\n\n/** Select field — multi-value variant. */\nexport interface SelectFieldMany<T extends string = string> extends BaseField {\n readonly type: \"select\";\n /** The available options for this select field. */\n options: readonly SelectOption<T>[];\n /** Default value for new documents. */\n defaultValue?: T;\n /** Display labels for the field (singular/plural). */\n labels?: Labels;\n hasMany: true;\n}\n\n/** Select field definition with typed options. Discriminated on `hasMany`. */\nexport type SelectFieldDef<T extends string = string> =\n | SelectFieldSingle<T>\n | SelectFieldMany<T>;\n\n/** Date field definition. Stores epoch milliseconds. */\nexport interface DateFieldDef extends BaseField {\n readonly type: \"date\";\n /** Default value for new documents (epoch ms). */\n defaultValue?: number;\n}\n\n/** Image URL field definition. Stores a URL string, renders as thumbnail. */\nexport interface ImageUrlFieldDef extends BaseField {\n readonly type: \"imageUrl\";\n /** Default value for new documents. */\n defaultValue?: string;\n /** Width (px) of the image */\n width?: number;\n /** Height (px) of the image */\n height?: number;\n}\n\n/** Relationship field — single reference variant. */\nexport interface RelationshipFieldSingle extends BaseField {\n readonly type: \"relationship\";\n /** Target table name. */\n to: string;\n hasMany?: false;\n}\n\n/** Relationship field — multi-reference variant. */\nexport interface RelationshipFieldMany extends BaseField {\n readonly type: \"relationship\";\n /** Target table name. */\n to: string;\n /** Display labels for the field (singular/plural). */\n labels?: Labels;\n hasMany: true;\n}\n\n/** Relationship field definition. Discriminated on `hasMany`. */\nexport type RelationshipFieldDef = RelationshipFieldSingle | RelationshipFieldMany;\n\n/** Shared upload field properties. */\ninterface UploadFieldBase extends BaseField {\n readonly type: \"upload\";\n /** Target media collection slug. */\n to: string;\n /**\n * Accepted MIME types for file uploads.\n * Supports exact types (\"image/png\") and wildcards (\"image/*\").\n * When not set, all file types are accepted.\n */\n accept?: string[];\n /**\n * Maximum file size in bytes for uploads.\n * When not set, no size limit is enforced (beyond storage provider limits).\n */\n maxSize?: number;\n}\n\n/** Upload field — single reference variant. */\nexport interface UploadFieldSingle extends UploadFieldBase {\n hasMany?: false;\n}\n\n/** Upload field — multi-reference variant. */\nexport interface UploadFieldMany extends UploadFieldBase {\n /** Display labels for the field (singular/plural). */\n labels?: Labels;\n hasMany: true;\n}\n\n/**\n * Upload field definition. References a media collection document via `v.id()`.\n * Discriminated on `hasMany`.\n */\nexport type UploadFieldDef = UploadFieldSingle | UploadFieldMany;\n\n/** JSON field definition. Stores arbitrary data via `v.any()`. */\nexport interface JsonFieldDef extends BaseField {\n readonly type: \"json\";\n}\n\n/** Object field definition. Stores a named group of sub-fields as `v.object()`. */\nexport interface ObjectFieldDef extends BaseField {\n readonly type: \"object\";\n /** Named sub-fields that make up this object. */\n fields: Record<string, VexField>;\n}\n\n/** Array field definition. Wraps an inner field in `v.array()`. */\nexport interface ArrayFieldDef extends BaseField {\n readonly type: \"array\";\n /** Display labels for the field (singular/plural). */\n labels?: Labels;\n /** The field type for each item in the array. */\n items: VexField;\n /** Default value for the array (used when creating new documents/blocks). */\n defaultValue?: unknown[];\n /** Minimum number of items. */\n min?: number;\n /** Maximum number of items. */\n max?: number;\n}\n\nimport type { VexEditorAdapter, RichTextDocument } from \"./editor\";\n\n/** Rich text field definition. Stores Plate/Slate JSON via `v.any()`. */\nexport interface RichTextFieldDef extends BaseField {\n readonly type: \"richtext\";\n /**\n * Editor adapter override for this specific field.\n * If not set, uses the global editor from `VexConfig.editor`.\n */\n editor?: VexEditorAdapter;\n /**\n * Media collection slug for image uploads.\n * When set, the editor can pick images from the specified media collection,\n * and paste/drop image uploads are auto-saved to this collection.\n * When not set, images can only be inserted by URL.\n */\n mediaCollection?: string;\n}\n\n/**\n * Color picker field. Stores a color string in the configured format.\n *\n * @example\n * ```ts\n * accentColor: color({ label: \"Accent Color\", format: \"hex\" })\n * primaryColor: color({ label: \"Primary\", format: \"oklch\", themeColors: true })\n * ```\n */\nexport interface ColorFieldDef extends BaseField {\n readonly type: \"color\";\n /**\n * Default color value.\n * Should be in the configured format (hex, hsl, or oklch).\n */\n defaultValue?: string;\n /**\n * Output format for the color value.\n * - \"hex\" — e.g., \"#3b82f6\" (default)\n * - \"hsl\" — e.g., \"hsl(217, 91%, 60%)\"\n * - \"oklch\" — e.g., \"oklch(0.623 0.214 259.1)\"\n */\n format?: \"hex\" | \"hsl\" | \"oklch\";\n /**\n * When true, shows a \"Theme Colors\" tab in the color picker\n * that displays CSS variables from the current page's computed styles.\n * Users can select a theme color variable instead of picking a custom color.\n *\n * Default: false\n */\n themeColors?: boolean;\n}\n\n/**\n * A single tab definition within a tabs field.\n */\nexport interface TabDef<\n TSlug extends string = string,\n TFields extends Record<string, VexField> = Record<string, VexField>,\n> {\n /** Display label for the tab in the admin panel. */\n label: string;\n /**\n * All fields in this tab are nested under this key as an object.\n * e.g., `slug: \"light\"` → `{ light: { background: \"#fff\", ... } }`\n */\n slug: TSlug;\n /** Fields within this tab. */\n fields: TFields;\n}\n\n/**\n * Tabs field definition. Groups fields into tabbed UI sections in the admin panel.\n *\n * - Tabs with `slug` create nested objects in the document\n * - Tabs without `slug` flatten their fields onto the parent\n *\n * @example\n * ```ts\n * themeColors: tabs({\n * label: \"Theme Colors\",\n * tabs: [\n * {\n * label: \"Light\",\n * slug: \"light\",\n * fields: {\n * background: color({ label: \"Background\" }),\n * foreground: color({ label: \"Foreground\" }),\n * },\n * },\n * {\n * label: \"Dark\",\n * slug: \"dark\",\n * fields: {\n * background: color({ label: \"Background\" }),\n * foreground: color({ label: \"Foreground\" }),\n * },\n * },\n * ],\n * })\n * ```\n */\nexport interface TabsFieldDef<TTabs extends TabDef[] = TabDef[]> extends BaseField {\n readonly type: \"tabs\";\n /** The tab definitions. */\n tabs: TTabs;\n}\n\n/**\n * UI field definition. Non-persisted — renders a custom component only.\n * Skipped during schema generation, form validation, and column generation.\n * Requires admin.components.Field to be set.\n */\nexport interface UIFieldDef extends BaseField {\n readonly type: \"ui\";\n /**\n * Admin config — components.Field is required for ui fields.\n */\n admin: FieldAdminConfig & {\n components: {\n Field: ComponentType<FieldComponentProps>;\n };\n };\n}\n\n// =============================================================================\n// BLOCK TYPES\n// =============================================================================\n\n/**\n * Admin configuration specific to block definitions.\n */\nexport interface BlockAdminConfig {\n /** Icon identifier for the block picker UI (e.g., \"layout-template\"). */\n icon?: string;\n /** Custom admin components for this block (future — Spec 09b). */\n components?: {\n Editor?: ComponentType<any>;\n };\n /**\n * Enable block style controls in the admin panel.\n *\n * - `true` — enables container styles only (equivalent to `[\"container\"]`)\n * - `StyleTier[]` — enables specific style tiers (e.g., `[\"container\", \"text\", \"media\"]`)\n * - `undefined` / omitted — no style controls shown\n *\n * Available tiers: \"container\", \"text\", \"layout\", \"media\"\n */\n blockStyles?: true | StyleTier[];\n}\n\n/**\n * A block definition created by `defineBlock()`.\n * Blocks are reusable field groups composed into ordered lists via the `blocks()` field type.\n *\n * @example\n * ```ts\n * const heroBlock = defineBlock({\n * slug: \"hero\",\n * label: \"Hero Section\",\n * fields: { heading: text({ required: true }), subheading: text() },\n * })\n * ```\n */\nexport interface BlockDef<TFields extends Record<string, VexField> = Record<string, VexField>> {\n /** Unique identifier for this block type. Used as the `blockType` discriminant in stored data. */\n readonly slug: string;\n /** Display label for the block in the admin picker. */\n label: string;\n /** Field definitions for this block's data shape. */\n fields: TFields;\n /** Admin UI configuration. */\n admin?: BlockAdminConfig;\n /**\n * TypeScript interface name used in generated `vex.types.ts`.\n * If not set, auto-generated from slug via PascalCase conversion.\n * @example \"HeroBlock\"\n */\n interfaceName?: string;\n}\n\n/** Reserved field names that cannot be used in block field definitions. */\nexport const RESERVED_BLOCK_FIELD_NAMES = [\"blockType\", \"blockName\", \"_key\", \"blockStyles\"] as const;\n\n/** Blocks field definition. Stores an ordered array of block instances. */\nexport interface BlocksFieldDef extends BaseField {\n readonly type: \"blocks\";\n /** The block definitions allowed in this field. */\n blocks: BlockDef[];\n /** Display labels for the field (singular/plural). */\n labels?: Labels;\n /** Minimum number of blocks. */\n min?: number;\n /** Maximum number of blocks. */\n max?: number;\n}\n\n// =============================================================================\n// UTILITY TYPES\n// =============================================================================\n\n/**\n * Distributive version of `Omit` that preserves union branches.\n * Standard `Omit` collapses unions; this applies `Omit` to each branch individually.\n */\nexport type DistributiveOmit<T, K extends PropertyKey> = T extends unknown\n ? Omit<T, K>\n : never;\n\n// =============================================================================\n// DISCRIMINATED UNION\n// =============================================================================\n\n/**\n * Discriminated union of all field types. Switch on `field.type` to narrow.\n *\n * @example\n * ```ts\n * function handle(field: VexField) {\n * switch (field.type) {\n * case \"text\":\n * field.maxLength; // TextFieldDef ✓\n * break;\n * case \"select\":\n * field.options; // SelectFieldDef ✓\n * break;\n * }\n * }\n * ```\n */\nexport type VexField =\n | TextFieldDef\n | NumberFieldDef\n | CheckboxFieldDef\n | SelectFieldDef<string>\n | DateFieldDef\n | ImageUrlFieldDef\n | RelationshipFieldDef\n | UploadFieldDef\n | JsonFieldDef\n | ObjectFieldDef\n | ArrayFieldDef\n | RichTextFieldDef\n | UIFieldDef\n | BlocksFieldDef\n | ColorFieldDef\n | TabsFieldDef;\n\n// =============================================================================\n// TYPE INFERENCE\n// =============================================================================\n\n/**\n * Infer the TypeScript value type from a VexField.\n * Uses the `type` discriminant and field options to determine the type.\n */\nexport type InferFieldType<F extends VexField> = F extends { type: \"text\" }\n ? string\n : F extends { type: \"number\" }\n ? number\n : F extends { type: \"checkbox\" }\n ? boolean\n : F extends { type: \"select\"; hasMany: true }\n ? string[]\n : F extends { type: \"select\" }\n ? string\n : F extends { type: \"date\" }\n ? number\n : F extends { type: \"imageUrl\" }\n ? string\n : F extends { type: \"relationship\"; hasMany: true }\n ? string[]\n : F extends { type: \"relationship\" }\n ? string\n : F extends { type: \"upload\"; hasMany: true }\n ? string[]\n : F extends { type: \"upload\" }\n ? string\n : F extends { type: \"json\" }\n ? unknown\n : F extends { type: \"object\" }\n ? Record<string, unknown>\n : F extends { type: \"richtext\" }\n ? RichTextDocument\n : F extends { type: \"blocks\" }\n ? Array<InferBlockUnion<F>>\n : F extends { type: \"array\" }\n ? unknown[]\n : F extends { type: \"ui\" }\n ? never\n : F extends { type: \"color\" }\n ? string\n : F extends { type: \"tabs\" }\n ? Record<string, unknown>\n : never;\n\n/**\n * Infer the discriminated union type for a blocks field.\n * Each block becomes an object type with `blockType` literal + `_key` + its field types.\n */\nexport type InferBlockUnion<F extends VexField> = F extends BlocksFieldDef\n ? F[\"blocks\"][number] extends infer B\n ? B extends BlockDef<infer TFields>\n ? { blockType: B[\"slug\"]; blockName?: string; _key: string } & {\n [K in keyof TFields]: InferFieldType<TFields[K] & VexField>;\n }\n : never\n : never\n : never;\n\n/**\n * Infer the expanded tab fields from a tabs field definition.\n * Each tab becomes a property keyed by its slug with an object of its inferred fields.\n */\ntype InferTabsExpansion<F extends TabsFieldDef> =\n F[\"tabs\"][number] extends infer T\n ? T extends TabDef<infer TSlug, infer TFields>\n ? { [K in TSlug]?: { [FK in keyof TFields]: InferFieldType<TFields[FK] & VexField> } }\n : {}\n : {};\n\n/**\n * Extract keys of fields that are tabs fields.\n */\ntype TabsFieldKeys<F extends Record<string, any>> = {\n [K in keyof F]: (F[K] & VexField) extends { type: \"tabs\" } ? K : never;\n}[keyof F];\n\n/**\n * Extract keys of fields that are NOT tabs fields.\n */\ntype NonTabsFieldKeys<F extends Record<string, any>> = {\n [K in keyof F]: (F[K] & VexField) extends { type: \"tabs\" } ? never : K;\n}[keyof F];\n\n/**\n * Expand all tabs fields in a record into their tab slug entries.\n * Produces a union of objects (one per tabs field) which gets intersected.\n */\ntype ExpandTabsFields<F extends Record<string, any>> =\n TabsFieldKeys<F> extends infer TK\n ? TK extends keyof F\n ? InferTabsExpansion<F[TK] & TabsFieldDef>\n : {}\n : {};\n\n/**\n * Infer the document type from a record of fields.\n * Tabs fields are expanded: instead of `colors: Record<string, unknown>`,\n * produces `light?: { ... }; dark?: { ... }` based on the tab definitions.\n *\n * @example\n * ```ts\n * type Doc = InferFieldsType<{\n * title: { type: \"text\"; required: true };\n * count: { type: \"number\" };\n * }>;\n * // { title: string; count: number }\n * ```\n */\nexport type InferFieldsType<F extends Record<string, VexField>> =\n // When F is `any`, fall back to a simple index signature to avoid conditional type issues\n 0 extends (1 & F)\n ? { [x: string]: unknown }\n : {\n [K in NonTabsFieldKeys<F> & keyof F]: InferFieldType<F[K] & VexField>;\n } & UnionToIntersection<ExpandTabsFields<F>>;\n\n/**\n * Convert a union to an intersection.\n * Used to merge expanded tab objects into a single type.\n */\ntype UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;\n","import type { BlockDef, VexField } from \"../types\";\nimport { RESERVED_BLOCK_FIELD_NAMES } from \"../types/fields\";\nimport { VexBlockValidationError } from \"../errors\";\n\n/**\n * Define a block type for use with the `blocks()` field.\n *\n * @param props.slug - Unique identifier for this block type\n * @param props.label - Display label for the admin picker\n * @param props.fields - Field definitions for this block's data shape\n * @param props.admin - Optional admin UI configuration (icon, custom components)\n * @returns A BlockDef object\n *\n * @throws VexBlockValidationError if slug is empty or contains invalid characters\n * @throws VexBlockValidationError if any field name is reserved (blockType, _key)\n *\n * @example\n * ```ts\n * const heroBlock = defineBlock({\n * slug: \"hero\",\n * label: \"Hero Section\",\n * fields: {\n * heading: text({ required: true }),\n * subheading: text(),\n * },\n * })\n * ```\n */\nexport function defineBlock<TFields extends Record<string, VexField>>(props: {\n slug: string;\n label: string;\n fields: TFields;\n admin?: BlockDef[\"admin\"];\n interfaceName?: string;\n}): BlockDef<TFields> {\n if (!props.slug || !/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(props.slug)) {\n throw new VexBlockValidationError(\n props.slug || \"(empty)\",\n `Invalid block slug \"${props.slug}\". Slugs must start with a letter and contain only letters, numbers, hyphens, and underscores.`,\n );\n }\n\n for (const fieldName of Object.keys(props.fields)) {\n if ((RESERVED_BLOCK_FIELD_NAMES as readonly string[]).includes(fieldName)) {\n throw new VexBlockValidationError(\n props.slug,\n `Field name \"${fieldName}\" is reserved in block definitions. Reserved names: ${RESERVED_BLOCK_FIELD_NAMES.join(\", \")}`,\n );\n }\n }\n\n // Validate admin.blockStyles\n const VALID_STYLE_TIERS = [\"container\", \"text\", \"layout\", \"media\"];\n\n if (props.admin?.blockStyles && props.admin.blockStyles !== true) {\n if (!Array.isArray(props.admin.blockStyles)) {\n throw new VexBlockValidationError(\n props.slug,\n `admin.blockStyles must be true or an array of style tier names. Got: ${typeof props.admin.blockStyles}`,\n );\n }\n for (const tier of props.admin.blockStyles) {\n if (!VALID_STYLE_TIERS.includes(tier)) {\n throw new VexBlockValidationError(\n props.slug,\n `Invalid style tier \"${tier}\" in admin.blockStyles. Valid tiers: ${VALID_STYLE_TIERS.join(\", \")}`,\n );\n }\n }\n }\n\n return {\n slug: props.slug,\n label: props.label,\n fields: props.fields,\n admin: props.admin,\n interfaceName: props.interfaceName,\n };\n}\n","export interface StylePreset {\n /** Tailwind scale value (stored in blockStyles JSON). */\n value: string;\n /** Display label in the popover. */\n label: string;\n /** Size hint shown next to the label (e.g., \"16px / 1rem\"). */\n hint: string;\n}\n\n// ---------------------------------------------------------------------------\n// Spacing presets (margin, padding, gap)\n// ---------------------------------------------------------------------------\n\nexport const SPACING_PRESETS: StylePreset[] = [\n { value: \"0\", label: \"0\", hint: \"0px\" },\n { value: \"0.5\", label: \"0.5\", hint: \"2px / 0.125rem\" },\n { value: \"1\", label: \"1\", hint: \"4px / 0.25rem\" },\n { value: \"1.5\", label: \"1.5\", hint: \"6px / 0.375rem\" },\n { value: \"2\", label: \"2\", hint: \"8px / 0.5rem\" },\n { value: \"3\", label: \"3\", hint: \"12px / 0.75rem\" },\n { value: \"4\", label: \"4\", hint: \"16px / 1rem\" },\n { value: \"5\", label: \"5\", hint: \"20px / 1.25rem\" },\n { value: \"6\", label: \"6\", hint: \"24px / 1.5rem\" },\n { value: \"8\", label: \"8\", hint: \"32px / 2rem\" },\n { value: \"10\", label: \"10\", hint: \"40px / 2.5rem\" },\n { value: \"12\", label: \"12\", hint: \"48px / 3rem\" },\n { value: \"16\", label: \"16\", hint: \"64px / 4rem\" },\n { value: \"20\", label: \"20\", hint: \"80px / 5rem\" },\n { value: \"24\", label: \"24\", hint: \"96px / 6rem\" },\n];\n\n// ---------------------------------------------------------------------------\n// Font size presets\n// ---------------------------------------------------------------------------\n\nexport const FONT_SIZE_PRESETS: StylePreset[] = [\n { value: \"xs\", label: \"XS\", hint: \"12px / 0.75rem\" },\n { value: \"sm\", label: \"SM\", hint: \"14px / 0.875rem\" },\n { value: \"base\", label: \"Base\", hint: \"16px / 1rem\" },\n { value: \"lg\", label: \"LG\", hint: \"18px / 1.125rem\" },\n { value: \"xl\", label: \"XL\", hint: \"20px / 1.25rem\" },\n { value: \"2xl\", label: \"2XL\", hint: \"24px / 1.5rem\" },\n { value: \"3xl\", label: \"3XL\", hint: \"30px / 1.875rem\" },\n { value: \"4xl\", label: \"4XL\", hint: \"36px / 2.25rem\" },\n { value: \"5xl\", label: \"5XL\", hint: \"48px / 3rem\" },\n];\n\n// ---------------------------------------------------------------------------\n// Font weight presets\n// ---------------------------------------------------------------------------\n\nexport const FONT_WEIGHT_PRESETS: StylePreset[] = [\n { value: \"thin\", label: \"Thin\", hint: \"100\" },\n { value: \"light\", label: \"Light\", hint: \"300\" },\n { value: \"normal\", label: \"Normal\", hint: \"400\" },\n { value: \"medium\", label: \"Medium\", hint: \"500\" },\n { value: \"semibold\", label: \"Semibold\", hint: \"600\" },\n { value: \"bold\", label: \"Bold\", hint: \"700\" },\n { value: \"extrabold\", label: \"Extra Bold\", hint: \"800\" },\n];\n\n// ---------------------------------------------------------------------------\n// Border radius presets\n// ---------------------------------------------------------------------------\n\nexport const BORDER_RADIUS_PRESETS: StylePreset[] = [\n { value: \"none\", label: \"None\", hint: \"0px\" },\n { value: \"sm\", label: \"SM\", hint: \"2px / 0.125rem\" },\n { value: \"DEFAULT\", label: \"Default\", hint: \"4px / 0.25rem\" },\n { value: \"md\", label: \"MD\", hint: \"6px / 0.375rem\" },\n { value: \"lg\", label: \"LG\", hint: \"8px / 0.5rem\" },\n { value: \"xl\", label: \"XL\", hint: \"12px / 0.75rem\" },\n { value: \"2xl\", label: \"2XL\", hint: \"16px / 1rem\" },\n { value: \"3xl\", label: \"3XL\", hint: \"24px / 1.5rem\" },\n { value: \"full\", label: \"Full\", hint: \"9999px\" },\n];\n\n// ---------------------------------------------------------------------------\n// Box shadow presets\n// ---------------------------------------------------------------------------\n\nexport const BOX_SHADOW_PRESETS: StylePreset[] = [\n { value: \"none\", label: \"None\", hint: \"no shadow\" },\n { value: \"sm\", label: \"SM\", hint: \"small\" },\n { value: \"DEFAULT\", label: \"Default\", hint: \"medium\" },\n { value: \"md\", label: \"MD\", hint: \"medium\" },\n { value: \"lg\", label: \"LG\", hint: \"large\" },\n { value: \"xl\", label: \"XL\", hint: \"extra large\" },\n { value: \"2xl\", label: \"2XL\", hint: \"xx-large\" },\n];\n\n// ---------------------------------------------------------------------------\n// Opacity presets\n// ---------------------------------------------------------------------------\n\nexport const OPACITY_PRESETS: StylePreset[] = [\n { value: \"0\", label: \"0%\", hint: \"invisible\" },\n { value: \"5\", label: \"5%\", hint: \"\" },\n { value: \"10\", label: \"10%\", hint: \"\" },\n { value: \"25\", label: \"25%\", hint: \"\" },\n { value: \"50\", label: \"50%\", hint: \"\" },\n { value: \"75\", label: \"75%\", hint: \"\" },\n { value: \"100\", label: \"100%\", hint: \"fully visible\" },\n];\n\n// ---------------------------------------------------------------------------\n// Width presets\n// ---------------------------------------------------------------------------\n\nexport const WIDTH_PRESETS: StylePreset[] = [\n { value: \"auto\", label: \"Auto\", hint: \"auto\" },\n { value: \"full\", label: \"Full\", hint: \"100%\" },\n { value: \"screen\", label: \"Screen\", hint: \"100vw\" },\n { value: \"1/2\", label: \"1/2\", hint: \"50%\" },\n { value: \"1/3\", label: \"1/3\", hint: \"33.33%\" },\n { value: \"2/3\", label: \"2/3\", hint: \"66.67%\" },\n { value: \"1/4\", label: \"1/4\", hint: \"25%\" },\n { value: \"3/4\", label: \"3/4\", hint: \"75%\" },\n { value: \"max\", label: \"Max Content\", hint: \"max-content\" },\n { value: \"fit\", label: \"Fit Content\", hint: \"fit-content\" },\n];\n\n// ---------------------------------------------------------------------------\n// Max-width presets\n// ---------------------------------------------------------------------------\n\nexport const MAX_WIDTH_PRESETS: StylePreset[] = [\n { value: \"none\", label: \"None\", hint: \"no limit\" },\n { value: \"xs\", label: \"XS\", hint: \"320px / 20rem\" },\n { value: \"sm\", label: \"SM\", hint: \"384px / 24rem\" },\n { value: \"md\", label: \"MD\", hint: \"448px / 28rem\" },\n { value: \"lg\", label: \"LG\", hint: \"512px / 32rem\" },\n { value: \"xl\", label: \"XL\", hint: \"576px / 36rem\" },\n { value: \"2xl\", label: \"2XL\", hint: \"672px / 42rem\" },\n { value: \"3xl\", label: \"3XL\", hint: \"768px / 48rem\" },\n { value: \"4xl\", label: \"4XL\", hint: \"896px / 56rem\" },\n { value: \"5xl\", label: \"5XL\", hint: \"1024px / 64rem\" },\n { value: \"6xl\", label: \"6XL\", hint: \"1152px / 72rem\" },\n { value: \"7xl\", label: \"7XL\", hint: \"1280px / 80rem\" },\n { value: \"full\", label: \"Full\", hint: \"100%\" },\n { value: \"screen\", label: \"Screen\", hint: \"100vw\" },\n];\n\n// ---------------------------------------------------------------------------\n// Line height presets\n// ---------------------------------------------------------------------------\n\nexport const LINE_HEIGHT_PRESETS: StylePreset[] = [\n { value: \"none\", label: \"None\", hint: \"1\" },\n { value: \"tight\", label: \"Tight\", hint: \"1.25\" },\n { value: \"snug\", label: \"Snug\", hint: \"1.375\" },\n { value: \"normal\", label: \"Normal\", hint: \"1.5\" },\n { value: \"relaxed\", label: \"Relaxed\", hint: \"1.625\" },\n { value: \"loose\", label: \"Loose\", hint: \"2\" },\n];\n\n// ---------------------------------------------------------------------------\n// Letter spacing presets\n// ---------------------------------------------------------------------------\n\nexport const LETTER_SPACING_PRESETS: StylePreset[] = [\n { value: \"tighter\", label: \"Tighter\", hint: \"-0.05em\" },\n { value: \"tight\", label: \"Tight\", hint: \"-0.025em\" },\n { value: \"normal\", label: \"Normal\", hint: \"0em\" },\n { value: \"wide\", label: \"Wide\", hint: \"0.025em\" },\n { value: \"wider\", label: \"Wider\", hint: \"0.05em\" },\n { value: \"widest\", label: \"Widest\", hint: \"0.1em\" },\n];\n\n// ---------------------------------------------------------------------------\n// Border width presets\n// ---------------------------------------------------------------------------\n\nexport const BORDER_WIDTH_PRESETS: StylePreset[] = [\n { value: \"0\", label: \"None\", hint: \"0px\" },\n { value: \"DEFAULT\", label: \"Default\", hint: \"1px\" },\n { value: \"2\", label: \"2\", hint: \"2px\" },\n { value: \"4\", label: \"4\", hint: \"4px\" },\n { value: \"8\", label: \"8\", hint: \"8px\" },\n];\n\n// ---------------------------------------------------------------------------\n// Aspect ratio presets\n// ---------------------------------------------------------------------------\n\nexport const ASPECT_RATIO_PRESETS: StylePreset[] = [\n { value: \"auto\", label: \"Auto\", hint: \"auto\" },\n { value: \"square\", label: \"Square\", hint: \"1 / 1\" },\n { value: \"video\", label: \"Video\", hint: \"16 / 9\" },\n { value: \"4/3\", label: \"4:3\", hint: \"4 / 3\" },\n { value: \"3/2\", label: \"3:2\", hint: \"3 / 2\" },\n];\n","import type { BlockStylesData, BlockStyleValues } from \"./types\";\n\n/**\n * Property-to-Tailwind class mapping.\n * Each function takes a style value and returns the corresponding Tailwind class.\n */\nconst PROPERTY_CLASS_MAP: Record<\n keyof BlockStyleValues,\n (v: string) => string\n> = {\n // Container — spacing\n margin: (v) => `m-${v}`,\n marginTop: (v) => `mt-${v}`,\n marginRight: (v) => `mr-${v}`,\n marginBottom: (v) => `mb-${v}`,\n marginLeft: (v) => `ml-${v}`,\n padding: (v) => `p-${v}`,\n paddingTop: (v) => `pt-${v}`,\n paddingRight: (v) => `pr-${v}`,\n paddingBottom: (v) => `pb-${v}`,\n paddingLeft: (v) => `pl-${v}`,\n\n // Container — sizing\n width: (v) => `w-${v}`,\n maxWidth: (v) => `max-w-${v}`,\n\n // Container — background\n backgroundColor: (v) => {\n if (\n v.startsWith(\"var(\") ||\n v.startsWith(\"#\") ||\n v.startsWith(\"rgb\") ||\n v.startsWith(\"hsl\") ||\n v.startsWith(\"oklch\")\n ) {\n return `bg-[${v}]`;\n }\n return `bg-${v}`;\n },\n\n // Container — border\n borderWidth: (v) => (v === \"DEFAULT\" ? \"border\" : `border-${v}`),\n borderColor: (v) => {\n if (\n v.startsWith(\"var(\") ||\n v.startsWith(\"#\") ||\n v.startsWith(\"rgb\") ||\n v.startsWith(\"hsl\") ||\n v.startsWith(\"oklch\")\n ) {\n return `border-[${v}]`;\n }\n return `border-${v}`;\n },\n borderStyle: (v) => `border-${v}`,\n borderRadius: (v) => (v === \"DEFAULT\" ? \"rounded\" : `rounded-${v}`),\n\n // Container — effects\n boxShadow: (v) => (v === \"DEFAULT\" ? \"shadow\" : `shadow-${v}`),\n opacity: (v) => `opacity-${v}`,\n\n // Container — display\n display: (v) => {\n if (v === \"inline-flex\") return \"inline-flex\";\n return v;\n },\n overflow: (v) => `overflow-${v}`,\n\n // Text\n textAlign: (v) => `text-${v}`,\n fontSize: (v) => `text-${v}`,\n fontWeight: (v) => `font-${v}`,\n color: (v) => {\n if (\n v.startsWith(\"var(\") ||\n v.startsWith(\"#\") ||\n v.startsWith(\"rgb\") ||\n v.startsWith(\"hsl\") ||\n v.startsWith(\"oklch\")\n ) {\n return `text-[${v}]`;\n }\n return `text-${v}`;\n },\n lineHeight: (v) => `leading-${v}`,\n letterSpacing: (v) => `tracking-${v}`,\n\n // Layout\n gap: (v) => `gap-${v}`,\n flexDirection: (v) => {\n const map: Record<string, string> = {\n row: \"flex-row\",\n column: \"flex-col\",\n \"row-reverse\": \"flex-row-reverse\",\n \"column-reverse\": \"flex-col-reverse\",\n };\n return map[v] ?? `flex-${v}`;\n },\n alignItems: (v) => `items-${v}`,\n justifyContent: (v) => `justify-${v}`,\n flexWrap: (v) => `flex-${v}`,\n\n // Media\n objectFit: (v) => `object-${v}`,\n aspectRatio: (v) => `aspect-${v}`,\n objectPosition: (v) => `object-${v}`,\n};\n\n/**\n * Convert a single breakpoint's style values into an array of Tailwind classes.\n */\nfunction stylesToClasses(props: { styles: BlockStyleValues }): string[] {\n const classes: string[] = [];\n\n for (const [key, value] of Object.entries(props.styles)) {\n if (value === undefined || value === null || value === \"\") continue;\n\n const mapper = PROPERTY_CLASS_MAP[key as keyof BlockStyleValues];\n if (!mapper) continue;\n\n classes.push(mapper(String(value)));\n }\n\n return classes;\n}\n\n/**\n * Convert a blockStyles JSON string into a Tailwind class string.\n *\n * Handles responsive breakpoint prefixes. The \"base\" breakpoint has no prefix,\n * all other breakpoints use their key as prefix (e.g., \"sm:\", \"md:\", \"lg:\").\n *\n * @param props.blockStylesJson - The raw JSON string from the block instance's blockStyles field\n * @returns Tailwind class string ready to use in className, or empty string if input is empty/invalid\n *\n * @example\n * ```ts\n * blockStylesToTailwind({\n * blockStylesJson: '{\"base\":{\"margin\":\"4\",\"padding\":\"2\"},\"sm\":{\"margin\":\"6\"}}'\n * })\n * // → \"m-4 p-2 sm:m-6\"\n * ```\n */\nexport function blockStylesToTailwind(props: {\n blockStylesJson: string | undefined;\n}): string {\n if (!props.blockStylesJson) return \"\";\n\n let data: BlockStylesData;\n try {\n data = JSON.parse(props.blockStylesJson);\n } catch {\n return \"\";\n }\n\n const result: string[] = [];\n\n // Process \"base\" first (no breakpoint prefix)\n if (data.base) {\n result.push(...stylesToClasses({ styles: data.base }));\n }\n\n // Process remaining breakpoints sorted alphabetically for deterministic output\n const breakpointKeys = Object.keys(data)\n .filter((k) => k !== \"base\")\n .sort();\n\n for (const bp of breakpointKeys) {\n const classes = stylesToClasses({ styles: data[bp] });\n for (const cls of classes) {\n result.push(`${bp}:${cls}`);\n }\n }\n\n return result.join(\" \");\n}\n","/**\n * Convert a slug string to a PascalCase interface name.\n *\n * @param props.slug - The slug to convert (e.g., \"blog-posts\", \"new_block\", \"media\")\n * @returns PascalCase string (e.g., \"BlogPosts\", \"NewBlock\", \"Media\")\n */\nexport function slugToInterfaceName(props: { slug: string }): string {\n return props.slug\n .replace(/[-_]+/g, \" \")\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .split(/\\s+/)\n .filter(Boolean)\n .map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1).toLowerCase())\n .join(\"\");\n}\n","import type { VexField } from \"../types\";\nimport { slugToInterfaceName } from \"./slugToInterfaceName\";\n\n/**\n * Convert a VexField to its TypeScript type string for generated interfaces.\n *\n * @param props.field - The field definition\n * @param props.blockInterfaceNames - Map of block slug → interface name (for blocks fields)\n * @returns TypeScript type string (e.g., \"string\", \"number\", \"'draft' | 'published'\", \"HeroBlock[]\")\n */\nexport function fieldToTypeString(props: {\n field: VexField;\n blockInterfaceNames?: Map<string, string>;\n}): string {\n switch (props.field.type) {\n case \"text\":\n return \"string\";\n case \"number\":\n return \"number\";\n case \"checkbox\":\n return \"boolean\";\n case \"date\":\n return \"number\";\n case \"imageUrl\":\n return \"string\";\n case \"json\":\n return \"Record<string, unknown>\";\n case \"object\":\n return \"Record<string, unknown>\";\n case \"richtext\":\n return \"RichTextDocument\";\n case \"color\":\n return \"string\";\n case \"tabs\":\n return \"Record<string, unknown>\";\n case \"ui\":\n return \"never\";\n\n case \"select\": {\n const values = props.field.options.map((o) => o.value);\n if (values.length === 0) return \"string\";\n const union = values.map((v) => `'${v}'`).join(\" | \");\n if (props.field.hasMany) {\n return `(${union})[]`;\n }\n return union;\n }\n\n case \"relationship\": {\n const idType = `Id<'${props.field.to}'>`;\n return props.field.hasMany ? `${idType}[]` : idType;\n }\n\n case \"upload\": {\n const idType = `Id<'${props.field.to}'>`;\n return props.field.hasMany ? `${idType}[]` : idType;\n }\n\n case \"array\": {\n const inner = fieldToTypeString({\n field: props.field.items,\n blockInterfaceNames: props.blockInterfaceNames,\n });\n const needsParens = inner.includes(\"|\");\n return needsParens ? `(${inner})[]` : `${inner}[]`;\n }\n\n case \"blocks\": {\n const names = props.field.blocks.map((b) => {\n if (props.blockInterfaceNames?.has(b.slug)) {\n return props.blockInterfaceNames.get(b.slug)!;\n }\n return b.interfaceName ?? slugToInterfaceName({ slug: b.slug });\n });\n if (names.length === 0) return \"unknown[]\";\n if (names.length === 1) return `${names[0]}[]`;\n return `(${names.join(\" | \")})[]`;\n }\n\n default:\n return \"unknown\";\n }\n}\n","import type { VexConfig, VexField, BlockDef } from \"../types\";\nimport type { TabsFieldDef } from \"../types/fields\";\nimport { mergeAuthCollectionWithUserCollection } from \"../valueTypes/merge\";\nimport { LOCKED_MEDIA_FIELDS, OVERRIDABLE_MEDIA_FIELDS } from \"../types/media\";\nimport { fieldToTypeString } from \"./fieldToTypeString\";\nimport { slugToInterfaceName } from \"./slugToInterfaceName\";\nimport { VexError } from \"../errors\";\n\n/**\n * Generate the complete TypeScript source for `vex.types.ts`.\n *\n * @param props.config - The resolved VexConfig\n * @returns TypeScript source code string\n */\nexport function generateVexTypes(props: { config: VexConfig }): string {\n const config = props.config;\n const parts: string[] = [];\n\n // ── 1. Collect all blocks and build name maps ──\n\n const blocksBySlug = new Map<string, BlockDef>();\n const blockInterfaceNames = new Map<string, string>();\n\n function collectBlocks(fields: Record<string, VexField>) {\n for (const field of Object.values(fields)) {\n if (field.type === \"blocks\") {\n for (const block of field.blocks) {\n if (!blocksBySlug.has(block.slug)) {\n blocksBySlug.set(block.slug, block);\n collectBlocks(block.fields as Record<string, VexField>);\n }\n }\n } else if (field.type === \"tabs\") {\n for (const tab of (field as TabsFieldDef).tabs) {\n collectBlocks(tab.fields as Record<string, VexField>);\n }\n }\n }\n }\n\n for (const col of config.collections) {\n collectBlocks(col.fields as Record<string, VexField>);\n }\n if (config.media?.collections) {\n for (const col of config.media.collections) {\n collectBlocks(col.fields as Record<string, VexField>);\n }\n }\n for (const g of config.globals) {\n collectBlocks(g.fields as Record<string, VexField>);\n }\n\n for (const [slug, block] of blocksBySlug) {\n blockInterfaceNames.set(\n slug,\n block.interfaceName ?? slugToInterfaceName({ slug }),\n );\n }\n\n // ── 2. Build collection & global name maps, check for duplicates ──\n\n const allNames = new Map<string, string>(); // name → source description\n\n function registerName(name: string, source: string) {\n if (allNames.has(name)) {\n throw new VexError(\n `Duplicate interface name \"${name}\" — used by ${allNames.get(name)} and ${source}. ` +\n `Set a unique \\`interfaceName\\` on one of them.`,\n );\n }\n allNames.set(name, source);\n }\n\n const collectionNames = new Map<string, string>(); // slug → interfaceName\n for (const col of config.collections) {\n const name = col.interfaceName ?? slugToInterfaceName({ slug: col.slug });\n registerName(name, `collection \"${col.slug}\"`);\n collectionNames.set(col.slug, name);\n }\n\n if (config.media?.collections) {\n for (const col of config.media.collections) {\n const name = col.interfaceName ?? slugToInterfaceName({ slug: col.slug });\n registerName(name, `media collection \"${col.slug}\"`);\n collectionNames.set(col.slug, name);\n }\n }\n\n // Auth-only collections (not matched to user collections)\n const authCollectionMap = new Map(\n config.auth.collections.map((c) => [c.slug, c]),\n );\n const userCollectionSlugs = new Set(config.collections.map((c) => c.slug));\n const mediaSlugs = new Set(\n (config.media?.collections ?? []).map((c) => c.slug),\n );\n for (const authCol of config.auth.collections) {\n if (!userCollectionSlugs.has(authCol.slug) && !mediaSlugs.has(authCol.slug)) {\n const name = authCol.interfaceName ?? slugToInterfaceName({ slug: authCol.slug });\n registerName(name, `auth collection \"${authCol.slug}\"`);\n collectionNames.set(authCol.slug, name);\n }\n }\n\n const globalNames = new Map<string, string>();\n for (const g of config.globals) {\n const name = g.interfaceName ?? slugToInterfaceName({ slug: g.slug });\n registerName(name, `global \"${g.slug}\"`);\n globalNames.set(g.slug, name);\n }\n\n for (const [slug, name] of blockInterfaceNames) {\n registerName(name, `block \"${slug}\"`);\n }\n\n // ── 3. Check if Id import is needed ──\n\n let needsIdImport = false;\n function checkForIdFields(fields: Record<string, VexField>) {\n for (const field of Object.values(fields)) {\n if (field.type === \"relationship\" || field.type === \"upload\") {\n needsIdImport = true;\n } else if (field.type === \"tabs\") {\n for (const tab of (field as TabsFieldDef).tabs) {\n checkForIdFields(tab.fields as Record<string, VexField>);\n }\n }\n }\n }\n for (const col of config.collections) {\n checkForIdFields(col.fields as Record<string, VexField>);\n }\n if (config.media?.collections) {\n for (const col of config.media.collections) {\n checkForIdFields(col.fields as Record<string, VexField>);\n }\n }\n for (const g of config.globals) {\n checkForIdFields(g.fields as Record<string, VexField>);\n }\n for (const block of blocksBySlug.values()) {\n checkForIdFields(block.fields as Record<string, VexField>);\n }\n // Collections always have _id which is Id<slug>, so always need it\n if (config.collections.length > 0 || (config.media?.collections?.length ?? 0) > 0 || config.globals.length > 0) {\n needsIdImport = true;\n }\n\n // Check if RichTextDocument import is needed\n let needsRichTextImport = false;\n function checkForRichTextFields(fields: Record<string, VexField>) {\n for (const field of Object.values(fields)) {\n if (field.type === \"richtext\") {\n needsRichTextImport = true;\n } else if (field.type === \"tabs\") {\n for (const tab of (field as TabsFieldDef).tabs) {\n checkForRichTextFields(tab.fields as Record<string, VexField>);\n }\n }\n }\n }\n for (const col of config.collections) {\n checkForRichTextFields(col.fields as Record<string, VexField>);\n }\n if (config.media?.collections) {\n for (const col of config.media.collections) {\n checkForRichTextFields(col.fields as Record<string, VexField>);\n }\n }\n for (const g of config.globals) {\n checkForRichTextFields(g.fields as Record<string, VexField>);\n }\n for (const block of blocksBySlug.values()) {\n checkForRichTextFields(block.fields as Record<string, VexField>);\n }\n\n // ── 4. File header ──\n\n parts.push(\"// ⚠️ AUTO-GENERATED BY VEX CMS — DO NOT EDIT ⚠️\");\n parts.push(\"\");\n if (needsIdImport) {\n parts.push(\"import type { Id } from './_generated/dataModel';\");\n }\n if (needsRichTextImport) {\n parts.push(\"import type { RichTextDocument } from '@vexcms/core';\");\n }\n if (needsIdImport || needsRichTextImport) {\n parts.push(\"\");\n }\n\n // ── 5. Block interfaces ──\n\n const sortedBlockSlugs = [...blocksBySlug.keys()].sort();\n for (const slug of sortedBlockSlugs) {\n const block = blocksBySlug.get(slug)!;\n const name = blockInterfaceNames.get(slug)!;\n parts.push(generateBlockInterface({ block, name, blockInterfaceNames }));\n parts.push(\"\");\n }\n\n // ── 6. Collection interfaces ──\n\n for (const col of config.collections) {\n const name = collectionNames.get(col.slug)!;\n const authCol = authCollectionMap.get(col.slug);\n let fields: Record<string, VexField>;\n\n if (authCol) {\n const merged = mergeAuthCollectionWithUserCollection({\n authCollection: authCol,\n userCollection: col,\n });\n fields = merged.fields;\n } else {\n fields = col.fields as Record<string, VexField>;\n }\n\n const isVersioned = !!(col as any).versions?.drafts;\n parts.push(\n generateCollectionInterface({\n name,\n slug: col.slug,\n fields,\n isVersioned,\n blockInterfaceNames,\n }),\n );\n parts.push(\"\");\n }\n\n // Auth-only collections\n for (const authCol of config.auth.collections) {\n if (userCollectionSlugs.has(authCol.slug) || mediaSlugs.has(authCol.slug)) continue;\n const name = collectionNames.get(authCol.slug)!;\n parts.push(\n generateCollectionInterface({\n name,\n slug: authCol.slug,\n fields: authCol.fields as Record<string, VexField>,\n isVersioned: false,\n blockInterfaceNames,\n }),\n );\n parts.push(\"\");\n }\n\n // Media collections\n if (config.media?.collections) {\n for (const col of config.media.collections) {\n const name = collectionNames.get(col.slug)!;\n parts.push(\n generateMediaCollectionInterface({\n name,\n slug: col.slug,\n userFields: col.fields as Record<string, VexField>,\n blockInterfaceNames,\n }),\n );\n parts.push(\"\");\n }\n }\n\n // ── 7. Global interfaces ──\n\n for (const g of config.globals) {\n const name = globalNames.get(g.slug)!;\n parts.push(\n generateGlobalInterface({\n name,\n slug: g.slug,\n tableName: g.tableName ?? g.slug,\n fields: g.fields as Record<string, VexField>,\n blockInterfaceNames,\n }),\n );\n parts.push(\"\");\n }\n\n // ── 8. Barrel types ──\n\n if (collectionNames.size > 0) {\n const entries = [...collectionNames.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([slug, name]) => ` ${slug}: ${name};`)\n .join(\"\\n\");\n parts.push(`export interface VexCollectionTypes {\\n${entries}\\n}`);\n parts.push(\"\");\n }\n\n if (globalNames.size > 0) {\n const entries = [...globalNames.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([slug, name]) => ` ${slug}: ${name};`)\n .join(\"\\n\");\n parts.push(`export interface VexGlobalTypes {\\n${entries}\\n}`);\n parts.push(\"\");\n }\n\n return parts.join(\"\\n\");\n}\n\n// ── Helpers ──\n\nfunction generateBlockInterface(props: {\n block: BlockDef;\n name: string;\n blockInterfaceNames: Map<string, string>;\n}): string {\n const lines: string[] = [];\n lines.push(`export interface ${props.name} {`);\n lines.push(` blockType: '${props.block.slug}';`);\n lines.push(` blockName?: string;`);\n lines.push(` _key: string;`);\n\n lines.push(...generateFieldLines({ fields: props.block.fields as Record<string, VexField>, blockInterfaceNames: props.blockInterfaceNames }));\n\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nfunction generateCollectionInterface(props: {\n name: string;\n slug: string;\n fields: Record<string, VexField>;\n isVersioned: boolean;\n blockInterfaceNames: Map<string, string>;\n}): string {\n const lines: string[] = [];\n lines.push(`export interface ${props.name} {`);\n lines.push(` _id: Id<'${props.slug}'>;`);\n lines.push(` _creationTime: number;`);\n\n if (props.isVersioned) {\n lines.push(` vex_status?: 'draft' | 'published';`);\n lines.push(` vex_version?: number;`);\n lines.push(` vex_publishedAt?: number;`);\n }\n\n lines.push(...generateFieldLines({ fields: props.fields, blockInterfaceNames: props.blockInterfaceNames }));\n\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nfunction generateMediaCollectionInterface(props: {\n name: string;\n slug: string;\n userFields: Record<string, VexField>;\n blockInterfaceNames: Map<string, string>;\n}): string {\n const lines: string[] = [];\n lines.push(`export interface ${props.name} {`);\n lines.push(` _id: Id<'${props.slug}'>;`);\n lines.push(` _creationTime: number;`);\n\n // Locked fields\n lines.push(` storageId: string;`);\n lines.push(` filename: string;`);\n lines.push(` mimeType: string;`);\n lines.push(` size: number;`);\n\n // Overridable fields (optional unless user defines them)\n lines.push(` url?: string;`);\n lines.push(` width?: number;`);\n lines.push(` height?: number;`);\n\n // User-defined fields\n const lockedSet = new Set([...LOCKED_MEDIA_FIELDS, ...OVERRIDABLE_MEDIA_FIELDS]);\n const filteredFields: Record<string, VexField> = {};\n for (const [fieldName, field] of Object.entries(props.userFields)) {\n if (lockedSet.has(fieldName as any)) continue;\n filteredFields[fieldName] = field as VexField;\n }\n lines.push(...generateFieldLines({ fields: filteredFields, blockInterfaceNames: props.blockInterfaceNames }));\n\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nfunction generateGlobalInterface(props: {\n name: string;\n slug: string;\n tableName: string;\n fields: Record<string, VexField>;\n blockInterfaceNames: Map<string, string>;\n}): string {\n const lines: string[] = [];\n lines.push(`export interface ${props.name} {`);\n lines.push(` _id: Id<'${props.tableName}'>;`);\n lines.push(` _creationTime: number;`);\n\n lines.push(...generateFieldLines({ fields: props.fields, blockInterfaceNames: props.blockInterfaceNames }));\n\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate interface field lines from a record of fields, expanding tabs fields\n * into their individual tab slugs with proper nested object types.\n * This mirrors the expandFields() logic in schema generation.\n */\nfunction generateFieldLines(props: {\n fields: Record<string, VexField>;\n blockInterfaceNames: Map<string, string>;\n}): string[] {\n const lines: string[] = [];\n\n for (const [fieldName, field] of Object.entries(props.fields)) {\n const f = field as VexField;\n if (f.type === \"ui\") continue;\n\n if (f.type === \"tabs\") {\n const tabsField = f as TabsFieldDef;\n for (const tab of tabsField.tabs) {\n const innerProps: string[] = [];\n for (const [innerName, innerField] of Object.entries(tab.fields) as [string, VexField][]) {\n if (innerField.type === \"ui\") continue;\n const innerOptional = innerField.required ? \"\" : \"?\";\n const innerTypeStr = fieldToTypeString({\n field: innerField,\n blockInterfaceNames: props.blockInterfaceNames,\n });\n innerProps.push(`${innerName}${innerOptional}: ${innerTypeStr}`);\n }\n if (innerProps.length > 0) {\n lines.push(` ${tab.slug}?: { ${innerProps.join(\"; \")} };`);\n }\n }\n } else {\n const label = f.label;\n if (label) lines.push(` /** ${label} */`);\n const optional = f.required ? \"\" : \"?\";\n const typeStr = fieldToTypeString({\n field: f,\n blockInterfaceNames: props.blockInterfaceNames,\n });\n lines.push(` ${fieldName}${optional}: ${typeStr};`);\n }\n }\n\n return lines;\n}\n","/**\n * System field names injected into versioned collection schemas.\n * These are excluded from user-editable fields and version snapshots.\n */\nexport const VERSION_SYSTEM_FIELDS = [\n \"vex_status\",\n \"vex_version\",\n \"vex_publishedAt\",\n] as const;\n\n/**\n * All system fields (Convex built-in + versioning) to strip when\n * extracting user content from a document.\n */\nexport const ALL_SYSTEM_FIELDS = new Set([\n \"_id\",\n \"_creationTime\",\n ...VERSION_SYSTEM_FIELDS,\n]);\n\n/**\n * Default max versions to keep per document.\n */\nexport const DEFAULT_MAX_VERSIONS_PER_DOC = 100;\n\n/**\n * Default autosave interval in milliseconds.\n */\nexport const DEFAULT_AUTOSAVE_INTERVAL = 2000;\n","import { ALL_SYSTEM_FIELDS } from \"./constants\";\n\n/**\n * Extracts user-defined fields from a document, stripping all\n * system fields (_id, _creationTime, _status, _version, _publishedAt).\n *\n * Used to create version snapshots that contain only content fields.\n *\n * @param props.document - The full document including system fields\n * @returns A new object with only user-defined fields\n */\nexport function extractUserFields(props: {\n document: Record<string, unknown>;\n}): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props.document)) {\n if (!ALL_SYSTEM_FIELDS.has(key)) {\n result[key] = value;\n }\n }\n return result;\n}\n","import type { LivePreviewConfig } from \"../types/livePreview\";\n\n/**\n * Resolves the preview URL from a collection's live preview config.\n *\n * @param props.config - The collection's livePreview config\n * @param props.doc - The current document data (must include `_id`)\n * @param props.fallbackURL - URL to return if the function throws\n * @returns The resolved preview URL\n * @throws If the resolved URL is empty and no fallbackURL is provided\n */\nexport function resolvePreviewURL(props: {\n config: LivePreviewConfig;\n doc: { _id: string; [key: string]: any };\n fallbackURL?: string;\n}): string {\n if (typeof props.config.url === \"string\") {\n return props.config.url;\n }\n\n try {\n const result = props.config.url(props.doc);\n if (!result) {\n throw new Error(\n `Live preview URL resolved to empty string for document ${props.doc._id}`,\n );\n }\n return result;\n } catch (error) {\n if (props.fallbackURL !== undefined) {\n return props.fallbackURL;\n }\n throw error;\n }\n}\n","import type { LivePreviewConfig } from \"../types/livePreview\";\n\n/**\n * Determines if the preview iframe URL should be recomputed.\n *\n * @param props.config - The collection's livePreview config\n * @param props.changedFields - Set of field names that changed in the save\n * @returns true if the URL should be recomputed\n */\nexport function shouldReloadURL(props: {\n config: LivePreviewConfig;\n changedFields: string[];\n}): boolean {\n if (props.config.reloadOnFields === undefined) {\n return true;\n }\n\n if (props.config.reloadOnFields.length === 0) {\n return false;\n }\n\n return props.changedFields.some((field) =>\n props.config.reloadOnFields!.includes(field),\n );\n}\n","import type { LivePreviewBreakpoint } from \"../types/livePreview\";\n\nexport const DEFAULT_BREAKPOINTS: LivePreviewBreakpoint[] = [\n { label: \"Mobile\", width: 375, height: 667, icon: \"smartphone\" },\n { label: \"Tablet\", width: 768, height: 1024, icon: \"tablet\" },\n { label: \"Laptop\", width: 1280, height: 800, icon: \"laptop\" },\n { label: \"Desktop\", width: 1920, height: 1080, icon: \"monitor\" },\n];\n\n/**\n * Debounce interval for writing preview snapshots on form changes.\n */\nexport const PREVIEW_SNAPSHOT_DEBOUNCE_MS = 500;\n","import type { GenericMutationCtx, GenericQueryCtx, GenericDataModel } from \"convex/server\";\n\n/**\n * Upserts a preview snapshot for a document.\n * If a snapshot already exists for this collection+document, it is updated in place.\n * If not, a new entry is created.\n *\n * @param props.ctx - Convex mutation context\n * @param props.collection - Collection slug\n * @param props.documentId - Document ID\n * @param props.snapshot - Complete field snapshot from the form\n */\nexport async function upsertPreviewSnapshot<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>;\n collection: string;\n documentId: string;\n snapshot: Record<string, unknown>;\n}): Promise<void> {\n const existing = await (props.ctx.db as any)\n .query(\"vex_versions\")\n .withIndex(\"by_document_status\", (q: any) =>\n q\n .eq(\"collection\", props.collection)\n .eq(\"documentId\", props.documentId)\n .eq(\"status\", \"previewSnapshot\"),\n )\n .first();\n\n if (existing) {\n await (props.ctx.db as any).patch(existing._id, {\n snapshot: props.snapshot,\n createdAt: Date.now(),\n });\n } else {\n await (props.ctx.db as any).insert(\"vex_versions\", {\n collection: props.collection,\n documentId: props.documentId,\n version: 0,\n status: \"previewSnapshot\",\n snapshot: props.snapshot,\n createdAt: Date.now(),\n createdBy: undefined,\n isAutosave: false,\n restoredFrom: undefined,\n });\n }\n}\n\n/**\n * Deletes the preview snapshot for a document.\n * Called after a successful save to clean up transient state.\n *\n * @param props.ctx - Convex mutation context\n * @param props.collection - Collection slug\n * @param props.documentId - Document ID\n */\nexport async function deletePreviewSnapshot<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>;\n collection: string;\n documentId: string;\n}): Promise<void> {\n const entries = await (props.ctx.db as any)\n .query(\"vex_versions\")\n .withIndex(\"by_document_status\", (q: any) =>\n q\n .eq(\"collection\", props.collection)\n .eq(\"documentId\", props.documentId)\n .eq(\"status\", \"previewSnapshot\"),\n )\n .collect();\n\n for (const entry of entries) {\n await (props.ctx.db as any).delete(entry._id);\n }\n}\n\n/**\n * Gets the preview data for a document.\n *\n * Lookup order:\n * 1. Preview snapshot (transient, written by admin form on each change)\n * 2. Latest version from vex_versions (draft or published, excluding autosave/previewSnapshot)\n * 3. null (fall back to main document)\n *\n * @param props.ctx - Convex query context\n * @param props.collection - Collection slug\n * @param props.documentId - Document ID\n * @returns The snapshot data, or null if no preview/version exists\n */\nexport async function getPreviewSnapshot<DataModel extends GenericDataModel>(props: {\n ctx: GenericQueryCtx<DataModel>;\n collection: string;\n documentId: string;\n}): Promise<Record<string, unknown> | null> {\n // 1. Check for a transient preview snapshot (written by admin form edits)\n const previewEntry = await (props.ctx.db as any)\n .query(\"vex_versions\")\n .withIndex(\"by_document_status\", (q: any) =>\n q\n .eq(\"collection\", props.collection)\n .eq(\"documentId\", props.documentId)\n .eq(\"status\", \"previewSnapshot\"),\n )\n .first();\n\n if (previewEntry) {\n return previewEntry.snapshot as Record<string, unknown>;\n }\n\n // 2. Fall back to the latest version (draft or published)\n const allVersions = await (props.ctx.db as any)\n .query(\"vex_versions\")\n .withIndex(\"by_document\", (q: any) =>\n q.eq(\"collection\", props.collection).eq(\"documentId\", props.documentId),\n )\n .collect();\n\n let latestVersion: Record<string, unknown> | null = null;\n let maxVersion = -1;\n for (const v of allVersions) {\n if (v.status === \"previewSnapshot\" || v.status === \"autosave\") continue;\n const ver = v.version as number;\n if (ver > maxVersion) {\n maxVersion = ver;\n latestVersion = v;\n }\n }\n\n if (latestVersion) {\n return (latestVersion as any).snapshot as Record<string, unknown>;\n }\n\n // 3. No versions at all — caller will use the main document\n return null;\n}\n","import {\n queryGeneric,\n type QueryBuilder,\n type GenericQueryCtx,\n type GenericDataModel,\n type RegisteredQuery,\n} from \"convex/server\";\nimport { v, type ObjectType, type PropertyValidators } from \"convex/values\";\n\n/**\n * Drafts mode for vexQuery.\n * - \"snapshot\": Fetch the transient preview snapshot (written by admin on form changes)\n * - true: Fetch the latest draft version (from versioning system)\n * - false: Fetch published content only\n */\nexport type VexDraftsMode = \"snapshot\" | boolean;\n\n/**\n * Context passed to vexQuery handlers.\n * Extends the standard Convex QueryCtx with draft-awareness.\n */\nexport interface VexQueryCtx<DataModel extends GenericDataModel = GenericDataModel>\n extends GenericQueryCtx<DataModel> {\n /**\n * The resolved drafts mode.\n * - \"snapshot\": caller wants preview snapshot data\n * - true: caller wants latest draft version\n * - false: caller wants published content only\n *\n * Defaults to \"snapshot\" when not explicitly passed by the caller.\n */\n drafts: VexDraftsMode;\n}\n\nfunction wrapHandler<DataModel extends GenericDataModel, Args extends PropertyValidators, Output>(\n handler: (ctx: VexQueryCtx<DataModel>, args: ObjectType<Args>) => Output | Promise<Output>,\n) {\n return async (ctx: GenericQueryCtx<any>, args: any): Promise<Awaited<Output>> => {\n const { _vexDrafts, ...userArgs } = args;\n\n const drafts: VexDraftsMode = _vexDrafts !== undefined\n ? (_vexDrafts as VexDraftsMode)\n : \"snapshot\";\n\n const vexCtx = Object.assign(\n Object.create(Object.getPrototypeOf(ctx)),\n ctx,\n { drafts },\n ) as VexQueryCtx<DataModel>;\n\n return handler(vexCtx, userArgs as ObjectType<Args>) as Promise<Awaited<Output>>;\n };\n}\n\n/**\n * Create a typed vexQuery builder from your project's query builder.\n *\n * Call this once in your project to get a `vexQuery` function that\n * preserves full return type inference from your DataModel.\n *\n * @example\n * ```ts\n * // convex/vex/helpers.ts\n * import { createVexQuery } from \"@vexcms/core\";\n * import { query } from \"../_generated/server\";\n *\n * export const vexQuery = createVexQuery(query);\n * ```\n *\n * Then use it in your query files:\n * ```ts\n * // convex/pages.ts\n * import { vexQuery } from \"./vex/helpers\";\n * import { getPreviewSnapshot } from \"@vexcms/core\";\n *\n * export const getBySlug = vexQuery({\n * args: { slug: v.string() },\n * handler: async (ctx, args) => {\n * const page = await ctx.db\n * .query(\"pages\")\n * .withIndex(\"by_slug\", (q) => q.eq(\"slug\", args.slug))\n * .first();\n * if (!page) return null;\n * if (ctx.drafts === \"snapshot\") {\n * const snapshot = await getPreviewSnapshot({ ctx, collection: \"pages\", documentId: page._id });\n * if (snapshot) return { ...page, ...snapshot };\n * }\n * return page;\n * },\n * });\n * ```\n */\nexport function createVexQuery<DataModel extends GenericDataModel>(\n _queryBuilder: QueryBuilder<DataModel, \"public\">,\n) {\n return <Args extends PropertyValidators, Output>(props: {\n args: Args;\n handler: (\n ctx: VexQueryCtx<DataModel>,\n args: ObjectType<Args>,\n ) => Output | Promise<Output>;\n }): RegisteredQuery<\"public\", ObjectType<Args & { _vexDrafts: typeof v.optional<any> }>, Awaited<Output>> => {\n const mergedArgs = {\n ...props.args,\n _vexDrafts: v.optional(v.union(v.literal(\"snapshot\"), v.boolean())),\n };\n\n return queryGeneric({\n args: mergedArgs,\n handler: wrapHandler<DataModel, Args, Output>(props.handler),\n }) as RegisteredQuery<\"public\", ObjectType<Args & { _vexDrafts: typeof v.optional<any> }>, Awaited<Output>>;\n };\n}\n\n/**\n * Generic vexQuery for use without project-specific types.\n * Prefer `createVexQuery(query)` for full type inference.\n *\n * @deprecated Use `createVexQuery(query)` instead for proper return type inference.\n */\nexport function vexQuery<Args extends PropertyValidators, Output>(props: {\n args: Args;\n handler: (\n ctx: VexQueryCtx,\n args: ObjectType<Args>,\n ) => Output | Promise<Output>;\n}): RegisteredQuery<\"public\", ObjectType<Args & { _vexDrafts: typeof v.optional<any> }>, Awaited<Output>> {\n const mergedArgs = {\n ...props.args,\n _vexDrafts: v.optional(v.union(v.literal(\"snapshot\"), v.boolean())),\n };\n\n return queryGeneric({\n args: mergedArgs,\n handler: wrapHandler(props.handler),\n }) as RegisteredQuery<\"public\", ObjectType<Args & { _vexDrafts: typeof v.optional<any> }>, Awaited<Output>>;\n}\n","import type {\n GenericDataModel,\n GenericMutationCtx,\n GenericQueryCtx,\n PaginationOptions,\n TableNamesInDataModel,\n} from \"convex/server\"\n\nimport { ConvexError } from \"convex/values\"\nimport { generateFormSchema } from \"../../formSchema/generateFormSchema\"\nimport { getPreviewSnapshot } from \"../previewSnapshot\"\nimport type { VexField } from \"../../types\"\nimport type { CollectionKind } from \"../../config/findCollectionBySlug\"\n\nasync function resolveStorageUrl(\n ctx: { storage: { getUrl: (id: any) => Promise<string | null> } },\n doc: any,\n) {\n if (doc?.storageId && (!doc.url || doc.url === \"\")) {\n const url = await ctx.storage.getUrl(doc.storageId)\n if (url) return { ...doc, url }\n }\n return doc\n}\n\nexport async function listDocuments<DataModel extends GenericDataModel>(props: {\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n paginationOpts: PaginationOptions\n order?: \"asc\" | \"desc\"\n }\n ctx: GenericQueryCtx<DataModel>\n}) {\n const { args, ctx } = props\n const q = args.order === \"desc\"\n ? ctx.db.query(args.collectionSlug).order(\"desc\")\n : ctx.db.query(args.collectionSlug)\n const result = await q.paginate(args.paginationOpts)\n const resolvedPage = await Promise.all(\n result.page.map((doc: any) => resolveStorageUrl(ctx, doc)),\n )\n return { ...result, page: resolvedPage }\n}\n\nexport async function countDocuments<DataModel extends GenericDataModel>(props: {\n ctx: GenericQueryCtx<DataModel>\n args: { collectionSlug: TableNamesInDataModel<DataModel> }\n}): Promise<number> {\n return await (props.ctx.db.query(props.args.collectionSlug) as any).count()\n}\n\nexport async function getDocument<DataModel extends GenericDataModel>(props: {\n ctx: GenericQueryCtx<DataModel>\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n documentId: string\n /** When true, merges the transient preview snapshot (from admin live preview) */\n preview?: boolean\n }\n}) {\n const doc = await props.ctx.db.get(props.args.documentId as any)\n if (!doc) return null\n const resolved = await resolveStorageUrl(props.ctx, doc)\n\n // Merge preview snapshot when explicitly requested (live preview iframe).\n if (props.args.preview) {\n const snapshot = await getPreviewSnapshot<DataModel>({\n ctx: props.ctx,\n collection: props.args.collectionSlug as string,\n documentId: props.args.documentId,\n })\n if (snapshot) {\n return { ...resolved, ...snapshot }\n }\n }\n\n return resolved\n}\n\nexport async function updateDocument<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n documentId: string\n fields: Record<string, unknown>\n collectionFields: Record<string, VexField>\n }\n}) {\n const f = { ...props.args.fields }\n\n // Resolve the file URL from storageId when replacing a media file\n if (f.storageId && f.url === \"\") {\n const url = await props.ctx.storage.getUrl(f.storageId as any)\n if (url) f.url = url\n }\n\n const schema = generateFormSchema({\n fields: props.args.collectionFields,\n }).partial()\n\n const result = schema.safeParse(f)\n if (!result.success) {\n throw new ConvexError({\n message: \"Validation failed\",\n errors: result.error.flatten(),\n })\n }\n\n await props.ctx.db.patch(props.args.documentId as any, result.data as any)\n return props.args.documentId\n}\n\nexport async function createDocument<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n fields: Record<string, unknown>\n collectionFields: Record<string, VexField>\n kind: CollectionKind\n }\n}): Promise<string> {\n if (props.args.kind === \"global\") {\n const existing = await props.ctx.db.query(props.args.collectionSlug).first()\n if (existing) {\n throw new ConvexError(\n `Global \"${props.args.collectionSlug}\" already exists. Globals can only have one document.`,\n )\n }\n }\n\n const schema = generateFormSchema({\n fields: props.args.collectionFields,\n })\n\n const result = schema.safeParse(props.args.fields)\n if (!result.success) {\n throw new ConvexError({\n message: \"Validation failed\",\n errors: result.error.flatten(),\n })\n }\n\n const id = await props.ctx.db.insert(props.args.collectionSlug as any, result.data as any)\n return id as string\n}\n\nexport async function deleteDocument<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n documentId: string\n kind: CollectionKind\n }\n}): Promise<void> {\n if (props.args.kind === \"global\") {\n const existing = await props.ctx.db.get(props.args.documentId as any)\n if (!existing) {\n throw new ConvexError(\n `Global \"${props.args.collectionSlug}\" document not found. Cannot delete a non-existent global.`,\n )\n }\n }\n\n await props.ctx.db.delete(props.args.documentId as any)\n}\n\nexport async function bulkDeleteDocuments<DataModel extends GenericDataModel>(props: {\n ctx: GenericMutationCtx<DataModel>\n args: {\n documentIds: string[]\n }\n}): Promise<{ deleted: number }> {\n for (const id of props.args.documentIds) {\n await props.ctx.db.delete(id as any)\n }\n return { deleted: props.args.documentIds.length }\n}\n\nexport async function searchDocuments<DataModel extends GenericDataModel>(props: {\n args: {\n collectionSlug: TableNamesInDataModel<DataModel>\n searchIndexName: string\n searchField: string\n query: string\n }\n ctx: GenericQueryCtx<DataModel>\n}) {\n const { args, ctx } = props\n const docs = await (ctx.db.query(args.collectionSlug) as any)\n .withSearchIndex(args.searchIndexName, (q: any) => q.search(args.searchField, args.query))\n .take(50)\n return Promise.all(docs.map((doc: any) => resolveStorageUrl(ctx, doc)))\n}\n","import type { VexConfig, VexCollection } from \"../types\";\n\n/** Sentinel string placed at the top of every generated file. */\nexport const GENERATED_HEADER =\n \"// ⚠️ AUTO-GENERATED BY VEX CMS — DO NOT EDIT ⚠️\";\n\n/**\n * Relative import paths used inside generated files.\n * Computed by the CLI from cwd + convexDir; passed in so this function\n * stays pure and testable.\n */\nexport interface CollectionQueryImports {\n /** Import path for vex.config.ts from api/ dir. e.g. `\"../../../vex.config\"` */\n vexConfigFromApi: string;\n /** Import path for _generated/ from api/ dir. e.g. `\"../../_generated\"` */\n generatedDirFromApi: string;\n /** Import path for the user's auth helper from api/ dir. e.g. `\"../auth\"` */\n authFromApi: string;\n /** Import path for _generated/ from model/api/ dir. e.g. `\"../../../_generated\"` */\n generatedDirFromModel: string;\n}\n\n/**\n * Result of generating all collection files.\n * Keys are relative paths from the vex/ directory.\n * e.g. `\"api/articles.ts\"`, `\"model/api/articles.ts\"`, `\"api/index.ts\"`\n */\nexport type GeneratedFiles = Record<string, string>;\n\n/**\n * Generate typed Convex query/mutation files for all collections in `config`.\n *\n * Produces two files per collection:\n * - `model/api/{slug}.ts` — typed model functions (DB logic)\n * - `api/{slug}.ts` — Convex query/mutation exports (auth + RBAC + calls model)\n * Plus a barrel `api/index.ts`.\n */\nexport function generateCollectionQueries(props: {\n config: VexConfig;\n imports: CollectionQueryImports;\n}): GeneratedFiles {\n const { config, imports } = props;\n const result: GeneratedFiles = {};\n const slugs: string[] = [];\n\n // Regular collections\n for (const collection of config.collections) {\n const { apiFile, modelFile } = generateCollectionPair({\n collection,\n isMedia: false,\n imports,\n });\n result[`api/${collection.slug}.ts`] = apiFile;\n result[`model/api/${collection.slug}.ts`] = modelFile;\n slugs.push(collection.slug);\n }\n\n // Media collections\n if (config.media?.collections) {\n for (const collection of config.media.collections) {\n const { apiFile, modelFile } = generateCollectionPair({\n collection,\n isMedia: true,\n imports,\n });\n result[`api/${collection.slug}.ts`] = apiFile;\n result[`model/api/${collection.slug}.ts`] = modelFile;\n slugs.push(collection.slug);\n }\n }\n\n // Globals (treated like collections for API generation)\n if (config.globals) {\n for (const global of config.globals) {\n if (slugs.includes(global.slug)) continue;\n const collection = {\n slug: global.slug,\n tableName: global.tableName ?? global.slug,\n fields: global.fields,\n searchIndexes: undefined,\n } as unknown as VexCollection;\n const { apiFile, modelFile } = generateCollectionPair({\n collection,\n isMedia: false,\n imports,\n });\n result[`api/${global.slug}.ts`] = apiFile;\n result[`model/api/${global.slug}.ts`] = modelFile;\n slugs.push(global.slug);\n }\n }\n\n // Auth collections that opt in with generateApi: true\n if (config.auth?.collections) {\n for (const collection of config.auth.collections) {\n if (!collection.generateApi) continue;\n // Skip if already generated (user may have the same collection in config.collections)\n if (slugs.includes(collection.slug)) continue;\n const { apiFile, modelFile } = generateCollectionPair({\n collection,\n isMedia: false,\n imports,\n });\n result[`api/${collection.slug}.ts`] = apiFile;\n result[`model/api/${collection.slug}.ts`] = modelFile;\n slugs.push(collection.slug);\n }\n }\n\n // Barrel index\n result[\"api/index.ts\"] = generateIndexFile({ slugs });\n\n return result;\n}\n\n// ─── Per-collection pair generation ──────────────────────────────────────────\n\n/**\n * Generate both the model file and the API file for a single collection.\n */\nexport function generateCollectionPair(props: {\n collection: VexCollection;\n isMedia: boolean;\n imports: CollectionQueryImports;\n}): { apiFile: string; modelFile: string } {\n const { collection, isMedia, imports } = props;\n const slug = collection.slug;\n const tableName = collection.tableName ?? collection.slug;\n const firstSearchIndex = collection.searchIndexes?.[0] ?? null;\n\n const modelFile = generateModelFile({ slug, tableName, isMedia, firstSearchIndex, imports });\n const apiFile = generateApiFile({ slug, tableName, isMedia, firstSearchIndex, imports });\n\n return { apiFile, modelFile };\n}\n\n// ─── Model file generation ──────────────────────────────────────────────────\n\nexport function generateModelFile(props: {\n slug: string;\n tableName: string;\n isMedia: boolean;\n firstSearchIndex: { name: string; searchField: string } | null;\n imports: CollectionQueryImports;\n}): string {\n const { tableName, isMedia, firstSearchIndex, imports } = props;\n const parts: string[] = [];\n\n // Header + imports\n const coreImports = [\"getPreviewSnapshot\"];\n if (!isMedia) {\n coreImports.push(\"generateFormSchema\");\n }\n\n const coreTypeImports: string[] = [\"CollectionKind\"];\n if (!isMedia) {\n coreTypeImports.push(\"VexField\");\n }\n\n const coreTypeImportLine = coreTypeImports.length > 0\n ? `\\nimport type { ${coreTypeImports.join(\", \")} } from \"@vexcms/core\"`\n : \"\";\n\n const convexTypeImports = isMedia ? \"\" : `\\nimport type { WithoutSystemFields } from \"convex/server\"`;\n\n parts.push(`${GENERATED_HEADER}\nimport type { Doc, Id } from \"${imports.generatedDirFromModel}/dataModel\"\nimport type { QueryCtx, MutationCtx } from \"${imports.generatedDirFromModel}/server\"${convexTypeImports}\nimport { ConvexError } from \"convex/values\"\nimport { ${coreImports.join(\", \")} } from \"@vexcms/core\"${coreTypeImportLine}`);\n\n // getDocument\n parts.push(buildModelGetDocument({ tableName }));\n\n // listDocuments\n parts.push(buildModelListDocuments({ tableName }));\n\n // createDocument (not for media)\n if (!isMedia) {\n parts.push(buildModelCreateDocument({ tableName }));\n }\n\n // updateDocument (not for media)\n if (!isMedia) {\n parts.push(buildModelUpdateDocument({ tableName }));\n }\n\n // deleteDocument\n parts.push(buildModelDeleteDocument({ tableName }));\n\n // searchDocuments (only if search index)\n if (firstSearchIndex) {\n parts.push(buildModelSearchDocuments({\n tableName,\n searchIndexName: firstSearchIndex.name,\n searchField: firstSearchIndex.searchField as string,\n }));\n }\n\n return parts.join(\"\\n\\n\") + \"\\n\";\n}\n\nexport function buildModelGetDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export async function getDocument(props: {\n ctx: QueryCtx\n documentId: Id<\"${tableName}\">\n preview?: boolean\n}): Promise<Doc<\"${tableName}\"> | null> {\n const doc = await props.ctx.db.get(props.documentId)\n if (!doc) return null\n\n if (props.preview) {\n const snapshot = await getPreviewSnapshot({\n ctx: props.ctx,\n collection: \"${tableName}\",\n documentId: props.documentId,\n })\n if (snapshot) {\n return { ...doc, ...snapshot } as Doc<\"${tableName}\">\n }\n }\n\n return doc\n}`;\n}\n\nexport function buildModelListDocuments(props: { tableName: string }): string {\n const { tableName } = props;\n return `export async function listDocuments(props: {\n ctx: QueryCtx\n paginationOpts: { numItems: number; cursor: string | null }\n order?: \"asc\" | \"desc\"\n}) {\n const q = props.order === \"desc\"\n ? props.ctx.db.query(\"${tableName}\").order(\"desc\")\n : props.ctx.db.query(\"${tableName}\")\n return await q.paginate(props.paginationOpts)\n}`;\n}\n\nexport function buildModelCreateDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export async function createDocument(props: {\n collectionFields: Record<string, VexField>\n ctx: MutationCtx\n fields: unknown\n kind: CollectionKind\n}): Promise<Id<\"${tableName}\">> {\n if (props.kind === \"global\") {\n const existing = await props.ctx.db.query(\"${tableName}\").first()\n if (existing) {\n throw new ConvexError(\\`Global \"${tableName}\" already exists. Globals can only have one document.\\`)\n }\n }\n\n const schema = generateFormSchema({ fields: props.collectionFields })\n const parsed = schema.safeParse(props.fields)\n if (!parsed.success) {\n throw new ConvexError({ message: \"Validation failed\", errors: parsed.error.flatten() })\n }\n\n const data = { ...parsed.data }\n data.vex_status ??= \"published\"\n return await props.ctx.db.insert(\"${tableName}\", data as WithoutSystemFields<Doc<\"${tableName}\">>)\n}`;\n}\n\nexport function buildModelUpdateDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export async function updateDocument(props: {\n collectionFields: Record<string, VexField>\n ctx: MutationCtx\n documentId: Id<\"${tableName}\">\n fields: unknown\n}): Promise<Id<\"${tableName}\">> {\n const schema = generateFormSchema({ fields: props.collectionFields }).partial()\n const parsed = schema.safeParse(props.fields)\n if (!parsed.success) {\n throw new ConvexError({ message: \"Validation failed\", errors: parsed.error.flatten() })\n }\n\n await props.ctx.db.patch(props.documentId, parsed.data as Partial<Doc<\"${tableName}\">>)\n return props.documentId\n}`;\n}\n\nexport function buildModelDeleteDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export async function deleteDocument(props: {\n ctx: MutationCtx\n documentId: Id<\"${tableName}\">\n kind: CollectionKind\n}): Promise<void> {\n if (props.kind === \"global\") {\n const existing = await props.ctx.db.get(props.documentId)\n if (!existing) {\n throw new ConvexError(\\`Global \"${tableName}\" document not found. Cannot delete a non-existent global.\\`)\n }\n }\n\n await props.ctx.db.delete(props.documentId)\n}`;\n}\n\nexport function buildModelSearchDocuments(props: {\n tableName: string;\n searchIndexName: string;\n searchField: string;\n}): string {\n const { tableName, searchIndexName, searchField } = props;\n return `export async function searchDocuments(props: {\n ctx: QueryCtx\n query: string\n}): Promise<Doc<\"${tableName}\">[]> {\n return await props.ctx.db.query(\"${tableName}\")\n .withSearchIndex(\"${searchIndexName}\", (q) => q.search(\"${searchField}\", props.query))\n .take(50)\n}`;\n}\n\n// ─── API file generation ─────────────────────────────────────────────────────\n\nexport function generateApiFile(props: {\n slug: string;\n tableName: string;\n isMedia: boolean;\n firstSearchIndex: { name: string; searchField: string } | null;\n imports: CollectionQueryImports;\n}): string {\n const { slug, tableName, isMedia, firstSearchIndex, imports } = props;\n const parts: string[] = [];\n\n // Model imports\n const modelFns = [\n \"getDocument\",\n \"listDocuments\",\n ...(isMedia ? [] : [\"createDocument\", \"updateDocument\"]),\n \"deleteDocument\",\n ...(firstSearchIndex ? [\"searchDocuments\"] : []),\n ];\n\n parts.push(`${GENERATED_HEADER}\nimport { v } from \"convex/values\"\nimport { paginationOptsValidator } from \"convex/server\"\nimport { ConvexError } from \"convex/values\"\nimport { query, mutation } from \"${imports.generatedDirFromApi}/server\"\nimport type { QueryCtx, MutationCtx } from \"${imports.generatedDirFromApi}/server\"\nimport { hasPermission, findCollectionBySlug } from \"@vexcms/core\"\nimport { getUser } from \"${imports.authFromApi}\"\nimport vexConfig from \"${imports.vexConfigFromApi}\"\nimport { ${modelFns.join(\", \")} } from \"../model/api/${slug}\"`);\n\n // SLUG constant + requireAuth helper\n parts.push(`const SLUG = \"${slug}\" as const\n\nasync function requireAuth(ctx: QueryCtx | MutationCtx) {\n const auth = await getUser(ctx)\n if (!auth) throw new ConvexError(\"Not authenticated\")\n return auth\n}`);\n\n // getDocument\n parts.push(buildApiGetDocument({ tableName }));\n\n // listDocuments\n parts.push(buildApiListDocuments({ tableName }));\n\n // createDocument (not for media)\n if (!isMedia) {\n parts.push(buildApiCreateDocument({ slug, tableName }));\n }\n\n // updateDocument (not for media)\n if (!isMedia) {\n parts.push(buildApiUpdateDocument({ slug, tableName }));\n }\n\n // deleteDocument\n parts.push(buildApiDeleteDocument({ tableName }));\n\n // searchDocuments (only if search index)\n if (firstSearchIndex) {\n parts.push(buildApiSearchDocuments());\n }\n\n return parts.join(\"\\n\\n\") + \"\\n\";\n}\n\nexport function buildApiGetDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export const get = query({\n args: {\n id: v.id(\"${tableName}\"),\n _vexDrafts: v.optional(v.union(v.literal(\"snapshot\"), v.boolean())),\n },\n handler: async (ctx, args) => {\n const preview = (args._vexDrafts ?? \"snapshot\") === \"snapshot\"\n const doc = await getDocument({\n ctx,\n documentId: args.id,\n preview,\n })\n if (!doc) return null\n const auth = await getUser(ctx)\n if (auth) {\n const allowed = hasPermission({\n access: vexConfig.access,\n user: auth.user,\n userRoles: auth.roles,\n resource: SLUG,\n action: \"read\",\n data: doc,\n })\n if (!allowed) return null\n }\n return doc\n },\n})`;\n}\n\nexport function buildApiListDocuments(_props: { tableName: string }): string {\n return `export const list = query({\n args: {\n paginationOpts: paginationOptsValidator,\n order: v.optional(v.union(v.literal(\"asc\"), v.literal(\"desc\"))),\n },\n handler: async (ctx, args) => {\n const result = await listDocuments({\n ctx,\n paginationOpts: args.paginationOpts,\n order: args.order,\n })\n const auth = await getUser(ctx)\n if (!auth) return result\n const filteredPage = result.page.filter((doc) =>\n hasPermission({\n access: vexConfig.access,\n user: auth.user,\n userRoles: auth.roles,\n resource: SLUG,\n action: \"read\",\n data: doc,\n }) === true,\n )\n return { ...result, page: filteredPage }\n },\n})`;\n}\n\nexport function buildApiCreateDocument(_props: {\n slug: string;\n tableName: string;\n}): string {\n return `export const create = mutation({\n args: { fields: v.any() },\n handler: async (ctx, args) => {\n const { user, roles } = await requireAuth(ctx)\n hasPermission({\n access: vexConfig.access,\n user,\n userRoles: roles,\n resource: SLUG,\n action: \"create\",\n throwOnDenied: true,\n })\n const collection = findCollectionBySlug({ slug: SLUG, config: vexConfig })\n if (!collection) throw new ConvexError(\\`Collection \"\\${SLUG}\" not found in vex config\\`)\n return createDocument({\n collectionFields: collection.fields,\n ctx,\n fields: args.fields as unknown,\n kind: \"collection\",\n })\n },\n})`;\n}\n\nexport function buildApiUpdateDocument(props: {\n slug: string;\n tableName: string;\n}): string {\n const { tableName } = props;\n return `export const update = mutation({\n args: { id: v.id(\"${tableName}\"), fields: v.any() },\n handler: async (ctx, args) => {\n const { user, roles } = await requireAuth(ctx)\n hasPermission({\n access: vexConfig.access,\n user,\n userRoles: roles,\n resource: SLUG,\n action: \"update\",\n throwOnDenied: true,\n })\n const collection = findCollectionBySlug({ slug: SLUG, config: vexConfig })\n if (!collection) throw new ConvexError(\\`Collection \"\\${SLUG}\" not found in vex config\\`)\n return updateDocument({\n collectionFields: collection.fields,\n ctx,\n documentId: args.id,\n fields: args.fields,\n })\n },\n})`;\n}\n\nexport function buildApiDeleteDocument(props: { tableName: string }): string {\n const { tableName } = props;\n return `export const remove = mutation({\n args: { id: v.id(\"${tableName}\") },\n handler: async (ctx, args) => {\n const { user, roles } = await requireAuth(ctx)\n hasPermission({\n access: vexConfig.access,\n user,\n userRoles: roles,\n resource: SLUG,\n action: \"delete\",\n throwOnDenied: true,\n })\n await deleteDocument({\n ctx,\n documentId: args.id,\n kind: \"collection\",\n })\n },\n})`;\n}\n\nexport function buildApiSearchDocuments(): string {\n return `export const search = query({\n args: { query: v.string() },\n handler: async (ctx, args) => {\n const results = await searchDocuments({\n ctx,\n query: args.query,\n })\n const auth = await getUser(ctx)\n if (!auth) return results\n return results.filter((doc) =>\n hasPermission({\n access: vexConfig.access,\n user: auth.user,\n userRoles: auth.roles,\n resource: SLUG,\n action: \"read\",\n data: doc,\n }) === true,\n )\n },\n})`;\n}\n\n// ─── Barrel index ────────────────────────────────────────────────────────────\n\n/**\n * Generate the barrel `index.ts` that namespace-re-exports all collection files.\n */\nexport function generateIndexFile(props: { slugs: string[] }): string {\n const sorted = [...props.slugs].sort();\n if (sorted.length === 0) {\n return GENERATED_HEADER + \"\\n\";\n }\n const exports = sorted\n .map((slug) => `export * as ${slug} from \"./${slug}\"`)\n .join(\"\\n\");\n return `${GENERATED_HEADER}\\n${exports}\\n`;\n}\n","// =============================================================================\n// SCHEMA DIFF — compares old vs new generated schema to detect migration needs\n// =============================================================================\n\nexport interface SchemaFieldInfo {\n /** Table name (export const name). */\n table: string;\n /** Field name within the table. */\n field: string;\n /** Full value type string, e.g. \"v.string()\" or \"v.optional(v.string())\". */\n valueType: string;\n /** Whether the field is wrapped in v.optional(...). */\n isOptional: boolean;\n}\n\nexport interface RemovedFieldInfo {\n /** Table name (export const name). */\n table: string;\n /** Field name that was removed. */\n field: string;\n /** The old value type string, e.g. \"v.string()\". */\n valueType: string;\n /** Whether the field was optional in the old schema. */\n wasOptional: boolean;\n}\n\nexport interface SchemaDiff {\n /** Fields that changed from optional → required (need backfill). */\n newRequired: SchemaFieldInfo[];\n /** Fields that are entirely new and required (need backfill). */\n addedRequired: SchemaFieldInfo[];\n /** Fields that are entirely new and optional (may need backfill if they have a defaultValue). */\n addedOptional: SchemaFieldInfo[];\n /** Fields that existed in old schema but are absent in new schema. */\n removedFields: RemovedFieldInfo[];\n /** All fields that need migration. */\n needsMigration: SchemaFieldInfo[];\n}\n\ninterface ParsedTable {\n name: string;\n fields: Map<string, { valueType: string; isOptional: boolean }>;\n}\n\n/**\n * Parse a generated vex schema string into a map of table → fields.\n *\n * Relies on the known output format of `generateVexSchema()`:\n * ```\n * export const <name> = defineTable({\n * field1: v.string(),\n * field2: v.optional(v.string()),\n * })\n * ```\n */\nfunction parseTables(schema: string): Map<string, ParsedTable> {\n const tables = new Map<string, ParsedTable>();\n if (!schema.trim()) return tables;\n\n // Match each `export const <name> = defineTable({ ... })`\n const tableRegex =\n /export\\s+const\\s+(\\w+)\\s*=\\s*defineTable\\(\\{([\\s\\S]*?)\\}\\)/g;\n\n let match: RegExpExecArray | null;\n while ((match = tableRegex.exec(schema)) !== null) {\n const name = match[1]!;\n const body = match[2]!;\n const fields = new Map<string, { valueType: string; isOptional: boolean }>();\n\n // Match field entries like ` fieldName: v.string(),` or ` fieldName: v.optional(v.string()),`\n // The value type can contain nested parens, so we use a greedy match up to the trailing comma\n const fieldRegex = /^\\s+(\\w+):\\s+(v\\..+?),?\\s*$/gm;\n let fieldMatch: RegExpExecArray | null;\n while ((fieldMatch = fieldRegex.exec(body)) !== null) {\n const fieldName = fieldMatch[1]!;\n const valueType = fieldMatch[2]!.replace(/,\\s*$/, \"\");\n const isOptional = valueType.startsWith(\"v.optional(\");\n fields.set(fieldName, { valueType, isOptional });\n }\n\n tables.set(name, { name, fields });\n }\n\n return tables;\n}\n\n/**\n * Compare two generated schema strings and return fields that need migration.\n *\n * A field needs migration when:\n * 1. It exists in the new schema but not the old, and is NOT optional → `addedRequired`\n * 2. It exists in the new schema but not the old, and IS optional → `addedOptional`\n * (planMigration decides whether to backfill based on defaultValue)\n * 3. It exists in both, was optional in old but is NOT optional in new → `newRequired`\n */\nexport function diffSchema(oldSchema: string, newSchema: string): SchemaDiff {\n const oldTables = parseTables(oldSchema);\n const newTables = parseTables(newSchema);\n\n const addedRequired: SchemaFieldInfo[] = [];\n const addedOptional: SchemaFieldInfo[] = [];\n const newRequired: SchemaFieldInfo[] = [];\n const removedFields: RemovedFieldInfo[] = [];\n\n for (const [tableName, newTable] of newTables) {\n const oldTable = oldTables.get(tableName);\n\n for (const [fieldName, newField] of newTable.fields) {\n const info: SchemaFieldInfo = {\n table: tableName,\n field: fieldName,\n valueType: newField.valueType,\n isOptional: newField.isOptional,\n };\n\n if (!oldTable) {\n // Entire table is new\n if (newField.isOptional) {\n addedOptional.push(info);\n } else {\n addedRequired.push(info);\n }\n } else {\n const oldField = oldTable.fields.get(fieldName);\n if (!oldField) {\n // Field is new\n if (newField.isOptional) {\n addedOptional.push(info);\n } else {\n addedRequired.push(info);\n }\n } else if (oldField.isOptional && !newField.isOptional) {\n // Field changed from optional → required\n newRequired.push(info);\n }\n }\n }\n }\n\n // Detect removed fields: fields that exist in old but not in new\n for (const [tableName, oldTable] of oldTables) {\n const newTable = newTables.get(tableName);\n if (!newTable) continue; // Entire table removed — not our concern here\n\n for (const [fieldName, oldField] of oldTable.fields) {\n if (!newTable.fields.has(fieldName)) {\n removedFields.push({\n table: tableName,\n field: fieldName,\n valueType: oldField.valueType,\n wasOptional: oldField.isOptional,\n });\n }\n }\n }\n\n return {\n addedRequired,\n addedOptional,\n newRequired,\n removedFields,\n needsMigration: [...addedRequired, ...addedOptional, ...newRequired],\n };\n}\n\n/**\n * Rewrite specific fields in a schema string to be `v.optional(...)`.\n *\n * Used to produce an interim schema where new required fields are temporarily\n * optional, allowing Convex to accept the schema before documents are backfilled.\n */\nexport function makeFieldsOptional(\n schema: string,\n fields: SchemaFieldInfo[],\n): string {\n let result = schema;\n\n for (const field of fields) {\n if (field.isOptional) continue; // Already optional\n\n // Match ` <fieldName>: <valueType>,` within the schema and wrap in v.optional(...)\n // The field line looks like: ` fieldName: v.string(),`\n const escaped = field.field.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = new RegExp(\n `(\\\\s+${escaped}:\\\\s+)(${field.valueType.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")})(,?)`,\n );\n result = result.replace(pattern, `$1v.optional($2)$3`);\n }\n\n return result;\n}\n\n/**\n * Re-insert removed fields into a schema string as `v.optional(...)`.\n *\n * Used to produce an interim schema that still accepts documents with the\n * removed field, so we can strip the field from documents before deploying\n * the final schema without the field.\n */\nexport function addRemovedFieldsAsOptional(\n schema: string,\n fields: RemovedFieldInfo[],\n): string {\n let result = schema;\n\n // Group removed fields by table for efficient insertion\n const byTable = new Map<string, RemovedFieldInfo[]>();\n for (const f of fields) {\n const list = byTable.get(f.table) ?? [];\n list.push(f);\n byTable.set(f.table, list);\n }\n\n for (const [tableName, tableFields] of byTable) {\n // Find the closing `})` of the defineTable for this table\n const tablePattern = new RegExp(\n `(export\\\\s+const\\\\s+${tableName}\\\\s*=\\\\s*defineTable\\\\(\\\\{[\\\\s\\\\S]*?)(\\\\}\\\\))`,\n );\n const tableMatch = result.match(tablePattern);\n if (!tableMatch) continue;\n\n // Build the extra field lines\n const extraLines = tableFields.map((f) => {\n const optionalType = f.wasOptional\n ? f.valueType\n : `v.optional(${f.valueType})`;\n return ` ${f.field}: ${optionalType},`;\n });\n\n // Insert the extra fields before the closing `})`\n result = result.replace(\n tablePattern,\n `$1${extraLines.join(\"\\n\")}\\n$2`,\n );\n }\n\n return result;\n}\n","// =============================================================================\n// MIGRATION PLAN — maps schema diff to concrete backfill operations\n// =============================================================================\n\nimport type { SchemaDiff } from \"./diffSchema\";\nimport type { VexConfig } from \"../types\";\nimport type { VexField } from \"../types/fields\";\n\nexport interface MigrationOp {\n /** The table name (as exported in the schema). */\n table: string;\n /** The field name to backfill. */\n field: string;\n /** The default value to set on existing documents. */\n defaultValue: unknown;\n}\n\n/**\n * Given a schema diff and the full Vex config, produce a list of\n * migration operations — one per field that needs backfilling.\n *\n * Fields are matched by looking up the collection whose table name\n * (or slug) matches the diff's table, then finding the field's\n * `defaultValue`.\n *\n * Auth-only fields (fields that come from the auth adapter, not from\n * user-defined collections) are skipped — auth manages its own data.\n */\nexport function planMigration(props: {\n diff: SchemaDiff;\n config: VexConfig;\n}): MigrationOp[] {\n const { diff, config } = props;\n\n if (diff.needsMigration.length === 0) return [];\n\n // Build a lookup: table export name → collection fields\n const tableFieldsMap = new Map<\n string,\n Record<string, VexField>\n >();\n\n for (const collection of config.collections) {\n tableFieldsMap.set(collection.slug, collection.fields);\n }\n\n for (const global of config.globals) {\n tableFieldsMap.set(global.slug, global.fields);\n }\n\n const ops: MigrationOp[] = [];\n\n for (const fieldInfo of diff.needsMigration) {\n const collectionFields = tableFieldsMap.get(fieldInfo.table);\n\n if (!collectionFields) {\n // Table not found in user collections — likely an auth-only table\n continue;\n }\n\n const field = collectionFields[fieldInfo.field] as VexField | undefined;\n if (!field) {\n // Field not found in collection config — likely an auth-managed field\n continue;\n }\n\n if (!field.required) {\n // Only migrate required fields — optional fields don't need backfill\n continue;\n }\n const defaultValue = (field as any).defaultValue;\n if (defaultValue === undefined) {\n // No defaultValue — skip (required fields enforce defaultValue at config time)\n continue;\n }\n\n ops.push({\n table: fieldInfo.table,\n field: fieldInfo.field,\n defaultValue,\n });\n }\n\n return ops;\n}\n"],"mappings":"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","names":["v","v","jsx","ui","v","schema","v","v","v"]}