@metaobjectsdev/cli 0.23.2 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -0
- package/dist/src/commands/docs.d.ts.map +1 -1
- package/dist/src/commands/docs.js +157 -59
- package/dist/src/commands/docs.js.map +1 -1
- package/dist/src/commands/export.d.ts.map +1 -1
- package/dist/src/commands/export.js +28 -6
- package/dist/src/commands/export.js.map +1 -1
- package/dist/src/commands/gen.d.ts.map +1 -1
- package/dist/src/commands/gen.js +66 -22
- package/dist/src/commands/gen.js.map +1 -1
- package/dist/src/commands/init.d.ts +8 -0
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +142 -52
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/migrate.d.ts +9 -2
- package/dist/src/commands/migrate.d.ts.map +1 -1
- package/dist/src/commands/migrate.js +399 -73
- package/dist/src/commands/migrate.js.map +1 -1
- package/dist/src/commands/prompt-snapshot.d.ts.map +1 -1
- package/dist/src/commands/prompt-snapshot.js +40 -18
- package/dist/src/commands/prompt-snapshot.js.map +1 -1
- package/dist/src/commands/upgrade.d.ts +2 -0
- package/dist/src/commands/upgrade.d.ts.map +1 -0
- package/dist/src/commands/upgrade.js +163 -0
- package/dist/src/commands/upgrade.js.map +1 -0
- package/dist/src/commands/verify.d.ts.map +1 -1
- package/dist/src/commands/verify.js +360 -48
- package/dist/src/commands/verify.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +55 -19
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib/allow.d.ts.map +1 -1
- package/dist/src/lib/allow.js +4 -0
- package/dist/src/lib/allow.js.map +1 -1
- package/dist/src/lib/args.d.ts +16 -2
- package/dist/src/lib/args.d.ts.map +1 -1
- package/dist/src/lib/args.js +19 -3
- package/dist/src/lib/args.js.map +1 -1
- package/dist/src/lib/codegen-drift.d.ts +8 -1
- package/dist/src/lib/codegen-drift.d.ts.map +1 -1
- package/dist/src/lib/codegen-drift.js +9 -1
- package/dist/src/lib/codegen-drift.js.map +1 -1
- package/dist/src/lib/detect-stack.d.ts +1 -1
- package/dist/src/lib/detect-stack.d.ts.map +1 -1
- package/dist/src/lib/detect-stack.js +22 -37
- package/dist/src/lib/detect-stack.js.map +1 -1
- package/dist/src/lib/load-metaobjects-config.d.ts +79 -1
- package/dist/src/lib/load-metaobjects-config.d.ts.map +1 -1
- package/dist/src/lib/load-metaobjects-config.js +123 -1
- package/dist/src/lib/load-metaobjects-config.js.map +1 -1
- package/dist/src/lib/manifest-ignored-check.d.ts +12 -0
- package/dist/src/lib/manifest-ignored-check.d.ts.map +1 -0
- package/dist/src/lib/manifest-ignored-check.js +74 -0
- package/dist/src/lib/manifest-ignored-check.js.map +1 -0
- package/dist/src/lib/migrate-scope.d.ts +49 -0
- package/dist/src/lib/migrate-scope.d.ts.map +1 -0
- package/dist/src/lib/migrate-scope.js +92 -0
- package/dist/src/lib/migrate-scope.js.map +1 -0
- package/dist/src/lib/output.d.ts +1 -1
- package/dist/src/lib/output.d.ts.map +1 -1
- package/dist/src/lib/output.js +9 -3
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/requirement-check.d.ts.map +1 -1
- package/dist/src/lib/requirement-check.js +10 -57
- package/dist/src/lib/requirement-check.js.map +1 -1
- package/package.json +11 -11
- package/src/commands/docs.ts +174 -61
- package/src/commands/export.ts +30 -6
- package/src/commands/gen.ts +68 -22
- package/src/commands/init.ts +161 -58
- package/src/commands/migrate.ts +423 -75
- package/src/commands/prompt-snapshot.ts +43 -18
- package/src/commands/upgrade.ts +179 -0
- package/src/commands/verify.ts +397 -48
- package/src/index.ts +55 -19
- package/src/lib/allow.ts +4 -0
- package/src/lib/args.ts +35 -4
- package/src/lib/codegen-drift.ts +9 -0
- package/src/lib/detect-stack.ts +20 -33
- package/src/lib/load-metaobjects-config.ts +129 -2
- package/src/lib/manifest-ignored-check.ts +75 -0
- package/src/lib/migrate-scope.ts +102 -0
- package/src/lib/output.ts +8 -4
- package/src/lib/requirement-check.ts +10 -58
- package/dist/src/lib/verified-by-scan.d.ts +0 -20
- package/dist/src/lib/verified-by-scan.d.ts.map +0 -1
- package/dist/src/lib/verified-by-scan.js +0 -344
- package/dist/src/lib/verified-by-scan.js.map +0 -1
- package/src/lib/verified-by-scan.ts +0 -375
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect-stack.d.ts","sourceRoot":"","sources":["../../../src/lib/detect-stack.ts"],"names":[],"mappings":"AAGA,OAAO,EAEkC,KAAK,KAAK,EAElD,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"detect-stack.d.ts","sourceRoot":"","sources":["../../../src/lib/detect-stack.ts"],"names":[],"mappings":"AAGA,OAAO,EAEkC,KAAK,KAAK,EAElD,MAAM,mCAAmC,CAAC;AAkD3C;;qEAEqE;AACrE,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAUnH"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { resolveCollection } from "@metaobjectsdev/sdk";
|
|
3
4
|
import { detectStack, detectConcerns, makeStack, SERVER_LANGS, CLIENT_FRAMEWORKS, } from "@metaobjectsdev/sdk/agent-context";
|
|
4
5
|
function depNames(cwd) {
|
|
5
6
|
const out = new Set();
|
|
@@ -16,64 +17,48 @@ function depNames(cwd) {
|
|
|
16
17
|
}
|
|
17
18
|
return out;
|
|
18
19
|
}
|
|
19
|
-
const METADATA_DIR = "metaobjects";
|
|
20
|
-
const METADATA_FILE_PATTERN = /\.(json|ya?ml)$/i;
|
|
21
20
|
// Cheap substring probe, not a metamodel load: matches both canonical JSON's
|
|
22
21
|
// quoted `"requirement.functional"` key and sigil-free YAML's bare
|
|
23
22
|
// `requirement.functional:` authoring form.
|
|
24
23
|
const REQUIREMENT_NODE_MARKER = "requirement.";
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
entries = readdirSync(dir, { withFileTypes: true });
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
continue; // unreadable directory — skip it, keep scanning siblings
|
|
42
|
-
}
|
|
43
|
-
for (const entry of entries) {
|
|
44
|
-
const full = join(dir, entry.name);
|
|
45
|
-
if (entry.isDirectory()) {
|
|
46
|
-
pending.push(full);
|
|
47
|
-
}
|
|
48
|
-
else if (METADATA_FILE_PATTERN.test(entry.name)) {
|
|
49
|
-
try {
|
|
50
|
-
if (readFileSync(full, "utf8").includes(REQUIREMENT_NODE_MARKER))
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
catch { /* unreadable file — treat as no match */ }
|
|
54
|
-
}
|
|
24
|
+
/** Scans the project's resolved metadata collection (`resolveCollection` — the
|
|
25
|
+
* single authority on where metadata lives, honouring declared `sources` rather
|
|
26
|
+
* than assuming `metaobjects/`) for any file containing a `requirement.*` node
|
|
27
|
+
* marker. Defensive throughout: no declared sources and no default directory, an
|
|
28
|
+
* unresolvable source, or an unreadable file are all treated as "not found",
|
|
29
|
+
* never thrown — this is a cheap heuristic, not a metamodel load. */
|
|
30
|
+
async function hasRequirementNodes(cwd) {
|
|
31
|
+
try {
|
|
32
|
+
const { files } = await resolveCollection(cwd);
|
|
33
|
+
for (const file of files) {
|
|
34
|
+
if (readFileSync(file, "utf8").includes(REQUIREMENT_NODE_MARKER))
|
|
35
|
+
return true;
|
|
55
36
|
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
56
41
|
}
|
|
57
|
-
return false;
|
|
58
42
|
}
|
|
59
|
-
function probe(cwd) {
|
|
43
|
+
async function probe(cwd) {
|
|
60
44
|
const deps = depNames(cwd);
|
|
61
45
|
const names = existsSync(cwd) ? readdirSync(cwd) : [];
|
|
46
|
+
const requirementNodes = await hasRequirementNodes(cwd);
|
|
62
47
|
return {
|
|
63
48
|
hasDep: (name) => deps.has(name),
|
|
64
49
|
hasFileMatching: (re) => names.some((n) => re.test(n)),
|
|
65
|
-
hasRequirementNodes: () =>
|
|
50
|
+
hasRequirementNodes: () => requirementNodes,
|
|
66
51
|
};
|
|
67
52
|
}
|
|
68
53
|
/** Resolve the stack: explicit --server/--client overrides take precedence; otherwise detect.
|
|
69
54
|
* Concern tokens (e.g. requirements) are always OBSERVED from project state, independent of
|
|
70
55
|
* any --server/--client override — a concern is not a stack axis. */
|
|
71
|
-
export function resolveStack(cwd, overrides) {
|
|
56
|
+
export async function resolveStack(cwd, overrides) {
|
|
72
57
|
const validServers = SERVER_LANGS;
|
|
73
58
|
const validClients = CLIENT_FRAMEWORKS;
|
|
74
59
|
const oServers = overrides.servers.filter((s) => validServers.includes(s));
|
|
75
60
|
const oClients = overrides.clients.filter((c) => validClients.includes(c));
|
|
76
|
-
const p = probe(cwd);
|
|
61
|
+
const p = await probe(cwd);
|
|
77
62
|
const concerns = detectConcerns(p);
|
|
78
63
|
if (oServers.length > 0 || oClients.length > 0)
|
|
79
64
|
return makeStack(oServers, oClients, concerns);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect-stack.js","sourceRoot":"","sources":["../../../src/lib/detect-stack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"detect-stack.js","sourceRoot":"","sources":["../../../src/lib/detect-stack.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,81 @@
|
|
|
1
|
-
import type { MetaobjectsGenConfig } from "@metaobjectsdev/codegen-ts";
|
|
1
|
+
import type { MetaDataTypeProvider, MetaobjectsGenConfig } from "@metaobjectsdev/codegen-ts";
|
|
2
|
+
import { type Collection } from "@metaobjectsdev/sdk";
|
|
3
|
+
/**
|
|
4
|
+
* The `loadMemory` options a project's gen config contributes.
|
|
5
|
+
*
|
|
6
|
+
* One helper rather than a spread pair repeated at each of the eight load sites,
|
|
7
|
+
* because threading one of these and forgetting the other is exactly how #333
|
|
8
|
+
* happened: `providers` reached every command while `libraries` reached none, so a
|
|
9
|
+
* generator was registered FOR the CLI with its input unreachable THROUGH it. Adding a
|
|
10
|
+
* third contribution later should not mean finding eight call sites again.
|
|
11
|
+
*
|
|
12
|
+
* Conditional spreads honour `exactOptionalPropertyTypes` — a key is omitted rather
|
|
13
|
+
* than set to `undefined`, which is what lets `loadMemory` apply its own defaults.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadMemoryOptionsFrom(cfg: Pick<MetaobjectsGenConfig, "providers" | "libraries"> | undefined): {
|
|
16
|
+
providers?: readonly MetaDataTypeProvider[];
|
|
17
|
+
libraries?: readonly string[];
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* The directory whose `metaobjects.config.ts` governs a run started in `startDir` —
|
|
21
|
+
* the nearest ancestor carrying that file, `fallback` when there is none.
|
|
22
|
+
*
|
|
23
|
+
* This is a SECOND walk, deliberately separate from `resolveCollection`'s. The two
|
|
24
|
+
* files answer different questions and design §4.6 already says so: `.metaobjects/
|
|
25
|
+
* config.json` declares where metadata comes from — port-neutral, read by all five
|
|
26
|
+
* CLIs, and reasonably repo-global in a polyglot monorepo — while
|
|
27
|
+
* `metaobjects.config.ts` declares how THIS TypeScript package generates code. Reading
|
|
28
|
+
* the second from the directory that carried the first (#326) meant a Maven- or
|
|
29
|
+
* pip-rooted repo with a JS app underneath could not run `meta gen` at all: the
|
|
30
|
+
* collection resolved to the repo root, and the app's config, sitting in the very
|
|
31
|
+
* directory the command was invoked from, was never looked at.
|
|
32
|
+
*
|
|
33
|
+
* Nearest wins, which is what keeps the opposite arm — the divergence commit
|
|
34
|
+
* 0c8fd136e fixed — closed: a run from a subdirectory that declares NO config of its
|
|
35
|
+
* own walks up to the project root's, exactly as before, rather than silently
|
|
36
|
+
* defaulting `columnNamingStrategy` and emitting a migration that renames every
|
|
37
|
+
* column. When the two files sit together, as they do in every `meta init` project,
|
|
38
|
+
* this walk and the collection walk return the same directory by construction.
|
|
39
|
+
*
|
|
40
|
+
* The `fallback` is the collection's directory, so a project with no
|
|
41
|
+
* `metaobjects.config.ts` anywhere keeps today's diagnostics unchanged: this walk can
|
|
42
|
+
* only ever move the answer CLOSER to the invocation, never further away.
|
|
43
|
+
*
|
|
44
|
+
* Boundaries mirror `discoverCollectionRoot` (sdk `discovery.ts`): the marker is
|
|
45
|
+
* checked before `.git`, so a repo-root project sharing its directory with `.git` is
|
|
46
|
+
* still reachable from any subdirectory, and the walk stops there so a monorepo can
|
|
47
|
+
* never adopt a parent checkout's codegen config.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveGenConfigDir(startDir: string, fallback: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* The collection a TypeScript package GENERATES FROM (#340).
|
|
52
|
+
*
|
|
53
|
+
* #326/#327 established that the two config files answer different questions, and gave
|
|
54
|
+
* `metaobjects.config.ts` its own walk. This is the remaining half of the same split:
|
|
55
|
+
* a sub-project whose TS config sits below the collection root was still LOADING the
|
|
56
|
+
* ancestor's whole source set, so its `src/generated` absorbed metadata belonging to
|
|
57
|
+
* unrelated parts of the repository — one adopter's web app went from 376 files to 831,
|
|
58
|
+
* the surplus being another module's server-side prompt payload DTOs. It fails OPEN
|
|
59
|
+
* (`tsc` passes, tests pass), so the only symptom is a directory that quietly doubled.
|
|
60
|
+
*
|
|
61
|
+
* The rule: an ancestor `.metaobjects/config.json` is the DEFAULT for a package that
|
|
62
|
+
* declares no sources of its own, never an ADDITION to one that does. So when the TS
|
|
63
|
+
* config sits somewhere the collection did not, that directory is re-resolved as a
|
|
64
|
+
* collection in its own right, and it wins if it actually resolves any metadata.
|
|
65
|
+
*
|
|
66
|
+
* It can only ever NARROW, and only in a shape that could not have worked before:
|
|
67
|
+
* - the two directories coincide (every `meta init` project, and every run from a
|
|
68
|
+
* project root) — returns the original, untouched, without a second resolve;
|
|
69
|
+
* - the sub-project declares no sources — the pinned resolve throws
|
|
70
|
+
* `ERR_SOURCE_UNRESOLVED` or comes back empty, and the ancestor stands, so a
|
|
71
|
+
* package that genuinely lives off an ancestor tree keeps working;
|
|
72
|
+
* - the sub-project has its own metadata — it generates from exactly that, which is
|
|
73
|
+
* what it did before source resolution learned to walk upward.
|
|
74
|
+
*
|
|
75
|
+
* Deliberately NOT applied to `.metaobjects/` STATE. Migrations, snapshots and the
|
|
76
|
+
* operational block stay keyed on the discovered collection's directory (#326 settled
|
|
77
|
+
* that); this narrows what is LOADED, and nothing about where state lives.
|
|
78
|
+
*/
|
|
79
|
+
export declare function resolveGenCollection(collection: Collection, genConfigDir: string): Promise<Collection>;
|
|
2
80
|
export declare function loadMetaobjectsConfig(projectRoot: string): Promise<MetaobjectsGenConfig>;
|
|
3
81
|
//# sourceMappingURL=load-metaobjects-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-metaobjects-config.d.ts","sourceRoot":"","sources":["../../../src/lib/load-metaobjects-config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"load-metaobjects-config.d.ts","sourceRoot":"","sources":["../../../src/lib/load-metaobjects-config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAC7F,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAgJzE;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,IAAI,CAAC,oBAAoB,EAAE,WAAW,GAAG,WAAW,CAAC,GAAG,SAAS,GACrE;IAAE,SAAS,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAKhF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAU9E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,UAAU,CAAC,CAUrB;AAED,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0I9F"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { existsSync, readdirSync, unlinkSync } from "node:fs";
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
|
-
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { randomBytes } from "node:crypto";
|
|
7
7
|
import { createJiti } from "jiti";
|
|
8
|
+
import { resolveCollection } from "@metaobjectsdev/sdk";
|
|
8
9
|
const CONFIG_FILE = "metaobjects.config.ts";
|
|
9
10
|
// Prefix for the transient, pre-processed config the loader writes next to the
|
|
10
11
|
// user's config (see the rewrite step below). Normally deleted in a finally
|
|
@@ -137,6 +138,110 @@ function rewriteImportSpecifiers(source, aliasMap) {
|
|
|
137
138
|
}
|
|
138
139
|
return result;
|
|
139
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* The `loadMemory` options a project's gen config contributes.
|
|
143
|
+
*
|
|
144
|
+
* One helper rather than a spread pair repeated at each of the eight load sites,
|
|
145
|
+
* because threading one of these and forgetting the other is exactly how #333
|
|
146
|
+
* happened: `providers` reached every command while `libraries` reached none, so a
|
|
147
|
+
* generator was registered FOR the CLI with its input unreachable THROUGH it. Adding a
|
|
148
|
+
* third contribution later should not mean finding eight call sites again.
|
|
149
|
+
*
|
|
150
|
+
* Conditional spreads honour `exactOptionalPropertyTypes` — a key is omitted rather
|
|
151
|
+
* than set to `undefined`, which is what lets `loadMemory` apply its own defaults.
|
|
152
|
+
*/
|
|
153
|
+
export function loadMemoryOptionsFrom(cfg) {
|
|
154
|
+
return {
|
|
155
|
+
...(cfg?.providers !== undefined ? { providers: cfg.providers } : {}),
|
|
156
|
+
...(cfg?.libraries !== undefined ? { libraries: cfg.libraries } : {}),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The directory whose `metaobjects.config.ts` governs a run started in `startDir` —
|
|
161
|
+
* the nearest ancestor carrying that file, `fallback` when there is none.
|
|
162
|
+
*
|
|
163
|
+
* This is a SECOND walk, deliberately separate from `resolveCollection`'s. The two
|
|
164
|
+
* files answer different questions and design §4.6 already says so: `.metaobjects/
|
|
165
|
+
* config.json` declares where metadata comes from — port-neutral, read by all five
|
|
166
|
+
* CLIs, and reasonably repo-global in a polyglot monorepo — while
|
|
167
|
+
* `metaobjects.config.ts` declares how THIS TypeScript package generates code. Reading
|
|
168
|
+
* the second from the directory that carried the first (#326) meant a Maven- or
|
|
169
|
+
* pip-rooted repo with a JS app underneath could not run `meta gen` at all: the
|
|
170
|
+
* collection resolved to the repo root, and the app's config, sitting in the very
|
|
171
|
+
* directory the command was invoked from, was never looked at.
|
|
172
|
+
*
|
|
173
|
+
* Nearest wins, which is what keeps the opposite arm — the divergence commit
|
|
174
|
+
* 0c8fd136e fixed — closed: a run from a subdirectory that declares NO config of its
|
|
175
|
+
* own walks up to the project root's, exactly as before, rather than silently
|
|
176
|
+
* defaulting `columnNamingStrategy` and emitting a migration that renames every
|
|
177
|
+
* column. When the two files sit together, as they do in every `meta init` project,
|
|
178
|
+
* this walk and the collection walk return the same directory by construction.
|
|
179
|
+
*
|
|
180
|
+
* The `fallback` is the collection's directory, so a project with no
|
|
181
|
+
* `metaobjects.config.ts` anywhere keeps today's diagnostics unchanged: this walk can
|
|
182
|
+
* only ever move the answer CLOSER to the invocation, never further away.
|
|
183
|
+
*
|
|
184
|
+
* Boundaries mirror `discoverCollectionRoot` (sdk `discovery.ts`): the marker is
|
|
185
|
+
* checked before `.git`, so a repo-root project sharing its directory with `.git` is
|
|
186
|
+
* still reachable from any subdirectory, and the walk stops there so a monorepo can
|
|
187
|
+
* never adopt a parent checkout's codegen config.
|
|
188
|
+
*/
|
|
189
|
+
export function resolveGenConfigDir(startDir, fallback) {
|
|
190
|
+
let dir = resolve(startDir);
|
|
191
|
+
for (;;) {
|
|
192
|
+
if (existsSync(join(dir, CONFIG_FILE)))
|
|
193
|
+
return dir;
|
|
194
|
+
if (existsSync(join(dir, ".git")))
|
|
195
|
+
break;
|
|
196
|
+
const parent = dirname(dir);
|
|
197
|
+
if (parent === dir)
|
|
198
|
+
break;
|
|
199
|
+
dir = parent;
|
|
200
|
+
}
|
|
201
|
+
return fallback;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* The collection a TypeScript package GENERATES FROM (#340).
|
|
205
|
+
*
|
|
206
|
+
* #326/#327 established that the two config files answer different questions, and gave
|
|
207
|
+
* `metaobjects.config.ts` its own walk. This is the remaining half of the same split:
|
|
208
|
+
* a sub-project whose TS config sits below the collection root was still LOADING the
|
|
209
|
+
* ancestor's whole source set, so its `src/generated` absorbed metadata belonging to
|
|
210
|
+
* unrelated parts of the repository — one adopter's web app went from 376 files to 831,
|
|
211
|
+
* the surplus being another module's server-side prompt payload DTOs. It fails OPEN
|
|
212
|
+
* (`tsc` passes, tests pass), so the only symptom is a directory that quietly doubled.
|
|
213
|
+
*
|
|
214
|
+
* The rule: an ancestor `.metaobjects/config.json` is the DEFAULT for a package that
|
|
215
|
+
* declares no sources of its own, never an ADDITION to one that does. So when the TS
|
|
216
|
+
* config sits somewhere the collection did not, that directory is re-resolved as a
|
|
217
|
+
* collection in its own right, and it wins if it actually resolves any metadata.
|
|
218
|
+
*
|
|
219
|
+
* It can only ever NARROW, and only in a shape that could not have worked before:
|
|
220
|
+
* - the two directories coincide (every `meta init` project, and every run from a
|
|
221
|
+
* project root) — returns the original, untouched, without a second resolve;
|
|
222
|
+
* - the sub-project declares no sources — the pinned resolve throws
|
|
223
|
+
* `ERR_SOURCE_UNRESOLVED` or comes back empty, and the ancestor stands, so a
|
|
224
|
+
* package that genuinely lives off an ancestor tree keeps working;
|
|
225
|
+
* - the sub-project has its own metadata — it generates from exactly that, which is
|
|
226
|
+
* what it did before source resolution learned to walk upward.
|
|
227
|
+
*
|
|
228
|
+
* Deliberately NOT applied to `.metaobjects/` STATE. Migrations, snapshots and the
|
|
229
|
+
* operational block stay keyed on the discovered collection's directory (#326 settled
|
|
230
|
+
* that); this narrows what is LOADED, and nothing about where state lives.
|
|
231
|
+
*/
|
|
232
|
+
export async function resolveGenCollection(collection, genConfigDir) {
|
|
233
|
+
if (resolve(genConfigDir) === resolve(collection.configDir))
|
|
234
|
+
return collection;
|
|
235
|
+
try {
|
|
236
|
+
const pinned = await resolveCollection(genConfigDir, { explicitDir: genConfigDir });
|
|
237
|
+
return pinned.files.length > 0 ? pinned : collection;
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
// The sub-project declares nothing resolvable of its own — inherit, exactly as a
|
|
241
|
+
// package with no config always has.
|
|
242
|
+
return collection;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
140
245
|
export async function loadMetaobjectsConfig(projectRoot) {
|
|
141
246
|
const fullPath = resolve(projectRoot, CONFIG_FILE);
|
|
142
247
|
if (!existsSync(fullPath)) {
|
|
@@ -238,6 +343,23 @@ export async function loadMetaobjectsConfig(projectRoot) {
|
|
|
238
343
|
if (!cfg || typeof cfg !== "object" || !Array.isArray(cfg.generators)) {
|
|
239
344
|
throw new Error(`metaobjects.config.ts at ${fullPath} did not export a valid MetaobjectsGenConfig (missing 'generators' array).`);
|
|
240
345
|
}
|
|
346
|
+
// An unknown `libraries` name is a hard config error naming the valid ones, while
|
|
347
|
+
// `librarySources` keeps skipping one silently for a programmatic caller. The two
|
|
348
|
+
// are deliberately different: an API caller asking for a package this version does
|
|
349
|
+
// not ship should still be able to load its own metadata, but a name a human typed
|
|
350
|
+
// into a config file is a mistake worth failing on — skipped, it resurfaces later as
|
|
351
|
+
// ERR_UNRESOLVED_SUPER pointing at the adopter's own metadata, which is the wrong
|
|
352
|
+
// place to send someone looking. Python's `project_config` draws the same line in
|
|
353
|
+
// the same place, and the two ports agreeing here is the point.
|
|
354
|
+
if (cfg.libraries !== undefined && cfg.libraries.length > 0) {
|
|
355
|
+
const { knownLibraryPackages } = await import("@metaobjectsdev/metadata/library");
|
|
356
|
+
const available = knownLibraryPackages();
|
|
357
|
+
const unknown = cfg.libraries.filter((n) => !available.includes(n));
|
|
358
|
+
if (unknown.length > 0) {
|
|
359
|
+
throw new Error(`metaobjects.config.ts at ${fullPath}: 'libraries' names unknown package(s) ` +
|
|
360
|
+
`${JSON.stringify(unknown)}; available: ${JSON.stringify(available)}.`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
241
363
|
return cfg;
|
|
242
364
|
}
|
|
243
365
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-metaobjects-config.js","sourceRoot":"","sources":["../../../src/lib/load-metaobjects-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"load-metaobjects-config.js","sourceRoot":"","sources":["../../../src/lib/load-metaobjects-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Project-relative path of the manifest — the one artifact of `.gen-state/` that is
|
|
2
|
+
* meant to be committed. */
|
|
3
|
+
export declare const HASH_MANIFEST_REL: string;
|
|
4
|
+
/**
|
|
5
|
+
* Warn once when the hash manifest is git-ignored, naming the fix.
|
|
6
|
+
*
|
|
7
|
+
* Silent when: it is tracked correctly, the project is not a git repository, git is
|
|
8
|
+
* unavailable, or no generated output has ever been produced (nothing to protect yet).
|
|
9
|
+
* Never throws, never blocks.
|
|
10
|
+
*/
|
|
11
|
+
export declare function warnIfManifestIgnored(cwd: string): void;
|
|
12
|
+
//# sourceMappingURL=manifest-ignored-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-ignored-check.d.ts","sourceRoot":"","sources":["../../../src/lib/manifest-ignored-check.ts"],"names":[],"mappings":"AAsBA;6BAC6B;AAC7B,eAAO,MAAM,iBAAiB,QAAqD,CAAC;AA4BpF;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAevD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Advisory: is the codegen hash manifest git-ignored?
|
|
2
|
+
//
|
|
3
|
+
// `.gen-state/.hashes.json` is what lets `meta gen` tell "this file is exactly what
|
|
4
|
+
// I wrote" from "somebody edited this" on a machine that did not generate it. If it
|
|
5
|
+
// is ignored, that knowledge never leaves the generating machine, and on every other
|
|
6
|
+
// machine a hand-edited generated file cannot be recognised as such.
|
|
7
|
+
//
|
|
8
|
+
// The reason this check exists rather than only a migration doc: the failure is
|
|
9
|
+
// INVISIBLE. A project with the manifest ignored looks completely normal — `meta gen`
|
|
10
|
+
// succeeds, output is correct — right up until a fresh clone refuses a wall of files
|
|
11
|
+
// or (before the fix) silently ate an edit. This repo's own 0.23.1 lesson was that a
|
|
12
|
+
// fix ships with the check that would have caught it, or it survives as folklore.
|
|
13
|
+
//
|
|
14
|
+
// Deliberately advisory. It cannot be an error: a project that genuinely does not
|
|
15
|
+
// commit generated output has no use for the manifest, and failing its build over an
|
|
16
|
+
// unused artifact would be wrong.
|
|
17
|
+
import { existsSync } from "node:fs";
|
|
18
|
+
import { spawnSync } from "node:child_process";
|
|
19
|
+
import { join } from "node:path";
|
|
20
|
+
import { log } from "./log.js";
|
|
21
|
+
/** Project-relative path of the manifest — the one artifact of `.gen-state/` that is
|
|
22
|
+
* meant to be committed. */
|
|
23
|
+
export const HASH_MANIFEST_REL = join(".metaobjects", ".gen-state", ".hashes.json");
|
|
24
|
+
/**
|
|
25
|
+
* Ask git whether `relPath` is ignored, or undefined when the question cannot be
|
|
26
|
+
* answered (not a repository, git missing).
|
|
27
|
+
*
|
|
28
|
+
* `check-ignore` is the only reliable answer: parsing `.gitignore` by hand would have
|
|
29
|
+
* to reimplement precedence, negation and nested ignore files — and the specific trap
|
|
30
|
+
* this check exists to catch (`.gen-state/` excluding a directory so a `!` negation
|
|
31
|
+
* inside it can never apply) is exactly the rule a hand-rolled parser gets wrong.
|
|
32
|
+
*/
|
|
33
|
+
function isGitIgnored(cwd, relPath) {
|
|
34
|
+
const gitBin = process.env.META_GEN_GIT ?? "git";
|
|
35
|
+
let res;
|
|
36
|
+
try {
|
|
37
|
+
res = spawnSync(gitBin, ["-C", cwd, "check-ignore", "-q", "--", relPath], {
|
|
38
|
+
encoding: "utf-8",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
if (res.error !== undefined)
|
|
45
|
+
return undefined;
|
|
46
|
+
// 0 = ignored, 1 = not ignored, 128 = not a git repo / other git error.
|
|
47
|
+
if (res.status === 0)
|
|
48
|
+
return true;
|
|
49
|
+
if (res.status === 1)
|
|
50
|
+
return false;
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Warn once when the hash manifest is git-ignored, naming the fix.
|
|
55
|
+
*
|
|
56
|
+
* Silent when: it is tracked correctly, the project is not a git repository, git is
|
|
57
|
+
* unavailable, or no generated output has ever been produced (nothing to protect yet).
|
|
58
|
+
* Never throws, never blocks.
|
|
59
|
+
*/
|
|
60
|
+
export function warnIfManifestIgnored(cwd) {
|
|
61
|
+
// Nothing generated yet ⇒ nothing at risk ⇒ nothing worth saying.
|
|
62
|
+
if (!existsSync(join(cwd, HASH_MANIFEST_REL)))
|
|
63
|
+
return;
|
|
64
|
+
if (isGitIgnored(cwd, HASH_MANIFEST_REL) !== true)
|
|
65
|
+
return;
|
|
66
|
+
log.warn(`${HASH_MANIFEST_REL} is git-ignored, so it never reaches another machine — ` +
|
|
67
|
+
`on a fresh clone or CI runner 'meta gen' cannot tell your hand edits from its ` +
|
|
68
|
+
`own stale output, and will refuse to overwrite rather than guess. Fix it in ` +
|
|
69
|
+
`.metaobjects/.gitignore by replacing '.gen-state/' with '.gen-state/*' plus ` +
|
|
70
|
+
`'!.gen-state/.hashes.json' (the glob matters — git will not descend into an ` +
|
|
71
|
+
`excluded directory, so a negation under '.gen-state/' can never apply), then ` +
|
|
72
|
+
`commit the manifest. If you deliberately do not commit generated output, ignore this.`);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=manifest-ignored-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-ignored-check.js","sourceRoot":"","sources":["../../../src/lib/manifest-ignored-check.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,oFAAoF;AACpF,oFAAoF;AACpF,qFAAqF;AACrF,qEAAqE;AACrE,EAAE;AACF,gFAAgF;AAChF,sFAAsF;AACtF,qFAAqF;AACrF,qFAAqF;AACrF,kFAAkF;AAClF,EAAE;AACF,kFAAkF;AAClF,qFAAqF;AACrF,kCAAkC;AAElC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B;6BAC6B;AAC7B,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,cAAc,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;AAEpF;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,GAAW,EAAE,OAAe;IAChD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,KAAK,CAAC;IACjD,IAAI,GAAG,CAAC;IACR,IAAI,CAAC;QACH,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;YACxE,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC9C,wEAAwE;IACxE,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,kEAAkE;IAClE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;QAAE,OAAO;IAEtD,IAAI,YAAY,CAAC,GAAG,EAAE,iBAAiB,CAAC,KAAK,IAAI;QAAE,OAAO;IAE1D,GAAG,CAAC,IAAI,CACN,GAAG,iBAAiB,yDAAyD;QAC3E,gFAAgF;QAChF,8EAA8E;QAC9E,8EAA8E;QAC9E,8EAA8E;QAC9E,+EAA+E;QAC/E,uFAAuF,CAC1F,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Collection } from "@metaobjectsdev/sdk";
|
|
2
|
+
import type { SchemaProvenance } from "@metaobjectsdev/migrate-ts";
|
|
3
|
+
/**
|
|
4
|
+
* Say what a declared `migrate.scope` left out, for `migrate` and `verify --db`
|
|
5
|
+
* alike.
|
|
6
|
+
*
|
|
7
|
+
* An excluded object produces neither a create nor a drop and is neither checked
|
|
8
|
+
* nor reported as drift, so without this line "no changes" and "no changes to the
|
|
9
|
+
* half of the model this run governs" read identically — and an unchecked table is
|
|
10
|
+
* indistinguishable from a checked-and-clean one.
|
|
11
|
+
*
|
|
12
|
+
* One sentence, one definition: the two commands say the same thing about the same
|
|
13
|
+
* declaration, and this is a string a user reads, so drift between two copies of it
|
|
14
|
+
* is drift the user sees.
|
|
15
|
+
*/
|
|
16
|
+
export declare function outOfScopeNote(command: string, names: readonly string[]): string;
|
|
17
|
+
/**
|
|
18
|
+
* The refusal for a `migrate.scope` that matches NOTHING it could govern.
|
|
19
|
+
*
|
|
20
|
+
* A scope matching zero of the objects that declare a table or view can never be
|
|
21
|
+
* what someone meant — it says "every table in this model belongs to somebody
|
|
22
|
+
* else", which is a project with no schema to migrate at all, expressed the hard
|
|
23
|
+
* way. In practice it is a typo'd or stale package pattern, or a scope over a
|
|
24
|
+
* package that holds only value objects and abstracts (shapes that can never
|
|
25
|
+
* contribute a table or view), and it is silent: migrate reports "no changes"
|
|
26
|
+
* while having compared nothing.
|
|
27
|
+
*
|
|
28
|
+
* It is also actively dangerous, which is why this is a refusal and not a warning.
|
|
29
|
+
* An empty expected side is what `diff` reads as "no model, govern the whole
|
|
30
|
+
* database" — the inversion `scopeExpectedSchema`'s `declaredSchemas` closes
|
|
31
|
+
* structurally (migrate-ts `scope.ts`). This is the second lock on the same door:
|
|
32
|
+
* the structural fix stops a wrong scope proposing a destructive change, and this
|
|
33
|
+
* stops the wrong scope going unnoticed in the first place.
|
|
34
|
+
*
|
|
35
|
+
* Returns the message to report, or `undefined` when there is nothing to refuse —
|
|
36
|
+
* no scope declared, or at least one table- or view-declaring object inside it.
|
|
37
|
+
* Callers report it and exit 2 (a configuration error), rather than this throwing,
|
|
38
|
+
* so it reads like every other config failure in these commands.
|
|
39
|
+
*/
|
|
40
|
+
export declare function migrateScopeMismatch(collection: Collection,
|
|
41
|
+
/**
|
|
42
|
+
* The UNSCOPED expected schema's provenance (migrate-ts
|
|
43
|
+
* `buildExpectedSchemaWithProvenance`) — qualified table/view name → declaring
|
|
44
|
+
* FQN. Supplied lazily because it is consulted only under a declared scope, so
|
|
45
|
+
* a project with no `migrate.scope` pays nothing for this check and its runs
|
|
46
|
+
* are byte-for-byte what they always were.
|
|
47
|
+
*/
|
|
48
|
+
provenance: () => SchemaProvenance): string | undefined;
|
|
49
|
+
//# sourceMappingURL=migrate-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-scope.d.ts","sourceRoot":"","sources":["../../../src/lib/migrate-scope.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAKhF;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,UAAU;AACtB;;;;;;GAMG;AACH,UAAU,EAAE,MAAM,gBAAgB,GACjC,MAAM,GAAG,SAAS,CA8BpB"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// What `meta migrate` and `meta verify --db` SAY about a declared `migrate.scope`.
|
|
2
|
+
//
|
|
3
|
+
// The scope itself needs no adapter: `resolveCollection` hands back
|
|
4
|
+
// `inMigrateScope` already in migrate-ts's predicate shape, so the pattern grammar
|
|
5
|
+
// lives in exactly one place (`matchesScope`, @metaobjectsdev/sdk) and `migrate` and
|
|
6
|
+
// `gen` cannot come to disagree about what `acme::platform::**` means.
|
|
7
|
+
//
|
|
8
|
+
// What DOES need one home is the user-facing language, and both commands import it
|
|
9
|
+
// from here: they govern the identical object set from one declaration, so a note
|
|
10
|
+
// or a refusal that drifted between them would be drift the user reads.
|
|
11
|
+
/**
|
|
12
|
+
* Say what a declared `migrate.scope` left out, for `migrate` and `verify --db`
|
|
13
|
+
* alike.
|
|
14
|
+
*
|
|
15
|
+
* An excluded object produces neither a create nor a drop and is neither checked
|
|
16
|
+
* nor reported as drift, so without this line "no changes" and "no changes to the
|
|
17
|
+
* half of the model this run governs" read identically — and an unchecked table is
|
|
18
|
+
* indistinguishable from a checked-and-clean one.
|
|
19
|
+
*
|
|
20
|
+
* One sentence, one definition: the two commands say the same thing about the same
|
|
21
|
+
* declaration, and this is a string a user reads, so drift between two copies of it
|
|
22
|
+
* is drift the user sees.
|
|
23
|
+
*/
|
|
24
|
+
export function outOfScopeNote(command, names) {
|
|
25
|
+
return (`meta ${command} — ${names.length} object(s) out-of-scope ` +
|
|
26
|
+
`(outside migrate.scope, governed elsewhere): ${names.join(", ")}`);
|
|
27
|
+
}
|
|
28
|
+
/** How many loaded FQNs to name in the refusal below — enough to show the shape
|
|
29
|
+
* an author's patterns have to match, short enough to stay readable. */
|
|
30
|
+
const EXAMPLE_FQN_CAP = 3;
|
|
31
|
+
/**
|
|
32
|
+
* The refusal for a `migrate.scope` that matches NOTHING it could govern.
|
|
33
|
+
*
|
|
34
|
+
* A scope matching zero of the objects that declare a table or view can never be
|
|
35
|
+
* what someone meant — it says "every table in this model belongs to somebody
|
|
36
|
+
* else", which is a project with no schema to migrate at all, expressed the hard
|
|
37
|
+
* way. In practice it is a typo'd or stale package pattern, or a scope over a
|
|
38
|
+
* package that holds only value objects and abstracts (shapes that can never
|
|
39
|
+
* contribute a table or view), and it is silent: migrate reports "no changes"
|
|
40
|
+
* while having compared nothing.
|
|
41
|
+
*
|
|
42
|
+
* It is also actively dangerous, which is why this is a refusal and not a warning.
|
|
43
|
+
* An empty expected side is what `diff` reads as "no model, govern the whole
|
|
44
|
+
* database" — the inversion `scopeExpectedSchema`'s `declaredSchemas` closes
|
|
45
|
+
* structurally (migrate-ts `scope.ts`). This is the second lock on the same door:
|
|
46
|
+
* the structural fix stops a wrong scope proposing a destructive change, and this
|
|
47
|
+
* stops the wrong scope going unnoticed in the first place.
|
|
48
|
+
*
|
|
49
|
+
* Returns the message to report, or `undefined` when there is nothing to refuse —
|
|
50
|
+
* no scope declared, or at least one table- or view-declaring object inside it.
|
|
51
|
+
* Callers report it and exit 2 (a configuration error), rather than this throwing,
|
|
52
|
+
* so it reads like every other config failure in these commands.
|
|
53
|
+
*/
|
|
54
|
+
export function migrateScopeMismatch(collection,
|
|
55
|
+
/**
|
|
56
|
+
* The UNSCOPED expected schema's provenance (migrate-ts
|
|
57
|
+
* `buildExpectedSchemaWithProvenance`) — qualified table/view name → declaring
|
|
58
|
+
* FQN. Supplied lazily because it is consulted only under a declared scope, so
|
|
59
|
+
* a project with no `migrate.scope` pays nothing for this check and its runs
|
|
60
|
+
* are byte-for-byte what they always were.
|
|
61
|
+
*/
|
|
62
|
+
provenance) {
|
|
63
|
+
const { inMigrateScope, migrateScopePatterns } = collection;
|
|
64
|
+
if (inMigrateScope === undefined)
|
|
65
|
+
return undefined;
|
|
66
|
+
// The declaring FQNs of every table and view the UNSCOPED model contributes —
|
|
67
|
+
// the same provenance `scopeExpectedSchema` decides scope on, so the refusal
|
|
68
|
+
// asks exactly the question the run answers. NOT the loaded object set: that
|
|
69
|
+
// counts value objects and abstracts, which can never declare a table or view
|
|
70
|
+
// (persistability derives from a declared/inherited writable source, never
|
|
71
|
+
// from a subtype — #248), so a scope over only those objects passed this
|
|
72
|
+
// refusal while governing zero tables. And not a fresh walk either: it would
|
|
73
|
+
// have to re-implement the builder's skip rules (abstract, TPH subtype, no
|
|
74
|
+
// writable source, `@unmanaged`) and would drift from them.
|
|
75
|
+
const fqns = [...new Set(provenance().values())];
|
|
76
|
+
// A model that declares no table or view at all is not a scope error: there is
|
|
77
|
+
// nothing for a pattern to govern, scoped or not, and an empty schema has its
|
|
78
|
+
// own (much louder) failure modes downstream.
|
|
79
|
+
if (fqns.length === 0)
|
|
80
|
+
return undefined;
|
|
81
|
+
if (fqns.some(inMigrateScope))
|
|
82
|
+
return undefined;
|
|
83
|
+
const patterns = JSON.stringify(migrateScopePatterns ?? []);
|
|
84
|
+
const examples = fqns.slice(0, EXAMPLE_FQN_CAP).join(", ");
|
|
85
|
+
const more = fqns.length > EXAMPLE_FQN_CAP ? `, …and ${fqns.length - EXAMPLE_FQN_CAP} more` : "";
|
|
86
|
+
return (`migrate.scope matched none of the ${fqns.length} object(s) declaring a table or view, ` +
|
|
87
|
+
`so this run would treat every one of them as another owner's and compare nothing. ` +
|
|
88
|
+
`Patterns: ${patterns}. Declaring a table or view: ${examples}${more}. ` +
|
|
89
|
+
`Fix the patterns in .metaobjects/config.json (migrate.scope), or remove the key to ` +
|
|
90
|
+
`govern everything the model declares.`);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=migrate-scope.js.map
|