aontu 0.63.0 → 0.64.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 +6 -6
- package/dist/aontu.d.ts +3 -3
- package/dist/aontu.js +4 -6
- package/dist/aontu.js.map +1 -1
- package/dist/aontumodel.js +6 -12
- package/dist/aontumodel.js.map +1 -1
- package/dist/casing.d.ts +5 -0
- package/dist/casing.js +90 -0
- package/dist/casing.js.map +1 -0
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +147 -335
- package/dist/cli.js.map +1 -1
- package/dist/helpdoc.js +1 -1
- package/dist/helpdoc.js.map +1 -1
- package/dist/hints.js +3 -0
- package/dist/hints.js.map +1 -1
- package/dist/lsp.d.ts +1 -1
- package/dist/mcp.js +0 -36
- package/dist/mcp.js.map +1 -1
- package/dist/mod-tool.js +16 -1
- package/dist/mod-tool.js.map +1 -1
- package/dist/profile.d.ts +9 -0
- package/dist/profile.js +28 -0
- package/dist/profile.js.map +1 -0
- package/dist/trace.d.ts +21 -0
- package/dist/trace.js +107 -0
- package/dist/trace.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/unify.js +1 -6
- package/dist/unify.js.map +1 -1
- package/dist/val/CmpFuncVal.d.ts +2 -0
- package/dist/val/CmpFuncVal.js +47 -13
- package/dist/val/CmpFuncVal.js.map +1 -1
- package/dist/val/NomFuncVal.js +11 -13
- package/dist/val/NomFuncVal.js.map +1 -1
- package/dist/val/ReferFuncVal.js +3 -0
- package/dist/val/ReferFuncVal.js.map +1 -1
- package/package.json +1 -1
- package/skill/tasks.md +9 -7
- package/src/aontu.ts +3 -8
- package/src/aontumodel.ts +6 -12
- package/src/casing.ts +95 -0
- package/src/cli.ts +162 -359
- package/src/helpdoc.ts +1 -1
- package/src/hints.ts +3 -0
- package/src/mcp.ts +0 -39
- package/src/mod-tool.ts +18 -1
- package/src/profile.ts +42 -0
- package/src/trace.ts +157 -0
- package/src/unify.ts +1 -6
- package/src/val/CmpFuncVal.ts +66 -20
- package/src/val/NomFuncVal.ts +3 -5
- package/src/val/ReferFuncVal.ts +4 -0
- package/dist/lower.d.ts +0 -23
- package/dist/lower.js +0 -528
- package/dist/lower.js.map +0 -1
- package/dist/render.d.ts +0 -53
- package/dist/render.js +0 -432
- package/dist/render.js.map +0 -1
- package/src/lower.ts +0 -586
- package/src/render.ts +0 -580
package/dist/cli.js
CHANGED
|
@@ -13,8 +13,8 @@ exports.runRelations = runRelations;
|
|
|
13
13
|
exports.runReaches = runReaches;
|
|
14
14
|
exports.runView = runView;
|
|
15
15
|
exports.runJsonSchema = runJsonSchema;
|
|
16
|
-
exports.runRender = runRender;
|
|
17
16
|
exports.runTemplate = runTemplate;
|
|
17
|
+
exports.runTrace = runTrace;
|
|
18
18
|
exports.runMod = runMod;
|
|
19
19
|
exports.runHash = runHash;
|
|
20
20
|
exports.runGet = runGet;
|
|
@@ -40,8 +40,8 @@ const node_path_1 = require("node:path");
|
|
|
40
40
|
const node_os_1 = require("node:os");
|
|
41
41
|
const node_readline_1 = require("node:readline");
|
|
42
42
|
const aontu_1 = require("./aontu");
|
|
43
|
+
const trace_1 = require("./trace");
|
|
43
44
|
const template_1 = require("./template");
|
|
44
|
-
const mcp_1 = require("./mcp");
|
|
45
45
|
const report_sarif_1 = require("./report-sarif");
|
|
46
46
|
const lsp_server_1 = require("./lsp-server");
|
|
47
47
|
const mcp_server_1 = require("./mcp-server");
|
|
@@ -67,11 +67,10 @@ const HELP = `Usage: aontu [options] [file]
|
|
|
67
67
|
aontu view <kind> [options] <file>...
|
|
68
68
|
aontu view --views <path> [--check] [options] <file>
|
|
69
69
|
aontu jsonschema [--at <path>] [--strict] [options] <file>
|
|
70
|
-
aontu render [--at <path>] [--profile <file>]... [--unit <path>]
|
|
71
|
-
[--stdout | --out <dir> | --check <dir> | --coverage]
|
|
72
|
-
[--coverage-at <path>] [--strict] <file>
|
|
73
70
|
aontu template [--resugar] [--check] [--marker <token>]
|
|
74
71
|
[--profile <file>] <file>
|
|
72
|
+
aontu trace [--at <path>] [--format json] [--marker <token>]
|
|
73
|
+
[--profile <file>] <file>
|
|
75
74
|
aontu hash [options] <file>
|
|
76
75
|
aontu mod tidy|verify|vendor|manifest [options] [dir]
|
|
77
76
|
aontu get <path> [options] <file>
|
|
@@ -317,37 +316,11 @@ View exit codes: 0 rendered, 1 --check mismatch or lossy under
|
|
|
317
316
|
--strict, 2 usage or --max-rows exceeded, 4 the document does not stand
|
|
318
317
|
up on its own, or a relation, root or path that names nothing.
|
|
319
318
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
one per language
|
|
326
|
-
--unit <path> Render only the unit with this path
|
|
327
|
-
--stdout One unit's bytes and nothing else (with --unit when
|
|
328
|
-
the instance has several)
|
|
329
|
-
--out <dir> Write every unit below dir, or nothing; never deletes
|
|
330
|
-
--check <dir> Compare every unit with dir/<path>; drift is listed
|
|
331
|
-
--coverage Report what the render read and what it did not:
|
|
332
|
-
model paths no output consumed, and rendered
|
|
333
|
-
declarations no rule produced. Writes nothing
|
|
334
|
-
--coverage-at <p> Measure coverage under this path only, instead of
|
|
335
|
-
the document root
|
|
336
|
-
--strict Refuse the opaque escapes (a text declaration, a raw
|
|
337
|
-
block)
|
|
338
|
-
--format <f> text (default) or json, the whole report; json
|
|
339
|
-
carries the dispatch trace, one entry per emitted
|
|
340
|
-
piece
|
|
341
|
-
|
|
342
|
-
Render exit codes: 0 rendered, 1 lossy under --strict or drift under
|
|
343
|
-
--check, 2 usage or I/O (a refused unit path included), 4 the document
|
|
344
|
-
does not stand up or the instance is not aontu:code.
|
|
345
|
-
|
|
346
|
-
A render entry file whose extension is not .aon is a TEMPLATE: a
|
|
347
|
-
generator in the target's own syntax, whose marker lines carry aontu
|
|
348
|
-
and whose other lines are output. It is desugared before it is
|
|
349
|
-
evaluated, and a language the table does not know names its marker with
|
|
350
|
-
--marker, or declares it once in a profile file that --profile reads.
|
|
319
|
+
A template entry file whose extension is not .aon is a GENERATOR: a
|
|
320
|
+
document in the target's own syntax, whose marker lines carry aontu and
|
|
321
|
+
whose other lines are output. It is desugared before it is evaluated,
|
|
322
|
+
and a language the table does not know names its marker with --marker,
|
|
323
|
+
or declares it once in a profile file that --profile reads.
|
|
351
324
|
|
|
352
325
|
Template options:
|
|
353
326
|
--resugar The file is the canonical aontu; print the template
|
|
@@ -457,11 +430,11 @@ Fmt options:
|
|
|
457
430
|
The fmt verb prints one document in the agreed form; with no file it
|
|
458
431
|
reads standard input. Several files need one of the options above.
|
|
459
432
|
|
|
460
|
-
A file whose extension is not .aon is a GENERATOR, as it is for
|
|
461
|
-
the aontu its marker lines carry is formatted, the marker
|
|
462
|
-
left margin with the aontu indented after it, and every
|
|
463
|
-
is held on a line of its own. A file with no marker line
|
|
464
|
-
another language's, and is refused.
|
|
433
|
+
A file whose extension is not .aon is a GENERATOR, as it is for
|
|
434
|
+
template: the aontu its marker lines carry is formatted, the marker
|
|
435
|
+
stands at the left margin with the aontu indented after it, and every
|
|
436
|
+
line of output is held on a line of its own. A file with no marker line
|
|
437
|
+
in it is another language's, and is refused.
|
|
465
438
|
|
|
466
439
|
Fmt exit codes: 0 formatted or clean, 1 a --check file would change or
|
|
467
440
|
a --strict finding, 2 usage, 4 a document does not parse.
|
|
@@ -1764,6 +1737,12 @@ const VIEW_USAGE_CODES = [
|
|
|
1764
1737
|
];
|
|
1765
1738
|
const MOD_HELP = 'aontu mod tidy|verify|vendor|manifest [dir] (try --help)';
|
|
1766
1739
|
function runMod(argv) {
|
|
1740
|
+
const trusted = takeTrust(argv);
|
|
1741
|
+
if (null == trusted) {
|
|
1742
|
+
return 2;
|
|
1743
|
+
}
|
|
1744
|
+
argv = trusted.argv;
|
|
1745
|
+
const trust = trusted.trust;
|
|
1767
1746
|
const rest = [];
|
|
1768
1747
|
let format = 'text';
|
|
1769
1748
|
let against;
|
|
@@ -1819,10 +1798,11 @@ function runMod(argv) {
|
|
|
1819
1798
|
process.stderr.write('aontu: --against is a manifest option\n');
|
|
1820
1799
|
return 2;
|
|
1821
1800
|
}
|
|
1822
|
-
const
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1801
|
+
const modopts = modToolOptions(trust, (0, node_path_1.resolve)(dir));
|
|
1802
|
+
const report = 'tidy' === sub ? (0, mod_tool_1.modTidy)(dir, modopts) :
|
|
1803
|
+
'verify' === sub ? (0, mod_tool_1.modVerify)(dir, modopts) :
|
|
1804
|
+
'vendor' === sub ? (0, mod_tool_1.modVendor)(dir, modopts) :
|
|
1805
|
+
(0, mod_tool_1.modManifest)(dir, modopts, against);
|
|
1826
1806
|
process.stdout.write(('json' === format ?
|
|
1827
1807
|
(0, aontu_1.exactJSON)({ aontu: { version: version(), verb: 'mod ' + sub }, ...report }, 2) :
|
|
1828
1808
|
modText(sub, report)) + '\n');
|
|
@@ -1843,11 +1823,16 @@ const MOD_EXIT = {
|
|
|
1843
1823
|
// The tooling's evaluator: the same standalone evaluation the module
|
|
1844
1824
|
// resolver verifies with (ts/src/mod.ts), and for the same reason —
|
|
1845
1825
|
// only the engine can say what a module MEANS.
|
|
1846
|
-
function modToolOptions() {
|
|
1826
|
+
function modToolOptions(trust, entryRoot) {
|
|
1827
|
+
const opts = verbOpts(trust, entryRoot);
|
|
1828
|
+
// The user cache lives outside any confinement root, so a confined
|
|
1829
|
+
// run reads the vendor tree only -- as the evaluator's own module
|
|
1830
|
+
// leg already does when a root is set.
|
|
1831
|
+
const rooted = null != opts.trust?.include?.root;
|
|
1847
1832
|
return {
|
|
1848
|
-
cache: (0, mod_1.modCacheDir)(),
|
|
1833
|
+
...(rooted ? {} : { cache: (0, mod_1.modCacheDir)() }),
|
|
1849
1834
|
eval: (src, path) => {
|
|
1850
|
-
const a0 = new aontu_1.Aontu();
|
|
1835
|
+
const a0 = new aontu_1.Aontu(opts);
|
|
1851
1836
|
const ctx = a0.ctx({ collect: true });
|
|
1852
1837
|
const val = a0.unify(src, { path }, ctx);
|
|
1853
1838
|
return {
|
|
@@ -1981,6 +1966,108 @@ function runRelations(argv) {
|
|
|
1981
1966
|
}
|
|
1982
1967
|
return RELATIONS_EXIT[report.verdict];
|
|
1983
1968
|
}
|
|
1969
|
+
const TRACE_HELP = 'aontu trace [--at <path>] [--format json] [--marker <token>] ' +
|
|
1970
|
+
'[--profile <file>] <file>';
|
|
1971
|
+
// WHAT WROTE THIS LINE. Every piece a rule stamped, under the
|
|
1972
|
+
// component tree, with the file it reached, the rule set that wrote it
|
|
1973
|
+
// and the model node the dispatch matched.
|
|
1974
|
+
function runTrace(argv) {
|
|
1975
|
+
const trusted = takeTrust(argv);
|
|
1976
|
+
if (null == trusted) {
|
|
1977
|
+
return 2;
|
|
1978
|
+
}
|
|
1979
|
+
argv = trusted.argv;
|
|
1980
|
+
const trust = trusted.trust;
|
|
1981
|
+
const rest = [];
|
|
1982
|
+
const profileFiles = [];
|
|
1983
|
+
let format = 'text';
|
|
1984
|
+
let at = undefined;
|
|
1985
|
+
let marker = undefined;
|
|
1986
|
+
for (let i = 0; i < argv.length; i++) {
|
|
1987
|
+
const arg = argv[i];
|
|
1988
|
+
if ('-h' === arg || '--help' === arg) {
|
|
1989
|
+
process.stdout.write(HELP);
|
|
1990
|
+
return 0;
|
|
1991
|
+
}
|
|
1992
|
+
if ('--format' === arg) {
|
|
1993
|
+
const f = argv[++i];
|
|
1994
|
+
if ('text' !== f && 'json' !== f) {
|
|
1995
|
+
process.stderr.write('aontu: --format needs text or json\n');
|
|
1996
|
+
return 2;
|
|
1997
|
+
}
|
|
1998
|
+
format = f;
|
|
1999
|
+
}
|
|
2000
|
+
else if ('--at' === arg) {
|
|
2001
|
+
at = argv[++i];
|
|
2002
|
+
if (null == at) {
|
|
2003
|
+
process.stderr.write('aontu: --at needs a path\n');
|
|
2004
|
+
return 2;
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
else if ('--marker' === arg) {
|
|
2008
|
+
marker = argv[++i];
|
|
2009
|
+
if (null == marker) {
|
|
2010
|
+
process.stderr.write('aontu: --marker needs a token\n');
|
|
2011
|
+
return 2;
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
else if ('--profile' === arg) {
|
|
2015
|
+
const pf = argv[++i];
|
|
2016
|
+
if (null == pf) {
|
|
2017
|
+
process.stderr.write('aontu: --profile needs a file\n');
|
|
2018
|
+
return 2;
|
|
2019
|
+
}
|
|
2020
|
+
profileFiles.push(pf);
|
|
2021
|
+
}
|
|
2022
|
+
else if (arg.startsWith('-')) {
|
|
2023
|
+
process.stderr.write(`aontu: unknown trace option ${arg} (try --help)\n`);
|
|
2024
|
+
return 2;
|
|
2025
|
+
}
|
|
2026
|
+
else {
|
|
2027
|
+
rest.push(arg);
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
if (1 !== rest.length) {
|
|
2031
|
+
process.stderr.write(`aontu: trace needs one file\n${TRACE_HELP}\n`);
|
|
2032
|
+
return 2;
|
|
2033
|
+
}
|
|
2034
|
+
let src;
|
|
2035
|
+
try {
|
|
2036
|
+
src = (0, node_fs_1.readFileSync)(rest[0], 'utf8');
|
|
2037
|
+
}
|
|
2038
|
+
catch (err) {
|
|
2039
|
+
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2040
|
+
return 2;
|
|
2041
|
+
}
|
|
2042
|
+
const declared = loadProfiles(profileFiles, trust);
|
|
2043
|
+
if ('number' === typeof declared) {
|
|
2044
|
+
return declared;
|
|
2045
|
+
}
|
|
2046
|
+
// A GENERATOR IS AN ENTRY, not a preprocessing step: the file whose
|
|
2047
|
+
// provenance is asked for is the one the author edits.
|
|
2048
|
+
if (!rest[0].endsWith('.aon')) {
|
|
2049
|
+
src = (0, template_1.desugarTemplate)(src, marker ??
|
|
2050
|
+
(0, template_1.markerFromProfiles)(declared, rest[0]) ?? (0, template_1.markerFor)(rest[0]));
|
|
2051
|
+
}
|
|
2052
|
+
const report = (0, trace_1.traceRun)(src, {
|
|
2053
|
+
path: rest[0], at,
|
|
2054
|
+
...verbOpts(trust, entryRootOf(rest[0])),
|
|
2055
|
+
});
|
|
2056
|
+
if ('error' === report.verdict) {
|
|
2057
|
+
// An error report always carries its findings.
|
|
2058
|
+
const errors = report.errors;
|
|
2059
|
+
process.stderr.write(errors.map(renderFinding).join('\n') + '\n');
|
|
2060
|
+
return 4;
|
|
2061
|
+
}
|
|
2062
|
+
if ('json' === format) {
|
|
2063
|
+
process.stdout.write(JSON.stringify({ trace: report.trace }) + '\n');
|
|
2064
|
+
return 0;
|
|
2065
|
+
}
|
|
2066
|
+
for (const e of report.trace) {
|
|
2067
|
+
process.stdout.write([e.file, e.at, e.node, e.rule].join('\t') + '\n');
|
|
2068
|
+
}
|
|
2069
|
+
return 0;
|
|
2070
|
+
}
|
|
1984
2071
|
function runReaches(argv) {
|
|
1985
2072
|
const trusted = takeTrust(argv);
|
|
1986
2073
|
if (null == trusted) {
|
|
@@ -2530,281 +2617,6 @@ function runJsonSchema(argv) {
|
|
|
2530
2617
|
return 'error' === report.verdict ? 4 :
|
|
2531
2618
|
strict && 'lossy' === report.verdict ? 1 : 0;
|
|
2532
2619
|
}
|
|
2533
|
-
const RENDER_HELP = 'aontu render [--at <path>] [--profile <file>]... [--unit <path>] ' +
|
|
2534
|
-
'[--stdout | --out <dir> | --check <dir> | --coverage] ' +
|
|
2535
|
-
'[--coverage-at <path>] [--strict] [--marker <token>] <file> (try --help)';
|
|
2536
|
-
function runRender(argv) {
|
|
2537
|
-
const trusted = takeTrust(argv);
|
|
2538
|
-
if (null == trusted) {
|
|
2539
|
-
return 2;
|
|
2540
|
-
}
|
|
2541
|
-
argv = trusted.argv;
|
|
2542
|
-
const trust = trusted.trust;
|
|
2543
|
-
const files = [];
|
|
2544
|
-
const profileFiles = [];
|
|
2545
|
-
let format = 'text';
|
|
2546
|
-
let at = undefined;
|
|
2547
|
-
let unit = undefined;
|
|
2548
|
-
let out = undefined;
|
|
2549
|
-
let check = undefined;
|
|
2550
|
-
let toStdout = false;
|
|
2551
|
-
let strict = false;
|
|
2552
|
-
let coverage = false;
|
|
2553
|
-
let coverageAt = undefined;
|
|
2554
|
-
let marker = undefined;
|
|
2555
|
-
for (let i = 0; i < argv.length; i++) {
|
|
2556
|
-
const arg = argv[i];
|
|
2557
|
-
if ('-h' === arg || '--help' === arg) {
|
|
2558
|
-
process.stdout.write(HELP);
|
|
2559
|
-
return 0;
|
|
2560
|
-
}
|
|
2561
|
-
if ('--format' === arg) {
|
|
2562
|
-
const f = argv[++i];
|
|
2563
|
-
if ('text' !== f && 'json' !== f) {
|
|
2564
|
-
process.stderr.write('aontu: --format needs text or json\n');
|
|
2565
|
-
return 2;
|
|
2566
|
-
}
|
|
2567
|
-
format = f;
|
|
2568
|
-
}
|
|
2569
|
-
else if ('--at' === arg) {
|
|
2570
|
-
at = argv[++i];
|
|
2571
|
-
if (null == at) {
|
|
2572
|
-
process.stderr.write('aontu: --at needs a path\n');
|
|
2573
|
-
return 2;
|
|
2574
|
-
}
|
|
2575
|
-
}
|
|
2576
|
-
else if ('--unit' === arg) {
|
|
2577
|
-
unit = argv[++i];
|
|
2578
|
-
if (null == unit) {
|
|
2579
|
-
process.stderr.write('aontu: --unit needs a unit path\n');
|
|
2580
|
-
return 2;
|
|
2581
|
-
}
|
|
2582
|
-
}
|
|
2583
|
-
else if ('--profile' === arg) {
|
|
2584
|
-
const pf = argv[++i];
|
|
2585
|
-
if (null == pf) {
|
|
2586
|
-
process.stderr.write('aontu: --profile needs a file\n');
|
|
2587
|
-
return 2;
|
|
2588
|
-
}
|
|
2589
|
-
profileFiles.push(pf);
|
|
2590
|
-
}
|
|
2591
|
-
else if ('--out' === arg) {
|
|
2592
|
-
out = argv[++i];
|
|
2593
|
-
if (null == out) {
|
|
2594
|
-
process.stderr.write('aontu: --out needs a directory\n');
|
|
2595
|
-
return 2;
|
|
2596
|
-
}
|
|
2597
|
-
}
|
|
2598
|
-
else if ('--check' === arg) {
|
|
2599
|
-
check = argv[++i];
|
|
2600
|
-
if (null == check) {
|
|
2601
|
-
process.stderr.write('aontu: --check needs a directory\n');
|
|
2602
|
-
return 2;
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2605
|
-
else if ('--stdout' === arg) {
|
|
2606
|
-
toStdout = true;
|
|
2607
|
-
}
|
|
2608
|
-
else if ('--coverage' === arg) {
|
|
2609
|
-
coverage = true;
|
|
2610
|
-
}
|
|
2611
|
-
else if ('--marker' === arg) {
|
|
2612
|
-
marker = argv[++i];
|
|
2613
|
-
if (null == marker) {
|
|
2614
|
-
process.stderr.write('aontu: --marker needs a token\n');
|
|
2615
|
-
return 2;
|
|
2616
|
-
}
|
|
2617
|
-
}
|
|
2618
|
-
else if ('--coverage-at' === arg) {
|
|
2619
|
-
coverageAt = argv[++i];
|
|
2620
|
-
if (null == coverageAt) {
|
|
2621
|
-
process.stderr.write('aontu: --coverage-at needs a path\n');
|
|
2622
|
-
return 2;
|
|
2623
|
-
}
|
|
2624
|
-
}
|
|
2625
|
-
else if ('--strict' === arg) {
|
|
2626
|
-
strict = true;
|
|
2627
|
-
}
|
|
2628
|
-
else if (arg.startsWith('-')) {
|
|
2629
|
-
process.stderr.write(`aontu: unknown render option ${arg} (try --help)\n`);
|
|
2630
|
-
return 2;
|
|
2631
|
-
}
|
|
2632
|
-
else {
|
|
2633
|
-
files.push(arg);
|
|
2634
|
-
}
|
|
2635
|
-
}
|
|
2636
|
-
if (1 !== files.length) {
|
|
2637
|
-
process.stderr.write(`aontu: render needs one file\n${RENDER_HELP}\n`);
|
|
2638
|
-
return 2;
|
|
2639
|
-
}
|
|
2640
|
-
const modes = [toStdout, undefined !== out, undefined !== check, coverage]
|
|
2641
|
-
.filter((on) => on).length;
|
|
2642
|
-
if (1 < modes) {
|
|
2643
|
-
process.stderr.write('aontu: render takes one of --stdout, --out, --check or --coverage\n');
|
|
2644
|
-
return 2;
|
|
2645
|
-
}
|
|
2646
|
-
// A NARROWER MEASURE NEEDS SOMETHING TO NARROW. `--coverage-at`
|
|
2647
|
-
// without `--coverage` asks for a report the run does not compute,
|
|
2648
|
-
// and answering silently would be the wrong half of the request.
|
|
2649
|
-
if (undefined !== coverageAt && !coverage) {
|
|
2650
|
-
process.stderr.write('aontu: --coverage-at needs --coverage\n');
|
|
2651
|
-
return 2;
|
|
2652
|
-
}
|
|
2653
|
-
let src;
|
|
2654
|
-
try {
|
|
2655
|
-
src = (0, node_fs_1.readFileSync)(files[0], 'utf8');
|
|
2656
|
-
}
|
|
2657
|
-
catch (err) {
|
|
2658
|
-
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2659
|
-
return 2;
|
|
2660
|
-
}
|
|
2661
|
-
const loadedProfiles = loadProfiles(profileFiles, trust);
|
|
2662
|
-
if ('number' === typeof loadedProfiles) {
|
|
2663
|
-
return loadedProfiles;
|
|
2664
|
-
}
|
|
2665
|
-
const profiles = loadedProfiles;
|
|
2666
|
-
if (!files[0].endsWith('.aon')) {
|
|
2667
|
-
src = (0, template_1.desugarTemplate)(src, marker ??
|
|
2668
|
-
(0, template_1.markerFromProfiles)(profiles, files[0]) ?? (0, template_1.markerFor)(files[0]));
|
|
2669
|
-
}
|
|
2670
|
-
// A RENDER WITH NO PROFILE PRODUCES NO UNITS, and said so with zero
|
|
2671
|
-
// bytes and exit 0. The profile is what maps a model onto a
|
|
2672
|
-
// language, so without one there is nothing for the renderer to
|
|
2673
|
-
// write -- which is a usable answer only if the caller is told.
|
|
2674
|
-
const noProfiles = 0 === profiles.length;
|
|
2675
|
-
const report = (0, aontu_1.render)(src, {
|
|
2676
|
-
at, unit, strict, profiles, path: files[0],
|
|
2677
|
-
coverage, coverageAt,
|
|
2678
|
-
// THE JSON REPORT CARRIES THE TRACE (D9), which is what the shape
|
|
2679
|
-
// there has always said; a text run computes it only when the
|
|
2680
|
-
// coverage report needs it.
|
|
2681
|
-
trace: 'json' === format,
|
|
2682
|
-
...verbOpts(trust, entryRootOf(files[0])),
|
|
2683
|
-
});
|
|
2684
|
-
// Said once, whatever the format: stdout stays the report.
|
|
2685
|
-
if ('error' !== report.verdict && 0 === report.units.length) {
|
|
2686
|
-
vacuous('nothing was rendered', noProfiles
|
|
2687
|
-
? 'no profile was given, and the document declares none' +
|
|
2688
|
-
' (see aontu help tasks)'
|
|
2689
|
-
: 'the document produced no units under this profile');
|
|
2690
|
-
}
|
|
2691
|
-
if ('json' === format) {
|
|
2692
|
-
process.stdout.write((0, aontu_1.exactJSON)({
|
|
2693
|
-
aontu: { version: version(), verb: 'render' },
|
|
2694
|
-
verdict: report.verdict,
|
|
2695
|
-
units: report.units,
|
|
2696
|
-
lossy: report.lossy,
|
|
2697
|
-
...(null == report.errors ? {} : { errors: report.errors }),
|
|
2698
|
-
...(null == report.trace ? {} : { trace: report.trace }),
|
|
2699
|
-
...(null == report.coverage ? {} : { coverage: report.coverage }),
|
|
2700
|
-
}, 2) + '\n');
|
|
2701
|
-
return renderExit(report, 0);
|
|
2702
|
-
}
|
|
2703
|
-
if ('error' === report.verdict) {
|
|
2704
|
-
process.stderr.write(report.errors.map(renderFinding).join('\n') + '\n');
|
|
2705
|
-
return renderExit(report, 0);
|
|
2706
|
-
}
|
|
2707
|
-
let drift = 0;
|
|
2708
|
-
if (toStdout) {
|
|
2709
|
-
// ONE UNIT'S BYTES AND NOTHING ELSE, so the output can be piped
|
|
2710
|
-
// into a formatter or a file.
|
|
2711
|
-
if (1 !== report.units.length) {
|
|
2712
|
-
process.stderr.write('aontu: --stdout needs exactly one unit, and the instance has ' +
|
|
2713
|
-
`${report.units.length}; --unit names one\n`);
|
|
2714
|
-
return 2;
|
|
2715
|
-
}
|
|
2716
|
-
process.stdout.write(report.units[0].text);
|
|
2717
|
-
}
|
|
2718
|
-
else if (undefined !== out) {
|
|
2719
|
-
// EVERY UNIT BELOW <dir>, OR NOTHING: every unit rendered first
|
|
2720
|
-
// (the report above), and no file touched unless all did. The
|
|
2721
|
-
// directory is realpath-confined; a unit path is already a relative
|
|
2722
|
-
// descent (render_path refuses the rest), and the check here is
|
|
2723
|
-
// against the symlink inside it. render never deletes.
|
|
2724
|
-
for (const u of report.units) {
|
|
2725
|
-
if ((0, mcp_1.outsideRoot)(out, (0, node_path_1.resolve)(out, u.path))) {
|
|
2726
|
-
process.stderr.write(`aontu: ${u.path} escapes ${out}\n`);
|
|
2727
|
-
return 2;
|
|
2728
|
-
}
|
|
2729
|
-
}
|
|
2730
|
-
for (const u of report.units) {
|
|
2731
|
-
const full = (0, node_path_1.resolve)(out, u.path);
|
|
2732
|
-
try {
|
|
2733
|
-
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(full), { recursive: true });
|
|
2734
|
-
(0, node_fs_1.writeFileSync)(full, u.text, 'utf8');
|
|
2735
|
-
}
|
|
2736
|
-
catch (err) {
|
|
2737
|
-
process.stderr.write(`aontu: cannot write ${u.path}: ${err.message}\n`);
|
|
2738
|
-
return 2;
|
|
2739
|
-
}
|
|
2740
|
-
process.stderr.write(`wrote ${u.path}\n`);
|
|
2741
|
-
}
|
|
2742
|
-
}
|
|
2743
|
-
else if (undefined !== check) {
|
|
2744
|
-
// RENDER AND COMPARE: a unit whose bytes differ from the file at
|
|
2745
|
-
// <dir>/<path>, or whose file is absent, is drift, listed by path.
|
|
2746
|
-
// The CI form.
|
|
2747
|
-
for (const u of report.units) {
|
|
2748
|
-
let have = undefined;
|
|
2749
|
-
try {
|
|
2750
|
-
have = (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(check, u.path), 'utf8');
|
|
2751
|
-
}
|
|
2752
|
-
catch {
|
|
2753
|
-
// Absent is drift, reported below.
|
|
2754
|
-
}
|
|
2755
|
-
if (undefined === have) {
|
|
2756
|
-
drift++;
|
|
2757
|
-
process.stderr.write(`aontu: ${u.path} is missing from ${check}\n`);
|
|
2758
|
-
}
|
|
2759
|
-
else if (have !== u.text) {
|
|
2760
|
-
drift++;
|
|
2761
|
-
process.stderr.write(`aontu: ${u.path} differs from the rendered unit\n`);
|
|
2762
|
-
}
|
|
2763
|
-
}
|
|
2764
|
-
}
|
|
2765
|
-
else if (coverage) {
|
|
2766
|
-
// THE COVERAGE REPORT (P7), one line per finding and a count at
|
|
2767
|
-
// the end: dead model first, then the declarations no rule
|
|
2768
|
-
// produced. A clean report is the count line alone.
|
|
2769
|
-
const cov = report.coverage;
|
|
2770
|
-
for (const d of cov.dead) {
|
|
2771
|
-
process.stdout.write(`dead: ${d}\n`);
|
|
2772
|
-
}
|
|
2773
|
-
for (const u of cov.unruled) {
|
|
2774
|
-
process.stdout.write(`unruled: ${u.unit} ${u.path}\n`);
|
|
2775
|
-
}
|
|
2776
|
-
process.stdout.write(`coverage: ${cov.read.length} path(s) read, ${cov.dead.length} ` +
|
|
2777
|
-
`no output consumed, ${cov.unruled.length} declaration(s) ` +
|
|
2778
|
-
'no rule produced\n');
|
|
2779
|
-
}
|
|
2780
|
-
else {
|
|
2781
|
-
// THE SUMMARY: one line per unit -- its path, its language and its
|
|
2782
|
-
// size -- since several units have no one text to print.
|
|
2783
|
-
for (const u of report.units) {
|
|
2784
|
-
process.stdout.write(`${u.path}\t${u.lang}\t${u.text.length} bytes\n`);
|
|
2785
|
-
}
|
|
2786
|
-
}
|
|
2787
|
-
for (const l of report.lossy) {
|
|
2788
|
-
process.stderr.write(`lossy: ${l.unit} ${l.path} tier ${l.tier} ${l.construct}: ${l.reason}\n`);
|
|
2789
|
-
}
|
|
2790
|
-
return renderExit(report, drift);
|
|
2791
|
-
}
|
|
2792
|
-
// D8's exit table over a report: a refused unit path is usage (2), a
|
|
2793
|
-
// strict refusal is lossy (1), any other error is the document's (4);
|
|
2794
|
-
// drift under --check is 1.
|
|
2795
|
-
function renderExit(report, drift) {
|
|
2796
|
-
if ('error' === report.verdict) {
|
|
2797
|
-
const errors = report.errors;
|
|
2798
|
-
if (errors.every((f) => 'render_path' === f.code)) {
|
|
2799
|
-
return 2;
|
|
2800
|
-
}
|
|
2801
|
-
if (errors.every((f) => 'render_strict' === f.code)) {
|
|
2802
|
-
return 1;
|
|
2803
|
-
}
|
|
2804
|
-
return 4;
|
|
2805
|
-
}
|
|
2806
|
-
return 0 < drift ? 1 : 0;
|
|
2807
|
-
}
|
|
2808
2620
|
const TEMPLATE_HELP = 'aontu template [--resugar] [--check] [--marker <token>] <file> (try --help)';
|
|
2809
2621
|
function runTemplate(argv) {
|
|
2810
2622
|
const trusted = takeTrust(argv);
|
|
@@ -2896,9 +2708,9 @@ function runTemplate(argv) {
|
|
|
2896
2708
|
return 0;
|
|
2897
2709
|
}
|
|
2898
2710
|
// The profiles named by --profile, vetted, or the exit code that says
|
|
2899
|
-
// why not. A profile is a language declared as data: `
|
|
2900
|
-
// one to a
|
|
2901
|
-
//
|
|
2711
|
+
// why not. A profile is a language declared as data: `template` and
|
|
2712
|
+
// `fmt` match one to a file by the extensions its `template.ext`
|
|
2713
|
+
// names.
|
|
2902
2714
|
function loadProfiles(profileFiles, trust) {
|
|
2903
2715
|
const profiles = [];
|
|
2904
2716
|
const langs = new Map();
|
|
@@ -2911,7 +2723,7 @@ function loadProfiles(profileFiles, trust) {
|
|
|
2911
2723
|
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2912
2724
|
return 2;
|
|
2913
2725
|
}
|
|
2914
|
-
const loaded = (0, aontu_1.
|
|
2726
|
+
const loaded = (0, aontu_1.loadProfile)(text, { path: (0, node_path_1.resolve)(pf), ...verbOpts(trust, entryRootOf(pf)) });
|
|
2915
2727
|
if (undefined !== loaded.errors) {
|
|
2916
2728
|
process.stderr.write(loaded.errors.map(renderFinding).join('\n') + '\n');
|
|
2917
2729
|
return 4;
|
|
@@ -3583,8 +3395,8 @@ function runFmt(argv) {
|
|
|
3583
3395
|
}
|
|
3584
3396
|
else if ('--marker' === arg) {
|
|
3585
3397
|
// THE MARKER SAYS THE FILE IS A GENERATOR, whatever its
|
|
3586
|
-
// extension: `
|
|
3587
|
-
//
|
|
3398
|
+
// extension: `fmt` and `template` take the same option for the
|
|
3399
|
+
// same reason, a language the table has never seen.
|
|
3588
3400
|
marker = argv[++i];
|
|
3589
3401
|
if (null == marker) {
|
|
3590
3402
|
process.stderr.write('aontu: --marker needs a token\n');
|
|
@@ -3991,8 +3803,8 @@ function runInit(argv) {
|
|
|
3991
3803
|
const KNOWN_VERBS = [
|
|
3992
3804
|
'agentsmd', 'allow', 'breaking', 'explain', 'fmt', 'get', 'hash',
|
|
3993
3805
|
'help', 'init', 'jsonschema', 'lsp', 'mcp', 'mod', 'reaches',
|
|
3994
|
-
'relations', '
|
|
3995
|
-
'view', 'why',
|
|
3806
|
+
'relations', 'set', 'subsume', 'template', 'trace', 'trim',
|
|
3807
|
+
'vet', 'view', 'why',
|
|
3996
3808
|
];
|
|
3997
3809
|
exports.KNOWN_VERBS = KNOWN_VERBS;
|
|
3998
3810
|
// looksLikeVerb reports whether an unreadable argument was meant as a
|
|
@@ -4112,12 +3924,12 @@ function main(argv, servers = SERVERS) {
|
|
|
4112
3924
|
if ('jsonschema' === argv[2]) {
|
|
4113
3925
|
return finish(runJsonSchema(argv.slice(3)));
|
|
4114
3926
|
}
|
|
4115
|
-
if ('render' === argv[2]) {
|
|
4116
|
-
return finish(runRender(argv.slice(3)));
|
|
4117
|
-
}
|
|
4118
3927
|
if ('template' === argv[2]) {
|
|
4119
3928
|
return finish(runTemplate(argv.slice(3)));
|
|
4120
3929
|
}
|
|
3930
|
+
if ('trace' === argv[2]) {
|
|
3931
|
+
return finish(runTrace(argv.slice(3)));
|
|
3932
|
+
}
|
|
4121
3933
|
if ('reaches' === argv[2]) {
|
|
4122
3934
|
return finish(runReaches(argv.slice(3)));
|
|
4123
3935
|
}
|
|
@@ -4212,5 +4024,5 @@ function main(argv, servers = SERVERS) {
|
|
|
4212
4024
|
else {
|
|
4213
4025
|
runStdin(mode, format, trust).then((code) => finish(code));
|
|
4214
4026
|
}
|
|
4215
|
-
} /* node:coverage ignore next
|
|
4027
|
+
} /* node:coverage ignore next 21 */
|
|
4216
4028
|
//# sourceMappingURL=cli.js.map
|