@cleverbrush/knex-schema 4.0.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SchemaQueryBuilder.d.ts +37 -990
- package/dist/index.js +23 -23
- package/dist/index.js.map +1 -1
- package/dist/operations/delete.d.ts +6 -0
- package/dist/operations/helpers.d.ts +57 -0
- package/dist/operations/insert.d.ts +26 -0
- package/dist/operations/join.d.ts +6 -0
- package/dist/operations/pagination.d.ts +15 -0
- package/dist/operations/select.d.ts +15 -0
- package/dist/operations/state.d.ts +39 -0
- package/dist/operations/update.d.ts +7 -0
- package/dist/operations/where.d.ts +29 -0
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/columns.ts","../src/ddl.ts","../src/entity.ts","../src/mappers.ts","../src/migration.ts","../src/raw.ts","../src/SchemaQueryBuilder.ts","../src/validate.ts","../src/snapshot.ts"],"sourcesContent":["// @cleverbrush/knex-schema — Column resolution and mapping\n\nimport type { SchemaBuilder } from '@cleverbrush/schema';\nimport {\n ObjectSchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { getColumnName } from './extension.js';\nimport type { ColumnRef } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Column map cache (schema → { propToCol, colToProp })\n// ---------------------------------------------------------------------------\n\ninterface ColumnMapResult {\n propToCol: Map<string, string>;\n colToProp: Map<string, string>;\n}\n\nconst columnMapCache = new WeakMap<object, ColumnMapResult>();\n\n/**\n * Build a bidirectional column map from an ObjectSchemaBuilder's properties.\n * Uses `getExtension('columnName')` per property, falling back to the property key.\n * Result is cached per schema instance via WeakMap.\n */\nexport function buildColumnMap(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): ColumnMapResult {\n const cached = columnMapCache.get(schema);\n if (cached) return cached;\n\n const introspected = schema.introspect() as any;\n const properties: Record<\n string,\n SchemaBuilder<any, any, any>\n > = introspected.properties ?? {};\n\n const propToCol = new Map<string, string>();\n const colToProp = new Map<string, string>();\n\n for (const propKey of Object.keys(properties)) {\n const propSchema = properties[propKey];\n const colName = getColumnName(propSchema, propKey);\n\n propToCol.set(propKey, colName);\n colToProp.set(colName, propKey);\n }\n\n const result: ColumnMapResult = { propToCol, colToProp };\n columnMapCache.set(schema, result);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Resolve a ColumnRef (string | accessor) to a SQL column name or Knex.Raw\n// ---------------------------------------------------------------------------\n\n/**\n * Build a `Knex.Raw` expression for accessing a nested JSON/JSONB path.\n *\n * - Single-key path: `\"col\"->>'key'` (text output, `->>` operator).\n * - Multi-key path: `\"col\"#>>'{a,b,...}'` (text output, `#>>` operator).\n *\n * Both use positional bindings to prevent SQL injection.\n */\nfunction jsonPathRaw(knex: Knex, col: string, jsonPath: string[]): Knex.Raw {\n if (jsonPath.length === 1) {\n return knex.raw('??->>?', [col, jsonPath[0]]);\n }\n // #>> expects a text array literal, e.g. '{address,city}'\n const pathLiteral = `{${jsonPath.join(',')}}`;\n return knex.raw('??#>>?', [col, pathLiteral]);\n}\n\n/**\n * Resolve a ColumnRef to a plain SQL column name (or a Knex.Raw expression for\n * nested JSON paths when `knex` is supplied).\n *\n * - String refs are treated as **property keys** (or dot-separated nested paths\n * such as `'address.city'`) and translated to column names via the column map.\n * - Function refs (property accessor) are resolved via PropertyDescriptorTree,\n * then translated to column names. Nested accessors (e.g. `t => t.address.city`)\n * produce a `Knex.Raw` JSON-path expression when `knex` is provided.\n *\n * @param ref - Column reference (property key, dotted path, or accessor fn).\n * @param schema - Root ObjectSchemaBuilder.\n * @param label - Human-readable label for error messages.\n * @param knex - Knex instance. Required for nested JSON-path refs; when omitted\n * and a nested path is detected, an error is thrown.\n */\nexport function resolveColumnRef(\n ref: ColumnRef<any>,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n label: string,\n knex: Knex\n): string | Knex.Raw;\nexport function resolveColumnRef(\n ref: ColumnRef<any>,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n label: string\n): string;\nexport function resolveColumnRef(\n ref: ColumnRef<any>,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n label: string,\n knex?: Knex\n): string | Knex.Raw {\n if (typeof ref === 'string') {\n if (!ref) throw new Error(`${label} must be a non-empty string`);\n\n // Dotted paths like 'address.city' — first segment is the top-level prop.\n if (ref.includes('.')) {\n const [topProp, ...jsonPath] = ref.split('.');\n const { propToCol } = buildColumnMap(schema);\n const col = propToCol.get(topProp) ?? topProp;\n if (!knex) {\n throw new Error(\n `${label}: a Knex instance is required to resolve nested JSON path '${ref}'`\n );\n }\n return jsonPathRaw(knex, col, jsonPath);\n }\n\n const { propToCol } = buildColumnMap(schema);\n const col = propToCol.get(ref);\n // If the string is a known property key, return its column name;\n // otherwise assume it's already a raw column name and pass through.\n return col ?? ref;\n }\n\n if (typeof ref === 'function') {\n const tree = ObjectSchemaBuilder.getPropertiesFor(schema as any);\n const descriptor = ref(tree as any);\n\n if (\n !descriptor ||\n typeof descriptor !== 'object' ||\n !(SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in descriptor)\n ) {\n throw new Error(\n `${label} accessor must return a valid property descriptor`\n );\n }\n\n const inner = (descriptor as any)[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n const pointer: string = inner.toJsonPointer();\n\n // pointer is an RFC-6901 JSON Pointer, e.g. '' (root), '/name', '/address/city'\n if (!pointer) {\n throw new Error(`${label} accessor returned the root descriptor`);\n }\n\n // Split '/address/city' → ['address', 'city']\n const segments = pointer\n .slice(1)\n .split('/')\n .map((s: string) => s.replace(/~1/g, '/').replace(/~0/g, '~'));\n\n if (segments.length === 0) {\n throw new Error(`${label} accessor returned the root descriptor`);\n }\n\n const [topProp, ...jsonPath] = segments;\n const { propToCol } = buildColumnMap(schema);\n const col = propToCol.get(topProp) ?? topProp;\n\n if (jsonPath.length === 0) {\n // Top-level property — plain column name\n return col;\n }\n\n // Nested path — need Knex.Raw\n if (!knex) {\n throw new Error(\n `${label}: a Knex instance is required to resolve nested JSON path '${pointer}'`\n );\n }\n return jsonPathRaw(knex, col, jsonPath);\n }\n\n throw new Error(\n `${label} must be a string or a property descriptor accessor function`\n );\n}\n\n/**\n * Resolve a ColumnRef to the **property key** (not the column name).\n * Used for result mapping.\n */\nexport function resolvePropertyKey(\n ref: ColumnRef<any>,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n label: string\n): string {\n if (typeof ref === 'string') {\n if (!ref) throw new Error(`${label} must be a non-empty string`);\n return ref;\n }\n\n if (typeof ref === 'function') {\n const tree = ObjectSchemaBuilder.getPropertiesFor(schema as any);\n const descriptor = ref(tree as any);\n\n if (\n !descriptor ||\n typeof descriptor !== 'object' ||\n !(SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in descriptor)\n ) {\n throw new Error(\n `${label} accessor must return a valid property descriptor`\n );\n }\n\n const inner = (descriptor as any)[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n const pointer: string = inner.toJsonPointer();\n\n if (!pointer) {\n throw new Error(`${label} accessor returned the root descriptor`);\n }\n\n // Return the first segment (top-level property key) for mapping purposes\n const topProp = pointer.slice(1).split('/')[0];\n return topProp.replace(/~1/g, '/').replace(/~0/g, '~');\n }\n\n throw new Error(\n `${label} must be a string or a property descriptor accessor function`\n );\n}\n\n// ---------------------------------------------------------------------------\n// Primary-key introspection\n// ---------------------------------------------------------------------------\n\n/**\n * Result of {@link getPrimaryKeyColumns}.\n *\n * `propertyKeys` are the schema property names (the keys you'd use in\n * `.where(t => t.id, ...)` style accessors); `columnNames` are the SQL\n * column names after applying any `hasColumnName()` overrides. Order is\n * preserved: composite-PK ordering matches the user's `hasPrimaryKey()`\n * declaration; single-PK arrays have length 1.\n *\n * @public\n */\nexport interface PrimaryKeyColumns {\n readonly propertyKeys: readonly string[];\n readonly columnNames: readonly string[];\n}\n\n/**\n * Resolve the primary-key columns of a schema at runtime.\n *\n * Composite primary keys (declared via `.hasPrimaryKey([...])` on the\n * object schema) take precedence over single-column primary keys. The\n * `columns` argument to `.hasPrimaryKey()` may contain either property keys\n * or SQL column names — both forms are accepted and normalised.\n *\n * Returns `{ propertyKeys: [], columnNames: [] }` when no primary key is\n * declared.\n *\n * @public\n */\nexport function getPrimaryKeyColumns(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): PrimaryKeyColumns {\n const introspected = schema.introspect() as {\n properties?: Record<string, SchemaBuilder<any, any, any>>;\n extensions?: Record<string, unknown>;\n };\n const properties = introspected.properties ?? {};\n const extensions = introspected.extensions ?? {};\n const { propToCol, colToProp } = buildColumnMap(schema);\n\n // Composite PK takes precedence.\n const composite = extensions.compositePrimaryKey as\n | readonly string[]\n | undefined;\n if (composite && composite.length > 0) {\n const propertyKeys: string[] = [];\n const columnNames: string[] = [];\n for (const entry of composite) {\n // Accept either column name or property key.\n if (propToCol.has(entry)) {\n propertyKeys.push(entry);\n columnNames.push(propToCol.get(entry) as string);\n } else if (colToProp.has(entry)) {\n columnNames.push(entry);\n propertyKeys.push(colToProp.get(entry) as string);\n } else {\n // Unknown identifier — pass through as both (best effort).\n propertyKeys.push(entry);\n columnNames.push(entry);\n }\n }\n return { propertyKeys, columnNames };\n }\n\n // Single-column PK — first property whose schema carries the\n // `primaryKey` extension wins.\n for (const [propKey, propSchema] of Object.entries(properties)) {\n const propExt =\n (\n propSchema as {\n introspect?: () => {\n extensions?: Record<string, unknown>;\n };\n }\n ).introspect?.().extensions ?? {};\n if (propExt.primaryKey) {\n return {\n propertyKeys: [propKey],\n columnNames: [propToCol.get(propKey) ?? propKey]\n };\n }\n }\n\n return { propertyKeys: [], columnNames: [] };\n}\n\n// ---------------------------------------------------------------------------\n// Row-version introspection\n// ---------------------------------------------------------------------------\n\n/**\n * Concurrency-token strategy stored by `.rowVersion()`.\n * - `'increment'` — ORM increments an integer counter on each UPDATE.\n * - `'timestamp'` — ORM sets the value to `new Date()` on each UPDATE.\n * - `'manual'` — caller supplies the new value; ORM only enforces the check.\n *\n * @public\n */\nexport type RowVersionStrategy = 'increment' | 'timestamp' | 'manual';\n\n/**\n * Resolved row-version column for a schema, returned by\n * {@link getRowVersionColumn}.\n *\n * @public\n */\nexport interface RowVersionColumn {\n /** Schema property name. */\n propertyKey: string;\n /** SQL column name (after any `hasColumnName()` override). */\n columnName: string;\n /** Concurrency-token update strategy. */\n strategy: RowVersionStrategy;\n}\n\n/**\n * Find the first column marked `.rowVersion()` on the schema and return its\n * metadata. Returns `null` when no row-version column is declared.\n *\n * @public\n */\nexport function getRowVersionColumn(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): RowVersionColumn | null {\n const introspected = schema.introspect() as {\n properties?: Record<\n string,\n { introspect?: () => { extensions?: Record<string, unknown> } }\n >;\n };\n const properties = introspected.properties ?? {};\n const { propToCol } = buildColumnMap(schema);\n\n for (const [propKey, propSchema] of Object.entries(properties)) {\n const ext = propSchema.introspect?.()?.extensions ?? {};\n const rv = ext.rowVersion as { strategy?: string } | undefined;\n if (rv) {\n return {\n propertyKey: propKey,\n columnName: propToCol.get(propKey) ?? propKey,\n strategy: (rv.strategy as RowVersionStrategy) ?? 'increment'\n };\n }\n }\n return null;\n}\n","// @cleverbrush/knex-schema — DDL generation from schema introspection\n\nimport type { ObjectSchemaBuilder, SchemaBuilder } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport {\n getColumnName,\n getPolymorphicVariantSchemas,\n getTableName\n} from './extension.js';\n\n// ---------------------------------------------------------------------------\n// Type mapping\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the Knex column type from a schema property's introspection data and\n * DDL extensions.\n *\n * Priority:\n * 1. Explicit `columnType` extension (e.g. `'text'`, `'uuid'`, `'jsonb'`).\n * 2. Schema type (`string`, `number`, `boolean`, `date`).\n *\n * @param table - Knex table builder.\n * @param col - SQL column name.\n * @param introspected - Result of `propSchema.introspect()`.\n * @param ext - The property's `extensions` object.\n * @returns A Knex column builder.\n */\nfunction resolveColumnType(\n table: Knex.CreateTableBuilder,\n col: string,\n introspected: any,\n ext: Record<string, any>\n): Knex.ColumnBuilder {\n if (ext.columnType) {\n return table.specificType(col, ext.columnType);\n }\n switch (introspected.type) {\n case 'string': {\n const maxLen = ext.maxLength ?? introspected.maxLength ?? undefined;\n return maxLen ? table.string(col, maxLen) : table.string(col);\n }\n case 'number':\n return introspected.isInteger !== false\n ? table.integer(col)\n : table.float(col);\n case 'boolean':\n return table.boolean(col);\n case 'date':\n return table.timestamp(col);\n case 'object':\n // Nested objects are stored as jsonb by default; override via .columnType()\n return table.specificType(col, 'jsonb');\n default:\n return table.specificType(col, 'text');\n }\n}\n\n/**\n * Apply a default value to a Knex column builder.\n *\n * Handles special values:\n * - `'now'` → `knex.fn.now()`\n * - `'auto_increment'` → no-op (handled by `table.increments()`)\n * - `{ raw: string }` → `knex.raw(expression)`\n * - Otherwise → literal value.\n *\n * @param column - Knex column builder.\n * @param defaultValue - The default value from the `defaultTo` extension.\n * @param knex - Knex instance (needed for `fn.now()` and `raw()`).\n * @returns The column builder with the default applied.\n */\nfunction applyDefault(\n column: Knex.ColumnBuilder,\n defaultValue: any,\n knex: Knex\n): Knex.ColumnBuilder {\n if (defaultValue === 'now') return column.defaultTo(knex.fn.now());\n if (defaultValue === 'auto_increment') return column;\n if (\n typeof defaultValue === 'object' &&\n defaultValue !== null &&\n defaultValue.raw\n ) {\n return column.defaultTo(knex.raw(defaultValue.raw));\n }\n return column.defaultTo(defaultValue);\n}\n\n// ---------------------------------------------------------------------------\n// generateCreateTable\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a Knex `schema.createTable()` call from an ObjectSchemaBuilder's\n * introspected metadata and DDL extensions.\n *\n * Returns a function that accepts a Knex instance and returns a\n * `SchemaBuilder` (thenable). Call it inside a migration or setup script:\n *\n * @param schema - An `ObjectSchemaBuilder` with `.hasTableName()` and\n * column-level DDL extensions (`.primaryKey()`, `.references()`, etc.).\n * @returns `(knex: Knex) => Knex.SchemaBuilder` — a function that creates the\n * table when executed.\n *\n * @example\n * ```ts\n * const createUsersTable = generateCreateTable(UserSchema);\n * await createUsersTable(knex);\n * ```\n */\nexport function generateCreateTable(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): (knex: Knex) => Knex.SchemaBuilder {\n const tableName = getTableName(schema);\n const introspected = schema.introspect() as any;\n const tableExt: Record<string, any> = introspected.extensions ?? {};\n\n // Column names fully managed by table-level extensions; skip them in the\n // property loop to avoid duplicate DDL.\n const extensionManagedCols = new Set<string>();\n if (tableExt.timestamps) {\n extensionManagedCols.add(tableExt.timestamps.createdAt);\n extensionManagedCols.add(tableExt.timestamps.updatedAt);\n }\n if (tableExt.softDelete) {\n extensionManagedCols.add(tableExt.softDelete.column);\n }\n\n return (knex: Knex) => {\n const builder = knex.schema.createTable(\n tableName,\n (table: Knex.CreateTableBuilder) => {\n const properties: Record<\n string,\n SchemaBuilder<any, any, any>\n > = introspected.properties ?? {};\n\n for (const [propKey, propSchema] of Object.entries(\n properties\n )) {\n const col = getColumnName(propSchema, propKey);\n const propIntrospected = propSchema.introspect() as any;\n const ext: Record<string, any> =\n propIntrospected.extensions ?? {};\n\n // Skip array navigation properties without an explicit\n // columnType override — these are ORM relations. Nested\n // object properties default to jsonb and are NOT skipped.\n if (propIntrospected.type === 'array' && !ext.columnType) {\n continue;\n }\n // Skip columns owned by table-level extensions.\n if (extensionManagedCols.has(col)) {\n continue;\n }\n\n // Determine column builder\n let column: Knex.ColumnBuilder;\n\n if (ext.primaryKey?.autoIncrement) {\n column = table.increments(col);\n } else {\n column = resolveColumnType(\n table,\n col,\n propIntrospected,\n ext\n );\n }\n\n // Primary key (non-auto-increment)\n if (ext.primaryKey && !ext.primaryKey.autoIncrement) {\n column = column.primary();\n }\n\n // Unique constraint\n if (ext.unique) {\n column = column.unique(\n typeof ext.unique === 'string'\n ? { indexName: ext.unique }\n : undefined\n );\n }\n\n // Index\n if (ext.index) {\n column = column.index(\n typeof ext.index === 'string'\n ? ext.index\n : undefined\n );\n }\n\n // Default value\n if (ext.defaultTo !== undefined) {\n column = applyDefault(column, ext.defaultTo, knex);\n }\n\n // Nullability\n if (\n propIntrospected.isRequired &&\n !ext.primaryKey?.autoIncrement\n ) {\n column = column.notNullable();\n } else if (!propIntrospected.isRequired) {\n column = column.nullable();\n }\n\n // Foreign key references\n if (ext.references) {\n const fkBuilder = column\n .references(ext.references.column)\n .inTable(ext.references.table);\n if (ext.onDelete) fkBuilder.onDelete(ext.onDelete);\n if (ext.onUpdate) fkBuilder.onUpdate(ext.onUpdate);\n }\n\n // Column-level CHECK constraint\n if (ext.check) {\n table.check(ext.check);\n }\n }\n\n // ----- Table-level constraints from object extensions -----\n\n // Composite indexes\n for (const idx of tableExt.indexes ?? []) {\n if (idx.unique) {\n table.unique(idx.columns, {\n indexName: idx.name ?? undefined\n });\n } else {\n table.index(idx.columns, idx.name ?? undefined);\n }\n }\n\n // Composite unique constraints\n for (const unq of tableExt.uniques ?? []) {\n table.unique(unq.columns, {\n indexName: unq.name ?? undefined\n });\n }\n\n // Table-level CHECK constraints\n for (const chk of tableExt.checks ?? []) {\n table.check(chk);\n }\n\n // Composite primary key\n if (tableExt.compositePrimaryKey) {\n table.primary(tableExt.compositePrimaryKey);\n }\n\n // Raw columns (not backed by schema properties)\n for (const rawCol of tableExt.rawColumns ?? []) {\n table.specificType(rawCol.name, rawCol.definition);\n }\n\n // Timestamps (auto-added columns)\n if (tableExt.timestamps) {\n table\n .timestamp(tableExt.timestamps.createdAt)\n .defaultTo(knex.fn.now())\n .notNullable();\n table\n .timestamp(tableExt.timestamps.updatedAt)\n .defaultTo(knex.fn.now())\n .notNullable();\n }\n\n // Soft delete column\n if (tableExt.softDelete) {\n table.timestamp(tableExt.softDelete.column).nullable();\n }\n }\n );\n\n // Raw indexes are executed as separate statements after table creation\n const rawIndexes: string[] = tableExt.rawIndexes ?? [];\n if (rawIndexes.length > 0) {\n return builder.then(async () => {\n for (const rawIdx of rawIndexes) {\n await knex.raw(rawIdx);\n }\n }) as any;\n }\n\n return builder;\n };\n}\n\n// ---------------------------------------------------------------------------\n// generateCreateTableSource\n// ---------------------------------------------------------------------------\n\n/**\n * Generate `up` and `down` TypeScript code *strings* (4-space-indented\\n * fragments) for creating a table from a schema.\n *\n * Unlike {@link generateCreateTable} (which returns a Knex callback), the\n * output is plain source text suitable for writing into a migration file. The\n * fragments are designed to be embedded directly inside `up()` / `down()`\n * functions.\n *\n * @param schema - An `ObjectSchemaBuilder` with `.hasTableName()` and column\n * DDL extensions.\n * @returns `{ up, down }` source fragments.\n *\n * @example\n * ```ts\n * const { up, down } = generateCreateTableSource(UserSchema);\n * // up: \" await knex.schema.createTable('users', (table) => { … });\"\n * // down: \" await knex.schema.dropTableIfExists('users');\"\n * ```\n */\nexport function generateCreateTableSource(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): { up: string; down: string } {\n const tableName = getTableName(schema);\n const introspected = schema.introspect() as any;\n const tableExt: Record<string, any> = introspected.extensions ?? {};\n const properties: Record<\n string,\n SchemaBuilder<any, any, any>\n > = introspected.properties ?? {};\n\n const lines: string[] = [];\n\n // Column names owned by table-level extensions; skip in property loop.\n const extensionManagedCols = new Set<string>();\n if (tableExt.timestamps) {\n extensionManagedCols.add(tableExt.timestamps.createdAt);\n extensionManagedCols.add(tableExt.timestamps.updatedAt);\n }\n if (tableExt.softDelete) {\n extensionManagedCols.add(tableExt.softDelete.column);\n }\n\n for (const [propKey, propSchema] of Object.entries(properties)) {\n const col = getColumnName(propSchema, propKey);\n const propIntrospected = propSchema.introspect() as any;\n const ext: Record<string, any> = propIntrospected.extensions ?? {};\n\n // Skip navigation properties and extension-managed columns.\n if (\n (propIntrospected.type === 'object' ||\n propIntrospected.type === 'array') &&\n !ext.columnType\n ) {\n continue;\n }\n if (extensionManagedCols.has(col)) {\n continue;\n }\n\n let line: string;\n\n if (ext.primaryKey?.autoIncrement) {\n line = ` table.increments('${col}')`;\n } else {\n line = ` ${_colTypeCode(col, propIntrospected, ext)}`;\n }\n\n // Primary key (non-auto-increment)\n if (ext.primaryKey && !ext.primaryKey.autoIncrement) {\n line += '.primary()';\n }\n\n // Unique\n if (ext.unique) {\n if (typeof ext.unique === 'string') {\n line += `.unique({ indexName: '${ext.unique}' })`;\n } else {\n line += '.unique()';\n }\n }\n\n // Index\n if (ext.index) {\n if (typeof ext.index === 'string') {\n line += `.index('${ext.index}')`;\n } else {\n line += '.index()';\n }\n }\n\n // Default value\n if (ext.defaultTo !== undefined) {\n line += `.defaultTo(${_fmtDefault(ext.defaultTo)})`;\n }\n\n // Nullability\n if (propIntrospected.isRequired && !ext.primaryKey?.autoIncrement) {\n line += '.notNullable()';\n } else if (!propIntrospected.isRequired) {\n line += '.nullable()';\n }\n\n // Foreign key references\n if (ext.references) {\n line += `.references('${ext.references.column}').inTable('${ext.references.table}')`;\n if (ext.onDelete) line += `.onDelete('${ext.onDelete}')`;\n if (ext.onUpdate) line += `.onUpdate('${ext.onUpdate}')`;\n }\n\n lines.push(line + ';');\n\n // Column-level CHECK (separate statement after column line)\n if (ext.check) {\n lines.push(` table.check(${JSON.stringify(ext.check)});`);\n }\n }\n\n // Composite indexes\n for (const idx of tableExt.indexes ?? []) {\n const cols = JSON.stringify(idx.columns);\n if (idx.unique) {\n lines.push(\n ` table.unique(${cols}${idx.name ? `, { indexName: '${idx.name}' }` : ''});`\n );\n } else {\n lines.push(\n ` table.index(${cols}${idx.name ? `, '${idx.name}'` : ''});`\n );\n }\n }\n\n // Composite unique constraints\n for (const unq of tableExt.uniques ?? []) {\n const cols = JSON.stringify(unq.columns);\n lines.push(\n ` table.unique(${cols}${unq.name ? `, { indexName: '${unq.name}' }` : ''});`\n );\n }\n\n // Table-level CHECK constraints\n for (const chk of tableExt.checks ?? []) {\n lines.push(` table.check(${JSON.stringify(chk)});`);\n }\n\n // Composite primary key\n if (tableExt.compositePrimaryKey) {\n lines.push(\n ` table.primary(${JSON.stringify(tableExt.compositePrimaryKey)});`\n );\n }\n\n // Raw columns\n for (const rawCol of tableExt.rawColumns ?? []) {\n lines.push(\n ` table.specificType('${rawCol.name}', '${rawCol.definition}');`\n );\n }\n\n // Timestamps\n if (tableExt.timestamps) {\n lines.push(\n ` table.timestamp('${tableExt.timestamps.createdAt}').notNullable().defaultTo(knex.fn.now());`\n );\n lines.push(\n ` table.timestamp('${tableExt.timestamps.updatedAt}').notNullable().defaultTo(knex.fn.now());`\n );\n }\n\n // Soft-delete column\n if (tableExt.softDelete) {\n lines.push(\n ` table.timestamp('${tableExt.softDelete.column}').nullable();`\n );\n }\n\n const rawIndexes: string[] = tableExt.rawIndexes ?? [];\n const rawIndexLines = rawIndexes.map(\n ri => ` await knex.raw(${JSON.stringify(ri)});`\n );\n\n const up =\n ` await knex.schema.createTable('${tableName}', (table) => {\\n${lines.join('\\n')}\\n });` +\n (rawIndexLines.length > 0 ? '\\n' + rawIndexLines.join('\\n') : '');\n\n const down = ` await knex.schema.dropTableIfExists('${tableName}');`;\n\n return { up, down };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers for generateCreateTableSource\n// ---------------------------------------------------------------------------\n\n/** @internal Render a column type expression for code generation. */\nfunction _colTypeCode(\n col: string,\n introspected: any,\n ext: Record<string, any>\n): string {\n if (ext.columnType)\n return `table.specificType('${col}', '${ext.columnType}')`;\n switch (introspected.type) {\n case 'string': {\n const maxLen = ext.maxLength ?? introspected.maxLength ?? undefined;\n return maxLen\n ? `table.string('${col}', ${maxLen})`\n : `table.string('${col}')`;\n }\n case 'number':\n return introspected.isInteger !== false\n ? `table.integer('${col}')`\n : `table.float('${col}')`;\n case 'boolean':\n return `table.boolean('${col}')`;\n case 'date':\n return `table.timestamp('${col}')`;\n case 'object':\n return `table.specificType('${col}', 'jsonb')`;\n default:\n return `table.specificType('${col}', 'text')`;\n }\n}\n\n/** @internal Format a defaultTo value as a code string for migration source. */\nfunction _fmtDefault(value: any): string {\n if (value === 'now') return 'knex.fn.now()';\n if (typeof value === 'object' && value !== null && value.raw) {\n return `knex.raw('${String(value.raw).replace(/'/g, \"\\\\'\")}')`;\n }\n if (typeof value === 'string') return `'${value.replace(/'/g, \"\\\\'\")}'`;\n return String(value);\n}\n\n// ---------------------------------------------------------------------------\n// generateCreatePolymorphicTables\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a series of Knex `schema.createTable()` calls for a polymorphic\n * schema and all its CTI variant tables.\n *\n * Returns an array of `(knex: Knex) => Knex.SchemaBuilder` functions — one\n * for the base table and one for each CTI variant. STI variants add their\n * columns to the base table itself so no extra table is needed.\n *\n * Execute them sequentially in a migration:\n *\n * @param schema - The base `ObjectSchemaBuilder` with `.withVariants()` applied.\n * @returns An array of table-creation functions to execute in order.\n *\n * @example\n * ```ts\n * const creators = generateCreatePolymorphicTables(FileSchema);\n * for (const create of creators) {\n * await create(knex);\n * }\n * ```\n */\nexport function generateCreatePolymorphicTables(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): Array<(knex: Knex) => Knex.SchemaBuilder> {\n const result: Array<(knex: Knex) => Knex.SchemaBuilder> = [\n generateCreateTable(schema)\n ];\n\n const variantSchemas = getPolymorphicVariantSchemas(schema);\n for (const variantSchema of variantSchemas) {\n // Only CTI variants have their own table\n const tableName = variantSchema.getExtension('tableName') as\n | string\n | undefined;\n if (tableName) {\n result.push(generateCreateTable(variantSchema));\n }\n }\n\n return result;\n}\n","// @cleverbrush/knex-schema — Entity wrapper\n//\n// Provides a typed wrapper around an ObjectSchemaBuilder that tracks\n// declared relations as a real generic parameter (TRels). Unlike the\n// brand-based approach, TRels survives method chaining because we own\n// every method's return type.\n//\n// Relations are still stored at runtime in the schema's `relations`\n// extension (compatible with the existing query/include implementation).\n\nimport {\n type ArraySchemaBuilder,\n type InferType,\n ObjectSchemaBuilder,\n type PropertyDescriptorTree,\n type SchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\n\nimport { buildColumnMap } from './columns.js';\nimport {\n applyVariantsToSchema,\n getColumnName,\n type VariantInputForResolver\n} from './extension.js';\nimport type { ResolvedVariantRelationSpec } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Type-level helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Phantom info for a single declared relation, stored on `Entity`'s `TRels`\n * generic. `TForeign` is captured so `.include()` can type the customize\n * callback against the correct foreign schema.\n *\n * @public\n */\nexport interface RelationInfo<\n TKind extends 'belongsTo' | 'hasOne' | 'hasMany' | 'belongsToMany' = any,\n TForeign extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = ObjectSchemaBuilder<any, any, any, any, any, any, any>\n> {\n readonly kind: TKind;\n readonly foreign: TForeign;\n}\n\n/**\n * Extract the property record `{ [name]: SchemaBuilder }` from any\n * `ObjectSchemaBuilder` regardless of variance positions.\n *\n * @public\n */\nexport type SchemaProps<T> =\n T extends ObjectSchemaBuilder<infer P, any, any, any, any, any, any>\n ? P\n : never;\n\n/**\n * Strips the `withExtensions()` overlay from a schema type, reducing it to a\n * plain `ObjectSchemaBuilder<TProps, TReq>` so `PropertyDescriptorTree<...>`\n * resolves without hitting TypeScript's recursion depth limit.\n *\n * @internal\n */\ntype EntitySchemaBase<\n T extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n> =\n T extends ObjectSchemaBuilder<infer P, infer Req, any, any, any, any, any>\n ? ObjectSchemaBuilder<P, Req>\n : never;\n\n/**\n * `PropertyDescriptorTree` overlay that pins each top-level property's\n * literal `propertyName` into its descriptor. Required because\n * `PropertyDescriptorTree` widens `propertyName` to `string` for sub-trees\n * whose property is itself an `ObjectSchemaBuilder` (since\n * `PropertyDescriptorTree` lacks a `TPropertyKey` generic).\n *\n * @internal\n */\ntype EntityTree<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n> = PropertyDescriptorTree<\n EntitySchemaBase<TSchema>,\n EntitySchemaBase<TSchema>\n> & {\n readonly [K in keyof SchemaProps<TSchema> & string]: {\n readonly [SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]: {\n readonly propertyName: K;\n };\n };\n};\n\n/**\n * Selector callback that receives a real {@link PropertyDescriptorTree} so\n * `t => t.someProp` navigates to the property definition and preserves its\n * JSDoc in IDE tooltips. The return shape is matched structurally on the\n * `[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR].propertyName` field, which captures\n * the literal property key as `TKey`.\n *\n * @public\n */\nexport type EntityPropSelector<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TKey extends string = string\n> = (t: EntityTree<TSchema>) => {\n readonly [SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]: {\n readonly propertyName: TKey;\n };\n};\n\n/**\n * Peel `.optional()` / `array(...)` wrappers off a navigation property's\n * schema to recover the underlying foreign `ObjectSchemaBuilder`.\n *\n * @public\n */\nexport type UnwrapNavSchema<TProp> =\n TProp extends ArraySchemaBuilder<infer TEl, any, any, any>\n ? TEl extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n ? TEl\n : never\n : TProp extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n ? TProp\n : TProp extends SchemaBuilder<infer T, any, any, any, any>\n ? T extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n ? T\n : never\n : never;\n\n/**\n * Merge type for a single polymorphic variant branch: variant schema fields\n * overlay base schema fields (narrowing the discriminator from `string` to its\n * specific literal value).\n *\n * @public\n */\nexport type VariantBranch<\n TBaseSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TVarSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n> = Omit<InferType<TBaseSchema>, keyof InferType<TVarSchema>> &\n InferType<TVarSchema>;\n\n/**\n * Return type for an Entity method that adds a relation: keeps `TSchema`,\n * extends `TRels` with one more entry, and preserves `TVariantUnion`.\n *\n * @public\n */\nexport type WithRelation<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TRels extends Record<string, RelationInfo>,\n TKey extends string,\n TKind extends 'belongsTo' | 'hasOne' | 'hasMany' | 'belongsToMany',\n TForeign extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TVariantUnion = never\n> = Entity<\n TSchema,\n TRels & Record<TKey, RelationInfo<TKind, TForeign>>,\n TVariantUnion\n>;\n\n// ---------------------------------------------------------------------------\n// Entity\n// ---------------------------------------------------------------------------\n\n/**\n * A typed wrapper around an `ObjectSchemaBuilder` that tracks declared\n * relations in its `TRels` generic. Use {@link defineEntity} to create one.\n *\n * Relations are declared via `.hasOne()` / `.hasMany()` / `.belongsTo()` /\n * `.belongsToMany()` on the entity (NOT on the underlying schema). Each\n * call returns a new `Entity` whose `TRels` includes the new relation, so\n * `query(db, entity).include(t => t.assignee)` is fully typed.\n *\n * @public\n */\nexport class Entity<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TRels extends Record<string, RelationInfo> = {},\n TVariantUnion = never\n> {\n /** The underlying schema (relations registered via `withExtension('relations', ...)`). */\n readonly schema: TSchema;\n\n /** @internal Phantom slot to retain `TRels` in inferred types. */\n private declare readonly __relations__: TRels;\n\n /** @internal Phantom slot to retain `TVariantUnion` in inferred types. */\n private declare readonly __variantUnion__: TVariantUnion;\n\n constructor(schema: TSchema) {\n this.schema = schema;\n }\n\n private _addRelation(spec: {\n type: 'belongsTo' | 'hasOne' | 'hasMany' | 'belongsToMany';\n name: string;\n schema: any;\n foreignKey?: any;\n through?: { table: string; localKey: string; foreignKey: string };\n optional?: boolean;\n }): Entity<TSchema, any> {\n const existing =\n ((this.schema as any).getExtension?.('relations') as any[]) ?? [];\n const next = (this.schema as any).withExtension('relations', [\n ...existing,\n spec\n ]);\n return new Entity(next);\n }\n\n /**\n * Declare a one-to-one relation where the FK lives on the FOREIGN table.\n * `navSel` selects the navigation property on THIS schema (must hold the\n * foreign schema, typically `.optional()`). The foreign schema is\n * auto-resolved at runtime from that property; provided explicitly here\n * via `opts.foreign` only when peeling fails.\n *\n * @param navSel Selector of nav property: `t => t.author`\n * @param localSel Selector of local-side join key: `l => l.id`\n * @param remoteSel Selector of remote-side FK on foreign schema: `r => r.userId`\n * @param opts Optional `{ optional?: boolean }` (default false).\n */\n hasOne<\n TKey extends keyof SchemaProps<TSchema> & string,\n TForeign extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = UnwrapNavSchema<SchemaProps<TSchema>[TKey]>\n >(\n navSel: EntityPropSelector<TSchema, TKey>,\n _localSel: EntityPropSelector<TSchema>,\n remoteSel: EntityPropSelector<TForeign>,\n opts?: { optional?: boolean }\n ): WithRelation<TSchema, TRels, TKey, 'hasOne', TForeign, TVariantUnion> {\n const navName = this._resolvePropName(\n navSel as EntityPropSelector<TSchema>,\n this.schema\n );\n const foreignSchema = this._resolveForeignSchema(navName);\n const remoteKey = this._resolvePropName(\n remoteSel as EntityPropSelector<any>,\n foreignSchema\n );\n // For hasOne the FK is on the FOREIGN table → store remoteKey.\n return this._addRelation({\n type: 'hasOne',\n name: navName,\n schema: foreignSchema,\n foreignKey: remoteKey,\n optional: opts?.optional\n }) as any;\n }\n\n /**\n * Declare a one-to-many relation where the FK lives on the FOREIGN table.\n *\n * @param navSel Selector of nav array property: `t => t.posts`\n * @param localSel Selector of local-side join key: `l => l.id`\n * @param remoteSel Selector of remote-side FK on foreign schema: `r => r.userId`\n */\n hasMany<\n TKey extends keyof SchemaProps<TSchema> & string,\n TForeign extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = UnwrapNavSchema<SchemaProps<TSchema>[TKey]>\n >(\n navSel: EntityPropSelector<TSchema, TKey>,\n _localSel: EntityPropSelector<TSchema>,\n remoteSel: EntityPropSelector<TForeign>\n ): WithRelation<TSchema, TRels, TKey, 'hasMany', TForeign, TVariantUnion> {\n const navName = this._resolvePropName(\n navSel as EntityPropSelector<TSchema>,\n this.schema\n );\n const foreignSchema = this._resolveForeignSchema(navName);\n const remoteKey = this._resolvePropName(\n remoteSel as EntityPropSelector<any>,\n foreignSchema\n );\n return this._addRelation({\n type: 'hasMany',\n name: navName,\n schema: foreignSchema,\n foreignKey: remoteKey\n }) as any;\n }\n\n /**\n * Declare a many-to-one relation where the FK lives on THIS table.\n *\n * @param navSel Selector of nav property (foreign schema, usually `.optional()`).\n * @param localSel Selector of local-side FK property: `l => l.userId`\n * @param remoteSel Selector of foreign-side PK property: `r => r.id`\n */\n belongsTo<\n TKey extends keyof SchemaProps<TSchema> & string,\n TForeign extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = UnwrapNavSchema<SchemaProps<TSchema>[TKey]>\n >(\n navSel: EntityPropSelector<TSchema, TKey>,\n localSel: EntityPropSelector<TSchema>,\n _remoteSel: EntityPropSelector<TForeign>,\n opts?: { optional?: boolean }\n ): WithRelation<\n TSchema,\n TRels,\n TKey,\n 'belongsTo',\n TForeign,\n TVariantUnion\n > {\n const navName = this._resolvePropName(\n navSel as EntityPropSelector<TSchema>,\n this.schema\n );\n const foreignSchema = this._resolveForeignSchema(navName);\n const localKey = this._resolvePropName(localSel, this.schema);\n // For belongsTo the FK is on THIS table → store localKey.\n return this._addRelation({\n type: 'belongsTo',\n name: navName,\n schema: foreignSchema,\n foreignKey: localKey,\n optional: opts?.optional\n }) as any;\n }\n\n /**\n * Declare a many-to-many relation through a pivot table.\n *\n * @param navSel Selector of nav array property: `t => t.tags`\n * @param through Pivot table config `{ table, localKey, foreignKey }`.\n */\n belongsToMany<\n TKey extends keyof SchemaProps<TSchema> & string,\n TForeign extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = UnwrapNavSchema<SchemaProps<TSchema>[TKey]>\n >(\n navSel: EntityPropSelector<TSchema, TKey>,\n through: { table: string; localKey: string; foreignKey: string }\n ): WithRelation<\n TSchema,\n TRels,\n TKey,\n 'belongsToMany',\n TForeign,\n TVariantUnion\n > {\n const navName = this._resolvePropName(\n navSel as EntityPropSelector<TSchema>,\n this.schema\n );\n const foreignSchema = this._resolveForeignSchema(navName);\n return this._addRelation({\n type: 'belongsToMany',\n name: navName,\n schema: foreignSchema,\n through\n }) as any;\n }\n\n /**\n * Mark this entity as polymorphic by selecting the discriminator\n * property. Returns a new `Entity` whose `.ctiVariant()` /\n * `.stiVariant()` methods declare each variant.\n *\n * Declare ordinary relations (`.belongsTo()` etc.) on this entity BEFORE\n * `.discriminator()`. After `.discriminator()` you are in the\n * polymorphic-builder phase: `.hasOne/.hasMany/.belongsTo/.belongsToMany`\n * still work, but the per-variant relations live on the `.ctiVariant()`\n * / `.stiVariant()` calls.\n *\n * @example\n * ```ts\n * const FileEntity = defineEntity(FileSchema)\n * .discriminator(t => t.type)\n * .ctiVariant('image', ImageEntity, t => t.fileId)\n * .ctiVariant('document', DocumentEntity, t => t.fileId);\n * ```\n */\n discriminator<TKey extends keyof SchemaProps<TSchema> & string>(\n sel: TKey | EntityPropSelector<TSchema, TKey>\n ): Entity<TSchema, TRels, never> {\n const discKey =\n typeof sel === 'string'\n ? (sel as string)\n : this._resolvePropName(\n sel as EntityPropSelector<TSchema>,\n this.schema\n );\n const next = new Entity(this.schema) as Entity<TSchema, TRels>;\n // Carry the variant-builder state on the new Entity so subsequent\n // `.ctiVariant()`/`.stiVariant()` calls can extend it. Stored on\n // the instance (not in the schema) so the original schema is\n // unchanged until the first variant is added.\n (next as any)._variantBuilder = {\n discKey,\n variants: {} as Record<string, VariantInputForResolver>\n };\n return next;\n }\n\n /**\n * Declare a CTI (Class Table Inheritance) variant. Only valid after\n * `.discriminator()`. Returns a new `Entity` whose schema carries the\n * updated `'variants'` extension.\n *\n * @param key Discriminator literal (e.g. `'image'`).\n * @param variant Entity wrapping the variant table schema.\n * @param fkSel Accessor returning the FK property on the variant\n * schema that joins back to the base PK.\n * @param opts `{ allowOrphan?: boolean; relations?: ... }` — see CTI docs.\n */\n ctiVariant<\n TVarSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n >(\n key: string,\n variant: Entity<TVarSchema, any>,\n fkSel: (t: EntityTree<TVarSchema>) => any,\n opts?: {\n allowOrphan?: boolean;\n relations?: Record<string, VariantRelationInput<TVarSchema>>;\n }\n ): Entity<\n TSchema,\n TRels,\n TVariantUnion | VariantBranch<TSchema, TVarSchema>\n > {\n const builder = (this as any)._variantBuilder as\n | VariantBuilderState\n | undefined;\n if (!builder) {\n throw new Error(\n 'ctiVariant: call `.discriminator(...)` first to begin a polymorphic builder chain'\n );\n }\n const fkColumn = resolveCtiForeignKeyColumn(\n variant.schema,\n fkSel as (t: any) => any\n );\n const nextVariants: Record<string, VariantInputForResolver> = {\n ...builder.variants,\n [key]: {\n schema: variant.schema,\n storage: 'cti',\n foreignKeyColumn: fkColumn,\n allowOrphan: opts?.allowOrphan,\n relations: [\n ...entityRelationsToVariantRelations(variant),\n ...resolveInlineVariantRelations(\n variant.schema,\n opts?.relations\n )\n ]\n }\n };\n return this._withVariantBuilder<\n TVariantUnion | VariantBranch<TSchema, TVarSchema>\n >(builder.discKey, nextVariants);\n }\n\n /**\n * Declare an STI (Single Table Inheritance) variant. Only valid after\n * `.discriminator()`. Accepts either an {@link Entity} or a bare\n * {@link ObjectSchemaBuilder}.\n */\n stiVariant<\n TVarSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n >(\n key: string,\n body: Entity<TVarSchema, any> | TVarSchema,\n opts?: {\n enforceCheck?: boolean;\n relations?: Record<string, VariantRelationInput<TVarSchema>>;\n }\n ): Entity<\n TSchema,\n TRels,\n TVariantUnion | VariantBranch<TSchema, TVarSchema>\n > {\n const builder = (this as any)._variantBuilder as\n | VariantBuilderState\n | undefined;\n if (!builder) {\n throw new Error(\n 'stiVariant: call `.discriminator(...)` first to begin a polymorphic builder chain'\n );\n }\n const isEntity = body instanceof Entity;\n const varSchema = (\n isEntity ? (body as Entity<any, any>).schema : body\n ) as ObjectSchemaBuilder<any, any, any, any, any, any, any>;\n const nextVariants: Record<string, VariantInputForResolver> = {\n ...builder.variants,\n [key]: {\n schema: varSchema,\n storage: 'sti',\n enforceCheck: opts?.enforceCheck,\n relations: [\n ...(isEntity\n ? entityRelationsToVariantRelations(\n body as Entity<any, any>\n )\n : []),\n ...resolveInlineVariantRelations(varSchema, opts?.relations)\n ]\n }\n };\n return this._withVariantBuilder<\n TVariantUnion | VariantBranch<TSchema, TVarSchema>\n >(builder.discKey, nextVariants);\n }\n\n /** @internal Apply the variant extension to the schema and return a new Entity. */\n private _withVariantBuilder<TNewUnion>(\n discKey: string,\n variants: Record<string, VariantInputForResolver>\n ): Entity<TSchema, TRels, TNewUnion> {\n let newSchema = applyVariantsToSchema(\n this.schema,\n discKey,\n variants\n ) as any;\n // Preserve any existing `relations` extension across the rebuild.\n const existingRelations =\n (this.schema as any).getExtension?.('relations') ?? [];\n if (existingRelations.length) {\n newSchema = newSchema.withExtension('relations', existingRelations);\n }\n const next = new Entity(newSchema as TSchema) as Entity<\n TSchema,\n TRels,\n TNewUnion\n >;\n (next as any)._variantBuilder = { discKey, variants };\n return next;\n }\n\n /**\n * @internal\n * Resolve a selector callback against the real `PropertyDescriptorTree`\n * of the given schema, returning the top-level property name. Throws if\n * the accessor does not yield a valid descriptor.\n */\n private _resolvePropName(\n selector: (t: any) => any,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n ): string {\n const tree = ObjectSchemaBuilder.getPropertiesFor(schema as any);\n const descriptor = selector(tree as any);\n if (\n !descriptor ||\n typeof descriptor !== 'object' ||\n !(SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in descriptor)\n ) {\n throw new Error(\n 'Entity relation selector must return a property descriptor, e.g. `t => t.author`.'\n );\n }\n const inner = (descriptor as any)[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n if (typeof inner.propertyName !== 'string') {\n throw new Error(\n 'Entity relation selector must return a top-level property descriptor.'\n );\n }\n return inner.propertyName as string;\n }\n\n /** @internal Resolve the foreign schema from a nav property. */\n private _resolveForeignSchema(navName: string): any {\n const props = (this.schema as any).introspect?.()?.properties ?? {};\n const propSchema = props[navName];\n if (!propSchema) {\n throw new Error(\n `Entity.relation: navigation property \"${navName}\" not found on schema`\n );\n }\n const intro = propSchema.introspect?.() ?? propSchema;\n // Array → use elementSchema\n if (intro.type === 'array' && intro.elementSchema) {\n return intro.elementSchema;\n }\n // Object schema directly (with or without optional)\n if (\n intro.type === 'object' ||\n propSchema.constructor?.name === 'ObjectSchemaBuilder'\n ) {\n return propSchema;\n }\n // Fall back: assume it's already the schema\n return propSchema;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Polymorphic variant helpers (used by Entity.discriminator/ctiVariant/stiVariant)\n// ---------------------------------------------------------------------------\n\n/** @internal Variant-builder state carried on an Entity instance during a\n * `.discriminator().ctiVariant()/.stiVariant()` chain. */\ninterface VariantBuilderState {\n discKey: string;\n variants: Record<string, VariantInputForResolver>;\n}\n\n/**\n * @internal Convert an Entity's stored relations (which use property-name\n * foreign keys) into the column-name form required by\n * {@link ResolvedVariantRelationSpec}.\n */\nfunction entityRelationsToVariantRelations(\n varEntity: Entity<any, any>\n): ResolvedVariantRelationSpec[] {\n const rels: any[] =\n (varEntity.schema as any).getExtension?.('relations') ?? [];\n if (rels.length === 0) return [];\n\n const { propToCol } = buildColumnMap(varEntity.schema as any);\n\n return rels.map(r => {\n // belongsToMany has no `foreignKey` on the spec itself (uses through.*).\n const fkPropName: string | undefined =\n typeof r.foreignKey === 'string' ? r.foreignKey : undefined;\n const fkColName = fkPropName\n ? (propToCol.get(fkPropName) ?? fkPropName)\n : undefined;\n return {\n name: r.name,\n type: r.type,\n schema: r.schema,\n foreignKey: fkColName,\n through: r.through\n } satisfies ResolvedVariantRelationSpec;\n });\n}\n\n/**\n * @internal Resolve a foreign-key accessor (`t => t.fileId`) against a\n * variant schema to a SQL column name.\n */\nfunction resolveCtiForeignKeyColumn(\n varSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n fkSel: (t: any) => any\n): string {\n const tree = ObjectSchemaBuilder.getPropertiesFor(varSchema as any);\n const desc = fkSel(tree as any);\n const inner = (desc as any)?.[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n if (!inner?.propertyName) {\n throw new Error(\n 'ctiVariant: foreignKey accessor must return a top-level property descriptor on the variant schema'\n );\n }\n const propKey: string = inner.propertyName;\n const props = (varSchema as any).introspect?.()?.properties ?? {};\n const propSchema = props[propKey];\n if (!propSchema) {\n throw new Error(\n `ctiVariant: foreignKey property \"${propKey}\" not found on variant schema`\n );\n }\n return getColumnName(propSchema, propKey);\n}\n\n/**\n * Inline relation spec accepted by {@link Entity.ctiVariant} /\n * {@link Entity.stiVariant} via `opts.relations`. The `foreignKey`\n * accessor (when given) is typed against the variant's own schema and\n * resolved to a SQL column name.\n *\n * @public\n */\nexport interface VariantRelationInput<\n TVarSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = ObjectSchemaBuilder<any, any, any, any, any, any, any>\n> {\n type: 'belongsTo' | 'hasOne' | 'hasMany' | 'belongsToMany';\n /**\n * Foreign side — accept either a bare schema, an Entity wrapper, or a\n * lazy thunk for forward references.\n */\n schema?:\n | ObjectSchemaBuilder<any, any, any, any, any, any, any>\n | (() => ObjectSchemaBuilder<any, any, any, any, any, any, any>);\n entity?: Entity<any, any>;\n foreignKey?: (t: EntityTree<TVarSchema>) => any;\n through?: { table: string; localKey: string; foreignKey: string };\n}\n\n/**\n * @internal Resolve a map of {@link VariantRelationInput} into the\n * column-resolved {@link ResolvedVariantRelationSpec[]} shape stored on a\n * resolved variant spec.\n */\nfunction resolveInlineVariantRelations(\n varSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n relations: Record<string, VariantRelationInput<any>> | undefined\n): ResolvedVariantRelationSpec[] {\n if (!relations) return [];\n const { propToCol } = buildColumnMap(varSchema);\n const result: ResolvedVariantRelationSpec[] = [];\n const tree = ObjectSchemaBuilder.getPropertiesFor(varSchema as any);\n\n for (const [name, spec] of Object.entries(relations)) {\n let foreignKey: string | undefined;\n if (spec.foreignKey) {\n const desc = spec.foreignKey(tree as any);\n const inner = (desc as any)?.[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n if (!inner?.propertyName) {\n throw new Error(\n `variant relation \"${name}\": foreignKey accessor must return a top-level property descriptor on the variant schema`\n );\n }\n const propKey: string = inner.propertyName;\n foreignKey = propToCol.get(propKey) ?? propKey;\n }\n const targetSchema = spec.entity ? spec.entity.schema : spec.schema;\n result.push({\n name,\n type: spec.type,\n schema: targetSchema,\n foreignKey,\n through: spec.through\n });\n }\n return result;\n}\n\n/**\n * Wrap an `ObjectSchemaBuilder` in an {@link Entity}, enabling typed relation\n * declaration via `.hasOne()` / `.hasMany()` / `.belongsTo()` / `.belongsToMany()`.\n *\n * @public\n *\n * @example\n * ```ts\n * const UserEntity = defineEntity(\n * object({\n * id: number().primaryKey(),\n * name: string(),\n * posts: array(PostEntity.schema)\n * }).hasTableName('users')\n * ).hasMany(t => t.posts, l => l.id, r => r.userId);\n * ```\n */\nexport function defineEntity<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n>(schema: TSchema): Entity<TSchema, {}> {\n return new Entity(schema);\n}\n\n/**\n * Type-level helper: extract `TRels` from any `Entity` type.\n * @public\n */\nexport type EntityRelations<E> =\n E extends Entity<any, infer R, any> ? R : never;\n\n/**\n * Type-level helper: extract the underlying schema type from any `Entity`.\n * @public\n */\nexport type EntitySchema<E> = E extends Entity<infer S, any, any> ? S : never;\n\n/**\n * Type-level helper: extract the accumulated variant union from any `Entity`.\n * Resolves to `never` for non-polymorphic entities.\n * @public\n */\nexport type EntityVariantUnion<E> =\n E extends Entity<any, any, infer U> ? U : never;\n\n/**\n * Type-level helper: union of relation key names declared on an entity.\n * Used by `SchemaQueryBuilder.insert()/update()/upsert()` to omit relation\n * navigation properties from accepted input.\n * @public\n */\nexport type EntityRelationKeys<E> =\n E extends Entity<any, infer R, any> ? keyof R & string : never;\n","// @cleverbrush/knex-schema — Post-load value transformers (from knex-eager)\n\nimport type { ValidatedSpec } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Built-in named mappers\n// ---------------------------------------------------------------------------\n\n/**\n * Built-in named value mapper functions.\n *\n * Each entry maps a string key to a transformation function. Pass the key as\n * the `mapper` argument to {@link mapValue} instead of a custom function.\n *\n * Currently available:\n * - `date_from_json` — converts a JSON date string (`string | null`) to a\n * JavaScript `Date` object (or passes through falsy values unchanged).\n */\nexport const MAPPERS: Record<string, (value: any) => any> = {\n date_from_json: (value: any) => {\n if (!value) return value;\n return new Date(Date.parse(value));\n }\n};\n\n// ---------------------------------------------------------------------------\n// mapValue — apply a mapper (function or built-in name) to a value\n// ---------------------------------------------------------------------------\n\n/**\n * Apply a single mapper to a value.\n *\n * @param mapper - Either a transformation function `(v: any) => any`, or a\n * string key referencing one of the {@link MAPPERS} built-ins (e.g.\n * `'date_from_json'`).\n * @param value - The raw value to transform.\n * @returns The transformed value.\n *\n * @throws If `mapper` is a string that does not exist in {@link MAPPERS}.\n */\nexport function mapValue(mapper: ((v: any) => any) | string, value: any): any {\n if (typeof mapper === 'string') {\n if (typeof MAPPERS[mapper] !== 'function') {\n throw new Error(`unknown mapper \"${mapper}\"`);\n }\n return MAPPERS[mapper](value);\n }\n if (typeof mapper === 'function') {\n return mapper(value);\n }\n throw new Error(\"couldn't map value\");\n}\n\n// ---------------------------------------------------------------------------\n// mapObject — apply mappers to all matching keys of an object\n// ---------------------------------------------------------------------------\n\n/**\n * Apply a map of per-key transformations to an object, returning a new object\n * with the transformed values.\n *\n * Keys not present in `mappers` are copied through unchanged. Keys present in\n * `mappers` are passed through {@link mapValue}.\n *\n * @param obj - The source object (e.g. a raw database row).\n * @param mappers - A `Record` mapping property keys to mapper functions or\n * {@link MAPPERS} built-in names.\n * @returns A shallow copy of `obj` with the specified values transformed.\n *\n * @throws If `obj` is `null` or a non-object, it is returned as-is.\n */\nexport function mapObject<T extends Record<string, any>>(\n obj: T,\n mappers: Record<string, ((v: any) => any) | string>\n): T {\n if (!mappers) throw new Error('mappers should be an object');\n if (!obj || typeof obj !== 'object' || obj === null) return obj;\n\n const result = {} as Record<string, any>;\n for (const key of Object.keys(obj)) {\n result[key] = mappers[key]\n ? mapValue(mappers[key], obj[key])\n : obj[key];\n }\n return result as T;\n}\n\n// ---------------------------------------------------------------------------\n// clearRow — apply mappers to joined data in a result row\n// ---------------------------------------------------------------------------\n\n/**\n * Apply value mappers to the joined fields of a result row in place.\n *\n * After an eager-loaded query resolves, joined objects and arrays may contain\n * raw database values that need transformation (e.g. date strings → `Date`).\n * This function iterates over the one-to-one and one-to-many specs, applies\n * the `mappers` defined on each spec to the nested data, and returns the\n * mutated row.\n *\n * This is an internal helper used by {@link SchemaQueryBuilder}'s result\n * mapping pipeline. Exported to allow custom post-processing if needed.\n *\n * @param row - The raw result row (mutated in place).\n * @param oneSpecs - Validated one-to-one join specs with optional `mappers`.\n * @param manySpecs - Validated one-to-many join specs with optional `mappers`.\n * @returns The mutated `row` object.\n */\nexport function clearRow(\n row: Record<string, any>,\n oneSpecs: Array<ValidatedSpec & { type: 'one' }>,\n manySpecs: Array<ValidatedSpec & { type: 'many' }>\n): Record<string, any> {\n for (const spec of oneSpecs) {\n const fieldName = spec.as;\n if (\n spec.mappers &&\n typeof row[fieldName] !== 'undefined' &&\n row[fieldName] !== null\n ) {\n row[fieldName] = mapObject(row[fieldName], spec.mappers);\n }\n }\n\n for (const spec of manySpecs) {\n const fieldName = spec.as;\n if (Array.isArray(row[fieldName])) {\n for (let k = 0; k < row[fieldName].length; k++) {\n if (row[fieldName][k]) {\n if (spec.mappers) {\n row[fieldName][k] = mapObject(\n row[fieldName][k],\n spec.mappers\n );\n }\n }\n }\n }\n }\n\n return row;\n}\n","// @cleverbrush/knex-schema — Schema diff & migration generation\n\nimport type { ObjectSchemaBuilder, SchemaBuilder } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { generateCreateTableSource } from './ddl.js';\nimport type { Entity } from './entity.js';\nimport {\n getColumnName,\n getPolymorphicVariantSchemas,\n getTableName\n} from './extension.js';\nimport type {\n AddColumnDiff,\n AddForeignKeyDiff,\n AddIndexDiff,\n AlterColumnDiff,\n DatabaseCheckInfo,\n DatabaseColumnInfo,\n DatabaseForeignKeyInfo,\n DatabaseIndexInfo,\n DatabaseTableState,\n MigrationDiff,\n SchemaSnapshot\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// Database introspection\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize raw database query results into a {@link DatabaseTableState}.\n * @internal\n */\nfunction normalizeDbState(\n columns: any[],\n indexes: any[],\n foreignKeys: any[],\n checks: any[]\n): DatabaseTableState {\n const colMap: Record<string, DatabaseColumnInfo> = {};\n for (const row of columns) {\n colMap[row.column_name] = {\n name: row.column_name,\n type: row.data_type,\n nullable: row.is_nullable === 'YES',\n defaultValue: row.column_default ?? null,\n maxLength: row.character_maximum_length ?? null,\n numericPrecision: row.numeric_precision ?? null\n };\n }\n\n const idxList: DatabaseIndexInfo[] = indexes.map((row: any) => ({\n name: row.indexname,\n columns: Array.isArray(row.columns) ? row.columns : [],\n unique: (row.indexdef ?? '').toUpperCase().includes('UNIQUE'),\n definition: row.indexdef ?? ''\n }));\n\n const fkList: DatabaseForeignKeyInfo[] = foreignKeys.map((row: any) => ({\n constraintName: row.constraint_name,\n columnName: row.column_name,\n foreignTable: row.foreign_table,\n foreignColumn: row.foreign_column,\n deleteRule: row.delete_rule,\n updateRule: row.update_rule\n }));\n\n const chkList: DatabaseCheckInfo[] = checks.map((row: any) => ({\n name: row.conname,\n definition: row.definition\n }));\n\n return {\n columns: colMap,\n indexes: idxList,\n foreignKeys: fkList,\n checks: chkList\n };\n}\n\n/**\n * Introspect a PostgreSQL table and return its current state.\n *\n * Queries `information_schema.columns`, `pg_indexes`, `pg_constraint`, and\n * referential constraint metadata to build a complete picture of the table's\n * columns, indexes, foreign keys, and check constraints.\n *\n * @param knex - A configured Knex instance connected to a PostgreSQL database.\n * @param tableName - The table name to introspect.\n * @returns The current database state for the table.\n *\n * @example\n * ```ts\n * const dbState = await introspectDatabase(knex, 'users');\n * console.log(dbState.columns); // { id: { type: 'integer', ... }, ... }\n * ```\n */\nexport async function introspectDatabase(\n knex: Knex,\n tableName: string\n): Promise<DatabaseTableState> {\n const [columns, indexes, foreignKeys, checks] = await Promise.all([\n knex.raw(\n `SELECT column_name, data_type, is_nullable, column_default,\n character_maximum_length, numeric_precision\n FROM information_schema.columns\n WHERE table_name = ? AND table_schema = 'public'\n ORDER BY ordinal_position`,\n [tableName]\n ),\n knex.raw(\n `SELECT indexname, indexdef,\n array_agg(a.attname ORDER BY array_position(ix.indkey, a.attnum)) as columns\n FROM pg_indexes\n JOIN pg_class t ON t.relname = ?\n JOIN pg_index ix ON ix.indrelid = t.oid\n JOIN pg_class i ON i.oid = ix.indexrelid AND i.relname = pg_indexes.indexname\n JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\n WHERE pg_indexes.tablename = ?\n GROUP BY indexname, indexdef`,\n [tableName, tableName]\n ),\n knex.raw(\n `SELECT tc.constraint_name, kcu.column_name,\n ccu.table_name AS foreign_table, ccu.column_name AS foreign_column,\n rc.delete_rule, rc.update_rule\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu USING (constraint_name, table_schema)\n JOIN information_schema.constraint_column_usage ccu USING (constraint_name, table_schema)\n JOIN information_schema.referential_constraints rc USING (constraint_name, constraint_schema)\n WHERE tc.table_name = ? AND tc.constraint_type = 'FOREIGN KEY'`,\n [tableName]\n ),\n knex.raw(\n `SELECT conname, pg_get_constraintdef(oid) as definition\n FROM pg_constraint\n WHERE conrelid = ?::regclass AND contype = 'c'`,\n [tableName]\n )\n ]);\n\n return normalizeDbState(\n columns.rows,\n indexes.rows,\n foreignKeys.rows,\n checks.rows\n );\n}\n\n// ---------------------------------------------------------------------------\n// Schema → column info extraction\n// ---------------------------------------------------------------------------\n\n/** @internal Map a schema type to a PostgreSQL data_type string for comparison. */\nfunction schemaTypeToDbType(\n introspected: any,\n ext: Record<string, any>\n): string {\n if (ext.columnType) return ext.columnType;\n if (ext.primaryKey?.autoIncrement) return 'integer';\n switch (introspected.type) {\n case 'string':\n return 'character varying';\n case 'number':\n return introspected.isInteger !== false\n ? 'integer'\n : 'double precision';\n case 'boolean':\n return 'boolean';\n case 'date':\n return 'timestamp without time zone';\n default:\n return 'text';\n }\n}\n\n// ---------------------------------------------------------------------------\n// entitySchemaToTableState\n// ---------------------------------------------------------------------------\n\n/**\n * Derive a {@link DatabaseTableState} from a code-first `ObjectSchemaBuilder`\n * without connecting to the database.\n *\n * The result mirrors what {@link introspectDatabase} would return after the\n * schema has been fully applied, so it can be fed directly into\n * {@link diffSchema} as the `dbState` argument. This is the foundation of\n * snapshot-based migration generation.\n *\n * @param schema - An `ObjectSchemaBuilder` with DDL extensions.\n * @returns A {@link DatabaseTableState} representing the schema's ideal DB shape.\n *\n * @example\n * ```ts\n * const state = entitySchemaToTableState(UserSchema);\n * // state.columns, state.foreignKeys, state.indexes …\n * ```\n */\nexport function entitySchemaToTableState(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): DatabaseTableState {\n const tableName = getTableName(schema);\n const introspected = schema.introspect() as any;\n const properties: Record<\n string,\n SchemaBuilder<any, any, any>\n > = introspected.properties ?? {};\n const tableExt: Record<string, any> = introspected.extensions ?? {};\n\n const columns: Record<string, DatabaseColumnInfo> = {};\n const indexes: DatabaseIndexInfo[] = [];\n const foreignKeys: DatabaseForeignKeyInfo[] = [];\n const checks: DatabaseCheckInfo[] = [];\n\n for (const [propKey, propSchema] of Object.entries(properties)) {\n const col = getColumnName(propSchema, propKey);\n const propIntrospected = propSchema.introspect() as any;\n const ext: Record<string, any> = propIntrospected.extensions ?? {};\n\n // Skip navigation properties (object/array without an explicit columnType).\n if (\n (propIntrospected.type === 'object' ||\n propIntrospected.type === 'array') &&\n !ext.columnType\n ) {\n continue;\n }\n\n columns[col] = {\n name: col,\n type: schemaTypeToDbType(propIntrospected, ext),\n nullable: !propIntrospected.isRequired,\n defaultValue: ext.defaultTo ?? null,\n maxLength: ext.maxLength ?? propIntrospected.maxLength ?? null,\n numericPrecision: null\n };\n\n if (ext.references) {\n foreignKeys.push({\n // Use Knex's default FK constraint naming convention\n constraintName: `${tableName}_${col}_foreign`,\n columnName: col,\n foreignTable: ext.references.table,\n foreignColumn: ext.references.column,\n deleteRule: (ext.onDelete ?? 'NO ACTION').toUpperCase(),\n updateRule: (ext.onUpdate ?? 'NO ACTION').toUpperCase()\n });\n }\n }\n\n // Timestamp columns (created_at / updated_at)\n if (tableExt.timestamps) {\n const ts = tableExt.timestamps;\n const createdAtCol: string = ts.createdAt ?? 'created_at';\n const updatedAtCol: string = ts.updatedAt ?? 'updated_at';\n columns[createdAtCol] = {\n name: createdAtCol,\n type: 'timestamp without time zone',\n nullable: false,\n defaultValue: 'now',\n maxLength: null,\n numericPrecision: null\n };\n columns[updatedAtCol] = {\n name: updatedAtCol,\n type: 'timestamp without time zone',\n nullable: false,\n defaultValue: 'now',\n maxLength: null,\n numericPrecision: null\n };\n }\n\n // Soft-delete column\n if (tableExt.softDelete) {\n const delCol: string = tableExt.softDelete.column ?? 'deleted_at';\n columns[delCol] = {\n name: delCol,\n type: 'timestamp without time zone',\n nullable: true,\n defaultValue: null,\n maxLength: null,\n numericPrecision: null\n };\n }\n\n // Non-unique indexes\n for (const idx of tableExt.indexes ?? []) {\n const idxName: string =\n idx.name ?? `idx_${(idx.columns as string[]).join('_')}`;\n indexes.push({\n name: idxName,\n columns: idx.columns,\n unique: idx.unique ?? false,\n definition: ''\n });\n }\n\n // Unique constraints\n for (const unq of tableExt.uniques ?? []) {\n const unqName: string =\n unq.name ?? `unq_${(unq.columns as string[]).join('_')}`;\n indexes.push({\n name: unqName,\n columns: unq.columns,\n unique: true,\n definition: ''\n });\n }\n\n return { columns, indexes, foreignKeys, checks };\n}\n\n// ---------------------------------------------------------------------------\n// diffSchema\n// ---------------------------------------------------------------------------\n\n/**\n * Compare a code-first schema model against a live database table state and\n * produce a diff describing the changes needed to bring the database in sync.\n *\n * @param schema - The code-first `ObjectSchemaBuilder`.\n * @param dbState - The current database state from {@link introspectDatabase}.\n * @returns A {@link MigrationDiff} describing columns, indexes, and foreign\n * keys to add, drop, or alter.\n *\n * @example\n * ```ts\n * const dbState = await introspectDatabase(knex, 'users');\n * const diff = diffSchema(UserSchema, dbState);\n * if (diff.addColumns.length > 0) {\n * const migration = generateMigration(diff, 'users');\n * console.log(migration.up);\n * }\n * ```\n */\nexport function diffSchema(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n dbState: DatabaseTableState\n): MigrationDiff {\n const introspected = schema.introspect() as any;\n const properties: Record<\n string,\n SchemaBuilder<any, any, any>\n > = introspected.properties ?? {};\n const tableExt: Record<string, any> = introspected.extensions ?? {};\n\n const addColumns: AddColumnDiff[] = [];\n const dropColumns: string[] = [];\n const alterColumns: AlterColumnDiff[] = [];\n const addIndexes: AddIndexDiff[] = [];\n const dropIndexes: string[] = [];\n const addForeignKeys: AddForeignKeyDiff[] = [];\n const dropForeignKeys: string[] = [];\n\n // Columns whose default values are owned by table-level extensions\n // (hasTimestamps, softDelete). Don't compare defaultValue for these —\n // the extension is authoritative.\n const extensionOwnedDefaults = new Set<string>();\n if (tableExt.timestamps) {\n extensionOwnedDefaults.add(tableExt.timestamps.createdAt);\n extensionOwnedDefaults.add(tableExt.timestamps.updatedAt);\n }\n\n // Set of schema-defined column names\n const schemaColumns = new Set<string>();\n\n // --- Column diff ---\n for (const [propKey, propSchema] of Object.entries(properties)) {\n const col = getColumnName(propSchema, propKey);\n const propIntrospected = propSchema.introspect() as any;\n const ext: Record<string, any> = propIntrospected.extensions ?? {};\n\n // Skip navigation properties (object/array without explicit columnType).\n if (\n (propIntrospected.type === 'object' ||\n propIntrospected.type === 'array') &&\n !ext.columnType\n ) {\n continue;\n }\n\n schemaColumns.add(col);\n\n const dbCol = dbState.columns[col];\n if (!dbCol) {\n // Column exists in schema but not in DB → add\n addColumns.push({\n name: col,\n type: schemaTypeToDbType(propIntrospected, ext),\n nullable: !propIntrospected.isRequired,\n defaultValue: ext.defaultTo,\n references: ext.references,\n onDelete: ext.onDelete,\n onUpdate: ext.onUpdate\n });\n } else {\n // Column exists in both → check for alterations\n const changes: Record<string, { from: any; to: any }> = {};\n\n const expectedNullable = !propIntrospected.isRequired;\n if (dbCol.nullable !== expectedNullable) {\n changes.nullable = {\n from: dbCol.nullable,\n to: expectedNullable\n };\n }\n\n // Compare defaultValue (null / undefined both mean \"no default\")\n // Skip columns whose default is controlled by a table-level extension,\n // or auto-increment PKs whose nextval(...) default is DB-managed.\n if (\n !extensionOwnedDefaults.has(col) &&\n !ext.primaryKey?.autoIncrement\n ) {\n const snapshotDefault = dbCol.defaultValue ?? null;\n const schemaDefault = ext.defaultTo ?? null;\n if (snapshotDefault !== schemaDefault) {\n changes.defaultValue = {\n from: snapshotDefault,\n to: schemaDefault\n };\n }\n }\n\n if (Object.keys(changes).length > 0) {\n alterColumns.push({ name: col, changes });\n }\n }\n\n // Foreign key diff\n if (ext.references) {\n const existingFK = dbState.foreignKeys.find(\n fk => fk.columnName === col\n );\n if (!existingFK) {\n addForeignKeys.push({\n column: col,\n foreignTable: ext.references.table,\n foreignColumn: ext.references.column,\n onDelete: ext.onDelete,\n onUpdate: ext.onUpdate\n });\n }\n }\n }\n\n // Include timestamp columns in schema column set\n if (tableExt.timestamps) {\n schemaColumns.add(tableExt.timestamps.createdAt);\n schemaColumns.add(tableExt.timestamps.updatedAt);\n }\n if (tableExt.softDelete) {\n schemaColumns.add(tableExt.softDelete.column);\n }\n\n // Columns in DB but not in schema → drop\n for (const colName of Object.keys(dbState.columns)) {\n if (!schemaColumns.has(colName)) {\n dropColumns.push(colName);\n }\n }\n\n // --- Index diff ---\n const schemaIndexNames = new Set<string>();\n\n for (const idx of tableExt.indexes ?? []) {\n const idxName = idx.name ?? `idx_${idx.columns.join('_')}`;\n schemaIndexNames.add(idxName);\n const existingIdx = dbState.indexes.find(\n dbIdx => dbIdx.name === idxName\n );\n if (!existingIdx) {\n addIndexes.push({\n columns: idx.columns,\n name: idx.name,\n unique: idx.unique\n });\n }\n }\n\n for (const unq of tableExt.uniques ?? []) {\n const unqName = unq.name ?? `unq_${unq.columns.join('_')}`;\n schemaIndexNames.add(unqName);\n const existingIdx = dbState.indexes.find(\n dbIdx => dbIdx.name === unqName\n );\n if (!existingIdx) {\n addIndexes.push({\n columns: unq.columns,\n name: unq.name,\n unique: true\n });\n }\n }\n\n // FK constraints that exist in DB but not in schema → drop\n for (const fk of dbState.foreignKeys) {\n const propSchema = Object.entries(properties).find(([propKey, ps]) => {\n return getColumnName(ps, propKey) === fk.columnName;\n });\n if (propSchema) {\n const ext = (propSchema[1].introspect() as any).extensions ?? {};\n if (!ext.references) {\n dropForeignKeys.push(fk.constraintName);\n }\n } else {\n dropForeignKeys.push(fk.constraintName);\n }\n }\n\n return {\n addColumns,\n dropColumns,\n alterColumns,\n addIndexes,\n dropIndexes,\n addForeignKeys,\n dropForeignKeys\n };\n}\n\n// ---------------------------------------------------------------------------\n// generateMigration\n// ---------------------------------------------------------------------------\n\n/**\n * Generate migration `up` and `down` code strings from a {@link MigrationDiff}.\n *\n * The generated code is valid TypeScript that uses Knex's schema builder API.\n * Write it to a migration file and run via Knex's migration system.\n *\n * @param diff - The schema diff from {@link diffSchema}.\n * @param tableName - The table name to alter.\n * @returns An object with `up` and `down` migration code strings.\n *\n * @example\n * ```ts\n * const diff = diffSchema(UserSchema, dbState);\n * const migration = generateMigration(diff, 'users');\n * fs.writeFileSync('migration.ts', migration.full);\n * ```\n */\nexport function generateMigration(\n diff: MigrationDiff,\n tableName: string\n): { up: string; down: string; full: string } {\n const { up, down } = buildAlterTableFragments(diff, tableName);\n\n const full = `import type { Knex } from 'knex';\n\nexport async function up(knex: Knex): Promise<void> {\n${up}\n}\n\nexport async function down(knex: Knex): Promise<void> {\n${down}\n}\n`;\n\n return { up, down, full };\n}\n\n// ---------------------------------------------------------------------------\n// tableExistsInDb\n// ---------------------------------------------------------------------------\n\n/**\n * Check whether a table exists in the connected PostgreSQL database.\n *\n * @param knex - A configured Knex instance (or transaction).\n * @param tableName - The table name to check.\n * @returns `true` when the table exists.\n *\n * @example\n * ```ts\n * const exists = await tableExistsInDb(knex, 'users');\n * if (!exists) await generateCreateTable(UserSchema)(knex);\n * ```\n */\nexport async function tableExistsInDb(\n knex: Knex,\n tableName: string\n): Promise<boolean> {\n return knex.schema.hasTable(tableName);\n}\n\n// ---------------------------------------------------------------------------\n// isDiffEmpty\n// ---------------------------------------------------------------------------\n\n/**\n * Return `true` when a {@link MigrationDiff} has no operations — i.e. the\n * database table is already in sync with the schema.\n */\nexport function isDiffEmpty(diff: MigrationDiff): boolean {\n return (\n diff.addColumns.length === 0 &&\n diff.dropColumns.length === 0 &&\n diff.alterColumns.length === 0 &&\n diff.addIndexes.length === 0 &&\n diff.dropIndexes.length === 0 &&\n diff.addForeignKeys.length === 0 &&\n diff.dropForeignKeys.length === 0\n );\n}\n\n// ---------------------------------------------------------------------------\n// applyDiff\n// ---------------------------------------------------------------------------\n\n/**\n * Execute a {@link MigrationDiff} directly against a live database without\n * writing a migration file. Intended for `db push` (dev-only schema sync).\n *\n * Foreign-key constraint drops are executed as raw `ALTER TABLE … DROP\n * CONSTRAINT` statements before the main `alterTable` call.\n *\n * @param knex - A configured Knex instance or transaction.\n * @param diff - The diff from {@link diffSchema}.\n * @param tableName - The table to alter.\n *\n * @example\n * ```ts\n * const dbState = await introspectDatabase(knex, 'users');\n * const diff = diffSchema(UserSchema, dbState);\n * if (!isDiffEmpty(diff)) await applyDiff(knex, diff, 'users');\n * ```\n */\nexport async function applyDiff(\n knex: Knex,\n diff: MigrationDiff,\n tableName: string\n): Promise<void> {\n if (isDiffEmpty(diff)) return;\n\n // FK constraint drops require raw SQL (we only have constraint names, not\n // column names, in the diff so Knex's dropForeign helper cannot be used).\n for (const constraintName of diff.dropForeignKeys) {\n await knex.raw('ALTER TABLE ?? DROP CONSTRAINT ??', [\n tableName,\n constraintName\n ]);\n }\n\n const hasTableChanges =\n diff.addColumns.length > 0 ||\n diff.dropColumns.length > 0 ||\n diff.alterColumns.length > 0 ||\n diff.addIndexes.length > 0 ||\n diff.dropIndexes.length > 0 ||\n diff.addForeignKeys.length > 0;\n\n if (!hasTableChanges) return;\n\n await knex.schema.alterTable(tableName, table => {\n // Add columns\n for (const col of diff.addColumns) {\n let column = buildColumnFromDbType(\n table as unknown as Knex.CreateTableBuilder,\n col.name,\n col.type\n );\n if (col.nullable) column = column.nullable();\n else column = column.notNullable();\n if (col.defaultValue !== undefined) {\n if (col.defaultValue === 'now') {\n column = column.defaultTo(knex.fn.now());\n } else if (\n typeof col.defaultValue === 'object' &&\n col.defaultValue !== null &&\n col.defaultValue.raw\n ) {\n column = column.defaultTo(knex.raw(col.defaultValue.raw));\n } else {\n column = column.defaultTo(col.defaultValue);\n }\n }\n if (col.references) {\n const fkBuilder = column\n .references(col.references.column)\n .inTable(col.references.table);\n if (col.onDelete) fkBuilder.onDelete(col.onDelete);\n if (col.onUpdate) fkBuilder.onUpdate(col.onUpdate);\n }\n }\n\n // Drop columns\n for (const colName of diff.dropColumns) {\n table.dropColumn(colName);\n }\n\n // Alter nullable / default\n for (const col of diff.alterColumns) {\n for (const [key, change] of Object.entries(col.changes)) {\n if (key === 'nullable') {\n if (change.to) {\n (table as any).setNullable(col.name);\n } else {\n (table as any).dropNullable(col.name);\n }\n } else if (key === 'defaultValue') {\n if (change.to === null) {\n table.dropColumn(col.name); // fallback — handled in source gen\n } else {\n // ALTER COLUMN SET DEFAULT is not directly in Knex builder;\n // handled via raw in source generation\n }\n }\n }\n }\n\n // Add indexes\n for (const idx of diff.addIndexes) {\n if (idx.unique) {\n table.unique(\n idx.columns,\n idx.name ? { indexName: idx.name } : undefined\n );\n } else {\n table.index(idx.columns, idx.name);\n }\n }\n\n // Drop indexes\n for (const idx of diff.dropIndexes) {\n table.dropIndex([], idx);\n }\n\n // Add foreign keys\n for (const fk of diff.addForeignKeys) {\n let builder = table\n .foreign(fk.column)\n .references(fk.foreignColumn)\n .inTable(fk.foreignTable);\n if (fk.onDelete) builder = builder.onDelete(fk.onDelete);\n if (fk.onUpdate) builder = builder.onUpdate(fk.onUpdate);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// generateMigrationsForContext\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a single combined migration (up + down) for a set of entities by\n * diffing the current code-first schemas against a **serialized snapshot**\n * stored in the repository — no live database connection required.\n *\n * For each entity's table the function:\n * - **New tables** (in entities but not in `prevSnapshot`): emits `CREATE TABLE`.\n * - **Existing tables** (in both): diffs entity schema against the snapshot\n * state via {@link diffSchema} and emits `ALTER TABLE` when changes exist.\n * - **Dropped tables** (in `prevSnapshot` but not in entities): emits\n * `DROP TABLE` with a best-effort `CREATE TABLE` in the `down` direction.\n * - Orders tables topologically by FK dependencies so parent tables are\n * created before child tables in `up` (and dropped after in `down`).\n *\n * @param entities - The entities from your {@link EntityMap}.\n * @param prevSnapshot - The last committed {@link SchemaSnapshot} (empty on first run).\n * @returns `{ up, down, full, isEmpty, nextSnapshot }` where `nextSnapshot`\n * should be written to disk after the migration file is created.\n *\n * @example\n * ```ts\n * const prev = loadSnapshot('./migrations/snapshot.json');\n * const result = generateMigrationsForContext(\n * Object.values({ todos: TodoEntity, users: UserEntity }),\n * prev\n * );\n * if (!result.isEmpty) {\n * fs.writeFileSync('migrations/20260423000000_init.ts', result.full);\n * writeSnapshot('./migrations/snapshot.json', result.nextSnapshot);\n * }\n * ```\n */\nexport function generateMigrationsForContext(\n entities: Entity<any, any>[],\n prevSnapshot: SchemaSnapshot\n): {\n up: string;\n down: string;\n full: string;\n isEmpty: boolean;\n nextSnapshot: SchemaSnapshot;\n} {\n // 1. Collect all (schema, tableName) pairs including CTI variant tables\n const tableEntries: {\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>;\n tableName: string;\n }[] = [];\n\n for (const entity of entities) {\n const schema = entity.schema;\n const tableName = getTableName(schema);\n tableEntries.push({ schema, tableName });\n\n // CTI variant tables each have their own tableName extension set\n for (const vs of getPolymorphicVariantSchemas(schema)) {\n const variantTableName = vs.getExtension('tableName') as\n | string\n | undefined;\n if (variantTableName) {\n tableEntries.push({ schema: vs, tableName: variantTableName });\n }\n }\n }\n\n // 2. Deduplicate (STI variants share the base table)\n const seen = new Set<string>();\n const uniqueEntries = tableEntries.filter(e => {\n if (seen.has(e.tableName)) return false;\n seen.add(e.tableName);\n return true;\n });\n\n // 3. Topological sort by FK dependencies\n const sorted = topologicalSort(uniqueEntries);\n\n // 4. Generate CREATE or ALTER fragment for each current table\n const upParts: string[] = [];\n const downParts: string[] = [];\n\n const currentTableNames = new Set(sorted.map(e => e.tableName));\n\n for (const { schema, tableName } of sorted) {\n const snapshotState = prevSnapshot.tables[tableName];\n if (!snapshotState) {\n // New table — emit CREATE TABLE\n const { up, down } = generateCreateTableSource(schema);\n upParts.push(up);\n downParts.push(down);\n } else {\n // Existing table — diff schema against snapshot (pure, no DB)\n const diff = diffSchema(schema, snapshotState);\n if (!isDiffEmpty(diff)) {\n const { up, down } = buildAlterTableFragments(diff, tableName);\n upParts.push(up);\n downParts.push(down);\n }\n }\n }\n\n // 5. Tables in snapshot but absent from current entities → DROP TABLE\n for (const tableName of Object.keys(prevSnapshot.tables)) {\n if (!currentTableNames.has(tableName)) {\n const state = prevSnapshot.tables[tableName];\n const { up, down } = generateDropTableSource(tableName, state);\n upParts.push(up);\n // Recreate before other downs so FK deps are satisfied\n downParts.unshift(down);\n }\n }\n\n const isEmpty = upParts.length === 0;\n\n // Down reverses creation order so child tables are dropped before parents\n const up = upParts.join('\\n\\n');\n const down = [...downParts].reverse().join('\\n\\n');\n\n const full = `import type { Knex } from 'knex';\n\nexport async function up(knex: Knex): Promise<void> {\n${isEmpty ? ' // No changes needed' : up}\n}\n\nexport async function down(knex: Knex): Promise<void> {\n${isEmpty ? ' // No changes needed' : down}\n}\n`;\n\n // Build the next snapshot from current entity schemas\n const nextTables: Record<string, DatabaseTableState> = {};\n for (const { schema, tableName } of sorted) {\n nextTables[tableName] = entitySchemaToTableState(schema);\n }\n const nextSnapshot: SchemaSnapshot = { version: 1, tables: nextTables };\n\n return { up, down, full, isEmpty, nextSnapshot };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * @internal\n * Emit `DROP TABLE` (up) and a best-effort `CREATE TABLE` reconstruction\n * (down) from a {@link DatabaseTableState} stored in the snapshot.\n * Called for tables that exist in the previous snapshot but are absent from\n * the current entity set.\n */\nfunction generateDropTableSource(\n tableName: string,\n state: DatabaseTableState\n): { up: string; down: string } {\n const up =\n ` // TODO: review destructive change — dropped table '${tableName}'\\n` +\n ` await knex.schema.dropTableIfExists(${JSON.stringify(tableName)});`;\n\n // Reconstruct CREATE TABLE from snapshot state using specificType for\n // all columns so the raw DB types are preserved faithfully.\n const colLines: string[] = [];\n for (const [colName, col] of Object.entries(state.columns)) {\n let line = ` table.specificType(${JSON.stringify(colName)}, ${JSON.stringify(col.type)})`;\n if (col.nullable) line += '.nullable()';\n else line += '.notNullable()';\n if (col.defaultValue !== null && col.defaultValue !== undefined) {\n line += `.defaultTo(${JSON.stringify(col.defaultValue)})`;\n }\n colLines.push(line + ';');\n }\n for (const fk of state.foreignKeys) {\n colLines.push(\n ` table.foreign(${JSON.stringify(fk.columnName)}).references(${JSON.stringify(fk.foreignColumn)}).inTable(${JSON.stringify(fk.foreignTable)}).onDelete(${JSON.stringify(fk.deleteRule)}).onUpdate(${JSON.stringify(fk.updateRule)});`\n );\n }\n for (const idx of state.indexes) {\n if (idx.unique) {\n colLines.push(\n ` table.unique(${JSON.stringify(idx.columns)}, { indexName: ${JSON.stringify(idx.name)} });`\n );\n } else {\n colLines.push(\n ` table.index(${JSON.stringify(idx.columns)}, ${JSON.stringify(idx.name)});`\n );\n }\n }\n\n const down =\n ` await knex.schema.createTable(${JSON.stringify(tableName)}, (table) => {\\n` +\n colLines.join('\\n') +\n '\\n });';\n\n return { up, down };\n}\n\n/**\n * @internal\n * Extract the body of a MigrationDiff into up/down Knex schema code strings\n * (indented 4 spaces, wrapped in `alterTable` when non-empty).\n * Used by both {@link generateMigration} and {@link generateMigrationsForContext}.\n */\nfunction buildAlterTableFragments(\n diff: MigrationDiff,\n tableName: string\n): { up: string; down: string } {\n const upLines: string[] = [];\n const downLines: string[] = [];\n\n // --- ADD COLUMNS ---\n for (const col of diff.addColumns) {\n const typeCall = col.type.includes(' ')\n ? `table.specificType('${col.name}', '${col.type}')`\n : `table.${mapTypeToKnex(col.type)}('${col.name}')`;\n\n let line = ` ${typeCall}`;\n if (col.nullable) line += '.nullable()';\n else line += '.notNullable()';\n if (col.defaultValue !== undefined) {\n line += `.defaultTo(${formatDefault(col.defaultValue)})`;\n }\n line += ';';\n\n upLines.push(line);\n downLines.push(` table.dropColumn('${col.name}');`);\n }\n\n // --- DROP COLUMNS ---\n for (const col of diff.dropColumns) {\n upLines.push(` table.dropColumn('${col}');`);\n downLines.push(\n ` // TODO: recreate column '${col}' with original definition`\n );\n }\n\n // --- ALTER COLUMNS ---\n for (const col of diff.alterColumns) {\n for (const [key, change] of Object.entries(col.changes)) {\n if (key === 'nullable') {\n if (change.to) {\n upLines.push(` table.setNullable('${col.name}');`);\n downLines.push(\n ` table.dropNullable('${col.name}');`\n );\n } else {\n upLines.push(` table.dropNullable('${col.name}');`);\n downLines.push(` table.setNullable('${col.name}');`);\n }\n } else if (key === 'defaultValue') {\n const toVal = change.to;\n const fromVal = change.from;\n if (toVal === null) {\n upLines.push(\n ` table.timestamp('${col.name}').alter(); // DROP DEFAULT`\n );\n downLines.push(\n ` table.timestamp('${col.name}').defaultTo(knex.fn.now()).alter();`\n );\n } else {\n upLines.push(\n ` table.timestamp('${col.name}').notNullable().defaultTo(knex.fn.now()).alter();`\n );\n downLines.push(\n fromVal === null\n ? ` table.timestamp('${col.name}').notNullable().alter();`\n : ` table.timestamp('${col.name}').notNullable().defaultTo(knex.fn.now()).alter();`\n );\n }\n }\n }\n }\n\n // --- ADD INDEXES ---\n for (const idx of diff.addIndexes) {\n const cols = JSON.stringify(idx.columns);\n if (idx.unique) {\n upLines.push(\n ` table.unique(${cols}${idx.name ? `, { indexName: '${idx.name}' }` : ''});`\n );\n downLines.push(\n ` table.dropUnique(${cols}${idx.name ? `, '${idx.name}'` : ''});`\n );\n } else {\n upLines.push(\n ` table.index(${cols}${idx.name ? `, '${idx.name}'` : ''});`\n );\n downLines.push(\n ` table.dropIndex([]${idx.name ? `, '${idx.name}'` : ''});`\n );\n }\n }\n\n // --- DROP INDEXES ---\n for (const idx of diff.dropIndexes) {\n upLines.push(` table.dropIndex([], '${idx}');`);\n downLines.push(\n ` // TODO: recreate index '${idx}' with original definition`\n );\n }\n\n // --- ADD FOREIGN KEYS ---\n for (const fk of diff.addForeignKeys) {\n let line = ` table.foreign('${fk.column}').references('${fk.foreignColumn}').inTable('${fk.foreignTable}')`;\n if (fk.onDelete) line += `.onDelete('${fk.onDelete}')`;\n if (fk.onUpdate) line += `.onUpdate('${fk.onUpdate}')`;\n line += ';';\n upLines.push(line);\n downLines.push(` table.dropForeign('${fk.column}');`);\n }\n\n // --- DROP FOREIGN KEYS ---\n for (const fk of diff.dropForeignKeys) {\n upLines.push(` // TODO: drop foreign key constraint '${fk}'`);\n }\n\n const isEmpty = upLines.length === 0;\n\n const up = isEmpty\n ? ` // No changes needed`\n : ` await knex.schema.alterTable('${tableName}', (table) => {\\n${upLines.join('\\n')}\\n });`;\n\n const down = isEmpty\n ? ` // No changes needed`\n : ` await knex.schema.alterTable('${tableName}', (table) => {\\n${downLines.join('\\n')}\\n });`;\n\n return { up, down };\n}\n\n/** @internal Build a Knex ColumnBuilder from a PostgreSQL data type string (runtime use). */\nfunction buildColumnFromDbType(\n table: Knex.CreateTableBuilder,\n name: string,\n dbType: string\n): Knex.ColumnBuilder {\n switch (dbType) {\n case 'integer':\n return table.integer(name);\n case 'character varying':\n return table.string(name);\n case 'text':\n return table.text(name);\n case 'boolean':\n return table.boolean(name);\n case 'timestamp without time zone':\n case 'timestamp':\n return table.timestamp(name);\n case 'double precision':\n case 'float':\n return table.float(name);\n case 'jsonb':\n case 'json':\n return table.specificType(name, 'jsonb');\n case 'uuid':\n return table.uuid(name);\n default:\n return table.specificType(name, dbType);\n }\n}\n\n/**\n * @internal\n * Topologically sort table entries by FK dependency so parent tables\n * come first in `up` (and last in `down`). Falls back to original order\n * for cycles or external references.\n */\nfunction topologicalSort(\n entries: {\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>;\n tableName: string;\n }[]\n): typeof entries {\n const tableSet = new Set(entries.map(e => e.tableName));\n const deps = new Map<string, Set<string>>();\n\n for (const { schema, tableName } of entries) {\n const depSet = new Set<string>();\n const properties: Record<string, any> =\n (schema.introspect() as any).properties ?? {};\n for (const [, propSchema] of Object.entries(properties)) {\n const ext =\n ((propSchema as any).introspect?.() as any)?.extensions ?? {};\n if (ext.references?.table && tableSet.has(ext.references.table)) {\n depSet.add(ext.references.table);\n }\n }\n deps.set(tableName, depSet);\n }\n\n // Kahn's algorithm\n const inDegree = new Map<string, number>();\n const graph = new Map<string, string[]>(); // dep -> tables that depend on it\n for (const { tableName } of entries) {\n inDegree.set(tableName, 0);\n graph.set(tableName, []);\n }\n for (const { tableName } of entries) {\n for (const dep of deps.get(tableName) ?? []) {\n graph.get(dep)!.push(tableName);\n inDegree.set(tableName, (inDegree.get(tableName) ?? 0) + 1);\n }\n }\n\n const queue: string[] = [];\n for (const [t, deg] of inDegree) {\n if (deg === 0) queue.push(t);\n }\n\n const sortedNames: string[] = [];\n while (queue.length > 0) {\n const t = queue.shift()!;\n sortedNames.push(t);\n for (const dependent of graph.get(t) ?? []) {\n const newDeg = inDegree.get(dependent)! - 1;\n inDegree.set(dependent, newDeg);\n if (newDeg === 0) queue.push(dependent);\n }\n }\n\n // Append any cycles / unresolved entries in their original relative order\n const sortedSet = new Set(sortedNames);\n const remaining = entries.filter(e => !sortedSet.has(e.tableName));\n const byName = new Map(entries.map(e => [e.tableName, e]));\n return [...sortedNames.map(t => byName.get(t)!), ...remaining];\n}\n\n/** @internal Map a PostgreSQL data type string to a Knex column method name. */\nfunction mapTypeToKnex(type: string): string {\n switch (type) {\n case 'integer':\n return 'integer';\n case 'character varying':\n return 'string';\n case 'text':\n return 'text';\n case 'boolean':\n return 'boolean';\n case 'timestamp without time zone':\n case 'timestamp':\n return 'timestamp';\n case 'double precision':\n case 'float':\n return 'float';\n case 'jsonb':\n case 'json':\n return 'jsonb';\n case 'uuid':\n return 'uuid';\n default:\n return `specificType('${type}')` as any;\n }\n}\n\n/** @internal Format a default value for migration code generation. */\nfunction formatDefault(value: any): string {\n if (value === 'now') return 'knex.fn.now()';\n if (typeof value === 'object' && value !== null && value.raw) {\n return `knex.raw('${value.raw.replace(/'/g, \"\\\\'\")}')`;\n }\n if (typeof value === 'string') return `'${value.replace(/'/g, \"\\\\'\")}'`;\n return String(value);\n}\n","// @cleverbrush/knex-schema — Raw query execution with schema result mapping\n\nimport type { InferType, ObjectSchemaBuilder } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { buildColumnMap } from './columns.js';\n\n/**\n * Execute a raw SQL query or Knex query builder and map the result rows\n * through the schema's column→property name mapping.\n *\n * This is the escape hatch for complex queries that can't be expressed with\n * the typed `SchemaQueryBuilder` API. The schema is used only for result\n * mapping — column names in the result are converted back to property names.\n * Extra columns (not in the schema) are passed through unchanged.\n *\n * @param knex - A configured Knex instance.\n * @param schema - The `ObjectSchemaBuilder` for result mapping.\n * @param queryOrSql - A raw SQL string or a `Knex.QueryBuilder`.\n * @param bindings - Optional bindings for parameterised SQL queries.\n * @returns Mapped result rows.\n *\n * @example\n * ```ts\n * // Raw SQL with schema result mapping\n * const results = await rawQuery(knex, PostSchema, `\n * SELECT p.*, COUNT(c.id) AS comment_count\n * FROM posts p\n * LEFT JOIN comments c ON c.post_id = p.id\n * GROUP BY p.id\n * ORDER BY comment_count DESC\n * LIMIT ?\n * `, [10]);\n *\n * // Knex query builder as the source\n * const subQuery = knex('posts').select('author_id', knex.raw('COUNT(*) as post_count')).groupBy('author_id');\n * const results = await rawQuery(knex, UserSchema, subQuery);\n * ```\n */\nexport async function rawQuery<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n>(\n knex: Knex,\n schema: TSchema,\n queryOrSql: string | Knex.QueryBuilder,\n bindings?: any[]\n): Promise<(InferType<TSchema> & Record<string, any>)[]> {\n let rows: any[];\n\n if (typeof queryOrSql === 'string') {\n const result = await knex.raw(queryOrSql, bindings ?? []);\n rows = result.rows ?? result;\n } else {\n rows = await queryOrSql;\n }\n\n if (!rows || !Array.isArray(rows)) return [];\n\n const { colToProp } = buildColumnMap(schema);\n\n return rows.map(row => {\n const mapped: Record<string, any> = {};\n for (const [key, value] of Object.entries(row)) {\n const propName = colToProp.get(key);\n mapped[propName ?? key] = value;\n }\n return mapped;\n }) as any;\n}\n","// @cleverbrush/knex-schema — SchemaQueryBuilder\n\nimport type { InferType } from '@cleverbrush/schema';\nimport {\n EXTRA_TYPE_BRAND,\n METHOD_LITERAL_BRAND,\n ObjectSchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport {\n buildColumnMap,\n getPrimaryKeyColumns,\n resolveColumnRef,\n resolvePropertyKey\n} from './columns.js';\nimport {\n getProjections,\n getTableName,\n getVariants,\n POLYMORPHIC_TYPE_BRAND\n} from './extension.js';\nimport { clearRow } from './mappers.js';\nimport type {\n ColumnRef,\n CursorPaginationResult,\n InsertType,\n JoinManySpec,\n JoinOneSpec,\n PaginationResult,\n RelationSpec,\n ResolvedVariantConfig,\n ResolvedVariantRelationSpec,\n SelectProjection,\n SelectSelector,\n ValidatedSpec,\n VariantWhereFilter,\n WithJoinedMany,\n WithJoinedOne\n} from './types.js';\nimport {\n validateJoinMany,\n validateJoinOne,\n validateUniqueFieldNames\n} from './validate.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extracts the scope names registered on a schema via `.scope(name, fn)`.\n * Returns `never` when no scopes are defined (making `.scoped()` uncallable).\n * Falls back to `string` for `any`-typed schemas to preserve loose behaviour.\n *\n * @internal\n */\ntype ScopesOf<S> = S extends {\n readonly [METHOD_LITERAL_BRAND]?: infer N;\n}\n ? Extract<N, string>\n : never;\n\n/**\n * Extracts the named projection map from a schema type.\n * Returns a `Record<name, readonly keys[]>` type where each key is a\n * registered projection name and the value is the tuple of property keys.\n * Returns `Record<never, never>` (no projections) when the schema has none,\n * making `.projected()` uncallable on undecorated schemas.\n *\n * @internal\n */\ntype ProjectionsOf<S> = S extends {\n readonly [EXTRA_TYPE_BRAND]?: infer P;\n}\n ? P extends Record<string, readonly string[]>\n ? P\n : Record<never, never>\n : Record<never, never>;\n\n/**\n * Extracts the string-key union for a specific projection name from a schema\n * type. This indirection is needed because TypeScript cannot directly index\n * `ProjectionsOf<S>[K]` with `number` inside a generic function signature.\n *\n * @internal\n */\ntype ProjectionKeysOf<\n S,\n K extends keyof ProjectionsOf<S> & string\n> = ProjectionsOf<S>[K] extends readonly (infer T extends string)[]\n ? T\n : string;\n\n// ---------------------------------------------------------------------------\n// Polymorphic result type — driven by POLYMORPHIC_TYPE_BRAND phantom type\n// ---------------------------------------------------------------------------\n\n/**\n * When a schema carries the `POLYMORPHIC_TYPE_BRAND` phantom type (set by\n * `.withVariants()`), extract the discriminated-union result type from it.\n * Otherwise fall back to `InferType<TLocalSchema>`.\n *\n * @internal\n */\ntype QueryResultType<TLocalSchema> = TLocalSchema extends {\n readonly [POLYMORPHIC_TYPE_BRAND]?: infer U;\n}\n ? NonNullable<U>\n : InferType<TLocalSchema>;\n\n// ---------------------------------------------------------------------------\n// OnConflictBuilder\n// ---------------------------------------------------------------------------\n\n/**\n * Intermediate builder returned by {@link SchemaQueryBuilder.onConflict}.\n * Call `.merge()` or `.ignore()` to complete the upsert/insert-ignore operation.\n *\n * @internal\n */\nexport class OnConflictBuilder<\n TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TResult\n> {\n readonly #knex: Knex;\n readonly #localSchema: TLocalSchema;\n readonly #conflictColumns: string[];\n\n /** @internal */\n constructor(\n knex: Knex,\n localSchema: TLocalSchema,\n _parent: SchemaQueryBuilder<TLocalSchema, TResult>,\n conflictColumns: string[]\n ) {\n this.#knex = knex;\n this.#localSchema = localSchema;\n this.#conflictColumns = conflictColumns;\n }\n\n /**\n * Insert and merge (update) conflicting rows.\n *\n * @param data - Row to insert.\n * @param updateData - Optional partial object of columns to update on\n * conflict. If omitted, all inserted columns are updated.\n * @returns The resulting row.\n */\n async merge(\n data: InsertType<TLocalSchema>,\n updateData?: Partial<InferType<TLocalSchema>>\n ): Promise<TResult> {\n return this.#execute(data, 'merge', updateData) as Promise<TResult>;\n }\n\n /**\n * Insert and silently ignore conflicts.\n *\n * @param data - Row to insert.\n * @returns The row if inserted, or `undefined` if the conflict was ignored.\n */\n async ignore(data: InsertType<TLocalSchema>): Promise<TResult | undefined> {\n return this.#execute(data, 'ignore');\n }\n\n async #execute(\n data: InsertType<TLocalSchema>,\n mode: 'merge' | 'ignore',\n updateData?: Partial<InferType<TLocalSchema>>\n ): Promise<TResult | undefined> {\n const tableName = getTableName(this.#localSchema);\n const timestamps: { createdAt: string; updatedAt: string } | null =\n (this.#localSchema as any).getExtension?.('timestamps') ?? null;\n\n const beforeHooks: Function[] =\n (this.#localSchema as any).getExtension?.('beforeInsert') ?? [];\n\n let processed = { ...(data as Record<string, any>) };\n for (const hook of beforeHooks) {\n processed = (await hook(processed)) ?? processed;\n }\n\n const { propToCol } = buildColumnMap(this.#localSchema as any);\n const mapped: Record<string, any> = {};\n for (const [key, val] of Object.entries(processed)) {\n mapped[propToCol.get(key) ?? key] = val;\n }\n if (timestamps) {\n mapped[timestamps.createdAt] = this.#knex.fn.now();\n mapped[timestamps.updatedAt] = this.#knex.fn.now();\n }\n\n let qb = this.#knex(tableName)\n .insert(mapped)\n .onConflict(this.#conflictColumns);\n\n if (mode === 'ignore') {\n qb = (qb as any).ignore();\n } else {\n let mergeObj: Record<string, any>;\n if (updateData) {\n mergeObj = {};\n for (const [key, val] of Object.entries(\n updateData as Record<string, any>\n )) {\n mergeObj[propToCol.get(key) ?? key] = val;\n }\n } else {\n mergeObj = { ...mapped };\n if (timestamps) {\n delete mergeObj[timestamps.createdAt];\n mergeObj[timestamps.updatedAt] = this.#knex.fn.now();\n }\n }\n qb = (qb as any).merge(mergeObj);\n }\n\n const rows = await (qb as any).returning('*');\n if (!rows || rows.length === 0) return undefined;\n\n const { colToProp } = buildColumnMap(this.#localSchema as any);\n const result: Record<string, any> = {};\n for (const [col, val] of Object.entries(rows[0])) {\n result[colToProp.get(col) ?? col] = val;\n }\n return result as TResult;\n }\n}\n\n// ---------------------------------------------------------------------------\n// SchemaQueryBuilder\n// ---------------------------------------------------------------------------\n\n/**\n * Type-safe, schema-driven query builder for Knex.\n *\n * `SchemaQueryBuilder` wraps a Knex.QueryBuilder and adds:\n * - **Type-safe column references** — pass a property accessor (`t => t.name`)\n * or a string property name; both are resolved to the correct SQL column\n * through the schema's `hasColumnName()` metadata automatically.\n * - **Eager loading without N+1** — {@link joinOne} and {@link joinMany} use\n * PostgreSQL CTEs and `jsonb_agg` to load related rows in a single query.\n * - **Bidirectional result mapping** — rows returned from Postgres (column\n * names) are converted back to schema property names before being returned.\n * - **Thenable protocol** — the builder itself is `await`-able so you can\n * write `await query(db, Schema)` without calling {@link execute} explicitly.\n *\n * Create instances via the {@link query} factory function rather than\n * calling the constructor directly.\n *\n * @typeParam TLocalSchema - The `ObjectSchemaBuilder` describing the main table.\n * @typeParam TResult - The inferred row type, widened automatically as joins\n * are registered via {@link joinOne} / {@link joinMany}.\n *\n * @example\n * ```ts\n * import knex from 'knex';\n * import { query, object, string, number } from '@cleverbrush/knex-schema';\n *\n * const UserSchema = object({\n * id: number(),\n * name: string(),\n * age: number().optional(),\n * }).hasTableName('users');\n *\n * const db = knex({ client: 'pg', connection: process.env.DB_URL });\n *\n * // Fetch all users older than 18, ordered by name\n * const adults = await query(db, UserSchema)\n * .where(t => t.age, '>', 18)\n * .orderBy(t => t.name);\n * // adults: Array<{ id: number; name: string; age?: number }>\n * ```\n */\nexport class SchemaQueryBuilder<\n TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TResult\n> {\n readonly #knex: Knex;\n readonly #baseQuery: Knex.QueryBuilder;\n readonly #localSchema: TLocalSchema;\n readonly #specs: ValidatedSpec[] = [];\n readonly #tableName: string;\n /**\n * Tracks the SQL column names that were explicitly passed to `.select()`.\n * `null` means no explicit select was made (SELECT *).\n */\n #explicitSelects: string[] | null = null;\n\n /**\n * Tracks which column-selection mode is active on this builder.\n * - `null` — no explicit SELECT issued yet (SELECT *).\n * - `'select'` — `.select()` / `.distinct()` was called.\n * - `'aggregate'` — `.count()` / `.countDistinct()` / `.min()` / etc.\n * - `'projection'` — `.projected()` was called.\n *\n * Only one mode is allowed per query. Calling a method that would switch\n * to a different mode throws an error.\n */\n #selectionMode: 'select' | 'aggregate' | 'projection' | null = null;\n /** Name of the projection currently applied, for use in error messages. */\n #appliedProjection: string | null = null;\n\n /** When true, soft-delete filter is not applied to SELECT queries. */\n #includeDeleted = false;\n /** When true, only soft-deleted rows are returned. */\n #onlyDeleted = false;\n /** When true, default scope is not applied. */\n #skipDefaultScope = false;\n\n // -----------------------------------------------------------------------\n // Polymorphic variant state\n // -----------------------------------------------------------------------\n\n /**\n * Resolved variant config, lazily populated from the schema's `'variants'`\n * extension. `undefined` = not yet read; `null` = schema is not polymorphic.\n */\n #variantConfig: ResolvedVariantConfig | null | undefined = undefined;\n\n /**\n * When set, only these discriminator values are returned (added to WHERE).\n * `null` means all variants are included.\n */\n #enabledVariants: Set<string> | null = null;\n\n /** Pending per-variant WHERE filters registered via `.whereVariant()`. */\n #variantWhereFilters: VariantWhereFilter[] = [];\n\n /**\n * Variant-relation eager-load requests registered via `.includeVariant()`.\n * Each entry names the variant key and the relation name to load.\n * Processed inside `#applyVariantJoins()`.\n */\n #variantRelationIncludes: Array<{\n variantKey: string;\n relationName: string;\n customize?: (q: SchemaQueryBuilder<any, any>) => void;\n }> = [];\n\n /**\n * Memoized result of `#buildQuery()`. Invalidated by any mutating method\n * (where, orderBy, limit, etc.) and re-built lazily on the next read.\n */\n #cachedBuiltQuery: Knex.QueryBuilder | null = null;\n\n /** Invalidate the compiled-query cache. Called by every mutating method. */\n #invalidateCache(): void {\n this.#cachedBuiltQuery = null;\n }\n\n /** Return the built query, building it once and caching the result. */\n #getQuery(): Knex.QueryBuilder {\n if (!this.#cachedBuiltQuery) {\n this.#cachedBuiltQuery = this.#buildQuery();\n }\n return this.#cachedBuiltQuery;\n }\n\n /**\n * @param knex - A configured Knex instance.\n * @param localSchema - The `ObjectSchemaBuilder` for the primary table.\n * Must have a table name set via `.hasTableName()`.\n * @param baseQuery - Optional pre-configured `Knex.QueryBuilder` to use as\n * the base query instead of the default `knex(tableName)`. Useful when you\n * need custom joins, CTEs, or other Knex features not exposed by this API.\n */\n constructor(\n knex: Knex,\n localSchema: TLocalSchema,\n baseQuery?: Knex.QueryBuilder\n ) {\n this.#knex = knex;\n this.#localSchema = localSchema;\n this.#tableName = getTableName(localSchema);\n this.#baseQuery = baseQuery ?? knex(this.#tableName);\n }\n\n // =======================================================================\n // Private helpers\n // =======================================================================\n\n #resolveColumn(\n ref: any,\n label = 'column'\n ): string | import('knex').Knex.Raw {\n return resolveColumnRef(\n ref as ColumnRef<any>,\n this.#localSchema,\n label,\n this.#knex\n );\n }\n\n /** @internal Read soft-delete extension from schema. */\n #getSoftDelete(): { column: string } | null {\n const ext = (this.#localSchema as any).getExtension?.('softDelete');\n return ext ?? null;\n }\n\n /** @internal Read default scope function from schema. */\n #getDefaultScope(): Function | null {\n const fn = (this.#localSchema as any).getExtension?.('defaultScope');\n return typeof fn === 'function' ? fn : null;\n }\n\n /** @internal Read timestamps config from schema. */\n #getTimestamps(): { createdAt: string; updatedAt: string } | null {\n const ts = (this.#localSchema as any).getExtension?.('timestamps');\n return ts ?? null;\n }\n\n // -----------------------------------------------------------------------\n // Polymorphic helpers\n // -----------------------------------------------------------------------\n\n /**\n * Read and cache the variant config from the schema. Returns `null` when\n * the schema is not polymorphic.\n * @internal\n */\n #getVariantConfig(): ResolvedVariantConfig | null {\n if (this.#variantConfig !== undefined) return this.#variantConfig;\n\n const raw = getVariants(this.#localSchema);\n if (!raw) {\n this.#variantConfig = null;\n return null;\n }\n\n // Resolve discriminator property key → SQL column name\n const { propToCol } = buildColumnMap(this.#localSchema);\n const discCol =\n propToCol.get(raw.discriminatorKey) ?? raw.discriminatorKey;\n\n this.#variantConfig = {\n ...raw,\n discriminatorColumn: discCol\n };\n return this.#variantConfig;\n }\n\n /**\n * Validate allowed SQL operators for `whereVariant`.\n * Guards against SQL injection via the `op` parameter.\n * @internal\n */\n static #ALLOWED_OPS = new Set([\n '=',\n '!=',\n '<>',\n '<',\n '>',\n '<=',\n '>=',\n 'like',\n 'not like',\n 'ilike',\n 'not ilike',\n 'in',\n 'not in',\n 'is',\n 'is not'\n ]);\n\n /**\n * Apply variant LEFT JOINs and aliased column selects to a base query,\n * then add any `whereVariant` / `selectVariants` filters.\n *\n * For CTI variants:\n * - `LEFT JOIN variantTable AS __v_<key> ON __v_<key>.<fk> = base.<pk> AND base.<disc> = '<key>'`\n * - `SELECT __v_<key>.<col> AS __v_<key>__<col>` for every column (incl. FK for orphan detection)\n *\n * For STI variants:\n * - No extra JOIN needed; columns are already in the base row.\n *\n * @internal\n */\n #applyVariantJoins(\n base: Knex.QueryBuilder,\n variantConfig: ResolvedVariantConfig\n ): Knex.QueryBuilder {\n const knex = this.#knex;\n const baseTable = this.#tableName;\n const basePkCol = this.#findPrimaryKeyColumn(this.#localSchema);\n const discCol = variantConfig.discriminatorColumn;\n\n // Clone base and ensure we SELECT base.* so variant aliases don't\n // collide with the base column list when the caller used SELECT *.\n const qb = base.clone().select(`${baseTable}.*`);\n\n for (const [key, spec] of Object.entries(variantConfig.variants)) {\n // Skip disabled variants when selectVariants() was called\n if (\n this.#enabledVariants !== null &&\n !this.#enabledVariants.has(key)\n )\n continue;\n\n if (spec.storage === 'cti') {\n const variantAlias = `__v_${key}`;\n const variantTable = spec.tableName!;\n const fkCol = spec.foreignKey!;\n\n // LEFT JOIN with discriminator gate so we only pick up rows\n // for the matching variant.\n qb.leftJoin(\n `${variantTable} as ${variantAlias}`,\n knex.raw(`?? = ?? AND ?? = ?`, [\n `${variantAlias}.${fkCol}`,\n `${baseTable}.${basePkCol}`,\n `${baseTable}.${discCol}`,\n key\n ])\n );\n\n // SELECT each variant column with a namespaced alias\n const { propToCol } = buildColumnMap(spec.schema);\n const variantIntrospect = spec.schema.introspect() as any;\n const variantProps: Record<string, unknown> =\n variantIntrospect.properties ?? {};\n\n for (const propKey of Object.keys(variantProps)) {\n const colName = propToCol.get(propKey) ?? propKey;\n // Alias: __v_image.width AS __v_image__width\n qb.select(\n knex.raw('?? as ??', [\n `${variantAlias}.${colName}`,\n `${variantAlias}__${colName}`\n ])\n );\n }\n }\n // STI: no extra JOIN — variant columns are already in the base row\n }\n\n // Apply variant-relation eager-load JOINs (registered via .includeVariant())\n for (const vrInc of this.#variantRelationIncludes) {\n const variantSpec = variantConfig.variants[vrInc.variantKey];\n if (!variantSpec) continue;\n\n const relSpec = variantSpec.relations.find(\n (r: ResolvedVariantRelationSpec) =>\n r.name === vrInc.relationName\n );\n if (!relSpec) continue;\n\n const foreignSchema = this.#resolveSchema(relSpec.schema);\n const foreignTableName = getTableName(foreignSchema);\n const relAlias = `__v_${vrInc.variantKey}__rel_${vrInc.relationName}`;\n\n if (relSpec.type === 'belongsTo' || relSpec.type === 'hasOne') {\n // Determine join condition columns\n let localCol: string;\n let foreignCol: string;\n\n if (relSpec.type === 'belongsTo') {\n // FK is on the variant table (or base table for STI)\n localCol =\n relSpec.foreignKey ??\n ((): string => {\n throw new Error(\n `includeVariant: relation \"${vrInc.relationName}\" on variant \"${vrInc.variantKey}\" requires foreignKey`\n );\n })();\n foreignCol = this.#findPrimaryKeyColumn(foreignSchema);\n } else {\n // hasOne: FK is on the foreign table\n localCol = this.#findPrimaryKeyColumn(this.#localSchema);\n foreignCol =\n relSpec.foreignKey ??\n ((): string => {\n throw new Error(\n `includeVariant: relation \"${vrInc.relationName}\" on variant \"${vrInc.variantKey}\" requires foreignKey`\n );\n })();\n }\n\n // Build the join ON condition, gated by the discriminator\n let onExpr: string;\n const variantAlias = `__v_${vrInc.variantKey}`;\n\n if (variantSpec.storage === 'cti') {\n if (relSpec.type === 'belongsTo') {\n // FK lives on the CTI variant alias table\n onExpr = `${relAlias}.${foreignCol} = ${variantAlias}.${localCol} AND ${baseTable}.${discCol} = '${vrInc.variantKey}'`;\n } else {\n // hasOne: FK on foreign table, local col is base PK\n onExpr = `${relAlias}.${foreignCol} = ${baseTable}.${localCol} AND ${baseTable}.${discCol} = '${vrInc.variantKey}'`;\n }\n } else {\n // STI: all columns are in the base table\n if (relSpec.type === 'belongsTo') {\n onExpr = `${relAlias}.${foreignCol} = ${baseTable}.${localCol} AND ${baseTable}.${discCol} = '${vrInc.variantKey}'`;\n } else {\n onExpr = `${relAlias}.${foreignCol} = ${baseTable}.${localCol} AND ${baseTable}.${discCol} = '${vrInc.variantKey}'`;\n }\n }\n\n // Build the foreign query (applying customize if provided)\n const foreignKnex: Knex.QueryBuilder =\n this.#knex(foreignTableName);\n\n // Determine which columns to select from the foreign table.\n // Run customize on a probe proxy to capture projection/explicit-select state.\n const selectionSql = this.#buildVariantRelationSelect(\n foreignSchema,\n relAlias,\n foreignTableName,\n vrInc.customize\n );\n\n qb.leftJoin(\n knex.raw(`?? as ??`, [foreignTableName, relAlias]),\n knex.raw(onExpr)\n );\n void foreignKnex; // probe was used only for column determination\n\n for (const sel of selectionSql) {\n qb.select(sel);\n }\n }\n // NOTE: hasMany / belongsToMany on variants are not yet supported\n // via inline JOINs (they would multiply rows). Future: secondary query.\n }\n\n // Apply per-variant WHERE filters (added via .whereVariant())\n for (const filter of this.#variantWhereFilters) {\n const discColFull = `${baseTable}.${discCol}`;\n // (base.disc = 'key' AND variant_col op value) OR base.disc != 'key'\n // → restricts matching rows, passes through non-matching variants\n qb.where(function (this: Knex.QueryBuilder) {\n this.where(discColFull, filter.key)\n .andWhere(filter.qualifiedColumn, filter.op, filter.value)\n .orWhere(discColFull, '!=', filter.key);\n });\n }\n\n // Apply selectVariants restriction\n if (this.#enabledVariants !== null) {\n qb.whereIn(`${baseTable}.${discCol}`, [...this.#enabledVariants]);\n }\n\n return qb;\n }\n\n /**\n * Build the list of `knex.raw(\"?? as ??\", ...)` select expressions that\n * project a variant-relation alias table's columns into the namespaced\n * prefix `__v_<key>__rel_<name>__<col>`.\n *\n * When `customize` applies a projection, only the projected columns are\n * selected. Otherwise every column in the foreign schema is selected.\n *\n * @internal\n */\n #buildVariantRelationSelect(\n foreignSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n relAlias: string,\n foreignTableName: string,\n customize?: (q: SchemaQueryBuilder<any, any>) => void\n ): Knex.Raw[] {\n const knex = this.#knex;\n const { propToCol } = buildColumnMap(foreignSchema);\n const foreignIntrospect = foreignSchema.introspect() as any;\n const foreignProps: Record<string, unknown> =\n foreignIntrospect.properties ?? {};\n\n // Determine which property keys to include.\n // Run customize on a probe proxy to capture #explicitSelects state.\n let columnsToSelect: string[];\n\n if (customize) {\n const probe = new SchemaQueryBuilder(\n this.#knex,\n foreignSchema,\n this.#knex(foreignTableName)\n );\n customize(probe);\n const explicit = probe.#explicitSelects;\n if (explicit && explicit.length > 0) {\n columnsToSelect = explicit;\n } else {\n columnsToSelect = Object.keys(foreignProps).map(\n p => propToCol.get(p) ?? p\n );\n }\n } else {\n columnsToSelect = Object.keys(foreignProps).map(\n p => propToCol.get(p) ?? p\n );\n }\n\n return columnsToSelect.map(colName =>\n knex.raw('?? as ??', [\n `${relAlias}.${colName}`,\n `${relAlias}__${colName}`\n ])\n );\n }\n\n /**\n * Map a raw SQL row from a polymorphic query to a schema-property-named\n * object for the active variant.\n *\n * - Base columns are mapped via the base schema's `colToProp` map.\n * - CTI variant columns (aliased as `__v_<key>__<col>`) are mapped via\n * the variant schema's `colToProp` map for the matching discriminator value.\n * - STI variant columns are already in the base row; they are mapped via\n * the variant schema's `colToProp` map.\n * - The CTI FK column alias (`__v_<key>__<fkCol>`) is used only for orphan\n * detection and is NOT included in the result.\n *\n * @internal\n */\n #mapPolymorphicRow(\n row: Record<string, any>,\n variantConfig: ResolvedVariantConfig\n ): Record<string, any> {\n const { colToProp: baseColToProp } = buildColumnMap(this.#localSchema);\n const result: Record<string, any> = {};\n\n // Pass 1: map base columns (skip __v_* aliases)\n for (const [colName, value] of Object.entries(row)) {\n if (colName.startsWith('__v_')) continue;\n const propName = baseColToProp.get(colName);\n if (propName) {\n result[propName] = value;\n } else {\n // Unknown column (raw expression, joined field) — pass through\n result[colName] = value;\n }\n }\n\n // Pass 2: map variant columns for the active discriminator value\n const discPropKey = variantConfig.discriminatorKey;\n const discValue: string | undefined = result[discPropKey];\n\n if (discValue != null) {\n const variantSpec = variantConfig.variants[discValue];\n if (variantSpec) {\n if (variantSpec.storage === 'cti') {\n const { colToProp: varColToProp } = buildColumnMap(\n variantSpec.schema\n );\n const variantAlias = `__v_${discValue}`;\n const prefix = `${variantAlias}__`;\n const fkCol = variantSpec.foreignKey;\n\n // Check for orphaned discriminator (FK alias is NULL)\n if (fkCol) {\n const fkAlias = `${prefix}${fkCol}`;\n if (!variantSpec.allowOrphan && row[fkAlias] == null) {\n throw new Error(\n `Polymorphic orphan: \"${discPropKey}\" = \"${discValue}\" ` +\n `but no matching row found in variant table ` +\n `\"${variantSpec.tableName}\". ` +\n `Set allowOrphan: true on this variant to suppress.`\n );\n }\n }\n\n for (const [colName, value] of Object.entries(row)) {\n if (!colName.startsWith(prefix)) continue;\n const origCol = colName.slice(prefix.length);\n // Skip FK column — it duplicates the base PK\n if (origCol === fkCol) continue;\n const propName = varColToProp.get(origCol) ?? origCol;\n result[propName] = value;\n }\n } else {\n // STI: variant columns are in the base row (no prefix)\n const { colToProp: varColToProp } = buildColumnMap(\n variantSpec.schema\n );\n for (const [colName, value] of Object.entries(row)) {\n if (colName.startsWith('__v_')) continue;\n if (baseColToProp.has(colName)) continue; // already mapped\n const propName = varColToProp.get(colName);\n if (propName) {\n result[propName] = value;\n }\n }\n }\n }\n }\n\n // Pass 3: extract variant-relation nested objects\n if (this.#variantRelationIncludes.length > 0 && discValue != null) {\n const variantSpec3 = variantConfig.variants[discValue];\n if (variantSpec3) {\n for (const vrInc of this.#variantRelationIncludes) {\n if (vrInc.variantKey !== discValue) continue;\n\n const relSpec = variantSpec3.relations.find(\n (r: ResolvedVariantRelationSpec) =>\n r.name === vrInc.relationName\n );\n if (!relSpec) continue;\n\n if (\n relSpec.type === 'belongsTo' ||\n relSpec.type === 'hasOne'\n ) {\n const relAlias = `__v_${discValue}__rel_${vrInc.relationName}`;\n const prefix = `${relAlias}__`;\n const foreignSchema = this.#resolveSchema(\n relSpec.schema\n );\n const { colToProp: relColToProp } =\n buildColumnMap(foreignSchema);\n const nested: Record<string, unknown> = {};\n let anyNonNull = false;\n\n for (const [colName, value] of Object.entries(row)) {\n if (!colName.startsWith(prefix)) continue;\n const origCol = colName.slice(prefix.length);\n const propName =\n relColToProp.get(origCol) ?? origCol;\n nested[propName] = value;\n if (value !== null && value !== undefined) {\n anyNonNull = true;\n }\n }\n result[vrInc.relationName] = anyNonNull ? nested : null;\n }\n }\n }\n }\n\n return result;\n }\n\n /**\n * Build the effective base query with soft-delete and default-scope\n * filters applied lazily. Does NOT include CTE wrapping.\n */\n #getEffectiveBaseQuery(): Knex.QueryBuilder {\n let effectiveBase = this.#baseQuery;\n let cloned = false;\n\n // Apply soft delete filter\n const softDelete = this.#getSoftDelete();\n if (softDelete && this.#onlyDeleted) {\n if (!cloned) {\n effectiveBase = effectiveBase.clone();\n cloned = true;\n }\n effectiveBase.whereNotNull(softDelete.column);\n } else if (softDelete && !this.#includeDeleted) {\n if (!cloned) {\n effectiveBase = effectiveBase.clone();\n cloned = true;\n }\n effectiveBase.whereNull(softDelete.column);\n }\n\n // Apply default scope\n if (!this.#skipDefaultScope) {\n const defaultScopeFn = this.#getDefaultScope();\n if (defaultScopeFn) {\n if (!cloned) {\n effectiveBase = effectiveBase.clone();\n cloned = true;\n }\n const proxy = new SchemaQueryBuilder(\n this.#knex,\n this.#localSchema,\n effectiveBase\n );\n proxy.#skipDefaultScope = true;\n defaultScopeFn(proxy);\n }\n }\n\n return effectiveBase;\n }\n\n /** @internal Resolve a lazy schema reference `schema | () => schema`. */\n #resolveSchema(\n schema: any\n ): ObjectSchemaBuilder<any, any, any, any, any, any, any> {\n return typeof schema === 'function' ? schema() : schema;\n }\n\n /** @internal Find the primary key column name from schema extensions. */\n #findPrimaryKeyColumn(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n ): string {\n const pk = getPrimaryKeyColumns(schema);\n if (pk.columnNames.length > 0) return pk.columnNames[0];\n return 'id';\n }\n\n // =======================================================================\n // Relation methods — eager loading (absorbed from knex-eager)\n // =======================================================================\n\n /**\n * Eager-load a single related row (one-to-one / many-to-one relationship).\n *\n * The related rows are fetched using a single CTE + `jsonb_agg` — no N+1\n * queries. The related object is attached to each result row under the\n * field name specified by `spec.as`.\n *\n * @param spec - Join specification. Key fields:\n * - `foreignSchema` — the `ObjectSchemaBuilder` of the related table.\n * - `localColumn` — the local column that holds the foreign-table reference.\n * - `foreignColumn` — the primary/unique key on the foreign table.\n * - `as` — the property name to attach the related object under.\n * - `required` — if `true` (default), rows without a matching related\n * record are excluded (inner join); if `false`, they are included with\n * `null` (left join).\n * - `foreignQuery` — optional pre-filtered `Knex.QueryBuilder` for the\n * foreign table (e.g. to apply scopes).\n *\n * @returns `this` (with an updated `TResult` type that includes the new field)\n * for chaining.\n *\n * @example\n * ```ts\n * const PostSchema = object({\n * id: number(),\n * title: string(),\n * authorId: number(),\n * }).hasTableName('posts');\n *\n * const AuthorSchema = object({\n * id: number(),\n * name: string(),\n * }).hasTableName('authors');\n *\n * const posts = await query(db, PostSchema)\n * .joinOne({\n * foreignSchema: AuthorSchema,\n * localColumn: t => t.authorId,\n * foreignColumn: t => t.id,\n * as: 'author',\n * });\n * // posts[0].author.name — typed as string ✓\n * ```\n */\n joinOne<\n TForeignSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >,\n TFieldName extends string,\n TRequired extends boolean = true\n >(\n spec: JoinOneSpec<TLocalSchema, TForeignSchema, TFieldName, TRequired>\n ): SchemaQueryBuilder<\n TLocalSchema,\n WithJoinedOne<TResult, TFieldName, TForeignSchema, TRequired>\n > {\n const validated = validateJoinOne(spec, this.#localSchema, this.#knex);\n this.#specs.push({ type: 'one' as const, ...validated });\n validateUniqueFieldNames(this.#specs);\n this.#invalidateCache();\n return this as any;\n }\n\n /**\n * Eager-load a collection of related rows (one-to-many relationship).\n *\n * Related rows are fetched via a single CTE + `jsonb_agg` query. The\n * collection is attached to each result row under the field name specified\n * by `spec.as`. Supports `limit`, `offset`, and `orderBy` per-parent\n * using a `row_number()` window function to avoid fetching the full\n * relation before slicing.\n *\n * @param spec - Join specification. Key fields:\n * - `foreignSchema` — the `ObjectSchemaBuilder` of the related table.\n * - `localColumn` — the primary/unique key on the local table.\n * - `foreignColumn` — the column on the foreign table that references `localColumn`.\n * - `as` — the property name to attach the array under.\n * - `limit` / `offset` — optional pagination per parent row.\n * - `orderBy` — optional `{ column, direction }` for the sub-collection.\n * - `foreignQuery` — optional pre-filtered `Knex.QueryBuilder`.\n *\n * @returns `this` (with an updated `TResult` type that includes the new field)\n * for chaining.\n *\n * @example\n * ```ts\n * const UserSchema = object({\n * id: number(),\n * name: string(),\n * }).hasTableName('users');\n *\n * const PostSchema = object({\n * id: number(),\n * title: string(),\n * authorId: number(),\n * }).hasTableName('posts');\n *\n * const users = await query(db, UserSchema)\n * .joinMany({\n * foreignSchema: PostSchema,\n * localColumn: t => t.id,\n * foreignColumn: t => t.authorId,\n * as: 'posts',\n * limit: 5,\n * orderBy: { column: t => t.id, direction: 'desc' },\n * });\n * // users[0].posts — typed as Array<{ id: number; title: string; authorId: number }>\n * ```\n */\n joinMany<\n TForeignSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >,\n TFieldName extends string\n >(\n spec: JoinManySpec<TLocalSchema, TForeignSchema, TFieldName>\n ): SchemaQueryBuilder<\n TLocalSchema,\n WithJoinedMany<TResult, TFieldName, TForeignSchema>\n > {\n const validated = validateJoinMany(spec, this.#localSchema, this.#knex);\n this.#specs.push({ type: 'many' as const, ...validated });\n validateUniqueFieldNames(this.#specs);\n this.#invalidateCache();\n return this as any;\n }\n\n // =======================================================================\n // WHERE methods\n // =======================================================================\n\n /**\n * Add a `WHERE` clause to the query.\n *\n * Accepts a column reference, an optional operator, and a value:\n * - `where(t => t.age, '>', 18)` — property accessor + operator + value.\n * - `where('age', 18)` — string key + value (defaults to `=`).\n * - `where({ name: 'Alice' })` — record object; property keys are mapped\n * to column names automatically.\n * - `where(builder => { ... })` — Knex sub-builder callback for grouped\n * conditions.\n * - `where(knex.raw('...'))` — raw SQL expression.\n *\n * Multiple `.where()` calls are combined with `AND`.\n *\n * @returns `this` for chaining.\n */\n where(column: ColumnRef<TLocalSchema>, operator: string, value: any): this;\n where(column: ColumnRef<TLocalSchema>, value: any): this;\n where(raw: Knex.Raw, operator: string, value: any): this;\n where(callback: (builder: Knex.QueryBuilder) => void): this;\n where(record: Record<string, any>): this;\n where(raw: Knex.Raw): this;\n where(\n columnOrRaw:\n | ColumnRef<TLocalSchema>\n | Knex.Raw\n | Record<string, any>\n | ((builder: Knex.QueryBuilder) => void),\n ...args: any[]\n ): this {\n this.#invalidateCache();\n if (\n typeof columnOrRaw === 'function' &&\n !this.#isColumnAccessor(columnOrRaw)\n ) {\n (this.#baseQuery.where as any)(columnOrRaw, ...args);\n } else if (\n typeof columnOrRaw === 'object' &&\n columnOrRaw !== null &&\n !('toSQL' in columnOrRaw)\n ) {\n // Record<string, any> — map property keys to column names\n const mapped = this.#mapRecordToColumns(\n columnOrRaw as Record<string, any>\n );\n (this.#baseQuery.where as any)(mapped, ...args);\n } else {\n const col = this.#resolveColumnArg(columnOrRaw);\n (this.#baseQuery.where as any)(col, ...args);\n }\n return this;\n }\n\n /**\n * Alias for {@link where} — explicitly adds an `AND WHERE` clause.\n * Identical to calling `.where()` when no logical-OR grouping is needed.\n * @returns `this` for chaining.\n */\n andWhere(\n column: ColumnRef<TLocalSchema>,\n operator: string,\n value: any\n ): this;\n andWhere(column: ColumnRef<TLocalSchema>, value: any): this;\n andWhere(record: Record<string, any>): this;\n andWhere(callback: (builder: Knex.QueryBuilder) => void): this;\n andWhere(raw: Knex.Raw): this;\n andWhere(\n columnOrRaw:\n | ColumnRef<TLocalSchema>\n | Knex.Raw\n | Record<string, any>\n | ((builder: Knex.QueryBuilder) => void),\n ...args: any[]\n ): this {\n this.#invalidateCache();\n if (\n typeof columnOrRaw === 'function' &&\n !this.#isColumnAccessor(columnOrRaw)\n ) {\n (this.#baseQuery.andWhere as any)(columnOrRaw, ...args);\n } else if (\n typeof columnOrRaw === 'object' &&\n columnOrRaw !== null &&\n !('toSQL' in columnOrRaw)\n ) {\n const mapped = this.#mapRecordToColumns(\n columnOrRaw as Record<string, any>\n );\n (this.#baseQuery.andWhere as any)(mapped, ...args);\n } else {\n const col = this.#resolveColumnArg(columnOrRaw);\n (this.#baseQuery.andWhere as any)(col, ...args);\n }\n return this;\n }\n\n /**\n * Add an `OR WHERE` clause. Use this to create alternative filter branches.\n * @returns `this` for chaining.\n */\n orWhere(\n column: ColumnRef<TLocalSchema>,\n operator: string,\n value: any\n ): this;\n orWhere(column: ColumnRef<TLocalSchema>, value: any): this;\n orWhere(record: Record<string, any>): this;\n orWhere(callback: (builder: Knex.QueryBuilder) => void): this;\n orWhere(raw: Knex.Raw): this;\n orWhere(\n columnOrRaw:\n | ColumnRef<TLocalSchema>\n | Knex.Raw\n | Record<string, any>\n | ((builder: Knex.QueryBuilder) => void),\n ...args: any[]\n ): this {\n this.#invalidateCache();\n if (\n typeof columnOrRaw === 'function' &&\n !this.#isColumnAccessor(columnOrRaw)\n ) {\n (this.#baseQuery.orWhere as any)(columnOrRaw, ...args);\n } else if (\n typeof columnOrRaw === 'object' &&\n columnOrRaw !== null &&\n !('toSQL' in columnOrRaw)\n ) {\n const mapped = this.#mapRecordToColumns(\n columnOrRaw as Record<string, any>\n );\n (this.#baseQuery.orWhere as any)(mapped, ...args);\n } else {\n const col = this.#resolveColumnArg(columnOrRaw);\n (this.#baseQuery.orWhere as any)(col, ...args);\n }\n return this;\n }\n\n /**\n * Add a `WHERE NOT` clause — negates the condition.\n * @returns `this` for chaining.\n */\n whereNot(\n column: ColumnRef<TLocalSchema>,\n operator: string,\n value: any\n ): this;\n whereNot(column: ColumnRef<TLocalSchema>, value: any): this;\n whereNot(record: Record<string, any>): this;\n whereNot(callback: (builder: Knex.QueryBuilder) => void): this;\n whereNot(raw: Knex.Raw): this;\n whereNot(\n columnOrRaw:\n | ColumnRef<TLocalSchema>\n | Knex.Raw\n | Record<string, any>\n | ((builder: Knex.QueryBuilder) => void),\n ...args: any[]\n ): this {\n this.#invalidateCache();\n if (\n typeof columnOrRaw === 'function' &&\n !this.#isColumnAccessor(columnOrRaw)\n ) {\n (this.#baseQuery.whereNot as any)(columnOrRaw, ...args);\n } else if (\n typeof columnOrRaw === 'object' &&\n columnOrRaw !== null &&\n !('toSQL' in columnOrRaw)\n ) {\n const mapped = this.#mapRecordToColumns(\n columnOrRaw as Record<string, any>\n );\n (this.#baseQuery.whereNot as any)(mapped, ...args);\n } else {\n const col = this.#resolveColumnArg(columnOrRaw);\n (this.#baseQuery.whereNot as any)(col, ...args);\n }\n return this;\n }\n\n /**\n * Add a `WHERE column IN (values)` clause.\n * @param column - Column reference (property accessor or string key).\n * @param values - Array of values or a sub-query.\n * @returns `this` for chaining.\n */\n whereIn(\n column: ColumnRef<TLocalSchema>,\n values: readonly any[] | Knex.QueryBuilder\n ): this {\n this.#invalidateCache();\n this.#baseQuery.whereIn(\n this.#resolveColumn(column, 'whereIn') as any,\n values as any\n );\n return this;\n }\n\n /**\n * Add a `WHERE column NOT IN (values)` clause.\n * @param column - Column reference.\n * @param values - Array of values or a sub-query.\n * @returns `this` for chaining.\n */\n whereNotIn(\n column: ColumnRef<TLocalSchema>,\n values: readonly any[] | Knex.QueryBuilder\n ): this {\n this.#invalidateCache();\n this.#baseQuery.whereNotIn(\n this.#resolveColumn(column, 'whereNotIn') as any,\n values as any\n );\n return this;\n }\n\n /**\n * Add an `OR WHERE column IN (values)` clause.\n * @returns `this` for chaining.\n */\n orWhereIn(\n column: ColumnRef<TLocalSchema>,\n values: readonly any[] | Knex.QueryBuilder\n ): this {\n this.#invalidateCache();\n (this.#baseQuery as any).orWhereIn(\n this.#resolveColumn(column, 'orWhereIn'),\n values as any\n );\n return this;\n }\n\n /**\n * Add an `OR WHERE column NOT IN (values)` clause.\n * @returns `this` for chaining.\n */\n orWhereNotIn(\n column: ColumnRef<TLocalSchema>,\n values: readonly any[] | Knex.QueryBuilder\n ): this {\n this.#invalidateCache();\n (this.#baseQuery as any).orWhereNotIn(\n this.#resolveColumn(column, 'orWhereNotIn'),\n values as any\n );\n return this;\n }\n\n /**\n * Add a `WHERE column IS NULL` clause.\n * @returns `this` for chaining.\n */\n whereNull(column: ColumnRef<TLocalSchema>): this {\n this.#invalidateCache();\n this.#baseQuery.whereNull(\n this.#resolveColumn(column, 'whereNull') as any\n );\n return this;\n }\n\n /**\n * Add a `WHERE column IS NOT NULL` clause.\n * @returns `this` for chaining.\n */\n whereNotNull(column: ColumnRef<TLocalSchema>): this {\n this.#invalidateCache();\n this.#baseQuery.whereNotNull(\n this.#resolveColumn(column, 'whereNotNull') as any\n );\n return this;\n }\n\n /**\n * Add an `OR WHERE column IS NULL` clause.\n * @returns `this` for chaining.\n */\n orWhereNull(column: ColumnRef<TLocalSchema>): this {\n this.#invalidateCache();\n (this.#baseQuery as any).orWhereNull(\n this.#resolveColumn(column, 'orWhereNull')\n );\n return this;\n }\n\n /**\n * Add an `OR WHERE column IS NOT NULL` clause.\n * @returns `this` for chaining.\n */\n orWhereNotNull(column: ColumnRef<TLocalSchema>): this {\n this.#invalidateCache();\n (this.#baseQuery as any).orWhereNotNull(\n this.#resolveColumn(column, 'orWhereNotNull')\n );\n return this;\n }\n\n /**\n * Add a `WHERE column BETWEEN low AND high` clause.\n * @param range - A two-element tuple `[low, high]`.\n * @returns `this` for chaining.\n */\n whereBetween(\n column: ColumnRef<TLocalSchema>,\n range: readonly [any, any]\n ): this {\n this.#invalidateCache();\n this.#baseQuery.whereBetween(\n this.#resolveColumn(column, 'whereBetween') as any,\n range as [any, any]\n );\n return this;\n }\n\n /**\n * Add a `WHERE column NOT BETWEEN low AND high` clause.\n * @param range - A two-element tuple `[low, high]`.\n * @returns `this` for chaining.\n */\n whereNotBetween(\n column: ColumnRef<TLocalSchema>,\n range: readonly [any, any]\n ): this {\n this.#invalidateCache();\n this.#baseQuery.whereNotBetween(\n this.#resolveColumn(column, 'whereNotBetween') as any,\n range as [any, any]\n );\n return this;\n }\n\n /**\n * Add a case-sensitive `WHERE column LIKE value` clause.\n * @param value - A SQL LIKE pattern (e.g. `'Alice%'`).\n * @returns `this` for chaining.\n */\n whereLike(column: ColumnRef<TLocalSchema>, value: string): this {\n this.#invalidateCache();\n (this.#baseQuery as any).whereLike(\n this.#resolveColumn(column, 'whereLike'),\n value\n );\n return this;\n }\n\n /**\n * Add a case-insensitive `WHERE column ILIKE value` clause (PostgreSQL).\n * @param value - A SQL LIKE pattern (e.g. `'alice%'`).\n * @returns `this` for chaining.\n */\n whereILike(column: ColumnRef<TLocalSchema>, value: string): this {\n this.#invalidateCache();\n (this.#baseQuery as any).whereILike(\n this.#resolveColumn(column, 'whereILike'),\n value\n );\n return this;\n }\n\n /**\n * Add a raw `WHERE` clause. Useful for database-specific expressions.\n * @param sql - Raw SQL string with optional `:binding:` or `?` placeholders.\n * @param bindings - Values for the placeholders.\n * @returns `this` for chaining.\n */\n whereRaw(sql: string, ...bindings: any[]): this {\n this.#invalidateCache();\n this.#baseQuery.whereRaw(sql, ...bindings);\n return this;\n }\n\n /**\n * Add a `WHERE EXISTS (subquery)` clause.\n * @param callback - A Knex query callback or sub-query builder.\n * @returns `this` for chaining.\n */\n whereExists(callback: Knex.QueryCallback | Knex.QueryBuilder): this {\n this.#invalidateCache();\n this.#baseQuery.whereExists(callback as any);\n return this;\n }\n\n /**\n * Add a `WHERE NOT EXISTS (subquery)` clause.\n * @param callback - A Knex query callback or sub-query builder.\n * @returns `this` for chaining.\n */\n whereNotExists(callback: Knex.QueryCallback | Knex.QueryBuilder): this {\n this.#invalidateCache();\n (this.#baseQuery as any).whereNotExists(callback as any);\n return this;\n }\n\n /**\n * Add a PostgreSQL JSON path filter using `@?` / `@@` operators or\n * a path-based equality test via `jsonb_path_query_first`.\n *\n * Only supported on `pg` clients — throws at runtime on others.\n *\n * @param column - Column reference for the `jsonb` column.\n * @param path - Dot-separated property path (e.g. `'a.b.c'`) or a\n * JSONPath expression string (e.g. `'$.a.b ? (@ == 1)'`).\n * @param operator - Comparison operator (`=`, `!=`, `<`, `<=`, `>`, `>=`,\n * `@?`, `@@`). Use `@?` / `@@` for JSONPath existence / predicate tests.\n * @param value - The right-hand side value. Ignored for `@?` and `@@`.\n * @returns `this` for chaining.\n *\n * @example\n * ```ts\n * // Filter rows where data->>'status' = 'active'\n * query(db, Schema).whereJsonPath(t => t.data, 'status', '=', 'active');\n *\n * // JSONPath existence\n * query(db, Schema).whereJsonPath(t => t.data, '$.tags[*] ? (@ == \"sale\")', '@?');\n * ```\n */\n whereJsonPath(\n column: ColumnRef<TLocalSchema>,\n path: string,\n operator?: string,\n value?: any\n ): this {\n this.#invalidateCache();\n const client = (this.#knex as any).client?.config?.client as\n | string\n | undefined;\n if (\n client !== 'pg' &&\n client !== 'postgresql' &&\n client !== 'postgres'\n ) {\n throw new Error(\n `whereJsonPath() is only supported on PostgreSQL (got client: \"${client ?? 'unknown'}\")`\n );\n }\n\n const col = this.#resolveColumn(column, 'whereJsonPath');\n const op = operator ?? '=';\n\n if (op === '@?' || op === '@@') {\n // JSONPath existence / predicate.\n // Note: `@?` contains a `?` which Knex would treat as a binding\n // placeholder inside whereRaw. Escape it with `\\?` → `\\\\?` in JS.\n const escapedOp = op === '@?' ? '@\\\\?' : '@@';\n this.#baseQuery.whereRaw(`?? ${escapedOp} ?`, [col, path]);\n } else {\n // Path-based value test: jsonb_path_query_first(col, path) op value\n const jsonPath = path.startsWith('$')\n ? path\n : `$.${path.replace(/\\./g, '.')}`;\n this.#baseQuery.whereRaw(\n `jsonb_path_query_first(??, ?) ${op} ?::jsonb`,\n [col, jsonPath, JSON.stringify(value)]\n );\n }\n return this;\n }\n\n // =======================================================================\n // ORDER BY\n // =======================================================================\n\n /**\n * Order the results by a column.\n * @param column - Column reference or raw expression.\n * @param direction - `'asc'` (default) or `'desc'`.\n * @returns `this` for chaining.\n *\n * @example\n * ```ts\n * query(db, UserSchema).orderBy(t => t.name).orderBy(t => t.createdAt, 'desc');\n * ```\n */\n orderBy(\n column: ColumnRef<TLocalSchema> | Knex.Raw,\n direction?: 'asc' | 'desc'\n ): this {\n this.#invalidateCache();\n const col = this.#resolveColumnArg(column);\n this.#baseQuery.orderBy(col as string, direction);\n return this;\n }\n\n /**\n * Order the results by a raw SQL expression.\n * @param sql - Raw SQL (e.g. `'LOWER(name) ASC'`).\n * @returns `this` for chaining.\n */\n orderByRaw(sql: string, ...bindings: any[]): this {\n this.#invalidateCache();\n this.#baseQuery.orderByRaw(sql, ...bindings);\n return this;\n }\n\n // =======================================================================\n // GROUP BY / HAVING\n // =======================================================================\n\n /**\n * Add a `GROUP BY` clause.\n * @param columns - One or more column references or raw expressions.\n * @returns `this` for chaining.\n */\n groupBy(...columns: (ColumnRef<TLocalSchema> | Knex.Raw)[]): this {\n this.#invalidateCache();\n const resolved = columns.map(c => this.#resolveColumnArg(c));\n this.#baseQuery.groupBy(...(resolved as string[]));\n return this;\n }\n\n /**\n * Add a raw `GROUP BY` expression.\n * @returns `this` for chaining.\n */\n groupByRaw(sql: string, ...bindings: any[]): this {\n this.#invalidateCache();\n this.#baseQuery.groupByRaw(sql, ...bindings);\n return this;\n }\n\n /**\n * Add a `HAVING column operator value` clause (used with `GROUP BY`).\n * @returns `this` for chaining.\n */\n having(\n column: ColumnRef<TLocalSchema> | Knex.Raw,\n operator: string,\n value: any\n ): this {\n this.#invalidateCache();\n const col = this.#resolveColumnArg(column);\n this.#baseQuery.having(col as string, operator, value);\n return this;\n }\n\n /**\n * Add a raw `HAVING` expression.\n * @returns `this` for chaining.\n */\n havingRaw(sql: string, ...bindings: any[]): this {\n this.#invalidateCache();\n this.#baseQuery.havingRaw(sql, ...bindings);\n return this;\n }\n\n // =======================================================================\n // PAGINATION\n // =======================================================================\n\n /**\n * Limit the number of rows returned.\n * @param n - Maximum number of rows.\n * @returns `this` for chaining.\n */\n limit(n: number): this {\n this.#invalidateCache();\n this.#baseQuery.limit(n);\n return this;\n }\n\n /**\n * Skip the first `n` rows in the result set (for cursor/offset pagination).\n * @param n - Number of rows to skip.\n * @returns `this` for chaining.\n */\n offset(n: number): this {\n this.#invalidateCache();\n this.#baseQuery.offset(n);\n return this;\n }\n\n // =======================================================================\n // SELECT / DISTINCT\n // =======================================================================\n\n /**\n * Select specific columns instead of `*`. Each column reference is\n * resolved to its SQL column name through the schema.\n * @param columns - One or more column references or raw expressions.\n * @returns `this` for chaining.\n */\n select(...columns: (ColumnRef<TLocalSchema> | Knex.Raw)[]): this;\n /**\n * DTO projection: select multiple aliased columns at once via a\n * descriptor record. Returns a query whose result rows match the\n * shape of the selector's return value (each value typed as the\n * inferred schema-property type).\n *\n * @example\n * ```ts\n * const dtos = await query(db, UserSchema)\n * .where(t => t.id, '>', 0)\n * .select(t => ({ id: t.id, n: t.name }))\n * .execute();\n * // dtos: { id: number; n: string }[]\n * ```\n */\n select<TSel extends SelectSelector<TLocalSchema>>(\n selector: TSel\n ): SchemaQueryBuilder<TLocalSchema, SelectProjection<ReturnType<TSel>>>;\n select(...args: unknown[]): SchemaQueryBuilder<TLocalSchema, any> {\n // DTO projection overload: a single function whose return value\n // is a Record<alias, descriptor> (NOT a single descriptor — those\n // are handled by the column-list path via #resolveColumnArg).\n if (args.length === 1 && typeof args[0] === 'function') {\n const fn = args[0] as (t: any) => unknown;\n const tree = ObjectSchemaBuilder.getPropertiesFor(\n this.#localSchema as any\n );\n const result = fn(tree);\n if (\n result &&\n typeof result === 'object' &&\n !(SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in (result as object))\n ) {\n this.#invalidateCache();\n this.#assertNotProjection('select');\n this.#selectionMode = 'projection';\n this.#appliedProjection = '<inline>';\n\n const aliasMap: Record<string, string> = {};\n this.#explicitSelects ??= [];\n for (const [alias, descriptor] of Object.entries(\n result as Record<string, unknown>\n )) {\n if (\n !descriptor ||\n typeof descriptor !== 'object' ||\n !(\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in\n (descriptor as object)\n )\n ) {\n throw new Error(\n `select(selector): value for alias \"${alias}\" must be a property descriptor (e.g. \\`t.someProp\\`).`\n );\n }\n const col = this.#resolveColumn(\n (() => descriptor) as ColumnRef<TLocalSchema>,\n `select(selector).${alias}`\n );\n aliasMap[alias] = col as string;\n this.#explicitSelects.push(col as string);\n }\n this.#baseQuery.select(aliasMap);\n return this as unknown as SchemaQueryBuilder<TLocalSchema, any>;\n }\n // Fall through: single descriptor → column-list path.\n }\n\n // Column-list path (existing behaviour).\n this.#invalidateCache();\n this.#assertNotProjection('select');\n this.#selectionMode = 'select';\n const resolved = (args as (ColumnRef<TLocalSchema> | Knex.Raw)[]).map(\n c => this.#resolveColumnArg(c)\n );\n this.#baseQuery.select(...(resolved as string[]));\n // Track the string-resolved columns (not Knex.Raw) for CTE column management\n this.#explicitSelects ??= [];\n for (const r of resolved) {\n if (typeof r === 'string') {\n this.#explicitSelects.push(r);\n }\n }\n return this as unknown as SchemaQueryBuilder<TLocalSchema, any>;\n }\n\n /** @internal Throw if a projection has already been applied. */\n #assertNotProjection(method: string): void {\n if (this.#selectionMode === 'projection') {\n throw new Error(\n `Cannot call .${method}() after .projected('${\n this.#appliedProjection\n }'). Choose one column-selection mode per query.`\n );\n }\n }\n\n /** @internal Throw if .select() or .projected() has already been applied. */\n #assertNotExplicitSelect(method: string): void {\n if (this.#selectionMode === 'select') {\n throw new Error(\n `Cannot call .${method}() after .select(). Choose one column-selection mode per query.`\n );\n }\n if (this.#selectionMode === 'aggregate') {\n throw new Error(\n `Cannot call .${method}() after an aggregate method. Choose one column-selection mode per query.`\n );\n }\n if (this.#selectionMode === 'projection') {\n throw new Error(\n `Cannot call .${method}() after .projected('${\n this.#appliedProjection\n }'). Choose one column-selection mode per query.`\n );\n }\n }\n\n /**\n * Add `DISTINCT` to the select clause. Duplicate rows are eliminated.\n * @param columns - One or more column references or raw expressions.\n * @returns `this` for chaining.\n */\n distinct(...columns: (ColumnRef<TLocalSchema> | Knex.Raw)[]): this {\n this.#invalidateCache();\n const resolved = columns.map(c => this.#resolveColumnArg(c));\n this.#baseQuery.distinct(...(resolved as string[]));\n return this;\n }\n\n // =======================================================================\n // AGGREGATES\n // =======================================================================\n\n /**\n * Add a `COUNT(*)` or `COUNT(column)` aggregate to the select list.\n * @param column - Optional column to count (defaults to `*`).\n * @returns `this` for chaining.\n */\n count(column?: ColumnRef<TLocalSchema> | Knex.Raw): this {\n this.#invalidateCache();\n this.#assertNotProjection('count');\n this.#selectionMode = 'aggregate';\n if (column) {\n this.#baseQuery.count(this.#resolveColumnArg(column) as string);\n } else {\n this.#baseQuery.count();\n }\n return this;\n }\n\n /**\n * Add a `COUNT(DISTINCT column)` aggregate to the select list.\n * @param column - Optional column (defaults to `*`).\n * @returns `this` for chaining.\n */\n countDistinct(column?: ColumnRef<TLocalSchema> | Knex.Raw): this {\n this.#invalidateCache();\n this.#assertNotProjection('countDistinct');\n this.#selectionMode = 'aggregate';\n if (column) {\n this.#baseQuery.countDistinct(\n this.#resolveColumnArg(column) as string\n );\n } else {\n this.#baseQuery.countDistinct();\n }\n return this;\n }\n\n /**\n * Add a `MIN(column)` aggregate.\n * @returns `this` for chaining.\n */\n min(column: ColumnRef<TLocalSchema> | Knex.Raw): this {\n this.#invalidateCache();\n this.#assertNotProjection('min');\n this.#selectionMode = 'aggregate';\n this.#baseQuery.min(this.#resolveColumnArg(column) as string);\n return this;\n }\n\n /**\n * Add a `MAX(column)` aggregate.\n * @returns `this` for chaining.\n */\n max(column: ColumnRef<TLocalSchema> | Knex.Raw): this {\n this.#invalidateCache();\n this.#assertNotProjection('max');\n this.#selectionMode = 'aggregate';\n this.#baseQuery.max(this.#resolveColumnArg(column) as string);\n return this;\n }\n\n /**\n * Add a `SUM(column)` aggregate.\n * @returns `this` for chaining.\n */\n sum(column: ColumnRef<TLocalSchema> | Knex.Raw): this {\n this.#invalidateCache();\n this.#assertNotProjection('sum');\n this.#selectionMode = 'aggregate';\n this.#baseQuery.sum(this.#resolveColumnArg(column) as string);\n return this;\n }\n\n /**\n * Add an `AVG(column)` aggregate.\n * @returns `this` for chaining.\n */\n avg(column: ColumnRef<TLocalSchema> | Knex.Raw): this {\n this.#invalidateCache();\n this.#assertNotProjection('avg');\n this.#selectionMode = 'aggregate';\n this.#baseQuery.avg(this.#resolveColumnArg(column) as string);\n return this;\n }\n\n // =======================================================================\n // WRITE OPERATIONS\n // =======================================================================\n\n /**\n * Insert a single row into the table and return the inserted record.\n *\n * Property keys are mapped to SQL column names via the schema's\n * `hasColumnName()` metadata before the `INSERT` is executed. The\n * returned row is mapped back to property names.\n *\n * @param data - The object to insert. Keys must be valid schema property names.\n * @returns The full inserted row (including database-generated fields).\n *\n * @example\n * ```ts\n * const user = await query(db, UserSchema).insert({ name: 'Alice', age: 30 });\n * // user.id is populated by the database DEFAULT / SERIAL\n * ```\n */\n async insert(data: InsertType<TLocalSchema>): Promise<TResult> {\n let processedData = { ...(data as Record<string, any>) };\n\n // Run beforeInsert hooks\n const beforeHooks =\n ((this.#localSchema as any).getExtension?.('beforeInsert') as\n | Function[]\n | undefined) ?? [];\n for (const hook of beforeHooks) {\n processedData = (await hook(processedData)) ?? processedData;\n }\n\n const mapped = this.#mapObjectToColumns(processedData);\n\n // Apply timestamps\n const timestamps = this.#getTimestamps();\n if (timestamps) {\n mapped[timestamps.createdAt] = this.#knex.fn.now();\n mapped[timestamps.updatedAt] = this.#knex.fn.now();\n }\n\n const [row] = await this.#knex(this.#tableName)\n .insert(mapped)\n .returning('*');\n const result = this.#mapRow(row) as TResult;\n\n // Run afterInsert hooks\n const afterHooks =\n ((this.#localSchema as any).getExtension?.('afterInsert') as\n | Function[]\n | undefined) ?? [];\n for (const hook of afterHooks) {\n await hook(result);\n }\n\n return result;\n }\n\n /**\n * Insert multiple rows in a single `INSERT` statement and return all\n * inserted records.\n *\n * @param data - Array of objects to insert.\n * @returns The full inserted rows in insertion order.\n */\n async insertMany(data: InsertType<TLocalSchema>[]): Promise<TResult[]> {\n const timestamps = this.#getTimestamps();\n const beforeHooks =\n ((this.#localSchema as any).getExtension?.('beforeInsert') as\n | Function[]\n | undefined) ?? [];\n\n const mapped = [];\n for (const d of data) {\n let processedData = { ...(d as Record<string, any>) };\n for (const hook of beforeHooks) {\n processedData = (await hook(processedData)) ?? processedData;\n }\n const m = this.#mapObjectToColumns(processedData);\n if (timestamps) {\n m[timestamps.createdAt] = this.#knex.fn.now();\n m[timestamps.updatedAt] = this.#knex.fn.now();\n }\n mapped.push(m);\n }\n\n const rows = await this.#knex(this.#tableName)\n .insert(mapped)\n .returning('*');\n const results = rows.map((row: any) => this.#mapRow(row) as TResult);\n\n // Run afterInsert hooks\n const afterHooks =\n ((this.#localSchema as any).getExtension?.('afterInsert') as\n | Function[]\n | undefined) ?? [];\n for (const result of results) {\n for (const hook of afterHooks) {\n await hook(result);\n }\n }\n\n return results;\n }\n\n /**\n * Insert a row (or rows) with an `ON CONFLICT` clause.\n *\n * Returns a chainable object with `.merge()` and `.ignore()` methods.\n *\n * - `.merge(updateData?)` — updates the conflicting row with the provided\n * fields (or all insert fields if omitted).\n * - `.ignore()` — skips the insert when a conflict occurs (INSERT IGNORE).\n *\n * @param conflictColumns - Column references that define the conflict target.\n * @returns A chainable conflict builder.\n *\n * @example\n * ```ts\n * // Upsert: insert or update on conflict\n * await query(db, UserSchema)\n * .onConflict(t => t.email)\n * .merge({ name: 'Bob' });\n *\n * // Insert and ignore on conflict\n * await query(db, UserSchema)\n * .onConflict(t => t.email)\n * .ignore();\n * ```\n */\n onConflict(\n ...conflictColumns: ColumnRef<TLocalSchema>[]\n ): OnConflictBuilder<TLocalSchema, TResult> {\n const cols = conflictColumns.map(\n c => this.#resolveColumn(c, 'onConflict') as string\n );\n return new OnConflictBuilder(this.#knex, this.#localSchema, this, cols);\n }\n\n /**\n * Insert or update a row based on a conflict target (upsert shorthand).\n *\n * Equivalent to calling `.onConflict(conflictColumns).merge(updateData)`.\n *\n * @param data - The row data to insert.\n * @param opts - `{ conflictColumns, updateColumns? }`.\n * @returns The resulting row (inserted or updated).\n *\n * @example\n * ```ts\n * const user = await query(db, UserSchema).upsert(\n * { email: 'alice@example.com', name: 'Alice' },\n * { conflictColumns: [t => t.email], updateColumns: [t => t.name] }\n * );\n * ```\n */\n async upsert(\n data: InsertType<TLocalSchema>,\n opts: {\n conflictColumns: ColumnRef<TLocalSchema>[];\n updateColumns?: ColumnRef<TLocalSchema>[];\n }\n ): Promise<TResult> {\n const timestamps = this.#getTimestamps();\n const beforeHooks =\n ((this.#localSchema as any).getExtension?.('beforeInsert') as\n | Function[]\n | undefined) ?? [];\n\n let processedData = { ...(data as Record<string, any>) };\n for (const hook of beforeHooks) {\n processedData = (await hook(processedData)) ?? processedData;\n }\n\n const mapped = this.#mapObjectToColumns(processedData);\n if (timestamps) {\n mapped[timestamps.createdAt] = this.#knex.fn.now();\n mapped[timestamps.updatedAt] = this.#knex.fn.now();\n }\n\n const conflictCols = opts.conflictColumns.map(\n c => this.#resolveColumn(c, 'upsert conflict') as string\n );\n\n let qb = this.#knex(this.#tableName)\n .insert(mapped)\n .onConflict(conflictCols);\n\n if (opts.updateColumns && opts.updateColumns.length > 0) {\n const updateCols = opts.updateColumns.map(\n c => this.#resolveColumn(c, 'upsert update') as string\n );\n const updateData: Record<string, any> = {};\n for (const col of updateCols) {\n if (col in mapped) {\n updateData[col] = mapped[col];\n }\n }\n if (timestamps) {\n updateData[timestamps.updatedAt] = this.#knex.fn.now();\n }\n qb = (qb as any).merge(updateData);\n } else {\n const updateData = { ...mapped };\n // Don't overwrite createdAt on upsert\n if (timestamps) {\n delete updateData[timestamps.createdAt];\n updateData[timestamps.updatedAt] = this.#knex.fn.now();\n }\n qb = (qb as any).merge(updateData);\n }\n\n const [row] = await (qb as any).returning('*');\n return this.#mapRow(row) as TResult;\n }\n\n /**\n * Update all rows that match the current `WHERE` clause and return the\n * updated records.\n *\n * Only the keys present in `data` are updated (partial update). Property\n * keys are resolved to column names automatically.\n *\n * @param data - Partial schema object with fields to update.\n * @returns All rows that were updated.\n *\n * @example\n * ```ts\n * const updated = await query(db, UserSchema)\n * .where(t => t.id, userId)\n * .update({ name: 'Bob' });\n * ```\n */\n async update(data: Partial<InferType<TLocalSchema>>): Promise<TResult[]> {\n let processedData = { ...(data as Record<string, any>) };\n\n // Run beforeUpdate hooks\n const beforeHooks =\n ((this.#localSchema as any).getExtension?.('beforeUpdate') as\n | Function[]\n | undefined) ?? [];\n for (const hook of beforeHooks) {\n processedData = (await hook(processedData)) ?? processedData;\n }\n\n const mapped = this.#mapObjectToColumns(processedData);\n\n // Apply timestamps\n const timestamps = this.#getTimestamps();\n if (timestamps) {\n mapped[timestamps.updatedAt] = this.#knex.fn.now();\n }\n\n const rows = await this.#baseQuery.update(mapped).returning('*');\n return rows.map((row: any) => this.#mapRow(row) as TResult);\n }\n\n /**\n * Delete all rows that match the current `WHERE` clause.\n *\n * If the schema has soft-delete enabled via `.softDelete()`, this performs\n * an `UPDATE SET deleted_at = NOW()` instead of a real `DELETE`.\n * Use {@link hardDelete} for permanent deletion.\n *\n * @returns The number of rows deleted (or soft-deleted).\n *\n * @example\n * ```ts\n * const count = await query(db, UserSchema).where(t => t.id, id).delete();\n * ```\n */\n async delete(): Promise<number> {\n // Run beforeDelete hooks\n const hooks =\n ((this.#localSchema as any).getExtension?.('beforeDelete') as\n | Function[]\n | undefined) ?? [];\n for (const hook of hooks) {\n await hook(this);\n }\n\n const softDelete = this.#getSoftDelete();\n if (softDelete) {\n return this.#baseQuery.update({\n [softDelete.column]: this.#knex.fn.now()\n });\n }\n return this.#baseQuery.delete();\n }\n\n // =======================================================================\n // BULK WRITE OPERATIONS\n // =======================================================================\n\n /**\n * Bulk-insert many rows in chunks. The default chunk size of `500` keeps\n * comfortably below Postgres' parameter-count limit of 65535. The chunk\n * size also auto-shrinks when the number of bindings per row would\n * exceed that ceiling.\n *\n * When `opts.onConflict` is supplied each chunk is wrapped in an\n * `INSERT ... ON CONFLICT` clause:\n *\n * - `'ignore'` — `ON CONFLICT (...) DO NOTHING`\n * - `'merge'` — `ON CONFLICT (...) DO UPDATE SET ...` (uses `conflictColumns` as\n * the conflict target and updates every inserted column).\n *\n * `beforeInsert` / `afterInsert` hooks fire per row, identically to\n * {@link insertMany}.\n *\n * @returns The inserted rows (excluding rows skipped by `'ignore'`).\n */\n async bulkInsert(\n rows: InsertType<TLocalSchema>[],\n opts?: {\n chunkSize?: number;\n onConflict?: 'ignore' | 'merge';\n conflictColumns?: ColumnRef<TLocalSchema>[];\n }\n ): Promise<TResult[]> {\n if (rows.length === 0) return [];\n\n const requestedChunkSize = opts?.chunkSize ?? 500;\n const bindingsPerRow = Object.keys(rows[0] as object).length || 1;\n const safeChunkCap = Math.max(\n 1,\n Math.floor(60000 / Math.max(1, bindingsPerRow))\n );\n const chunkSize = Math.max(\n 1,\n Math.min(requestedChunkSize, safeChunkCap)\n );\n\n const timestamps = this.#getTimestamps();\n const beforeHooks =\n ((this.#localSchema as any).getExtension?.('beforeInsert') as\n | Function[]\n | undefined) ?? [];\n const afterHooks =\n ((this.#localSchema as any).getExtension?.('afterInsert') as\n | Function[]\n | undefined) ?? [];\n\n const conflictCols =\n opts?.onConflict && opts.conflictColumns\n ? opts.conflictColumns.map(\n c =>\n this.#resolveColumn(\n c,\n 'bulkInsert.onConflict'\n ) as string\n )\n : null;\n if (opts?.onConflict && (!conflictCols || conflictCols.length === 0)) {\n throw new Error(\n 'bulkInsert: `conflictColumns` is required when `onConflict` is set.'\n );\n }\n\n const results: TResult[] = [];\n\n for (let i = 0; i < rows.length; i += chunkSize) {\n const chunk = rows.slice(i, i + chunkSize);\n const mapped: Record<string, any>[] = [];\n for (const row of chunk) {\n let processed = { ...(row as Record<string, any>) };\n for (const hook of beforeHooks) {\n processed = (await hook(processed)) ?? processed;\n }\n const m = this.#mapObjectToColumns(processed);\n if (timestamps) {\n m[timestamps.createdAt] = this.#knex.fn.now();\n m[timestamps.updatedAt] = this.#knex.fn.now();\n }\n mapped.push(m);\n }\n\n let qb: any = this.#knex(this.#tableName).insert(mapped);\n\n if (conflictCols) {\n qb = qb.onConflict(conflictCols);\n if (opts!.onConflict === 'ignore') {\n qb = qb.ignore();\n } else {\n // Merge — update every non-conflict-target column.\n const updateCols = new Set<string>();\n for (const m of mapped) {\n for (const k of Object.keys(m)) updateCols.add(k);\n }\n for (const c of conflictCols) updateCols.delete(c);\n if (timestamps) {\n updateCols.delete(timestamps.createdAt);\n updateCols.add(timestamps.updatedAt);\n }\n qb = qb.merge(Array.from(updateCols));\n }\n }\n\n const inserted: any[] = await qb.returning('*');\n for (const row of inserted) {\n const mappedRow = this.#mapRow(row) as TResult;\n for (const hook of afterHooks) {\n await hook(mappedRow);\n }\n results.push(mappedRow);\n }\n }\n\n return results;\n }\n\n /**\n * Bulk-upsert many rows in chunks. Equivalent to\n * `.bulkInsert(rows, { onConflict: 'merge', conflictColumns })`.\n */\n async bulkUpsert(\n rows: InsertType<TLocalSchema>[],\n opts: {\n conflictColumns: ColumnRef<TLocalSchema>[];\n chunkSize?: number;\n }\n ): Promise<TResult[]> {\n return this.bulkInsert(rows, {\n chunkSize: opts.chunkSize,\n onConflict: 'merge',\n conflictColumns: opts.conflictColumns\n });\n }\n\n /**\n * Bulk-update many rows in a single SQL statement using a CASE\n * expression keyed on the entity's primary key.\n *\n * Each entry's `where` clause must fully match the entity's primary key\n * columns (single or composite). Updates that touch different columns\n * are coalesced into one statement; rows whose PK appears in `updates`\n * but whose `set` does not contain a given column retain their existing\n * value.\n *\n * @returns The number of rows affected.\n */\n async bulkUpdate(\n updates: ReadonlyArray<{\n where: Partial<InferType<TLocalSchema>>;\n set: Partial<InferType<TLocalSchema>>;\n }>\n ): Promise<number> {\n if (updates.length === 0) return 0;\n\n const pk = this.#resolvePkColumns();\n const { propToCol } = buildColumnMap(this.#localSchema as any);\n const beforeHooks =\n ((this.#localSchema as any).getExtension?.('beforeUpdate') as\n | Function[]\n | undefined) ?? [];\n const timestamps = this.#getTimestamps();\n\n // Pre-process: run hooks, map keys, validate PK presence in `where`.\n const processed: Array<{\n pkValues: unknown[];\n set: Record<string, any>;\n }> = [];\n for (const entry of updates) {\n let setData = { ...(entry.set as Record<string, any>) };\n for (const hook of beforeHooks) {\n setData = (await hook(setData)) ?? setData;\n }\n const setMapped = this.#mapObjectToColumns(setData);\n if (timestamps) {\n setMapped[timestamps.updatedAt] = this.#knex.fn.now();\n }\n\n const whereRec = entry.where as Record<string, unknown>;\n const pkValues: unknown[] = [];\n for (const propKey of pk.propertyKeys) {\n const value =\n propKey in whereRec\n ? whereRec[propKey]\n : (whereRec[propToCol.get(propKey) ?? propKey] as\n | unknown\n | undefined);\n if (value === undefined) {\n throw new Error(\n `bulkUpdate: each \\`where\\` clause must include the entity's primary key (missing \"${propKey}\").`\n );\n }\n pkValues.push(value);\n }\n processed.push({ pkValues, set: setMapped });\n }\n\n // Collect every column referenced in any `set`.\n const allSetCols = new Set<string>();\n for (const p of processed) {\n for (const k of Object.keys(p.set)) allSetCols.add(k);\n }\n if (allSetCols.size === 0) return 0;\n\n // Build the SET clause: one CASE per column, keyed by PK.\n const knex = this.#knex;\n const updateExpr: Record<string, any> = {};\n for (const col of allSetCols) {\n const fragments: string[] = [];\n const bindings: unknown[] = [];\n for (const p of processed) {\n if (!(col in p.set)) continue;\n if (pk.columnNames.length === 1) {\n fragments.push('WHEN ?? = ? THEN ?');\n bindings.push(pk.columnNames[0], p.pkValues[0], p.set[col]);\n } else {\n const conditions = pk.columnNames\n .map(() => '?? = ?')\n .join(' AND ');\n fragments.push(`WHEN ${conditions} THEN ?`);\n for (let i = 0; i < pk.columnNames.length; i++) {\n bindings.push(pk.columnNames[i], p.pkValues[i]);\n }\n bindings.push(p.set[col]);\n }\n }\n if (fragments.length === 0) continue;\n // ELSE keeps the existing column value untouched.\n updateExpr[col] = knex.raw(\n `CASE ${fragments.join(' ')} ELSE ?? END`,\n [...bindings, col] as any\n );\n }\n\n // WHERE: restrict to the PK tuples covered by the batch.\n let qb: any = knex(this.#tableName).update(updateExpr);\n if (pk.columnNames.length === 1) {\n qb = qb.whereIn(\n pk.columnNames[0],\n processed.map(p => p.pkValues[0])\n );\n } else {\n qb = qb.where(function (this: Knex.QueryBuilder) {\n for (const p of processed) {\n this.orWhere(function (this: Knex.QueryBuilder) {\n for (let i = 0; i < pk.columnNames.length; i++) {\n this.andWhere(\n pk.columnNames[i],\n p.pkValues[i] as any\n );\n }\n });\n }\n });\n }\n\n return await qb;\n }\n\n /**\n * @internal Resolve the entity's primary-key columns, throwing a clear\n * error when none is declared. Used by bulk-update / find helpers.\n */\n #resolvePkColumns(): {\n propertyKeys: readonly string[];\n columnNames: readonly string[];\n } {\n const pk = getPrimaryKeyColumns(this.#localSchema as any);\n if (pk.columnNames.length === 0) {\n throw new Error(\n 'No primary key declared on this schema. Use `.primaryKey()` on a column or `.hasPrimaryKey([...])` on the schema.'\n );\n }\n return pk;\n }\n\n // =======================================================================\n // ESCAPE HATCH\n // =======================================================================\n\n /**\n * Escape hatch: apply any Knex method to the underlying base query.\n *\n * Use this when you need a Knex feature not exposed by this API (e.g.\n * `forUpdate()`, CTEs, `join()`, `union()`).\n *\n * @param fn - A callback that receives the raw `Knex.QueryBuilder` and\n * may mutate it in place.\n * @returns `this` for chaining.\n *\n * @example\n * ```ts\n * query(db, UserSchema).apply(qb => qb.forUpdate().noWait());\n * ```\n */\n apply(fn: (builder: Knex.QueryBuilder) => void): this {\n this.#invalidateCache();\n fn(this.#baseQuery);\n return this;\n }\n\n // =======================================================================\n // Transaction support\n // =======================================================================\n\n /**\n * Bind this query builder to a Knex transaction.\n *\n * Returns a **new** builder that runs all operations — SELECT, INSERT,\n * UPDATE, DELETE, and eager-loaded sub-queries — within the given\n * transaction. The original builder is left unchanged.\n *\n * Use this when you already have a transaction obtained from\n * `knex.transaction()` and want all operations performed by the returned\n * builder to participate in that transaction.\n *\n * @param trx - The Knex transaction obtained from `knex.transaction()`.\n * @returns A new {@link SchemaQueryBuilder} bound to the transaction.\n *\n * @example\n * ```ts\n * async function createUser(\n * data: InsertType<typeof UserSchema>,\n * trx: Knex.Transaction\n * ) {\n * return query(db, UserSchema).transacting(trx).insert(data);\n * }\n *\n * await db.transaction(async trx => {\n * const user = await createUser({ name: 'Alice' }, trx);\n * await query(db, PostSchema).transacting(trx).insert({ authorId: user.id, title: 'Hello' });\n * });\n * ```\n */\n transacting(\n trx: Knex.Transaction\n ): SchemaQueryBuilder<TLocalSchema, TResult> {\n const builder = new SchemaQueryBuilder<TLocalSchema, TResult>(\n trx as unknown as Knex,\n this.#localSchema,\n this.#baseQuery.clone().transacting(trx)\n );\n for (const spec of this.#specs) {\n builder.#specs.push({\n ...spec,\n foreignQuery: spec.foreignQuery.clone().transacting(trx)\n });\n }\n builder.#explicitSelects = this.#explicitSelects\n ? [...this.#explicitSelects]\n : null;\n builder.#selectionMode = this.#selectionMode;\n builder.#appliedProjection = this.#appliedProjection;\n builder.#includeDeleted = this.#includeDeleted;\n builder.#onlyDeleted = this.#onlyDeleted;\n builder.#skipDefaultScope = this.#skipDefaultScope;\n // Copy polymorphic variant state\n builder.#variantConfig = this.#variantConfig;\n builder.#enabledVariants =\n this.#enabledVariants !== null\n ? new Set(this.#enabledVariants)\n : null;\n builder.#variantWhereFilters = [...this.#variantWhereFilters];\n builder.#variantRelationIncludes = [...this.#variantRelationIncludes];\n return builder;\n }\n\n // =======================================================================\n // Include (relation-based eager loading)\n // =======================================================================\n\n /**\n * Eager-load a named relation defined via `.hasMany()`, `.belongsTo()`,\n * `.hasOne()`, or `.belongsToMany()` on the schema.\n *\n * @param relationName - The relation name passed to the schema's relation method.\n * @param customize - Optional callback to customise the foreign query\n * (e.g. add ordering, limits).\n * @returns `this` for chaining.\n *\n * @example\n * ```ts\n * const posts = await query(db, PostWithRelations)\n * .include('author')\n * .include('tags');\n * ```\n */\n include(\n relationName: string,\n customize?: (q: SchemaQueryBuilder<any, any>) => void\n ): this {\n this.#invalidateCache();\n const relations: RelationSpec[] =\n (this.#localSchema as any).getExtension?.('relations') ?? [];\n const relation = relations.find(\n (r: RelationSpec) => r.name === relationName\n );\n if (!relation) {\n // Try variant relations as fallback (auto-routing)\n const variantConfig = this.#getVariantConfig();\n if (variantConfig) {\n const matches: Array<{ variantKey: string }> = [];\n for (const [vKey, vSpec] of Object.entries(\n variantConfig.variants\n )) {\n if (\n vSpec.relations.some(\n (r: ResolvedVariantRelationSpec) =>\n r.name === relationName\n )\n ) {\n matches.push({ variantKey: vKey });\n }\n }\n if (matches.length === 1) {\n return this.includeVariant(\n matches[0].variantKey,\n relationName,\n customize\n );\n }\n if (matches.length > 1) {\n throw new Error(\n `Ambiguous relation \"${relationName}\" — found on variants: ${matches.map(m => m.variantKey).join(', ')}. Use .includeVariant(key, name) to be explicit.`\n );\n }\n }\n throw new Error(\n `Unknown relation \"${relationName}\" on schema for table \"${this.#tableName}\"`\n );\n }\n\n const foreignSchema = this.#resolveSchema(relation.schema);\n const foreignTableName = getTableName(foreignSchema);\n\n switch (relation.type) {\n case 'belongsTo': {\n const localColumn = resolveColumnRef(\n relation.foreignKey,\n this.#localSchema,\n 'foreignKey'\n );\n const foreignColumn = this.#findPrimaryKeyColumn(foreignSchema);\n\n const foreignQuery1: Knex.QueryBuilder =\n this.#knex(foreignTableName);\n if (customize) {\n const proxy = new SchemaQueryBuilder(\n this.#knex,\n foreignSchema,\n foreignQuery1\n );\n customize(proxy);\n }\n\n this.joinOne({\n foreignSchema,\n localColumn,\n foreignColumn,\n as: relationName,\n foreignQuery: foreignQuery1\n } as any);\n break;\n }\n case 'hasOne': {\n const localColumn = this.#findPrimaryKeyColumn(\n this.#localSchema\n );\n const foreignColumn = resolveColumnRef(\n relation.foreignKey,\n foreignSchema,\n 'foreignKey'\n );\n\n const foreignQuery2: Knex.QueryBuilder =\n this.#knex(foreignTableName);\n if (customize) {\n const proxy = new SchemaQueryBuilder(\n this.#knex,\n foreignSchema,\n foreignQuery2\n );\n customize(proxy);\n }\n\n this.joinOne({\n foreignSchema,\n localColumn,\n foreignColumn,\n as: relationName,\n required: false,\n foreignQuery: foreignQuery2\n } as any);\n break;\n }\n case 'hasMany': {\n const localColumn = this.#findPrimaryKeyColumn(\n this.#localSchema\n );\n const foreignColumn = resolveColumnRef(\n relation.foreignKey,\n foreignSchema,\n 'foreignKey'\n );\n\n const foreignQuery3: Knex.QueryBuilder =\n this.#knex(foreignTableName);\n if (customize) {\n const proxy = new SchemaQueryBuilder(\n this.#knex,\n foreignSchema,\n foreignQuery3\n );\n customize(proxy);\n }\n\n this.joinMany({\n foreignSchema,\n localColumn,\n foreignColumn,\n as: relationName,\n foreignQuery: foreignQuery3\n } as any);\n break;\n }\n case 'belongsToMany': {\n const through = relation.through!;\n const localColumn = this.#findPrimaryKeyColumn(\n this.#localSchema\n );\n\n const foreignQuery = this.#knex(foreignTableName)\n .join(\n through.table,\n `${through.table}.${through.foreignKey}`,\n `${foreignTableName}.${this.#findPrimaryKeyColumn(foreignSchema)}`\n )\n .select(\n `${foreignTableName}.*`,\n `${through.table}.${through.localKey}`\n );\n\n if (customize) {\n const proxy = new SchemaQueryBuilder(\n this.#knex,\n foreignSchema,\n foreignQuery\n );\n customize(proxy);\n }\n\n this.joinMany({\n foreignSchema,\n localColumn,\n foreignColumn: through.localKey,\n as: relationName,\n foreignQuery\n } as any);\n break;\n }\n }\n\n return this;\n }\n\n /**\n * Eager-load a named relation declared inside a `withVariants` variant spec.\n *\n * The relation is loaded via a LEFT JOIN on the variant's alias table and\n * only populated on rows whose discriminator matches `variantKey`.\n *\n * @param variantKey - The variant key (e.g. `'assigned'`).\n * @param relationName - The relation name declared in `variants[key].relations`.\n * @param customize - Optional callback to restrict which columns are\n * selected from the foreign table (scope / projection).\n *\n * @example\n * ```ts\n * await query(db, TodoActivity)\n * .includeVariant('assigned', 'assignee', q => q.projected('summary'));\n * ```\n */\n includeVariant(\n variantKey: string,\n relationName: string,\n customize?: (q: SchemaQueryBuilder<any, any>) => void\n ): this {\n this.#invalidateCache();\n const variantConfig = this.#getVariantConfig();\n if (!variantConfig) {\n throw new Error(\n `includeVariant: schema for table \"${this.#tableName}\" is not polymorphic (no .withVariants() config found)`\n );\n }\n const variantSpec = variantConfig.variants[variantKey];\n if (!variantSpec) {\n throw new Error(\n `includeVariant: unknown variant key \"${variantKey}\" on schema for table \"${this.#tableName}\"`\n );\n }\n const relSpec = variantSpec.relations.find(\n (r: ResolvedVariantRelationSpec) => r.name === relationName\n );\n if (!relSpec) {\n throw new Error(\n `includeVariant: unknown relation \"${relationName}\" on variant \"${variantKey}\" of table \"${this.#tableName}\"`\n );\n }\n this.#variantRelationIncludes.push({\n variantKey,\n relationName,\n customize\n });\n return this;\n }\n\n // =======================================================================\n // Scopes\n // =======================================================================\n\n /**\n * Apply a named scope defined on the schema via `.scope(name, fn)`.\n *\n * The `name` parameter is constrained to the literal scope names registered\n * on the schema, so IDEs show only valid completions and typos are caught\n * at compile time.\n *\n * @param name - The scope name.\n * @returns `this` for chaining.\n *\n * @example\n * ```ts\n * await query(db, Post).scoped('published').scoped('recent');\n * ```\n */\n /**\n * Apply a **named projection** defined on the schema via\n * `.projection(name, columns)`.\n *\n * Calling `.projected()` on the query builder does two things:\n * 1. Restricts the SQL `SELECT` clause to the columns registered under\n * `name` (SQL column names are resolved via `.hasColumnName()`).\n * 2. Narrows the TypeScript result row type to `Pick<Row, Keys>` so\n * accessing columns outside the projection is a compile-time error.\n *\n * The `name` parameter is constrained to the literal projection names\n * registered on the schema — TypeScript will report an error for any\n * unregistered name.\n *\n * Calling `.projected()` after `.select()`, any aggregate method\n * (`.count()`, `.min()`, etc.), or a second `.projected()` call throws\n * at runtime with a clear error message.\n *\n * @param name - The projection name.\n * @returns A new builder whose result type is `Pick<Row, ProjectionKeys>`.\n *\n * @example\n * ```ts\n * const PostSchema = object({ id: number(), title: string(), body: string() })\n * .hasTableName('posts')\n * .projection('summary', 'id', 'title');\n *\n * const rows = await query(db, PostSchema)\n * .scoped('published')\n * .projected('summary');\n * // rows: Array<Pick<Post, 'id' | 'title'>>\n * // rows[0].body // ← TS error: not in projection\n * ```\n *\n * @see {@link ddlExtension} `.projection()` for schema-side definition.\n */\n projected<K extends keyof ProjectionsOf<TLocalSchema> & string>(\n name: K\n ): SchemaQueryBuilder<\n TLocalSchema,\n Pick<TResult, ProjectionKeysOf<TLocalSchema, K> & keyof TResult>\n > {\n this.#assertNotExplicitSelect('projected');\n if (this.#selectionMode === 'projection') {\n throw new Error(\n `Cannot call .projected('${name}') — .projected('${\n this.#appliedProjection\n }') was already applied. Only one projection per query.`\n );\n }\n const projections = getProjections(this.#localSchema as any);\n const projection = projections[name];\n if (!projection) {\n throw new Error(\n `Unknown projection \"${name}\" on schema for table \"${\n this.#tableName\n }\"`\n );\n }\n // Translate property keys → SQL column names\n const { propToCol } = buildColumnMap(this.#localSchema as any);\n const sqlCols = projection.keys.map(key => propToCol.get(key) ?? key);\n this.#baseQuery.select(...sqlCols);\n this.#explicitSelects ??= [];\n for (const col of sqlCols) {\n this.#explicitSelects.push(col);\n }\n this.#selectionMode = 'projection';\n this.#appliedProjection = name;\n this.#invalidateCache();\n return this as any;\n }\n\n scoped<K extends ScopesOf<TLocalSchema>>(name: K): this {\n this.#invalidateCache();\n const scopes = (this.#localSchema as any).getExtension?.('scopes') as\n | Record<string, Function>\n | undefined;\n const scopeFn = scopes?.[name];\n if (!scopeFn) {\n throw new Error(\n `Unknown scope \"${name}\" on schema for table \"${this.#tableName}\"`\n );\n }\n scopeFn(this);\n return this;\n }\n\n /**\n * Bypass the default scope (and soft-delete scope) for this query.\n *\n * @returns `this` for chaining.\n *\n * @example\n * ```ts\n * await query(db, Post).unscoped().where(t => t.id, 1);\n * ```\n */\n unscoped(): this {\n this.#invalidateCache();\n this.#skipDefaultScope = true;\n this.#includeDeleted = true;\n return this;\n }\n\n // =======================================================================\n // Polymorphic variant methods\n // =======================================================================\n\n /**\n * Add a WHERE condition that applies **only to rows matching a specific\n * variant** of a polymorphic schema. Rows for other variants pass through\n * unaffected (the condition is ORed away for non-matching discriminator values).\n *\n * The column name is resolved against the **variant's** schema properties.\n *\n * Only valid on a polymorphic schema (created via `.withVariants()`).\n *\n * @param key - The discriminator value identifying the variant (e.g. `'image'`).\n * @param column - Property key on the variant's schema (e.g. `'width'`).\n * @param operator - SQL comparison operator (`'='`, `'>'`, `'<'`, `'like'`, etc.).\n * @param value - The value to compare against.\n * @returns `this` for chaining.\n *\n * @example\n * ```ts\n * // Return all documents and only images wider than 1024 px\n * const files = await query(db, FileSchema)\n * .whereVariant('image', 'width', '>', 1024);\n * ```\n */\n whereVariant(\n key: string,\n column: string,\n operator: string,\n value: any\n ): this {\n const variantConfig = this.#getVariantConfig();\n if (!variantConfig) {\n throw new Error(\n 'whereVariant() can only be used on a polymorphic schema (created with .withVariants())'\n );\n }\n\n const spec = variantConfig.variants[key];\n if (!spec) {\n throw new Error(\n `whereVariant: unknown variant key \"${key}\". ` +\n `Valid keys: ${Object.keys(variantConfig.variants).join(', ')}`\n );\n }\n\n const op = operator.toLowerCase();\n if (!SchemaQueryBuilder.#ALLOWED_OPS.has(op)) {\n throw new Error(\n `whereVariant: operator \"${operator}\" is not allowed. ` +\n `Allowed operators: ${[...SchemaQueryBuilder.#ALLOWED_OPS].join(', ')}`\n );\n }\n\n // Resolve property key → SQL column name via variant schema column map\n const { propToCol } = buildColumnMap(spec.schema);\n const colName = propToCol.get(column) ?? column;\n\n let qualifiedColumn: string;\n if (spec.storage === 'cti') {\n qualifiedColumn = `__v_${key}.${colName}`;\n } else {\n // STI: column is on the base table\n qualifiedColumn = `${this.#tableName}.${colName}`;\n }\n\n this.#variantWhereFilters.push({ key, qualifiedColumn, op, value });\n this.#invalidateCache();\n return this;\n }\n\n /**\n * Restrict the query to only return rows for the specified variant keys.\n *\n * Adds `WHERE <discriminator> IN (...)` to the query and skips the LEFT\n * JOINs for excluded variants. This is more efficient than filtering after\n * loading all variants.\n *\n * Only valid on a polymorphic schema (created via `.withVariants()`).\n *\n * @param keys - Discriminator values to include (e.g. `['image', 'document']`).\n * @returns `this` for chaining.\n *\n * @example\n * ```ts\n * const images = await query(db, FileSchema).selectVariants(['image']);\n * // images: Array<{ id; name; type: 'image'; width; height; format }>\n * ```\n */\n selectVariants(keys: string[]): this {\n if (!this.#getVariantConfig()) {\n throw new Error(\n 'selectVariants() can only be used on a polymorphic schema (created with .withVariants())'\n );\n }\n this.#enabledVariants = new Set(keys);\n this.#invalidateCache();\n return this;\n }\n\n // =======================================================================\n // Soft delete methods\n // =======================================================================\n\n /**\n * Include soft-deleted rows in the results.\n *\n * By default, schemas with `.softDelete()` automatically filter out\n * rows where `deleted_at IS NOT NULL`. Call `.withDeleted()` to\n * include them.\n *\n * @returns `this` for chaining.\n */\n withDeleted(): this {\n this.#invalidateCache();\n this.#includeDeleted = true;\n return this;\n }\n\n /**\n * Return only soft-deleted rows (`WHERE deleted_at IS NOT NULL`).\n *\n * @returns `this` for chaining.\n */\n onlyDeleted(): this {\n this.#invalidateCache();\n this.#onlyDeleted = true;\n this.#includeDeleted = true;\n return this;\n }\n\n /**\n * Permanently delete rows matching the current WHERE clause, bypassing\n * the soft-delete mechanism.\n *\n * @returns The number of rows deleted.\n */\n async hardDelete(): Promise<number> {\n // Run beforeDelete hooks\n const hooks =\n ((this.#localSchema as any).getExtension?.('beforeDelete') as\n | Function[]\n | undefined) ?? [];\n for (const hook of hooks) {\n await hook(this);\n }\n return this.#baseQuery.delete();\n }\n\n /**\n * Restore soft-deleted rows by setting `deleted_at = NULL`.\n *\n * @returns The restored rows.\n */\n async restore(): Promise<TResult[]> {\n const softDelete = this.#getSoftDelete();\n if (!softDelete) {\n throw new Error(\n 'Schema does not have soft delete enabled. Use .softDelete() on the schema.'\n );\n }\n const rows = await this.#baseQuery\n .update({ [softDelete.column]: null })\n .returning('*');\n return rows.map((row: any) => this.#mapRow(row) as TResult);\n }\n\n // =======================================================================\n // Pagination\n // =======================================================================\n\n /**\n * Execute an offset-based paginated query.\n *\n * Runs a count query and a data query in parallel. Returns the page data\n * along with pagination metadata.\n *\n * @param opts - `{ page, pageSize }` — 1-based page number and page size.\n * @returns A {@link PaginationResult} with data, total count, and page info.\n *\n * @example\n * ```ts\n * const page = await query(db, Post)\n * .where(t => t.status, 'published')\n * .paginate({ page: 2, pageSize: 20 });\n * // page.data, page.total, page.totalPages, page.hasNextPage, ...\n * ```\n */\n async paginate(opts: {\n page: number;\n pageSize: number;\n }): Promise<PaginationResult<TResult>> {\n const { page, pageSize } = opts;\n\n const effectiveBase = this.#getEffectiveBaseQuery();\n\n // Count query (no CTE, no ordering, no eager loading)\n const countResult = await effectiveBase\n .clone()\n .clearSelect()\n .clearOrder()\n .count('* as count')\n .first();\n const total = Number((countResult as any)?.count ?? 0);\n\n // Data query (with CTE for eager loading)\n this.limit(pageSize).offset((page - 1) * pageSize);\n const data = await this.execute();\n\n const totalPages = Math.ceil(total / pageSize);\n\n return {\n data,\n total,\n page,\n pageSize,\n totalPages,\n hasNextPage: page < totalPages,\n hasPreviousPage: page > 1\n };\n }\n\n /**\n * Execute a cursor-based (keyset) paginated query.\n *\n * More efficient than offset pagination for large datasets. Fetches one\n * extra row to determine whether more data exists.\n *\n * @param opts - `{ cursor, limit, column?, direction? }`.\n * @returns A {@link CursorPaginationResult} with data, next cursor, and\n * `hasMore` flag.\n *\n * @example\n * ```ts\n * const page = await query(db, Post)\n * .orderBy(t => t.createdAt, 'desc')\n * .paginateAfter({ cursor: lastCreatedAt, limit: 20 });\n * ```\n */\n async paginateAfter(opts: {\n cursor?: any;\n limit: number;\n column?: ColumnRef<TLocalSchema>;\n direction?: 'asc' | 'desc';\n }): Promise<CursorPaginationResult<TResult>> {\n const direction = opts.direction ?? 'desc';\n const column = opts.column ?? ('id' as any);\n\n if (opts.cursor != null) {\n const op = direction === 'desc' ? '<' : '>';\n this.where(column, op, opts.cursor);\n }\n\n this.orderBy(column, direction).limit(opts.limit + 1);\n const rows = await this.execute();\n\n const hasMore = rows.length > opts.limit;\n const data = hasMore ? rows.slice(0, opts.limit) : rows;\n\n const propKey =\n typeof column === 'string'\n ? column\n : resolvePropertyKey(\n column as any,\n this.#localSchema,\n 'cursor'\n );\n\n const nextCursor =\n hasMore && data.length > 0\n ? String((data[data.length - 1] as any)[propKey])\n : null;\n\n return { data, nextCursor, hasMore };\n }\n\n // =======================================================================\n // Select Raw\n // =======================================================================\n\n /**\n * Add a raw SQL expression to the SELECT clause.\n *\n * @param sql - Raw SQL (e.g. `'*, ts_rank(vector, query) AS rank'`).\n * @param bindings - Optional parameter bindings.\n * @returns `this` for chaining.\n */\n selectRaw(sql: string, bindings?: any[]): this {\n this.#invalidateCache();\n if (bindings) {\n this.#baseQuery.select(this.#knex.raw(sql, bindings));\n } else {\n this.#baseQuery.select(this.#knex.raw(sql));\n }\n return this;\n }\n\n // =======================================================================\n // CTE-based eager loading query building (from knex-eager)\n // =======================================================================\n\n #buildQuery(): Knex.QueryBuilder {\n const effectiveBase = this.#getEffectiveBaseQuery();\n\n // Apply polymorphic variant joins (CTI LEFT JOINs + selectVariants /\n // whereVariant filters) before any CTE wrapping so the CTE also\n // contains variant columns.\n const variantConfig = this.#getVariantConfig();\n const queryBase = variantConfig\n ? this.#applyVariantJoins(effectiveBase, variantConfig)\n : effectiveBase;\n\n if (this.#specs.length === 0) {\n return queryBase;\n }\n\n const knex = this.#knex;\n const specs = this.#specs;\n\n // Collect all localColumns needed for CTE joins\n const requiredLocalColumns = [\n ...new Set(specs.map(s => s.localColumn))\n ];\n\n // If the caller used .select(...), some localColumns may have been\n // omitted. Clone the base query and ensure those columns are always\n // included in the CTE so the join conditions work at runtime.\n // Track which columns we added so they can be excluded from the\n // final SELECT (preserving the original column set the caller asked for).\n let cteQuery = queryBase;\n let extraColumns: string[] = [];\n\n if (this.#explicitSelects !== null) {\n const selectedSet = new Set(this.#explicitSelects);\n extraColumns = requiredLocalColumns.filter(\n col => !selectedSet.has(col)\n );\n if (extraColumns.length > 0) {\n cteQuery = queryBase.clone();\n for (const col of extraColumns) {\n cteQuery.column(col);\n }\n }\n }\n\n // Build the outer query that wraps the CTE.\n // When we added extra columns, select only the original columns + joined\n // aliases (instead of originalQuery.*) so the caller's column set is\n // preserved in the final result.\n const resultQuery = knex.queryBuilder().with('originalQuery', cteQuery);\n\n if (extraColumns.length > 0 && this.#explicitSelects !== null) {\n // Explicit column list: original user selections only\n for (const col of this.#explicitSelects) {\n resultQuery.select(\n knex.raw(':originalQuery:.:col: as :col:', {\n originalQuery: 'originalQuery',\n col\n })\n );\n }\n } else {\n resultQuery.select('originalQuery.*');\n }\n\n resultQuery.from(\n knex.raw(':originalQuery:', {\n originalQuery: 'originalQuery'\n })\n );\n\n for (let i = 0; i < specs.length; i++) {\n const spec = specs[i];\n const relationAlias = `eagerRelation${i}`;\n\n if (spec.type === 'one') {\n this.#buildJoinOne(resultQuery, spec, relationAlias);\n } else {\n this.#buildJoinMany(resultQuery, spec, relationAlias, i);\n }\n }\n\n return resultQuery;\n }\n\n #buildJoinOne(\n resultQuery: Knex.QueryBuilder,\n spec: ValidatedSpec & { type: 'one' },\n relationAlias: string\n ): void {\n const knex = this.#knex;\n const foreignTable = spec.foreignQuery;\n const foreignTableName = (foreignTable as any)._single?.table;\n\n if (!foreignTableName) {\n throw new Error(\n `Could not determine table name from foreignQuery for \"${spec.as}\". ` +\n 'Make sure foreignQuery is created via knex(\"tableName\").'\n );\n }\n\n resultQuery.select(\n knex.raw(':relationAlias:.:as:->0 as :as:', {\n relationAlias,\n as: spec.as\n })\n );\n\n const subquery = knex\n .from(foreignTable.as(foreignTableName))\n .select(\n knex.raw(':foreignTable:.:foreignColumn:', {\n foreignTable: foreignTableName,\n foreignColumn: spec.foreignColumn\n })\n )\n .select(\n knex.raw('jsonb_agg(:foreignTable:) as :as:', {\n foreignTable: foreignTableName,\n as: spec.as\n })\n )\n .groupByRaw(':foreignTable:.:foreignColumn:', {\n foreignTable: foreignTableName,\n foreignColumn: spec.foreignColumn\n })\n .as(relationAlias);\n\n const joinMethod = spec.required ? 'join' : 'leftJoin';\n resultQuery[joinMethod](subquery, function () {\n this.on(\n knex.raw(\n ':relationAlias:.:foreignColumn: = :originalQuery:.:localColumn:',\n {\n originalQuery: 'originalQuery',\n relationAlias,\n foreignColumn: spec.foreignColumn,\n localColumn: spec.localColumn\n }\n )\n );\n });\n }\n\n #buildJoinMany(\n resultQuery: Knex.QueryBuilder,\n spec: ValidatedSpec & { type: 'many' },\n relationAlias: string,\n i: number\n ): void {\n const knex = this.#knex;\n const filterName = `withFilter${i}`;\n\n const hasLimitOffset =\n (spec.limit !== null && spec.limit > 0) ||\n (spec.offset !== null && spec.offset > 0);\n\n const orderByColumn = spec.orderBy\n ? spec.orderBy.column\n : spec.foreignColumn;\n const orderByDirection = spec.orderBy ? spec.orderBy.direction : 'asc';\n\n if (hasLimitOffset) {\n resultQuery.with(\n filterName,\n knex\n .from(\n spec.foreignQuery\n .clone()\n .whereIn(\n spec.foreignColumn,\n knex\n .from(\n knex.raw(':originalQuery:', {\n originalQuery: 'originalQuery'\n })\n )\n .distinct(spec.localColumn)\n )\n .as(`__wf_inner_${i}`)\n )\n .select(`__wf_inner_${i}.*`)\n .select(\n knex.raw(\n `row_number() over(partition by :foreignColumn: order by :orderByColumn: ${orderByDirection}) as \"__rn__\"`,\n {\n foreignColumn: spec.foreignColumn,\n orderByColumn\n }\n )\n )\n );\n } else {\n resultQuery.with(\n filterName,\n spec.foreignQuery.clone().whereIn(\n spec.foreignColumn,\n knex\n .from(\n knex.raw(':originalQuery:', {\n originalQuery: 'originalQuery'\n })\n )\n .distinct(spec.localColumn)\n )\n );\n }\n\n const aggSubquery = knex.from(filterName);\n\n if (hasLimitOffset) {\n const hasLimit = spec.limit !== null && spec.limit > 0;\n const hasOffset = spec.offset !== null && spec.offset > 0;\n const effectiveOffset = spec.offset ?? 0;\n const effectiveLimit = effectiveOffset + (spec.limit ?? 0);\n\n const condition =\n hasLimit && hasOffset\n ? '\"__rn__\" > :offset and \"__rn__\" <= :limit'\n : hasLimit\n ? '\"__rn__\" <= :limit'\n : '\"__rn__\" > :offset';\n\n aggSubquery.whereRaw(condition, {\n limit: effectiveLimit,\n offset: effectiveOffset\n });\n\n aggSubquery.select(\n knex.raw(':foreignColumn:', {\n foreignColumn: spec.foreignColumn\n })\n );\n aggSubquery.select(\n knex.raw(\n \"coalesce(jsonb_agg(to_jsonb(:filterName:) - '__rn__' order by \\\"__rn__\\\"), '[]'::jsonb) as :as:\",\n { filterName, as: spec.as }\n )\n );\n } else {\n aggSubquery.select(\n knex.raw(':foreignColumn:', {\n foreignColumn: spec.foreignColumn\n })\n );\n\n const orderClause = spec.orderBy\n ? `jsonb_agg(:filterName: order by :filterName:.:orderByColumn: ${orderByDirection})`\n : 'jsonb_agg(:filterName:)';\n\n aggSubquery.select(\n knex.raw(\n `coalesce(${orderClause}, '[]'::jsonb) as :as:`,\n spec.orderBy\n ? { filterName, orderByColumn, as: spec.as }\n : { filterName, as: spec.as }\n )\n );\n }\n\n aggSubquery.groupByRaw(':foreignColumn:', {\n foreignColumn: spec.foreignColumn\n });\n\n const subquery = aggSubquery.as(relationAlias);\n\n resultQuery.select(\n knex.raw(\"coalesce(:relationAlias:.:as:, '[]'::jsonb) as :as:\", {\n relationAlias,\n as: spec.as\n })\n );\n\n resultQuery.leftJoin(subquery, function () {\n this.on(\n knex.raw(\n ':relationAlias:.:foreignColumn: = :originalQuery:.:localColumn:',\n {\n relationAlias,\n foreignColumn: spec.foreignColumn,\n originalQuery: 'originalQuery',\n localColumn: spec.localColumn\n }\n )\n );\n });\n }\n\n // =======================================================================\n // Result mapping\n // =======================================================================\n\n /**\n * Map a SQL result row (column names) back to schema property names.\n * Also handles joined fields (which are already named by `as`).\n * Delegates to `#mapPolymorphicRow` for polymorphic schemas.\n */\n #mapRow(row: Record<string, any>): Record<string, any> {\n if (!row) return row;\n\n const variantConfig = this.#getVariantConfig();\n if (variantConfig) {\n return this.#mapPolymorphicRow(row, variantConfig);\n }\n\n const { colToProp } = buildColumnMap(this.#localSchema);\n const result: Record<string, any> = {};\n\n // Map known columns back to property names\n for (const [colName, value] of Object.entries(row)) {\n const propName = colToProp.get(colName);\n if (propName) {\n result[propName] = value;\n } else {\n // Unknown column (e.g., joined field, raw expression) — pass through\n result[colName] = value;\n }\n }\n\n return result;\n }\n\n /**\n * Clean a row that has eager-loaded relations (apply mappers, then map columns).\n */\n #cleanAndMapRow(row: Record<string, any>): Record<string, any> {\n const oneSpecs = this.#specs.filter(\n (s): s is ValidatedSpec & { type: 'one' } => s.type === 'one'\n );\n const manySpecs = this.#specs.filter(\n (s): s is ValidatedSpec & { type: 'many' } => s.type === 'many'\n );\n const cleaned = clearRow(row, oneSpecs, manySpecs);\n return this.#mapRow(cleaned);\n }\n\n // =======================================================================\n // Column mapping helpers\n // =======================================================================\n\n /**\n * Map a schema-shaped object (property keys) to a SQL object (column names).\n * Used for INSERT / UPDATE.\n */\n #mapObjectToColumns(obj: Record<string, any>): Record<string, any> {\n const { propToCol } = buildColumnMap(this.#localSchema);\n const result: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const colName = propToCol.get(key);\n if (colName) {\n result[colName] = value;\n } else {\n // Unknown key — pass through (could be a raw column)\n result[key] = value;\n }\n }\n\n return result;\n }\n\n /**\n * Map a Record<propertyKey, value> to Record<columnName, value>.\n * Used for `.where({ name: 'John' })` style calls.\n */\n #mapRecordToColumns(record: Record<string, any>): Record<string, any> {\n return this.#mapObjectToColumns(record);\n }\n\n /**\n * Resolve a column argument that could be a ColumnRef, Knex.Raw, or callback.\n * Returns the resolved string or passes through Knex.Raw.\n */\n #resolveColumnArg(col: any): string | Knex.Raw {\n if (typeof col === 'string') {\n return this.#resolveColumn(col, 'column');\n }\n if (typeof col === 'function') {\n // Property descriptor accessor\n return this.#resolveColumn(col, 'column');\n }\n // Knex.Raw — pass through\n return col;\n }\n\n /**\n * Detect if a function is a property descriptor accessor (takes tree, returns descriptor)\n * vs a knex sub-builder callback (takes builder, returns void).\n *\n * Heuristic: property descriptor accessors are arrow functions that access\n * tree properties. We cannot distinguish at runtime, so we try the accessor\n * and fallback to callback if it fails.\n *\n * For safety, we check if the function parameter count can help:\n * - Knex callbacks typically have 1 parameter named `builder` or `qb`\n * - Property accessors typically have 1 parameter named `t` or similar\n *\n * Since both are `(arg) => result`, we use a try/catch approach:\n * attempt to resolve as column accessor first.\n */\n #isColumnAccessor(fn: Function): boolean {\n // Try to invoke the accessor with the property descriptor tree\n try {\n const tree = ObjectSchemaBuilder.getPropertiesFor(\n this.#localSchema as any\n );\n const result = fn(tree);\n // If it returns a valid property descriptor, it's an accessor\n if (\n result &&\n typeof result === 'object' &&\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in result\n ) {\n return true;\n }\n } catch {\n // Not an accessor\n }\n return false;\n }\n\n // =======================================================================\n // Execution\n // =======================================================================\n\n /**\n * Return the raw SQL string that would be executed, for debugging.\n * Does not execute the query against the database.\n */\n toQuery(): string {\n return this.#getQuery().toQuery();\n }\n\n /**\n * Returns the underlying Knex query builder. Useful when passing this\n * query as a `foreignQuery` in `.joinOne()` / `.joinMany()`, or any context\n * that expects a raw `Knex.QueryBuilder`.\n */\n toKnexQuery(): Knex.QueryBuilder {\n return this.#getQuery();\n }\n\n /**\n * Alias for {@link toQuery} — returns the raw SQL string.\n */\n toString(): string {\n return this.#getQuery().toString();\n }\n\n /**\n * Execute the query and return all matching rows, mapped back to schema\n * property names.\n *\n * @returns A promise that resolves to an array of result objects typed as\n * `TResult[]`.\n *\n * @example\n * ```ts\n * const users = await query(db, UserSchema).execute();\n * ```\n */\n async execute(): Promise<TResult[]> {\n const query = this.#getQuery();\n const rows = await query;\n\n if (!rows) return [];\n if (!Array.isArray(rows))\n return [this.#cleanAndMapRow(rows)] as TResult[];\n\n return rows.map((row: any) => this.#cleanAndMapRow(row)) as TResult[];\n }\n\n /**\n * Execute the query and return only the first row, or `undefined` if no\n * rows match.\n *\n * @example\n * ```ts\n * const user = await query(db, UserSchema).where(t => t.id, id).first();\n * if (user) { /* ... *\\/ }\n * ```\n */\n async first(): Promise<TResult | undefined> {\n const query = this.#getQuery().first();\n const row = await query;\n\n if (!row) return undefined;\n return this.#cleanAndMapRow(row) as TResult;\n }\n\n /**\n * Execute the query and return an array of values for a single column.\n *\n * @param column - Column reference (property accessor or string key) for\n * the column whose values should be returned.\n * @returns A promise resolving to an array of values for that column.\n *\n * @example\n * ```ts\n * const names = await query(db, UserSchema).pluck(t => t.name);\n * // names: string[]\n * ```\n */\n async pluck<K extends keyof TResult & string>(\n column: ColumnRef<TLocalSchema>\n ): Promise<TResult[K][]> {\n const col = this.#resolveColumn(column, 'pluck') as string;\n const rows = await this.#buildQuery().select(col);\n return rows.map(\n (row: any) => row[col] ?? row[column as string]\n ) as TResult[K][];\n }\n\n /**\n * Thenable implementation — allows the builder to be awaited directly\n * without calling {@link execute} explicitly.\n *\n * @example\n * ```ts\n * const users = await query(db, UserSchema).where(t => t.name, 'Alice');\n * // Equivalent to: await query(db, UserSchema).where(...).execute()\n * ```\n */\n // biome-ignore lint/suspicious/noThenProperty: intentional thenable for `await builder` support\n then<TReturn1 = TResult[], TReturn2 = never>(\n onfulfilled?:\n | ((value: TResult[]) => TReturn1 | PromiseLike<TReturn1>)\n | null,\n onrejected?: ((reason: any) => TReturn2 | PromiseLike<TReturn2>) | null\n ): Promise<TReturn1 | TReturn2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n}\n\n// ---------------------------------------------------------------------------\n// query() — main entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Create a typed {@link SchemaQueryBuilder} for the table described by `schema`.\n *\n * The schema must have a table name configured via `.hasTableName()`.\n * Column name mappings set via `.hasColumnName()` are applied automatically\n * to all query methods. The returned builder is thenable — you can `await` it\n * directly to execute the query and get `TResult[]`.\n *\n * @param knex - A configured Knex instance.\n * @param schema - The `ObjectSchemaBuilder` describing the table.\n * @returns A new {@link SchemaQueryBuilder} ready for chaining.\n *\n * @example\n * ```ts\n * import knex from 'knex';\n * import { query, object, string, number } from '@cleverbrush/knex-schema';\n *\n * const UserSchema = object({ id: number(), name: string() }).hasTableName('users');\n * const db = knex({ client: 'pg', connection: process.env.DB_URL });\n *\n * const users = await query(db, UserSchema).where(t => t.name, 'like', 'A%');\n * ```\n */\nexport function query<\n TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n>(\n knex: Knex,\n schema: TLocalSchema\n): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;\n\n/**\n * Create a typed {@link SchemaQueryBuilder} from an existing Knex query builder.\n *\n * Use this overload when you need to supply a pre-configured base query —\n * for example one that already has a sub-query, CTE, or a schema scope applied.\n *\n * @param knex - A configured Knex instance.\n * @param schema - The `ObjectSchemaBuilder` describing the table.\n * @param baseQuery - An existing `Knex.QueryBuilder` to use as the base.\n * @returns A new {@link SchemaQueryBuilder} wrapping `baseQuery`.\n *\n * @example\n * ```ts\n * // Use a scoped base query (e.g. soft-delete filter applied globally)\n * const base = db('users').where('deleted_at', null);\n * const activeUsers = await query(db, UserSchema, base).where(t => t.age, '>', 18);\n * ```\n */\nexport function query<\n TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n>(\n knex: Knex,\n schema: TLocalSchema,\n baseQuery: Knex.QueryBuilder\n): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;\n\nexport function query<\n TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n>(\n knex: Knex,\n schema: TLocalSchema,\n baseQuery?: Knex.QueryBuilder\n): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>> {\n return new SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>(\n knex,\n schema,\n baseQuery\n );\n}\n\n// ---------------------------------------------------------------------------\n// createQuery() — knex-bound factory\n// ---------------------------------------------------------------------------\n\n/** Bound query function returned by {@link createQuery}. */\nexport interface BoundQuery {\n <\n TLocalSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n >(\n schema: TLocalSchema\n ): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;\n <\n TLocalSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n >(\n schema: TLocalSchema,\n baseQuery: Knex.QueryBuilder\n ): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;\n /**\n * Return a version of this bound factory whose queries all run within the\n * given Knex transaction. Equivalent to calling `.transacting(trx)` on\n * each individual builder, but more convenient when every query in a block\n * must share the same transaction.\n *\n * @example\n * ```ts\n * const db = createQuery(knex);\n *\n * await knex.transaction(async trx => {\n * const dbTrx = db.withTransaction(trx);\n * const user = await dbTrx(UserSchema).insert({ name: 'Alice' });\n * await dbTrx(PostSchema).insert({ authorId: user.id, title: 'Hello' });\n * });\n * ```\n */\n withTransaction(trx: Knex.Transaction): BoundQuery;\n /**\n * Start a Knex transaction and run `callback` inside it, passing a\n * transaction-bound `BoundQuery` factory as the argument. The transaction\n * is committed when the callback resolves and rolled back if it rejects.\n *\n * This is the callback-style counterpart to {@link withTransaction} — you\n * don't need to obtain a `Knex.Transaction` object yourself.\n *\n * @param callback - An async function that receives a transaction-bound\n * `BoundQuery` and returns a value. The returned value is forwarded as\n * the resolved value of the outer `Promise`.\n * @returns A `Promise` that resolves with the value returned by `callback`.\n *\n * @example\n * ```ts\n * const db = createQuery(knex);\n *\n * const user = await db.transaction(async dbTrx => {\n * const newUser = await dbTrx(UserSchema).insert({ name: 'Alice' });\n * await dbTrx(PostSchema).insert({ authorId: newUser.id, title: 'Hello' });\n * return newUser;\n * });\n * ```\n */\n transaction<T>(callback: (db: BoundQuery) => Promise<T>): Promise<T>;\n}\n\n/**\n * Bind a Knex instance once and get back a `query(schema)` function that\n * doesn't require repeating the knex argument on every call.\n *\n * @param knex - A configured Knex instance.\n * @returns A bound query factory: `(schema, baseQuery?) => SchemaQueryBuilder`.\n *\n * @example\n * ```ts\n * import Knex from 'knex';\n * import { createQuery } from '@cleverbrush/knex-schema';\n *\n * const knex = Knex({ client: 'pg', connection: process.env.DB_URL });\n * const query = createQuery(knex);\n *\n * // No knex argument needed from here on\n * const users = await query(UserSchema).where(t => t.role, '=', 'admin');\n * const post = await query(PostSchema).where(t => t.id, '=', 42).first();\n *\n * // Optional base query (e.g. soft-delete scope applied globally)\n * const active = query(UserSchema, knex('users').where('deleted_at', null));\n * ```\n */\nexport function createQuery(knexInstance: Knex): BoundQuery {\n function boundQuery<\n TLocalSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n >(\n schema: TLocalSchema,\n baseQuery?: Knex.QueryBuilder\n ): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>> {\n return baseQuery\n ? query(knexInstance, schema, baseQuery)\n : query(knexInstance, schema);\n }\n\n (boundQuery as BoundQuery).withTransaction = (\n trx: Knex.Transaction\n ): BoundQuery => createQuery(trx as unknown as Knex);\n\n (boundQuery as BoundQuery).transaction = <T>(\n callback: (db: BoundQuery) => Promise<T>\n ): Promise<T> =>\n knexInstance.transaction(trx =>\n callback(createQuery(trx as unknown as Knex))\n );\n\n return boundQuery as BoundQuery;\n}\n","// @cleverbrush/knex-schema — Validation of join specs\n\nimport type { ObjectSchemaBuilder } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { resolveColumnRef } from './columns.js';\nimport { getTableName } from './extension.js';\nimport { MAPPERS } from './mappers.js';\nimport type {\n JoinManySpec,\n JoinOneSpec,\n ValidatedJoinManySpec,\n ValidatedJoinOneSpec\n} from './types.js';\n\n/**\n * Resolve foreignQuery: use the provided one, or auto-derive from\n * the foreign schema's tableName extension.\n * Also normalizes SchemaQueryBuilder instances to raw Knex.QueryBuilder\n * by calling `.toKnexQuery()` if available.\n */\nfunction resolveForeignQuery(\n spec: {\n foreignQuery?: Knex.QueryBuilder | { toKnexQuery(): Knex.QueryBuilder };\n foreignSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>;\n },\n knex: Knex\n): Knex.QueryBuilder {\n if (spec.foreignQuery) {\n if ('toKnexQuery' in spec.foreignQuery) {\n return spec.foreignQuery.toKnexQuery();\n }\n return spec.foreignQuery as Knex.QueryBuilder;\n }\n\n const tableName = getTableName(spec.foreignSchema);\n return knex(tableName);\n}\n\nexport function validateJoinOne(\n spec: JoinOneSpec<any, any, any, any>,\n localSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n knex: Knex\n): ValidatedJoinOneSpec {\n const localColumn = resolveColumnRef(\n spec.localColumn,\n localSchema,\n 'localColumn'\n );\n const foreignColumn = resolveColumnRef(\n spec.foreignColumn,\n spec.foreignSchema,\n 'foreignColumn'\n );\n if (typeof spec.as !== 'string' || !spec.as) {\n throw new Error('as must be a non-empty string');\n }\n\n const foreignQuery = resolveForeignQuery(spec, knex);\n const required = spec.required !== false;\n\n if (spec.mappers !== undefined) {\n validateMappers(spec.mappers);\n }\n\n return {\n localColumn,\n foreignColumn,\n as: spec.as,\n required,\n foreignQuery,\n mappers: spec.mappers as\n | Record<string, ((value: any) => any) | string>\n | undefined\n };\n}\n\nexport function validateJoinMany(\n spec: JoinManySpec<any, any, any>,\n localSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n knex: Knex\n): ValidatedJoinManySpec {\n const localColumn = resolveColumnRef(\n spec.localColumn,\n localSchema,\n 'localColumn'\n );\n const foreignColumn = resolveColumnRef(\n spec.foreignColumn,\n spec.foreignSchema,\n 'foreignColumn'\n );\n if (typeof spec.as !== 'string' || !spec.as) {\n throw new Error('as must be a non-empty string');\n }\n\n const foreignQuery = resolveForeignQuery(spec, knex);\n\n if (spec.mappers !== undefined) {\n validateMappers(spec.mappers);\n }\n\n const limit =\n Number.isFinite(spec.limit) && (spec.limit as number) > 0\n ? (spec.limit as number)\n : null;\n const offset =\n Number.isFinite(spec.offset) && (spec.offset as number) > 0\n ? (spec.offset as number)\n : null;\n const orderBy = spec.orderBy\n ? {\n column: resolveColumnRef(\n spec.orderBy.column,\n spec.foreignSchema,\n 'orderBy.column'\n ),\n direction: spec.orderBy.direction ?? ('asc' as const)\n }\n : null;\n\n return {\n localColumn,\n foreignColumn,\n as: spec.as,\n foreignQuery,\n limit,\n offset,\n orderBy,\n mappers: spec.mappers as\n | Record<string, ((value: any) => any) | string>\n | undefined\n };\n}\n\nfunction validateMappers(mappers: Record<string, unknown>): void {\n if (typeof mappers !== 'object' || mappers === null) {\n throw new Error('mappers must be an object');\n }\n for (const key of Object.keys(mappers)) {\n const m = mappers[key];\n if (typeof m === 'string') {\n if (typeof MAPPERS[m] !== 'function') {\n throw new Error(\n `mapper for \"${key}\": unknown built-in mapper name \"${m}\"`\n );\n }\n } else if (typeof m !== 'function') {\n throw new Error(\n `mapper for \"${key}\" must be a function or a built-in mapper name`\n );\n }\n }\n}\n\nexport function validateUniqueFieldNames(specs: Array<{ as: string }>): void {\n const seen = new Set<string>();\n for (const spec of specs) {\n if (seen.has(spec.as)) {\n throw new Error(`duplicate field name: ${spec.as}`);\n }\n seen.add(spec.as);\n }\n}\n","// @cleverbrush/knex-schema — Schema snapshot serialization\n\nimport { readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport type { Entity } from './entity.js';\nimport { getPolymorphicVariantSchemas, getTableName } from './extension.js';\nimport { entitySchemaToTableState } from './migration.js';\nimport type { SchemaSnapshot } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Builders\n// ---------------------------------------------------------------------------\n\n/**\n * Build a {@link SchemaSnapshot} from a set of entities without a live DB.\n *\n * Handles polymorphic (CTI) entities by including each variant table.\n * Deduplicates tables so STI variants sharing a base table are only included\n * once.\n *\n * @param entities - The entities from your `EntityMap`.\n * @returns A snapshot reflecting the current code-first schema state.\n *\n * @example\n * ```ts\n * const snapshot = entitiesToSnapshot(Object.values(entityMap));\n * writeSnapshot('./migrations/snapshot.json', snapshot);\n * ```\n */\nexport function entitiesToSnapshot(\n entities: Entity<any, any>[]\n): SchemaSnapshot {\n const tables: SchemaSnapshot['tables'] = {};\n\n for (const entity of entities) {\n const schema = entity.schema;\n const tableName = getTableName(schema);\n if (!tables[tableName]) {\n tables[tableName] = entitySchemaToTableState(schema);\n }\n\n for (const vs of getPolymorphicVariantSchemas(schema)) {\n const variantTableName = vs.getExtension('tableName') as\n | string\n | undefined;\n if (variantTableName && !tables[variantTableName]) {\n tables[variantTableName] = entitySchemaToTableState(vs);\n }\n }\n }\n\n return { version: 1, tables };\n}\n\n// ---------------------------------------------------------------------------\n// I/O\n// ---------------------------------------------------------------------------\n\n/**\n * Load a {@link SchemaSnapshot} from disk.\n *\n * Returns an empty snapshot (no tables) when the file does not exist — this\n * is the \"first run\" case, which causes `migrate generate` to emit a single\n * migration containing `CREATE TABLE` for every entity.\n *\n * @param snapshotPath - Absolute or cwd-relative path to `snapshot.json`.\n * @returns The parsed snapshot, or `{ version: 1, tables: {} }` if missing or\n * unreadable.\n */\nexport function loadSnapshot(snapshotPath: string): SchemaSnapshot {\n try {\n const raw = readFileSync(resolve(snapshotPath), 'utf-8');\n const parsed = JSON.parse(raw) as SchemaSnapshot;\n if (\n parsed.version !== 1 ||\n parsed.tables == null ||\n typeof parsed.tables !== 'object'\n ) {\n return { version: 1, tables: {} };\n }\n return parsed;\n } catch {\n return { version: 1, tables: {} };\n }\n}\n\n/**\n * Write a {@link SchemaSnapshot} to disk atomically (temp-file + rename) with\n * deterministic key ordering so diffs in version control are minimal.\n *\n * @param snapshotPath - Absolute or cwd-relative path to write `snapshot.json`.\n * @param snapshot - The snapshot to serialize.\n */\nexport function writeSnapshot(\n snapshotPath: string,\n snapshot: SchemaSnapshot\n): void {\n const absPath = resolve(snapshotPath);\n const tmp = absPath + '.tmp';\n writeFileSync(\n tmp,\n JSON.stringify(_sortSnapshot(snapshot), null, 2) + '\\n',\n 'utf-8'\n );\n renameSync(tmp, absPath);\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** @internal Sort all keys in the snapshot for deterministic JSON output. */\nfunction _sortSnapshot(snapshot: SchemaSnapshot): SchemaSnapshot {\n const sortedTables: SchemaSnapshot['tables'] = {};\n for (const tableName of Object.keys(snapshot.tables).sort()) {\n const state = snapshot.tables[tableName];\n sortedTables[tableName] = {\n columns: Object.fromEntries(\n Object.entries(state.columns).sort(([a], [b]) =>\n a.localeCompare(b)\n )\n ),\n indexes: [...state.indexes].sort((a, b) =>\n a.name.localeCompare(b.name)\n ),\n foreignKeys: [...state.foreignKeys].sort((a, b) =>\n a.constraintName.localeCompare(b.constraintName)\n ),\n checks: [...state.checks].sort((a, b) =>\n a.name.localeCompare(b.name)\n )\n };\n }\n return { version: 1, tables: sortedTables };\n}\n"],"mappings":"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","names":["ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","columnMapCache","buildColumnMap","schema","cached","properties","propToCol","colToProp","propKey","propSchema","colName","getColumnName","result","jsonPathRaw","knex","col","jsonPath","pathLiteral","resolveColumnRef","ref","label","topProp","tree","ObjectSchemaBuilder","descriptor","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","pointer","segments","s","resolvePropertyKey","getPrimaryKeyColumns","introspected","extensions","composite","propertyKeys","columnNames","entry","getRowVersionColumn","rv","resolveColumnType","table","col","introspected","ext","maxLen","applyDefault","column","defaultValue","knex","generateCreateTable","schema","tableName","getTableName","tableExt","extensionManagedCols","builder","properties","propKey","propSchema","getColumnName","propIntrospected","fkBuilder","idx","unq","chk","rawCol","rawIndexes","rawIdx","generateCreateTableSource","lines","line","_colTypeCode","_fmtDefault","cols","rawIndexLines","ri","up","down","value","generateCreatePolymorphicTables","result","variantSchemas","getPolymorphicVariantSchemas","variantSchema","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","Entity","_Entity","schema","spec","existing","next","navSel","_localSel","remoteSel","opts","navName","foreignSchema","remoteKey","localSel","_remoteSel","localKey","through","sel","discKey","key","variant","fkSel","builder","fkColumn","resolveCtiForeignKeyColumn","nextVariants","entityRelationsToVariantRelations","resolveInlineVariantRelations","body","isEntity","varSchema","variants","newSchema","applyVariantsToSchema","existingRelations","selector","tree","ObjectSchemaBuilder","descriptor","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","inner","propSchema","intro","varEntity","rels","propToCol","buildColumnMap","r","fkPropName","fkColName","propKey","getColumnName","relations","result","name","foreignKey","targetSchema","defineEntity","MAPPERS","value","mapValue","mapper","mapObject","obj","mappers","result","key","clearRow","row","oneSpecs","manySpecs","spec","fieldName","k","normalizeDbState","columns","indexes","foreignKeys","checks","colMap","row","idxList","fkList","chkList","introspectDatabase","knex","tableName","schemaTypeToDbType","introspected","ext","entitySchemaToTableState","schema","getTableName","properties","tableExt","propKey","propSchema","col","getColumnName","propIntrospected","ts","createdAtCol","updatedAtCol","delCol","idx","idxName","unq","unqName","diffSchema","dbState","addColumns","dropColumns","alterColumns","addIndexes","dropIndexes","addForeignKeys","dropForeignKeys","extensionOwnedDefaults","schemaColumns","dbCol","changes","expectedNullable","snapshotDefault","schemaDefault","fk","colName","schemaIndexNames","dbIdx","ps","generateMigration","diff","up","down","buildAlterTableFragments","full","tableExistsInDb","isDiffEmpty","applyDiff","constraintName","table","column","buildColumnFromDbType","fkBuilder","key","change","builder","generateMigrationsForContext","entities","prevSnapshot","tableEntries","entity","vs","getPolymorphicVariantSchemas","variantTableName","seen","uniqueEntries","e","sorted","topologicalSort","upParts","downParts","currentTableNames","snapshotState","generateCreateTableSource","state","generateDropTableSource","isEmpty","nextTables","colLines","line","upLines","downLines","mapTypeToKnex","formatDefault","toVal","fromVal","cols","name","dbType","entries","tableSet","deps","depSet","inDegree","graph","dep","queue","t","deg","sortedNames","dependent","newDeg","sortedSet","remaining","byName","type","value","rawQuery","knex","schema","queryOrSql","bindings","rows","result","colToProp","buildColumnMap","row","mapped","key","value","propName","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","resolveForeignQuery","spec","knex","tableName","getTableName","validateJoinOne","localSchema","localColumn","resolveColumnRef","foreignColumn","foreignQuery","required","validateMappers","validateJoinMany","limit","offset","orderBy","mappers","key","m","MAPPERS","validateUniqueFieldNames","specs","seen","OnConflictBuilder","#knex","#localSchema","#conflictColumns","knex","localSchema","_parent","conflictColumns","data","updateData","#execute","mode","tableName","getTableName","timestamps","beforeHooks","processed","hook","propToCol","buildColumnMap","mapped","key","val","qb","mergeObj","rows","colToProp","result","col","SchemaQueryBuilder","_SchemaQueryBuilder","#baseQuery","#specs","#tableName","#explicitSelects","#selectionMode","#appliedProjection","#includeDeleted","#onlyDeleted","#skipDefaultScope","#variantConfig","#enabledVariants","#variantWhereFilters","#variantRelationIncludes","#cachedBuiltQuery","#invalidateCache","#getQuery","#buildQuery","baseQuery","#resolveColumn","ref","label","resolveColumnRef","#getSoftDelete","#getDefaultScope","fn","#getTimestamps","#getVariantConfig","raw","getVariants","discCol","#ALLOWED_OPS","#applyVariantJoins","base","variantConfig","baseTable","basePkCol","#findPrimaryKeyColumn","spec","variantAlias","variantTable","fkCol","variantProps","propKey","colName","vrInc","variantSpec","relSpec","r","foreignSchema","#resolveSchema","foreignTableName","relAlias","localCol","foreignCol","onExpr","foreignKnex","selectionSql","#buildVariantRelationSelect","sel","filter","discColFull","customize","foreignProps","columnsToSelect","probe","explicit","p","#mapPolymorphicRow","row","baseColToProp","value","propName","discPropKey","discValue","varColToProp","prefix","fkAlias","origCol","variantSpec3","relColToProp","nested","anyNonNull","#getEffectiveBaseQuery","effectiveBase","cloned","softDelete","defaultScopeFn","proxy","schema","pk","getPrimaryKeyColumns","validated","validateJoinOne","validateUniqueFieldNames","validateJoinMany","columnOrRaw","args","#isColumnAccessor","#mapRecordToColumns","#resolveColumnArg","column","values","range","sql","bindings","callback","path","operator","client","op","escapedOp","jsonPath","direction","columns","resolved","c","n","tree","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","#assertNotProjection","aliasMap","alias","descriptor","method","#assertNotExplicitSelect","processedData","#mapObjectToColumns","#mapRow","afterHooks","d","m","results","cols","opts","conflictCols","updateCols","hooks","requestedChunkSize","bindingsPerRow","safeChunkCap","chunkSize","i","chunk","k","inserted","mappedRow","updates","#resolvePkColumns","entry","setData","setMapped","whereRec","pkValues","allSetCols","updateExpr","fragments","conditions","trx","builder","relationName","relation","matches","vKey","vSpec","localColumn","foreignColumn","foreignQuery1","foreignQuery2","foreignQuery3","through","foreignQuery","variantKey","name","projection","getProjections","sqlCols","scopeFn","qualifiedColumn","keys","page","pageSize","countResult","total","totalPages","hasMore","resolvePropertyKey","nextCursor","queryBase","specs","requiredLocalColumns","s","cteQuery","extraColumns","selectedSet","resultQuery","relationAlias","#buildJoinOne","#buildJoinMany","foreignTable","subquery","joinMethod","filterName","hasLimitOffset","orderByColumn","orderByDirection","aggSubquery","hasLimit","hasOffset","effectiveOffset","effectiveLimit","condition","orderClause","#cleanAndMapRow","oneSpecs","manySpecs","cleaned","clearRow","obj","record","onfulfilled","onrejected","query","createQuery","knexInstance","boundQuery","readFileSync","renameSync","writeFileSync","resolve","entitiesToSnapshot","entities","tables","entity","schema","tableName","getTableName","entitySchemaToTableState","vs","getPolymorphicVariantSchemas","variantTableName","loadSnapshot","snapshotPath","raw","readFileSync","resolve","parsed","writeSnapshot","snapshot","absPath","tmp","writeFileSync","_sortSnapshot","renameSync","sortedTables","state","a","b"]}
|
|
1
|
+
{"version":3,"sources":["../src/columns.ts","../src/ddl.ts","../src/entity.ts","../src/mappers.ts","../src/migration.ts","../src/raw.ts","../src/operations/select.ts","../src/operations/helpers.ts","../src/operations/state.ts","../src/operations/insert.ts","../src/operations/delete.ts","../src/validate.ts","../src/operations/join.ts","../src/operations/where.ts","../src/operations/pagination.ts","../src/operations/update.ts","../src/SchemaQueryBuilder.ts","../src/snapshot.ts"],"sourcesContent":["// @cleverbrush/knex-schema — Column resolution and mapping\n\nimport type { SchemaBuilder } from '@cleverbrush/schema';\nimport {\n ObjectSchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { getColumnName } from './extension.js';\nimport type { ColumnRef } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Column map cache (schema → { propToCol, colToProp })\n// ---------------------------------------------------------------------------\n\ninterface ColumnMapResult {\n propToCol: Map<string, string>;\n colToProp: Map<string, string>;\n}\n\nconst columnMapCache = new WeakMap<object, ColumnMapResult>();\n\n/**\n * Build a bidirectional column map from an ObjectSchemaBuilder's properties.\n * Uses `getExtension('columnName')` per property, falling back to the property key.\n * Result is cached per schema instance via WeakMap.\n */\nexport function buildColumnMap(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): ColumnMapResult {\n const cached = columnMapCache.get(schema);\n if (cached) return cached;\n\n const introspected = schema.introspect() as any;\n const properties: Record<\n string,\n SchemaBuilder<any, any, any>\n > = introspected.properties ?? {};\n\n const propToCol = new Map<string, string>();\n const colToProp = new Map<string, string>();\n\n for (const propKey of Object.keys(properties)) {\n const propSchema = properties[propKey];\n const colName = getColumnName(propSchema, propKey);\n\n propToCol.set(propKey, colName);\n colToProp.set(colName, propKey);\n }\n\n const result: ColumnMapResult = { propToCol, colToProp };\n columnMapCache.set(schema, result);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Resolve a ColumnRef (string | accessor) to a SQL column name or Knex.Raw\n// ---------------------------------------------------------------------------\n\n/**\n * Build a `Knex.Raw` expression for accessing a nested JSON/JSONB path.\n *\n * - Single-key path: `\"col\"->>'key'` (text output, `->>` operator).\n * - Multi-key path: `\"col\"#>>'{a,b,...}'` (text output, `#>>` operator).\n *\n * Both use positional bindings to prevent SQL injection.\n */\nfunction jsonPathRaw(knex: Knex, col: string, jsonPath: string[]): Knex.Raw {\n if (jsonPath.length === 1) {\n return knex.raw('??->>?', [col, jsonPath[0]]);\n }\n // #>> expects a text array literal, e.g. '{address,city}'\n const pathLiteral = `{${jsonPath.join(',')}}`;\n return knex.raw('??#>>?', [col, pathLiteral]);\n}\n\n/**\n * Resolve a ColumnRef to a plain SQL column name (or a Knex.Raw expression for\n * nested JSON paths when `knex` is supplied).\n *\n * - String refs are treated as **property keys** (or dot-separated nested paths\n * such as `'address.city'`) and translated to column names via the column map.\n * - Function refs (property accessor) are resolved via PropertyDescriptorTree,\n * then translated to column names. Nested accessors (e.g. `t => t.address.city`)\n * produce a `Knex.Raw` JSON-path expression when `knex` is provided.\n *\n * @param ref - Column reference (property key, dotted path, or accessor fn).\n * @param schema - Root ObjectSchemaBuilder.\n * @param label - Human-readable label for error messages.\n * @param knex - Knex instance. Required for nested JSON-path refs; when omitted\n * and a nested path is detected, an error is thrown.\n */\nexport function resolveColumnRef(\n ref: ColumnRef<any>,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n label: string,\n knex: Knex\n): string | Knex.Raw;\nexport function resolveColumnRef(\n ref: ColumnRef<any>,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n label: string\n): string;\nexport function resolveColumnRef(\n ref: ColumnRef<any>,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n label: string,\n knex?: Knex\n): string | Knex.Raw {\n if (typeof ref === 'string') {\n if (!ref) throw new Error(`${label} must be a non-empty string`);\n\n // Dotted paths like 'address.city' — first segment is the top-level prop.\n if (ref.includes('.')) {\n const [topProp, ...jsonPath] = ref.split('.');\n const { propToCol } = buildColumnMap(schema);\n const col = propToCol.get(topProp) ?? topProp;\n if (!knex) {\n throw new Error(\n `${label}: a Knex instance is required to resolve nested JSON path '${ref}'`\n );\n }\n return jsonPathRaw(knex, col, jsonPath);\n }\n\n const { propToCol } = buildColumnMap(schema);\n const col = propToCol.get(ref);\n // If the string is a known property key, return its column name;\n // otherwise assume it's already a raw column name and pass through.\n return col ?? ref;\n }\n\n if (typeof ref === 'function') {\n const tree = ObjectSchemaBuilder.getPropertiesFor(schema as any);\n const descriptor = ref(tree as any);\n\n if (\n !descriptor ||\n typeof descriptor !== 'object' ||\n !(SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in descriptor)\n ) {\n throw new Error(\n `${label} accessor must return a valid property descriptor`\n );\n }\n\n const inner = (descriptor as any)[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n const pointer: string = inner.toJsonPointer();\n\n // pointer is an RFC-6901 JSON Pointer, e.g. '' (root), '/name', '/address/city'\n if (!pointer) {\n throw new Error(`${label} accessor returned the root descriptor`);\n }\n\n // Split '/address/city' → ['address', 'city']\n const segments = pointer\n .slice(1)\n .split('/')\n .map((s: string) => s.replace(/~1/g, '/').replace(/~0/g, '~'));\n\n if (segments.length === 0) {\n throw new Error(`${label} accessor returned the root descriptor`);\n }\n\n const [topProp, ...jsonPath] = segments;\n const { propToCol } = buildColumnMap(schema);\n const col = propToCol.get(topProp) ?? topProp;\n\n if (jsonPath.length === 0) {\n // Top-level property — plain column name\n return col;\n }\n\n // Nested path — need Knex.Raw\n if (!knex) {\n throw new Error(\n `${label}: a Knex instance is required to resolve nested JSON path '${pointer}'`\n );\n }\n return jsonPathRaw(knex, col, jsonPath);\n }\n\n throw new Error(\n `${label} must be a string or a property descriptor accessor function`\n );\n}\n\n/**\n * Resolve a ColumnRef to the **property key** (not the column name).\n * Used for result mapping.\n */\nexport function resolvePropertyKey(\n ref: ColumnRef<any>,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n label: string\n): string {\n if (typeof ref === 'string') {\n if (!ref) throw new Error(`${label} must be a non-empty string`);\n return ref;\n }\n\n if (typeof ref === 'function') {\n const tree = ObjectSchemaBuilder.getPropertiesFor(schema as any);\n const descriptor = ref(tree as any);\n\n if (\n !descriptor ||\n typeof descriptor !== 'object' ||\n !(SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in descriptor)\n ) {\n throw new Error(\n `${label} accessor must return a valid property descriptor`\n );\n }\n\n const inner = (descriptor as any)[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n const pointer: string = inner.toJsonPointer();\n\n if (!pointer) {\n throw new Error(`${label} accessor returned the root descriptor`);\n }\n\n // Return the first segment (top-level property key) for mapping purposes\n const topProp = pointer.slice(1).split('/')[0];\n return topProp.replace(/~1/g, '/').replace(/~0/g, '~');\n }\n\n throw new Error(\n `${label} must be a string or a property descriptor accessor function`\n );\n}\n\n// ---------------------------------------------------------------------------\n// Primary-key introspection\n// ---------------------------------------------------------------------------\n\n/**\n * Result of {@link getPrimaryKeyColumns}.\n *\n * `propertyKeys` are the schema property names (the keys you'd use in\n * `.where(t => t.id, ...)` style accessors); `columnNames` are the SQL\n * column names after applying any `hasColumnName()` overrides. Order is\n * preserved: composite-PK ordering matches the user's `hasPrimaryKey()`\n * declaration; single-PK arrays have length 1.\n *\n * @public\n */\nexport interface PrimaryKeyColumns {\n readonly propertyKeys: readonly string[];\n readonly columnNames: readonly string[];\n}\n\n/**\n * Resolve the primary-key columns of a schema at runtime.\n *\n * Composite primary keys (declared via `.hasPrimaryKey([...])` on the\n * object schema) take precedence over single-column primary keys. The\n * `columns` argument to `.hasPrimaryKey()` may contain either property keys\n * or SQL column names — both forms are accepted and normalised.\n *\n * Returns `{ propertyKeys: [], columnNames: [] }` when no primary key is\n * declared.\n *\n * @public\n */\nexport function getPrimaryKeyColumns(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): PrimaryKeyColumns {\n const introspected = schema.introspect() as {\n properties?: Record<string, SchemaBuilder<any, any, any>>;\n extensions?: Record<string, unknown>;\n };\n const properties = introspected.properties ?? {};\n const extensions = introspected.extensions ?? {};\n const { propToCol, colToProp } = buildColumnMap(schema);\n\n // Composite PK takes precedence.\n const composite = extensions.compositePrimaryKey as\n | readonly string[]\n | undefined;\n if (composite && composite.length > 0) {\n const propertyKeys: string[] = [];\n const columnNames: string[] = [];\n for (const entry of composite) {\n // Accept either column name or property key.\n if (propToCol.has(entry)) {\n propertyKeys.push(entry);\n columnNames.push(propToCol.get(entry) as string);\n } else if (colToProp.has(entry)) {\n columnNames.push(entry);\n propertyKeys.push(colToProp.get(entry) as string);\n } else {\n // Unknown identifier — pass through as both (best effort).\n propertyKeys.push(entry);\n columnNames.push(entry);\n }\n }\n return { propertyKeys, columnNames };\n }\n\n // Single-column PK — first property whose schema carries the\n // `primaryKey` extension wins.\n for (const [propKey, propSchema] of Object.entries(properties)) {\n const propExt =\n (\n propSchema as {\n introspect?: () => {\n extensions?: Record<string, unknown>;\n };\n }\n ).introspect?.().extensions ?? {};\n if (propExt.primaryKey) {\n return {\n propertyKeys: [propKey],\n columnNames: [propToCol.get(propKey) ?? propKey]\n };\n }\n }\n\n return { propertyKeys: [], columnNames: [] };\n}\n\n// ---------------------------------------------------------------------------\n// Row-version introspection\n// ---------------------------------------------------------------------------\n\n/**\n * Concurrency-token strategy stored by `.rowVersion()`.\n * - `'increment'` — ORM increments an integer counter on each UPDATE.\n * - `'timestamp'` — ORM sets the value to `new Date()` on each UPDATE.\n * - `'manual'` — caller supplies the new value; ORM only enforces the check.\n *\n * @public\n */\nexport type RowVersionStrategy = 'increment' | 'timestamp' | 'manual';\n\n/**\n * Resolved row-version column for a schema, returned by\n * {@link getRowVersionColumn}.\n *\n * @public\n */\nexport interface RowVersionColumn {\n /** Schema property name. */\n propertyKey: string;\n /** SQL column name (after any `hasColumnName()` override). */\n columnName: string;\n /** Concurrency-token update strategy. */\n strategy: RowVersionStrategy;\n}\n\n/**\n * Find the first column marked `.rowVersion()` on the schema and return its\n * metadata. Returns `null` when no row-version column is declared.\n *\n * @public\n */\nexport function getRowVersionColumn(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): RowVersionColumn | null {\n const introspected = schema.introspect() as {\n properties?: Record<\n string,\n { introspect?: () => { extensions?: Record<string, unknown> } }\n >;\n };\n const properties = introspected.properties ?? {};\n const { propToCol } = buildColumnMap(schema);\n\n for (const [propKey, propSchema] of Object.entries(properties)) {\n const ext = propSchema.introspect?.()?.extensions ?? {};\n const rv = ext.rowVersion as { strategy?: string } | undefined;\n if (rv) {\n return {\n propertyKey: propKey,\n columnName: propToCol.get(propKey) ?? propKey,\n strategy: (rv.strategy as RowVersionStrategy) ?? 'increment'\n };\n }\n }\n return null;\n}\n","// @cleverbrush/knex-schema — DDL generation from schema introspection\n\nimport type { ObjectSchemaBuilder, SchemaBuilder } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport {\n getColumnName,\n getPolymorphicVariantSchemas,\n getTableName\n} from './extension.js';\n\n// ---------------------------------------------------------------------------\n// Type mapping\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the Knex column type from a schema property's introspection data and\n * DDL extensions.\n *\n * Priority:\n * 1. Explicit `columnType` extension (e.g. `'text'`, `'uuid'`, `'jsonb'`).\n * 2. Schema type (`string`, `number`, `boolean`, `date`).\n *\n * @param table - Knex table builder.\n * @param col - SQL column name.\n * @param introspected - Result of `propSchema.introspect()`.\n * @param ext - The property's `extensions` object.\n * @returns A Knex column builder.\n */\nfunction resolveColumnType(\n table: Knex.CreateTableBuilder,\n col: string,\n introspected: any,\n ext: Record<string, any>\n): Knex.ColumnBuilder {\n if (ext.columnType) {\n return table.specificType(col, ext.columnType);\n }\n switch (introspected.type) {\n case 'string': {\n const maxLen = ext.maxLength ?? introspected.maxLength ?? undefined;\n return maxLen ? table.string(col, maxLen) : table.string(col);\n }\n case 'number':\n return introspected.isInteger !== false\n ? table.integer(col)\n : table.float(col);\n case 'boolean':\n return table.boolean(col);\n case 'date':\n return table.timestamp(col);\n case 'object':\n // Nested objects are stored as jsonb by default; override via .columnType()\n return table.specificType(col, 'jsonb');\n default:\n return table.specificType(col, 'text');\n }\n}\n\n/**\n * Apply a default value to a Knex column builder.\n *\n * Handles special values:\n * - `'now'` → `knex.fn.now()`\n * - `'auto_increment'` → no-op (handled by `table.increments()`)\n * - `{ raw: string }` → `knex.raw(expression)`\n * - Otherwise → literal value.\n *\n * @param column - Knex column builder.\n * @param defaultValue - The default value from the `defaultTo` extension.\n * @param knex - Knex instance (needed for `fn.now()` and `raw()`).\n * @returns The column builder with the default applied.\n */\nfunction applyDefault(\n column: Knex.ColumnBuilder,\n defaultValue: any,\n knex: Knex\n): Knex.ColumnBuilder {\n if (defaultValue === 'now') return column.defaultTo(knex.fn.now());\n if (defaultValue === 'auto_increment') return column;\n if (\n typeof defaultValue === 'object' &&\n defaultValue !== null &&\n defaultValue.raw\n ) {\n return column.defaultTo(knex.raw(defaultValue.raw));\n }\n return column.defaultTo(defaultValue);\n}\n\n// ---------------------------------------------------------------------------\n// generateCreateTable\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a Knex `schema.createTable()` call from an ObjectSchemaBuilder's\n * introspected metadata and DDL extensions.\n *\n * Returns a function that accepts a Knex instance and returns a\n * `SchemaBuilder` (thenable). Call it inside a migration or setup script:\n *\n * @param schema - An `ObjectSchemaBuilder` with `.hasTableName()` and\n * column-level DDL extensions (`.primaryKey()`, `.references()`, etc.).\n * @returns `(knex: Knex) => Knex.SchemaBuilder` — a function that creates the\n * table when executed.\n *\n * @example\n * ```ts\n * const createUsersTable = generateCreateTable(UserSchema);\n * await createUsersTable(knex);\n * ```\n */\nexport function generateCreateTable(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): (knex: Knex) => Knex.SchemaBuilder {\n const tableName = getTableName(schema);\n const introspected = schema.introspect() as any;\n const tableExt: Record<string, any> = introspected.extensions ?? {};\n\n // Column names fully managed by table-level extensions; skip them in the\n // property loop to avoid duplicate DDL.\n const extensionManagedCols = new Set<string>();\n if (tableExt.timestamps) {\n extensionManagedCols.add(tableExt.timestamps.createdAt);\n extensionManagedCols.add(tableExt.timestamps.updatedAt);\n }\n if (tableExt.softDelete) {\n extensionManagedCols.add(tableExt.softDelete.column);\n }\n\n return (knex: Knex) => {\n const builder = knex.schema.createTable(\n tableName,\n (table: Knex.CreateTableBuilder) => {\n const properties: Record<\n string,\n SchemaBuilder<any, any, any>\n > = introspected.properties ?? {};\n\n for (const [propKey, propSchema] of Object.entries(\n properties\n )) {\n const col = getColumnName(propSchema, propKey);\n const propIntrospected = propSchema.introspect() as any;\n const ext: Record<string, any> =\n propIntrospected.extensions ?? {};\n\n // Skip array navigation properties without an explicit\n // columnType override — these are ORM relations. Nested\n // object properties default to jsonb and are NOT skipped.\n if (propIntrospected.type === 'array' && !ext.columnType) {\n continue;\n }\n // Skip columns owned by table-level extensions.\n if (extensionManagedCols.has(col)) {\n continue;\n }\n\n // Determine column builder\n let column: Knex.ColumnBuilder;\n\n if (ext.primaryKey?.autoIncrement) {\n column = table.increments(col);\n } else {\n column = resolveColumnType(\n table,\n col,\n propIntrospected,\n ext\n );\n }\n\n // Primary key (non-auto-increment)\n if (ext.primaryKey && !ext.primaryKey.autoIncrement) {\n column = column.primary();\n }\n\n // Unique constraint\n if (ext.unique) {\n column = column.unique(\n typeof ext.unique === 'string'\n ? { indexName: ext.unique }\n : undefined\n );\n }\n\n // Index\n if (ext.index) {\n column = column.index(\n typeof ext.index === 'string'\n ? ext.index\n : undefined\n );\n }\n\n // Default value\n if (ext.defaultTo !== undefined) {\n column = applyDefault(column, ext.defaultTo, knex);\n }\n\n // Nullability\n if (\n propIntrospected.isRequired &&\n !ext.primaryKey?.autoIncrement\n ) {\n column = column.notNullable();\n } else if (!propIntrospected.isRequired) {\n column = column.nullable();\n }\n\n // Foreign key references\n if (ext.references) {\n const fkBuilder = column\n .references(ext.references.column)\n .inTable(ext.references.table);\n if (ext.onDelete) fkBuilder.onDelete(ext.onDelete);\n if (ext.onUpdate) fkBuilder.onUpdate(ext.onUpdate);\n }\n\n // Column-level CHECK constraint\n if (ext.check) {\n table.check(ext.check);\n }\n }\n\n // ----- Table-level constraints from object extensions -----\n\n // Composite indexes\n for (const idx of tableExt.indexes ?? []) {\n if (idx.unique) {\n table.unique(idx.columns, {\n indexName: idx.name ?? undefined\n });\n } else {\n table.index(idx.columns, idx.name ?? undefined);\n }\n }\n\n // Composite unique constraints\n for (const unq of tableExt.uniques ?? []) {\n table.unique(unq.columns, {\n indexName: unq.name ?? undefined\n });\n }\n\n // Table-level CHECK constraints\n for (const chk of tableExt.checks ?? []) {\n table.check(chk);\n }\n\n // Composite primary key\n if (tableExt.compositePrimaryKey) {\n table.primary(tableExt.compositePrimaryKey);\n }\n\n // Raw columns (not backed by schema properties)\n for (const rawCol of tableExt.rawColumns ?? []) {\n table.specificType(rawCol.name, rawCol.definition);\n }\n\n // Timestamps (auto-added columns)\n if (tableExt.timestamps) {\n table\n .timestamp(tableExt.timestamps.createdAt)\n .defaultTo(knex.fn.now())\n .notNullable();\n table\n .timestamp(tableExt.timestamps.updatedAt)\n .defaultTo(knex.fn.now())\n .notNullable();\n }\n\n // Soft delete column\n if (tableExt.softDelete) {\n table.timestamp(tableExt.softDelete.column).nullable();\n }\n }\n );\n\n // Raw indexes are executed as separate statements after table creation\n const rawIndexes: string[] = tableExt.rawIndexes ?? [];\n if (rawIndexes.length > 0) {\n return builder.then(async () => {\n for (const rawIdx of rawIndexes) {\n await knex.raw(rawIdx);\n }\n }) as any;\n }\n\n return builder;\n };\n}\n\n// ---------------------------------------------------------------------------\n// generateCreateTableSource\n// ---------------------------------------------------------------------------\n\n/**\n * Generate `up` and `down` TypeScript code *strings* (4-space-indented\\n * fragments) for creating a table from a schema.\n *\n * Unlike {@link generateCreateTable} (which returns a Knex callback), the\n * output is plain source text suitable for writing into a migration file. The\n * fragments are designed to be embedded directly inside `up()` / `down()`\n * functions.\n *\n * @param schema - An `ObjectSchemaBuilder` with `.hasTableName()` and column\n * DDL extensions.\n * @returns `{ up, down }` source fragments.\n *\n * @example\n * ```ts\n * const { up, down } = generateCreateTableSource(UserSchema);\n * // up: \" await knex.schema.createTable('users', (table) => { … });\"\n * // down: \" await knex.schema.dropTableIfExists('users');\"\n * ```\n */\nexport function generateCreateTableSource(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): { up: string; down: string } {\n const tableName = getTableName(schema);\n const introspected = schema.introspect() as any;\n const tableExt: Record<string, any> = introspected.extensions ?? {};\n const properties: Record<\n string,\n SchemaBuilder<any, any, any>\n > = introspected.properties ?? {};\n\n const lines: string[] = [];\n\n // Column names owned by table-level extensions; skip in property loop.\n const extensionManagedCols = new Set<string>();\n if (tableExt.timestamps) {\n extensionManagedCols.add(tableExt.timestamps.createdAt);\n extensionManagedCols.add(tableExt.timestamps.updatedAt);\n }\n if (tableExt.softDelete) {\n extensionManagedCols.add(tableExt.softDelete.column);\n }\n\n for (const [propKey, propSchema] of Object.entries(properties)) {\n const col = getColumnName(propSchema, propKey);\n const propIntrospected = propSchema.introspect() as any;\n const ext: Record<string, any> = propIntrospected.extensions ?? {};\n\n // Skip navigation properties and extension-managed columns.\n if (\n (propIntrospected.type === 'object' ||\n propIntrospected.type === 'array') &&\n !ext.columnType\n ) {\n continue;\n }\n if (extensionManagedCols.has(col)) {\n continue;\n }\n\n let line: string;\n\n if (ext.primaryKey?.autoIncrement) {\n line = ` table.increments('${col}')`;\n } else {\n line = ` ${_colTypeCode(col, propIntrospected, ext)}`;\n }\n\n // Primary key (non-auto-increment)\n if (ext.primaryKey && !ext.primaryKey.autoIncrement) {\n line += '.primary()';\n }\n\n // Unique\n if (ext.unique) {\n if (typeof ext.unique === 'string') {\n line += `.unique({ indexName: '${ext.unique}' })`;\n } else {\n line += '.unique()';\n }\n }\n\n // Index\n if (ext.index) {\n if (typeof ext.index === 'string') {\n line += `.index('${ext.index}')`;\n } else {\n line += '.index()';\n }\n }\n\n // Default value\n if (ext.defaultTo !== undefined) {\n line += `.defaultTo(${_fmtDefault(ext.defaultTo)})`;\n }\n\n // Nullability\n if (propIntrospected.isRequired && !ext.primaryKey?.autoIncrement) {\n line += '.notNullable()';\n } else if (!propIntrospected.isRequired) {\n line += '.nullable()';\n }\n\n // Foreign key references\n if (ext.references) {\n line += `.references('${ext.references.column}').inTable('${ext.references.table}')`;\n if (ext.onDelete) line += `.onDelete('${ext.onDelete}')`;\n if (ext.onUpdate) line += `.onUpdate('${ext.onUpdate}')`;\n }\n\n lines.push(line + ';');\n\n // Column-level CHECK (separate statement after column line)\n if (ext.check) {\n lines.push(` table.check(${JSON.stringify(ext.check)});`);\n }\n }\n\n // Composite indexes\n for (const idx of tableExt.indexes ?? []) {\n const cols = JSON.stringify(idx.columns);\n if (idx.unique) {\n lines.push(\n ` table.unique(${cols}${idx.name ? `, { indexName: '${idx.name}' }` : ''});`\n );\n } else {\n lines.push(\n ` table.index(${cols}${idx.name ? `, '${idx.name}'` : ''});`\n );\n }\n }\n\n // Composite unique constraints\n for (const unq of tableExt.uniques ?? []) {\n const cols = JSON.stringify(unq.columns);\n lines.push(\n ` table.unique(${cols}${unq.name ? `, { indexName: '${unq.name}' }` : ''});`\n );\n }\n\n // Table-level CHECK constraints\n for (const chk of tableExt.checks ?? []) {\n lines.push(` table.check(${JSON.stringify(chk)});`);\n }\n\n // Composite primary key\n if (tableExt.compositePrimaryKey) {\n lines.push(\n ` table.primary(${JSON.stringify(tableExt.compositePrimaryKey)});`\n );\n }\n\n // Raw columns\n for (const rawCol of tableExt.rawColumns ?? []) {\n lines.push(\n ` table.specificType('${rawCol.name}', '${rawCol.definition}');`\n );\n }\n\n // Timestamps\n if (tableExt.timestamps) {\n lines.push(\n ` table.timestamp('${tableExt.timestamps.createdAt}').notNullable().defaultTo(knex.fn.now());`\n );\n lines.push(\n ` table.timestamp('${tableExt.timestamps.updatedAt}').notNullable().defaultTo(knex.fn.now());`\n );\n }\n\n // Soft-delete column\n if (tableExt.softDelete) {\n lines.push(\n ` table.timestamp('${tableExt.softDelete.column}').nullable();`\n );\n }\n\n const rawIndexes: string[] = tableExt.rawIndexes ?? [];\n const rawIndexLines = rawIndexes.map(\n ri => ` await knex.raw(${JSON.stringify(ri)});`\n );\n\n const up =\n ` await knex.schema.createTable('${tableName}', (table) => {\\n${lines.join('\\n')}\\n });` +\n (rawIndexLines.length > 0 ? '\\n' + rawIndexLines.join('\\n') : '');\n\n const down = ` await knex.schema.dropTableIfExists('${tableName}');`;\n\n return { up, down };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers for generateCreateTableSource\n// ---------------------------------------------------------------------------\n\n/** @internal Render a column type expression for code generation. */\nfunction _colTypeCode(\n col: string,\n introspected: any,\n ext: Record<string, any>\n): string {\n if (ext.columnType)\n return `table.specificType('${col}', '${ext.columnType}')`;\n switch (introspected.type) {\n case 'string': {\n const maxLen = ext.maxLength ?? introspected.maxLength ?? undefined;\n return maxLen\n ? `table.string('${col}', ${maxLen})`\n : `table.string('${col}')`;\n }\n case 'number':\n return introspected.isInteger !== false\n ? `table.integer('${col}')`\n : `table.float('${col}')`;\n case 'boolean':\n return `table.boolean('${col}')`;\n case 'date':\n return `table.timestamp('${col}')`;\n case 'object':\n return `table.specificType('${col}', 'jsonb')`;\n default:\n return `table.specificType('${col}', 'text')`;\n }\n}\n\n/** @internal Format a defaultTo value as a code string for migration source. */\nfunction _fmtDefault(value: any): string {\n if (value === 'now') return 'knex.fn.now()';\n if (typeof value === 'object' && value !== null && value.raw) {\n return `knex.raw('${String(value.raw).replace(/'/g, \"\\\\'\")}')`;\n }\n if (typeof value === 'string') return `'${value.replace(/'/g, \"\\\\'\")}'`;\n return String(value);\n}\n\n// ---------------------------------------------------------------------------\n// generateCreatePolymorphicTables\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a series of Knex `schema.createTable()` calls for a polymorphic\n * schema and all its CTI variant tables.\n *\n * Returns an array of `(knex: Knex) => Knex.SchemaBuilder` functions — one\n * for the base table and one for each CTI variant. STI variants add their\n * columns to the base table itself so no extra table is needed.\n *\n * Execute them sequentially in a migration:\n *\n * @param schema - The base `ObjectSchemaBuilder` with `.withVariants()` applied.\n * @returns An array of table-creation functions to execute in order.\n *\n * @example\n * ```ts\n * const creators = generateCreatePolymorphicTables(FileSchema);\n * for (const create of creators) {\n * await create(knex);\n * }\n * ```\n */\nexport function generateCreatePolymorphicTables(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): Array<(knex: Knex) => Knex.SchemaBuilder> {\n const result: Array<(knex: Knex) => Knex.SchemaBuilder> = [\n generateCreateTable(schema)\n ];\n\n const variantSchemas = getPolymorphicVariantSchemas(schema);\n for (const variantSchema of variantSchemas) {\n // Only CTI variants have their own table\n const tableName = variantSchema.getExtension('tableName') as\n | string\n | undefined;\n if (tableName) {\n result.push(generateCreateTable(variantSchema));\n }\n }\n\n return result;\n}\n","// @cleverbrush/knex-schema — Entity wrapper\n//\n// Provides a typed wrapper around an ObjectSchemaBuilder that tracks\n// declared relations as a real generic parameter (TRels). Unlike the\n// brand-based approach, TRels survives method chaining because we own\n// every method's return type.\n//\n// Relations are still stored at runtime in the schema's `relations`\n// extension (compatible with the existing query/include implementation).\n\nimport {\n type ArraySchemaBuilder,\n type InferType,\n ObjectSchemaBuilder,\n type PropertyDescriptorTree,\n type SchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\n\nimport { buildColumnMap } from './columns.js';\nimport {\n applyVariantsToSchema,\n getColumnName,\n type VariantInputForResolver\n} from './extension.js';\nimport type { ResolvedVariantRelationSpec } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Type-level helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Phantom info for a single declared relation, stored on `Entity`'s `TRels`\n * generic. `TForeign` is captured so `.include()` can type the customize\n * callback against the correct foreign schema.\n *\n * @public\n */\nexport interface RelationInfo<\n TKind extends 'belongsTo' | 'hasOne' | 'hasMany' | 'belongsToMany' = any,\n TForeign extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = ObjectSchemaBuilder<any, any, any, any, any, any, any>\n> {\n readonly kind: TKind;\n readonly foreign: TForeign;\n}\n\n/**\n * Extract the property record `{ [name]: SchemaBuilder }` from any\n * `ObjectSchemaBuilder` regardless of variance positions.\n *\n * @public\n */\nexport type SchemaProps<T> =\n T extends ObjectSchemaBuilder<infer P, any, any, any, any, any, any>\n ? P\n : never;\n\n/**\n * Strips the `withExtensions()` overlay from a schema type, reducing it to a\n * plain `ObjectSchemaBuilder<TProps, TReq>` so `PropertyDescriptorTree<...>`\n * resolves without hitting TypeScript's recursion depth limit.\n *\n * @internal\n */\ntype EntitySchemaBase<\n T extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n> =\n T extends ObjectSchemaBuilder<infer P, infer Req, any, any, any, any, any>\n ? ObjectSchemaBuilder<P, Req>\n : never;\n\n/**\n * `PropertyDescriptorTree` overlay that pins each top-level property's\n * literal `propertyName` into its descriptor. Required because\n * `PropertyDescriptorTree` widens `propertyName` to `string` for sub-trees\n * whose property is itself an `ObjectSchemaBuilder` (since\n * `PropertyDescriptorTree` lacks a `TPropertyKey` generic).\n *\n * @internal\n */\ntype EntityTree<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n> = PropertyDescriptorTree<\n EntitySchemaBase<TSchema>,\n EntitySchemaBase<TSchema>\n> & {\n readonly [K in keyof SchemaProps<TSchema> & string]: {\n readonly [SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]: {\n readonly propertyName: K;\n };\n };\n};\n\n/**\n * Selector callback that receives a real {@link PropertyDescriptorTree} so\n * `t => t.someProp` navigates to the property definition and preserves its\n * JSDoc in IDE tooltips. The return shape is matched structurally on the\n * `[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR].propertyName` field, which captures\n * the literal property key as `TKey`.\n *\n * @public\n */\nexport type EntityPropSelector<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TKey extends string = string\n> = (t: EntityTree<TSchema>) => {\n readonly [SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]: {\n readonly propertyName: TKey;\n };\n};\n\n/**\n * Peel `.optional()` / `array(...)` wrappers off a navigation property's\n * schema to recover the underlying foreign `ObjectSchemaBuilder`.\n *\n * @public\n */\nexport type UnwrapNavSchema<TProp> =\n TProp extends ArraySchemaBuilder<infer TEl, any, any, any>\n ? TEl extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n ? TEl\n : never\n : TProp extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n ? TProp\n : TProp extends SchemaBuilder<infer T, any, any, any, any>\n ? T extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n ? T\n : never\n : never;\n\n/**\n * Merge type for a single polymorphic variant branch: variant schema fields\n * overlay base schema fields (narrowing the discriminator from `string` to its\n * specific literal value).\n *\n * @public\n */\nexport type VariantBranch<\n TBaseSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TVarSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n> = Omit<InferType<TBaseSchema>, keyof InferType<TVarSchema>> &\n InferType<TVarSchema>;\n\n/**\n * Return type for an Entity method that adds a relation: keeps `TSchema`,\n * extends `TRels` with one more entry, and preserves `TVariantUnion`.\n *\n * @public\n */\nexport type WithRelation<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TRels extends Record<string, RelationInfo>,\n TKey extends string,\n TKind extends 'belongsTo' | 'hasOne' | 'hasMany' | 'belongsToMany',\n TForeign extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TVariantUnion = never\n> = Entity<\n TSchema,\n TRels & Record<TKey, RelationInfo<TKind, TForeign>>,\n TVariantUnion\n>;\n\n// ---------------------------------------------------------------------------\n// Entity\n// ---------------------------------------------------------------------------\n\n/**\n * A typed wrapper around an `ObjectSchemaBuilder` that tracks declared\n * relations in its `TRels` generic. Use {@link defineEntity} to create one.\n *\n * Relations are declared via `.hasOne()` / `.hasMany()` / `.belongsTo()` /\n * `.belongsToMany()` on the entity (NOT on the underlying schema). Each\n * call returns a new `Entity` whose `TRels` includes the new relation, so\n * `query(db, entity).include(t => t.assignee)` is fully typed.\n *\n * @public\n */\nexport class Entity<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TRels extends Record<string, RelationInfo> = {},\n TVariantUnion = never\n> {\n /** The underlying schema (relations registered via `withExtension('relations', ...)`). */\n readonly schema: TSchema;\n\n /** @internal Phantom slot to retain `TRels` in inferred types. */\n private declare readonly __relations__: TRels;\n\n /** @internal Phantom slot to retain `TVariantUnion` in inferred types. */\n private declare readonly __variantUnion__: TVariantUnion;\n\n constructor(schema: TSchema) {\n this.schema = schema;\n }\n\n private _addRelation(spec: {\n type: 'belongsTo' | 'hasOne' | 'hasMany' | 'belongsToMany';\n name: string;\n schema: any;\n foreignKey?: any;\n through?: { table: string; localKey: string; foreignKey: string };\n optional?: boolean;\n }): Entity<TSchema, any> {\n const existing =\n ((this.schema as any).getExtension?.('relations') as any[]) ?? [];\n const next = (this.schema as any).withExtension('relations', [\n ...existing,\n spec\n ]);\n return new Entity(next);\n }\n\n /**\n * Declare a one-to-one relation where the FK lives on the FOREIGN table.\n * `navSel` selects the navigation property on THIS schema (must hold the\n * foreign schema, typically `.optional()`). The foreign schema is\n * auto-resolved at runtime from that property; provided explicitly here\n * via `opts.foreign` only when peeling fails.\n *\n * @param navSel Selector of nav property: `t => t.author`\n * @param localSel Selector of local-side join key: `l => l.id`\n * @param remoteSel Selector of remote-side FK on foreign schema: `r => r.userId`\n * @param opts Optional `{ optional?: boolean }` (default false).\n */\n hasOne<\n TKey extends keyof SchemaProps<TSchema> & string,\n TForeign extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = UnwrapNavSchema<SchemaProps<TSchema>[TKey]>\n >(\n navSel: EntityPropSelector<TSchema, TKey>,\n _localSel: EntityPropSelector<TSchema>,\n remoteSel: EntityPropSelector<TForeign>,\n opts?: { optional?: boolean }\n ): WithRelation<TSchema, TRels, TKey, 'hasOne', TForeign, TVariantUnion> {\n const navName = this._resolvePropName(\n navSel as EntityPropSelector<TSchema>,\n this.schema\n );\n const foreignSchema = this._resolveForeignSchema(navName);\n const remoteKey = this._resolvePropName(\n remoteSel as EntityPropSelector<any>,\n foreignSchema\n );\n // For hasOne the FK is on the FOREIGN table → store remoteKey.\n return this._addRelation({\n type: 'hasOne',\n name: navName,\n schema: foreignSchema,\n foreignKey: remoteKey,\n optional: opts?.optional\n }) as any;\n }\n\n /**\n * Declare a one-to-many relation where the FK lives on the FOREIGN table.\n *\n * @param navSel Selector of nav array property: `t => t.posts`\n * @param localSel Selector of local-side join key: `l => l.id`\n * @param remoteSel Selector of remote-side FK on foreign schema: `r => r.userId`\n */\n hasMany<\n TKey extends keyof SchemaProps<TSchema> & string,\n TForeign extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = UnwrapNavSchema<SchemaProps<TSchema>[TKey]>\n >(\n navSel: EntityPropSelector<TSchema, TKey>,\n _localSel: EntityPropSelector<TSchema>,\n remoteSel: EntityPropSelector<TForeign>\n ): WithRelation<TSchema, TRels, TKey, 'hasMany', TForeign, TVariantUnion> {\n const navName = this._resolvePropName(\n navSel as EntityPropSelector<TSchema>,\n this.schema\n );\n const foreignSchema = this._resolveForeignSchema(navName);\n const remoteKey = this._resolvePropName(\n remoteSel as EntityPropSelector<any>,\n foreignSchema\n );\n return this._addRelation({\n type: 'hasMany',\n name: navName,\n schema: foreignSchema,\n foreignKey: remoteKey\n }) as any;\n }\n\n /**\n * Declare a many-to-one relation where the FK lives on THIS table.\n *\n * @param navSel Selector of nav property (foreign schema, usually `.optional()`).\n * @param localSel Selector of local-side FK property: `l => l.userId`\n * @param remoteSel Selector of foreign-side PK property: `r => r.id`\n */\n belongsTo<\n TKey extends keyof SchemaProps<TSchema> & string,\n TForeign extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = UnwrapNavSchema<SchemaProps<TSchema>[TKey]>\n >(\n navSel: EntityPropSelector<TSchema, TKey>,\n localSel: EntityPropSelector<TSchema>,\n _remoteSel: EntityPropSelector<TForeign>,\n opts?: { optional?: boolean }\n ): WithRelation<\n TSchema,\n TRels,\n TKey,\n 'belongsTo',\n TForeign,\n TVariantUnion\n > {\n const navName = this._resolvePropName(\n navSel as EntityPropSelector<TSchema>,\n this.schema\n );\n const foreignSchema = this._resolveForeignSchema(navName);\n const localKey = this._resolvePropName(localSel, this.schema);\n // For belongsTo the FK is on THIS table → store localKey.\n return this._addRelation({\n type: 'belongsTo',\n name: navName,\n schema: foreignSchema,\n foreignKey: localKey,\n optional: opts?.optional\n }) as any;\n }\n\n /**\n * Declare a many-to-many relation through a pivot table.\n *\n * @param navSel Selector of nav array property: `t => t.tags`\n * @param through Pivot table config `{ table, localKey, foreignKey }`.\n */\n belongsToMany<\n TKey extends keyof SchemaProps<TSchema> & string,\n TForeign extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = UnwrapNavSchema<SchemaProps<TSchema>[TKey]>\n >(\n navSel: EntityPropSelector<TSchema, TKey>,\n through: { table: string; localKey: string; foreignKey: string }\n ): WithRelation<\n TSchema,\n TRels,\n TKey,\n 'belongsToMany',\n TForeign,\n TVariantUnion\n > {\n const navName = this._resolvePropName(\n navSel as EntityPropSelector<TSchema>,\n this.schema\n );\n const foreignSchema = this._resolveForeignSchema(navName);\n return this._addRelation({\n type: 'belongsToMany',\n name: navName,\n schema: foreignSchema,\n through\n }) as any;\n }\n\n /**\n * Mark this entity as polymorphic by selecting the discriminator\n * property. Returns a new `Entity` whose `.ctiVariant()` /\n * `.stiVariant()` methods declare each variant.\n *\n * Declare ordinary relations (`.belongsTo()` etc.) on this entity BEFORE\n * `.discriminator()`. After `.discriminator()` you are in the\n * polymorphic-builder phase: `.hasOne/.hasMany/.belongsTo/.belongsToMany`\n * still work, but the per-variant relations live on the `.ctiVariant()`\n * / `.stiVariant()` calls.\n *\n * @example\n * ```ts\n * const FileEntity = defineEntity(FileSchema)\n * .discriminator(t => t.type)\n * .ctiVariant('image', ImageEntity, t => t.fileId)\n * .ctiVariant('document', DocumentEntity, t => t.fileId);\n * ```\n */\n discriminator<TKey extends keyof SchemaProps<TSchema> & string>(\n sel: TKey | EntityPropSelector<TSchema, TKey>\n ): Entity<TSchema, TRels, never> {\n const discKey =\n typeof sel === 'string'\n ? (sel as string)\n : this._resolvePropName(\n sel as EntityPropSelector<TSchema>,\n this.schema\n );\n const next = new Entity(this.schema) as Entity<TSchema, TRels>;\n // Carry the variant-builder state on the new Entity so subsequent\n // `.ctiVariant()`/`.stiVariant()` calls can extend it. Stored on\n // the instance (not in the schema) so the original schema is\n // unchanged until the first variant is added.\n (next as any)._variantBuilder = {\n discKey,\n variants: {} as Record<string, VariantInputForResolver>\n };\n return next;\n }\n\n /**\n * Declare a CTI (Class Table Inheritance) variant. Only valid after\n * `.discriminator()`. Returns a new `Entity` whose schema carries the\n * updated `'variants'` extension.\n *\n * @param key Discriminator literal (e.g. `'image'`).\n * @param variant Entity wrapping the variant table schema.\n * @param fkSel Accessor returning the FK property on the variant\n * schema that joins back to the base PK.\n * @param opts `{ allowOrphan?: boolean; relations?: ... }` — see CTI docs.\n */\n ctiVariant<\n TVarSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n >(\n key: string,\n variant: Entity<TVarSchema, any>,\n fkSel: (t: EntityTree<TVarSchema>) => any,\n opts?: {\n allowOrphan?: boolean;\n relations?: Record<string, VariantRelationInput<TVarSchema>>;\n }\n ): Entity<\n TSchema,\n TRels,\n TVariantUnion | VariantBranch<TSchema, TVarSchema>\n > {\n const builder = (this as any)._variantBuilder as\n | VariantBuilderState\n | undefined;\n if (!builder) {\n throw new Error(\n 'ctiVariant: call `.discriminator(...)` first to begin a polymorphic builder chain'\n );\n }\n const fkColumn = resolveCtiForeignKeyColumn(\n variant.schema,\n fkSel as (t: any) => any\n );\n const nextVariants: Record<string, VariantInputForResolver> = {\n ...builder.variants,\n [key]: {\n schema: variant.schema,\n storage: 'cti',\n foreignKeyColumn: fkColumn,\n allowOrphan: opts?.allowOrphan,\n relations: [\n ...entityRelationsToVariantRelations(variant),\n ...resolveInlineVariantRelations(\n variant.schema,\n opts?.relations\n )\n ]\n }\n };\n return this._withVariantBuilder<\n TVariantUnion | VariantBranch<TSchema, TVarSchema>\n >(builder.discKey, nextVariants);\n }\n\n /**\n * Declare an STI (Single Table Inheritance) variant. Only valid after\n * `.discriminator()`. Accepts either an {@link Entity} or a bare\n * {@link ObjectSchemaBuilder}.\n */\n stiVariant<\n TVarSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n >(\n key: string,\n body: Entity<TVarSchema, any> | TVarSchema,\n opts?: {\n enforceCheck?: boolean;\n relations?: Record<string, VariantRelationInput<TVarSchema>>;\n }\n ): Entity<\n TSchema,\n TRels,\n TVariantUnion | VariantBranch<TSchema, TVarSchema>\n > {\n const builder = (this as any)._variantBuilder as\n | VariantBuilderState\n | undefined;\n if (!builder) {\n throw new Error(\n 'stiVariant: call `.discriminator(...)` first to begin a polymorphic builder chain'\n );\n }\n const isEntity = body instanceof Entity;\n const varSchema = (\n isEntity ? (body as Entity<any, any>).schema : body\n ) as ObjectSchemaBuilder<any, any, any, any, any, any, any>;\n const nextVariants: Record<string, VariantInputForResolver> = {\n ...builder.variants,\n [key]: {\n schema: varSchema,\n storage: 'sti',\n enforceCheck: opts?.enforceCheck,\n relations: [\n ...(isEntity\n ? entityRelationsToVariantRelations(\n body as Entity<any, any>\n )\n : []),\n ...resolveInlineVariantRelations(varSchema, opts?.relations)\n ]\n }\n };\n return this._withVariantBuilder<\n TVariantUnion | VariantBranch<TSchema, TVarSchema>\n >(builder.discKey, nextVariants);\n }\n\n /** @internal Apply the variant extension to the schema and return a new Entity. */\n private _withVariantBuilder<TNewUnion>(\n discKey: string,\n variants: Record<string, VariantInputForResolver>\n ): Entity<TSchema, TRels, TNewUnion> {\n let newSchema = applyVariantsToSchema(\n this.schema,\n discKey,\n variants\n ) as any;\n // Preserve any existing `relations` extension across the rebuild.\n const existingRelations =\n (this.schema as any).getExtension?.('relations') ?? [];\n if (existingRelations.length) {\n newSchema = newSchema.withExtension('relations', existingRelations);\n }\n const next = new Entity(newSchema as TSchema) as Entity<\n TSchema,\n TRels,\n TNewUnion\n >;\n (next as any)._variantBuilder = { discKey, variants };\n return next;\n }\n\n /**\n * @internal\n * Resolve a selector callback against the real `PropertyDescriptorTree`\n * of the given schema, returning the top-level property name. Throws if\n * the accessor does not yield a valid descriptor.\n */\n private _resolvePropName(\n selector: (t: any) => any,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n ): string {\n const tree = ObjectSchemaBuilder.getPropertiesFor(schema as any);\n const descriptor = selector(tree as any);\n if (\n !descriptor ||\n typeof descriptor !== 'object' ||\n !(SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in descriptor)\n ) {\n throw new Error(\n 'Entity relation selector must return a property descriptor, e.g. `t => t.author`.'\n );\n }\n const inner = (descriptor as any)[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n if (typeof inner.propertyName !== 'string') {\n throw new Error(\n 'Entity relation selector must return a top-level property descriptor.'\n );\n }\n return inner.propertyName as string;\n }\n\n /** @internal Resolve the foreign schema from a nav property. */\n private _resolveForeignSchema(navName: string): any {\n const props = (this.schema as any).introspect?.()?.properties ?? {};\n const propSchema = props[navName];\n if (!propSchema) {\n throw new Error(\n `Entity.relation: navigation property \"${navName}\" not found on schema`\n );\n }\n const intro = propSchema.introspect?.() ?? propSchema;\n // Array → use elementSchema\n if (intro.type === 'array' && intro.elementSchema) {\n return intro.elementSchema;\n }\n // Object schema directly (with or without optional)\n if (\n intro.type === 'object' ||\n propSchema.constructor?.name === 'ObjectSchemaBuilder'\n ) {\n return propSchema;\n }\n // Fall back: assume it's already the schema\n return propSchema;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Polymorphic variant helpers (used by Entity.discriminator/ctiVariant/stiVariant)\n// ---------------------------------------------------------------------------\n\n/** @internal Variant-builder state carried on an Entity instance during a\n * `.discriminator().ctiVariant()/.stiVariant()` chain. */\ninterface VariantBuilderState {\n discKey: string;\n variants: Record<string, VariantInputForResolver>;\n}\n\n/**\n * @internal Convert an Entity's stored relations (which use property-name\n * foreign keys) into the column-name form required by\n * {@link ResolvedVariantRelationSpec}.\n */\nfunction entityRelationsToVariantRelations(\n varEntity: Entity<any, any>\n): ResolvedVariantRelationSpec[] {\n const rels: any[] =\n (varEntity.schema as any).getExtension?.('relations') ?? [];\n if (rels.length === 0) return [];\n\n const { propToCol } = buildColumnMap(varEntity.schema as any);\n\n return rels.map(r => {\n // belongsToMany has no `foreignKey` on the spec itself (uses through.*).\n const fkPropName: string | undefined =\n typeof r.foreignKey === 'string' ? r.foreignKey : undefined;\n const fkColName = fkPropName\n ? (propToCol.get(fkPropName) ?? fkPropName)\n : undefined;\n return {\n name: r.name,\n type: r.type,\n schema: r.schema,\n foreignKey: fkColName,\n through: r.through\n } satisfies ResolvedVariantRelationSpec;\n });\n}\n\n/**\n * @internal Resolve a foreign-key accessor (`t => t.fileId`) against a\n * variant schema to a SQL column name.\n */\nfunction resolveCtiForeignKeyColumn(\n varSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n fkSel: (t: any) => any\n): string {\n const tree = ObjectSchemaBuilder.getPropertiesFor(varSchema as any);\n const desc = fkSel(tree as any);\n const inner = (desc as any)?.[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n if (!inner?.propertyName) {\n throw new Error(\n 'ctiVariant: foreignKey accessor must return a top-level property descriptor on the variant schema'\n );\n }\n const propKey: string = inner.propertyName;\n const props = (varSchema as any).introspect?.()?.properties ?? {};\n const propSchema = props[propKey];\n if (!propSchema) {\n throw new Error(\n `ctiVariant: foreignKey property \"${propKey}\" not found on variant schema`\n );\n }\n return getColumnName(propSchema, propKey);\n}\n\n/**\n * Inline relation spec accepted by {@link Entity.ctiVariant} /\n * {@link Entity.stiVariant} via `opts.relations`. The `foreignKey`\n * accessor (when given) is typed against the variant's own schema and\n * resolved to a SQL column name.\n *\n * @public\n */\nexport interface VariantRelationInput<\n TVarSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n > = ObjectSchemaBuilder<any, any, any, any, any, any, any>\n> {\n type: 'belongsTo' | 'hasOne' | 'hasMany' | 'belongsToMany';\n /**\n * Foreign side — accept either a bare schema, an Entity wrapper, or a\n * lazy thunk for forward references.\n */\n schema?:\n | ObjectSchemaBuilder<any, any, any, any, any, any, any>\n | (() => ObjectSchemaBuilder<any, any, any, any, any, any, any>);\n entity?: Entity<any, any>;\n foreignKey?: (t: EntityTree<TVarSchema>) => any;\n through?: { table: string; localKey: string; foreignKey: string };\n}\n\n/**\n * @internal Resolve a map of {@link VariantRelationInput} into the\n * column-resolved {@link ResolvedVariantRelationSpec[]} shape stored on a\n * resolved variant spec.\n */\nfunction resolveInlineVariantRelations(\n varSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n relations: Record<string, VariantRelationInput<any>> | undefined\n): ResolvedVariantRelationSpec[] {\n if (!relations) return [];\n const { propToCol } = buildColumnMap(varSchema);\n const result: ResolvedVariantRelationSpec[] = [];\n const tree = ObjectSchemaBuilder.getPropertiesFor(varSchema as any);\n\n for (const [name, spec] of Object.entries(relations)) {\n let foreignKey: string | undefined;\n if (spec.foreignKey) {\n const desc = spec.foreignKey(tree as any);\n const inner = (desc as any)?.[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n if (!inner?.propertyName) {\n throw new Error(\n `variant relation \"${name}\": foreignKey accessor must return a top-level property descriptor on the variant schema`\n );\n }\n const propKey: string = inner.propertyName;\n foreignKey = propToCol.get(propKey) ?? propKey;\n }\n const targetSchema = spec.entity ? spec.entity.schema : spec.schema;\n result.push({\n name,\n type: spec.type,\n schema: targetSchema,\n foreignKey,\n through: spec.through\n });\n }\n return result;\n}\n\n/**\n * Wrap an `ObjectSchemaBuilder` in an {@link Entity}, enabling typed relation\n * declaration via `.hasOne()` / `.hasMany()` / `.belongsTo()` / `.belongsToMany()`.\n *\n * @public\n *\n * @example\n * ```ts\n * const UserEntity = defineEntity(\n * object({\n * id: number().primaryKey(),\n * name: string(),\n * posts: array(PostEntity.schema)\n * }).hasTableName('users')\n * ).hasMany(t => t.posts, l => l.id, r => r.userId);\n * ```\n */\nexport function defineEntity<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n>(schema: TSchema): Entity<TSchema, {}> {\n return new Entity(schema);\n}\n\n/**\n * Type-level helper: extract `TRels` from any `Entity` type.\n * @public\n */\nexport type EntityRelations<E> =\n E extends Entity<any, infer R, any> ? R : never;\n\n/**\n * Type-level helper: extract the underlying schema type from any `Entity`.\n * @public\n */\nexport type EntitySchema<E> = E extends Entity<infer S, any, any> ? S : never;\n\n/**\n * Type-level helper: extract the accumulated variant union from any `Entity`.\n * Resolves to `never` for non-polymorphic entities.\n * @public\n */\nexport type EntityVariantUnion<E> =\n E extends Entity<any, any, infer U> ? U : never;\n\n/**\n * Type-level helper: union of relation key names declared on an entity.\n * Used by `SchemaQueryBuilder.insert()/update()/upsert()` to omit relation\n * navigation properties from accepted input.\n * @public\n */\nexport type EntityRelationKeys<E> =\n E extends Entity<any, infer R, any> ? keyof R & string : never;\n","// @cleverbrush/knex-schema — Post-load value transformers (from knex-eager)\n\nimport type { ValidatedSpec } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Built-in named mappers\n// ---------------------------------------------------------------------------\n\n/**\n * Built-in named value mapper functions.\n *\n * Each entry maps a string key to a transformation function. Pass the key as\n * the `mapper` argument to {@link mapValue} instead of a custom function.\n *\n * Currently available:\n * - `date_from_json` — converts a JSON date string (`string | null`) to a\n * JavaScript `Date` object (or passes through falsy values unchanged).\n */\nexport const MAPPERS: Record<string, (value: any) => any> = {\n date_from_json: (value: any) => {\n if (!value) return value;\n return new Date(Date.parse(value));\n }\n};\n\n// ---------------------------------------------------------------------------\n// mapValue — apply a mapper (function or built-in name) to a value\n// ---------------------------------------------------------------------------\n\n/**\n * Apply a single mapper to a value.\n *\n * @param mapper - Either a transformation function `(v: any) => any`, or a\n * string key referencing one of the {@link MAPPERS} built-ins (e.g.\n * `'date_from_json'`).\n * @param value - The raw value to transform.\n * @returns The transformed value.\n *\n * @throws If `mapper` is a string that does not exist in {@link MAPPERS}.\n */\nexport function mapValue(mapper: ((v: any) => any) | string, value: any): any {\n if (typeof mapper === 'string') {\n if (typeof MAPPERS[mapper] !== 'function') {\n throw new Error(`unknown mapper \"${mapper}\"`);\n }\n return MAPPERS[mapper](value);\n }\n if (typeof mapper === 'function') {\n return mapper(value);\n }\n throw new Error(\"couldn't map value\");\n}\n\n// ---------------------------------------------------------------------------\n// mapObject — apply mappers to all matching keys of an object\n// ---------------------------------------------------------------------------\n\n/**\n * Apply a map of per-key transformations to an object, returning a new object\n * with the transformed values.\n *\n * Keys not present in `mappers` are copied through unchanged. Keys present in\n * `mappers` are passed through {@link mapValue}.\n *\n * @param obj - The source object (e.g. a raw database row).\n * @param mappers - A `Record` mapping property keys to mapper functions or\n * {@link MAPPERS} built-in names.\n * @returns A shallow copy of `obj` with the specified values transformed.\n *\n * @throws If `obj` is `null` or a non-object, it is returned as-is.\n */\nexport function mapObject<T extends Record<string, any>>(\n obj: T,\n mappers: Record<string, ((v: any) => any) | string>\n): T {\n if (!mappers) throw new Error('mappers should be an object');\n if (!obj || typeof obj !== 'object' || obj === null) return obj;\n\n const result = {} as Record<string, any>;\n for (const key of Object.keys(obj)) {\n result[key] = mappers[key]\n ? mapValue(mappers[key], obj[key])\n : obj[key];\n }\n return result as T;\n}\n\n// ---------------------------------------------------------------------------\n// clearRow — apply mappers to joined data in a result row\n// ---------------------------------------------------------------------------\n\n/**\n * Apply value mappers to the joined fields of a result row in place.\n *\n * After an eager-loaded query resolves, joined objects and arrays may contain\n * raw database values that need transformation (e.g. date strings → `Date`).\n * This function iterates over the one-to-one and one-to-many specs, applies\n * the `mappers` defined on each spec to the nested data, and returns the\n * mutated row.\n *\n * This is an internal helper used by {@link SchemaQueryBuilder}'s result\n * mapping pipeline. Exported to allow custom post-processing if needed.\n *\n * @param row - The raw result row (mutated in place).\n * @param oneSpecs - Validated one-to-one join specs with optional `mappers`.\n * @param manySpecs - Validated one-to-many join specs with optional `mappers`.\n * @returns The mutated `row` object.\n */\nexport function clearRow(\n row: Record<string, any>,\n oneSpecs: Array<ValidatedSpec & { type: 'one' }>,\n manySpecs: Array<ValidatedSpec & { type: 'many' }>\n): Record<string, any> {\n for (const spec of oneSpecs) {\n const fieldName = spec.as;\n if (\n spec.mappers &&\n typeof row[fieldName] !== 'undefined' &&\n row[fieldName] !== null\n ) {\n row[fieldName] = mapObject(row[fieldName], spec.mappers);\n }\n }\n\n for (const spec of manySpecs) {\n const fieldName = spec.as;\n if (Array.isArray(row[fieldName])) {\n for (let k = 0; k < row[fieldName].length; k++) {\n if (row[fieldName][k]) {\n if (spec.mappers) {\n row[fieldName][k] = mapObject(\n row[fieldName][k],\n spec.mappers\n );\n }\n }\n }\n }\n }\n\n return row;\n}\n","// @cleverbrush/knex-schema — Schema diff & migration generation\n\nimport type { ObjectSchemaBuilder, SchemaBuilder } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { generateCreateTableSource } from './ddl.js';\nimport type { Entity } from './entity.js';\nimport {\n getColumnName,\n getPolymorphicVariantSchemas,\n getTableName\n} from './extension.js';\nimport type {\n AddColumnDiff,\n AddForeignKeyDiff,\n AddIndexDiff,\n AlterColumnDiff,\n DatabaseCheckInfo,\n DatabaseColumnInfo,\n DatabaseForeignKeyInfo,\n DatabaseIndexInfo,\n DatabaseTableState,\n MigrationDiff,\n SchemaSnapshot\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// Database introspection\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize raw database query results into a {@link DatabaseTableState}.\n * @internal\n */\nfunction normalizeDbState(\n columns: any[],\n indexes: any[],\n foreignKeys: any[],\n checks: any[]\n): DatabaseTableState {\n const colMap: Record<string, DatabaseColumnInfo> = {};\n for (const row of columns) {\n colMap[row.column_name] = {\n name: row.column_name,\n type: row.data_type,\n nullable: row.is_nullable === 'YES',\n defaultValue: row.column_default ?? null,\n maxLength: row.character_maximum_length ?? null,\n numericPrecision: row.numeric_precision ?? null\n };\n }\n\n const idxList: DatabaseIndexInfo[] = indexes.map((row: any) => ({\n name: row.indexname,\n columns: Array.isArray(row.columns) ? row.columns : [],\n unique: (row.indexdef ?? '').toUpperCase().includes('UNIQUE'),\n definition: row.indexdef ?? ''\n }));\n\n const fkList: DatabaseForeignKeyInfo[] = foreignKeys.map((row: any) => ({\n constraintName: row.constraint_name,\n columnName: row.column_name,\n foreignTable: row.foreign_table,\n foreignColumn: row.foreign_column,\n deleteRule: row.delete_rule,\n updateRule: row.update_rule\n }));\n\n const chkList: DatabaseCheckInfo[] = checks.map((row: any) => ({\n name: row.conname,\n definition: row.definition\n }));\n\n return {\n columns: colMap,\n indexes: idxList,\n foreignKeys: fkList,\n checks: chkList\n };\n}\n\n/**\n * Introspect a PostgreSQL table and return its current state.\n *\n * Queries `information_schema.columns`, `pg_indexes`, `pg_constraint`, and\n * referential constraint metadata to build a complete picture of the table's\n * columns, indexes, foreign keys, and check constraints.\n *\n * @param knex - A configured Knex instance connected to a PostgreSQL database.\n * @param tableName - The table name to introspect.\n * @returns The current database state for the table.\n *\n * @example\n * ```ts\n * const dbState = await introspectDatabase(knex, 'users');\n * console.log(dbState.columns); // { id: { type: 'integer', ... }, ... }\n * ```\n */\nexport async function introspectDatabase(\n knex: Knex,\n tableName: string\n): Promise<DatabaseTableState> {\n const [columns, indexes, foreignKeys, checks] = await Promise.all([\n knex.raw(\n `SELECT column_name, data_type, is_nullable, column_default,\n character_maximum_length, numeric_precision\n FROM information_schema.columns\n WHERE table_name = ? AND table_schema = 'public'\n ORDER BY ordinal_position`,\n [tableName]\n ),\n knex.raw(\n `SELECT indexname, indexdef,\n array_agg(a.attname ORDER BY array_position(ix.indkey, a.attnum)) as columns\n FROM pg_indexes\n JOIN pg_class t ON t.relname = ?\n JOIN pg_index ix ON ix.indrelid = t.oid\n JOIN pg_class i ON i.oid = ix.indexrelid AND i.relname = pg_indexes.indexname\n JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\n WHERE pg_indexes.tablename = ?\n GROUP BY indexname, indexdef`,\n [tableName, tableName]\n ),\n knex.raw(\n `SELECT tc.constraint_name, kcu.column_name,\n ccu.table_name AS foreign_table, ccu.column_name AS foreign_column,\n rc.delete_rule, rc.update_rule\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu USING (constraint_name, table_schema)\n JOIN information_schema.constraint_column_usage ccu USING (constraint_name, table_schema)\n JOIN information_schema.referential_constraints rc USING (constraint_name, constraint_schema)\n WHERE tc.table_name = ? AND tc.constraint_type = 'FOREIGN KEY'`,\n [tableName]\n ),\n knex.raw(\n `SELECT conname, pg_get_constraintdef(oid) as definition\n FROM pg_constraint\n WHERE conrelid = ?::regclass AND contype = 'c'`,\n [tableName]\n )\n ]);\n\n return normalizeDbState(\n columns.rows,\n indexes.rows,\n foreignKeys.rows,\n checks.rows\n );\n}\n\n// ---------------------------------------------------------------------------\n// Schema → column info extraction\n// ---------------------------------------------------------------------------\n\n/** @internal Map a schema type to a PostgreSQL data_type string for comparison. */\nfunction schemaTypeToDbType(\n introspected: any,\n ext: Record<string, any>\n): string {\n if (ext.columnType) return ext.columnType;\n if (ext.primaryKey?.autoIncrement) return 'integer';\n switch (introspected.type) {\n case 'string':\n return 'character varying';\n case 'number':\n return introspected.isInteger !== false\n ? 'integer'\n : 'double precision';\n case 'boolean':\n return 'boolean';\n case 'date':\n return 'timestamp without time zone';\n default:\n return 'text';\n }\n}\n\n// ---------------------------------------------------------------------------\n// entitySchemaToTableState\n// ---------------------------------------------------------------------------\n\n/**\n * Derive a {@link DatabaseTableState} from a code-first `ObjectSchemaBuilder`\n * without connecting to the database.\n *\n * The result mirrors what {@link introspectDatabase} would return after the\n * schema has been fully applied, so it can be fed directly into\n * {@link diffSchema} as the `dbState` argument. This is the foundation of\n * snapshot-based migration generation.\n *\n * @param schema - An `ObjectSchemaBuilder` with DDL extensions.\n * @returns A {@link DatabaseTableState} representing the schema's ideal DB shape.\n *\n * @example\n * ```ts\n * const state = entitySchemaToTableState(UserSchema);\n * // state.columns, state.foreignKeys, state.indexes …\n * ```\n */\nexport function entitySchemaToTableState(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): DatabaseTableState {\n const tableName = getTableName(schema);\n const introspected = schema.introspect() as any;\n const properties: Record<\n string,\n SchemaBuilder<any, any, any>\n > = introspected.properties ?? {};\n const tableExt: Record<string, any> = introspected.extensions ?? {};\n\n const columns: Record<string, DatabaseColumnInfo> = {};\n const indexes: DatabaseIndexInfo[] = [];\n const foreignKeys: DatabaseForeignKeyInfo[] = [];\n const checks: DatabaseCheckInfo[] = [];\n\n for (const [propKey, propSchema] of Object.entries(properties)) {\n const col = getColumnName(propSchema, propKey);\n const propIntrospected = propSchema.introspect() as any;\n const ext: Record<string, any> = propIntrospected.extensions ?? {};\n\n // Skip navigation properties (object/array without an explicit columnType).\n if (\n (propIntrospected.type === 'object' ||\n propIntrospected.type === 'array') &&\n !ext.columnType\n ) {\n continue;\n }\n\n columns[col] = {\n name: col,\n type: schemaTypeToDbType(propIntrospected, ext),\n nullable: !propIntrospected.isRequired,\n defaultValue: ext.defaultTo ?? null,\n maxLength: ext.maxLength ?? propIntrospected.maxLength ?? null,\n numericPrecision: null\n };\n\n if (ext.references) {\n foreignKeys.push({\n // Use Knex's default FK constraint naming convention\n constraintName: `${tableName}_${col}_foreign`,\n columnName: col,\n foreignTable: ext.references.table,\n foreignColumn: ext.references.column,\n deleteRule: (ext.onDelete ?? 'NO ACTION').toUpperCase(),\n updateRule: (ext.onUpdate ?? 'NO ACTION').toUpperCase()\n });\n }\n }\n\n // Timestamp columns (created_at / updated_at)\n if (tableExt.timestamps) {\n const ts = tableExt.timestamps;\n const createdAtCol: string = ts.createdAt ?? 'created_at';\n const updatedAtCol: string = ts.updatedAt ?? 'updated_at';\n columns[createdAtCol] = {\n name: createdAtCol,\n type: 'timestamp without time zone',\n nullable: false,\n defaultValue: 'now',\n maxLength: null,\n numericPrecision: null\n };\n columns[updatedAtCol] = {\n name: updatedAtCol,\n type: 'timestamp without time zone',\n nullable: false,\n defaultValue: 'now',\n maxLength: null,\n numericPrecision: null\n };\n }\n\n // Soft-delete column\n if (tableExt.softDelete) {\n const delCol: string = tableExt.softDelete.column ?? 'deleted_at';\n columns[delCol] = {\n name: delCol,\n type: 'timestamp without time zone',\n nullable: true,\n defaultValue: null,\n maxLength: null,\n numericPrecision: null\n };\n }\n\n // Non-unique indexes\n for (const idx of tableExt.indexes ?? []) {\n const idxName: string =\n idx.name ?? `idx_${(idx.columns as string[]).join('_')}`;\n indexes.push({\n name: idxName,\n columns: idx.columns,\n unique: idx.unique ?? false,\n definition: ''\n });\n }\n\n // Unique constraints\n for (const unq of tableExt.uniques ?? []) {\n const unqName: string =\n unq.name ?? `unq_${(unq.columns as string[]).join('_')}`;\n indexes.push({\n name: unqName,\n columns: unq.columns,\n unique: true,\n definition: ''\n });\n }\n\n return { columns, indexes, foreignKeys, checks };\n}\n\n// ---------------------------------------------------------------------------\n// diffSchema\n// ---------------------------------------------------------------------------\n\n/**\n * Compare a code-first schema model against a live database table state and\n * produce a diff describing the changes needed to bring the database in sync.\n *\n * @param schema - The code-first `ObjectSchemaBuilder`.\n * @param dbState - The current database state from {@link introspectDatabase}.\n * @returns A {@link MigrationDiff} describing columns, indexes, and foreign\n * keys to add, drop, or alter.\n *\n * @example\n * ```ts\n * const dbState = await introspectDatabase(knex, 'users');\n * const diff = diffSchema(UserSchema, dbState);\n * if (diff.addColumns.length > 0) {\n * const migration = generateMigration(diff, 'users');\n * console.log(migration.up);\n * }\n * ```\n */\nexport function diffSchema(\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n dbState: DatabaseTableState\n): MigrationDiff {\n const introspected = schema.introspect() as any;\n const properties: Record<\n string,\n SchemaBuilder<any, any, any>\n > = introspected.properties ?? {};\n const tableExt: Record<string, any> = introspected.extensions ?? {};\n\n const addColumns: AddColumnDiff[] = [];\n const dropColumns: string[] = [];\n const alterColumns: AlterColumnDiff[] = [];\n const addIndexes: AddIndexDiff[] = [];\n const dropIndexes: string[] = [];\n const addForeignKeys: AddForeignKeyDiff[] = [];\n const dropForeignKeys: string[] = [];\n\n // Columns whose default values are owned by table-level extensions\n // (hasTimestamps, softDelete). Don't compare defaultValue for these —\n // the extension is authoritative.\n const extensionOwnedDefaults = new Set<string>();\n if (tableExt.timestamps) {\n extensionOwnedDefaults.add(tableExt.timestamps.createdAt);\n extensionOwnedDefaults.add(tableExt.timestamps.updatedAt);\n }\n\n // Set of schema-defined column names\n const schemaColumns = new Set<string>();\n\n // --- Column diff ---\n for (const [propKey, propSchema] of Object.entries(properties)) {\n const col = getColumnName(propSchema, propKey);\n const propIntrospected = propSchema.introspect() as any;\n const ext: Record<string, any> = propIntrospected.extensions ?? {};\n\n // Skip navigation properties (object/array without explicit columnType).\n if (\n (propIntrospected.type === 'object' ||\n propIntrospected.type === 'array') &&\n !ext.columnType\n ) {\n continue;\n }\n\n schemaColumns.add(col);\n\n const dbCol = dbState.columns[col];\n if (!dbCol) {\n // Column exists in schema but not in DB → add\n addColumns.push({\n name: col,\n type: schemaTypeToDbType(propIntrospected, ext),\n nullable: !propIntrospected.isRequired,\n defaultValue: ext.defaultTo,\n references: ext.references,\n onDelete: ext.onDelete,\n onUpdate: ext.onUpdate\n });\n } else {\n // Column exists in both → check for alterations\n const changes: Record<string, { from: any; to: any }> = {};\n\n const expectedNullable = !propIntrospected.isRequired;\n if (dbCol.nullable !== expectedNullable) {\n changes.nullable = {\n from: dbCol.nullable,\n to: expectedNullable\n };\n }\n\n // Compare defaultValue (null / undefined both mean \"no default\")\n // Skip columns whose default is controlled by a table-level extension,\n // or auto-increment PKs whose nextval(...) default is DB-managed.\n if (\n !extensionOwnedDefaults.has(col) &&\n !ext.primaryKey?.autoIncrement\n ) {\n const snapshotDefault = dbCol.defaultValue ?? null;\n const schemaDefault = ext.defaultTo ?? null;\n if (snapshotDefault !== schemaDefault) {\n changes.defaultValue = {\n from: snapshotDefault,\n to: schemaDefault\n };\n }\n }\n\n if (Object.keys(changes).length > 0) {\n alterColumns.push({ name: col, changes });\n }\n }\n\n // Foreign key diff\n if (ext.references) {\n const existingFK = dbState.foreignKeys.find(\n fk => fk.columnName === col\n );\n if (!existingFK) {\n addForeignKeys.push({\n column: col,\n foreignTable: ext.references.table,\n foreignColumn: ext.references.column,\n onDelete: ext.onDelete,\n onUpdate: ext.onUpdate\n });\n }\n }\n }\n\n // Include timestamp columns in schema column set\n if (tableExt.timestamps) {\n schemaColumns.add(tableExt.timestamps.createdAt);\n schemaColumns.add(tableExt.timestamps.updatedAt);\n }\n if (tableExt.softDelete) {\n schemaColumns.add(tableExt.softDelete.column);\n }\n\n // Columns in DB but not in schema → drop\n for (const colName of Object.keys(dbState.columns)) {\n if (!schemaColumns.has(colName)) {\n dropColumns.push(colName);\n }\n }\n\n // --- Index diff ---\n const schemaIndexNames = new Set<string>();\n\n for (const idx of tableExt.indexes ?? []) {\n const idxName = idx.name ?? `idx_${idx.columns.join('_')}`;\n schemaIndexNames.add(idxName);\n const existingIdx = dbState.indexes.find(\n dbIdx => dbIdx.name === idxName\n );\n if (!existingIdx) {\n addIndexes.push({\n columns: idx.columns,\n name: idx.name,\n unique: idx.unique\n });\n }\n }\n\n for (const unq of tableExt.uniques ?? []) {\n const unqName = unq.name ?? `unq_${unq.columns.join('_')}`;\n schemaIndexNames.add(unqName);\n const existingIdx = dbState.indexes.find(\n dbIdx => dbIdx.name === unqName\n );\n if (!existingIdx) {\n addIndexes.push({\n columns: unq.columns,\n name: unq.name,\n unique: true\n });\n }\n }\n\n // FK constraints that exist in DB but not in schema → drop\n for (const fk of dbState.foreignKeys) {\n const propSchema = Object.entries(properties).find(([propKey, ps]) => {\n return getColumnName(ps, propKey) === fk.columnName;\n });\n if (propSchema) {\n const ext = (propSchema[1].introspect() as any).extensions ?? {};\n if (!ext.references) {\n dropForeignKeys.push(fk.constraintName);\n }\n } else {\n dropForeignKeys.push(fk.constraintName);\n }\n }\n\n return {\n addColumns,\n dropColumns,\n alterColumns,\n addIndexes,\n dropIndexes,\n addForeignKeys,\n dropForeignKeys\n };\n}\n\n// ---------------------------------------------------------------------------\n// generateMigration\n// ---------------------------------------------------------------------------\n\n/**\n * Generate migration `up` and `down` code strings from a {@link MigrationDiff}.\n *\n * The generated code is valid TypeScript that uses Knex's schema builder API.\n * Write it to a migration file and run via Knex's migration system.\n *\n * @param diff - The schema diff from {@link diffSchema}.\n * @param tableName - The table name to alter.\n * @returns An object with `up` and `down` migration code strings.\n *\n * @example\n * ```ts\n * const diff = diffSchema(UserSchema, dbState);\n * const migration = generateMigration(diff, 'users');\n * fs.writeFileSync('migration.ts', migration.full);\n * ```\n */\nexport function generateMigration(\n diff: MigrationDiff,\n tableName: string\n): { up: string; down: string; full: string } {\n const { up, down } = buildAlterTableFragments(diff, tableName);\n\n const full = `import type { Knex } from 'knex';\n\nexport async function up(knex: Knex): Promise<void> {\n${up}\n}\n\nexport async function down(knex: Knex): Promise<void> {\n${down}\n}\n`;\n\n return { up, down, full };\n}\n\n// ---------------------------------------------------------------------------\n// tableExistsInDb\n// ---------------------------------------------------------------------------\n\n/**\n * Check whether a table exists in the connected PostgreSQL database.\n *\n * @param knex - A configured Knex instance (or transaction).\n * @param tableName - The table name to check.\n * @returns `true` when the table exists.\n *\n * @example\n * ```ts\n * const exists = await tableExistsInDb(knex, 'users');\n * if (!exists) await generateCreateTable(UserSchema)(knex);\n * ```\n */\nexport async function tableExistsInDb(\n knex: Knex,\n tableName: string\n): Promise<boolean> {\n return knex.schema.hasTable(tableName);\n}\n\n// ---------------------------------------------------------------------------\n// isDiffEmpty\n// ---------------------------------------------------------------------------\n\n/**\n * Return `true` when a {@link MigrationDiff} has no operations — i.e. the\n * database table is already in sync with the schema.\n */\nexport function isDiffEmpty(diff: MigrationDiff): boolean {\n return (\n diff.addColumns.length === 0 &&\n diff.dropColumns.length === 0 &&\n diff.alterColumns.length === 0 &&\n diff.addIndexes.length === 0 &&\n diff.dropIndexes.length === 0 &&\n diff.addForeignKeys.length === 0 &&\n diff.dropForeignKeys.length === 0\n );\n}\n\n// ---------------------------------------------------------------------------\n// applyDiff\n// ---------------------------------------------------------------------------\n\n/**\n * Execute a {@link MigrationDiff} directly against a live database without\n * writing a migration file. Intended for `db push` (dev-only schema sync).\n *\n * Foreign-key constraint drops are executed as raw `ALTER TABLE … DROP\n * CONSTRAINT` statements before the main `alterTable` call.\n *\n * @param knex - A configured Knex instance or transaction.\n * @param diff - The diff from {@link diffSchema}.\n * @param tableName - The table to alter.\n *\n * @example\n * ```ts\n * const dbState = await introspectDatabase(knex, 'users');\n * const diff = diffSchema(UserSchema, dbState);\n * if (!isDiffEmpty(diff)) await applyDiff(knex, diff, 'users');\n * ```\n */\nexport async function applyDiff(\n knex: Knex,\n diff: MigrationDiff,\n tableName: string\n): Promise<void> {\n if (isDiffEmpty(diff)) return;\n\n // FK constraint drops require raw SQL (we only have constraint names, not\n // column names, in the diff so Knex's dropForeign helper cannot be used).\n for (const constraintName of diff.dropForeignKeys) {\n await knex.raw('ALTER TABLE ?? DROP CONSTRAINT ??', [\n tableName,\n constraintName\n ]);\n }\n\n const hasTableChanges =\n diff.addColumns.length > 0 ||\n diff.dropColumns.length > 0 ||\n diff.alterColumns.length > 0 ||\n diff.addIndexes.length > 0 ||\n diff.dropIndexes.length > 0 ||\n diff.addForeignKeys.length > 0;\n\n if (!hasTableChanges) return;\n\n await knex.schema.alterTable(tableName, table => {\n // Add columns\n for (const col of diff.addColumns) {\n let column = buildColumnFromDbType(\n table as unknown as Knex.CreateTableBuilder,\n col.name,\n col.type\n );\n if (col.nullable) column = column.nullable();\n else column = column.notNullable();\n if (col.defaultValue !== undefined) {\n if (col.defaultValue === 'now') {\n column = column.defaultTo(knex.fn.now());\n } else if (\n typeof col.defaultValue === 'object' &&\n col.defaultValue !== null &&\n col.defaultValue.raw\n ) {\n column = column.defaultTo(knex.raw(col.defaultValue.raw));\n } else {\n column = column.defaultTo(col.defaultValue);\n }\n }\n if (col.references) {\n const fkBuilder = column\n .references(col.references.column)\n .inTable(col.references.table);\n if (col.onDelete) fkBuilder.onDelete(col.onDelete);\n if (col.onUpdate) fkBuilder.onUpdate(col.onUpdate);\n }\n }\n\n // Drop columns\n for (const colName of diff.dropColumns) {\n table.dropColumn(colName);\n }\n\n // Alter nullable / default\n for (const col of diff.alterColumns) {\n for (const [key, change] of Object.entries(col.changes)) {\n if (key === 'nullable') {\n if (change.to) {\n (table as any).setNullable(col.name);\n } else {\n (table as any).dropNullable(col.name);\n }\n } else if (key === 'defaultValue') {\n if (change.to === null) {\n table.dropColumn(col.name); // fallback — handled in source gen\n } else {\n // ALTER COLUMN SET DEFAULT is not directly in Knex builder;\n // handled via raw in source generation\n }\n }\n }\n }\n\n // Add indexes\n for (const idx of diff.addIndexes) {\n if (idx.unique) {\n table.unique(\n idx.columns,\n idx.name ? { indexName: idx.name } : undefined\n );\n } else {\n table.index(idx.columns, idx.name);\n }\n }\n\n // Drop indexes\n for (const idx of diff.dropIndexes) {\n table.dropIndex([], idx);\n }\n\n // Add foreign keys\n for (const fk of diff.addForeignKeys) {\n let builder = table\n .foreign(fk.column)\n .references(fk.foreignColumn)\n .inTable(fk.foreignTable);\n if (fk.onDelete) builder = builder.onDelete(fk.onDelete);\n if (fk.onUpdate) builder = builder.onUpdate(fk.onUpdate);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// generateMigrationsForContext\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a single combined migration (up + down) for a set of entities by\n * diffing the current code-first schemas against a **serialized snapshot**\n * stored in the repository — no live database connection required.\n *\n * For each entity's table the function:\n * - **New tables** (in entities but not in `prevSnapshot`): emits `CREATE TABLE`.\n * - **Existing tables** (in both): diffs entity schema against the snapshot\n * state via {@link diffSchema} and emits `ALTER TABLE` when changes exist.\n * - **Dropped tables** (in `prevSnapshot` but not in entities): emits\n * `DROP TABLE` with a best-effort `CREATE TABLE` in the `down` direction.\n * - Orders tables topologically by FK dependencies so parent tables are\n * created before child tables in `up` (and dropped after in `down`).\n *\n * @param entities - The entities from your {@link EntityMap}.\n * @param prevSnapshot - The last committed {@link SchemaSnapshot} (empty on first run).\n * @returns `{ up, down, full, isEmpty, nextSnapshot }` where `nextSnapshot`\n * should be written to disk after the migration file is created.\n *\n * @example\n * ```ts\n * const prev = loadSnapshot('./migrations/snapshot.json');\n * const result = generateMigrationsForContext(\n * Object.values({ todos: TodoEntity, users: UserEntity }),\n * prev\n * );\n * if (!result.isEmpty) {\n * fs.writeFileSync('migrations/20260423000000_init.ts', result.full);\n * writeSnapshot('./migrations/snapshot.json', result.nextSnapshot);\n * }\n * ```\n */\nexport function generateMigrationsForContext(\n entities: Entity<any, any>[],\n prevSnapshot: SchemaSnapshot\n): {\n up: string;\n down: string;\n full: string;\n isEmpty: boolean;\n nextSnapshot: SchemaSnapshot;\n} {\n // 1. Collect all (schema, tableName) pairs including CTI variant tables\n const tableEntries: {\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>;\n tableName: string;\n }[] = [];\n\n for (const entity of entities) {\n const schema = entity.schema;\n const tableName = getTableName(schema);\n tableEntries.push({ schema, tableName });\n\n // CTI variant tables each have their own tableName extension set\n for (const vs of getPolymorphicVariantSchemas(schema)) {\n const variantTableName = vs.getExtension('tableName') as\n | string\n | undefined;\n if (variantTableName) {\n tableEntries.push({ schema: vs, tableName: variantTableName });\n }\n }\n }\n\n // 2. Deduplicate (STI variants share the base table)\n const seen = new Set<string>();\n const uniqueEntries = tableEntries.filter(e => {\n if (seen.has(e.tableName)) return false;\n seen.add(e.tableName);\n return true;\n });\n\n // 3. Topological sort by FK dependencies\n const sorted = topologicalSort(uniqueEntries);\n\n // 4. Generate CREATE or ALTER fragment for each current table\n const upParts: string[] = [];\n const downParts: string[] = [];\n\n const currentTableNames = new Set(sorted.map(e => e.tableName));\n\n for (const { schema, tableName } of sorted) {\n const snapshotState = prevSnapshot.tables[tableName];\n if (!snapshotState) {\n // New table — emit CREATE TABLE\n const { up, down } = generateCreateTableSource(schema);\n upParts.push(up);\n downParts.push(down);\n } else {\n // Existing table — diff schema against snapshot (pure, no DB)\n const diff = diffSchema(schema, snapshotState);\n if (!isDiffEmpty(diff)) {\n const { up, down } = buildAlterTableFragments(diff, tableName);\n upParts.push(up);\n downParts.push(down);\n }\n }\n }\n\n // 5. Tables in snapshot but absent from current entities → DROP TABLE\n for (const tableName of Object.keys(prevSnapshot.tables)) {\n if (!currentTableNames.has(tableName)) {\n const state = prevSnapshot.tables[tableName];\n const { up, down } = generateDropTableSource(tableName, state);\n upParts.push(up);\n // Recreate before other downs so FK deps are satisfied\n downParts.unshift(down);\n }\n }\n\n const isEmpty = upParts.length === 0;\n\n // Down reverses creation order so child tables are dropped before parents\n const up = upParts.join('\\n\\n');\n const down = [...downParts].reverse().join('\\n\\n');\n\n const full = `import type { Knex } from 'knex';\n\nexport async function up(knex: Knex): Promise<void> {\n${isEmpty ? ' // No changes needed' : up}\n}\n\nexport async function down(knex: Knex): Promise<void> {\n${isEmpty ? ' // No changes needed' : down}\n}\n`;\n\n // Build the next snapshot from current entity schemas\n const nextTables: Record<string, DatabaseTableState> = {};\n for (const { schema, tableName } of sorted) {\n nextTables[tableName] = entitySchemaToTableState(schema);\n }\n const nextSnapshot: SchemaSnapshot = { version: 1, tables: nextTables };\n\n return { up, down, full, isEmpty, nextSnapshot };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * @internal\n * Emit `DROP TABLE` (up) and a best-effort `CREATE TABLE` reconstruction\n * (down) from a {@link DatabaseTableState} stored in the snapshot.\n * Called for tables that exist in the previous snapshot but are absent from\n * the current entity set.\n */\nfunction generateDropTableSource(\n tableName: string,\n state: DatabaseTableState\n): { up: string; down: string } {\n const up =\n ` // TODO: review destructive change — dropped table '${tableName}'\\n` +\n ` await knex.schema.dropTableIfExists(${JSON.stringify(tableName)});`;\n\n // Reconstruct CREATE TABLE from snapshot state using specificType for\n // all columns so the raw DB types are preserved faithfully.\n const colLines: string[] = [];\n for (const [colName, col] of Object.entries(state.columns)) {\n let line = ` table.specificType(${JSON.stringify(colName)}, ${JSON.stringify(col.type)})`;\n if (col.nullable) line += '.nullable()';\n else line += '.notNullable()';\n if (col.defaultValue !== null && col.defaultValue !== undefined) {\n line += `.defaultTo(${JSON.stringify(col.defaultValue)})`;\n }\n colLines.push(line + ';');\n }\n for (const fk of state.foreignKeys) {\n colLines.push(\n ` table.foreign(${JSON.stringify(fk.columnName)}).references(${JSON.stringify(fk.foreignColumn)}).inTable(${JSON.stringify(fk.foreignTable)}).onDelete(${JSON.stringify(fk.deleteRule)}).onUpdate(${JSON.stringify(fk.updateRule)});`\n );\n }\n for (const idx of state.indexes) {\n if (idx.unique) {\n colLines.push(\n ` table.unique(${JSON.stringify(idx.columns)}, { indexName: ${JSON.stringify(idx.name)} });`\n );\n } else {\n colLines.push(\n ` table.index(${JSON.stringify(idx.columns)}, ${JSON.stringify(idx.name)});`\n );\n }\n }\n\n const down =\n ` await knex.schema.createTable(${JSON.stringify(tableName)}, (table) => {\\n` +\n colLines.join('\\n') +\n '\\n });';\n\n return { up, down };\n}\n\n/**\n * @internal\n * Extract the body of a MigrationDiff into up/down Knex schema code strings\n * (indented 4 spaces, wrapped in `alterTable` when non-empty).\n * Used by both {@link generateMigration} and {@link generateMigrationsForContext}.\n */\nfunction buildAlterTableFragments(\n diff: MigrationDiff,\n tableName: string\n): { up: string; down: string } {\n const upLines: string[] = [];\n const downLines: string[] = [];\n\n // --- ADD COLUMNS ---\n for (const col of diff.addColumns) {\n const typeCall = col.type.includes(' ')\n ? `table.specificType('${col.name}', '${col.type}')`\n : `table.${mapTypeToKnex(col.type)}('${col.name}')`;\n\n let line = ` ${typeCall}`;\n if (col.nullable) line += '.nullable()';\n else line += '.notNullable()';\n if (col.defaultValue !== undefined) {\n line += `.defaultTo(${formatDefault(col.defaultValue)})`;\n }\n line += ';';\n\n upLines.push(line);\n downLines.push(` table.dropColumn('${col.name}');`);\n }\n\n // --- DROP COLUMNS ---\n for (const col of diff.dropColumns) {\n upLines.push(` table.dropColumn('${col}');`);\n downLines.push(\n ` // TODO: recreate column '${col}' with original definition`\n );\n }\n\n // --- ALTER COLUMNS ---\n for (const col of diff.alterColumns) {\n for (const [key, change] of Object.entries(col.changes)) {\n if (key === 'nullable') {\n if (change.to) {\n upLines.push(` table.setNullable('${col.name}');`);\n downLines.push(\n ` table.dropNullable('${col.name}');`\n );\n } else {\n upLines.push(` table.dropNullable('${col.name}');`);\n downLines.push(` table.setNullable('${col.name}');`);\n }\n } else if (key === 'defaultValue') {\n const toVal = change.to;\n const fromVal = change.from;\n if (toVal === null) {\n upLines.push(\n ` table.timestamp('${col.name}').alter(); // DROP DEFAULT`\n );\n downLines.push(\n ` table.timestamp('${col.name}').defaultTo(knex.fn.now()).alter();`\n );\n } else {\n upLines.push(\n ` table.timestamp('${col.name}').notNullable().defaultTo(knex.fn.now()).alter();`\n );\n downLines.push(\n fromVal === null\n ? ` table.timestamp('${col.name}').notNullable().alter();`\n : ` table.timestamp('${col.name}').notNullable().defaultTo(knex.fn.now()).alter();`\n );\n }\n }\n }\n }\n\n // --- ADD INDEXES ---\n for (const idx of diff.addIndexes) {\n const cols = JSON.stringify(idx.columns);\n if (idx.unique) {\n upLines.push(\n ` table.unique(${cols}${idx.name ? `, { indexName: '${idx.name}' }` : ''});`\n );\n downLines.push(\n ` table.dropUnique(${cols}${idx.name ? `, '${idx.name}'` : ''});`\n );\n } else {\n upLines.push(\n ` table.index(${cols}${idx.name ? `, '${idx.name}'` : ''});`\n );\n downLines.push(\n ` table.dropIndex([]${idx.name ? `, '${idx.name}'` : ''});`\n );\n }\n }\n\n // --- DROP INDEXES ---\n for (const idx of diff.dropIndexes) {\n upLines.push(` table.dropIndex([], '${idx}');`);\n downLines.push(\n ` // TODO: recreate index '${idx}' with original definition`\n );\n }\n\n // --- ADD FOREIGN KEYS ---\n for (const fk of diff.addForeignKeys) {\n let line = ` table.foreign('${fk.column}').references('${fk.foreignColumn}').inTable('${fk.foreignTable}')`;\n if (fk.onDelete) line += `.onDelete('${fk.onDelete}')`;\n if (fk.onUpdate) line += `.onUpdate('${fk.onUpdate}')`;\n line += ';';\n upLines.push(line);\n downLines.push(` table.dropForeign('${fk.column}');`);\n }\n\n // --- DROP FOREIGN KEYS ---\n for (const fk of diff.dropForeignKeys) {\n upLines.push(` // TODO: drop foreign key constraint '${fk}'`);\n }\n\n const isEmpty = upLines.length === 0;\n\n const up = isEmpty\n ? ` // No changes needed`\n : ` await knex.schema.alterTable('${tableName}', (table) => {\\n${upLines.join('\\n')}\\n });`;\n\n const down = isEmpty\n ? ` // No changes needed`\n : ` await knex.schema.alterTable('${tableName}', (table) => {\\n${downLines.join('\\n')}\\n });`;\n\n return { up, down };\n}\n\n/** @internal Build a Knex ColumnBuilder from a PostgreSQL data type string (runtime use). */\nfunction buildColumnFromDbType(\n table: Knex.CreateTableBuilder,\n name: string,\n dbType: string\n): Knex.ColumnBuilder {\n switch (dbType) {\n case 'integer':\n return table.integer(name);\n case 'character varying':\n return table.string(name);\n case 'text':\n return table.text(name);\n case 'boolean':\n return table.boolean(name);\n case 'timestamp without time zone':\n case 'timestamp':\n return table.timestamp(name);\n case 'double precision':\n case 'float':\n return table.float(name);\n case 'jsonb':\n case 'json':\n return table.specificType(name, 'jsonb');\n case 'uuid':\n return table.uuid(name);\n default:\n return table.specificType(name, dbType);\n }\n}\n\n/**\n * @internal\n * Topologically sort table entries by FK dependency so parent tables\n * come first in `up` (and last in `down`). Falls back to original order\n * for cycles or external references.\n */\nfunction topologicalSort(\n entries: {\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>;\n tableName: string;\n }[]\n): typeof entries {\n const tableSet = new Set(entries.map(e => e.tableName));\n const deps = new Map<string, Set<string>>();\n\n for (const { schema, tableName } of entries) {\n const depSet = new Set<string>();\n const properties: Record<string, any> =\n (schema.introspect() as any).properties ?? {};\n for (const [, propSchema] of Object.entries(properties)) {\n const ext =\n ((propSchema as any).introspect?.() as any)?.extensions ?? {};\n if (ext.references?.table && tableSet.has(ext.references.table)) {\n depSet.add(ext.references.table);\n }\n }\n deps.set(tableName, depSet);\n }\n\n // Kahn's algorithm\n const inDegree = new Map<string, number>();\n const graph = new Map<string, string[]>(); // dep -> tables that depend on it\n for (const { tableName } of entries) {\n inDegree.set(tableName, 0);\n graph.set(tableName, []);\n }\n for (const { tableName } of entries) {\n for (const dep of deps.get(tableName) ?? []) {\n graph.get(dep)!.push(tableName);\n inDegree.set(tableName, (inDegree.get(tableName) ?? 0) + 1);\n }\n }\n\n const queue: string[] = [];\n for (const [t, deg] of inDegree) {\n if (deg === 0) queue.push(t);\n }\n\n const sortedNames: string[] = [];\n while (queue.length > 0) {\n const t = queue.shift()!;\n sortedNames.push(t);\n for (const dependent of graph.get(t) ?? []) {\n const newDeg = inDegree.get(dependent)! - 1;\n inDegree.set(dependent, newDeg);\n if (newDeg === 0) queue.push(dependent);\n }\n }\n\n // Append any cycles / unresolved entries in their original relative order\n const sortedSet = new Set(sortedNames);\n const remaining = entries.filter(e => !sortedSet.has(e.tableName));\n const byName = new Map(entries.map(e => [e.tableName, e]));\n return [...sortedNames.map(t => byName.get(t)!), ...remaining];\n}\n\n/** @internal Map a PostgreSQL data type string to a Knex column method name. */\nfunction mapTypeToKnex(type: string): string {\n switch (type) {\n case 'integer':\n return 'integer';\n case 'character varying':\n return 'string';\n case 'text':\n return 'text';\n case 'boolean':\n return 'boolean';\n case 'timestamp without time zone':\n case 'timestamp':\n return 'timestamp';\n case 'double precision':\n case 'float':\n return 'float';\n case 'jsonb':\n case 'json':\n return 'jsonb';\n case 'uuid':\n return 'uuid';\n default:\n return `specificType('${type}')` as any;\n }\n}\n\n/** @internal Format a default value for migration code generation. */\nfunction formatDefault(value: any): string {\n if (value === 'now') return 'knex.fn.now()';\n if (typeof value === 'object' && value !== null && value.raw) {\n return `knex.raw('${value.raw.replace(/'/g, \"\\\\'\")}')`;\n }\n if (typeof value === 'string') return `'${value.replace(/'/g, \"\\\\'\")}'`;\n return String(value);\n}\n","// @cleverbrush/knex-schema — Raw query execution with schema result mapping\n\nimport type { InferType, ObjectSchemaBuilder } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { buildColumnMap } from './columns.js';\n\n/**\n * Execute a raw SQL query or Knex query builder and map the result rows\n * through the schema's column→property name mapping.\n *\n * This is the escape hatch for complex queries that can't be expressed with\n * the typed `SchemaQueryBuilder` API. The schema is used only for result\n * mapping — column names in the result are converted back to property names.\n * Extra columns (not in the schema) are passed through unchanged.\n *\n * @param knex - A configured Knex instance.\n * @param schema - The `ObjectSchemaBuilder` for result mapping.\n * @param queryOrSql - A raw SQL string or a `Knex.QueryBuilder`.\n * @param bindings - Optional bindings for parameterised SQL queries.\n * @returns Mapped result rows.\n *\n * @example\n * ```ts\n * // Raw SQL with schema result mapping\n * const results = await rawQuery(knex, PostSchema, `\n * SELECT p.*, COUNT(c.id) AS comment_count\n * FROM posts p\n * LEFT JOIN comments c ON c.post_id = p.id\n * GROUP BY p.id\n * ORDER BY comment_count DESC\n * LIMIT ?\n * `, [10]);\n *\n * // Knex query builder as the source\n * const subQuery = knex('posts').select('author_id', knex.raw('COUNT(*) as post_count')).groupBy('author_id');\n * const results = await rawQuery(knex, UserSchema, subQuery);\n * ```\n */\nexport async function rawQuery<\n TSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n>(\n knex: Knex,\n schema: TSchema,\n queryOrSql: string | Knex.QueryBuilder,\n bindings?: any[]\n): Promise<(InferType<TSchema> & Record<string, any>)[]> {\n let rows: any[];\n\n if (typeof queryOrSql === 'string') {\n const result = await knex.raw(queryOrSql, bindings ?? []);\n rows = result.rows ?? result;\n } else {\n rows = await queryOrSql;\n }\n\n if (!rows || !Array.isArray(rows)) return [];\n\n const { colToProp } = buildColumnMap(schema);\n\n return rows.map(row => {\n const mapped: Record<string, any> = {};\n for (const [key, value] of Object.entries(row)) {\n const propName = colToProp.get(key);\n mapped[propName ?? key] = value;\n }\n return mapped;\n }) as any;\n}\n","// @cleverbrush/knex-schema — SELECT / DISTINCT / aggregates / projections / scopes\n\nimport {\n ObjectSchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { buildColumnMap } from '../columns.js';\nimport { getProjections } from '../extension.js';\nimport type { SchemaQueryBuilder } from '../SchemaQueryBuilder.js';\nimport type { ColumnRef } from '../types.js';\nimport {\n assertNotExplicitSelect,\n assertNotProjection,\n invalidateCache,\n resolveColumn,\n resolveColumnArg\n} from './helpers.js';\nimport { getState } from './state.js';\n\nexport function selectImpl(\n builder: SchemaQueryBuilder<any, any>,\n ...args: unknown[]\n): any {\n const state = getState(builder);\n\n if (args.length === 1 && typeof args[0] === 'function') {\n const fn = args[0] as (t: any) => unknown;\n const tree = ObjectSchemaBuilder.getPropertiesFor(\n state.localSchema as any\n );\n const result = fn(tree);\n if (\n result &&\n typeof result === 'object' &&\n !(SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in (result as object))\n ) {\n invalidateCache(builder);\n assertNotProjection(builder, 'select');\n state.selectionMode = 'projection';\n state.appliedProjection = '<inline>';\n\n const aliasMap: Record<string, string> = {};\n state.explicitSelects ??= [];\n for (const [alias, descriptor] of Object.entries(\n result as Record<string, unknown>\n )) {\n if (\n !descriptor ||\n typeof descriptor !== 'object' ||\n !(\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in\n (descriptor as object)\n )\n ) {\n throw new Error(\n `select(selector): value for alias \"${alias}\" must be a property descriptor (e.g. \\`t.someProp\\`).`\n );\n }\n const col = resolveColumn(\n builder,\n (() => descriptor) as ColumnRef<any>,\n `select(selector).${alias}`\n );\n aliasMap[alias] = col as string;\n state.explicitSelects.push(col as string);\n }\n state.baseQuery.select(aliasMap);\n return builder;\n }\n }\n\n invalidateCache(builder);\n assertNotProjection(builder, 'select');\n state.selectionMode = 'select';\n const resolved = (args as (ColumnRef<any> | Knex.Raw)[]).map(c =>\n resolveColumnArg(builder, c)\n );\n state.baseQuery.select(...(resolved as string[]));\n state.explicitSelects ??= [];\n for (const r of resolved) {\n if (typeof r === 'string') {\n state.explicitSelects.push(r);\n }\n }\n return builder;\n}\n\nexport function distinctImpl(\n builder: SchemaQueryBuilder<any, any>,\n ...columns: (ColumnRef<any> | Knex.Raw)[]\n): any {\n invalidateCache(builder);\n const resolved = columns.map(c => resolveColumnArg(builder, c));\n getState(builder).baseQuery.distinct(...(resolved as string[]));\n return builder;\n}\n\nexport function countImpl(\n builder: SchemaQueryBuilder<any, any>,\n column?: ColumnRef<any> | Knex.Raw\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n assertNotProjection(builder, 'count');\n state.selectionMode = 'aggregate';\n if (column) {\n state.baseQuery.count(resolveColumnArg(builder, column) as string);\n } else {\n state.baseQuery.count();\n }\n return builder;\n}\n\nexport function countDistinctImpl(\n builder: SchemaQueryBuilder<any, any>,\n column?: ColumnRef<any> | Knex.Raw\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n assertNotProjection(builder, 'countDistinct');\n state.selectionMode = 'aggregate';\n if (column) {\n state.baseQuery.countDistinct(\n resolveColumnArg(builder, column) as string\n );\n } else {\n state.baseQuery.countDistinct();\n }\n return builder;\n}\n\nexport function minImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any> | Knex.Raw\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n assertNotProjection(builder, 'min');\n state.selectionMode = 'aggregate';\n state.baseQuery.min(resolveColumnArg(builder, column) as string);\n return builder;\n}\n\nexport function maxImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any> | Knex.Raw\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n assertNotProjection(builder, 'max');\n state.selectionMode = 'aggregate';\n state.baseQuery.max(resolveColumnArg(builder, column) as string);\n return builder;\n}\n\nexport function sumImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any> | Knex.Raw\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n assertNotProjection(builder, 'sum');\n state.selectionMode = 'aggregate';\n state.baseQuery.sum(resolveColumnArg(builder, column) as string);\n return builder;\n}\n\nexport function avgImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any> | Knex.Raw\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n assertNotProjection(builder, 'avg');\n state.selectionMode = 'aggregate';\n state.baseQuery.avg(resolveColumnArg(builder, column) as string);\n return builder;\n}\n\nexport function selectRawImpl(\n builder: SchemaQueryBuilder<any, any>,\n sql: string,\n bindings?: any[]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n if (bindings) {\n state.baseQuery.select(state.knex.raw(sql, bindings));\n } else {\n state.baseQuery.select(state.knex.raw(sql));\n }\n return builder;\n}\n\nexport function projectedImpl(\n builder: SchemaQueryBuilder<any, any>,\n name: string\n): any {\n const state = getState(builder);\n assertNotExplicitSelect(builder, 'projected');\n if (state.selectionMode === 'projection') {\n throw new Error(\n `Cannot call .projected('${name}') — .projected('${\n state.appliedProjection\n }') was already applied. Only one projection per query.`\n );\n }\n const projections = getProjections(state.localSchema as any);\n const projection = projections[name];\n if (!projection) {\n throw new Error(\n `Unknown projection \"${name}\" on schema for table \"${\n state.tableName\n }\"`\n );\n }\n const { propToCol } = buildColumnMap(state.localSchema as any);\n const sqlCols = projection.keys.map(key => propToCol.get(key) ?? key);\n state.baseQuery.select(...sqlCols);\n state.explicitSelects ??= [];\n for (const col of sqlCols) {\n state.explicitSelects.push(col);\n }\n state.selectionMode = 'projection';\n state.appliedProjection = name;\n invalidateCache(builder);\n return builder;\n}\n\nexport function scopedImpl(\n builder: SchemaQueryBuilder<any, any>,\n name: string\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n const scopes = (state.localSchema as any).getExtension?.('scopes') as\n | Record<string, Function>\n | undefined;\n const scopeFn = scopes?.[name];\n if (!scopeFn) {\n throw new Error(\n `Unknown scope \"${name}\" on schema for table \"${state.tableName}\"`\n );\n }\n scopeFn(builder);\n return builder;\n}\n\nexport function unscopedImpl(builder: SchemaQueryBuilder<any, any>): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.skipDefaultScope = true;\n state.includeDeleted = true;\n return builder;\n}\n","// @cleverbrush/knex-schema — Extracted helper functions from SchemaQueryBuilder\n\nimport type { InferType } from '@cleverbrush/schema';\nimport {\n EXTRA_TYPE_BRAND,\n METHOD_LITERAL_BRAND,\n ObjectSchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport {\n buildColumnMap,\n getPrimaryKeyColumns,\n resolveColumnRef\n} from '../columns.js';\nimport {\n getTableName,\n getVariants,\n POLYMORPHIC_TYPE_BRAND\n} from '../extension.js';\nimport { clearRow } from '../mappers.js';\nimport type { SchemaQueryBuilder } from '../SchemaQueryBuilder.js';\nimport type {\n ColumnRef,\n ResolvedVariantConfig,\n ResolvedVariantRelationSpec,\n ValidatedSpec\n} from '../types.js';\nimport { getState } from './state.js';\n\n// ---------------------------------------------------------------------------\n// Type-level helpers\n// ---------------------------------------------------------------------------\n\nexport type ScopesOf<S> = S extends {\n readonly [METHOD_LITERAL_BRAND]?: infer N;\n}\n ? Extract<N, string>\n : never;\n\nexport type ProjectionsOf<S> = S extends {\n readonly [EXTRA_TYPE_BRAND]?: infer P;\n}\n ? P extends Record<string, readonly string[]>\n ? P\n : Record<never, never>\n : Record<never, never>;\n\nexport type ProjectionKeysOf<\n S,\n K extends keyof ProjectionsOf<S> & string\n> = ProjectionsOf<S>[K] extends readonly (infer T extends string)[]\n ? T\n : string;\n\nexport type QueryResultType<TLocalSchema> = TLocalSchema extends {\n readonly [POLYMORPHIC_TYPE_BRAND]?: infer U;\n}\n ? NonNullable<U>\n : InferType<TLocalSchema>;\n\n// ---------------------------------------------------------------------------\n// State-based helpers\n// ---------------------------------------------------------------------------\n\nexport function resolveColumn(\n builder: SchemaQueryBuilder<any, any>,\n ref: any,\n label = 'column'\n): string | Knex.Raw {\n const state = getState(builder);\n return resolveColumnRef(\n ref as ColumnRef<any>,\n state.localSchema,\n label,\n state.knex\n );\n}\n\nexport function invalidateCache(builder: SchemaQueryBuilder<any, any>): void {\n getState(builder).cachedBuiltQuery = null;\n}\n\nexport function getSoftDelete(\n builder: SchemaQueryBuilder<any, any>\n): { column: string } | null {\n const state = getState(builder);\n const ext = (state.localSchema as any).getExtension?.('softDelete');\n return ext ?? null;\n}\n\nexport function getDefaultScope(\n builder: SchemaQueryBuilder<any, any>\n): Function | null {\n const state = getState(builder);\n const fn = (state.localSchema as any).getExtension?.('defaultScope');\n return typeof fn === 'function' ? fn : null;\n}\n\nexport function getTimestamps(\n builder: SchemaQueryBuilder<any, any>\n): { createdAt: string; updatedAt: string } | null {\n const state = getState(builder);\n const ts = (state.localSchema as any).getExtension?.('timestamps');\n return ts ?? null;\n}\n\nconst ALLOWED_OPS = new Set([\n '=',\n '!=',\n '<>',\n '<',\n '>',\n '<=',\n '>=',\n 'like',\n 'not like',\n 'ilike',\n 'not ilike',\n 'in',\n 'not in',\n 'is',\n 'is not'\n]);\n\nexport { ALLOWED_OPS };\n\nexport function getVariantConfig(\n builder: SchemaQueryBuilder<any, any>\n): ResolvedVariantConfig | null {\n const state = getState(builder);\n if (state.variantConfig !== undefined) return state.variantConfig;\n\n const raw = getVariants(state.localSchema);\n if (!raw) {\n state.variantConfig = null;\n return null;\n }\n\n const { propToCol } = buildColumnMap(state.localSchema);\n const discCol = propToCol.get(raw.discriminatorKey) ?? raw.discriminatorKey;\n\n state.variantConfig = {\n ...raw,\n discriminatorColumn: discCol\n };\n return state.variantConfig;\n}\n\nexport function applyVariantJoins(\n builder: SchemaQueryBuilder<any, any>,\n base: Knex.QueryBuilder,\n variantConfig: ResolvedVariantConfig\n): Knex.QueryBuilder {\n const state = getState(builder);\n const knex = state.knex;\n const baseTable = state.tableName;\n const basePkCol = findPrimaryKeyColumn(builder, state.localSchema);\n const discCol = variantConfig.discriminatorColumn;\n\n const qb = base.clone().select(`${baseTable}.*`);\n\n for (const [key, spec] of Object.entries(variantConfig.variants)) {\n if (state.enabledVariants !== null && !state.enabledVariants.has(key))\n continue;\n\n if (spec.storage === 'cti') {\n const variantAlias = `__v_${key}`;\n const variantTable = spec.tableName!;\n const fkCol = spec.foreignKey!;\n\n qb.leftJoin(\n `${variantTable} as ${variantAlias}`,\n knex.raw(`?? = ?? AND ?? = ?`, [\n `${variantAlias}.${fkCol}`,\n `${baseTable}.${basePkCol}`,\n `${baseTable}.${discCol}`,\n key\n ])\n );\n\n const { propToCol } = buildColumnMap(spec.schema);\n const variantIntrospect = spec.schema.introspect() as any;\n const variantProps: Record<string, unknown> =\n variantIntrospect.properties ?? {};\n\n for (const propKey of Object.keys(variantProps)) {\n const colName = propToCol.get(propKey) ?? propKey;\n qb.select(\n knex.raw('?? as ??', [\n `${variantAlias}.${colName}`,\n `${variantAlias}__${colName}`\n ])\n );\n }\n }\n }\n\n for (const vrInc of state.variantRelationIncludes) {\n const variantSpec = variantConfig.variants[vrInc.variantKey];\n if (!variantSpec) continue;\n\n const relSpec = variantSpec.relations.find(\n (r: ResolvedVariantRelationSpec) => r.name === vrInc.relationName\n );\n if (!relSpec) continue;\n\n const foreignSchema = resolveSchema(builder, relSpec.schema);\n const foreignTableName = getTableName(foreignSchema);\n const relAlias = `__v_${vrInc.variantKey}__rel_${vrInc.relationName}`;\n\n if (relSpec.type === 'belongsTo' || relSpec.type === 'hasOne') {\n let localCol: string;\n let foreignCol: string;\n\n if (relSpec.type === 'belongsTo') {\n localCol =\n relSpec.foreignKey ??\n ((): string => {\n throw new Error(\n `includeVariant: relation \"${vrInc.relationName}\" on variant \"${vrInc.variantKey}\" requires foreignKey`\n );\n })();\n foreignCol = findPrimaryKeyColumn(builder, foreignSchema);\n } else {\n localCol = findPrimaryKeyColumn(builder, state.localSchema);\n foreignCol =\n relSpec.foreignKey ??\n ((): string => {\n throw new Error(\n `includeVariant: relation \"${vrInc.relationName}\" on variant \"${vrInc.variantKey}\" requires foreignKey`\n );\n })();\n }\n\n let onExpr: string;\n const variantAlias = `__v_${vrInc.variantKey}`;\n\n if (variantSpec.storage === 'cti') {\n if (relSpec.type === 'belongsTo') {\n onExpr = `${relAlias}.${foreignCol} = ${variantAlias}.${localCol} AND ${baseTable}.${discCol} = '${vrInc.variantKey}'`;\n } else {\n onExpr = `${relAlias}.${foreignCol} = ${baseTable}.${localCol} AND ${baseTable}.${discCol} = '${vrInc.variantKey}'`;\n }\n } else {\n if (relSpec.type === 'belongsTo') {\n onExpr = `${relAlias}.${foreignCol} = ${baseTable}.${localCol} AND ${baseTable}.${discCol} = '${vrInc.variantKey}'`;\n } else {\n onExpr = `${relAlias}.${foreignCol} = ${baseTable}.${localCol} AND ${baseTable}.${discCol} = '${vrInc.variantKey}'`;\n }\n }\n\n const foreignKnex: Knex.QueryBuilder = state.knex(foreignTableName);\n\n const selectionSql = buildVariantRelationSelect(\n builder,\n foreignSchema,\n relAlias,\n foreignTableName,\n vrInc.customize\n );\n\n qb.leftJoin(\n knex.raw(`?? as ??`, [foreignTableName, relAlias]),\n knex.raw(onExpr)\n );\n void foreignKnex;\n\n for (const sel of selectionSql) {\n qb.select(sel);\n }\n }\n }\n\n for (const filter of state.variantWhereFilters) {\n const discColFull = `${baseTable}.${discCol}`;\n qb.where(function (this: Knex.QueryBuilder) {\n this.where(discColFull, filter.key)\n .andWhere(filter.qualifiedColumn, filter.op, filter.value)\n .orWhere(discColFull, '!=', filter.key);\n });\n }\n\n if (state.enabledVariants !== null) {\n qb.whereIn(`${baseTable}.${discCol}`, [...state.enabledVariants]);\n }\n\n return qb;\n}\n\n// Circular-dependency-safe SchemaQueryBuilder constructor reference\n// Set by SchemaQueryBuilder.ts after the class is defined.\nlet SchemaQueryBuilderCtor: new (...args: any[]) => any = null!;\nexport function registerSchemaQueryBuilder(\n ctor: new (...args: any[]) => any\n): void {\n SchemaQueryBuilderCtor = ctor;\n}\nexport function getSchemaQueryBuilderCtor(): new (...args: any[]) => any {\n return SchemaQueryBuilderCtor;\n}\n\nexport function buildVariantRelationSelect(\n builder: SchemaQueryBuilder<any, any>,\n foreignSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n relAlias: string,\n foreignTableName: string,\n customize?: (q: SchemaQueryBuilder<any, any>) => void\n): Knex.Raw[] {\n const state = getState(builder);\n const knex = state.knex;\n const { propToCol } = buildColumnMap(foreignSchema);\n const foreignIntrospect = foreignSchema.introspect() as any;\n const foreignProps: Record<string, unknown> =\n foreignIntrospect.properties ?? {};\n\n let columnsToSelect: string[];\n\n if (customize) {\n const probe = new (SchemaQueryBuilderCtor as any)(\n state.knex,\n foreignSchema,\n state.knex(foreignTableName)\n );\n customize(probe);\n const state2 = getState(probe);\n const explicit = state2.explicitSelects;\n if (explicit && explicit.length > 0) {\n columnsToSelect = explicit;\n } else {\n columnsToSelect = Object.keys(foreignProps).map(\n p => propToCol.get(p) ?? p\n );\n }\n } else {\n columnsToSelect = Object.keys(foreignProps).map(\n p => propToCol.get(p) ?? p\n );\n }\n\n return columnsToSelect.map(colName =>\n knex.raw('?? as ??', [\n `${relAlias}.${colName}`,\n `${relAlias}__${colName}`\n ])\n );\n}\n\nexport function mapPolymorphicRow(\n builder: SchemaQueryBuilder<any, any>,\n row: Record<string, any>,\n variantConfig: ResolvedVariantConfig\n): Record<string, any> {\n const state = getState(builder);\n const { colToProp: baseColToProp } = buildColumnMap(state.localSchema);\n const result: Record<string, any> = {};\n\n for (const [colName, value] of Object.entries(row)) {\n if (colName.startsWith('__v_')) continue;\n const propName = baseColToProp.get(colName);\n if (propName) {\n result[propName] = value;\n } else {\n result[colName] = value;\n }\n }\n\n const discPropKey = variantConfig.discriminatorKey;\n const discValue: string | undefined = result[discPropKey];\n\n if (discValue != null) {\n const variantSpec = variantConfig.variants[discValue];\n if (variantSpec) {\n if (variantSpec.storage === 'cti') {\n const { colToProp: varColToProp } = buildColumnMap(\n variantSpec.schema\n );\n const variantAlias = `__v_${discValue}`;\n const prefix = `${variantAlias}__`;\n const fkCol = variantSpec.foreignKey;\n\n if (fkCol) {\n const fkAlias = `${prefix}${fkCol}`;\n if (!variantSpec.allowOrphan && row[fkAlias] == null) {\n throw new Error(\n `Polymorphic orphan: \"${discPropKey}\" = \"${discValue}\" ` +\n `but no matching row found in variant table ` +\n `\"${variantSpec.tableName}\". ` +\n `Set allowOrphan: true on this variant to suppress.`\n );\n }\n }\n\n for (const [colName, value] of Object.entries(row)) {\n if (!colName.startsWith(prefix)) continue;\n const origCol = colName.slice(prefix.length);\n if (origCol === fkCol) continue;\n const propName = varColToProp.get(origCol) ?? origCol;\n result[propName] = value;\n }\n } else {\n const { colToProp: varColToProp } = buildColumnMap(\n variantSpec.schema\n );\n for (const [colName, value] of Object.entries(row)) {\n if (colName.startsWith('__v_')) continue;\n if (baseColToProp.has(colName)) continue;\n const propName = varColToProp.get(colName);\n if (propName) {\n result[propName] = value;\n }\n }\n }\n }\n }\n\n if (state.variantRelationIncludes.length > 0 && discValue != null) {\n const variantSpec3 = variantConfig.variants[discValue];\n if (variantSpec3) {\n for (const vrInc of state.variantRelationIncludes) {\n if (vrInc.variantKey !== discValue) continue;\n\n const relSpec = variantSpec3.relations.find(\n (r: ResolvedVariantRelationSpec) =>\n r.name === vrInc.relationName\n );\n if (!relSpec) continue;\n\n if (relSpec.type === 'belongsTo' || relSpec.type === 'hasOne') {\n const relAlias = `__v_${discValue}__rel_${vrInc.relationName}`;\n const prefix = `${relAlias}__`;\n const foreignSchema = resolveSchema(\n builder,\n relSpec.schema\n );\n const { colToProp: relColToProp } =\n buildColumnMap(foreignSchema);\n const nested: Record<string, unknown> = {};\n let anyNonNull = false;\n\n for (const [colName, value] of Object.entries(row)) {\n if (!colName.startsWith(prefix)) continue;\n const origCol = colName.slice(prefix.length);\n const propName = relColToProp.get(origCol) ?? origCol;\n nested[propName] = value;\n if (value !== null && value !== undefined) {\n anyNonNull = true;\n }\n }\n result[vrInc.relationName] = anyNonNull ? nested : null;\n }\n }\n }\n }\n\n return result;\n}\n\nexport function resolveSchema(\n _builder: SchemaQueryBuilder<any, any>,\n schema: any\n): ObjectSchemaBuilder<any, any, any, any, any, any, any> {\n return typeof schema === 'function' ? schema() : schema;\n}\n\nexport function findPrimaryKeyColumn(\n _builder: SchemaQueryBuilder<any, any>,\n schema: ObjectSchemaBuilder<any, any, any, any, any, any, any>\n): string {\n const pk = getPrimaryKeyColumns(schema);\n if (pk.columnNames.length > 0) return pk.columnNames[0];\n return 'id';\n}\n\nexport function resolvePkColumns(builder: SchemaQueryBuilder<any, any>): {\n propertyKeys: readonly string[];\n columnNames: readonly string[];\n} {\n const state = getState(builder);\n const pk = getPrimaryKeyColumns(state.localSchema as any);\n if (pk.columnNames.length === 0) {\n throw new Error(\n 'No primary key declared on this schema. Use `.primaryKey()` on a column or `.hasPrimaryKey([...])` on the schema.'\n );\n }\n return pk;\n}\n\nexport function getEffectiveBaseQuery(\n builder: SchemaQueryBuilder<any, any>\n): Knex.QueryBuilder {\n const state = getState(builder);\n let effectiveBase = state.baseQuery;\n let cloned = false;\n\n const softDelete = getSoftDelete(builder);\n if (softDelete && state.onlyDeleted) {\n if (!cloned) {\n effectiveBase = effectiveBase.clone();\n cloned = true;\n }\n effectiveBase.whereNotNull(softDelete.column);\n } else if (softDelete && !state.includeDeleted) {\n if (!cloned) {\n effectiveBase = effectiveBase.clone();\n cloned = true;\n }\n effectiveBase.whereNull(softDelete.column);\n }\n\n if (!state.skipDefaultScope) {\n const defaultScopeFn = getDefaultScope(builder);\n if (defaultScopeFn) {\n if (!cloned) {\n effectiveBase = effectiveBase.clone();\n cloned = true;\n }\n const proxy = new (SchemaQueryBuilderCtor as any)(\n state.knex,\n state.localSchema,\n effectiveBase\n );\n const proxyState = getState(proxy);\n proxyState.skipDefaultScope = true;\n defaultScopeFn(proxy);\n }\n }\n\n return effectiveBase;\n}\n\nexport function buildJoinOne(\n builder: SchemaQueryBuilder<any, any>,\n resultQuery: Knex.QueryBuilder,\n spec: ValidatedSpec & { type: 'one' },\n relationAlias: string\n): void {\n const state = getState(builder);\n const knex = state.knex;\n const foreignTable = spec.foreignQuery;\n const foreignTableName = (foreignTable as any)._single?.table;\n\n if (!foreignTableName) {\n throw new Error(\n `Could not determine table name from foreignQuery for \"${spec.as}\". ` +\n 'Make sure foreignQuery is created via knex(\"tableName\").'\n );\n }\n\n resultQuery.select(\n knex.raw(':relationAlias:.:as:->0 as :as:', {\n relationAlias,\n as: spec.as\n })\n );\n\n const subquery = knex\n .from(foreignTable.as(foreignTableName))\n .select(\n knex.raw(':foreignTable:.:foreignColumn:', {\n foreignTable: foreignTableName,\n foreignColumn: spec.foreignColumn\n })\n )\n .select(\n knex.raw('jsonb_agg(:foreignTable:) as :as:', {\n foreignTable: foreignTableName,\n as: spec.as\n })\n )\n .groupByRaw(':foreignTable:.:foreignColumn:', {\n foreignTable: foreignTableName,\n foreignColumn: spec.foreignColumn\n })\n .as(relationAlias);\n\n const joinMethod = spec.required ? 'join' : 'leftJoin';\n resultQuery[joinMethod](subquery, function () {\n this.on(\n knex.raw(\n ':relationAlias:.:foreignColumn: = :originalQuery:.:localColumn:',\n {\n originalQuery: 'originalQuery',\n relationAlias,\n foreignColumn: spec.foreignColumn,\n localColumn: spec.localColumn\n }\n )\n );\n });\n}\n\nexport function buildJoinMany(\n builder: SchemaQueryBuilder<any, any>,\n resultQuery: Knex.QueryBuilder,\n spec: ValidatedSpec & { type: 'many' },\n relationAlias: string,\n i: number\n): void {\n const state = getState(builder);\n const knex = state.knex;\n const filterName = `withFilter${i}`;\n\n const hasLimitOffset =\n (spec.limit !== null && spec.limit > 0) ||\n (spec.offset !== null && spec.offset > 0);\n\n const orderByColumn = spec.orderBy\n ? spec.orderBy.column\n : spec.foreignColumn;\n const orderByDirection = spec.orderBy ? spec.orderBy.direction : 'asc';\n\n if (hasLimitOffset) {\n resultQuery.with(\n filterName,\n knex\n .from(\n spec.foreignQuery\n .clone()\n .whereIn(\n spec.foreignColumn,\n knex\n .from(\n knex.raw(':originalQuery:', {\n originalQuery: 'originalQuery'\n })\n )\n .distinct(spec.localColumn)\n .as(`__wf_inner_${i}`)\n )\n .as(`__wf_inner_${i}`)\n )\n .select(`__wf_inner_${i}.*`)\n .select(\n knex.raw(\n `row_number() over(partition by :foreignColumn: order by :orderByColumn: ${orderByDirection}) as \"__rn__\"`,\n {\n foreignColumn: spec.foreignColumn,\n orderByColumn\n }\n )\n )\n );\n } else {\n resultQuery.with(\n filterName,\n spec.foreignQuery.clone().whereIn(\n spec.foreignColumn,\n knex\n .from(\n knex.raw(':originalQuery:', {\n originalQuery: 'originalQuery'\n })\n )\n .distinct(spec.localColumn)\n )\n );\n }\n\n const aggSubquery = knex.from(filterName);\n\n if (hasLimitOffset) {\n const hasLimit = spec.limit !== null && spec.limit > 0;\n const hasOffset = spec.offset !== null && spec.offset > 0;\n const effectiveOffset = spec.offset ?? 0;\n const effectiveLimit = effectiveOffset + (spec.limit ?? 0);\n\n const condition =\n hasLimit && hasOffset\n ? '\"__rn__\" > :offset and \"__rn__\" <= :limit'\n : hasLimit\n ? '\"__rn__\" <= :limit'\n : '\"__rn__\" > :offset';\n\n aggSubquery.whereRaw(condition, {\n limit: effectiveLimit,\n offset: effectiveOffset\n });\n\n aggSubquery.select(\n knex.raw(':foreignColumn:', {\n foreignColumn: spec.foreignColumn\n })\n );\n aggSubquery.select(\n knex.raw(\n \"coalesce(jsonb_agg(to_jsonb(:filterName:) - '__rn__' order by \\\"__rn__\\\"), '[]'::jsonb) as :as:\",\n { filterName, as: spec.as }\n )\n );\n } else {\n aggSubquery.select(\n knex.raw(':foreignColumn:', {\n foreignColumn: spec.foreignColumn\n })\n );\n\n const orderClause = spec.orderBy\n ? `jsonb_agg(:filterName: order by :filterName:.:orderByColumn: ${orderByDirection})`\n : 'jsonb_agg(:filterName:)';\n\n aggSubquery.select(\n knex.raw(\n `coalesce(${orderClause}, '[]'::jsonb) as :as:`,\n spec.orderBy\n ? { filterName, orderByColumn, as: spec.as }\n : { filterName, as: spec.as }\n )\n );\n }\n\n aggSubquery.groupByRaw(':foreignColumn:', {\n foreignColumn: spec.foreignColumn\n });\n\n const subquery = aggSubquery.as(relationAlias);\n\n resultQuery.select(\n knex.raw(\"coalesce(:relationAlias:.:as:, '[]'::jsonb) as :as:\", {\n relationAlias,\n as: spec.as\n })\n );\n\n resultQuery.leftJoin(subquery, function () {\n this.on(\n knex.raw(\n ':relationAlias:.:foreignColumn: = :originalQuery:.:localColumn:',\n {\n relationAlias,\n foreignColumn: spec.foreignColumn,\n originalQuery: 'originalQuery',\n localColumn: spec.localColumn\n }\n )\n );\n });\n}\n\nexport function buildQuery(\n builder: SchemaQueryBuilder<any, any>\n): Knex.QueryBuilder {\n const state = getState(builder);\n const effectiveBase = getEffectiveBaseQuery(builder);\n\n const variantConfig = getVariantConfig(builder);\n const queryBase = variantConfig\n ? applyVariantJoins(builder, effectiveBase, variantConfig)\n : effectiveBase;\n\n if (state.specs.length === 0) {\n return queryBase;\n }\n\n const knex = state.knex;\n const specs = state.specs;\n\n const requiredLocalColumns = [...new Set(specs.map(s => s.localColumn))];\n\n let cteQuery = queryBase;\n let extraColumns: string[] = [];\n\n if (state.explicitSelects !== null) {\n const selectedSet = new Set(state.explicitSelects);\n extraColumns = requiredLocalColumns.filter(\n col => !selectedSet.has(col)\n );\n if (extraColumns.length > 0) {\n cteQuery = queryBase.clone();\n for (const col of extraColumns) {\n cteQuery.column(col);\n }\n }\n }\n\n const resultQuery = knex.queryBuilder().with('originalQuery', cteQuery);\n\n if (extraColumns.length > 0 && state.explicitSelects !== null) {\n for (const col of state.explicitSelects) {\n resultQuery.select(\n knex.raw(':originalQuery:.:col: as :col:', {\n originalQuery: 'originalQuery',\n col\n })\n );\n }\n } else {\n resultQuery.select('originalQuery.*');\n }\n\n resultQuery.from(\n knex.raw(':originalQuery:', {\n originalQuery: 'originalQuery'\n })\n );\n\n for (let i = 0; i < specs.length; i++) {\n const spec = specs[i];\n const relationAlias = `eagerRelation${i}`;\n\n if (spec.type === 'one') {\n buildJoinOne(builder, resultQuery, spec, relationAlias);\n } else {\n buildJoinMany(builder, resultQuery, spec, relationAlias, i);\n }\n }\n\n return resultQuery;\n}\n\nexport function getQuery(\n builder: SchemaQueryBuilder<any, any>\n): Knex.QueryBuilder {\n const state = getState(builder);\n if (!state.cachedBuiltQuery) {\n state.cachedBuiltQuery = buildQuery(builder);\n }\n return state.cachedBuiltQuery;\n}\n\nexport function mapRow(\n builder: SchemaQueryBuilder<any, any>,\n row: Record<string, any>\n): Record<string, any> {\n if (!row) return row;\n\n const variantConfig = getVariantConfig(builder);\n if (variantConfig) {\n return mapPolymorphicRow(builder, row, variantConfig);\n }\n\n const state = getState(builder);\n const { colToProp } = buildColumnMap(state.localSchema);\n const result: Record<string, any> = {};\n\n for (const [colName, value] of Object.entries(row)) {\n const propName = colToProp.get(colName);\n if (propName) {\n result[propName] = value;\n } else {\n result[colName] = value;\n }\n }\n\n return result;\n}\n\nexport function cleanAndMapRow(\n builder: SchemaQueryBuilder<any, any>,\n row: Record<string, any>\n): Record<string, any> {\n const state = getState(builder);\n const oneSpecs = state.specs.filter(\n (s): s is ValidatedSpec & { type: 'one' } => s.type === 'one'\n );\n const manySpecs = state.specs.filter(\n (s): s is ValidatedSpec & { type: 'many' } => s.type === 'many'\n );\n const cleaned = clearRow(row, oneSpecs, manySpecs);\n return mapRow(builder, cleaned);\n}\n\nexport function mapObjectToColumns(\n builder: SchemaQueryBuilder<any, any>,\n obj: Record<string, any>\n): Record<string, any> {\n const state = getState(builder);\n const { propToCol } = buildColumnMap(state.localSchema);\n const result: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const colName = propToCol.get(key);\n if (colName) {\n result[colName] = value;\n } else {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nexport function mapRecordToColumns(\n builder: SchemaQueryBuilder<any, any>,\n record: Record<string, any>\n): Record<string, any> {\n return mapObjectToColumns(builder, record);\n}\n\nexport function resolveColumnArg(\n builder: SchemaQueryBuilder<any, any>,\n col: any\n): string | Knex.Raw {\n if (typeof col === 'string') {\n return resolveColumn(builder, col, 'column');\n }\n if (typeof col === 'function') {\n return resolveColumn(builder, col, 'column');\n }\n return col;\n}\n\nexport function isColumnAccessor(\n builder: SchemaQueryBuilder<any, any>,\n fn: Function\n): boolean {\n const state = getState(builder);\n try {\n const tree = ObjectSchemaBuilder.getPropertiesFor(\n state.localSchema as any\n );\n const result = fn(tree);\n if (\n result &&\n typeof result === 'object' &&\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in result\n ) {\n return true;\n }\n } catch {}\n return false;\n}\n\nexport function assertNotProjection(\n builder: SchemaQueryBuilder<any, any>,\n method: string\n): void {\n const state = getState(builder);\n if (state.selectionMode === 'projection') {\n throw new Error(\n `Cannot call .${method}() after .projected('${\n state.appliedProjection\n }'). Choose one column-selection mode per query.`\n );\n }\n}\n\nexport function assertNotExplicitSelect(\n builder: SchemaQueryBuilder<any, any>,\n method: string\n): void {\n const state = getState(builder);\n if (state.selectionMode === 'select') {\n throw new Error(\n `Cannot call .${method}() after .select(). Choose one column-selection mode per query.`\n );\n }\n if (state.selectionMode === 'aggregate') {\n throw new Error(\n `Cannot call .${method}() after an aggregate method. Choose one column-selection mode per query.`\n );\n }\n if (state.selectionMode === 'projection') {\n throw new Error(\n `Cannot call .${method}() after .projected('${\n state.appliedProjection\n }'). Choose one column-selection mode per query.`\n );\n }\n}\n","// @cleverbrush/knex-schema — Shared mutable state store for SchemaQueryBuilder\n\nimport type { ObjectSchemaBuilder } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport type { SchemaQueryBuilder } from '../SchemaQueryBuilder.js';\nimport type {\n ResolvedVariantConfig,\n ValidatedSpec,\n VariantWhereFilter\n} from '../types.js';\n\nexport interface QueryBuilderState {\n knex: Knex;\n baseQuery: Knex.QueryBuilder;\n localSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>;\n specs: ValidatedSpec[];\n tableName: string;\n\n /** SQL column names explicitly passed to `.select()`. null = SELECT *. */\n explicitSelects: string[] | null;\n\n /** Column-selection mode: null, 'select', 'aggregate', or 'projection'. */\n selectionMode: 'select' | 'aggregate' | 'projection' | null;\n\n /** Name of the projection currently applied, for error messages. */\n appliedProjection: string | null;\n\n /** When true, soft-delete filter is NOT applied. */\n includeDeleted: boolean;\n\n /** When true, only soft-deleted rows are returned. */\n onlyDeleted: boolean;\n\n /** When true, default scope is not applied. */\n skipDefaultScope: boolean;\n\n /** Resolved variant config, lazily populated. undefined = not yet read; null = not polymorphic. */\n variantConfig: ResolvedVariantConfig | null | undefined;\n\n /** When set, only these discriminator values are returned. null = all variants. */\n enabledVariants: Set<string> | null;\n\n /** Pending per-variant WHERE filters registered via .whereVariant(). */\n variantWhereFilters: VariantWhereFilter[];\n\n /** Variant-relation eager-load requests registered via .includeVariant(). */\n variantRelationIncludes: Array<{\n variantKey: string;\n relationName: string;\n customize?: (q: SchemaQueryBuilder<any, any>) => void;\n }>;\n\n /** Memoized result of buildQuery(). null = needs rebuild. */\n cachedBuiltQuery: Knex.QueryBuilder | null;\n}\n\nconst STATE = new WeakMap<SchemaQueryBuilder<any, any>, QueryBuilderState>();\n\nexport function getState(\n builder: SchemaQueryBuilder<any, any>\n): QueryBuilderState {\n const s = STATE.get(builder);\n if (!s) {\n throw new Error(\n 'SchemaQueryBuilder state not found — builder was not properly initialized'\n );\n }\n return s;\n}\n\nexport function setState(\n builder: SchemaQueryBuilder<any, any>,\n state: QueryBuilderState\n): void {\n STATE.set(builder, state);\n}\n","// @cleverbrush/knex-schema — INSERT / upsert / bulk operations\n\nimport type { InferType } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { buildColumnMap } from '../columns.js';\nimport { getTableName } from '../extension.js';\nimport type { SchemaQueryBuilder } from '../SchemaQueryBuilder.js';\nimport type { ColumnRef, InsertType } from '../types.js';\nimport {\n getTimestamps,\n mapObjectToColumns,\n mapRow,\n resolveColumn\n} from './helpers.js';\nimport { getState } from './state.js';\n\n// ---------------------------------------------------------------------------\n// OnConflictBuilder\n// ---------------------------------------------------------------------------\n\nexport class OnConflictBuilder<\n TLocalSchema extends import('@cleverbrush/schema').ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >,\n TResult\n> {\n readonly #knex: Knex;\n readonly #localSchema: TLocalSchema;\n readonly #conflictColumns: string[];\n\n constructor(\n knex: Knex,\n localSchema: TLocalSchema,\n _parent: SchemaQueryBuilder<TLocalSchema, TResult>,\n conflictColumns: string[]\n ) {\n this.#knex = knex;\n this.#localSchema = localSchema;\n this.#conflictColumns = conflictColumns;\n }\n\n async merge(\n data: InsertType<TLocalSchema>,\n updateData?: Partial<InferType<TLocalSchema>>\n ): Promise<TResult> {\n return this.#execute(data, 'merge', updateData) as Promise<TResult>;\n }\n\n async ignore(data: InsertType<TLocalSchema>): Promise<TResult | undefined> {\n return this.#execute(data, 'ignore');\n }\n\n async #execute(\n data: InsertType<TLocalSchema>,\n mode: 'merge' | 'ignore',\n updateData?: Partial<InferType<TLocalSchema>>\n ): Promise<TResult | undefined> {\n const tableName = getTableName(this.#localSchema);\n const timestamps: { createdAt: string; updatedAt: string } | null =\n (this.#localSchema as any).getExtension?.('timestamps') ?? null;\n\n const beforeHooks: Function[] =\n (this.#localSchema as any).getExtension?.('beforeInsert') ?? [];\n\n let processed = { ...(data as Record<string, any>) };\n for (const hook of beforeHooks) {\n processed = (await hook(processed)) ?? processed;\n }\n\n const { propToCol } = buildColumnMap(this.#localSchema as any);\n const mapped: Record<string, any> = {};\n for (const [key, val] of Object.entries(processed)) {\n mapped[propToCol.get(key) ?? key] = val;\n }\n if (timestamps) {\n mapped[timestamps.createdAt] = this.#knex.fn.now();\n mapped[timestamps.updatedAt] = this.#knex.fn.now();\n }\n\n let qb = this.#knex(tableName)\n .insert(mapped)\n .onConflict(this.#conflictColumns);\n\n if (mode === 'ignore') {\n qb = (qb as any).ignore();\n } else {\n let mergeObj: Record<string, any>;\n if (updateData) {\n mergeObj = {};\n for (const [key, val] of Object.entries(\n updateData as Record<string, any>\n )) {\n mergeObj[propToCol.get(key) ?? key] = val;\n }\n } else {\n mergeObj = { ...mapped };\n if (timestamps) {\n delete mergeObj[timestamps.createdAt];\n mergeObj[timestamps.updatedAt] = this.#knex.fn.now();\n }\n }\n qb = (qb as any).merge(mergeObj);\n }\n\n const rows = await (qb as any).returning('*');\n if (!rows || rows.length === 0) return undefined;\n\n const { colToProp } = buildColumnMap(this.#localSchema as any);\n const result: Record<string, any> = {};\n for (const [col, val] of Object.entries(rows[0])) {\n result[colToProp.get(col) ?? col] = val;\n }\n return result as TResult;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Insert operation functions\n// ---------------------------------------------------------------------------\n\nexport async function insertImpl(\n builder: SchemaQueryBuilder<any, any>,\n data: InsertType<any>\n): Promise<any> {\n const state = getState(builder);\n\n let processedData = { ...(data as Record<string, any>) };\n\n const beforeHooks =\n ((state.localSchema as any).getExtension?.('beforeInsert') as\n | Function[]\n | undefined) ?? [];\n for (const hook of beforeHooks) {\n processedData = (await hook(processedData)) ?? processedData;\n }\n\n const mapped = mapObjectToColumns(builder, processedData);\n\n const timestamps = getTimestamps(builder);\n if (timestamps) {\n mapped[timestamps.createdAt] = state.knex.fn.now();\n mapped[timestamps.updatedAt] = state.knex.fn.now();\n }\n\n const [row] = await state\n .knex(state.tableName)\n .insert(mapped)\n .returning('*');\n const result = mapRow(builder, row);\n\n const afterHooks =\n ((state.localSchema as any).getExtension?.('afterInsert') as\n | Function[]\n | undefined) ?? [];\n for (const hook of afterHooks) {\n await hook(result);\n }\n\n return result;\n}\n\nexport async function insertManyImpl(\n builder: SchemaQueryBuilder<any, any>,\n data: InsertType<any>[]\n): Promise<any[]> {\n const state = getState(builder);\n const timestamps = getTimestamps(builder);\n const beforeHooks =\n ((state.localSchema as any).getExtension?.('beforeInsert') as\n | Function[]\n | undefined) ?? [];\n\n const mapped = [];\n for (const d of data) {\n let processedData = { ...(d as Record<string, any>) };\n for (const hook of beforeHooks) {\n processedData = (await hook(processedData)) ?? processedData;\n }\n const m = mapObjectToColumns(builder, processedData);\n if (timestamps) {\n m[timestamps.createdAt] = state.knex.fn.now();\n m[timestamps.updatedAt] = state.knex.fn.now();\n }\n mapped.push(m);\n }\n\n const rows = await state\n .knex(state.tableName)\n .insert(mapped)\n .returning('*');\n const results = rows.map((row: any) => mapRow(builder, row));\n\n const afterHooks =\n ((state.localSchema as any).getExtension?.('afterInsert') as\n | Function[]\n | undefined) ?? [];\n for (const result of results) {\n for (const hook of afterHooks) {\n await hook(result);\n }\n }\n\n return results;\n}\n\nexport function onConflictImpl(\n builder: SchemaQueryBuilder<any, any>,\n ...conflictColumns: ColumnRef<any>[]\n): OnConflictBuilder<any, any> {\n const state = getState(builder);\n const cols = conflictColumns.map(\n c => resolveColumn(builder, c, 'onConflict') as string\n );\n return new OnConflictBuilder(state.knex, state.localSchema, builder, cols);\n}\n\nexport async function upsertImpl(\n builder: SchemaQueryBuilder<any, any>,\n data: InsertType<any>,\n opts: {\n conflictColumns: ColumnRef<any>[];\n updateColumns?: ColumnRef<any>[];\n }\n): Promise<any> {\n const state = getState(builder);\n const cols = opts.conflictColumns.map(\n c => resolveColumn(builder, c, 'upsert') as string\n );\n\n const qb = state\n .knex(state.tableName)\n .insert(mapObjectToColumns(builder, data as Record<string, any>))\n .onConflict(cols);\n\n if (opts.updateColumns && opts.updateColumns.length > 0) {\n const updateCols = opts.updateColumns.map(\n c => resolveColumn(builder, c, 'upsert') as string\n );\n (qb as any).merge(updateCols);\n } else {\n (qb as any).merge();\n }\n\n const [row] = await (qb as any).returning('*');\n return mapRow(builder, row);\n}\n\nexport async function bulkInsertImpl(\n builder: SchemaQueryBuilder<any, any>,\n rows: InsertType<any>[],\n opts?: {\n chunkSize?: number;\n onConflict?: 'ignore' | 'merge';\n conflictColumns?: ColumnRef<any>[];\n }\n): Promise<any[]> {\n if (rows.length === 0) return [];\n\n const state = getState(builder);\n\n const requestedChunkSize = opts?.chunkSize ?? 500;\n const bindingsPerRow = Object.keys(rows[0] as object).length || 1;\n const safeChunkCap = Math.max(\n 1,\n Math.floor(60000 / Math.max(1, bindingsPerRow))\n );\n const chunkSize = Math.max(1, Math.min(requestedChunkSize, safeChunkCap));\n\n const timestamps = getTimestamps(builder);\n const beforeHooks =\n ((state.localSchema as any).getExtension?.('beforeInsert') as\n | Function[]\n | undefined) ?? [];\n const afterHooks =\n ((state.localSchema as any).getExtension?.('afterInsert') as\n | Function[]\n | undefined) ?? [];\n\n const conflictCols =\n opts?.onConflict && opts.conflictColumns\n ? opts.conflictColumns.map(\n c =>\n resolveColumn(\n builder,\n c,\n 'bulkInsert.onConflict'\n ) as string\n )\n : null;\n if (opts?.onConflict && (!conflictCols || conflictCols.length === 0)) {\n throw new Error(\n 'bulkInsert: `conflictColumns` is required when `onConflict` is set.'\n );\n }\n\n const results: any[] = [];\n\n for (let i = 0; i < rows.length; i += chunkSize) {\n const chunk = rows.slice(i, i + chunkSize);\n const mapped: Record<string, any>[] = [];\n for (const row of chunk) {\n let processed = { ...(row as Record<string, any>) };\n for (const hook of beforeHooks) {\n processed = (await hook(processed)) ?? processed;\n }\n const m = mapObjectToColumns(builder, processed);\n if (timestamps) {\n m[timestamps.createdAt] = state.knex.fn.now();\n m[timestamps.updatedAt] = state.knex.fn.now();\n }\n mapped.push(m);\n }\n\n let qb: any = state.knex(state.tableName).insert(mapped);\n\n if (conflictCols) {\n qb = qb.onConflict(conflictCols);\n if (opts!.onConflict === 'ignore') {\n qb = qb.ignore();\n } else {\n const updateCols = new Set<string>();\n for (const m of mapped) {\n for (const k of Object.keys(m)) updateCols.add(k);\n }\n for (const c of conflictCols) updateCols.delete(c);\n if (timestamps) {\n updateCols.delete(timestamps.createdAt);\n updateCols.add(timestamps.updatedAt);\n }\n qb = qb.merge(Array.from(updateCols));\n }\n }\n\n const inserted: any[] = await qb.returning('*');\n for (const row of inserted) {\n const mappedRow = mapRow(builder, row);\n for (const hook of afterHooks) {\n await hook(mappedRow);\n }\n results.push(mappedRow);\n }\n }\n\n return results;\n}\n\nexport async function bulkUpsertImpl(\n builder: SchemaQueryBuilder<any, any>,\n rows: InsertType<any>[],\n opts: {\n conflictColumns: ColumnRef<any>[];\n chunkSize?: number;\n }\n): Promise<any[]> {\n return bulkInsertImpl(builder, rows, {\n chunkSize: opts.chunkSize,\n onConflict: 'merge',\n conflictColumns: opts.conflictColumns\n });\n}\n","// @cleverbrush/knex-schema — DELETE / soft-delete / restore operations\n\nimport type { SchemaQueryBuilder } from '../SchemaQueryBuilder.js';\nimport { getSoftDelete, invalidateCache, mapRow } from './helpers.js';\nimport { getState } from './state.js';\n\nexport async function deleteImpl(\n builder: SchemaQueryBuilder<any, any>\n): Promise<number> {\n const state = getState(builder);\n\n const hooks =\n ((state.localSchema as any).getExtension?.('beforeDelete') as\n | Function[]\n | undefined) ?? [];\n for (const hook of hooks) {\n await hook(builder);\n }\n\n const softDelete = getSoftDelete(builder);\n if (softDelete) {\n return state.baseQuery.update({\n [softDelete.column]: state.knex.fn.now()\n });\n }\n return state.baseQuery.delete();\n}\n\nexport function withDeletedImpl(builder: SchemaQueryBuilder<any, any>): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.includeDeleted = true;\n return builder;\n}\n\nexport function onlyDeletedImpl(builder: SchemaQueryBuilder<any, any>): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.onlyDeleted = true;\n state.includeDeleted = true;\n return builder;\n}\n\nexport async function hardDeleteImpl(\n builder: SchemaQueryBuilder<any, any>\n): Promise<number> {\n const state = getState(builder);\n const hooks =\n ((state.localSchema as any).getExtension?.('beforeDelete') as\n | Function[]\n | undefined) ?? [];\n for (const hook of hooks) {\n await hook(builder);\n }\n return state.baseQuery.delete();\n}\n\nexport async function restoreImpl(\n builder: SchemaQueryBuilder<any, any>\n): Promise<any[]> {\n const state = getState(builder);\n const softDelete = getSoftDelete(builder);\n if (!softDelete) {\n throw new Error(\n 'Schema does not have soft delete enabled. Use .softDelete() on the schema.'\n );\n }\n const rows = await state.baseQuery\n .update({ [softDelete.column]: null })\n .returning('*');\n return rows.map((row: any) => mapRow(builder, row));\n}\n","// @cleverbrush/knex-schema — Validation of join specs\n\nimport type { ObjectSchemaBuilder } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { resolveColumnRef } from './columns.js';\nimport { getTableName } from './extension.js';\nimport { MAPPERS } from './mappers.js';\nimport type {\n JoinManySpec,\n JoinOneSpec,\n ValidatedJoinManySpec,\n ValidatedJoinOneSpec\n} from './types.js';\n\n/**\n * Resolve foreignQuery: use the provided one, or auto-derive from\n * the foreign schema's tableName extension.\n * Also normalizes SchemaQueryBuilder instances to raw Knex.QueryBuilder\n * by calling `.toKnexQuery()` if available.\n */\nfunction resolveForeignQuery(\n spec: {\n foreignQuery?: Knex.QueryBuilder | { toKnexQuery(): Knex.QueryBuilder };\n foreignSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>;\n },\n knex: Knex\n): Knex.QueryBuilder {\n if (spec.foreignQuery) {\n if ('toKnexQuery' in spec.foreignQuery) {\n return spec.foreignQuery.toKnexQuery();\n }\n return spec.foreignQuery as Knex.QueryBuilder;\n }\n\n const tableName = getTableName(spec.foreignSchema);\n return knex(tableName);\n}\n\nexport function validateJoinOne(\n spec: JoinOneSpec<any, any, any, any>,\n localSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n knex: Knex\n): ValidatedJoinOneSpec {\n const localColumn = resolveColumnRef(\n spec.localColumn,\n localSchema,\n 'localColumn'\n );\n const foreignColumn = resolveColumnRef(\n spec.foreignColumn,\n spec.foreignSchema,\n 'foreignColumn'\n );\n if (typeof spec.as !== 'string' || !spec.as) {\n throw new Error('as must be a non-empty string');\n }\n\n const foreignQuery = resolveForeignQuery(spec, knex);\n const required = spec.required !== false;\n\n if (spec.mappers !== undefined) {\n validateMappers(spec.mappers);\n }\n\n return {\n localColumn,\n foreignColumn,\n as: spec.as,\n required,\n foreignQuery,\n mappers: spec.mappers as\n | Record<string, ((value: any) => any) | string>\n | undefined\n };\n}\n\nexport function validateJoinMany(\n spec: JoinManySpec<any, any, any>,\n localSchema: ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n knex: Knex\n): ValidatedJoinManySpec {\n const localColumn = resolveColumnRef(\n spec.localColumn,\n localSchema,\n 'localColumn'\n );\n const foreignColumn = resolveColumnRef(\n spec.foreignColumn,\n spec.foreignSchema,\n 'foreignColumn'\n );\n if (typeof spec.as !== 'string' || !spec.as) {\n throw new Error('as must be a non-empty string');\n }\n\n const foreignQuery = resolveForeignQuery(spec, knex);\n\n if (spec.mappers !== undefined) {\n validateMappers(spec.mappers);\n }\n\n const limit =\n Number.isFinite(spec.limit) && (spec.limit as number) > 0\n ? (spec.limit as number)\n : null;\n const offset =\n Number.isFinite(spec.offset) && (spec.offset as number) > 0\n ? (spec.offset as number)\n : null;\n const orderBy = spec.orderBy\n ? {\n column: resolveColumnRef(\n spec.orderBy.column,\n spec.foreignSchema,\n 'orderBy.column'\n ),\n direction: spec.orderBy.direction ?? ('asc' as const)\n }\n : null;\n\n return {\n localColumn,\n foreignColumn,\n as: spec.as,\n foreignQuery,\n limit,\n offset,\n orderBy,\n mappers: spec.mappers as\n | Record<string, ((value: any) => any) | string>\n | undefined\n };\n}\n\nfunction validateMappers(mappers: Record<string, unknown>): void {\n if (typeof mappers !== 'object' || mappers === null) {\n throw new Error('mappers must be an object');\n }\n for (const key of Object.keys(mappers)) {\n const m = mappers[key];\n if (typeof m === 'string') {\n if (typeof MAPPERS[m] !== 'function') {\n throw new Error(\n `mapper for \"${key}\": unknown built-in mapper name \"${m}\"`\n );\n }\n } else if (typeof m !== 'function') {\n throw new Error(\n `mapper for \"${key}\" must be a function or a built-in mapper name`\n );\n }\n }\n}\n\nexport function validateUniqueFieldNames(specs: Array<{ as: string }>): void {\n const seen = new Set<string>();\n for (const spec of specs) {\n if (seen.has(spec.as)) {\n throw new Error(`duplicate field name: ${spec.as}`);\n }\n seen.add(spec.as);\n }\n}\n","// @cleverbrush/knex-schema — Eager-loading JOIN operations (joinOne, joinMany, include, includeVariant)\n\nimport type { Knex } from 'knex';\nimport { resolveColumnRef } from '../columns.js';\nimport { getTableName } from '../extension.js';\nimport type { SchemaQueryBuilder } from '../SchemaQueryBuilder.js';\nimport type {\n JoinManySpec,\n JoinOneSpec,\n RelationSpec,\n ResolvedVariantRelationSpec\n} from '../types.js';\nimport {\n validateJoinMany,\n validateJoinOne,\n validateUniqueFieldNames\n} from '../validate.js';\nimport {\n findPrimaryKeyColumn,\n getSchemaQueryBuilderCtor,\n getVariantConfig,\n invalidateCache,\n resolveSchema\n} from './helpers.js';\nimport { getState } from './state.js';\n\nexport function joinOneImpl(\n builder: SchemaQueryBuilder<any, any>,\n spec: JoinOneSpec<any, any, any, any>\n): any {\n const state = getState(builder);\n const validated = validateJoinOne(spec, state.localSchema, state.knex);\n state.specs.push({ type: 'one' as const, ...validated });\n validateUniqueFieldNames(state.specs);\n invalidateCache(builder);\n return builder;\n}\n\nexport function joinManyImpl(\n builder: SchemaQueryBuilder<any, any>,\n spec: JoinManySpec<any, any, any>\n): any {\n const state = getState(builder);\n const validated = validateJoinMany(spec, state.localSchema, state.knex);\n state.specs.push({ type: 'many' as const, ...validated });\n validateUniqueFieldNames(state.specs);\n invalidateCache(builder);\n return builder;\n}\n\nexport function includeImpl(\n builder: SchemaQueryBuilder<any, any>,\n relationName: string,\n customize?: (q: SchemaQueryBuilder<any, any>) => void\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n const relations: RelationSpec[] =\n (state.localSchema as any).getExtension?.('relations') ?? [];\n const relation = relations.find(\n (r: RelationSpec) => r.name === relationName\n );\n if (!relation) {\n const variantConfig = getVariantConfig(builder);\n if (variantConfig) {\n const matches: Array<{ variantKey: string }> = [];\n for (const [vKey, vSpec] of Object.entries(\n variantConfig.variants\n )) {\n if (\n vSpec.relations.some(\n (r: ResolvedVariantRelationSpec) =>\n r.name === relationName\n )\n ) {\n matches.push({ variantKey: vKey });\n }\n }\n if (matches.length === 1) {\n return includeVariantImpl(\n builder,\n matches[0].variantKey,\n relationName,\n customize\n );\n }\n if (matches.length > 1) {\n throw new Error(\n `Ambiguous relation \"${relationName}\" — found on variants: ${matches.map(m => m.variantKey).join(', ')}. Use .includeVariant(key, name) to be explicit.`\n );\n }\n }\n throw new Error(\n `Unknown relation \"${relationName}\" on schema for table \"${state.tableName}\"`\n );\n }\n\n const foreignSchema = resolveSchema(builder, relation.schema);\n const foreignTableName = getTableName(foreignSchema);\n\n switch (relation.type) {\n case 'belongsTo': {\n const localColumn = resolveColumnRef(\n relation.foreignKey,\n state.localSchema,\n 'foreignKey'\n );\n const foreignColumn = findPrimaryKeyColumn(builder, foreignSchema);\n\n const foreignQuery1: Knex.QueryBuilder =\n state.knex(foreignTableName);\n if (customize) {\n const SQB = getSchemaQueryBuilderCtor();\n const proxy = new SQB(state.knex, foreignSchema, foreignQuery1);\n customize(proxy);\n }\n\n joinOneImpl(builder, {\n foreignSchema,\n localColumn,\n foreignColumn,\n as: relationName,\n foreignQuery: foreignQuery1\n } as any);\n break;\n }\n case 'hasOne': {\n const localColumn = findPrimaryKeyColumn(\n builder,\n state.localSchema\n );\n const foreignColumn = resolveColumnRef(\n relation.foreignKey,\n foreignSchema,\n 'foreignKey'\n );\n\n const foreignQuery2: Knex.QueryBuilder =\n state.knex(foreignTableName);\n if (customize) {\n const SQB = getSchemaQueryBuilderCtor();\n const proxy = new SQB(state.knex, foreignSchema, foreignQuery2);\n customize(proxy);\n }\n\n joinOneImpl(builder, {\n foreignSchema,\n localColumn,\n foreignColumn,\n as: relationName,\n required: false,\n foreignQuery: foreignQuery2\n } as any);\n break;\n }\n case 'hasMany': {\n const localColumn = findPrimaryKeyColumn(\n builder,\n state.localSchema\n );\n const foreignColumn = resolveColumnRef(\n relation.foreignKey,\n foreignSchema,\n 'foreignKey'\n );\n\n const foreignQuery3: Knex.QueryBuilder =\n state.knex(foreignTableName);\n if (customize) {\n const SQB = getSchemaQueryBuilderCtor();\n const proxy = new SQB(state.knex, foreignSchema, foreignQuery3);\n customize(proxy);\n }\n\n joinManyImpl(builder, {\n foreignSchema,\n localColumn,\n foreignColumn,\n as: relationName,\n foreignQuery: foreignQuery3\n } as any);\n break;\n }\n case 'belongsToMany': {\n const through = relation.through!;\n const localColumn = findPrimaryKeyColumn(\n builder,\n state.localSchema\n );\n\n const foreignQuery = state\n .knex(foreignTableName)\n .join(\n through.table,\n `${through.table}.${through.foreignKey}`,\n `${foreignTableName}.${findPrimaryKeyColumn(builder, foreignSchema)}`\n )\n .select(\n `${foreignTableName}.*`,\n `${through.table}.${through.localKey}`\n );\n\n if (customize) {\n const SQB = getSchemaQueryBuilderCtor();\n const proxy = new SQB(state.knex, foreignSchema, foreignQuery);\n customize(proxy);\n }\n\n joinManyImpl(builder, {\n foreignSchema,\n localColumn,\n foreignColumn: through.localKey,\n as: relationName,\n foreignQuery\n } as any);\n break;\n }\n }\n\n return builder;\n}\n\nexport function includeVariantImpl(\n builder: SchemaQueryBuilder<any, any>,\n variantKey: string,\n relationName: string,\n customize?: (q: SchemaQueryBuilder<any, any>) => void\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n const variantConfig = getVariantConfig(builder);\n if (!variantConfig) {\n throw new Error(\n `includeVariant: schema for table \"${state.tableName}\" is not polymorphic (no .withVariants() config found)`\n );\n }\n const variantSpec = variantConfig.variants[variantKey];\n if (!variantSpec) {\n throw new Error(\n `includeVariant: unknown variant key \"${variantKey}\" on schema for table \"${state.tableName}\"`\n );\n }\n const relSpec = variantSpec.relations.find(\n (r: ResolvedVariantRelationSpec) => r.name === relationName\n );\n if (!relSpec) {\n throw new Error(\n `includeVariant: unknown relation \"${relationName}\" on variant \"${variantKey}\" of table \"${state.tableName}\"`\n );\n }\n state.variantRelationIncludes.push({\n variantKey,\n relationName,\n customize\n });\n return builder;\n}\n","// @cleverbrush/knex-schema — WHERE / ORDER BY / GROUP BY / HAVING operations\n\nimport type { Knex } from 'knex';\nimport type { SchemaQueryBuilder } from '../SchemaQueryBuilder.js';\nimport type { ColumnRef } from '../types.js';\nimport {\n invalidateCache,\n isColumnAccessor,\n mapRecordToColumns,\n resolveColumn,\n resolveColumnArg\n} from './helpers.js';\nimport { getState } from './state.js';\n\nexport function whereImpl(\n builder: SchemaQueryBuilder<any, any>,\n columnOrRaw: any,\n ...args: any[]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n if (\n typeof columnOrRaw === 'function' &&\n !isColumnAccessor(builder, columnOrRaw)\n ) {\n (state.baseQuery.where as any)(columnOrRaw, ...args);\n } else if (\n typeof columnOrRaw === 'object' &&\n columnOrRaw !== null &&\n !('toSQL' in columnOrRaw)\n ) {\n const mapped = mapRecordToColumns(\n builder,\n columnOrRaw as Record<string, any>\n );\n (state.baseQuery.where as any)(mapped, ...args);\n } else {\n const col = resolveColumnArg(builder, columnOrRaw);\n (state.baseQuery.where as any)(col, ...args);\n }\n return builder;\n}\n\nexport function andWhereImpl(\n builder: SchemaQueryBuilder<any, any>,\n columnOrRaw: any,\n ...args: any[]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n if (\n typeof columnOrRaw === 'function' &&\n !isColumnAccessor(builder, columnOrRaw)\n ) {\n (state.baseQuery.andWhere as any)(columnOrRaw, ...args);\n } else if (\n typeof columnOrRaw === 'object' &&\n columnOrRaw !== null &&\n !('toSQL' in columnOrRaw)\n ) {\n const mapped = mapRecordToColumns(\n builder,\n columnOrRaw as Record<string, any>\n );\n (state.baseQuery.andWhere as any)(mapped, ...args);\n } else {\n const col = resolveColumnArg(builder, columnOrRaw);\n (state.baseQuery.andWhere as any)(col, ...args);\n }\n return builder;\n}\n\nexport function orWhereImpl(\n builder: SchemaQueryBuilder<any, any>,\n columnOrRaw: any,\n ...args: any[]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n if (\n typeof columnOrRaw === 'function' &&\n !isColumnAccessor(builder, columnOrRaw)\n ) {\n (state.baseQuery.orWhere as any)(columnOrRaw, ...args);\n } else if (\n typeof columnOrRaw === 'object' &&\n columnOrRaw !== null &&\n !('toSQL' in columnOrRaw)\n ) {\n const mapped = mapRecordToColumns(\n builder,\n columnOrRaw as Record<string, any>\n );\n (state.baseQuery.orWhere as any)(mapped, ...args);\n } else {\n const col = resolveColumnArg(builder, columnOrRaw);\n (state.baseQuery.orWhere as any)(col, ...args);\n }\n return builder;\n}\n\nexport function whereNotImpl(\n builder: SchemaQueryBuilder<any, any>,\n columnOrRaw: any,\n ...args: any[]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n if (\n typeof columnOrRaw === 'function' &&\n !isColumnAccessor(builder, columnOrRaw)\n ) {\n (state.baseQuery.whereNot as any)(columnOrRaw, ...args);\n } else if (\n typeof columnOrRaw === 'object' &&\n columnOrRaw !== null &&\n !('toSQL' in columnOrRaw)\n ) {\n const mapped = mapRecordToColumns(\n builder,\n columnOrRaw as Record<string, any>\n );\n (state.baseQuery.whereNot as any)(mapped, ...args);\n } else {\n const col = resolveColumnArg(builder, columnOrRaw);\n (state.baseQuery.whereNot as any)(col, ...args);\n }\n return builder;\n}\n\nexport function whereInImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>,\n values: readonly any[] | Knex.QueryBuilder\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.whereIn(\n resolveColumn(builder, column, 'whereIn') as any,\n values as any\n );\n return builder;\n}\n\nexport function whereNotInImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>,\n values: readonly any[] | Knex.QueryBuilder\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.whereNotIn(\n resolveColumn(builder, column, 'whereNotIn') as any,\n values as any\n );\n return builder;\n}\n\nexport function orWhereInImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>,\n values: readonly any[] | Knex.QueryBuilder\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n (state.baseQuery as any).orWhereIn(\n resolveColumn(builder, column, 'orWhereIn'),\n values as any\n );\n return builder;\n}\n\nexport function orWhereNotInImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>,\n values: readonly any[] | Knex.QueryBuilder\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n (state.baseQuery as any).orWhereNotIn(\n resolveColumn(builder, column, 'orWhereNotIn'),\n values as any\n );\n return builder;\n}\n\nexport function whereNullImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.whereNull(\n resolveColumn(builder, column, 'whereNull') as any\n );\n return builder;\n}\n\nexport function whereNotNullImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.whereNotNull(\n resolveColumn(builder, column, 'whereNotNull') as any\n );\n return builder;\n}\n\nexport function orWhereNullImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n (state.baseQuery as any).orWhereNull(\n resolveColumn(builder, column, 'orWhereNull')\n );\n return builder;\n}\n\nexport function orWhereNotNullImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n (state.baseQuery as any).orWhereNotNull(\n resolveColumn(builder, column, 'orWhereNotNull')\n );\n return builder;\n}\n\nexport function whereBetweenImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>,\n range: readonly [any, any]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.whereBetween(\n resolveColumn(builder, column, 'whereBetween') as any,\n range as [any, any]\n );\n return builder;\n}\n\nexport function whereNotBetweenImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>,\n range: readonly [any, any]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.whereNotBetween(\n resolveColumn(builder, column, 'whereNotBetween') as any,\n range as [any, any]\n );\n return builder;\n}\n\nexport function whereLikeImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>,\n value: string\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n (state.baseQuery as any).whereLike(\n resolveColumn(builder, column, 'whereLike'),\n value\n );\n return builder;\n}\n\nexport function whereILikeImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>,\n value: string\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n (state.baseQuery as any).whereILike(\n resolveColumn(builder, column, 'whereILike'),\n value\n );\n return builder;\n}\n\nexport function whereRawImpl(\n builder: SchemaQueryBuilder<any, any>,\n sql: string,\n ...bindings: any[]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.whereRaw(sql, ...bindings);\n return builder;\n}\n\nexport function whereExistsImpl(\n builder: SchemaQueryBuilder<any, any>,\n callback: Knex.QueryCallback | Knex.QueryBuilder\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.whereExists(callback as any);\n return builder;\n}\n\nexport function whereNotExistsImpl(\n builder: SchemaQueryBuilder<any, any>,\n callback: Knex.QueryCallback | Knex.QueryBuilder\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n (state.baseQuery as any).whereNotExists(callback as any);\n return builder;\n}\n\nexport function whereJsonPathImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any>,\n path: string,\n operator?: string,\n value?: any\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n const client = (state.knex as any).client?.config?.client as\n | string\n | undefined;\n if (client !== 'pg' && client !== 'postgresql' && client !== 'postgres') {\n throw new Error(\n `whereJsonPath() is only supported on PostgreSQL (got client: \"${client ?? 'unknown'}\")`\n );\n }\n\n const col = resolveColumn(builder, column, 'whereJsonPath');\n const op = operator ?? '=';\n\n if (op === '@?' || op === '@@') {\n const escapedOp = op === '@?' ? '@\\\\?' : '@@';\n state.baseQuery.whereRaw(`?? ${escapedOp} ?`, [col, path]);\n } else {\n const jsonPath = path.startsWith('$')\n ? path\n : `$.${path.replace(/\\./g, '.')}`;\n state.baseQuery.whereRaw(\n `jsonb_path_query_first(??, ?) ${op} ?::jsonb`,\n [col, jsonPath, JSON.stringify(value)]\n );\n }\n return builder;\n}\n\nexport function orderByImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any> | Knex.Raw,\n direction?: 'asc' | 'desc'\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n const col = resolveColumnArg(builder, column);\n state.baseQuery.orderBy(col as string, direction);\n return builder;\n}\n\nexport function orderByRawImpl(\n builder: SchemaQueryBuilder<any, any>,\n sql: string,\n ...bindings: any[]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.orderByRaw(sql, ...bindings);\n return builder;\n}\n\nexport function groupByImpl(\n builder: SchemaQueryBuilder<any, any>,\n ...columns: (ColumnRef<any> | Knex.Raw)[]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n const resolved = columns.map(c => resolveColumnArg(builder, c));\n state.baseQuery.groupBy(...(resolved as string[]));\n return builder;\n}\n\nexport function groupByRawImpl(\n builder: SchemaQueryBuilder<any, any>,\n sql: string,\n ...bindings: any[]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.groupByRaw(sql, ...bindings);\n return builder;\n}\n\nexport function havingImpl(\n builder: SchemaQueryBuilder<any, any>,\n column: ColumnRef<any> | Knex.Raw,\n operator: string,\n value: any\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n const col = resolveColumnArg(builder, column);\n state.baseQuery.having(col as string, operator, value);\n return builder;\n}\n\nexport function havingRawImpl(\n builder: SchemaQueryBuilder<any, any>,\n sql: string,\n ...bindings: any[]\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.havingRaw(sql, ...bindings);\n return builder;\n}\n","// @cleverbrush/knex-schema — Pagination (offset & cursor-based)\n\nimport { resolvePropertyKey } from '../columns.js';\nimport type { SchemaQueryBuilder } from '../SchemaQueryBuilder.js';\nimport type {\n ColumnRef,\n CursorPaginationResult,\n PaginationResult\n} from '../types.js';\nimport {\n cleanAndMapRow,\n getEffectiveBaseQuery,\n getQuery,\n invalidateCache\n} from './helpers.js';\nimport { getState } from './state.js';\nimport { orderByImpl, whereImpl } from './where.js';\n\nexport function limitImpl(\n builder: SchemaQueryBuilder<any, any>,\n n: number\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.limit(n);\n return builder;\n}\n\nexport function offsetImpl(\n builder: SchemaQueryBuilder<any, any>,\n n: number\n): any {\n const state = getState(builder);\n invalidateCache(builder);\n state.baseQuery.offset(n);\n return builder;\n}\n\nexport async function paginateImpl(\n builder: SchemaQueryBuilder<any, any>,\n opts: {\n page: number;\n pageSize: number;\n }\n): Promise<PaginationResult<any>> {\n const { page, pageSize } = opts;\n const _state = getState(builder);\n\n const effectiveBase = getEffectiveBaseQuery(builder);\n\n const countResult = await effectiveBase\n .clone()\n .clearSelect()\n .clearOrder()\n .count('* as count')\n .first();\n const total = Number((countResult as any)?.count ?? 0);\n\n limitImpl(builder, pageSize);\n offsetImpl(builder, (page - 1) * pageSize);\n const data = await executeImpl(builder);\n\n const totalPages = Math.ceil(total / pageSize);\n\n return {\n data,\n total,\n page,\n pageSize,\n totalPages,\n hasNextPage: page < totalPages,\n hasPreviousPage: page > 1\n } as PaginationResult<any>;\n}\n\nexport async function paginateAfterImpl(\n builder: SchemaQueryBuilder<any, any>,\n opts: {\n cursor?: any;\n limit: number;\n column?: ColumnRef<any>;\n direction?: 'asc' | 'desc';\n }\n): Promise<CursorPaginationResult<any>> {\n const direction = opts.direction ?? 'desc';\n const column = opts.column ?? ('id' as any);\n const state = getState(builder);\n\n if (opts.cursor != null) {\n const op = direction === 'desc' ? '<' : '>';\n whereImpl(builder, column, op, opts.cursor);\n }\n\n orderByImpl(builder, column, direction);\n limitImpl(builder, opts.limit + 1);\n const rows = await executeImpl(builder);\n\n const hasMore = rows.length > opts.limit;\n const data = hasMore ? rows.slice(0, opts.limit) : rows;\n\n const propKey =\n typeof column === 'string'\n ? column\n : resolvePropertyKey(column, state.localSchema, 'cursor');\n\n const nextCursor =\n hasMore && data.length > 0\n ? String((data[data.length - 1] as any)[propKey])\n : null;\n\n return { data, nextCursor, hasMore } as CursorPaginationResult<any>;\n}\n\nexport async function executeImpl(\n builder: SchemaQueryBuilder<any, any>\n): Promise<any[]> {\n const query = getQuery(builder);\n const rows = await query;\n\n if (!rows) return [];\n if (!Array.isArray(rows)) return [cleanAndMapRow(builder, rows)];\n\n return rows.map((row: any) => cleanAndMapRow(builder, row));\n}\n","// @cleverbrush/knex-schema — UPDATE / bulk-update operations\n\nimport type { InferType } from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { buildColumnMap } from '../columns.js';\nimport type { SchemaQueryBuilder } from '../SchemaQueryBuilder.js';\nimport {\n getTimestamps,\n mapObjectToColumns,\n mapRow,\n resolvePkColumns\n} from './helpers.js';\nimport { getState } from './state.js';\n\nexport async function updateImpl(\n builder: SchemaQueryBuilder<any, any>,\n data: Partial<InferType<any>>\n): Promise<any[]> {\n const state = getState(builder);\n\n let processedData = { ...(data as Record<string, any>) };\n\n const beforeHooks =\n ((state.localSchema as any).getExtension?.('beforeUpdate') as\n | Function[]\n | undefined) ?? [];\n for (const hook of beforeHooks) {\n processedData = (await hook(processedData)) ?? processedData;\n }\n\n const mapped = mapObjectToColumns(builder, processedData);\n\n const timestamps = getTimestamps(builder);\n if (timestamps) {\n mapped[timestamps.updatedAt] = state.knex.fn.now();\n }\n\n const rows = await state.baseQuery.update(mapped).returning('*');\n return rows.map((row: any) => mapRow(builder, row));\n}\n\nexport async function bulkUpdateImpl(\n builder: SchemaQueryBuilder<any, any>,\n updates: ReadonlyArray<{\n where: Partial<InferType<any>>;\n set: Partial<InferType<any>>;\n }>\n): Promise<number> {\n if (updates.length === 0) return 0;\n\n const state = getState(builder);\n const pk = resolvePkColumns(builder);\n const { propToCol } = buildColumnMap(state.localSchema as any);\n const beforeHooks =\n ((state.localSchema as any).getExtension?.('beforeUpdate') as\n | Function[]\n | undefined) ?? [];\n const timestamps = getTimestamps(builder);\n\n const processed: Array<{\n pkValues: unknown[];\n set: Record<string, any>;\n }> = [];\n for (const entry of updates) {\n let setData = { ...(entry.set as Record<string, any>) };\n for (const hook of beforeHooks) {\n setData = (await hook(setData)) ?? setData;\n }\n const setMapped = mapObjectToColumns(builder, setData);\n if (timestamps) {\n setMapped[timestamps.updatedAt] = state.knex.fn.now();\n }\n\n const whereRec = entry.where as Record<string, unknown>;\n const pkValues: unknown[] = [];\n for (const propKey of pk.propertyKeys) {\n const value =\n propKey in whereRec\n ? whereRec[propKey]\n : (whereRec[propToCol.get(propKey) ?? propKey] as\n | unknown\n | undefined);\n if (value === undefined) {\n throw new Error(\n `bulkUpdate: each \\`where\\` clause must include the entity's primary key (missing \"${propKey}\").`\n );\n }\n pkValues.push(value);\n }\n processed.push({ pkValues, set: setMapped });\n }\n\n const allSetCols = new Set<string>();\n for (const p of processed) {\n for (const k of Object.keys(p.set)) allSetCols.add(k);\n }\n if (allSetCols.size === 0) return 0;\n\n const knex = state.knex;\n const updateExpr: Record<string, any> = {};\n for (const col of allSetCols) {\n const fragments: string[] = [];\n const bindings: unknown[] = [];\n for (const p of processed) {\n if (!(col in p.set)) continue;\n if (pk.columnNames.length === 1) {\n fragments.push('WHEN ?? = ? THEN ?');\n bindings.push(pk.columnNames[0], p.pkValues[0], p.set[col]);\n } else {\n const conditions = pk.columnNames\n .map(() => '?? = ?')\n .join(' AND ');\n fragments.push(`WHEN ${conditions} THEN ?`);\n for (let i = 0; i < pk.columnNames.length; i++) {\n bindings.push(pk.columnNames[i], p.pkValues[i]);\n }\n bindings.push(p.set[col]);\n }\n }\n if (fragments.length === 0) continue;\n updateExpr[col] = knex.raw(`CASE ${fragments.join(' ')} ELSE ?? END`, [\n ...bindings,\n col\n ] as any);\n }\n\n let qb: any = knex(state.tableName).update(updateExpr);\n if (pk.columnNames.length === 1) {\n qb = qb.whereIn(\n pk.columnNames[0],\n processed.map(p => p.pkValues[0])\n );\n } else {\n qb = qb.where(function (this: Knex.QueryBuilder) {\n for (const p of processed) {\n this.orWhere(function (this: Knex.QueryBuilder) {\n for (let i = 0; i < pk.columnNames.length; i++) {\n this.andWhere(pk.columnNames[i], p.pkValues[i] as any);\n }\n });\n }\n });\n }\n\n return await qb;\n}\n","// @cleverbrush/knex-schema — SchemaQueryBuilder\n\nimport type { InferType } from '@cleverbrush/schema';\nimport {\n EXTRA_TYPE_BRAND,\n METHOD_LITERAL_BRAND,\n type ObjectSchemaBuilder\n} from '@cleverbrush/schema';\nimport type { Knex } from 'knex';\nimport { buildColumnMap } from './columns.js';\nimport { getTableName, POLYMORPHIC_TYPE_BRAND } from './extension.js';\n// Operations\nimport {\n avgImpl,\n countDistinctImpl,\n countImpl,\n distinctImpl,\n maxImpl,\n minImpl,\n projectedImpl,\n scopedImpl,\n selectImpl,\n selectRawImpl,\n sumImpl,\n unscopedImpl\n} from './operations/select.js';\nimport type {\n ColumnRef,\n CursorPaginationResult,\n InsertType,\n JoinManySpec,\n JoinOneSpec,\n PaginationResult,\n SelectProjection,\n SelectSelector\n} from './types.js';\n\nexport { OnConflictBuilder } from './operations/insert.js';\n\nimport {\n deleteImpl,\n hardDeleteImpl,\n onlyDeletedImpl,\n restoreImpl,\n withDeletedImpl\n} from './operations/delete.js';\nimport {\n ALLOWED_OPS,\n buildQuery,\n cleanAndMapRow,\n getQuery,\n getVariantConfig,\n invalidateCache,\n registerSchemaQueryBuilder,\n resolveColumn\n} from './operations/helpers.js';\nimport {\n bulkInsertImpl,\n bulkUpsertImpl,\n insertImpl,\n insertManyImpl,\n onConflictImpl,\n upsertImpl\n} from './operations/insert.js';\nimport {\n includeImpl,\n includeVariantImpl,\n joinManyImpl,\n joinOneImpl\n} from './operations/join.js';\nimport {\n executeImpl,\n limitImpl,\n offsetImpl,\n paginateAfterImpl,\n paginateImpl\n} from './operations/pagination.js';\nimport { getState, setState } from './operations/state.js';\nimport { bulkUpdateImpl, updateImpl } from './operations/update.js';\nimport {\n andWhereImpl,\n groupByImpl,\n groupByRawImpl,\n havingImpl,\n havingRawImpl,\n orderByImpl,\n orderByRawImpl,\n orWhereImpl,\n orWhereInImpl,\n orWhereNotInImpl,\n orWhereNotNullImpl,\n orWhereNullImpl,\n whereBetweenImpl,\n whereExistsImpl,\n whereILikeImpl,\n whereImpl,\n whereInImpl,\n whereJsonPathImpl,\n whereLikeImpl,\n whereNotBetweenImpl,\n whereNotExistsImpl,\n whereNotImpl,\n whereNotInImpl,\n whereNotNullImpl,\n whereNullImpl,\n whereRawImpl\n} from './operations/where.js';\n\n// ---------------------------------------------------------------------------\n// Type-level helpers\n// ---------------------------------------------------------------------------\n\ntype ScopesOf<S> = S extends {\n readonly [METHOD_LITERAL_BRAND]?: infer N;\n}\n ? Extract<N, string>\n : never;\n\ntype ProjectionsOf<S> = S extends {\n readonly [EXTRA_TYPE_BRAND]?: infer P;\n}\n ? P extends Record<string, readonly string[]>\n ? P\n : Record<never, never>\n : Record<never, never>;\n\ntype ProjectionKeysOf<\n S,\n K extends keyof ProjectionsOf<S> & string\n> = ProjectionsOf<S>[K] extends readonly (infer T extends string)[]\n ? T\n : string;\n\ntype QueryResultType<TLocalSchema> = TLocalSchema extends {\n readonly [POLYMORPHIC_TYPE_BRAND]?: infer U;\n}\n ? NonNullable<U>\n : InferType<TLocalSchema>;\n\n// ---------------------------------------------------------------------------\n// SchemaQueryBuilder\n// ---------------------------------------------------------------------------\n\nexport class SchemaQueryBuilder<\n TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>,\n TResult\n> {\n constructor(\n knex: Knex,\n localSchema: TLocalSchema,\n baseQuery?: Knex.QueryBuilder\n ) {\n const tableName = getTableName(localSchema);\n setState(this, {\n knex,\n baseQuery: baseQuery ?? knex(tableName),\n localSchema,\n specs: [],\n tableName,\n explicitSelects: null,\n selectionMode: null,\n appliedProjection: null,\n includeDeleted: false,\n onlyDeleted: false,\n skipDefaultScope: false,\n variantConfig: undefined,\n enabledVariants: null,\n variantWhereFilters: [],\n variantRelationIncludes: [],\n cachedBuiltQuery: null\n });\n }\n\n // =======================================================================\n // SELECT / DISTINCT / AGGREGATES\n // =======================================================================\n\n select(...columns: (ColumnRef<TLocalSchema> | Knex.Raw)[]): this;\n select<TSel extends SelectSelector<TLocalSchema>>(\n selector: TSel\n ): SchemaQueryBuilder<TLocalSchema, SelectProjection<ReturnType<TSel>>>;\n select(...args: unknown[]): any {\n return selectImpl(this as any, ...args);\n }\n\n distinct(...columns: (ColumnRef<TLocalSchema> | Knex.Raw)[]): this {\n return (distinctImpl as any)(this, ...columns);\n }\n\n count(column?: ColumnRef<TLocalSchema> | Knex.Raw): this {\n return (countImpl as any)(this, column);\n }\n\n countDistinct(column?: ColumnRef<TLocalSchema> | Knex.Raw): this {\n return (countDistinctImpl as any)(this, column);\n }\n\n min(column: ColumnRef<TLocalSchema> | Knex.Raw): this {\n return (minImpl as any)(this, column);\n }\n\n max(column: ColumnRef<TLocalSchema> | Knex.Raw): this {\n return (maxImpl as any)(this, column);\n }\n\n sum(column: ColumnRef<TLocalSchema> | Knex.Raw): this {\n return (sumImpl as any)(this, column);\n }\n\n avg(column: ColumnRef<TLocalSchema> | Knex.Raw): this {\n return (avgImpl as any)(this, column);\n }\n\n selectRaw(sql: string, bindings?: any[]): this {\n return selectRawImpl(this as any, sql, bindings);\n }\n\n projected<K extends keyof ProjectionsOf<TLocalSchema> & string>(\n name: K\n ): SchemaQueryBuilder<\n TLocalSchema,\n Pick<TResult, ProjectionKeysOf<TLocalSchema, K> & keyof TResult>\n > {\n return projectedImpl(this as any, name);\n }\n\n scoped<K extends ScopesOf<TLocalSchema>>(name: K): this {\n return scopedImpl(this as any, name as string);\n }\n\n unscoped(): this {\n return unscopedImpl(this as any);\n }\n\n // =======================================================================\n // WHERE\n // =======================================================================\n\n where(column: ColumnRef<TLocalSchema>, operator: string, value: any): this;\n where(column: ColumnRef<TLocalSchema>, value: any): this;\n where(raw: Knex.Raw, operator: string, value: any): this;\n where(callback: (builder: Knex.QueryBuilder) => void): this;\n where(record: Record<string, any>): this;\n where(raw: Knex.Raw): this;\n where(columnOrRaw: any, ...args: any[]): this {\n return whereImpl(this as any, columnOrRaw, ...args);\n }\n\n andWhere(\n column: ColumnRef<TLocalSchema>,\n operator: string,\n value: any\n ): this;\n andWhere(column: ColumnRef<TLocalSchema>, value: any): this;\n andWhere(record: Record<string, any>): this;\n andWhere(callback: (builder: Knex.QueryBuilder) => void): this;\n andWhere(raw: Knex.Raw): this;\n andWhere(columnOrRaw: any, ...args: any[]): this {\n return andWhereImpl(this as any, columnOrRaw, ...args);\n }\n\n orWhere(\n column: ColumnRef<TLocalSchema>,\n operator: string,\n value: any\n ): this;\n orWhere(column: ColumnRef<TLocalSchema>, value: any): this;\n orWhere(record: Record<string, any>): this;\n orWhere(callback: (builder: Knex.QueryBuilder) => void): this;\n orWhere(raw: Knex.Raw): this;\n orWhere(columnOrRaw: any, ...args: any[]): this {\n return orWhereImpl(this as any, columnOrRaw, ...args);\n }\n\n whereNot(\n column: ColumnRef<TLocalSchema>,\n operator: string,\n value: any\n ): this;\n whereNot(column: ColumnRef<TLocalSchema>, value: any): this;\n whereNot(record: Record<string, any>): this;\n whereNot(callback: (builder: Knex.QueryBuilder) => void): this;\n whereNot(raw: Knex.Raw): this;\n whereNot(columnOrRaw: any, ...args: any[]): this {\n return whereNotImpl(this as any, columnOrRaw, ...args);\n }\n\n whereIn(\n column: ColumnRef<TLocalSchema>,\n values: readonly any[] | Knex.QueryBuilder\n ): this {\n return (whereInImpl as any)(this, column, values);\n }\n\n whereNotIn(\n column: ColumnRef<TLocalSchema>,\n values: readonly any[] | Knex.QueryBuilder\n ): this {\n return (whereNotInImpl as any)(this, column, values);\n }\n\n orWhereIn(\n column: ColumnRef<TLocalSchema>,\n values: readonly any[] | Knex.QueryBuilder\n ): this {\n return (orWhereInImpl as any)(this, column, values);\n }\n\n orWhereNotIn(\n column: ColumnRef<TLocalSchema>,\n values: readonly any[] | Knex.QueryBuilder\n ): this {\n return (orWhereNotInImpl as any)(this, column, values);\n }\n\n whereNull(column: ColumnRef<TLocalSchema>): this {\n return (whereNullImpl as any)(this, column);\n }\n\n whereNotNull(column: ColumnRef<TLocalSchema>): this {\n return (whereNotNullImpl as any)(this, column);\n }\n\n orWhereNull(column: ColumnRef<TLocalSchema>): this {\n return (orWhereNullImpl as any)(this, column);\n }\n\n orWhereNotNull(column: ColumnRef<TLocalSchema>): this {\n return (orWhereNotNullImpl as any)(this, column);\n }\n\n whereBetween(\n column: ColumnRef<TLocalSchema>,\n range: readonly [any, any]\n ): this {\n return (whereBetweenImpl as any)(this, column, range);\n }\n\n whereNotBetween(\n column: ColumnRef<TLocalSchema>,\n range: readonly [any, any]\n ): this {\n return (whereNotBetweenImpl as any)(this, column, range);\n }\n\n whereLike(column: ColumnRef<TLocalSchema>, value: string): this {\n return (whereLikeImpl as any)(this, column, value);\n }\n\n whereILike(column: ColumnRef<TLocalSchema>, value: string): this {\n return (whereILikeImpl as any)(this, column, value);\n }\n\n whereRaw(sql: string, ...bindings: any[]): this {\n return (whereRawImpl as any)(this, sql, ...bindings);\n }\n\n whereExists(callback: Knex.QueryCallback | Knex.QueryBuilder): this {\n return (whereExistsImpl as any)(this, callback);\n }\n\n whereNotExists(callback: Knex.QueryCallback | Knex.QueryBuilder): this {\n return (whereNotExistsImpl as any)(this, callback);\n }\n\n whereJsonPath(\n column: ColumnRef<TLocalSchema>,\n path: string,\n operator?: string,\n value?: any\n ): this {\n return (whereJsonPathImpl as any)(this, column, path, operator, value);\n }\n\n // =======================================================================\n // ORDER BY\n // =======================================================================\n\n orderBy(\n column: ColumnRef<TLocalSchema> | Knex.Raw,\n direction?: 'asc' | 'desc'\n ): this {\n return (orderByImpl as any)(this, column, direction);\n }\n\n orderByRaw(sql: string, ...bindings: any[]): this {\n return (orderByRawImpl as any)(this, sql, ...bindings);\n }\n\n // =======================================================================\n // GROUP BY / HAVING\n // =======================================================================\n\n groupBy(...columns: (ColumnRef<TLocalSchema> | Knex.Raw)[]): this {\n return (groupByImpl as any)(this, ...columns);\n }\n\n groupByRaw(sql: string, ...bindings: any[]): this {\n return (groupByRawImpl as any)(this, sql, ...bindings);\n }\n\n having(\n column: ColumnRef<TLocalSchema> | Knex.Raw,\n operator: string,\n value: any\n ): this {\n return (havingImpl as any)(this, column, operator, value);\n }\n\n havingRaw(sql: string, ...bindings: any[]): this {\n return havingRawImpl(this as any, sql, ...bindings);\n }\n\n // =======================================================================\n // PAGINATION\n // =======================================================================\n\n limit(n: number): this {\n return limitImpl(this as any, n);\n }\n\n offset(n: number): this {\n return offsetImpl(this as any, n);\n }\n\n async paginate(opts: {\n page: number;\n pageSize: number;\n }): Promise<PaginationResult<TResult>> {\n return paginateImpl(this as any, opts) as Promise<\n PaginationResult<TResult>\n >;\n }\n\n async paginateAfter(opts: {\n cursor?: any;\n limit: number;\n column?: ColumnRef<TLocalSchema>;\n direction?: 'asc' | 'desc';\n }): Promise<CursorPaginationResult<TResult>> {\n return (paginateAfterImpl as any)(this, opts) as Promise<\n CursorPaginationResult<TResult>\n >;\n }\n\n // =======================================================================\n // WRITE OPERATIONS\n // =======================================================================\n\n async insert(data: InsertType<TLocalSchema>): Promise<TResult> {\n return insertImpl(this as any, data) as Promise<TResult>;\n }\n\n async insertMany(data: InsertType<TLocalSchema>[]): Promise<TResult[]> {\n return insertManyImpl(this as any, data) as Promise<TResult[]>;\n }\n\n onConflict(\n ...conflictColumns: ColumnRef<TLocalSchema>[]\n ): import('./operations/insert.js').OnConflictBuilder<\n TLocalSchema,\n TResult\n > {\n return (onConflictImpl as any)(this, ...conflictColumns);\n }\n\n async upsert(\n data: InsertType<TLocalSchema>,\n opts: {\n conflictColumns: ColumnRef<TLocalSchema>[];\n updateColumns?: ColumnRef<TLocalSchema>[];\n }\n ): Promise<TResult> {\n return (upsertImpl as any)(this, data, opts);\n }\n\n async bulkInsert(\n rows: InsertType<TLocalSchema>[],\n opts?: {\n chunkSize?: number;\n onConflict?: 'ignore' | 'merge';\n conflictColumns?: ColumnRef<TLocalSchema>[];\n }\n ): Promise<TResult[]> {\n return (bulkInsertImpl as any)(this, rows, opts);\n }\n\n async bulkUpsert(\n rows: InsertType<TLocalSchema>[],\n opts: {\n conflictColumns: ColumnRef<TLocalSchema>[];\n chunkSize?: number;\n }\n ): Promise<TResult[]> {\n return (bulkUpsertImpl as any)(this, rows, opts);\n }\n\n // =======================================================================\n // UPDATE\n // =======================================================================\n\n async update(data: Partial<InferType<TLocalSchema>>): Promise<TResult[]> {\n return updateImpl(this as any, data) as Promise<TResult[]>;\n }\n\n async bulkUpdate(\n updates: ReadonlyArray<{\n where: Partial<InferType<TLocalSchema>>;\n set: Partial<InferType<TLocalSchema>>;\n }>\n ): Promise<number> {\n return bulkUpdateImpl(this as any, updates as any);\n }\n\n // =======================================================================\n // DELETE / SOFT DELETE\n // =======================================================================\n\n async delete(): Promise<number> {\n return deleteImpl(this as any);\n }\n\n withDeleted(): this {\n return withDeletedImpl(this as any);\n }\n\n onlyDeleted(): this {\n return onlyDeletedImpl(this as any);\n }\n\n async hardDelete(): Promise<number> {\n return hardDeleteImpl(this as any);\n }\n\n async restore(): Promise<TResult[]> {\n return restoreImpl(this as any) as Promise<TResult[]>;\n }\n\n // =======================================================================\n // EAGER LOADING (JOIN)\n // =======================================================================\n\n joinOne<\n TForeignSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >,\n TFieldName extends string,\n TRequired extends boolean = true\n >(\n spec: JoinOneSpec<TLocalSchema, TForeignSchema, TFieldName, TRequired>\n ): SchemaQueryBuilder<\n TLocalSchema,\n import('./types.js').WithJoinedOne<\n TResult,\n TFieldName,\n TForeignSchema,\n TRequired\n >\n > {\n return joinOneImpl(this as any, spec);\n }\n\n joinMany<\n TForeignSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >,\n TFieldName extends string\n >(\n spec: JoinManySpec<TLocalSchema, TForeignSchema, TFieldName>\n ): SchemaQueryBuilder<\n TLocalSchema,\n import('./types.js').WithJoinedMany<TResult, TFieldName, TForeignSchema>\n > {\n return joinManyImpl(this as any, spec);\n }\n\n include(\n relationName: string,\n customize?: (q: SchemaQueryBuilder<any, any>) => void\n ): this {\n return includeImpl(this as any, relationName, customize);\n }\n\n includeVariant(\n variantKey: string,\n relationName: string,\n customize?: (q: SchemaQueryBuilder<any, any>) => void\n ): this {\n return includeVariantImpl(\n this as any,\n variantKey,\n relationName,\n customize\n );\n }\n\n // =======================================================================\n // POLYMORPHIC VARIANTS\n // =======================================================================\n\n whereVariant(\n key: string,\n column: string,\n operator: string,\n value: any\n ): this {\n const state = getState(this);\n const variantConfig = getVariantConfig(this);\n if (!variantConfig) {\n throw new Error(\n 'whereVariant() can only be used on a polymorphic schema (created with .withVariants())'\n );\n }\n\n const spec = variantConfig.variants[key];\n if (!spec) {\n throw new Error(\n `whereVariant: unknown variant key \"${key}\". ` +\n `Valid keys: ${Object.keys(variantConfig.variants).join(', ')}`\n );\n }\n\n const op = operator.toLowerCase();\n if (!ALLOWED_OPS.has(op)) {\n throw new Error(\n `whereVariant: operator \"${operator}\" is not allowed. ` +\n `Allowed operators: ${[...ALLOWED_OPS].join(', ')}`\n );\n }\n\n const { propToCol } = buildColumnMap(spec.schema);\n const colName = propToCol.get(column) ?? column;\n\n let qualifiedColumn: string;\n if (spec.storage === 'cti') {\n qualifiedColumn = `__v_${key}.${colName}`;\n } else {\n qualifiedColumn = `${state.tableName}.${colName}`;\n }\n\n state.variantWhereFilters.push({ key, qualifiedColumn, op, value });\n invalidateCache(this);\n return this;\n }\n\n selectVariants(keys: string[]): this {\n const state = getState(this);\n if (!getVariantConfig(this)) {\n throw new Error(\n 'selectVariants() can only be used on a polymorphic schema (created with .withVariants())'\n );\n }\n state.enabledVariants = new Set(keys);\n invalidateCache(this);\n return this;\n }\n\n // =======================================================================\n // ESCAPE HATCH\n // =======================================================================\n\n apply(fn: (builder: Knex.QueryBuilder) => void): this {\n const state = getState(this);\n invalidateCache(this);\n fn(state.baseQuery);\n return this;\n }\n\n // =======================================================================\n // TRANSACTION\n // =======================================================================\n\n transacting(\n trx: Knex.Transaction\n ): SchemaQueryBuilder<TLocalSchema, TResult> {\n const state = getState(this);\n const builder = new SchemaQueryBuilder<TLocalSchema, TResult>(\n trx as unknown as Knex,\n state.localSchema as TLocalSchema,\n state.baseQuery.clone().transacting(trx)\n );\n const builderState = getState(builder);\n for (const spec of state.specs) {\n builderState.specs.push({\n ...spec,\n foreignQuery: spec.foreignQuery.clone().transacting(trx)\n });\n }\n builderState.explicitSelects = state.explicitSelects\n ? [...state.explicitSelects]\n : null;\n builderState.selectionMode = state.selectionMode;\n builderState.appliedProjection = state.appliedProjection;\n builderState.includeDeleted = state.includeDeleted;\n builderState.onlyDeleted = state.onlyDeleted;\n builderState.skipDefaultScope = state.skipDefaultScope;\n builderState.variantConfig = state.variantConfig;\n builderState.enabledVariants =\n state.enabledVariants !== null\n ? new Set(state.enabledVariants)\n : null;\n builderState.variantWhereFilters = [...state.variantWhereFilters];\n builderState.variantRelationIncludes = [\n ...state.variantRelationIncludes\n ];\n return builder;\n }\n\n // =======================================================================\n // EXECUTION\n // =======================================================================\n\n toQuery(): string {\n return getQuery(this).toQuery();\n }\n\n toKnexQuery(): Knex.QueryBuilder {\n return getQuery(this);\n }\n\n toString(): string {\n return getQuery(this).toString();\n }\n\n async execute(): Promise<TResult[]> {\n return executeImpl(this) as Promise<TResult[]>;\n }\n\n async first(): Promise<TResult | undefined> {\n const query = getQuery(this).first();\n const row = await query;\n\n if (!row) return undefined;\n return cleanAndMapRow(this, row) as TResult;\n }\n\n async pluck<K extends keyof TResult & string>(\n column: ColumnRef<TLocalSchema>\n ): Promise<TResult[K][]> {\n const _state = getState(this);\n const col = resolveColumn(this, column, 'pluck') as string;\n const rows = await buildQuery(this).select(col);\n return rows.map(\n (row: any) => row[col] ?? row[column as string]\n ) as TResult[K][];\n }\n\n // biome-ignore lint/suspicious/noThenProperty: intentional thenable\n then<TReturn1 = TResult[], TReturn2 = never>(\n onfulfilled?:\n | ((value: TResult[]) => TReturn1 | PromiseLike<TReturn1>)\n | null,\n onrejected?: ((reason: any) => TReturn2 | PromiseLike<TReturn2>) | null\n ): Promise<TReturn1 | TReturn2> {\n return this.execute().then(onfulfilled, onrejected);\n }\n}\n\n// Register the constructor for circular-dependency-safe access\nregisterSchemaQueryBuilder(SchemaQueryBuilder);\n\n// ---------------------------------------------------------------------------\n// query() — main entry point\n// ---------------------------------------------------------------------------\n\nexport function query<\n TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n>(\n knex: Knex,\n schema: TLocalSchema\n): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;\n\nexport function query<\n TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n>(\n knex: Knex,\n schema: TLocalSchema,\n baseQuery: Knex.QueryBuilder\n): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;\n\nexport function query<\n TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>\n>(\n knex: Knex,\n schema: TLocalSchema,\n baseQuery?: Knex.QueryBuilder\n): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>> {\n return new SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>(\n knex,\n schema,\n baseQuery\n );\n}\n\n// ---------------------------------------------------------------------------\n// createQuery() — knex-bound factory\n// ---------------------------------------------------------------------------\n\nexport interface BoundQuery {\n <\n TLocalSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n >(\n schema: TLocalSchema\n ): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;\n <\n TLocalSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n >(\n schema: TLocalSchema,\n baseQuery: Knex.QueryBuilder\n ): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;\n withTransaction(trx: Knex.Transaction): BoundQuery;\n transaction<T>(callback: (db: BoundQuery) => Promise<T>): Promise<T>;\n}\n\nexport function createQuery(knexInstance: Knex): BoundQuery {\n function boundQuery<\n TLocalSchema extends ObjectSchemaBuilder<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n >(\n schema: TLocalSchema,\n baseQuery?: Knex.QueryBuilder\n ): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>> {\n return baseQuery\n ? query(knexInstance, schema, baseQuery)\n : query(knexInstance, schema);\n }\n\n (boundQuery as BoundQuery).withTransaction = (\n trx: Knex.Transaction\n ): BoundQuery => createQuery(trx as unknown as Knex);\n\n (boundQuery as BoundQuery).transaction = <T>(\n callback: (db: BoundQuery) => Promise<T>\n ): Promise<T> =>\n knexInstance.transaction(trx =>\n callback(createQuery(trx as unknown as Knex))\n );\n\n return boundQuery as BoundQuery;\n}\n","// @cleverbrush/knex-schema — Schema snapshot serialization\n\nimport { readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport type { Entity } from './entity.js';\nimport { getPolymorphicVariantSchemas, getTableName } from './extension.js';\nimport { entitySchemaToTableState } from './migration.js';\nimport type { SchemaSnapshot } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Builders\n// ---------------------------------------------------------------------------\n\n/**\n * Build a {@link SchemaSnapshot} from a set of entities without a live DB.\n *\n * Handles polymorphic (CTI) entities by including each variant table.\n * Deduplicates tables so STI variants sharing a base table are only included\n * once.\n *\n * @param entities - The entities from your `EntityMap`.\n * @returns A snapshot reflecting the current code-first schema state.\n *\n * @example\n * ```ts\n * const snapshot = entitiesToSnapshot(Object.values(entityMap));\n * writeSnapshot('./migrations/snapshot.json', snapshot);\n * ```\n */\nexport function entitiesToSnapshot(\n entities: Entity<any, any>[]\n): SchemaSnapshot {\n const tables: SchemaSnapshot['tables'] = {};\n\n for (const entity of entities) {\n const schema = entity.schema;\n const tableName = getTableName(schema);\n if (!tables[tableName]) {\n tables[tableName] = entitySchemaToTableState(schema);\n }\n\n for (const vs of getPolymorphicVariantSchemas(schema)) {\n const variantTableName = vs.getExtension('tableName') as\n | string\n | undefined;\n if (variantTableName && !tables[variantTableName]) {\n tables[variantTableName] = entitySchemaToTableState(vs);\n }\n }\n }\n\n return { version: 1, tables };\n}\n\n// ---------------------------------------------------------------------------\n// I/O\n// ---------------------------------------------------------------------------\n\n/**\n * Load a {@link SchemaSnapshot} from disk.\n *\n * Returns an empty snapshot (no tables) when the file does not exist — this\n * is the \"first run\" case, which causes `migrate generate` to emit a single\n * migration containing `CREATE TABLE` for every entity.\n *\n * @param snapshotPath - Absolute or cwd-relative path to `snapshot.json`.\n * @returns The parsed snapshot, or `{ version: 1, tables: {} }` if missing or\n * unreadable.\n */\nexport function loadSnapshot(snapshotPath: string): SchemaSnapshot {\n try {\n const raw = readFileSync(resolve(snapshotPath), 'utf-8');\n const parsed = JSON.parse(raw) as SchemaSnapshot;\n if (\n parsed.version !== 1 ||\n parsed.tables == null ||\n typeof parsed.tables !== 'object'\n ) {\n return { version: 1, tables: {} };\n }\n return parsed;\n } catch {\n return { version: 1, tables: {} };\n }\n}\n\n/**\n * Write a {@link SchemaSnapshot} to disk atomically (temp-file + rename) with\n * deterministic key ordering so diffs in version control are minimal.\n *\n * @param snapshotPath - Absolute or cwd-relative path to write `snapshot.json`.\n * @param snapshot - The snapshot to serialize.\n */\nexport function writeSnapshot(\n snapshotPath: string,\n snapshot: SchemaSnapshot\n): void {\n const absPath = resolve(snapshotPath);\n const tmp = absPath + '.tmp';\n writeFileSync(\n tmp,\n JSON.stringify(_sortSnapshot(snapshot), null, 2) + '\\n',\n 'utf-8'\n );\n renameSync(tmp, absPath);\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** @internal Sort all keys in the snapshot for deterministic JSON output. */\nfunction _sortSnapshot(snapshot: SchemaSnapshot): SchemaSnapshot {\n const sortedTables: SchemaSnapshot['tables'] = {};\n for (const tableName of Object.keys(snapshot.tables).sort()) {\n const state = snapshot.tables[tableName];\n sortedTables[tableName] = {\n columns: Object.fromEntries(\n Object.entries(state.columns).sort(([a], [b]) =>\n a.localeCompare(b)\n )\n ),\n indexes: [...state.indexes].sort((a, b) =>\n a.name.localeCompare(b.name)\n ),\n foreignKeys: [...state.foreignKeys].sort((a, b) =>\n a.constraintName.localeCompare(b.constraintName)\n ),\n checks: [...state.checks].sort((a, b) =>\n a.name.localeCompare(b.name)\n )\n };\n }\n return { version: 1, tables: sortedTables };\n}\n"],"mappings":"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","names":["ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","columnMapCache","buildColumnMap","schema","cached","properties","propToCol","colToProp","propKey","propSchema","colName","getColumnName","result","jsonPathRaw","knex","col","jsonPath","pathLiteral","resolveColumnRef","ref","label","topProp","tree","ObjectSchemaBuilder","descriptor","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","pointer","segments","s","resolvePropertyKey","getPrimaryKeyColumns","introspected","extensions","composite","propertyKeys","columnNames","entry","getRowVersionColumn","rv","resolveColumnType","table","col","introspected","ext","maxLen","applyDefault","column","defaultValue","knex","generateCreateTable","schema","tableName","getTableName","tableExt","extensionManagedCols","builder","properties","propKey","propSchema","getColumnName","propIntrospected","fkBuilder","idx","unq","chk","rawCol","rawIndexes","rawIdx","generateCreateTableSource","lines","line","_colTypeCode","_fmtDefault","cols","rawIndexLines","ri","up","down","value","generateCreatePolymorphicTables","result","variantSchemas","getPolymorphicVariantSchemas","variantSchema","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","Entity","_Entity","schema","spec","existing","next","navSel","_localSel","remoteSel","opts","navName","foreignSchema","remoteKey","localSel","_remoteSel","localKey","through","sel","discKey","key","variant","fkSel","builder","fkColumn","resolveCtiForeignKeyColumn","nextVariants","entityRelationsToVariantRelations","resolveInlineVariantRelations","body","isEntity","varSchema","variants","newSchema","applyVariantsToSchema","existingRelations","selector","tree","ObjectSchemaBuilder","descriptor","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","inner","propSchema","intro","varEntity","rels","propToCol","buildColumnMap","r","fkPropName","fkColName","propKey","getColumnName","relations","result","name","foreignKey","targetSchema","defineEntity","MAPPERS","value","mapValue","mapper","mapObject","obj","mappers","result","key","clearRow","row","oneSpecs","manySpecs","spec","fieldName","k","normalizeDbState","columns","indexes","foreignKeys","checks","colMap","row","idxList","fkList","chkList","introspectDatabase","knex","tableName","schemaTypeToDbType","introspected","ext","entitySchemaToTableState","schema","getTableName","properties","tableExt","propKey","propSchema","col","getColumnName","propIntrospected","ts","createdAtCol","updatedAtCol","delCol","idx","idxName","unq","unqName","diffSchema","dbState","addColumns","dropColumns","alterColumns","addIndexes","dropIndexes","addForeignKeys","dropForeignKeys","extensionOwnedDefaults","schemaColumns","dbCol","changes","expectedNullable","snapshotDefault","schemaDefault","fk","colName","schemaIndexNames","dbIdx","ps","generateMigration","diff","up","down","buildAlterTableFragments","full","tableExistsInDb","isDiffEmpty","applyDiff","constraintName","table","column","buildColumnFromDbType","fkBuilder","key","change","builder","generateMigrationsForContext","entities","prevSnapshot","tableEntries","entity","vs","getPolymorphicVariantSchemas","variantTableName","seen","uniqueEntries","e","sorted","topologicalSort","upParts","downParts","currentTableNames","snapshotState","generateCreateTableSource","state","generateDropTableSource","isEmpty","nextTables","colLines","line","upLines","downLines","mapTypeToKnex","formatDefault","toVal","fromVal","cols","name","dbType","entries","tableSet","deps","depSet","inDegree","graph","dep","queue","t","deg","sortedNames","dependent","newDeg","sortedSet","remaining","byName","type","value","rawQuery","knex","schema","queryOrSql","bindings","rows","result","colToProp","buildColumnMap","row","mapped","key","value","propName","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","STATE","getState","builder","s","setState","state","resolveColumn","builder","ref","label","state","getState","resolveColumnRef","invalidateCache","getSoftDelete","getDefaultScope","fn","getTimestamps","ALLOWED_OPS","getVariantConfig","builder","state","getState","raw","getVariants","propToCol","buildColumnMap","discCol","applyVariantJoins","base","variantConfig","knex","baseTable","basePkCol","findPrimaryKeyColumn","qb","key","spec","variantAlias","variantTable","fkCol","variantProps","propKey","colName","vrInc","variantSpec","relSpec","r","foreignSchema","resolveSchema","foreignTableName","getTableName","relAlias","localCol","foreignCol","onExpr","foreignKnex","selectionSql","buildVariantRelationSelect","sel","filter","discColFull","SchemaQueryBuilderCtor","registerSchemaQueryBuilder","ctor","getSchemaQueryBuilderCtor","customize","foreignProps","columnsToSelect","probe","explicit","p","mapPolymorphicRow","row","baseColToProp","result","value","propName","discPropKey","discValue","varColToProp","prefix","fkAlias","origCol","variantSpec3","relColToProp","nested","anyNonNull","_builder","schema","pk","getPrimaryKeyColumns","resolvePkColumns","getEffectiveBaseQuery","effectiveBase","cloned","softDelete","getSoftDelete","defaultScopeFn","getDefaultScope","proxy","proxyState","buildJoinOne","resultQuery","relationAlias","foreignTable","subquery","joinMethod","buildJoinMany","i","filterName","hasLimitOffset","orderByColumn","orderByDirection","aggSubquery","hasLimit","hasOffset","effectiveOffset","effectiveLimit","condition","orderClause","buildQuery","queryBase","specs","requiredLocalColumns","s","cteQuery","extraColumns","selectedSet","col","getQuery","mapRow","colToProp","cleanAndMapRow","oneSpecs","manySpecs","cleaned","clearRow","mapObjectToColumns","obj","mapRecordToColumns","record","resolveColumnArg","resolveColumn","isColumnAccessor","fn","tree","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","assertNotProjection","method","assertNotExplicitSelect","selectImpl","builder","args","state","getState","fn","tree","ObjectSchemaBuilder","result","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","invalidateCache","assertNotProjection","aliasMap","alias","descriptor","col","resolveColumn","resolved","c","resolveColumnArg","r","distinctImpl","columns","countImpl","column","countDistinctImpl","minImpl","maxImpl","sumImpl","avgImpl","selectRawImpl","sql","bindings","projectedImpl","name","assertNotExplicitSelect","projection","getProjections","propToCol","buildColumnMap","sqlCols","key","scopedImpl","scopeFn","unscopedImpl","OnConflictBuilder","#knex","#localSchema","#conflictColumns","knex","localSchema","_parent","conflictColumns","data","updateData","#execute","mode","tableName","getTableName","timestamps","beforeHooks","processed","hook","propToCol","buildColumnMap","mapped","key","val","qb","mergeObj","rows","colToProp","result","col","insertImpl","builder","state","getState","processedData","mapObjectToColumns","getTimestamps","row","mapRow","afterHooks","insertManyImpl","d","m","results","onConflictImpl","cols","c","resolveColumn","upsertImpl","opts","updateCols","bulkInsertImpl","requestedChunkSize","bindingsPerRow","safeChunkCap","chunkSize","conflictCols","i","chunk","k","inserted","mappedRow","bulkUpsertImpl","deleteImpl","builder","state","getState","hooks","hook","softDelete","getSoftDelete","withDeletedImpl","invalidateCache","onlyDeletedImpl","hardDeleteImpl","restoreImpl","row","mapRow","resolveForeignQuery","spec","knex","tableName","getTableName","validateJoinOne","localSchema","localColumn","resolveColumnRef","foreignColumn","foreignQuery","required","validateMappers","validateJoinMany","limit","offset","orderBy","mappers","key","m","MAPPERS","validateUniqueFieldNames","specs","seen","joinOneImpl","builder","spec","state","getState","validated","validateJoinOne","validateUniqueFieldNames","invalidateCache","joinManyImpl","validateJoinMany","includeImpl","relationName","customize","relation","r","variantConfig","getVariantConfig","matches","vKey","vSpec","includeVariantImpl","m","foreignSchema","resolveSchema","foreignTableName","getTableName","localColumn","resolveColumnRef","foreignColumn","findPrimaryKeyColumn","foreignQuery1","SQB","getSchemaQueryBuilderCtor","proxy","foreignQuery2","foreignQuery3","through","foreignQuery","variantKey","variantSpec","whereImpl","builder","columnOrRaw","args","state","getState","invalidateCache","isColumnAccessor","mapped","mapRecordToColumns","col","resolveColumnArg","andWhereImpl","orWhereImpl","whereNotImpl","whereInImpl","column","values","resolveColumn","whereNotInImpl","orWhereInImpl","orWhereNotInImpl","whereNullImpl","whereNotNullImpl","orWhereNullImpl","orWhereNotNullImpl","whereBetweenImpl","range","whereNotBetweenImpl","whereLikeImpl","value","whereILikeImpl","whereRawImpl","sql","bindings","whereExistsImpl","callback","whereNotExistsImpl","whereJsonPathImpl","path","operator","client","op","escapedOp","jsonPath","orderByImpl","direction","orderByRawImpl","groupByImpl","columns","resolved","c","groupByRawImpl","havingImpl","havingRawImpl","limitImpl","builder","state","getState","invalidateCache","offsetImpl","paginateImpl","opts","page","pageSize","_state","countResult","getEffectiveBaseQuery","total","data","executeImpl","totalPages","paginateAfterImpl","direction","column","whereImpl","orderByImpl","rows","hasMore","propKey","resolvePropertyKey","nextCursor","getQuery","row","cleanAndMapRow","updateImpl","builder","data","state","getState","processedData","beforeHooks","hook","mapped","mapObjectToColumns","timestamps","getTimestamps","row","mapRow","bulkUpdateImpl","updates","pk","resolvePkColumns","propToCol","buildColumnMap","processed","entry","setData","setMapped","whereRec","pkValues","propKey","value","allSetCols","p","k","knex","updateExpr","col","fragments","bindings","conditions","i","qb","SchemaQueryBuilder","_SchemaQueryBuilder","knex","localSchema","baseQuery","tableName","getTableName","setState","args","selectImpl","columns","distinctImpl","column","countImpl","countDistinctImpl","minImpl","maxImpl","sumImpl","avgImpl","sql","bindings","selectRawImpl","name","projectedImpl","scopedImpl","unscopedImpl","columnOrRaw","whereImpl","andWhereImpl","orWhereImpl","whereNotImpl","values","whereInImpl","whereNotInImpl","orWhereInImpl","orWhereNotInImpl","whereNullImpl","whereNotNullImpl","orWhereNullImpl","orWhereNotNullImpl","range","whereBetweenImpl","whereNotBetweenImpl","value","whereLikeImpl","whereILikeImpl","whereRawImpl","callback","whereExistsImpl","whereNotExistsImpl","path","operator","whereJsonPathImpl","direction","orderByImpl","orderByRawImpl","groupByImpl","groupByRawImpl","havingImpl","havingRawImpl","limitImpl","offsetImpl","opts","paginateImpl","paginateAfterImpl","data","insertImpl","insertManyImpl","conflictColumns","onConflictImpl","upsertImpl","rows","bulkInsertImpl","bulkUpsertImpl","updateImpl","updates","bulkUpdateImpl","deleteImpl","withDeletedImpl","onlyDeletedImpl","hardDeleteImpl","restoreImpl","spec","joinOneImpl","joinManyImpl","relationName","customize","includeImpl","variantKey","includeVariantImpl","key","state","getState","variantConfig","getVariantConfig","op","ALLOWED_OPS","propToCol","buildColumnMap","colName","qualifiedColumn","invalidateCache","keys","fn","trx","builder","builderState","getQuery","executeImpl","row","cleanAndMapRow","_state","col","resolveColumn","buildQuery","onfulfilled","onrejected","registerSchemaQueryBuilder","query","schema","createQuery","knexInstance","boundQuery","readFileSync","renameSync","writeFileSync","resolve","entitiesToSnapshot","entities","tables","entity","schema","tableName","getTableName","entitySchemaToTableState","vs","getPolymorphicVariantSchemas","variantTableName","loadSnapshot","snapshotPath","raw","readFileSync","resolve","parsed","writeSnapshot","snapshot","absPath","tmp","writeFileSync","_sortSnapshot","renameSync","sortedTables","state","a","b"]}
|