@metaobjectsdev/cli 1.0.2 → 1.0.4-rc.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 +13 -5
- package/dist/src/commands/deps.d.ts +3 -0
- package/dist/src/commands/deps.d.ts.map +1 -0
- package/dist/src/commands/deps.js +200 -0
- package/dist/src/commands/deps.js.map +1 -0
- package/dist/src/commands/docs.d.ts.map +1 -1
- package/dist/src/commands/docs.js +19 -3
- package/dist/src/commands/docs.js.map +1 -1
- package/dist/src/commands/eject.d.ts +2 -1
- package/dist/src/commands/eject.d.ts.map +1 -1
- package/dist/src/commands/eject.js +235 -75
- package/dist/src/commands/eject.js.map +1 -1
- package/dist/src/commands/gen.d.ts.map +1 -1
- package/dist/src/commands/gen.js +173 -30
- package/dist/src/commands/gen.js.map +1 -1
- package/dist/src/commands/init.d.ts +5 -9
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +92 -402
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/migrate.d.ts.map +1 -1
- package/dist/src/commands/migrate.js +24 -19
- 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 +2 -1
- package/dist/src/commands/prompt-snapshot.js.map +1 -1
- package/dist/src/commands/verify.d.ts.map +1 -1
- package/dist/src/commands/verify.js +186 -29
- package/dist/src/commands/verify.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +97 -15
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib/advisory.d.ts +6 -0
- package/dist/src/lib/advisory.d.ts.map +1 -1
- package/dist/src/lib/advisory.js +10 -0
- package/dist/src/lib/advisory.js.map +1 -1
- package/dist/src/lib/agent-context-staleness.d.ts.map +1 -1
- package/dist/src/lib/agent-context-staleness.js +7 -1
- package/dist/src/lib/agent-context-staleness.js.map +1 -1
- package/dist/src/lib/args.d.ts +75 -3
- package/dist/src/lib/args.d.ts.map +1 -1
- package/dist/src/lib/args.js +54 -5
- package/dist/src/lib/args.js.map +1 -1
- package/dist/src/lib/catalog-listing.d.ts +92 -0
- package/dist/src/lib/catalog-listing.d.ts.map +1 -0
- package/dist/src/lib/catalog-listing.js +268 -0
- package/dist/src/lib/catalog-listing.js.map +1 -0
- package/dist/src/lib/catalog.d.ts +41 -0
- package/dist/src/lib/catalog.d.ts.map +1 -0
- package/dist/src/lib/catalog.js +89 -0
- package/dist/src/lib/catalog.js.map +1 -0
- package/dist/src/lib/collection-load-options.d.ts +13 -0
- package/dist/src/lib/collection-load-options.d.ts.map +1 -0
- package/dist/src/lib/collection-load-options.js +25 -0
- package/dist/src/lib/collection-load-options.js.map +1 -0
- package/dist/src/lib/dependency-sync.d.ts +170 -0
- package/dist/src/lib/dependency-sync.d.ts.map +1 -0
- package/dist/src/lib/dependency-sync.js +457 -0
- package/dist/src/lib/dependency-sync.js.map +1 -0
- package/dist/src/lib/install-set.d.ts +31 -0
- package/dist/src/lib/install-set.d.ts.map +1 -0
- package/dist/src/lib/install-set.js +103 -0
- package/dist/src/lib/install-set.js.map +1 -0
- package/dist/src/lib/library-eject.d.ts +79 -0
- package/dist/src/lib/library-eject.d.ts.map +1 -0
- package/dist/src/lib/library-eject.js +241 -0
- package/dist/src/lib/library-eject.js.map +1 -0
- package/dist/src/lib/library-listing.d.ts +63 -0
- package/dist/src/lib/library-listing.d.ts.map +1 -0
- package/dist/src/lib/library-listing.js +178 -0
- package/dist/src/lib/library-listing.js.map +1 -0
- package/dist/src/lib/library-prefix-advisory.d.ts +17 -0
- package/dist/src/lib/library-prefix-advisory.d.ts.map +1 -0
- package/dist/src/lib/library-prefix-advisory.js +67 -0
- package/dist/src/lib/library-prefix-advisory.js.map +1 -0
- package/dist/src/lib/load-metaobjects-config.d.ts +1 -2
- package/dist/src/lib/load-metaobjects-config.d.ts.map +1 -1
- package/dist/src/lib/load-metaobjects-config.js +11 -17
- package/dist/src/lib/load-metaobjects-config.js.map +1 -1
- package/dist/src/lib/migrate-scope.d.ts +32 -1
- package/dist/src/lib/migrate-scope.d.ts.map +1 -1
- package/dist/src/lib/migrate-scope.js +51 -3
- package/dist/src/lib/migrate-scope.js.map +1 -1
- package/dist/src/lib/overlay-lint.d.ts +37 -0
- package/dist/src/lib/overlay-lint.d.ts.map +1 -0
- package/dist/src/lib/overlay-lint.js +102 -0
- package/dist/src/lib/overlay-lint.js.map +1 -0
- package/dist/src/lib/requirement-check.d.ts +26 -3
- package/dist/src/lib/requirement-check.d.ts.map +1 -1
- package/dist/src/lib/requirement-check.js +71 -13
- package/dist/src/lib/requirement-check.js.map +1 -1
- package/package.json +10 -10
- package/src/commands/deps.ts +231 -0
- package/src/commands/docs.ts +19 -3
- package/src/commands/eject.ts +304 -90
- package/src/commands/gen.ts +189 -29
- package/src/commands/init.ts +95 -407
- package/src/commands/migrate.ts +26 -16
- package/src/commands/prompt-snapshot.ts +2 -1
- package/src/commands/verify.ts +213 -30
- package/src/index.ts +97 -15
- package/src/lib/advisory.ts +13 -0
- package/src/lib/agent-context-staleness.ts +7 -1
- package/src/lib/args.ts +118 -8
- package/src/lib/catalog-listing.ts +369 -0
- package/src/lib/catalog.ts +107 -0
- package/src/lib/collection-load-options.ts +42 -0
- package/src/lib/dependency-sync.ts +656 -0
- package/src/lib/install-set.ts +116 -0
- package/src/lib/library-eject.ts +298 -0
- package/src/lib/library-listing.ts +258 -0
- package/src/lib/library-prefix-advisory.ts +78 -0
- package/src/lib/load-metaobjects-config.ts +15 -21
- package/src/lib/migrate-scope.ts +59 -4
- package/src/lib/overlay-lint.ts +129 -0
- package/src/lib/requirement-check.ts +100 -14
package/src/index.ts
CHANGED
|
@@ -17,7 +17,7 @@ const VERSION = cliVersion();
|
|
|
17
17
|
* human text. It is named ONCE and used by both the warning below and the help
|
|
18
18
|
* text above, so the two cannot drift apart.
|
|
19
19
|
*/
|
|
20
|
-
const FORMAT_AWARE_COMMANDS: readonly string[] = ["gen", "verify", "migrate", "types"];
|
|
20
|
+
const FORMAT_AWARE_COMMANDS: readonly string[] = ["gen", "verify", "migrate", "types", "deps", "eject"];
|
|
21
21
|
|
|
22
22
|
const HELP_TEXT = `meta — MetaObjects CLI (v${VERSION})
|
|
23
23
|
|
|
@@ -32,10 +32,13 @@ COMMANDS:
|
|
|
32
32
|
gen [<entity>...] Codegen TS targets from your declared metadata
|
|
33
33
|
eject <generator> Copy a reference generator into codegen/generators/ to own it (any time after init)
|
|
34
34
|
eject --list List every ejectable generator name, grouped by package
|
|
35
|
+
deps sync [<name>...] Resolve declared dependencies (path transport): sync the committed
|
|
36
|
+
snapshot + sha256 lock (.metaobjects/deps/, .metaobjects/deps.lock.json)
|
|
37
|
+
deps list One line per locked dependency: name, version, hash, node/package summary
|
|
35
38
|
types [query] Search the metadata vocabulary (types, subtypes, @attrs) by name or description
|
|
36
39
|
export Flatten loaded metadata to one canonical JSON artifact
|
|
37
40
|
docs [<project-root>] --out <dir> Generate neutral metadata documentation (entity + template pages; --site for HTML site)
|
|
38
|
-
verify Drift gate — subverbs: --templates / --db / --codegen / --docs (bare = --templates)
|
|
41
|
+
verify Drift gate — subverbs: --templates / --db / --codegen / --docs / --deps (bare = --templates)
|
|
39
42
|
upgrade Rewrite retired metadata vocabulary (previews; --apply writes)
|
|
40
43
|
prompt-snapshot Snapshot rendered template.* output; --check gates drift
|
|
41
44
|
migrate Diff metadata vs live DB; emit migration SQL files
|
|
@@ -55,8 +58,14 @@ GLOBAL OPTIONS:
|
|
|
55
58
|
|
|
56
59
|
GEN FLAGS:
|
|
57
60
|
--dry-run Compute and print, don't write
|
|
58
|
-
--list Print the generator
|
|
59
|
-
|
|
61
|
+
--list Print the generator CATALOG (name, layer, tier, what it emits,
|
|
62
|
+
what to install) and exit. Codegen is opt-in: nothing runs until
|
|
63
|
+
you wire it, and this is where you choose. No config or metadata
|
|
64
|
+
required — add --format json for the same catalog, machine-readable.
|
|
65
|
+
--probe With --list: construct every catalog generator and dry-run it
|
|
66
|
+
against YOUR model, reporting how many files each would emit.
|
|
67
|
+
A count per generator beats any category label — and it
|
|
68
|
+
cannot go stale, because it runs the generators. Needs a project.
|
|
60
69
|
--baseline <default|adopt|fresh>
|
|
61
70
|
First-time-on-existing-file behavior. Default: refuse a file that
|
|
62
71
|
cannot be proved to be generated output. "adopt" records the files
|
|
@@ -94,6 +103,10 @@ VERIFY FLAGS (ADR-0021 D2 — explicit subverbs; combine any; exit 1 on ANY drif
|
|
|
94
103
|
run would emit; never reports an extra file, because docs.outDir
|
|
95
104
|
holds hand-written documentation MetaObjects did not write.
|
|
96
105
|
Needs metaobjects.config.ts; exit 2 if absent.
|
|
106
|
+
--deps Dependency drift — re-resolve each declared dependency and compare
|
|
107
|
+
its installed artifact's hash against .metaobjects/deps.lock.json
|
|
108
|
+
(the same check 'meta deps check' runs). Never part of the bare-verify
|
|
109
|
+
default — it needs the publisher reachable, which CI may not have.
|
|
97
110
|
--db <url> Schema drift — live DB URL enables the schema-drift gate.
|
|
98
111
|
Supports: file:, libsql:, postgres:, postgresql:. Omit to skip.
|
|
99
112
|
D1 has no URL — use --dialect d1 / --d1 <binding> instead.
|
|
@@ -108,6 +121,8 @@ VERIFY FLAGS (ADR-0021 D2 — explicit subverbs; combine any; exit 1 on ANY drif
|
|
|
108
121
|
--no-antipatterns Suppress the advisory "you hand-rolled what MetaObjects can
|
|
109
122
|
model" pass (aggregate/currency/enum hints; warnings only)
|
|
110
123
|
--no-requirement-lint Suppress the advisory requirement AUTHORING lint (not the gate)
|
|
124
|
+
--no-overlay-lint Suppress the advisory overlay-redeclaration AUTHORING lint
|
|
125
|
+
(never a gate — this lint can't fail the build)
|
|
111
126
|
--limit <n|all> How many advisory lines TEXT output prints per section before
|
|
112
127
|
it truncates (default 20). Never applies to --format
|
|
113
128
|
toon/json, which carry every finding and every diagnostic.
|
|
@@ -147,8 +162,14 @@ USAGE:
|
|
|
147
162
|
|
|
148
163
|
FLAGS:
|
|
149
164
|
--dry-run Compute and print, don't write
|
|
150
|
-
--list Print the generator
|
|
151
|
-
|
|
165
|
+
--list Print the generator CATALOG (name, layer, tier, what it emits,
|
|
166
|
+
what to install) and exit. Codegen is opt-in: nothing runs until
|
|
167
|
+
you wire it, and this is where you choose. No config or metadata
|
|
168
|
+
required — add --format json for the same catalog, machine-readable.
|
|
169
|
+
--probe With --list: construct every catalog generator and dry-run it
|
|
170
|
+
against YOUR model, reporting how many files each would emit.
|
|
171
|
+
A count per generator beats any category label — and it cannot go
|
|
172
|
+
stale, because it runs the generators. Needs a project.
|
|
152
173
|
--baseline <default|adopt|fresh>
|
|
153
174
|
First-time-on-existing-file behavior. Default: refuse a file that
|
|
154
175
|
cannot be proved to be generated output. "adopt" records the files
|
|
@@ -174,23 +195,65 @@ limit on the machine-readable result.
|
|
|
174
195
|
|
|
175
196
|
NOTE: outDir, dialect, dbImport, extStyle are read from metaobjects.config.ts
|
|
176
197
|
`,
|
|
177
|
-
eject: `meta eject — copy
|
|
198
|
+
eject: `meta eject — copy reference generators into your repo so you own them
|
|
178
199
|
|
|
179
200
|
USAGE:
|
|
180
|
-
meta eject <name
|
|
201
|
+
meta eject <name>... Copy each generator into codegen/generators/<name>.ts
|
|
181
202
|
meta eject --list List every ejectable generator name, grouped by package
|
|
182
203
|
|
|
204
|
+
Codegen is opt-in — \`meta init\` wires nothing — so this is the door every generator
|
|
205
|
+
you run comes through. Take several at once: the install set is CONSOLIDATED, so
|
|
206
|
+
\`meta eject form hooks grid\` prints one install line, not three. An unknown name
|
|
207
|
+
refuses the whole call and copies nothing.
|
|
208
|
+
|
|
183
209
|
FLAGS:
|
|
184
210
|
--list List ejectable generators instead of copying one
|
|
185
211
|
--force Overwrite an already-ejected file (default: never clobber)
|
|
212
|
+
--format <toon|json|text> Output format (global flag). The structured form carries
|
|
213
|
+
each file's wire lines, the consolidated install set and the
|
|
214
|
+
config keys the ejected generators read.
|
|
186
215
|
--help, -h Print this help
|
|
187
216
|
|
|
188
|
-
\`meta init\` copies
|
|
189
|
-
|
|
190
|
-
the
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
217
|
+
\`meta init\` copies NO generators — codegen is opt-in, and codegen/generators/
|
|
218
|
+
starts empty on purpose. Everything you run comes through here (ADR-0034
|
|
219
|
+
scaffold-and-own): the file is YOURS to edit, and \`meta gen\` runs your copy, not
|
|
220
|
+
the package's. It prints the import line and the entry to add in
|
|
221
|
+
metaobjects.config.ts, and never overwrites a file you already own without --force.
|
|
222
|
+
|
|
223
|
+
Find names with \`meta gen --list\` — add --probe to see how many files each would
|
|
224
|
+
emit for your model.
|
|
225
|
+
`,
|
|
226
|
+
deps: `meta deps — sync a declared metadata dependency's committed snapshot
|
|
227
|
+
|
|
228
|
+
USAGE:
|
|
229
|
+
meta deps sync [<name>...] Resolve each declared dependency (path transport only in
|
|
230
|
+
this release — npm/python refuse by name), validate its
|
|
231
|
+
manifest + artifact, copy it into .metaobjects/deps/<name>/,
|
|
232
|
+
and pin it in .metaobjects/deps.lock.json. Naming one or more
|
|
233
|
+
<name>s syncs only those; bare 'sync' syncs everything
|
|
234
|
+
declared. A dependency removed from config is PRUNED from
|
|
235
|
+
the lock and its snapshot dir deleted, every run.
|
|
236
|
+
meta deps list One line per locked dependency: name, version, hash8,
|
|
237
|
+
node count, packages.
|
|
238
|
+
meta deps check Re-resolve each declared dependency (path transport, same
|
|
239
|
+
as sync steps 1-2) and compare its INSTALLED artifact's hash
|
|
240
|
+
against .metaobjects/deps.lock.json. Read-only — never
|
|
241
|
+
touches the lock or the snapshot. Exits 1 if any dependency
|
|
242
|
+
has drifted or cannot be resolved (ERR_DEPENDENCY_UPSTREAM_DRIFT).
|
|
243
|
+
|
|
244
|
+
FLAGS:
|
|
245
|
+
--dry-run Plan and report; write nothing (sync only)
|
|
246
|
+
--format <toon|json|text> Output format (global flag; default toon off-TTY)
|
|
247
|
+
--help, -h Print this help
|
|
248
|
+
|
|
249
|
+
Only the "path" transport resolves in this release — a "npm"/"python" dependency spec is
|
|
250
|
+
valid config (reserved for a future toolchain) but 'meta deps sync' refuses it by name:
|
|
251
|
+
"transport \`npm\` is not supported by this toolchain yet; use \`path\`".
|
|
252
|
+
|
|
253
|
+
The lock is the ONLY thing 'meta deps sync' writes to besides the snapshot directory —
|
|
254
|
+
sync never touches your own metadata files. 'meta deps check' compares the lock against
|
|
255
|
+
what is installed right now (the same check 'meta verify --deps' runs); 'meta deps sync'
|
|
256
|
+
only ever compares against what config DECLARES.
|
|
194
257
|
`,
|
|
195
258
|
verify: `meta verify — drift gate (templates / DB schema / codegen / migration replay)
|
|
196
259
|
|
|
@@ -210,6 +273,12 @@ FLAGS:
|
|
|
210
273
|
a namespace MetaObjects owns); the count of exempt pages is
|
|
211
274
|
reported either way, and a run where every page is ignored is
|
|
212
275
|
refused rather than reported clean.
|
|
276
|
+
--deps Dependency drift — re-resolve each declared dependency exactly as
|
|
277
|
+
'meta deps check' does and compare its installed artifact's hash
|
|
278
|
+
against .metaobjects/deps.lock.json. Exits 1 if any dependency has
|
|
279
|
+
drifted or cannot be resolved (ERR_DEPENDENCY_UPSTREAM_DRIFT). NEVER
|
|
280
|
+
part of the bare-verify default — it needs the publisher reachable,
|
|
281
|
+
which CI may not have.
|
|
213
282
|
--db <url> Schema drift — live DB URL enables the schema-drift gate.
|
|
214
283
|
Supports: file:, libsql:, postgres:, postgresql:
|
|
215
284
|
D1 has no URL — use --dialect d1 / --d1 <binding> instead.
|
|
@@ -237,6 +306,8 @@ FLAGS:
|
|
|
237
306
|
migrating a model onto a registered provider.
|
|
238
307
|
--no-antipatterns Suppress the advisory "hand-rolled what MetaObjects can model" pass
|
|
239
308
|
--no-requirement-lint Suppress the advisory requirement AUTHORING lint (not the gate)
|
|
309
|
+
--no-overlay-lint Suppress the advisory overlay-redeclaration AUTHORING lint —
|
|
310
|
+
never a gate; this lint can't fail the build
|
|
240
311
|
--limit <n|all> Advisory lines TEXT output prints PER SECTION before truncating
|
|
241
312
|
(default 20; per-section so the authoring lint can never push
|
|
242
313
|
the gate's own warnings off the end)
|
|
@@ -258,6 +329,13 @@ lint in its own section: names that are not addressable, prose slots holding one
|
|
|
258
329
|
sentence twice, content written where no surface reads it. Warnings only — it can
|
|
259
330
|
never fail the build. Opt out with --no-requirement-lint or META_NO_REQUIREMENT_LINT=1.
|
|
260
331
|
The requirements GATE itself (dangling refs, link floor, levels) always runs.
|
|
332
|
+
|
|
333
|
+
verify also prints an ADVISORY overlay authoring lint, in its own section: a
|
|
334
|
+
top-level declaration redeclared in two or more files where more than one
|
|
335
|
+
redeclaration lacks 'overlay: true' — today's default merge rule reuses it
|
|
336
|
+
silently, but the same unflagged redeclaration silently becomes a NEW object
|
|
337
|
+
the day the target is renamed or removed upstream. Warnings only — it can
|
|
338
|
+
never fail the build. Opt out with --no-overlay-lint or META_NO_OVERLAY_LINT=1.
|
|
261
339
|
`,
|
|
262
340
|
export: `meta export — flatten loaded metadata to one canonical JSON artifact
|
|
263
341
|
|
|
@@ -528,7 +606,11 @@ export async function run(argv: string[]): Promise<number> {
|
|
|
528
606
|
}
|
|
529
607
|
case "eject": {
|
|
530
608
|
const { ejectCommand } = await import("./commands/eject.js");
|
|
531
|
-
return ejectCommand(rest, cwd);
|
|
609
|
+
return ejectCommand(rest, cwd, fmt);
|
|
610
|
+
}
|
|
611
|
+
case "deps": {
|
|
612
|
+
const { depsCommand } = await import("./commands/deps.js");
|
|
613
|
+
return depsCommand(rest, cwd, fmt);
|
|
532
614
|
}
|
|
533
615
|
case "export": {
|
|
534
616
|
const { exportCommand } = await import("./commands/export.js");
|
package/src/lib/advisory.ts
CHANGED
|
@@ -150,6 +150,19 @@ export function removedPropRows(findings: readonly RemovedPropFinding[]): Adviso
|
|
|
150
150
|
}));
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
/** FR-043 §3.5 findings in the same row shape. */
|
|
154
|
+
export function libraryPrefixRows(
|
|
155
|
+
findings: readonly { file: string; fqn: string; message: string }[],
|
|
156
|
+
): AdvisoryFindingRow[] {
|
|
157
|
+
return findings.map((f) => ({
|
|
158
|
+
file: f.file,
|
|
159
|
+
line: 0,
|
|
160
|
+
rule: "library-prefix-unprovenanced",
|
|
161
|
+
construct: f.fqn,
|
|
162
|
+
message: f.message,
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
|
|
153
166
|
// ---------------------------------------------------------------------------
|
|
154
167
|
// text output
|
|
155
168
|
// ---------------------------------------------------------------------------
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
|
|
3
|
+
// The agent-context subpath, not the root barrel: `@metaobjectsdev/sdk` exports TWO
|
|
4
|
+
// types named `Manifest` — this one (the scaffolded agent context) via `export *`,
|
|
5
|
+
// and FR-023's `metaobjects.pkg.json` explicitly. An explicit export shadows a
|
|
6
|
+
// star one, so the root barrel now hands out the dependency manifest under this
|
|
7
|
+
// name. `init.ts` already imports these from the subpath; this was the last site
|
|
8
|
+
// reading them from the root.
|
|
9
|
+
import { AGENT_CONTEXT_MANIFEST_PATH, agentContextStaleness, type Manifest } from "@metaobjectsdev/sdk/agent-context";
|
|
4
10
|
import { cliVersion } from "./version.js";
|
|
5
11
|
import { log } from "./log.js";
|
|
6
12
|
|
package/src/lib/args.ts
CHANGED
|
@@ -107,6 +107,12 @@ export interface GenFlags {
|
|
|
107
107
|
/** ADR-0021 D3 — print the stable-name generator registry and exit without
|
|
108
108
|
* running codegen. */
|
|
109
109
|
list: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* `--list` only: construct every catalog generator and dry-run it against THIS
|
|
112
|
+
* project's model, reporting a real file count per generator. Needs a project;
|
|
113
|
+
* plain `--list` deliberately does not (it describes the installed engine).
|
|
114
|
+
*/
|
|
115
|
+
probe: boolean;
|
|
110
116
|
/** Suppress the advisory anti-pattern (verify-as-teacher) pass. */
|
|
111
117
|
noAntipatterns: boolean;
|
|
112
118
|
/**
|
|
@@ -122,6 +128,7 @@ export const GEN_OPTIONS = {
|
|
|
122
128
|
"dry-run": { type: "boolean", default: false },
|
|
123
129
|
"baseline": { type: "string" },
|
|
124
130
|
"list": { type: "boolean", default: false },
|
|
131
|
+
"probe": { type: "boolean", default: false },
|
|
125
132
|
"no-antipatterns": { type: "boolean", default: false },
|
|
126
133
|
"limit": { type: "string" },
|
|
127
134
|
} as const;
|
|
@@ -149,6 +156,7 @@ export function parseGenArgs(argv: string[]): GenFlags {
|
|
|
149
156
|
entities: positionals,
|
|
150
157
|
baseline: (baselineRaw as "default" | "fresh" | "adopt" | undefined) ?? "default",
|
|
151
158
|
list: !!values.list,
|
|
159
|
+
probe: !!values.probe,
|
|
152
160
|
noAntipatterns: !!values["no-antipatterns"],
|
|
153
161
|
// Throws on a bad value; the command layer reports it and exits 2, exactly as
|
|
154
162
|
// it does for --baseline above.
|
|
@@ -296,7 +304,17 @@ export interface VerifyFlags {
|
|
|
296
304
|
* read as that flag's opposite rather than as a replay depth.
|
|
297
305
|
*/
|
|
298
306
|
replaySnapshot: boolean;
|
|
299
|
-
/**
|
|
307
|
+
/**
|
|
308
|
+
* Dependency drift (Task 15, FR-023) — re-resolve each declared dependency and
|
|
309
|
+
* compare its installed artifact's hash against `.metaobjects/deps.lock.json`
|
|
310
|
+
* (the same comparison `meta deps check` runs). Deliberately NEVER part of the
|
|
311
|
+
* bare-verify default, unlike --templates: it needs the publisher reachable,
|
|
312
|
+
* which CI may not have. It is still counted in `anyExplicit`, same as
|
|
313
|
+
* --codegen/--docs, so a lone `verify --deps` does not ALSO run the template
|
|
314
|
+
* gate.
|
|
315
|
+
*/
|
|
316
|
+
deps: boolean;
|
|
317
|
+
/** Whether ANY explicit subverb flag (--templates/--db/--codegen/--docs/--deps/--replay*) was passed. */
|
|
300
318
|
anyExplicit: boolean;
|
|
301
319
|
/** Suppress the advisory anti-pattern (verify-as-teacher) pass. */
|
|
302
320
|
noAntipatterns: boolean;
|
|
@@ -308,6 +326,16 @@ export interface VerifyFlags {
|
|
|
308
326
|
* the half that CAN fail a build switched on. Same shape as --no-antipatterns.
|
|
309
327
|
*/
|
|
310
328
|
noRequirementLint: boolean;
|
|
329
|
+
/**
|
|
330
|
+
* Suppress the advisory overlay AUTHORING lint (FR-023 §11.1 item 4) — the
|
|
331
|
+
* finding that an unflagged cross-file redeclaration works today only
|
|
332
|
+
* because the parser's default merge rule reuses the existing node by
|
|
333
|
+
* (type, resolutionKey); it silently becomes a NEW object the day the
|
|
334
|
+
* target is renamed or removed upstream. Same shape as
|
|
335
|
+
* --no-requirement-lint: mutes the advisory half only, never a gate (this
|
|
336
|
+
* lint has no gate half at all — it can never fail the build).
|
|
337
|
+
*/
|
|
338
|
+
noOverlayLint: boolean;
|
|
311
339
|
/**
|
|
312
340
|
* ADR-0023 strict-attr load opt-OUT (#96). `verify` is strict-by-default — an
|
|
313
341
|
* undeclared/typo'd own `@attr` fails verify (ERR_UNKNOWN_ATTR). `--lax`
|
|
@@ -342,10 +370,12 @@ export const VERIFY_OPTIONS = {
|
|
|
342
370
|
templates: { type: "boolean", default: false },
|
|
343
371
|
codegen: { type: "boolean", default: false },
|
|
344
372
|
docs: { type: "boolean", default: false },
|
|
373
|
+
deps: { type: "boolean", default: false },
|
|
345
374
|
replay: { type: "boolean", default: false },
|
|
346
375
|
"replay-snapshot": { type: "boolean", default: false },
|
|
347
376
|
"no-antipatterns": { type: "boolean", default: false },
|
|
348
377
|
"no-requirement-lint": { type: "boolean", default: false },
|
|
378
|
+
"no-overlay-lint": { type: "boolean", default: false },
|
|
349
379
|
lax: { type: "boolean", default: false },
|
|
350
380
|
"d1": { type: "string" },
|
|
351
381
|
"remote": { type: "boolean", default: false },
|
|
@@ -397,15 +427,17 @@ export function parseVerifyArgs(argv: string[]): VerifyFlags {
|
|
|
397
427
|
const templates = !!values.templates;
|
|
398
428
|
const codegen = !!values.codegen;
|
|
399
429
|
const docs = !!values.docs;
|
|
430
|
+
const deps = !!values.deps;
|
|
400
431
|
const replay = !!values.replay;
|
|
401
432
|
const replaySnapshot = !!values["replay-snapshot"];
|
|
402
433
|
// --db is itself an explicit subverb selector: passing a connection URL means
|
|
403
434
|
// "run the schema-drift mode". So is `--dialect d1` (D1 has no --db connection
|
|
404
435
|
// URL — see the `d1` field doc above). The replay flags are subverbs too, and
|
|
405
436
|
// must be listed here or `meta verify --replay` would ALSO run the template gate
|
|
406
|
-
// as the bare-verify default.
|
|
437
|
+
// as the bare-verify default. --deps joins the same list for the same reason —
|
|
438
|
+
// it must NOT also be part of that default (see the VerifyFlags doc on `deps`).
|
|
407
439
|
const anyExplicit =
|
|
408
|
-
templates || codegen || docs || values.db !== undefined || dialect === "d1" || replay || replaySnapshot;
|
|
440
|
+
templates || codegen || docs || deps || values.db !== undefined || dialect === "d1" || replay || replaySnapshot;
|
|
409
441
|
|
|
410
442
|
return {
|
|
411
443
|
prompts: values.prompts,
|
|
@@ -416,11 +448,13 @@ export function parseVerifyArgs(argv: string[]): VerifyFlags {
|
|
|
416
448
|
templates,
|
|
417
449
|
codegen,
|
|
418
450
|
docs,
|
|
451
|
+
deps,
|
|
419
452
|
replay,
|
|
420
453
|
replaySnapshot,
|
|
421
454
|
anyExplicit,
|
|
422
455
|
noAntipatterns: !!values["no-antipatterns"],
|
|
423
456
|
noRequirementLint: !!values["no-requirement-lint"],
|
|
457
|
+
noOverlayLint: !!values["no-overlay-lint"],
|
|
424
458
|
lax: !!values.lax,
|
|
425
459
|
d1: values.d1 as string | undefined,
|
|
426
460
|
remote: !!values.remote,
|
|
@@ -576,8 +610,14 @@ export function parseMigrateArgs(argv: string[]): MigrateFlags {
|
|
|
576
610
|
// ---------------------------------------------------------------------------
|
|
577
611
|
|
|
578
612
|
export interface EjectFlags {
|
|
579
|
-
/**
|
|
580
|
-
|
|
613
|
+
/**
|
|
614
|
+
* The generator names to eject, in the order given. Empty when only --list was given.
|
|
615
|
+
*
|
|
616
|
+
* MANY, not one: choosing a client tier means `form hooks grid`, and three separate
|
|
617
|
+
* invocations produce three separate install lines for the same package. The
|
|
618
|
+
* consolidated install set is the point of taking them together.
|
|
619
|
+
*/
|
|
620
|
+
names: string[];
|
|
581
621
|
list: boolean;
|
|
582
622
|
/** Overwrite an already-ejected file; default false — eject never clobbers. */
|
|
583
623
|
force: boolean;
|
|
@@ -597,13 +637,83 @@ export function parseEjectArgs(argv: string[]): EjectFlags {
|
|
|
597
637
|
allowPositionals: true,
|
|
598
638
|
});
|
|
599
639
|
|
|
600
|
-
|
|
601
|
-
|
|
640
|
+
// `Set.add` returns the SET, which is always truthy — so the tempting
|
|
641
|
+
// `positionals.filter((n) => !seen.add(n))` never reports anything.
|
|
642
|
+
const seen = new Set<string>();
|
|
643
|
+
const duplicates: string[] = [];
|
|
644
|
+
for (const n of positionals) {
|
|
645
|
+
if (seen.has(n)) duplicates.push(n);
|
|
646
|
+
else seen.add(n);
|
|
647
|
+
}
|
|
648
|
+
if (duplicates.length > 0) {
|
|
649
|
+
throw new Error(
|
|
650
|
+
`meta eject: repeated generator name(s): ${[...new Set(duplicates)].join(", ")}`,
|
|
651
|
+
);
|
|
602
652
|
}
|
|
603
653
|
|
|
604
654
|
return {
|
|
605
|
-
|
|
655
|
+
names: positionals,
|
|
606
656
|
list: !!values.list,
|
|
607
657
|
force: !!values.force,
|
|
608
658
|
};
|
|
609
659
|
}
|
|
660
|
+
|
|
661
|
+
// ---------------------------------------------------------------------------
|
|
662
|
+
// deps flags — FR-023 Phase 1a Task 14
|
|
663
|
+
// ---------------------------------------------------------------------------
|
|
664
|
+
|
|
665
|
+
/** `meta deps`'s subcommand. `sync` and `list` are this task's; `check` is
|
|
666
|
+
* parsed (so the grammar and its usage errors are stable now) but not yet
|
|
667
|
+
* implemented — Task 15 wires its behavior. */
|
|
668
|
+
export type DepsSubverb = "sync" | "check" | "list";
|
|
669
|
+
|
|
670
|
+
const DEPS_SUBVERBS: readonly DepsSubverb[] = ["sync", "check", "list"];
|
|
671
|
+
|
|
672
|
+
export interface DepsFlags {
|
|
673
|
+
subverb: DepsSubverb;
|
|
674
|
+
/** Dependency names to narrow to — `sync`'s `[<name>…]`. Empty means "all
|
|
675
|
+
* declared dependencies." Accepted (and ignored) by every subverb rather
|
|
676
|
+
* than rejected outright: the positional grammar is one shape for all
|
|
677
|
+
* three, and only `sync` gives the list meaning today. */
|
|
678
|
+
names: string[];
|
|
679
|
+
/** `sync` only: plan and report, write nothing. */
|
|
680
|
+
dryRun: boolean;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/** The flag table `parseDepsArgs` parses. Exported so the help text can be
|
|
684
|
+
* gated against it. Deliberately carries no "format" key: `--format` is a
|
|
685
|
+
* GLOBAL flag `index.ts` strips from argv before any command's parser ever
|
|
686
|
+
* runs (see `MIGRATE_OPTIONS`'s "--migration-format, not --format" note
|
|
687
|
+
* above) — `meta deps` becomes format-aware by index.ts adding "deps" to
|
|
688
|
+
* `FORMAT_AWARE_COMMANDS` and passing the resolved `fmt` through, exactly as
|
|
689
|
+
* gen/verify/migrate do, not by re-declaring the flag here. */
|
|
690
|
+
export const DEPS_OPTIONS = {
|
|
691
|
+
"dry-run": { type: "boolean", default: false },
|
|
692
|
+
} as const;
|
|
693
|
+
|
|
694
|
+
export function parseDepsArgs(argv: string[]): DepsFlags {
|
|
695
|
+
const { values, positionals } = parseArgs({
|
|
696
|
+
args: argv,
|
|
697
|
+
options: DEPS_OPTIONS,
|
|
698
|
+
strict: true,
|
|
699
|
+
allowPositionals: true,
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
const [subverbRaw, ...names] = positionals;
|
|
703
|
+
if (subverbRaw === undefined) {
|
|
704
|
+
throw new Error(
|
|
705
|
+
"meta deps requires a subcommand: sync | check | list. Try `meta deps sync`.",
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
if (!DEPS_SUBVERBS.includes(subverbRaw as DepsSubverb)) {
|
|
709
|
+
throw new Error(
|
|
710
|
+
`meta deps: unknown subcommand "${subverbRaw}"; expected one of: ${DEPS_SUBVERBS.join(", ")}.`,
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
return {
|
|
715
|
+
subverb: subverbRaw as DepsSubverb,
|
|
716
|
+
names,
|
|
717
|
+
dryRun: !!values["dry-run"],
|
|
718
|
+
};
|
|
719
|
+
}
|