@metaobjectsdev/cli 1.0.12 → 1.1.0
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 +32 -22
- package/dist/bin/meta.js +14 -2
- package/dist/bin/meta.js.map +1 -1
- package/dist/src/commands/docs.d.ts +1 -14
- package/dist/src/commands/docs.d.ts.map +1 -1
- package/dist/src/commands/docs.js +11 -835
- package/dist/src/commands/docs.js.map +1 -1
- package/dist/src/commands/eject.d.ts +24 -1
- package/dist/src/commands/eject.d.ts.map +1 -1
- package/dist/src/commands/eject.js +240 -69
- package/dist/src/commands/eject.js.map +1 -1
- package/dist/src/commands/gen.d.ts +7 -0
- package/dist/src/commands/gen.d.ts.map +1 -1
- package/dist/src/commands/gen.js +91 -21
- package/dist/src/commands/gen.js.map +1 -1
- package/dist/src/commands/generator.js +2 -2
- package/dist/src/commands/generator.js.map +1 -1
- package/dist/src/commands/init.d.ts +7 -0
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +71 -36
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/migrate.d.ts +1 -1
- package/dist/src/commands/migrate.d.ts.map +1 -1
- package/dist/src/commands/migrate.js +224 -125
- package/dist/src/commands/migrate.js.map +1 -1
- package/dist/src/commands/types.d.ts.map +1 -1
- package/dist/src/commands/types.js +16 -2
- package/dist/src/commands/types.js.map +1 -1
- package/dist/src/commands/upgrade.d.ts.map +1 -1
- package/dist/src/commands/upgrade.js +4 -1
- package/dist/src/commands/upgrade.js.map +1 -1
- package/dist/src/commands/verify.d.ts.map +1 -1
- package/dist/src/commands/verify.js +189 -125
- package/dist/src/commands/verify.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +59 -72
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib/agent-context-staleness.d.ts +8 -1
- package/dist/src/lib/agent-context-staleness.d.ts.map +1 -1
- package/dist/src/lib/agent-context-staleness.js +20 -5
- package/dist/src/lib/agent-context-staleness.js.map +1 -1
- package/dist/src/lib/agent-schema.d.ts +9 -0
- package/dist/src/lib/agent-schema.d.ts.map +1 -0
- package/dist/src/lib/agent-schema.js +61 -0
- package/dist/src/lib/agent-schema.js.map +1 -0
- package/dist/src/lib/allow.d.ts +6 -0
- package/dist/src/lib/allow.d.ts.map +1 -1
- package/dist/src/lib/allow.js +49 -5
- package/dist/src/lib/allow.js.map +1 -1
- package/dist/src/lib/anti-patterns.d.ts.map +1 -1
- package/dist/src/lib/anti-patterns.js +4 -2
- package/dist/src/lib/anti-patterns.js.map +1 -1
- package/dist/src/lib/args.d.ts +51 -10
- package/dist/src/lib/args.d.ts.map +1 -1
- package/dist/src/lib/args.js +44 -18
- package/dist/src/lib/args.js.map +1 -1
- package/dist/src/lib/catalog-listing.d.ts +21 -1
- package/dist/src/lib/catalog-listing.d.ts.map +1 -1
- package/dist/src/lib/catalog-listing.js +85 -16
- package/dist/src/lib/catalog-listing.js.map +1 -1
- package/dist/src/lib/catalog.d.ts +30 -0
- package/dist/src/lib/catalog.d.ts.map +1 -1
- package/dist/src/lib/catalog.js +40 -5
- package/dist/src/lib/catalog.js.map +1 -1
- package/dist/src/lib/codegen-drift.d.ts +31 -2
- package/dist/src/lib/codegen-drift.d.ts.map +1 -1
- package/dist/src/lib/codegen-drift.js +109 -4
- package/dist/src/lib/codegen-drift.js.map +1 -1
- package/dist/src/lib/collection-load-options.d.ts +1 -1
- package/dist/src/lib/collection-load-options.d.ts.map +1 -1
- package/dist/src/lib/collection-load-options.js +1 -0
- package/dist/src/lib/collection-load-options.js.map +1 -1
- package/dist/src/lib/config.d.ts +4 -2
- package/dist/src/lib/config.d.ts.map +1 -1
- package/dist/src/lib/config.js +4 -2
- package/dist/src/lib/config.js.map +1 -1
- package/dist/src/lib/decimal-precision-advisory.d.ts +10 -0
- package/dist/src/lib/decimal-precision-advisory.d.ts.map +1 -0
- package/dist/src/lib/decimal-precision-advisory.js +34 -0
- package/dist/src/lib/decimal-precision-advisory.js.map +1 -0
- package/dist/src/lib/deprecation-lint.d.ts.map +1 -1
- package/dist/src/lib/deprecation-lint.js +17 -26
- package/dist/src/lib/deprecation-lint.js.map +1 -1
- package/dist/src/lib/docs-removed.d.ts +13 -0
- package/dist/src/lib/docs-removed.d.ts.map +1 -0
- package/dist/src/lib/docs-removed.js +31 -0
- package/dist/src/lib/docs-removed.js.map +1 -0
- package/dist/src/lib/docs-site-eject.d.ts +13 -0
- package/dist/src/lib/docs-site-eject.d.ts.map +1 -0
- package/dist/src/lib/docs-site-eject.js +40 -0
- package/dist/src/lib/docs-site-eject.js.map +1 -0
- package/dist/src/lib/field-lint.d.ts +25 -0
- package/dist/src/lib/field-lint.d.ts.map +1 -0
- package/dist/src/lib/field-lint.js +102 -0
- package/dist/src/lib/field-lint.js.map +1 -0
- package/dist/src/lib/fk-index-advisory.d.ts +1 -2
- package/dist/src/lib/fk-index-advisory.d.ts.map +1 -1
- package/dist/src/lib/fk-index-advisory.js +4 -3
- package/dist/src/lib/fk-index-advisory.js.map +1 -1
- package/dist/src/lib/format.d.ts +7 -0
- package/dist/src/lib/format.d.ts.map +1 -1
- package/dist/src/lib/format.js +13 -0
- package/dist/src/lib/format.js.map +1 -1
- package/dist/src/lib/gen-migrate-advice.d.ts +3 -1
- package/dist/src/lib/gen-migrate-advice.d.ts.map +1 -1
- package/dist/src/lib/gen-migrate-advice.js +3 -4
- package/dist/src/lib/gen-migrate-advice.js.map +1 -1
- package/dist/src/lib/install-set.d.ts +10 -1
- package/dist/src/lib/install-set.d.ts.map +1 -1
- package/dist/src/lib/install-set.js +20 -2
- package/dist/src/lib/install-set.js.map +1 -1
- package/dist/src/lib/load-metaobjects-config.d.ts +13 -11
- package/dist/src/lib/load-metaobjects-config.d.ts.map +1 -1
- package/dist/src/lib/load-metaobjects-config.js +53 -75
- package/dist/src/lib/load-metaobjects-config.js.map +1 -1
- package/dist/src/lib/manifest-ignored-check.d.ts +4 -1
- package/dist/src/lib/manifest-ignored-check.d.ts.map +1 -1
- package/dist/src/lib/manifest-ignored-check.js +9 -4
- package/dist/src/lib/manifest-ignored-check.js.map +1 -1
- package/dist/src/lib/output.d.ts +15 -0
- package/dist/src/lib/output.d.ts.map +1 -1
- package/dist/src/lib/output.js +9 -1
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/payload-field-tree.d.ts +4 -5
- package/dist/src/lib/payload-field-tree.d.ts.map +1 -1
- package/dist/src/lib/payload-field-tree.js +16 -31
- package/dist/src/lib/payload-field-tree.js.map +1 -1
- package/dist/src/lib/requirement-check.d.ts +7 -0
- package/dist/src/lib/requirement-check.d.ts.map +1 -1
- package/dist/src/lib/requirement-check.js +14 -7
- package/dist/src/lib/requirement-check.js.map +1 -1
- package/dist/src/lib/strict-args.d.ts +28 -0
- package/dist/src/lib/strict-args.d.ts.map +1 -0
- package/dist/src/lib/strict-args.js +49 -0
- package/dist/src/lib/strict-args.js.map +1 -0
- package/dist/src/lib/template-eject.d.ts +108 -0
- package/dist/src/lib/template-eject.d.ts.map +1 -0
- package/dist/src/lib/template-eject.js +438 -0
- package/dist/src/lib/template-eject.js.map +1 -0
- package/dist/src/lib/version.d.ts +9 -0
- package/dist/src/lib/version.d.ts.map +1 -1
- package/dist/src/lib/version.js +15 -0
- package/dist/src/lib/version.js.map +1 -1
- package/package.json +10 -10
- package/src/commands/docs.ts +11 -952
- package/src/commands/eject.ts +318 -73
- package/src/commands/gen.ts +94 -22
- package/src/commands/generator.ts +2 -2
- package/src/commands/init.ts +80 -38
- package/src/commands/migrate.ts +248 -117
- package/src/commands/types.ts +18 -2
- package/src/commands/upgrade.ts +5 -1
- package/src/commands/verify.ts +229 -136
- package/src/index.ts +59 -72
- package/src/lib/agent-context-staleness.ts +20 -5
- package/src/lib/agent-schema.ts +74 -0
- package/src/lib/allow.ts +57 -6
- package/src/lib/anti-patterns.ts +4 -2
- package/src/lib/args.ts +83 -28
- package/src/lib/catalog-listing.ts +105 -25
- package/src/lib/catalog.ts +51 -6
- package/src/lib/codegen-drift.ts +138 -3
- package/src/lib/collection-load-options.ts +2 -1
- package/src/lib/config.ts +5 -3
- package/src/lib/decimal-precision-advisory.ts +50 -0
- package/src/lib/deprecation-lint.ts +16 -24
- package/src/lib/docs-removed.ts +41 -0
- package/src/lib/docs-site-eject.ts +48 -0
- package/src/lib/field-lint.ts +122 -0
- package/src/lib/fk-index-advisory.ts +4 -4
- package/src/lib/format.ts +12 -0
- package/src/lib/gen-migrate-advice.ts +6 -4
- package/src/lib/install-set.ts +20 -1
- package/src/lib/load-metaobjects-config.ts +57 -78
- package/src/lib/manifest-ignored-check.ts +14 -10
- package/src/lib/output.ts +18 -1
- package/src/lib/payload-field-tree.ts +18 -35
- package/src/lib/requirement-check.ts +21 -6
- package/src/lib/strict-args.ts +52 -0
- package/src/lib/template-eject.ts +526 -0
- package/src/lib/version.ts +18 -0
- package/dist/src/lib/docs-drift.d.ts +0 -42
- package/dist/src/lib/docs-drift.d.ts.map +0 -1
- package/dist/src/lib/docs-drift.js +0 -264
- package/dist/src/lib/docs-drift.js.map +0 -1
- package/src/lib/docs-drift.ts +0 -312
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
2
|
import { log } from "./lib/log.js";
|
|
3
|
-
import { cliVersion } from "./lib/version.js";
|
|
3
|
+
import { cliVersion, isVersionFlag } from "./lib/version.js";
|
|
4
4
|
import { resolveFormat, isValidFormat, VALID_FORMATS, type OutputFormat } from "./lib/format.js";
|
|
5
5
|
import { resolveCollection } from "@metaobjectsdev/sdk";
|
|
6
6
|
import { GENERATOR_HELP } from "./commands/generator-help.js";
|
|
@@ -42,12 +42,11 @@ COMMANDS:
|
|
|
42
42
|
types [query] Search the metadata vocabulary (types, subtypes, @attrs) by name or description
|
|
43
43
|
export Flatten loaded metadata to one canonical JSON artifact
|
|
44
44
|
fmt [<file>...] Rewrite metadata files into canonical form; --check lists drift, exits non-zero
|
|
45
|
-
|
|
46
|
-
verify Drift gate — subverbs: --templates / --db / --codegen / --docs / --deps (bare = --templates)
|
|
45
|
+
verify Drift gate — subverbs: --templates / --db / --codegen / --deps (bare = --templates)
|
|
47
46
|
upgrade Rewrite retired metadata vocabulary (previews; --apply writes)
|
|
48
47
|
prompt-snapshot Snapshot rendered template.* output; --check gates drift
|
|
49
48
|
migrate Diff metadata vs live DB; emit migration SQL files
|
|
50
|
-
--version, -v
|
|
49
|
+
--version, -v, -V Print version
|
|
51
50
|
--help, -h Print this help
|
|
52
51
|
|
|
53
52
|
GLOBAL OPTIONS:
|
|
@@ -81,8 +80,12 @@ GEN FLAGS:
|
|
|
81
80
|
--limit <n|all> How many advisory lines TEXT output prints before it truncates
|
|
82
81
|
(default 20). Never applies to --format toon/json, which
|
|
83
82
|
carry every finding.
|
|
83
|
+
--generators <names> Narrow the run to these DECLARED generators, by stable name, comma-
|
|
84
|
+
separated (e.g. docs,api-docs to write only the documentation). A
|
|
85
|
+
name metaobjects.config.ts does not declare is refused: it never adds one.
|
|
84
86
|
<entity> [<entity>] Positional filter on entity names
|
|
85
|
-
(outDir, dialect, dbImport, extStyle are read from metaobjects.config.ts
|
|
87
|
+
(outDir, dialect, dbImport, extStyle are read from metaobjects.config.ts. Every generator,
|
|
88
|
+
documentation included, is an entry in its \`generators\`; nothing else is generated.)
|
|
86
89
|
|
|
87
90
|
EXPORT FLAGS:
|
|
88
91
|
--out <file> Write output to a file (default: stdout)
|
|
@@ -102,26 +105,10 @@ FMT FLAGS:
|
|
|
102
105
|
find-or-reuse behavior would otherwise silently fold a same-file
|
|
103
106
|
base + overlay into one node, dropping the overlay marker.
|
|
104
107
|
|
|
105
|
-
DOCS FLAGS:
|
|
106
|
-
[<project-root>] PROJECT ROOT to resolve metadata from — the directory that CONTAINS
|
|
107
|
-
your metadata, NOT the metadata directory. Passing it SCOPES the run
|
|
108
|
-
(default: cwd)
|
|
109
|
-
--out <dir>, -o Output directory for THIS run (default: ./docs/generated). It does
|
|
110
|
-
NOT survive the run — set 'docs: { outDir }' in metaobjects.config.ts
|
|
111
|
-
for a directory that persists, which is what 'meta verify --docs'
|
|
112
|
-
measures. The default is a sub-directory on purpose: these pages are
|
|
113
|
-
regenerated and overwritten, and 'docs/' itself is usually yours.
|
|
114
|
-
--templates <dir> Project root to resolve adopter templates/ overrides (default: <project-root>)
|
|
115
|
-
--prompts <dir> Extra dir holding prompt .mustache sources for --site (e.g. data/templates/)
|
|
116
|
-
|
|
117
108
|
VERIFY FLAGS (ADR-0021 D2 — explicit subverbs; combine any; exit 1 on ANY drift):
|
|
118
109
|
--templates Template/prompt {{field}}↔payload drift (the bare-verify default)
|
|
119
110
|
--codegen Codegen drift — regenerate to a temp dir and diff the committed
|
|
120
|
-
output (config outDir/targets)
|
|
121
|
-
--docs Docs drift — run 'meta docs' into a temp dir and diff the committed
|
|
122
|
-
docs tree (docs.outDir). Reports a page that changed or that a fresh
|
|
123
|
-
run would emit; never reports an extra file, because docs.outDir
|
|
124
|
-
holds hand-written documentation MetaObjects did not write.
|
|
111
|
+
output (config outDir/targets), documentation included.
|
|
125
112
|
Needs metaobjects.config.ts; exit 2 if absent.
|
|
126
113
|
--deps Dependency drift — re-resolve each declared dependency and compare
|
|
127
114
|
its installed artifact's hash against .metaobjects/deps.lock.json
|
|
@@ -135,18 +122,31 @@ VERIFY FLAGS (ADR-0021 D2 — explicit subverbs; combine any; exit 1 on ANY drif
|
|
|
135
122
|
--allow <csv> Accepted for parity with 'migrate'; does NOT affect the
|
|
136
123
|
verify drift gate (the gate fails on ANY detected change)
|
|
137
124
|
--skip-schema Skip the schema-drift gate even when --db is present
|
|
125
|
+
--migration-format default|flyway
|
|
126
|
+
Migration file layout (default: default), as for 'meta migrate'.
|
|
127
|
+
Under 'flyway' the schema-drift gate leaves flyway_schema_history
|
|
128
|
+
out of the comparison, because Flyway owns it. Also settable
|
|
129
|
+
once as migrate.format in .metaobjects/config.json.
|
|
138
130
|
--d1 <binding> D1 binding name from wrangler.toml (only with --dialect d1)
|
|
139
131
|
--remote Target remote D1 instead of local (only with --dialect d1) —
|
|
140
132
|
the ONLY way to verify the actual deployed D1 database
|
|
141
133
|
--no-antipatterns Suppress the advisory "you hand-rolled what MetaObjects can
|
|
142
134
|
model" pass (aggregate/currency/enum hints; warnings only)
|
|
143
135
|
--no-requirement-lint Suppress the advisory requirement AUTHORING lint (not the gate)
|
|
136
|
+
--require-implementers
|
|
137
|
+
Fail (exit 1) when a live functional requirement has nothing
|
|
138
|
+
implementing it. That finding is a warning without this flag;
|
|
139
|
+
with it, the same WARN_REQUIREMENT_NOTHING_IMPLEMENTS code is
|
|
140
|
+
reported as an error. Also: META_REQUIRE_IMPLEMENTERS=1.
|
|
144
141
|
--no-overlay-lint Suppress the advisory overlay-redeclaration AUTHORING lint
|
|
145
142
|
(never a gate — this lint can't fail the build)
|
|
146
143
|
--no-name-lint Suppress the advisory node-name AUTHORING lint (whitespace
|
|
147
144
|
in a name; never a gate — this lint can't fail the build)
|
|
148
145
|
--no-deprecation-lint Suppress the advisory deprecated-reference AUTHORING lint
|
|
149
146
|
(never a gate — this lint can't fail the build)
|
|
147
|
+
--no-field-lint Suppress the advisory field AUTHORING lint (a reference
|
|
148
|
+
identity over a missing field; a duplicate field name —
|
|
149
|
+
never a gate; this lint can't fail the build)
|
|
150
150
|
--limit <n|all> How many advisory lines TEXT output prints per section before
|
|
151
151
|
it truncates (default 20). Never applies to --format
|
|
152
152
|
toon/json, which carry every finding and every diagnostic.
|
|
@@ -175,9 +175,9 @@ MIGRATE FLAGS:
|
|
|
175
175
|
--remote Target remote D1 instead of local (only with --dialect d1)
|
|
176
176
|
--apply Run 'wrangler d1 migrations apply' after writing files
|
|
177
177
|
--yes Skip the --remote --apply confirmation pause
|
|
178
|
-
--dry-run Print SQL
|
|
178
|
+
--dry-run Print the SQL, don't write (json/toon: in the document's sql field)
|
|
179
179
|
|
|
180
|
-
See https://metaobjects.
|
|
180
|
+
See https://metaobjects.dev for docs.
|
|
181
181
|
`;
|
|
182
182
|
|
|
183
183
|
/** Focused per-subcommand usage slices shown by `<cmd> --help`. */
|
|
@@ -206,6 +206,9 @@ FLAGS:
|
|
|
206
206
|
overwrites them with fresh output and re-baselines (discards edits).
|
|
207
207
|
--no-antipatterns Suppress the advisory "hand-rolled what MetaObjects can model" pass
|
|
208
208
|
--limit <n|all> Advisory lines TEXT output prints before truncating (default 20)
|
|
209
|
+
--generators <names> Narrow the run to these DECLARED generators, by stable name, comma-
|
|
210
|
+
separated (e.g. docs,api-docs to write only the documentation). A
|
|
211
|
+
name metaobjects.config.ts does not declare is refused: it never adds one.
|
|
209
212
|
--format <toon|json|text> Output format (global flag; default toon off-TTY)
|
|
210
213
|
<entity> [<entity>] Positional filter on entity names
|
|
211
214
|
--help, -h Print this help
|
|
@@ -229,8 +232,9 @@ USAGE:
|
|
|
229
232
|
meta eject <name>... Copy each generator into codegen/generators/<name>.ts
|
|
230
233
|
meta eject --list List every ejectable generator name, grouped by package
|
|
231
234
|
|
|
232
|
-
|
|
233
|
-
|
|
235
|
+
Eject a generator to CHANGE what it emits. To run one as shipped, import its factory
|
|
236
|
+
from its package instead — \`meta gen --list\` prints the import line — and copy
|
|
237
|
+
nothing. Take several at once: the install set is CONSOLIDATED, so
|
|
234
238
|
\`meta eject form hooks grid\` prints one install line, not three. An unknown name
|
|
235
239
|
refuses the whole call and copies nothing.
|
|
236
240
|
|
|
@@ -243,9 +247,9 @@ FLAGS:
|
|
|
243
247
|
--help, -h Print this help
|
|
244
248
|
|
|
245
249
|
\`meta init\` copies NO generators — codegen is opt-in, and codegen/generators/
|
|
246
|
-
starts empty on purpose.
|
|
247
|
-
scaffold-and-own)
|
|
248
|
-
the
|
|
250
|
+
starts empty on purpose. An ejected file is YOURS to edit (ADR-0034
|
|
251
|
+
scaffold-and-own), and \`meta gen\` runs your copy, not the package's. Eject prints
|
|
252
|
+
the import line to swap in for the package one and the entry to add in
|
|
249
253
|
metaobjects.config.ts, and never overwrites a file you already own without --force.
|
|
250
254
|
|
|
251
255
|
Find names with \`meta gen --list\` — add --probe to see how many files each would
|
|
@@ -299,12 +303,8 @@ FLAGS:
|
|
|
299
303
|
(a notice, exit code unchanged), so an edit is never invisible.
|
|
300
304
|
--forbid-hand-edits With --codegen: fail (exit 1) on ANY hand edit inside generated
|
|
301
305
|
code, for teams that want generated files untouchable.
|
|
302
|
-
--docs
|
|
303
|
-
|
|
304
|
-
project GIT-IGNORES is exempt (docs.outDir is a directory, not
|
|
305
|
-
a namespace MetaObjects owns); the count of exempt pages is
|
|
306
|
-
reported either way, and a run where every page is ignored is
|
|
307
|
-
refused rather than reported clean.
|
|
306
|
+
--docs Removed in 1.1.0: says so and exits 2. --codegen checks documentation
|
|
307
|
+
with everything else \`generators\` declares.
|
|
308
308
|
--deps Dependency drift — re-resolve each declared dependency exactly as
|
|
309
309
|
'meta deps check' does and compare its installed artifact's hash
|
|
310
310
|
against .metaobjects/deps.lock.json. Exits 1 if any dependency has
|
|
@@ -329,6 +329,11 @@ FLAGS:
|
|
|
329
329
|
--dialect sqlite|postgres|d1 Optional override (auto-detected from --db URL scheme)
|
|
330
330
|
--allow <csv> Accepted for parity with 'migrate'; does NOT affect the drift gate
|
|
331
331
|
--skip-schema Skip the schema-drift gate even when --db is present
|
|
332
|
+
--migration-format default|flyway
|
|
333
|
+
Migration file layout (default: default), as for 'meta migrate'.
|
|
334
|
+
Under 'flyway' the schema-drift gate leaves flyway_schema_history
|
|
335
|
+
out of the comparison, because Flyway owns it. Also settable
|
|
336
|
+
once as migrate.format in .metaobjects/config.json.
|
|
332
337
|
--d1 <binding> D1 binding name from wrangler.toml (only with --dialect d1)
|
|
333
338
|
--remote Target remote D1 instead of local (only with --dialect d1) —
|
|
334
339
|
the ONLY way to verify the actual deployed D1 database
|
|
@@ -338,12 +343,20 @@ FLAGS:
|
|
|
338
343
|
migrating a model onto a registered provider.
|
|
339
344
|
--no-antipatterns Suppress the advisory "hand-rolled what MetaObjects can model" pass
|
|
340
345
|
--no-requirement-lint Suppress the advisory requirement AUTHORING lint (not the gate)
|
|
346
|
+
--require-implementers
|
|
347
|
+
Fail (exit 1) when a live functional requirement has nothing
|
|
348
|
+
implementing it. That finding is a warning without this flag;
|
|
349
|
+
with it, the same WARN_REQUIREMENT_NOTHING_IMPLEMENTS code is
|
|
350
|
+
reported as an error. Also: META_REQUIRE_IMPLEMENTERS=1.
|
|
341
351
|
--no-overlay-lint Suppress the advisory overlay-redeclaration AUTHORING lint —
|
|
342
352
|
never a gate; this lint can't fail the build
|
|
343
353
|
--no-name-lint Suppress the advisory node-name AUTHORING lint (whitespace in
|
|
344
354
|
a name) — never a gate; this lint can't fail the build
|
|
345
355
|
--no-deprecation-lint Suppress the advisory deprecated-reference AUTHORING lint —
|
|
346
356
|
never a gate; this lint can't fail the build
|
|
357
|
+
--no-field-lint Suppress the advisory field AUTHORING lint (a reference
|
|
358
|
+
identity over a missing field; a duplicate field name) —
|
|
359
|
+
never a gate; this lint can't fail the build
|
|
347
360
|
--limit <n|all> Advisory lines TEXT output prints PER SECTION before truncating
|
|
348
361
|
(default 20; per-section so the authoring lint can never push
|
|
349
362
|
the gate's own warnings off the end)
|
|
@@ -367,6 +380,9 @@ lint in its own section: names that are not addressable, prose slots holding one
|
|
|
367
380
|
sentence twice, content written where no surface reads it. Warnings only — it can
|
|
368
381
|
never fail the build. Opt out with --no-requirement-lint or META_NO_REQUIREMENT_LINT=1.
|
|
369
382
|
The requirements GATE itself (dangling refs, link floor, levels) always runs.
|
|
383
|
+
One of its findings is a warning you can raise: a live functional requirement that
|
|
384
|
+
nothing implements fails the build under --require-implementers or
|
|
385
|
+
META_REQUIRE_IMPLEMENTERS=1. The diagnostic keeps its code; only its severity moves.
|
|
370
386
|
|
|
371
387
|
verify also prints an ADVISORY overlay authoring lint, in its own section: a
|
|
372
388
|
top-level declaration redeclared in two or more files where more than one
|
|
@@ -389,6 +405,12 @@ the deprecated node also carries @replacedBy, the finding names the replacement.
|
|
|
389
405
|
A node referencing itself (a recursive FK, a same-entity passthrough) is not a
|
|
390
406
|
finding. Warnings only — it can never fail the build. Opt out with
|
|
391
407
|
--no-deprecation-lint or META_NO_DEPRECATION_LINT=1.
|
|
408
|
+
|
|
409
|
+
verify also prints an ADVISORY field authoring lint, in its own section. It reports
|
|
410
|
+
an identity.reference whose @fields names a field the object does not have
|
|
411
|
+
(inherited and overlaid fields count as present), and a field name declared more
|
|
412
|
+
than once in one object's children list. Both load with no error. Warnings only —
|
|
413
|
+
it can never fail the build. Opt out with --no-field-lint or META_NO_FIELD_LINT=1.
|
|
392
414
|
`,
|
|
393
415
|
export: `meta export — flatten loaded metadata to one canonical JSON artifact
|
|
394
416
|
|
|
@@ -431,42 +453,6 @@ skipped — not only when no base exists in the same file. A formatter never
|
|
|
431
453
|
changes structure: even when a same-file base IS present, merging it with
|
|
432
454
|
the overlay (what the ordinary loader would do) would drop the overlay
|
|
433
455
|
marker from the output, so fmt refuses that too and leaves the file as-is.
|
|
434
|
-
`,
|
|
435
|
-
docs: `meta docs — generate neutral metadata documentation (entity + template pages)
|
|
436
|
-
|
|
437
|
-
USAGE:
|
|
438
|
-
meta docs [<project-root>] [flags]
|
|
439
|
-
|
|
440
|
-
FLAGS:
|
|
441
|
-
[<project-root>] PROJECT ROOT to resolve metadata from — the directory that CONTAINS
|
|
442
|
-
your metadata, NOT the metadata directory itself. (The Python and C#
|
|
443
|
-
'docs' positionals mean the metadata dir; this one does not.) Passing
|
|
444
|
-
it SCOPES the run to that directory's own sources; no ancestor
|
|
445
|
-
.metaobjects/config.json is consulted. Omitted (default), the project
|
|
446
|
-
is discovered by walking up.
|
|
447
|
-
--out <dir>, -o Output directory for THIS run (default: ./docs/generated). It does
|
|
448
|
-
NOT survive the run — set 'docs: { outDir }' in metaobjects.config.ts
|
|
449
|
-
for a directory that persists, which is what 'meta verify --docs'
|
|
450
|
-
measures. The default is a sub-directory on purpose: these pages are
|
|
451
|
-
regenerated and overwritten, and 'docs/' itself is usually yours.
|
|
452
|
-
--model Emit the markdown model surface (entity + template pages)
|
|
453
|
-
--api Emit the markdown api surface (generated SDK reference)
|
|
454
|
-
--requirements Emit the declared requirement ledger (requirements.md + .toon).
|
|
455
|
-
Emits nothing when the project declares no requirement.* node.
|
|
456
|
-
--agent Emit the agent surface — agent/schema.md (the physical schema),
|
|
457
|
-
agent/ui.md (the generated forms and grids) and
|
|
458
|
-
agent/requirements.md (the ledger plus a claimed-node index).
|
|
459
|
-
Needs metaobjects.config.ts (the dialect and physical names come
|
|
460
|
-
from it); each page is skipped when its tier has nothing to describe
|
|
461
|
-
— agent/ui.md needs a UI generator (a form, hook or grid) in the
|
|
462
|
-
suite, not merely objects that could have one.
|
|
463
|
-
--metamodel Document the built-in metamodel vocabulary (no metadata needed)
|
|
464
|
-
--site Generate the browsable HTML documentation site (<out>/site/)
|
|
465
|
-
--scaffold-site Copy the site's templates + assets into codegen/docs-site/ to own (theme) them
|
|
466
|
-
--templates <dir> Project root to resolve adopter templates/ overrides (default: <project-root>)
|
|
467
|
-
--prompts <dir> Extra dir holding prompt .mustache sources (for --site) when they
|
|
468
|
-
live outside the metadata sources or templates/ (e.g. data/templates/)
|
|
469
|
-
--help, -h Print this help
|
|
470
456
|
`,
|
|
471
457
|
init: `meta init — scaffold a MetaObjects project in the current repo
|
|
472
458
|
|
|
@@ -604,7 +590,7 @@ export async function run(argv: string[]): Promise<number> {
|
|
|
604
590
|
}
|
|
605
591
|
|
|
606
592
|
// Intercept per-subcommand --help / -h before dispatching (mirrors migrate's own pattern).
|
|
607
|
-
if (cmd !== undefined && cmd !== "--help" && cmd !== "-h" && cmd
|
|
593
|
+
if (cmd !== undefined && cmd !== "--help" && cmd !== "-h" && !isVersionFlag(cmd)) {
|
|
608
594
|
if (rest.includes("--help") || rest.includes("-h")) {
|
|
609
595
|
const helpText = COMMAND_HELP[cmd];
|
|
610
596
|
if (helpText !== undefined) {
|
|
@@ -651,6 +637,7 @@ export async function run(argv: string[]): Promise<number> {
|
|
|
651
637
|
return 0;
|
|
652
638
|
case "--version":
|
|
653
639
|
case "-v":
|
|
640
|
+
case "-V":
|
|
654
641
|
log.info(VERSION);
|
|
655
642
|
return 0;
|
|
656
643
|
case "init": {
|
|
@@ -6,25 +6,40 @@ import { join } from "node:path";
|
|
|
6
6
|
// star one, so the root barrel now hands out the dependency manifest under this
|
|
7
7
|
// name. `init.ts` already imports these from the subpath; this was the last site
|
|
8
8
|
// reading them from the root.
|
|
9
|
-
import { AGENT_CONTEXT_MANIFEST_PATH, agentContextStaleness, type Manifest } from "@metaobjectsdev/sdk/agent-context";
|
|
9
|
+
import { AGENT_CONTEXT_MANIFEST_PATH, agentContextStaleness, hashAgentContextRoot, resolveAgentContextRoot, type Manifest } from "@metaobjectsdev/sdk/agent-context";
|
|
10
|
+
import { docsRefForVersion } from "@metaobjectsdev/metadata";
|
|
10
11
|
import { cliVersion } from "./version.js";
|
|
11
12
|
import { log } from "./log.js";
|
|
12
13
|
|
|
14
|
+
/** The installed content's hash, or nothing when the content tree cannot be found (version compare then). */
|
|
15
|
+
export function currentContentHash(): { currentContentHash?: string } {
|
|
16
|
+
try {
|
|
17
|
+
return { currentContentHash: hashAgentContextRoot(resolveAgentContextRoot(), docsRefForVersion(cliVersion())) };
|
|
18
|
+
} catch {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
13
23
|
/**
|
|
14
24
|
* Advisory: if a scaffolded MetaObjects agent context predates this CLI version,
|
|
15
25
|
* print a one-line nudge to re-scaffold. Never throws, never blocks — an absent or
|
|
16
26
|
* corrupt manifest is silently ignored (this is a reminder, not a gate).
|
|
27
|
+
*
|
|
28
|
+
* Returns the line it printed, so a command with a structured result can carry it
|
|
29
|
+
* there too; undefined when it said nothing.
|
|
17
30
|
*/
|
|
18
|
-
export function warnIfAgentContextStale(cwd: string):
|
|
31
|
+
export function warnIfAgentContextStale(cwd: string): string | undefined {
|
|
19
32
|
const p = join(cwd, AGENT_CONTEXT_MANIFEST_PATH);
|
|
20
33
|
let manifest: Manifest | undefined;
|
|
21
34
|
if (existsSync(p)) {
|
|
22
35
|
try {
|
|
23
36
|
manifest = JSON.parse(readFileSync(p, "utf8")) as Manifest;
|
|
24
37
|
} catch {
|
|
25
|
-
return; // unreadable/corrupt — say nothing
|
|
38
|
+
return undefined; // unreadable/corrupt — say nothing
|
|
26
39
|
}
|
|
27
40
|
}
|
|
28
|
-
const msg = agentContextStaleness({ manifest, currentVersion: cliVersion() });
|
|
29
|
-
if (msg
|
|
41
|
+
const msg = agentContextStaleness({ manifest, currentVersion: cliVersion(), ...currentContentHash() });
|
|
42
|
+
if (msg === null) return undefined;
|
|
43
|
+
log.warn(msg);
|
|
44
|
+
return msg;
|
|
30
45
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// The physical schema `agent/schema.md` describes (the `agent-docs` generator), built by the
|
|
2
|
+
// package that owns it, `migrate-ts`, with its own resolvers handed across. codegen-ts
|
|
3
|
+
// deliberately computes none of it (see agent-schema-input.ts there), so `meta gen` and
|
|
4
|
+
// `meta verify --codegen` build it here and hand it to the run as `RunGenOpts.agentSchema`;
|
|
5
|
+
// the runner calls it only when a declared generator asks.
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
buildProjectionViews,
|
|
9
|
+
dbEmittingObjects,
|
|
10
|
+
DEFAULT_DIALECT,
|
|
11
|
+
missingDialectMessage,
|
|
12
|
+
} from "@metaobjectsdev/codegen-ts";
|
|
13
|
+
import type { AgentSchemaInput, Dialect, SchemaColumnLike } from "@metaobjectsdev/codegen-ts";
|
|
14
|
+
import { buildExpectedSchemaWithProvenance, columnTypeSql, qualifiedDbName } from "@metaobjectsdev/migrate-ts";
|
|
15
|
+
import type { MetaRoot } from "@metaobjectsdev/metadata";
|
|
16
|
+
import { describeError } from "./error-text.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The schema for `agent/schema.md`, or undefined, after saying why through `warn`, when the
|
|
20
|
+
* page is to be SKIPPED. A skipped page is not a silent pass: `meta verify --codegen` convicts
|
|
21
|
+
* a committed `agent/schema.md` that a fresh run no longer writes.
|
|
22
|
+
*/
|
|
23
|
+
export function buildAgentSchemaInput(
|
|
24
|
+
root: MetaRoot,
|
|
25
|
+
configured: Dialect | undefined,
|
|
26
|
+
warn: (message: string) => void,
|
|
27
|
+
): AgentSchemaInput | undefined {
|
|
28
|
+
// THE RUNNER'S OWN GUARD DECIDES THIS, not a default applied here. `DEFAULT_DIALECT` is
|
|
29
|
+
// inert: `meta gen` refuses a model that emits database code with no dialect declared, so a
|
|
30
|
+
// persisted model with no dialect is not a sqlite project. Documenting it as one would state
|
|
31
|
+
// an answer the toolchain never gave. A model with no persisted object needs no dialect and
|
|
32
|
+
// renders an empty schema page anyway, so the inert default is right for exactly the
|
|
33
|
+
// projects the guard lets through.
|
|
34
|
+
const dbEmitting = dbEmittingObjects(root.objects());
|
|
35
|
+
if (dbEmitting.length > 0 && configured === undefined) {
|
|
36
|
+
warn(`agent/schema.md skipped — ${missingDialectMessage(dbEmitting)}`);
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
// MySQL: MetaObjects does not own the schema, so there is no migrate-built schema to
|
|
40
|
+
// describe. The generated Drizzle tables are the description.
|
|
41
|
+
if (configured === "mysql") {
|
|
42
|
+
warn("agent/schema.md skipped — MetaObjects does not own a MySQL schema (the generated Drizzle tables describe it).");
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const dialect = configured ?? DEFAULT_DIALECT;
|
|
46
|
+
try {
|
|
47
|
+
const built = buildExpectedSchemaWithProvenance(root, {
|
|
48
|
+
dialect,
|
|
49
|
+
// Views come from codegen-ts (migrate-ts never generates view DDL), exactly as
|
|
50
|
+
// `verify --db` threads them.
|
|
51
|
+
views: buildProjectionViews(root, { dialect }),
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
dialect,
|
|
55
|
+
tables: built.snapshot.tables,
|
|
56
|
+
views: built.snapshot.views,
|
|
57
|
+
provenance: built.provenance,
|
|
58
|
+
// The structural `SchemaColumnLike` is migrate-ts's own ColumnDescriptor, narrowed to
|
|
59
|
+
// what the page reads; the cast hands the full descriptor back to the renderer that
|
|
60
|
+
// produced it.
|
|
61
|
+
columnType: (c: SchemaColumnLike) => columnTypeSql(c as never, dialect),
|
|
62
|
+
qualify: qualifiedDbName,
|
|
63
|
+
};
|
|
64
|
+
} catch (err) {
|
|
65
|
+
// A model the schema builder refuses is a real condition (a primary-key move, a duplicate
|
|
66
|
+
// physical name) that `meta migrate` reports properly. Documentation must not be the
|
|
67
|
+
// command that fails on it, so the schema page is skipped and the other pages still emit.
|
|
68
|
+
warn(
|
|
69
|
+
`agent/schema.md skipped — the expected schema could not be built ` +
|
|
70
|
+
`(${describeError(err)}). Run 'meta migrate' for the full diagnosis.`,
|
|
71
|
+
);
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/lib/allow.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// both `meta migrate` and `meta verify --db`. Keeping a single copy avoids the
|
|
3
3
|
// two commands drifting on which `--allow` tokens exist or how a change reads.
|
|
4
4
|
|
|
5
|
-
import { allowOptionFor, suggestColumnRenames } from "@metaobjectsdev/migrate-ts";
|
|
6
|
-
import type { AllowOptions, Change, ColumnRenameSuggestion } from "@metaobjectsdev/migrate-ts";
|
|
5
|
+
import { allowOptionFor, describeSqlType, isViewRecreateOnly, suggestColumnRenames } from "@metaobjectsdev/migrate-ts";
|
|
6
|
+
import type { AllowOptions, Change, ColumnRenameSuggestion, ViewChangeReason } from "@metaobjectsdev/migrate-ts";
|
|
7
7
|
import type { BlockedEntry } from "./output.js";
|
|
8
8
|
|
|
9
9
|
// Map CLI allow tokens → migrate-ts AllowOptions field names.
|
|
@@ -71,7 +71,7 @@ export function describeChange(c: Change): string {
|
|
|
71
71
|
const from = c.fromDefault?.value ?? "none";
|
|
72
72
|
const to = c.toDefault?.value ?? "none";
|
|
73
73
|
const dflt = from === to && c.fromDefault?.kind === c.toDefault?.kind ? "" : `, default ${from} → ${to}`;
|
|
74
|
-
return `${c.table}.${c.column} (${c.from
|
|
74
|
+
return `${c.table}.${c.column} (${describeSqlType(c.from)} → ${describeSqlType(c.to)}${dflt})`;
|
|
75
75
|
}
|
|
76
76
|
case "change-column-nullable": return `${c.table}.${c.column} (${c.from ? "NULL" : "NOT NULL"} → ${c.to ? "NULL" : "NOT NULL"})`;
|
|
77
77
|
case "change-column-default": return `${c.table}.${c.column}`;
|
|
@@ -84,9 +84,9 @@ export function describeChange(c: Change): string {
|
|
|
84
84
|
return c.restore !== undefined
|
|
85
85
|
? `${c.table} check ${c.check} (${c.restore.expression})`
|
|
86
86
|
: `${c.table} check ${c.check}`;
|
|
87
|
-
case "create-view": return c.view.name;
|
|
88
|
-
case "replace-view": return c.view.name;
|
|
89
|
-
case "drop-view": return c.view;
|
|
87
|
+
case "create-view": return withViewReason(c.view.name, c.reason);
|
|
88
|
+
case "replace-view": return withViewReason(c.view.name, c.reason);
|
|
89
|
+
case "drop-view": return withViewReason(c.view, c.reason);
|
|
90
90
|
}
|
|
91
91
|
// Exhaustive: a new Change kind fails to compile here rather than printing a JSON dump
|
|
92
92
|
// of the change object to a person (which is what a blocked drop-check used to do).
|
|
@@ -94,6 +94,57 @@ export function describeChange(c: Change): string {
|
|
|
94
94
|
return unhandled;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
/**
|
|
98
|
+
* A view's name plus WHY the diff planned its change. A bare name was all a view change
|
|
99
|
+
* ever printed, so a view whose definition matched the metadata — dropped and recreated only
|
|
100
|
+
* because the migration alters a table it reads — read exactly like one that differed (D3).
|
|
101
|
+
*/
|
|
102
|
+
function withViewReason(name: string, reason: ViewChangeReason | undefined): string {
|
|
103
|
+
return reason === undefined ? name : `${name} (${viewReasonText(reason)})`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function viewReasonText(r: ViewChangeReason): string {
|
|
107
|
+
switch (r.kind) {
|
|
108
|
+
case "missing": return "declared by the metadata, not in the database";
|
|
109
|
+
case "undeclared": return "in the database, declared by no metadata object";
|
|
110
|
+
case "definition": {
|
|
111
|
+
const what = r.compared === "fingerprint"
|
|
112
|
+
? "definition differs: the database view's fingerprint does not match the metadata's"
|
|
113
|
+
: r.firstDifference !== undefined
|
|
114
|
+
? `definition text differs: metadata «${r.firstDifference.expected}» vs database «${r.firstDifference.actual}»`
|
|
115
|
+
: "definition text differs";
|
|
116
|
+
return recreatedAround(what, r.tables);
|
|
117
|
+
}
|
|
118
|
+
case "unfingerprinted":
|
|
119
|
+
return recreatedAround(
|
|
120
|
+
"the database view carries no MetaObjects fingerprint, so its definition cannot be compared",
|
|
121
|
+
r.tables,
|
|
122
|
+
);
|
|
123
|
+
case "unchanged":
|
|
124
|
+
return `definition matches the metadata; recreated because the migration alters ${tableList(r.tables)}`;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function recreatedAround(what: string, tables: readonly string[] | undefined): string {
|
|
129
|
+
return tables === undefined ? what : `${what}; recreated around the change to ${tableList(tables)}`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function tableList(tables: readonly string[]): string {
|
|
133
|
+
return `${tables.length === 1 ? "table" : "tables"} ${tables.join(", ")}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* One line naming the views a migration drops and recreates only because it alters a table
|
|
138
|
+
* they read. Their definitions match the metadata, and the migration needs the pair, but
|
|
139
|
+
* without this line the DROP VIEW / CREATE VIEW in the SQL reads like a view change (D3).
|
|
140
|
+
*/
|
|
141
|
+
export function viewRecreateNote(changes: readonly Change[]): string | undefined {
|
|
142
|
+
const views = changes.flatMap((c) => c.kind === "create-view" && isViewRecreateOnly(c) ? [c.view.name] : []);
|
|
143
|
+
if (views.length === 0) return undefined;
|
|
144
|
+
return `${views.length} view(s) match the metadata and are recreated only because the migration ` +
|
|
145
|
+
`alters a table they read: ${views.join(", ")}`;
|
|
146
|
+
}
|
|
147
|
+
|
|
97
148
|
/** The `--allow` token that unblocks `c`. migrate-ts picks the permission by what blocked the
|
|
98
149
|
* change (a type change can be blocked by the auto-sequence default it carries), so this only
|
|
99
150
|
* maps that permission back to its CLI token. */
|
package/src/lib/anti-patterns.ts
CHANGED
|
@@ -202,8 +202,10 @@ function matchLine(line: string, isSql: boolean):
|
|
|
202
202
|
|
|
203
203
|
const ADVICE: Record<AntiPatternFinding["rule"], string> = {
|
|
204
204
|
"hand-rolled-aggregate":
|
|
205
|
-
"you're computing an aggregate by hand — MetaObjects derives it:
|
|
206
|
-
"
|
|
205
|
+
"you're computing an aggregate by hand — MetaObjects derives it: for grouped, " +
|
|
206
|
+
"served or reported figures declare an object.report (dimensions + measures, a " +
|
|
207
|
+
"read-only list route); an object.projection with an origin.aggregate child still " +
|
|
208
|
+
"fits a per-row figure on one entity read through its generated query",
|
|
207
209
|
"money-float":
|
|
208
210
|
"money handled as a float / hand-rolled minor units — MetaObjects has " +
|
|
209
211
|
"field.currency (integer minor units stored, formatted client-side)",
|