@vibeorm/migrate 2.0.0-alpha.1 → 2.0.0-alpha.10
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/mysql.d.ts.map +1 -1
- package/dist/ddl/postgres.d.ts.map +1 -1
- package/dist/ddl/render.d.ts.map +1 -1
- package/dist/ddl/rls.d.ts +40 -0
- package/dist/ddl/rls.d.ts.map +1 -0
- package/dist/ddl/sqlite.d.ts +18 -1
- package/dist/ddl/sqlite.d.ts.map +1 -1
- package/dist/differ.d.ts +8 -0
- package/dist/differ.d.ts.map +1 -1
- package/dist/down.d.ts +2 -0
- package/dist/down.d.ts.map +1 -1
- package/dist/enum-values.d.ts +14 -1
- package/dist/enum-values.d.ts.map +1 -1
- package/dist/execute.d.ts +84 -1
- package/dist/execute.d.ts.map +1 -1
- package/dist/execution.d.ts +168 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3697 -1822
- package/dist/index.js.map +29 -23
- package/dist/introspect/mysql.d.ts.map +1 -1
- package/dist/introspect/postgres-rls.d.ts +41 -0
- package/dist/introspect/postgres-rls.d.ts.map +1 -0
- package/dist/introspect/postgres.d.ts +5 -18
- package/dist/introspect/postgres.d.ts.map +1 -1
- package/dist/introspect/shared.d.ts +8 -1
- package/dist/introspect/shared.d.ts.map +1 -1
- package/dist/introspect/sqlite.d.ts.map +1 -1
- package/dist/journal-table.d.ts +15 -0
- package/dist/journal-table.d.ts.map +1 -0
- package/dist/mysql-types.d.ts.map +1 -1
- package/dist/normalize.d.ts +32 -4
- package/dist/normalize.d.ts.map +1 -1
- package/dist/postgres-types.d.ts +8 -1
- package/dist/postgres-types.d.ts.map +1 -1
- package/dist/push.d.ts +6 -0
- package/dist/push.d.ts.map +1 -1
- package/dist/recovery.d.ts +41 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/relations.d.ts +16 -6
- package/dist/relations.d.ts.map +1 -1
- package/dist/renames.d.ts +58 -0
- package/dist/renames.d.ts.map +1 -0
- package/dist/runner.d.ts +87 -26
- package/dist/runner.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 +114 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../src/introspect/mysql.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../src/introspect/mysql.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAUV,QAAQ,EACT,MAAM,iBAAiB,CAAC;AASzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAyH/C,uEAAuE;AACvE,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,WAAW,CAAA;CAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6M1F"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { SchemaIR } from "@vibeorm/schema";
|
|
2
|
+
import type { SqlExecutor } from "../types.ts";
|
|
3
|
+
/** Catalog attributes are intentionally not represented as authored policy declarations. */
|
|
4
|
+
export type PostgresRlsPolicy = {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly command: string;
|
|
7
|
+
readonly permissive: boolean;
|
|
8
|
+
readonly roles: string;
|
|
9
|
+
readonly using: string | null;
|
|
10
|
+
readonly withCheck: string | null;
|
|
11
|
+
readonly comment: string | null;
|
|
12
|
+
};
|
|
13
|
+
/** Every public ordinary/partitioned table, including tables with flags but no policies. */
|
|
14
|
+
export type PostgresRlsTable = {
|
|
15
|
+
readonly table: string;
|
|
16
|
+
readonly enabled: boolean;
|
|
17
|
+
readonly force: boolean;
|
|
18
|
+
readonly policies: readonly PostgresRlsPolicy[];
|
|
19
|
+
};
|
|
20
|
+
/** Read both clauses and all structural attributes; callers pin search_path and transaction. */
|
|
21
|
+
export declare function readPostgresRls(params: {
|
|
22
|
+
executor: SqlExecutor;
|
|
23
|
+
}): Promise<PostgresRlsTable[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Compare against a trusted deployed declaration, not a policy name/comment/hash.
|
|
26
|
+
* An explicit previousSchema/status check requires every declared policy to exist.
|
|
27
|
+
* Push without a previous schema permits installing protection on an ordinary table.
|
|
28
|
+
* Must run inside the caller's transaction. Locks survive the rolled-back probe.
|
|
29
|
+
*/
|
|
30
|
+
export declare function verifyPostgresRls(params: {
|
|
31
|
+
executor: SqlExecutor;
|
|
32
|
+
schema?: SchemaIR;
|
|
33
|
+
requireInstalled?: boolean;
|
|
34
|
+
}): Promise<ReadonlySet<string>>;
|
|
35
|
+
/** Attach only verified declarations, mapped to the physical names introspection uses. No SQL parsing. */
|
|
36
|
+
export declare function projectPostgresRls(params: {
|
|
37
|
+
physical: SchemaIR;
|
|
38
|
+
declared?: SchemaIR;
|
|
39
|
+
matched: ReadonlySet<string>;
|
|
40
|
+
}): SchemaIR;
|
|
41
|
+
//# sourceMappingURL=postgres-rls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-rls.d.ts","sourceRoot":"","sources":["../../src/introspect/postgres-rls.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAwB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,4FAA4F;AAC5F,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AACF,4FAA4F;AAC5F,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACjD,CAAC;AAeF,gGAAgG;AAChG,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,WAAW,CAAA;CAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAepG;AAUD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAC9C,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAyD/B;AAED,0GAA0G;AAC1G,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAAE,GAAG,QAAQ,CAsB9H"}
|
|
@@ -1,25 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Postgres / PGlite introspection: live database → SchemaIR.
|
|
3
|
-
*
|
|
4
|
-
* Representation contract (the differ's round-trip depends on it, LEARNINGS):
|
|
5
|
-
*
|
|
6
|
-
* - Type mapping is the REVERSE of dialect-matrix §2; `nativeType` is set only
|
|
7
|
-
* when the column's type is NOT the canonical mapping for its scalar.
|
|
8
|
-
* - Identity columns and `nextval(...)` defaults → `@default(autoincrement())`.
|
|
9
|
-
* - Enum ARRAY columns (`data_type = 'ARRAY'`, `udt_name = '_EnumName'`) are
|
|
10
|
-
* enum lists — never `String[]`.
|
|
11
|
-
* - Unknown column types (tsvector, geometry, …) become `isUnsupported` fields
|
|
12
|
-
* with the raw type in `nativeType` — kept, not dropped.
|
|
13
|
-
* - FK/join-table representation comes from introspect/shared.ts — the ONE
|
|
14
|
-
* structural rule every dialect introspector uses.
|
|
15
|
-
* - Views (`isView: true`) are returned with their columns only.
|
|
16
|
-
* - The `_vibe_migrations` bookkeeping table is skipped.
|
|
17
|
-
* - Hardcoded to the `public` schema (v1 parity).
|
|
18
|
-
*/
|
|
19
1
|
import type { SchemaIR } from "@vibeorm/schema";
|
|
20
2
|
import type { SqlExecutor } from "../types.ts";
|
|
21
3
|
/** Introspect a live postgres/pglite database (public schema) into SchemaIR. */
|
|
22
4
|
export declare function introspectPostgres(params: {
|
|
23
5
|
executor: SqlExecutor;
|
|
6
|
+
/** Trusted policy declaration; missing this refuses lossy RLS introspection/export. */
|
|
7
|
+
rlsSchema?: SchemaIR;
|
|
8
|
+
/** The caller owns BEGIN/COMMIT, keeping probe locks through subsequent migration DDL. */
|
|
9
|
+
inTransaction?: boolean;
|
|
10
|
+
requireInstalledRls?: boolean;
|
|
24
11
|
}): Promise<SchemaIR>;
|
|
25
12
|
//# sourceMappingURL=postgres.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/introspect/postgres.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/introspect/postgres.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EASV,QAAQ,EACT,MAAM,iBAAiB,CAAC;AASzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA0L/C,gFAAgF;AAChF,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAC/C,QAAQ,EAAE,WAAW,CAAC;IACtB,uFAAuF;IACvF,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,0FAA0F;IAC1F,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuBpB"}
|
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
* consumer). Every dialect introspector produces the same representation:
|
|
6
6
|
*
|
|
7
7
|
* - FKs become an UNNAMED `manyToOne` on the owning model plus an UNNAMED
|
|
8
|
-
* `oneToMany` list side on the target
|
|
8
|
+
* `oneToMany` list side on the target — EXCEPT when the model pair carries
|
|
9
|
+
* more than one unnamed relation pair (mutual FKs, twin FKs to one target,
|
|
10
|
+
* an FK alongside a default-named join table): those FK pairs get a
|
|
11
|
+
* synthesized `@relation` name so `db pull` output re-parses (the parser
|
|
12
|
+
* rejects the unnamed shape as `ambiguous-relation`) and implicit-M2M
|
|
13
|
+
* detection keeps its name keys unique.
|
|
9
14
|
* - A table matching the implicit join-table shape (name `_X`, exactly columns
|
|
10
15
|
* "A" and "B", two single-column FKs, a unique index on (A, B)) is NOT a
|
|
11
16
|
* model: it becomes two unnamed `oneToMany` list sides on the joined models,
|
|
@@ -36,6 +41,8 @@ export type IntrospectedIndex = {
|
|
|
36
41
|
readonly desc: boolean;
|
|
37
42
|
}[];
|
|
38
43
|
readonly where?: string;
|
|
44
|
+
/** `UNIQUE NULLS NOT DISTINCT` (postgres 15+). */
|
|
45
|
+
readonly nullsNotDistinct?: boolean;
|
|
39
46
|
};
|
|
40
47
|
/** A detected physical join table. */
|
|
41
48
|
export type JoinTableInfo = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/introspect/shared.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/introspect/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAc,MAAM,iBAAiB,CAAC;AAI1E,sEAAsE;AACtE,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,qEAAqE;AACrE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC/E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC,CAAC;AAEF,sCAAsC;AACtC,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAIF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACvC,GAAG,aAAa,GAAG,IAAI,CA8BvB;AAID,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,MAAM,EAAE;IACrC,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAChD,GAAG,IAAI,CA+CP;AAED,8EAA8E;AAC9E,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAChD,GAAG,IAAI,CAuCP;AAmGD,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/introspect/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAQV,QAAQ,EACT,MAAM,iBAAiB,CAAC;AAUzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAyB/C,uDAAuD;AACvD,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,WAAW,CAAA;CAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/introspect/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAQV,QAAQ,EACT,MAAM,iBAAiB,CAAC;AAUzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAyB/C,uDAAuD;AACvD,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,WAAW,CAAA;CAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuI3F;AAwGD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAC/C,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,EAAE,GAAG,IAAI,CAqD3C"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bookkeeping table's name, alone in a leaf module.
|
|
3
|
+
*
|
|
4
|
+
* It used to live in runner.ts, which the three introspectors import while
|
|
5
|
+
* runner.ts is itself importing THEM — a cycle whose outcome depended on which
|
|
6
|
+
* module the process happened to evaluate first, and which surfaced as
|
|
7
|
+
* "Cannot access 'MIGRATIONS_TABLE_NAME' before initialization" as soon as the
|
|
8
|
+
* import order shifted. A leaf module has no such ordering: it can be
|
|
9
|
+
* evaluated before anything that needs it.
|
|
10
|
+
*
|
|
11
|
+
* runner.ts re-exports the name, so the public surface is unchanged.
|
|
12
|
+
*/
|
|
13
|
+
/** Name of the migrations bookkeeping table (skipped by introspection). */
|
|
14
|
+
export declare const MIGRATIONS_TABLE_NAME: string;
|
|
15
|
+
//# sourceMappingURL=journal-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal-table.d.ts","sourceRoot":"","sources":["../src/journal-table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,qBAAqB,EAAE,MAA2B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql-types.d.ts","sourceRoot":"","sources":["../src/mysql-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"mysql-types.d.ts","sourceRoot":"","sources":["../src/mysql-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMnE,6EAA6E;AAC7E,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAUhE,CAAC;AAEF,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,CAMvE;AAaD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CASlE;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC,GAAG,MAAM,CAgBT;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAEjF;AAID,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC,GAAG,MAAM,CA8BT;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAuB9E;AAID,yEAAyE;AACzE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAQxF"}
|
package/dist/normalize.d.ts
CHANGED
|
@@ -39,6 +39,8 @@ export type NormalizedIndex = {
|
|
|
39
39
|
readonly unique: boolean;
|
|
40
40
|
readonly columns: readonly IndexColumn[];
|
|
41
41
|
readonly where?: string;
|
|
42
|
+
/** `UNIQUE NULLS NOT DISTINCT` (postgres 15+). */
|
|
43
|
+
readonly nullsNotDistinct?: boolean;
|
|
42
44
|
};
|
|
43
45
|
/** A foreign key ready for comparison. `key` excludes the cascade actions. */
|
|
44
46
|
export type NormalizedFk = {
|
|
@@ -60,6 +62,12 @@ export type NormalizedTable = {
|
|
|
60
62
|
readonly pk: readonly string[];
|
|
61
63
|
readonly indexes: ReadonlyMap<string, NormalizedIndex>;
|
|
62
64
|
readonly fks: ReadonlyMap<string, NormalizedFk>;
|
|
65
|
+
/**
|
|
66
|
+
* CHECK constraints, name → raw expression. NAME-keyed in the diff —
|
|
67
|
+
* engines re-serialize expressions on introspection, so text is never
|
|
68
|
+
* compared (an expression change = rename the check).
|
|
69
|
+
*/
|
|
70
|
+
readonly checks: ReadonlyMap<string, string>;
|
|
63
71
|
};
|
|
64
72
|
/** An implicit M2M join table collapsed to its database shape. */
|
|
65
73
|
export type NormalizedJoinTable = {
|
|
@@ -87,6 +95,13 @@ export declare function normalizeSchema(params: {
|
|
|
87
95
|
schema: SchemaIR;
|
|
88
96
|
dialect?: Dialect;
|
|
89
97
|
}): NormalizedSchema;
|
|
98
|
+
/** Refuse string storage that cannot preserve every enum label verbatim. */
|
|
99
|
+
export declare function assertStringEnumLabelsFit(params: {
|
|
100
|
+
field: FieldIR;
|
|
101
|
+
values: readonly string[];
|
|
102
|
+
dialect: Dialect;
|
|
103
|
+
table: string;
|
|
104
|
+
}): void;
|
|
90
105
|
/** Dialect-routed column type comparison key. */
|
|
91
106
|
export declare function columnTypeKeyFor(params: {
|
|
92
107
|
field: FieldIR;
|
|
@@ -99,10 +114,23 @@ export declare function defaultFingerprintFor(params: {
|
|
|
99
114
|
dialect: Dialect;
|
|
100
115
|
}): string | null;
|
|
101
116
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
117
|
+
* Comparison key for a partial-index predicate.
|
|
118
|
+
*
|
|
119
|
+
* The engines re-serialize these expressions on introspection (postgres adds
|
|
120
|
+
* parentheses around every operand, quotes identifiers and appends `::type`
|
|
121
|
+
* casts), so the key must absorb THAT and nothing else. Erasing quotes,
|
|
122
|
+
* parentheses and case wholesale (what this did before, F29) made
|
|
123
|
+
* `'ACTIVE'` equal to `'active'` and `(a OR b) AND c` equal to
|
|
124
|
+
* `a OR (b AND c)` — two different indexes comparing equal is a migration
|
|
125
|
+
* step that never gets generated.
|
|
126
|
+
*
|
|
127
|
+
* So: string literals keep their bytes; identifiers and keywords fold to lower
|
|
128
|
+
* case and lose their quoting; `::type` casts and REDUNDANT parentheses are
|
|
129
|
+
* dropped by parsing the boolean structure and re-emitting it with the minimum
|
|
130
|
+
* parenthesization, which keeps genuine grouping differences visible.
|
|
131
|
+
*
|
|
132
|
+
* A predicate this parser cannot read falls back to its token sequence — never
|
|
133
|
+
* to the old lossy key.
|
|
106
134
|
*/
|
|
107
135
|
export declare function normalizeWhere(params: {
|
|
108
136
|
where: string | undefined;
|
package/dist/normalize.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,OAAO,EACP,MAAM,EACN,OAAO,EAEP,OAAO,EACP,QAAQ,EACT,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"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"}
|
package/dist/postgres-types.d.ts
CHANGED
|
@@ -21,7 +21,10 @@ export declare function normalizeNativeType(params: {
|
|
|
21
21
|
/**
|
|
22
22
|
* Comparison key for a column's type. Two columns with equal keys need no
|
|
23
23
|
* ALTER. A native type equal to the scalar's canonical mapping is dropped, so
|
|
24
|
-
* `DateTime` and `DateTime @db.Timestamptz
|
|
24
|
+
* `DateTime` and `DateTime @db.Timestamptz` compare equal — and so do the
|
|
25
|
+
* mapping's `CANONICAL_EQUIVALENTS` (`@db.Timestamptz(6)`, the same type
|
|
26
|
+
* spelled explicitly, and `@db.Timestamptz(3)`, what the 2.0 alphas created).
|
|
27
|
+
* Any other precision stays distinct and still diffs.
|
|
25
28
|
*/
|
|
26
29
|
export declare function columnTypeKey(params: {
|
|
27
30
|
field: FieldIR;
|
|
@@ -62,6 +65,10 @@ export declare function defaultFingerprint(params: {
|
|
|
62
65
|
export declare function defaultSql(params: {
|
|
63
66
|
field: FieldIR;
|
|
64
67
|
}): string | undefined;
|
|
68
|
+
/** True for scalars whose defaults postgres reports back as numeric literals. */
|
|
69
|
+
export declare function isNumericScalar(params: {
|
|
70
|
+
type: ScalarType;
|
|
71
|
+
}): boolean;
|
|
65
72
|
/**
|
|
66
73
|
* `pg_constraint.confdeltype` / `confupdtype` single-char codes → IR actions
|
|
67
74
|
* (used by the introspector).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-types.d.ts","sourceRoot":"","sources":["../src/postgres-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAK1E,kDAAkD;AAClD,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAU7D,CAAC;AA+
|
|
1
|
+
{"version":3,"file":"postgres-types.d.ts","sourceRoot":"","sources":["../src/postgres-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAK1E,kDAAkD;AAClD,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAU7D,CAAC;AA+CF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAMnE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAmBhE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAMrF;AAID,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAsBhE;AAED,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAQpE;AAID;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAsC5E;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAuBzE;AAKD,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG,OAAO,CAGrE;AAID;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAM7E,CAAC;AAEF,uCAAuC;AACvC,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAMtE,CAAC;AAEF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE;IACtC,QAAQ,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC,QAAQ,EAAE,OAAO,CAAC;CACnB,GAAG,aAAa,CAGhB;AAED,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,aAAa,GAAG,SAAS,CAAA;CAAE,GAAG,aAAa,CAE9F;AAID,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAE/D"}
|
package/dist/push.d.ts
CHANGED
|
@@ -31,6 +31,12 @@ export declare function push(params: {
|
|
|
31
31
|
executor: SqlExecutor;
|
|
32
32
|
schema: SchemaIR;
|
|
33
33
|
acceptDataLoss?: boolean;
|
|
34
|
+
/** Separate authorization for removing or potentially widening native policies. */
|
|
35
|
+
acceptSecurityChanges?: boolean;
|
|
36
|
+
/** Deployed declaration when changing a policy or its referenced columns. */
|
|
37
|
+
previousSchema?: SchemaIR;
|
|
38
|
+
/** Return planned SQL and security changes without applying or requiring acknowledgements. */
|
|
39
|
+
dryRun?: boolean;
|
|
34
40
|
/** Configured extension instances — their artifacts apply with the diff. */
|
|
35
41
|
extensions?: readonly VibeExtension[];
|
|
36
42
|
}): Promise<PushResult>;
|
package/dist/push.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../src/push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../src/push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAqB,QAAQ,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAuB3F,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;;;;;;GASG;AACH,wBAAsB,IAAI,CAAC,MAAM,EAAE;IACjC,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,EAAE,QAAQ,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mFAAmF;IACnF,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,6EAA6E;IAC7E,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,8FAA8F;IAC9F,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CACvC,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBtB;AAiJD;;;GAGG;AACH,wBAAsB,IAAI,CAAC,MAAM,EAAE;IACjC,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAGpB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Establishing what actually happened, before a nontransactional migration
|
|
3
|
+
* re-runs anything.
|
|
4
|
+
*
|
|
5
|
+
* A migration that runs outside a transaction can die between a statement
|
|
6
|
+
* committing and the journal recording it. The only honest recovery is to ask
|
|
7
|
+
* the database what the world looks like now and compare it against the
|
|
8
|
+
* statement's DECLARED postcondition (execution.ts). Three answers exist:
|
|
9
|
+
*
|
|
10
|
+
* - `"satisfied"` — the live catalog already matches the declaration. Skip it.
|
|
11
|
+
* - `"runnable"` — the declaration is demonstrably not in effect, and running
|
|
12
|
+
* the statement is the way to get there.
|
|
13
|
+
* - a thrown `VibeError` — the state is neither, and no automatic action is
|
|
14
|
+
* safe. Nothing is dropped, nothing is re-run: the operator decides.
|
|
15
|
+
*
|
|
16
|
+
* There is deliberately NO fourth answer of the form "probably fine, re-run
|
|
17
|
+
* it". This module never claims exactly-once execution of arbitrary SQL; it
|
|
18
|
+
* only decides the cases a declared postcondition can actually settle.
|
|
19
|
+
*
|
|
20
|
+
* Comparison is conservative by design. Expressions must match verbatim apart
|
|
21
|
+
* from surrounding whitespace. Quotes and whitespace inside literals can change
|
|
22
|
+
* meaning; any difference is a CONFLICT — a false conflict costs an operator one
|
|
23
|
+
* look, a false match corrupts a schema.
|
|
24
|
+
*/
|
|
25
|
+
import type { Dialect } from "@vibeorm/schema";
|
|
26
|
+
import type { MigrationOperation } from "./execution.ts";
|
|
27
|
+
import type { SqlExecutor } from "./types.ts";
|
|
28
|
+
/** Whether a declared operation's postcondition already holds. */
|
|
29
|
+
export type OperationState = "satisfied" | "runnable";
|
|
30
|
+
/**
|
|
31
|
+
* Ask the database whether a declared operation is already in effect.
|
|
32
|
+
*
|
|
33
|
+
* PostgreSQL only: it is the one dialect with a nontransactional migration
|
|
34
|
+
* regime here, and every probe reads its catalogs.
|
|
35
|
+
*/
|
|
36
|
+
export declare function establishOperationState(params: {
|
|
37
|
+
executor: SqlExecutor;
|
|
38
|
+
dialect: Dialect;
|
|
39
|
+
operation: MigrationOperation;
|
|
40
|
+
}): Promise<OperationState>;
|
|
41
|
+
//# sourceMappingURL=recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../src/recovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAS/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,kEAAkE;AAClE,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,UAAU,CAAC;AA6BtD;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE;IACpD,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,kBAAkB,CAAC;CAC/B,GAAG,OAAO,CAAC,cAAc,CAAC,CAkG1B"}
|
package/dist/relations.d.ts
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Implicit many-to-many detection on Schema IR.
|
|
3
3
|
*
|
|
4
|
-
* ONE structural rule,
|
|
5
|
-
*
|
|
4
|
+
* ONE structural rule in @vibeorm/schema, also used by RLS validation and
|
|
5
|
+
* matching the parser's ambiguity rule (see LEARNINGS): two fields form an
|
|
6
6
|
* implicit M:N **iff** both are lists that declare no FK columns, they are
|
|
7
7
|
* distinct fields (self-exclusion — a 1:N self-relation must never pair with
|
|
8
|
-
* itself),
|
|
9
|
-
* the same name)
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* itself), their relation names match symmetrically (both unnamed, or both
|
|
9
|
+
* the same name), and each side is the OTHER'S SOLE counterpart under that
|
|
10
|
+
* name key. Detection never reads `relation.type`, because an introspected
|
|
11
|
+
* schema represents a real join table as two unnamed `oneToMany` list sides —
|
|
12
|
+
* trusting the type would break round-trip stability.
|
|
13
|
+
*
|
|
14
|
+
* The sole-counterpart requirement is the phantom-join-table fix, round two:
|
|
15
|
+
* two models holding foreign keys INTO EACH OTHER introspect as an unnamed
|
|
16
|
+
* fieldless list on each side (every FK synthesizes one on its target), and
|
|
17
|
+
* name-matching alone would marry those lists into a join table that exists
|
|
18
|
+
* nowhere. Counting EVERY relation under the name key — FK-owning sides
|
|
19
|
+
* included — disambiguates: the parser rejects the same shape as
|
|
20
|
+
* `ambiguous-relation` at parse time, so parsed and introspected schemas
|
|
21
|
+
* resolve identically.
|
|
12
22
|
*
|
|
13
23
|
* The join-table naming itself comes from the ONE shared convention in
|
|
14
24
|
* `@vibeorm/schema` (`implicitJoinTable`) — never re-derived here.
|
package/dist/relations.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../src/relations.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../src/relations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,iFAAiF;AACjF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,2DAA2D;AAC3D,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GAAG,eAAe,EAAE,CA4BtF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EXPLICIT physical renames.
|
|
3
|
+
*
|
|
4
|
+
* The differ deliberately has no rename detection: two schemas that differ by
|
|
5
|
+
* a name are indistinguishable from a drop plus a create, and guessing between
|
|
6
|
+
* them from "similar shapes" is how a migration tool silently destroys a
|
|
7
|
+
* column. A rename therefore only ever happens because someone WROTE one down,
|
|
8
|
+
* as an old physical name and a new physical name, and it is validated against
|
|
9
|
+
* both schemas before a single statement is rendered.
|
|
10
|
+
*
|
|
11
|
+
* `@map` / `@@map` remains the no-DDL option: mapping a model or field to the
|
|
12
|
+
* name the database already uses changes generated code only. Use a rename
|
|
13
|
+
* intent when the DATABASE object must actually move.
|
|
14
|
+
*
|
|
15
|
+
* What a physical rename preserves, on every dialect that supports it: the
|
|
16
|
+
* rows, the column defaults, the indexes and constraints attached to the
|
|
17
|
+
* object, and inbound foreign keys — the object keeps its identity, only its
|
|
18
|
+
* name changes. PostgreSQL policy expressions follow the rename too, because
|
|
19
|
+
* they are stored parsed and reference the object by identity, not by text.
|
|
20
|
+
*
|
|
21
|
+
* What refuses instead of guessing: renaming a table and one of its columns in
|
|
22
|
+
* the same plan (the second intent's table name is then ambiguous), an intent
|
|
23
|
+
* whose endpoints do not both check out against the two schemas, and two
|
|
24
|
+
* intents pointing at the same object.
|
|
25
|
+
*/
|
|
26
|
+
import type { Dialect, SchemaIR } from "@vibeorm/schema";
|
|
27
|
+
import type { MigrationStep } from "./types.ts";
|
|
28
|
+
/** One deliberately written rename, in PHYSICAL (database) names. */
|
|
29
|
+
export type RenameIntent = {
|
|
30
|
+
readonly kind: "table";
|
|
31
|
+
readonly from: string;
|
|
32
|
+
readonly to: string;
|
|
33
|
+
} | {
|
|
34
|
+
readonly kind: "column";
|
|
35
|
+
readonly table: string;
|
|
36
|
+
readonly from: string;
|
|
37
|
+
readonly to: string;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Validate rename intents against the two schemas and turn them into steps,
|
|
41
|
+
* returning the SOURCE schema rewritten as if the renames had happened.
|
|
42
|
+
*
|
|
43
|
+
* The rewrite is what keeps the rest of the diff honest: once the source model
|
|
44
|
+
* carries the new physical name, the ordinary differ sees one table on both
|
|
45
|
+
* sides and emits no drop/create pair for it. Only `dbName` moves — the
|
|
46
|
+
* logical IR graph (relations, index field lists) is untouched, so nothing
|
|
47
|
+
* downstream has to know a rename happened.
|
|
48
|
+
*/
|
|
49
|
+
export declare function planRenames(params: {
|
|
50
|
+
from: SchemaIR;
|
|
51
|
+
to: SchemaIR;
|
|
52
|
+
renames: readonly RenameIntent[];
|
|
53
|
+
dialect: Dialect;
|
|
54
|
+
}): {
|
|
55
|
+
readonly steps: readonly MigrationStep[];
|
|
56
|
+
readonly from: SchemaIR;
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=renames.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renames.d.ts","sourceRoot":"","sources":["../src/renames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAW,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,qEAAqE;AACrE,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAuBpG;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,QAAQ,CAAC;IACb,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;CAClB,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAkGxE"}
|
package/dist/runner.d.ts
CHANGED
|
@@ -2,21 +2,40 @@
|
|
|
2
2
|
* Migration runner: generate named migrations from IR diffs, apply them with
|
|
3
3
|
* bookkeeping in `_vibe_migrations`, report status, and repair records.
|
|
4
4
|
*
|
|
5
|
-
* Concurrency: `applyMigrations`
|
|
6
|
-
* `pg_advisory_lock(1447645253)` on postgres ("VIBE" in
|
|
7
|
-
* released in a finally), `GET_LOCK('vibeorm_migrate', 60)`
|
|
8
|
-
* VIBE_MIGRATION on timeout). sqlite needs none: it is
|
|
9
|
-
* `BEGIN` serializes. Locks are session-scoped — the
|
|
10
|
-
* (types.ts) requires one session for the whole
|
|
5
|
+
* Concurrency: `applyMigrations` and `rollbackMigration` take an advisory lock
|
|
6
|
+
* for the whole run — `pg_advisory_lock(1447645253)` on postgres ("VIBE" in
|
|
7
|
+
* ASCII, blocking, released in a finally), `GET_LOCK('vibeorm_migrate', 60)`
|
|
8
|
+
* on mysql (throws VIBE_MIGRATION on timeout). sqlite needs none: it is
|
|
9
|
+
* single-writer and `BEGIN` serializes. Locks are session-scoped — the
|
|
10
|
+
* SqlExecutor contract (types.ts) requires one session for the whole
|
|
11
|
+
* operation.
|
|
11
12
|
*
|
|
12
|
-
*
|
|
13
|
+
* Lock ORDER matters: the lock is taken BEFORE `ensureMigrationsTable`, never
|
|
14
|
+
* after. Two concurrent first-time runs against a fresh postgres database
|
|
15
|
+
* would otherwise both issue `CREATE TABLE IF NOT EXISTS _vibe_migrations`,
|
|
16
|
+
* which is a catalog race on postgres (a duplicate-key error on
|
|
17
|
+
* `pg_type_typname_nsp_index`, not a no-op). `migrationStatus` and
|
|
18
|
+
* `resolveMigration` deliberately take NO lock — wrapping reads in the
|
|
19
|
+
* migration lock would make `status` block behind a running migrate — so two
|
|
20
|
+
* concurrent FIRST-EVER `status`/`resolve` calls on a fresh database can still
|
|
21
|
+
* hit that race; retrying either is enough, since the table then exists.
|
|
22
|
+
*
|
|
23
|
+
* Execution strategy per dialect (`DIALECT_CAPABILITIES[dialect]`) AND per
|
|
24
|
+
* script:
|
|
13
25
|
*
|
|
14
26
|
* - transactionalDdl (postgres, sqlite): each migration runs inside
|
|
15
|
-
* BEGIN/COMMIT with its bookkeeping INSERT — atomic.
|
|
16
|
-
*
|
|
17
|
-
* (execute.ts `usesSelfManagedTransactions`)
|
|
18
|
-
*
|
|
19
|
-
*
|
|
27
|
+
* BEGIN/COMMIT with its bookkeeping INSERT — atomic.
|
|
28
|
+
* - EXCEPT sqlite scripts containing a table-rebuild block, which manage their
|
|
29
|
+
* own transactions (execute.ts `usesSelfManagedTransactions`) and therefore
|
|
30
|
+
* cannot be wrapped. Those take the SAME per-statement bookkeeping as mysql
|
|
31
|
+
* (below). They are NOT simply "re-runnable": a pure rebuild block is
|
|
32
|
+
* effectively idempotent, but any plain statement in the same script
|
|
33
|
+
* auto-commits on its own, so without a recorded statement_index a crash
|
|
34
|
+
* wedged the migration forever (every later run replayed statements that had
|
|
35
|
+
* already run). Resuming into a rebuild block rewinds to that block's
|
|
36
|
+
* `PRAGMA foreign_keys=OFF` (execute.ts `selfManagedResumeStart`): the block
|
|
37
|
+
* is transactional, so nothing of it survived, and the pragma is
|
|
38
|
+
* session-scoped and gone after a crash.
|
|
20
39
|
* - mysql (transactionalDdl: false — DDL auto-commits): the runner records
|
|
21
40
|
* PER-STATEMENT progress instead. The row is inserted up front
|
|
22
41
|
* (statement_index 0), advanced after every statement, and on failure the
|
|
@@ -26,22 +45,36 @@
|
|
|
26
45
|
* reaches the statement count (or its checksum is empty — resolveMigration
|
|
27
46
|
* records, which store statement_index 2147483647).
|
|
28
47
|
*
|
|
48
|
+
* `usesStatementBookkeeping` is the ONE predicate deciding which of the two
|
|
49
|
+
* regimes a (dialect, script) pair is in; apply, status and rollback all read
|
|
50
|
+
* it, so they can never disagree about whether a record is complete.
|
|
51
|
+
*
|
|
29
52
|
* Checksums (sha256 over the joined SQL) pin a migration's content:
|
|
30
53
|
* re-applying a renamed-or-edited migration is a VIBE_MIGRATION error, never
|
|
31
54
|
* a silent divergence.
|
|
32
55
|
*/
|
|
33
56
|
import type { Dialect, SchemaIR, VibeExtension } from "@vibeorm/schema";
|
|
34
|
-
import type {
|
|
35
|
-
|
|
36
|
-
|
|
57
|
+
import type { MigrationExecution } from "./execution.ts";
|
|
58
|
+
import type { RenameIntent } from "./renames.ts";
|
|
59
|
+
import type { AppliedResult, MigrationFile, MigrationStatus, RecordedMigration, SqlExecutor } from "./types.ts";
|
|
60
|
+
export { MIGRATIONS_TABLE_NAME } from "./journal-table.ts";
|
|
37
61
|
/** Create the bookkeeping table when missing. */
|
|
38
62
|
export declare function ensureMigrationsTable(params: {
|
|
39
63
|
executor: SqlExecutor;
|
|
40
64
|
dialect?: Dialect;
|
|
41
65
|
}): Promise<void>;
|
|
42
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* sha256 hex over the migration's statements — its identity across runs.
|
|
68
|
+
*
|
|
69
|
+
* A NON-default execution block (execution.ts) folds a canonical description
|
|
70
|
+
* of itself in, so changing how a migration executes after it was applied is
|
|
71
|
+
* caught by the same checksum refusal that catches changing its SQL. A default
|
|
72
|
+
* or absent block contributes NOTHING, which is what keeps every migration
|
|
73
|
+
* written before this feature — and every journal row recording one — valid.
|
|
74
|
+
*/
|
|
43
75
|
export declare function migrationChecksum(params: {
|
|
44
76
|
sql: readonly string[];
|
|
77
|
+
execution?: MigrationExecution;
|
|
45
78
|
}): string;
|
|
46
79
|
/**
|
|
47
80
|
* Diff two IRs and render a named migration for a dialect (postgres if
|
|
@@ -56,18 +89,24 @@ export declare function generateMigration(params: {
|
|
|
56
89
|
dialect?: Dialect;
|
|
57
90
|
/** Configured extension instances — their artifacts land in the migration. */
|
|
58
91
|
extensions?: readonly VibeExtension[];
|
|
92
|
+
/** Explicit physical renames (renames.ts); never inferred from the diff. */
|
|
93
|
+
renames?: readonly RenameIntent[];
|
|
94
|
+
/** Explicit execution semantics for the generated file. */
|
|
95
|
+
execution?: MigrationExecution;
|
|
59
96
|
}): MigrationFile;
|
|
60
97
|
/**
|
|
61
98
|
* Apply migrations in order under an advisory lock (see module doc).
|
|
62
99
|
* Already-recorded migrations are checksum-verified and skipped; a mismatch
|
|
63
100
|
* throws VIBE_MIGRATION (a recorded migration whose SQL changed is
|
|
64
|
-
* corruption, not drift to paper over).
|
|
101
|
+
* corruption, not drift to paper over). Where progress is recorded per
|
|
102
|
+
* statement (mysql, and self-managed sqlite scripts), a partially-applied
|
|
65
103
|
* migration RESUMES from its recorded statement_index. Records created by
|
|
66
104
|
* `resolveMigration` (empty checksum) skip verification.
|
|
67
105
|
*/
|
|
68
106
|
export declare function applyMigrations(params: {
|
|
69
107
|
executor: SqlExecutor;
|
|
70
108
|
migrations: readonly MigrationFile[];
|
|
109
|
+
acceptSecurityChanges?: boolean;
|
|
71
110
|
/** Execution dialect; postgres if omitted. */
|
|
72
111
|
dialect?: Dialect;
|
|
73
112
|
}): Promise<AppliedResult>;
|
|
@@ -77,7 +116,26 @@ export declare function migrationStatus(params: {
|
|
|
77
116
|
migrations: readonly MigrationFile[];
|
|
78
117
|
/** Bookkeeping dialect; postgres if omitted. */
|
|
79
118
|
dialect?: Dialect;
|
|
119
|
+
/** Trusted current deployment; policy state is verified independently of migration records. */
|
|
120
|
+
schema?: SchemaIR;
|
|
80
121
|
}): Promise<MigrationStatus>;
|
|
122
|
+
/**
|
|
123
|
+
* The bookkeeping journal itself, in the order rows were written — i.e. the
|
|
124
|
+
* order migrations were actually applied, which is what a rollback must walk
|
|
125
|
+
* backwards. Every row is returned and classified, including the ones
|
|
126
|
+
* `migrationStatus` folds away: a mismatched record, a partially applied one
|
|
127
|
+
* and a record whose file is gone all still occupy a position in history, and
|
|
128
|
+
* a caller that skips them rolls back the WRONG migration (F28).
|
|
129
|
+
*
|
|
130
|
+
* Takes no lock, exactly like `migrationStatus`.
|
|
131
|
+
*/
|
|
132
|
+
export declare function recordedMigrations(params: {
|
|
133
|
+
executor: SqlExecutor;
|
|
134
|
+
/** Known migration files — classification needs their SQL. */
|
|
135
|
+
migrations: readonly MigrationFile[];
|
|
136
|
+
/** Bookkeeping dialect; postgres if omitted. */
|
|
137
|
+
dialect?: Dialect;
|
|
138
|
+
}): Promise<RecordedMigration[]>;
|
|
81
139
|
/**
|
|
82
140
|
* Repair the bookkeeping table without running SQL: mark a migration as
|
|
83
141
|
* `"applied"` (upsert its record; pass `checksum` to also pin its content —
|
|
@@ -101,19 +159,22 @@ export declare function resolveMigration(params: {
|
|
|
101
159
|
* the record pins a checksum — its up SQL must still match (rolling back with
|
|
102
160
|
* drifted files would run a down that no longer mirrors what was applied).
|
|
103
161
|
*
|
|
104
|
-
* Dialect behavior mirrors apply
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
162
|
+
* Dialect behavior mirrors apply exactly (same `usesStatementBookkeeping`
|
|
163
|
+
* predicate, read over the DOWN script): postgres/sqlite run the down inside
|
|
164
|
+
* BEGIN/COMMIT with the bookkeeping DELETE (atomic). mysql DDL auto-commits,
|
|
165
|
+
* and a sqlite down containing a table-rebuild block cannot be wrapped, so
|
|
166
|
+
* both record progress per-statement in the existing `statement_index`
|
|
167
|
+
* column, NEGATIVE to mark the rollback direction: after k down statements,
|
|
168
|
+
* the row stores -(k+1). A failed rollback resumes from the recorded
|
|
169
|
+
* statement on the next call; `applyMigrations` refuses a mid-rollback record
|
|
170
|
+
* (that check reads the sign only, so it holds for every dialect). A
|
|
171
|
+
* partially APPLIED migration cannot be rolled back — its down mirrors the
|
|
172
|
+
* full up; finish applying (apply resumes) or repair with `resolveMigration`.
|
|
113
173
|
*/
|
|
114
174
|
export declare function rollbackMigration(params: {
|
|
115
175
|
executor: SqlExecutor;
|
|
116
176
|
migration: MigrationFile;
|
|
177
|
+
acceptSecurityChanges?: boolean;
|
|
117
178
|
/** Execution dialect; postgres if omitted. */
|
|
118
179
|
dialect?: Dialect;
|
|
119
180
|
}): Promise<void>;
|