@invect/core 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"schema-generator.cjs","names":[],"sources":["../../src/database/schema-generator.ts"],"sourcesContent":["/**\n * Drizzle Schema Generators\n *\n * Converts the merged abstract schema (core + plugins) into three\n * dialect-specific Drizzle ORM schema files as TypeScript source code.\n *\n * Each generator produces a complete, self-contained .ts file that can\n * be used by Drizzle Kit for migration generation.\n */\n\nimport type { PluginFieldAttribute, PluginFieldType } from 'src/types/plugin.types';\nimport type { MergedSchema, MergedTable } from './schema-merger';\n\n// =============================================================================\n// Common Utilities\n// =============================================================================\n\n/**\n * Convert camelCase to snake_case for DB column names.\n */\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Check if a field type is an enum (string array).\n */\nfunction isEnumType(type: PluginFieldType): type is string[] {\n return Array.isArray(type);\n}\n\n/**\n * Generate a variable name for an enum from a table + field.\n * e.g., flowRuns + status → flowRunStatusEnum\n */\nfunction enumVarName(tableName: string, fieldName: string): string {\n return `${tableName}${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}Enum`;\n}\n\nconst SQLITE_RUNTIME_DEFAULT_IMPORTS: Record<string, string> = {\n FlowRunStatus: '@invect/core',\n NodeExecutionStatus: '@invect/core',\n};\n\nfunction collectSqliteRuntimeDefaultImports(schema: MergedSchema): Map<string, Set<string>> {\n const importsByModule = new Map<string, Set<string>>();\n\n for (const table of schema.tables) {\n for (const field of Object.values(table.definition.fields)) {\n if (typeof field.defaultValue !== 'string' || !field.typeAnnotation) {\n continue;\n }\n\n const importPath = SQLITE_RUNTIME_DEFAULT_IMPORTS[field.typeAnnotation];\n if (!importPath) {\n continue;\n }\n\n const existing = importsByModule.get(importPath) ?? new Set<string>();\n existing.add(field.typeAnnotation);\n importsByModule.set(importPath, existing);\n }\n }\n\n return importsByModule;\n}\n\n// =============================================================================\n// SQLite Generator\n// =============================================================================\n\nexport function generateSqliteSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n const runtimeImports = collectSqliteRuntimeDefaultImports(schema);\n\n // Header\n lines.push(`// SQLite schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(``);\n lines.push(\n `import { sqliteTable, text, integer, primaryKey, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';`,\n );\n lines.push(`import { relations, sql } from 'drizzle-orm';`);\n for (const [importPath, identifiers] of runtimeImports.entries()) {\n lines.push(`import { ${Array.from(identifiers).sort().join(', ')} } from '${importPath}';`);\n }\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`// Type imports — these are used for $type<>() annotations`);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Collect all typeAnnotations to generate type imports\n const typeAnnotations = collectTypeAnnotations(schema);\n if (typeAnnotations.size > 0) {\n lines.push(`// Plugin & core type annotations`);\n lines.push(`// You may need to adjust these imports based on your project structure`);\n lines.push(``);\n }\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateSqliteTable(table, schema));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const varName = table.name;\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${varName}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${varName}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generateSqliteTable(table: MergedTable, schema: MergedSchema): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = sqliteTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(` ${fieldName}: ${sqliteColumn(fieldName, colName, field, name, schema)},`);\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction sqliteColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n schema?: MergedSchema,\n): string {\n let col: string;\n\n if (isEnumType(field.type)) {\n // SQLite: enums are just text columns\n col = `text('${colName}')`;\n } else {\n switch (field.type) {\n case 'string':\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `text('${colName}')`;\n break;\n case 'number':\n case 'bigint':\n col = `integer('${colName}')`;\n break;\n case 'boolean':\n col = `integer('${colName}', { mode: 'boolean' })`;\n break;\n case 'date':\n col = `text('${colName}')`;\n break;\n case 'json':\n col = `text('${colName}', { mode: 'json' })`;\n break;\n default:\n col = `text('${colName}')`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += sqliteDefault(field.defaultValue, field.type, field.typeAnnotation);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnySQLiteColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction sqliteDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n typeAnnotation?: string,\n): string {\n if (value === 'uuid()') {\n return `.$defaultFn(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.default(sql\\`CURRENT_TIMESTAMP\\`)`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n if (typeAnnotation && SQLITE_RUNTIME_DEFAULT_IMPORTS[typeAnnotation]) {\n return `.default(${typeAnnotation}.${value})`;\n }\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// PostgreSQL Generator\n// =============================================================================\n\nexport function generatePostgresSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// PostgreSQL schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(``);\n lines.push(`import {`);\n lines.push(` pgTable,`);\n lines.push(` text,`);\n lines.push(` integer,`);\n lines.push(` boolean,`);\n lines.push(` timestamp,`);\n lines.push(` json,`);\n lines.push(` pgEnum,`);\n lines.push(` uuid,`);\n lines.push(` bigint,`);\n lines.push(` type AnyPgColumn,`);\n lines.push(` primaryKey,`);\n lines.push(`} from 'drizzle-orm/pg-core';`);\n lines.push(`import { relations } from 'drizzle-orm';`);\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Enums\n const enums = collectEnums(schema);\n if (enums.length > 0) {\n lines.push(`// =============================================================================`);\n lines.push(`// Enums`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const e of enums) {\n lines.push(\n `export const ${e.varName} = pgEnum('${e.dbName}', [${e.values.map((v) => `'${v}'`).join(', ')}]);`,\n );\n }\n lines.push(``);\n }\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generatePostgresTable(table, schema, enums));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generatePostgresTable(table: MergedTable, schema: MergedSchema, enums: EnumDef[]): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = pgTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(\n ` ${fieldName}: ${postgresColumn(fieldName, colName, field, name, enums, schema)},`,\n );\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction postgresColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n enums: EnumDef[],\n schema?: MergedSchema,\n): string {\n let col: string;\n\n if (isEnumType(field.type)) {\n const eVar = enums.find((e) => e.tableName === tableName && e.fieldName === fieldName)?.varName;\n col = eVar ? `${eVar}('${colName}')` : `text('${colName}')`;\n } else {\n switch (field.type) {\n case 'string':\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `uuid('${colName}')`;\n break;\n case 'number':\n col = `integer('${colName}')`;\n break;\n case 'bigint':\n col = `bigint('${colName}', { mode: 'bigint' })`;\n break;\n case 'boolean':\n col = `boolean('${colName}')`;\n break;\n case 'date':\n col = `timestamp('${colName}')`;\n break;\n case 'json':\n col = `json('${colName}')`;\n break;\n default:\n col = `text('${colName}')`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += postgresDefault(field.defaultValue, field.type);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnyPgColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction postgresDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n): string {\n if (value === 'uuid()') {\n return `.$default(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.defaultNow()`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// MySQL Generator\n// =============================================================================\n\nexport function generateMysqlSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// MySQL schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(``);\n lines.push(`import {`);\n lines.push(` mysqlTable,`);\n lines.push(` varchar,`);\n lines.push(` text,`);\n lines.push(` int,`);\n lines.push(` bigint,`);\n lines.push(` boolean,`);\n lines.push(` timestamp,`);\n lines.push(` json,`);\n lines.push(` mysqlEnum,`);\n lines.push(` type AnyMySqlColumn,`);\n lines.push(` primaryKey,`);\n lines.push(`} from 'drizzle-orm/mysql-core';`);\n lines.push(`import { relations, sql } from 'drizzle-orm';`);\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateMysqlTable(table, schema));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generateMysqlTable(table: MergedTable, schema: MergedSchema): string {\n // schema is used by mysqlColumn for FK reference resolution\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = mysqlTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(` ${fieldName}: ${mysqlColumn(fieldName, colName, field, name, schema)},`);\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction mysqlColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n schema?: MergedSchema,\n): string {\n const maxLen = field.maxLength ?? 255;\n let col: string;\n\n if (isEnumType(field.type)) {\n const enumValues = field.type.map((v) => `'${v}'`).join(', ');\n col = `mysqlEnum('${colName}', [${enumValues}])`;\n } else {\n switch (field.type) {\n case 'string':\n col = `varchar('${colName}', { length: ${maxLen} })`;\n break;\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `varchar('${colName}', { length: 36 })`;\n break;\n case 'number':\n col = `int('${colName}')`;\n break;\n case 'bigint':\n col = `bigint('${colName}', { mode: 'bigint' })`;\n break;\n case 'boolean':\n col = `boolean('${colName}')`;\n break;\n case 'date':\n col = `timestamp('${colName}')`;\n break;\n case 'json':\n col = `json('${colName}')`;\n break;\n default:\n col = `varchar('${colName}', { length: ${maxLen} })`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += mysqlDefault(field.defaultValue, field.type);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnyMySqlColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction mysqlDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n): string {\n if (value === 'uuid()') {\n return `.$defaultFn(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.default(sql\\`CURRENT_TIMESTAMP\\`)`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// Append-mode Generators\n// =============================================================================\n//\n// These produce only the table definitions, relations, and type exports\n// for appending to an existing Drizzle schema file. They include:\n// - A commented section marker\n// - Additional imports needed (inserted at top when used by CLI)\n// - Table definitions\n// - Relations\n// - Type exports\n//\n// The CLI handles merging the import lines into the existing file.\n// This approach mirrors how better-auth generates schema code that can\n// be appended to the user's existing schema file.\n\nexport interface AppendSchemaResult {\n /** Import statements that need to be added (CLI merges these) */\n imports: string[];\n /** Table + relation + type code to append */\n code: string;\n}\n\nexport function generateSqliteSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const runtimeImports = collectSqliteRuntimeDefaultImports(schema);\n const imports = [\n `import { sqliteTable, text, integer, primaryKey, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';`,\n `import { relations, sql } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n for (const [importPath, identifiers] of runtimeImports.entries()) {\n imports.push(`import { ${Array.from(identifiers).sort().join(', ')} } from '${importPath}';`);\n }\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateSqliteTable(table, schema));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\nexport function generatePostgresSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const imports = [\n `import { pgTable, text, integer, boolean, timestamp, json, pgEnum, uuid, bigint, primaryKey, type AnyPgColumn } from 'drizzle-orm/pg-core';`,\n `import { relations } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n const enums = collectEnums(schema);\n if (enums.length > 0) {\n for (const e of enums) {\n lines.push(\n `export const ${e.varName} = pgEnum('${e.dbName}', [${e.values.map((v) => `'${v}'`).join(', ')}]);`,\n );\n }\n lines.push(``);\n }\n\n for (const table of schema.tables) {\n lines.push(generatePostgresTable(table, schema, enums));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\nexport function generateMysqlSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const imports = [\n `import { mysqlTable, varchar, text, int, bigint, boolean, timestamp, json, mysqlEnum, primaryKey, type AnyMySqlColumn } from 'drizzle-orm/mysql-core';`,\n `import { relations, sql } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateMysqlTable(table, schema));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\n// =============================================================================\n// Relation Generator (shared across dialects)\n// =============================================================================\n\nfunction generateRelations(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Build a map of FK references: which tables reference which\n const refs: { from: string; fromField: string; to: string; toField: string }[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (field.references) {\n const toTableVar = findTableVarForDbName(field.references.table, schema);\n refs.push({\n from: table.name,\n fromField: fieldName,\n to: toTableVar,\n toField: field.references.field,\n });\n }\n }\n }\n\n for (const table of schema.tables) {\n // Find \"one\" relations (this table has FK → other table)\n const oneRels = refs.filter((r) => r.from === table.name);\n // Find \"many\" relations (other tables have FK → this table)\n const manyRels = refs.filter((r) => r.to === table.name);\n\n if (oneRels.length === 0 && manyRels.length === 0) {\n continue;\n }\n\n const relParts: string[] = [];\n const destructure: string[] = [];\n\n if (oneRels.length > 0) {\n destructure.push('one');\n }\n if (manyRels.length > 0) {\n destructure.push('many');\n }\n\n for (const rel of oneRels) {\n // Derive a relation name from the FK field: \"flowId\" → \"flow\"\n const relName = rel.fromField.replace(/Id$/, '').replace(/(_id)$/, '');\n relParts.push(\n ` ${relName}: one(${rel.to}, { fields: [${table.name}.${rel.fromField}], references: [${rel.to}.${rel.toField}] }),`,\n );\n }\n\n for (const rel of manyRels) {\n // Derive a relation name from the source table\n const relName = rel.from;\n // Avoid duplicates (e.g., multiple FKs from same table)\n relParts.push(` ${relName}: many(${rel.from}),`);\n }\n\n lines.push(\n `export const ${table.name}Relations = relations(${table.name}, ({ ${destructure.join(', ')} }) => ({`,\n );\n lines.push(relParts.join('\\n'));\n lines.push(`}));`);\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Enum Collection\n// =============================================================================\n\ninterface EnumDef {\n varName: string;\n dbName: string;\n values: string[];\n tableName: string;\n fieldName: string;\n}\n\nfunction collectEnums(schema: MergedSchema): EnumDef[] {\n const enums: EnumDef[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (isEnumType(field.type)) {\n const varName = enumVarName(table.name, fieldName);\n const dbName = `${toSnakeCase(table.name)}_${toSnakeCase(fieldName)}`;\n enums.push({\n varName,\n dbName,\n values: field.type,\n tableName: table.name,\n fieldName,\n });\n }\n }\n }\n\n return enums;\n}\n\n// =============================================================================\n// Type Annotation Collection\n// =============================================================================\n\nfunction collectTypeAnnotations(schema: MergedSchema): Set<string> {\n const annotations = new Set<string>();\n for (const table of schema.tables) {\n for (const field of Object.values(table.definition.fields)) {\n if (field.typeAnnotation) {\n annotations.add(field.typeAnnotation);\n }\n }\n }\n return annotations;\n}\n\n// =============================================================================\n// Shared Helpers\n// =============================================================================\n\n/**\n * Build a map from DB table name → JS variable name from the schema.\n */\nfunction buildTableMap(schema: MergedSchema): Map<string, string> {\n const map = new Map<string, string>();\n for (const table of schema.tables) {\n const dbName = table.definition.tableName || toSnakeCase(table.name);\n map.set(dbName, table.name);\n // Also map by logical name for convenience\n map.set(table.name, table.name);\n }\n return map;\n}\n\n/**\n * Find the JS variable name for a given DB table name.\n * Uses the schema to do a proper lookup (e.g., 'execution_traces' → 'nodeExecutions').\n * Falls back to camelCase heuristic if no schema provided.\n */\nfunction findTableVarForDbName(dbName: string, schema?: MergedSchema): string {\n if (schema) {\n const tableMap = buildTableMap(schema);\n const found = tableMap.get(dbName);\n if (found) {\n return found;\n }\n }\n // Fallback: convert snake_case to camelCase\n if (dbName.includes('_')) {\n return dbName.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n }\n return dbName;\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"schema-generator.cjs","names":[],"sources":["../../src/database/schema-generator.ts"],"sourcesContent":["/**\n * Drizzle Schema Generators\n *\n * Converts the merged abstract schema (core + plugins) into three\n * dialect-specific Drizzle ORM schema files as TypeScript source code.\n *\n * Each generator produces a complete, self-contained .ts file that can\n * be used by Drizzle Kit for migration generation.\n */\n\nimport type { PluginFieldAttribute, PluginFieldType } from 'src/types/plugin.types';\nimport type { MergedSchema, MergedTable } from './schema-merger';\n\n// =============================================================================\n// Common Utilities\n// =============================================================================\n\n/**\n * Convert camelCase to snake_case for DB column names.\n */\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Check if a field type is an enum (string array).\n */\nfunction isEnumType(type: PluginFieldType): type is string[] {\n return Array.isArray(type);\n}\n\n/**\n * Generate a variable name for an enum from a table + field.\n * e.g., flowRuns + status → flowRunStatusEnum\n */\nfunction enumVarName(tableName: string, fieldName: string): string {\n return `${tableName}${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}Enum`;\n}\n\nconst SQLITE_RUNTIME_DEFAULT_IMPORTS: Record<string, string> = {\n FlowRunStatus: '@invect/core',\n NodeExecutionStatus: '@invect/core',\n};\n\nfunction collectSqliteRuntimeDefaultImports(schema: MergedSchema): Map<string, Set<string>> {\n const importsByModule = new Map<string, Set<string>>();\n\n for (const table of schema.tables) {\n for (const field of Object.values(table.definition.fields)) {\n if (typeof field.defaultValue !== 'string' || !field.typeAnnotation) {\n continue;\n }\n\n const importPath = SQLITE_RUNTIME_DEFAULT_IMPORTS[field.typeAnnotation];\n if (!importPath) {\n continue;\n }\n\n const existing = importsByModule.get(importPath) ?? new Set<string>();\n existing.add(field.typeAnnotation);\n importsByModule.set(importPath, existing);\n }\n }\n\n return importsByModule;\n}\n\n// =============================================================================\n// SQLite Generator\n// =============================================================================\n\nexport function generateSqliteSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n const runtimeImports = collectSqliteRuntimeDefaultImports(schema);\n\n // Header\n lines.push(`// SQLite schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(``);\n lines.push(\n `import { sqliteTable, text, integer, primaryKey, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';`,\n );\n lines.push(`import { relations, sql } from 'drizzle-orm';`);\n for (const [importPath, identifiers] of runtimeImports.entries()) {\n lines.push(`import { ${Array.from(identifiers).sort().join(', ')} } from '${importPath}';`);\n }\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`// Type imports — these are used for $type<>() annotations`);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Collect all typeAnnotations to generate type imports\n const typeAnnotations = collectTypeAnnotations(schema);\n if (typeAnnotations.size > 0) {\n lines.push(`// Plugin & core type annotations`);\n lines.push(`// You may need to adjust these imports based on your project structure`);\n lines.push(``);\n }\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateSqliteTable(table, schema));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const varName = table.name;\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${varName}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${varName}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generateSqliteTable(table: MergedTable, schema: MergedSchema): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = sqliteTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(` ${fieldName}: ${sqliteColumn(fieldName, colName, field, name, schema)},`);\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction sqliteColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n schema?: MergedSchema,\n): string {\n let col: string;\n\n if (isEnumType(field.type)) {\n // SQLite: enums are just text columns\n col = `text('${colName}')`;\n } else {\n switch (field.type) {\n case 'string':\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `text('${colName}')`;\n break;\n case 'number':\n case 'bigint':\n col = `integer('${colName}')`;\n break;\n case 'boolean':\n col = `integer('${colName}', { mode: 'boolean' })`;\n break;\n case 'date':\n col = `text('${colName}')`;\n break;\n case 'json':\n col = `text('${colName}', { mode: 'json' })`;\n break;\n default:\n col = `text('${colName}')`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += sqliteDefault(field.defaultValue, field.type, field.typeAnnotation);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnySQLiteColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction sqliteDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n typeAnnotation?: string,\n): string {\n if (value === 'uuid()') {\n return `.$defaultFn(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.default(sql\\`CURRENT_TIMESTAMP\\`)`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n if (typeAnnotation && SQLITE_RUNTIME_DEFAULT_IMPORTS[typeAnnotation]) {\n return `.default(${typeAnnotation}.${value})`;\n }\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// PostgreSQL Generator\n// =============================================================================\n\nexport function generatePostgresSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// PostgreSQL schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(``);\n lines.push(`import {`);\n lines.push(` pgTable,`);\n lines.push(` text,`);\n lines.push(` integer,`);\n lines.push(` boolean,`);\n lines.push(` timestamp,`);\n lines.push(` json,`);\n lines.push(` pgEnum,`);\n lines.push(` uuid,`);\n lines.push(` bigint,`);\n lines.push(` type AnyPgColumn,`);\n lines.push(` primaryKey,`);\n lines.push(`} from 'drizzle-orm/pg-core';`);\n lines.push(`import { relations } from 'drizzle-orm';`);\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Enums\n const enums = collectEnums(schema);\n if (enums.length > 0) {\n lines.push(`// =============================================================================`);\n lines.push(`// Enums`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const e of enums) {\n lines.push(\n `export const ${e.varName} = pgEnum('${e.dbName}', [${e.values.map((v) => `'${v}'`).join(', ')}]);`,\n );\n }\n lines.push(``);\n }\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generatePostgresTable(table, schema, enums));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generatePostgresTable(table: MergedTable, schema: MergedSchema, enums: EnumDef[]): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = pgTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(\n ` ${fieldName}: ${postgresColumn(fieldName, colName, field, name, enums, schema)},`,\n );\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction postgresColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n enums: EnumDef[],\n schema?: MergedSchema,\n): string {\n let col: string;\n\n if (isEnumType(field.type)) {\n const eVar = enums.find((e) => e.tableName === tableName && e.fieldName === fieldName)?.varName;\n col = eVar ? `${eVar}('${colName}')` : `text('${colName}')`;\n } else {\n switch (field.type) {\n case 'string':\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `uuid('${colName}')`;\n break;\n case 'number':\n col = `integer('${colName}')`;\n break;\n case 'bigint':\n col = `bigint('${colName}', { mode: 'bigint' })`;\n break;\n case 'boolean':\n col = `boolean('${colName}')`;\n break;\n case 'date':\n col = `timestamp('${colName}')`;\n break;\n case 'json':\n col = `json('${colName}')`;\n break;\n default:\n col = `text('${colName}')`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += postgresDefault(field.defaultValue, field.type);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnyPgColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction postgresDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n): string {\n if (value === 'uuid()') {\n return `.$default(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.defaultNow()`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// MySQL Generator\n// =============================================================================\n\nexport function generateMysqlSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// MySQL schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(``);\n lines.push(`import {`);\n lines.push(` mysqlTable,`);\n lines.push(` varchar,`);\n lines.push(` text,`);\n lines.push(` int,`);\n lines.push(` bigint,`);\n lines.push(` boolean,`);\n lines.push(` timestamp,`);\n lines.push(` json,`);\n lines.push(` mysqlEnum,`);\n lines.push(` type AnyMySqlColumn,`);\n lines.push(` primaryKey,`);\n lines.push(`} from 'drizzle-orm/mysql-core';`);\n lines.push(`import { relations, sql } from 'drizzle-orm';`);\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateMysqlTable(table, schema));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generateMysqlTable(table: MergedTable, schema: MergedSchema): string {\n // schema is used by mysqlColumn for FK reference resolution\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = mysqlTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(` ${fieldName}: ${mysqlColumn(fieldName, colName, field, name, schema)},`);\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction mysqlColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n schema?: MergedSchema,\n): string {\n const maxLen = field.maxLength ?? 255;\n let col: string;\n\n if (isEnumType(field.type)) {\n const enumValues = field.type.map((v) => `'${v}'`).join(', ');\n col = `mysqlEnum('${colName}', [${enumValues}])`;\n } else {\n switch (field.type) {\n case 'string':\n col = `varchar('${colName}', { length: ${maxLen} })`;\n break;\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `varchar('${colName}', { length: 36 })`;\n break;\n case 'number':\n col = `int('${colName}')`;\n break;\n case 'bigint':\n col = `bigint('${colName}', { mode: 'bigint' })`;\n break;\n case 'boolean':\n col = `boolean('${colName}')`;\n break;\n case 'date':\n col = `timestamp('${colName}')`;\n break;\n case 'json':\n col = `json('${colName}')`;\n break;\n default:\n col = `varchar('${colName}', { length: ${maxLen} })`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += mysqlDefault(field.defaultValue, field.type);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnyMySqlColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction mysqlDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n): string {\n if (value === 'uuid()') {\n return `.$defaultFn(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.default(sql\\`CURRENT_TIMESTAMP\\`)`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// Append-mode Generators\n// =============================================================================\n//\n// These produce only the table definitions, relations, and type exports\n// for appending to an existing Drizzle schema file. They include:\n// - A commented section marker\n// - Additional imports needed (inserted at top when used by CLI)\n// - Table definitions\n// - Relations\n// - Type exports\n//\n// The CLI handles merging the import lines into the existing file.\n// This approach mirrors how better-auth generates schema code that can\n// be appended to the user's existing schema file.\n\nexport interface AppendSchemaResult {\n /** Import statements that need to be added (CLI merges these) */\n imports: string[];\n /** Table + relation + type code to append */\n code: string;\n}\n\nexport function generateSqliteSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const runtimeImports = collectSqliteRuntimeDefaultImports(schema);\n const imports = [\n `import { sqliteTable, text, integer, primaryKey, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';`,\n `import { relations, sql } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n for (const [importPath, identifiers] of runtimeImports.entries()) {\n imports.push(`import { ${Array.from(identifiers).sort().join(', ')} } from '${importPath}';`);\n }\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateSqliteTable(table, schema));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\nexport function generatePostgresSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const imports = [\n `import { pgTable, text, integer, boolean, timestamp, json, pgEnum, uuid, bigint, primaryKey, type AnyPgColumn } from 'drizzle-orm/pg-core';`,\n `import { relations } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n const enums = collectEnums(schema);\n if (enums.length > 0) {\n for (const e of enums) {\n lines.push(\n `export const ${e.varName} = pgEnum('${e.dbName}', [${e.values.map((v) => `'${v}'`).join(', ')}]);`,\n );\n }\n lines.push(``);\n }\n\n for (const table of schema.tables) {\n lines.push(generatePostgresTable(table, schema, enums));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\nexport function generateMysqlSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const imports = [\n `import { mysqlTable, varchar, text, int, bigint, boolean, timestamp, json, mysqlEnum, primaryKey, type AnyMySqlColumn } from 'drizzle-orm/mysql-core';`,\n `import { relations, sql } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateMysqlTable(table, schema));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\n// =============================================================================\n// Relation Generator (shared across dialects)\n// =============================================================================\n\nfunction generateRelations(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Build a map of FK references: which tables reference which\n const refs: { from: string; fromField: string; to: string; toField: string }[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (field.references) {\n const toTableVar = findTableVarForDbName(field.references.table, schema);\n refs.push({\n from: table.name,\n fromField: fieldName,\n to: toTableVar,\n toField: field.references.field,\n });\n }\n }\n }\n\n for (const table of schema.tables) {\n // Find \"one\" relations (this table has FK → other table)\n const oneRels = refs.filter((r) => r.from === table.name);\n // Find \"many\" relations (other tables have FK → this table)\n const manyRels = refs.filter((r) => r.to === table.name);\n\n if (oneRels.length === 0 && manyRels.length === 0) {\n continue;\n }\n\n const relParts: string[] = [];\n const destructure: string[] = [];\n\n if (oneRels.length > 0) {\n destructure.push('one');\n }\n if (manyRels.length > 0) {\n destructure.push('many');\n }\n\n for (const rel of oneRels) {\n // Derive a relation name from the FK field: \"flowId\" → \"flow\"\n const relName = rel.fromField.replace(/Id$/, '').replace(/(_id)$/, '');\n relParts.push(\n ` ${relName}: one(${rel.to}, { fields: [${table.name}.${rel.fromField}], references: [${rel.to}.${rel.toField}] }),`,\n );\n }\n\n for (const rel of manyRels) {\n // Derive a relation name from the source table\n const relName = rel.from;\n // Avoid duplicates (e.g., multiple FKs from same table)\n relParts.push(` ${relName}: many(${rel.from}),`);\n }\n\n lines.push(\n `export const ${table.name}Relations = relations(${table.name}, ({ ${destructure.join(', ')} }) => ({`,\n );\n lines.push(relParts.join('\\n'));\n lines.push(`}));`);\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Enum Collection\n// =============================================================================\n\ninterface EnumDef {\n varName: string;\n dbName: string;\n values: string[];\n tableName: string;\n fieldName: string;\n}\n\nfunction collectEnums(schema: MergedSchema): EnumDef[] {\n const enums: EnumDef[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (isEnumType(field.type)) {\n const varName = enumVarName(table.name, fieldName);\n const dbName = `${toSnakeCase(table.name)}_${toSnakeCase(fieldName)}`;\n enums.push({\n varName,\n dbName,\n values: field.type,\n tableName: table.name,\n fieldName,\n });\n }\n }\n }\n\n return enums;\n}\n\n// =============================================================================\n// Type Annotation Collection\n// =============================================================================\n\nfunction collectTypeAnnotations(schema: MergedSchema): Set<string> {\n const annotations = new Set<string>();\n for (const table of schema.tables) {\n for (const field of Object.values(table.definition.fields)) {\n if (field.typeAnnotation) {\n annotations.add(field.typeAnnotation);\n }\n }\n }\n return annotations;\n}\n\n// =============================================================================\n// Shared Helpers\n// =============================================================================\n\n/**\n * Build a map from DB table name → JS variable name from the schema.\n */\nfunction buildTableMap(schema: MergedSchema): Map<string, string> {\n const map = new Map<string, string>();\n for (const table of schema.tables) {\n const dbName = table.definition.tableName || toSnakeCase(table.name);\n map.set(dbName, table.name);\n // Also map by logical name for convenience\n map.set(table.name, table.name);\n }\n return map;\n}\n\n/**\n * Find the JS variable name for a given DB table name.\n * Uses the schema to do a proper lookup (e.g., 'execution_traces' → 'nodeExecutions').\n * Falls back to camelCase heuristic if no schema provided.\n */\nfunction findTableVarForDbName(dbName: string, schema?: MergedSchema): string {\n if (schema) {\n const tableMap = buildTableMap(schema);\n const found = tableMap.get(dbName);\n if (found) {\n return found;\n }\n }\n // Fallback: convert snake_case to camelCase\n if (dbName.includes('_')) {\n return dbName.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n }\n return dbName;\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n"],"mappings":"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"}
@@ -38,7 +38,7 @@ function generateSqliteSchema(schema) {
38
38
  const lines = [];
39
39
  const runtimeImports = collectSqliteRuntimeDefaultImports(schema);
40
40
  lines.push(`// SQLite schema for Invect — AUTO-GENERATED by @invect/cli`);
41
- lines.push(`// Do not edit manually. Run \`npx invect generate\` to regenerate.`);
41
+ lines.push(`// Do not edit manually. Run \`npx invect-cli generate\` to regenerate.`);
42
42
  lines.push(``);
43
43
  lines.push(`import { sqliteTable, text, integer, primaryKey, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';`);
44
44
  lines.push(`import { relations, sql } from 'drizzle-orm';`);
@@ -149,7 +149,7 @@ function sqliteDefault(value, _type, typeAnnotation) {
149
149
  function generatePostgresSchema(schema) {
150
150
  const lines = [];
151
151
  lines.push(`// PostgreSQL schema for Invect — AUTO-GENERATED by @invect/cli`);
152
- lines.push(`// Do not edit manually. Run \`npx invect generate\` to regenerate.`);
152
+ lines.push(`// Do not edit manually. Run \`npx invect-cli generate\` to regenerate.`);
153
153
  lines.push(``);
154
154
  lines.push(`import {`);
155
155
  lines.push(` pgTable,`);
@@ -274,7 +274,7 @@ function postgresDefault(value, _type) {
274
274
  function generateMysqlSchema(schema) {
275
275
  const lines = [];
276
276
  lines.push(`// MySQL schema for Invect — AUTO-GENERATED by @invect/cli`);
277
- lines.push(`// Do not edit manually. Run \`npx invect generate\` to regenerate.`);
277
+ lines.push(`// Do not edit manually. Run \`npx invect-cli generate\` to regenerate.`);
278
278
  lines.push(``);
279
279
  lines.push(`import {`);
280
280
  lines.push(` mysqlTable,`);
@@ -400,7 +400,7 @@ function generateSqliteSchemaAppend(schema) {
400
400
  lines.push(``);
401
401
  lines.push(`// =============================================================================`);
402
402
  lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);
403
- lines.push(`// Do not edit below this line. Run \`npx invect generate\` to regenerate.`);
403
+ lines.push(`// Do not edit below this line. Run \`npx invect-cli generate\` to regenerate.`);
404
404
  lines.push(`// =============================================================================`);
405
405
  lines.push(``);
406
406
  for (const table of schema.tables) {
@@ -429,7 +429,7 @@ function generatePostgresSchemaAppend(schema) {
429
429
  lines.push(``);
430
430
  lines.push(`// =============================================================================`);
431
431
  lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);
432
- lines.push(`// Do not edit below this line. Run \`npx invect generate\` to regenerate.`);
432
+ lines.push(`// Do not edit below this line. Run \`npx invect-cli generate\` to regenerate.`);
433
433
  lines.push(`// =============================================================================`);
434
434
  lines.push(``);
435
435
  const enums = collectEnums(schema);
@@ -463,7 +463,7 @@ function generateMysqlSchemaAppend(schema) {
463
463
  lines.push(``);
464
464
  lines.push(`// =============================================================================`);
465
465
  lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);
466
- lines.push(`// Do not edit below this line. Run \`npx invect generate\` to regenerate.`);
466
+ lines.push(`// Do not edit below this line. Run \`npx invect-cli generate\` to regenerate.`);
467
467
  lines.push(`// =============================================================================`);
468
468
  lines.push(``);
469
469
  for (const table of schema.tables) {
@@ -1 +1 @@
1
- {"version":3,"file":"schema-generator.js","names":[],"sources":["../../src/database/schema-generator.ts"],"sourcesContent":["/**\n * Drizzle Schema Generators\n *\n * Converts the merged abstract schema (core + plugins) into three\n * dialect-specific Drizzle ORM schema files as TypeScript source code.\n *\n * Each generator produces a complete, self-contained .ts file that can\n * be used by Drizzle Kit for migration generation.\n */\n\nimport type { PluginFieldAttribute, PluginFieldType } from 'src/types/plugin.types';\nimport type { MergedSchema, MergedTable } from './schema-merger';\n\n// =============================================================================\n// Common Utilities\n// =============================================================================\n\n/**\n * Convert camelCase to snake_case for DB column names.\n */\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Check if a field type is an enum (string array).\n */\nfunction isEnumType(type: PluginFieldType): type is string[] {\n return Array.isArray(type);\n}\n\n/**\n * Generate a variable name for an enum from a table + field.\n * e.g., flowRuns + status → flowRunStatusEnum\n */\nfunction enumVarName(tableName: string, fieldName: string): string {\n return `${tableName}${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}Enum`;\n}\n\nconst SQLITE_RUNTIME_DEFAULT_IMPORTS: Record<string, string> = {\n FlowRunStatus: '@invect/core',\n NodeExecutionStatus: '@invect/core',\n};\n\nfunction collectSqliteRuntimeDefaultImports(schema: MergedSchema): Map<string, Set<string>> {\n const importsByModule = new Map<string, Set<string>>();\n\n for (const table of schema.tables) {\n for (const field of Object.values(table.definition.fields)) {\n if (typeof field.defaultValue !== 'string' || !field.typeAnnotation) {\n continue;\n }\n\n const importPath = SQLITE_RUNTIME_DEFAULT_IMPORTS[field.typeAnnotation];\n if (!importPath) {\n continue;\n }\n\n const existing = importsByModule.get(importPath) ?? new Set<string>();\n existing.add(field.typeAnnotation);\n importsByModule.set(importPath, existing);\n }\n }\n\n return importsByModule;\n}\n\n// =============================================================================\n// SQLite Generator\n// =============================================================================\n\nexport function generateSqliteSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n const runtimeImports = collectSqliteRuntimeDefaultImports(schema);\n\n // Header\n lines.push(`// SQLite schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(``);\n lines.push(\n `import { sqliteTable, text, integer, primaryKey, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';`,\n );\n lines.push(`import { relations, sql } from 'drizzle-orm';`);\n for (const [importPath, identifiers] of runtimeImports.entries()) {\n lines.push(`import { ${Array.from(identifiers).sort().join(', ')} } from '${importPath}';`);\n }\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`// Type imports — these are used for $type<>() annotations`);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Collect all typeAnnotations to generate type imports\n const typeAnnotations = collectTypeAnnotations(schema);\n if (typeAnnotations.size > 0) {\n lines.push(`// Plugin & core type annotations`);\n lines.push(`// You may need to adjust these imports based on your project structure`);\n lines.push(``);\n }\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateSqliteTable(table, schema));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const varName = table.name;\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${varName}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${varName}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generateSqliteTable(table: MergedTable, schema: MergedSchema): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = sqliteTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(` ${fieldName}: ${sqliteColumn(fieldName, colName, field, name, schema)},`);\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction sqliteColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n schema?: MergedSchema,\n): string {\n let col: string;\n\n if (isEnumType(field.type)) {\n // SQLite: enums are just text columns\n col = `text('${colName}')`;\n } else {\n switch (field.type) {\n case 'string':\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `text('${colName}')`;\n break;\n case 'number':\n case 'bigint':\n col = `integer('${colName}')`;\n break;\n case 'boolean':\n col = `integer('${colName}', { mode: 'boolean' })`;\n break;\n case 'date':\n col = `text('${colName}')`;\n break;\n case 'json':\n col = `text('${colName}', { mode: 'json' })`;\n break;\n default:\n col = `text('${colName}')`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += sqliteDefault(field.defaultValue, field.type, field.typeAnnotation);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnySQLiteColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction sqliteDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n typeAnnotation?: string,\n): string {\n if (value === 'uuid()') {\n return `.$defaultFn(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.default(sql\\`CURRENT_TIMESTAMP\\`)`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n if (typeAnnotation && SQLITE_RUNTIME_DEFAULT_IMPORTS[typeAnnotation]) {\n return `.default(${typeAnnotation}.${value})`;\n }\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// PostgreSQL Generator\n// =============================================================================\n\nexport function generatePostgresSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// PostgreSQL schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(``);\n lines.push(`import {`);\n lines.push(` pgTable,`);\n lines.push(` text,`);\n lines.push(` integer,`);\n lines.push(` boolean,`);\n lines.push(` timestamp,`);\n lines.push(` json,`);\n lines.push(` pgEnum,`);\n lines.push(` uuid,`);\n lines.push(` bigint,`);\n lines.push(` type AnyPgColumn,`);\n lines.push(` primaryKey,`);\n lines.push(`} from 'drizzle-orm/pg-core';`);\n lines.push(`import { relations } from 'drizzle-orm';`);\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Enums\n const enums = collectEnums(schema);\n if (enums.length > 0) {\n lines.push(`// =============================================================================`);\n lines.push(`// Enums`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const e of enums) {\n lines.push(\n `export const ${e.varName} = pgEnum('${e.dbName}', [${e.values.map((v) => `'${v}'`).join(', ')}]);`,\n );\n }\n lines.push(``);\n }\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generatePostgresTable(table, schema, enums));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generatePostgresTable(table: MergedTable, schema: MergedSchema, enums: EnumDef[]): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = pgTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(\n ` ${fieldName}: ${postgresColumn(fieldName, colName, field, name, enums, schema)},`,\n );\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction postgresColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n enums: EnumDef[],\n schema?: MergedSchema,\n): string {\n let col: string;\n\n if (isEnumType(field.type)) {\n const eVar = enums.find((e) => e.tableName === tableName && e.fieldName === fieldName)?.varName;\n col = eVar ? `${eVar}('${colName}')` : `text('${colName}')`;\n } else {\n switch (field.type) {\n case 'string':\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `uuid('${colName}')`;\n break;\n case 'number':\n col = `integer('${colName}')`;\n break;\n case 'bigint':\n col = `bigint('${colName}', { mode: 'bigint' })`;\n break;\n case 'boolean':\n col = `boolean('${colName}')`;\n break;\n case 'date':\n col = `timestamp('${colName}')`;\n break;\n case 'json':\n col = `json('${colName}')`;\n break;\n default:\n col = `text('${colName}')`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += postgresDefault(field.defaultValue, field.type);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnyPgColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction postgresDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n): string {\n if (value === 'uuid()') {\n return `.$default(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.defaultNow()`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// MySQL Generator\n// =============================================================================\n\nexport function generateMysqlSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// MySQL schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(``);\n lines.push(`import {`);\n lines.push(` mysqlTable,`);\n lines.push(` varchar,`);\n lines.push(` text,`);\n lines.push(` int,`);\n lines.push(` bigint,`);\n lines.push(` boolean,`);\n lines.push(` timestamp,`);\n lines.push(` json,`);\n lines.push(` mysqlEnum,`);\n lines.push(` type AnyMySqlColumn,`);\n lines.push(` primaryKey,`);\n lines.push(`} from 'drizzle-orm/mysql-core';`);\n lines.push(`import { relations, sql } from 'drizzle-orm';`);\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateMysqlTable(table, schema));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generateMysqlTable(table: MergedTable, schema: MergedSchema): string {\n // schema is used by mysqlColumn for FK reference resolution\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = mysqlTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(` ${fieldName}: ${mysqlColumn(fieldName, colName, field, name, schema)},`);\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction mysqlColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n schema?: MergedSchema,\n): string {\n const maxLen = field.maxLength ?? 255;\n let col: string;\n\n if (isEnumType(field.type)) {\n const enumValues = field.type.map((v) => `'${v}'`).join(', ');\n col = `mysqlEnum('${colName}', [${enumValues}])`;\n } else {\n switch (field.type) {\n case 'string':\n col = `varchar('${colName}', { length: ${maxLen} })`;\n break;\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `varchar('${colName}', { length: 36 })`;\n break;\n case 'number':\n col = `int('${colName}')`;\n break;\n case 'bigint':\n col = `bigint('${colName}', { mode: 'bigint' })`;\n break;\n case 'boolean':\n col = `boolean('${colName}')`;\n break;\n case 'date':\n col = `timestamp('${colName}')`;\n break;\n case 'json':\n col = `json('${colName}')`;\n break;\n default:\n col = `varchar('${colName}', { length: ${maxLen} })`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += mysqlDefault(field.defaultValue, field.type);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnyMySqlColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction mysqlDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n): string {\n if (value === 'uuid()') {\n return `.$defaultFn(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.default(sql\\`CURRENT_TIMESTAMP\\`)`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// Append-mode Generators\n// =============================================================================\n//\n// These produce only the table definitions, relations, and type exports\n// for appending to an existing Drizzle schema file. They include:\n// - A commented section marker\n// - Additional imports needed (inserted at top when used by CLI)\n// - Table definitions\n// - Relations\n// - Type exports\n//\n// The CLI handles merging the import lines into the existing file.\n// This approach mirrors how better-auth generates schema code that can\n// be appended to the user's existing schema file.\n\nexport interface AppendSchemaResult {\n /** Import statements that need to be added (CLI merges these) */\n imports: string[];\n /** Table + relation + type code to append */\n code: string;\n}\n\nexport function generateSqliteSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const runtimeImports = collectSqliteRuntimeDefaultImports(schema);\n const imports = [\n `import { sqliteTable, text, integer, primaryKey, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';`,\n `import { relations, sql } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n for (const [importPath, identifiers] of runtimeImports.entries()) {\n imports.push(`import { ${Array.from(identifiers).sort().join(', ')} } from '${importPath}';`);\n }\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateSqliteTable(table, schema));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\nexport function generatePostgresSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const imports = [\n `import { pgTable, text, integer, boolean, timestamp, json, pgEnum, uuid, bigint, primaryKey, type AnyPgColumn } from 'drizzle-orm/pg-core';`,\n `import { relations } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n const enums = collectEnums(schema);\n if (enums.length > 0) {\n for (const e of enums) {\n lines.push(\n `export const ${e.varName} = pgEnum('${e.dbName}', [${e.values.map((v) => `'${v}'`).join(', ')}]);`,\n );\n }\n lines.push(``);\n }\n\n for (const table of schema.tables) {\n lines.push(generatePostgresTable(table, schema, enums));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\nexport function generateMysqlSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const imports = [\n `import { mysqlTable, varchar, text, int, bigint, boolean, timestamp, json, mysqlEnum, primaryKey, type AnyMySqlColumn } from 'drizzle-orm/mysql-core';`,\n `import { relations, sql } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateMysqlTable(table, schema));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\n// =============================================================================\n// Relation Generator (shared across dialects)\n// =============================================================================\n\nfunction generateRelations(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Build a map of FK references: which tables reference which\n const refs: { from: string; fromField: string; to: string; toField: string }[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (field.references) {\n const toTableVar = findTableVarForDbName(field.references.table, schema);\n refs.push({\n from: table.name,\n fromField: fieldName,\n to: toTableVar,\n toField: field.references.field,\n });\n }\n }\n }\n\n for (const table of schema.tables) {\n // Find \"one\" relations (this table has FK → other table)\n const oneRels = refs.filter((r) => r.from === table.name);\n // Find \"many\" relations (other tables have FK → this table)\n const manyRels = refs.filter((r) => r.to === table.name);\n\n if (oneRels.length === 0 && manyRels.length === 0) {\n continue;\n }\n\n const relParts: string[] = [];\n const destructure: string[] = [];\n\n if (oneRels.length > 0) {\n destructure.push('one');\n }\n if (manyRels.length > 0) {\n destructure.push('many');\n }\n\n for (const rel of oneRels) {\n // Derive a relation name from the FK field: \"flowId\" → \"flow\"\n const relName = rel.fromField.replace(/Id$/, '').replace(/(_id)$/, '');\n relParts.push(\n ` ${relName}: one(${rel.to}, { fields: [${table.name}.${rel.fromField}], references: [${rel.to}.${rel.toField}] }),`,\n );\n }\n\n for (const rel of manyRels) {\n // Derive a relation name from the source table\n const relName = rel.from;\n // Avoid duplicates (e.g., multiple FKs from same table)\n relParts.push(` ${relName}: many(${rel.from}),`);\n }\n\n lines.push(\n `export const ${table.name}Relations = relations(${table.name}, ({ ${destructure.join(', ')} }) => ({`,\n );\n lines.push(relParts.join('\\n'));\n lines.push(`}));`);\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Enum Collection\n// =============================================================================\n\ninterface EnumDef {\n varName: string;\n dbName: string;\n values: string[];\n tableName: string;\n fieldName: string;\n}\n\nfunction collectEnums(schema: MergedSchema): EnumDef[] {\n const enums: EnumDef[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (isEnumType(field.type)) {\n const varName = enumVarName(table.name, fieldName);\n const dbName = `${toSnakeCase(table.name)}_${toSnakeCase(fieldName)}`;\n enums.push({\n varName,\n dbName,\n values: field.type,\n tableName: table.name,\n fieldName,\n });\n }\n }\n }\n\n return enums;\n}\n\n// =============================================================================\n// Type Annotation Collection\n// =============================================================================\n\nfunction collectTypeAnnotations(schema: MergedSchema): Set<string> {\n const annotations = new Set<string>();\n for (const table of schema.tables) {\n for (const field of Object.values(table.definition.fields)) {\n if (field.typeAnnotation) {\n annotations.add(field.typeAnnotation);\n }\n }\n }\n return annotations;\n}\n\n// =============================================================================\n// Shared Helpers\n// =============================================================================\n\n/**\n * Build a map from DB table name → JS variable name from the schema.\n */\nfunction buildTableMap(schema: MergedSchema): Map<string, string> {\n const map = new Map<string, string>();\n for (const table of schema.tables) {\n const dbName = table.definition.tableName || toSnakeCase(table.name);\n map.set(dbName, table.name);\n // Also map by logical name for convenience\n map.set(table.name, table.name);\n }\n return map;\n}\n\n/**\n * Find the JS variable name for a given DB table name.\n * Uses the schema to do a proper lookup (e.g., 'execution_traces' → 'nodeExecutions').\n * Falls back to camelCase heuristic if no schema provided.\n */\nfunction findTableVarForDbName(dbName: string, schema?: MergedSchema): string {\n if (schema) {\n const tableMap = buildTableMap(schema);\n const found = tableMap.get(dbName);\n if (found) {\n return found;\n }\n }\n // Fallback: convert snake_case to camelCase\n if (dbName.includes('_')) {\n return dbName.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n }\n return dbName;\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n"],"mappings":";;;;AAoBA,SAAS,YAAY,KAAqB;AACxC,QAAO,IAAI,QAAQ,WAAW,WAAW,IAAI,OAAO,aAAa,GAAG;;;;;AAMtE,SAAS,WAAW,MAAyC;AAC3D,QAAO,MAAM,QAAQ,KAAK;;;;;;AAO5B,SAAS,YAAY,WAAmB,WAA2B;AACjE,QAAO,GAAG,YAAY,UAAU,OAAO,EAAE,CAAC,aAAa,GAAG,UAAU,MAAM,EAAE,CAAC;;AAG/E,MAAM,iCAAyD;CAC7D,eAAe;CACf,qBAAqB;CACtB;AAED,SAAS,mCAAmC,QAAgD;CAC1F,MAAM,kCAAkB,IAAI,KAA0B;AAEtD,MAAK,MAAM,SAAS,OAAO,OACzB,MAAK,MAAM,SAAS,OAAO,OAAO,MAAM,WAAW,OAAO,EAAE;AAC1D,MAAI,OAAO,MAAM,iBAAiB,YAAY,CAAC,MAAM,eACnD;EAGF,MAAM,aAAa,+BAA+B,MAAM;AACxD,MAAI,CAAC,WACH;EAGF,MAAM,WAAW,gBAAgB,IAAI,WAAW,oBAAI,IAAI,KAAa;AACrE,WAAS,IAAI,MAAM,eAAe;AAClC,kBAAgB,IAAI,YAAY,SAAS;;AAI7C,QAAO;;AAOT,SAAgB,qBAAqB,QAA8B;CACjE,MAAM,QAAkB,EAAE;CAC1B,MAAM,iBAAiB,mCAAmC,OAAO;AAGjE,OAAM,KAAK,8DAA8D;AACzE,OAAM,KAAK,sEAAsE;AACjF,OAAM,KAAK,GAAG;AACd,OAAM,KACJ,0GACD;AACD,OAAM,KAAK,gDAAgD;AAC3D,MAAK,MAAM,CAAC,YAAY,gBAAgB,eAAe,SAAS,CAC9D,OAAM,KAAK,YAAY,MAAM,KAAK,YAAY,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,WAAW,WAAW,IAAI;AAE7F,OAAM,KAAK,uCAAuC;AAClD,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,6DAA6D;AACxE,OAAM,KAAK,sCAAsC;AACjD,OAAM,KAAK,GAAG;AAId,KADwB,uBAAuB,OAAO,CAClC,OAAO,GAAG;AAC5B,QAAM,KAAK,oCAAoC;AAC/C,QAAM,KAAK,0EAA0E;AACrF,QAAM,KAAK,GAAG;;AAIhB,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,YAAY;AACvB,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AAEd,MAAK,MAAM,SAAS,OAAO,QAAQ;AACjC,QAAM,KAAK,oBAAoB,OAAO,OAAO,CAAC;AAC9C,QAAM,KAAK,GAAG;;AAIhB,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,eAAe;AAC1B,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,kBAAkB,OAAO,CAAC;AAGrC,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,kBAAkB;AAC7B,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AACd,MAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,UAAU,MAAM;EACtB,MAAM,WAAW,WAAW,MAAM,KAAK;AACvC,QAAM,KAAK,eAAe,SAAS,YAAY,QAAQ,gBAAgB;AACvE,QAAM,KAAK,kBAAkB,SAAS,YAAY,QAAQ,gBAAgB;;AAG5E,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,oBAAoB,OAAoB,QAA8B;CAC7E,MAAM,QAAkB,EAAE;CAC1B,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,cAAc,WAAW,aAAa,YAAY,KAAK;CAC7D,MAAM,iBAAiB,CAAC,CAAC,WAAW,qBAAqB;AAEzD,OAAM,KAAK,gBAAgB,KAAK,kBAAkB,YAAY,MAAM;AAEpE,MAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,WAAW,OAAO,EAAE;EAClE,MAAM,UAAU,YAAY,UAAU;AACtC,QAAM,KAAK,KAAK,UAAU,IAAI,aAAa,WAAW,SAAS,OAAO,MAAM,OAAO,CAAC,GAAG;;AAGzF,KAAI,gBAAgB;EAClB,MAAM,UAAU,WAAW,uBAAuB,EAAE,EAAE,KAAK,MAAM,SAAS,IAAI,CAAC,KAAK,KAAK;AACzF,QAAM,KAAK,yCAAyC,OAAO,SAAS;OAEpE,OAAM,KAAK,MAAM;AAGnB,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,aACP,WACA,SACA,OACA,WACA,QACQ;CACR,IAAI;AAEJ,KAAI,WAAW,MAAM,KAAK,CAExB,OAAM,SAAS,QAAQ;KAEvB,SAAQ,MAAM,MAAd;EACE,KAAK;EACL,KAAK;AACH,SAAM,SAAS,QAAQ;AACvB;EACF,KAAK;AACH,SAAM,SAAS,QAAQ;AACvB;EACF,KAAK;EACL,KAAK;AACH,SAAM,YAAY,QAAQ;AAC1B;EACF,KAAK;AACH,SAAM,YAAY,QAAQ;AAC1B;EACF,KAAK;AACH,SAAM,SAAS,QAAQ;AACvB;EACF,KAAK;AACH,SAAM,SAAS,QAAQ;AACvB;EACF,QACE,OAAM,SAAS,QAAQ;;AAK7B,KAAI,MAAM,eACR,QAAO,UAAU,MAAM,eAAe;AAIxC,KAAI,MAAM,WACR,QAAO;AAIT,KAAI,MAAM,aAAa,MACrB,QAAO;AAIT,KAAI,MAAM,OACR,QAAO;AAIT,KAAI,MAAM,iBAAiB,KAAA,EACzB,QAAO,cAAc,MAAM,cAAc,MAAM,MAAM,MAAM,eAAe;AAI5E,KAAI,MAAM,YAAY;EACpB,MAAM,WAAW,sBAAsB,MAAM,WAAW,OAAO,OAAO;EACtE,MAAM,WAAW,MAAM,WAAW;EAClC,MAAM,WAAW,MAAM,WAAW,YAAY;AAC9C,MAAI,aAAa,UACf,QAAO,sCAAsC,SAAS,GAAG,SAAS,iBAAiB,SAAS;MAE5F,QAAO,qBAAqB,SAAS,GAAG,SAAS,iBAAiB,SAAS;;AAI/E,QAAO;;AAGT,SAAS,cACP,OACA,OACA,gBACQ;AACR,KAAI,UAAU,SACZ,QAAO;AAET,KAAI,UAAU,QACZ,QAAO;AAET,KAAI,OAAO,UAAU,UACnB,QAAO,YAAY,MAAM;AAE3B,KAAI,OAAO,UAAU,SACnB,QAAO,YAAY,MAAM;AAE3B,KAAI,OAAO,UAAU,UAAU;AAC7B,MAAI,kBAAkB,+BAA+B,gBACnD,QAAO,YAAY,eAAe,GAAG,MAAM;AAE7C,SAAO,aAAa,MAAM;;AAE5B,QAAO;;AAOT,SAAgB,uBAAuB,QAA8B;CACnE,MAAM,QAAkB,EAAE;AAG1B,OAAM,KAAK,kEAAkE;AAC7E,OAAM,KAAK,sEAAsE;AACjF,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,WAAW;AACtB,OAAM,KAAK,aAAa;AACxB,OAAM,KAAK,UAAU;AACrB,OAAM,KAAK,aAAa;AACxB,OAAM,KAAK,aAAa;AACxB,OAAM,KAAK,eAAe;AAC1B,OAAM,KAAK,UAAU;AACrB,OAAM,KAAK,YAAY;AACvB,OAAM,KAAK,UAAU;AACrB,OAAM,KAAK,YAAY;AACvB,OAAM,KAAK,sBAAsB;AACjC,OAAM,KAAK,gBAAgB;AAC3B,OAAM,KAAK,gCAAgC;AAC3C,OAAM,KAAK,2CAA2C;AACtD,OAAM,KAAK,uCAAuC;AAClD,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,sCAAsC;AACjD,OAAM,KAAK,GAAG;CAGd,MAAM,QAAQ,aAAa,OAAO;AAClC,KAAI,MAAM,SAAS,GAAG;AACpB,QAAM,KAAK,mFAAmF;AAC9F,QAAM,KAAK,WAAW;AACtB,QAAM,KAAK,mFAAmF;AAC9F,QAAM,KAAK,GAAG;AACd,OAAK,MAAM,KAAK,MACd,OAAM,KACJ,gBAAgB,EAAE,QAAQ,aAAa,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK,CAAC,KAChG;AAEH,QAAM,KAAK,GAAG;;AAIhB,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,YAAY;AACvB,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AAEd,MAAK,MAAM,SAAS,OAAO,QAAQ;AACjC,QAAM,KAAK,sBAAsB,OAAO,QAAQ,MAAM,CAAC;AACvD,QAAM,KAAK,GAAG;;AAIhB,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,eAAe;AAC1B,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,kBAAkB,OAAO,CAAC;AAGrC,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,kBAAkB;AAC7B,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AACd,MAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,WAAW,WAAW,MAAM,KAAK;AACvC,QAAM,KAAK,eAAe,SAAS,YAAY,MAAM,KAAK,gBAAgB;AAC1E,QAAM,KAAK,kBAAkB,SAAS,YAAY,MAAM,KAAK,gBAAgB;;AAG/E,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,sBAAsB,OAAoB,QAAsB,OAA0B;CACjG,MAAM,QAAkB,EAAE;CAC1B,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,cAAc,WAAW,aAAa,YAAY,KAAK;CAC7D,MAAM,iBAAiB,CAAC,CAAC,WAAW,qBAAqB;AAEzD,OAAM,KAAK,gBAAgB,KAAK,cAAc,YAAY,MAAM;AAEhE,MAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,WAAW,OAAO,EAAE;EAClE,MAAM,UAAU,YAAY,UAAU;AACtC,QAAM,KACJ,KAAK,UAAU,IAAI,eAAe,WAAW,SAAS,OAAO,MAAM,OAAO,OAAO,CAAC,GACnF;;AAGH,KAAI,gBAAgB;EAClB,MAAM,UAAU,WAAW,uBAAuB,EAAE,EAAE,KAAK,MAAM,SAAS,IAAI,CAAC,KAAK,KAAK;AACzF,QAAM,KAAK,yCAAyC,OAAO,SAAS;OAEpE,OAAM,KAAK,MAAM;AAGnB,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,eACP,WACA,SACA,OACA,WACA,OACA,QACQ;CACR,IAAI;AAEJ,KAAI,WAAW,MAAM,KAAK,EAAE;EAC1B,MAAM,OAAO,MAAM,MAAM,MAAM,EAAE,cAAc,aAAa,EAAE,cAAc,UAAU,EAAE;AACxF,QAAM,OAAO,GAAG,KAAK,IAAI,QAAQ,MAAM,SAAS,QAAQ;OAExD,SAAQ,MAAM,MAAd;EACE,KAAK;EACL,KAAK;AACH,SAAM,SAAS,QAAQ;AACvB;EACF,KAAK;AACH,SAAM,SAAS,QAAQ;AACvB;EACF,KAAK;AACH,SAAM,YAAY,QAAQ;AAC1B;EACF,KAAK;AACH,SAAM,WAAW,QAAQ;AACzB;EACF,KAAK;AACH,SAAM,YAAY,QAAQ;AAC1B;EACF,KAAK;AACH,SAAM,cAAc,QAAQ;AAC5B;EACF,KAAK;AACH,SAAM,SAAS,QAAQ;AACvB;EACF,QACE,OAAM,SAAS,QAAQ;;AAK7B,KAAI,MAAM,eACR,QAAO,UAAU,MAAM,eAAe;AAIxC,KAAI,MAAM,WACR,QAAO;AAIT,KAAI,MAAM,aAAa,MACrB,QAAO;AAIT,KAAI,MAAM,OACR,QAAO;AAIT,KAAI,MAAM,iBAAiB,KAAA,EACzB,QAAO,gBAAgB,MAAM,cAAc,MAAM,KAAK;AAIxD,KAAI,MAAM,YAAY;EACpB,MAAM,WAAW,sBAAsB,MAAM,WAAW,OAAO,OAAO;EACtE,MAAM,WAAW,MAAM,WAAW;EAClC,MAAM,WAAW,MAAM,WAAW,YAAY;AAC9C,MAAI,aAAa,UACf,QAAO,kCAAkC,SAAS,GAAG,SAAS,iBAAiB,SAAS;MAExF,QAAO,qBAAqB,SAAS,GAAG,SAAS,iBAAiB,SAAS;;AAI/E,QAAO;;AAGT,SAAS,gBACP,OACA,OACQ;AACR,KAAI,UAAU,SACZ,QAAO;AAET,KAAI,UAAU,QACZ,QAAO;AAET,KAAI,OAAO,UAAU,UACnB,QAAO,YAAY,MAAM;AAE3B,KAAI,OAAO,UAAU,SACnB,QAAO,YAAY,MAAM;AAE3B,KAAI,OAAO,UAAU,SACnB,QAAO,aAAa,MAAM;AAE5B,QAAO;;AAOT,SAAgB,oBAAoB,QAA8B;CAChE,MAAM,QAAkB,EAAE;AAG1B,OAAM,KAAK,6DAA6D;AACxE,OAAM,KAAK,sEAAsE;AACjF,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,WAAW;AACtB,OAAM,KAAK,gBAAgB;AAC3B,OAAM,KAAK,aAAa;AACxB,OAAM,KAAK,UAAU;AACrB,OAAM,KAAK,SAAS;AACpB,OAAM,KAAK,YAAY;AACvB,OAAM,KAAK,aAAa;AACxB,OAAM,KAAK,eAAe;AAC1B,OAAM,KAAK,UAAU;AACrB,OAAM,KAAK,eAAe;AAC1B,OAAM,KAAK,yBAAyB;AACpC,OAAM,KAAK,gBAAgB;AAC3B,OAAM,KAAK,mCAAmC;AAC9C,OAAM,KAAK,gDAAgD;AAC3D,OAAM,KAAK,uCAAuC;AAClD,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,sCAAsC;AACjD,OAAM,KAAK,GAAG;AAGd,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,YAAY;AACvB,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AAEd,MAAK,MAAM,SAAS,OAAO,QAAQ;AACjC,QAAM,KAAK,mBAAmB,OAAO,OAAO,CAAC;AAC7C,QAAM,KAAK,GAAG;;AAIhB,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,eAAe;AAC1B,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,kBAAkB,OAAO,CAAC;AAGrC,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,kBAAkB;AAC7B,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AACd,MAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,WAAW,WAAW,MAAM,KAAK;AACvC,QAAM,KAAK,eAAe,SAAS,YAAY,MAAM,KAAK,gBAAgB;AAC1E,QAAM,KAAK,kBAAkB,SAAS,YAAY,MAAM,KAAK,gBAAgB;;AAG/E,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,mBAAmB,OAAoB,QAA8B;CAE5E,MAAM,QAAkB,EAAE;CAC1B,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,cAAc,WAAW,aAAa,YAAY,KAAK;CAC7D,MAAM,iBAAiB,CAAC,CAAC,WAAW,qBAAqB;AAEzD,OAAM,KAAK,gBAAgB,KAAK,iBAAiB,YAAY,MAAM;AAEnE,MAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,WAAW,OAAO,EAAE;EAClE,MAAM,UAAU,YAAY,UAAU;AACtC,QAAM,KAAK,KAAK,UAAU,IAAI,YAAY,WAAW,SAAS,OAAO,MAAM,OAAO,CAAC,GAAG;;AAGxF,KAAI,gBAAgB;EAClB,MAAM,UAAU,WAAW,uBAAuB,EAAE,EAAE,KAAK,MAAM,SAAS,IAAI,CAAC,KAAK,KAAK;AACzF,QAAM,KAAK,yCAAyC,OAAO,SAAS;OAEpE,OAAM,KAAK,MAAM;AAGnB,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,YACP,WACA,SACA,OACA,WACA,QACQ;CACR,MAAM,SAAS,MAAM,aAAa;CAClC,IAAI;AAEJ,KAAI,WAAW,MAAM,KAAK,CAExB,OAAM,cAAc,QAAQ,MADT,MAAM,KAAK,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK,CAChB;KAE7C,SAAQ,MAAM,MAAd;EACE,KAAK;AACH,SAAM,YAAY,QAAQ,eAAe,OAAO;AAChD;EACF,KAAK;AACH,SAAM,SAAS,QAAQ;AACvB;EACF,KAAK;AACH,SAAM,YAAY,QAAQ;AAC1B;EACF,KAAK;AACH,SAAM,QAAQ,QAAQ;AACtB;EACF,KAAK;AACH,SAAM,WAAW,QAAQ;AACzB;EACF,KAAK;AACH,SAAM,YAAY,QAAQ;AAC1B;EACF,KAAK;AACH,SAAM,cAAc,QAAQ;AAC5B;EACF,KAAK;AACH,SAAM,SAAS,QAAQ;AACvB;EACF,QACE,OAAM,YAAY,QAAQ,eAAe,OAAO;;AAKtD,KAAI,MAAM,eACR,QAAO,UAAU,MAAM,eAAe;AAIxC,KAAI,MAAM,WACR,QAAO;AAIT,KAAI,MAAM,aAAa,MACrB,QAAO;AAIT,KAAI,MAAM,OACR,QAAO;AAIT,KAAI,MAAM,iBAAiB,KAAA,EACzB,QAAO,aAAa,MAAM,cAAc,MAAM,KAAK;AAIrD,KAAI,MAAM,YAAY;EACpB,MAAM,WAAW,sBAAsB,MAAM,WAAW,OAAO,OAAO;EACtE,MAAM,WAAW,MAAM,WAAW;EAClC,MAAM,WAAW,MAAM,WAAW,YAAY;AAC9C,MAAI,aAAa,UACf,QAAO,qCAAqC,SAAS,GAAG,SAAS,iBAAiB,SAAS;MAE3F,QAAO,qBAAqB,SAAS,GAAG,SAAS,iBAAiB,SAAS;;AAI/E,QAAO;;AAGT,SAAS,aACP,OACA,OACQ;AACR,KAAI,UAAU,SACZ,QAAO;AAET,KAAI,UAAU,QACZ,QAAO;AAET,KAAI,OAAO,UAAU,UACnB,QAAO,YAAY,MAAM;AAE3B,KAAI,OAAO,UAAU,SACnB,QAAO,YAAY,MAAM;AAE3B,KAAI,OAAO,UAAU,SACnB,QAAO,aAAa,MAAM;AAE5B,QAAO;;AA0BT,SAAgB,2BAA2B,QAA0C;CACnF,MAAM,iBAAiB,mCAAmC,OAAO;CACjE,MAAM,UAAU;EACd;EACA;EACA;EACD;AAED,MAAK,MAAM,CAAC,YAAY,gBAAgB,eAAe,SAAS,CAC9D,SAAQ,KAAK,YAAY,MAAM,KAAK,YAAY,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,WAAW,WAAW,IAAI;CAG/F,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,mDAAmD;AAC9D,OAAM,KAAK,6EAA6E;AACxF,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AAEd,MAAK,MAAM,SAAS,OAAO,QAAQ;AACjC,QAAM,KAAK,oBAAoB,OAAO,OAAO,CAAC;AAC9C,QAAM,KAAK,GAAG;;AAGhB,OAAM,KAAK,kBAAkB,OAAO,CAAC;AACrC,OAAM,KAAK,GAAG;AAEd,MAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,WAAW,WAAW,MAAM,KAAK;AACvC,QAAM,KAAK,eAAe,SAAS,YAAY,MAAM,KAAK,gBAAgB;AAC1E,QAAM,KAAK,kBAAkB,SAAS,YAAY,MAAM,KAAK,gBAAgB;;AAG/E,QAAO;EAAE;EAAS,MAAM,MAAM,KAAK,KAAK;EAAE;;AAG5C,SAAgB,6BAA6B,QAA0C;CACrF,MAAM,UAAU;EACd;EACA;EACA;EACD;CAED,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,mDAAmD;AAC9D,OAAM,KAAK,6EAA6E;AACxF,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;CAEd,MAAM,QAAQ,aAAa,OAAO;AAClC,KAAI,MAAM,SAAS,GAAG;AACpB,OAAK,MAAM,KAAK,MACd,OAAM,KACJ,gBAAgB,EAAE,QAAQ,aAAa,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK,CAAC,KAChG;AAEH,QAAM,KAAK,GAAG;;AAGhB,MAAK,MAAM,SAAS,OAAO,QAAQ;AACjC,QAAM,KAAK,sBAAsB,OAAO,QAAQ,MAAM,CAAC;AACvD,QAAM,KAAK,GAAG;;AAGhB,OAAM,KAAK,kBAAkB,OAAO,CAAC;AACrC,OAAM,KAAK,GAAG;AAEd,MAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,WAAW,WAAW,MAAM,KAAK;AACvC,QAAM,KAAK,eAAe,SAAS,YAAY,MAAM,KAAK,gBAAgB;AAC1E,QAAM,KAAK,kBAAkB,SAAS,YAAY,MAAM,KAAK,gBAAgB;;AAG/E,QAAO;EAAE;EAAS,MAAM,MAAM,KAAK,KAAK;EAAE;;AAG5C,SAAgB,0BAA0B,QAA0C;CAClF,MAAM,UAAU;EACd;EACA;EACA;EACD;CAED,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,mDAAmD;AAC9D,OAAM,KAAK,6EAA6E;AACxF,OAAM,KAAK,mFAAmF;AAC9F,OAAM,KAAK,GAAG;AAEd,MAAK,MAAM,SAAS,OAAO,QAAQ;AACjC,QAAM,KAAK,mBAAmB,OAAO,OAAO,CAAC;AAC7C,QAAM,KAAK,GAAG;;AAGhB,OAAM,KAAK,kBAAkB,OAAO,CAAC;AACrC,OAAM,KAAK,GAAG;AAEd,MAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,WAAW,WAAW,MAAM,KAAK;AACvC,QAAM,KAAK,eAAe,SAAS,YAAY,MAAM,KAAK,gBAAgB;AAC1E,QAAM,KAAK,kBAAkB,SAAS,YAAY,MAAM,KAAK,gBAAgB;;AAG/E,QAAO;EAAE;EAAS,MAAM,MAAM,KAAK,KAAK;EAAE;;AAO5C,SAAS,kBAAkB,QAA8B;CACvD,MAAM,QAAkB,EAAE;CAG1B,MAAM,OAA2E,EAAE;AAEnF,MAAK,MAAM,SAAS,OAAO,OACzB,MAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,WAAW,OAAO,CACtE,KAAI,MAAM,YAAY;EACpB,MAAM,aAAa,sBAAsB,MAAM,WAAW,OAAO,OAAO;AACxE,OAAK,KAAK;GACR,MAAM,MAAM;GACZ,WAAW;GACX,IAAI;GACJ,SAAS,MAAM,WAAW;GAC3B,CAAC;;AAKR,MAAK,MAAM,SAAS,OAAO,QAAQ;EAEjC,MAAM,UAAU,KAAK,QAAQ,MAAM,EAAE,SAAS,MAAM,KAAK;EAEzD,MAAM,WAAW,KAAK,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAK;AAExD,MAAI,QAAQ,WAAW,KAAK,SAAS,WAAW,EAC9C;EAGF,MAAM,WAAqB,EAAE;EAC7B,MAAM,cAAwB,EAAE;AAEhC,MAAI,QAAQ,SAAS,EACnB,aAAY,KAAK,MAAM;AAEzB,MAAI,SAAS,SAAS,EACpB,aAAY,KAAK,OAAO;AAG1B,OAAK,MAAM,OAAO,SAAS;GAEzB,MAAM,UAAU,IAAI,UAAU,QAAQ,OAAO,GAAG,CAAC,QAAQ,UAAU,GAAG;AACtE,YAAS,KACP,KAAK,QAAQ,QAAQ,IAAI,GAAG,eAAe,MAAM,KAAK,GAAG,IAAI,UAAU,kBAAkB,IAAI,GAAG,GAAG,IAAI,QAAQ,OAChH;;AAGH,OAAK,MAAM,OAAO,UAAU;GAE1B,MAAM,UAAU,IAAI;AAEpB,YAAS,KAAK,KAAK,QAAQ,SAAS,IAAI,KAAK,IAAI;;AAGnD,QAAM,KACJ,gBAAgB,MAAM,KAAK,wBAAwB,MAAM,KAAK,OAAO,YAAY,KAAK,KAAK,CAAC,WAC7F;AACD,QAAM,KAAK,SAAS,KAAK,KAAK,CAAC;AAC/B,QAAM,KAAK,OAAO;AAClB,QAAM,KAAK,GAAG;;AAGhB,QAAO,MAAM,KAAK,KAAK;;AAezB,SAAS,aAAa,QAAiC;CACrD,MAAM,QAAmB,EAAE;AAE3B,MAAK,MAAM,SAAS,OAAO,OACzB,MAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,WAAW,OAAO,CACtE,KAAI,WAAW,MAAM,KAAK,EAAE;EAC1B,MAAM,UAAU,YAAY,MAAM,MAAM,UAAU;EAClD,MAAM,SAAS,GAAG,YAAY,MAAM,KAAK,CAAC,GAAG,YAAY,UAAU;AACnE,QAAM,KAAK;GACT;GACA;GACA,QAAQ,MAAM;GACd,WAAW,MAAM;GACjB;GACD,CAAC;;AAKR,QAAO;;AAOT,SAAS,uBAAuB,QAAmC;CACjE,MAAM,8BAAc,IAAI,KAAa;AACrC,MAAK,MAAM,SAAS,OAAO,OACzB,MAAK,MAAM,SAAS,OAAO,OAAO,MAAM,WAAW,OAAO,CACxD,KAAI,MAAM,eACR,aAAY,IAAI,MAAM,eAAe;AAI3C,QAAO;;;;;AAUT,SAAS,cAAc,QAA2C;CAChE,MAAM,sBAAM,IAAI,KAAqB;AACrC,MAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,SAAS,MAAM,WAAW,aAAa,YAAY,MAAM,KAAK;AACpE,MAAI,IAAI,QAAQ,MAAM,KAAK;AAE3B,MAAI,IAAI,MAAM,MAAM,MAAM,KAAK;;AAEjC,QAAO;;;;;;;AAQT,SAAS,sBAAsB,QAAgB,QAA+B;AAC5E,KAAI,QAAQ;EAEV,MAAM,QADW,cAAc,OAAO,CACf,IAAI,OAAO;AAClC,MAAI,MACF,QAAO;;AAIX,KAAI,OAAO,SAAS,IAAI,CACtB,QAAO,OAAO,QAAQ,cAAc,GAAG,MAAM,EAAE,aAAa,CAAC;AAE/D,QAAO;;AAGT,SAAS,WAAW,KAAqB;AACvC,QAAO,IAAI,OAAO,EAAE,CAAC,aAAa,GAAG,IAAI,MAAM,EAAE"}
1
+ {"version":3,"file":"schema-generator.js","names":[],"sources":["../../src/database/schema-generator.ts"],"sourcesContent":["/**\n * Drizzle Schema Generators\n *\n * Converts the merged abstract schema (core + plugins) into three\n * dialect-specific Drizzle ORM schema files as TypeScript source code.\n *\n * Each generator produces a complete, self-contained .ts file that can\n * be used by Drizzle Kit for migration generation.\n */\n\nimport type { PluginFieldAttribute, PluginFieldType } from 'src/types/plugin.types';\nimport type { MergedSchema, MergedTable } from './schema-merger';\n\n// =============================================================================\n// Common Utilities\n// =============================================================================\n\n/**\n * Convert camelCase to snake_case for DB column names.\n */\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Check if a field type is an enum (string array).\n */\nfunction isEnumType(type: PluginFieldType): type is string[] {\n return Array.isArray(type);\n}\n\n/**\n * Generate a variable name for an enum from a table + field.\n * e.g., flowRuns + status → flowRunStatusEnum\n */\nfunction enumVarName(tableName: string, fieldName: string): string {\n return `${tableName}${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}Enum`;\n}\n\nconst SQLITE_RUNTIME_DEFAULT_IMPORTS: Record<string, string> = {\n FlowRunStatus: '@invect/core',\n NodeExecutionStatus: '@invect/core',\n};\n\nfunction collectSqliteRuntimeDefaultImports(schema: MergedSchema): Map<string, Set<string>> {\n const importsByModule = new Map<string, Set<string>>();\n\n for (const table of schema.tables) {\n for (const field of Object.values(table.definition.fields)) {\n if (typeof field.defaultValue !== 'string' || !field.typeAnnotation) {\n continue;\n }\n\n const importPath = SQLITE_RUNTIME_DEFAULT_IMPORTS[field.typeAnnotation];\n if (!importPath) {\n continue;\n }\n\n const existing = importsByModule.get(importPath) ?? new Set<string>();\n existing.add(field.typeAnnotation);\n importsByModule.set(importPath, existing);\n }\n }\n\n return importsByModule;\n}\n\n// =============================================================================\n// SQLite Generator\n// =============================================================================\n\nexport function generateSqliteSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n const runtimeImports = collectSqliteRuntimeDefaultImports(schema);\n\n // Header\n lines.push(`// SQLite schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(``);\n lines.push(\n `import { sqliteTable, text, integer, primaryKey, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';`,\n );\n lines.push(`import { relations, sql } from 'drizzle-orm';`);\n for (const [importPath, identifiers] of runtimeImports.entries()) {\n lines.push(`import { ${Array.from(identifiers).sort().join(', ')} } from '${importPath}';`);\n }\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`// Type imports — these are used for $type<>() annotations`);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Collect all typeAnnotations to generate type imports\n const typeAnnotations = collectTypeAnnotations(schema);\n if (typeAnnotations.size > 0) {\n lines.push(`// Plugin & core type annotations`);\n lines.push(`// You may need to adjust these imports based on your project structure`);\n lines.push(``);\n }\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateSqliteTable(table, schema));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const varName = table.name;\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${varName}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${varName}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generateSqliteTable(table: MergedTable, schema: MergedSchema): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = sqliteTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(` ${fieldName}: ${sqliteColumn(fieldName, colName, field, name, schema)},`);\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction sqliteColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n schema?: MergedSchema,\n): string {\n let col: string;\n\n if (isEnumType(field.type)) {\n // SQLite: enums are just text columns\n col = `text('${colName}')`;\n } else {\n switch (field.type) {\n case 'string':\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `text('${colName}')`;\n break;\n case 'number':\n case 'bigint':\n col = `integer('${colName}')`;\n break;\n case 'boolean':\n col = `integer('${colName}', { mode: 'boolean' })`;\n break;\n case 'date':\n col = `text('${colName}')`;\n break;\n case 'json':\n col = `text('${colName}', { mode: 'json' })`;\n break;\n default:\n col = `text('${colName}')`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += sqliteDefault(field.defaultValue, field.type, field.typeAnnotation);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnySQLiteColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction sqliteDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n typeAnnotation?: string,\n): string {\n if (value === 'uuid()') {\n return `.$defaultFn(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.default(sql\\`CURRENT_TIMESTAMP\\`)`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n if (typeAnnotation && SQLITE_RUNTIME_DEFAULT_IMPORTS[typeAnnotation]) {\n return `.default(${typeAnnotation}.${value})`;\n }\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// PostgreSQL Generator\n// =============================================================================\n\nexport function generatePostgresSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// PostgreSQL schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(``);\n lines.push(`import {`);\n lines.push(` pgTable,`);\n lines.push(` text,`);\n lines.push(` integer,`);\n lines.push(` boolean,`);\n lines.push(` timestamp,`);\n lines.push(` json,`);\n lines.push(` pgEnum,`);\n lines.push(` uuid,`);\n lines.push(` bigint,`);\n lines.push(` type AnyPgColumn,`);\n lines.push(` primaryKey,`);\n lines.push(`} from 'drizzle-orm/pg-core';`);\n lines.push(`import { relations } from 'drizzle-orm';`);\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Enums\n const enums = collectEnums(schema);\n if (enums.length > 0) {\n lines.push(`// =============================================================================`);\n lines.push(`// Enums`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const e of enums) {\n lines.push(\n `export const ${e.varName} = pgEnum('${e.dbName}', [${e.values.map((v) => `'${v}'`).join(', ')}]);`,\n );\n }\n lines.push(``);\n }\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generatePostgresTable(table, schema, enums));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generatePostgresTable(table: MergedTable, schema: MergedSchema, enums: EnumDef[]): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = pgTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(\n ` ${fieldName}: ${postgresColumn(fieldName, colName, field, name, enums, schema)},`,\n );\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction postgresColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n enums: EnumDef[],\n schema?: MergedSchema,\n): string {\n let col: string;\n\n if (isEnumType(field.type)) {\n const eVar = enums.find((e) => e.tableName === tableName && e.fieldName === fieldName)?.varName;\n col = eVar ? `${eVar}('${colName}')` : `text('${colName}')`;\n } else {\n switch (field.type) {\n case 'string':\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `uuid('${colName}')`;\n break;\n case 'number':\n col = `integer('${colName}')`;\n break;\n case 'bigint':\n col = `bigint('${colName}', { mode: 'bigint' })`;\n break;\n case 'boolean':\n col = `boolean('${colName}')`;\n break;\n case 'date':\n col = `timestamp('${colName}')`;\n break;\n case 'json':\n col = `json('${colName}')`;\n break;\n default:\n col = `text('${colName}')`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += postgresDefault(field.defaultValue, field.type);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnyPgColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction postgresDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n): string {\n if (value === 'uuid()') {\n return `.$default(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.defaultNow()`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// MySQL Generator\n// =============================================================================\n\nexport function generateMysqlSchema(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// MySQL schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit manually. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(``);\n lines.push(`import {`);\n lines.push(` mysqlTable,`);\n lines.push(` varchar,`);\n lines.push(` text,`);\n lines.push(` int,`);\n lines.push(` bigint,`);\n lines.push(` boolean,`);\n lines.push(` timestamp,`);\n lines.push(` json,`);\n lines.push(` mysqlEnum,`);\n lines.push(` type AnyMySqlColumn,`);\n lines.push(` primaryKey,`);\n lines.push(`} from 'drizzle-orm/mysql-core';`);\n lines.push(`import { relations, sql } from 'drizzle-orm';`);\n lines.push(`import { randomUUID } from 'crypto';`);\n lines.push(``);\n lines.push(`import type { JSONValue } from '.';`);\n lines.push(``);\n\n // Tables\n lines.push(`// =============================================================================`);\n lines.push(`// Tables`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateMysqlTable(table, schema));\n lines.push(``);\n }\n\n // Relations\n lines.push(`// =============================================================================`);\n lines.push(`// Relations`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n lines.push(generateRelations(schema));\n\n // Type exports\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Type exports`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return lines.join('\\n');\n}\n\nfunction generateMysqlTable(table: MergedTable, schema: MergedSchema): string {\n // schema is used by mysqlColumn for FK reference resolution\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const hasCompositePK = !!definition.compositePrimaryKey?.length;\n\n lines.push(`export const ${name} = mysqlTable('${dbTableName}', {`);\n\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const colName = toSnakeCase(fieldName);\n lines.push(` ${fieldName}: ${mysqlColumn(fieldName, colName, field, name, schema)},`);\n }\n\n if (hasCompositePK) {\n const pkCols = (definition.compositePrimaryKey ?? []).map((f) => `table.${f}`).join(', ');\n lines.push(`}, (table) => [primaryKey({ columns: [${pkCols}] })]);`);\n } else {\n lines.push(`});`);\n }\n\n return lines.join('\\n');\n}\n\nfunction mysqlColumn(\n fieldName: string,\n colName: string,\n field: PluginFieldAttribute,\n tableName: string,\n schema?: MergedSchema,\n): string {\n const maxLen = field.maxLength ?? 255;\n let col: string;\n\n if (isEnumType(field.type)) {\n const enumValues = field.type.map((v) => `'${v}'`).join(', ');\n col = `mysqlEnum('${colName}', [${enumValues}])`;\n } else {\n switch (field.type) {\n case 'string':\n col = `varchar('${colName}', { length: ${maxLen} })`;\n break;\n case 'text':\n col = `text('${colName}')`;\n break;\n case 'uuid':\n col = `varchar('${colName}', { length: 36 })`;\n break;\n case 'number':\n col = `int('${colName}')`;\n break;\n case 'bigint':\n col = `bigint('${colName}', { mode: 'bigint' })`;\n break;\n case 'boolean':\n col = `boolean('${colName}')`;\n break;\n case 'date':\n col = `timestamp('${colName}')`;\n break;\n case 'json':\n col = `json('${colName}')`;\n break;\n default:\n col = `varchar('${colName}', { length: ${maxLen} })`;\n }\n }\n\n // Type annotation\n if (field.typeAnnotation) {\n col += `.$type<${field.typeAnnotation}>()`;\n }\n\n // Primary key\n if (field.primaryKey) {\n col += `.primaryKey()`;\n }\n\n // Not null\n if (field.required !== false) {\n col += `.notNull()`;\n }\n\n // Unique\n if (field.unique) {\n col += `.unique()`;\n }\n\n // Default value\n if (field.defaultValue !== undefined) {\n col += mysqlDefault(field.defaultValue, field.type);\n }\n\n // Foreign key\n if (field.references) {\n const refTable = findTableVarForDbName(field.references.table, schema);\n const refField = field.references.field;\n const onDelete = field.references.onDelete || 'no action';\n if (refTable === tableName) {\n col += `.references((): AnyMySqlColumn => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n } else {\n col += `.references(() => ${refTable}.${refField}, { onDelete: '${onDelete}' })`;\n }\n }\n\n return col;\n}\n\nfunction mysqlDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n): string {\n if (value === 'uuid()') {\n return `.$defaultFn(() => randomUUID())`;\n }\n if (value === 'now()') {\n return `.default(sql\\`CURRENT_TIMESTAMP\\`)`;\n }\n if (typeof value === 'boolean') {\n return `.default(${value})`;\n }\n if (typeof value === 'number') {\n return `.default(${value})`;\n }\n if (typeof value === 'string') {\n return `.default('${value}')`;\n }\n return '';\n}\n\n// =============================================================================\n// Append-mode Generators\n// =============================================================================\n//\n// These produce only the table definitions, relations, and type exports\n// for appending to an existing Drizzle schema file. They include:\n// - A commented section marker\n// - Additional imports needed (inserted at top when used by CLI)\n// - Table definitions\n// - Relations\n// - Type exports\n//\n// The CLI handles merging the import lines into the existing file.\n// This approach mirrors how better-auth generates schema code that can\n// be appended to the user's existing schema file.\n\nexport interface AppendSchemaResult {\n /** Import statements that need to be added (CLI merges these) */\n imports: string[];\n /** Table + relation + type code to append */\n code: string;\n}\n\nexport function generateSqliteSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const runtimeImports = collectSqliteRuntimeDefaultImports(schema);\n const imports = [\n `import { sqliteTable, text, integer, primaryKey, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';`,\n `import { relations, sql } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n for (const [importPath, identifiers] of runtimeImports.entries()) {\n imports.push(`import { ${Array.from(identifiers).sort().join(', ')} } from '${importPath}';`);\n }\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateSqliteTable(table, schema));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\nexport function generatePostgresSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const imports = [\n `import { pgTable, text, integer, boolean, timestamp, json, pgEnum, uuid, bigint, primaryKey, type AnyPgColumn } from 'drizzle-orm/pg-core';`,\n `import { relations } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n const enums = collectEnums(schema);\n if (enums.length > 0) {\n for (const e of enums) {\n lines.push(\n `export const ${e.varName} = pgEnum('${e.dbName}', [${e.values.map((v) => `'${v}'`).join(', ')}]);`,\n );\n }\n lines.push(``);\n }\n\n for (const table of schema.tables) {\n lines.push(generatePostgresTable(table, schema, enums));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\nexport function generateMysqlSchemaAppend(schema: MergedSchema): AppendSchemaResult {\n const imports = [\n `import { mysqlTable, varchar, text, int, bigint, boolean, timestamp, json, mysqlEnum, primaryKey, type AnyMySqlColumn } from 'drizzle-orm/mysql-core';`,\n `import { relations, sql } from 'drizzle-orm';`,\n `import { randomUUID } from 'crypto';`,\n ];\n\n const lines: string[] = [];\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit below this line. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generateMysqlTable(table, schema));\n lines.push(``);\n }\n\n lines.push(generateRelations(schema));\n lines.push(``);\n\n for (const table of schema.tables) {\n const typeName = capitalize(table.name);\n lines.push(`export type ${typeName} = typeof ${table.name}.$inferSelect;`);\n lines.push(`export type New${typeName} = typeof ${table.name}.$inferInsert;`);\n }\n\n return { imports, code: lines.join('\\n') };\n}\n\n// =============================================================================\n// Relation Generator (shared across dialects)\n// =============================================================================\n\nfunction generateRelations(schema: MergedSchema): string {\n const lines: string[] = [];\n\n // Build a map of FK references: which tables reference which\n const refs: { from: string; fromField: string; to: string; toField: string }[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (field.references) {\n const toTableVar = findTableVarForDbName(field.references.table, schema);\n refs.push({\n from: table.name,\n fromField: fieldName,\n to: toTableVar,\n toField: field.references.field,\n });\n }\n }\n }\n\n for (const table of schema.tables) {\n // Find \"one\" relations (this table has FK → other table)\n const oneRels = refs.filter((r) => r.from === table.name);\n // Find \"many\" relations (other tables have FK → this table)\n const manyRels = refs.filter((r) => r.to === table.name);\n\n if (oneRels.length === 0 && manyRels.length === 0) {\n continue;\n }\n\n const relParts: string[] = [];\n const destructure: string[] = [];\n\n if (oneRels.length > 0) {\n destructure.push('one');\n }\n if (manyRels.length > 0) {\n destructure.push('many');\n }\n\n for (const rel of oneRels) {\n // Derive a relation name from the FK field: \"flowId\" → \"flow\"\n const relName = rel.fromField.replace(/Id$/, '').replace(/(_id)$/, '');\n relParts.push(\n ` ${relName}: one(${rel.to}, { fields: [${table.name}.${rel.fromField}], references: [${rel.to}.${rel.toField}] }),`,\n );\n }\n\n for (const rel of manyRels) {\n // Derive a relation name from the source table\n const relName = rel.from;\n // Avoid duplicates (e.g., multiple FKs from same table)\n relParts.push(` ${relName}: many(${rel.from}),`);\n }\n\n lines.push(\n `export const ${table.name}Relations = relations(${table.name}, ({ ${destructure.join(', ')} }) => ({`,\n );\n lines.push(relParts.join('\\n'));\n lines.push(`}));`);\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Enum Collection\n// =============================================================================\n\ninterface EnumDef {\n varName: string;\n dbName: string;\n values: string[];\n tableName: string;\n fieldName: string;\n}\n\nfunction collectEnums(schema: MergedSchema): EnumDef[] {\n const enums: EnumDef[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (isEnumType(field.type)) {\n const varName = enumVarName(table.name, fieldName);\n const dbName = `${toSnakeCase(table.name)}_${toSnakeCase(fieldName)}`;\n enums.push({\n varName,\n dbName,\n values: field.type,\n tableName: table.name,\n fieldName,\n });\n }\n }\n }\n\n return enums;\n}\n\n// =============================================================================\n// Type Annotation Collection\n// =============================================================================\n\nfunction collectTypeAnnotations(schema: MergedSchema): Set<string> {\n const annotations = new Set<string>();\n for (const table of schema.tables) {\n for (const field of Object.values(table.definition.fields)) {\n if (field.typeAnnotation) {\n annotations.add(field.typeAnnotation);\n }\n }\n }\n return annotations;\n}\n\n// =============================================================================\n// Shared Helpers\n// =============================================================================\n\n/**\n * Build a map from DB table name → JS variable name from the schema.\n */\nfunction buildTableMap(schema: MergedSchema): Map<string, string> {\n const map = new Map<string, string>();\n for (const table of schema.tables) {\n const dbName = table.definition.tableName || toSnakeCase(table.name);\n map.set(dbName, table.name);\n // Also map by logical name for convenience\n map.set(table.name, table.name);\n }\n return map;\n}\n\n/**\n * Find the JS variable name for a given DB table name.\n * Uses the schema to do a proper lookup (e.g., 'execution_traces' → 'nodeExecutions').\n * Falls back to camelCase heuristic if no schema provided.\n */\nfunction findTableVarForDbName(dbName: string, schema?: MergedSchema): string {\n if (schema) {\n const tableMap = buildTableMap(schema);\n const found = tableMap.get(dbName);\n if (found) {\n return found;\n }\n }\n // Fallback: convert snake_case to camelCase\n if (dbName.includes('_')) {\n return dbName.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n }\n return dbName;\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema-merger.cjs","names":["CORE_SCHEMA"],"sources":["../../src/database/schema-merger.ts"],"sourcesContent":["/**\n * Schema Merger\n *\n * Merges the core abstract schema with plugin schemas to produce a\n * unified abstract schema. The CLI schema generator then converts\n * this merged schema into dialect-specific Drizzle files.\n *\n * Handles:\n * - New plugin tables\n * - Plugin fields added to existing core tables (additive only)\n * - Duplicate field detection (throws error)\n * - Ordering by foreign key dependencies\n */\n\nimport type { InvectPlugin, PluginTableDefinition } from 'src/types/plugin.types';\nimport { CORE_SCHEMA, CORE_TABLE_NAMES } from './core-schema';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface MergedSchema {\n /** All tables (core + plugin) in dependency-resolved order */\n tables: MergedTable[];\n /** Which plugin contributed each table/field (for diagnostics) */\n provenance: SchemaProvenance[];\n}\n\nexport interface MergedTable {\n /** Logical table name (camelCase) */\n name: string;\n /** The merged table definition */\n definition: PluginTableDefinition;\n /** Which source this table came from */\n source: 'core' | string; // 'core' or plugin ID\n}\n\nexport interface SchemaProvenance {\n /** Table name */\n table: string;\n /** Field name (null for table-level provenance) */\n field: string | null;\n /** Source: 'core' or plugin ID */\n source: string;\n}\n\nexport interface SchemaMergeError {\n type: 'duplicate_field' | 'duplicate_table' | 'invalid_reference';\n message: string;\n table: string;\n field?: string;\n plugin: string;\n}\n\n// =============================================================================\n// Merge Function\n// =============================================================================\n\n/**\n * Merge core schema with all plugin schemas.\n *\n * @param plugins - Array of plugins (only those with `schema` are processed)\n * @returns Merged schema with tables in dependency order\n * @throws Error if there are conflicting field definitions\n */\nexport function mergeSchemas(plugins: InvectPlugin[]): MergedSchema {\n const errors: SchemaMergeError[] = [];\n const provenance: SchemaProvenance[] = [];\n\n // Start with a deep copy of the core schema\n const merged: Record<string, PluginTableDefinition> = {};\n const tableSources: Record<string, string> = {}; // table → source\n\n // Add core tables\n for (const [name, def] of Object.entries(CORE_SCHEMA)) {\n merged[name] = deepCopyTableDef(def);\n tableSources[name] = 'core';\n provenance.push({ table: name, field: null, source: 'core' });\n for (const fieldName of Object.keys(def.fields)) {\n provenance.push({ table: name, field: fieldName, source: 'core' });\n }\n }\n\n // Merge each plugin's schema\n for (const plugin of plugins) {\n if (!plugin.schema) {\n continue;\n }\n\n for (const [tableName, tableDef] of Object.entries(plugin.schema)) {\n if (tableDef.disableMigration) {\n continue;\n }\n\n const _isCoreTable = CORE_TABLE_NAMES.includes(tableName);\n const existsAlready = tableName in merged;\n\n if (existsAlready) {\n // Extending an existing table — merge fields additively\n const existing = merged[tableName];\n if (!existing) {\n continue;\n }\n\n for (const [fieldName, fieldDef] of Object.entries(tableDef.fields)) {\n if (fieldName in existing.fields) {\n // Field already exists — error unless it's from the same source\n const existingSource = provenance.find(\n (p) => p.table === tableName && p.field === fieldName,\n )?.source;\n\n if (existingSource && existingSource !== plugin.id) {\n errors.push({\n type: 'duplicate_field',\n message: `Field \"${fieldName}\" on table \"${tableName}\" already defined by \"${existingSource}\". Plugin \"${plugin.id}\" cannot override it.`,\n table: tableName,\n field: fieldName,\n plugin: plugin.id,\n });\n }\n continue; // Skip duplicate\n }\n\n // Add new field to existing table\n existing.fields[fieldName] = { ...fieldDef };\n provenance.push({ table: tableName, field: fieldName, source: plugin.id });\n }\n } else {\n // New table from plugin\n merged[tableName] = deepCopyTableDef(tableDef);\n tableSources[tableName] = plugin.id;\n provenance.push({ table: tableName, field: null, source: plugin.id });\n\n for (const fieldName of Object.keys(tableDef.fields)) {\n provenance.push({ table: tableName, field: fieldName, source: plugin.id });\n }\n }\n }\n }\n\n // Validate foreign key references\n for (const [tableName, tableDef] of Object.entries(merged)) {\n for (const [fieldName, fieldDef] of Object.entries(tableDef.fields)) {\n if (fieldDef.references) {\n // Check if the referenced table exists (by tableName property, not logical name)\n const refTableName = fieldDef.references.table;\n const refExists = Object.values(merged).some(\n (t) => t.tableName === refTableName || Object.keys(merged).includes(refTableName),\n );\n\n if (!refExists) {\n errors.push({\n type: 'invalid_reference',\n message: `Field \"${fieldName}\" on table \"${tableName}\" references table \"${refTableName}\" which does not exist.`,\n table: tableName,\n field: fieldName,\n plugin: tableSources[tableName] || 'unknown',\n });\n }\n }\n }\n }\n\n if (errors.length > 0) {\n const messages = errors.map((e) => ` - [${e.plugin}] ${e.message}`).join('\\n');\n throw new Error(`Schema merge errors:\\n${messages}`);\n }\n\n // Sort tables by order, then by name for stability\n const tables: MergedTable[] = Object.entries(merged)\n .map(([name, definition]) => ({\n name,\n definition,\n source: (tableSources[name] || 'core') as 'core' | string,\n }))\n .sort((a, b) => {\n const orderA = a.definition.order ?? 100;\n const orderB = b.definition.order ?? 100;\n if (orderA !== orderB) {\n return orderA - orderB;\n }\n return a.name.localeCompare(b.name);\n });\n\n return { tables, provenance };\n}\n\n// =============================================================================\n// Diff Utilities (for `npx invect generate --diff` preview)\n// =============================================================================\n\nexport interface SchemaDiff {\n newTables: { name: string; source: string }[];\n newFields: { table: string; field: string; source: string }[];\n unchangedTables: string[];\n}\n\n/**\n * Compare a merged schema against a \"previous\" schema (e.g., from last generation).\n * Used for preview/diff output in the CLI.\n */\nexport function diffSchemas(current: MergedSchema, previous: MergedSchema | null): SchemaDiff {\n const diff: SchemaDiff = {\n newTables: [],\n newFields: [],\n unchangedTables: [],\n };\n\n if (!previous) {\n // Everything is new\n diff.newTables = current.tables.map((t) => ({ name: t.name, source: t.source }));\n return diff;\n }\n\n const previousTableNames = new Set(previous.tables.map((t) => t.name));\n const previousFieldsByTable = new Map<string, Set<string>>();\n\n for (const table of previous.tables) {\n previousFieldsByTable.set(table.name, new Set(Object.keys(table.definition.fields)));\n }\n\n for (const table of current.tables) {\n if (!previousTableNames.has(table.name)) {\n diff.newTables.push({ name: table.name, source: table.source });\n continue;\n }\n\n const prevFields = previousFieldsByTable.get(table.name) || new Set();\n let hasNewFields = false;\n\n for (const fieldName of Object.keys(table.definition.fields)) {\n if (!prevFields.has(fieldName)) {\n diff.newFields.push({\n table: table.name,\n field: fieldName,\n source: table.source,\n });\n hasNewFields = true;\n }\n }\n\n if (!hasNewFields) {\n diff.unchangedTables.push(table.name);\n }\n }\n\n return diff;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction deepCopyTableDef(def: PluginTableDefinition): PluginTableDefinition {\n return {\n ...def,\n fields: Object.fromEntries(Object.entries(def.fields).map(([k, v]) => [k, { ...v }])),\n compositePrimaryKey: def.compositePrimaryKey ? [...def.compositePrimaryKey] : undefined,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"schema-merger.cjs","names":["CORE_SCHEMA"],"sources":["../../src/database/schema-merger.ts"],"sourcesContent":["/**\n * Schema Merger\n *\n * Merges the core abstract schema with plugin schemas to produce a\n * unified abstract schema. The CLI schema generator then converts\n * this merged schema into dialect-specific Drizzle files.\n *\n * Handles:\n * - New plugin tables\n * - Plugin fields added to existing core tables (additive only)\n * - Duplicate field detection (throws error)\n * - Ordering by foreign key dependencies\n */\n\nimport type { InvectPlugin, PluginTableDefinition } from 'src/types/plugin.types';\nimport { CORE_SCHEMA, CORE_TABLE_NAMES } from './core-schema';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface MergedSchema {\n /** All tables (core + plugin) in dependency-resolved order */\n tables: MergedTable[];\n /** Which plugin contributed each table/field (for diagnostics) */\n provenance: SchemaProvenance[];\n}\n\nexport interface MergedTable {\n /** Logical table name (camelCase) */\n name: string;\n /** The merged table definition */\n definition: PluginTableDefinition;\n /** Which source this table came from */\n source: 'core' | string; // 'core' or plugin ID\n}\n\nexport interface SchemaProvenance {\n /** Table name */\n table: string;\n /** Field name (null for table-level provenance) */\n field: string | null;\n /** Source: 'core' or plugin ID */\n source: string;\n}\n\nexport interface SchemaMergeError {\n type: 'duplicate_field' | 'duplicate_table' | 'invalid_reference';\n message: string;\n table: string;\n field?: string;\n plugin: string;\n}\n\n// =============================================================================\n// Merge Function\n// =============================================================================\n\n/**\n * Merge core schema with all plugin schemas.\n *\n * @param plugins - Array of plugins (only those with `schema` are processed)\n * @returns Merged schema with tables in dependency order\n * @throws Error if there are conflicting field definitions\n */\nexport function mergeSchemas(plugins: InvectPlugin[]): MergedSchema {\n const errors: SchemaMergeError[] = [];\n const provenance: SchemaProvenance[] = [];\n\n // Start with a deep copy of the core schema\n const merged: Record<string, PluginTableDefinition> = {};\n const tableSources: Record<string, string> = {}; // table → source\n\n // Add core tables\n for (const [name, def] of Object.entries(CORE_SCHEMA)) {\n merged[name] = deepCopyTableDef(def);\n tableSources[name] = 'core';\n provenance.push({ table: name, field: null, source: 'core' });\n for (const fieldName of Object.keys(def.fields)) {\n provenance.push({ table: name, field: fieldName, source: 'core' });\n }\n }\n\n // Merge each plugin's schema\n for (const plugin of plugins) {\n if (!plugin.schema) {\n continue;\n }\n\n for (const [tableName, tableDef] of Object.entries(plugin.schema)) {\n if (tableDef.disableMigration) {\n continue;\n }\n\n const _isCoreTable = CORE_TABLE_NAMES.includes(tableName);\n const existsAlready = tableName in merged;\n\n if (existsAlready) {\n // Extending an existing table — merge fields additively\n const existing = merged[tableName];\n if (!existing) {\n continue;\n }\n\n for (const [fieldName, fieldDef] of Object.entries(tableDef.fields)) {\n if (fieldName in existing.fields) {\n // Field already exists — error unless it's from the same source\n const existingSource = provenance.find(\n (p) => p.table === tableName && p.field === fieldName,\n )?.source;\n\n if (existingSource && existingSource !== plugin.id) {\n errors.push({\n type: 'duplicate_field',\n message: `Field \"${fieldName}\" on table \"${tableName}\" already defined by \"${existingSource}\". Plugin \"${plugin.id}\" cannot override it.`,\n table: tableName,\n field: fieldName,\n plugin: plugin.id,\n });\n }\n continue; // Skip duplicate\n }\n\n // Add new field to existing table\n existing.fields[fieldName] = { ...fieldDef };\n provenance.push({ table: tableName, field: fieldName, source: plugin.id });\n }\n } else {\n // New table from plugin\n merged[tableName] = deepCopyTableDef(tableDef);\n tableSources[tableName] = plugin.id;\n provenance.push({ table: tableName, field: null, source: plugin.id });\n\n for (const fieldName of Object.keys(tableDef.fields)) {\n provenance.push({ table: tableName, field: fieldName, source: plugin.id });\n }\n }\n }\n }\n\n // Validate foreign key references\n for (const [tableName, tableDef] of Object.entries(merged)) {\n for (const [fieldName, fieldDef] of Object.entries(tableDef.fields)) {\n if (fieldDef.references) {\n // Check if the referenced table exists (by tableName property, not logical name)\n const refTableName = fieldDef.references.table;\n const refExists = Object.values(merged).some(\n (t) => t.tableName === refTableName || Object.keys(merged).includes(refTableName),\n );\n\n if (!refExists) {\n errors.push({\n type: 'invalid_reference',\n message: `Field \"${fieldName}\" on table \"${tableName}\" references table \"${refTableName}\" which does not exist.`,\n table: tableName,\n field: fieldName,\n plugin: tableSources[tableName] || 'unknown',\n });\n }\n }\n }\n }\n\n if (errors.length > 0) {\n const messages = errors.map((e) => ` - [${e.plugin}] ${e.message}`).join('\\n');\n throw new Error(`Schema merge errors:\\n${messages}`);\n }\n\n // Sort tables by order, then by name for stability\n const tables: MergedTable[] = Object.entries(merged)\n .map(([name, definition]) => ({\n name,\n definition,\n source: (tableSources[name] || 'core') as 'core' | string,\n }))\n .sort((a, b) => {\n const orderA = a.definition.order ?? 100;\n const orderB = b.definition.order ?? 100;\n if (orderA !== orderB) {\n return orderA - orderB;\n }\n return a.name.localeCompare(b.name);\n });\n\n return { tables, provenance };\n}\n\n// =============================================================================\n// Diff Utilities (for `npx invect-cli generate --diff` preview)\n// =============================================================================\n\nexport interface SchemaDiff {\n newTables: { name: string; source: string }[];\n newFields: { table: string; field: string; source: string }[];\n unchangedTables: string[];\n}\n\n/**\n * Compare a merged schema against a \"previous\" schema (e.g., from last generation).\n * Used for preview/diff output in the CLI.\n */\nexport function diffSchemas(current: MergedSchema, previous: MergedSchema | null): SchemaDiff {\n const diff: SchemaDiff = {\n newTables: [],\n newFields: [],\n unchangedTables: [],\n };\n\n if (!previous) {\n // Everything is new\n diff.newTables = current.tables.map((t) => ({ name: t.name, source: t.source }));\n return diff;\n }\n\n const previousTableNames = new Set(previous.tables.map((t) => t.name));\n const previousFieldsByTable = new Map<string, Set<string>>();\n\n for (const table of previous.tables) {\n previousFieldsByTable.set(table.name, new Set(Object.keys(table.definition.fields)));\n }\n\n for (const table of current.tables) {\n if (!previousTableNames.has(table.name)) {\n diff.newTables.push({ name: table.name, source: table.source });\n continue;\n }\n\n const prevFields = previousFieldsByTable.get(table.name) || new Set();\n let hasNewFields = false;\n\n for (const fieldName of Object.keys(table.definition.fields)) {\n if (!prevFields.has(fieldName)) {\n diff.newFields.push({\n table: table.name,\n field: fieldName,\n source: table.source,\n });\n hasNewFields = true;\n }\n }\n\n if (!hasNewFields) {\n diff.unchangedTables.push(table.name);\n }\n }\n\n return diff;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction deepCopyTableDef(def: PluginTableDefinition): PluginTableDefinition {\n return {\n ...def,\n fields: Object.fromEntries(Object.entries(def.fields).map(([k, v]) => [k, { ...v }])),\n compositePrimaryKey: def.compositePrimaryKey ? [...def.compositePrimaryKey] : undefined,\n };\n}\n"],"mappings":"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"}