@metaobjectsdev/migrate-ts 1.0.1 → 1.0.3
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/diff/index.d.ts +2 -1
- package/dist/diff/index.d.ts.map +1 -1
- package/dist/diff/index.js +18 -4
- package/dist/diff/index.js.map +1 -1
- package/dist/diff/status.d.ts.map +1 -1
- package/dist/diff/status.js +25 -13
- package/dist/diff/status.js.map +1 -1
- package/dist/drift/drift.d.ts +19 -0
- package/dist/drift/drift.d.ts.map +1 -1
- package/dist/drift/drift.js +2 -1
- package/dist/drift/drift.js.map +1 -1
- package/dist/emit/postgres.d.ts.map +1 -1
- package/dist/emit/postgres.js +130 -4
- package/dist/emit/postgres.js.map +1 -1
- package/dist/errors.d.ts +8 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +24 -9
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pg-identity-default.d.ts +6 -0
- package/dist/pg-identity-default.d.ts.map +1 -1
- package/dist/pg-identity-default.js +7 -0
- package/dist/pg-identity-default.js.map +1 -1
- package/dist/scope.d.ts +36 -8
- package/dist/scope.d.ts.map +1 -1
- package/dist/scope.js +71 -19
- package/dist/scope.js.map +1 -1
- package/dist/snapshot/plan.d.ts +14 -1
- package/dist/snapshot/plan.d.ts.map +1 -1
- package/dist/snapshot/plan.js +8 -2
- package/dist/snapshot/plan.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/diff/index.ts +15 -4
- package/src/diff/status.ts +28 -15
- package/src/drift/drift.ts +21 -0
- package/src/emit/postgres.ts +158 -4
- package/src/errors.ts +26 -10
- package/src/index.ts +1 -1
- package/src/pg-identity-default.ts +10 -0
- package/src/scope.ts +93 -18
- package/src/snapshot/plan.ts +22 -2
- package/src/types.ts +9 -1
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAO7C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,8EAA8E;IAC9E,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB;;;OAGG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,QAAQ,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAChC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;OAeG;IACH,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;CAC/C;AAED,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;AAEzE,oDAAoD;AACpD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wFAAwF;AACxF,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,OAAO,EAAE,GAAG,GAAG,GAAG,CAAC;IACnB;;;;;OAKG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC1C;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC1C;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B;AAMD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,MAAM,GACd;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACvF;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACvG;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACzF;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACtG;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACzH;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACzG;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAC3E,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/migrate-ts",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Schema migration tooling for MetaObjects: diff metadata vs DB and emit SQL for Postgres and SQLite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@iarna/toml": "^2.2.5",
|
|
48
|
-
"@metaobjectsdev/metadata": "1.0.
|
|
48
|
+
"@metaobjectsdev/metadata": "1.0.3"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"kysely": ">=0.27.0 <0.30.0",
|
package/src/diff/index.ts
CHANGED
|
@@ -380,11 +380,15 @@ function diffTableColumns(
|
|
|
380
380
|
// dialect-aware: SQLite/D1 cannot physically represent a VARCHAR length or a
|
|
381
381
|
// native json type, so those distinctions must not read as drift (see
|
|
382
382
|
// canonTypeForDialect). Postgres stays exact.
|
|
383
|
+
// A type change CARRIES the column's default change (fromDefault/toDefault, types.ts),
|
|
384
|
+
// filled in below once the identity rule has decided what the default should be.
|
|
385
|
+
let typeChange: Extract<Change, { kind: "change-column-type" }> | undefined;
|
|
383
386
|
if (!sqlTypeEqualsForDialect(ec.sqlType, ac.sqlType, dialect)) {
|
|
384
|
-
|
|
387
|
+
typeChange = {
|
|
385
388
|
kind: "change-column-type", table, ...sx, column: name,
|
|
386
389
|
from: ac.sqlType, to: ec.sqlType, status: ALLOWED,
|
|
387
|
-
}
|
|
390
|
+
};
|
|
391
|
+
changes.push(typeChange);
|
|
388
392
|
}
|
|
389
393
|
if (ec.nullable !== ac.nullable) {
|
|
390
394
|
changes.push({
|
|
@@ -420,7 +424,14 @@ function diffTableColumns(
|
|
|
420
424
|
ac.default !== undefined && ac.default.kind === "expr" && isPgAutoSequenceDefault(ac.default.value);
|
|
421
425
|
const skipIdentityDefaultDiff =
|
|
422
426
|
ec.identity === "uuid" || (ec.identity === "increment" && liveIsAutoSequenceDefault);
|
|
423
|
-
if (
|
|
427
|
+
if (typeChange) {
|
|
428
|
+
// An identity default the diff deliberately never compares is KEPT: the emitter drops
|
|
429
|
+
// and re-sets a default around a converting type change, so leaving `toDefault` unset
|
|
430
|
+
// here would drop it for good.
|
|
431
|
+
const toDefault = skipIdentityDefaultDiff ? ac.default : ec.default;
|
|
432
|
+
if (ac.default !== undefined) typeChange.fromDefault = ac.default;
|
|
433
|
+
if (toDefault !== undefined) typeChange.toDefault = toDefault;
|
|
434
|
+
} else if (!skipIdentityDefaultDiff && !columnDefaultsEqual(ec.default, ac.default)) {
|
|
424
435
|
const change: Change = {
|
|
425
436
|
kind: "change-column-default", table, ...sx, column: name,
|
|
426
437
|
status: ALLOWED,
|
|
@@ -830,7 +841,7 @@ function recreateViewsDependingOnChangedTables(
|
|
|
830
841
|
}
|
|
831
842
|
}
|
|
832
843
|
|
|
833
|
-
function columnDefaultsEqual(a: ColumnDescriptor["default"], b: ColumnDescriptor["default"]): boolean {
|
|
844
|
+
export function columnDefaultsEqual(a: ColumnDescriptor["default"], b: ColumnDescriptor["default"]): boolean {
|
|
834
845
|
if (a === undefined && b === undefined) return true;
|
|
835
846
|
if (a === undefined || b === undefined) return false;
|
|
836
847
|
return a.kind === b.kind && a.value === b.value;
|
package/src/diff/status.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Change, AllowOptions } from "../types.js";
|
|
1
|
+
import type { Change, AllowOptions, ColumnDefault } from "../types.js";
|
|
2
2
|
import { isWidening } from "../sql-type.js";
|
|
3
|
-
import {
|
|
3
|
+
import { dropsAutoSequenceDefault } from "../pg-identity-default.js";
|
|
4
4
|
import { DEFAULT_DB_SCHEMA_POSTGRES } from "@metaobjectsdev/metadata";
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -101,9 +101,14 @@ function blockedReasonFor(
|
|
|
101
101
|
}
|
|
102
102
|
return null;
|
|
103
103
|
|
|
104
|
-
case "change-column-type":
|
|
104
|
+
case "change-column-type": {
|
|
105
|
+
// A type change carries its column's default change (types.ts), so the one gated
|
|
106
|
+
// default shape (see change-column-default below) is gated here as well.
|
|
107
|
+
const refusal = autoSequenceDropRefusal(c.table, c.column, c.fromDefault, c.toDefault, allow);
|
|
108
|
+
if (refusal !== null) return refusal;
|
|
105
109
|
if (isWidening(c.from, c.to)) return null; // widening always allowed
|
|
106
110
|
return allow.typeChange ? null : "lossy type change (pass allow.typeChange)";
|
|
111
|
+
}
|
|
107
112
|
|
|
108
113
|
case "change-column-nullable":
|
|
109
114
|
// from = actual.nullable, to = expected.nullable
|
|
@@ -129,18 +134,7 @@ function blockedReasonFor(
|
|
|
129
134
|
// than guess. Anything else about change-column-default — including
|
|
130
135
|
// dropping a plain literal default — falls through to the unconditional
|
|
131
136
|
// `return null` below.
|
|
132
|
-
|
|
133
|
-
c.to === undefined && c.from?.kind === "expr" && isPgAutoSequenceDefault(c.from.value);
|
|
134
|
-
if (droppingAutoSequence && !allow.dropIdentityDefault) {
|
|
135
|
-
return `column "${c.table}"."${c.column}" has a live Postgres auto-increment default `
|
|
136
|
-
+ `(${c.from!.value}) but its metadata declares no @generation — this is ambiguous: it `
|
|
137
|
-
+ `could mean @generation was never declared, or that auto-increment is being removed on `
|
|
138
|
-
+ `purpose. Dropping the default is destructive (every insert that omits the column starts `
|
|
139
|
-
+ `failing), so this refuses rather than guessing. Declare @generation: increment on the `
|
|
140
|
-
+ `identity to keep the sequence, or pass --allow drop-identity-default if removing it is `
|
|
141
|
-
+ `intentional`;
|
|
142
|
-
}
|
|
143
|
-
return null;
|
|
137
|
+
return autoSequenceDropRefusal(c.table, c.column, c.from, c.to, allow);
|
|
144
138
|
}
|
|
145
139
|
|
|
146
140
|
// Always-allowed kinds
|
|
@@ -155,3 +149,22 @@ function blockedReasonFor(
|
|
|
155
149
|
return null;
|
|
156
150
|
}
|
|
157
151
|
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Dropping a live Postgres auto-sequence default (`nextval(...)`) while the metadata declares
|
|
155
|
+
* no identity is ambiguous, so it is refused unless allowed. Shared by `change-column-default`
|
|
156
|
+
* and `change-column-type`, which carries its column's default change.
|
|
157
|
+
*/
|
|
158
|
+
function autoSequenceDropRefusal(
|
|
159
|
+
table: string, column: string, from: ColumnDefault | undefined, to: ColumnDefault | undefined,
|
|
160
|
+
allow: { dropIdentityDefault?: boolean },
|
|
161
|
+
): string | null {
|
|
162
|
+
if (!dropsAutoSequenceDefault(from, to) || allow.dropIdentityDefault) return null;
|
|
163
|
+
return `column "${table}"."${column}" has a live Postgres auto-increment default `
|
|
164
|
+
+ `(${from!.value}) but its metadata declares no @generation — this is ambiguous: it `
|
|
165
|
+
+ `could mean @generation was never declared, or that auto-increment is being removed on `
|
|
166
|
+
+ `purpose. Dropping the default is destructive (every insert that omits the column starts `
|
|
167
|
+
+ `failing), so this refuses rather than guessing. Declare @generation: increment on the `
|
|
168
|
+
+ `identity to keep the sequence, or pass --allow drop-identity-default if removing it is `
|
|
169
|
+
+ `intentional`;
|
|
170
|
+
}
|
package/src/drift/drift.ts
CHANGED
|
@@ -58,6 +58,18 @@ export interface ComputeDriftOptions {
|
|
|
58
58
|
* failing on tables migrate does not own is incoherent.
|
|
59
59
|
*/
|
|
60
60
|
inScope?: ObjectScopePredicate;
|
|
61
|
+
/**
|
|
62
|
+
* FR-023 — objects a DEPENDENCY owns. Such an object is loaded so this project's own
|
|
63
|
+
* model can resolve against it and is governed by nobody here unless `inScope`
|
|
64
|
+
* admits it: it leaves the expected side, is suppressed on the actual side, and —
|
|
65
|
+
* unlike an `inScope` exclusion — takes the publisher's database schema out of the
|
|
66
|
+
* run's scope with it, so a table the publisher never exported is not reported as an
|
|
67
|
+
* extra table in a schema this project does not manage (migrate-ts `scope.ts`).
|
|
68
|
+
*
|
|
69
|
+
* `verify --db` and `migrate` share this declaration for the same reason they share
|
|
70
|
+
* `inScope`. Omit for a project with no dependencies (unchanged behavior).
|
|
71
|
+
*/
|
|
72
|
+
imported?: ObjectScopePredicate;
|
|
61
73
|
}
|
|
62
74
|
|
|
63
75
|
export interface DriftResult extends DiffResult {
|
|
@@ -77,6 +89,13 @@ export interface DriftResult extends DiffResult {
|
|
|
77
89
|
* `GovernedScope`, which is what `excludeFromSnapshot` takes.
|
|
78
90
|
*/
|
|
79
91
|
declaredSchemas: readonly string[] | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* The subset of `outOfScope` a DEPENDENCY contributed (FR-023). Reported for the
|
|
94
|
+
* same reason `declaredSchemas` is: so the caller states WHY an object was left out
|
|
95
|
+
* without re-deriving the decision from a second expected-schema build, which could
|
|
96
|
+
* come to disagree with the one this comparison actually made.
|
|
97
|
+
*/
|
|
98
|
+
importedOutOfScope: readonly string[] | undefined;
|
|
80
99
|
}
|
|
81
100
|
|
|
82
101
|
/**
|
|
@@ -106,6 +125,7 @@ export async function computeDriftFromActual(
|
|
|
106
125
|
...(opts?.views !== undefined ? { views: opts.views } : {}),
|
|
107
126
|
}),
|
|
108
127
|
opts?.inScope,
|
|
128
|
+
opts?.imported !== undefined ? { imported: opts.imported } : undefined,
|
|
109
129
|
);
|
|
110
130
|
const result = await diff({
|
|
111
131
|
// The three scoped-diff obligations as one value (see scope.ts's header):
|
|
@@ -122,6 +142,7 @@ export async function computeDriftFromActual(
|
|
|
122
142
|
...result,
|
|
123
143
|
outOfScope: scoped.outOfScope,
|
|
124
144
|
declaredSchemas: scoped.declaredSchemas,
|
|
145
|
+
importedOutOfScope: scoped.importedOutOfScope,
|
|
125
146
|
};
|
|
126
147
|
}
|
|
127
148
|
|
package/src/emit/postgres.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { SqlType } from "../sql-type.js";
|
|
|
6
6
|
import { DEFAULT_DB_SCHEMA_POSTGRES } from "@metaobjectsdev/metadata";
|
|
7
7
|
import { renderFingerprintMarker, viewFingerprint } from "../view-fingerprint.js";
|
|
8
8
|
import { viewReplaceIsLegal } from "../view-column-types.js";
|
|
9
|
+
import { columnDefaultsEqual } from "../diff/index.js";
|
|
9
10
|
|
|
10
11
|
// Stages run low → high. drop-view runs BEFORE drop-table so a view that
|
|
11
12
|
// depends on a soon-to-be-dropped table is removed first. create-view runs
|
|
@@ -53,9 +54,17 @@ export function renderPostgres(changes: Change[]): EmitResult {
|
|
|
53
54
|
downStmts.push(renderDown(c));
|
|
54
55
|
}
|
|
55
56
|
// Down runs in reverse order (so creates undo correctly w.r.t. FKs).
|
|
57
|
+
const upHelpers = conversionHelpers(sorted, "up");
|
|
58
|
+
const downHelpers = conversionHelpers(sorted, "down");
|
|
56
59
|
return {
|
|
57
|
-
up: [
|
|
58
|
-
|
|
60
|
+
up: [
|
|
61
|
+
...createSchemaStmts(sorted), ...upHelpers.map(createHelper),
|
|
62
|
+
...upStmts, ...upHelpers.map(dropHelper),
|
|
63
|
+
].join("\n\n"),
|
|
64
|
+
down: [
|
|
65
|
+
...downHelpers.map(createHelper),
|
|
66
|
+
...[...downStmts].reverse(), ...downHelpers.map(dropHelper),
|
|
67
|
+
].join("\n\n"),
|
|
59
68
|
recreatedTables: new Set(), // postgres alters in place; no recreate-and-copy
|
|
60
69
|
};
|
|
61
70
|
}
|
|
@@ -109,7 +118,7 @@ function renderUp(c: Change): string {
|
|
|
109
118
|
}
|
|
110
119
|
case "drop-column": return `ALTER TABLE ${quoteQualified(c.table, c.schema)} DROP COLUMN ${quote(c.column)};`;
|
|
111
120
|
case "rename-column": return `ALTER TABLE ${quoteQualified(c.table, c.schema)} RENAME COLUMN ${quote(c.from)} TO ${quote(c.to)};`;
|
|
112
|
-
case "change-column-type": return
|
|
121
|
+
case "change-column-type": return renderAlterColumnType(c, c.from, c.to, c.fromDefault, c.toDefault);
|
|
113
122
|
case "change-column-nullable":
|
|
114
123
|
return c.to
|
|
115
124
|
? `ALTER TABLE ${quoteQualified(c.table, c.schema)} ALTER COLUMN ${quote(c.column)} DROP NOT NULL;`
|
|
@@ -191,7 +200,7 @@ function renderDown(c: Change): string {
|
|
|
191
200
|
? `ALTER TABLE ${quoteQualified(c.table, c.schema)} ADD COLUMN ${renderColumn(c.restore)};\n-- NOTE: column data is not restored by this down migration.`
|
|
192
201
|
: `-- WARNING: down migration cannot restore data\n-- TODO: re-add dropped column "${c.column}" manually with original type/nullable/default`;
|
|
193
202
|
case "rename-column": return `ALTER TABLE ${quoteQualified(c.table, c.schema)} RENAME COLUMN ${quote(c.to)} TO ${quote(c.from)};`;
|
|
194
|
-
case "change-column-type": return
|
|
203
|
+
case "change-column-type": return renderAlterColumnType(c, c.to, c.from, c.toDefault, c.fromDefault);
|
|
195
204
|
case "change-column-nullable":
|
|
196
205
|
return c.from
|
|
197
206
|
? `ALTER TABLE ${quoteQualified(c.table, c.schema)} ALTER COLUMN ${quote(c.column)} DROP NOT NULL;`
|
|
@@ -356,6 +365,151 @@ function fkActionSql(a: FkAction): string {
|
|
|
356
365
|
}
|
|
357
366
|
}
|
|
358
367
|
|
|
368
|
+
type ColumnTypeChange = Extract<Change, { kind: "change-column-type" }>;
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* `ALTER COLUMN … TYPE`, with the `USING` clause the conversion needs.
|
|
372
|
+
*
|
|
373
|
+
* Postgres changes a column's type in place only along an ASSIGNMENT cast. Many cross-kind
|
|
374
|
+
* changes have none (jsonb → text[], text[] → jsonb, text → text[], boolean → integer), and the
|
|
375
|
+
* bare ALTER is refused ("cannot be cast automatically"), so a migration `meta migrate` wrote
|
|
376
|
+
* could not be applied by anything. {@link conversion} names each one.
|
|
377
|
+
*
|
|
378
|
+
* A DEFAULT is converted by an assignment cast too, and never through USING, so a default in
|
|
379
|
+
* the way of a converting change is dropped first and set again after. The change carries both
|
|
380
|
+
* defaults for exactly this (types.ts).
|
|
381
|
+
*/
|
|
382
|
+
function renderAlterColumnType(
|
|
383
|
+
c: ColumnTypeChange, from: SqlType, to: SqlType,
|
|
384
|
+
fromDefault: ColumnDefault | undefined, toDefault: ColumnDefault | undefined,
|
|
385
|
+
): string {
|
|
386
|
+
const col = quote(c.column);
|
|
387
|
+
const alterColumn = `ALTER TABLE ${quoteQualified(c.table, c.schema)} ALTER COLUMN ${col}`;
|
|
388
|
+
const { using } = conversion(col, from, to, c.schema);
|
|
389
|
+
const alterType = `${alterColumn} TYPE ${pgType(to)}${using};`;
|
|
390
|
+
if (using === "" && columnDefaultsEqual(fromDefault, toDefault)) return alterType;
|
|
391
|
+
return [
|
|
392
|
+
...(fromDefault !== undefined ? [`${alterColumn} DROP DEFAULT;`] : []),
|
|
393
|
+
alterType,
|
|
394
|
+
...(toDefault !== undefined ? [`${alterColumn} SET DEFAULT ${renderDefault(toDefault)};`] : []),
|
|
395
|
+
].join("\n");
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* The `USING` clause for a change (`""` when the assignment cast a bare ALTER uses is right),
|
|
400
|
+
* and the helper function it calls, if any.
|
|
401
|
+
*
|
|
402
|
+
* - jsonb → T[]: a subquery is not allowed in USING, so the rows are unpacked by a helper. It
|
|
403
|
+
* keeps element order, maps a JSON `null` to NULL, and RAISES on a scalar or an object.
|
|
404
|
+
* - T[] → jsonb: `to_jsonb`, since no cast from an array to jsonb exists.
|
|
405
|
+
* - scalar → T[]: the value becomes the array's one element. An explicit `::T[]` would PARSE the
|
|
406
|
+
* text as an array literal instead ('{a,b}' → two elements, 'hello' → an error).
|
|
407
|
+
* - T[] → scalar: the one element a row holds, through a helper that RAISES on a row holding
|
|
408
|
+
* more. Neither alternative is safe: `c[1]` silently keeps the first element, and the bare
|
|
409
|
+
* assignment cast to text stores the array literal '{a,b}' as the value.
|
|
410
|
+
* - anything else cross-kind: an explicit cast, which is the assignment cast where one exists
|
|
411
|
+
* and the only cast where it does not.
|
|
412
|
+
*/
|
|
413
|
+
function conversion(
|
|
414
|
+
col: string, from: SqlType, to: SqlType, schema: string | undefined,
|
|
415
|
+
): { using: string; helper?: ConversionHelper } {
|
|
416
|
+
if (from.kind === "json" && to.kind === "array") {
|
|
417
|
+
const helper = JSONB_ARRAY_TO_TEXT_ARRAY;
|
|
418
|
+
return { using: ` USING ${helperCall(helper, col, schema)}${castIfNeeded(TEXT_ARRAY, to)}`, helper };
|
|
419
|
+
}
|
|
420
|
+
if (from.kind === "array" && to.kind === "json") return { using: ` USING to_jsonb(${col})` };
|
|
421
|
+
if (from.kind !== "array" && to.kind === "array") {
|
|
422
|
+
return {
|
|
423
|
+
using: ` USING (CASE WHEN ${col} IS NULL THEN NULL ELSE ARRAY[${col}] END)`
|
|
424
|
+
+ castIfNeeded({ kind: "array", element: from }, to),
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
if (from.kind === "array" && to.kind !== "array") {
|
|
428
|
+
const helper = ARRAY_TO_SCALAR;
|
|
429
|
+
return { using: ` USING ${helperCall(helper, col, schema)}${castIfNeeded(from.element, to)}`, helper };
|
|
430
|
+
}
|
|
431
|
+
const cast = castIfNeeded(from, to);
|
|
432
|
+
return { using: cast === "" ? "" : ` USING ${col}${cast}` };
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* `::T` when a value of `from` has no assignment cast to `to`. A change TO text never needs one,
|
|
437
|
+
* since every type has an assignment cast to text, and must not get one: an explicit cast to
|
|
438
|
+
* VARCHAR(n) TRUNCATES an over-length value that the assignment cast refuses.
|
|
439
|
+
*/
|
|
440
|
+
function castIfNeeded(from: SqlType, to: SqlType): string {
|
|
441
|
+
return needsExplicitCast(from, to) ? `::${pgType(to)}` : "";
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function needsExplicitCast(from: SqlType, to: SqlType): boolean {
|
|
445
|
+
if (to.kind === "text") return false;
|
|
446
|
+
if (from.kind !== to.kind) return true;
|
|
447
|
+
if (from.kind === "array" && to.kind === "array") return needsExplicitCast(from.element, to.element);
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const TEXT_ARRAY: SqlType = { kind: "array", element: { kind: "text" } };
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* A function a conversion calls. It is an ordinary function created in the table's schema
|
|
455
|
+
* before the ALTERs and dropped at the end of the same file, not a `pg_temp` one: a database
|
|
456
|
+
* that revokes TEMP from PUBLIC (a common hardening step) refuses pg_temp, while CREATE on the
|
|
457
|
+
* schema is a privilege the migration already needs for its tables.
|
|
458
|
+
*/
|
|
459
|
+
interface ConversionHelper {
|
|
460
|
+
readonly name: string;
|
|
461
|
+
/** Parameter list, return type and language, as written after the function name. */
|
|
462
|
+
readonly signature: string;
|
|
463
|
+
/** Argument types, as `DROP FUNCTION` needs them. */
|
|
464
|
+
readonly argTypes: string;
|
|
465
|
+
readonly body: string;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const JSONB_ARRAY_TO_TEXT_ARRAY: ConversionHelper = {
|
|
469
|
+
name: "metaobjects_jsonb_array_to_text_array",
|
|
470
|
+
signature: "(j jsonb) RETURNS text[] LANGUAGE sql IMMUTABLE",
|
|
471
|
+
argTypes: "jsonb",
|
|
472
|
+
body: "SELECT CASE WHEN j IS NULL OR jsonb_typeof(j) = 'null' THEN NULL "
|
|
473
|
+
+ "ELSE ARRAY(SELECT e FROM jsonb_array_elements_text(j) WITH ORDINALITY AS x(e, i) ORDER BY i) END",
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
const ARRAY_TO_SCALAR: ConversionHelper = {
|
|
477
|
+
name: "metaobjects_array_to_scalar",
|
|
478
|
+
signature: "(a anyarray) RETURNS anyelement LANGUAGE plpgsql IMMUTABLE",
|
|
479
|
+
argTypes: "anyarray",
|
|
480
|
+
body: "BEGIN IF cardinality(a) > 1 THEN RAISE EXCEPTION "
|
|
481
|
+
+ "'metaobjects: cannot narrow an array of % elements to one value', cardinality(a); "
|
|
482
|
+
+ "END IF; RETURN a[1]; END",
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
function helperCall(helper: ConversionHelper, col: string, schema: string | undefined): string {
|
|
486
|
+
return `${quoteQualified(helper.name, schema)}(${col})`;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/** The helpers one direction of the migration calls: each once per schema, in a stable order. */
|
|
490
|
+
function conversionHelpers(
|
|
491
|
+
changes: readonly Change[], direction: "up" | "down",
|
|
492
|
+
): { helper: ConversionHelper; schema: string | undefined }[] {
|
|
493
|
+
const needed = new Map<string, { helper: ConversionHelper; schema: string | undefined }>();
|
|
494
|
+
for (const c of changes) {
|
|
495
|
+
if (c.kind !== "change-column-type") continue;
|
|
496
|
+
const [from, to] = direction === "up" ? [c.from, c.to] : [c.to, c.from];
|
|
497
|
+
const { helper } = conversion("", from, to, c.schema);
|
|
498
|
+
if (helper === undefined) continue;
|
|
499
|
+
const schema = c.schema === DEFAULT_DB_SCHEMA_POSTGRES ? undefined : c.schema;
|
|
500
|
+
needed.set(`${schema ?? ""}.${helper.name}`, { helper, schema });
|
|
501
|
+
}
|
|
502
|
+
return [...needed.keys()].sort().flatMap((k) => needed.get(k) ?? []);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
function createHelper({ helper, schema }: { helper: ConversionHelper; schema: string | undefined }): string {
|
|
506
|
+
return `CREATE OR REPLACE FUNCTION ${quoteQualified(helper.name, schema)}${helper.signature} AS $$ ${helper.body} $$;`;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function dropHelper({ helper, schema }: { helper: ConversionHelper; schema: string | undefined }): string {
|
|
510
|
+
return `DROP FUNCTION IF EXISTS ${quoteQualified(helper.name, schema)}(${helper.argTypes});`;
|
|
511
|
+
}
|
|
512
|
+
|
|
359
513
|
function quote(ident: string): string {
|
|
360
514
|
// Conservative double-quoting; reject embedded quotes (defense).
|
|
361
515
|
if (ident.includes('"')) throw new Error(`unsafe identifier: ${ident}`);
|
package/src/errors.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { Change, ChangeKind } from "./types.js";
|
|
1
|
+
import type { AllowOptions, Change, ChangeKind } from "./types.js";
|
|
2
|
+
import { dropsAutoSequenceDefault } from "./pg-identity-default.js";
|
|
2
3
|
|
|
3
4
|
// ---------------------------------------------------------------------------
|
|
4
5
|
// SetNullNotNullableError — surfaced by buildExpectedSchema
|
|
@@ -33,19 +34,33 @@ export class SetNullNotNullableError extends Error {
|
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
const
|
|
37
|
-
"drop-column": "
|
|
38
|
-
"drop-table": "
|
|
39
|
-
"change-column-type": "
|
|
40
|
-
"change-column-nullable": "
|
|
41
|
-
"drop-index": "
|
|
42
|
-
"drop-fk": "
|
|
37
|
+
const ALLOW_OPTION_BY_KIND: Partial<Record<ChangeKind, keyof AllowOptions>> = {
|
|
38
|
+
"drop-column": "dropColumn",
|
|
39
|
+
"drop-table": "dropTable",
|
|
40
|
+
"change-column-type": "typeChange",
|
|
41
|
+
"change-column-nullable": "nullableToNotNull",
|
|
42
|
+
"drop-index": "dropIndex",
|
|
43
|
+
"drop-fk": "dropFk",
|
|
44
|
+
"drop-check": "dropCheck",
|
|
43
45
|
// change-column-default is blocked in exactly one shape — dropping a live
|
|
44
46
|
// Postgres auto-sequence default with no declared @generation (see
|
|
45
47
|
// diff/status.ts) — and allow.dropIdentityDefault is the flag that enables it.
|
|
46
|
-
"change-column-default": "
|
|
48
|
+
"change-column-default": "dropIdentityDefault",
|
|
47
49
|
};
|
|
48
50
|
|
|
51
|
+
/**
|
|
52
|
+
* The `AllowOptions` field that unblocks `c`, chosen by what BLOCKED it rather than by its kind
|
|
53
|
+
* alone. A type change carries its column's default change, so one that would drop a live
|
|
54
|
+
* auto-sequence default is blocked by THAT, and `typeChange` would not unblock it. The single
|
|
55
|
+
* source for this error's hints and the CLI's `--allow` token.
|
|
56
|
+
*/
|
|
57
|
+
export function allowOptionFor(c: Change): keyof AllowOptions | undefined {
|
|
58
|
+
if (c.kind === "change-column-type" && dropsAutoSequenceDefault(c.fromDefault, c.toDefault)) {
|
|
59
|
+
return "dropIdentityDefault";
|
|
60
|
+
}
|
|
61
|
+
return ALLOW_OPTION_BY_KIND[c.kind];
|
|
62
|
+
}
|
|
63
|
+
|
|
49
64
|
function changeLocator(c: Change): string {
|
|
50
65
|
switch (c.kind) {
|
|
51
66
|
case "drop-column":
|
|
@@ -88,7 +103,8 @@ export class BlockedChangesError extends Error {
|
|
|
88
103
|
|
|
89
104
|
constructor(blocked: Change[]) {
|
|
90
105
|
const hints = blocked.map((c) => {
|
|
91
|
-
const
|
|
106
|
+
const option = allowOptionFor(c);
|
|
107
|
+
const flag = option === undefined ? "(no flag enables this)" : `allow.${option}`;
|
|
92
108
|
return `${c.kind} on ${changeLocator(c)}: pass ${flag}`;
|
|
93
109
|
});
|
|
94
110
|
const msg = `${blocked.length} blocked change(s):\n - ${hints.join("\n - ")}`;
|
package/src/index.ts
CHANGED
|
@@ -47,7 +47,7 @@ export { planOffline, baselineFromMetadata } from "./snapshot/plan.js";
|
|
|
47
47
|
export type { PlanOfflineArgs, PlanOfflineResult } from "./snapshot/plan.js";
|
|
48
48
|
|
|
49
49
|
// Errors
|
|
50
|
-
export { BlockedChangesError, SetNullNotNullableError, PrimaryKeyChangeError } from "./errors.js";
|
|
50
|
+
export { BlockedChangesError, SetNullNotNullableError, PrimaryKeyChangeError, allowOptionFor } from "./errors.js";
|
|
51
51
|
|
|
52
52
|
// SqlType helpers (rarely needed but useful for advanced consumers)
|
|
53
53
|
export { isWidening, sqlTypeEquals } from "./sql-type.js";
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ColumnDefault } from "./types.js";
|
|
2
|
+
|
|
1
3
|
// src/pg-identity-default.ts
|
|
2
4
|
//
|
|
3
5
|
// Postgres "auto-sequence" column DEFAULT — the `nextval('<seq>'::regclass)`
|
|
@@ -17,3 +19,11 @@
|
|
|
17
19
|
export function isPgAutoSequenceDefault(raw: string | null | undefined): boolean {
|
|
18
20
|
return raw !== null && raw !== undefined && /^nextval\(/i.test(raw);
|
|
19
21
|
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A default change that DROPS a live auto-sequence default: the one default shape the diff
|
|
25
|
+
* gates (diff/status.ts), whether it arrives as its own change or folded into a type change.
|
|
26
|
+
*/
|
|
27
|
+
export function dropsAutoSequenceDefault(from: ColumnDefault | undefined, to: ColumnDefault | undefined): boolean {
|
|
28
|
+
return to === undefined && from?.kind === "expr" && isPgAutoSequenceDefault(from.value);
|
|
29
|
+
}
|
package/src/scope.ts
CHANGED
|
@@ -34,6 +34,18 @@
|
|
|
34
34
|
// survivors instead is precisely the inversion above. Declaring a scope is not a way
|
|
35
35
|
// to hand a schema over; removing the objects from the model is.
|
|
36
36
|
//
|
|
37
|
+
// FR-023 — AN IMPORT IS THE ONE EXCLUSION THAT MUST MOVE THE SCHEMA SET. The rule
|
|
38
|
+
// above is stated for `migrate.scope`, where it is right: that scope narrows a model
|
|
39
|
+
// which DID declare into the schema, so the schema stays this model's to manage. A
|
|
40
|
+
// dependency's node is the opposite case — the consumer never declared it, and the
|
|
41
|
+
// publisher owns the schema it sits in. Leaving that schema pinned would make every
|
|
42
|
+
// table the publisher did NOT export, tables this consumer has never heard of, a
|
|
43
|
+
// proposed DROP against the publisher's data.
|
|
44
|
+
//
|
|
45
|
+
// So `scopeExpectedSchema`'s optional `imported` predicate partitions those objects
|
|
46
|
+
// out FIRST, and `declaredSchemas` is derived from what remains. Everything
|
|
47
|
+
// `migrate.scope` excluded is still in that remainder, so the rule above is untouched.
|
|
48
|
+
//
|
|
37
49
|
// `scopedDiffInputs` exists so no caller has to remember any of this: it returns all
|
|
38
50
|
// three obligations as one object, and every scoped `diff` call goes through it.
|
|
39
51
|
|
|
@@ -74,6 +86,16 @@ export interface ScopedExpectedSchema {
|
|
|
74
86
|
* (nothing to derive from; `diff`'s legacy whole-DB fallback is preserved).
|
|
75
87
|
*/
|
|
76
88
|
declaredSchemas?: string[];
|
|
89
|
+
/**
|
|
90
|
+
* The subset of `outOfScope` a DEPENDENCY contributed (FR-023), so a caller can say
|
|
91
|
+
* why an object was excluded. `outOfScope` deliberately stays the FULL set — it is
|
|
92
|
+
* what feeds `unmanagedNames`, and splitting it would silently drop half of the
|
|
93
|
+
* actual-side suppression.
|
|
94
|
+
*
|
|
95
|
+
* `undefined` when no `imported` predicate was supplied, which is every project that
|
|
96
|
+
* declares no dependencies.
|
|
97
|
+
*/
|
|
98
|
+
importedOutOfScope?: string[];
|
|
77
99
|
}
|
|
78
100
|
|
|
79
101
|
/**
|
|
@@ -217,45 +239,98 @@ export function declaredSchemasOf(snapshot: SchemaSnapshot): string[] {
|
|
|
217
239
|
].sort();
|
|
218
240
|
}
|
|
219
241
|
|
|
242
|
+
/** Optional exclusions layered on top of `inScope`. */
|
|
243
|
+
export interface ScopeExpectedSchemaOptions {
|
|
244
|
+
/**
|
|
245
|
+
* FR-023 — is this object's declaring FQN owned by one of the project's
|
|
246
|
+
* DEPENDENCIES? Such an object is loaded so the consumer's own model can resolve
|
|
247
|
+
* against it, and is governed by nobody here unless the consumer's own
|
|
248
|
+
* `migrate.scope` names its package (which `inScope` then admits).
|
|
249
|
+
*
|
|
250
|
+
* Supplied only by a project that declares dependencies: absent, this function
|
|
251
|
+
* behaves exactly as it always has.
|
|
252
|
+
*/
|
|
253
|
+
imported?: ObjectScopePredicate;
|
|
254
|
+
}
|
|
255
|
+
|
|
220
256
|
/**
|
|
221
257
|
* Narrow an expected schema to the objects inside `inScope`.
|
|
222
258
|
*
|
|
223
|
-
* An undefined predicate returns the input untouched — the SAME
|
|
224
|
-
* not an equal copy — so a project that declares no `migrate.scope`
|
|
225
|
-
* diff, the emitter and the committed snapshot
|
|
259
|
+
* An undefined predicate with no `opts` returns the input untouched — the SAME
|
|
260
|
+
* snapshot object, not an equal copy — so a project that declares no `migrate.scope`
|
|
261
|
+
* and no dependencies reaches the diff, the emitter and the committed snapshot
|
|
262
|
+
* through an unchanged value.
|
|
263
|
+
*
|
|
264
|
+
* A table or view with NO recorded provenance is KEPT, by both exclusions. Scope
|
|
265
|
+
* decides on the declaring object's FQN, and an object whose FQN is unknown was never
|
|
266
|
+
* proven to be anyone else's; dropping it would silently un-manage it (and, worse,
|
|
267
|
+
* suppressing its name on the actual side would hide real drift).
|
|
226
268
|
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
* its name on the actual side would hide real drift).
|
|
269
|
+
* With `opts.imported`, an imported object the scope does not admit leaves the
|
|
270
|
+
* expected side BEFORE `declaredSchemas` is computed — see the module header for why
|
|
271
|
+
* that ordering is the whole point.
|
|
231
272
|
*/
|
|
232
273
|
export function scopeExpectedSchema(
|
|
233
274
|
built: ExpectedSchemaWithProvenance,
|
|
234
275
|
inScope: ObjectScopePredicate | undefined,
|
|
276
|
+
opts?: ScopeExpectedSchemaOptions,
|
|
235
277
|
): ScopedExpectedSchema {
|
|
236
|
-
|
|
278
|
+
const imported = opts?.imported;
|
|
279
|
+
if (inScope === undefined && imported === undefined) {
|
|
280
|
+
return { snapshot: built.snapshot, outOfScope: [] };
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// PASS 1 — the import partition. An imported object survives only when the
|
|
284
|
+
// consumer's own scope NAMES it, which is how a consumer opts into owning a
|
|
285
|
+
// dependency's tables (DESIGN §11.1 item 2: "explicit include replaces `mode`").
|
|
286
|
+
//
|
|
287
|
+
// An `inScope` of `undefined` does NOT rescue it. That combination cannot arise
|
|
288
|
+
// from the CLI — `inMigrateScope` is defined whenever dependencies exist — and
|
|
289
|
+
// resolving it the other way would be the unsafe direction: excluding an import
|
|
290
|
+
// costs nothing, while keeping one risks DDL against the publisher's database.
|
|
291
|
+
const importedOutOfScope: string[] = [];
|
|
292
|
+
const declaredHere = <T extends { name: string; schema?: string }>(obj: T): boolean => {
|
|
293
|
+
if (imported === undefined) return true;
|
|
294
|
+
const qualified = qualifiedDbName(obj);
|
|
295
|
+
const fqn = built.provenance.get(qualified);
|
|
296
|
+
if (fqn === undefined || !imported(fqn)) return true;
|
|
297
|
+
if (inScope?.(fqn) === true) return true;
|
|
298
|
+
importedOutOfScope.push(qualified);
|
|
299
|
+
return false;
|
|
300
|
+
};
|
|
301
|
+
const remainder: SchemaSnapshot = {
|
|
302
|
+
...built.snapshot,
|
|
303
|
+
tables: built.snapshot.tables.filter(declaredHere),
|
|
304
|
+
views: built.snapshot.views.filter(declaredHere),
|
|
305
|
+
};
|
|
237
306
|
|
|
238
|
-
// Computed from
|
|
239
|
-
// the filter below
|
|
240
|
-
// the defect
|
|
241
|
-
|
|
307
|
+
// Computed from the REMAINDER — everything this model actually declares — and
|
|
308
|
+
// before the scope filter below. Deriving it from the scope's survivors instead
|
|
309
|
+
// would reproduce exactly the defect the module header describes; deriving it from
|
|
310
|
+
// the unpartitioned side would pin the publisher's schema. Both halves matter.
|
|
311
|
+
const declared = declaredSchemasOf(remainder);
|
|
242
312
|
|
|
243
|
-
|
|
313
|
+
// PASS 2 — the per-command scope, unchanged.
|
|
314
|
+
const scopeOutOfScope: string[] = [];
|
|
244
315
|
const governed = <T extends { name: string; schema?: string }>(obj: T): boolean => {
|
|
316
|
+
if (inScope === undefined) return true;
|
|
245
317
|
const qualified = qualifiedDbName(obj);
|
|
246
318
|
const fqn = built.provenance.get(qualified);
|
|
247
319
|
if (fqn === undefined || inScope(fqn)) return true;
|
|
248
|
-
|
|
320
|
+
scopeOutOfScope.push(qualified);
|
|
249
321
|
return false;
|
|
250
322
|
};
|
|
251
323
|
|
|
252
324
|
return {
|
|
253
325
|
snapshot: {
|
|
254
|
-
...
|
|
255
|
-
tables:
|
|
256
|
-
views:
|
|
326
|
+
...remainder,
|
|
327
|
+
tables: remainder.tables.filter(governed),
|
|
328
|
+
views: remainder.views.filter(governed),
|
|
257
329
|
},
|
|
258
|
-
|
|
330
|
+
// ONE suppression set: both exclusions must reach `unmanagedNames`, or the
|
|
331
|
+
// objects they removed from `expected` come back as proposed drops.
|
|
332
|
+
outOfScope: [...importedOutOfScope, ...scopeOutOfScope],
|
|
259
333
|
...(declared.length > 0 ? { declaredSchemas: declared } : {}),
|
|
334
|
+
...(imported !== undefined ? { importedOutOfScope } : {}),
|
|
260
335
|
};
|
|
261
336
|
}
|