@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.
Files changed (51) hide show
  1. package/dist/ddl/mysql.d.ts.map +1 -1
  2. package/dist/ddl/postgres.d.ts.map +1 -1
  3. package/dist/ddl/render.d.ts.map +1 -1
  4. package/dist/ddl/rls.d.ts +40 -0
  5. package/dist/ddl/rls.d.ts.map +1 -0
  6. package/dist/ddl/sqlite.d.ts +18 -1
  7. package/dist/ddl/sqlite.d.ts.map +1 -1
  8. package/dist/differ.d.ts +8 -0
  9. package/dist/differ.d.ts.map +1 -1
  10. package/dist/down.d.ts +2 -0
  11. package/dist/down.d.ts.map +1 -1
  12. package/dist/enum-values.d.ts +14 -1
  13. package/dist/enum-values.d.ts.map +1 -1
  14. package/dist/execute.d.ts +84 -1
  15. package/dist/execute.d.ts.map +1 -1
  16. package/dist/execution.d.ts +168 -0
  17. package/dist/execution.d.ts.map +1 -0
  18. package/dist/index.d.ts +8 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +3697 -1822
  21. package/dist/index.js.map +29 -23
  22. package/dist/introspect/mysql.d.ts.map +1 -1
  23. package/dist/introspect/postgres-rls.d.ts +41 -0
  24. package/dist/introspect/postgres-rls.d.ts.map +1 -0
  25. package/dist/introspect/postgres.d.ts +5 -18
  26. package/dist/introspect/postgres.d.ts.map +1 -1
  27. package/dist/introspect/shared.d.ts +8 -1
  28. package/dist/introspect/shared.d.ts.map +1 -1
  29. package/dist/introspect/sqlite.d.ts.map +1 -1
  30. package/dist/journal-table.d.ts +15 -0
  31. package/dist/journal-table.d.ts.map +1 -0
  32. package/dist/mysql-types.d.ts.map +1 -1
  33. package/dist/normalize.d.ts +32 -4
  34. package/dist/normalize.d.ts.map +1 -1
  35. package/dist/postgres-types.d.ts +8 -1
  36. package/dist/postgres-types.d.ts.map +1 -1
  37. package/dist/push.d.ts +6 -0
  38. package/dist/push.d.ts.map +1 -1
  39. package/dist/recovery.d.ts +41 -0
  40. package/dist/recovery.d.ts.map +1 -0
  41. package/dist/relations.d.ts +16 -6
  42. package/dist/relations.d.ts.map +1 -1
  43. package/dist/renames.d.ts +58 -0
  44. package/dist/renames.d.ts.map +1 -0
  45. package/dist/runner.d.ts +87 -26
  46. package/dist/runner.d.ts.map +1 -1
  47. package/dist/sqlite-types.d.ts +14 -0
  48. package/dist/sqlite-types.d.ts.map +1 -1
  49. package/dist/types.d.ts +114 -2
  50. package/dist/types.d.ts.map +1 -1
  51. 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,EASV,QAAQ,EACT,MAAM,iBAAiB,CAAC;AASzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA0G/C,uEAAuE;AACvE,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,WAAW,CAAA;CAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CA0K1F"}
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":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAQV,QAAQ,EACT,MAAM,iBAAiB,CAAC;AASzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA4J/C,gFAAgF;AAChF,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,WAAW,CAAA;CAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwK7F"}
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;;;;;;;;;;;;;GAaG;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;CACzB,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,CAsCP;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;AAwDD,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD"}
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,CAwH3F;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"}
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;AAGH,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"}
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"}
@@ -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
- * Partial-index predicates are compared loosely: postgres re-serializes the
103
- * expression (extra parentheses, quoted identifiers), so the comparison key
104
- * strips quoting, parentheses, whitespace and case. `::type` casts postgres
105
- * adds during normalization (e.g. `'x'::text`) are stripped too.
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;
@@ -1 +1 @@
1
- {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"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"}
@@ -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(3)` compare equal.
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+BF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAMnE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAgBhE;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,CA2B5E;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAuBzE;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"}
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>;
@@ -1 +1 @@
1
- {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../src/push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAoBxE,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,4EAA4E;IAC5E,UAAU,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CACvC,GAAG,OAAO,CAAC,UAAU,CAAC,CA8EtB;AAED;;;GAGG;AACH,wBAAsB,IAAI,CAAC,MAAM,EAAE;IACjC,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAEpB"}
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"}
@@ -1,14 +1,24 @@
1
1
  /**
2
2
  * Implicit many-to-many detection on Schema IR.
3
3
  *
4
- * ONE structural rule, kept in lock-step with the parser's
5
- * `findImplicitM2MCounterpart` (see LEARNINGS): two relation fields form an
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), and their relation names match symmetrically (both unnamed, or both
9
- * the same name). Detection never reads `relation.type`, because an
10
- * introspected schema represents a real join table as two unnamed `oneToMany`
11
- * list sides — trusting the type would break round-trip stability.
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.
@@ -1 +1 @@
1
- {"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../src/relations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAuB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAErE,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,CA2CtF"}
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` 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.
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
- * Execution strategy per dialect (`DIALECT_CAPABILITIES[dialect]`):
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. 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.
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 { 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;
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
- /** sha256 hex over the migration's statements — its identity across runs. */
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). On mysql, a partially-applied
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: 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`.
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>;