@vibeorm/migrate 1.3.1 → 2.0.0-alpha.2
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/README.md +33 -66
- package/dist/ddl/drop-order.d.ts +25 -0
- package/dist/ddl/drop-order.d.ts.map +1 -0
- package/dist/ddl/mysql.d.ts +46 -0
- package/dist/ddl/mysql.d.ts.map +1 -0
- package/dist/ddl/postgres.d.ts +24 -0
- package/dist/ddl/postgres.d.ts.map +1 -0
- package/dist/ddl/render.d.ts +25 -0
- package/dist/ddl/render.d.ts.map +1 -0
- package/dist/ddl/sqlite.d.ts +62 -0
- package/dist/ddl/sqlite.d.ts.map +1 -0
- package/dist/differ.d.ts +33 -0
- package/dist/differ.d.ts.map +1 -0
- package/dist/down.d.ts +55 -0
- package/dist/down.d.ts.map +1 -0
- package/dist/enum-values.d.ts +19 -0
- package/dist/enum-values.d.ts.map +1 -0
- package/dist/execute.d.ts +41 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/extensions.d.ts +74 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3858 -0
- package/dist/index.js.map +31 -0
- package/dist/introspect/mysql.d.ts +31 -0
- package/dist/introspect/mysql.d.ts.map +1 -0
- package/dist/introspect/postgres.d.ts +25 -0
- package/dist/introspect/postgres.d.ts.map +1 -0
- package/dist/introspect/shared.d.ts +76 -0
- package/dist/introspect/shared.d.ts.map +1 -0
- package/dist/introspect/sqlite.d.ts +53 -0
- package/dist/introspect/sqlite.d.ts.map +1 -0
- package/dist/mysql-types.d.ts +66 -0
- package/dist/mysql-types.d.ts.map +1 -0
- package/dist/normalize.d.ts +115 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/postgres-types.d.ts +95 -0
- package/dist/postgres-types.d.ts.map +1 -0
- package/dist/push.d.ts +45 -0
- package/dist/push.d.ts.map +1 -0
- package/dist/relations.d.ts +40 -0
- package/dist/relations.d.ts.map +1 -0
- package/dist/runner.d.ts +120 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/sqlite-types.d.ts +87 -0
- package/dist/sqlite-types.d.ts.map +1 -0
- package/dist/types.d.ts +217 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +33 -23
- package/src/cascade-actions.ts +0 -88
- package/src/ddl-builder.ts +0 -415
- package/src/index.ts +0 -41
- package/src/introspector.ts +0 -684
- package/src/migration-runner.ts +0 -127
- package/src/relation-utils.ts +0 -79
- package/src/schema-differ.ts +0 -865
- package/src/schema-printer.ts +0 -259
- package/src/snapshot.ts +0 -141
- package/src/sql-utils.ts +0 -45
- package/src/types.ts +0 -13
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration runner: generate named migrations from IR diffs, apply them with
|
|
3
|
+
* bookkeeping in `_vibe_migrations`, report status, and repair records.
|
|
4
|
+
*
|
|
5
|
+
* Concurrency: `applyMigrations` takes an advisory lock for the whole run —
|
|
6
|
+
* `pg_advisory_lock(1447645253)` on postgres ("VIBE" in ASCII, blocking,
|
|
7
|
+
* released in a finally), `GET_LOCK('vibeorm_migrate', 60)` on mysql (throws
|
|
8
|
+
* VIBE_MIGRATION on timeout). sqlite needs none: it is single-writer and
|
|
9
|
+
* `BEGIN` serializes. Locks are session-scoped — the SqlExecutor contract
|
|
10
|
+
* (types.ts) requires one session for the whole operation.
|
|
11
|
+
*
|
|
12
|
+
* Execution strategy per dialect (`DIALECT_CAPABILITIES[dialect]`):
|
|
13
|
+
*
|
|
14
|
+
* - transactionalDdl (postgres, sqlite): each migration runs inside
|
|
15
|
+
* BEGIN/COMMIT with its bookkeeping INSERT — atomic. EXCEPT sqlite scripts
|
|
16
|
+
* containing a table-rebuild block, which manage their own transactions
|
|
17
|
+
* (execute.ts `usesSelfManagedTransactions`); those run unwrapped and are
|
|
18
|
+
* re-runnable (the rebuild recipe is effectively idempotent), with the
|
|
19
|
+
* record written after the script completes.
|
|
20
|
+
* - mysql (transactionalDdl: false — DDL auto-commits): the runner records
|
|
21
|
+
* PER-STATEMENT progress instead. The row is inserted up front
|
|
22
|
+
* (statement_index 0), advanced after every statement, and on failure the
|
|
23
|
+
* error lands in the `error` column. Re-running RESUMES from the recorded
|
|
24
|
+
* statement_index — and REFUSES if the migration's checksum changed since
|
|
25
|
+
* the partial application. A row is "complete" when its statement_index
|
|
26
|
+
* reaches the statement count (or its checksum is empty — resolveMigration
|
|
27
|
+
* records, which store statement_index 2147483647).
|
|
28
|
+
*
|
|
29
|
+
* Checksums (sha256 over the joined SQL) pin a migration's content:
|
|
30
|
+
* re-applying a renamed-or-edited migration is a VIBE_MIGRATION error, never
|
|
31
|
+
* a silent divergence.
|
|
32
|
+
*/
|
|
33
|
+
import type { Dialect, SchemaIR, VibeExtension } from "@vibeorm/schema";
|
|
34
|
+
import type { AppliedResult, MigrationFile, MigrationStatus, SqlExecutor } from "./types.ts";
|
|
35
|
+
/** Name of the migrations bookkeeping table (skipped by introspection). */
|
|
36
|
+
export declare const MIGRATIONS_TABLE_NAME: string;
|
|
37
|
+
/** Create the bookkeeping table when missing. */
|
|
38
|
+
export declare function ensureMigrationsTable(params: {
|
|
39
|
+
executor: SqlExecutor;
|
|
40
|
+
dialect?: Dialect;
|
|
41
|
+
}): Promise<void>;
|
|
42
|
+
/** sha256 hex over the migration's statements — its identity across runs. */
|
|
43
|
+
export declare function migrationChecksum(params: {
|
|
44
|
+
sql: readonly string[];
|
|
45
|
+
}): string;
|
|
46
|
+
/**
|
|
47
|
+
* Diff two IRs and render a named migration for a dialect (postgres if
|
|
48
|
+
* omitted). `destructive` aggregates the steps' flags so callers can gate
|
|
49
|
+
* confirmation before applying.
|
|
50
|
+
*/
|
|
51
|
+
export declare function generateMigration(params: {
|
|
52
|
+
from: SchemaIR;
|
|
53
|
+
to: SchemaIR;
|
|
54
|
+
name: string;
|
|
55
|
+
/** Rendering dialect; postgres if omitted. */
|
|
56
|
+
dialect?: Dialect;
|
|
57
|
+
/** Configured extension instances — their artifacts land in the migration. */
|
|
58
|
+
extensions?: readonly VibeExtension[];
|
|
59
|
+
}): MigrationFile;
|
|
60
|
+
/**
|
|
61
|
+
* Apply migrations in order under an advisory lock (see module doc).
|
|
62
|
+
* Already-recorded migrations are checksum-verified and skipped; a mismatch
|
|
63
|
+
* throws VIBE_MIGRATION (a recorded migration whose SQL changed is
|
|
64
|
+
* corruption, not drift to paper over). On mysql, a partially-applied
|
|
65
|
+
* migration RESUMES from its recorded statement_index. Records created by
|
|
66
|
+
* `resolveMigration` (empty checksum) skip verification.
|
|
67
|
+
*/
|
|
68
|
+
export declare function applyMigrations(params: {
|
|
69
|
+
executor: SqlExecutor;
|
|
70
|
+
migrations: readonly MigrationFile[];
|
|
71
|
+
/** Execution dialect; postgres if omitted. */
|
|
72
|
+
dialect?: Dialect;
|
|
73
|
+
}): Promise<AppliedResult>;
|
|
74
|
+
/** Compare known migrations against the bookkeeping table. */
|
|
75
|
+
export declare function migrationStatus(params: {
|
|
76
|
+
executor: SqlExecutor;
|
|
77
|
+
migrations: readonly MigrationFile[];
|
|
78
|
+
/** Bookkeeping dialect; postgres if omitted. */
|
|
79
|
+
dialect?: Dialect;
|
|
80
|
+
}): Promise<MigrationStatus>;
|
|
81
|
+
/**
|
|
82
|
+
* Repair the bookkeeping table without running SQL: mark a migration as
|
|
83
|
+
* `"applied"` (upsert its record; pass `checksum` to also pin its content —
|
|
84
|
+
* omitted, the record stores an empty checksum and later runs skip
|
|
85
|
+
* verification for it) or `"rolled-back"` (delete its record).
|
|
86
|
+
*/
|
|
87
|
+
export declare function resolveMigration(params: {
|
|
88
|
+
executor: SqlExecutor;
|
|
89
|
+
name: string;
|
|
90
|
+
as: "applied" | "rolled-back";
|
|
91
|
+
checksum?: string;
|
|
92
|
+
/** Bookkeeping dialect; postgres if omitted. */
|
|
93
|
+
dialect?: Dialect;
|
|
94
|
+
}): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* Roll back ONE applied migration by executing its `downSql` and deleting its
|
|
97
|
+
* bookkeeping row, under the same advisory lock as `applyMigrations`.
|
|
98
|
+
*
|
|
99
|
+
* Guards, in order: the migration must carry `downSql` (older migrations
|
|
100
|
+
* predate down-migration support), must be recorded as applied, and — when
|
|
101
|
+
* the record pins a checksum — its up SQL must still match (rolling back with
|
|
102
|
+
* drifted files would run a down that no longer mirrors what was applied).
|
|
103
|
+
*
|
|
104
|
+
* Dialect behavior mirrors apply: postgres/sqlite run the down inside
|
|
105
|
+
* BEGIN/COMMIT with the bookkeeping DELETE (atomic; sqlite rebuild scripts
|
|
106
|
+
* run unwrapped, see module doc). mysql DDL auto-commits, so progress is
|
|
107
|
+
* recorded per-statement in the existing `statement_index` column, NEGATIVE
|
|
108
|
+
* to mark the rollback direction: after k down statements, the row stores
|
|
109
|
+
* -(k+1). A failed mysql rollback resumes from the recorded statement on the
|
|
110
|
+
* next call; `applyMigrations` refuses a mid-rollback record. A partially
|
|
111
|
+
* APPLIED mysql migration cannot be rolled back — its down mirrors the full
|
|
112
|
+
* up; finish applying (apply resumes) or repair with `resolveMigration`.
|
|
113
|
+
*/
|
|
114
|
+
export declare function rollbackMigration(params: {
|
|
115
|
+
executor: SqlExecutor;
|
|
116
|
+
migration: MigrationFile;
|
|
117
|
+
/** Execution dialect; postgres if omitted. */
|
|
118
|
+
dialect?: Dialect;
|
|
119
|
+
}): Promise<void>;
|
|
120
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAexE,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI7F,2EAA2E;AAC3E,eAAO,MAAM,qBAAqB,EAAE,MAA2B,CAAC;AAsChE,iDAAiD;AACjD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhB;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG,MAAM,CAE5E;AAID;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,QAAQ,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CACvC,GAAG,aAAa,CA6BhB;AAID;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,QAAQ,EAAE,WAAW,CAAC;IACtB,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IACrC,8CAA8C;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,aAAa,CAAC,CA6DzB;AAID,8DAA8D;AAC9D,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,QAAQ,EAAE,WAAW,CAAC;IACtB,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IACrC,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,eAAe,CAAC,CAqC3B;AAID;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,QAAQ,EAAE,WAAW,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,SAAS,GAAG,aAAa,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhB;AAID;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAC9C,QAAQ,EAAE,WAAW,CAAC;IACtB,SAAS,EAAE,aAAa,CAAC;IACzB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDhB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite column-type mapping (IR → storage class and back), comparison keys,
|
|
3
|
+
* default rendering/fingerprints, and the enum CHECK-constraint convention.
|
|
4
|
+
*
|
|
5
|
+
* dialect-matrix §2: sqlite columns use the four storage classes only —
|
|
6
|
+
* String/DateTime/Decimal/Json → TEXT, Boolean/Int/BigInt → INTEGER,
|
|
7
|
+
* Float → REAL, Bytes → BLOB. Enums are TEXT plus a named CHECK constraint
|
|
8
|
+
* (`CONSTRAINT "<table>_<column>_enum_<Enum>" CHECK ("<column>" IN (…))`) —
|
|
9
|
+
* the constraint NAME is the marker that lets introspection recover the enum's
|
|
10
|
+
* name, and the IN list recovers its values. Scalar lists are unsupported
|
|
11
|
+
* (refused by the differ; this module throws as the render-time backstop).
|
|
12
|
+
*
|
|
13
|
+
* THE TEXT AMBIGUITY, stated honestly: DateTime, Decimal and Json all live in
|
|
14
|
+
* TEXT, and Boolean/BigInt live in INTEGER — a pulled schema reports such
|
|
15
|
+
* columns as String/Int (there is no marker to say otherwise). Column
|
|
16
|
+
* comparison is therefore STORAGE-CLASS based on sqlite (`sqliteColumnTypeKey`
|
|
17
|
+
* compares what the database actually stores), so `diff(introspect(push(X)),
|
|
18
|
+
* X)` stays [] even though the introspected IR says String where X said
|
|
19
|
+
* DateTime.
|
|
20
|
+
*/
|
|
21
|
+
import type { FieldIR, ScalarType } from "@vibeorm/schema";
|
|
22
|
+
import type { EnumIR } from "@vibeorm/schema";
|
|
23
|
+
/** IR scalar → sqlite storage class. */
|
|
24
|
+
export declare const SCALAR_TO_SQLITE: Readonly<Record<ScalarType, string>>;
|
|
25
|
+
/** Render-time backstop for scalar-list columns (the differ refuses earlier). */
|
|
26
|
+
export declare function refuseSqliteScalarList(params: {
|
|
27
|
+
field: FieldIR;
|
|
28
|
+
}): never;
|
|
29
|
+
/**
|
|
30
|
+
* Storage class for a column. Unsupported columns render their nativeType
|
|
31
|
+
* verbatim (fidelity over guessing); enums are TEXT (the CHECK is separate).
|
|
32
|
+
*/
|
|
33
|
+
export declare function sqliteStorageType(params: {
|
|
34
|
+
field: FieldIR;
|
|
35
|
+
}): string;
|
|
36
|
+
/**
|
|
37
|
+
* Comparison key for a column on sqlite: the STORAGE CLASS, not the IR type —
|
|
38
|
+
* String and DateTime are both `t:TEXT` because the database cannot tell them
|
|
39
|
+
* apart. Enum columns key on their VALUE LIST (`e:A|B`), never their name
|
|
40
|
+
* (the name only lives in our CHECK-constraint convention): adding an enum
|
|
41
|
+
* value changes the key and flows through `alterColumn` → table rebuild with
|
|
42
|
+
* the widened CHECK.
|
|
43
|
+
*/
|
|
44
|
+
export declare function sqliteColumnTypeKey(params: {
|
|
45
|
+
field: FieldIR;
|
|
46
|
+
enums: ReadonlyMap<string, EnumIR>;
|
|
47
|
+
}): string;
|
|
48
|
+
/**
|
|
49
|
+
* Default fingerprint on sqlite: postgres rules, except booleans compare as
|
|
50
|
+
* their INTEGER storage (`true` → `num:1`) — an introspected sqlite schema can
|
|
51
|
+
* only ever report `DEFAULT 1`, and the fingerprint must not churn on that.
|
|
52
|
+
*/
|
|
53
|
+
export declare function sqliteDefaultFingerprint(params: {
|
|
54
|
+
field: FieldIR;
|
|
55
|
+
}): string | null;
|
|
56
|
+
/**
|
|
57
|
+
* Render the `DEFAULT` expression for a field on sqlite, or `undefined` when
|
|
58
|
+
* the column takes none (app-level generators, autoincrement — which renders
|
|
59
|
+
* as `INTEGER PRIMARY KEY AUTOINCREMENT` instead). Booleans store as 1/0.
|
|
60
|
+
*/
|
|
61
|
+
export declare function sqliteDefaultSql(params: {
|
|
62
|
+
field: FieldIR;
|
|
63
|
+
}): string | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Name of the enum CHECK constraint for a column — the `_enum_` infix is the
|
|
66
|
+
* introspection marker that recovers the enum's name from `sqlite_master.sql`.
|
|
67
|
+
*/
|
|
68
|
+
export declare function sqliteEnumCheckName(params: {
|
|
69
|
+
table: string;
|
|
70
|
+
column: string;
|
|
71
|
+
enumName: string;
|
|
72
|
+
}): string;
|
|
73
|
+
/** One parsed enum CHECK constraint from a table's `sqlite_master.sql`. */
|
|
74
|
+
export type ParsedEnumCheck = {
|
|
75
|
+
readonly column: string;
|
|
76
|
+
readonly enumName: string;
|
|
77
|
+
readonly values: readonly string[];
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Recover enum columns from a table's `sqlite_master.sql` text. Only checks
|
|
81
|
+
* following OUR naming convention are recognized; foreign CHECK constraints
|
|
82
|
+
* are ignored (and — documented limitation — do not survive a table rebuild).
|
|
83
|
+
*/
|
|
84
|
+
export declare function parseSqliteEnumChecks(params: {
|
|
85
|
+
tableSql: string;
|
|
86
|
+
}): ParsedEnumCheck[];
|
|
87
|
+
//# sourceMappingURL=sqlite-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-types.d.ts","sourceRoot":"","sources":["../src/sqlite-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAI9C,wCAAwC;AACxC,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAUjE,CAAC;AAEF,iFAAiF;AACjF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,CAMxE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAepE;AAID;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC,GAAG,MAAM,CAWT;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAOlF;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAuB/E;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CAET;AAED,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,CAAC;AAKF;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,eAAe,EAAE,CAYrF"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public types of @vibeorm/migrate: the executor contract, the dialect-neutral
|
|
3
|
+
* migration step model, and the runner's file/result shapes.
|
|
4
|
+
*
|
|
5
|
+
* Steps carry Schema-IR fragments (FieldIR, EnumIR) — never SQL text. SQL is
|
|
6
|
+
* produced exclusively by the per-dialect renderers (ddl-postgres.ts), so every
|
|
7
|
+
* SQL-text decision stays reviewable in one place (constitution rule 3/4).
|
|
8
|
+
*/
|
|
9
|
+
import type { CascadeAction, EnumIR, FieldIR } from "@vibeorm/schema";
|
|
10
|
+
/**
|
|
11
|
+
* Minimal SQL execution contract the migrate engine runs on. Structurally
|
|
12
|
+
* identical to @vibeorm/runtime's `SqlExecutor` (its `toSqlExecutor` bridges a
|
|
13
|
+
* DatabaseAdapter to this shape) — declared here so the dependency direction
|
|
14
|
+
* stays schema ← sql ← migrate.
|
|
15
|
+
*
|
|
16
|
+
* SESSION AFFINITY: the migrate engine issues session-scoped statements
|
|
17
|
+
* through this contract (BEGIN/COMMIT, `PRAGMA foreign_keys`, advisory locks
|
|
18
|
+
* `pg_advisory_lock` / `GET_LOCK`), so every call MUST hit the same database
|
|
19
|
+
* session. Single-connection adapters (pglite, sqlite) satisfy this by
|
|
20
|
+
* construction; pool-backed executors must pin one connection for the whole
|
|
21
|
+
* migrate operation.
|
|
22
|
+
*/
|
|
23
|
+
export type SqlExecutor = (params: {
|
|
24
|
+
text: string;
|
|
25
|
+
values?: unknown[];
|
|
26
|
+
}) => Promise<Record<string, unknown>[]>;
|
|
27
|
+
/** Which aspects of a column an `alterColumn` step changes. */
|
|
28
|
+
export type AlterColumnAspect = "type" | "nullability" | "default";
|
|
29
|
+
/** One column of an index, with its sort direction. */
|
|
30
|
+
export type IndexColumn = {
|
|
31
|
+
readonly name: string;
|
|
32
|
+
readonly desc: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* The field is a Decimal (SQLITE-2, SQL review round 2). Inert everywhere
|
|
35
|
+
* except the sqlite DDL renderer: Decimal stores as TEXT there and every
|
|
36
|
+
* compare/order site reads `CAST(col AS REAL)` (B4), which a plain-column
|
|
37
|
+
* index can never serve (EQP-proven SCAN) — sqlite renders an EXPRESSION
|
|
38
|
+
* index over the same cast instead. Not part of the index comparison key:
|
|
39
|
+
* both sides compare by column name + direction.
|
|
40
|
+
*/
|
|
41
|
+
readonly decimal?: boolean;
|
|
42
|
+
};
|
|
43
|
+
/** One side of an implicit many-to-many join table. */
|
|
44
|
+
export type JoinTableEnd = {
|
|
45
|
+
/** Referenced table (db name). */
|
|
46
|
+
readonly table: string;
|
|
47
|
+
/** Referenced primary-key column (db name). */
|
|
48
|
+
readonly column: string;
|
|
49
|
+
/** The referenced primary-key field — its type renders the join column's type. */
|
|
50
|
+
readonly field: FieldIR;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* A dialect-neutral migration step produced by `diffSchemas`. `destructive`
|
|
54
|
+
* marks steps that can lose data (dropTable / dropJoinTable / dropColumn /
|
|
55
|
+
* dropEnum / narrowing type changes) — `push` refuses them without
|
|
56
|
+
* `acceptDataLoss`, and `generateMigration` surfaces the flag.
|
|
57
|
+
*/
|
|
58
|
+
export type MigrationStep = {
|
|
59
|
+
readonly kind: "createEnum";
|
|
60
|
+
readonly enumDef: EnumIR;
|
|
61
|
+
readonly destructive: false;
|
|
62
|
+
} | {
|
|
63
|
+
readonly kind: "dropEnum";
|
|
64
|
+
readonly enumName: string;
|
|
65
|
+
readonly destructive: true;
|
|
66
|
+
} | {
|
|
67
|
+
readonly kind: "addEnumValue";
|
|
68
|
+
readonly enumName: string;
|
|
69
|
+
readonly value: string;
|
|
70
|
+
readonly destructive: false;
|
|
71
|
+
} | {
|
|
72
|
+
readonly kind: "createTable";
|
|
73
|
+
readonly table: string;
|
|
74
|
+
readonly columns: readonly FieldIR[];
|
|
75
|
+
/** Primary-key column db names (empty = no PK). */
|
|
76
|
+
readonly primaryKey: readonly string[];
|
|
77
|
+
readonly destructive: false;
|
|
78
|
+
} | {
|
|
79
|
+
readonly kind: "dropTable";
|
|
80
|
+
readonly table: string;
|
|
81
|
+
readonly destructive: true;
|
|
82
|
+
} | {
|
|
83
|
+
readonly kind: "addColumn";
|
|
84
|
+
readonly table: string;
|
|
85
|
+
readonly column: FieldIR;
|
|
86
|
+
readonly destructive: false;
|
|
87
|
+
} | {
|
|
88
|
+
readonly kind: "dropColumn";
|
|
89
|
+
readonly table: string;
|
|
90
|
+
readonly column: string;
|
|
91
|
+
readonly destructive: true;
|
|
92
|
+
} | {
|
|
93
|
+
readonly kind: "alterColumn";
|
|
94
|
+
readonly table: string;
|
|
95
|
+
/** Column db name. */
|
|
96
|
+
readonly column: string;
|
|
97
|
+
readonly from: FieldIR;
|
|
98
|
+
readonly to: FieldIR;
|
|
99
|
+
readonly changes: readonly AlterColumnAspect[];
|
|
100
|
+
readonly destructive: boolean;
|
|
101
|
+
} | {
|
|
102
|
+
readonly kind: "createIndex";
|
|
103
|
+
readonly table: string;
|
|
104
|
+
readonly name: string;
|
|
105
|
+
/** IR index kind ("btree", "gin", …) — `unique` indexes are always btree. */
|
|
106
|
+
readonly indexKind: string;
|
|
107
|
+
readonly unique: boolean;
|
|
108
|
+
readonly columns: readonly IndexColumn[];
|
|
109
|
+
/** Partial-index predicate, raw SQL. */
|
|
110
|
+
readonly where?: string;
|
|
111
|
+
readonly destructive: false;
|
|
112
|
+
} | {
|
|
113
|
+
readonly kind: "dropIndex";
|
|
114
|
+
readonly name: string;
|
|
115
|
+
/**
|
|
116
|
+
* Table the index belongs to. Optional for postgres/sqlite (their DROP
|
|
117
|
+
* INDEX is schema-global) but REQUIRED by the mysql renderer
|
|
118
|
+
* (`DROP INDEX … ON table`); the differ always fills it.
|
|
119
|
+
*/
|
|
120
|
+
readonly table?: string;
|
|
121
|
+
readonly destructive: false;
|
|
122
|
+
} | {
|
|
123
|
+
readonly kind: "addForeignKey";
|
|
124
|
+
readonly table: string;
|
|
125
|
+
readonly constraintName: string;
|
|
126
|
+
readonly columns: readonly string[];
|
|
127
|
+
readonly refTable: string;
|
|
128
|
+
readonly refColumns: readonly string[];
|
|
129
|
+
readonly onDelete: CascadeAction;
|
|
130
|
+
readonly onUpdate: CascadeAction;
|
|
131
|
+
readonly destructive: false;
|
|
132
|
+
} | {
|
|
133
|
+
readonly kind: "dropForeignKey";
|
|
134
|
+
readonly table: string;
|
|
135
|
+
readonly constraintName: string;
|
|
136
|
+
readonly destructive: false;
|
|
137
|
+
} | {
|
|
138
|
+
readonly kind: "createJoinTable";
|
|
139
|
+
readonly table: string;
|
|
140
|
+
readonly a: JoinTableEnd;
|
|
141
|
+
readonly b: JoinTableEnd;
|
|
142
|
+
readonly destructive: false;
|
|
143
|
+
} | {
|
|
144
|
+
readonly kind: "dropJoinTable";
|
|
145
|
+
readonly table: string;
|
|
146
|
+
readonly destructive: true;
|
|
147
|
+
} | {
|
|
148
|
+
readonly kind: "addPrimaryKey";
|
|
149
|
+
readonly table: string;
|
|
150
|
+
readonly columns: readonly string[];
|
|
151
|
+
readonly destructive: false;
|
|
152
|
+
} | {
|
|
153
|
+
readonly kind: "dropPrimaryKey";
|
|
154
|
+
readonly table: string;
|
|
155
|
+
readonly destructive: false;
|
|
156
|
+
} | {
|
|
157
|
+
/**
|
|
158
|
+
* Drop a view present in the live database but absent from the target
|
|
159
|
+
* schema (board #26). Ordered FIRST — postgres refuses dropping a column
|
|
160
|
+
* a leftover view depends on (2BP01), so removed views must go before
|
|
161
|
+
* the table/column changes they block. Destructive: the view definition
|
|
162
|
+
* is not stored in the IR, so the drop cannot be reversed.
|
|
163
|
+
*/
|
|
164
|
+
readonly kind: "dropView";
|
|
165
|
+
/** View db name. */
|
|
166
|
+
readonly table: string;
|
|
167
|
+
readonly destructive: true;
|
|
168
|
+
};
|
|
169
|
+
/** One-line human description of a step (refusal messages, CLI output). */
|
|
170
|
+
export declare function describeStep(params: {
|
|
171
|
+
step: MigrationStep;
|
|
172
|
+
}): string;
|
|
173
|
+
/** A named migration: ordered SQL statements plus its aggregate destructiveness. */
|
|
174
|
+
export type MigrationFile = {
|
|
175
|
+
readonly name: string;
|
|
176
|
+
/** One SQL string per statement, in execution order. */
|
|
177
|
+
readonly sql: readonly string[];
|
|
178
|
+
/** True when any underlying step can lose data. */
|
|
179
|
+
readonly destructive: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Reverse statements (`down.sql`), when the migration carries them.
|
|
182
|
+
* Migrations generated before down-migration support have none —
|
|
183
|
+
* `rollbackMigration` refuses those with a clear error.
|
|
184
|
+
*/
|
|
185
|
+
readonly downSql?: readonly string[];
|
|
186
|
+
};
|
|
187
|
+
/** Result of `applyMigrations`. */
|
|
188
|
+
export type AppliedResult = {
|
|
189
|
+
/** Migrations executed by this call, in order. */
|
|
190
|
+
readonly applied: readonly string[];
|
|
191
|
+
/** Migrations already recorded and verified, skipped. */
|
|
192
|
+
readonly skipped: readonly string[];
|
|
193
|
+
};
|
|
194
|
+
/** Result of `migrationStatus`. */
|
|
195
|
+
export type MigrationStatus = {
|
|
196
|
+
/** Recorded migrations whose checksum matches. */
|
|
197
|
+
readonly applied: readonly string[];
|
|
198
|
+
/** Migrations with no record yet. */
|
|
199
|
+
readonly pending: readonly string[];
|
|
200
|
+
/** Recorded migrations whose checksum no longer matches their SQL. */
|
|
201
|
+
readonly mismatched: readonly string[];
|
|
202
|
+
/**
|
|
203
|
+
* Migrations whose rollback started but did not finish (mysql only — its
|
|
204
|
+
* DDL is non-transactional, so `rollbackMigration` records per-statement
|
|
205
|
+
* progress). Re-run the rollback to resume, or repair with
|
|
206
|
+
* `resolveMigration`.
|
|
207
|
+
*/
|
|
208
|
+
readonly rollingBack: readonly string[];
|
|
209
|
+
};
|
|
210
|
+
/** Result of `push`. */
|
|
211
|
+
export type PushResult = {
|
|
212
|
+
/** The diff that was applied (empty = database already matched). */
|
|
213
|
+
readonly steps: readonly MigrationStep[];
|
|
214
|
+
/** The SQL statements that were executed, in order. */
|
|
215
|
+
readonly applied: readonly string[];
|
|
216
|
+
};
|
|
217
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,42 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeorm/migrate",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Migration
|
|
5
|
-
"license": "MIT",
|
|
3
|
+
"version": "2.0.0-alpha.2",
|
|
4
|
+
"description": "Migration engine for VibeORM v2 — IR differ, per-dialect DDL, migration runner, introspection",
|
|
6
5
|
"keywords": [
|
|
7
6
|
"orm",
|
|
8
|
-
"migrations",
|
|
9
|
-
"postgresql",
|
|
10
|
-
"bun",
|
|
11
7
|
"typescript",
|
|
12
|
-
"
|
|
8
|
+
"sql",
|
|
9
|
+
"database",
|
|
10
|
+
"bun",
|
|
11
|
+
"type-safe",
|
|
12
|
+
"migrations",
|
|
13
|
+
"ddl",
|
|
14
|
+
"introspection",
|
|
15
|
+
"schema-diff",
|
|
16
|
+
"postgres",
|
|
17
|
+
"mysql",
|
|
18
|
+
"sqlite"
|
|
13
19
|
],
|
|
20
|
+
"homepage": "https://github.com/vibeorm/vibeorm/tree/master/packages/migrate#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/vibeorm/vibeorm/issues"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/vibeorm/vibeorm.git",
|
|
27
|
+
"directory": "packages/migrate"
|
|
28
|
+
},
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"author": "VibeORM contributors",
|
|
14
31
|
"type": "module",
|
|
15
32
|
"exports": {
|
|
16
33
|
".": {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
19
36
|
}
|
|
20
37
|
},
|
|
21
38
|
"files": [
|
|
22
|
-
"
|
|
39
|
+
"dist",
|
|
40
|
+
"README.md"
|
|
23
41
|
],
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"url": "https://github.com/vibeorm/vibeorm.git",
|
|
27
|
-
"directory": "packages/migrate"
|
|
42
|
+
"engines": {
|
|
43
|
+
"bun": ">=1.2.0"
|
|
28
44
|
},
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
"
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@vibeorm/schema": "2.0.0-alpha.1",
|
|
47
|
+
"@vibeorm/sql": "2.0.0-alpha.1"
|
|
32
48
|
},
|
|
33
49
|
"publishConfig": {
|
|
34
50
|
"access": "public"
|
|
35
|
-
},
|
|
36
|
-
"engines": {
|
|
37
|
-
"bun": ">=1.1.0"
|
|
38
|
-
},
|
|
39
|
-
"dependencies": {
|
|
40
|
-
"@vibeorm/parser": "1.3.1"
|
|
41
51
|
}
|
|
42
52
|
}
|
package/src/cascade-actions.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cascade-action resolution and SQL serialisation.
|
|
3
|
-
*
|
|
4
|
-
* Translates a `CascadeAction` from the parser IR into a Postgres
|
|
5
|
-
* `ON DELETE`/`ON UPDATE` clause, applying Prisma-compatible defaults when
|
|
6
|
-
* the schema doesn't specify an action explicitly.
|
|
7
|
-
*
|
|
8
|
-
* Defaults (matching Prisma's Postgres behaviour):
|
|
9
|
-
* - `onDelete`: required FK → `Restrict`, optional FK → `SetNull`
|
|
10
|
-
* - `onUpdate`: always → `Cascade`
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import type { CascadeAction, RelationField } from "@vibeorm/parser";
|
|
14
|
-
|
|
15
|
-
const ACTION_TO_SQL: Record<CascadeAction, string> = {
|
|
16
|
-
Cascade: "CASCADE",
|
|
17
|
-
Restrict: "RESTRICT",
|
|
18
|
-
NoAction: "NO ACTION",
|
|
19
|
-
SetNull: "SET NULL",
|
|
20
|
-
SetDefault: "SET DEFAULT",
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Inverse of {@link ACTION_TO_SQL} — used by the introspector when reading
|
|
25
|
-
* `pg_constraint.confdeltype`/`confupdtype`. The single-char codes are
|
|
26
|
-
* Postgres's catalog representation.
|
|
27
|
-
*/
|
|
28
|
-
export const PG_CHAR_TO_CASCADE_ACTION: Record<string, CascadeAction> = {
|
|
29
|
-
a: "NoAction",
|
|
30
|
-
r: "Restrict",
|
|
31
|
-
c: "Cascade",
|
|
32
|
-
n: "SetNull",
|
|
33
|
-
d: "SetDefault",
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Resolve the effective onDelete action for a relation, applying the Prisma
|
|
38
|
-
* default when the schema didn't say anything explicit.
|
|
39
|
-
*
|
|
40
|
-
* `isRequired` is the FK column's nullability (Prisma's "required relation").
|
|
41
|
-
*/
|
|
42
|
-
export function resolveOnDelete(params: {
|
|
43
|
-
explicit: CascadeAction | undefined;
|
|
44
|
-
isRequired: boolean;
|
|
45
|
-
}): CascadeAction {
|
|
46
|
-
if (params.explicit) return params.explicit;
|
|
47
|
-
return params.isRequired ? "Restrict" : "SetNull";
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/** Resolve the effective onUpdate action. Prisma's Postgres default is Cascade. */
|
|
51
|
-
export function resolveOnUpdate(params: {
|
|
52
|
-
explicit: CascadeAction | undefined;
|
|
53
|
-
}): CascadeAction {
|
|
54
|
-
return params.explicit ?? "Cascade";
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** Convenience: serialise a CascadeAction to its Postgres clause body. */
|
|
58
|
-
export function cascadeActionSql(params: { action: CascadeAction }): string {
|
|
59
|
-
return ACTION_TO_SQL[params.action];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Build the full `ON DELETE X ON UPDATE Y` clause for a relation field,
|
|
64
|
-
* applying defaults as needed.
|
|
65
|
-
*/
|
|
66
|
-
export function buildFkActionClause(params: { rel: RelationField }): string {
|
|
67
|
-
const { rel } = params;
|
|
68
|
-
const onDelete = resolveOnDelete({
|
|
69
|
-
explicit: rel.relation.onDelete,
|
|
70
|
-
isRequired: rel.isRequired,
|
|
71
|
-
});
|
|
72
|
-
const onUpdate = resolveOnUpdate({ explicit: rel.relation.onUpdate });
|
|
73
|
-
return `ON DELETE ${ACTION_TO_SQL[onDelete]} ON UPDATE ${ACTION_TO_SQL[onUpdate]}`;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Stable comparison key for whether two relations have the same effective
|
|
78
|
-
* cascade behaviour. Used by the differ to detect drift even when the schema
|
|
79
|
-
* was written without explicit actions (defaults must still be considered).
|
|
80
|
-
*/
|
|
81
|
-
export function fkActionFingerprint(params: { rel: RelationField }): string {
|
|
82
|
-
const onDelete = resolveOnDelete({
|
|
83
|
-
explicit: params.rel.relation.onDelete,
|
|
84
|
-
isRequired: params.rel.isRequired,
|
|
85
|
-
});
|
|
86
|
-
const onUpdate = resolveOnUpdate({ explicit: params.rel.relation.onUpdate });
|
|
87
|
-
return `${onDelete}|${onUpdate}`;
|
|
88
|
-
}
|