@metaobjectsdev/migrate-ts 1.0.2 → 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/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/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/package.json +2 -2
- package/src/drift/drift.ts +21 -0
- package/src/scope.ts +93 -18
- package/src/snapshot/plan.ts +22 -2
package/dist/drift/drift.d.ts
CHANGED
|
@@ -38,6 +38,18 @@ export interface ComputeDriftOptions {
|
|
|
38
38
|
* failing on tables migrate does not own is incoherent.
|
|
39
39
|
*/
|
|
40
40
|
inScope?: ObjectScopePredicate;
|
|
41
|
+
/**
|
|
42
|
+
* FR-023 — objects a DEPENDENCY owns. Such an object is loaded so this project's own
|
|
43
|
+
* model can resolve against it and is governed by nobody here unless `inScope`
|
|
44
|
+
* admits it: it leaves the expected side, is suppressed on the actual side, and —
|
|
45
|
+
* unlike an `inScope` exclusion — takes the publisher's database schema out of the
|
|
46
|
+
* run's scope with it, so a table the publisher never exported is not reported as an
|
|
47
|
+
* extra table in a schema this project does not manage (migrate-ts `scope.ts`).
|
|
48
|
+
*
|
|
49
|
+
* `verify --db` and `migrate` share this declaration for the same reason they share
|
|
50
|
+
* `inScope`. Omit for a project with no dependencies (unchanged behavior).
|
|
51
|
+
*/
|
|
52
|
+
imported?: ObjectScopePredicate;
|
|
41
53
|
}
|
|
42
54
|
export interface DriftResult extends DiffResult {
|
|
43
55
|
/**
|
|
@@ -56,6 +68,13 @@ export interface DriftResult extends DiffResult {
|
|
|
56
68
|
* `GovernedScope`, which is what `excludeFromSnapshot` takes.
|
|
57
69
|
*/
|
|
58
70
|
declaredSchemas: readonly string[] | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* The subset of `outOfScope` a DEPENDENCY contributed (FR-023). Reported for the
|
|
73
|
+
* same reason `declaredSchemas` is: so the caller states WHY an object was left out
|
|
74
|
+
* without re-deriving the decision from a second expected-schema build, which could
|
|
75
|
+
* come to disagree with the one this comparison actually made.
|
|
76
|
+
*/
|
|
77
|
+
importedOutOfScope: readonly string[] | undefined;
|
|
59
78
|
}
|
|
60
79
|
/**
|
|
61
80
|
* Compute the drift between an ALREADY-INTROSPECTED schema snapshot and the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drift.d.ts","sourceRoot":"","sources":["../../src/drift/drift.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAKrE,OAAO,EAAyC,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAErF,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,OAAO,uBAAuB,EAAE,iBAAiB,EAAE,CAAC;IACrE;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"drift.d.ts","sourceRoot":"","sources":["../../src/drift/drift.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAKrE,OAAO,EAAyC,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAErF,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,OAAO,uBAAuB,EAAE,iBAAiB,EAAE,CAAC;IACrE;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C;;;;OAIG;IACH,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;;;;;;;OAQG;IACH,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC/C;;;;;OAKG;IACH,kBAAkB,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CACnD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,IAAI,CAAC,EAAE,mBAAmB,GACzB,OAAO,CAAC,WAAW,CAAC,CA6BtB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACnC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,IAAI,CAAC,EAAE,mBAAmB,GACzB,OAAO,CAAC,WAAW,CAAC,CAGtB"}
|
package/dist/drift/drift.js
CHANGED
|
@@ -36,7 +36,7 @@ export async function computeDriftFromActual(actual, dialect, metadata, opts) {
|
|
|
36
36
|
? { columnNamingStrategy: opts.columnNamingStrategy }
|
|
37
37
|
: {}),
|
|
38
38
|
...(opts?.views !== undefined ? { views: opts.views } : {}),
|
|
39
|
-
}), opts?.inScope);
|
|
39
|
+
}), opts?.inScope, opts?.imported !== undefined ? { imported: opts.imported } : undefined);
|
|
40
40
|
const result = await diff({
|
|
41
41
|
// The three scoped-diff obligations as one value (see scope.ts's header):
|
|
42
42
|
// the narrowed expected side, `unmanagedNames` merging @unmanaged with the
|
|
@@ -52,6 +52,7 @@ export async function computeDriftFromActual(actual, dialect, metadata, opts) {
|
|
|
52
52
|
...result,
|
|
53
53
|
outOfScope: scoped.outOfScope,
|
|
54
54
|
declaredSchemas: scoped.declaredSchemas,
|
|
55
|
+
importedOutOfScope: scoped.importedOutOfScope,
|
|
55
56
|
};
|
|
56
57
|
}
|
|
57
58
|
/**
|
package/dist/drift/drift.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drift.js","sourceRoot":"","sources":["../../src/drift/drift.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,gEAAgE;AAChE,wEAAwE;AACxE,EAAE;AACF,+EAA+E;AAC/E,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,8CAA8C;AAC9C,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AACjF,oFAAoF;AAKpF,OAAO,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAA6B,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"drift.js","sourceRoot":"","sources":["../../src/drift/drift.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,gEAAgE;AAChE,wEAAwE;AACxE,EAAE;AACF,+EAA+E;AAC/E,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,8CAA8C;AAC9C,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AACjF,oFAAoF;AAKpF,OAAO,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAA6B,MAAM,aAAa,CAAC;AA8E/F;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAsB,EACtB,OAAgB,EAChB,QAAkB,EAClB,IAA0B;IAE1B,MAAM,MAAM,GAAG,mBAAmB,CAChC,iCAAiC,CAAC,QAAQ,EAAE;QAC1C,OAAO;QACP,GAAG,CAAC,IAAI,EAAE,oBAAoB,KAAK,SAAS;YAC1C,CAAC,CAAC,EAAE,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAAE;YACrD,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5D,CAAC,EACF,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,CACvE,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC;QACxB,0EAA0E;QAC1E,2EAA2E;QAC3E,2EAA2E;QAC3E,0EAA0E;QAC1E,GAAG,gBAAgB,CAAC,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM;QACN,OAAO;QACP,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE;QACxB,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjF,CAAC,CAAC;IACH,OAAO;QACL,GAAG,MAAM;QACT,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;KAC9C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,EAAmC,EACnC,OAAgB,EAChB,QAAkB,EAClB,IAA0B;IAE1B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC7C,OAAO,sBAAsB,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AACjE,CAAC"}
|
package/dist/scope.d.ts
CHANGED
|
@@ -31,6 +31,16 @@ export interface ScopedExpectedSchema {
|
|
|
31
31
|
* (nothing to derive from; `diff`'s legacy whole-DB fallback is preserved).
|
|
32
32
|
*/
|
|
33
33
|
declaredSchemas?: string[];
|
|
34
|
+
/**
|
|
35
|
+
* The subset of `outOfScope` a DEPENDENCY contributed (FR-023), so a caller can say
|
|
36
|
+
* why an object was excluded. `outOfScope` deliberately stays the FULL set — it is
|
|
37
|
+
* what feeds `unmanagedNames`, and splitting it would silently drop half of the
|
|
38
|
+
* actual-side suppression.
|
|
39
|
+
*
|
|
40
|
+
* `undefined` when no `imported` predicate was supplied, which is every project that
|
|
41
|
+
* declares no dependencies.
|
|
42
|
+
*/
|
|
43
|
+
importedOutOfScope?: string[];
|
|
34
44
|
}
|
|
35
45
|
/**
|
|
36
46
|
* Carry an out-of-scope object forward into the snapshot a run is about to commit.
|
|
@@ -105,17 +115,35 @@ export declare function scopedDiffInputs(scoped: ScopedExpectedSchema, unmanaged
|
|
|
105
115
|
* `diff`'s legacy whole-database fallback for a genuinely empty model.
|
|
106
116
|
*/
|
|
107
117
|
export declare function declaredSchemasOf(snapshot: SchemaSnapshot): string[];
|
|
118
|
+
/** Optional exclusions layered on top of `inScope`. */
|
|
119
|
+
export interface ScopeExpectedSchemaOptions {
|
|
120
|
+
/**
|
|
121
|
+
* FR-023 — is this object's declaring FQN owned by one of the project's
|
|
122
|
+
* DEPENDENCIES? Such an object is loaded so the consumer's own model can resolve
|
|
123
|
+
* against it, and is governed by nobody here unless the consumer's own
|
|
124
|
+
* `migrate.scope` names its package (which `inScope` then admits).
|
|
125
|
+
*
|
|
126
|
+
* Supplied only by a project that declares dependencies: absent, this function
|
|
127
|
+
* behaves exactly as it always has.
|
|
128
|
+
*/
|
|
129
|
+
imported?: ObjectScopePredicate;
|
|
130
|
+
}
|
|
108
131
|
/**
|
|
109
132
|
* Narrow an expected schema to the objects inside `inScope`.
|
|
110
133
|
*
|
|
111
|
-
* An undefined predicate returns the input untouched — the SAME
|
|
112
|
-
* not an equal copy — so a project that declares no `migrate.scope`
|
|
113
|
-
* diff, the emitter and the committed snapshot
|
|
134
|
+
* An undefined predicate with no `opts` returns the input untouched — the SAME
|
|
135
|
+
* snapshot object, not an equal copy — so a project that declares no `migrate.scope`
|
|
136
|
+
* and no dependencies reaches the diff, the emitter and the committed snapshot
|
|
137
|
+
* through an unchanged value.
|
|
138
|
+
*
|
|
139
|
+
* A table or view with NO recorded provenance is KEPT, by both exclusions. Scope
|
|
140
|
+
* decides on the declaring object's FQN, and an object whose FQN is unknown was never
|
|
141
|
+
* proven to be anyone else's; dropping it would silently un-manage it (and, worse,
|
|
142
|
+
* suppressing its name on the actual side would hide real drift).
|
|
114
143
|
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* its name on the actual side would hide real drift).
|
|
144
|
+
* With `opts.imported`, an imported object the scope does not admit leaves the
|
|
145
|
+
* expected side BEFORE `declaredSchemas` is computed — see the module header for why
|
|
146
|
+
* that ordering is the whole point.
|
|
119
147
|
*/
|
|
120
|
-
export declare function scopeExpectedSchema(built: ExpectedSchemaWithProvenance, inScope: ObjectScopePredicate | undefined): ScopedExpectedSchema;
|
|
148
|
+
export declare function scopeExpectedSchema(built: ExpectedSchemaWithProvenance, inScope: ObjectScopePredicate | undefined, opts?: ScopeExpectedSchemaOptions): ScopedExpectedSchema;
|
|
121
149
|
//# sourceMappingURL=scope.d.ts.map
|
package/dist/scope.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAoDA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACnC,4DAA4D;IAC5D,QAAQ,EAAE,cAAc,CAAC;IACzB;;;;;OAKG;IACH,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,cAAc,EACrB,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,cAAc,CAQhB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,aAAa,GACtB,oBAAoB,CAatB;AAED,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CAC1D;AAoBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,oBAAoB,EAC5B,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,IAAI,CAAC,QAAQ,EAAE,UAAU,GAAG,gBAAgB,GAAG,cAAc,CAAC,CAMhE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,EAAE,CAQpE;AAED,uDAAuD;AACvD,MAAM,WAAW,0BAA0B;IACzC;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,4BAA4B,EACnC,OAAO,EAAE,oBAAoB,GAAG,SAAS,EACzC,IAAI,CAAC,EAAE,0BAA0B,GAChC,oBAAoB,CA2DtB"}
|
package/dist/scope.js
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
|
import { DEFAULT_DB_SCHEMA_POSTGRES } from "@metaobjectsdev/metadata";
|
|
@@ -155,39 +167,79 @@ export function declaredSchemasOf(snapshot) {
|
|
|
155
167
|
/**
|
|
156
168
|
* Narrow an expected schema to the objects inside `inScope`.
|
|
157
169
|
*
|
|
158
|
-
* An undefined predicate returns the input untouched — the SAME
|
|
159
|
-
* not an equal copy — so a project that declares no `migrate.scope`
|
|
160
|
-
* diff, the emitter and the committed snapshot
|
|
170
|
+
* An undefined predicate with no `opts` returns the input untouched — the SAME
|
|
171
|
+
* snapshot object, not an equal copy — so a project that declares no `migrate.scope`
|
|
172
|
+
* and no dependencies reaches the diff, the emitter and the committed snapshot
|
|
173
|
+
* through an unchanged value.
|
|
174
|
+
*
|
|
175
|
+
* A table or view with NO recorded provenance is KEPT, by both exclusions. Scope
|
|
176
|
+
* decides on the declaring object's FQN, and an object whose FQN is unknown was never
|
|
177
|
+
* proven to be anyone else's; dropping it would silently un-manage it (and, worse,
|
|
178
|
+
* suppressing its name on the actual side would hide real drift).
|
|
161
179
|
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* its name on the actual side would hide real drift).
|
|
180
|
+
* With `opts.imported`, an imported object the scope does not admit leaves the
|
|
181
|
+
* expected side BEFORE `declaredSchemas` is computed — see the module header for why
|
|
182
|
+
* that ordering is the whole point.
|
|
166
183
|
*/
|
|
167
|
-
export function scopeExpectedSchema(built, inScope) {
|
|
168
|
-
|
|
184
|
+
export function scopeExpectedSchema(built, inScope, opts) {
|
|
185
|
+
const imported = opts?.imported;
|
|
186
|
+
if (inScope === undefined && imported === undefined) {
|
|
169
187
|
return { snapshot: built.snapshot, outOfScope: [] };
|
|
170
|
-
|
|
171
|
-
// the
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
188
|
+
}
|
|
189
|
+
// PASS 1 — the import partition. An imported object survives only when the
|
|
190
|
+
// consumer's own scope NAMES it, which is how a consumer opts into owning a
|
|
191
|
+
// dependency's tables (DESIGN §11.1 item 2: "explicit include replaces `mode`").
|
|
192
|
+
//
|
|
193
|
+
// An `inScope` of `undefined` does NOT rescue it. That combination cannot arise
|
|
194
|
+
// from the CLI — `inMigrateScope` is defined whenever dependencies exist — and
|
|
195
|
+
// resolving it the other way would be the unsafe direction: excluding an import
|
|
196
|
+
// costs nothing, while keeping one risks DDL against the publisher's database.
|
|
197
|
+
const importedOutOfScope = [];
|
|
198
|
+
const declaredHere = (obj) => {
|
|
199
|
+
if (imported === undefined)
|
|
200
|
+
return true;
|
|
201
|
+
const qualified = qualifiedDbName(obj);
|
|
202
|
+
const fqn = built.provenance.get(qualified);
|
|
203
|
+
if (fqn === undefined || !imported(fqn))
|
|
204
|
+
return true;
|
|
205
|
+
if (inScope?.(fqn) === true)
|
|
206
|
+
return true;
|
|
207
|
+
importedOutOfScope.push(qualified);
|
|
208
|
+
return false;
|
|
209
|
+
};
|
|
210
|
+
const remainder = {
|
|
211
|
+
...built.snapshot,
|
|
212
|
+
tables: built.snapshot.tables.filter(declaredHere),
|
|
213
|
+
views: built.snapshot.views.filter(declaredHere),
|
|
214
|
+
};
|
|
215
|
+
// Computed from the REMAINDER — everything this model actually declares — and
|
|
216
|
+
// before the scope filter below. Deriving it from the scope's survivors instead
|
|
217
|
+
// would reproduce exactly the defect the module header describes; deriving it from
|
|
218
|
+
// the unpartitioned side would pin the publisher's schema. Both halves matter.
|
|
219
|
+
const declared = declaredSchemasOf(remainder);
|
|
220
|
+
// PASS 2 — the per-command scope, unchanged.
|
|
221
|
+
const scopeOutOfScope = [];
|
|
175
222
|
const governed = (obj) => {
|
|
223
|
+
if (inScope === undefined)
|
|
224
|
+
return true;
|
|
176
225
|
const qualified = qualifiedDbName(obj);
|
|
177
226
|
const fqn = built.provenance.get(qualified);
|
|
178
227
|
if (fqn === undefined || inScope(fqn))
|
|
179
228
|
return true;
|
|
180
|
-
|
|
229
|
+
scopeOutOfScope.push(qualified);
|
|
181
230
|
return false;
|
|
182
231
|
};
|
|
183
232
|
return {
|
|
184
233
|
snapshot: {
|
|
185
|
-
...
|
|
186
|
-
tables:
|
|
187
|
-
views:
|
|
234
|
+
...remainder,
|
|
235
|
+
tables: remainder.tables.filter(governed),
|
|
236
|
+
views: remainder.views.filter(governed),
|
|
188
237
|
},
|
|
189
|
-
|
|
238
|
+
// ONE suppression set: both exclusions must reach `unmanagedNames`, or the
|
|
239
|
+
// objects they removed from `expected` come back as proposed drops.
|
|
240
|
+
outOfScope: [...importedOutOfScope, ...scopeOutOfScope],
|
|
190
241
|
...(declared.length > 0 ? { declaredSchemas: declared } : {}),
|
|
242
|
+
...(imported !== undefined ? { importedOutOfScope } : {}),
|
|
191
243
|
};
|
|
192
244
|
}
|
|
193
245
|
//# sourceMappingURL=scope.js.map
|
package/dist/scope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,4DAA4D;AAC5D,kFAAkF;AAClF,uEAAuE;AACvE,EAAE;AACF,2EAA2E;AAC3E,kFAAkF;AAClF,mEAAmE;AACnE,EAAE;AACF,qFAAqF;AACrF,mFAAmF;AACnF,oFAAoF;AACpF,kDAAkD;AAClD,EAAE;AACF,gFAAgF;AAChF,4EAA4E;AAC5E,mFAAmF;AACnF,8EAA8E;AAC9E,oFAAoF;AACpF,qFAAqF;AACrF,gFAAgF;AAChF,qFAAqF;AACrF,sFAAsF;AACtF,wCAAwC;AACxC,EAAE;AACF,oFAAoF;AACpF,mFAAmF;AACnF,oFAAoF;AACpF,+EAA+E;AAC/E,qFAAqF;AACrF,6EAA6E;AAC7E,qFAAqF;AACrF,qFAAqF;AACrF,iEAAiE;AACjE,EAAE;AACF,qFAAqF;AACrF,iFAAiF;AAEjF,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAGtE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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"}
|
package/dist/snapshot/plan.d.ts
CHANGED
|
@@ -18,6 +18,15 @@ export interface PlanOfflineArgs extends Pick<DiffArgs, "allow" | "onAmbiguous"
|
|
|
18
18
|
* loaded (unchanged behavior).
|
|
19
19
|
*/
|
|
20
20
|
inScope?: ObjectScopePredicate;
|
|
21
|
+
/**
|
|
22
|
+
* FR-023 — objects a DEPENDENCY owns. Imported metadata is loaded so this project's
|
|
23
|
+
* own model can resolve against it and is governed by nobody here unless `inScope`
|
|
24
|
+
* admits it, so such an object leaves BOTH sides of the diff and, unlike an
|
|
25
|
+
* `inScope` exclusion, takes its database schema out of the run's scope with it
|
|
26
|
+
* (migrate-ts `scope.ts` header). Omit for a project with no dependencies
|
|
27
|
+
* (unchanged behavior).
|
|
28
|
+
*/
|
|
29
|
+
imported?: ObjectScopePredicate;
|
|
21
30
|
}
|
|
22
31
|
export interface PlanOfflineResult {
|
|
23
32
|
/** The change set to emit, from diffing metadata-expected against the snapshot. */
|
|
@@ -36,8 +45,12 @@ export interface PlanOfflineResult {
|
|
|
36
45
|
* only for what it governs.
|
|
37
46
|
*/
|
|
38
47
|
expected: SchemaSnapshot;
|
|
39
|
-
/** Qualified physical names excluded by `inScope`; empty when
|
|
48
|
+
/** Qualified physical names excluded by `inScope` OR by `imported`; empty when
|
|
49
|
+
* neither was given. */
|
|
40
50
|
outOfScope: readonly string[];
|
|
51
|
+
/** The subset of `outOfScope` a dependency contributed (FR-023), so the CLI can say
|
|
52
|
+
* WHY those objects were excluded. `undefined` when no `imported` was given. */
|
|
53
|
+
importedOutOfScope: readonly string[] | undefined;
|
|
41
54
|
}
|
|
42
55
|
/**
|
|
43
56
|
* Plan a migration offline: build the expected schema from metadata and diff it
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/snapshot/plan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAE/E,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAiE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACvH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,aAAa,GAAG,cAAc,CAAC;IAC/F,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,4GAA4G;IAC5G,QAAQ,EAAE,cAAc,CAAC;IACzB,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,kGAAkG;IAClG,KAAK,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACrC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/snapshot/plan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAE/E,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAiE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACvH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,aAAa,GAAG,cAAc,CAAC;IAC/F,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,4GAA4G;IAC5G,QAAQ,EAAE,cAAc,CAAC;IACzB,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,kGAAkG;IAClG,KAAK,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACrC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,IAAI,EAAE,UAAU,CAAC;IACjB;;;;;OAKG;IACH,YAAY,EAAE,cAAc,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,EAAE,cAAc,CAAC;IACzB;6BACyB;IACzB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;qFACiF;IACjF,kBAAkB,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CACnD;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAwCnF;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,oBAAoB,CAAC,EAAE,oBAAoB,EAC3C,KAAK,CAAC,EAAE,SAAS,iBAAiB,EAAE,GACnC,cAAc,CAMhB"}
|
package/dist/snapshot/plan.js
CHANGED
|
@@ -12,7 +12,7 @@ export async function planOffline(args) {
|
|
|
12
12
|
dialect: args.dialect,
|
|
13
13
|
...(args.columnNamingStrategy ? { columnNamingStrategy: args.columnNamingStrategy } : {}),
|
|
14
14
|
...(args.views !== undefined ? { views: args.views } : {}),
|
|
15
|
-
}), args.inScope);
|
|
15
|
+
}), args.inScope, args.imported !== undefined ? { imported: args.imported } : undefined);
|
|
16
16
|
// The DIFF runs against the narrowed side; the SNAPSHOT keeps what this run
|
|
17
17
|
// excluded. Committing the narrowed schema would delete every out-of-scope entry
|
|
18
18
|
// the previous snapshot held, so removing or widening `migrate.scope` later would
|
|
@@ -36,7 +36,13 @@ export async function planOffline(args) {
|
|
|
36
36
|
...(args.onAmbiguous ? { onAmbiguous: args.onAmbiguous } : {}),
|
|
37
37
|
...(args.ignoreTables ? { ignoreTables: args.ignoreTables } : {}),
|
|
38
38
|
});
|
|
39
|
-
return {
|
|
39
|
+
return {
|
|
40
|
+
diff: result,
|
|
41
|
+
nextSnapshot,
|
|
42
|
+
expected: scoped.snapshot,
|
|
43
|
+
outOfScope: scoped.outOfScope,
|
|
44
|
+
importedOutOfScope: scoped.importedOutOfScope,
|
|
45
|
+
};
|
|
40
46
|
}
|
|
41
47
|
/** Seed an initial reference snapshot from metadata (greenfield baseline). */
|
|
42
48
|
export function baselineFromMetadata(metadata, dialect, columnNamingStrategy, views) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/snapshot/plan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AAC/F,OAAO,EAAE,IAAI,EAAiB,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,gBAAgB,EAA6B,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/snapshot/plan.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/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/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
|
}
|
package/src/snapshot/plan.ts
CHANGED
|
@@ -22,6 +22,15 @@ export interface PlanOfflineArgs extends Pick<DiffArgs, "allow" | "onAmbiguous"
|
|
|
22
22
|
* loaded (unchanged behavior).
|
|
23
23
|
*/
|
|
24
24
|
inScope?: ObjectScopePredicate;
|
|
25
|
+
/**
|
|
26
|
+
* FR-023 — objects a DEPENDENCY owns. Imported metadata is loaded so this project's
|
|
27
|
+
* own model can resolve against it and is governed by nobody here unless `inScope`
|
|
28
|
+
* admits it, so such an object leaves BOTH sides of the diff and, unlike an
|
|
29
|
+
* `inScope` exclusion, takes its database schema out of the run's scope with it
|
|
30
|
+
* (migrate-ts `scope.ts` header). Omit for a project with no dependencies
|
|
31
|
+
* (unchanged behavior).
|
|
32
|
+
*/
|
|
33
|
+
imported?: ObjectScopePredicate;
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
export interface PlanOfflineResult {
|
|
@@ -41,8 +50,12 @@ export interface PlanOfflineResult {
|
|
|
41
50
|
* only for what it governs.
|
|
42
51
|
*/
|
|
43
52
|
expected: SchemaSnapshot;
|
|
44
|
-
/** Qualified physical names excluded by `inScope`; empty when
|
|
53
|
+
/** Qualified physical names excluded by `inScope` OR by `imported`; empty when
|
|
54
|
+
* neither was given. */
|
|
45
55
|
outOfScope: readonly string[];
|
|
56
|
+
/** The subset of `outOfScope` a dependency contributed (FR-023), so the CLI can say
|
|
57
|
+
* WHY those objects were excluded. `undefined` when no `imported` was given. */
|
|
58
|
+
importedOutOfScope: readonly string[] | undefined;
|
|
46
59
|
}
|
|
47
60
|
|
|
48
61
|
/**
|
|
@@ -58,6 +71,7 @@ export async function planOffline(args: PlanOfflineArgs): Promise<PlanOfflineRes
|
|
|
58
71
|
...(args.views !== undefined ? { views: args.views } : {}),
|
|
59
72
|
}),
|
|
60
73
|
args.inScope,
|
|
74
|
+
args.imported !== undefined ? { imported: args.imported } : undefined,
|
|
61
75
|
);
|
|
62
76
|
// The DIFF runs against the narrowed side; the SNAPSHOT keeps what this run
|
|
63
77
|
// excluded. Committing the narrowed schema would delete every out-of-scope entry
|
|
@@ -82,7 +96,13 @@ export async function planOffline(args: PlanOfflineArgs): Promise<PlanOfflineRes
|
|
|
82
96
|
...(args.onAmbiguous ? { onAmbiguous: args.onAmbiguous } : {}),
|
|
83
97
|
...(args.ignoreTables ? { ignoreTables: args.ignoreTables } : {}),
|
|
84
98
|
});
|
|
85
|
-
return {
|
|
99
|
+
return {
|
|
100
|
+
diff: result,
|
|
101
|
+
nextSnapshot,
|
|
102
|
+
expected: scoped.snapshot,
|
|
103
|
+
outOfScope: scoped.outOfScope,
|
|
104
|
+
importedOutOfScope: scoped.importedOutOfScope,
|
|
105
|
+
};
|
|
86
106
|
}
|
|
87
107
|
|
|
88
108
|
/** Seed an initial reference snapshot from metadata (greenfield baseline). */
|