@vibeorm/migrate 2.0.0-alpha.3 → 2.0.0-alpha.5
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/ddl/sqlite.d.ts.map +1 -1
- package/dist/differ.d.ts.map +1 -1
- package/dist/index.js +226 -24
- package/dist/index.js.map +13 -13
- package/dist/introspect/mysql.d.ts.map +1 -1
- package/dist/introspect/postgres.d.ts.map +1 -1
- package/dist/introspect/shared.d.ts +2 -0
- package/dist/introspect/shared.d.ts.map +1 -1
- package/dist/introspect/sqlite.d.ts.map +1 -1
- package/dist/normalize.d.ts +8 -0
- package/dist/normalize.d.ts.map +1 -1
- package/dist/sqlite-types.d.ts +14 -0
- package/dist/sqlite-types.d.ts.map +1 -1
- package/dist/types.d.ts +17 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
package/dist/index.js.map
CHANGED
|
@@ -2,30 +2,30 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/types.ts", "../src/differ.ts", "../src/enum-values.ts", "../src/normalize.ts", "../src/relations.ts", "../src/postgres-types.ts", "../src/sqlite-types.ts", "../src/mysql-types.ts", "../src/ddl/postgres.ts", "../src/ddl/sqlite.ts", "../src/ddl/drop-order.ts", "../src/ddl/mysql.ts", "../src/ddl/render.ts", "../src/runner.ts", "../src/extensions.ts", "../src/execute.ts", "../src/introspect/shared.ts", "../src/introspect/postgres.ts", "../src/introspect/sqlite.ts", "../src/introspect/mysql.ts", "../src/down.ts", "../src/push.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Public types of @vibeorm/migrate: the executor contract, the dialect-neutral\n * migration step model, and the runner's file/result shapes.\n *\n * Steps carry Schema-IR fragments (FieldIR, EnumIR) — never SQL text. SQL is\n * produced exclusively by the per-dialect renderers (ddl-postgres.ts), so every\n * SQL-text decision stays reviewable in one place (constitution rule 3/4).\n */\n\nimport type { CascadeAction, EnumIR, FieldIR } from \"@vibeorm/schema\";\n\n// ─── Executor ─────────────────────────────────────────────────────\n\n/**\n * Minimal SQL execution contract the migrate engine runs on. Structurally\n * identical to @vibeorm/runtime's `SqlExecutor` (its `toSqlExecutor` bridges a\n * DatabaseAdapter to this shape) — declared here so the dependency direction\n * stays schema ← sql ← migrate.\n *\n * SESSION AFFINITY: the migrate engine issues session-scoped statements\n * through this contract (BEGIN/COMMIT, `PRAGMA foreign_keys`, advisory locks\n * `pg_advisory_lock` / `GET_LOCK`), so every call MUST hit the same database\n * session. Single-connection adapters (pglite, sqlite) satisfy this by\n * construction; pool-backed executors must pin one connection for the whole\n * migrate operation.\n */\nexport type SqlExecutor = (params: {\n text: string;\n values?: unknown[];\n}) => Promise<Record<string, unknown>[]>;\n\n// ─── Step building blocks ─────────────────────────────────────────\n\n/** Which aspects of a column an `alterColumn` step changes. */\nexport type AlterColumnAspect = \"type\" | \"nullability\" | \"default\";\n\n/** One column of an index, with its sort direction. */\nexport type IndexColumn = {\n readonly name: string;\n readonly desc: boolean;\n /**\n * The field is a Decimal (SQLITE-2, SQL review round 2). Inert everywhere\n * except the sqlite DDL renderer: Decimal stores as TEXT there and every\n * compare/order site reads `CAST(col AS REAL)` (B4), which a plain-column\n * index can never serve (EQP-proven SCAN) — sqlite renders an EXPRESSION\n * index over the same cast instead. Not part of the index comparison key:\n * both sides compare by column name + direction.\n */\n readonly decimal?: boolean;\n};\n\n/** One side of an implicit many-to-many join table. */\nexport type JoinTableEnd = {\n /** Referenced table (db name). */\n readonly table: string;\n /** Referenced primary-key column (db name). */\n readonly column: string;\n /** The referenced primary-key field — its type renders the join column's type. */\n readonly field: FieldIR;\n};\n\n// ─── Steps ────────────────────────────────────────────────────────\n\n/**\n * A dialect-neutral migration step produced by `diffSchemas`. `destructive`\n * marks steps that can lose data (dropTable / dropJoinTable / dropColumn /\n * dropEnum / narrowing type changes) — `push` refuses them without\n * `acceptDataLoss`, and `generateMigration` surfaces the flag.\n */\nexport type MigrationStep =\n | {\n readonly kind: \"createEnum\";\n readonly enumDef: EnumIR;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropEnum\";\n readonly enumName: string;\n readonly destructive: true;\n }\n | {\n readonly kind: \"addEnumValue\";\n readonly enumName: string;\n readonly value: string;\n readonly destructive: false;\n }\n | {\n readonly kind: \"createTable\";\n readonly table: string;\n readonly columns: readonly FieldIR[];\n /** Primary-key column db names (empty = no PK). */\n readonly primaryKey: readonly string[];\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropTable\";\n readonly table: string;\n readonly destructive: true;\n }\n | {\n readonly kind: \"addColumn\";\n readonly table: string;\n readonly column: FieldIR;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropColumn\";\n readonly table: string;\n readonly column: string;\n readonly destructive: true;\n }\n | {\n readonly kind: \"alterColumn\";\n readonly table: string;\n /** Column db name. */\n readonly column: string;\n readonly from: FieldIR;\n readonly to: FieldIR;\n readonly changes: readonly AlterColumnAspect[];\n readonly destructive: boolean;\n }\n | {\n readonly kind: \"createIndex\";\n readonly table: string;\n readonly name: string;\n /** IR index kind (\"btree\", \"gin\", …) — `unique` indexes are always btree. */\n readonly indexKind: string;\n readonly unique: boolean;\n readonly columns: readonly IndexColumn[];\n /** Partial-index predicate, raw SQL. */\n readonly where?: string;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropIndex\";\n readonly name: string;\n /**\n * Table the index belongs to. Optional for postgres/sqlite (their DROP\n * INDEX is schema-global) but REQUIRED by the mysql renderer\n * (`DROP INDEX … ON table`); the differ always fills it.\n */\n readonly table?: string;\n readonly destructive: false;\n }\n | {\n readonly kind: \"addForeignKey\";\n readonly table: string;\n readonly constraintName: string;\n readonly columns: readonly string[];\n readonly refTable: string;\n readonly refColumns: readonly string[];\n readonly onDelete: CascadeAction;\n readonly onUpdate: CascadeAction;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropForeignKey\";\n readonly table: string;\n readonly constraintName: string;\n readonly destructive: false;\n }\n | {\n readonly kind: \"createJoinTable\";\n readonly table: string;\n readonly a: JoinTableEnd;\n readonly b: JoinTableEnd;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropJoinTable\";\n readonly table: string;\n readonly destructive: true;\n }\n | {\n readonly kind: \"addPrimaryKey\";\n readonly table: string;\n readonly columns: readonly string[];\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropPrimaryKey\";\n readonly table: string;\n readonly destructive: false;\n }\n | {\n /**\n * Drop a view present in the live database but absent from the target\n * schema (board #26). Ordered FIRST — postgres refuses dropping a column\n * a leftover view depends on (2BP01), so removed views must go before\n * the table/column changes they block. Destructive: the view definition\n * is not stored in the IR, so the drop cannot be reversed.\n */\n readonly kind: \"dropView\";\n /** View db name. */\n readonly table: string;\n readonly destructive: true;\n };\n\n/** One-line human description of a step (refusal messages, CLI output). */\nexport function describeStep(params: { step: MigrationStep }): string {\n const { step } = params;\n switch (step.kind) {\n case \"createEnum\":\n return `create enum \"${step.enumDef.dbName ?? step.enumDef.name}\"`;\n case \"dropEnum\":\n return `drop enum \"${step.enumName}\"`;\n case \"addEnumValue\":\n return `add value \"${step.value}\" to enum \"${step.enumName}\"`;\n case \"createTable\":\n return `create table \"${step.table}\"`;\n case \"dropTable\":\n return `drop table \"${step.table}\"`;\n case \"addColumn\":\n return `add column \"${step.table}\".\"${step.column.dbName ?? step.column.name}\"`;\n case \"dropColumn\":\n return `drop column \"${step.table}\".\"${step.column}\"`;\n case \"alterColumn\":\n return `alter column \"${step.table}\".\"${step.column}\" (${step.changes.join(\", \")})`;\n case \"createIndex\":\n return `create ${step.unique ? \"unique \" : \"\"}index \"${step.name}\" on \"${step.table}\"`;\n case \"dropIndex\":\n return `drop index \"${step.name}\"`;\n case \"addForeignKey\":\n return `add foreign key \"${step.constraintName}\" on \"${step.table}\"`;\n case \"dropForeignKey\":\n return `drop foreign key \"${step.constraintName}\" on \"${step.table}\"`;\n case \"createJoinTable\":\n return `create join table \"${step.table}\"`;\n case \"dropJoinTable\":\n return `drop join table \"${step.table}\"`;\n case \"addPrimaryKey\":\n return `add primary key on \"${step.table}\"`;\n case \"dropPrimaryKey\":\n return `drop primary key on \"${step.table}\"`;\n case \"dropView\":\n return `drop view \"${step.table}\"`;\n }\n}\n\n// ─── Runner shapes ────────────────────────────────────────────────\n\n/** A named migration: ordered SQL statements plus its aggregate destructiveness. */\nexport type MigrationFile = {\n readonly name: string;\n /** One SQL string per statement, in execution order. */\n readonly sql: readonly string[];\n /** True when any underlying step can lose data. */\n readonly destructive: boolean;\n /**\n * Reverse statements (`down.sql`), when the migration carries them.\n * Migrations generated before down-migration support have none —\n * `rollbackMigration` refuses those with a clear error.\n */\n readonly downSql?: readonly string[];\n};\n\n/** Result of `applyMigrations`. */\nexport type AppliedResult = {\n /** Migrations executed by this call, in order. */\n readonly applied: readonly string[];\n /** Migrations already recorded and verified, skipped. */\n readonly skipped: readonly string[];\n};\n\n/** Result of `migrationStatus`. */\nexport type MigrationStatus = {\n /** Recorded migrations whose checksum matches. */\n readonly applied: readonly string[];\n /** Migrations with no record yet. */\n readonly pending: readonly string[];\n /** Recorded migrations whose checksum no longer matches their SQL. */\n readonly mismatched: readonly string[];\n /**\n * Migrations whose rollback started but did not finish (mysql only — its\n * DDL is non-transactional, so `rollbackMigration` records per-statement\n * progress). Re-run the rollback to resume, or repair with\n * `resolveMigration`.\n */\n readonly rollingBack: readonly string[];\n};\n\n/** Result of `push`. */\nexport type PushResult = {\n /** The diff that was applied (empty = database already matched). */\n readonly steps: readonly MigrationStep[];\n /** The SQL statements that were executed, in order. */\n readonly applied: readonly string[];\n};\n",
|
|
6
|
-
"/**\n * IR-vs-IR schema differ → dialect-neutral migration steps.\n *\n * The contract that matters most: `diffSchemas({ from: introspect(push(X)),\n * to: X })` is EMPTY — both sides normalize through normalize.ts before\n * comparison, so representation differences (implicit list sides vs explicit\n * M2M fields, `@unique` vs `@@unique`, app-level defaults, cascade-action\n * defaults) never produce phantom steps and `db push` twice is a no-op.\n *\n * No rename detection (v1 parity): a renamed table/column diffs as drop +\n * create. Removing a value from a surviving enum throws\n * VIBE_UNSUPPORTED_CAPABILITY — postgres cannot drop enum values without a\n * manual type rebuild, and silence would be dialect dishonesty.\n */\n\nimport { isEnumType, unsupportedCapability } from \"@vibeorm/schema\";\nimport type { Dialect, EnumIR, SchemaIR } from \"@vibeorm/schema\";\nimport { resolveEnumValues } from \"./enum-values.ts\";\nimport { normalizeSchema } from \"./normalize.ts\";\nimport type { NormalizedSchema, NormalizedTable } from \"./normalize.ts\";\nimport { isScalarToArrayChange } from \"./postgres-types.ts\";\nimport type { AlterColumnAspect, MigrationStep } from \"./types.ts\";\n\n// ─── Ordered step buckets ─────────────────────────────────────────\n\n/**\n * Steps are emitted in dependency-safe buckets: view drops first of all (a\n * leftover view blocks dropping any column it references — postgres 2BP01,\n * board #26), enums next (columns reference the types), FK/index drops before\n * the objects they attach to disappear, table creates before the\n * FKs/indexes/join tables that need them, enum drops last (after every column\n * using the type is gone).\n */\ntype StepBuckets = {\n dropView: MigrationStep[];\n createEnum: MigrationStep[];\n addEnumValue: MigrationStep[];\n dropForeignKey: MigrationStep[];\n dropIndex: MigrationStep[];\n dropJoinTable: MigrationStep[];\n dropTable: MigrationStep[];\n createTable: MigrationStep[];\n addColumn: MigrationStep[];\n alterColumn: MigrationStep[];\n dropColumn: MigrationStep[];\n dropPrimaryKey: MigrationStep[];\n addPrimaryKey: MigrationStep[];\n createIndex: MigrationStep[];\n addForeignKey: MigrationStep[];\n createJoinTable: MigrationStep[];\n dropEnum: MigrationStep[];\n};\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/**\n * Diff two Schema IRs into an ordered list of dialect-neutral migration steps\n * that transform the `from` database shape into the `to` shape.\n *\n * `dialect` (default postgres) selects the comparison rules: sqlite/mysql\n * compare columns by physical type (see normalize.ts), refuse scalar-list\n * columns up front (no array types — VIBE_UNSUPPORTED_CAPABILITY naming the\n * model.field), skip standalone enum steps (their enums are inline: TEXT +\n * CHECK on sqlite, `ENUM(…)` on mysql — value changes flow through\n * `alterColumn`), and refuse enum-value REMOVAL at the column level.\n */\nexport function diffSchemas(params: {\n from: SchemaIR;\n to: SchemaIR;\n dialect?: Dialect;\n}): MigrationStep[] {\n const dialect = params.dialect ?? \"postgres\";\n if (dialect !== \"postgres\") refuseScalarListColumns({ schema: params.to, dialect });\n\n const from = normalizeSchema({ schema: params.from, dialect });\n const to = normalizeSchema({ schema: params.to, dialect });\n\n const buckets: StepBuckets = {\n dropView: [],\n createEnum: [],\n addEnumValue: [],\n dropForeignKey: [],\n dropIndex: [],\n dropJoinTable: [],\n dropTable: [],\n createTable: [],\n addColumn: [],\n alterColumn: [],\n dropColumn: [],\n dropPrimaryKey: [],\n addPrimaryKey: [],\n createIndex: [],\n addForeignKey: [],\n createJoinTable: [],\n dropEnum: [],\n };\n\n // Standalone enum objects only exist on postgres (CREATE TYPE); sqlite and\n // mysql inline their enums into the columns, so value changes surface as\n // alterColumn steps via the value-based type keys instead.\n if (dialect === \"postgres\") diffEnums({ from, to, buckets });\n diffViews({ from, to, buckets });\n diffJoinTables({ from, to, buckets });\n diffTables({ from, to, buckets, dialect });\n\n return [\n ...buckets.dropView,\n ...buckets.createEnum,\n ...buckets.addEnumValue,\n ...buckets.dropForeignKey,\n ...buckets.dropIndex,\n ...buckets.dropJoinTable,\n ...buckets.dropTable,\n ...buckets.createTable,\n ...buckets.addColumn,\n ...buckets.alterColumn,\n ...buckets.dropColumn,\n ...buckets.dropPrimaryKey,\n ...buckets.addPrimaryKey,\n ...buckets.createIndex,\n ...buckets.addForeignKey,\n ...buckets.createJoinTable,\n ...buckets.dropEnum,\n ];\n}\n\n// ─── Enums ────────────────────────────────────────────────────────\n\ntype NormalizedPair = {\n from: NormalizedSchema;\n to: NormalizedSchema;\n buckets: StepBuckets;\n};\n\n// ─── Capability guards ────────────────────────────────────────────\n\n/** sqlite/mysql have no array columns — refuse every scalar-list field loudly. */\nfunction refuseScalarListColumns(params: { schema: SchemaIR; dialect: Dialect }): void {\n const { schema, dialect } = params;\n for (const model of schema.models) {\n if (model.isView) continue;\n for (const field of model.fields) {\n if (!field.isList || field.isUnsupported === true) continue;\n throw unsupportedCapability({\n dialect,\n feature: `scalar list column \"${model.name}.${field.name}\"`,\n hint: `${dialect} has no array column type — model the list as a separate table or a ${\n dialect === \"mysql\" ? \"JSON\" : \"Json\"\n } column`,\n });\n }\n }\n}\n\nfunction diffEnums(params: NormalizedPair): void {\n const { from, to, buckets } = params;\n\n for (const [name, enumDef] of to.enums) {\n const previous = from.enums.get(name);\n if (previous === undefined) {\n buckets.createEnum.push({ kind: \"createEnum\", enumDef, destructive: false });\n continue;\n }\n\n const previousValues = new Set(previous.values);\n const currentValues = new Set(enumDef.values);\n for (const value of enumDef.values) {\n if (!previousValues.has(value)) {\n buckets.addEnumValue.push({ kind: \"addEnumValue\", enumName: name, value, destructive: false });\n }\n }\n for (const value of previous.values) {\n if (!currentValues.has(value)) {\n throw unsupportedCapability({\n dialect: \"postgres\",\n feature: `removing value \"${value}\" from enum \"${name}\"`,\n hint: \"postgres cannot drop enum values — recreate the type manually (create new type, ALTER COLUMN ... USING, drop old type)\",\n });\n }\n }\n }\n\n for (const [name] of from.enums) {\n if (!to.enums.has(name)) {\n buckets.dropEnum.push({ kind: \"dropEnum\", enumName: name, destructive: true });\n }\n }\n}\n\n// ─── Views (#26) ──────────────────────────────────────────\n\n/**\n * A view in `from` the target no longer declares gets a `dropView` step — a\n * leftover view otherwise blocks the column drops beneath it (postgres 2BP01)\n * and `push` fails on a schema the user considers valid. Views only in `to`\n * emit nothing: view CREATION stays out-of-band in this wave (see #11), and\n * whatever design lands there must keep this drop rule.\n */\nfunction diffViews(params: NormalizedPair): void {\n const { from, to, buckets } = params;\n for (const [name] of from.views) {\n if (!to.views.has(name)) {\n buckets.dropView.push({ kind: \"dropView\", table: name, destructive: true });\n }\n }\n}\n\n// ─── Join tables ──────────────────────────────────────────────────\n\nfunction diffJoinTables(params: NormalizedPair): void {\n const { from, to, buckets } = params;\n\n for (const [table, joinTable] of to.joinTables) {\n if (!from.joinTables.has(table)) {\n buckets.createJoinTable.push({\n kind: \"createJoinTable\",\n table,\n a: joinTable.a,\n b: joinTable.b,\n destructive: false,\n });\n }\n }\n for (const [table] of from.joinTables) {\n if (!to.joinTables.has(table)) {\n buckets.dropJoinTable.push({ kind: \"dropJoinTable\", table, destructive: true });\n }\n }\n}\n\n// ─── Tables ───────────────────────────────────────────────────────\n\nfunction diffTables(params: NormalizedPair & { dialect: Dialect }): void {\n const { from, to, buckets, dialect } = params;\n\n for (const [name, table] of to.tables) {\n const previous = from.tables.get(name);\n if (previous === undefined) createWholeTable({ table, buckets });\n else\n diffOneTable({\n previous,\n current: table,\n buckets,\n dialect,\n fromEnums: from.enums,\n toEnums: to.enums,\n });\n }\n\n // FKs on a dropped table vanish with it (DROP TABLE ... CASCADE); FKs on\n // SURVIVING tables pointing here are handled by those tables' own diffs.\n for (const [name] of from.tables) {\n if (to.tables.has(name)) continue;\n buckets.dropTable.push({ kind: \"dropTable\", table: name, destructive: true });\n }\n}\n\nfunction createWholeTable(params: { table: NormalizedTable; buckets: StepBuckets }): void {\n const { table, buckets } = params;\n\n buckets.createTable.push({\n kind: \"createTable\",\n table: table.table,\n columns: [...table.columns.values()].map((column) => column.field),\n primaryKey: table.pk,\n destructive: false,\n });\n\n for (const index of table.indexes.values()) {\n buckets.createIndex.push({\n kind: \"createIndex\",\n table: table.table,\n name: index.name,\n indexKind: index.kind,\n unique: index.unique,\n columns: index.columns,\n ...(index.where === undefined ? {} : { where: index.where }),\n destructive: false,\n });\n }\n\n for (const fk of table.fks.values()) {\n buckets.addForeignKey.push({\n kind: \"addForeignKey\",\n table: table.table,\n constraintName: fk.constraintName,\n columns: fk.columns,\n refTable: fk.refTable,\n refColumns: fk.refColumns,\n onDelete: fk.onDelete,\n onUpdate: fk.onUpdate,\n destructive: false,\n });\n }\n}\n\nfunction diffOneTable(params: {\n previous: NormalizedTable;\n current: NormalizedTable;\n buckets: StepBuckets;\n dialect: Dialect;\n fromEnums: ReadonlyMap<string, EnumIR>;\n toEnums: ReadonlyMap<string, EnumIR>;\n}): void {\n const { previous, current, buckets, dialect, fromEnums, toEnums } = params;\n const table = current.table;\n\n // Columns.\n for (const [name, column] of current.columns) {\n const before = previous.columns.get(name);\n if (before === undefined) {\n buckets.addColumn.push({ kind: \"addColumn\", table, column: column.field, destructive: false });\n continue;\n }\n\n const changes: AlterColumnAspect[] = [];\n if (before.typeKey !== column.typeKey) changes.push(\"type\");\n if (before.nullable !== column.nullable) changes.push(\"nullability\");\n if (before.defaultKey !== column.defaultKey) changes.push(\"default\");\n if (changes.length === 0) continue;\n\n let narrowingType =\n changes.includes(\"type\") &&\n !isScalarToArrayChange({ from: before.field, to: column.field });\n\n // Inline-enum dialects: an enum→enum type change is a value-list change.\n // Pure widening (values only added) is safe and non-destructive; REMOVING\n // a value is refused outright — existing rows may hold it, and silence\n // would be dialect dishonesty.\n if (\n dialect !== \"postgres\" &&\n changes.includes(\"type\") &&\n isEnumType(before.field.type) &&\n isEnumType(column.field.type)\n ) {\n const fromValues = resolveEnumValues({ name: before.field.type.enum, enums: fromEnums });\n const toValues = resolveEnumValues({ name: column.field.type.enum, enums: toEnums });\n if (fromValues !== undefined && toValues !== undefined) {\n const removed = fromValues.filter((value) => !toValues.includes(value));\n if (removed.length > 0) {\n throw unsupportedCapability({\n dialect,\n feature: `removing value(s) ${removed.map((value) => `\"${value}\"`).join(\", \")} from enum column \"${table}\".\"${name}\"`,\n hint: \"migrate the stored values away first, then recreate the column with the narrower enum\",\n });\n }\n narrowingType = false; // Pure widening — no data can be lost.\n }\n }\n\n buckets.alterColumn.push({\n kind: \"alterColumn\",\n table,\n column: name,\n from: before.field,\n to: column.field,\n changes,\n destructive: narrowingType,\n });\n }\n\n for (const [name] of previous.columns) {\n if (!current.columns.has(name)) {\n buckets.dropColumn.push({ kind: \"dropColumn\", table, column: name, destructive: true });\n }\n }\n\n // Primary key.\n const pkBefore = previous.pk.join(\",\");\n const pkAfter = current.pk.join(\",\");\n if (pkBefore !== pkAfter) {\n if (previous.pk.length > 0) {\n buckets.dropPrimaryKey.push({ kind: \"dropPrimaryKey\", table, destructive: false });\n }\n if (current.pk.length > 0) {\n buckets.addPrimaryKey.push({\n kind: \"addPrimaryKey\",\n table,\n columns: current.pk,\n destructive: false,\n });\n }\n }\n\n // Indexes (uniques included — normalize.ts already merged @unique fields in).\n for (const [key, index] of current.indexes) {\n if (previous.indexes.has(key)) continue;\n buckets.createIndex.push({\n kind: \"createIndex\",\n table,\n name: index.name,\n indexKind: index.kind,\n unique: index.unique,\n columns: index.columns,\n ...(index.where === undefined ? {} : { where: index.where }),\n destructive: false,\n });\n }\n for (const [key, index] of previous.indexes) {\n if (current.indexes.has(key)) continue;\n buckets.dropIndex.push({ kind: \"dropIndex\", name: index.name, table, destructive: false });\n }\n\n // Foreign keys. Cascade-action drift needs DROP + ADD — postgres has no\n // ALTER CONSTRAINT ... ON DELETE for FKs (LEARNINGS).\n for (const [key, fk] of current.fks) {\n const before = previous.fks.get(key);\n if (before === undefined) {\n buckets.addForeignKey.push({\n kind: \"addForeignKey\",\n table,\n constraintName: fk.constraintName,\n columns: fk.columns,\n refTable: fk.refTable,\n refColumns: fk.refColumns,\n onDelete: fk.onDelete,\n onUpdate: fk.onUpdate,\n destructive: false,\n });\n continue;\n }\n if (before.onDelete !== fk.onDelete || before.onUpdate !== fk.onUpdate) {\n buckets.dropForeignKey.push({\n kind: \"dropForeignKey\",\n table,\n constraintName: before.constraintName,\n destructive: false,\n });\n buckets.addForeignKey.push({\n kind: \"addForeignKey\",\n table,\n constraintName: fk.constraintName,\n columns: fk.columns,\n refTable: fk.refTable,\n refColumns: fk.refColumns,\n onDelete: fk.onDelete,\n onUpdate: fk.onUpdate,\n destructive: false,\n });\n }\n }\n for (const [key, fk] of previous.fks) {\n if (current.fks.has(key)) continue;\n buckets.dropForeignKey.push({\n kind: \"dropForeignKey\",\n table,\n constraintName: fk.constraintName,\n destructive: false,\n });\n }\n}\n",
|
|
5
|
+
"/**\n * Public types of @vibeorm/migrate: the executor contract, the dialect-neutral\n * migration step model, and the runner's file/result shapes.\n *\n * Steps carry Schema-IR fragments (FieldIR, EnumIR) — never SQL text. SQL is\n * produced exclusively by the per-dialect renderers (ddl-postgres.ts), so every\n * SQL-text decision stays reviewable in one place (constitution rule 3/4).\n */\n\nimport type { CascadeAction, CheckIR, EnumIR, FieldIR } from \"@vibeorm/schema\";\n\n// ─── Executor ─────────────────────────────────────────────────────\n\n/**\n * Minimal SQL execution contract the migrate engine runs on. Structurally\n * identical to @vibeorm/runtime's `SqlExecutor` (its `toSqlExecutor` bridges a\n * DatabaseAdapter to this shape) — declared here so the dependency direction\n * stays schema ← sql ← migrate.\n *\n * SESSION AFFINITY: the migrate engine issues session-scoped statements\n * through this contract (BEGIN/COMMIT, `PRAGMA foreign_keys`, advisory locks\n * `pg_advisory_lock` / `GET_LOCK`), so every call MUST hit the same database\n * session. Single-connection adapters (pglite, sqlite) satisfy this by\n * construction; pool-backed executors must pin one connection for the whole\n * migrate operation.\n */\nexport type SqlExecutor = (params: {\n text: string;\n values?: unknown[];\n}) => Promise<Record<string, unknown>[]>;\n\n// ─── Step building blocks ─────────────────────────────────────────\n\n/** Which aspects of a column an `alterColumn` step changes. */\nexport type AlterColumnAspect = \"type\" | \"nullability\" | \"default\";\n\n/** One column of an index, with its sort direction. */\nexport type IndexColumn = {\n readonly name: string;\n readonly desc: boolean;\n /**\n * The field is a Decimal (SQLITE-2, SQL review round 2). Inert everywhere\n * except the sqlite DDL renderer: Decimal stores as TEXT there and every\n * compare/order site reads `CAST(col AS REAL)` (B4), which a plain-column\n * index can never serve (EQP-proven SCAN) — sqlite renders an EXPRESSION\n * index over the same cast instead. Not part of the index comparison key:\n * both sides compare by column name + direction.\n */\n readonly decimal?: boolean;\n};\n\n/** One side of an implicit many-to-many join table. */\nexport type JoinTableEnd = {\n /** Referenced table (db name). */\n readonly table: string;\n /** Referenced primary-key column (db name). */\n readonly column: string;\n /** The referenced primary-key field — its type renders the join column's type. */\n readonly field: FieldIR;\n};\n\n// ─── Steps ────────────────────────────────────────────────────────\n\n/**\n * A dialect-neutral migration step produced by `diffSchemas`. `destructive`\n * marks steps that can lose data (dropTable / dropJoinTable / dropColumn /\n * dropEnum / narrowing type changes) — `push` refuses them without\n * `acceptDataLoss`, and `generateMigration` surfaces the flag.\n */\nexport type MigrationStep =\n | {\n readonly kind: \"createEnum\";\n readonly enumDef: EnumIR;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropEnum\";\n readonly enumName: string;\n readonly destructive: true;\n }\n | {\n readonly kind: \"addEnumValue\";\n readonly enumName: string;\n readonly value: string;\n readonly destructive: false;\n }\n | {\n readonly kind: \"createTable\";\n readonly table: string;\n readonly columns: readonly FieldIR[];\n /** Primary-key column db names (empty = no PK). */\n readonly primaryKey: readonly string[];\n /** Named CHECK constraints, rendered into the CREATE TABLE. */\n readonly checks?: readonly CheckIR[];\n readonly destructive: false;\n }\n | {\n readonly kind: \"addCheck\";\n readonly table: string;\n readonly name: string;\n /** Raw SQL expression, rendered verbatim. */\n readonly expression: string;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropCheck\";\n readonly table: string;\n readonly name: string;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropTable\";\n readonly table: string;\n readonly destructive: true;\n }\n | {\n readonly kind: \"addColumn\";\n readonly table: string;\n readonly column: FieldIR;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropColumn\";\n readonly table: string;\n readonly column: string;\n readonly destructive: true;\n }\n | {\n readonly kind: \"alterColumn\";\n readonly table: string;\n /** Column db name. */\n readonly column: string;\n readonly from: FieldIR;\n readonly to: FieldIR;\n readonly changes: readonly AlterColumnAspect[];\n readonly destructive: boolean;\n }\n | {\n readonly kind: \"createIndex\";\n readonly table: string;\n readonly name: string;\n /** IR index kind (\"btree\", \"gin\", …) — `unique` indexes are always btree. */\n readonly indexKind: string;\n readonly unique: boolean;\n readonly columns: readonly IndexColumn[];\n /** Partial-index predicate, raw SQL. */\n readonly where?: string;\n /** `UNIQUE NULLS NOT DISTINCT` (postgres 15+; sqlite/mysql renderers refuse). */\n readonly nullsNotDistinct?: boolean;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropIndex\";\n readonly name: string;\n /**\n * Table the index belongs to. Optional for postgres/sqlite (their DROP\n * INDEX is schema-global) but REQUIRED by the mysql renderer\n * (`DROP INDEX … ON table`); the differ always fills it.\n */\n readonly table?: string;\n readonly destructive: false;\n }\n | {\n readonly kind: \"addForeignKey\";\n readonly table: string;\n readonly constraintName: string;\n readonly columns: readonly string[];\n readonly refTable: string;\n readonly refColumns: readonly string[];\n readonly onDelete: CascadeAction;\n readonly onUpdate: CascadeAction;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropForeignKey\";\n readonly table: string;\n readonly constraintName: string;\n readonly destructive: false;\n }\n | {\n readonly kind: \"createJoinTable\";\n readonly table: string;\n readonly a: JoinTableEnd;\n readonly b: JoinTableEnd;\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropJoinTable\";\n readonly table: string;\n readonly destructive: true;\n }\n | {\n readonly kind: \"addPrimaryKey\";\n readonly table: string;\n readonly columns: readonly string[];\n readonly destructive: false;\n }\n | {\n readonly kind: \"dropPrimaryKey\";\n readonly table: string;\n readonly destructive: false;\n }\n | {\n /**\n * Drop a view present in the live database but absent from the target\n * schema (board #26). Ordered FIRST — postgres refuses dropping a column\n * a leftover view depends on (2BP01), so removed views must go before\n * the table/column changes they block. Destructive: the view definition\n * is not stored in the IR, so the drop cannot be reversed.\n */\n readonly kind: \"dropView\";\n /** View db name. */\n readonly table: string;\n readonly destructive: true;\n };\n\n/** One-line human description of a step (refusal messages, CLI output). */\nexport function describeStep(params: { step: MigrationStep }): string {\n const { step } = params;\n switch (step.kind) {\n case \"createEnum\":\n return `create enum \"${step.enumDef.dbName ?? step.enumDef.name}\"`;\n case \"dropEnum\":\n return `drop enum \"${step.enumName}\"`;\n case \"addEnumValue\":\n return `add value \"${step.value}\" to enum \"${step.enumName}\"`;\n case \"createTable\":\n return `create table \"${step.table}\"`;\n case \"dropTable\":\n return `drop table \"${step.table}\"`;\n case \"addColumn\":\n return `add column \"${step.table}\".\"${step.column.dbName ?? step.column.name}\"`;\n case \"dropColumn\":\n return `drop column \"${step.table}\".\"${step.column}\"`;\n case \"alterColumn\":\n return `alter column \"${step.table}\".\"${step.column}\" (${step.changes.join(\", \")})`;\n case \"createIndex\":\n return `create ${step.unique ? \"unique \" : \"\"}index \"${step.name}\" on \"${step.table}\"`;\n case \"addCheck\":\n return `add check \"${step.name}\" on \"${step.table}\"`;\n case \"dropCheck\":\n return `drop check \"${step.name}\" on \"${step.table}\"`;\n case \"dropIndex\":\n return `drop index \"${step.name}\"`;\n case \"addForeignKey\":\n return `add foreign key \"${step.constraintName}\" on \"${step.table}\"`;\n case \"dropForeignKey\":\n return `drop foreign key \"${step.constraintName}\" on \"${step.table}\"`;\n case \"createJoinTable\":\n return `create join table \"${step.table}\"`;\n case \"dropJoinTable\":\n return `drop join table \"${step.table}\"`;\n case \"addPrimaryKey\":\n return `add primary key on \"${step.table}\"`;\n case \"dropPrimaryKey\":\n return `drop primary key on \"${step.table}\"`;\n case \"dropView\":\n return `drop view \"${step.table}\"`;\n }\n}\n\n// ─── Runner shapes ────────────────────────────────────────────────\n\n/** A named migration: ordered SQL statements plus its aggregate destructiveness. */\nexport type MigrationFile = {\n readonly name: string;\n /** One SQL string per statement, in execution order. */\n readonly sql: readonly string[];\n /** True when any underlying step can lose data. */\n readonly destructive: boolean;\n /**\n * Reverse statements (`down.sql`), when the migration carries them.\n * Migrations generated before down-migration support have none —\n * `rollbackMigration` refuses those with a clear error.\n */\n readonly downSql?: readonly string[];\n};\n\n/** Result of `applyMigrations`. */\nexport type AppliedResult = {\n /** Migrations executed by this call, in order. */\n readonly applied: readonly string[];\n /** Migrations already recorded and verified, skipped. */\n readonly skipped: readonly string[];\n};\n\n/** Result of `migrationStatus`. */\nexport type MigrationStatus = {\n /** Recorded migrations whose checksum matches. */\n readonly applied: readonly string[];\n /** Migrations with no record yet. */\n readonly pending: readonly string[];\n /** Recorded migrations whose checksum no longer matches their SQL. */\n readonly mismatched: readonly string[];\n /**\n * Migrations whose rollback started but did not finish (mysql only — its\n * DDL is non-transactional, so `rollbackMigration` records per-statement\n * progress). Re-run the rollback to resume, or repair with\n * `resolveMigration`.\n */\n readonly rollingBack: readonly string[];\n};\n\n/** Result of `push`. */\nexport type PushResult = {\n /** The diff that was applied (empty = database already matched). */\n readonly steps: readonly MigrationStep[];\n /** The SQL statements that were executed, in order. */\n readonly applied: readonly string[];\n};\n",
|
|
6
|
+
"/**\n * IR-vs-IR schema differ → dialect-neutral migration steps.\n *\n * The contract that matters most: `diffSchemas({ from: introspect(push(X)),\n * to: X })` is EMPTY — both sides normalize through normalize.ts before\n * comparison, so representation differences (implicit list sides vs explicit\n * M2M fields, `@unique` vs `@@unique`, app-level defaults, cascade-action\n * defaults) never produce phantom steps and `db push` twice is a no-op.\n *\n * No rename detection (v1 parity): a renamed table/column diffs as drop +\n * create. Removing a value from a surviving enum throws\n * VIBE_UNSUPPORTED_CAPABILITY — postgres cannot drop enum values without a\n * manual type rebuild, and silence would be dialect dishonesty.\n */\n\nimport { isEnumType, unsupportedCapability } from \"@vibeorm/schema\";\nimport type { Dialect, EnumIR, SchemaIR } from \"@vibeorm/schema\";\nimport { resolveEnumValues } from \"./enum-values.ts\";\nimport { normalizeSchema } from \"./normalize.ts\";\nimport type { NormalizedSchema, NormalizedTable } from \"./normalize.ts\";\nimport { isScalarToArrayChange } from \"./postgres-types.ts\";\nimport type { AlterColumnAspect, MigrationStep } from \"./types.ts\";\n\n// ─── Ordered step buckets ─────────────────────────────────────────\n\n/**\n * Steps are emitted in dependency-safe buckets: view drops first of all (a\n * leftover view blocks dropping any column it references — postgres 2BP01,\n * board #26), enums next (columns reference the types), FK/index drops before\n * the objects they attach to disappear, table creates before the\n * FKs/indexes/join tables that need them, enum drops last (after every column\n * using the type is gone).\n */\ntype StepBuckets = {\n dropView: MigrationStep[];\n createEnum: MigrationStep[];\n addEnumValue: MigrationStep[];\n dropForeignKey: MigrationStep[];\n dropIndex: MigrationStep[];\n dropJoinTable: MigrationStep[];\n dropTable: MigrationStep[];\n createTable: MigrationStep[];\n addColumn: MigrationStep[];\n alterColumn: MigrationStep[];\n dropColumn: MigrationStep[];\n dropPrimaryKey: MigrationStep[];\n addPrimaryKey: MigrationStep[];\n dropCheck: MigrationStep[];\n addCheck: MigrationStep[];\n createIndex: MigrationStep[];\n addForeignKey: MigrationStep[];\n createJoinTable: MigrationStep[];\n dropEnum: MigrationStep[];\n};\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/**\n * Diff two Schema IRs into an ordered list of dialect-neutral migration steps\n * that transform the `from` database shape into the `to` shape.\n *\n * `dialect` (default postgres) selects the comparison rules: sqlite/mysql\n * compare columns by physical type (see normalize.ts), refuse scalar-list\n * columns up front (no array types — VIBE_UNSUPPORTED_CAPABILITY naming the\n * model.field), skip standalone enum steps (their enums are inline: TEXT +\n * CHECK on sqlite, `ENUM(…)` on mysql — value changes flow through\n * `alterColumn`), and refuse enum-value REMOVAL at the column level.\n */\nexport function diffSchemas(params: {\n from: SchemaIR;\n to: SchemaIR;\n dialect?: Dialect;\n}): MigrationStep[] {\n const dialect = params.dialect ?? \"postgres\";\n if (dialect !== \"postgres\") refuseScalarListColumns({ schema: params.to, dialect });\n\n const from = normalizeSchema({ schema: params.from, dialect });\n const to = normalizeSchema({ schema: params.to, dialect });\n\n const buckets: StepBuckets = {\n dropView: [],\n createEnum: [],\n addEnumValue: [],\n dropForeignKey: [],\n dropIndex: [],\n dropJoinTable: [],\n dropTable: [],\n createTable: [],\n addColumn: [],\n alterColumn: [],\n dropColumn: [],\n dropPrimaryKey: [],\n addPrimaryKey: [],\n dropCheck: [],\n addCheck: [],\n createIndex: [],\n addForeignKey: [],\n createJoinTable: [],\n dropEnum: [],\n };\n\n // Standalone enum objects only exist on postgres (CREATE TYPE); sqlite and\n // mysql inline their enums into the columns, so value changes surface as\n // alterColumn steps via the value-based type keys instead.\n if (dialect === \"postgres\") diffEnums({ from, to, buckets });\n diffViews({ from, to, buckets });\n diffJoinTables({ from, to, buckets });\n diffTables({ from, to, buckets, dialect });\n\n return [\n ...buckets.dropView,\n ...buckets.createEnum,\n ...buckets.addEnumValue,\n ...buckets.dropForeignKey,\n ...buckets.dropIndex,\n ...buckets.dropJoinTable,\n ...buckets.dropTable,\n ...buckets.createTable,\n ...buckets.addColumn,\n ...buckets.alterColumn,\n ...buckets.dropColumn,\n ...buckets.dropPrimaryKey,\n ...buckets.addPrimaryKey,\n ...buckets.dropCheck,\n ...buckets.addCheck,\n ...buckets.createIndex,\n ...buckets.addForeignKey,\n ...buckets.createJoinTable,\n ...buckets.dropEnum,\n ];\n}\n\n// ─── Enums ────────────────────────────────────────────────────────\n\ntype NormalizedPair = {\n from: NormalizedSchema;\n to: NormalizedSchema;\n buckets: StepBuckets;\n};\n\n// ─── Capability guards ────────────────────────────────────────────\n\n/** sqlite/mysql have no array columns — refuse every scalar-list field loudly. */\nfunction refuseScalarListColumns(params: { schema: SchemaIR; dialect: Dialect }): void {\n const { schema, dialect } = params;\n for (const model of schema.models) {\n if (model.isView) continue;\n for (const field of model.fields) {\n if (!field.isList || field.isUnsupported === true) continue;\n throw unsupportedCapability({\n dialect,\n feature: `scalar list column \"${model.name}.${field.name}\"`,\n hint: `${dialect} has no array column type — model the list as a separate table or a ${\n dialect === \"mysql\" ? \"JSON\" : \"Json\"\n } column`,\n });\n }\n }\n}\n\nfunction diffEnums(params: NormalizedPair): void {\n const { from, to, buckets } = params;\n\n for (const [name, enumDef] of to.enums) {\n const previous = from.enums.get(name);\n if (previous === undefined) {\n buckets.createEnum.push({ kind: \"createEnum\", enumDef, destructive: false });\n continue;\n }\n\n const previousValues = new Set(previous.values);\n const currentValues = new Set(enumDef.values);\n for (const value of enumDef.values) {\n if (!previousValues.has(value)) {\n buckets.addEnumValue.push({ kind: \"addEnumValue\", enumName: name, value, destructive: false });\n }\n }\n for (const value of previous.values) {\n if (!currentValues.has(value)) {\n throw unsupportedCapability({\n dialect: \"postgres\",\n feature: `removing value \"${value}\" from enum \"${name}\"`,\n hint: \"postgres cannot drop enum values — recreate the type manually (create new type, ALTER COLUMN ... USING, drop old type)\",\n });\n }\n }\n }\n\n for (const [name] of from.enums) {\n if (!to.enums.has(name)) {\n buckets.dropEnum.push({ kind: \"dropEnum\", enumName: name, destructive: true });\n }\n }\n}\n\n// ─── Views (#26) ──────────────────────────────────────────\n\n/**\n * A view in `from` the target no longer declares gets a `dropView` step — a\n * leftover view otherwise blocks the column drops beneath it (postgres 2BP01)\n * and `push` fails on a schema the user considers valid. Views only in `to`\n * emit nothing: view CREATION stays out-of-band in this wave (see #11), and\n * whatever design lands there must keep this drop rule.\n */\nfunction diffViews(params: NormalizedPair): void {\n const { from, to, buckets } = params;\n for (const [name] of from.views) {\n if (!to.views.has(name)) {\n buckets.dropView.push({ kind: \"dropView\", table: name, destructive: true });\n }\n }\n}\n\n// ─── Join tables ──────────────────────────────────────────────────\n\nfunction diffJoinTables(params: NormalizedPair): void {\n const { from, to, buckets } = params;\n\n for (const [table, joinTable] of to.joinTables) {\n if (!from.joinTables.has(table)) {\n buckets.createJoinTable.push({\n kind: \"createJoinTable\",\n table,\n a: joinTable.a,\n b: joinTable.b,\n destructive: false,\n });\n }\n }\n for (const [table] of from.joinTables) {\n if (!to.joinTables.has(table)) {\n buckets.dropJoinTable.push({ kind: \"dropJoinTable\", table, destructive: true });\n }\n }\n}\n\n// ─── Tables ───────────────────────────────────────────────────────\n\nfunction diffTables(params: NormalizedPair & { dialect: Dialect }): void {\n const { from, to, buckets, dialect } = params;\n\n for (const [name, table] of to.tables) {\n const previous = from.tables.get(name);\n if (previous === undefined) createWholeTable({ table, buckets });\n else\n diffOneTable({\n previous,\n current: table,\n buckets,\n dialect,\n fromEnums: from.enums,\n toEnums: to.enums,\n });\n }\n\n // FKs on a dropped table vanish with it (DROP TABLE ... CASCADE); FKs on\n // SURVIVING tables pointing here are handled by those tables' own diffs.\n for (const [name] of from.tables) {\n if (to.tables.has(name)) continue;\n buckets.dropTable.push({ kind: \"dropTable\", table: name, destructive: true });\n }\n}\n\nfunction createWholeTable(params: { table: NormalizedTable; buckets: StepBuckets }): void {\n const { table, buckets } = params;\n\n buckets.createTable.push({\n kind: \"createTable\",\n table: table.table,\n columns: [...table.columns.values()].map((column) => column.field),\n primaryKey: table.pk,\n checks: [...table.checks].map(([name, expression]) => ({ name, expression })),\n destructive: false,\n });\n\n for (const index of table.indexes.values()) {\n buckets.createIndex.push({\n kind: \"createIndex\",\n table: table.table,\n name: index.name,\n indexKind: index.kind,\n unique: index.unique,\n columns: index.columns,\n ...(index.where === undefined ? {} : { where: index.where }),\n ...(index.nullsNotDistinct === true ? { nullsNotDistinct: true } : {}),\n destructive: false,\n });\n }\n\n for (const fk of table.fks.values()) {\n buckets.addForeignKey.push({\n kind: \"addForeignKey\",\n table: table.table,\n constraintName: fk.constraintName,\n columns: fk.columns,\n refTable: fk.refTable,\n refColumns: fk.refColumns,\n onDelete: fk.onDelete,\n onUpdate: fk.onUpdate,\n destructive: false,\n });\n }\n}\n\nfunction diffOneTable(params: {\n previous: NormalizedTable;\n current: NormalizedTable;\n buckets: StepBuckets;\n dialect: Dialect;\n fromEnums: ReadonlyMap<string, EnumIR>;\n toEnums: ReadonlyMap<string, EnumIR>;\n}): void {\n const { previous, current, buckets, dialect, fromEnums, toEnums } = params;\n const table = current.table;\n\n // Columns.\n for (const [name, column] of current.columns) {\n const before = previous.columns.get(name);\n if (before === undefined) {\n buckets.addColumn.push({ kind: \"addColumn\", table, column: column.field, destructive: false });\n continue;\n }\n\n const changes: AlterColumnAspect[] = [];\n if (before.typeKey !== column.typeKey) changes.push(\"type\");\n if (before.nullable !== column.nullable) changes.push(\"nullability\");\n if (before.defaultKey !== column.defaultKey) changes.push(\"default\");\n if (changes.length === 0) continue;\n\n let narrowingType =\n changes.includes(\"type\") &&\n !isScalarToArrayChange({ from: before.field, to: column.field });\n\n // Inline-enum dialects: an enum→enum type change is a value-list change.\n // Pure widening (values only added) is safe and non-destructive; REMOVING\n // a value is refused outright — existing rows may hold it, and silence\n // would be dialect dishonesty.\n if (\n dialect !== \"postgres\" &&\n changes.includes(\"type\") &&\n isEnumType(before.field.type) &&\n isEnumType(column.field.type)\n ) {\n const fromValues = resolveEnumValues({ name: before.field.type.enum, enums: fromEnums });\n const toValues = resolveEnumValues({ name: column.field.type.enum, enums: toEnums });\n if (fromValues !== undefined && toValues !== undefined) {\n const removed = fromValues.filter((value) => !toValues.includes(value));\n if (removed.length > 0) {\n throw unsupportedCapability({\n dialect,\n feature: `removing value(s) ${removed.map((value) => `\"${value}\"`).join(\", \")} from enum column \"${table}\".\"${name}\"`,\n hint: \"migrate the stored values away first, then recreate the column with the narrower enum\",\n });\n }\n narrowingType = false; // Pure widening — no data can be lost.\n }\n }\n\n buckets.alterColumn.push({\n kind: \"alterColumn\",\n table,\n column: name,\n from: before.field,\n to: column.field,\n changes,\n destructive: narrowingType,\n });\n }\n\n for (const [name] of previous.columns) {\n if (!current.columns.has(name)) {\n buckets.dropColumn.push({ kind: \"dropColumn\", table, column: name, destructive: true });\n }\n }\n\n // Primary key.\n const pkBefore = previous.pk.join(\",\");\n const pkAfter = current.pk.join(\",\");\n if (pkBefore !== pkAfter) {\n if (previous.pk.length > 0) {\n buckets.dropPrimaryKey.push({ kind: \"dropPrimaryKey\", table, destructive: false });\n }\n if (current.pk.length > 0) {\n buckets.addPrimaryKey.push({\n kind: \"addPrimaryKey\",\n table,\n columns: current.pk,\n destructive: false,\n });\n }\n }\n\n // CHECK constraints — NAME-keyed: engines re-serialize expressions on\n // introspection, so text comparison would churn forever; an expression\n // change is expressed as a rename (drop old name + add new).\n for (const [name, expression] of current.checks) {\n if (previous.checks.has(name)) continue;\n buckets.addCheck.push({ kind: \"addCheck\", table, name, expression, destructive: false });\n }\n for (const [name] of previous.checks) {\n if (current.checks.has(name)) continue;\n buckets.dropCheck.push({ kind: \"dropCheck\", table, name, destructive: false });\n }\n\n // Indexes (uniques included — normalize.ts already merged @unique fields in).\n for (const [key, index] of current.indexes) {\n if (previous.indexes.has(key)) continue;\n buckets.createIndex.push({\n kind: \"createIndex\",\n table,\n name: index.name,\n indexKind: index.kind,\n unique: index.unique,\n columns: index.columns,\n ...(index.where === undefined ? {} : { where: index.where }),\n ...(index.nullsNotDistinct === true ? { nullsNotDistinct: true } : {}),\n destructive: false,\n });\n }\n for (const [key, index] of previous.indexes) {\n if (current.indexes.has(key)) continue;\n buckets.dropIndex.push({ kind: \"dropIndex\", name: index.name, table, destructive: false });\n }\n\n // Foreign keys. Cascade-action drift needs DROP + ADD — postgres has no\n // ALTER CONSTRAINT ... ON DELETE for FKs (LEARNINGS).\n for (const [key, fk] of current.fks) {\n const before = previous.fks.get(key);\n if (before === undefined) {\n buckets.addForeignKey.push({\n kind: \"addForeignKey\",\n table,\n constraintName: fk.constraintName,\n columns: fk.columns,\n refTable: fk.refTable,\n refColumns: fk.refColumns,\n onDelete: fk.onDelete,\n onUpdate: fk.onUpdate,\n destructive: false,\n });\n continue;\n }\n if (before.onDelete !== fk.onDelete || before.onUpdate !== fk.onUpdate) {\n buckets.dropForeignKey.push({\n kind: \"dropForeignKey\",\n table,\n constraintName: before.constraintName,\n destructive: false,\n });\n buckets.addForeignKey.push({\n kind: \"addForeignKey\",\n table,\n constraintName: fk.constraintName,\n columns: fk.columns,\n refTable: fk.refTable,\n refColumns: fk.refColumns,\n onDelete: fk.onDelete,\n onUpdate: fk.onUpdate,\n destructive: false,\n });\n }\n }\n for (const [key, fk] of previous.fks) {\n if (current.fks.has(key)) continue;\n buckets.dropForeignKey.push({\n kind: \"dropForeignKey\",\n table,\n constraintName: fk.constraintName,\n destructive: false,\n });\n }\n}\n",
|
|
7
7
|
"/**\n * Enum-value resolution shared by the sqlite/mysql type mappers.\n *\n * On dialects without named enum types (sqlite: TEXT + CHECK, mysql: inline\n * `ENUM(...)`) the enum's NAME does not survive in the database — only its\n * VALUES do. Column comparison keys and DDL rendering therefore resolve a\n * field's enum reference to its value list; the name is presentation only.\n */\n\nimport type { EnumIR } from \"@vibeorm/schema\";\n\n/**\n * Resolve an enum name to its values. The map is keyed by db name\n * (`dbName ?? name`, the normalize.ts convention); a schema-side reference by\n * IR name falls back to a scan so both key styles resolve.\n */\nexport function resolveEnumValues(params: {\n name: string;\n enums: ReadonlyMap<string, EnumIR>;\n}): readonly string[] | undefined {\n const { name, enums } = params;\n const direct = enums.get(name);\n if (direct !== undefined) return direct.values;\n for (const enumDef of enums.values()) {\n if (enumDef.name === name) return enumDef.values;\n }\n return undefined;\n}\n",
|
|
8
|
-
"/**\n * Schema-IR normalization for diffing.\n *\n * Both sides of a diff (a parsed/DSL schema and an introspected one) collapse\n * into the same normalized shape, so representation differences never produce\n * phantom steps. The normalizations, each pinned by a differ test:\n *\n * - `@unique` on a field and a `kind: \"unique\"` model index are the same\n * unique index (the database stores both identically).\n * - A single `@id` field and a single-field `@@id` are the same primary key.\n * - Field names resolve to db names (`@map` / `@@map`) everywhere.\n * - FK cascade actions resolve Prisma's defaults (required → Restrict,\n * optional → SetNull, onUpdate → Cascade) before comparing.\n * - App-level defaults (uuid/cuid/nanoid/ulid) compare as \"no database\n * default\"; `isUpdatedAt` is app-level and ignored entirely.\n * - Implicit M2M pairs collapse to their join table regardless of whether the\n * sides are parser `manyToMany` fields or introspected unnamed `oneToMany`\n * list sides (structural detection, LEARNINGS).\n * - Views never join the table diff (migrate does not manage view DDL in this\n * wave) but ARE collected by db name, so the differ can emit DROP VIEW for\n * views the target schema no longer declares (board #26).\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\nimport type {\n CascadeAction,\n Dialect,\n EnumIR,\n FieldIR,\n IndexIR,\n ModelIR,\n SchemaIR,\n} from \"@vibeorm/schema\";\nimport { detectImplicitM2MPairs } from \"./relations.ts\";\nimport {\n columnTypeKey,\n defaultFingerprint,\n resolveOnDelete,\n resolveOnUpdate,\n} from \"./postgres-types.ts\";\nimport { sqliteColumnTypeKey, sqliteDefaultFingerprint } from \"./sqlite-types.ts\";\nimport { mysqlColumnTypeKey, mysqlDefaultFingerprint } from \"./mysql-types.ts\";\nimport type { IndexColumn, JoinTableEnd } from \"./types.ts\";\n\n// ─── Normalized shapes ────────────────────────────────────────────\n\n/** A column ready for comparison. */\nexport type NormalizedColumn = {\n /** Column db name. */\n readonly name: string;\n readonly field: FieldIR;\n readonly typeKey: string;\n readonly nullable: boolean;\n readonly defaultKey: string | null;\n};\n\n/** An index (unique or not) ready for comparison. `key` ignores the name. */\nexport type NormalizedIndex = {\n readonly key: string;\n readonly name: string;\n readonly kind: string;\n readonly unique: boolean;\n readonly columns: readonly IndexColumn[];\n readonly where?: string;\n};\n\n/** A foreign key ready for comparison. `key` excludes the cascade actions. */\nexport type NormalizedFk = {\n readonly key: string;\n readonly constraintName: string;\n readonly columns: readonly string[];\n readonly refTable: string;\n readonly refColumns: readonly string[];\n readonly onDelete: CascadeAction;\n readonly onUpdate: CascadeAction;\n};\n\n/** A model collapsed to its database shape. */\nexport type NormalizedTable = {\n readonly model: ModelIR;\n /** Table db name. */\n readonly table: string;\n readonly columns: ReadonlyMap<string, NormalizedColumn>;\n /** Primary-key column db names (empty = none). */\n readonly pk: readonly string[];\n readonly indexes: ReadonlyMap<string, NormalizedIndex>;\n readonly fks: ReadonlyMap<string, NormalizedFk>;\n};\n\n/** An implicit M2M join table collapsed to its database shape. */\nexport type NormalizedJoinTable = {\n readonly table: string;\n readonly a: JoinTableEnd;\n readonly b: JoinTableEnd;\n};\n\n/** A whole schema, ready for diffing. */\nexport type NormalizedSchema = {\n readonly tables: ReadonlyMap<string, NormalizedTable>;\n readonly joinTables: ReadonlyMap<string, NormalizedJoinTable>;\n /** Enums keyed by db name. */\n readonly enums: ReadonlyMap<string, EnumIR>;\n /** View models keyed by db name — present for drop detection only (#26). */\n readonly views: ReadonlyMap<string, ModelIR>;\n};\n\n// ─── Entry point ──────────────────────────────────────────────────\n\n/**\n * Collapse a SchemaIR into its comparable database shape. `dialect` (default\n * postgres) selects the column comparison keys: on sqlite columns compare by\n * STORAGE CLASS (TEXT/INTEGER/REAL/BLOB — the TEXT-ambiguity rule), on mysql\n * by mysql column type; enum columns on both compare by VALUE LIST, never by\n * name (the database does not store one).\n */\nexport function normalizeSchema(params: {\n schema: SchemaIR;\n dialect?: Dialect;\n}): NormalizedSchema {\n const { schema } = params;\n const dialect = params.dialect ?? \"postgres\";\n\n const enums = new Map<string, EnumIR>();\n for (const enumDef of schema.enums) {\n enums.set(enumDef.dbName ?? enumDef.name, enumDef);\n }\n\n const tables = new Map<string, NormalizedTable>();\n const views = new Map<string, ModelIR>();\n for (const model of schema.models) {\n if (model.isView) {\n views.set(model.dbName ?? model.name, model);\n continue;\n }\n const table = normalizeModel({ model, schema, dialect, enums });\n tables.set(table.table, table);\n }\n\n const joinTables = new Map<string, NormalizedJoinTable>();\n for (const pair of detectImplicitM2MPairs({ schema })) {\n joinTables.set(pair.tableName, normalizeJoinTable({ pair, schema }));\n }\n\n return { tables, joinTables, enums, views };\n}\n\n// ─── Per-dialect column keys ─────────────────────────────────\n\n/** Dialect-routed column type comparison key. */\nexport function columnTypeKeyFor(params: {\n field: FieldIR;\n dialect: Dialect;\n enums: ReadonlyMap<string, EnumIR>;\n}): string {\n const { field, dialect, enums } = params;\n switch (dialect) {\n case \"postgres\":\n return columnTypeKey({ field });\n case \"sqlite\":\n return sqliteColumnTypeKey({ field, enums });\n case \"mysql\":\n return mysqlColumnTypeKey({ field, enums });\n }\n}\n\n/** Dialect-routed default fingerprint. */\nexport function defaultFingerprintFor(params: {\n field: FieldIR;\n dialect: Dialect;\n}): string | null {\n const { field, dialect } = params;\n switch (dialect) {\n case \"postgres\":\n return defaultFingerprint({ field });\n case \"sqlite\":\n return sqliteDefaultFingerprint({ field });\n case \"mysql\":\n return mysqlDefaultFingerprint({ field });\n }\n}\n\n// ─── Model → table ────────────────────────────────────────────────\n\nfunction normalizeModel(params: {\n model: ModelIR;\n schema: SchemaIR;\n dialect: Dialect;\n enums: ReadonlyMap<string, EnumIR>;\n}): NormalizedTable {\n const { model, schema, dialect, enums } = params;\n const table = model.dbName ?? model.name;\n\n const columns = new Map<string, NormalizedColumn>();\n for (const field of model.fields) {\n const name = field.dbName ?? field.name;\n columns.set(name, {\n name,\n field,\n typeKey: columnTypeKeyFor({ field, dialect, enums }),\n nullable: field.isOptional,\n defaultKey: defaultFingerprintFor({ field, dialect }),\n });\n }\n\n const pk = normalizePk({ model });\n const indexes = normalizeIndexes({ model, table });\n const fks = normalizeFks({ model, table, schema });\n\n return { model, table, columns, pk, indexes, fks };\n}\n\nfunction normalizePk(params: { model: ModelIR }): readonly string[] {\n const { model } = params;\n if (model.primaryKey !== undefined && model.primaryKey.fields.length > 0) {\n return model.primaryKey.fields.map((name) => fieldDbName({ model, name }));\n }\n return model.fields.filter((field) => field.isId).map((field) => field.dbName ?? field.name);\n}\n\nfunction normalizeIndexes(params: {\n model: ModelIR;\n table: string;\n}): ReadonlyMap<string, NormalizedIndex> {\n const { model, table } = params;\n const result = new Map<string, NormalizedIndex>();\n\n const add = (index: IndexIR): void => {\n const unique = index.kind === \"unique\";\n const kind = unique ? \"btree\" : index.kind;\n const columns: IndexColumn[] = index.fields.map((field) => {\n const fieldIR = model.fields.find((candidate) => candidate.name === field.name);\n // SQLITE-2: Decimal-typed index columns carry a marker — the sqlite DDL\n // renderer emits CAST(col AS REAL) expression indexes so B4's cast\n // compare sites stay indexable. Inert on other dialects and absent from\n // the comparison key.\n const decimal = fieldIR !== undefined && fieldIR.type === \"Decimal\" && fieldIR.isList !== true;\n return {\n name: fieldDbName({ model, name: field.name }),\n desc: field.sort === \"desc\",\n ...(decimal ? { decimal: true } : {}),\n };\n });\n const where = index.where;\n const key = indexComparisonKey({ unique, kind, columns, where });\n if (result.has(key)) return;\n const name =\n index.name ??\n `${table}_${columns.map((column) => column.name).join(\"_\")}_${unique ? \"key\" : \"idx\"}`;\n result.set(key, {\n key,\n name,\n kind,\n unique,\n columns,\n ...(where === undefined ? {} : { where }),\n });\n };\n\n for (const index of model.indexes) add(index);\n\n // `@unique` on a field is the same database object as `@@unique([field])`.\n for (const field of model.fields) {\n if (!field.isUnique) continue;\n add({ kind: \"unique\", fields: [{ name: field.name }] });\n }\n\n return result;\n}\n\nfunction indexComparisonKey(params: {\n unique: boolean;\n kind: string;\n columns: readonly IndexColumn[];\n where: string | undefined;\n}): string {\n const { unique, kind, columns, where } = params;\n const cols = columns\n .map((column) => `${column.name}${column.desc ? \" desc\" : \"\"}`)\n .join(\",\");\n return `${unique ? \"u\" : \"i\"}:${kind}:${cols}:${normalizeWhere({ where })}`;\n}\n\n/**\n * Partial-index predicates are compared loosely: postgres re-serializes the\n * expression (extra parentheses, quoted identifiers), so the comparison key\n * strips quoting, parentheses, whitespace and case. `::type` casts postgres\n * adds during normalization (e.g. `'x'::text`) are stripped too.\n */\nexport function normalizeWhere(params: { where: string | undefined }): string {\n const { where } = params;\n if (where === undefined) return \"\";\n return where\n .toLowerCase()\n .replace(/::[a-z_0-9 ]+/g, \"\")\n .replace(/[()\"'\\s]/g, \"\");\n}\n\nfunction normalizeFks(params: {\n model: ModelIR;\n table: string;\n schema: SchemaIR;\n}): ReadonlyMap<string, NormalizedFk> {\n const { model, table, schema } = params;\n const result = new Map<string, NormalizedFk>();\n\n for (const relation of model.relations) {\n if (relation.fields === undefined || relation.fields.length === 0) continue;\n\n const target = schema.models.find((candidate) => candidate.name === relation.targetModel);\n // A view is not a table — no dialect can reference one from a foreign key.\n // Views are skipped as tables everywhere else here (normalizeSchema,\n // differ, detectImplicitM2MPairs); the FK side skips them for the same\n // reason, so a model may carry a relation INTO a view for query purposes\n // without the DDL ever trying to constrain it.\n if (target !== undefined && target.isView) continue;\n const refTable = target === undefined ? relation.targetModel : (target.dbName ?? target.name);\n const columns = relation.fields.map((name) => fieldDbName({ model, name }));\n const refColumns = (relation.references ?? []).map((name) =>\n target === undefined ? name : fieldDbName({ model: target, name }),\n );\n\n // Required = every FK column is non-nullable (the ground truth the\n // database sees; Prisma's cascade defaults key off it).\n const required = relation.fields.every((name) => {\n const field = model.fields.find((candidate) => candidate.name === name);\n return field === undefined ? true : !field.isOptional;\n });\n\n const key = `${columns.join(\",\")}→${refTable}.${refColumns.join(\",\")}`;\n if (result.has(key)) continue;\n result.set(key, {\n key,\n constraintName: `${table}_${columns.join(\"_\")}_fkey`,\n columns,\n refTable,\n refColumns,\n onDelete: resolveOnDelete({ explicit: relation.onDelete, required }),\n onUpdate: resolveOnUpdate({ explicit: relation.onUpdate }),\n });\n }\n\n return result;\n}\n\n// ─── Join tables ──────────────────────────────────────────────────\n\nfunction normalizeJoinTable(params: {\n pair: { modelA: string; modelB: string; tableName: string };\n schema: SchemaIR;\n}): NormalizedJoinTable {\n const { pair, schema } = params;\n return {\n table: pair.tableName,\n a: joinTableEnd({ modelName: pair.modelA, schema, joinTable: pair.tableName }),\n b: joinTableEnd({ modelName: pair.modelB, schema, joinTable: pair.tableName }),\n };\n}\n\nfunction joinTableEnd(params: {\n modelName: string;\n schema: SchemaIR;\n joinTable: string;\n}): JoinTableEnd {\n const { modelName, schema, joinTable } = params;\n const model = schema.models.find((candidate) => candidate.name === modelName);\n if (model === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `implicit many-to-many table \"${joinTable}\" references unknown model \"${modelName}\"`,\n meta: { joinTable, model: modelName },\n });\n }\n\n const pkFields =\n model.primaryKey !== undefined && model.primaryKey.fields.length > 0\n ? model.primaryKey.fields.map((name) => model.fields.find((field) => field.name === name))\n : model.fields.filter((field) => field.isId);\n\n const pkField = pkFields[0];\n if (pkFields.length !== 1 || pkField === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `implicit many-to-many relations require a single-column primary key on \"${modelName}\" (join table \"${joinTable}\")`,\n meta: { joinTable, model: modelName },\n });\n }\n\n return {\n table: model.dbName ?? model.name,\n column: pkField.dbName ?? pkField.name,\n field: pkField,\n };\n}\n\n// ─── Shared helper ────────────────────────────────────────────────\n\n/** Resolve a field name to its db column name on a model. */\nexport function fieldDbName(params: { model: ModelIR; name: string }): string {\n const { model, name } = params;\n const field = model.fields.find((candidate) => candidate.name === name);\n return field === undefined ? name : (field.dbName ?? field.name);\n}\n",
|
|
8
|
+
"/**\n * Schema-IR normalization for diffing.\n *\n * Both sides of a diff (a parsed/DSL schema and an introspected one) collapse\n * into the same normalized shape, so representation differences never produce\n * phantom steps. The normalizations, each pinned by a differ test:\n *\n * - `@unique` on a field and a `kind: \"unique\"` model index are the same\n * unique index (the database stores both identically).\n * - A single `@id` field and a single-field `@@id` are the same primary key.\n * - Field names resolve to db names (`@map` / `@@map`) everywhere.\n * - FK cascade actions resolve Prisma's defaults (required → Restrict,\n * optional → SetNull, onUpdate → Cascade) before comparing.\n * - App-level defaults (uuid/cuid/nanoid/ulid) compare as \"no database\n * default\"; `isUpdatedAt` is app-level and ignored entirely.\n * - Implicit M2M pairs collapse to their join table regardless of whether the\n * sides are parser `manyToMany` fields or introspected unnamed `oneToMany`\n * list sides (structural detection, LEARNINGS).\n * - Views never join the table diff (migrate does not manage view DDL in this\n * wave) but ARE collected by db name, so the differ can emit DROP VIEW for\n * views the target schema no longer declares (board #26).\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\nimport type {\n CascadeAction,\n Dialect,\n EnumIR,\n FieldIR,\n IndexIR,\n ModelIR,\n SchemaIR,\n} from \"@vibeorm/schema\";\nimport { detectImplicitM2MPairs } from \"./relations.ts\";\nimport {\n columnTypeKey,\n defaultFingerprint,\n resolveOnDelete,\n resolveOnUpdate,\n} from \"./postgres-types.ts\";\nimport { sqliteColumnTypeKey, sqliteDefaultFingerprint } from \"./sqlite-types.ts\";\nimport { mysqlColumnTypeKey, mysqlDefaultFingerprint } from \"./mysql-types.ts\";\nimport type { IndexColumn, JoinTableEnd } from \"./types.ts\";\n\n// ─── Normalized shapes ────────────────────────────────────────────\n\n/** A column ready for comparison. */\nexport type NormalizedColumn = {\n /** Column db name. */\n readonly name: string;\n readonly field: FieldIR;\n readonly typeKey: string;\n readonly nullable: boolean;\n readonly defaultKey: string | null;\n};\n\n/** An index (unique or not) ready for comparison. `key` ignores the name. */\nexport type NormalizedIndex = {\n readonly key: string;\n readonly name: string;\n readonly kind: string;\n readonly unique: boolean;\n readonly columns: readonly IndexColumn[];\n readonly where?: string;\n /** `UNIQUE NULLS NOT DISTINCT` (postgres 15+). */\n readonly nullsNotDistinct?: boolean;\n};\n\n/** A foreign key ready for comparison. `key` excludes the cascade actions. */\nexport type NormalizedFk = {\n readonly key: string;\n readonly constraintName: string;\n readonly columns: readonly string[];\n readonly refTable: string;\n readonly refColumns: readonly string[];\n readonly onDelete: CascadeAction;\n readonly onUpdate: CascadeAction;\n};\n\n/** A model collapsed to its database shape. */\nexport type NormalizedTable = {\n readonly model: ModelIR;\n /** Table db name. */\n readonly table: string;\n readonly columns: ReadonlyMap<string, NormalizedColumn>;\n /** Primary-key column db names (empty = none). */\n readonly pk: readonly string[];\n readonly indexes: ReadonlyMap<string, NormalizedIndex>;\n readonly fks: ReadonlyMap<string, NormalizedFk>;\n /**\n * CHECK constraints, name → raw expression. NAME-keyed in the diff —\n * engines re-serialize expressions on introspection, so text is never\n * compared (an expression change = rename the check).\n */\n readonly checks: ReadonlyMap<string, string>;\n};\n\n/** An implicit M2M join table collapsed to its database shape. */\nexport type NormalizedJoinTable = {\n readonly table: string;\n readonly a: JoinTableEnd;\n readonly b: JoinTableEnd;\n};\n\n/** A whole schema, ready for diffing. */\nexport type NormalizedSchema = {\n readonly tables: ReadonlyMap<string, NormalizedTable>;\n readonly joinTables: ReadonlyMap<string, NormalizedJoinTable>;\n /** Enums keyed by db name. */\n readonly enums: ReadonlyMap<string, EnumIR>;\n /** View models keyed by db name — present for drop detection only (#26). */\n readonly views: ReadonlyMap<string, ModelIR>;\n};\n\n// ─── Entry point ──────────────────────────────────────────────────\n\n/**\n * Collapse a SchemaIR into its comparable database shape. `dialect` (default\n * postgres) selects the column comparison keys: on sqlite columns compare by\n * STORAGE CLASS (TEXT/INTEGER/REAL/BLOB — the TEXT-ambiguity rule), on mysql\n * by mysql column type; enum columns on both compare by VALUE LIST, never by\n * name (the database does not store one).\n */\nexport function normalizeSchema(params: {\n schema: SchemaIR;\n dialect?: Dialect;\n}): NormalizedSchema {\n const { schema } = params;\n const dialect = params.dialect ?? \"postgres\";\n\n const enums = new Map<string, EnumIR>();\n for (const enumDef of schema.enums) {\n enums.set(enumDef.dbName ?? enumDef.name, enumDef);\n }\n\n const tables = new Map<string, NormalizedTable>();\n const views = new Map<string, ModelIR>();\n for (const model of schema.models) {\n if (model.isView) {\n views.set(model.dbName ?? model.name, model);\n continue;\n }\n const table = normalizeModel({ model, schema, dialect, enums });\n tables.set(table.table, table);\n }\n\n const joinTables = new Map<string, NormalizedJoinTable>();\n for (const pair of detectImplicitM2MPairs({ schema })) {\n joinTables.set(pair.tableName, normalizeJoinTable({ pair, schema }));\n }\n\n return { tables, joinTables, enums, views };\n}\n\n// ─── Per-dialect column keys ─────────────────────────────────\n\n/** Dialect-routed column type comparison key. */\nexport function columnTypeKeyFor(params: {\n field: FieldIR;\n dialect: Dialect;\n enums: ReadonlyMap<string, EnumIR>;\n}): string {\n const { field, dialect, enums } = params;\n switch (dialect) {\n case \"postgres\":\n return columnTypeKey({ field });\n case \"sqlite\":\n return sqliteColumnTypeKey({ field, enums });\n case \"mysql\":\n return mysqlColumnTypeKey({ field, enums });\n }\n}\n\n/** Dialect-routed default fingerprint. */\nexport function defaultFingerprintFor(params: {\n field: FieldIR;\n dialect: Dialect;\n}): string | null {\n const { field, dialect } = params;\n switch (dialect) {\n case \"postgres\":\n return defaultFingerprint({ field });\n case \"sqlite\":\n return sqliteDefaultFingerprint({ field });\n case \"mysql\":\n return mysqlDefaultFingerprint({ field });\n }\n}\n\n// ─── Model → table ────────────────────────────────────────────────\n\nfunction normalizeModel(params: {\n model: ModelIR;\n schema: SchemaIR;\n dialect: Dialect;\n enums: ReadonlyMap<string, EnumIR>;\n}): NormalizedTable {\n const { model, schema, dialect, enums } = params;\n const table = model.dbName ?? model.name;\n\n const columns = new Map<string, NormalizedColumn>();\n for (const field of model.fields) {\n const name = field.dbName ?? field.name;\n columns.set(name, {\n name,\n field,\n typeKey: columnTypeKeyFor({ field, dialect, enums }),\n nullable: field.isOptional,\n defaultKey: defaultFingerprintFor({ field, dialect }),\n });\n }\n\n const pk = normalizePk({ model });\n const indexes = normalizeIndexes({ model, table });\n const fks = normalizeFks({ model, table, schema });\n\n const checks = new Map<string, string>();\n for (const check of model.checks ?? []) checks.set(check.name, check.expression);\n\n return { model, table, columns, pk, indexes, fks, checks };\n}\n\nfunction normalizePk(params: { model: ModelIR }): readonly string[] {\n const { model } = params;\n if (model.primaryKey !== undefined && model.primaryKey.fields.length > 0) {\n return model.primaryKey.fields.map((name) => fieldDbName({ model, name }));\n }\n return model.fields.filter((field) => field.isId).map((field) => field.dbName ?? field.name);\n}\n\nfunction normalizeIndexes(params: {\n model: ModelIR;\n table: string;\n}): ReadonlyMap<string, NormalizedIndex> {\n const { model, table } = params;\n const result = new Map<string, NormalizedIndex>();\n\n const add = (index: IndexIR): void => {\n const unique = index.kind === \"unique\";\n const kind = unique ? \"btree\" : index.kind;\n const columns: IndexColumn[] = index.fields.map((field) => {\n const fieldIR = model.fields.find((candidate) => candidate.name === field.name);\n // SQLITE-2: Decimal-typed index columns carry a marker — the sqlite DDL\n // renderer emits CAST(col AS REAL) expression indexes so B4's cast\n // compare sites stay indexable. Inert on other dialects and absent from\n // the comparison key.\n const decimal = fieldIR !== undefined && fieldIR.type === \"Decimal\" && fieldIR.isList !== true;\n return {\n name: fieldDbName({ model, name: field.name }),\n desc: field.sort === \"desc\",\n ...(decimal ? { decimal: true } : {}),\n };\n });\n const where = index.where;\n const nullsNotDistinct = unique && index.nullsNotDistinct === true;\n const key = indexComparisonKey({ unique, kind, columns, where, nullsNotDistinct });\n if (result.has(key)) return;\n const name =\n index.name ??\n `${table}_${columns.map((column) => column.name).join(\"_\")}_${unique ? \"key\" : \"idx\"}`;\n result.set(key, {\n key,\n name,\n kind,\n unique,\n columns,\n ...(where === undefined ? {} : { where }),\n ...(nullsNotDistinct ? { nullsNotDistinct: true } : {}),\n });\n };\n\n for (const index of model.indexes) add(index);\n\n // `@unique` on a field is the same database object as `@@unique([field])`.\n for (const field of model.fields) {\n if (!field.isUnique) continue;\n add({ kind: \"unique\", fields: [{ name: field.name }] });\n }\n\n return result;\n}\n\nfunction indexComparisonKey(params: {\n unique: boolean;\n kind: string;\n columns: readonly IndexColumn[];\n where: string | undefined;\n nullsNotDistinct?: boolean;\n}): string {\n const { unique, kind, columns, where, nullsNotDistinct } = params;\n const cols = columns\n .map((column) => `${column.name}${column.desc ? \" desc\" : \"\"}`)\n .join(\",\");\n return `${unique ? \"u\" : \"i\"}${nullsNotDistinct === true ? \"n\" : \"\"}:${kind}:${cols}:${normalizeWhere({ where })}`;\n}\n\n/**\n * Partial-index predicates are compared loosely: postgres re-serializes the\n * expression (extra parentheses, quoted identifiers), so the comparison key\n * strips quoting, parentheses, whitespace and case. `::type` casts postgres\n * adds during normalization (e.g. `'x'::text`) are stripped too.\n */\nexport function normalizeWhere(params: { where: string | undefined }): string {\n const { where } = params;\n if (where === undefined) return \"\";\n return where\n .toLowerCase()\n .replace(/::[a-z_0-9 ]+/g, \"\")\n .replace(/[()\"'\\s]/g, \"\");\n}\n\nfunction normalizeFks(params: {\n model: ModelIR;\n table: string;\n schema: SchemaIR;\n}): ReadonlyMap<string, NormalizedFk> {\n const { model, table, schema } = params;\n const result = new Map<string, NormalizedFk>();\n\n for (const relation of model.relations) {\n if (relation.fields === undefined || relation.fields.length === 0) continue;\n\n const target = schema.models.find((candidate) => candidate.name === relation.targetModel);\n // A view is not a table — no dialect can reference one from a foreign key.\n // Views are skipped as tables everywhere else here (normalizeSchema,\n // differ, detectImplicitM2MPairs); the FK side skips them for the same\n // reason, so a model may carry a relation INTO a view for query purposes\n // without the DDL ever trying to constrain it.\n if (target !== undefined && target.isView) continue;\n const refTable = target === undefined ? relation.targetModel : (target.dbName ?? target.name);\n const columns = relation.fields.map((name) => fieldDbName({ model, name }));\n const refColumns = (relation.references ?? []).map((name) =>\n target === undefined ? name : fieldDbName({ model: target, name }),\n );\n\n // Required = every FK column is non-nullable (the ground truth the\n // database sees; Prisma's cascade defaults key off it).\n const required = relation.fields.every((name) => {\n const field = model.fields.find((candidate) => candidate.name === name);\n return field === undefined ? true : !field.isOptional;\n });\n\n const key = `${columns.join(\",\")}→${refTable}.${refColumns.join(\",\")}`;\n if (result.has(key)) continue;\n result.set(key, {\n key,\n constraintName: `${table}_${columns.join(\"_\")}_fkey`,\n columns,\n refTable,\n refColumns,\n onDelete: resolveOnDelete({ explicit: relation.onDelete, required }),\n onUpdate: resolveOnUpdate({ explicit: relation.onUpdate }),\n });\n }\n\n return result;\n}\n\n// ─── Join tables ──────────────────────────────────────────────────\n\nfunction normalizeJoinTable(params: {\n pair: { modelA: string; modelB: string; tableName: string };\n schema: SchemaIR;\n}): NormalizedJoinTable {\n const { pair, schema } = params;\n return {\n table: pair.tableName,\n a: joinTableEnd({ modelName: pair.modelA, schema, joinTable: pair.tableName }),\n b: joinTableEnd({ modelName: pair.modelB, schema, joinTable: pair.tableName }),\n };\n}\n\nfunction joinTableEnd(params: {\n modelName: string;\n schema: SchemaIR;\n joinTable: string;\n}): JoinTableEnd {\n const { modelName, schema, joinTable } = params;\n const model = schema.models.find((candidate) => candidate.name === modelName);\n if (model === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `implicit many-to-many table \"${joinTable}\" references unknown model \"${modelName}\"`,\n meta: { joinTable, model: modelName },\n });\n }\n\n const pkFields =\n model.primaryKey !== undefined && model.primaryKey.fields.length > 0\n ? model.primaryKey.fields.map((name) => model.fields.find((field) => field.name === name))\n : model.fields.filter((field) => field.isId);\n\n const pkField = pkFields[0];\n if (pkFields.length !== 1 || pkField === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `implicit many-to-many relations require a single-column primary key on \"${modelName}\" (join table \"${joinTable}\")`,\n meta: { joinTable, model: modelName },\n });\n }\n\n return {\n table: model.dbName ?? model.name,\n column: pkField.dbName ?? pkField.name,\n field: pkField,\n };\n}\n\n// ─── Shared helper ────────────────────────────────────────────────\n\n/** Resolve a field name to its db column name on a model. */\nexport function fieldDbName(params: { model: ModelIR; name: string }): string {\n const { model, name } = params;\n const field = model.fields.find((candidate) => candidate.name === name);\n return field === undefined ? name : (field.dbName ?? field.name);\n}\n",
|
|
9
9
|
"/**\n * Implicit many-to-many detection on Schema IR.\n *\n * ONE structural rule, kept in lock-step with the parser's\n * `findImplicitM2MCounterpart` (see LEARNINGS): two relation fields form an\n * implicit M:N **iff** both are lists that declare no FK columns, they are\n * distinct fields (self-exclusion — a 1:N self-relation must never pair with\n * itself), their relation names match symmetrically (both unnamed, or both\n * the same name), and each side is the OTHER'S SOLE counterpart under that\n * name key. Detection never reads `relation.type`, because an introspected\n * schema represents a real join table as two unnamed `oneToMany` list sides —\n * trusting the type would break round-trip stability.\n *\n * The sole-counterpart requirement is the phantom-join-table fix, round two:\n * two models holding foreign keys INTO EACH OTHER introspect as an unnamed\n * fieldless list on each side (every FK synthesizes one on its target), and\n * name-matching alone would marry those lists into a join table that exists\n * nowhere. Counting EVERY relation under the name key — FK-owning sides\n * included — disambiguates: the parser rejects the same shape as\n * `ambiguous-relation` at parse time, so parsed and introspected schemas\n * resolve identically.\n *\n * The join-table naming itself comes from the ONE shared convention in\n * `@vibeorm/schema` (`implicitJoinTable`) — never re-derived here.\n */\n\nimport { implicitJoinTable } from \"@vibeorm/schema\";\nimport type { ModelIR, RelationIR, SchemaIR } from \"@vibeorm/schema\";\n\n/** A detected implicit many-to-many relation. `modelA` sorts before `modelB`. */\nexport type ImplicitM2MPair = {\n readonly modelA: string;\n readonly modelB: string;\n /** Shared explicit relation name, when both sides declare one. */\n readonly relationName?: string;\n /** Join table name per the shared convention (`_PostToTag`, `_tags`). */\n readonly tableName: string;\n};\n\n/** Detect every implicit many-to-many pair in a schema. */\nexport function detectImplicitM2MPairs(params: { schema: SchemaIR }): ImplicitM2MPair[] {\n const { schema } = params;\n const modelsByName = new Map<string, ModelIR>(schema.models.map((model) => [model.name, model]));\n const pairs: ImplicitM2MPair[] = [];\n const seen = new Set<string>();\n\n for (const model of schema.models) {\n if (model.isView) continue;\n for (const relation of model.relations) {\n if (!isFieldlessListSide({ relation })) continue;\n\n const target = modelsByName.get(relation.targetModel);\n if (target === undefined || target.isView) continue;\n\n const counterpart = soleCounterpart({ relation, ownModel: model.name, target });\n if (counterpart === undefined || !isFieldlessListSide({ relation: counterpart })) continue;\n // Symmetry: the counterpart's own name key must resolve back to exactly\n // this relation, or the pairing is ambiguous from its side.\n if (soleCounterpart({ relation: counterpart, ownModel: target.name, target: model }) !== relation) {\n continue;\n }\n\n const joinTable = implicitJoinTable({\n modelA: model.name,\n modelB: relation.targetModel,\n ...(relation.relationName === undefined ? {} : { relationName: relation.relationName }),\n });\n if (seen.has(joinTable.tableName)) continue;\n seen.add(joinTable.tableName);\n\n pairs.push({\n modelA: joinTable.modelA,\n modelB: joinTable.modelB,\n ...(relation.relationName === undefined ? {} : { relationName: relation.relationName }),\n tableName: joinTable.tableName,\n });\n }\n }\n\n return pairs;\n}\n\nfunction isFieldlessListSide(params: { relation: RelationIR }): boolean {\n const { relation } = params;\n return relation.isList && (relation.fields === undefined || relation.fields.length === 0);\n}\n\n/**\n * The single relation on `target` pointing back at `ownModel` under the same\n * relation-name key (self-excluded — a 1:N self-relation must never pair with\n * itself), or `undefined` when there is none or the key is ambiguous (>1\n * candidate). Candidates are counted WITHOUT filtering by shape: an FK-owning\n * side under the same key means the fieldless list is a 1:N inverse, not an\n * implicit M:N side.\n */\nfunction soleCounterpart(params: {\n relation: RelationIR;\n ownModel: string;\n target: ModelIR;\n}): RelationIR | undefined {\n const { relation, ownModel, target } = params;\n const candidates = target.relations.filter(\n (candidate) =>\n candidate !== relation &&\n candidate.targetModel === ownModel &&\n // Symmetric relation-name match: both unnamed, or both the same name.\n candidate.relationName === relation.relationName,\n );\n return candidates.length === 1 ? candidates[0] : undefined;\n}\n",
|
|
10
10
|
"/**\n * Postgres column-type mapping (IR → pg text and back), native-type\n * normalization, default-value fingerprints/rendering, and cascade-action\n * resolution.\n *\n * The forward mapping implements dialect-matrix §2; the fingerprint helpers are\n * the differ's normalization layer — both the differ and the introspector lean\n * on them so `diff(introspect(push(X)), X) = []` holds by construction.\n */\n\nimport { VibeError, isEnumType } from \"@vibeorm/schema\";\nimport type { CascadeAction, FieldIR, ScalarType } from \"@vibeorm/schema\";\nimport { postgresDialect } from \"@vibeorm/sql\";\n\n// ─── Canonical scalar mapping (dialect-matrix §2) ─────────────────\n\n/** IR scalar → canonical postgres column type. */\nexport const SCALAR_TO_PG: Readonly<Record<ScalarType, string>> = {\n String: \"text\",\n Boolean: \"boolean\",\n Int: \"integer\",\n BigInt: \"bigint\",\n Float: \"double precision\",\n Decimal: \"numeric\",\n DateTime: \"timestamptz\",\n Json: \"jsonb\",\n Bytes: \"bytea\",\n};\n\n/**\n * Native spellings that compare EQUAL to a scalar's canonical mapping without\n * being it (comparison only — rendering keeps the declared spelling, so\n * `@db.Timestamptz(3)` still creates a precision-3 column). The canonical\n * DateTime mapping is bare `timestamptz` — postgres's server default,\n * precision 6, exactly what v1 emitted — so v1-created (and hand-written, and\n * Prisma-created) databases upgrade with zero DDL. `timestamptz(6)` is the\n * same type spelled explicitly, and `timestamptz(3)` is grandfathered for\n * databases created by the 2.0 alphas, which emitted it: without this class\n * either population would report a destructive type change on every DateTime\n * column. Any other precision stays distinct and still diffs.\n */\nconst CANONICAL_EQUIVALENTS: Readonly<Partial<Record<ScalarType, readonly string[]>>> = {\n DateTime: [\"timestamptz(3)\", \"timestamptz(6)\"],\n};\n\n// ─── Native-type normalization ────────────────────────────────────\n\n/**\n * Alias map applied to the base name of a native type (everything before the\n * parenthesized modifier) so that schema-declared `@db.*` spellings and\n * catalog-reported names compare equal.\n */\nconst NATIVE_ALIASES: Readonly<Record<string, string>> = {\n charactervarying: \"varchar\",\n character: \"char\",\n bpchar: \"char\",\n int: \"integer\",\n int4: \"integer\",\n int2: \"smallint\",\n int8: \"bigint\",\n serial: \"integer\",\n bigserial: \"bigint\",\n bool: \"boolean\",\n float4: \"real\",\n float8: \"doubleprecision\",\n double: \"doubleprecision\",\n doubleprecision: \"doubleprecision\",\n decimal: \"numeric\",\n timestampwithtimezone: \"timestamptz\",\n timestampwithouttimezone: \"timestamp\",\n timewithtimezone: \"timetz\",\n timewithouttimezone: \"time\",\n};\n\n/**\n * Normalize a native type string for comparison: lowercase, whitespace\n * stripped, base name de-aliased. `\"VarChar(191)\"` and `\"character varying(191)\"`\n * both become `\"varchar(191)\"`.\n */\nexport function normalizeNativeType(params: { raw: string }): string {\n const compact = params.raw.toLowerCase().replace(/\\s+/g, \"\");\n const match = compact.match(/^([a-z_0-9]+)(\\(.*\\))?(\\[\\])?$/);\n if (match === null) return compact;\n const base = NATIVE_ALIASES[match[1] as string] ?? (match[1] as string);\n return `${base}${match[2] ?? \"\"}${match[3] ?? \"\"}`;\n}\n\n/**\n * Comparison key for a column's type. Two columns with equal keys need no\n * ALTER. A native type equal to the scalar's canonical mapping is dropped, so\n * `DateTime` and `DateTime @db.Timestamptz` compare equal — and so do the\n * mapping's `CANONICAL_EQUIVALENTS` (`@db.Timestamptz(6)`, the same type\n * spelled explicitly, and `@db.Timestamptz(3)`, what the 2.0 alphas created).\n * Any other precision stays distinct and still diffs.\n */\nexport function columnTypeKey(params: { field: FieldIR }): string {\n const { field } = params;\n const listSuffix = field.isList ? \"[]\" : \"\";\n\n if (field.isUnsupported === true) {\n return `u:${normalizeNativeType({ raw: field.nativeType ?? \"\" })}`;\n }\n if (isEnumType(field.type)) {\n return `e:${field.type.enum}${listSuffix}`;\n }\n if (field.nativeType !== undefined) {\n const normalized = normalizeNativeType({ raw: field.nativeType });\n const canonical = normalizeNativeType({ raw: SCALAR_TO_PG[field.type] });\n const isCanonical =\n normalized === canonical ||\n (CANONICAL_EQUIVALENTS[field.type]?.includes(normalized) ?? false);\n if (!isCanonical) return `n:${normalized}${listSuffix}`;\n }\n return `s:${field.type}${listSuffix}`;\n}\n\n/**\n * True when a type change from `from` to `to` is the safe scalar→array repair\n * (same base type, scalar becomes a one-element array via a `USING` clause —\n * the LEARNINGS enum-array lesson). Every other type change is treated as\n * potentially narrowing, i.e. destructive.\n */\nexport function isScalarToArrayChange(params: { from: FieldIR; to: FieldIR }): boolean {\n const { from, to } = params;\n if (from.isList || !to.isList) return false;\n const fromBase = columnTypeKey({ field: { ...from, isList: false } });\n const toBase = columnTypeKey({ field: { ...to, isList: false } });\n return fromBase === toBase;\n}\n\n// ─── Column type rendering ────────────────────────────────────────\n\n/** Render the postgres column type for a field (no identity, no default). */\nexport function columnTypeSql(params: { field: FieldIR }): string {\n const { field } = params;\n if (field.isUnsupported === true) {\n if (field.nativeType === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `unsupported column \"${field.name}\" carries no native type to render`,\n meta: { field: field.name },\n });\n }\n return field.nativeType;\n }\n const listSuffix = field.isList ? \"[]\" : \"\";\n if (isEnumType(field.type)) {\n return `${postgresDialect.quoteIdent({ name: field.type.enum })}${listSuffix}`;\n }\n if (field.nativeType !== undefined) {\n const normalized = normalizeNativeType({ raw: field.nativeType });\n const canonical = normalizeNativeType({ raw: SCALAR_TO_PG[field.type] });\n if (normalized !== canonical) return `${field.nativeType.toLowerCase()}${listSuffix}`;\n }\n return `${SCALAR_TO_PG[field.type]}${listSuffix}`;\n}\n\n/** True when the field renders as an identity column (autoincrement Int/BigInt). */\nexport function isIdentityColumn(params: { field: FieldIR }): boolean {\n const { field } = params;\n return (\n field.default?.kind === \"autoincrement\" &&\n !field.isList &&\n !isEnumType(field.type) &&\n (field.type === \"Int\" || field.type === \"BigInt\")\n );\n}\n\n// ─── Defaults ─────────────────────────────────────────────────────\n\n/**\n * Normalized fingerprint of a column default for diffing, or `null` when the\n * database carries no default. App-level id generators (uuid / cuid / nanoid /\n * ulid) fingerprint as `null`: the runtime injects them client-side, so the\n * database honestly has no default — this is what keeps introspection\n * round-trips stable for `@default(uuid())` columns.\n */\nexport function defaultFingerprint(params: { field: FieldIR }): string | null {\n const { field } = params;\n const def = field.default;\n if (def === undefined) return null;\n switch (def.kind) {\n case \"autoincrement\":\n return \"autoincrement\";\n case \"now\":\n return \"now\";\n case \"uuid\":\n case \"cuid\":\n case \"nanoid\":\n case \"ulid\":\n return null;\n case \"literal\": {\n const value = def.value;\n if (typeof value === \"boolean\") return `bool:${value}`;\n if (typeof value === \"number\") return `num:${value}`;\n // A string literal on an enum column is the same default as an enumValue.\n if (isEnumType(field.type)) return `enum:${value}`;\n // A numeric string on a numeric column (`Decimal @default(\"0\")`) is the\n // same default as the number: postgres reports it back as `'0'::numeric`\n // and introspection parses that numerically, so a `str:` fingerprint\n // here would make the in-sync state unreachable — the step re-appears\n // after every push, forever.\n if (isNumericScalar({ type: field.type }) && NUMERIC_LITERAL.test(value)) {\n return `num:${Number(value)}`;\n }\n return `str:${value}`;\n }\n case \"enumValue\":\n return `enum:${def.value}`;\n case \"dbgenerated\":\n return `db:${def.sql.toLowerCase().replace(/\\s+/g, \"\")}`;\n }\n}\n\n/**\n * Render the `DEFAULT` expression for a field, or `undefined` when the column\n * takes no database default (no default declared, app-level generators,\n * autoincrement — which renders as identity instead).\n */\nexport function defaultSql(params: { field: FieldIR }): string | undefined {\n const def = params.field.default;\n if (def === undefined) return undefined;\n switch (def.kind) {\n case \"autoincrement\":\n case \"uuid\":\n case \"cuid\":\n case \"nanoid\":\n case \"ulid\":\n return undefined;\n case \"now\":\n return \"CURRENT_TIMESTAMP\";\n case \"literal\": {\n const value = def.value;\n if (typeof value === \"boolean\") return value ? \"true\" : \"false\";\n if (typeof value === \"number\") return String(value);\n return quotePgString({ value });\n }\n case \"enumValue\":\n return quotePgString({ value: def.value });\n case \"dbgenerated\":\n return def.sql;\n }\n}\n\n/** Integer/decimal literal shape — the same one the introspector accepts. */\nconst NUMERIC_LITERAL: RegExp = /^-?\\d+(\\.\\d+)?$/;\n\n/** True for scalars whose defaults postgres reports back as numeric literals. */\nexport function isNumericScalar(params: { type: ScalarType }): boolean {\n const { type } = params;\n return type === \"Int\" || type === \"BigInt\" || type === \"Float\" || type === \"Decimal\";\n}\n\n// ─── Cascade actions ──────────────────────────────────────────────\n\n/**\n * `pg_constraint.confdeltype` / `confupdtype` single-char codes → IR actions\n * (used by the introspector).\n */\nexport const PG_CHAR_TO_CASCADE_ACTION: Readonly<Record<string, CascadeAction>> = {\n a: \"NoAction\",\n r: \"Restrict\",\n c: \"Cascade\",\n n: \"SetNull\",\n d: \"SetDefault\",\n};\n\n/** CascadeAction → SQL clause body. */\nexport const CASCADE_ACTION_SQL: Readonly<Record<CascadeAction, string>> = {\n Cascade: \"CASCADE\",\n Restrict: \"RESTRICT\",\n NoAction: \"NO ACTION\",\n SetNull: \"SET NULL\",\n SetDefault: \"SET DEFAULT\",\n};\n\n/**\n * Effective onDelete with Prisma's postgres defaults applied (LEARNINGS):\n * required FK → Restrict, optional FK → SetNull.\n */\nexport function resolveOnDelete(params: {\n explicit: CascadeAction | undefined;\n required: boolean;\n}): CascadeAction {\n if (params.explicit !== undefined) return params.explicit;\n return params.required ? \"Restrict\" : \"SetNull\";\n}\n\n/** Effective onUpdate — Prisma's postgres default is Cascade. */\nexport function resolveOnUpdate(params: { explicit: CascadeAction | undefined }): CascadeAction {\n return params.explicit ?? \"Cascade\";\n}\n\n// ─── Small quoting helpers ────────────────────────────────────────\n\n/** Quote a postgres string literal (single quotes, doubled embedded quotes). */\nexport function quotePgString(params: { value: string }): string {\n return `'${params.value.replaceAll(\"'\", \"''\")}'`;\n}\n",
|
|
11
|
-
"/**\n * SQLite column-type mapping (IR → storage class and back), comparison keys,\n * default rendering/fingerprints, and the enum CHECK-constraint convention.\n *\n * dialect-matrix §2: sqlite columns use the four storage classes only —\n * String/DateTime/Decimal/Json → TEXT, Boolean/Int/BigInt → INTEGER,\n * Float → REAL, Bytes → BLOB. Enums are TEXT plus a named CHECK constraint\n * (`CONSTRAINT \"<table>_<column>_enum_<Enum>\" CHECK (\"<column>\" IN (…))`) —\n * the constraint NAME is the marker that lets introspection recover the enum's\n * name, and the IN list recovers its values. Scalar lists are unsupported\n * (refused by the differ; this module throws as the render-time backstop).\n *\n * THE TEXT AMBIGUITY, stated honestly: DateTime, Decimal and Json all live in\n * TEXT, and Boolean/BigInt live in INTEGER — a pulled schema reports such\n * columns as String/Int (there is no marker to say otherwise). Column\n * comparison is therefore STORAGE-CLASS based on sqlite (`sqliteColumnTypeKey`\n * compares what the database actually stores), so `diff(introspect(push(X)),\n * X)` stays [] even though the introspected IR says String where X said\n * DateTime.\n */\n\nimport { VibeError, isEnumType, unsupportedCapability } from \"@vibeorm/schema\";\nimport type { FieldIR, ScalarType } from \"@vibeorm/schema\";\nimport { resolveEnumValues } from \"./enum-values.ts\";\nimport { defaultFingerprint, quotePgString } from \"./postgres-types.ts\";\nimport type { EnumIR } from \"@vibeorm/schema\";\n\n// ─── Canonical scalar mapping (dialect-matrix §2) ─────────────────\n\n/** IR scalar → sqlite storage class. */\nexport const SCALAR_TO_SQLITE: Readonly<Record<ScalarType, string>> = {\n String: \"TEXT\",\n Boolean: \"INTEGER\",\n Int: \"INTEGER\",\n BigInt: \"INTEGER\",\n Float: \"REAL\",\n Decimal: \"TEXT\",\n DateTime: \"TEXT\",\n Json: \"TEXT\",\n Bytes: \"BLOB\",\n};\n\n/** Render-time backstop for scalar-list columns (the differ refuses earlier). */\nexport function refuseSqliteScalarList(params: { field: FieldIR }): never {\n throw unsupportedCapability({\n dialect: \"sqlite\",\n feature: `scalar list column \"${params.field.name}\"`,\n hint: \"sqlite has no array column type — model the list as a separate table or a Json column\",\n });\n}\n\n/**\n * Storage class for a column. Unsupported columns render their nativeType\n * verbatim (fidelity over guessing); enums are TEXT (the CHECK is separate).\n */\nexport function sqliteStorageType(params: { field: FieldIR }): string {\n const { field } = params;\n if (field.isUnsupported === true) {\n if (field.nativeType === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `unsupported column \"${field.name}\" carries no native type to render`,\n meta: { field: field.name },\n });\n }\n return field.nativeType;\n }\n if (field.isList) refuseSqliteScalarList({ field });\n if (isEnumType(field.type)) return \"TEXT\";\n return SCALAR_TO_SQLITE[field.type];\n}\n\n// ─── Comparison keys (the differ's sqlite normalization) ──────────\n\n/**\n * Comparison key for a column on sqlite: the STORAGE CLASS, not the IR type —\n * String and DateTime are both `t:TEXT` because the database cannot tell them\n * apart. Enum columns key on their VALUE LIST (`e:A|B`), never their name\n * (the name only lives in our CHECK-constraint convention): adding an enum\n * value changes the key and flows through `alterColumn` → table rebuild with\n * the widened CHECK.\n */\nexport function sqliteColumnTypeKey(params: {\n field: FieldIR;\n enums: ReadonlyMap<string, EnumIR>;\n}): string {\n const { field, enums } = params;\n if (field.isUnsupported === true) {\n return `u:${(field.nativeType ?? \"\").toLowerCase().replace(/\\s+/g, \"\")}`;\n }\n if (isEnumType(field.type)) {\n const values = resolveEnumValues({ name: field.type.enum, enums });\n return values === undefined ? `e:?${field.type.enum}` : `e:${values.join(\"|\")}`;\n }\n const listSuffix = field.isList ? \"[]\" : \"\";\n return `t:${SCALAR_TO_SQLITE[field.type]}${listSuffix}`;\n}\n\n/**\n * Default fingerprint on sqlite: postgres rules, except booleans compare as\n * their INTEGER storage (`true` → `num:1`) — an introspected sqlite schema can\n * only ever report `DEFAULT 1`, and the fingerprint must not churn on that.\n */\nexport function sqliteDefaultFingerprint(params: { field: FieldIR }): string | null {\n const { field } = params;\n const def = field.default;\n if (def?.kind === \"literal\" && typeof def.value === \"boolean\") {\n return `num:${def.value ? 1 : 0}`;\n }\n return defaultFingerprint({ field });\n}\n\n// ─── Default rendering ────────────────────────────────────────────\n\n/**\n * Render the `DEFAULT` expression for a field on sqlite, or `undefined` when\n * the column takes none (app-level generators, autoincrement — which renders\n * as `INTEGER PRIMARY KEY AUTOINCREMENT` instead). Booleans store as 1/0.\n */\nexport function sqliteDefaultSql(params: { field: FieldIR }): string | undefined {\n const def = params.field.default;\n if (def === undefined) return undefined;\n switch (def.kind) {\n case \"autoincrement\":\n case \"uuid\":\n case \"cuid\":\n case \"nanoid\":\n case \"ulid\":\n return undefined;\n case \"now\":\n return \"CURRENT_TIMESTAMP\";\n case \"literal\": {\n const value = def.value;\n if (typeof value === \"boolean\") return value ? \"1\" : \"0\";\n if (typeof value === \"number\") return String(value);\n return quotePgString({ value });\n }\n case \"enumValue\":\n return quotePgString({ value: def.value });\n case \"dbgenerated\":\n return def.sql;\n }\n}\n\n// ─── Enum CHECK-constraint convention ─────────────────────────────\n\n/**\n * Name of the enum CHECK constraint for a column — the `_enum_` infix is the\n * introspection marker that recovers the enum's name from `sqlite_master.sql`.\n */\nexport function sqliteEnumCheckName(params: {\n table: string;\n column: string;\n enumName: string;\n}): string {\n return `${params.table}_${params.column}_enum_${params.enumName}`;\n}\n\n/** One parsed enum CHECK constraint from a table's `sqlite_master.sql`. */\nexport type ParsedEnumCheck = {\n readonly column: string;\n readonly enumName: string;\n readonly values: readonly string[];\n};\n\nconst ENUM_CHECK_PATTERN =\n /CONSTRAINT \"((?:[^\"]|\"\")+)_enum_((?:[^\"]|\"\")+)\" CHECK \\(\"((?:[^\"]|\"\")+)\" IN \\(([^)]*)\\)\\)/g;\n\n/**\n * Recover enum columns from a table's `sqlite_master.sql` text. Only checks\n * following OUR naming convention are recognized; foreign CHECK constraints\n * are ignored (and — documented limitation — do not survive a table rebuild).\n */\nexport function parseSqliteEnumChecks(params: { tableSql: string }): ParsedEnumCheck[] {\n const result: ParsedEnumCheck[] = [];\n for (const match of params.tableSql.matchAll(ENUM_CHECK_PATTERN)) {\n const enumName = (match[2] as string).replaceAll('\"\"', '\"');\n const column = (match[3] as string).replaceAll('\"\"', '\"');\n const values: string[] = [];\n for (const value of (match[4] as string).matchAll(/'((?:[^']|'')*)'/g)) {\n values.push((value[1] as string).replaceAll(\"''\", \"'\"));\n }\n result.push({ column, enumName, values });\n }\n return result;\n}\n",
|
|
11
|
+
"/**\n * SQLite column-type mapping (IR → storage class and back), comparison keys,\n * default rendering/fingerprints, and the enum CHECK-constraint convention.\n *\n * dialect-matrix §2: sqlite columns use the four storage classes only —\n * String/DateTime/Decimal/Json → TEXT, Boolean/Int/BigInt → INTEGER,\n * Float → REAL, Bytes → BLOB. Enums are TEXT plus a named CHECK constraint\n * (`CONSTRAINT \"<table>_<column>_enum_<Enum>\" CHECK (\"<column>\" IN (…))`) —\n * the constraint NAME is the marker that lets introspection recover the enum's\n * name, and the IN list recovers its values. Scalar lists are unsupported\n * (refused by the differ; this module throws as the render-time backstop).\n *\n * THE TEXT AMBIGUITY, stated honestly: DateTime, Decimal and Json all live in\n * TEXT, and Boolean/BigInt live in INTEGER — a pulled schema reports such\n * columns as String/Int (there is no marker to say otherwise). Column\n * comparison is therefore STORAGE-CLASS based on sqlite (`sqliteColumnTypeKey`\n * compares what the database actually stores), so `diff(introspect(push(X)),\n * X)` stays [] even though the introspected IR says String where X said\n * DateTime.\n */\n\nimport { VibeError, isEnumType, unsupportedCapability } from \"@vibeorm/schema\";\nimport type { FieldIR, ScalarType } from \"@vibeorm/schema\";\nimport { resolveEnumValues } from \"./enum-values.ts\";\nimport { defaultFingerprint, quotePgString } from \"./postgres-types.ts\";\nimport type { EnumIR } from \"@vibeorm/schema\";\n\n// ─── Canonical scalar mapping (dialect-matrix §2) ─────────────────\n\n/** IR scalar → sqlite storage class. */\nexport const SCALAR_TO_SQLITE: Readonly<Record<ScalarType, string>> = {\n String: \"TEXT\",\n Boolean: \"INTEGER\",\n Int: \"INTEGER\",\n BigInt: \"INTEGER\",\n Float: \"REAL\",\n Decimal: \"TEXT\",\n DateTime: \"TEXT\",\n Json: \"TEXT\",\n Bytes: \"BLOB\",\n};\n\n/** Render-time backstop for scalar-list columns (the differ refuses earlier). */\nexport function refuseSqliteScalarList(params: { field: FieldIR }): never {\n throw unsupportedCapability({\n dialect: \"sqlite\",\n feature: `scalar list column \"${params.field.name}\"`,\n hint: \"sqlite has no array column type — model the list as a separate table or a Json column\",\n });\n}\n\n/**\n * Storage class for a column. Unsupported columns render their nativeType\n * verbatim (fidelity over guessing); enums are TEXT (the CHECK is separate).\n */\nexport function sqliteStorageType(params: { field: FieldIR }): string {\n const { field } = params;\n if (field.isUnsupported === true) {\n if (field.nativeType === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `unsupported column \"${field.name}\" carries no native type to render`,\n meta: { field: field.name },\n });\n }\n return field.nativeType;\n }\n if (field.isList) refuseSqliteScalarList({ field });\n if (isEnumType(field.type)) return \"TEXT\";\n return SCALAR_TO_SQLITE[field.type];\n}\n\n// ─── Comparison keys (the differ's sqlite normalization) ──────────\n\n/**\n * Comparison key for a column on sqlite: the STORAGE CLASS, not the IR type —\n * String and DateTime are both `t:TEXT` because the database cannot tell them\n * apart. Enum columns key on their VALUE LIST (`e:A|B`), never their name\n * (the name only lives in our CHECK-constraint convention): adding an enum\n * value changes the key and flows through `alterColumn` → table rebuild with\n * the widened CHECK.\n */\nexport function sqliteColumnTypeKey(params: {\n field: FieldIR;\n enums: ReadonlyMap<string, EnumIR>;\n}): string {\n const { field, enums } = params;\n if (field.isUnsupported === true) {\n return `u:${(field.nativeType ?? \"\").toLowerCase().replace(/\\s+/g, \"\")}`;\n }\n if (isEnumType(field.type)) {\n const values = resolveEnumValues({ name: field.type.enum, enums });\n return values === undefined ? `e:?${field.type.enum}` : `e:${values.join(\"|\")}`;\n }\n const listSuffix = field.isList ? \"[]\" : \"\";\n return `t:${SCALAR_TO_SQLITE[field.type]}${listSuffix}`;\n}\n\n/**\n * Default fingerprint on sqlite: postgres rules, except booleans compare as\n * their INTEGER storage (`true` → `num:1`) — an introspected sqlite schema can\n * only ever report `DEFAULT 1`, and the fingerprint must not churn on that.\n */\nexport function sqliteDefaultFingerprint(params: { field: FieldIR }): string | null {\n const { field } = params;\n const def = field.default;\n if (def?.kind === \"literal\" && typeof def.value === \"boolean\") {\n return `num:${def.value ? 1 : 0}`;\n }\n return defaultFingerprint({ field });\n}\n\n// ─── Default rendering ────────────────────────────────────────────\n\n/**\n * Render the `DEFAULT` expression for a field on sqlite, or `undefined` when\n * the column takes none (app-level generators, autoincrement — which renders\n * as `INTEGER PRIMARY KEY AUTOINCREMENT` instead). Booleans store as 1/0.\n */\nexport function sqliteDefaultSql(params: { field: FieldIR }): string | undefined {\n const def = params.field.default;\n if (def === undefined) return undefined;\n switch (def.kind) {\n case \"autoincrement\":\n case \"uuid\":\n case \"cuid\":\n case \"nanoid\":\n case \"ulid\":\n return undefined;\n case \"now\":\n return \"CURRENT_TIMESTAMP\";\n case \"literal\": {\n const value = def.value;\n if (typeof value === \"boolean\") return value ? \"1\" : \"0\";\n if (typeof value === \"number\") return String(value);\n return quotePgString({ value });\n }\n case \"enumValue\":\n return quotePgString({ value: def.value });\n case \"dbgenerated\":\n return def.sql;\n }\n}\n\n// ─── Enum CHECK-constraint convention ─────────────────────────────\n\n/**\n * Name of the enum CHECK constraint for a column — the `_enum_` infix is the\n * introspection marker that recovers the enum's name from `sqlite_master.sql`.\n */\nexport function sqliteEnumCheckName(params: {\n table: string;\n column: string;\n enumName: string;\n}): string {\n return `${params.table}_${params.column}_enum_${params.enumName}`;\n}\n\n/** One parsed enum CHECK constraint from a table's `sqlite_master.sql`. */\nexport type ParsedEnumCheck = {\n readonly column: string;\n readonly enumName: string;\n readonly values: readonly string[];\n};\n\nconst ENUM_CHECK_PATTERN =\n /CONSTRAINT \"((?:[^\"]|\"\")+)_enum_((?:[^\"]|\"\")+)\" CHECK \\(\"((?:[^\"]|\"\")+)\" IN \\(([^)]*)\\)\\)/g;\n\n/** One parsed NAMED user CHECK from a table's `sqlite_master.sql`. */\nexport type ParsedNamedCheck = {\n readonly name: string;\n readonly expression: string;\n};\n\n/**\n * Every `CONSTRAINT \"name\" CHECK (…)` in a table's `sqlite_master.sql`, with\n * a balanced-paren walk for the expression (a regex capture would stop at the\n * first `)`). The caller filters out the enum-convention names — those are\n * column machinery, not user checks.\n */\nexport function parseSqliteNamedChecks(params: { tableSql: string }): ParsedNamedCheck[] {\n const { tableSql } = params;\n const result: ParsedNamedCheck[] = [];\n for (const match of tableSql.matchAll(/CONSTRAINT \"((?:[^\"]|\"\")+)\" CHECK\\s*\\(/g)) {\n const name = (match[1] as string).replaceAll('\"\"', '\"');\n const open = (match.index ?? 0) + match[0].length - 1;\n let depth = 0;\n let close = -1;\n for (let index = open; index < tableSql.length; index++) {\n const char = tableSql[index];\n if (char === \"(\") depth += 1;\n else if (char === \")\") {\n depth -= 1;\n if (depth === 0) {\n close = index;\n break;\n }\n }\n }\n if (close === -1) continue;\n result.push({ name, expression: tableSql.slice(open + 1, close) });\n }\n return result;\n}\n\n/**\n * Recover enum columns from a table's `sqlite_master.sql` text. Only checks\n * following OUR naming convention are recognized; foreign CHECK constraints\n * are ignored (and — documented limitation — do not survive a table rebuild).\n */\nexport function parseSqliteEnumChecks(params: { tableSql: string }): ParsedEnumCheck[] {\n const result: ParsedEnumCheck[] = [];\n for (const match of params.tableSql.matchAll(ENUM_CHECK_PATTERN)) {\n const enumName = (match[2] as string).replaceAll('\"\"', '\"');\n const column = (match[3] as string).replaceAll('\"\"', '\"');\n const values: string[] = [];\n for (const value of (match[4] as string).matchAll(/'((?:[^']|'')*)'/g)) {\n values.push((value[1] as string).replaceAll(\"''\", \"'\"));\n }\n result.push({ column, enumName, values });\n }\n return result;\n}\n",
|
|
12
12
|
"/**\n * MySQL column-type mapping (IR → column type and back), native-type\n * normalization, comparison keys and default rendering.\n *\n * dialect-matrix §2: String → varchar(191) by default (191 because\n * utf8mb4 × 4 bytes keeps the column inside the 767-byte legacy index-key\n * limit; `@db.Text` opts into TEXT, which we never index), Boolean →\n * tinyint(1) (THE marker that lets introspection recover Boolean),\n * Int → int, BigInt → bigint, Float → double, Decimal → decimal(65,30),\n * DateTime → datetime(3), Json → json, Bytes → longblob, enums → inline\n * `ENUM('A', 'B')` — nameless in the database, so comparison keys use the\n * VALUE LIST (like sqlite) and a pulled schema synthesizes\n * `<Table>_<column>` enum names. Scalar lists are unsupported.\n */\n\nimport { VibeError, isEnumType, unsupportedCapability } from \"@vibeorm/schema\";\nimport type { EnumIR, FieldIR, ScalarType } from \"@vibeorm/schema\";\nimport { resolveEnumValues } from \"./enum-values.ts\";\nimport { defaultFingerprint, quotePgString } from \"./postgres-types.ts\";\n\n// ─── Canonical scalar mapping (dialect-matrix §2) ─────────────────\n\n/** IR scalar → canonical mysql column type (information_schema spelling). */\nexport const SCALAR_TO_MYSQL: Readonly<Record<ScalarType, string>> = {\n String: \"varchar(191)\",\n Boolean: \"tinyint(1)\",\n Int: \"int\",\n BigInt: \"bigint\",\n Float: \"double\",\n Decimal: \"decimal(65,30)\",\n DateTime: \"datetime(3)\",\n Json: \"json\",\n Bytes: \"longblob\",\n};\n\n/** Render-time backstop for scalar-list columns (the differ refuses earlier). */\nexport function refuseMysqlScalarList(params: { field: FieldIR }): never {\n throw unsupportedCapability({\n dialect: \"mysql\",\n feature: `scalar list column \"${params.field.name}\"`,\n hint: \"mysql has no array column type — model the list as a separate table or a JSON column\",\n });\n}\n\n// ─── Native-type normalization ────────────────────────────────────\n\nconst MYSQL_NATIVE_ALIASES: Readonly<Record<string, string>> = {\n integer: \"int\",\n dec: \"decimal\",\n numeric: \"decimal\",\n bool: \"tinyint(1)\",\n boolean: \"tinyint(1)\",\n character: \"char\",\n};\n\n/**\n * Normalize a mysql type string for comparison: lowercase, whitespace\n * stripped, base de-aliased, integer display widths dropped (mysql 8.0.19+\n * omits them; older catalogs report `int(11)`) — EXCEPT `tinyint(1)`, which is\n * the Boolean marker and must survive normalization.\n */\nexport function normalizeMysqlType(params: { raw: string }): string {\n const compact = params.raw.toLowerCase().replace(/\\s+/g, \"\");\n if (compact === \"tinyint(1)\" || compact === \"bool\" || compact === \"boolean\") return \"tinyint(1)\";\n const match = compact.match(/^([a-z_0-9]+)(\\(.*\\))?(.*)$/);\n if (match === null) return compact;\n const base = MYSQL_NATIVE_ALIASES[match[1] as string] ?? (match[1] as string);\n let modifier = match[2] ?? \"\";\n if (/^(tinyint|smallint|mediumint|int|bigint)$/.test(base)) modifier = \"\";\n return `${base}${modifier}${match[3] ?? \"\"}`;\n}\n\n// ─── Comparison keys ──────────────────────────────────────────────\n\n/**\n * Comparison key for a column on mysql. Enum columns key on their VALUE LIST\n * (order-sensitive — mysql ENUM order defines sort order); a native type equal\n * to the scalar's canonical mapping is dropped so `String` and\n * `String @db.VarChar(191)` compare equal.\n */\nexport function mysqlColumnTypeKey(params: {\n field: FieldIR;\n enums: ReadonlyMap<string, EnumIR>;\n}): string {\n const { field, enums } = params;\n if (field.isUnsupported === true) {\n return `u:${normalizeMysqlType({ raw: field.nativeType ?? \"\" })}`;\n }\n if (isEnumType(field.type)) {\n const values = resolveEnumValues({ name: field.type.enum, enums });\n return values === undefined ? `e:?${field.type.enum}` : `e:${values.join(\"|\")}`;\n }\n const listSuffix = field.isList ? \"[]\" : \"\";\n if (field.nativeType !== undefined) {\n const normalized = normalizeMysqlType({ raw: field.nativeType });\n const canonical = normalizeMysqlType({ raw: SCALAR_TO_MYSQL[field.type] });\n if (normalized !== canonical) return `n:${normalized}${listSuffix}`;\n }\n return `t:${normalizeMysqlType({ raw: SCALAR_TO_MYSQL[field.type] })}${listSuffix}`;\n}\n\n/**\n * Default fingerprint on mysql: postgres rules verbatim — tinyint(1) lets the\n * introspector map `DEFAULT '1'` back to a boolean literal, so booleans keep\n * their `bool:` fingerprint (unlike sqlite).\n */\nexport function mysqlDefaultFingerprint(params: { field: FieldIR }): string | null {\n return defaultFingerprint({ field: params.field });\n}\n\n// ─── Column type & default rendering ──────────────────────────────\n\n/** Render the mysql column type for a field (no NOT NULL, no default). */\nexport function mysqlColumnTypeSql(params: {\n field: FieldIR;\n enums: ReadonlyMap<string, EnumIR>;\n}): string {\n const { field, enums } = params;\n if (field.isUnsupported === true) {\n if (field.nativeType === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `unsupported column \"${field.name}\" carries no native type to render`,\n meta: { field: field.name },\n });\n }\n return field.nativeType;\n }\n if (field.isList) refuseMysqlScalarList({ field });\n if (isEnumType(field.type)) {\n const values = resolveEnumValues({ name: field.type.enum, enums });\n if (values === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `enum \"${field.type.enum}\" on column \"${field.name}\" is not declared in the schema`,\n meta: { field: field.name, enum: field.type.enum },\n });\n }\n return `ENUM(${values.map((value) => quotePgString({ value })).join(\", \")})`;\n }\n if (field.nativeType !== undefined) {\n const normalized = normalizeMysqlType({ raw: field.nativeType });\n const canonical = normalizeMysqlType({ raw: SCALAR_TO_MYSQL[field.type] });\n if (normalized !== canonical) return field.nativeType.toLowerCase();\n }\n return SCALAR_TO_MYSQL[field.type];\n}\n\n/**\n * Render the `DEFAULT` expression for a field on mysql, or `undefined` when\n * the column takes none. `now()` renders `CURRENT_TIMESTAMP(3)` (precision\n * must match the datetime(3) column); booleans store as 1/0.\n */\nexport function mysqlDefaultSql(params: { field: FieldIR }): string | undefined {\n const def = params.field.default;\n if (def === undefined) return undefined;\n switch (def.kind) {\n case \"autoincrement\":\n case \"uuid\":\n case \"cuid\":\n case \"nanoid\":\n case \"ulid\":\n return undefined;\n case \"now\":\n return \"CURRENT_TIMESTAMP(3)\";\n case \"literal\": {\n const value = def.value;\n if (typeof value === \"boolean\") return value ? \"1\" : \"0\";\n if (typeof value === \"number\") return String(value);\n return quotePgString({ value });\n }\n case \"enumValue\":\n return quotePgString({ value: def.value });\n case \"dbgenerated\":\n return def.sql;\n }\n}\n\n// ─── COLUMN_TYPE parsing (introspection) ──────────────────────────\n\n/** Parse an information_schema `COLUMN_TYPE` of form `enum('A','B')`. */\nexport function parseMysqlEnumColumnType(params: { columnType: string }): string[] | null {\n const match = params.columnType.trim().match(/^enum\\((.*)\\)$/i);\n if (match === null) return null;\n const values: string[] = [];\n for (const value of (match[1] as string).matchAll(/'((?:[^']|'')*)'/g)) {\n values.push((value[1] as string).replaceAll(\"''\", \"'\"));\n }\n return values;\n}\n",
|
|
13
|
-
"/**\n * Postgres DDL renderer: migration steps → SQL statements.\n *\n * Every identifier is quoted through `postgresDialect.quoteIdent` — the ONE\n * quoting decision point (@vibeorm/sql). Choices, each pinned by a renderer\n * test:\n *\n * - autoincrement renders as `GENERATED BY DEFAULT AS IDENTITY` (SQL-standard,\n * no sequence-name coupling; postgres ≥10 and pglite both support it) — not\n * SERIAL. The introspector maps identity columns back to autoincrement.\n * - `DROP TABLE ... CASCADE`: inbound FK constraints drop with the table.\n * - scalar→array type changes carry the LEARNINGS `USING CASE WHEN col IS NULL\n * THEN NULL ELSE ARRAY[col] END` repair clause (postgres cannot implicit-cast).\n * - `ALTER TYPE ... ADD VALUE IF NOT EXISTS` appends at the end of the enum\n * (no BEFORE/AFTER positioning); fine inside a transaction on postgres ≥12.\n * - Unsupported columns render their `nativeType` verbatim and migrate like\n * any other column.\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\nimport type { FieldIR } from \"@vibeorm/schema\";\nimport { postgresDialect } from \"@vibeorm/sql\";\nimport {\n CASCADE_ACTION_SQL,\n columnTypeSql,\n defaultSql,\n isIdentityColumn,\n quotePgString,\n} from \"../postgres-types.ts\";\nimport type { MigrationStep } from \"../types.ts\";\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/** Render migration steps to postgres SQL (one string per statement, in order). */\nexport function renderPostgresSteps(params: { steps: readonly MigrationStep[] }): string[] {\n return params.steps.flatMap((step) => renderStep({ step }));\n}\n\n// ─── Per-step rendering ───────────────────────────────────────────\n\nfunction renderStep(params: { step: MigrationStep }): string[] {\n const { step } = params;\n switch (step.kind) {\n case \"createEnum\": {\n const name = step.enumDef.dbName ?? step.enumDef.name;\n const values = step.enumDef.values.map((value) => quotePgString({ value })).join(\", \");\n return [`CREATE TYPE ${q(name)} AS ENUM (${values});`];\n }\n case \"dropEnum\":\n return [`DROP TYPE ${q(step.enumName)};`];\n case \"addEnumValue\":\n return [\n `ALTER TYPE ${q(step.enumName)} ADD VALUE IF NOT EXISTS ${quotePgString({ value: step.value })};`,\n ];\n case \"createTable\": {\n const lines = step.columns.map((column) => ` ${columnDefSql({ field: column })}`);\n if (step.primaryKey.length > 0) {\n const pkCols = step.primaryKey.map((column) => q(column)).join(\", \");\n lines.push(` CONSTRAINT ${q(`${step.table}_pkey`)} PRIMARY KEY (${pkCols})`);\n }\n return [`CREATE TABLE ${q(step.table)} (\\n${lines.join(\",\\n\")}\\n);`];\n }\n case \"dropTable\":\n case \"dropJoinTable\":\n return [`DROP TABLE ${q(step.table)} CASCADE;`];\n case \"dropView\":\n // No CASCADE: a view-on-view dependency fails LOUDLY instead of silently\n // taking a surviving dependent view with it (#26).\n return [`DROP VIEW IF EXISTS ${q(step.table)};`];\n case \"addColumn\":\n return [`ALTER TABLE ${q(step.table)} ADD COLUMN ${columnDefSql({ field: step.column })};`];\n case \"dropColumn\":\n return [`ALTER TABLE ${q(step.table)} DROP COLUMN ${q(step.column)};`];\n case \"alterColumn\":\n return renderAlterColumn({ step });\n case \"createIndex\": {\n const unique = step.unique ? \"UNIQUE \" : \"\";\n const using = !step.unique && step.indexKind !== \"btree\" ? ` USING ${step.indexKind}` : \"\";\n const cols = step.columns\n .map((column) => `${q(column.name)}${column.desc ? \" DESC\" : \"\"}`)\n .join(\", \");\n const where = step.where === undefined ? \"\" : ` WHERE ${step.where}`;\n return [\n `CREATE ${unique}INDEX ${q(step.name)} ON ${q(step.table)}${using} (${cols})${where};`,\n ];\n }\n case \"dropIndex\":\n return [`DROP INDEX ${q(step.name)};`];\n case \"addForeignKey\": {\n const cols = step.columns.map((column) => q(column)).join(\", \");\n const refCols = step.refColumns.map((column) => q(column)).join(\", \");\n return [\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(step.constraintName)} FOREIGN KEY (${cols}) REFERENCES ${q(step.refTable)} (${refCols}) ON DELETE ${CASCADE_ACTION_SQL[step.onDelete]} ON UPDATE ${CASCADE_ACTION_SQL[step.onUpdate]};`,\n ];\n }\n case \"dropForeignKey\":\n return [`ALTER TABLE ${q(step.table)} DROP CONSTRAINT ${q(step.constraintName)};`];\n case \"createJoinTable\": {\n // Prisma's implicit join-table shape: columns \"A\"/\"B\", a unique index on\n // (A, B), an index on B, both FKs cascading (see @vibeorm/schema m2m.ts).\n const aType = columnTypeSql({ field: { ...step.a.field, isList: false } });\n const bType = columnTypeSql({ field: { ...step.b.field, isList: false } });\n return [\n `CREATE TABLE ${q(step.table)} (\\n \"A\" ${aType} NOT NULL,\\n \"B\" ${bType} NOT NULL\\n);`,\n `CREATE UNIQUE INDEX ${q(`${step.table}_AB_unique`)} ON ${q(step.table)} (\"A\", \"B\");`,\n `CREATE INDEX ${q(`${step.table}_B_index`)} ON ${q(step.table)} (\"B\");`,\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(`${step.table}_A_fkey`)} FOREIGN KEY (\"A\") REFERENCES ${q(step.a.table)} (${q(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(`${step.table}_B_fkey`)} FOREIGN KEY (\"B\") REFERENCES ${q(step.b.table)} (${q(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,\n ];\n }\n case \"addPrimaryKey\": {\n const cols = step.columns.map((column) => q(column)).join(\", \");\n return [\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(`${step.table}_pkey`)} PRIMARY KEY (${cols});`,\n ];\n }\n case \"dropPrimaryKey\":\n return [`ALTER TABLE ${q(step.table)} DROP CONSTRAINT ${q(`${step.table}_pkey`)};`];\n }\n}\n\n// ─── Column pieces ────────────────────────────────────────────────\n\nfunction columnDefSql(params: { field: FieldIR }): string {\n const { field } = params;\n const name = q(field.dbName ?? field.name);\n\n if (field.default?.kind === \"autoincrement\" && !isIdentityColumn({ field })) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `autoincrement default on \"${field.name}\" requires a non-list Int or BigInt column`,\n meta: { field: field.name },\n });\n }\n\n let def = `${name} ${columnTypeSql({ field })}`;\n if (isIdentityColumn({ field })) def += \" GENERATED BY DEFAULT AS IDENTITY\";\n if (!field.isOptional) def += \" NOT NULL\";\n const defaultExpr = defaultSql({ field });\n if (defaultExpr !== undefined) def += ` DEFAULT ${defaultExpr}`;\n return def;\n}\n\nfunction renderAlterColumn(params: {\n step: Extract<MigrationStep, { kind: \"alterColumn\" }>;\n}): string[] {\n const { step } = params;\n const statements: string[] = [];\n const column = q(step.column);\n const alterPrefix = `ALTER TABLE ${q(step.table)} ALTER COLUMN ${column}`;\n\n if (step.changes.includes(\"type\")) {\n // LEARNINGS: scalar→array of the same base type needs a USING repair —\n // postgres cannot implicit-cast a scalar into a one-element array.\n const scalarToArray =\n step.to.isList && !step.from.isList\n ? ` USING CASE WHEN ${column} IS NULL THEN NULL ELSE ARRAY[${column}] END`\n : \"\";\n statements.push(\n `${alterPrefix} SET DATA TYPE ${columnTypeSql({ field: step.to })}${scalarToArray};`,\n );\n }\n\n if (step.changes.includes(\"nullability\")) {\n statements.push(`${alterPrefix} ${step.to.isOptional ? \"DROP\" : \"SET\"} NOT NULL;`);\n }\n\n if (step.changes.includes(\"default\")) {\n if (step.to.default?.kind === \"autoincrement\") {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `cannot add autoincrement to existing column \"${step.table}\".\"${step.column}\" — drop and recreate the column instead`,\n meta: { table: step.table, column: step.column },\n });\n }\n const defaultExpr = defaultSql({ field: step.to });\n statements.push(\n defaultExpr === undefined\n ? `${alterPrefix} DROP DEFAULT;`\n : `${alterPrefix} SET DEFAULT ${defaultExpr};`,\n );\n }\n\n return statements;\n}\n\n// ─── Quoting ──────────────────────────────────────────────────────\n\nfunction q(name: string): string {\n return postgresDialect.quoteIdent({ name });\n}\n",
|
|
14
|
-
"/**\n * SQLite DDL renderer: migration steps → SQL statements, including THE TABLE\n * REBUILD — sqlite has no ALTER COLUMN, cannot add/drop constraints, and its\n * DROP COLUMN is heavily restricted, so any such step compiles to the\n * documented 12-step recipe (https://sqlite.org/lang_altertable.html §7),\n * emitted as an ordered, self-contained statement block:\n *\n * PRAGMA foreign_keys=OFF;\n * BEGIN;\n * CREATE TABLE \"T_new\" (…target shape: columns, PK, FKs, enum CHECKs…);\n * INSERT INTO \"T_new\" (common cols) SELECT common cols FROM \"T\";\n * DROP TABLE \"T\";\n * ALTER TABLE \"T_new\" RENAME TO \"T\";\n * CREATE …INDEX… (every index of the target table);\n * PRAGMA foreign_key_check;\n * COMMIT;\n * PRAGMA foreign_keys=ON;\n *\n * Because the block manages its own transaction (PRAGMA foreign_keys is a\n * no-op inside one), callers must NOT wrap scripts containing it — push and\n * the runner detect this via `usesSelfManagedTransactions` (execute.ts).\n * Rebuild blocks are emitted AFTER all other statements so a rebuilt table's\n * new FKs can reference tables created earlier in the same script.\n *\n * Cheap paths are preferred wherever sqlite's plain ALTER suffices:\n * `ADD COLUMN` (unless the column is required without a literal default, or\n * defaults to CURRENT_TIMESTAMP / an expression — both forbidden in ADD\n * COLUMN) and `DROP COLUMN` (unless the column is in the PK, any index or\n * partial-index predicate, an FK on either side, or carries an enum CHECK).\n *\n * Column-value transfer on rebuild: dropped columns are omitted, added\n * columns take their default (or NULL), type-changed columns are a PLAIN COPY\n * — sqlite's flexible typing keeps the stored values as-is, so e.g. non-numeric\n * TEXT survives verbatim inside an INTEGER column (documented lossy-ness:\n * nothing is coerced, nothing is validated beyond the new CHECK constraints).\n *\n * Other pinned choices:\n * - autoincrement renders `INTEGER PRIMARY KEY AUTOINCREMENT` (monotonic ids,\n * Prisma parity) — plain `INTEGER PRIMARY KEY` would reuse rowids after\n * deletes. The `PRIMARY KEY AUTOINCREMENT` text is also the introspection\n * marker. Costs the `sqlite_sequence` bookkeeping table (skipped on pull).\n * - Composite / non-autoincrement PKs render as an unnamed table-level\n * `PRIMARY KEY (…)` (sqlite keeps constraint names only as noise).\n * - Enums render TEXT + a NAMED column-level CHECK (see sqlite-types.ts) —\n * the name (`<table>_<column>_enum_<Enum>`) is how pull recovers the enum.\n * - `DROP TABLE` has no CASCADE on sqlite; table drops are topologically\n * ordered (referencing tables first) using the `from` schema.\n * - Index kinds other than btree/unique throw VIBE_UNSUPPORTED_CAPABILITY.\n */\n\nimport { VibeError, isEnumType, unsupportedCapability } from \"@vibeorm/schema\";\nimport type { EnumIR, FieldIR, SchemaIR } from \"@vibeorm/schema\";\nimport { sqliteDialect } from \"@vibeorm/sql\";\nimport { resolveEnumValues } from \"../enum-values.ts\";\nimport { orderDropsChildrenFirst } from \"./drop-order.ts\";\nimport { normalizeSchema } from \"../normalize.ts\";\nimport type { NormalizedSchema, NormalizedTable } from \"../normalize.ts\";\nimport { CASCADE_ACTION_SQL, quotePgString } from \"../postgres-types.ts\";\nimport {\n sqliteDefaultSql,\n sqliteEnumCheckName,\n sqliteStorageType,\n} from \"../sqlite-types.ts\";\nimport { describeStep } from \"../types.ts\";\nimport type { IndexColumn, MigrationStep } from \"../types.ts\";\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/**\n * Render migration steps to sqlite SQL. `from`/`to` (the schemas that produced\n * the steps) are required whenever a step triggers a table rebuild or renders\n * an enum column — `generateMigration` and `push` always pass them.\n */\nexport function renderSqliteSteps(params: {\n steps: readonly MigrationStep[];\n from?: SchemaIR;\n to?: SchemaIR;\n}): string[] {\n const { steps } = params;\n const fromNorm = params.from === undefined\n ? undefined\n : normalizeSchema({ schema: params.from, dialect: \"sqlite\" });\n const toNorm = params.to === undefined\n ? undefined\n : normalizeSchema({ schema: params.to, dialect: \"sqlite\" });\n const enums: ReadonlyMap<string, EnumIR> = toNorm?.enums ?? new Map();\n\n // ── Classification: which tables need the rebuild recipe? ──\n const createdTables = new Set<string>();\n for (const step of steps) {\n if (step.kind === \"createTable\" || step.kind === \"createJoinTable\") {\n createdTables.add(step.table);\n }\n }\n\n const foldedFks = new Map<string, Extract<MigrationStep, { kind: \"addForeignKey\" }>[]>();\n const rebuildTables: string[] = []; // Insertion order = deterministic block order.\n const markRebuild = (table: string): void => {\n if (!rebuildTables.includes(table)) rebuildTables.push(table);\n };\n\n for (const step of steps) {\n switch (step.kind) {\n case \"alterColumn\":\n case \"dropForeignKey\":\n case \"addPrimaryKey\":\n case \"dropPrimaryKey\":\n markRebuild(step.table);\n break;\n case \"addColumn\":\n if (!isCheapAddColumn({ field: step.column })) markRebuild(step.table);\n break;\n case \"dropColumn\":\n if (!canCheapDropColumn({ table: step.table, column: step.column, fromNorm })) {\n markRebuild(step.table);\n }\n break;\n case \"addForeignKey\":\n if (createdTables.has(step.table)) {\n const list = foldedFks.get(step.table);\n if (list === undefined) foldedFks.set(step.table, [step]);\n else list.push(step);\n } else {\n markRebuild(step.table);\n }\n break;\n default:\n break;\n }\n }\n const rebuildSet = new Set(rebuildTables);\n\n // ── Topological drop order (referencing tables first — no CASCADE). ──\n const dropNames = steps\n .filter((step) => step.kind === \"dropTable\" || step.kind === \"dropJoinTable\")\n .map((step) => (step as Extract<MigrationStep, { kind: \"dropTable\" }>).table);\n const orderedDrops = orderDropsChildrenFirst({ names: dropNames, fromNorm });\n let dropCursor = 0;\n\n // ── Emission: step order, rebuild-triggering steps absorbed. ──\n const statements: string[] = [];\n for (const step of steps) {\n switch (step.kind) {\n case \"createEnum\":\n case \"dropEnum\":\n case \"addEnumValue\":\n break; // No standalone enum objects on sqlite — enums live in columns.\n case \"createTable\":\n statements.push(\n createTableSql({\n table: step.table,\n constraintTable: step.table,\n columns: step.columns,\n primaryKey: step.primaryKey,\n fks: (foldedFks.get(step.table) ?? []).map((fk) => ({\n constraintName: fk.constraintName,\n columns: fk.columns,\n refTable: fk.refTable,\n refColumns: fk.refColumns,\n onDelete: CASCADE_ACTION_SQL[fk.onDelete],\n onUpdate: CASCADE_ACTION_SQL[fk.onUpdate],\n })),\n enums,\n }),\n );\n break;\n case \"createJoinTable\": {\n const aType = sqliteStorageType({ field: { ...step.a.field, isList: false } });\n const bType = sqliteStorageType({ field: { ...step.b.field, isList: false } });\n statements.push(\n `CREATE TABLE ${q(step.table)} (\\n \"A\" ${aType} NOT NULL,\\n \"B\" ${bType} NOT NULL,\\n CONSTRAINT ${q(`${step.table}_A_fkey`)} FOREIGN KEY (\"A\") REFERENCES ${q(step.a.table)} (${q(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE,\\n CONSTRAINT ${q(`${step.table}_B_fkey`)} FOREIGN KEY (\"B\") REFERENCES ${q(step.b.table)} (${q(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE\\n);`,\n `CREATE UNIQUE INDEX ${q(`${step.table}_AB_unique`)} ON ${q(step.table)} (\"A\", \"B\");`,\n `CREATE INDEX ${q(`${step.table}_B_index`)} ON ${q(step.table)} (\"B\");`,\n );\n break;\n }\n case \"addColumn\":\n if (!rebuildSet.has(step.table)) {\n statements.push(\n `ALTER TABLE ${q(step.table)} ADD COLUMN ${columnDefSql({\n field: step.column,\n constraintTable: step.table,\n enums,\n inlinePkAutoincrement: false,\n })};`,\n );\n }\n break;\n case \"dropColumn\":\n if (!rebuildSet.has(step.table)) {\n statements.push(`ALTER TABLE ${q(step.table)} DROP COLUMN ${q(step.column)};`);\n }\n break;\n case \"createIndex\":\n if (!rebuildSet.has(step.table)) {\n statements.push(\n createIndexSql({\n table: step.table,\n name: step.name,\n unique: step.unique,\n kind: step.indexKind,\n columns: step.columns,\n where: step.where,\n }),\n );\n }\n break;\n case \"dropIndex\":\n // Always emitted — dropping an index of a soon-rebuilt table early is\n // harmless (the rebuild recreates the target set) and keeps the\n // GLOBAL index namespace clean for later creates.\n statements.push(`DROP INDEX ${q(step.name)};`);\n break;\n case \"dropTable\":\n case \"dropJoinTable\":\n statements.push(`DROP TABLE ${q(orderedDrops[dropCursor] as string)};`);\n dropCursor += 1;\n break;\n case \"dropView\":\n // Ordered first by the differ (#26) — a leftover view would otherwise\n // block the column drops (or rebuilds) beneath it.\n statements.push(`DROP VIEW IF EXISTS ${q(step.table)};`);\n break;\n case \"alterColumn\":\n case \"addForeignKey\":\n case \"dropForeignKey\":\n case \"addPrimaryKey\":\n case \"dropPrimaryKey\":\n if (\n (step.kind === \"addForeignKey\" && createdTables.has(step.table)) ||\n !rebuildSet.has(step.table)\n ) {\n break; // Folded into CREATE TABLE, or absorbed by that table's rebuild.\n }\n requireSchemas({ step, fromNorm, toNorm });\n break;\n }\n }\n\n // ── Rebuild blocks last (new FK targets already exist by now). ──\n for (const table of rebuildTables) {\n const step = steps.find(\n (candidate) => \"table\" in candidate && candidate.table === table,\n ) as MigrationStep;\n requireSchemas({ step, fromNorm, toNorm });\n statements.push(\n ...renderTableRebuild({\n table,\n from: fromNorm as NormalizedSchema,\n to: toNorm as NormalizedSchema,\n }),\n );\n }\n\n return statements;\n}\n\n// ─── The table rebuild ────────────────────────────────────────────\n\nfunction renderTableRebuild(params: {\n table: string;\n from: NormalizedSchema;\n to: NormalizedSchema;\n}): string[] {\n const { table, from, to } = params;\n const source = from.tables.get(table);\n const target = to.tables.get(table);\n if (source === undefined || target === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `cannot rebuild \"${table}\" — the table is missing from the ${source === undefined ? \"from\" : \"to\"} schema`,\n meta: { table },\n });\n }\n\n const tmp = `${table}_new`;\n const statements: string[] = [\"PRAGMA foreign_keys=OFF;\", \"BEGIN;\"];\n\n statements.push(\n createTableSql({\n table: tmp,\n // CHECK-constraint names carry the FINAL table name so introspection\n // recovers enums after the RENAME.\n constraintTable: table,\n columns: [...target.columns.values()].map((column) => column.field),\n primaryKey: target.pk,\n fks: [...target.fks.values()].map((fk) => ({\n constraintName: fk.constraintName,\n columns: fk.columns,\n refTable: fk.refTable,\n refColumns: fk.refColumns,\n onDelete: CASCADE_ACTION_SQL[fk.onDelete],\n onUpdate: CASCADE_ACTION_SQL[fk.onUpdate],\n })),\n enums: to.enums,\n }),\n );\n\n // Transfer: target-order intersection of the two column sets. Dropped\n // columns are omitted; added columns take their default/NULL; type changes\n // copy values verbatim (see module doc for the lossy-ness contract).\n const common = [...target.columns.keys()].filter((name) => source.columns.has(name));\n if (common.length > 0) {\n const cols = common.map((name) => q(name)).join(\", \");\n statements.push(`INSERT INTO ${q(tmp)} (${cols}) SELECT ${cols} FROM ${q(table)};`);\n }\n\n statements.push(`DROP TABLE ${q(table)};`, `ALTER TABLE ${q(tmp)} RENAME TO ${q(table)};`);\n\n for (const index of target.indexes.values()) {\n statements.push(\n createIndexSql({\n table,\n name: index.name,\n unique: index.unique,\n kind: index.kind,\n columns: index.columns,\n where: index.where,\n }),\n );\n }\n\n statements.push(\"PRAGMA foreign_key_check;\", \"COMMIT;\", \"PRAGMA foreign_keys=ON;\");\n return statements;\n}\n\n// ─── Cheap-path detection ─────────────────────────────────────────\n\n/**\n * `ALTER TABLE … ADD COLUMN` suffices unless sqlite forbids the shape: the\n * new column may not default to CURRENT_* or an expression, and a NOT NULL\n * column needs a literal default (app-level id generators provide none).\n */\nfunction isCheapAddColumn(params: { field: FieldIR }): boolean {\n const { field } = params;\n const kind = field.default?.kind;\n if (kind === \"autoincrement\" || kind === \"now\" || kind === \"dbgenerated\") return false;\n const hasLiteralDefault = kind === \"literal\" || kind === \"enumValue\";\n if (!field.isOptional && !hasLiteralDefault) return false;\n return true;\n}\n\n/**\n * `ALTER TABLE … DROP COLUMN` works only when nothing references the column:\n * not the PK, no index (or partial-index predicate), no FK on either side, no\n * enum CHECK. Without the `from` schema the answer is unknowable → rebuild.\n */\nfunction canCheapDropColumn(params: {\n table: string;\n column: string;\n fromNorm: NormalizedSchema | undefined;\n}): boolean {\n const { table, column, fromNorm } = params;\n if (fromNorm === undefined) return false;\n const fromTable = fromNorm.tables.get(table);\n if (fromTable === undefined) return false;\n\n if (fromTable.pk.includes(column)) return false;\n const normalized = fromTable.columns.get(column);\n if (normalized !== undefined && isEnumType(normalized.field.type)) return false;\n for (const index of fromTable.indexes.values()) {\n if (index.columns.some((indexColumn) => indexColumn.name === column)) return false;\n if (index.where !== undefined && index.where.includes(column)) return false;\n }\n for (const fk of fromTable.fks.values()) {\n if (fk.columns.includes(column)) return false;\n }\n for (const other of fromNorm.tables.values()) {\n for (const fk of other.fks.values()) {\n if (fk.refTable === table && fk.refColumns.includes(column)) return false;\n }\n }\n return true;\n}\n\n// ─── Table & column pieces ────────────────────────────────────────\n\ntype InlineFk = {\n readonly constraintName: string;\n readonly columns: readonly string[];\n readonly refTable: string;\n readonly refColumns: readonly string[];\n readonly onDelete: string;\n readonly onUpdate: string;\n};\n\nfunction createTableSql(params: {\n table: string;\n /** Table name used in CHECK-constraint names (the FINAL name on rebuilds). */\n constraintTable: string;\n columns: readonly FieldIR[];\n primaryKey: readonly string[];\n fks: readonly InlineFk[];\n enums: ReadonlyMap<string, EnumIR>;\n}): string {\n const { table, constraintTable, columns, primaryKey, fks, enums } = params;\n\n const autoincrementPk = autoincrementPkColumn({ columns, primaryKey });\n const lines = columns.map(\n (field) =>\n ` ${columnDefSql({\n field,\n constraintTable,\n enums,\n inlinePkAutoincrement: (field.dbName ?? field.name) === autoincrementPk,\n })}`,\n );\n\n if (primaryKey.length > 0 && autoincrementPk === undefined) {\n lines.push(` PRIMARY KEY (${primaryKey.map((column) => q(column)).join(\", \")})`);\n }\n for (const fk of fks) {\n lines.push(\n ` CONSTRAINT ${q(fk.constraintName)} FOREIGN KEY (${fk.columns.map((column) => q(column)).join(\", \")}) REFERENCES ${q(fk.refTable)} (${fk.refColumns.map((column) => q(column)).join(\", \")}) ON DELETE ${fk.onDelete} ON UPDATE ${fk.onUpdate}`,\n );\n }\n\n return `CREATE TABLE ${q(table)} (\\n${lines.join(\",\\n\")}\\n);`;\n}\n\n/**\n * The db name of the single autoincrement Int/BigInt PK column — the one\n * column rendered inline as `INTEGER PRIMARY KEY AUTOINCREMENT` — or\n * undefined when the table has no such PK.\n */\nfunction autoincrementPkColumn(params: {\n columns: readonly FieldIR[];\n primaryKey: readonly string[];\n}): string | undefined {\n const { columns, primaryKey } = params;\n if (primaryKey.length !== 1) return undefined;\n const pkName = primaryKey[0] as string;\n const field = columns.find((candidate) => (candidate.dbName ?? candidate.name) === pkName);\n if (field === undefined) return undefined;\n const eligible =\n field.default?.kind === \"autoincrement\" &&\n !field.isList &&\n !isEnumType(field.type) &&\n (field.type === \"Int\" || field.type === \"BigInt\");\n return eligible ? pkName : undefined;\n}\n\nfunction columnDefSql(params: {\n field: FieldIR;\n constraintTable: string;\n enums: ReadonlyMap<string, EnumIR>;\n inlinePkAutoincrement: boolean;\n}): string {\n const { field, constraintTable, enums, inlinePkAutoincrement } = params;\n const name = field.dbName ?? field.name;\n\n if (field.default?.kind === \"autoincrement\" && !inlinePkAutoincrement) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `autoincrement on sqlite requires \"${field.name}\" to be the single-column Int or BigInt primary key`,\n meta: { field: field.name },\n });\n }\n if (inlinePkAutoincrement) {\n return `${q(name)} INTEGER PRIMARY KEY AUTOINCREMENT`;\n }\n\n let def = `${q(name)} ${sqliteStorageType({ field })}`;\n if (!field.isOptional) def += \" NOT NULL\";\n const defaultExpr = sqliteDefaultSql({ field });\n if (defaultExpr !== undefined) def += ` DEFAULT ${defaultExpr}`;\n\n if (isEnumType(field.type) && field.isUnsupported !== true) {\n const enumName = field.type.enum;\n const values = resolveEnumValues({ name: enumName, enums });\n if (values === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `enum \"${enumName}\" on column \"${field.name}\" is not declared in the schema — sqlite rendering needs the target schema's enums for the CHECK constraint`,\n meta: { field: field.name, enum: enumName },\n });\n }\n const check = sqliteEnumCheckName({ table: constraintTable, column: name, enumName });\n def += ` CONSTRAINT ${q(check)} CHECK (${q(name)} IN (${values\n .map((value) => quotePgString({ value }))\n .join(\", \")}))`;\n }\n\n return def;\n}\n\nfunction createIndexSql(params: {\n table: string;\n name: string;\n unique: boolean;\n kind: string;\n columns: readonly IndexColumn[];\n where: string | undefined;\n}): string {\n const { table, name, unique, kind, columns, where } = params;\n if (!unique && kind !== \"btree\") {\n throw unsupportedCapability({\n dialect: \"sqlite\",\n feature: `index kind \"${kind}\" (index \"${name}\")`,\n hint: \"sqlite indexes are btree only; use an extension-specific virtual table for others\",\n });\n }\n // SQLITE-2: a Decimal column stores as TEXT and every compare/order site\n // reads CAST(col AS REAL) (B4) — a plain-column index can never serve those\n // (EQP-proven SCAN with the index present). Index the same expression, so\n // sqlite's expression-index matching kicks in.\n const cols = columns\n .map(\n (column) =>\n `${column.decimal === true ? `CAST(${q(column.name)} AS REAL)` : q(column.name)}${column.desc ? \" DESC\" : \"\"}`,\n )\n .join(\", \");\n const whereClause = where === undefined ? \"\" : ` WHERE ${where}`;\n return `CREATE ${unique ? \"UNIQUE \" : \"\"}INDEX ${q(name)} ON ${q(table)} (${cols})${whereClause};`;\n}\n\n// ─── Drop ordering ────────────────────────────────────────────────\n\n\n// ─── Context guard & quoting ──────────────────────────────────────\n\nfunction requireSchemas(params: {\n step: MigrationStep;\n fromNorm: NormalizedSchema | undefined;\n toNorm: NormalizedSchema | undefined;\n}): void {\n const { step, fromNorm, toNorm } = params;\n if (fromNorm !== undefined && toNorm !== undefined) return;\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `sqlite step \"${describeStep({ step })}\" requires a table rebuild — renderSteps needs the { from, to } schemas to construct it`,\n meta: { step: step.kind },\n });\n}\n\nfunction q(name: string): string {\n return sqliteDialect.quoteIdent({ name });\n}\n",
|
|
13
|
+
"/**\n * Postgres DDL renderer: migration steps → SQL statements.\n *\n * Every identifier is quoted through `postgresDialect.quoteIdent` — the ONE\n * quoting decision point (@vibeorm/sql). Choices, each pinned by a renderer\n * test:\n *\n * - autoincrement renders as `GENERATED BY DEFAULT AS IDENTITY` (SQL-standard,\n * no sequence-name coupling; postgres ≥10 and pglite both support it) — not\n * SERIAL. The introspector maps identity columns back to autoincrement.\n * - `DROP TABLE ... CASCADE`: inbound FK constraints drop with the table.\n * - scalar→array type changes carry the LEARNINGS `USING CASE WHEN col IS NULL\n * THEN NULL ELSE ARRAY[col] END` repair clause (postgres cannot implicit-cast).\n * - `ALTER TYPE ... ADD VALUE IF NOT EXISTS` appends at the end of the enum\n * (no BEFORE/AFTER positioning); fine inside a transaction on postgres ≥12.\n * - Unsupported columns render their `nativeType` verbatim and migrate like\n * any other column.\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\nimport type { FieldIR } from \"@vibeorm/schema\";\nimport { postgresDialect } from \"@vibeorm/sql\";\nimport {\n CASCADE_ACTION_SQL,\n columnTypeSql,\n defaultSql,\n isIdentityColumn,\n quotePgString,\n} from \"../postgres-types.ts\";\nimport type { MigrationStep } from \"../types.ts\";\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/** Render migration steps to postgres SQL (one string per statement, in order). */\nexport function renderPostgresSteps(params: { steps: readonly MigrationStep[] }): string[] {\n return params.steps.flatMap((step) => renderStep({ step }));\n}\n\n// ─── Per-step rendering ───────────────────────────────────────────\n\nfunction renderStep(params: { step: MigrationStep }): string[] {\n const { step } = params;\n switch (step.kind) {\n case \"createEnum\": {\n const name = step.enumDef.dbName ?? step.enumDef.name;\n const values = step.enumDef.values.map((value) => quotePgString({ value })).join(\", \");\n return [`CREATE TYPE ${q(name)} AS ENUM (${values});`];\n }\n case \"dropEnum\":\n return [`DROP TYPE ${q(step.enumName)};`];\n case \"addEnumValue\":\n return [\n `ALTER TYPE ${q(step.enumName)} ADD VALUE IF NOT EXISTS ${quotePgString({ value: step.value })};`,\n ];\n case \"createTable\": {\n const lines = step.columns.map((column) => ` ${columnDefSql({ field: column })}`);\n if (step.primaryKey.length > 0) {\n const pkCols = step.primaryKey.map((column) => q(column)).join(\", \");\n lines.push(` CONSTRAINT ${q(`${step.table}_pkey`)} PRIMARY KEY (${pkCols})`);\n }\n for (const check of step.checks ?? []) {\n lines.push(` CONSTRAINT ${q(check.name)} CHECK (${check.expression})`);\n }\n return [`CREATE TABLE ${q(step.table)} (\\n${lines.join(\",\\n\")}\\n);`];\n }\n case \"dropTable\":\n case \"dropJoinTable\":\n return [`DROP TABLE ${q(step.table)} CASCADE;`];\n case \"dropView\":\n // No CASCADE: a view-on-view dependency fails LOUDLY instead of silently\n // taking a surviving dependent view with it (#26).\n return [`DROP VIEW IF EXISTS ${q(step.table)};`];\n case \"addColumn\":\n return [`ALTER TABLE ${q(step.table)} ADD COLUMN ${columnDefSql({ field: step.column })};`];\n case \"dropColumn\":\n return [`ALTER TABLE ${q(step.table)} DROP COLUMN ${q(step.column)};`];\n case \"alterColumn\":\n return renderAlterColumn({ step });\n case \"createIndex\": {\n const unique = step.unique ? \"UNIQUE \" : \"\";\n const using = !step.unique && step.indexKind !== \"btree\" ? ` USING ${step.indexKind}` : \"\";\n const cols = step.columns\n .map((column) => `${q(column.name)}${column.desc ? \" DESC\" : \"\"}`)\n .join(\", \");\n // pg 15+ clause; the flag sits between the column list and WHERE.\n const nulls = step.nullsNotDistinct === true ? \" NULLS NOT DISTINCT\" : \"\";\n const where = step.where === undefined ? \"\" : ` WHERE ${step.where}`;\n return [\n `CREATE ${unique}INDEX ${q(step.name)} ON ${q(step.table)}${using} (${cols})${nulls}${where};`,\n ];\n }\n case \"dropIndex\":\n return [`DROP INDEX ${q(step.name)};`];\n case \"addCheck\":\n return [\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(step.name)} CHECK (${step.expression});`,\n ];\n case \"dropCheck\":\n return [`ALTER TABLE ${q(step.table)} DROP CONSTRAINT ${q(step.name)};`];\n case \"addForeignKey\": {\n const cols = step.columns.map((column) => q(column)).join(\", \");\n const refCols = step.refColumns.map((column) => q(column)).join(\", \");\n return [\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(step.constraintName)} FOREIGN KEY (${cols}) REFERENCES ${q(step.refTable)} (${refCols}) ON DELETE ${CASCADE_ACTION_SQL[step.onDelete]} ON UPDATE ${CASCADE_ACTION_SQL[step.onUpdate]};`,\n ];\n }\n case \"dropForeignKey\":\n return [`ALTER TABLE ${q(step.table)} DROP CONSTRAINT ${q(step.constraintName)};`];\n case \"createJoinTable\": {\n // Prisma's implicit join-table shape: columns \"A\"/\"B\", a unique index on\n // (A, B), an index on B, both FKs cascading (see @vibeorm/schema m2m.ts).\n const aType = columnTypeSql({ field: { ...step.a.field, isList: false } });\n const bType = columnTypeSql({ field: { ...step.b.field, isList: false } });\n return [\n `CREATE TABLE ${q(step.table)} (\\n \"A\" ${aType} NOT NULL,\\n \"B\" ${bType} NOT NULL\\n);`,\n `CREATE UNIQUE INDEX ${q(`${step.table}_AB_unique`)} ON ${q(step.table)} (\"A\", \"B\");`,\n `CREATE INDEX ${q(`${step.table}_B_index`)} ON ${q(step.table)} (\"B\");`,\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(`${step.table}_A_fkey`)} FOREIGN KEY (\"A\") REFERENCES ${q(step.a.table)} (${q(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(`${step.table}_B_fkey`)} FOREIGN KEY (\"B\") REFERENCES ${q(step.b.table)} (${q(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,\n ];\n }\n case \"addPrimaryKey\": {\n const cols = step.columns.map((column) => q(column)).join(\", \");\n return [\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(`${step.table}_pkey`)} PRIMARY KEY (${cols});`,\n ];\n }\n case \"dropPrimaryKey\":\n return [`ALTER TABLE ${q(step.table)} DROP CONSTRAINT ${q(`${step.table}_pkey`)};`];\n }\n}\n\n// ─── Column pieces ────────────────────────────────────────────────\n\nfunction columnDefSql(params: { field: FieldIR }): string {\n const { field } = params;\n const name = q(field.dbName ?? field.name);\n\n if (field.default?.kind === \"autoincrement\" && !isIdentityColumn({ field })) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `autoincrement default on \"${field.name}\" requires a non-list Int or BigInt column`,\n meta: { field: field.name },\n });\n }\n\n let def = `${name} ${columnTypeSql({ field })}`;\n if (isIdentityColumn({ field })) def += \" GENERATED BY DEFAULT AS IDENTITY\";\n if (!field.isOptional) def += \" NOT NULL\";\n const defaultExpr = defaultSql({ field });\n if (defaultExpr !== undefined) def += ` DEFAULT ${defaultExpr}`;\n return def;\n}\n\nfunction renderAlterColumn(params: {\n step: Extract<MigrationStep, { kind: \"alterColumn\" }>;\n}): string[] {\n const { step } = params;\n const statements: string[] = [];\n const column = q(step.column);\n const alterPrefix = `ALTER TABLE ${q(step.table)} ALTER COLUMN ${column}`;\n\n if (step.changes.includes(\"type\")) {\n // LEARNINGS: scalar→array of the same base type needs a USING repair —\n // postgres cannot implicit-cast a scalar into a one-element array.\n const scalarToArray =\n step.to.isList && !step.from.isList\n ? ` USING CASE WHEN ${column} IS NULL THEN NULL ELSE ARRAY[${column}] END`\n : \"\";\n statements.push(\n `${alterPrefix} SET DATA TYPE ${columnTypeSql({ field: step.to })}${scalarToArray};`,\n );\n }\n\n if (step.changes.includes(\"nullability\")) {\n statements.push(`${alterPrefix} ${step.to.isOptional ? \"DROP\" : \"SET\"} NOT NULL;`);\n }\n\n if (step.changes.includes(\"default\")) {\n if (step.to.default?.kind === \"autoincrement\") {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `cannot add autoincrement to existing column \"${step.table}\".\"${step.column}\" — drop and recreate the column instead`,\n meta: { table: step.table, column: step.column },\n });\n }\n const defaultExpr = defaultSql({ field: step.to });\n statements.push(\n defaultExpr === undefined\n ? `${alterPrefix} DROP DEFAULT;`\n : `${alterPrefix} SET DEFAULT ${defaultExpr};`,\n );\n }\n\n return statements;\n}\n\n// ─── Quoting ──────────────────────────────────────────────────────\n\nfunction q(name: string): string {\n return postgresDialect.quoteIdent({ name });\n}\n",
|
|
14
|
+
"/**\n * SQLite DDL renderer: migration steps → SQL statements, including THE TABLE\n * REBUILD — sqlite has no ALTER COLUMN, cannot add/drop constraints, and its\n * DROP COLUMN is heavily restricted, so any such step compiles to the\n * documented 12-step recipe (https://sqlite.org/lang_altertable.html §7),\n * emitted as an ordered, self-contained statement block:\n *\n * PRAGMA foreign_keys=OFF;\n * BEGIN;\n * CREATE TABLE \"T_new\" (…target shape: columns, PK, FKs, enum CHECKs…);\n * INSERT INTO \"T_new\" (common cols) SELECT common cols FROM \"T\";\n * DROP TABLE \"T\";\n * ALTER TABLE \"T_new\" RENAME TO \"T\";\n * CREATE …INDEX… (every index of the target table);\n * PRAGMA foreign_key_check;\n * COMMIT;\n * PRAGMA foreign_keys=ON;\n *\n * Because the block manages its own transaction (PRAGMA foreign_keys is a\n * no-op inside one), callers must NOT wrap scripts containing it — push and\n * the runner detect this via `usesSelfManagedTransactions` (execute.ts).\n * Rebuild blocks are emitted AFTER all other statements so a rebuilt table's\n * new FKs can reference tables created earlier in the same script.\n *\n * Cheap paths are preferred wherever sqlite's plain ALTER suffices:\n * `ADD COLUMN` (unless the column is required without a literal default, or\n * defaults to CURRENT_TIMESTAMP / an expression — both forbidden in ADD\n * COLUMN) and `DROP COLUMN` (unless the column is in the PK, any index or\n * partial-index predicate, an FK on either side, or carries an enum CHECK).\n *\n * Column-value transfer on rebuild: dropped columns are omitted, added\n * columns take their default (or NULL), type-changed columns are a PLAIN COPY\n * — sqlite's flexible typing keeps the stored values as-is, so e.g. non-numeric\n * TEXT survives verbatim inside an INTEGER column (documented lossy-ness:\n * nothing is coerced, nothing is validated beyond the new CHECK constraints).\n *\n * Other pinned choices:\n * - autoincrement renders `INTEGER PRIMARY KEY AUTOINCREMENT` (monotonic ids,\n * Prisma parity) — plain `INTEGER PRIMARY KEY` would reuse rowids after\n * deletes. The `PRIMARY KEY AUTOINCREMENT` text is also the introspection\n * marker. Costs the `sqlite_sequence` bookkeeping table (skipped on pull).\n * - Composite / non-autoincrement PKs render as an unnamed table-level\n * `PRIMARY KEY (…)` (sqlite keeps constraint names only as noise).\n * - Enums render TEXT + a NAMED column-level CHECK (see sqlite-types.ts) —\n * the name (`<table>_<column>_enum_<Enum>`) is how pull recovers the enum.\n * - `DROP TABLE` has no CASCADE on sqlite; table drops are topologically\n * ordered (referencing tables first) using the `from` schema.\n * - Index kinds other than btree/unique throw VIBE_UNSUPPORTED_CAPABILITY.\n */\n\nimport { VibeError, isEnumType, unsupportedCapability } from \"@vibeorm/schema\";\nimport type { EnumIR, FieldIR, SchemaIR } from \"@vibeorm/schema\";\nimport { sqliteDialect } from \"@vibeorm/sql\";\nimport { resolveEnumValues } from \"../enum-values.ts\";\nimport { orderDropsChildrenFirst } from \"./drop-order.ts\";\nimport { normalizeSchema } from \"../normalize.ts\";\nimport type { NormalizedSchema, NormalizedTable } from \"../normalize.ts\";\nimport { CASCADE_ACTION_SQL, quotePgString } from \"../postgres-types.ts\";\nimport {\n sqliteDefaultSql,\n sqliteEnumCheckName,\n sqliteStorageType,\n} from \"../sqlite-types.ts\";\nimport { describeStep } from \"../types.ts\";\nimport type { IndexColumn, MigrationStep } from \"../types.ts\";\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/**\n * Render migration steps to sqlite SQL. `from`/`to` (the schemas that produced\n * the steps) are required whenever a step triggers a table rebuild or renders\n * an enum column — `generateMigration` and `push` always pass them.\n */\nexport function renderSqliteSteps(params: {\n steps: readonly MigrationStep[];\n from?: SchemaIR;\n to?: SchemaIR;\n}): string[] {\n const { steps } = params;\n const fromNorm = params.from === undefined\n ? undefined\n : normalizeSchema({ schema: params.from, dialect: \"sqlite\" });\n const toNorm = params.to === undefined\n ? undefined\n : normalizeSchema({ schema: params.to, dialect: \"sqlite\" });\n const enums: ReadonlyMap<string, EnumIR> = toNorm?.enums ?? new Map();\n\n // ── Classification: which tables need the rebuild recipe? ──\n const createdTables = new Set<string>();\n for (const step of steps) {\n if (step.kind === \"createTable\" || step.kind === \"createJoinTable\") {\n createdTables.add(step.table);\n }\n }\n\n const foldedFks = new Map<string, Extract<MigrationStep, { kind: \"addForeignKey\" }>[]>();\n const rebuildTables: string[] = []; // Insertion order = deterministic block order.\n const markRebuild = (table: string): void => {\n if (!rebuildTables.includes(table)) rebuildTables.push(table);\n };\n\n for (const step of steps) {\n switch (step.kind) {\n case \"alterColumn\":\n case \"dropForeignKey\":\n case \"addPrimaryKey\":\n case \"dropPrimaryKey\":\n // sqlite has no ALTER for CHECK constraints — both directions rebuild.\n case \"addCheck\":\n case \"dropCheck\":\n markRebuild(step.table);\n break;\n case \"addColumn\":\n if (!isCheapAddColumn({ field: step.column })) markRebuild(step.table);\n break;\n case \"dropColumn\":\n if (!canCheapDropColumn({ table: step.table, column: step.column, fromNorm })) {\n markRebuild(step.table);\n }\n break;\n case \"addForeignKey\":\n if (createdTables.has(step.table)) {\n const list = foldedFks.get(step.table);\n if (list === undefined) foldedFks.set(step.table, [step]);\n else list.push(step);\n } else {\n markRebuild(step.table);\n }\n break;\n default:\n break;\n }\n }\n const rebuildSet = new Set(rebuildTables);\n\n // ── Topological drop order (referencing tables first — no CASCADE). ──\n const dropNames = steps\n .filter((step) => step.kind === \"dropTable\" || step.kind === \"dropJoinTable\")\n .map((step) => (step as Extract<MigrationStep, { kind: \"dropTable\" }>).table);\n const orderedDrops = orderDropsChildrenFirst({ names: dropNames, fromNorm });\n let dropCursor = 0;\n\n // ── Emission: step order, rebuild-triggering steps absorbed. ──\n const statements: string[] = [];\n for (const step of steps) {\n switch (step.kind) {\n case \"createEnum\":\n case \"dropEnum\":\n case \"addEnumValue\":\n break; // No standalone enum objects on sqlite — enums live in columns.\n case \"createTable\":\n statements.push(\n createTableSql({\n table: step.table,\n constraintTable: step.table,\n columns: step.columns,\n primaryKey: step.primaryKey,\n checks: step.checks ?? [],\n fks: (foldedFks.get(step.table) ?? []).map((fk) => ({\n constraintName: fk.constraintName,\n columns: fk.columns,\n refTable: fk.refTable,\n refColumns: fk.refColumns,\n onDelete: CASCADE_ACTION_SQL[fk.onDelete],\n onUpdate: CASCADE_ACTION_SQL[fk.onUpdate],\n })),\n enums,\n }),\n );\n break;\n case \"addCheck\":\n case \"dropCheck\":\n break; // Absorbed by the table rebuild classified above.\n case \"createJoinTable\": {\n const aType = sqliteStorageType({ field: { ...step.a.field, isList: false } });\n const bType = sqliteStorageType({ field: { ...step.b.field, isList: false } });\n statements.push(\n `CREATE TABLE ${q(step.table)} (\\n \"A\" ${aType} NOT NULL,\\n \"B\" ${bType} NOT NULL,\\n CONSTRAINT ${q(`${step.table}_A_fkey`)} FOREIGN KEY (\"A\") REFERENCES ${q(step.a.table)} (${q(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE,\\n CONSTRAINT ${q(`${step.table}_B_fkey`)} FOREIGN KEY (\"B\") REFERENCES ${q(step.b.table)} (${q(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE\\n);`,\n `CREATE UNIQUE INDEX ${q(`${step.table}_AB_unique`)} ON ${q(step.table)} (\"A\", \"B\");`,\n `CREATE INDEX ${q(`${step.table}_B_index`)} ON ${q(step.table)} (\"B\");`,\n );\n break;\n }\n case \"addColumn\":\n if (!rebuildSet.has(step.table)) {\n statements.push(\n `ALTER TABLE ${q(step.table)} ADD COLUMN ${columnDefSql({\n field: step.column,\n constraintTable: step.table,\n enums,\n inlinePkAutoincrement: false,\n })};`,\n );\n }\n break;\n case \"dropColumn\":\n if (!rebuildSet.has(step.table)) {\n statements.push(`ALTER TABLE ${q(step.table)} DROP COLUMN ${q(step.column)};`);\n }\n break;\n case \"createIndex\":\n if (!rebuildSet.has(step.table)) {\n statements.push(\n createIndexSql({\n table: step.table,\n name: step.name,\n unique: step.unique,\n kind: step.indexKind,\n columns: step.columns,\n where: step.where,\n nullsNotDistinct: step.nullsNotDistinct,\n }),\n );\n }\n break;\n case \"dropIndex\":\n // Always emitted — dropping an index of a soon-rebuilt table early is\n // harmless (the rebuild recreates the target set) and keeps the\n // GLOBAL index namespace clean for later creates.\n statements.push(`DROP INDEX ${q(step.name)};`);\n break;\n case \"dropTable\":\n case \"dropJoinTable\":\n statements.push(`DROP TABLE ${q(orderedDrops[dropCursor] as string)};`);\n dropCursor += 1;\n break;\n case \"dropView\":\n // Ordered first by the differ (#26) — a leftover view would otherwise\n // block the column drops (or rebuilds) beneath it.\n statements.push(`DROP VIEW IF EXISTS ${q(step.table)};`);\n break;\n case \"alterColumn\":\n case \"addForeignKey\":\n case \"dropForeignKey\":\n case \"addPrimaryKey\":\n case \"dropPrimaryKey\":\n if (\n (step.kind === \"addForeignKey\" && createdTables.has(step.table)) ||\n !rebuildSet.has(step.table)\n ) {\n break; // Folded into CREATE TABLE, or absorbed by that table's rebuild.\n }\n requireSchemas({ step, fromNorm, toNorm });\n break;\n }\n }\n\n // ── Rebuild blocks last (new FK targets already exist by now). ──\n for (const table of rebuildTables) {\n const step = steps.find(\n (candidate) => \"table\" in candidate && candidate.table === table,\n ) as MigrationStep;\n requireSchemas({ step, fromNorm, toNorm });\n statements.push(\n ...renderTableRebuild({\n table,\n from: fromNorm as NormalizedSchema,\n to: toNorm as NormalizedSchema,\n }),\n );\n }\n\n return statements;\n}\n\n// ─── The table rebuild ────────────────────────────────────────────\n\nfunction renderTableRebuild(params: {\n table: string;\n from: NormalizedSchema;\n to: NormalizedSchema;\n}): string[] {\n const { table, from, to } = params;\n const source = from.tables.get(table);\n const target = to.tables.get(table);\n if (source === undefined || target === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `cannot rebuild \"${table}\" — the table is missing from the ${source === undefined ? \"from\" : \"to\"} schema`,\n meta: { table },\n });\n }\n\n const tmp = `${table}_new`;\n const statements: string[] = [\"PRAGMA foreign_keys=OFF;\", \"BEGIN;\"];\n\n statements.push(\n createTableSql({\n table: tmp,\n // CHECK-constraint names carry the FINAL table name so introspection\n // recovers enums after the RENAME.\n constraintTable: table,\n columns: [...target.columns.values()].map((column) => column.field),\n primaryKey: target.pk,\n checks: [...target.checks].map(([name, expression]) => ({ name, expression })),\n fks: [...target.fks.values()].map((fk) => ({\n constraintName: fk.constraintName,\n columns: fk.columns,\n refTable: fk.refTable,\n refColumns: fk.refColumns,\n onDelete: CASCADE_ACTION_SQL[fk.onDelete],\n onUpdate: CASCADE_ACTION_SQL[fk.onUpdate],\n })),\n enums: to.enums,\n }),\n );\n\n // Transfer: target-order intersection of the two column sets. Dropped\n // columns are omitted; added columns take their default/NULL; type changes\n // copy values verbatim (see module doc for the lossy-ness contract).\n const common = [...target.columns.keys()].filter((name) => source.columns.has(name));\n if (common.length > 0) {\n const cols = common.map((name) => q(name)).join(\", \");\n statements.push(`INSERT INTO ${q(tmp)} (${cols}) SELECT ${cols} FROM ${q(table)};`);\n }\n\n statements.push(`DROP TABLE ${q(table)};`, `ALTER TABLE ${q(tmp)} RENAME TO ${q(table)};`);\n\n for (const index of target.indexes.values()) {\n statements.push(\n createIndexSql({\n table,\n name: index.name,\n unique: index.unique,\n kind: index.kind,\n columns: index.columns,\n where: index.where,\n nullsNotDistinct: index.nullsNotDistinct,\n }),\n );\n }\n\n statements.push(\"PRAGMA foreign_key_check;\", \"COMMIT;\", \"PRAGMA foreign_keys=ON;\");\n return statements;\n}\n\n// ─── Cheap-path detection ─────────────────────────────────────────\n\n/**\n * `ALTER TABLE … ADD COLUMN` suffices unless sqlite forbids the shape: the\n * new column may not default to CURRENT_* or an expression, and a NOT NULL\n * column needs a literal default (app-level id generators provide none).\n */\nfunction isCheapAddColumn(params: { field: FieldIR }): boolean {\n const { field } = params;\n const kind = field.default?.kind;\n if (kind === \"autoincrement\" || kind === \"now\" || kind === \"dbgenerated\") return false;\n const hasLiteralDefault = kind === \"literal\" || kind === \"enumValue\";\n if (!field.isOptional && !hasLiteralDefault) return false;\n return true;\n}\n\n/**\n * `ALTER TABLE … DROP COLUMN` works only when nothing references the column:\n * not the PK, no index (or partial-index predicate), no FK on either side, no\n * enum CHECK. Without the `from` schema the answer is unknowable → rebuild.\n */\nfunction canCheapDropColumn(params: {\n table: string;\n column: string;\n fromNorm: NormalizedSchema | undefined;\n}): boolean {\n const { table, column, fromNorm } = params;\n if (fromNorm === undefined) return false;\n const fromTable = fromNorm.tables.get(table);\n if (fromTable === undefined) return false;\n\n if (fromTable.pk.includes(column)) return false;\n const normalized = fromTable.columns.get(column);\n if (normalized !== undefined && isEnumType(normalized.field.type)) return false;\n for (const index of fromTable.indexes.values()) {\n if (index.columns.some((indexColumn) => indexColumn.name === column)) return false;\n if (index.where !== undefined && index.where.includes(column)) return false;\n }\n for (const fk of fromTable.fks.values()) {\n if (fk.columns.includes(column)) return false;\n }\n for (const other of fromNorm.tables.values()) {\n for (const fk of other.fks.values()) {\n if (fk.refTable === table && fk.refColumns.includes(column)) return false;\n }\n }\n return true;\n}\n\n// ─── Table & column pieces ────────────────────────────────────────\n\ntype InlineFk = {\n readonly constraintName: string;\n readonly columns: readonly string[];\n readonly refTable: string;\n readonly refColumns: readonly string[];\n readonly onDelete: string;\n readonly onUpdate: string;\n};\n\nfunction createTableSql(params: {\n table: string;\n /** Table name used in CHECK-constraint names (the FINAL name on rebuilds). */\n constraintTable: string;\n columns: readonly FieldIR[];\n primaryKey: readonly string[];\n /** User-declared named CHECK constraints (raw expressions, verbatim). */\n checks: readonly { readonly name: string; readonly expression: string }[];\n fks: readonly InlineFk[];\n enums: ReadonlyMap<string, EnumIR>;\n}): string {\n const { table, constraintTable, columns, primaryKey, fks, enums } = params;\n\n const autoincrementPk = autoincrementPkColumn({ columns, primaryKey });\n const lines = columns.map(\n (field) =>\n ` ${columnDefSql({\n field,\n constraintTable,\n enums,\n inlinePkAutoincrement: (field.dbName ?? field.name) === autoincrementPk,\n })}`,\n );\n\n if (primaryKey.length > 0 && autoincrementPk === undefined) {\n lines.push(` PRIMARY KEY (${primaryKey.map((column) => q(column)).join(\", \")})`);\n }\n for (const check of params.checks) {\n lines.push(` CONSTRAINT ${q(check.name)} CHECK (${check.expression})`);\n }\n for (const fk of fks) {\n lines.push(\n ` CONSTRAINT ${q(fk.constraintName)} FOREIGN KEY (${fk.columns.map((column) => q(column)).join(\", \")}) REFERENCES ${q(fk.refTable)} (${fk.refColumns.map((column) => q(column)).join(\", \")}) ON DELETE ${fk.onDelete} ON UPDATE ${fk.onUpdate}`,\n );\n }\n\n return `CREATE TABLE ${q(table)} (\\n${lines.join(\",\\n\")}\\n);`;\n}\n\n/**\n * The db name of the single autoincrement Int/BigInt PK column — the one\n * column rendered inline as `INTEGER PRIMARY KEY AUTOINCREMENT` — or\n * undefined when the table has no such PK.\n */\nfunction autoincrementPkColumn(params: {\n columns: readonly FieldIR[];\n primaryKey: readonly string[];\n}): string | undefined {\n const { columns, primaryKey } = params;\n if (primaryKey.length !== 1) return undefined;\n const pkName = primaryKey[0] as string;\n const field = columns.find((candidate) => (candidate.dbName ?? candidate.name) === pkName);\n if (field === undefined) return undefined;\n const eligible =\n field.default?.kind === \"autoincrement\" &&\n !field.isList &&\n !isEnumType(field.type) &&\n (field.type === \"Int\" || field.type === \"BigInt\");\n return eligible ? pkName : undefined;\n}\n\nfunction columnDefSql(params: {\n field: FieldIR;\n constraintTable: string;\n enums: ReadonlyMap<string, EnumIR>;\n inlinePkAutoincrement: boolean;\n}): string {\n const { field, constraintTable, enums, inlinePkAutoincrement } = params;\n const name = field.dbName ?? field.name;\n\n if (field.default?.kind === \"autoincrement\" && !inlinePkAutoincrement) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `autoincrement on sqlite requires \"${field.name}\" to be the single-column Int or BigInt primary key`,\n meta: { field: field.name },\n });\n }\n if (inlinePkAutoincrement) {\n return `${q(name)} INTEGER PRIMARY KEY AUTOINCREMENT`;\n }\n\n let def = `${q(name)} ${sqliteStorageType({ field })}`;\n if (!field.isOptional) def += \" NOT NULL\";\n const defaultExpr = sqliteDefaultSql({ field });\n if (defaultExpr !== undefined) def += ` DEFAULT ${defaultExpr}`;\n\n if (isEnumType(field.type) && field.isUnsupported !== true) {\n const enumName = field.type.enum;\n const values = resolveEnumValues({ name: enumName, enums });\n if (values === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `enum \"${enumName}\" on column \"${field.name}\" is not declared in the schema — sqlite rendering needs the target schema's enums for the CHECK constraint`,\n meta: { field: field.name, enum: enumName },\n });\n }\n const check = sqliteEnumCheckName({ table: constraintTable, column: name, enumName });\n def += ` CONSTRAINT ${q(check)} CHECK (${q(name)} IN (${values\n .map((value) => quotePgString({ value }))\n .join(\", \")}))`;\n }\n\n return def;\n}\n\nfunction createIndexSql(params: {\n table: string;\n name: string;\n unique: boolean;\n kind: string;\n columns: readonly IndexColumn[];\n where: string | undefined;\n nullsNotDistinct?: boolean | undefined;\n}): string {\n const { table, name, unique, kind, columns, where } = params;\n if (params.nullsNotDistinct === true) {\n throw unsupportedCapability({\n dialect: \"sqlite\",\n feature: `UNIQUE NULLS NOT DISTINCT (index \"${name}\")`,\n hint: \"sqlite treats NULLs as distinct in unique indexes and has no switch — gate the flag per dialect\",\n });\n }\n if (!unique && kind !== \"btree\") {\n throw unsupportedCapability({\n dialect: \"sqlite\",\n feature: `index kind \"${kind}\" (index \"${name}\")`,\n hint: \"sqlite indexes are btree only; use an extension-specific virtual table for others\",\n });\n }\n // SQLITE-2: a Decimal column stores as TEXT and every compare/order site\n // reads CAST(col AS REAL) (B4) — a plain-column index can never serve those\n // (EQP-proven SCAN with the index present). Index the same expression, so\n // sqlite's expression-index matching kicks in.\n const cols = columns\n .map(\n (column) =>\n `${column.decimal === true ? `CAST(${q(column.name)} AS REAL)` : q(column.name)}${column.desc ? \" DESC\" : \"\"}`,\n )\n .join(\", \");\n const whereClause = where === undefined ? \"\" : ` WHERE ${where}`;\n return `CREATE ${unique ? \"UNIQUE \" : \"\"}INDEX ${q(name)} ON ${q(table)} (${cols})${whereClause};`;\n}\n\n// ─── Drop ordering ────────────────────────────────────────────────\n\n\n// ─── Context guard & quoting ──────────────────────────────────────\n\nfunction requireSchemas(params: {\n step: MigrationStep;\n fromNorm: NormalizedSchema | undefined;\n toNorm: NormalizedSchema | undefined;\n}): void {\n const { step, fromNorm, toNorm } = params;\n if (fromNorm !== undefined && toNorm !== undefined) return;\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `sqlite step \"${describeStep({ step })}\" requires a table rebuild — renderSteps needs the { from, to } schemas to construct it`,\n meta: { step: step.kind },\n });\n}\n\nfunction q(name: string): string {\n return sqliteDialect.quoteIdent({ name });\n}\n",
|
|
15
15
|
"/**\n * Topological ordering for DROP TABLE statements — children (referencing\n * tables) first.\n *\n * postgres never needs this: `DROP TABLE … CASCADE` takes inbound FK\n * constraints with it. sqlite and mysql have no working cascade for inbound\n * foreign keys — mysql refuses outright (errno 3730\n * `ER_FK_CANNOT_DROP_PARENT`, observed live on 8.4 when a fixture switch\n * dropped `Project` while the also-being-dropped `ProjectMember` still\n * referenced it). ONE shared implementation, consumed by both renderers —\n * the LEARNINGS rule: a structural rule is never re-implemented per consumer.\n */\n\nimport type { NormalizedSchema } from \"../normalize.ts\";\n\n/**\n * Order the tables in `names` so that no table is dropped while another\n * to-be-dropped table still references it. Tables unknown to `fromNorm` (or a\n * missing `fromNorm`, or a reference cycle) fall back to the given order —\n * rendering proceeds and the server reports what it cannot do (dialect\n * honesty beats silently dropping statements).\n */\nexport function orderDropsChildrenFirst(params: {\n names: readonly string[];\n fromNorm: NormalizedSchema | undefined;\n}): string[] {\n const { names, fromNorm } = params;\n if (fromNorm === undefined || names.length < 2) return [...names];\n\n const references = new Map<string, ReadonlySet<string>>();\n for (const name of names) {\n const table = fromNorm.tables.get(name);\n if (table !== undefined) {\n references.set(name, new Set([...table.fks.values()].map((fk) => fk.refTable)));\n continue;\n }\n const joinTable = fromNorm.joinTables.get(name);\n if (joinTable !== undefined) {\n references.set(name, new Set([joinTable.a.table, joinTable.b.table]));\n continue;\n }\n references.set(name, new Set());\n }\n\n const remaining = new Set(names);\n const result: string[] = [];\n while (remaining.size > 0) {\n let progressed = false;\n for (const name of names) {\n if (!remaining.has(name)) continue;\n const stillReferenced = [...remaining].some(\n (other) => other !== name && (references.get(other) ?? new Set()).has(name),\n );\n if (!stillReferenced) {\n result.push(name);\n remaining.delete(name);\n progressed = true;\n }\n }\n if (!progressed) {\n for (const name of names) if (remaining.has(name)) result.push(name);\n break;\n }\n }\n return result;\n}\n",
|
|
16
|
-
"/**\n * MySQL DDL renderer: migration steps → SQL statements.\n *\n * Every identifier is backtick-quoted through `mysqlDialect.quoteIdent` — the\n * ONE quoting decision point. Pinned choices:\n *\n * - String → varchar(191): utf8mb4 × 4 bytes keeps indexed String columns\n * inside the 767-byte legacy InnoDB index-key limit (`@db.Text` opts out —\n * TEXT columns are never indexed by us; indexing one would need a prefix\n * length we do not emit).\n * - autoincrement renders `AUTO_INCREMENT` (the column must be a key — the\n * PRIMARY KEY clause in the same CREATE TABLE satisfies that; ALTERing one\n * onto an existing column is refused, pg parity).\n * - Enums are inline `ENUM('A', 'B')` column types; the standalone enum steps\n * (createEnum/dropEnum/addEnumValue) render NOTHING — value changes arrive\n * as alterColumn steps (value-based type keys) and render as MODIFY COLUMN\n * with the widened list.\n * - alterColumn type/nullability → one `MODIFY COLUMN` with the full target\n * definition (mysql redefines the column wholesale); default-only changes\n * use `ALTER COLUMN … SET/DROP DEFAULT`.\n * - No partial indexes on mysql → VIBE_UNSUPPORTED_CAPABILITY naming the\n * index. Index kinds other than btree are refused the same way.\n * - `DROP INDEX … ON table` needs the table — the differ's dropIndex steps\n * carry it; a step without one is a VIBE_MIGRATION error.\n * - `DROP TABLE` has no cascade (mysql parses `CASCADE` and ignores it), and\n * dropping a parent still referenced by another to-be-dropped table fails\n * with errno 3730 `ER_FK_CANNOT_DROP_PARENT` (observed live on 8.4). FK\n * drops on SURVIVING tables come from the differ's bucket order; drops of\n * whole dependent groups are topologically reordered children-first here\n * (the shared `orderDropsChildrenFirst`, same rule as sqlite).\n */\n\nimport { VibeError, unsupportedCapability } from \"@vibeorm/schema\";\nimport type { EnumIR, FieldIR, SchemaIR } from \"@vibeorm/schema\";\nimport { mysqlDialect } from \"@vibeorm/sql\";\nimport { orderDropsChildrenFirst } from \"./drop-order.ts\";\nimport { normalizeSchema } from \"../normalize.ts\";\nimport { CASCADE_ACTION_SQL } from \"../postgres-types.ts\";\nimport { mysqlColumnTypeSql, mysqlDefaultSql } from \"../mysql-types.ts\";\nimport type { MigrationStep } from \"../types.ts\";\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/**\n * Render migration steps to mysql SQL. `to` (the target schema) is required\n * whenever an enum column is rendered — the inline `ENUM(…)` type needs the\n * enum's values, which live on the schema, not the step. `from` enables the\n * topological drop order (children before referenced parents); without it,\n * drops render in step order.\n */\nexport function renderMysqlSteps(params: {\n steps: readonly MigrationStep[];\n from?: SchemaIR;\n to?: SchemaIR;\n}): string[] {\n const enums = new Map<string, EnumIR>();\n for (const enumDef of params.to?.enums ?? []) {\n enums.set(enumDef.dbName ?? enumDef.name, enumDef);\n }\n\n // Topological drop order — mysql refuses to drop a parent that another\n // to-be-dropped table still references (no cascade; see module doc).\n const dropNames = params.steps\n .filter((step) => step.kind === \"dropTable\" || step.kind === \"dropJoinTable\")\n .map((step) => (step as Extract<MigrationStep, { kind: \"dropTable\" }>).table);\n const fromNorm =\n params.from === undefined ? undefined : normalizeSchema({ schema: params.from, dialect: \"mysql\" });\n const orderedDrops = orderDropsChildrenFirst({ names: dropNames, fromNorm });\n let dropCursor = 0;\n\n return params.steps.flatMap((step) => {\n if (step.kind === \"dropTable\" || step.kind === \"dropJoinTable\") {\n const table = orderedDrops[dropCursor] as string;\n dropCursor += 1;\n return [`DROP TABLE ${q(table)};`];\n }\n return renderStep({ step, enums });\n });\n}\n\n// ─── Per-step rendering ───────────────────────────────────────────\n\nfunction renderStep(params: {\n step: MigrationStep;\n enums: ReadonlyMap<string, EnumIR>;\n}): string[] {\n const { step, enums } = params;\n switch (step.kind) {\n case \"createEnum\":\n case \"dropEnum\":\n case \"addEnumValue\":\n return []; // Enums are inline column types on mysql.\n case \"createTable\": {\n const lines = step.columns.map((column) => ` ${columnDefSql({ field: column, enums })}`);\n if (step.primaryKey.length > 0) {\n lines.push(` PRIMARY KEY (${step.primaryKey.map((column) => q(column)).join(\", \")})`);\n }\n return [`CREATE TABLE ${q(step.table)} (\\n${lines.join(\",\\n\")}\\n);`];\n }\n case \"dropTable\":\n case \"dropJoinTable\":\n return [`DROP TABLE ${q(step.table)};`];\n case \"dropView\":\n return [`DROP VIEW IF EXISTS ${q(step.table)};`];\n case \"addColumn\":\n return [\n `ALTER TABLE ${q(step.table)} ADD COLUMN ${columnDefSql({ field: step.column, enums })};`,\n ];\n case \"dropColumn\":\n return [`ALTER TABLE ${q(step.table)} DROP COLUMN ${q(step.column)};`];\n case \"alterColumn\":\n return renderAlterColumn({ step, enums });\n case \"createIndex\": {\n if (step.where !== undefined) {\n throw unsupportedCapability({\n dialect: \"mysql\",\n feature: `partial index \"${step.name}\"`,\n hint: \"mysql has no partial indexes — drop the WHERE predicate or gate the index per dialect\",\n });\n }\n if (!step.unique && step.indexKind !== \"btree\") {\n throw unsupportedCapability({\n dialect: \"mysql\",\n feature: `index kind \"${step.indexKind}\" (index \"${step.name}\")`,\n hint: \"mysql secondary indexes are btree only\",\n });\n }\n const cols = step.columns\n .map((column) => `${q(column.name)}${column.desc ? \" DESC\" : \"\"}`)\n .join(\", \");\n return [\n `CREATE ${step.unique ? \"UNIQUE \" : \"\"}INDEX ${q(step.name)} ON ${q(step.table)} (${cols});`,\n ];\n }\n case \"dropIndex\": {\n if (step.table === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `dropIndex \"${step.name}\" carries no table — mysql's DROP INDEX requires one`,\n meta: { index: step.name },\n });\n }\n return [`DROP INDEX ${q(step.name)} ON ${q(step.table)};`];\n }\n case \"addForeignKey\": {\n const cols = step.columns.map((column) => q(column)).join(\", \");\n const refCols = step.refColumns.map((column) => q(column)).join(\", \");\n return [\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(step.constraintName)} FOREIGN KEY (${cols}) REFERENCES ${q(step.refTable)} (${refCols}) ON DELETE ${CASCADE_ACTION_SQL[step.onDelete]} ON UPDATE ${CASCADE_ACTION_SQL[step.onUpdate]};`,\n ];\n }\n case \"dropForeignKey\":\n return [`ALTER TABLE ${q(step.table)} DROP FOREIGN KEY ${q(step.constraintName)};`];\n case \"createJoinTable\": {\n const aType = mysqlColumnTypeSql({ field: { ...step.a.field, isList: false }, enums });\n const bType = mysqlColumnTypeSql({ field: { ...step.b.field, isList: false }, enums });\n return [\n `CREATE TABLE ${q(step.table)} (\\n \\`A\\` ${aType} NOT NULL,\\n \\`B\\` ${bType} NOT NULL\\n);`,\n `CREATE UNIQUE INDEX ${q(`${step.table}_AB_unique`)} ON ${q(step.table)} (\\`A\\`, \\`B\\`);`,\n `CREATE INDEX ${q(`${step.table}_B_index`)} ON ${q(step.table)} (\\`B\\`);`,\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(`${step.table}_A_fkey`)} FOREIGN KEY (\\`A\\`) REFERENCES ${q(step.a.table)} (${q(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(`${step.table}_B_fkey`)} FOREIGN KEY (\\`B\\`) REFERENCES ${q(step.b.table)} (${q(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,\n ];\n }\n case \"addPrimaryKey\":\n return [\n `ALTER TABLE ${q(step.table)} ADD PRIMARY KEY (${step.columns.map((column) => q(column)).join(\", \")});`,\n ];\n case \"dropPrimaryKey\":\n return [`ALTER TABLE ${q(step.table)} DROP PRIMARY KEY;`];\n }\n}\n\n// ─── Column pieces ────────────────────────────────────────────────\n\nfunction columnDefSql(params: { field: FieldIR; enums: ReadonlyMap<string, EnumIR> }): string {\n const { field, enums } = params;\n const name = q(field.dbName ?? field.name);\n\n const autoincrement = field.default?.kind === \"autoincrement\";\n if (autoincrement && field.type !== \"Int\" && field.type !== \"BigInt\") {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `autoincrement default on \"${field.name}\" requires a non-list Int or BigInt column`,\n meta: { field: field.name },\n });\n }\n\n let def = `${name} ${mysqlColumnTypeSql({ field, enums })}`;\n if (!field.isOptional) def += \" NOT NULL\";\n if (autoincrement) def += \" AUTO_INCREMENT\";\n const defaultExpr = mysqlDefaultSql({ field });\n if (defaultExpr !== undefined) def += ` DEFAULT ${defaultExpr}`;\n return def;\n}\n\nfunction renderAlterColumn(params: {\n step: Extract<MigrationStep, { kind: \"alterColumn\" }>;\n enums: ReadonlyMap<string, EnumIR>;\n}): string[] {\n const { step, enums } = params;\n\n if (step.to.default?.kind === \"autoincrement\" && step.from.default?.kind !== \"autoincrement\") {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `cannot add autoincrement to existing column \"${step.table}\".\"${step.column}\" — drop and recreate the column instead`,\n meta: { table: step.table, column: step.column },\n });\n }\n\n // Type or nullability changes redefine the whole column (MODIFY COLUMN\n // carries type + nullability + default in one definition).\n if (step.changes.includes(\"type\") || step.changes.includes(\"nullability\")) {\n return [\n `ALTER TABLE ${q(step.table)} MODIFY COLUMN ${columnDefSql({ field: step.to, enums })};`,\n ];\n }\n\n // Default-only change.\n const defaultExpr = mysqlDefaultSql({ field: step.to });\n return [\n defaultExpr === undefined\n ? `ALTER TABLE ${q(step.table)} ALTER COLUMN ${q(step.column)} DROP DEFAULT;`\n : `ALTER TABLE ${q(step.table)} ALTER COLUMN ${q(step.column)} SET DEFAULT ${defaultExpr};`,\n ];\n}\n\n// ─── Quoting ──────────────────────────────────────────────────────\n\nfunction q(name: string): string {\n return mysqlDialect.quoteIdent({ name });\n}\n",
|
|
16
|
+
"/**\n * MySQL DDL renderer: migration steps → SQL statements.\n *\n * Every identifier is backtick-quoted through `mysqlDialect.quoteIdent` — the\n * ONE quoting decision point. Pinned choices:\n *\n * - String → varchar(191): utf8mb4 × 4 bytes keeps indexed String columns\n * inside the 767-byte legacy InnoDB index-key limit (`@db.Text` opts out —\n * TEXT columns are never indexed by us; indexing one would need a prefix\n * length we do not emit).\n * - autoincrement renders `AUTO_INCREMENT` (the column must be a key — the\n * PRIMARY KEY clause in the same CREATE TABLE satisfies that; ALTERing one\n * onto an existing column is refused, pg parity).\n * - Enums are inline `ENUM('A', 'B')` column types; the standalone enum steps\n * (createEnum/dropEnum/addEnumValue) render NOTHING — value changes arrive\n * as alterColumn steps (value-based type keys) and render as MODIFY COLUMN\n * with the widened list.\n * - alterColumn type/nullability → one `MODIFY COLUMN` with the full target\n * definition (mysql redefines the column wholesale); default-only changes\n * use `ALTER COLUMN … SET/DROP DEFAULT`.\n * - No partial indexes on mysql → VIBE_UNSUPPORTED_CAPABILITY naming the\n * index. Index kinds other than btree are refused the same way.\n * - `DROP INDEX … ON table` needs the table — the differ's dropIndex steps\n * carry it; a step without one is a VIBE_MIGRATION error.\n * - `DROP TABLE` has no cascade (mysql parses `CASCADE` and ignores it), and\n * dropping a parent still referenced by another to-be-dropped table fails\n * with errno 3730 `ER_FK_CANNOT_DROP_PARENT` (observed live on 8.4). FK\n * drops on SURVIVING tables come from the differ's bucket order; drops of\n * whole dependent groups are topologically reordered children-first here\n * (the shared `orderDropsChildrenFirst`, same rule as sqlite).\n */\n\nimport { VibeError, unsupportedCapability } from \"@vibeorm/schema\";\nimport type { EnumIR, FieldIR, SchemaIR } from \"@vibeorm/schema\";\nimport { mysqlDialect } from \"@vibeorm/sql\";\nimport { orderDropsChildrenFirst } from \"./drop-order.ts\";\nimport { normalizeSchema } from \"../normalize.ts\";\nimport { CASCADE_ACTION_SQL } from \"../postgres-types.ts\";\nimport { mysqlColumnTypeSql, mysqlDefaultSql } from \"../mysql-types.ts\";\nimport type { MigrationStep } from \"../types.ts\";\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/**\n * Render migration steps to mysql SQL. `to` (the target schema) is required\n * whenever an enum column is rendered — the inline `ENUM(…)` type needs the\n * enum's values, which live on the schema, not the step. `from` enables the\n * topological drop order (children before referenced parents); without it,\n * drops render in step order.\n */\nexport function renderMysqlSteps(params: {\n steps: readonly MigrationStep[];\n from?: SchemaIR;\n to?: SchemaIR;\n}): string[] {\n const enums = new Map<string, EnumIR>();\n for (const enumDef of params.to?.enums ?? []) {\n enums.set(enumDef.dbName ?? enumDef.name, enumDef);\n }\n\n // Topological drop order — mysql refuses to drop a parent that another\n // to-be-dropped table still references (no cascade; see module doc).\n const dropNames = params.steps\n .filter((step) => step.kind === \"dropTable\" || step.kind === \"dropJoinTable\")\n .map((step) => (step as Extract<MigrationStep, { kind: \"dropTable\" }>).table);\n const fromNorm =\n params.from === undefined ? undefined : normalizeSchema({ schema: params.from, dialect: \"mysql\" });\n const orderedDrops = orderDropsChildrenFirst({ names: dropNames, fromNorm });\n let dropCursor = 0;\n\n return params.steps.flatMap((step) => {\n if (step.kind === \"dropTable\" || step.kind === \"dropJoinTable\") {\n const table = orderedDrops[dropCursor] as string;\n dropCursor += 1;\n return [`DROP TABLE ${q(table)};`];\n }\n return renderStep({ step, enums });\n });\n}\n\n// ─── Per-step rendering ───────────────────────────────────────────\n\nfunction renderStep(params: {\n step: MigrationStep;\n enums: ReadonlyMap<string, EnumIR>;\n}): string[] {\n const { step, enums } = params;\n switch (step.kind) {\n case \"createEnum\":\n case \"dropEnum\":\n case \"addEnumValue\":\n return []; // Enums are inline column types on mysql.\n case \"createTable\": {\n const lines = step.columns.map((column) => ` ${columnDefSql({ field: column, enums })}`);\n if (step.primaryKey.length > 0) {\n lines.push(` PRIMARY KEY (${step.primaryKey.map((column) => q(column)).join(\", \")})`);\n }\n for (const check of step.checks ?? []) {\n lines.push(` CONSTRAINT ${q(check.name)} CHECK (${check.expression})`);\n }\n return [`CREATE TABLE ${q(step.table)} (\\n${lines.join(\",\\n\")}\\n);`];\n }\n case \"dropTable\":\n case \"dropJoinTable\":\n return [`DROP TABLE ${q(step.table)};`];\n case \"dropView\":\n return [`DROP VIEW IF EXISTS ${q(step.table)};`];\n case \"addColumn\":\n return [\n `ALTER TABLE ${q(step.table)} ADD COLUMN ${columnDefSql({ field: step.column, enums })};`,\n ];\n case \"dropColumn\":\n return [`ALTER TABLE ${q(step.table)} DROP COLUMN ${q(step.column)};`];\n case \"alterColumn\":\n return renderAlterColumn({ step, enums });\n case \"createIndex\": {\n if (step.where !== undefined) {\n throw unsupportedCapability({\n dialect: \"mysql\",\n feature: `partial index \"${step.name}\"`,\n hint: \"mysql has no partial indexes — drop the WHERE predicate or gate the index per dialect\",\n });\n }\n if (step.nullsNotDistinct === true) {\n throw unsupportedCapability({\n dialect: \"mysql\",\n feature: `UNIQUE NULLS NOT DISTINCT (index \"${step.name}\")`,\n hint: \"mysql treats NULLs as distinct in unique indexes and has no switch — gate the flag per dialect\",\n });\n }\n if (!step.unique && step.indexKind !== \"btree\") {\n throw unsupportedCapability({\n dialect: \"mysql\",\n feature: `index kind \"${step.indexKind}\" (index \"${step.name}\")`,\n hint: \"mysql secondary indexes are btree only\",\n });\n }\n const cols = step.columns\n .map((column) => `${q(column.name)}${column.desc ? \" DESC\" : \"\"}`)\n .join(\", \");\n return [\n `CREATE ${step.unique ? \"UNIQUE \" : \"\"}INDEX ${q(step.name)} ON ${q(step.table)} (${cols});`,\n ];\n }\n case \"addCheck\":\n // MySQL 8.0.16+ parses AND enforces CHECK constraints.\n return [\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(step.name)} CHECK (${step.expression});`,\n ];\n case \"dropCheck\":\n return [`ALTER TABLE ${q(step.table)} DROP CHECK ${q(step.name)};`];\n case \"dropIndex\": {\n if (step.table === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `dropIndex \"${step.name}\" carries no table — mysql's DROP INDEX requires one`,\n meta: { index: step.name },\n });\n }\n return [`DROP INDEX ${q(step.name)} ON ${q(step.table)};`];\n }\n case \"addForeignKey\": {\n const cols = step.columns.map((column) => q(column)).join(\", \");\n const refCols = step.refColumns.map((column) => q(column)).join(\", \");\n return [\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(step.constraintName)} FOREIGN KEY (${cols}) REFERENCES ${q(step.refTable)} (${refCols}) ON DELETE ${CASCADE_ACTION_SQL[step.onDelete]} ON UPDATE ${CASCADE_ACTION_SQL[step.onUpdate]};`,\n ];\n }\n case \"dropForeignKey\":\n return [`ALTER TABLE ${q(step.table)} DROP FOREIGN KEY ${q(step.constraintName)};`];\n case \"createJoinTable\": {\n const aType = mysqlColumnTypeSql({ field: { ...step.a.field, isList: false }, enums });\n const bType = mysqlColumnTypeSql({ field: { ...step.b.field, isList: false }, enums });\n return [\n `CREATE TABLE ${q(step.table)} (\\n \\`A\\` ${aType} NOT NULL,\\n \\`B\\` ${bType} NOT NULL\\n);`,\n `CREATE UNIQUE INDEX ${q(`${step.table}_AB_unique`)} ON ${q(step.table)} (\\`A\\`, \\`B\\`);`,\n `CREATE INDEX ${q(`${step.table}_B_index`)} ON ${q(step.table)} (\\`B\\`);`,\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(`${step.table}_A_fkey`)} FOREIGN KEY (\\`A\\`) REFERENCES ${q(step.a.table)} (${q(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,\n `ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(`${step.table}_B_fkey`)} FOREIGN KEY (\\`B\\`) REFERENCES ${q(step.b.table)} (${q(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,\n ];\n }\n case \"addPrimaryKey\":\n return [\n `ALTER TABLE ${q(step.table)} ADD PRIMARY KEY (${step.columns.map((column) => q(column)).join(\", \")});`,\n ];\n case \"dropPrimaryKey\":\n return [`ALTER TABLE ${q(step.table)} DROP PRIMARY KEY;`];\n }\n}\n\n// ─── Column pieces ────────────────────────────────────────────────\n\nfunction columnDefSql(params: { field: FieldIR; enums: ReadonlyMap<string, EnumIR> }): string {\n const { field, enums } = params;\n const name = q(field.dbName ?? field.name);\n\n const autoincrement = field.default?.kind === \"autoincrement\";\n if (autoincrement && field.type !== \"Int\" && field.type !== \"BigInt\") {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `autoincrement default on \"${field.name}\" requires a non-list Int or BigInt column`,\n meta: { field: field.name },\n });\n }\n\n let def = `${name} ${mysqlColumnTypeSql({ field, enums })}`;\n if (!field.isOptional) def += \" NOT NULL\";\n if (autoincrement) def += \" AUTO_INCREMENT\";\n const defaultExpr = mysqlDefaultSql({ field });\n if (defaultExpr !== undefined) def += ` DEFAULT ${defaultExpr}`;\n return def;\n}\n\nfunction renderAlterColumn(params: {\n step: Extract<MigrationStep, { kind: \"alterColumn\" }>;\n enums: ReadonlyMap<string, EnumIR>;\n}): string[] {\n const { step, enums } = params;\n\n if (step.to.default?.kind === \"autoincrement\" && step.from.default?.kind !== \"autoincrement\") {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `cannot add autoincrement to existing column \"${step.table}\".\"${step.column}\" — drop and recreate the column instead`,\n meta: { table: step.table, column: step.column },\n });\n }\n\n // Type or nullability changes redefine the whole column (MODIFY COLUMN\n // carries type + nullability + default in one definition).\n if (step.changes.includes(\"type\") || step.changes.includes(\"nullability\")) {\n return [\n `ALTER TABLE ${q(step.table)} MODIFY COLUMN ${columnDefSql({ field: step.to, enums })};`,\n ];\n }\n\n // Default-only change.\n const defaultExpr = mysqlDefaultSql({ field: step.to });\n return [\n defaultExpr === undefined\n ? `ALTER TABLE ${q(step.table)} ALTER COLUMN ${q(step.column)} DROP DEFAULT;`\n : `ALTER TABLE ${q(step.table)} ALTER COLUMN ${q(step.column)} SET DEFAULT ${defaultExpr};`,\n ];\n}\n\n// ─── Quoting ──────────────────────────────────────────────────────\n\nfunction q(name: string): string {\n return mysqlDialect.quoteIdent({ name });\n}\n",
|
|
17
17
|
"/**\n * Dialect dispatcher for DDL rendering — the ONE public entry point. Routes to\n * the per-dialect renderers (ddl/postgres.ts, ddl/sqlite.ts, ddl/mysql.ts) so\n * every SQL-text decision stays in exactly one dialect module.\n */\n\nimport type { Dialect, SchemaIR } from \"@vibeorm/schema\";\nimport { renderPostgresSteps } from \"./postgres.ts\";\nimport { renderSqliteSteps } from \"./sqlite.ts\";\nimport { renderMysqlSteps } from \"./mysql.ts\";\nimport type { MigrationStep } from \"../types.ts\";\n\n/**\n * Render migration steps to SQL statements (one string per statement, in\n * order) for a dialect.\n *\n * `from`/`to` — the schemas the steps were diffed from — are OPTIONAL for\n * postgres (ignored) but needed by sqlite whenever a step compiles to the\n * table-rebuild recipe (the target table shape lives on the schema, not the\n * step) and by sqlite/mysql for enum columns (CHECK / inline ENUM values).\n * `generateMigration` and `push` always pass them; direct callers rendering\n * rebuild-free, enum-free steps may omit them.\n */\nexport function renderSteps(params: {\n steps: readonly MigrationStep[];\n dialect: Dialect;\n from?: SchemaIR;\n to?: SchemaIR;\n}): string[] {\n const { steps, dialect, from, to } = params;\n switch (dialect) {\n case \"postgres\":\n return renderPostgresSteps({ steps });\n case \"sqlite\":\n return renderSqliteSteps({\n steps,\n ...(from === undefined ? {} : { from }),\n ...(to === undefined ? {} : { to }),\n });\n case \"mysql\":\n return renderMysqlSteps({\n steps,\n ...(from === undefined ? {} : { from }),\n ...(to === undefined ? {} : { to }),\n });\n }\n}\n",
|
|
18
18
|
"/**\n * Migration runner: generate named migrations from IR diffs, apply them with\n * bookkeeping in `_vibe_migrations`, report status, and repair records.\n *\n * Concurrency: `applyMigrations` takes an advisory lock for the whole run —\n * `pg_advisory_lock(1447645253)` on postgres (\"VIBE\" in ASCII, blocking,\n * released in a finally), `GET_LOCK('vibeorm_migrate', 60)` on mysql (throws\n * VIBE_MIGRATION on timeout). sqlite needs none: it is single-writer and\n * `BEGIN` serializes. Locks are session-scoped — the SqlExecutor contract\n * (types.ts) requires one session for the whole operation.\n *\n * Execution strategy per dialect (`DIALECT_CAPABILITIES[dialect]`):\n *\n * - transactionalDdl (postgres, sqlite): each migration runs inside\n * BEGIN/COMMIT with its bookkeeping INSERT — atomic. EXCEPT sqlite scripts\n * containing a table-rebuild block, which manage their own transactions\n * (execute.ts `usesSelfManagedTransactions`); those run unwrapped and are\n * re-runnable (the rebuild recipe is effectively idempotent), with the\n * record written after the script completes.\n * - mysql (transactionalDdl: false — DDL auto-commits): the runner records\n * PER-STATEMENT progress instead. The row is inserted up front\n * (statement_index 0), advanced after every statement, and on failure the\n * error lands in the `error` column. Re-running RESUMES from the recorded\n * statement_index — and REFUSES if the migration's checksum changed since\n * the partial application. A row is \"complete\" when its statement_index\n * reaches the statement count (or its checksum is empty — resolveMigration\n * records, which store statement_index 2147483647).\n *\n * Checksums (sha256 over the joined SQL) pin a migration's content:\n * re-applying a renamed-or-edited migration is a VIBE_MIGRATION error, never\n * a silent divergence.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { VibeError } from \"@vibeorm/schema\";\nimport type { Dialect, SchemaIR, VibeExtension } from \"@vibeorm/schema\";\nimport { DIALECT_CAPABILITIES, getSqlDialect } from \"@vibeorm/sql\";\nimport { diffSchemas } from \"./differ.ts\";\nimport { renderSteps } from \"./ddl/render.ts\";\nimport {\n artifactCreateSql,\n collectExtensionArtifacts,\n planMissingArtifacts,\n stripExtensionArtifacts,\n} from \"./extensions.ts\";\nimport {\n cleanupSelfManagedFailure,\n executeStatement,\n usesSelfManagedTransactions,\n} from \"./execute.ts\";\nimport type { AppliedResult, MigrationFile, MigrationStatus, SqlExecutor } from \"./types.ts\";\n\n// ─── Bookkeeping table ────────────────────────────────────────────\n\n/** Name of the migrations bookkeeping table (skipped by introspection). */\nexport const MIGRATIONS_TABLE_NAME: string = \"_vibe_migrations\";\n\n/** Advisory-lock key for postgres — \"VIBE\" as a big-endian ASCII int32. */\nconst PG_ADVISORY_LOCK_KEY = 1447645253;\nconst MYSQL_LOCK_NAME = \"vibeorm_migrate\";\nconst MYSQL_LOCK_TIMEOUT_SECONDS = 60;\n\n/** statement_index recorded by resolveMigration — \"complete, content unseen\". */\nconst RESOLVED_STATEMENT_INDEX = 2147483647;\n\nconst CREATE_TABLE_SQL: Readonly<Record<Dialect, string>> = {\n postgres: `CREATE TABLE IF NOT EXISTS \"${MIGRATIONS_TABLE_NAME}\" (\n \"id\" integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,\n \"name\" text NOT NULL UNIQUE,\n \"checksum\" text NOT NULL,\n \"applied_at\" timestamptz(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"statement_index\" integer NOT NULL DEFAULT 0,\n \"error\" text\n);`,\n sqlite: `CREATE TABLE IF NOT EXISTS \"${MIGRATIONS_TABLE_NAME}\" (\n \"id\" INTEGER PRIMARY KEY AUTOINCREMENT,\n \"name\" TEXT NOT NULL UNIQUE,\n \"checksum\" TEXT NOT NULL,\n \"applied_at\" TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"statement_index\" INTEGER NOT NULL DEFAULT 0,\n \"error\" TEXT\n);`,\n mysql: `CREATE TABLE IF NOT EXISTS \\`${MIGRATIONS_TABLE_NAME}\\` (\n \\`id\\` int NOT NULL AUTO_INCREMENT,\n \\`name\\` varchar(191) NOT NULL UNIQUE,\n \\`checksum\\` text NOT NULL,\n \\`applied_at\\` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n \\`statement_index\\` int NOT NULL DEFAULT 0,\n \\`error\\` text,\n PRIMARY KEY (\\`id\\`)\n);`,\n};\n\n/** Create the bookkeeping table when missing. */\nexport async function ensureMigrationsTable(params: {\n executor: SqlExecutor;\n dialect?: Dialect;\n}): Promise<void> {\n await params.executor({ text: CREATE_TABLE_SQL[params.dialect ?? \"postgres\"] });\n}\n\n/** sha256 hex over the migration's statements — its identity across runs. */\nexport function migrationChecksum(params: { sql: readonly string[] }): string {\n return createHash(\"sha256\").update(params.sql.join(\"\\n\")).digest(\"hex\");\n}\n\n// ─── Generate ─────────────────────────────────────────────────────\n\n/**\n * Diff two IRs and render a named migration for a dialect (postgres if\n * omitted). `destructive` aggregates the steps' flags so callers can gate\n * confirmation before applying.\n */\nexport function generateMigration(params: {\n from: SchemaIR;\n to: SchemaIR;\n name: string;\n /** Rendering dialect; postgres if omitted. */\n dialect?: Dialect;\n /** Configured extension instances — their artifacts land in the migration. */\n extensions?: readonly VibeExtension[];\n}): MigrationFile {\n const { from, to, name } = params;\n const dialect = params.dialect ?? \"postgres\";\n\n const artifacts = collectExtensionArtifacts({\n schema: to,\n dialect,\n extensions: params.extensions ?? [],\n });\n const allArtifacts = [...artifacts.setup, ...artifacts.objects];\n const strippedFrom = stripExtensionArtifacts({ schema: from, artifacts: allArtifacts });\n\n const steps = diffSchemas({ from: strippedFrom, to, dialect });\n const coreSql = renderSteps({ steps, dialect, from: strippedFrom, to });\n const missing = planMissingArtifacts({ introspected: from, artifacts: allArtifacts });\n const sql = [\n ...artifactCreateSql({\n artifacts: missing.filter((artifact) => artifact.owns.kind === \"postgresExtension\"),\n }),\n ...coreSql,\n ...artifactCreateSql({\n artifacts: missing.filter((artifact) => artifact.owns.kind !== \"postgresExtension\"),\n }),\n ];\n return {\n name,\n sql,\n destructive: steps.some((step) => step.destructive),\n };\n}\n\n// ─── Apply ────────────────────────────────────────────────────────\n\n/**\n * Apply migrations in order under an advisory lock (see module doc).\n * Already-recorded migrations are checksum-verified and skipped; a mismatch\n * throws VIBE_MIGRATION (a recorded migration whose SQL changed is\n * corruption, not drift to paper over). On mysql, a partially-applied\n * migration RESUMES from its recorded statement_index. Records created by\n * `resolveMigration` (empty checksum) skip verification.\n */\nexport async function applyMigrations(params: {\n executor: SqlExecutor;\n migrations: readonly MigrationFile[];\n /** Execution dialect; postgres if omitted. */\n dialect?: Dialect;\n}): Promise<AppliedResult> {\n const { executor, migrations } = params;\n const dialect = params.dialect ?? \"postgres\";\n const transactional = DIALECT_CAPABILITIES[dialect].transactionalDdl;\n\n await ensureMigrationsTable({ executor, dialect });\n await acquireLock({ executor, dialect });\n\n try {\n const recorded = await recordedRows({ executor, dialect });\n\n const applied: string[] = [];\n const skipped: string[] = [];\n\n for (const migration of migrations) {\n const stored = recorded.get(migration.name);\n if (stored !== undefined) {\n // Negative statement_index = a mysql rollback started but did not\n // finish (see rollbackMigration). Applying over it would corrupt both\n // directions — finish or repair first.\n if (stored.statementIndex < 0) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `migration \"${migration.name}\" is mid-rollback (${-stored.statementIndex - 1} down statement(s) done) — finish it with \\`migrate down\\` or repair with resolveMigration before applying`,\n meta: { migration: migration.name, statementIndex: stored.statementIndex },\n });\n }\n const complete =\n stored.checksum === \"\" ||\n transactional ||\n stored.statementIndex >= migration.sql.length;\n if (complete) {\n assertChecksumMatches({ migration, stored: stored.checksum });\n skipped.push(migration.name);\n continue;\n }\n // mysql partial row → resume, but only for unchanged content.\n assertResumable({ migration, stored });\n await runNonTransactional({\n executor,\n dialect,\n migration,\n start: stored.statementIndex,\n insertRecord: false,\n });\n applied.push(migration.name);\n continue;\n }\n\n if (transactional) {\n await runTransactional({ executor, dialect, migration });\n } else {\n await runNonTransactional({ executor, dialect, migration, start: 0, insertRecord: true });\n }\n applied.push(migration.name);\n }\n\n return { applied, skipped };\n } finally {\n await releaseLock({ executor, dialect });\n }\n}\n\n// ─── Status ───────────────────────────────────────────────────────\n\n/** Compare known migrations against the bookkeeping table. */\nexport async function migrationStatus(params: {\n executor: SqlExecutor;\n migrations: readonly MigrationFile[];\n /** Bookkeeping dialect; postgres if omitted. */\n dialect?: Dialect;\n}): Promise<MigrationStatus> {\n const { executor, migrations } = params;\n const dialect = params.dialect ?? \"postgres\";\n const transactional = DIALECT_CAPABILITIES[dialect].transactionalDdl;\n await ensureMigrationsTable({ executor, dialect });\n const recorded = await recordedRows({ executor, dialect });\n\n const applied: string[] = [];\n const pending: string[] = [];\n const mismatched: string[] = [];\n const rollingBack: string[] = [];\n\n for (const migration of migrations) {\n const stored = recorded.get(migration.name);\n if (stored === undefined) {\n pending.push(migration.name);\n continue;\n }\n if (stored.statementIndex < 0) {\n rollingBack.push(migration.name);\n continue;\n }\n if (stored.checksum === \"\") {\n applied.push(migration.name);\n continue;\n }\n if (stored.checksum !== migrationChecksum({ sql: migration.sql })) {\n mismatched.push(migration.name);\n continue;\n }\n const complete = transactional || stored.statementIndex >= migration.sql.length;\n // A partial mysql row re-applies (resumes) — report it as pending.\n if (complete) applied.push(migration.name);\n else pending.push(migration.name);\n }\n\n return { applied, pending, mismatched, rollingBack };\n}\n\n// ─── Resolve (repair) ─────────────────────────────────────────────\n\n/**\n * Repair the bookkeeping table without running SQL: mark a migration as\n * `\"applied\"` (upsert its record; pass `checksum` to also pin its content —\n * omitted, the record stores an empty checksum and later runs skip\n * verification for it) or `\"rolled-back\"` (delete its record).\n */\nexport async function resolveMigration(params: {\n executor: SqlExecutor;\n name: string;\n as: \"applied\" | \"rolled-back\";\n checksum?: string;\n /** Bookkeeping dialect; postgres if omitted. */\n dialect?: Dialect;\n}): Promise<void> {\n const { executor, name } = params;\n const dialect = params.dialect ?? \"postgres\";\n await ensureMigrationsTable({ executor, dialect });\n\n if (params.as === \"applied\") {\n const insert = `INSERT INTO ${q(dialect, MIGRATIONS_TABLE_NAME)} (${q(dialect, \"name\")}, ${q(dialect, \"checksum\")}, ${q(dialect, \"statement_index\")}) VALUES (${ph(dialect, 1)}, ${ph(dialect, 2)}, ${RESOLVED_STATEMENT_INDEX})`;\n const upsert =\n dialect === \"mysql\"\n ? `${insert} ON DUPLICATE KEY UPDATE \\`checksum\\` = VALUES(\\`checksum\\`), \\`statement_index\\` = VALUES(\\`statement_index\\`), \\`error\\` = NULL`\n : `${insert} ON CONFLICT (\"name\") DO UPDATE SET \"checksum\" = EXCLUDED.\"checksum\", \"statement_index\" = EXCLUDED.\"statement_index\"`;\n await executor({ text: upsert, values: [name, params.checksum ?? \"\"] });\n return;\n }\n await executor({\n text: `DELETE FROM ${q(dialect, MIGRATIONS_TABLE_NAME)} WHERE ${q(dialect, \"name\")} = ${ph(dialect, 1)}`,\n values: [name],\n });\n}\n\n// ─── Rollback ─────────────────────────────────────────────────────\n\n/**\n * Roll back ONE applied migration by executing its `downSql` and deleting its\n * bookkeeping row, under the same advisory lock as `applyMigrations`.\n *\n * Guards, in order: the migration must carry `downSql` (older migrations\n * predate down-migration support), must be recorded as applied, and — when\n * the record pins a checksum — its up SQL must still match (rolling back with\n * drifted files would run a down that no longer mirrors what was applied).\n *\n * Dialect behavior mirrors apply: postgres/sqlite run the down inside\n * BEGIN/COMMIT with the bookkeeping DELETE (atomic; sqlite rebuild scripts\n * run unwrapped, see module doc). mysql DDL auto-commits, so progress is\n * recorded per-statement in the existing `statement_index` column, NEGATIVE\n * to mark the rollback direction: after k down statements, the row stores\n * -(k+1). A failed mysql rollback resumes from the recorded statement on the\n * next call; `applyMigrations` refuses a mid-rollback record. A partially\n * APPLIED mysql migration cannot be rolled back — its down mirrors the full\n * up; finish applying (apply resumes) or repair with `resolveMigration`.\n */\nexport async function rollbackMigration(params: {\n executor: SqlExecutor;\n migration: MigrationFile;\n /** Execution dialect; postgres if omitted. */\n dialect?: Dialect;\n}): Promise<void> {\n const { executor, migration } = params;\n const dialect = params.dialect ?? \"postgres\";\n const transactional = DIALECT_CAPABILITIES[dialect].transactionalDdl;\n\n const downSql = migration.downSql;\n if (downSql === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `migration \"${migration.name}\" has no down.sql — it predates down-migration support; roll it back manually, then repair with resolveMigration (as: \"rolled-back\")`,\n meta: { migration: migration.name },\n });\n }\n\n await ensureMigrationsTable({ executor, dialect });\n await acquireLock({ executor, dialect });\n\n try {\n const recorded = await recordedRows({ executor, dialect });\n const stored = recorded.get(migration.name);\n if (stored === undefined) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `migration \"${migration.name}\" is not recorded as applied — nothing to roll back`,\n meta: { migration: migration.name },\n });\n }\n\n const resumingDown = stored.statementIndex < 0;\n // Verify the up content still matches before trusting its down.\n assertChecksumMatches({ migration, stored: stored.checksum });\n if (!resumingDown) {\n const partialUp =\n !transactional &&\n stored.checksum !== \"\" &&\n stored.statementIndex < migration.sql.length;\n if (partialUp) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `migration \"${migration.name}\" is only partially applied (${stored.statementIndex} of ${migration.sql.length} statement(s)) — its down migration mirrors the FULL up; re-run applyMigrations to finish it (it resumes), or repair with resolveMigration`,\n meta: { migration: migration.name, statementIndex: stored.statementIndex },\n });\n }\n }\n\n if (transactional) {\n await runTransactionalDown({ executor, dialect, migration, downSql });\n } else {\n const start = resumingDown ? -stored.statementIndex - 1 : 0;\n await runNonTransactionalDown({ executor, dialect, migration, downSql, start });\n }\n } finally {\n await releaseLock({ executor, dialect });\n }\n}\n\n/** Atomic down path (postgres, sqlite): statements + record DELETE in one tx. */\nasync function runTransactionalDown(params: {\n executor: SqlExecutor;\n dialect: Dialect;\n migration: MigrationFile;\n downSql: readonly string[];\n}): Promise<void> {\n const { executor, dialect, migration, downSql } = params;\n const selfManaged = dialect === \"sqlite\" && usesSelfManagedTransactions({ sql: downSql });\n const wrap = !selfManaged;\n\n if (wrap) await executor({ text: \"BEGIN\" });\n try {\n for (const statement of downSql) {\n await executeStatement({ executor, statement, dialect });\n }\n await executor({\n text: `DELETE FROM ${q(dialect, MIGRATIONS_TABLE_NAME)} WHERE ${q(dialect, \"name\")} = ${ph(dialect, 1)}`,\n values: [migration.name],\n });\n if (wrap) await executor({ text: \"COMMIT\" });\n } catch (error) {\n if (wrap) {\n try {\n await executor({ text: \"ROLLBACK\" });\n } catch {\n // Rollback is best-effort; the original failure matters more.\n }\n } else {\n await cleanupSelfManagedFailure({ executor });\n }\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `rollback of \"${migration.name}\" failed: ${error instanceof Error ? error.message : String(error)}`,\n meta: { migration: migration.name },\n cause: error,\n });\n }\n}\n\n/**\n * mysql down path: per-statement progress in `statement_index`, stored\n * NEGATIVE (-(completed + 1)) so apply/status can tell the direction apart.\n */\nasync function runNonTransactionalDown(params: {\n executor: SqlExecutor;\n dialect: Dialect;\n migration: MigrationFile;\n downSql: readonly string[];\n start: number;\n}): Promise<void> {\n const { executor, dialect, migration, downSql, start } = params;\n const table = q(dialect, MIGRATIONS_TABLE_NAME);\n\n const recordProgress = async (completed: number): Promise<void> => {\n await executor({\n text: `UPDATE ${table} SET ${q(dialect, \"statement_index\")} = ${ph(dialect, 1)}, ${q(dialect, \"error\")} = NULL WHERE ${q(dialect, \"name\")} = ${ph(dialect, 2)}`,\n values: [-(completed + 1), migration.name],\n });\n };\n\n // Mark the rollback as started before the first statement runs, so a crash\n // between statements can never be mistaken for a completed apply.\n if (start === 0) await recordProgress(0);\n\n for (let index = start; index < downSql.length; index += 1) {\n try {\n await executeStatement({ executor, statement: downSql[index] as string, dialect });\n } catch (error) {\n try {\n await executor({\n text: `UPDATE ${table} SET ${q(dialect, \"error\")} = ${ph(dialect, 1)} WHERE ${q(dialect, \"name\")} = ${ph(dialect, 2)}`,\n values: [error instanceof Error ? error.message : String(error), migration.name],\n });\n } catch {\n // Progress row update is best-effort; the original failure matters more.\n }\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `rollback of \"${migration.name}\" failed at down statement ${index + 1} of ${downSql.length}: ${error instanceof Error ? error.message : String(error)} — progress is recorded; re-running the rollback resumes from this statement`,\n meta: { migration: migration.name, statementIndex: index },\n cause: error,\n });\n }\n await recordProgress(index + 1);\n }\n\n await executor({\n text: `DELETE FROM ${table} WHERE ${q(dialect, \"name\")} = ${ph(dialect, 1)}`,\n values: [migration.name],\n });\n}\n\n// ─── Execution paths ──────────────────────────────────────────────\n\n/** Transactional path (postgres, sqlite) — see module doc. */\nasync function runTransactional(params: {\n executor: SqlExecutor;\n dialect: Dialect;\n migration: MigrationFile;\n}): Promise<void> {\n const { executor, dialect, migration } = params;\n // sqlite rebuild scripts manage their own transactions — never wrap them.\n const selfManaged = dialect === \"sqlite\" && usesSelfManagedTransactions({ sql: migration.sql });\n const wrap = !selfManaged;\n\n if (wrap) await executor({ text: \"BEGIN\" });\n try {\n let statementIndex = 0;\n for (const statement of migration.sql) {\n await executeStatement({ executor, statement, dialect });\n statementIndex += 1;\n }\n await executor({\n text: `INSERT INTO ${q(dialect, MIGRATIONS_TABLE_NAME)} (${q(dialect, \"name\")}, ${q(dialect, \"checksum\")}, ${q(dialect, \"statement_index\")}) VALUES (${ph(dialect, 1)}, ${ph(dialect, 2)}, ${ph(dialect, 3)})`,\n values: [migration.name, migrationChecksum({ sql: migration.sql }), statementIndex],\n });\n if (wrap) await executor({ text: \"COMMIT\" });\n } catch (error) {\n if (wrap) {\n try {\n await executor({ text: \"ROLLBACK\" });\n } catch {\n // Rollback is best-effort; the original failure matters more.\n }\n } else {\n await cleanupSelfManagedFailure({ executor });\n }\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `migration \"${migration.name}\" failed: ${error instanceof Error ? error.message : String(error)}`,\n meta: { migration: migration.name },\n cause: error,\n });\n }\n}\n\n/**\n * Non-transactional path (mysql — DDL auto-commits): per-statement progress\n * in the bookkeeping row; failures record the error and later runs resume.\n */\nasync function runNonTransactional(params: {\n executor: SqlExecutor;\n dialect: Dialect;\n migration: MigrationFile;\n start: number;\n insertRecord: boolean;\n}): Promise<void> {\n const { executor, dialect, migration, start, insertRecord } = params;\n const table = q(dialect, MIGRATIONS_TABLE_NAME);\n\n if (insertRecord) {\n await executor({\n text: `INSERT INTO ${table} (${q(dialect, \"name\")}, ${q(dialect, \"checksum\")}, ${q(dialect, \"statement_index\")}) VALUES (${ph(dialect, 1)}, ${ph(dialect, 2)}, 0)`,\n values: [migration.name, migrationChecksum({ sql: migration.sql })],\n });\n }\n\n for (let index = start; index < migration.sql.length; index += 1) {\n try {\n await executeStatement({ executor, statement: migration.sql[index] as string, dialect });\n } catch (error) {\n // Record the failure (best-effort) — statement_index already points at\n // the failed statement, so a re-run resumes exactly here.\n try {\n await executor({\n text: `UPDATE ${table} SET ${q(dialect, \"error\")} = ${ph(dialect, 1)} WHERE ${q(dialect, \"name\")} = ${ph(dialect, 2)}`,\n values: [error instanceof Error ? error.message : String(error), migration.name],\n });\n } catch {\n // Progress row update is best-effort; the original failure matters more.\n }\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `migration \"${migration.name}\" failed at statement ${index + 1} of ${migration.sql.length}: ${error instanceof Error ? error.message : String(error)} — progress is recorded; re-running applyMigrations resumes from this statement`,\n meta: { migration: migration.name, statementIndex: index },\n cause: error,\n });\n }\n await executor({\n text: `UPDATE ${table} SET ${q(dialect, \"statement_index\")} = ${ph(dialect, 1)}, ${q(dialect, \"error\")} = NULL WHERE ${q(dialect, \"name\")} = ${ph(dialect, 2)}`,\n values: [index + 1, migration.name],\n });\n }\n}\n\n// ─── Advisory locks ───────────────────────────────────────────────\n\nasync function acquireLock(params: { executor: SqlExecutor; dialect: Dialect }): Promise<void> {\n const { executor, dialect } = params;\n if (dialect === \"postgres\") {\n await executor({ text: `SELECT pg_advisory_lock(${PG_ADVISORY_LOCK_KEY})` });\n return;\n }\n if (dialect === \"mysql\") {\n // values: [] forces the row-returning executor path (adapter contract:\n // value-less text may run as a row-less batch statement).\n const rows = await executor({\n text: `SELECT GET_LOCK('${MYSQL_LOCK_NAME}', ${MYSQL_LOCK_TIMEOUT_SECONDS}) AS \\`vibe_lock\\``,\n values: [],\n });\n const acquired = Number(rows[0]?.vibe_lock) === 1;\n if (!acquired) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `could not acquire the migration lock ('${MYSQL_LOCK_NAME}') within ${MYSQL_LOCK_TIMEOUT_SECONDS}s — another migration run is in progress`,\n meta: { lock: MYSQL_LOCK_NAME },\n });\n }\n }\n // sqlite: single-writer; BEGIN serializes — no advisory lock needed.\n}\n\nasync function releaseLock(params: { executor: SqlExecutor; dialect: Dialect }): Promise<void> {\n const { executor, dialect } = params;\n try {\n if (dialect === \"postgres\") {\n await executor({ text: `SELECT pg_advisory_unlock(${PG_ADVISORY_LOCK_KEY})` });\n } else if (dialect === \"mysql\") {\n await executor({ text: `SELECT RELEASE_LOCK('${MYSQL_LOCK_NAME}')` });\n }\n } catch {\n // Releasing is best-effort — the session dropping releases it anyway.\n }\n}\n\n// ─── Internals ────────────────────────────────────────────────────\n\ntype RecordedRow = { checksum: string; statementIndex: number };\n\nasync function recordedRows(params: {\n executor: SqlExecutor;\n dialect: Dialect;\n}): Promise<Map<string, RecordedRow>> {\n const { executor, dialect } = params;\n // values: [] forces the row-returning executor path (adapter contract:\n // value-less text may run as a row-less multi-statement batch on sqlite).\n const rows = await executor({\n text: `SELECT ${q(dialect, \"name\")}, ${q(dialect, \"checksum\")}, ${q(dialect, \"statement_index\")} FROM ${q(dialect, MIGRATIONS_TABLE_NAME)} ORDER BY ${q(dialect, \"id\")}`,\n values: [],\n });\n const result = new Map<string, RecordedRow>();\n for (const row of rows) {\n const rawIndex = Number(row.statement_index);\n result.set(row.name as string, {\n checksum: row.checksum as string,\n statementIndex: Number.isNaN(rawIndex) ? RESOLVED_STATEMENT_INDEX : rawIndex,\n });\n }\n return result;\n}\n\nfunction assertChecksumMatches(params: { migration: MigrationFile; stored: string }): void {\n const { migration, stored } = params;\n if (stored === \"\") return; // resolveMigration record — content unknown by design.\n const actual = migrationChecksum({ sql: migration.sql });\n if (stored === actual) return;\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `checksum mismatch for migration \"${migration.name}\" — its SQL changed after it was applied (recorded ${stored.slice(0, 12)}…, current ${actual.slice(0, 12)}…)`,\n meta: { migration: migration.name, recorded: stored, current: actual },\n });\n}\n\nfunction assertResumable(params: { migration: MigrationFile; stored: RecordedRow }): void {\n const { migration, stored } = params;\n const actual = migrationChecksum({ sql: migration.sql });\n if (stored.checksum === actual) return;\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `migration \"${migration.name}\" is partially applied (${stored.statementIndex} statement(s) done) and its SQL has CHANGED since — refusing to resume; restore the original SQL or repair with resolveMigration`,\n meta: {\n migration: migration.name,\n statementIndex: stored.statementIndex,\n recorded: stored.checksum,\n current: actual,\n },\n });\n}\n\n// ─── Quoting / placeholders ───────────────────────────────────────\n\nfunction q(dialect: Dialect, name: string): string {\n return getSqlDialect({ dialect }).quoteIdent({ name });\n}\n\nfunction ph(dialect: Dialect, index: number): string {\n return getSqlDialect({ dialect }).placeholder({ index });\n}\n",
|
|
19
19
|
"/**\n * Extension artifacts in the migrate pipeline (extensions.md §3 migrate plane).\n *\n * Extensions own database objects the core differ does not model: CREATE\n * EXTENSION, generated tsvector columns, FTS5 shadow tables + triggers,\n * specialty indexes (gin_trgm_ops, hnsw, bm25, FULLTEXT). The contract:\n *\n * 1. `collectExtensionArtifacts` asks each configured extension for its\n * artifacts (dialect-correct, idempotent SQL + a structured owner).\n * 2. `stripExtensionArtifacts` removes owned objects from the INTROSPECTED\n * IR before diffing, so the core differ never schedules their drop —\n * the introspector-representation-is-the-contract rule (LEARNINGS).\n * 3. `planMissingArtifacts` decides which artifacts must be created, by\n * checking the introspected IR for their owners (columns, indexes,\n * tables by name); non-introspectable owners (postgres extensions,\n * triggers) rely on their idempotent IF NOT EXISTS forms and always run.\n *\n * Removing a declaration does NOT auto-drop its artifacts (mirrors the v1\n * phantom-join-table precedent) — `drop` SQL is carried for tooling, not\n * scheduled by push.\n */\n\nimport { extensionDeclarations } from \"@vibeorm/schema\";\nimport type {\n Dialect,\n ExtensionArtifact,\n ModelIR,\n SchemaIR,\n VibeExtension,\n} from \"@vibeorm/schema\";\n\n// ─── Collection ───────────────────────────────────────────────────\n\n/** Artifacts of every configured extension for this schema, in order. */\nexport type CollectedArtifacts = {\n /** CREATE EXTENSION-class artifacts — run BEFORE the core diff SQL. */\n readonly setup: readonly ExtensionArtifact[];\n /** Object artifacts (columns, indexes, shadow tables, triggers) — run AFTER. */\n readonly objects: readonly ExtensionArtifact[];\n};\n\nexport function collectExtensionArtifacts(params: {\n schema: SchemaIR;\n dialect: Dialect;\n extensions: readonly VibeExtension[];\n}): CollectedArtifacts {\n const { schema, dialect, extensions } = params;\n const setup: ExtensionArtifact[] = [];\n const objects: ExtensionArtifact[] = [];\n\n for (const extension of extensions) {\n const artifactsHook = extension.migrate?.artifacts;\n if (artifactsHook === undefined) continue;\n const declarations = extensionDeclarations({ schema, name: extension.name });\n // A configured extension with no schema presence contributes nothing —\n // unless it is a config-only (replication-class) extension.\n if (Object.keys(declarations).length === 0 && extension.schema?.configOnly !== true) continue;\n\n for (const artifact of artifactsHook({\n schema,\n dialect,\n provider: schema.datasource.provider,\n options: extension.options,\n declarations,\n })) {\n (artifact.owns.kind === \"postgresExtension\" ? setup : objects).push(artifact);\n }\n }\n return { setup, objects };\n}\n\n// ─── Introspection filtering ──────────────────────────────────────\n\nfunction ownedTableNames(params: { artifacts: readonly ExtensionArtifact[] }): {\n exact: Set<string>;\n prefixes: string[];\n} {\n const exact = new Set<string>();\n const prefixes: string[] = [];\n for (const artifact of params.artifacts) {\n if (artifact.owns.kind !== \"table\") continue;\n exact.add(artifact.owns.name);\n prefixes.push(...(artifact.owns.auxiliaryPrefixes ?? []));\n }\n return { exact, prefixes };\n}\n\n/**\n * Remove extension-owned objects from an INTROSPECTED SchemaIR so the core\n * differ never sees them (they are neither dropped nor re-created by it).\n */\nexport function stripExtensionArtifacts(params: {\n schema: SchemaIR;\n artifacts: readonly ExtensionArtifact[];\n}): SchemaIR {\n const { schema, artifacts } = params;\n if (artifacts.length === 0) return schema;\n\n const tables = ownedTableNames({ artifacts });\n const ownedColumns = new Map<string, Set<string>>();\n const ownedIndexes = new Map<string, Set<string>>();\n for (const artifact of artifacts) {\n if (artifact.owns.kind === \"column\") {\n const set = ownedColumns.get(artifact.owns.table) ?? new Set<string>();\n set.add(artifact.owns.column);\n ownedColumns.set(artifact.owns.table, set);\n } else if (artifact.owns.kind === \"index\") {\n const set = ownedIndexes.get(artifact.owns.table) ?? new Set<string>();\n set.add(artifact.owns.name);\n ownedIndexes.set(artifact.owns.table, set);\n }\n }\n\n const models: ModelIR[] = [];\n for (const model of schema.models) {\n const tableName = model.dbName ?? model.name;\n if (tables.exact.has(tableName) || tables.prefixes.some((prefix) => tableName.startsWith(prefix))) {\n continue;\n }\n const columns = ownedColumns.get(tableName);\n const indexes = ownedIndexes.get(tableName);\n if (columns === undefined && indexes === undefined) {\n models.push(model);\n continue;\n }\n models.push({\n ...model,\n fields: model.fields.filter((field) => !(columns?.has(field.dbName ?? field.name) ?? false)),\n indexes: model.indexes.filter(\n (index) => !(index.name !== undefined && (indexes?.has(index.name) ?? false)),\n ),\n });\n }\n\n return { ...schema, models };\n}\n\n// ─── Presence planning ────────────────────────────────────────────\n\n/** Owner presence the IR cannot answer, probed live by push (both optional). */\nexport type InstalledExtensionState = {\n /** `SELECT extname FROM pg_extension` — postgres only. */\n readonly pgExtensions?: ReadonlySet<string>;\n /** `sqlite_master WHERE type='trigger'` names — sqlite only. */\n readonly triggers?: ReadonlySet<string>;\n};\n\n/**\n * The artifacts whose owner is missing from the introspected IR (must be\n * created). Owners the IR cannot see — postgres extensions and triggers —\n * consult the live-probed `installed` state when given, else always plan;\n * their `create` SQL is idempotent (IF NOT EXISTS) so replays converge.\n */\nexport function planMissingArtifacts(params: {\n introspected: SchemaIR;\n artifacts: readonly ExtensionArtifact[];\n installed?: InstalledExtensionState;\n}): ExtensionArtifact[] {\n const { introspected, artifacts, installed } = params;\n if (artifacts.length === 0) return [];\n\n const modelByTable = new Map<string, ModelIR>();\n for (const model of introspected.models) {\n modelByTable.set(model.dbName ?? model.name, model);\n }\n\n return artifacts.filter((artifact) => {\n const owner = artifact.owns;\n switch (owner.kind) {\n case \"postgresExtension\":\n return installed?.pgExtensions === undefined ? true : !installed.pgExtensions.has(owner.name);\n case \"trigger\":\n return installed?.triggers === undefined ? true : !installed.triggers.has(owner.name);\n case \"table\":\n return !modelByTable.has(owner.name);\n case \"column\": {\n const model = modelByTable.get(owner.table);\n if (model === undefined) return true;\n return !model.fields.some((field) => (field.dbName ?? field.name) === owner.column);\n }\n case \"index\": {\n const model = modelByTable.get(owner.table);\n if (model === undefined) return true;\n return !model.indexes.some((index) => index.name === owner.name);\n }\n }\n });\n}\n\n/** Probe live owner state the IR cannot carry (used by push before planning). */\nexport async function probeInstalledExtensionState(params: {\n executor: (execParams: { text: string; values?: unknown[] }) => Promise<Record<string, unknown>[]>;\n dialect: Dialect;\n artifacts: readonly ExtensionArtifact[];\n}): Promise<InstalledExtensionState> {\n const { executor, dialect, artifacts } = params;\n const state: { pgExtensions?: ReadonlySet<string>; triggers?: ReadonlySet<string> } = {};\n\n if (dialect === \"postgres\" && artifacts.some((artifact) => artifact.owns.kind === \"postgresExtension\")) {\n const rows = await executor({ text: \"SELECT extname FROM pg_extension\" });\n state.pgExtensions = new Set(rows.map((row) => String(row[\"extname\"])));\n }\n if (dialect === \"sqlite\" && artifacts.some((artifact) => artifact.owns.kind === \"trigger\")) {\n // `values: []` is the adapter-sqlite READ contract on the raw path.\n const rows = await executor({\n text: \"SELECT name FROM sqlite_master WHERE type = 'trigger'\",\n values: [],\n });\n state.triggers = new Set(rows.map((row) => String(row[\"name\"])));\n }\n return state;\n}\n\n/** Flatten artifacts to their create statements, in order. */\nexport function artifactCreateSql(params: {\n artifacts: readonly ExtensionArtifact[];\n}): string[] {\n return params.artifacts.flatMap((artifact) => [...artifact.create]);\n}\n",
|
|
20
20
|
"/**\n * Statement-execution helpers shared by push and the migration runner.\n *\n * Two sqlite realities live here:\n *\n * - SELF-MANAGED SCRIPTS: the table-rebuild recipe (ddl/sqlite.ts) carries its\n * own `PRAGMA foreign_keys=OFF; BEGIN; … COMMIT; PRAGMA foreign_keys=ON;`\n * sequence, because `PRAGMA foreign_keys` is a no-op inside a transaction.\n * Callers must NOT wrap such scripts in an outer BEGIN/COMMIT —\n * `usesSelfManagedTransactions` detects them. Plain statements in a\n * self-managed script auto-commit individually (documented sqlite\n * limitation: a mixed script is not atomic as a whole; each rebuild block\n * is).\n * - `PRAGMA foreign_key_check` RETURNS VIOLATION ROWS instead of failing —\n * `executeStatement` runs it row-returning (`values: []`, the adapter-sqlite\n * contract for reads) and throws VIBE_MIGRATION when any come back.\n */\n\nimport { VibeError } from \"@vibeorm/schema\";\nimport type { Dialect } from \"@vibeorm/schema\";\nimport type { SqlExecutor } from \"./types.ts\";\n\n/** Marker statement opening a self-managed sqlite script (rebuild recipe). */\nconst SELF_MANAGED_MARKER = \"PRAGMA foreign_keys=OFF\";\n\nconst FK_CHECK_PREFIX = \"PRAGMA foreign_key_check\";\n\n/** True when the script manages its own transactions (sqlite rebuilds). */\nexport function usesSelfManagedTransactions(params: { sql: readonly string[] }): boolean {\n return params.sql.some((statement) => statement.startsWith(SELF_MANAGED_MARKER));\n}\n\n/**\n * Execute one migration statement. On sqlite, `PRAGMA foreign_key_check` is\n * executed row-returning and its violations become a VIBE_MIGRATION error.\n */\nexport async function executeStatement(params: {\n executor: SqlExecutor;\n statement: string;\n dialect: Dialect;\n}): Promise<void> {\n const { executor, statement, dialect } = params;\n if (dialect === \"sqlite\" && statement.startsWith(FK_CHECK_PREFIX)) {\n const rows = await executor({ text: statement, values: [] });\n if (rows.length > 0) {\n const sample = rows\n .slice(0, 5)\n .map((row) => `${String(row.table)} rowid ${String(row.rowid)} → ${String(row.parent)}`)\n .join(\"; \");\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `foreign key check failed after table rebuild: ${rows.length} violation(s) — ${sample}`,\n meta: { violations: rows },\n });\n }\n return;\n }\n await executor({ text: statement });\n}\n\n/**\n * Best-effort cleanup after a failed self-managed sqlite script: roll back a\n * possibly-open rebuild transaction and restore FK enforcement. Never throws\n * — the original failure matters more.\n */\nexport async function cleanupSelfManagedFailure(params: { executor: SqlExecutor }): Promise<void> {\n try {\n await params.executor({ text: \"ROLLBACK;\" });\n } catch {\n // No transaction was open — fine.\n }\n try {\n await params.executor({ text: \"PRAGMA foreign_keys=ON;\" });\n } catch {\n // Restoring the pragma is best-effort.\n }\n}\n",
|
|
21
|
-
"/**\n * Introspection helpers shared by ALL dialect introspectors — the join-table\n * detection rule and the relation/naming conventions live HERE, once\n * (LEARNINGS: implicit-M2M conventions must never be re-implemented per\n * consumer). Every dialect introspector produces the same representation:\n *\n * - FKs become an UNNAMED `manyToOne` on the owning model plus an UNNAMED\n * `oneToMany` list side on the target — EXCEPT when the model pair carries\n * more than one unnamed relation pair (mutual FKs, twin FKs to one target,\n * an FK alongside a default-named join table): those FK pairs get a\n * synthesized `@relation` name so `db pull` output re-parses (the parser\n * rejects the unnamed shape as `ambiguous-relation`) and implicit-M2M\n * detection keeps its name keys unique.\n * - A table matching the implicit join-table shape (name `_X`, exactly columns\n * \"A\" and \"B\", two single-column FKs, a unique index on (A, B)) is NOT a\n * model: it becomes two unnamed `oneToMany` list sides on the joined models,\n * carrying `relationName` when the physical name differs from the default\n * `_AToB`.\n */\n\nimport type { CascadeAction, ModelIR, RelationIR } from \"@vibeorm/schema\";\n\n// ─── Shared shapes ────────────────────────────────────────────────\n\n/** A grouped foreign key (composite-capable), dialect-independent. */\nexport type FkGroup = {\n readonly constraintName: string;\n readonly table: string;\n readonly columns: readonly string[];\n readonly refTable: string;\n readonly refColumns: readonly string[];\n readonly onDelete: CascadeAction;\n readonly onUpdate: CascadeAction;\n /** Every FK column NOT NULL (drives isOptional on the relation). */\n readonly required: boolean;\n};\n\n/** An introspected index in the shape join-table detection needs. */\nexport type IntrospectedIndex = {\n readonly table: string;\n readonly name: string;\n readonly unique: boolean;\n readonly kind: string;\n readonly columns: readonly { readonly name: string; readonly desc: boolean }[];\n readonly where?: string;\n};\n\n/** A detected physical join table. */\nexport type JoinTableInfo = {\n readonly tableA: string;\n readonly tableB: string;\n readonly relationName?: string;\n};\n\n// ─── Join-table detection (THE structural rule) ───────────────────\n\n/**\n * Detect whether a physical table is an implicit many-to-many join table:\n * name starts with `_`, columns are exactly \"A\"/\"B\", two single-column FKs\n * cover them, and a unique index spans (A, B). Purely structural — never\n * reads relation types (round-trip stability, LEARNINGS).\n */\nexport function detectJoinTable(params: {\n table: string;\n columnNames: readonly string[];\n fkGroups: readonly FkGroup[];\n indexes: readonly IntrospectedIndex[];\n}): JoinTableInfo | null {\n const { table, columnNames, fkGroups, indexes } = params;\n if (!table.startsWith(\"_\")) return null;\n\n const names = [...columnNames].sort();\n if (names.length !== 2 || names[0] !== \"A\" || names[1] !== \"B\") return null;\n\n const tableFks = fkGroups.filter((group) => group.table === table);\n if (tableFks.length !== 2) return null;\n const fkA = tableFks.find((group) => group.columns.length === 1 && group.columns[0] === \"A\");\n const fkB = tableFks.find((group) => group.columns.length === 1 && group.columns[0] === \"B\");\n if (fkA === undefined || fkB === undefined) return null;\n\n const hasAbUnique = indexes.some(\n (index) =>\n index.table === table &&\n index.unique &&\n index.columns.length === 2 &&\n index.columns[0]?.name === \"A\" &&\n index.columns[1]?.name === \"B\",\n );\n if (!hasAbUnique) return null;\n\n const sorted = [fkA.refTable, fkB.refTable].sort();\n const defaultName = `_${sorted[0]}To${sorted[1]}`;\n return {\n tableA: fkA.refTable,\n tableB: fkB.refTable,\n ...(table === defaultName ? {} : { relationName: table.slice(1) }),\n };\n}\n\n// ─── Relation building ────────────────────────────────────────────\n\n/** Add manyToOne + inverse oneToMany relation pairs for every FK group. */\nexport function addFkRelations(params: {\n models: ModelIR[];\n fkGroups: readonly FkGroup[];\n joinTables: ReadonlyMap<string, JoinTableInfo>;\n}): void {\n const { models, fkGroups, joinTables } = params;\n const modelsByName = new Map(models.map((model) => [model.name, model]));\n const relationsByModel = new Map<string, RelationIR[]>();\n const takeName = nameAllocator({ models });\n const ambiguousPairs = detectAmbiguousPairs({ fkGroups, joinTables, modelsByName });\n\n for (const group of fkGroups) {\n if (joinTables.has(group.table)) continue;\n const owner = modelsByName.get(group.table);\n const target = modelsByName.get(group.refTable);\n if (owner === undefined || target === undefined) continue;\n\n // Prisma's pull convention: `<Table>_<col[_col]>To<RefTable>`, carried by\n // BOTH sides so they pair back deterministically on re-parse.\n const relationName = ambiguousPairs.has(modelPairKey({ a: group.table, b: group.refTable }))\n ? `${group.table}_${group.columns.join(\"_\")}To${group.refTable}`\n : undefined;\n\n const fkSide: RelationIR = {\n name: takeName({ model: owner.name, base: lowerFirst(group.refTable) }),\n model: owner.name,\n targetModel: group.refTable,\n type: \"manyToOne\",\n fields: group.columns,\n references: group.refColumns,\n onDelete: group.onDelete,\n onUpdate: group.onUpdate,\n isList: false,\n isOptional: !group.required,\n ...(relationName === undefined ? {} : { relationName }),\n };\n pushRelation({ relationsByModel, relation: fkSide });\n\n const listSide: RelationIR = {\n name: takeName({ model: target.name, base: lowerFirst(group.table) }),\n model: target.name,\n targetModel: group.table,\n type: \"oneToMany\",\n isList: true,\n isOptional: false,\n ...(relationName === undefined ? {} : { relationName }),\n };\n pushRelation({ relationsByModel, relation: listSide });\n }\n\n applyRelations({ models, relationsByModel });\n}\n\n/** Add the two unnamed oneToMany list sides for every detected join table. */\nexport function addJoinTableRelations(params: {\n models: ModelIR[];\n joinTables: ReadonlyMap<string, JoinTableInfo>;\n}): void {\n const { models, joinTables } = params;\n const modelsByName = new Map(models.map((model) => [model.name, model]));\n const relationsByModel = new Map<string, RelationIR[]>();\n const takeName = nameAllocator({ models });\n\n for (const [, joinTable] of joinTables) {\n const modelA = modelsByName.get(joinTable.tableA);\n const modelB = modelsByName.get(joinTable.tableB);\n if (modelA === undefined || modelB === undefined) continue;\n\n const shared = joinTable.relationName;\n pushRelation({\n relationsByModel,\n relation: {\n name: takeName({ model: modelA.name, base: lowerFirst(modelB.name) }),\n model: modelA.name,\n targetModel: modelB.name,\n type: \"oneToMany\",\n isList: true,\n isOptional: false,\n ...(shared === undefined ? {} : { relationName: shared }),\n },\n });\n pushRelation({\n relationsByModel,\n relation: {\n name: takeName({ model: modelB.name, base: lowerFirst(modelA.name) }),\n model: modelB.name,\n targetModel: modelA.name,\n type: \"oneToMany\",\n isList: true,\n isOptional: false,\n ...(shared === undefined ? {} : { relationName: shared }),\n },\n });\n }\n\n applyRelations({ models, relationsByModel });\n}\n\n// ─── Disambiguation ──────────────────────────────────────\n\n/** Collision-free key for an UNORDERED model pair (self-pairs included). */\nfunction modelPairKey(params: { a: string; b: string }): string {\n const { a, b } = params;\n return [a, b].sort().join(\"\\u0000\");\n}\n\n/**\n * Model pairs whose introspected relations would be ambiguous if every side\n * stayed unnamed: more than one unnamed relation pair between the same two\n * models — mutual FKs, twin FKs to one target, two self-FKs, or an FK\n * alongside a default-named join table. The parser rejects that shape as\n * `ambiguous-relation` (so `db pull` output would not re-parse), and migrate's\n * sole-counterpart M2M rule refuses to pair inside it (so a REAL join table\n * next to an FK would stop round-tripping). FK pairs on these model pairs get\n * synthesized names; join-table sides never do — their physical table name IS\n * their name, so the FK pairs yield.\n */\nfunction detectAmbiguousPairs(params: {\n fkGroups: readonly FkGroup[];\n joinTables: ReadonlyMap<string, JoinTableInfo>;\n modelsByName: ReadonlyMap<string, ModelIR>;\n}): ReadonlySet<string> {\n const { fkGroups, joinTables, modelsByName } = params;\n const counts = new Map<string, number>();\n const bump = (key: string): void => {\n counts.set(key, (counts.get(key) ?? 0) + 1);\n };\n for (const group of fkGroups) {\n if (joinTables.has(group.table)) continue;\n if (!modelsByName.has(group.table) || !modelsByName.has(group.refTable)) continue;\n bump(modelPairKey({ a: group.table, b: group.refTable }));\n }\n for (const [, joinTable] of joinTables) {\n if (joinTable.relationName !== undefined) continue;\n bump(modelPairKey({ a: joinTable.tableA, b: joinTable.tableB }));\n }\n return new Set(\n [...counts.entries()].filter(([, count]) => count > 1).map(([key]) => key),\n );\n}\n\n// ─── Internals ────────────────────────────────────────────────────\n\nfunction pushRelation(params: {\n relationsByModel: Map<string, RelationIR[]>;\n relation: RelationIR;\n}): void {\n const { relationsByModel, relation } = params;\n const list = relationsByModel.get(relation.model);\n if (list === undefined) relationsByModel.set(relation.model, [relation]);\n else list.push(relation);\n}\n\nfunction applyRelations(params: {\n models: ModelIR[];\n relationsByModel: ReadonlyMap<string, RelationIR[]>;\n}): void {\n const { models, relationsByModel } = params;\n for (let index = 0; index < models.length; index += 1) {\n const model = models[index] as ModelIR;\n const additions = relationsByModel.get(model.name);\n if (additions === undefined) continue;\n models[index] = { ...model, relations: [...model.relations, ...additions] };\n }\n}\n\n/** Allocate relation names unique per model AND clashing with no column name. */\nfunction nameAllocator(params: {\n models: readonly ModelIR[];\n}): (args: { model: string; base: string }) => string {\n const { models } = params;\n const used = new Map<string, Set<string>>();\n for (const model of models) {\n used.set(\n model.name,\n new Set([\n ...model.fields.map((field) => field.name),\n ...model.relations.map((relation) => relation.name),\n ]),\n );\n }\n return ({ model, base }) => {\n const names = used.get(model) ?? new Set<string>();\n used.set(model, names);\n let candidate = base;\n let suffix = 2;\n while (names.has(candidate)) {\n candidate = `${base}_${suffix}`;\n suffix += 1;\n }\n names.add(candidate);\n return candidate;\n };\n}\n\n/** Lower-case the first character (relation field names from table names). */\nexport function lowerFirst(value: string): string {\n return value.charAt(0).toLowerCase() + value.slice(1);\n}\n",
|
|
22
|
-
"/**\n * Postgres / PGlite introspection: live database → SchemaIR.\n *\n * Representation contract (the differ's round-trip depends on it, LEARNINGS):\n *\n * - Type mapping is the REVERSE of dialect-matrix §2; `nativeType` is set only\n * when the column's type is NOT the canonical mapping for its scalar.\n * - Identity columns and `nextval(...)` defaults → `@default(autoincrement())`.\n * - Enum ARRAY columns (`data_type = 'ARRAY'`, `udt_name = '_EnumName'`) are\n * enum lists — never `String[]`.\n * - Unknown column types (tsvector, geometry, …) become `isUnsupported` fields\n * with the raw type in `nativeType` — kept, not dropped.\n * - FK/join-table representation comes from introspect/shared.ts — the ONE\n * structural rule every dialect introspector uses.\n * - Views (`isView: true`) are returned with their columns only.\n * - The `_vibe_migrations` bookkeeping table is skipped.\n * - Hardcoded to the `public` schema (v1 parity).\n */\n\nimport type {\n DefaultValueIR,\n EnumIR,\n FieldIR,\n FieldType,\n IndexIR,\n ModelIR,\n ScalarType,\n SchemaIR,\n} from \"@vibeorm/schema\";\nimport { PG_CHAR_TO_CASCADE_ACTION, isNumericScalar } from \"../postgres-types.ts\";\nimport { MIGRATIONS_TABLE_NAME } from \"../runner.ts\";\nimport {\n addFkRelations,\n addJoinTableRelations,\n detectJoinTable,\n} from \"./shared.ts\";\nimport type { FkGroup, IntrospectedIndex, JoinTableInfo } from \"./shared.ts\";\nimport type { SqlExecutor } from \"../types.ts\";\n\n// ─── Catalog queries ──────────────────────────────────────────────\n\n/**\n * Relations that BELONG to an installed postgres extension (pg_depend\n * deptype 'e': postgis's spatial_ref_sys, its geometry_columns view, …) are\n * not user tables: they are created and dropped WITH the extension, and a\n * DROP TABLE on them fails. Excluding them here keeps push/migrate from ever\n * scheduling their drop — first surfaced live on ParadeDB, whose image\n * pre-installs postgis.\n */\nconst EXTENSION_OWNED_FILTER = `NOT EXISTS (\n SELECT 1\n FROM pg_catalog.pg_depend d\n JOIN pg_catalog.pg_class c ON c.oid = d.objid\n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n WHERE d.classid = 'pg_class'::regclass\n AND d.deptype = 'e'\n AND n.nspname = 'public'\n AND c.relname = table_name\n )`;\n\nconst TABLES_QUERY = `\n SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = 'public'\n AND table_type = 'BASE TABLE'\n AND table_name <> '${MIGRATIONS_TABLE_NAME}'\n AND ${EXTENSION_OWNED_FILTER}\n ORDER BY table_name;\n`;\n\nconst VIEWS_QUERY = `\n SELECT table_name\n FROM information_schema.views\n WHERE table_schema = 'public'\n AND ${EXTENSION_OWNED_FILTER}\n ORDER BY table_name;\n`;\n\nconst COLUMNS_QUERY = `\n SELECT\n table_name,\n column_name,\n data_type,\n udt_name,\n is_nullable,\n is_identity,\n column_default,\n datetime_precision,\n character_maximum_length,\n numeric_precision,\n numeric_scale,\n ordinal_position,\n (\n SELECT format_type(a.atttypid, a.atttypmod)\n FROM pg_attribute a\n JOIN pg_class c ON c.oid = a.attrelid\n JOIN pg_namespace n ON n.oid = c.relnamespace\n WHERE n.nspname = 'public'\n AND c.relname = columns.table_name\n AND a.attname = columns.column_name\n ) AS full_type\n FROM information_schema.columns AS columns\n WHERE table_schema = 'public'\n ORDER BY table_name, ordinal_position;\n`;\n\n/**\n * PK/unique constraints via pg_catalog, NOT information_schema:\n * `information_schema.table_constraints` / `key_column_usage` only show\n * constraints on tables the current user owns or holds some privilege OTHER\n * than SELECT on, so a read-only role would silently lose every `@id` while\n * the (already catalog-based) FK query still returns relations — the most\n * confusing possible failure. `unnest WITH ORDINALITY` preserves composite-key\n * column order, matching the FK query below.\n */\nconst CONSTRAINTS_QUERY = `\n SELECT\n c.conname AS constraint_name,\n CASE c.contype WHEN 'p' THEN 'PRIMARY KEY' ELSE 'UNIQUE' END AS constraint_type,\n cl.relname AS table_name,\n att.attname AS column_name\n FROM pg_catalog.pg_constraint c\n JOIN pg_catalog.pg_class cl ON cl.oid = c.conrelid\n JOIN pg_catalog.pg_namespace n ON n.oid = cl.relnamespace\n JOIN unnest(c.conkey) WITH ORDINALITY AS k(attnum, ord) ON true\n JOIN pg_catalog.pg_attribute att ON att.attrelid = c.conrelid AND att.attnum = k.attnum\n WHERE c.contype IN ('p', 'u')\n AND n.nspname = 'public'\n ORDER BY cl.relname, c.conname, k.ord;\n`;\n\n/**\n * FKs via pg_catalog (not information_schema): `unnest(...) WITH ORDINALITY`\n * preserves composite-FK column order across server versions, and\n * `confdeltype` / `confupdtype` surface the cascade actions directly (v1\n * lesson).\n */\nconst FOREIGN_KEYS_QUERY = `\n SELECT\n c.conname AS constraint_name,\n cl.relname AS table_name,\n att.attname AS column_name,\n fcl.relname AS foreign_table_name,\n fatt.attname AS foreign_column_name,\n c.confdeltype AS on_delete_char,\n c.confupdtype AS on_update_char\n FROM pg_catalog.pg_constraint c\n JOIN pg_catalog.pg_class cl ON cl.oid = c.conrelid\n JOIN pg_catalog.pg_namespace n ON n.oid = cl.relnamespace\n JOIN pg_catalog.pg_class fcl ON fcl.oid = c.confrelid\n JOIN pg_catalog.pg_namespace fn ON fn.oid = fcl.relnamespace\n JOIN unnest(c.conkey) WITH ORDINALITY AS lk(attnum, ord) ON true\n JOIN unnest(c.confkey) WITH ORDINALITY AS rk(attnum, ord) ON lk.ord = rk.ord\n JOIN pg_catalog.pg_attribute att ON att.attrelid = c.conrelid AND att.attnum = lk.attnum\n JOIN pg_catalog.pg_attribute fatt ON fatt.attrelid = c.confrelid AND fatt.attnum = rk.attnum\n WHERE c.contype = 'f'\n AND n.nspname = 'public'\n AND fn.nspname = 'public'\n ORDER BY cl.relname, c.conname, lk.ord;\n`;\n\nconst ENUMS_QUERY = `\n SELECT\n t.typname AS type_name,\n e.enumlabel AS enum_value,\n e.enumsortorder AS sort_order\n FROM pg_type t\n JOIN pg_enum e ON t.oid = e.enumtypid\n JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n WHERE n.nspname = 'public'\n ORDER BY t.typname, e.enumsortorder;\n`;\n\nconst INDEXES_QUERY = `\n SELECT\n tablename AS table_name,\n indexname AS index_name,\n indexdef AS index_def\n FROM pg_indexes\n WHERE schemaname = 'public'\n ORDER BY tablename, indexname;\n`;\n\n// ─── Row shapes ───────────────────────────────────────────────────\n\ntype ColumnRow = {\n table: string;\n name: string;\n dataType: string;\n udtName: string;\n nullable: boolean;\n identity: boolean;\n columnDefault: string | null;\n datetimePrecision: number | null;\n charMaxLength: number | null;\n numericPrecision: number | null;\n numericScale: number | null;\n /** `format_type(...)` — carries type modifiers of non-catalog types (vector(3)). */\n fullType: string | null;\n};\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/** Introspect a live postgres/pglite database (public schema) into SchemaIR. */\nexport async function introspectPostgres(params: { executor: SqlExecutor }): Promise<SchemaIR> {\n const { executor } = params;\n\n const [tableRows, viewRows, columnRows, constraintRows, fkRows, enumRows, indexRows] =\n await Promise.all([\n executor({ text: TABLES_QUERY }),\n executor({ text: VIEWS_QUERY }),\n executor({ text: COLUMNS_QUERY }),\n executor({ text: CONSTRAINTS_QUERY }),\n executor({ text: FOREIGN_KEYS_QUERY }),\n executor({ text: ENUMS_QUERY }),\n executor({ text: INDEXES_QUERY }),\n ]);\n\n const tables = tableRows.map((row) => row.table_name as string);\n const views = viewRows.map((row) => row.table_name as string);\n\n const columns: ColumnRow[] = columnRows.map((row) => ({\n table: row.table_name as string,\n name: row.column_name as string,\n dataType: row.data_type as string,\n udtName: row.udt_name as string,\n nullable: (row.is_nullable as string) === \"YES\",\n identity: (row.is_identity as string | null) === \"YES\",\n columnDefault: (row.column_default as string | null) ?? null,\n datetimePrecision: toNumberOrNull(row.datetime_precision),\n charMaxLength: toNumberOrNull(row.character_maximum_length),\n numericPrecision: toNumberOrNull(row.numeric_precision),\n numericScale: toNumberOrNull(row.numeric_scale),\n fullType: (row.full_type as string | null) ?? null,\n }));\n\n // Enums.\n const enums: EnumIR[] = [];\n {\n const valuesByName = new Map<string, string[]>();\n for (const row of enumRows) {\n const name = row.type_name as string;\n const list = valuesByName.get(name);\n if (list === undefined) valuesByName.set(name, [row.enum_value as string]);\n else list.push(row.enum_value as string);\n }\n for (const [name, values] of valuesByName) enums.push({ name, values });\n }\n const enumNames = new Set(enums.map((entry) => entry.name));\n\n // Constraints → PKs, single-column uniques, multi-column uniques.\n const pkByTable = new Map<string, string[]>();\n const uniquesByConstraint = new Map<string, { table: string; columns: string[] }>();\n const constraintNames = new Set<string>();\n for (const row of constraintRows) {\n const table = row.table_name as string;\n const constraintName = row.constraint_name as string;\n const columnName = row.column_name as string;\n constraintNames.add(constraintName);\n if ((row.constraint_type as string) === \"PRIMARY KEY\") {\n const list = pkByTable.get(table);\n if (list === undefined) pkByTable.set(table, [columnName]);\n else list.push(columnName);\n } else {\n const entry = uniquesByConstraint.get(constraintName);\n if (entry === undefined) uniquesByConstraint.set(constraintName, { table, columns: [columnName] });\n else entry.columns.push(columnName);\n }\n }\n\n // FK groups (composite support — actions live on the constraint).\n type MutableFkGroup = {\n constraintName: string;\n table: string;\n columns: string[];\n refTable: string;\n refColumns: string[];\n onDelete: FkGroup[\"onDelete\"];\n onUpdate: FkGroup[\"onUpdate\"];\n };\n const fkGroupsByName = new Map<string, MutableFkGroup>();\n for (const row of fkRows) {\n const constraintName = row.constraint_name as string;\n const existing = fkGroupsByName.get(constraintName);\n if (existing === undefined) {\n fkGroupsByName.set(constraintName, {\n constraintName,\n table: row.table_name as string,\n columns: [row.column_name as string],\n refTable: row.foreign_table_name as string,\n refColumns: [row.foreign_column_name as string],\n onDelete: PG_CHAR_TO_CASCADE_ACTION[(row.on_delete_char as string) ?? \"a\"] ?? \"NoAction\",\n onUpdate: PG_CHAR_TO_CASCADE_ACTION[(row.on_update_char as string) ?? \"a\"] ?? \"NoAction\",\n });\n } else {\n existing.columns.push(row.column_name as string);\n existing.refColumns.push(row.foreign_column_name as string);\n }\n }\n const fkGroups: FkGroup[] = [...fkGroupsByName.values()].map((group) => ({\n ...group,\n required: group.columns.every((columnName) => {\n const column = columns.find((c) => c.table === group.table && c.name === columnName);\n return column === undefined ? true : !column.nullable;\n }),\n }));\n\n // Indexes (parsed from indexdef).\n const indexes: IntrospectedIndex[] = [];\n for (const row of indexRows) {\n const parsed = parseIndexDef({\n table: row.table_name as string,\n name: row.index_name as string,\n def: row.index_def as string,\n });\n if (parsed !== null) indexes.push(parsed);\n }\n\n // Implicit join tables (the shared structural rule).\n const joinTables = new Map<string, JoinTableInfo>();\n for (const table of tables) {\n const detected = detectJoinTable({\n table,\n columnNames: columns.filter((column) => column.table === table).map((column) => column.name),\n fkGroups,\n indexes,\n });\n if (detected !== null) joinTables.set(table, detected);\n }\n\n // Models.\n const models: ModelIR[] = [];\n for (const table of tables) {\n if (joinTables.has(table)) continue;\n models.push(\n buildModel({\n table,\n isView: false,\n columns,\n pkByTable,\n uniquesByConstraint,\n constraintNames,\n indexes,\n enumNames,\n }),\n );\n }\n for (const view of views) {\n models.push(\n buildModel({\n table: view,\n isView: true,\n columns,\n pkByTable,\n uniquesByConstraint,\n constraintNames,\n indexes: [],\n enumNames,\n }),\n );\n }\n\n // Relations: FK side + inverse list side, then implicit M2M list sides.\n addFkRelations({ models, fkGroups, joinTables });\n addJoinTableRelations({ models, joinTables });\n\n return {\n datasource: { provider: \"postgresql\" },\n models,\n enums,\n extensions: [],\n };\n}\n\n// ─── Model building ───────────────────────────────────────────────\n\nfunction buildModel(params: {\n table: string;\n isView: boolean;\n columns: readonly ColumnRow[];\n pkByTable: ReadonlyMap<string, string[]>;\n uniquesByConstraint: ReadonlyMap<string, { table: string; columns: string[] }>;\n constraintNames: ReadonlySet<string>;\n indexes: readonly IntrospectedIndex[];\n enumNames: ReadonlySet<string>;\n}): ModelIR {\n const { table, isView, columns, pkByTable, uniquesByConstraint, constraintNames, indexes, enumNames } =\n params;\n\n const tableColumns = columns.filter((column) => column.table === table);\n const pk = pkByTable.get(table) ?? [];\n\n // Single-column uniqueness (constraints + unique indexes) → field.isUnique.\n const uniqueSingles = new Set<string>();\n const multiUniques: { name: string; columns: string[] }[] = [];\n for (const [name, unique] of uniquesByConstraint) {\n if (unique.table !== table) continue;\n if (unique.columns.length === 1) uniqueSingles.add(unique.columns[0] as string);\n else multiUniques.push({ name, columns: unique.columns });\n }\n const tableIndexes = indexes.filter(\n (index) => index.table === table && !constraintNames.has(index.name),\n );\n for (const index of tableIndexes) {\n if (!index.unique) continue;\n if (index.columns.length === 1) uniqueSingles.add((index.columns[0] as { name: string }).name);\n }\n\n const fields: FieldIR[] = tableColumns.map((column) =>\n buildField({ column, pk, uniqueSingles, enumNames }),\n );\n\n // Indexes: multi-column unique constraints + all non-constraint indexes\n // (single-column uniques were folded into the fields above).\n const modelIndexes: IndexIR[] = [];\n for (const unique of multiUniques) {\n modelIndexes.push({\n name: unique.name,\n kind: \"unique\",\n fields: unique.columns.map((name) => ({ name })),\n });\n }\n for (const index of tableIndexes) {\n if (index.unique && index.columns.length === 1) continue;\n modelIndexes.push({\n name: index.name,\n kind: index.unique ? \"unique\" : index.kind,\n fields: index.columns.map((column) => ({\n name: column.name,\n ...(column.desc ? { sort: \"desc\" as const } : {}),\n })),\n ...(index.where === undefined ? {} : { where: index.where }),\n });\n }\n\n return {\n name: table,\n fields,\n relations: [],\n indexes: modelIndexes,\n isView,\n ...(pk.length > 1 ? { primaryKey: { fields: pk } } : {}),\n };\n}\n\nfunction buildField(params: {\n column: ColumnRow;\n pk: readonly string[];\n uniqueSingles: ReadonlySet<string>;\n enumNames: ReadonlySet<string>;\n}): FieldIR {\n const { column, pk, uniqueSingles, enumNames } = params;\n const mapped = reverseMapType({ column, enumNames });\n const isId = pk.length === 1 && pk[0] === column.name;\n const defaultValue = parseColumnDefault({ column, mapped });\n\n return {\n name: column.name,\n type: mapped.type,\n isList: mapped.isList,\n isOptional: column.nullable,\n isId,\n isUnique: uniqueSingles.has(column.name),\n isUpdatedAt: false,\n ...(defaultValue === undefined ? {} : { default: defaultValue }),\n ...(mapped.nativeType === undefined ? {} : { nativeType: mapped.nativeType }),\n ...(mapped.isUnsupported === true ? { isUnsupported: true as const } : {}),\n };\n}\n\n// ─── Reverse type mapping (dialect-matrix §2, reversed) ───────────\n\ntype MappedType = {\n type: FieldType;\n isList: boolean;\n nativeType?: string;\n isUnsupported?: true;\n};\n\n/** udt_name → canonical scalar for types that ARE the canonical mapping. */\nconst CANONICAL_UDT: Readonly<Record<string, ScalarType>> = {\n text: \"String\",\n bool: \"Boolean\",\n int4: \"Int\",\n int8: \"BigInt\",\n float8: \"Float\",\n numeric: \"Decimal\",\n timestamptz: \"DateTime\",\n jsonb: \"Json\",\n bytea: \"Bytes\",\n};\n\n/** udt_name → scalar for non-canonical types (nativeType carries the truth). */\nconst NON_CANONICAL_UDT: Readonly<Record<string, ScalarType>> = {\n varchar: \"String\",\n bpchar: \"String\",\n uuid: \"String\",\n int2: \"Int\",\n float4: \"Float\",\n timestamp: \"DateTime\",\n date: \"DateTime\",\n json: \"Json\",\n};\n\nfunction reverseMapType(params: { column: ColumnRow; enumNames: ReadonlySet<string> }): MappedType {\n const { column, enumNames } = params;\n const isList = column.dataType === \"ARRAY\";\n const udt = isList ? column.udtName.replace(/^_/, \"\") : column.udtName;\n\n // Enum (scalar or array — the LEARNINGS `_EnumName` lesson).\n if (enumNames.has(udt)) {\n return { type: { enum: udt }, isList };\n }\n\n const canonical = CANONICAL_UDT[udt];\n if (canonical !== undefined) {\n const nativeType = nonCanonicalModifier({ column, udt, scalar: canonical });\n return { type: canonical, isList, ...(nativeType === undefined ? {} : { nativeType }) };\n }\n\n const nonCanonical = NON_CANONICAL_UDT[udt];\n if (nonCanonical !== undefined) {\n return { type: nonCanonical, isList, nativeType: withModifier({ column, udt }) };\n }\n\n // Unknown type → unsupported column, raw type preserved (F3: keep, don't\n // drop). `format_type` keeps modifiers (`vector(3)`), so an extension-lowered\n // column round-trips diff-clean against its declared native type.\n const raw = column.fullType ?? udt;\n return {\n type: \"String\",\n isList: false,\n nativeType: isList && !raw.endsWith(\"[]\") ? `${raw}[]` : raw,\n isUnsupported: true,\n };\n}\n\n/**\n * For canonical base types, return a nativeType only when a modifier makes the\n * column diverge from the canonical mapping (timestamptz(3), numeric(10,2)).\n * Bare `timestamptz` is the canonical DateTime mapping and postgres reports\n * its default precision as 6, so precision 6 (or none) means \"no override\";\n * every other precision is carried truthfully — the differ's equivalence\n * class, not this function, decides that timestamptz(3) needs no ALTER.\n */\nfunction nonCanonicalModifier(params: {\n column: ColumnRow;\n udt: string;\n scalar: ScalarType;\n}): string | undefined {\n const { column, udt, scalar } = params;\n if (scalar === \"DateTime\" && udt === \"timestamptz\") {\n const precision = column.datetimePrecision;\n return precision === null || precision === 6 ? undefined : `timestamptz(${precision})`;\n }\n if (scalar === \"Decimal\" && udt === \"numeric\") {\n if (column.numericPrecision === null) return undefined;\n const scale = column.numericScale ?? 0;\n return `numeric(${column.numericPrecision},${scale})`;\n }\n return undefined;\n}\n\n/** Render `udt(modifier)` for non-canonical types that carry one. */\nfunction withModifier(params: { column: ColumnRow; udt: string }): string {\n const { column, udt } = params;\n if ((udt === \"varchar\" || udt === \"bpchar\") && column.charMaxLength !== null) {\n return `${udt === \"bpchar\" ? \"char\" : \"varchar\"}(${column.charMaxLength})`;\n }\n if (udt === \"bpchar\") return \"char\";\n if (udt === \"timestamp\" && column.datetimePrecision !== null && column.datetimePrecision !== 6) {\n return `timestamp(${column.datetimePrecision})`;\n }\n return udt;\n}\n\n// ─── Default parsing ──────────────────────────────────────────────\n\nfunction parseColumnDefault(params: {\n column: ColumnRow;\n mapped: MappedType;\n}): DefaultValueIR | undefined {\n const { column, mapped } = params;\n\n if (column.identity) return { kind: \"autoincrement\" };\n\n const raw = column.columnDefault;\n if (raw === null) return undefined;\n if (raw.startsWith(\"NULL::\")) return undefined;\n\n if (raw.includes(\"nextval(\")) return { kind: \"autoincrement\" };\n if (raw === \"now()\" || raw.startsWith(\"CURRENT_TIMESTAMP\")) return { kind: \"now\" };\n if (raw === \"true\" || raw === \"false\") return { kind: \"literal\", value: raw === \"true\" };\n if (/^-?\\d+(\\.\\d+)?$/.test(raw)) return { kind: \"literal\", value: Number(raw) };\n\n // 'value' or 'value'::type — embedded quotes arrive doubled.\n const quoted = raw.match(/^'((?:[^']|'')*)'(::.*)?$/);\n if (quoted !== null) {\n const value = (quoted[1] as string).replaceAll(\"''\", \"'\");\n if (typeof mapped.type === \"object\") return { kind: \"enumValue\", value };\n if (isNumericScalar({ type: mapped.type }) && /^-?\\d+(\\.\\d+)?$/.test(value)) {\n return { kind: \"literal\", value: Number(value) };\n }\n // A cast to a non-string type (e.g. '{}'::text[]) is not a plain literal.\n const cast = quoted[2];\n if (cast !== undefined && cast !== \"\" && mapped.isList) {\n return { kind: \"dbgenerated\", sql: raw };\n }\n return { kind: \"literal\", value };\n }\n\n return { kind: \"dbgenerated\", sql: raw };\n}\n\n// ─── Index parsing ────────────────────────────────────────────────\n\n/**\n * Parse a `pg_indexes.indexdef` line:\n * `CREATE [UNIQUE] INDEX name ON schema.table USING method (cols) [WHERE pred]`.\n * The column list is scanned with balanced parentheses (expressions like\n * `lower(email)` and `WHERE` predicates both contain parens, so a regex over\n * the whole line cannot split them). Returns null for definitions that don't\n * match — never expected from pg.\n */\nfunction parseIndexDef(params: {\n table: string;\n name: string;\n def: string;\n}): IntrospectedIndex | null {\n const { table, name, def } = params;\n const head = def.match(/^CREATE (UNIQUE )?INDEX .*? USING (\\w+) \\(/);\n if (head === null) return null;\n\n // Scan the balanced column list starting right after the opening paren.\n const start = (head.index ?? 0) + head[0].length;\n let depth = 1;\n let end = -1;\n for (let position = start; position < def.length; position += 1) {\n const char = def[position];\n if (char === \"(\") depth += 1;\n else if (char === \")\") {\n depth -= 1;\n if (depth === 0) {\n end = position;\n break;\n }\n }\n }\n if (end === -1) return null;\n\n const columns = splitTopLevel({ text: def.slice(start, end) }).map((entry) => {\n const trimmed = entry.trim();\n const desc = / DESC$/i.test(trimmed);\n const nameOnly = trimmed.replace(/ (DESC|ASC)( NULLS (FIRST|LAST))?$/i, \"\");\n return { name: nameOnly.replaceAll('\"', \"\"), desc };\n });\n\n const tail = def.slice(end + 1).trim();\n const whereMatch = tail.match(/^WHERE (.*)$/);\n const whereRaw = whereMatch?.[1];\n return {\n table,\n name,\n unique: head[1] !== undefined,\n kind: (head[2] as string).toLowerCase(),\n columns,\n ...(whereRaw === undefined ? {} : { where: whereRaw }),\n };\n}\n\n/** Split a parenthesized column list on top-level commas only. */\nfunction splitTopLevel(params: { text: string }): string[] {\n const { text } = params;\n const parts: string[] = [];\n let depth = 0;\n let current = \"\";\n for (const char of text) {\n if (char === \"(\") depth += 1;\n if (char === \")\") depth -= 1;\n if (char === \",\" && depth === 0) {\n parts.push(current);\n current = \"\";\n continue;\n }\n current += char;\n }\n if (current.trim().length > 0) parts.push(current);\n return parts;\n}\n\nfunction toNumberOrNull(value: unknown): number | null {\n if (value === null || value === undefined) return null;\n const parsed = Number(value);\n return Number.isNaN(parsed) ? null : parsed;\n}\n",
|
|
23
|
-
"/**\n * SQLite introspection: live database → SchemaIR, from `sqlite_master` (table\n * and index SQL text) plus `PRAGMA table_info / index_list / index_xinfo /\n * foreign_key_list`.\n *\n * THE TEXT-TYPE AMBIGUITY, stated honestly: sqlite stores only the four\n * storage classes we emit, so the reverse mapping is TEXT→String,\n * INTEGER→Int, REAL→Float, BLOB→Bytes — ALWAYS. A DateTime/Decimal/Json\n * column pulls back as String and a Boolean/BigInt as Int; there is no marker\n * to recover the richer type. The differ compensates by comparing columns by\n * storage class on sqlite (normalize.ts), so round-trips stay diff-clean.\n * Two markers DO survive:\n * - enums: our named CHECK constraints (`<table>_<column>_enum_<Enum>`)\n * recover both the enum's name and values;\n * - autoincrement: the literal `PRIMARY KEY AUTOINCREMENT` text on a\n * single-column INTEGER PK.\n * Any other declared type (VARCHAR(30), DATETIME, … from a foreign database)\n * becomes an `isUnsupported` field with the raw type preserved in\n * `nativeType` (F3: keep, don't drop).\n *\n * Representation mirrors introspect/postgres.ts exactly (shared.ts is the one\n * relation/join-table rule): unnamed relation pairs, structural join-table\n * detection, single-column uniques folded into `isUnique`, composite PKs on\n * `model.primaryKey` (PK columns are never optional), views with columns\n * only. Skipped: the `_vibe_migrations` table, `sqlite_*` internals\n * (sqlite_sequence comes with AUTOINCREMENT), and expression indexes\n * (index_xinfo reports no column name for them).\n *\n * Every row-returning query passes `values: []` — through `toSqlExecutor` a\n * value-less text runs on the adapter's multi-statement batch path, which\n * returns no rows (adapter-sqlite contract).\n */\n\nimport type {\n CascadeAction,\n DefaultValueIR,\n EnumIR,\n FieldIR,\n FieldType,\n IndexIR,\n ModelIR,\n SchemaIR,\n} from \"@vibeorm/schema\";\nimport { sqliteDialect } from \"@vibeorm/sql\";\nimport { MIGRATIONS_TABLE_NAME } from \"../runner.ts\";\nimport { parseSqliteEnumChecks } from \"../sqlite-types.ts\";\nimport {\n addFkRelations,\n addJoinTableRelations,\n detectJoinTable,\n} from \"./shared.ts\";\nimport type { FkGroup, IntrospectedIndex, JoinTableInfo } from \"./shared.ts\";\nimport type { SqlExecutor } from \"../types.ts\";\n\n// ─── Row shapes ───────────────────────────────────────────────────\n\ntype MasterRow = { name: string; type: string; sql: string | null };\n\ntype ColumnInfo = {\n name: string;\n declaredType: string;\n notNull: boolean;\n defaultValue: string | null;\n /** 1-based position within the PK, 0 = not part of it. */\n pkPosition: number;\n};\n\nconst SQLITE_ACTION_TO_CASCADE: Readonly<Record<string, CascadeAction>> = {\n \"NO ACTION\": \"NoAction\",\n RESTRICT: \"Restrict\",\n CASCADE: \"Cascade\",\n \"SET NULL\": \"SetNull\",\n \"SET DEFAULT\": \"SetDefault\",\n};\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/** Introspect a live sqlite database into SchemaIR. */\nexport async function introspectSqlite(params: { executor: SqlExecutor }): Promise<SchemaIR> {\n const { executor } = params;\n\n const masterRows = await executor({\n text: `SELECT name, type, sql FROM sqlite_master WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%' AND name <> '${MIGRATIONS_TABLE_NAME}' ORDER BY name`,\n values: [],\n });\n const indexSqlRows = await executor({\n text: `SELECT name, tbl_name, sql FROM sqlite_master WHERE type = 'index' ORDER BY name`,\n values: [],\n });\n\n const entries: MasterRow[] = masterRows.map((row) => ({\n name: row.name as string,\n type: row.type as string,\n sql: (row.sql as string | null) ?? null,\n }));\n const tables = entries.filter((entry) => entry.type === \"table\");\n const views = entries.filter((entry) => entry.type === \"view\");\n\n const indexSqlByName = new Map<string, string | null>();\n for (const row of indexSqlRows) {\n indexSqlByName.set(row.name as string, (row.sql as string | null) ?? null);\n }\n\n // Per-table catalog: columns, indexes, FKs, enum checks.\n const columnsByTable = new Map<string, ColumnInfo[]>();\n const indexes: IntrospectedIndex[] = [];\n const uniqueSinglesByTable = new Map<string, Set<string>>();\n const modelIndexesByTable = new Map<string, IndexIR[]>();\n const fkGroups: FkGroup[] = [];\n const enumsByColumn = new Map<string, { enumName: string; values: readonly string[] }>();\n const enumRegistry = new Map<string, EnumIR>();\n const autoincrementTables = new Set<string>();\n\n for (const table of tables) {\n const columns = await readColumns({ executor, table: table.name });\n columnsByTable.set(table.name, columns);\n\n // Enum CHECK markers from the table's SQL text.\n for (const check of parseSqliteEnumChecks({ tableSql: table.sql ?? \"\" })) {\n enumsByColumn.set(`${table.name}.${check.column}`, {\n enumName: check.enumName,\n values: check.values,\n });\n if (!enumRegistry.has(check.enumName)) {\n enumRegistry.set(check.enumName, { name: check.enumName, values: check.values });\n }\n }\n\n // Autoincrement marker (single-column INTEGER PK only).\n if (/PRIMARY KEY AUTOINCREMENT/i.test(table.sql ?? \"\")) {\n autoincrementTables.add(table.name);\n }\n\n // Indexes.\n const { tableIndexes, uniqueSingles, modelIndexes } = await readIndexes({\n executor,\n table: table.name,\n indexSqlByName,\n });\n indexes.push(...tableIndexes);\n uniqueSinglesByTable.set(table.name, uniqueSingles);\n modelIndexesByTable.set(table.name, modelIndexes);\n\n // Foreign keys.\n fkGroups.push(...(await readForeignKeys({ executor, table: table.name, columns })));\n }\n\n // Implicit join tables (the shared structural rule).\n const joinTables = new Map<string, JoinTableInfo>();\n for (const table of tables) {\n const detected = detectJoinTable({\n table: table.name,\n columnNames: (columnsByTable.get(table.name) ?? []).map((column) => column.name),\n fkGroups,\n indexes,\n });\n if (detected !== null) joinTables.set(table.name, detected);\n }\n\n // Models.\n const models: ModelIR[] = [];\n for (const table of tables) {\n if (joinTables.has(table.name)) continue;\n models.push(\n buildModel({\n table: table.name,\n isView: false,\n columns: columnsByTable.get(table.name) ?? [],\n uniqueSingles: uniqueSinglesByTable.get(table.name) ?? new Set(),\n modelIndexes: modelIndexesByTable.get(table.name) ?? [],\n enumsByColumn,\n autoincrement: autoincrementTables.has(table.name),\n }),\n );\n }\n for (const view of views) {\n models.push(\n buildModel({\n table: view.name,\n isView: true,\n columns: await readColumns({ executor, table: view.name }),\n uniqueSingles: new Set(),\n modelIndexes: [],\n enumsByColumn,\n autoincrement: false,\n }),\n );\n }\n\n addFkRelations({ models, fkGroups, joinTables });\n addJoinTableRelations({ models, joinTables });\n\n return {\n datasource: { provider: \"sqlite\" },\n models,\n enums: [...enumRegistry.values()],\n extensions: [],\n };\n}\n\n// ─── Catalog readers ──────────────────────────────────────────────\n\nasync function readColumns(params: {\n executor: SqlExecutor;\n table: string;\n}): Promise<ColumnInfo[]> {\n const rows = await params.executor({\n text: `PRAGMA table_info(${q(params.table)})`,\n values: [],\n });\n return rows.map((row) => ({\n name: row.name as string,\n declaredType: (row.type as string | null) ?? \"\",\n notNull: Number(row.notnull) === 1,\n defaultValue: row.dflt_value === null || row.dflt_value === undefined ? null : String(row.dflt_value),\n pkPosition: Number(row.pk),\n }));\n}\n\nasync function readIndexes(params: {\n executor: SqlExecutor;\n table: string;\n indexSqlByName: ReadonlyMap<string, string | null>;\n}): Promise<{\n tableIndexes: IntrospectedIndex[];\n uniqueSingles: Set<string>;\n modelIndexes: IndexIR[];\n}> {\n const { executor, table, indexSqlByName } = params;\n const listRows = await executor({ text: `PRAGMA index_list(${q(table)})`, values: [] });\n\n const tableIndexes: IntrospectedIndex[] = [];\n const uniqueSingles = new Set<string>();\n const modelIndexes: IndexIR[] = [];\n\n for (const listRow of listRows) {\n const origin = listRow.origin as string;\n if (origin === \"pk\") continue; // The PK itself — table_info carries it.\n\n const name = listRow.name as string;\n const unique = Number(listRow.unique) === 1;\n const partial = Number(listRow.partial) === 1;\n\n const infoRows = await executor({ text: `PRAGMA index_xinfo(${q(name)})`, values: [] });\n const keyRows = infoRows\n .filter((row) => Number(row.key) === 1)\n .sort((a, b) => Number(a.seqno) - Number(b.seqno));\n let columns: { name: string; desc: boolean }[];\n if (keyRows.some((row) => row.name === null || row.name === undefined)) {\n // Expression index. OUR OWN Decimal form — CAST(\"col\" AS REAL), emitted\n // by the sqlite DDL renderer (SQLITE-2) — is recovered from the index's\n // sqlite_master SQL so `diff(introspect(push(X)), X)` stays [] and push\n // stays idempotent. Any OTHER expression index is skipped (documented\n // non-support), exactly as before.\n const recovered = parseIndexColumnsFromSql({ sql: indexSqlByName.get(name) ?? null });\n if (recovered === null) continue;\n columns = recovered;\n } else {\n columns = keyRows.map((row) => ({\n name: row.name as string,\n desc: Number(row.desc) === 1,\n }));\n }\n\n let where: string | undefined;\n if (partial) {\n const sql = indexSqlByName.get(name);\n const match = sql?.match(/\\sWHERE\\s+(.*)$/is);\n where = match?.[1]?.trim();\n }\n\n tableIndexes.push({\n table,\n name,\n unique,\n kind: \"btree\",\n columns,\n ...(where === undefined ? {} : { where }),\n });\n\n if (unique && columns.length === 1 && where === undefined) {\n uniqueSingles.add((columns[0] as { name: string }).name);\n continue;\n }\n modelIndexes.push({\n name,\n kind: unique ? \"unique\" : \"btree\",\n fields: columns.map((column) => ({\n name: column.name,\n ...(column.desc ? { sort: \"desc\" as const } : {}),\n })),\n ...(where === undefined ? {} : { where }),\n });\n }\n\n return { tableIndexes, uniqueSingles, modelIndexes };\n}\n\n/** One parsed index-column term: `\"col\" [DESC]` or `CAST(\"col\" AS REAL) [DESC]`. */\nconst PLAIN_INDEX_COLUMN = /^\"((?:[^\"]|\"\")+)\"(?:\\s+(ASC|DESC))?$/i;\nconst CAST_REAL_INDEX_COLUMN = /^CAST\\s*\\(\\s*\"((?:[^\"]|\"\")+)\"\\s+AS\\s+REAL\\s*\\)(?:\\s+(ASC|DESC))?$/i;\n\n/**\n * Recover an expression index's column list from its `sqlite_master.sql`\n * (SQLITE-2). Only shapes WE emit parse — plain quoted columns and\n * `CAST(\"col\" AS REAL)`, each with an optional direction; a trailing partial\n * WHERE clause is fine (it sits OUTSIDE the column list — closure item 2).\n * Anything else (other expressions, COLLATE clauses) returns null and the\n * caller skips the index as before.\n */\nexport function parseIndexColumnsFromSql(params: {\n sql: string | null;\n}): { name: string; desc: boolean }[] | null {\n const { sql } = params;\n if (sql === null) return null;\n // Locate the column list's OPENING paren after `ON \"table\"` and walk to its\n // matching close with a depth tracker — a greedy regex capture would swallow\n // through a PARTIAL index's WHERE clause (closure item 2: our own emitted\n // partial Decimal expression index then failed to parse, was skipped as\n // foreign, and every push re-created it).\n const onMatch = /\\sON\\s+\"(?:[^\"]|\"\")+\"\\s*\\(/i.exec(sql);\n if (onMatch === null) return null;\n const open = onMatch.index + onMatch[0].length - 1;\n let listDepth = 0;\n let close = -1;\n for (let index = open; index < sql.length; index++) {\n const char = sql[index];\n if (char === \"(\") listDepth += 1;\n else if (char === \")\") {\n listDepth -= 1;\n if (listDepth === 0) {\n close = index;\n break;\n }\n }\n }\n if (close === -1) return null;\n const list = sql.slice(open + 1, close);\n\n // Split on top-level commas — CAST(…) carries its own parens.\n const terms: string[] = [];\n let depth = 0;\n let start = 0;\n for (let index = 0; index < list.length; index++) {\n const char = list[index];\n if (char === \"(\") depth += 1;\n else if (char === \")\") depth -= 1;\n else if (char === \",\" && depth === 0) {\n terms.push(list.slice(start, index));\n start = index + 1;\n }\n }\n terms.push(list.slice(start));\n\n const columns: { name: string; desc: boolean }[] = [];\n for (const term of terms) {\n const trimmed = term.trim();\n const match = PLAIN_INDEX_COLUMN.exec(trimmed) ?? CAST_REAL_INDEX_COLUMN.exec(trimmed);\n if (match === null) return null;\n columns.push({\n name: (match[1] as string).replaceAll('\"\"', '\"'),\n desc: (match[2] ?? \"\").toUpperCase() === \"DESC\",\n });\n }\n return columns;\n}\n\nasync function readForeignKeys(params: {\n executor: SqlExecutor;\n table: string;\n columns: readonly ColumnInfo[];\n}): Promise<FkGroup[]> {\n const { executor, table, columns } = params;\n const rows = await executor({ text: `PRAGMA foreign_key_list(${q(table)})`, values: [] });\n\n type MutableGroup = {\n columns: string[];\n refTable: string;\n refColumns: string[];\n onDelete: CascadeAction;\n onUpdate: CascadeAction;\n };\n const groups = new Map<number, MutableGroup>();\n const ordered = [...rows].sort(\n (a, b) => Number(a.id) - Number(b.id) || Number(a.seq) - Number(b.seq),\n );\n for (const row of ordered) {\n const id = Number(row.id);\n const from = row.from as string;\n // `to` is null when the FK references the parent's implicit PK — we never\n // emit that form, but resolve it defensively to the parent's rowid alias.\n const to = (row.to as string | null) ?? \"rowid\";\n const existing = groups.get(id);\n if (existing === undefined) {\n groups.set(id, {\n columns: [from],\n refTable: row.table as string,\n refColumns: [to],\n onDelete: SQLITE_ACTION_TO_CASCADE[(row.on_delete as string) ?? \"NO ACTION\"] ?? \"NoAction\",\n onUpdate: SQLITE_ACTION_TO_CASCADE[(row.on_update as string) ?? \"NO ACTION\"] ?? \"NoAction\",\n });\n } else {\n existing.columns.push(from);\n existing.refColumns.push(to);\n }\n }\n\n return [...groups.values()].map((group) => ({\n // sqlite does not surface FK constraint names — recompute the convention\n // the differ's normalization uses, so keys line up.\n constraintName: `${table}_${group.columns.join(\"_\")}_fkey`,\n table,\n columns: group.columns,\n refTable: group.refTable,\n refColumns: group.refColumns,\n onDelete: group.onDelete,\n onUpdate: group.onUpdate,\n required: group.columns.every((columnName) => {\n const column = columns.find((candidate) => candidate.name === columnName);\n return column === undefined ? true : column.notNull;\n }),\n }));\n}\n\n// ─── Model building ───────────────────────────────────────────────\n\nfunction buildModel(params: {\n table: string;\n isView: boolean;\n columns: readonly ColumnInfo[];\n uniqueSingles: ReadonlySet<string>;\n modelIndexes: readonly IndexIR[];\n enumsByColumn: ReadonlyMap<string, { enumName: string; values: readonly string[] }>;\n autoincrement: boolean;\n}): ModelIR {\n const { table, isView, columns, uniqueSingles, modelIndexes, enumsByColumn, autoincrement } =\n params;\n\n const pk = columns\n .filter((column) => column.pkPosition > 0)\n .sort((a, b) => a.pkPosition - b.pkPosition)\n .map((column) => column.name);\n\n const fields: FieldIR[] = columns.map((column) => {\n const enumRef = enumsByColumn.get(`${table}.${column.name}`);\n const mapped = reverseMapType({ column, enumRef });\n const isId = pk.length === 1 && pk[0] === column.name;\n const isAutoincrement =\n autoincrement && isId && column.declaredType.toUpperCase() === \"INTEGER\";\n const defaultValue: DefaultValueIR | undefined = isAutoincrement\n ? { kind: \"autoincrement\" }\n : parseColumnDefault({ column, mapped });\n\n return {\n name: column.name,\n type: mapped.type,\n isList: false,\n // PK columns are never optional: sqlite's table_info reports notnull=0\n // for `INTEGER PRIMARY KEY` rowid aliases, but the column cannot\n // actually hold NULL (postgres-parity rule).\n isOptional: column.pkPosition > 0 ? false : !column.notNull,\n isId,\n isUnique: uniqueSingles.has(column.name),\n isUpdatedAt: false,\n ...(defaultValue === undefined ? {} : { default: defaultValue }),\n ...(mapped.nativeType === undefined ? {} : { nativeType: mapped.nativeType }),\n ...(mapped.isUnsupported === true ? { isUnsupported: true as const } : {}),\n };\n });\n\n return {\n name: table,\n fields,\n relations: [],\n indexes: [...modelIndexes],\n isView,\n ...(pk.length > 1 ? { primaryKey: { fields: pk } } : {}),\n };\n}\n\n// ─── Reverse type mapping (the TEXT-ambiguity rule) ───────────────\n\ntype MappedType = {\n type: FieldType;\n nativeType?: string;\n isUnsupported?: true;\n};\n\nfunction reverseMapType(params: {\n column: ColumnInfo;\n enumRef: { enumName: string; values: readonly string[] } | undefined;\n}): MappedType {\n const { column, enumRef } = params;\n const declared = column.declaredType.trim().toUpperCase();\n\n if (enumRef !== undefined && declared === \"TEXT\") {\n return { type: { enum: enumRef.enumName } };\n }\n switch (declared) {\n case \"TEXT\":\n return { type: \"String\" };\n case \"INTEGER\":\n return { type: \"Int\" };\n case \"REAL\":\n return { type: \"Float\" };\n case \"BLOB\":\n return { type: \"Bytes\" };\n default:\n // Foreign declared type (VARCHAR(30), DATETIME, …) — preserved, not\n // guessed at (F3: keep, don't drop).\n return { type: \"String\", nativeType: column.declaredType, isUnsupported: true };\n }\n}\n\n// ─── Default parsing ──────────────────────────────────────────────\n\nfunction parseColumnDefault(params: {\n column: ColumnInfo;\n mapped: MappedType;\n}): DefaultValueIR | undefined {\n const { column, mapped } = params;\n const raw = column.defaultValue;\n if (raw === null) return undefined;\n\n if (raw === \"CURRENT_TIMESTAMP\") return { kind: \"now\" };\n if (/^-?\\d+(\\.\\d+)?$/.test(raw)) return { kind: \"literal\", value: Number(raw) };\n\n const quoted = raw.match(/^'((?:[^']|'')*)'$/);\n if (quoted !== null) {\n const value = (quoted[1] as string).replaceAll(\"''\", \"'\");\n if (typeof mapped.type === \"object\") return { kind: \"enumValue\", value };\n if ((mapped.type === \"Int\" || mapped.type === \"Float\") && /^-?\\d+(\\.\\d+)?$/.test(value)) {\n return { kind: \"literal\", value: Number(value) };\n }\n return { kind: \"literal\", value };\n }\n\n return { kind: \"dbgenerated\", sql: raw };\n}\n\n// ─── Quoting ──────────────────────────────────────────────────────\n\nfunction q(name: string): string {\n return sqliteDialect.quoteIdent({ name });\n}\n",
|
|
24
|
-
"/**\n * MySQL introspection: live database → SchemaIR, from\n * `information_schema.{tables,views,columns,statistics,key_column_usage,\n * referential_constraints}` (scoped to `DATABASE()`).\n *\n * Representation mirrors introspect/postgres.ts exactly (shared.ts carries\n * the one relation/join-table rule). MySQL-specific decisions:\n *\n * - `COLUMN_TYPE` is the reverse-mapping source: `tinyint(1)` → Boolean (the\n * marker), `varchar(191)` → String, `enum('A','B')` → an enum whose values\n * are parsed from the type and whose NAME is synthesized as\n * `<Table>_<column>` — mysql enums are nameless, so the schema-declared\n * name is unrecoverable. The differ compares enum columns by VALUE LIST\n * (normalize.ts), so the synthetic names never produce phantom steps.\n * - `EXTRA = auto_increment` → `@default(autoincrement())`;\n * `DEFAULT_GENERATED` expressions → `dbgenerated` (CURRENT_TIMESTAMP(…) →\n * `now` first).\n * - Non-canonical column types keep `COLUMN_TYPE` in `nativeType`; unknown\n * types become `isUnsupported` fields (F3: keep, don't drop).\n * - Indexes named like an FK constraint on the same table are SKIPPED: mysql\n * auto-creates them for FKs without a covering index, and surfacing them\n * would churn round-trips with phantom index steps.\n * - The `_vibe_migrations` bookkeeping table is skipped.\n */\n\nimport type {\n CascadeAction,\n DefaultValueIR,\n EnumIR,\n FieldIR,\n FieldType,\n IndexIR,\n ModelIR,\n ScalarType,\n SchemaIR,\n} from \"@vibeorm/schema\";\nimport { normalizeMysqlType, parseMysqlEnumColumnType } from \"../mysql-types.ts\";\nimport { MIGRATIONS_TABLE_NAME } from \"../runner.ts\";\nimport {\n addFkRelations,\n addJoinTableRelations,\n detectJoinTable,\n} from \"./shared.ts\";\nimport type { FkGroup, IntrospectedIndex, JoinTableInfo } from \"./shared.ts\";\nimport type { SqlExecutor } from \"../types.ts\";\n\n// ─── Catalog queries ──────────────────────────────────────────────\n\nconst TABLES_QUERY = `\n SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = DATABASE()\n AND table_type = 'BASE TABLE'\n AND table_name <> '${MIGRATIONS_TABLE_NAME}'\n ORDER BY table_name;\n`;\n\nconst VIEWS_QUERY = `\n SELECT table_name\n FROM information_schema.views\n WHERE table_schema = DATABASE()\n ORDER BY table_name;\n`;\n\nconst COLUMNS_QUERY = `\n SELECT\n table_name,\n column_name,\n column_type,\n is_nullable,\n column_default,\n extra,\n ordinal_position\n FROM information_schema.columns\n WHERE table_schema = DATABASE()\n ORDER BY table_name, ordinal_position;\n`;\n\nconst STATISTICS_QUERY = `\n SELECT\n table_name,\n index_name,\n non_unique,\n seq_in_index,\n column_name,\n collation\n FROM information_schema.statistics\n WHERE table_schema = DATABASE()\n ORDER BY table_name, index_name, seq_in_index;\n`;\n\nconst FOREIGN_KEYS_QUERY = `\n SELECT\n constraint_name,\n table_name,\n column_name,\n ordinal_position,\n referenced_table_name,\n referenced_column_name\n FROM information_schema.key_column_usage\n WHERE table_schema = DATABASE()\n AND referenced_table_name IS NOT NULL\n ORDER BY table_name, constraint_name, ordinal_position;\n`;\n\nconst REFERENTIAL_QUERY = `\n SELECT constraint_name, update_rule, delete_rule\n FROM information_schema.referential_constraints\n WHERE constraint_schema = DATABASE();\n`;\n\n// ─── Row shapes ───────────────────────────────────────────────────\n\ntype ColumnRow = {\n table: string;\n name: string;\n columnType: string;\n nullable: boolean;\n columnDefault: string | null;\n extra: string;\n};\n\nconst MYSQL_RULE_TO_CASCADE: Readonly<Record<string, CascadeAction>> = {\n \"NO ACTION\": \"NoAction\",\n RESTRICT: \"Restrict\",\n CASCADE: \"Cascade\",\n \"SET NULL\": \"SetNull\",\n \"SET DEFAULT\": \"SetDefault\",\n};\n\n// ─── Catalog row reading ─────────────────────────────────\n\n/**\n * Read one column from an information_schema row by its lowercase name,\n * falling back to the UPPERCASE label.\n *\n * MySQL labels information_schema result columns from the data dictionary and\n * the casing has flipped across server lines — verified live on MySQL 8.4,\n * where `SELECT table_name FROM information_schema.tables` comes back labeled\n * `TABLE_NAME`, so every lowercase-only read returned `undefined` and\n * introspecting a NON-EMPTY database crashed (an empty catalog produced no\n * rows, which is why push against a fresh database masked the bug).\n */\nfunction catalogField(params: { row: Record<string, unknown>; name: string }): unknown {\n const value = params.row[params.name];\n return value !== undefined ? value : params.row[params.name.toUpperCase()];\n}\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/** Introspect a live mysql database (current schema) into SchemaIR. */\nexport async function introspectMysql(params: { executor: SqlExecutor }): Promise<SchemaIR> {\n const { executor } = params;\n\n const [tableRows, viewRows, columnRows, statisticRows, fkRows, refRows] = await Promise.all([\n executor({ text: TABLES_QUERY }),\n executor({ text: VIEWS_QUERY }),\n executor({ text: COLUMNS_QUERY }),\n executor({ text: STATISTICS_QUERY }),\n executor({ text: FOREIGN_KEYS_QUERY }),\n executor({ text: REFERENTIAL_QUERY }),\n ]);\n\n const tables = tableRows.map((row) => catalogField({ row, name: \"table_name\" }) as string);\n const views = viewRows.map((row) => catalogField({ row, name: \"table_name\" }) as string);\n\n const columns: ColumnRow[] = columnRows.map((row) => ({\n table: catalogField({ row, name: \"table_name\" }) as string,\n name: catalogField({ row, name: \"column_name\" }) as string,\n columnType: catalogField({ row, name: \"column_type\" }) as string,\n nullable: (catalogField({ row, name: \"is_nullable\" }) as string) === \"YES\",\n columnDefault: (catalogField({ row, name: \"column_default\" }) as string | null) ?? null,\n extra: ((catalogField({ row, name: \"extra\" }) as string | null) ?? \"\").toLowerCase(),\n }));\n\n // Referential rules by constraint name.\n const rulesByConstraint = new Map<string, { onDelete: CascadeAction; onUpdate: CascadeAction }>();\n for (const row of refRows) {\n rulesByConstraint.set(catalogField({ row, name: \"constraint_name\" }) as string, {\n onDelete:\n MYSQL_RULE_TO_CASCADE[\n ((catalogField({ row, name: \"delete_rule\" }) as string) ?? \"NO ACTION\").toUpperCase()\n ] ?? \"NoAction\",\n onUpdate:\n MYSQL_RULE_TO_CASCADE[\n ((catalogField({ row, name: \"update_rule\" }) as string) ?? \"NO ACTION\").toUpperCase()\n ] ?? \"NoAction\",\n });\n }\n\n // FK groups (composite support; ordinal_position preserves column order).\n type MutableGroup = {\n constraintName: string;\n table: string;\n columns: string[];\n refTable: string;\n refColumns: string[];\n };\n const groupsByKey = new Map<string, MutableGroup>();\n for (const row of fkRows) {\n const constraintName = catalogField({ row, name: \"constraint_name\" }) as string;\n const table = catalogField({ row, name: \"table_name\" }) as string;\n const key = `${table}\\u0000${constraintName}`;\n const existing = groupsByKey.get(key);\n if (existing === undefined) {\n groupsByKey.set(key, {\n constraintName,\n table,\n columns: [catalogField({ row, name: \"column_name\" }) as string],\n refTable: catalogField({ row, name: \"referenced_table_name\" }) as string,\n refColumns: [catalogField({ row, name: \"referenced_column_name\" }) as string],\n });\n } else {\n existing.columns.push(catalogField({ row, name: \"column_name\" }) as string);\n existing.refColumns.push(catalogField({ row, name: \"referenced_column_name\" }) as string);\n }\n }\n const fkGroups: FkGroup[] = [...groupsByKey.values()].map((group) => {\n const rules = rulesByConstraint.get(group.constraintName);\n return {\n ...group,\n onDelete: rules?.onDelete ?? \"NoAction\",\n onUpdate: rules?.onUpdate ?? \"NoAction\",\n required: group.columns.every((columnName) => {\n const column = columns.find(\n (candidate) => candidate.table === group.table && candidate.name === columnName,\n );\n return column === undefined ? true : !column.nullable;\n }),\n };\n });\n const fkNamesByTable = new Map<string, Set<string>>();\n for (const group of fkGroups) {\n const set = fkNamesByTable.get(group.table) ?? new Set<string>();\n set.add(group.constraintName);\n fkNamesByTable.set(group.table, set);\n }\n\n // Indexes + PKs from statistics.\n const pkByTable = new Map<string, string[]>();\n const indexes: IntrospectedIndex[] = [];\n {\n type MutableIndex = {\n table: string;\n name: string;\n unique: boolean;\n columns: { name: string; desc: boolean }[];\n };\n const byKey = new Map<string, MutableIndex>();\n for (const row of statisticRows) {\n const table = catalogField({ row, name: \"table_name\" }) as string;\n const name = catalogField({ row, name: \"index_name\" }) as string;\n const columnName = catalogField({ row, name: \"column_name\" }) as string;\n if (name === \"PRIMARY\") {\n const list = pkByTable.get(table);\n if (list === undefined) pkByTable.set(table, [columnName]);\n else list.push(columnName);\n continue;\n }\n // mysql auto-creates an index per FK lacking one, named after the\n // constraint — skip those to keep round-trips churn-free.\n if (fkNamesByTable.get(table)?.has(name) === true) continue;\n\n const key = `${table}\\u0000${name}`;\n const entry = byKey.get(key);\n const column = {\n name: columnName,\n desc: (catalogField({ row, name: \"collation\" }) as string | null) === \"D\",\n };\n if (entry === undefined) {\n byKey.set(key, {\n table,\n name,\n unique: Number(catalogField({ row, name: \"non_unique\" })) === 0,\n columns: [column],\n });\n } else {\n entry.columns.push(column);\n }\n }\n for (const entry of byKey.values()) {\n indexes.push({ ...entry, kind: \"btree\" });\n }\n }\n\n // Enum columns: values parsed from COLUMN_TYPE, names synthesized.\n const enums: EnumIR[] = [];\n\n // Implicit join tables (the shared structural rule).\n const joinTables = new Map<string, JoinTableInfo>();\n for (const table of tables) {\n const detected = detectJoinTable({\n table,\n columnNames: columns.filter((column) => column.table === table).map((column) => column.name),\n fkGroups,\n indexes,\n });\n if (detected !== null) joinTables.set(table, detected);\n }\n\n // Models.\n const models: ModelIR[] = [];\n for (const table of tables) {\n if (joinTables.has(table)) continue;\n models.push(buildModel({ table, isView: false, columns, pkByTable, indexes, enums }));\n }\n for (const view of views) {\n models.push(\n buildModel({ table: view, isView: true, columns, pkByTable: new Map(), indexes: [], enums }),\n );\n }\n\n addFkRelations({ models, fkGroups, joinTables });\n addJoinTableRelations({ models, joinTables });\n\n return {\n datasource: { provider: \"mysql\" },\n models,\n enums,\n extensions: [],\n };\n}\n\n// ─── Model building ───────────────────────────────────────────────\n\nfunction buildModel(params: {\n table: string;\n isView: boolean;\n columns: readonly ColumnRow[];\n pkByTable: ReadonlyMap<string, string[]>;\n indexes: readonly IntrospectedIndex[];\n enums: EnumIR[];\n}): ModelIR {\n const { table, isView, columns, pkByTable, indexes, enums } = params;\n\n const tableColumns = columns.filter((column) => column.table === table);\n const pk = pkByTable.get(table) ?? [];\n\n const tableIndexes = indexes.filter((index) => index.table === table);\n const uniqueSingles = new Set<string>();\n for (const index of tableIndexes) {\n if (index.unique && index.columns.length === 1) {\n uniqueSingles.add((index.columns[0] as { name: string }).name);\n }\n }\n\n const fields: FieldIR[] = tableColumns.map((column) => {\n const mapped = reverseMapType({ table, column, enums });\n const isId = pk.length === 1 && pk[0] === column.name;\n const defaultValue = parseColumnDefault({ column, mapped });\n return {\n name: column.name,\n type: mapped.type,\n isList: false,\n isOptional: column.nullable,\n isId,\n isUnique: uniqueSingles.has(column.name),\n isUpdatedAt: false,\n ...(defaultValue === undefined ? {} : { default: defaultValue }),\n ...(mapped.nativeType === undefined ? {} : { nativeType: mapped.nativeType }),\n ...(mapped.isUnsupported === true ? { isUnsupported: true as const } : {}),\n };\n });\n\n const modelIndexes: IndexIR[] = [];\n for (const index of tableIndexes) {\n if (index.unique && index.columns.length === 1) continue;\n modelIndexes.push({\n name: index.name,\n kind: index.unique ? \"unique\" : \"btree\",\n fields: index.columns.map((column) => ({\n name: column.name,\n ...(column.desc ? { sort: \"desc\" as const } : {}),\n })),\n });\n }\n\n return {\n name: table,\n fields,\n relations: [],\n indexes: modelIndexes,\n isView,\n ...(pk.length > 1 ? { primaryKey: { fields: pk } } : {}),\n };\n}\n\n// ─── Reverse type mapping (dialect-matrix §2, reversed) ───────────\n\ntype MappedType = {\n type: FieldType;\n nativeType?: string;\n isUnsupported?: true;\n};\n\n/** Normalized COLUMN_TYPE → scalar for types that ARE the canonical mapping. */\nconst CANONICAL_MYSQL: Readonly<Record<string, ScalarType>> = {\n \"varchar(191)\": \"String\",\n \"tinyint(1)\": \"Boolean\",\n int: \"Int\",\n bigint: \"BigInt\",\n double: \"Float\",\n \"decimal(65,30)\": \"Decimal\",\n \"datetime(3)\": \"DateTime\",\n json: \"Json\",\n longblob: \"Bytes\",\n};\n\n/** Base type → scalar for non-canonical spellings (nativeType keeps the truth). */\nconst BASE_TO_SCALAR: Readonly<Record<string, ScalarType>> = {\n varchar: \"String\",\n char: \"String\",\n text: \"String\",\n tinytext: \"String\",\n mediumtext: \"String\",\n longtext: \"String\",\n tinyint: \"Int\",\n smallint: \"Int\",\n mediumint: \"Int\",\n int: \"Int\",\n bigint: \"BigInt\",\n double: \"Float\",\n float: \"Float\",\n real: \"Float\",\n decimal: \"Decimal\",\n datetime: \"DateTime\",\n timestamp: \"DateTime\",\n date: \"DateTime\",\n json: \"Json\",\n blob: \"Bytes\",\n tinyblob: \"Bytes\",\n mediumblob: \"Bytes\",\n longblob: \"Bytes\",\n binary: \"Bytes\",\n varbinary: \"Bytes\",\n};\n\nfunction reverseMapType(params: {\n table: string;\n column: ColumnRow;\n enums: EnumIR[];\n}): MappedType {\n const { table, column, enums } = params;\n\n const enumValues = parseMysqlEnumColumnType({ columnType: column.columnType });\n if (enumValues !== null) {\n // mysql enums are nameless — synthesize `<Table>_<column>` and register.\n const name = `${table}_${column.name}`;\n if (!enums.some((entry) => entry.name === name)) {\n enums.push({ name, values: enumValues });\n }\n return { type: { enum: name } };\n }\n\n const normalized = normalizeMysqlType({ raw: column.columnType });\n const canonical = CANONICAL_MYSQL[normalized];\n if (canonical !== undefined) return { type: canonical };\n\n const base = normalized.match(/^([a-z_0-9]+)/)?.[1] ?? normalized;\n const scalar = BASE_TO_SCALAR[base];\n if (scalar !== undefined) {\n return { type: scalar, nativeType: column.columnType };\n }\n\n return { type: \"String\", nativeType: column.columnType, isUnsupported: true };\n}\n\n// ─── Default parsing ──────────────────────────────────────────────\n\nfunction parseColumnDefault(params: {\n column: ColumnRow;\n mapped: MappedType;\n}): DefaultValueIR | undefined {\n const { column, mapped } = params;\n\n if (column.extra.includes(\"auto_increment\")) return { kind: \"autoincrement\" };\n\n const raw = column.columnDefault;\n if (raw === null) return undefined;\n\n if (/^current_timestamp(\\(\\d+\\))?$/i.test(raw)) return { kind: \"now\" };\n if (column.extra.includes(\"default_generated\")) return { kind: \"dbgenerated\", sql: raw };\n\n if (typeof mapped.type === \"object\") return { kind: \"enumValue\", value: raw };\n if (mapped.type === \"Boolean\") {\n if (raw === \"1\" || raw === \"0\") return { kind: \"literal\", value: raw === \"1\" };\n return { kind: \"dbgenerated\", sql: raw };\n }\n if (isNumericScalar({ type: mapped.type }) && /^-?\\d+(\\.\\d+)?$/.test(raw)) {\n return { kind: \"literal\", value: Number(raw) };\n }\n return { kind: \"literal\", value: raw };\n}\n\nfunction isNumericScalar(params: { type: ScalarType }): boolean {\n const { type } = params;\n return type === \"Int\" || type === \"BigInt\" || type === \"Float\" || type === \"Decimal\";\n}\n",
|
|
21
|
+
"/**\n * Introspection helpers shared by ALL dialect introspectors — the join-table\n * detection rule and the relation/naming conventions live HERE, once\n * (LEARNINGS: implicit-M2M conventions must never be re-implemented per\n * consumer). Every dialect introspector produces the same representation:\n *\n * - FKs become an UNNAMED `manyToOne` on the owning model plus an UNNAMED\n * `oneToMany` list side on the target — EXCEPT when the model pair carries\n * more than one unnamed relation pair (mutual FKs, twin FKs to one target,\n * an FK alongside a default-named join table): those FK pairs get a\n * synthesized `@relation` name so `db pull` output re-parses (the parser\n * rejects the unnamed shape as `ambiguous-relation`) and implicit-M2M\n * detection keeps its name keys unique.\n * - A table matching the implicit join-table shape (name `_X`, exactly columns\n * \"A\" and \"B\", two single-column FKs, a unique index on (A, B)) is NOT a\n * model: it becomes two unnamed `oneToMany` list sides on the joined models,\n * carrying `relationName` when the physical name differs from the default\n * `_AToB`.\n */\n\nimport type { CascadeAction, ModelIR, RelationIR } from \"@vibeorm/schema\";\n\n// ─── Shared shapes ────────────────────────────────────────────────\n\n/** A grouped foreign key (composite-capable), dialect-independent. */\nexport type FkGroup = {\n readonly constraintName: string;\n readonly table: string;\n readonly columns: readonly string[];\n readonly refTable: string;\n readonly refColumns: readonly string[];\n readonly onDelete: CascadeAction;\n readonly onUpdate: CascadeAction;\n /** Every FK column NOT NULL (drives isOptional on the relation). */\n readonly required: boolean;\n};\n\n/** An introspected index in the shape join-table detection needs. */\nexport type IntrospectedIndex = {\n readonly table: string;\n readonly name: string;\n readonly unique: boolean;\n readonly kind: string;\n readonly columns: readonly { readonly name: string; readonly desc: boolean }[];\n readonly where?: string;\n /** `UNIQUE NULLS NOT DISTINCT` (postgres 15+). */\n readonly nullsNotDistinct?: boolean;\n};\n\n/** A detected physical join table. */\nexport type JoinTableInfo = {\n readonly tableA: string;\n readonly tableB: string;\n readonly relationName?: string;\n};\n\n// ─── Join-table detection (THE structural rule) ───────────────────\n\n/**\n * Detect whether a physical table is an implicit many-to-many join table:\n * name starts with `_`, columns are exactly \"A\"/\"B\", two single-column FKs\n * cover them, and a unique index spans (A, B). Purely structural — never\n * reads relation types (round-trip stability, LEARNINGS).\n */\nexport function detectJoinTable(params: {\n table: string;\n columnNames: readonly string[];\n fkGroups: readonly FkGroup[];\n indexes: readonly IntrospectedIndex[];\n}): JoinTableInfo | null {\n const { table, columnNames, fkGroups, indexes } = params;\n if (!table.startsWith(\"_\")) return null;\n\n const names = [...columnNames].sort();\n if (names.length !== 2 || names[0] !== \"A\" || names[1] !== \"B\") return null;\n\n const tableFks = fkGroups.filter((group) => group.table === table);\n if (tableFks.length !== 2) return null;\n const fkA = tableFks.find((group) => group.columns.length === 1 && group.columns[0] === \"A\");\n const fkB = tableFks.find((group) => group.columns.length === 1 && group.columns[0] === \"B\");\n if (fkA === undefined || fkB === undefined) return null;\n\n const hasAbUnique = indexes.some(\n (index) =>\n index.table === table &&\n index.unique &&\n index.columns.length === 2 &&\n index.columns[0]?.name === \"A\" &&\n index.columns[1]?.name === \"B\",\n );\n if (!hasAbUnique) return null;\n\n const sorted = [fkA.refTable, fkB.refTable].sort();\n const defaultName = `_${sorted[0]}To${sorted[1]}`;\n return {\n tableA: fkA.refTable,\n tableB: fkB.refTable,\n ...(table === defaultName ? {} : { relationName: table.slice(1) }),\n };\n}\n\n// ─── Relation building ────────────────────────────────────────────\n\n/** Add manyToOne + inverse oneToMany relation pairs for every FK group. */\nexport function addFkRelations(params: {\n models: ModelIR[];\n fkGroups: readonly FkGroup[];\n joinTables: ReadonlyMap<string, JoinTableInfo>;\n}): void {\n const { models, fkGroups, joinTables } = params;\n const modelsByName = new Map(models.map((model) => [model.name, model]));\n const relationsByModel = new Map<string, RelationIR[]>();\n const takeName = nameAllocator({ models });\n const ambiguousPairs = detectAmbiguousPairs({ fkGroups, joinTables, modelsByName });\n\n for (const group of fkGroups) {\n if (joinTables.has(group.table)) continue;\n const owner = modelsByName.get(group.table);\n const target = modelsByName.get(group.refTable);\n if (owner === undefined || target === undefined) continue;\n\n // Prisma's pull convention: `<Table>_<col[_col]>To<RefTable>`, carried by\n // BOTH sides so they pair back deterministically on re-parse.\n const relationName = ambiguousPairs.has(modelPairKey({ a: group.table, b: group.refTable }))\n ? `${group.table}_${group.columns.join(\"_\")}To${group.refTable}`\n : undefined;\n\n const fkSide: RelationIR = {\n name: takeName({ model: owner.name, base: lowerFirst(group.refTable) }),\n model: owner.name,\n targetModel: group.refTable,\n type: \"manyToOne\",\n fields: group.columns,\n references: group.refColumns,\n onDelete: group.onDelete,\n onUpdate: group.onUpdate,\n isList: false,\n isOptional: !group.required,\n ...(relationName === undefined ? {} : { relationName }),\n };\n pushRelation({ relationsByModel, relation: fkSide });\n\n const listSide: RelationIR = {\n name: takeName({ model: target.name, base: lowerFirst(group.table) }),\n model: target.name,\n targetModel: group.table,\n type: \"oneToMany\",\n isList: true,\n isOptional: false,\n ...(relationName === undefined ? {} : { relationName }),\n };\n pushRelation({ relationsByModel, relation: listSide });\n }\n\n applyRelations({ models, relationsByModel });\n}\n\n/** Add the two unnamed oneToMany list sides for every detected join table. */\nexport function addJoinTableRelations(params: {\n models: ModelIR[];\n joinTables: ReadonlyMap<string, JoinTableInfo>;\n}): void {\n const { models, joinTables } = params;\n const modelsByName = new Map(models.map((model) => [model.name, model]));\n const relationsByModel = new Map<string, RelationIR[]>();\n const takeName = nameAllocator({ models });\n\n for (const [, joinTable] of joinTables) {\n const modelA = modelsByName.get(joinTable.tableA);\n const modelB = modelsByName.get(joinTable.tableB);\n if (modelA === undefined || modelB === undefined) continue;\n\n const shared = joinTable.relationName;\n pushRelation({\n relationsByModel,\n relation: {\n name: takeName({ model: modelA.name, base: lowerFirst(modelB.name) }),\n model: modelA.name,\n targetModel: modelB.name,\n type: \"oneToMany\",\n isList: true,\n isOptional: false,\n ...(shared === undefined ? {} : { relationName: shared }),\n },\n });\n pushRelation({\n relationsByModel,\n relation: {\n name: takeName({ model: modelB.name, base: lowerFirst(modelA.name) }),\n model: modelB.name,\n targetModel: modelA.name,\n type: \"oneToMany\",\n isList: true,\n isOptional: false,\n ...(shared === undefined ? {} : { relationName: shared }),\n },\n });\n }\n\n applyRelations({ models, relationsByModel });\n}\n\n// ─── Disambiguation ──────────────────────────────────────\n\n/** Collision-free key for an UNORDERED model pair (self-pairs included). */\nfunction modelPairKey(params: { a: string; b: string }): string {\n const { a, b } = params;\n return [a, b].sort().join(\"\\u0000\");\n}\n\n/**\n * Model pairs whose introspected relations would be ambiguous if every side\n * stayed unnamed: more than one unnamed relation pair between the same two\n * models — mutual FKs, twin FKs to one target, two self-FKs, or an FK\n * alongside a default-named join table. The parser rejects that shape as\n * `ambiguous-relation` (so `db pull` output would not re-parse), and migrate's\n * sole-counterpart M2M rule refuses to pair inside it (so a REAL join table\n * next to an FK would stop round-tripping). FK pairs on these model pairs get\n * synthesized names; join-table sides never do — their physical table name IS\n * their name, so the FK pairs yield.\n */\nfunction detectAmbiguousPairs(params: {\n fkGroups: readonly FkGroup[];\n joinTables: ReadonlyMap<string, JoinTableInfo>;\n modelsByName: ReadonlyMap<string, ModelIR>;\n}): ReadonlySet<string> {\n const { fkGroups, joinTables, modelsByName } = params;\n const counts = new Map<string, number>();\n const bump = (key: string): void => {\n counts.set(key, (counts.get(key) ?? 0) + 1);\n };\n for (const group of fkGroups) {\n if (joinTables.has(group.table)) continue;\n if (!modelsByName.has(group.table) || !modelsByName.has(group.refTable)) continue;\n bump(modelPairKey({ a: group.table, b: group.refTable }));\n }\n for (const [, joinTable] of joinTables) {\n if (joinTable.relationName !== undefined) continue;\n bump(modelPairKey({ a: joinTable.tableA, b: joinTable.tableB }));\n }\n return new Set(\n [...counts.entries()].filter(([, count]) => count > 1).map(([key]) => key),\n );\n}\n\n// ─── Internals ────────────────────────────────────────────────────\n\nfunction pushRelation(params: {\n relationsByModel: Map<string, RelationIR[]>;\n relation: RelationIR;\n}): void {\n const { relationsByModel, relation } = params;\n const list = relationsByModel.get(relation.model);\n if (list === undefined) relationsByModel.set(relation.model, [relation]);\n else list.push(relation);\n}\n\nfunction applyRelations(params: {\n models: ModelIR[];\n relationsByModel: ReadonlyMap<string, RelationIR[]>;\n}): void {\n const { models, relationsByModel } = params;\n for (let index = 0; index < models.length; index += 1) {\n const model = models[index] as ModelIR;\n const additions = relationsByModel.get(model.name);\n if (additions === undefined) continue;\n models[index] = { ...model, relations: [...model.relations, ...additions] };\n }\n}\n\n/** Allocate relation names unique per model AND clashing with no column name. */\nfunction nameAllocator(params: {\n models: readonly ModelIR[];\n}): (args: { model: string; base: string }) => string {\n const { models } = params;\n const used = new Map<string, Set<string>>();\n for (const model of models) {\n used.set(\n model.name,\n new Set([\n ...model.fields.map((field) => field.name),\n ...model.relations.map((relation) => relation.name),\n ]),\n );\n }\n return ({ model, base }) => {\n const names = used.get(model) ?? new Set<string>();\n used.set(model, names);\n let candidate = base;\n let suffix = 2;\n while (names.has(candidate)) {\n candidate = `${base}_${suffix}`;\n suffix += 1;\n }\n names.add(candidate);\n return candidate;\n };\n}\n\n/** Lower-case the first character (relation field names from table names). */\nexport function lowerFirst(value: string): string {\n return value.charAt(0).toLowerCase() + value.slice(1);\n}\n",
|
|
22
|
+
"/**\n * Postgres / PGlite introspection: live database → SchemaIR.\n *\n * Representation contract (the differ's round-trip depends on it, LEARNINGS):\n *\n * - Type mapping is the REVERSE of dialect-matrix §2; `nativeType` is set only\n * when the column's type is NOT the canonical mapping for its scalar.\n * - Identity columns and `nextval(...)` defaults → `@default(autoincrement())`.\n * - Enum ARRAY columns (`data_type = 'ARRAY'`, `udt_name = '_EnumName'`) are\n * enum lists — never `String[]`.\n * - Unknown column types (tsvector, geometry, …) become `isUnsupported` fields\n * with the raw type in `nativeType` — kept, not dropped.\n * - FK/join-table representation comes from introspect/shared.ts — the ONE\n * structural rule every dialect introspector uses.\n * - Views (`isView: true`) are returned with their columns only.\n * - The `_vibe_migrations` bookkeeping table is skipped.\n * - Hardcoded to the `public` schema (v1 parity).\n */\n\nimport type {\n CheckIR,\n DefaultValueIR,\n EnumIR,\n FieldIR,\n FieldType,\n IndexIR,\n ModelIR,\n ScalarType,\n SchemaIR,\n} from \"@vibeorm/schema\";\nimport { PG_CHAR_TO_CASCADE_ACTION, isNumericScalar } from \"../postgres-types.ts\";\nimport { MIGRATIONS_TABLE_NAME } from \"../runner.ts\";\nimport {\n addFkRelations,\n addJoinTableRelations,\n detectJoinTable,\n} from \"./shared.ts\";\nimport type { FkGroup, IntrospectedIndex, JoinTableInfo } from \"./shared.ts\";\nimport type { SqlExecutor } from \"../types.ts\";\n\n// ─── Catalog queries ──────────────────────────────────────────────\n\n/**\n * Relations that BELONG to an installed postgres extension (pg_depend\n * deptype 'e': postgis's spatial_ref_sys, its geometry_columns view, …) are\n * not user tables: they are created and dropped WITH the extension, and a\n * DROP TABLE on them fails. Excluding them here keeps push/migrate from ever\n * scheduling their drop — first surfaced live on ParadeDB, whose image\n * pre-installs postgis.\n */\nconst EXTENSION_OWNED_FILTER = `NOT EXISTS (\n SELECT 1\n FROM pg_catalog.pg_depend d\n JOIN pg_catalog.pg_class c ON c.oid = d.objid\n JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n WHERE d.classid = 'pg_class'::regclass\n AND d.deptype = 'e'\n AND n.nspname = 'public'\n AND c.relname = table_name\n )`;\n\nconst TABLES_QUERY = `\n SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = 'public'\n AND table_type = 'BASE TABLE'\n AND table_name <> '${MIGRATIONS_TABLE_NAME}'\n AND ${EXTENSION_OWNED_FILTER}\n ORDER BY table_name;\n`;\n\nconst VIEWS_QUERY = `\n SELECT table_name\n FROM information_schema.views\n WHERE table_schema = 'public'\n AND ${EXTENSION_OWNED_FILTER}\n ORDER BY table_name;\n`;\n\nconst COLUMNS_QUERY = `\n SELECT\n table_name,\n column_name,\n data_type,\n udt_name,\n is_nullable,\n is_identity,\n column_default,\n datetime_precision,\n character_maximum_length,\n numeric_precision,\n numeric_scale,\n ordinal_position,\n (\n SELECT format_type(a.atttypid, a.atttypmod)\n FROM pg_attribute a\n JOIN pg_class c ON c.oid = a.attrelid\n JOIN pg_namespace n ON n.oid = c.relnamespace\n WHERE n.nspname = 'public'\n AND c.relname = columns.table_name\n AND a.attname = columns.column_name\n ) AS full_type\n FROM information_schema.columns AS columns\n WHERE table_schema = 'public'\n ORDER BY table_name, ordinal_position;\n`;\n\n/**\n * PK/unique constraints via pg_catalog, NOT information_schema:\n * `information_schema.table_constraints` / `key_column_usage` only show\n * constraints on tables the current user owns or holds some privilege OTHER\n * than SELECT on, so a read-only role would silently lose every `@id` while\n * the (already catalog-based) FK query still returns relations — the most\n * confusing possible failure. `unnest WITH ORDINALITY` preserves composite-key\n * column order, matching the FK query below.\n */\nconst CONSTRAINTS_QUERY = `\n SELECT\n c.conname AS constraint_name,\n CASE c.contype WHEN 'p' THEN 'PRIMARY KEY' ELSE 'UNIQUE' END AS constraint_type,\n cl.relname AS table_name,\n att.attname AS column_name\n FROM pg_catalog.pg_constraint c\n JOIN pg_catalog.pg_class cl ON cl.oid = c.conrelid\n JOIN pg_catalog.pg_namespace n ON n.oid = cl.relnamespace\n JOIN unnest(c.conkey) WITH ORDINALITY AS k(attnum, ord) ON true\n JOIN pg_catalog.pg_attribute att ON att.attrelid = c.conrelid AND att.attnum = k.attnum\n WHERE c.contype IN ('p', 'u')\n AND n.nspname = 'public'\n ORDER BY cl.relname, c.conname, k.ord;\n`;\n\n/**\n * Explicit CHECK constraints (contype 'c'), with their re-serialized\n * definition. NAME keys the diff; the expression only matters for `db pull`\n * output — postgres re-serializes it (extra parens, casts), which is exactly\n * why the differ never compares expression text.\n */\nconst CHECKS_QUERY = `\n SELECT\n cl.relname AS table_name,\n c.conname AS constraint_name,\n pg_get_constraintdef(c.oid) AS definition\n FROM pg_catalog.pg_constraint c\n JOIN pg_catalog.pg_class cl ON cl.oid = c.conrelid\n JOIN pg_catalog.pg_namespace n ON n.oid = cl.relnamespace\n WHERE c.contype = 'c'\n AND n.nspname = 'public'\n ORDER BY cl.relname, c.conname;\n`;\n\n/**\n * FKs via pg_catalog (not information_schema): `unnest(...) WITH ORDINALITY`\n * preserves composite-FK column order across server versions, and\n * `confdeltype` / `confupdtype` surface the cascade actions directly (v1\n * lesson).\n */\nconst FOREIGN_KEYS_QUERY = `\n SELECT\n c.conname AS constraint_name,\n cl.relname AS table_name,\n att.attname AS column_name,\n fcl.relname AS foreign_table_name,\n fatt.attname AS foreign_column_name,\n c.confdeltype AS on_delete_char,\n c.confupdtype AS on_update_char\n FROM pg_catalog.pg_constraint c\n JOIN pg_catalog.pg_class cl ON cl.oid = c.conrelid\n JOIN pg_catalog.pg_namespace n ON n.oid = cl.relnamespace\n JOIN pg_catalog.pg_class fcl ON fcl.oid = c.confrelid\n JOIN pg_catalog.pg_namespace fn ON fn.oid = fcl.relnamespace\n JOIN unnest(c.conkey) WITH ORDINALITY AS lk(attnum, ord) ON true\n JOIN unnest(c.confkey) WITH ORDINALITY AS rk(attnum, ord) ON lk.ord = rk.ord\n JOIN pg_catalog.pg_attribute att ON att.attrelid = c.conrelid AND att.attnum = lk.attnum\n JOIN pg_catalog.pg_attribute fatt ON fatt.attrelid = c.confrelid AND fatt.attnum = rk.attnum\n WHERE c.contype = 'f'\n AND n.nspname = 'public'\n AND fn.nspname = 'public'\n ORDER BY cl.relname, c.conname, lk.ord;\n`;\n\nconst ENUMS_QUERY = `\n SELECT\n t.typname AS type_name,\n e.enumlabel AS enum_value,\n e.enumsortorder AS sort_order\n FROM pg_type t\n JOIN pg_enum e ON t.oid = e.enumtypid\n JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n WHERE n.nspname = 'public'\n ORDER BY t.typname, e.enumsortorder;\n`;\n\nconst INDEXES_QUERY = `\n SELECT\n tablename AS table_name,\n indexname AS index_name,\n indexdef AS index_def\n FROM pg_indexes\n WHERE schemaname = 'public'\n ORDER BY tablename, indexname;\n`;\n\n// ─── Row shapes ───────────────────────────────────────────────────\n\ntype ColumnRow = {\n table: string;\n name: string;\n dataType: string;\n udtName: string;\n nullable: boolean;\n identity: boolean;\n columnDefault: string | null;\n datetimePrecision: number | null;\n charMaxLength: number | null;\n numericPrecision: number | null;\n numericScale: number | null;\n /** `format_type(...)` — carries type modifiers of non-catalog types (vector(3)). */\n fullType: string | null;\n};\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/** Introspect a live postgres/pglite database (public schema) into SchemaIR. */\nexport async function introspectPostgres(params: { executor: SqlExecutor }): Promise<SchemaIR> {\n const { executor } = params;\n\n const [tableRows, viewRows, columnRows, constraintRows, fkRows, enumRows, indexRows, checkRows] =\n await Promise.all([\n executor({ text: TABLES_QUERY }),\n executor({ text: VIEWS_QUERY }),\n executor({ text: COLUMNS_QUERY }),\n executor({ text: CONSTRAINTS_QUERY }),\n executor({ text: FOREIGN_KEYS_QUERY }),\n executor({ text: ENUMS_QUERY }),\n executor({ text: INDEXES_QUERY }),\n executor({ text: CHECKS_QUERY }),\n ]);\n\n const tables = tableRows.map((row) => row.table_name as string);\n const views = viewRows.map((row) => row.table_name as string);\n\n const columns: ColumnRow[] = columnRows.map((row) => ({\n table: row.table_name as string,\n name: row.column_name as string,\n dataType: row.data_type as string,\n udtName: row.udt_name as string,\n nullable: (row.is_nullable as string) === \"YES\",\n identity: (row.is_identity as string | null) === \"YES\",\n columnDefault: (row.column_default as string | null) ?? null,\n datetimePrecision: toNumberOrNull(row.datetime_precision),\n charMaxLength: toNumberOrNull(row.character_maximum_length),\n numericPrecision: toNumberOrNull(row.numeric_precision),\n numericScale: toNumberOrNull(row.numeric_scale),\n fullType: (row.full_type as string | null) ?? null,\n }));\n\n // Enums.\n const enums: EnumIR[] = [];\n {\n const valuesByName = new Map<string, string[]>();\n for (const row of enumRows) {\n const name = row.type_name as string;\n const list = valuesByName.get(name);\n if (list === undefined) valuesByName.set(name, [row.enum_value as string]);\n else list.push(row.enum_value as string);\n }\n for (const [name, values] of valuesByName) enums.push({ name, values });\n }\n const enumNames = new Set(enums.map((entry) => entry.name));\n\n // Constraints → PKs, single-column uniques, multi-column uniques.\n const pkByTable = new Map<string, string[]>();\n const uniquesByConstraint = new Map<string, { table: string; columns: string[] }>();\n const constraintNames = new Set<string>();\n for (const row of constraintRows) {\n const table = row.table_name as string;\n const constraintName = row.constraint_name as string;\n const columnName = row.column_name as string;\n constraintNames.add(constraintName);\n if ((row.constraint_type as string) === \"PRIMARY KEY\") {\n const list = pkByTable.get(table);\n if (list === undefined) pkByTable.set(table, [columnName]);\n else list.push(columnName);\n } else {\n const entry = uniquesByConstraint.get(constraintName);\n if (entry === undefined) uniquesByConstraint.set(constraintName, { table, columns: [columnName] });\n else entry.columns.push(columnName);\n }\n }\n\n // CHECK constraints, grouped per table (name + inner expression).\n const checksByTable = new Map<string, CheckIR[]>();\n for (const row of checkRows) {\n const table = row.table_name as string;\n const name = row.constraint_name as string;\n const expression = stripCheckDefinition({ definition: String(row.definition ?? \"\") });\n const list = checksByTable.get(table);\n if (list === undefined) checksByTable.set(table, [{ name, expression }]);\n else list.push({ name, expression });\n }\n\n // FK groups (composite support — actions live on the constraint).\n type MutableFkGroup = {\n constraintName: string;\n table: string;\n columns: string[];\n refTable: string;\n refColumns: string[];\n onDelete: FkGroup[\"onDelete\"];\n onUpdate: FkGroup[\"onUpdate\"];\n };\n const fkGroupsByName = new Map<string, MutableFkGroup>();\n for (const row of fkRows) {\n const constraintName = row.constraint_name as string;\n const existing = fkGroupsByName.get(constraintName);\n if (existing === undefined) {\n fkGroupsByName.set(constraintName, {\n constraintName,\n table: row.table_name as string,\n columns: [row.column_name as string],\n refTable: row.foreign_table_name as string,\n refColumns: [row.foreign_column_name as string],\n onDelete: PG_CHAR_TO_CASCADE_ACTION[(row.on_delete_char as string) ?? \"a\"] ?? \"NoAction\",\n onUpdate: PG_CHAR_TO_CASCADE_ACTION[(row.on_update_char as string) ?? \"a\"] ?? \"NoAction\",\n });\n } else {\n existing.columns.push(row.column_name as string);\n existing.refColumns.push(row.foreign_column_name as string);\n }\n }\n const fkGroups: FkGroup[] = [...fkGroupsByName.values()].map((group) => ({\n ...group,\n required: group.columns.every((columnName) => {\n const column = columns.find((c) => c.table === group.table && c.name === columnName);\n return column === undefined ? true : !column.nullable;\n }),\n }));\n\n // Indexes (parsed from indexdef).\n const indexes: IntrospectedIndex[] = [];\n for (const row of indexRows) {\n const parsed = parseIndexDef({\n table: row.table_name as string,\n name: row.index_name as string,\n def: row.index_def as string,\n });\n if (parsed !== null) indexes.push(parsed);\n }\n\n // Implicit join tables (the shared structural rule).\n const joinTables = new Map<string, JoinTableInfo>();\n for (const table of tables) {\n const detected = detectJoinTable({\n table,\n columnNames: columns.filter((column) => column.table === table).map((column) => column.name),\n fkGroups,\n indexes,\n });\n if (detected !== null) joinTables.set(table, detected);\n }\n\n // Models.\n const models: ModelIR[] = [];\n for (const table of tables) {\n if (joinTables.has(table)) continue;\n models.push(\n buildModel({\n table,\n isView: false,\n columns,\n pkByTable,\n uniquesByConstraint,\n constraintNames,\n indexes,\n enumNames,\n checks: checksByTable.get(table) ?? [],\n }),\n );\n }\n for (const view of views) {\n models.push(\n buildModel({\n table: view,\n isView: true,\n columns,\n pkByTable,\n uniquesByConstraint,\n constraintNames,\n indexes: [],\n enumNames,\n checks: [],\n }),\n );\n }\n\n // Relations: FK side + inverse list side, then implicit M2M list sides.\n addFkRelations({ models, fkGroups, joinTables });\n addJoinTableRelations({ models, joinTables });\n\n return {\n datasource: { provider: \"postgresql\" },\n models,\n enums,\n extensions: [],\n };\n}\n\n// ─── Model building ───────────────────────────────────────────────\n\nfunction buildModel(params: {\n table: string;\n isView: boolean;\n columns: readonly ColumnRow[];\n pkByTable: ReadonlyMap<string, string[]>;\n uniquesByConstraint: ReadonlyMap<string, { table: string; columns: string[] }>;\n constraintNames: ReadonlySet<string>;\n indexes: readonly IntrospectedIndex[];\n enumNames: ReadonlySet<string>;\n checks: readonly CheckIR[];\n}): ModelIR {\n const { table, isView, columns, pkByTable, uniquesByConstraint, constraintNames, indexes, enumNames } =\n params;\n\n const tableColumns = columns.filter((column) => column.table === table);\n const pk = pkByTable.get(table) ?? [];\n\n // Single-column uniqueness (constraints + unique indexes) → field.isUnique.\n const uniqueSingles = new Set<string>();\n const multiUniques: { name: string; columns: string[] }[] = [];\n for (const [name, unique] of uniquesByConstraint) {\n if (unique.table !== table) continue;\n if (unique.columns.length === 1) uniqueSingles.add(unique.columns[0] as string);\n else multiUniques.push({ name, columns: unique.columns });\n }\n const tableIndexes = indexes.filter(\n (index) => index.table === table && !constraintNames.has(index.name),\n );\n for (const index of tableIndexes) {\n if (!index.unique) continue;\n // A partial or NULLS-NOT-DISTINCT unique is NOT a plain field @unique —\n // folding it would drop the predicate/flag and make every diff recreate\n // the index. Those stay model-level indexes below.\n if (index.columns.length === 1 && index.where === undefined && index.nullsNotDistinct !== true) {\n uniqueSingles.add((index.columns[0] as { name: string }).name);\n }\n }\n\n const fields: FieldIR[] = tableColumns.map((column) =>\n buildField({ column, pk, uniqueSingles, enumNames }),\n );\n\n // Indexes: multi-column unique constraints + all non-constraint indexes\n // (single-column uniques were folded into the fields above).\n const modelIndexes: IndexIR[] = [];\n for (const unique of multiUniques) {\n modelIndexes.push({\n name: unique.name,\n kind: \"unique\",\n fields: unique.columns.map((name) => ({ name })),\n });\n }\n for (const index of tableIndexes) {\n if (\n index.unique &&\n index.columns.length === 1 &&\n index.where === undefined &&\n index.nullsNotDistinct !== true\n ) {\n continue; // folded into field.isUnique above\n }\n modelIndexes.push({\n name: index.name,\n kind: index.unique ? \"unique\" : index.kind,\n fields: index.columns.map((column) => ({\n name: column.name,\n ...(column.desc ? { sort: \"desc\" as const } : {}),\n })),\n ...(index.where === undefined ? {} : { where: index.where }),\n ...(index.nullsNotDistinct === true ? { nullsNotDistinct: true } : {}),\n });\n }\n\n return {\n name: table,\n fields,\n relations: [],\n indexes: modelIndexes,\n ...(params.checks.length === 0 ? {} : { checks: params.checks }),\n isView,\n ...(pk.length > 1 ? { primaryKey: { fields: pk } } : {}),\n };\n}\n\n/** `pg_get_constraintdef` → the inner expression: `CHECK ((amount >= 0))` → `(amount >= 0)`. */\nfunction stripCheckDefinition(params: { definition: string }): string {\n const trimmed = params.definition.trim();\n const match = trimmed.match(/^CHECK\\s*\\((.*)\\)$/is);\n return match === null ? trimmed : (match[1] as string).trim();\n}\n\nfunction buildField(params: {\n column: ColumnRow;\n pk: readonly string[];\n uniqueSingles: ReadonlySet<string>;\n enumNames: ReadonlySet<string>;\n}): FieldIR {\n const { column, pk, uniqueSingles, enumNames } = params;\n const mapped = reverseMapType({ column, enumNames });\n const isId = pk.length === 1 && pk[0] === column.name;\n const defaultValue = parseColumnDefault({ column, mapped });\n\n return {\n name: column.name,\n type: mapped.type,\n isList: mapped.isList,\n isOptional: column.nullable,\n isId,\n isUnique: uniqueSingles.has(column.name),\n isUpdatedAt: false,\n ...(defaultValue === undefined ? {} : { default: defaultValue }),\n ...(mapped.nativeType === undefined ? {} : { nativeType: mapped.nativeType }),\n ...(mapped.isUnsupported === true ? { isUnsupported: true as const } : {}),\n };\n}\n\n// ─── Reverse type mapping (dialect-matrix §2, reversed) ───────────\n\ntype MappedType = {\n type: FieldType;\n isList: boolean;\n nativeType?: string;\n isUnsupported?: true;\n};\n\n/** udt_name → canonical scalar for types that ARE the canonical mapping. */\nconst CANONICAL_UDT: Readonly<Record<string, ScalarType>> = {\n text: \"String\",\n bool: \"Boolean\",\n int4: \"Int\",\n int8: \"BigInt\",\n float8: \"Float\",\n numeric: \"Decimal\",\n timestamptz: \"DateTime\",\n jsonb: \"Json\",\n bytea: \"Bytes\",\n};\n\n/** udt_name → scalar for non-canonical types (nativeType carries the truth). */\nconst NON_CANONICAL_UDT: Readonly<Record<string, ScalarType>> = {\n varchar: \"String\",\n bpchar: \"String\",\n uuid: \"String\",\n int2: \"Int\",\n float4: \"Float\",\n timestamp: \"DateTime\",\n date: \"DateTime\",\n json: \"Json\",\n};\n\nfunction reverseMapType(params: { column: ColumnRow; enumNames: ReadonlySet<string> }): MappedType {\n const { column, enumNames } = params;\n const isList = column.dataType === \"ARRAY\";\n const udt = isList ? column.udtName.replace(/^_/, \"\") : column.udtName;\n\n // Enum (scalar or array — the LEARNINGS `_EnumName` lesson).\n if (enumNames.has(udt)) {\n return { type: { enum: udt }, isList };\n }\n\n const canonical = CANONICAL_UDT[udt];\n if (canonical !== undefined) {\n const nativeType = nonCanonicalModifier({ column, udt, scalar: canonical });\n return { type: canonical, isList, ...(nativeType === undefined ? {} : { nativeType }) };\n }\n\n const nonCanonical = NON_CANONICAL_UDT[udt];\n if (nonCanonical !== undefined) {\n return { type: nonCanonical, isList, nativeType: withModifier({ column, udt }) };\n }\n\n // Unknown type → unsupported column, raw type preserved (F3: keep, don't\n // drop). `format_type` keeps modifiers (`vector(3)`), so an extension-lowered\n // column round-trips diff-clean against its declared native type.\n const raw = column.fullType ?? udt;\n return {\n type: \"String\",\n isList: false,\n nativeType: isList && !raw.endsWith(\"[]\") ? `${raw}[]` : raw,\n isUnsupported: true,\n };\n}\n\n/**\n * For canonical base types, return a nativeType only when a modifier makes the\n * column diverge from the canonical mapping (timestamptz(3), numeric(10,2)).\n * Bare `timestamptz` is the canonical DateTime mapping and postgres reports\n * its default precision as 6, so precision 6 (or none) means \"no override\";\n * every other precision is carried truthfully — the differ's equivalence\n * class, not this function, decides that timestamptz(3) needs no ALTER.\n */\nfunction nonCanonicalModifier(params: {\n column: ColumnRow;\n udt: string;\n scalar: ScalarType;\n}): string | undefined {\n const { column, udt, scalar } = params;\n if (scalar === \"DateTime\" && udt === \"timestamptz\") {\n const precision = column.datetimePrecision;\n return precision === null || precision === 6 ? undefined : `timestamptz(${precision})`;\n }\n if (scalar === \"Decimal\" && udt === \"numeric\") {\n if (column.numericPrecision === null) return undefined;\n const scale = column.numericScale ?? 0;\n return `numeric(${column.numericPrecision},${scale})`;\n }\n return undefined;\n}\n\n/** Render `udt(modifier)` for non-canonical types that carry one. */\nfunction withModifier(params: { column: ColumnRow; udt: string }): string {\n const { column, udt } = params;\n if ((udt === \"varchar\" || udt === \"bpchar\") && column.charMaxLength !== null) {\n return `${udt === \"bpchar\" ? \"char\" : \"varchar\"}(${column.charMaxLength})`;\n }\n if (udt === \"bpchar\") return \"char\";\n if (udt === \"timestamp\" && column.datetimePrecision !== null && column.datetimePrecision !== 6) {\n return `timestamp(${column.datetimePrecision})`;\n }\n return udt;\n}\n\n// ─── Default parsing ──────────────────────────────────────────────\n\nfunction parseColumnDefault(params: {\n column: ColumnRow;\n mapped: MappedType;\n}): DefaultValueIR | undefined {\n const { column, mapped } = params;\n\n if (column.identity) return { kind: \"autoincrement\" };\n\n const raw = column.columnDefault;\n if (raw === null) return undefined;\n if (raw.startsWith(\"NULL::\")) return undefined;\n\n if (raw.includes(\"nextval(\")) return { kind: \"autoincrement\" };\n if (raw === \"now()\" || raw.startsWith(\"CURRENT_TIMESTAMP\")) return { kind: \"now\" };\n if (raw === \"true\" || raw === \"false\") return { kind: \"literal\", value: raw === \"true\" };\n if (/^-?\\d+(\\.\\d+)?$/.test(raw)) return { kind: \"literal\", value: Number(raw) };\n\n // 'value' or 'value'::type — embedded quotes arrive doubled.\n const quoted = raw.match(/^'((?:[^']|'')*)'(::.*)?$/);\n if (quoted !== null) {\n const value = (quoted[1] as string).replaceAll(\"''\", \"'\");\n if (typeof mapped.type === \"object\") return { kind: \"enumValue\", value };\n if (isNumericScalar({ type: mapped.type }) && /^-?\\d+(\\.\\d+)?$/.test(value)) {\n return { kind: \"literal\", value: Number(value) };\n }\n // A cast to a non-string type (e.g. '{}'::text[]) is not a plain literal.\n const cast = quoted[2];\n if (cast !== undefined && cast !== \"\" && mapped.isList) {\n return { kind: \"dbgenerated\", sql: raw };\n }\n return { kind: \"literal\", value };\n }\n\n return { kind: \"dbgenerated\", sql: raw };\n}\n\n// ─── Index parsing ────────────────────────────────────────────────\n\n/**\n * Parse a `pg_indexes.indexdef` line:\n * `CREATE [UNIQUE] INDEX name ON schema.table USING method (cols) [WHERE pred]`.\n * The column list is scanned with balanced parentheses (expressions like\n * `lower(email)` and `WHERE` predicates both contain parens, so a regex over\n * the whole line cannot split them). Returns null for definitions that don't\n * match — never expected from pg.\n */\nfunction parseIndexDef(params: {\n table: string;\n name: string;\n def: string;\n}): IntrospectedIndex | null {\n const { table, name, def } = params;\n const head = def.match(/^CREATE (UNIQUE )?INDEX .*? USING (\\w+) \\(/);\n if (head === null) return null;\n\n // Scan the balanced column list starting right after the opening paren.\n const start = (head.index ?? 0) + head[0].length;\n let depth = 1;\n let end = -1;\n for (let position = start; position < def.length; position += 1) {\n const char = def[position];\n if (char === \"(\") depth += 1;\n else if (char === \")\") {\n depth -= 1;\n if (depth === 0) {\n end = position;\n break;\n }\n }\n }\n if (end === -1) return null;\n\n const columns = splitTopLevel({ text: def.slice(start, end) }).map((entry) => {\n const trimmed = entry.trim();\n const desc = / DESC$/i.test(trimmed);\n const nameOnly = trimmed.replace(/ (DESC|ASC)( NULLS (FIRST|LAST))?$/i, \"\");\n return { name: nameOnly.replaceAll('\"', \"\"), desc };\n });\n\n let tail = def.slice(end + 1).trim();\n // pg 15+: `… (cols) NULLS NOT DISTINCT [WHERE …]` — the flag precedes WHERE.\n const nullsNotDistinct = /^NULLS NOT DISTINCT\\b/i.test(tail);\n if (nullsNotDistinct) tail = tail.slice(\"NULLS NOT DISTINCT\".length).trim();\n const whereMatch = tail.match(/^WHERE (.*)$/);\n const whereRaw = whereMatch?.[1];\n return {\n table,\n name,\n unique: head[1] !== undefined,\n kind: (head[2] as string).toLowerCase(),\n columns,\n ...(whereRaw === undefined ? {} : { where: whereRaw }),\n ...(nullsNotDistinct ? { nullsNotDistinct: true } : {}),\n };\n}\n\n/** Split a parenthesized column list on top-level commas only. */\nfunction splitTopLevel(params: { text: string }): string[] {\n const { text } = params;\n const parts: string[] = [];\n let depth = 0;\n let current = \"\";\n for (const char of text) {\n if (char === \"(\") depth += 1;\n if (char === \")\") depth -= 1;\n if (char === \",\" && depth === 0) {\n parts.push(current);\n current = \"\";\n continue;\n }\n current += char;\n }\n if (current.trim().length > 0) parts.push(current);\n return parts;\n}\n\nfunction toNumberOrNull(value: unknown): number | null {\n if (value === null || value === undefined) return null;\n const parsed = Number(value);\n return Number.isNaN(parsed) ? null : parsed;\n}\n",
|
|
23
|
+
"/**\n * SQLite introspection: live database → SchemaIR, from `sqlite_master` (table\n * and index SQL text) plus `PRAGMA table_info / index_list / index_xinfo /\n * foreign_key_list`.\n *\n * THE TEXT-TYPE AMBIGUITY, stated honestly: sqlite stores only the four\n * storage classes we emit, so the reverse mapping is TEXT→String,\n * INTEGER→Int, REAL→Float, BLOB→Bytes — ALWAYS. A DateTime/Decimal/Json\n * column pulls back as String and a Boolean/BigInt as Int; there is no marker\n * to recover the richer type. The differ compensates by comparing columns by\n * storage class on sqlite (normalize.ts), so round-trips stay diff-clean.\n * Two markers DO survive:\n * - enums: our named CHECK constraints (`<table>_<column>_enum_<Enum>`)\n * recover both the enum's name and values;\n * - autoincrement: the literal `PRIMARY KEY AUTOINCREMENT` text on a\n * single-column INTEGER PK.\n * Any other declared type (VARCHAR(30), DATETIME, … from a foreign database)\n * becomes an `isUnsupported` field with the raw type preserved in\n * `nativeType` (F3: keep, don't drop).\n *\n * Representation mirrors introspect/postgres.ts exactly (shared.ts is the one\n * relation/join-table rule): unnamed relation pairs, structural join-table\n * detection, single-column uniques folded into `isUnique`, composite PKs on\n * `model.primaryKey` (PK columns are never optional), views with columns\n * only. Skipped: the `_vibe_migrations` table, `sqlite_*` internals\n * (sqlite_sequence comes with AUTOINCREMENT), and expression indexes\n * (index_xinfo reports no column name for them).\n *\n * Every row-returning query passes `values: []` — through `toSqlExecutor` a\n * value-less text runs on the adapter's multi-statement batch path, which\n * returns no rows (adapter-sqlite contract).\n */\n\nimport type {\n CascadeAction,\n DefaultValueIR,\n EnumIR,\n FieldIR,\n FieldType,\n IndexIR,\n ModelIR,\n SchemaIR,\n} from \"@vibeorm/schema\";\nimport { sqliteDialect } from \"@vibeorm/sql\";\nimport { MIGRATIONS_TABLE_NAME } from \"../runner.ts\";\nimport { parseSqliteEnumChecks, parseSqliteNamedChecks, sqliteEnumCheckName } from \"../sqlite-types.ts\";\nimport {\n addFkRelations,\n addJoinTableRelations,\n detectJoinTable,\n} from \"./shared.ts\";\nimport type { FkGroup, IntrospectedIndex, JoinTableInfo } from \"./shared.ts\";\nimport type { SqlExecutor } from \"../types.ts\";\n\n// ─── Row shapes ───────────────────────────────────────────────────\n\ntype MasterRow = { name: string; type: string; sql: string | null };\n\ntype ColumnInfo = {\n name: string;\n declaredType: string;\n notNull: boolean;\n defaultValue: string | null;\n /** 1-based position within the PK, 0 = not part of it. */\n pkPosition: number;\n};\n\nconst SQLITE_ACTION_TO_CASCADE: Readonly<Record<string, CascadeAction>> = {\n \"NO ACTION\": \"NoAction\",\n RESTRICT: \"Restrict\",\n CASCADE: \"Cascade\",\n \"SET NULL\": \"SetNull\",\n \"SET DEFAULT\": \"SetDefault\",\n};\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/** Introspect a live sqlite database into SchemaIR. */\nexport async function introspectSqlite(params: { executor: SqlExecutor }): Promise<SchemaIR> {\n const { executor } = params;\n\n const masterRows = await executor({\n text: `SELECT name, type, sql FROM sqlite_master WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%' AND name <> '${MIGRATIONS_TABLE_NAME}' ORDER BY name`,\n values: [],\n });\n const indexSqlRows = await executor({\n text: `SELECT name, tbl_name, sql FROM sqlite_master WHERE type = 'index' ORDER BY name`,\n values: [],\n });\n\n const entries: MasterRow[] = masterRows.map((row) => ({\n name: row.name as string,\n type: row.type as string,\n sql: (row.sql as string | null) ?? null,\n }));\n const tables = entries.filter((entry) => entry.type === \"table\");\n const views = entries.filter((entry) => entry.type === \"view\");\n\n const indexSqlByName = new Map<string, string | null>();\n for (const row of indexSqlRows) {\n indexSqlByName.set(row.name as string, (row.sql as string | null) ?? null);\n }\n\n // Per-table catalog: columns, indexes, FKs, enum checks.\n const columnsByTable = new Map<string, ColumnInfo[]>();\n const indexes: IntrospectedIndex[] = [];\n const uniqueSinglesByTable = new Map<string, Set<string>>();\n const modelIndexesByTable = new Map<string, IndexIR[]>();\n const checksByTable = new Map<string, { name: string; expression: string }[]>();\n const fkGroups: FkGroup[] = [];\n const enumsByColumn = new Map<string, { enumName: string; values: readonly string[] }>();\n const enumRegistry = new Map<string, EnumIR>();\n const autoincrementTables = new Set<string>();\n\n for (const table of tables) {\n const columns = await readColumns({ executor, table: table.name });\n columnsByTable.set(table.name, columns);\n\n // Enum CHECK markers from the table's SQL text.\n const enumCheckNames = new Set<string>();\n for (const check of parseSqliteEnumChecks({ tableSql: table.sql ?? \"\" })) {\n enumsByColumn.set(`${table.name}.${check.column}`, {\n enumName: check.enumName,\n values: check.values,\n });\n enumCheckNames.add(\n sqliteEnumCheckName({ table: table.name, column: check.column, enumName: check.enumName }),\n );\n if (!enumRegistry.has(check.enumName)) {\n enumRegistry.set(check.enumName, { name: check.enumName, values: check.values });\n }\n }\n\n // User CHECK constraints — every named check that is NOT enum machinery.\n checksByTable.set(\n table.name,\n parseSqliteNamedChecks({ tableSql: table.sql ?? \"\" }).filter(\n (check) => !enumCheckNames.has(check.name),\n ),\n );\n\n // Autoincrement marker (single-column INTEGER PK only).\n if (/PRIMARY KEY AUTOINCREMENT/i.test(table.sql ?? \"\")) {\n autoincrementTables.add(table.name);\n }\n\n // Indexes.\n const { tableIndexes, uniqueSingles, modelIndexes } = await readIndexes({\n executor,\n table: table.name,\n indexSqlByName,\n });\n indexes.push(...tableIndexes);\n uniqueSinglesByTable.set(table.name, uniqueSingles);\n modelIndexesByTable.set(table.name, modelIndexes);\n\n // Foreign keys.\n fkGroups.push(...(await readForeignKeys({ executor, table: table.name, columns })));\n }\n\n // Implicit join tables (the shared structural rule).\n const joinTables = new Map<string, JoinTableInfo>();\n for (const table of tables) {\n const detected = detectJoinTable({\n table: table.name,\n columnNames: (columnsByTable.get(table.name) ?? []).map((column) => column.name),\n fkGroups,\n indexes,\n });\n if (detected !== null) joinTables.set(table.name, detected);\n }\n\n // Models.\n const models: ModelIR[] = [];\n for (const table of tables) {\n if (joinTables.has(table.name)) continue;\n models.push(\n buildModel({\n table: table.name,\n isView: false,\n columns: columnsByTable.get(table.name) ?? [],\n uniqueSingles: uniqueSinglesByTable.get(table.name) ?? new Set(),\n modelIndexes: modelIndexesByTable.get(table.name) ?? [],\n enumsByColumn,\n autoincrement: autoincrementTables.has(table.name),\n checks: checksByTable.get(table.name) ?? [],\n }),\n );\n }\n for (const view of views) {\n models.push(\n buildModel({\n table: view.name,\n isView: true,\n columns: await readColumns({ executor, table: view.name }),\n uniqueSingles: new Set(),\n modelIndexes: [],\n enumsByColumn,\n autoincrement: false,\n checks: [],\n }),\n );\n }\n\n addFkRelations({ models, fkGroups, joinTables });\n addJoinTableRelations({ models, joinTables });\n\n return {\n datasource: { provider: \"sqlite\" },\n models,\n enums: [...enumRegistry.values()],\n extensions: [],\n };\n}\n\n// ─── Catalog readers ──────────────────────────────────────────────\n\nasync function readColumns(params: {\n executor: SqlExecutor;\n table: string;\n}): Promise<ColumnInfo[]> {\n const rows = await params.executor({\n text: `PRAGMA table_info(${q(params.table)})`,\n values: [],\n });\n return rows.map((row) => ({\n name: row.name as string,\n declaredType: (row.type as string | null) ?? \"\",\n notNull: Number(row.notnull) === 1,\n defaultValue: row.dflt_value === null || row.dflt_value === undefined ? null : String(row.dflt_value),\n pkPosition: Number(row.pk),\n }));\n}\n\nasync function readIndexes(params: {\n executor: SqlExecutor;\n table: string;\n indexSqlByName: ReadonlyMap<string, string | null>;\n}): Promise<{\n tableIndexes: IntrospectedIndex[];\n uniqueSingles: Set<string>;\n modelIndexes: IndexIR[];\n}> {\n const { executor, table, indexSqlByName } = params;\n const listRows = await executor({ text: `PRAGMA index_list(${q(table)})`, values: [] });\n\n const tableIndexes: IntrospectedIndex[] = [];\n const uniqueSingles = new Set<string>();\n const modelIndexes: IndexIR[] = [];\n\n for (const listRow of listRows) {\n const origin = listRow.origin as string;\n if (origin === \"pk\") continue; // The PK itself — table_info carries it.\n\n const name = listRow.name as string;\n const unique = Number(listRow.unique) === 1;\n const partial = Number(listRow.partial) === 1;\n\n const infoRows = await executor({ text: `PRAGMA index_xinfo(${q(name)})`, values: [] });\n const keyRows = infoRows\n .filter((row) => Number(row.key) === 1)\n .sort((a, b) => Number(a.seqno) - Number(b.seqno));\n let columns: { name: string; desc: boolean }[];\n if (keyRows.some((row) => row.name === null || row.name === undefined)) {\n // Expression index. OUR OWN Decimal form — CAST(\"col\" AS REAL), emitted\n // by the sqlite DDL renderer (SQLITE-2) — is recovered from the index's\n // sqlite_master SQL so `diff(introspect(push(X)), X)` stays [] and push\n // stays idempotent. Any OTHER expression index is skipped (documented\n // non-support), exactly as before.\n const recovered = parseIndexColumnsFromSql({ sql: indexSqlByName.get(name) ?? null });\n if (recovered === null) continue;\n columns = recovered;\n } else {\n columns = keyRows.map((row) => ({\n name: row.name as string,\n desc: Number(row.desc) === 1,\n }));\n }\n\n let where: string | undefined;\n if (partial) {\n const sql = indexSqlByName.get(name);\n const match = sql?.match(/\\sWHERE\\s+(.*)$/is);\n where = match?.[1]?.trim();\n }\n\n tableIndexes.push({\n table,\n name,\n unique,\n kind: \"btree\",\n columns,\n ...(where === undefined ? {} : { where }),\n });\n\n if (unique && columns.length === 1 && where === undefined) {\n uniqueSingles.add((columns[0] as { name: string }).name);\n continue;\n }\n modelIndexes.push({\n name,\n kind: unique ? \"unique\" : \"btree\",\n fields: columns.map((column) => ({\n name: column.name,\n ...(column.desc ? { sort: \"desc\" as const } : {}),\n })),\n ...(where === undefined ? {} : { where }),\n });\n }\n\n return { tableIndexes, uniqueSingles, modelIndexes };\n}\n\n/** One parsed index-column term: `\"col\" [DESC]` or `CAST(\"col\" AS REAL) [DESC]`. */\nconst PLAIN_INDEX_COLUMN = /^\"((?:[^\"]|\"\")+)\"(?:\\s+(ASC|DESC))?$/i;\nconst CAST_REAL_INDEX_COLUMN = /^CAST\\s*\\(\\s*\"((?:[^\"]|\"\")+)\"\\s+AS\\s+REAL\\s*\\)(?:\\s+(ASC|DESC))?$/i;\n\n/**\n * Recover an expression index's column list from its `sqlite_master.sql`\n * (SQLITE-2). Only shapes WE emit parse — plain quoted columns and\n * `CAST(\"col\" AS REAL)`, each with an optional direction; a trailing partial\n * WHERE clause is fine (it sits OUTSIDE the column list — closure item 2).\n * Anything else (other expressions, COLLATE clauses) returns null and the\n * caller skips the index as before.\n */\nexport function parseIndexColumnsFromSql(params: {\n sql: string | null;\n}): { name: string; desc: boolean }[] | null {\n const { sql } = params;\n if (sql === null) return null;\n // Locate the column list's OPENING paren after `ON \"table\"` and walk to its\n // matching close with a depth tracker — a greedy regex capture would swallow\n // through a PARTIAL index's WHERE clause (closure item 2: our own emitted\n // partial Decimal expression index then failed to parse, was skipped as\n // foreign, and every push re-created it).\n const onMatch = /\\sON\\s+\"(?:[^\"]|\"\")+\"\\s*\\(/i.exec(sql);\n if (onMatch === null) return null;\n const open = onMatch.index + onMatch[0].length - 1;\n let listDepth = 0;\n let close = -1;\n for (let index = open; index < sql.length; index++) {\n const char = sql[index];\n if (char === \"(\") listDepth += 1;\n else if (char === \")\") {\n listDepth -= 1;\n if (listDepth === 0) {\n close = index;\n break;\n }\n }\n }\n if (close === -1) return null;\n const list = sql.slice(open + 1, close);\n\n // Split on top-level commas — CAST(…) carries its own parens.\n const terms: string[] = [];\n let depth = 0;\n let start = 0;\n for (let index = 0; index < list.length; index++) {\n const char = list[index];\n if (char === \"(\") depth += 1;\n else if (char === \")\") depth -= 1;\n else if (char === \",\" && depth === 0) {\n terms.push(list.slice(start, index));\n start = index + 1;\n }\n }\n terms.push(list.slice(start));\n\n const columns: { name: string; desc: boolean }[] = [];\n for (const term of terms) {\n const trimmed = term.trim();\n const match = PLAIN_INDEX_COLUMN.exec(trimmed) ?? CAST_REAL_INDEX_COLUMN.exec(trimmed);\n if (match === null) return null;\n columns.push({\n name: (match[1] as string).replaceAll('\"\"', '\"'),\n desc: (match[2] ?? \"\").toUpperCase() === \"DESC\",\n });\n }\n return columns;\n}\n\nasync function readForeignKeys(params: {\n executor: SqlExecutor;\n table: string;\n columns: readonly ColumnInfo[];\n}): Promise<FkGroup[]> {\n const { executor, table, columns } = params;\n const rows = await executor({ text: `PRAGMA foreign_key_list(${q(table)})`, values: [] });\n\n type MutableGroup = {\n columns: string[];\n refTable: string;\n refColumns: string[];\n onDelete: CascadeAction;\n onUpdate: CascadeAction;\n };\n const groups = new Map<number, MutableGroup>();\n const ordered = [...rows].sort(\n (a, b) => Number(a.id) - Number(b.id) || Number(a.seq) - Number(b.seq),\n );\n for (const row of ordered) {\n const id = Number(row.id);\n const from = row.from as string;\n // `to` is null when the FK references the parent's implicit PK — we never\n // emit that form, but resolve it defensively to the parent's rowid alias.\n const to = (row.to as string | null) ?? \"rowid\";\n const existing = groups.get(id);\n if (existing === undefined) {\n groups.set(id, {\n columns: [from],\n refTable: row.table as string,\n refColumns: [to],\n onDelete: SQLITE_ACTION_TO_CASCADE[(row.on_delete as string) ?? \"NO ACTION\"] ?? \"NoAction\",\n onUpdate: SQLITE_ACTION_TO_CASCADE[(row.on_update as string) ?? \"NO ACTION\"] ?? \"NoAction\",\n });\n } else {\n existing.columns.push(from);\n existing.refColumns.push(to);\n }\n }\n\n return [...groups.values()].map((group) => ({\n // sqlite does not surface FK constraint names — recompute the convention\n // the differ's normalization uses, so keys line up.\n constraintName: `${table}_${group.columns.join(\"_\")}_fkey`,\n table,\n columns: group.columns,\n refTable: group.refTable,\n refColumns: group.refColumns,\n onDelete: group.onDelete,\n onUpdate: group.onUpdate,\n required: group.columns.every((columnName) => {\n const column = columns.find((candidate) => candidate.name === columnName);\n return column === undefined ? true : column.notNull;\n }),\n }));\n}\n\n// ─── Model building ───────────────────────────────────────────────\n\nfunction buildModel(params: {\n table: string;\n isView: boolean;\n columns: readonly ColumnInfo[];\n uniqueSingles: ReadonlySet<string>;\n modelIndexes: readonly IndexIR[];\n enumsByColumn: ReadonlyMap<string, { enumName: string; values: readonly string[] }>;\n autoincrement: boolean;\n checks: readonly { readonly name: string; readonly expression: string }[];\n}): ModelIR {\n const { table, isView, columns, uniqueSingles, modelIndexes, enumsByColumn, autoincrement } =\n params;\n\n const pk = columns\n .filter((column) => column.pkPosition > 0)\n .sort((a, b) => a.pkPosition - b.pkPosition)\n .map((column) => column.name);\n\n const fields: FieldIR[] = columns.map((column) => {\n const enumRef = enumsByColumn.get(`${table}.${column.name}`);\n const mapped = reverseMapType({ column, enumRef });\n const isId = pk.length === 1 && pk[0] === column.name;\n const isAutoincrement =\n autoincrement && isId && column.declaredType.toUpperCase() === \"INTEGER\";\n const defaultValue: DefaultValueIR | undefined = isAutoincrement\n ? { kind: \"autoincrement\" }\n : parseColumnDefault({ column, mapped });\n\n return {\n name: column.name,\n type: mapped.type,\n isList: false,\n // PK columns are never optional: sqlite's table_info reports notnull=0\n // for `INTEGER PRIMARY KEY` rowid aliases, but the column cannot\n // actually hold NULL (postgres-parity rule).\n isOptional: column.pkPosition > 0 ? false : !column.notNull,\n isId,\n isUnique: uniqueSingles.has(column.name),\n isUpdatedAt: false,\n ...(defaultValue === undefined ? {} : { default: defaultValue }),\n ...(mapped.nativeType === undefined ? {} : { nativeType: mapped.nativeType }),\n ...(mapped.isUnsupported === true ? { isUnsupported: true as const } : {}),\n };\n });\n\n return {\n name: table,\n fields,\n relations: [],\n indexes: [...modelIndexes],\n ...(params.checks.length === 0 ? {} : { checks: params.checks }),\n isView,\n ...(pk.length > 1 ? { primaryKey: { fields: pk } } : {}),\n };\n}\n\n// ─── Reverse type mapping (the TEXT-ambiguity rule) ───────────────\n\ntype MappedType = {\n type: FieldType;\n nativeType?: string;\n isUnsupported?: true;\n};\n\nfunction reverseMapType(params: {\n column: ColumnInfo;\n enumRef: { enumName: string; values: readonly string[] } | undefined;\n}): MappedType {\n const { column, enumRef } = params;\n const declared = column.declaredType.trim().toUpperCase();\n\n if (enumRef !== undefined && declared === \"TEXT\") {\n return { type: { enum: enumRef.enumName } };\n }\n switch (declared) {\n case \"TEXT\":\n return { type: \"String\" };\n case \"INTEGER\":\n return { type: \"Int\" };\n case \"REAL\":\n return { type: \"Float\" };\n case \"BLOB\":\n return { type: \"Bytes\" };\n default:\n // Foreign declared type (VARCHAR(30), DATETIME, …) — preserved, not\n // guessed at (F3: keep, don't drop).\n return { type: \"String\", nativeType: column.declaredType, isUnsupported: true };\n }\n}\n\n// ─── Default parsing ──────────────────────────────────────────────\n\nfunction parseColumnDefault(params: {\n column: ColumnInfo;\n mapped: MappedType;\n}): DefaultValueIR | undefined {\n const { column, mapped } = params;\n const raw = column.defaultValue;\n if (raw === null) return undefined;\n\n if (raw === \"CURRENT_TIMESTAMP\") return { kind: \"now\" };\n if (/^-?\\d+(\\.\\d+)?$/.test(raw)) return { kind: \"literal\", value: Number(raw) };\n\n const quoted = raw.match(/^'((?:[^']|'')*)'$/);\n if (quoted !== null) {\n const value = (quoted[1] as string).replaceAll(\"''\", \"'\");\n if (typeof mapped.type === \"object\") return { kind: \"enumValue\", value };\n if ((mapped.type === \"Int\" || mapped.type === \"Float\") && /^-?\\d+(\\.\\d+)?$/.test(value)) {\n return { kind: \"literal\", value: Number(value) };\n }\n return { kind: \"literal\", value };\n }\n\n return { kind: \"dbgenerated\", sql: raw };\n}\n\n// ─── Quoting ──────────────────────────────────────────────────────\n\nfunction q(name: string): string {\n return sqliteDialect.quoteIdent({ name });\n}\n",
|
|
24
|
+
"/**\n * MySQL introspection: live database → SchemaIR, from\n * `information_schema.{tables,views,columns,statistics,key_column_usage,\n * referential_constraints}` (scoped to `DATABASE()`).\n *\n * Representation mirrors introspect/postgres.ts exactly (shared.ts carries\n * the one relation/join-table rule). MySQL-specific decisions:\n *\n * - `COLUMN_TYPE` is the reverse-mapping source: `tinyint(1)` → Boolean (the\n * marker), `varchar(191)` → String, `enum('A','B')` → an enum whose values\n * are parsed from the type and whose NAME is synthesized as\n * `<Table>_<column>` — mysql enums are nameless, so the schema-declared\n * name is unrecoverable. The differ compares enum columns by VALUE LIST\n * (normalize.ts), so the synthetic names never produce phantom steps.\n * - `EXTRA = auto_increment` → `@default(autoincrement())`;\n * `DEFAULT_GENERATED` expressions → `dbgenerated` (CURRENT_TIMESTAMP(…) →\n * `now` first).\n * - Non-canonical column types keep `COLUMN_TYPE` in `nativeType`; unknown\n * types become `isUnsupported` fields (F3: keep, don't drop).\n * - Indexes named like an FK constraint on the same table are SKIPPED: mysql\n * auto-creates them for FKs without a covering index, and surfacing them\n * would churn round-trips with phantom index steps.\n * - The `_vibe_migrations` bookkeeping table is skipped.\n */\n\nimport type {\n CascadeAction,\n CheckIR,\n DefaultValueIR,\n EnumIR,\n FieldIR,\n FieldType,\n IndexIR,\n ModelIR,\n ScalarType,\n SchemaIR,\n} from \"@vibeorm/schema\";\nimport { normalizeMysqlType, parseMysqlEnumColumnType } from \"../mysql-types.ts\";\nimport { MIGRATIONS_TABLE_NAME } from \"../runner.ts\";\nimport {\n addFkRelations,\n addJoinTableRelations,\n detectJoinTable,\n} from \"./shared.ts\";\nimport type { FkGroup, IntrospectedIndex, JoinTableInfo } from \"./shared.ts\";\nimport type { SqlExecutor } from \"../types.ts\";\n\n// ─── Catalog queries ──────────────────────────────────────────────\n\nconst TABLES_QUERY = `\n SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = DATABASE()\n AND table_type = 'BASE TABLE'\n AND table_name <> '${MIGRATIONS_TABLE_NAME}'\n ORDER BY table_name;\n`;\n\nconst VIEWS_QUERY = `\n SELECT table_name\n FROM information_schema.views\n WHERE table_schema = DATABASE()\n ORDER BY table_name;\n`;\n\nconst COLUMNS_QUERY = `\n SELECT\n table_name,\n column_name,\n column_type,\n is_nullable,\n column_default,\n extra,\n ordinal_position\n FROM information_schema.columns\n WHERE table_schema = DATABASE()\n ORDER BY table_name, ordinal_position;\n`;\n\nconst STATISTICS_QUERY = `\n SELECT\n table_name,\n index_name,\n non_unique,\n seq_in_index,\n column_name,\n collation\n FROM information_schema.statistics\n WHERE table_schema = DATABASE()\n ORDER BY table_name, index_name, seq_in_index;\n`;\n\nconst FOREIGN_KEYS_QUERY = `\n SELECT\n constraint_name,\n table_name,\n column_name,\n ordinal_position,\n referenced_table_name,\n referenced_column_name\n FROM information_schema.key_column_usage\n WHERE table_schema = DATABASE()\n AND referenced_table_name IS NOT NULL\n ORDER BY table_name, constraint_name, ordinal_position;\n`;\n\nconst REFERENTIAL_QUERY = `\n SELECT constraint_name, update_rule, delete_rule\n FROM information_schema.referential_constraints\n WHERE constraint_schema = DATABASE();\n`;\n\n/** Explicit CHECK constraints (MySQL 8.0.16+ stores and enforces them). */\nconst CHECKS_QUERY = `\n SELECT\n tc.table_name AS table_name,\n tc.constraint_name AS constraint_name,\n cc.check_clause AS definition\n FROM information_schema.table_constraints tc\n JOIN information_schema.check_constraints cc\n ON cc.constraint_schema = tc.constraint_schema\n AND cc.constraint_name = tc.constraint_name\n WHERE tc.table_schema = DATABASE()\n AND tc.constraint_type = 'CHECK'\n ORDER BY tc.table_name, tc.constraint_name;\n`;\n\n// ─── Row shapes ───────────────────────────────────────────────────\n\ntype ColumnRow = {\n table: string;\n name: string;\n columnType: string;\n nullable: boolean;\n columnDefault: string | null;\n extra: string;\n};\n\nconst MYSQL_RULE_TO_CASCADE: Readonly<Record<string, CascadeAction>> = {\n \"NO ACTION\": \"NoAction\",\n RESTRICT: \"Restrict\",\n CASCADE: \"Cascade\",\n \"SET NULL\": \"SetNull\",\n \"SET DEFAULT\": \"SetDefault\",\n};\n\n// ─── Catalog row reading ─────────────────────────────────\n\n/**\n * Read one column from an information_schema row by its lowercase name,\n * falling back to the UPPERCASE label.\n *\n * MySQL labels information_schema result columns from the data dictionary and\n * the casing has flipped across server lines — verified live on MySQL 8.4,\n * where `SELECT table_name FROM information_schema.tables` comes back labeled\n * `TABLE_NAME`, so every lowercase-only read returned `undefined` and\n * introspecting a NON-EMPTY database crashed (an empty catalog produced no\n * rows, which is why push against a fresh database masked the bug).\n */\nfunction catalogField(params: { row: Record<string, unknown>; name: string }): unknown {\n const value = params.row[params.name];\n return value !== undefined ? value : params.row[params.name.toUpperCase()];\n}\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/** Introspect a live mysql database (current schema) into SchemaIR. */\nexport async function introspectMysql(params: { executor: SqlExecutor }): Promise<SchemaIR> {\n const { executor } = params;\n\n const [tableRows, viewRows, columnRows, statisticRows, fkRows, refRows, checkRows] =\n await Promise.all([\n executor({ text: TABLES_QUERY }),\n executor({ text: VIEWS_QUERY }),\n executor({ text: COLUMNS_QUERY }),\n executor({ text: STATISTICS_QUERY }),\n executor({ text: FOREIGN_KEYS_QUERY }),\n executor({ text: REFERENTIAL_QUERY }),\n executor({ text: CHECKS_QUERY }),\n ]);\n\n // CHECK constraints per table. The stored clause arrives wrapped in one\n // outer paren pair — stripped when balanced; expression text is pull-print\n // material only (the differ keys on NAME).\n const checksByTable = new Map<string, CheckIR[]>();\n for (const row of checkRows) {\n const table = catalogField({ row, name: \"table_name\" }) as string;\n const name = catalogField({ row, name: \"constraint_name\" }) as string;\n const expression = stripBalancedOuterParens(\n String(catalogField({ row, name: \"definition\" }) ?? \"\"),\n );\n const list = checksByTable.get(table);\n if (list === undefined) checksByTable.set(table, [{ name, expression }]);\n else list.push({ name, expression });\n }\n\n const tables = tableRows.map((row) => catalogField({ row, name: \"table_name\" }) as string);\n const views = viewRows.map((row) => catalogField({ row, name: \"table_name\" }) as string);\n\n const columns: ColumnRow[] = columnRows.map((row) => ({\n table: catalogField({ row, name: \"table_name\" }) as string,\n name: catalogField({ row, name: \"column_name\" }) as string,\n columnType: catalogField({ row, name: \"column_type\" }) as string,\n nullable: (catalogField({ row, name: \"is_nullable\" }) as string) === \"YES\",\n columnDefault: (catalogField({ row, name: \"column_default\" }) as string | null) ?? null,\n extra: ((catalogField({ row, name: \"extra\" }) as string | null) ?? \"\").toLowerCase(),\n }));\n\n // Referential rules by constraint name.\n const rulesByConstraint = new Map<string, { onDelete: CascadeAction; onUpdate: CascadeAction }>();\n for (const row of refRows) {\n rulesByConstraint.set(catalogField({ row, name: \"constraint_name\" }) as string, {\n onDelete:\n MYSQL_RULE_TO_CASCADE[\n ((catalogField({ row, name: \"delete_rule\" }) as string) ?? \"NO ACTION\").toUpperCase()\n ] ?? \"NoAction\",\n onUpdate:\n MYSQL_RULE_TO_CASCADE[\n ((catalogField({ row, name: \"update_rule\" }) as string) ?? \"NO ACTION\").toUpperCase()\n ] ?? \"NoAction\",\n });\n }\n\n // FK groups (composite support; ordinal_position preserves column order).\n type MutableGroup = {\n constraintName: string;\n table: string;\n columns: string[];\n refTable: string;\n refColumns: string[];\n };\n const groupsByKey = new Map<string, MutableGroup>();\n for (const row of fkRows) {\n const constraintName = catalogField({ row, name: \"constraint_name\" }) as string;\n const table = catalogField({ row, name: \"table_name\" }) as string;\n const key = `${table}\\u0000${constraintName}`;\n const existing = groupsByKey.get(key);\n if (existing === undefined) {\n groupsByKey.set(key, {\n constraintName,\n table,\n columns: [catalogField({ row, name: \"column_name\" }) as string],\n refTable: catalogField({ row, name: \"referenced_table_name\" }) as string,\n refColumns: [catalogField({ row, name: \"referenced_column_name\" }) as string],\n });\n } else {\n existing.columns.push(catalogField({ row, name: \"column_name\" }) as string);\n existing.refColumns.push(catalogField({ row, name: \"referenced_column_name\" }) as string);\n }\n }\n const fkGroups: FkGroup[] = [...groupsByKey.values()].map((group) => {\n const rules = rulesByConstraint.get(group.constraintName);\n return {\n ...group,\n onDelete: rules?.onDelete ?? \"NoAction\",\n onUpdate: rules?.onUpdate ?? \"NoAction\",\n required: group.columns.every((columnName) => {\n const column = columns.find(\n (candidate) => candidate.table === group.table && candidate.name === columnName,\n );\n return column === undefined ? true : !column.nullable;\n }),\n };\n });\n const fkNamesByTable = new Map<string, Set<string>>();\n for (const group of fkGroups) {\n const set = fkNamesByTable.get(group.table) ?? new Set<string>();\n set.add(group.constraintName);\n fkNamesByTable.set(group.table, set);\n }\n\n // Indexes + PKs from statistics.\n const pkByTable = new Map<string, string[]>();\n const indexes: IntrospectedIndex[] = [];\n {\n type MutableIndex = {\n table: string;\n name: string;\n unique: boolean;\n columns: { name: string; desc: boolean }[];\n };\n const byKey = new Map<string, MutableIndex>();\n for (const row of statisticRows) {\n const table = catalogField({ row, name: \"table_name\" }) as string;\n const name = catalogField({ row, name: \"index_name\" }) as string;\n const columnName = catalogField({ row, name: \"column_name\" }) as string;\n if (name === \"PRIMARY\") {\n const list = pkByTable.get(table);\n if (list === undefined) pkByTable.set(table, [columnName]);\n else list.push(columnName);\n continue;\n }\n // mysql auto-creates an index per FK lacking one, named after the\n // constraint — skip those to keep round-trips churn-free.\n if (fkNamesByTable.get(table)?.has(name) === true) continue;\n\n const key = `${table}\\u0000${name}`;\n const entry = byKey.get(key);\n const column = {\n name: columnName,\n desc: (catalogField({ row, name: \"collation\" }) as string | null) === \"D\",\n };\n if (entry === undefined) {\n byKey.set(key, {\n table,\n name,\n unique: Number(catalogField({ row, name: \"non_unique\" })) === 0,\n columns: [column],\n });\n } else {\n entry.columns.push(column);\n }\n }\n for (const entry of byKey.values()) {\n indexes.push({ ...entry, kind: \"btree\" });\n }\n }\n\n // Enum columns: values parsed from COLUMN_TYPE, names synthesized.\n const enums: EnumIR[] = [];\n\n // Implicit join tables (the shared structural rule).\n const joinTables = new Map<string, JoinTableInfo>();\n for (const table of tables) {\n const detected = detectJoinTable({\n table,\n columnNames: columns.filter((column) => column.table === table).map((column) => column.name),\n fkGroups,\n indexes,\n });\n if (detected !== null) joinTables.set(table, detected);\n }\n\n // Models.\n const models: ModelIR[] = [];\n for (const table of tables) {\n if (joinTables.has(table)) continue;\n models.push(\n buildModel({\n table,\n isView: false,\n columns,\n pkByTable,\n indexes,\n enums,\n checks: checksByTable.get(table) ?? [],\n }),\n );\n }\n for (const view of views) {\n models.push(\n buildModel({\n table: view,\n isView: true,\n columns,\n pkByTable: new Map(),\n indexes: [],\n enums,\n checks: [],\n }),\n );\n }\n\n addFkRelations({ models, fkGroups, joinTables });\n addJoinTableRelations({ models, joinTables });\n\n return {\n datasource: { provider: \"mysql\" },\n models,\n enums,\n extensions: [],\n };\n}\n\n// ─── Model building ───────────────────────────────────────────────\n\nfunction buildModel(params: {\n table: string;\n isView: boolean;\n columns: readonly ColumnRow[];\n pkByTable: ReadonlyMap<string, string[]>;\n indexes: readonly IntrospectedIndex[];\n enums: EnumIR[];\n checks: readonly CheckIR[];\n}): ModelIR {\n const { table, isView, columns, pkByTable, indexes, enums } = params;\n\n const tableColumns = columns.filter((column) => column.table === table);\n const pk = pkByTable.get(table) ?? [];\n\n const tableIndexes = indexes.filter((index) => index.table === table);\n const uniqueSingles = new Set<string>();\n for (const index of tableIndexes) {\n if (index.unique && index.columns.length === 1) {\n uniqueSingles.add((index.columns[0] as { name: string }).name);\n }\n }\n\n const fields: FieldIR[] = tableColumns.map((column) => {\n const mapped = reverseMapType({ table, column, enums });\n const isId = pk.length === 1 && pk[0] === column.name;\n const defaultValue = parseColumnDefault({ column, mapped });\n return {\n name: column.name,\n type: mapped.type,\n isList: false,\n isOptional: column.nullable,\n isId,\n isUnique: uniqueSingles.has(column.name),\n isUpdatedAt: false,\n ...(defaultValue === undefined ? {} : { default: defaultValue }),\n ...(mapped.nativeType === undefined ? {} : { nativeType: mapped.nativeType }),\n ...(mapped.isUnsupported === true ? { isUnsupported: true as const } : {}),\n };\n });\n\n const modelIndexes: IndexIR[] = [];\n for (const index of tableIndexes) {\n if (index.unique && index.columns.length === 1) continue;\n modelIndexes.push({\n name: index.name,\n kind: index.unique ? \"unique\" : \"btree\",\n fields: index.columns.map((column) => ({\n name: column.name,\n ...(column.desc ? { sort: \"desc\" as const } : {}),\n })),\n });\n }\n\n return {\n name: table,\n fields,\n relations: [],\n indexes: modelIndexes,\n ...(params.checks.length === 0 ? {} : { checks: params.checks }),\n isView,\n ...(pk.length > 1 ? { primaryKey: { fields: pk } } : {}),\n };\n}\n\n/** Strip ONE balanced outer paren pair (`(a > 0)` → `a > 0`; `(a) AND (b)` stays). */\nfunction stripBalancedOuterParens(text: string): string {\n const trimmed = text.trim();\n if (!trimmed.startsWith(\"(\") || !trimmed.endsWith(\")\")) return trimmed;\n let depth = 0;\n for (let index = 0; index < trimmed.length; index++) {\n const char = trimmed[index];\n if (char === \"(\") depth += 1;\n else if (char === \")\") {\n depth -= 1;\n if (depth === 0 && index < trimmed.length - 1) return trimmed;\n }\n }\n return trimmed.slice(1, -1).trim();\n}\n\n// ─── Reverse type mapping (dialect-matrix §2, reversed) ───────────\n\ntype MappedType = {\n type: FieldType;\n nativeType?: string;\n isUnsupported?: true;\n};\n\n/** Normalized COLUMN_TYPE → scalar for types that ARE the canonical mapping. */\nconst CANONICAL_MYSQL: Readonly<Record<string, ScalarType>> = {\n \"varchar(191)\": \"String\",\n \"tinyint(1)\": \"Boolean\",\n int: \"Int\",\n bigint: \"BigInt\",\n double: \"Float\",\n \"decimal(65,30)\": \"Decimal\",\n \"datetime(3)\": \"DateTime\",\n json: \"Json\",\n longblob: \"Bytes\",\n};\n\n/** Base type → scalar for non-canonical spellings (nativeType keeps the truth). */\nconst BASE_TO_SCALAR: Readonly<Record<string, ScalarType>> = {\n varchar: \"String\",\n char: \"String\",\n text: \"String\",\n tinytext: \"String\",\n mediumtext: \"String\",\n longtext: \"String\",\n tinyint: \"Int\",\n smallint: \"Int\",\n mediumint: \"Int\",\n int: \"Int\",\n bigint: \"BigInt\",\n double: \"Float\",\n float: \"Float\",\n real: \"Float\",\n decimal: \"Decimal\",\n datetime: \"DateTime\",\n timestamp: \"DateTime\",\n date: \"DateTime\",\n json: \"Json\",\n blob: \"Bytes\",\n tinyblob: \"Bytes\",\n mediumblob: \"Bytes\",\n longblob: \"Bytes\",\n binary: \"Bytes\",\n varbinary: \"Bytes\",\n};\n\nfunction reverseMapType(params: {\n table: string;\n column: ColumnRow;\n enums: EnumIR[];\n}): MappedType {\n const { table, column, enums } = params;\n\n const enumValues = parseMysqlEnumColumnType({ columnType: column.columnType });\n if (enumValues !== null) {\n // mysql enums are nameless — synthesize `<Table>_<column>` and register.\n const name = `${table}_${column.name}`;\n if (!enums.some((entry) => entry.name === name)) {\n enums.push({ name, values: enumValues });\n }\n return { type: { enum: name } };\n }\n\n const normalized = normalizeMysqlType({ raw: column.columnType });\n const canonical = CANONICAL_MYSQL[normalized];\n if (canonical !== undefined) return { type: canonical };\n\n const base = normalized.match(/^([a-z_0-9]+)/)?.[1] ?? normalized;\n const scalar = BASE_TO_SCALAR[base];\n if (scalar !== undefined) {\n return { type: scalar, nativeType: column.columnType };\n }\n\n return { type: \"String\", nativeType: column.columnType, isUnsupported: true };\n}\n\n// ─── Default parsing ──────────────────────────────────────────────\n\nfunction parseColumnDefault(params: {\n column: ColumnRow;\n mapped: MappedType;\n}): DefaultValueIR | undefined {\n const { column, mapped } = params;\n\n if (column.extra.includes(\"auto_increment\")) return { kind: \"autoincrement\" };\n\n const raw = column.columnDefault;\n if (raw === null) return undefined;\n\n if (/^current_timestamp(\\(\\d+\\))?$/i.test(raw)) return { kind: \"now\" };\n if (column.extra.includes(\"default_generated\")) return { kind: \"dbgenerated\", sql: raw };\n\n if (typeof mapped.type === \"object\") return { kind: \"enumValue\", value: raw };\n if (mapped.type === \"Boolean\") {\n if (raw === \"1\" || raw === \"0\") return { kind: \"literal\", value: raw === \"1\" };\n return { kind: \"dbgenerated\", sql: raw };\n }\n if (isNumericScalar({ type: mapped.type }) && /^-?\\d+(\\.\\d+)?$/.test(raw)) {\n return { kind: \"literal\", value: Number(raw) };\n }\n return { kind: \"literal\", value: raw };\n}\n\nfunction isNumericScalar(params: { type: ScalarType }): boolean {\n const { type } = params;\n return type === \"Int\" || type === \"BigInt\" || type === \"Float\" || type === \"Decimal\";\n}\n",
|
|
25
25
|
"/**\n * Down-migration generation: the REVERSE diff of an up migration, with v1's\n * two rollback rules baked in (LEARNINGS / issue #15):\n *\n * 1. RE-ADDED COLUMNS COME BACK NULLABLE. The reverse of `dropColumn` is\n * `addColumn`, but the dropped column's data is gone — re-adding it\n * NOT NULL would fail on any populated table. Every `addColumn` step in a\n * down migration is therefore forced optional (its default, when present,\n * is kept). Whole-table re-creates (`createTable`) keep their NOT NULLs:\n * the re-created table is empty.\n * 2. IRREVERSIBLE UP-STEPS ARE SKIPPED, NOT THROWN. An up migration that\n * added an enum value has no reverse — postgres cannot drop enum values,\n * and sqlite/mysql refuse narrowing an inline enum whose rows may hold the\n * value. The rollback target keeps those values and the skip is reported\n * in `skipped`, so \"undo the last migration\" still works (v1's\n * `isReversible: false` behavior).\n *\n * Extension artifacts: object artifacts the up migration created (columns,\n * indexes, shadow tables, triggers) are dropped by the down migration via\n * their own `drop` SQL. `CREATE EXTENSION`-class artifacts are never dropped\n * — other database objects may depend on the extension — and are reported in\n * `skipped` instead.\n */\n\nimport type { Dialect, EnumIR, SchemaIR, VibeExtension } from \"@vibeorm/schema\";\nimport { diffSchemas } from \"./differ.ts\";\nimport { renderSteps } from \"./ddl/render.ts\";\nimport {\n collectExtensionArtifacts,\n planMissingArtifacts,\n stripExtensionArtifacts,\n} from \"./extensions.ts\";\nimport type { MigrationStep } from \"./types.ts\";\n\n// ─── Result shape ─────────────────────────────────────────────────\n\n/** A generated down migration: reverse SQL plus what could NOT be reversed. */\nexport type DownMigrationFile = {\n readonly name: string;\n /** One SQL string per statement, in execution order. */\n readonly sql: readonly string[];\n /** True when any reverse step can lose data (e.g. dropping an up-added column). */\n readonly destructive: boolean;\n /**\n * Human descriptions of up-changes this down migration cannot reverse\n * (added enum values, installed postgres extensions). Empty = full reverse.\n */\n readonly skipped: readonly string[];\n};\n\n// ─── Rollback target construction ─────────────────────────────────\n\n/**\n * Build the schema the down migration returns the database to. It is `from`\n * (the pre-migration shape) EXCEPT that enum values the up migration added\n * are retained — no dialect can remove an enum value a row may already hold —\n * with one `skipped` entry per retained value.\n */\nfunction buildRollbackTarget(params: {\n from: SchemaIR;\n to: SchemaIR;\n dialect: Dialect;\n}): { target: SchemaIR; skipped: string[] } {\n const { from, to, dialect } = params;\n const skipped: string[] = [];\n\n const toEnumsByKey = new Map<string, EnumIR>();\n for (const enumDef of to.enums) {\n toEnumsByKey.set(enumDef.dbName ?? enumDef.name, enumDef);\n }\n\n let patched = false;\n const enums: EnumIR[] = from.enums.map((enumDef) => {\n const key = enumDef.dbName ?? enumDef.name;\n const after = toEnumsByKey.get(key);\n if (after === undefined) return enumDef; // Enum dropped by up — reverse re-creates it.\n\n const before = new Set(enumDef.values);\n const added = after.values.filter((value) => !before.has(value));\n if (added.length === 0) return enumDef;\n\n for (const value of added) {\n skipped.push(\n `enum \"${key}\": value \"${value}\" added by the up migration is kept — ${dialect} cannot drop enum values`,\n );\n }\n patched = true;\n return { ...enumDef, values: [...enumDef.values, ...added] };\n });\n\n return { target: patched ? { ...from, enums } : from, skipped };\n}\n\n/** Rule 1: every re-added column comes back nullable (see module doc). */\nfunction forceReAddedColumnsNullable(params: {\n steps: readonly MigrationStep[];\n}): MigrationStep[] {\n return params.steps.map((step) => {\n if (step.kind !== \"addColumn\" || step.column.isOptional) return step;\n return { ...step, column: { ...step.column, isOptional: true } };\n });\n}\n\n// ─── Public API ───────────────────────────────────────────────────\n\n/**\n * Generate the DOWN migration for an up migration described by the same\n * `from`/`to` pair handed to `generateMigration`: `from` is the current\n * database shape, `to` the schema the up migration moves to. The down\n * migration transforms `to` back into `from` (modulo the skipped\n * irreversibles), so callers write it alongside the up file and apply it\n * newest-first to roll back.\n */\nexport function generateDownMigration(params: {\n from: SchemaIR;\n to: SchemaIR;\n name: string;\n /** Rendering dialect; postgres if omitted. */\n dialect?: Dialect;\n /** Configured extension instances — their up-created artifacts are dropped. */\n extensions?: readonly VibeExtension[];\n}): DownMigrationFile {\n const { from, to, name } = params;\n const dialect = params.dialect ?? \"postgres\";\n\n const artifacts = collectExtensionArtifacts({\n schema: to,\n dialect,\n extensions: params.extensions ?? [],\n });\n const allArtifacts = [...artifacts.setup, ...artifacts.objects];\n const strippedFrom = stripExtensionArtifacts({ schema: from, artifacts: allArtifacts });\n\n const { target, skipped } = buildRollbackTarget({ from: strippedFrom, to, dialect });\n\n // Rule 2 for views (#26): an up migration that DROPPED a view has no\n // reverse — the IR does not store view definitions (views are created\n // out-of-band in this wave), so the down migration cannot re-create it.\n const toViewNames = new Set(\n to.models.filter((model) => model.isView).map((model) => model.dbName ?? model.name),\n );\n for (const model of target.models) {\n if (!model.isView) continue;\n const name = model.dbName ?? model.name;\n if (!toViewNames.has(name)) {\n skipped.push(\n `view \"${name}\" dropped by the up migration is not re-created — its definition is not stored in the schema; re-create it manually`,\n );\n }\n }\n\n const steps = forceReAddedColumnsNullable({\n steps: diffSchemas({ from: to, to: target, dialect }),\n });\n const coreSql = renderSteps({ steps, dialect, from: to, to: target });\n\n // Drop the artifacts the up migration created (mirrors generateMigration's\n // planning), object artifacts first. CREATE EXTENSION is never reversed.\n const created = planMissingArtifacts({ introspected: from, artifacts: allArtifacts });\n const artifactDropSql: string[] = [];\n for (const artifact of [...created].reverse()) {\n if (artifact.owns.kind === \"postgresExtension\") {\n skipped.push(\n `extension \"${artifact.owns.name}\" stays installed — other objects may depend on it (drop it manually if intended)`,\n );\n continue;\n }\n artifactDropSql.push(...artifact.drop);\n }\n\n return {\n name,\n sql: [...artifactDropSql, ...coreSql],\n destructive: steps.some((step) => step.destructive),\n skipped,\n };\n}\n",
|
|
26
26
|
"/**\n * `db push` / `db pull` at library level (the CLI wires these).\n *\n * push = introspect → diff → render → apply, routed per dialect\n * (`providerToDialect(schema.datasource.provider)`):\n *\n * - postgres/pglite: all statements in ONE transaction (transactional DDL).\n * - sqlite: transactional too, UNLESS the script contains a table-rebuild\n * block — those manage their own `PRAGMA foreign_keys` + BEGIN/COMMIT\n * sequence (ddl/sqlite.ts) and run unwrapped; `PRAGMA foreign_key_check`\n * violations become VIBE_MIGRATION errors (execute.ts).\n * - mysql: DDL auto-commits — statements run sequentially, no wrap.\n *\n * Destructive steps are REFUSED unless `acceptDataLoss` is set — the error\n * lists every destructive step, loudly (dialect honesty: never silently drop\n * data).\n */\n\nimport { VibeError, assertValidSchemaIR, providerToDialect } from \"@vibeorm/schema\";\nimport type { Dialect, SchemaIR, VibeExtension } from \"@vibeorm/schema\";\nimport { DIALECT_CAPABILITIES } from \"@vibeorm/sql\";\nimport { diffSchemas } from \"./differ.ts\";\nimport { renderSteps } from \"./ddl/render.ts\";\nimport {\n artifactCreateSql,\n collectExtensionArtifacts,\n planMissingArtifacts,\n probeInstalledExtensionState,\n stripExtensionArtifacts,\n} from \"./extensions.ts\";\nimport {\n cleanupSelfManagedFailure,\n executeStatement,\n usesSelfManagedTransactions,\n} from \"./execute.ts\";\nimport { introspectPostgres } from \"./introspect/postgres.ts\";\nimport { introspectSqlite } from \"./introspect/sqlite.ts\";\nimport { introspectMysql } from \"./introspect/mysql.ts\";\nimport { describeStep } from \"./types.ts\";\nimport type { PushResult, SqlExecutor } from \"./types.ts\";\n\n/**\n * Make the live database match `schema`. Returns the steps that were applied\n * and the SQL executed (both empty when the database already matched — pushing\n * twice is a no-op by the differ's round-trip property).\n *\n * @throws VibeError VIBE_SCHEMA_INVALID when the target schema fails validation.\n * @throws VibeError VIBE_UNSUPPORTED_CAPABILITY for dialect-impossible constructs\n * (scalar lists on sqlite/mysql, partial indexes on mysql, enum-value removal).\n * @throws VibeError VIBE_MIGRATION when destructive steps exist and `acceptDataLoss` is not set.\n */\nexport async function push(params: {\n executor: SqlExecutor;\n schema: SchemaIR;\n acceptDataLoss?: boolean;\n /** Configured extension instances — their artifacts apply with the diff. */\n extensions?: readonly VibeExtension[];\n}): Promise<PushResult> {\n const { executor, schema } = params;\n\n assertValidSchemaIR({ schema });\n\n const dialect = providerToDialect({ provider: schema.datasource.provider });\n\n // Extension artifacts (extensions.md §3): collected BEFORE introspection so\n // an impossible declaration (vector on sqlite) fails before touching the DB.\n const artifacts = collectExtensionArtifacts({\n schema,\n dialect,\n extensions: params.extensions ?? [],\n });\n const allArtifacts = [...artifacts.setup, ...artifacts.objects];\n\n const introspected = await introspectDialect({ executor, dialect });\n // Owned objects leave the diff entirely: the differ neither drops nor\n // re-creates what an extension manages.\n const from = stripExtensionArtifacts({ schema: introspected, artifacts: allArtifacts });\n const steps = diffSchemas({ from, to: schema, dialect });\n\n const destructive = steps.filter((step) => step.destructive);\n if (destructive.length > 0 && params.acceptDataLoss !== true) {\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `push refused: ${destructive.length} destructive step(s) would lose data — pass acceptDataLoss: true to proceed:\\n${destructive\n .map((step) => ` - ${describeStep({ step })}`)\n .join(\"\\n\")}`,\n meta: { destructive: destructive.map((step) => describeStep({ step })) },\n });\n }\n\n const installed = await probeInstalledExtensionState({\n executor,\n dialect,\n artifacts: allArtifacts,\n });\n const missing = planMissingArtifacts({ introspected, artifacts: allArtifacts, installed });\n const setupSql = artifactCreateSql({\n artifacts: missing.filter((artifact) => artifact.owns.kind === \"postgresExtension\"),\n });\n const objectSql = artifactCreateSql({\n artifacts: missing.filter((artifact) => artifact.owns.kind !== \"postgresExtension\"),\n });\n\n const coreSql = renderSteps({ steps, dialect, from, to: schema });\n const sql = [...setupSql, ...coreSql, ...objectSql];\n if (sql.length === 0) return { steps, applied: [] };\n\n const wrap =\n DIALECT_CAPABILITIES[dialect].transactionalDdl && !usesSelfManagedTransactions({ sql });\n\n if (wrap) await executor({ text: \"BEGIN\" });\n try {\n for (const statement of sql) {\n await executeStatement({ executor, statement, dialect });\n }\n if (wrap) await executor({ text: \"COMMIT\" });\n } catch (error) {\n if (wrap) {\n try {\n await executor({ text: \"ROLLBACK\" });\n } catch {\n // Rollback is best-effort; the original failure matters more.\n }\n } else if (dialect === \"sqlite\") {\n await cleanupSelfManagedFailure({ executor });\n }\n throw new VibeError({\n code: \"VIBE_MIGRATION\",\n message: `push failed while applying schema changes: ${error instanceof Error ? error.message : String(error)}`,\n meta: { statements: sql },\n cause: error,\n });\n }\n\n return { steps, applied: sql };\n}\n\n/**\n * Introspect the live database into SchemaIR (the CLI's `db pull`).\n * `dialect` selects the introspector — postgres if omitted (back-compat).\n */\nexport async function pull(params: {\n executor: SqlExecutor;\n dialect?: Dialect;\n}): Promise<SchemaIR> {\n return introspectDialect({ executor: params.executor, dialect: params.dialect ?? \"postgres\" });\n}\n\n// ─── Dialect routing ──────────────────────────────────────────────\n\nasync function introspectDialect(params: {\n executor: SqlExecutor;\n dialect: Dialect;\n}): Promise<SchemaIR> {\n const { executor, dialect } = params;\n switch (dialect) {\n case \"postgres\":\n return introspectPostgres({ executor });\n case \"sqlite\":\n return introspectSqlite({ executor });\n case \"mysql\":\n return introspectMysql({ executor });\n }\n}\n"
|
|
27
27
|
],
|
|
28
|
-
"mappings": "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",
|
|
29
|
-
"debugId": "
|
|
28
|
+
"mappings": "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",
|
|
29
|
+
"debugId": "CA4C1473A398313F64756E2164756E21",
|
|
30
30
|
"names": []
|
|
31
31
|
}
|