aontu 0.63.0 → 0.65.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 +8 -8
- package/dist/agentsmd.js +3 -3
- package/dist/agentsmd.js.map +1 -1
- 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 +16 -3
- package/dist/cli.js +653 -455
- package/dist/cli.js.map +1 -1
- package/dist/compat.d.ts +7 -0
- package/dist/compat.js +113 -0
- package/dist/compat.js.map +1 -0
- package/dist/helpdoc.js +5 -5
- package/dist/helpdoc.js.map +1 -1
- package/dist/hints.js +14 -5
- package/dist/hints.js.map +1 -1
- package/dist/lang.d.ts +1 -0
- package/dist/lang.js +8 -0
- package/dist/lang.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.d.ts +18 -3
- package/dist/mod.js +117 -46
- package/dist/mod.js.map +1 -1
- package/dist/pkg-net.d.ts +227 -0
- package/dist/pkg-net.js +1598 -0
- package/dist/pkg-net.js.map +1 -0
- package/dist/pkg-zip.d.ts +8 -0
- package/dist/pkg-zip.js +196 -0
- package/dist/pkg-zip.js.map +1 -0
- package/dist/pkg.d.ts +159 -0
- package/dist/pkg.js +767 -0
- package/dist/pkg.js.map +1 -0
- package/dist/profile.d.ts +9 -0
- package/dist/profile.js +28 -0
- package/dist/profile.js.map +1 -0
- package/dist/report-sarif.js +1 -1
- package/dist/report-sarif.js.map +1 -1
- package/dist/subsume.d.ts +3 -1
- package/dist/subsume.js +2 -0
- package/dist/subsume.js.map +1 -1
- 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/SKILL.md +3 -3
- package/skill/error-codes.md +4 -4
- package/skill/examples.md +4 -4
- package/skill/grammar-card.md +1 -1
- package/skill/init/check.sh +2 -2
- package/skill/tasks.md +14 -12
- package/src/agentsmd.ts +3 -3
- package/src/aontu.ts +3 -8
- package/src/aontumodel.ts +6 -12
- package/src/casing.ts +95 -0
- package/src/cli.ts +758 -495
- package/src/compat.ts +148 -0
- package/src/helpdoc.ts +5 -5
- package/src/hints.ts +14 -7
- package/src/lang.ts +9 -1
- package/src/mcp.ts +0 -39
- package/src/mod.ts +142 -51
- package/src/pkg-net.ts +1945 -0
- package/src/pkg-zip.ts +228 -0
- package/src/pkg.ts +1018 -0
- package/src/profile.ts +42 -0
- package/src/report-sarif.ts +1 -1
- package/src/subsume.ts +2 -2
- 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/mod-tool.d.ts +0 -58
- package/dist/mod-tool.js +0 -403
- package/dist/mod-tool.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/mod-tool.ts +0 -561
- package/src/render.ts +0 -580
package/dist/cli.js
CHANGED
|
@@ -13,9 +13,13 @@ 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;
|
|
18
|
-
exports.
|
|
17
|
+
exports.runTrace = runTrace;
|
|
18
|
+
exports.runPkg = runPkg;
|
|
19
|
+
exports.runModel = runModel;
|
|
20
|
+
exports.runPackageVerb = runPackageVerb;
|
|
21
|
+
exports.pkgToolOptions = pkgToolOptions;
|
|
22
|
+
exports.serveUntilInterrupted = serveUntilInterrupted;
|
|
19
23
|
exports.runHash = runHash;
|
|
20
24
|
exports.runGet = runGet;
|
|
21
25
|
exports.runHelp = runHelp;
|
|
@@ -40,13 +44,14 @@ const node_path_1 = require("node:path");
|
|
|
40
44
|
const node_os_1 = require("node:os");
|
|
41
45
|
const node_readline_1 = require("node:readline");
|
|
42
46
|
const aontu_1 = require("./aontu");
|
|
47
|
+
const trace_1 = require("./trace");
|
|
43
48
|
const template_1 = require("./template");
|
|
44
|
-
const mcp_1 = require("./mcp");
|
|
45
49
|
const report_sarif_1 = require("./report-sarif");
|
|
46
50
|
const lsp_server_1 = require("./lsp-server");
|
|
47
51
|
const mcp_server_1 = require("./mcp-server");
|
|
48
52
|
const jsonschema_1 = require("./jsonschema");
|
|
49
|
-
const
|
|
53
|
+
const pkg_1 = require("./pkg");
|
|
54
|
+
const pkg_net_1 = require("./pkg-net");
|
|
50
55
|
const mod_1 = require("./mod");
|
|
51
56
|
const vet_1 = require("./vet");
|
|
52
57
|
const reach_1 = require("./reach");
|
|
@@ -67,16 +72,23 @@ const HELP = `Usage: aontu [options] [file]
|
|
|
67
72
|
aontu view <kind> [options] <file>...
|
|
68
73
|
aontu view --views <path> [--check] [options] <file>
|
|
69
74
|
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
75
|
aontu template [--resugar] [--check] [--marker <token>]
|
|
74
76
|
[--profile <file>] <file>
|
|
77
|
+
aontu trace [--at <path>] [--format json] [--marker <token>]
|
|
78
|
+
[--profile <file>] <file>
|
|
75
79
|
aontu hash [options] <file>
|
|
76
|
-
aontu
|
|
77
|
-
aontu
|
|
78
|
-
aontu
|
|
79
|
-
aontu
|
|
80
|
+
aontu sync [--frozen] [options] [dir]
|
|
81
|
+
aontu add <pkg>[@<version>] [options] [dir]
|
|
82
|
+
aontu get <pkg>[@<version>] [options] [dir]
|
|
83
|
+
aontu remove <pkg> [options] [dir]
|
|
84
|
+
aontu why <pkg> [options] [dir]
|
|
85
|
+
aontu publish [--yes] [--to <dir>] [options] [dir]
|
|
86
|
+
aontu pkg tidy|verify|vendor|manifest|refreeze|tree|outdated|serve
|
|
87
|
+
[options] [dir]
|
|
88
|
+
aontu pkg keygen <file>
|
|
89
|
+
aontu model get <path> [options] <file>
|
|
90
|
+
aontu model why <path> [options] <file>
|
|
91
|
+
aontu model set <path>=<value>... --entry <file> --overlay <file>
|
|
80
92
|
aontu allow --role <role> [--at <path>] <roles-file> <path>...
|
|
81
93
|
aontu agentsmd [--write <AGENTS.md>] [--depth <n>] <file>
|
|
82
94
|
aontu fmt [-w|-l|--check|-d|--lint] [--marker <token>]
|
|
@@ -145,18 +157,57 @@ Options:
|
|
|
145
157
|
named format keeps its meaning, and .js stays
|
|
146
158
|
refused. Every verb takes it
|
|
147
159
|
|
|
148
|
-
|
|
160
|
+
Package verbs (a module is imported; a package is published):
|
|
161
|
+
sync Make the project correct: resolve by minimum version
|
|
162
|
+
selection, fetch what is missing, write aontu_meta/pkg-lock.aon,
|
|
163
|
+
vendor, verify. --frozen refuses to change the lockfile
|
|
164
|
+
add Take on a dependency the project does not have, then sync;
|
|
165
|
+
refuses one it has and names get
|
|
166
|
+
get Add a dependency or raise its minimum, then sync. Without a
|
|
167
|
+
version, the newest version outside the cooldown
|
|
168
|
+
remove Drop a dependency, then sync
|
|
169
|
+
why Why is this package in the closure: every path of
|
|
170
|
+
requirements that reaches it
|
|
171
|
+
publish Publish this package. A dry run without --yes; --to <dir>
|
|
172
|
+
writes the repository layout into a directory instead
|
|
173
|
+
|
|
174
|
+
Package options:
|
|
149
175
|
--format <f> text (default) or json
|
|
150
|
-
--
|
|
176
|
+
--frozen sync: fail if the lockfile would change (the CI mode)
|
|
177
|
+
--yes publish: send it (the default is a dry run)
|
|
178
|
+
--to <dir> publish: write the read-path layout into a directory
|
|
179
|
+
--key <file> publish: the Ed25519 private key (PKCS#8 PEM) that
|
|
180
|
+
signs the manifest, for the key provider
|
|
181
|
+
--token <file> publish: the forge's OIDC token, read from a file
|
|
182
|
+
--base <url> the repository to read from (repeatable; overrides
|
|
183
|
+
pkg.aon repo.base)
|
|
184
|
+
--write <url> publish: the write path (overrides pkg.aon repo.write)
|
|
185
|
+
--against <dir> manifest: a prior version's tree, to gate on
|
|
186
|
+
--upstream <u> serve: fetch on miss from this repository (repeatable)
|
|
187
|
+
--listen <a> serve: the address to listen on (default 127.0.0.1:8017)
|
|
151
188
|
|
|
152
|
-
|
|
153
|
-
tidy Resolve the
|
|
154
|
-
rewrite aontu_meta/
|
|
155
|
-
verify Check every locked
|
|
156
|
-
pins, and change nothing
|
|
189
|
+
pkg subcommands (the rest of the package operations):
|
|
190
|
+
tidy Resolve the closure by minimum version selection and
|
|
191
|
+
rewrite aontu_meta/pkg-lock.aon in canonical form
|
|
192
|
+
verify Check every locked package still is and still means what
|
|
193
|
+
the lockfile pins, bytes before meaning, and change nothing
|
|
194
|
+
(the CI gate; tidy rewrites)
|
|
157
195
|
vendor Materialise the locked closure into aontu_meta/vendor/
|
|
158
|
-
manifest Print the
|
|
159
|
-
|
|
196
|
+
manifest Print the manifest a publish would send, gated on the
|
|
197
|
+
compatibility check against --against
|
|
198
|
+
refreeze Recompute every canon pin and nothing else, after a
|
|
199
|
+
canonical-form change in the engine
|
|
200
|
+
tree The locked closure as a graph
|
|
201
|
+
outdated What could move, and what would move with it
|
|
202
|
+
serve Serve a repository directory; with --upstream, a caching
|
|
203
|
+
proxy in front of another repository
|
|
204
|
+
keygen Write a new Ed25519 signing key (PKCS#8 PEM) to a file,
|
|
205
|
+
once, and print the signer id a consumer names
|
|
206
|
+
|
|
207
|
+
model subcommands (one document, interrogated or edited):
|
|
208
|
+
get What the document says at a path
|
|
209
|
+
why Every contribution to the value at a path
|
|
210
|
+
set Append a path-flattened conjunct to an overlay
|
|
160
211
|
|
|
161
212
|
Vet options:
|
|
162
213
|
--at <path> Validate against this path of the schema ($.a.b)
|
|
@@ -235,21 +286,21 @@ Hash options:
|
|
|
235
286
|
Hash exit codes: 0 hashed, 2 usage, 4 the document does not stand up
|
|
236
287
|
on its own.
|
|
237
288
|
|
|
238
|
-
|
|
289
|
+
Model get options:
|
|
239
290
|
-c, --canon Canonical-form fragment (default: generated JSON)
|
|
240
291
|
--keys Keys at the node, one per line
|
|
241
292
|
--types Shape view: concrete leaves lifted to their kinds
|
|
242
293
|
--depth <n> Structure to depth n; deeper nodes render as top
|
|
243
294
|
--format <f> text (default) or json
|
|
244
295
|
|
|
245
|
-
|
|
246
|
-
document does not stand up on its own.
|
|
296
|
+
Model get exit codes: 0 rendered, 1 the path names nothing, 2 usage, 4
|
|
297
|
+
the document does not stand up on its own.
|
|
247
298
|
|
|
248
|
-
|
|
299
|
+
Model why options:
|
|
249
300
|
--format <f> text (default) or json
|
|
250
301
|
|
|
251
|
-
|
|
252
|
-
2 usage, 4 the document does not stand up on its own.
|
|
302
|
+
Model why exit codes mirror get's: 0 explained, 1 the path names
|
|
303
|
+
nothing, 2 usage, 4 the document does not stand up on its own.
|
|
253
304
|
|
|
254
305
|
View kinds: doc, lattice, tree, matrix, graph, layer, sets, layers,
|
|
255
306
|
ladder, poset (the poset takes several files). The figure goes to stdout, the loss
|
|
@@ -317,37 +368,11 @@ View exit codes: 0 rendered, 1 --check mismatch or lossy under
|
|
|
317
368
|
--strict, 2 usage or --max-rows exceeded, 4 the document does not stand
|
|
318
369
|
up on its own, or a relation, root or path that names nothing.
|
|
319
370
|
|
|
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.
|
|
371
|
+
A template entry file whose extension is not .aon is a GENERATOR: a
|
|
372
|
+
document in the target's own syntax, whose marker lines carry aontu and
|
|
373
|
+
whose other lines are output. It is desugared before it is evaluated,
|
|
374
|
+
and a language the table does not know names its marker with --marker,
|
|
375
|
+
or declares it once in a profile file that --profile reads.
|
|
351
376
|
|
|
352
377
|
Template options:
|
|
353
378
|
--resugar The file is the canonical aontu; print the template
|
|
@@ -365,7 +390,7 @@ every other line is a line of output.
|
|
|
365
390
|
|
|
366
391
|
Template exit codes: 0 written, 1 --check drift, 2 usage or I/O.
|
|
367
392
|
|
|
368
|
-
|
|
393
|
+
Model set options:
|
|
369
394
|
--entry <file> The document the change is checked against
|
|
370
395
|
--overlay <file> The file the change is appended to (created if
|
|
371
396
|
absent; not written when the change does not hold)
|
|
@@ -381,7 +406,7 @@ Set options:
|
|
|
381
406
|
--format <f> text (default) or json
|
|
382
407
|
|
|
383
408
|
Set exit codes are vet's verdict classes: 0 valid, 1 invalid (the
|
|
384
|
-
change contradicts a pinned value -- aontu why locates it, and
|
|
409
|
+
change contradicts a pinned value -- aontu model why locates it, and
|
|
385
410
|
--in-place rewrites it), 2 usage, 3 incomplete, 4 the entry does not
|
|
386
411
|
stand up on its own.
|
|
387
412
|
|
|
@@ -457,11 +482,11 @@ Fmt options:
|
|
|
457
482
|
The fmt verb prints one document in the agreed form; with no file it
|
|
458
483
|
reads standard input. Several files need one of the options above.
|
|
459
484
|
|
|
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.
|
|
485
|
+
A file whose extension is not .aon is a GENERATOR, as it is for
|
|
486
|
+
template: the aontu its marker lines carry is formatted, the marker
|
|
487
|
+
stands at the left margin with the aontu indented after it, and every
|
|
488
|
+
line of output is held on a line of its own. A file with no marker line
|
|
489
|
+
in it is another language's, and is refused.
|
|
465
490
|
|
|
466
491
|
Fmt exit codes: 0 formatted or clean, 1 a --check file would change or
|
|
467
492
|
a --strict finding, 2 usage, 4 a document does not parse.
|
|
@@ -583,7 +608,7 @@ function trustOpts(trust, entryRoot) {
|
|
|
583
608
|
return { ...text, trustWarn: makeTrustWarn(), trustWarnRoot: entryRoot };
|
|
584
609
|
}
|
|
585
610
|
}
|
|
586
|
-
function takeTrust(argv) {
|
|
611
|
+
function takeTrust(argv, io = PROCESS_IO) {
|
|
587
612
|
const rest = [];
|
|
588
613
|
let trust = { kind: 'system-warn', textExt: [] };
|
|
589
614
|
let textExt = [];
|
|
@@ -592,7 +617,7 @@ function takeTrust(argv) {
|
|
|
592
617
|
if ('--trust' === arg) {
|
|
593
618
|
const parsed = null == argv[i + 1] ? undefined : parseTrustArg(argv[++i]);
|
|
594
619
|
if (null == parsed) {
|
|
595
|
-
|
|
620
|
+
io.err('aontu: --trust needs system, none, or root[:dir]\n');
|
|
596
621
|
return undefined;
|
|
597
622
|
}
|
|
598
623
|
trust = parsed;
|
|
@@ -600,7 +625,7 @@ function takeTrust(argv) {
|
|
|
600
625
|
else if ('--include-root' === arg) {
|
|
601
626
|
const dir = argv[++i];
|
|
602
627
|
if (null == dir) {
|
|
603
|
-
|
|
628
|
+
io.err('aontu: --include-root needs a directory\n');
|
|
604
629
|
return undefined;
|
|
605
630
|
}
|
|
606
631
|
trust = { kind: 'root', dir, textExt };
|
|
@@ -608,7 +633,7 @@ function takeTrust(argv) {
|
|
|
608
633
|
else if ('--text-ext' === arg) {
|
|
609
634
|
const list = null == argv[i + 1] ? undefined : parseTextExt(argv[++i]);
|
|
610
635
|
if (null == list) {
|
|
611
|
-
|
|
636
|
+
io.err('aontu: --text-ext needs extensions, without dots' +
|
|
612
637
|
' (--text-ext md,sql)\n');
|
|
613
638
|
return undefined;
|
|
614
639
|
}
|
|
@@ -621,7 +646,7 @@ function takeTrust(argv) {
|
|
|
621
646
|
return { argv: rest, trust: { ...trust, textExt } };
|
|
622
647
|
}
|
|
623
648
|
// `md,sql` or `.md,.sql` -- the dot is accepted and dropped, because a
|
|
624
|
-
// reader who has just written `@"notes.txt"` reaches for one. An empty
|
|
649
|
+
// reader who has just written `@"./notes.txt"` reaches for one. An empty
|
|
625
650
|
// element, or anything that is not an extension, is a usage error
|
|
626
651
|
// rather than a silently ignored word: a flag that quietly does
|
|
627
652
|
// nothing is how a document ends up refused with no reason visible.
|
|
@@ -1762,74 +1787,134 @@ const VIEW_USAGE_CODES = [
|
|
|
1762
1787
|
'view_at_required', 'view_sets_required', 'view_group_required',
|
|
1763
1788
|
'view_document_shape', 'view_style_profile', 'view_style_unknown',
|
|
1764
1789
|
];
|
|
1765
|
-
const
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1790
|
+
const PKG_HELP = 'aontu pkg tidy|verify|vendor|manifest|refreeze|tree|outdated|serve [dir] | keygen <file> (try --help)';
|
|
1791
|
+
const PKG_SUBS = [
|
|
1792
|
+
'tidy', 'verify', 'vendor', 'manifest', 'refreeze', 'tree', 'outdated',
|
|
1793
|
+
'serve', 'keygen',
|
|
1794
|
+
];
|
|
1795
|
+
function parsePkgArgs(argv, verb, io) {
|
|
1796
|
+
const out = {
|
|
1797
|
+
rest: [], format: 'text', frozen: false, yes: false, base: [], upstream: [],
|
|
1798
|
+
};
|
|
1799
|
+
const value = (name, i) => {
|
|
1800
|
+
const v = argv[i];
|
|
1801
|
+
if (null == v) {
|
|
1802
|
+
io.err(`aontu: ${name} needs a value\n`);
|
|
1803
|
+
}
|
|
1804
|
+
return v;
|
|
1805
|
+
};
|
|
1770
1806
|
for (let i = 0; i < argv.length; i++) {
|
|
1771
1807
|
const arg = argv[i];
|
|
1772
1808
|
if ('-h' === arg || '--help' === arg) {
|
|
1773
|
-
|
|
1774
|
-
return
|
|
1809
|
+
io.out(HELP);
|
|
1810
|
+
return undefined;
|
|
1775
1811
|
}
|
|
1776
1812
|
if ('--format' === arg) {
|
|
1777
1813
|
const f = argv[++i];
|
|
1778
1814
|
if ('text' !== f && 'json' !== f) {
|
|
1779
|
-
|
|
1780
|
-
return
|
|
1815
|
+
io.err('aontu: --format needs text or json\n');
|
|
1816
|
+
return undefined;
|
|
1781
1817
|
}
|
|
1782
|
-
format = f;
|
|
1818
|
+
out.format = f;
|
|
1783
1819
|
}
|
|
1784
|
-
else if ('--
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1820
|
+
else if ('--frozen' === arg) {
|
|
1821
|
+
out.frozen = true;
|
|
1822
|
+
}
|
|
1823
|
+
else if ('--yes' === arg) {
|
|
1824
|
+
out.yes = true;
|
|
1825
|
+
}
|
|
1826
|
+
else if ('--against' === arg || '--to' === arg || '--key' === arg ||
|
|
1827
|
+
'--token' === arg || '--write' === arg || '--listen' === arg) {
|
|
1828
|
+
const v = value(arg, ++i);
|
|
1829
|
+
if (null == v) {
|
|
1830
|
+
return undefined;
|
|
1831
|
+
}
|
|
1832
|
+
out['--against' === arg ? 'against' : '--to' === arg ? 'to' :
|
|
1833
|
+
'--key' === arg ? 'key' : '--token' === arg ? 'token' :
|
|
1834
|
+
'--write' === arg ? 'write' : 'listen'] = v;
|
|
1835
|
+
}
|
|
1836
|
+
else if ('--base' === arg || '--upstream' === arg) {
|
|
1837
|
+
const v = value(arg, ++i);
|
|
1838
|
+
if (null == v) {
|
|
1839
|
+
return undefined;
|
|
1789
1840
|
}
|
|
1790
|
-
|
|
1841
|
+
out['--base' === arg ? 'base' : 'upstream'].push(v);
|
|
1791
1842
|
}
|
|
1792
1843
|
else if (arg.startsWith('-')) {
|
|
1793
|
-
|
|
1794
|
-
return
|
|
1844
|
+
io.err(`aontu: unknown ${verb} option ${arg} (try --help)\n`);
|
|
1845
|
+
return undefined;
|
|
1795
1846
|
}
|
|
1796
1847
|
else {
|
|
1797
|
-
rest.push(arg);
|
|
1848
|
+
out.rest.push(arg);
|
|
1798
1849
|
}
|
|
1799
1850
|
}
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1851
|
+
return out;
|
|
1852
|
+
}
|
|
1853
|
+
// A verb that finds the older layout names the current one, once, and
|
|
1854
|
+
// reads nothing from it.
|
|
1855
|
+
function nameOldLayout(dir, io) {
|
|
1856
|
+
const old = ['aon_vendor', 'mod-lock.aon', 'mod.aon',
|
|
1857
|
+
(0, node_path_1.join)(mod_1.META_DIR, 'mod-lock.aon')].filter((f) => (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, f)));
|
|
1858
|
+
if (0 < old.length) {
|
|
1859
|
+
io.err('aontu: ' + old.join(', ') + ' belong to an older layout: the package ' +
|
|
1860
|
+
'file is ' + mod_1.PKG_FILE + ', the lockfile ' + (0, node_path_1.join)(mod_1.META_DIR, mod_1.LOCK_FILE) +
|
|
1861
|
+
' and the vendor tree ' + (0, node_path_1.join)(mod_1.META_DIR, 'vendor') + '; rename ' +
|
|
1862
|
+
mod_1.PKG_FILE + '\'s `mod` block to `pkg`, then run aontu sync\n');
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
function runPkg(argv, servers) {
|
|
1866
|
+
const io = servers.io ?? PROCESS_IO;
|
|
1867
|
+
const trusted = takeTrust(argv, io);
|
|
1868
|
+
if (null == trusted) {
|
|
1806
1869
|
return 2;
|
|
1807
1870
|
}
|
|
1808
|
-
|
|
1809
|
-
|
|
1871
|
+
const args = parsePkgArgs(trusted.argv, 'pkg', io);
|
|
1872
|
+
if (null == args) {
|
|
1873
|
+
return '-h' === trusted.argv[0] || trusted.argv.includes('--help') ? 0 : 2;
|
|
1874
|
+
}
|
|
1875
|
+
const trust = trusted.trust;
|
|
1876
|
+
const sub = args.rest[0];
|
|
1877
|
+
const dir = args.rest[1] ?? '.';
|
|
1878
|
+
if (!PKG_SUBS.includes(sub) || 2 < args.rest.length) {
|
|
1879
|
+
io.err(`aontu: pkg needs one of ${PKG_SUBS.join(', ')}\n${PKG_HELP}\n`);
|
|
1810
1880
|
return 2;
|
|
1811
1881
|
}
|
|
1812
|
-
if (
|
|
1813
|
-
|
|
1814
|
-
'
|
|
1882
|
+
if ('keygen' === sub) {
|
|
1883
|
+
if (2 !== args.rest.length) {
|
|
1884
|
+
io.err('aontu: pkg keygen needs the file to write\naontu pkg keygen <file>\n');
|
|
1885
|
+
return 2;
|
|
1886
|
+
}
|
|
1887
|
+
const made = (0, pkg_net_1.keygen)(args.rest[1]);
|
|
1888
|
+
if (null != made.refused) {
|
|
1889
|
+
io.err('aontu: ' + made.refused + '\n');
|
|
1890
|
+
return 2;
|
|
1891
|
+
}
|
|
1892
|
+
io.out('signer: ' + made.signer + '\n');
|
|
1893
|
+
return 0;
|
|
1815
1894
|
}
|
|
1816
|
-
|
|
1895
|
+
nameOldLayout(dir, io);
|
|
1896
|
+
// `--against` gates a manifest and means nothing to the others;
|
|
1817
1897
|
// accepting it there would say it had been honoured.
|
|
1818
|
-
if (null != against && 'manifest' !== sub) {
|
|
1819
|
-
|
|
1898
|
+
if (null != args.against && 'manifest' !== sub) {
|
|
1899
|
+
io.err('aontu: --against is a manifest option\n');
|
|
1820
1900
|
return 2;
|
|
1821
1901
|
}
|
|
1822
|
-
const
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1902
|
+
const opts = pkgToolOptions(trust, (0, node_path_1.resolve)(dir));
|
|
1903
|
+
if ('outdated' === sub || 'serve' === sub) {
|
|
1904
|
+
return runPkgNet(sub, dir, args, opts, servers, io);
|
|
1905
|
+
}
|
|
1906
|
+
const report = 'tidy' === sub ? (0, pkg_1.pkgTidy)(dir, opts) :
|
|
1907
|
+
'verify' === sub ? (0, pkg_1.pkgVerify)(dir, opts) :
|
|
1908
|
+
'vendor' === sub ? (0, pkg_1.pkgVendor)(dir, opts) :
|
|
1909
|
+
'refreeze' === sub ? (0, pkg_1.pkgRefreeze)(dir, opts) :
|
|
1910
|
+
'tree' === sub ? (0, pkg_1.pkgTree)(dir, opts) :
|
|
1911
|
+
(0, pkg_1.pkgManifest)(dir, opts, args.against);
|
|
1912
|
+
io.out(('json' === args.format ?
|
|
1913
|
+
(0, aontu_1.exactJSON)({ aontu: { version: version(), verb: 'pkg ' + sub }, ...report }, 2) :
|
|
1914
|
+
pkgText(sub, report)) + '\n');
|
|
1915
|
+
return PKG_EXIT[report.verdict];
|
|
1830
1916
|
}
|
|
1831
|
-
const
|
|
1832
|
-
const MOD_EXIT = {
|
|
1917
|
+
const PKG_EXIT = {
|
|
1833
1918
|
ok: 0,
|
|
1834
1919
|
missing: 1,
|
|
1835
1920
|
mismatch: 1,
|
|
@@ -1837,17 +1922,28 @@ const MOD_EXIT = {
|
|
|
1837
1922
|
// nothing to check, which is a refusal and not a pass.
|
|
1838
1923
|
unlocked: 1,
|
|
1839
1924
|
breaking: 1,
|
|
1925
|
+
frozen: 1,
|
|
1926
|
+
refused: 1,
|
|
1927
|
+
outdated: 1,
|
|
1928
|
+
sent: 0,
|
|
1929
|
+
'dry-run': 0,
|
|
1930
|
+
current: 0,
|
|
1840
1931
|
undecided: 3,
|
|
1841
1932
|
error: 4,
|
|
1842
1933
|
};
|
|
1843
1934
|
// The tooling's evaluator: the same standalone evaluation the module
|
|
1844
1935
|
// resolver verifies with (ts/src/mod.ts), and for the same reason —
|
|
1845
1936
|
// only the engine can say what a module MEANS.
|
|
1846
|
-
function
|
|
1937
|
+
function pkgToolOptions(trust, entryRoot) {
|
|
1938
|
+
const opts = verbOpts(trust, entryRoot);
|
|
1939
|
+
// The user cache lives outside any confinement root, so a confined
|
|
1940
|
+
// run reads the vendor tree only -- as the evaluator's own module
|
|
1941
|
+
// leg already does when a root is set.
|
|
1942
|
+
const rooted = null != opts.trust?.include?.root;
|
|
1847
1943
|
return {
|
|
1848
|
-
cache: (0, mod_1.modCacheDir)(),
|
|
1944
|
+
...(rooted ? {} : { cache: (0, mod_1.modCacheDir)() }),
|
|
1849
1945
|
eval: (src, path) => {
|
|
1850
|
-
const a0 = new aontu_1.Aontu();
|
|
1946
|
+
const a0 = new aontu_1.Aontu(opts);
|
|
1851
1947
|
const ctx = a0.ctx({ collect: true });
|
|
1852
1948
|
const val = a0.unify(src, { path }, ctx);
|
|
1853
1949
|
return {
|
|
@@ -1855,24 +1951,54 @@ function modToolOptions() {
|
|
|
1855
1951
|
hash: (0, aontu_1.canonHash)(val),
|
|
1856
1952
|
canon: val.canon,
|
|
1857
1953
|
// The same question `aontu hash` asks before it will answer:
|
|
1858
|
-
// did this document stand up ON ITS OWN? See
|
|
1954
|
+
// did this document stand up ON ITS OWN? See PkgToolEval.
|
|
1859
1955
|
ok: 0 === ctx.err.length && true !== val.isNil,
|
|
1860
1956
|
};
|
|
1861
1957
|
},
|
|
1862
1958
|
};
|
|
1863
1959
|
}
|
|
1864
|
-
function
|
|
1960
|
+
function pkgLockLines(entries) {
|
|
1961
|
+
return entries.map((e) => e.key + ' ' + e.v + ' ' + e.canon);
|
|
1962
|
+
}
|
|
1963
|
+
// The renderers verify, tidy and sync share, as the Go port's do.
|
|
1964
|
+
function pkgMismatchLines(mismatched) {
|
|
1965
|
+
return mismatched.map((m) => 'canon' === m.pin ?
|
|
1966
|
+
m.key + ': pinned ' + m.want + ' but the store means ' +
|
|
1967
|
+
('' === m.got ? 'nothing (it does not evaluate)' : m.got) :
|
|
1968
|
+
m.key + ': pinned ' + m.pin + ' ' + m.want + ' but the store holds ' + m.got);
|
|
1969
|
+
}
|
|
1970
|
+
// NOT a fetch: the package may well be sitting in the store. What is
|
|
1971
|
+
// absent is the PIN, and only a sync writes one.
|
|
1972
|
+
function pkgUnlockedLines(unlocked) {
|
|
1973
|
+
return unlocked.map((key) => key + ': not in the lockfile (run: aontu sync)');
|
|
1974
|
+
}
|
|
1975
|
+
function pkgForbiddenLines(forbidden) {
|
|
1976
|
+
return forbidden.map((f) => f + ': not admitted in a package');
|
|
1977
|
+
}
|
|
1978
|
+
function pkgText(sub, report) {
|
|
1865
1979
|
const lines = ['verdict: ' + report.verdict];
|
|
1866
1980
|
if ('manifest' === sub) {
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
lines.push('
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1981
|
+
const m = report.manifest;
|
|
1982
|
+
if (null != m) {
|
|
1983
|
+
lines.push(m.package + ' ' + m.version + ' ' + m.publish);
|
|
1984
|
+
lines.push('archive: ' + m.archive.digest + ' (' + m.archive.files.length +
|
|
1985
|
+
' files, ' + m.archive.size + ' bytes)');
|
|
1986
|
+
for (const mod of m.modules) {
|
|
1987
|
+
lines.push('module: ' + mod.path + ' ' + mod.main + ' ' + mod.canon);
|
|
1988
|
+
}
|
|
1989
|
+
for (const key of Object.keys(m.deps).sort(keyorder_1.cmpCodePoint)) {
|
|
1990
|
+
lines.push('dep: ' + key + ' ' + m.deps[key].v +
|
|
1991
|
+
(null == m.deps[key].pkg ? '' : ' (' + m.deps[key].pkg + ')'));
|
|
1992
|
+
}
|
|
1993
|
+
for (const v of m.retract ?? []) {
|
|
1994
|
+
lines.push('retract: ' + v);
|
|
1995
|
+
}
|
|
1996
|
+
if (null != m.moved) {
|
|
1997
|
+
lines.push('moved: ' + m.moved);
|
|
1998
|
+
}
|
|
1999
|
+
for (const f of m.archive.files) {
|
|
2000
|
+
lines.push('file: ' + f.path + ' ' + f.digest + ' ' + f.size);
|
|
2001
|
+
}
|
|
1876
2002
|
}
|
|
1877
2003
|
for (const f of report.findings) {
|
|
1878
2004
|
lines.push(f.path + ': ' + f.message);
|
|
@@ -1880,44 +2006,281 @@ function modText(sub, report) {
|
|
|
1880
2006
|
for (const miss of report.missing) {
|
|
1881
2007
|
lines.push(miss + ': missing');
|
|
1882
2008
|
}
|
|
2009
|
+
lines.push(...pkgForbiddenLines(report.forbidden));
|
|
1883
2010
|
return lines.join('\n');
|
|
1884
2011
|
}
|
|
1885
2012
|
if ('verify' === sub) {
|
|
1886
|
-
for (const
|
|
1887
|
-
lines.push(
|
|
2013
|
+
for (const key of report.verified) {
|
|
2014
|
+
lines.push(key + ': verified');
|
|
1888
2015
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
2016
|
+
lines.push(...pkgMismatchLines(report.mismatched), ...pkgUnlockedLines(report.unlocked));
|
|
2017
|
+
for (const miss of report.missing) {
|
|
2018
|
+
lines.push(miss + ': not fetched (run: aontu sync)');
|
|
1892
2019
|
}
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
2020
|
+
return lines.join('\n');
|
|
2021
|
+
}
|
|
2022
|
+
if ('refreeze' === sub) {
|
|
2023
|
+
for (const r of report.repinned) {
|
|
2024
|
+
lines.push(r.key + ': ' + r.from + ' -> ' + r.to);
|
|
2025
|
+
}
|
|
2026
|
+
for (const key of report.unchanged) {
|
|
2027
|
+
lines.push(key + ': unchanged');
|
|
2028
|
+
}
|
|
2029
|
+
for (const bad of report.unevaluable) {
|
|
2030
|
+
lines.push(bad + ': does not evaluate on its own; nothing to pin');
|
|
1897
2031
|
}
|
|
1898
2032
|
for (const miss of report.missing) {
|
|
1899
|
-
lines.push(miss + ': not fetched (run: aontu
|
|
2033
|
+
lines.push(miss + ': not fetched (run: aontu sync)');
|
|
1900
2034
|
}
|
|
1901
2035
|
return lines.join('\n');
|
|
1902
2036
|
}
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
2037
|
+
if ('tree' === sub) {
|
|
2038
|
+
const byKey = new Map(report.nodes.map((n) => [n.key, n]));
|
|
2039
|
+
const seen = new Set();
|
|
2040
|
+
const walk = (key, depth) => {
|
|
2041
|
+
const node = byKey.get(key);
|
|
2042
|
+
const again = seen.has(key);
|
|
2043
|
+
seen.add(key);
|
|
2044
|
+
lines.push(' '.repeat(depth) + key +
|
|
2045
|
+
(null == node || '' === node.v ? '' : ' ' + node.v) +
|
|
2046
|
+
(again ? ' (above)' : null == node ? ' (not locked)' : ''));
|
|
2047
|
+
if (again || null == node) {
|
|
2048
|
+
return;
|
|
2049
|
+
}
|
|
2050
|
+
for (const dep of node.deps) {
|
|
2051
|
+
walk(dep, depth + 1);
|
|
2052
|
+
}
|
|
2053
|
+
};
|
|
2054
|
+
walk(report.root, 0);
|
|
2055
|
+
for (const miss of report.missing) {
|
|
2056
|
+
lines.push(miss + ': not fetched (run: aontu sync)');
|
|
2057
|
+
}
|
|
2058
|
+
return lines.join('\n');
|
|
1907
2059
|
}
|
|
1908
|
-
|
|
2060
|
+
const done = 'tidy' === sub ? pkgLockLines(report.lock) : report.vendored;
|
|
2061
|
+
lines.push(...done);
|
|
2062
|
+
// A package that is PRESENT but does not stand up. Named separately
|
|
1909
2063
|
// from a missing one because the repair is different: a fetch cannot
|
|
1910
|
-
// help, the
|
|
2064
|
+
// help, the package itself has to be fixed (or its own dependencies
|
|
1911
2065
|
// vendored beside it). Before the missing tail, as the Go port's
|
|
1912
2066
|
// shared renderer orders them.
|
|
1913
2067
|
for (const bad of report.unevaluable ?? []) {
|
|
1914
2068
|
lines.push(bad + ': does not evaluate on its own; nothing to pin');
|
|
1915
2069
|
}
|
|
2070
|
+
lines.push(...pkgForbiddenLines(report.forbidden ?? []));
|
|
1916
2071
|
for (const miss of report.missing) {
|
|
1917
|
-
lines.push(miss + ': not fetched (run: aontu
|
|
2072
|
+
lines.push(miss + ': not fetched (run: aontu sync)');
|
|
1918
2073
|
}
|
|
1919
2074
|
return lines.join('\n');
|
|
1920
2075
|
}
|
|
2076
|
+
// The two `pkg` subcommands that reach a repository.
|
|
2077
|
+
async function runPkgNet(sub, dir, args, opts, servers, io) {
|
|
2078
|
+
if ('serve' === sub) {
|
|
2079
|
+
const served = await (0, pkg_net_1.startServe)({
|
|
2080
|
+
dir: (0, node_path_1.resolve)(dir), upstream: args.upstream,
|
|
2081
|
+
listen: args.listen ?? '127.0.0.1:8017', http: servers.http(),
|
|
2082
|
+
});
|
|
2083
|
+
io.out('serving ' + (0, node_path_1.resolve)(dir) + ' at ' + served.url + '\n' +
|
|
2084
|
+
args.upstream.map((u) => 'upstream: ' + u + '\n').join(''));
|
|
2085
|
+
await servers.serve(served);
|
|
2086
|
+
await served.close();
|
|
2087
|
+
return 0;
|
|
2088
|
+
}
|
|
2089
|
+
if (null == opts.cache) {
|
|
2090
|
+
io.err(NO_CACHE);
|
|
2091
|
+
return 2;
|
|
2092
|
+
}
|
|
2093
|
+
const report = await (0, pkg_net_1.pkgOutdated)(dir, opts, servers.http(), { base: netBase(args) });
|
|
2094
|
+
io.out(pkgReportText('pkg outdated', args.format, report) + '\n');
|
|
2095
|
+
return PKG_EXIT[report.verdict];
|
|
2096
|
+
}
|
|
2097
|
+
const NO_CACHE = 'aontu: this verb reads and writes the user cache, which a ' +
|
|
2098
|
+
'confined run (--trust root) does not reach and this host does not name ' +
|
|
2099
|
+
'(set XDG_CACHE_HOME or HOME)\n';
|
|
2100
|
+
function netBase(args) {
|
|
2101
|
+
return 0 === args.base.length ? undefined : args.base;
|
|
2102
|
+
}
|
|
2103
|
+
const PACKAGE_VERBS = ['sync', 'add', 'get', 'remove', 'why', 'publish'];
|
|
2104
|
+
const PACKAGE_HELP = {
|
|
2105
|
+
sync: 'aontu sync [--frozen] [dir] (try --help)',
|
|
2106
|
+
add: 'aontu add <pkg> [dir] (try --help)',
|
|
2107
|
+
get: 'aontu get <pkg>[@<version>] [dir] (try --help)',
|
|
2108
|
+
remove: 'aontu remove <pkg> [dir] (try --help)',
|
|
2109
|
+
why: 'aontu why <pkg> [dir] (try --help)',
|
|
2110
|
+
publish: 'aontu publish [--yes] [--to <dir>] [--key <file>] [dir] (try --help)',
|
|
2111
|
+
};
|
|
2112
|
+
// The top-level package verbs (ADR-039 part 5). Every one but `why`
|
|
2113
|
+
// reaches a repository, so every one runs behind the seam.
|
|
2114
|
+
async function runPackageVerb(verb, argv, servers) {
|
|
2115
|
+
const io = servers.io ?? PROCESS_IO;
|
|
2116
|
+
const trusted = takeTrust(argv, io);
|
|
2117
|
+
if (null == trusted) {
|
|
2118
|
+
return 2;
|
|
2119
|
+
}
|
|
2120
|
+
const args = parsePkgArgs(trusted.argv, verb, io);
|
|
2121
|
+
if (null == args) {
|
|
2122
|
+
return '-h' === trusted.argv[0] || trusted.argv.includes('--help') ? 0 : 2;
|
|
2123
|
+
}
|
|
2124
|
+
const wantsPkg = 'sync' !== verb && 'publish' !== verb;
|
|
2125
|
+
const dir = args.rest[wantsPkg ? 1 : 0] ?? '.';
|
|
2126
|
+
if (args.rest.length > (wantsPkg ? 2 : 1) || (wantsPkg && 0 === args.rest.length)) {
|
|
2127
|
+
io.err('aontu: ' + verb + (wantsPkg ? ' needs a package' : ' takes a directory') +
|
|
2128
|
+
'\n' + PACKAGE_HELP[verb] + '\n');
|
|
2129
|
+
return 2;
|
|
2130
|
+
}
|
|
2131
|
+
nameOldLayout(dir, io);
|
|
2132
|
+
const opts = pkgToolOptions(trusted.trust, (0, node_path_1.resolve)(dir));
|
|
2133
|
+
const http = servers.http();
|
|
2134
|
+
if ('why' === verb) {
|
|
2135
|
+
const report = (0, pkg_net_1.pkgWhy)(dir, opts, args.rest[0]);
|
|
2136
|
+
io.out(pkgReportText('why', args.format, report) + '\n');
|
|
2137
|
+
return PKG_EXIT[report.verdict];
|
|
2138
|
+
}
|
|
2139
|
+
if ('publish' === verb) {
|
|
2140
|
+
for (const f of [args.key, args.token]) {
|
|
2141
|
+
if (null != f && !(0, node_fs_1.existsSync)(f)) {
|
|
2142
|
+
io.err('aontu: cannot read ' + f + '\n');
|
|
2143
|
+
return 2;
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
if (true === args.yes && null == args.key) {
|
|
2147
|
+
io.err('aontu: publish --yes needs --key <file>, the Ed25519 key that signs\n');
|
|
2148
|
+
return 2;
|
|
2149
|
+
}
|
|
2150
|
+
const report = await (0, pkg_net_1.pkgPublish)(dir, opts, http, {
|
|
2151
|
+
yes: args.yes, to: null == args.to ? undefined : (0, node_path_1.resolve)(args.to), key: args.key,
|
|
2152
|
+
token: args.token, against: args.against, base: netBase(args), write: args.write,
|
|
2153
|
+
});
|
|
2154
|
+
io.out(pkgReportText('publish', args.format, report) + '\n');
|
|
2155
|
+
return PKG_EXIT[report.verdict];
|
|
2156
|
+
}
|
|
2157
|
+
if (null == opts.cache) {
|
|
2158
|
+
io.err(NO_CACHE);
|
|
2159
|
+
return 2;
|
|
2160
|
+
}
|
|
2161
|
+
const net = { base: netBase(args) };
|
|
2162
|
+
const report = 'sync' === verb ? await (0, pkg_net_1.pkgSync)(dir, opts, http, { ...net, frozen: args.frozen }) :
|
|
2163
|
+
'remove' === verb ? await (0, pkg_net_1.pkgRemove)(dir, opts, http, args.rest[0], net) :
|
|
2164
|
+
await (0, pkg_net_1.pkgGet)(dir, opts, http, args.rest[0], { ...net, mode: verb });
|
|
2165
|
+
if ('string' === typeof report) {
|
|
2166
|
+
io.err('aontu: ' + report + '\n');
|
|
2167
|
+
return 2;
|
|
2168
|
+
}
|
|
2169
|
+
io.out(pkgReportText(verb, args.format, report) + '\n');
|
|
2170
|
+
return PKG_EXIT[report.verdict];
|
|
2171
|
+
}
|
|
2172
|
+
function pkgReportText(verb, fmt, report) {
|
|
2173
|
+
return 'json' === fmt ?
|
|
2174
|
+
(0, aontu_1.exactJSON)({ aontu: { version: version(), verb }, ...report }, 2) :
|
|
2175
|
+
pkgNetText(verb, report);
|
|
2176
|
+
}
|
|
2177
|
+
function pkgNetText(verb, report) {
|
|
2178
|
+
const lines = ['verdict: ' + report.verdict];
|
|
2179
|
+
const tail = () => {
|
|
2180
|
+
for (const e of report.events ?? []) {
|
|
2181
|
+
lines.push(e.code + ': ' + e.message);
|
|
2182
|
+
}
|
|
2183
|
+
if (null != report.refusal) {
|
|
2184
|
+
lines.push('refused: ' + report.refusal.code + ': ' + report.refusal.message);
|
|
2185
|
+
}
|
|
2186
|
+
};
|
|
2187
|
+
if ('why' === verb) {
|
|
2188
|
+
const why = report;
|
|
2189
|
+
for (const p of why.paths) {
|
|
2190
|
+
lines.push(p.join(' -> '));
|
|
2191
|
+
}
|
|
2192
|
+
if ('missing' === why.verdict) {
|
|
2193
|
+
lines.push(why.pkg + ': not in the closure');
|
|
2194
|
+
}
|
|
2195
|
+
return lines.join('\n');
|
|
2196
|
+
}
|
|
2197
|
+
if ('publish' === verb) {
|
|
2198
|
+
const pub = report;
|
|
2199
|
+
lines.push(...pkgText('manifest', pub).split('\n').slice(1));
|
|
2200
|
+
if (null != pub.digest) {
|
|
2201
|
+
lines.push('digest: ' + pub.digest);
|
|
2202
|
+
}
|
|
2203
|
+
if (null != pub.signer) {
|
|
2204
|
+
lines.push('signer: ' + pub.signer);
|
|
2205
|
+
}
|
|
2206
|
+
if (null != pub.against) {
|
|
2207
|
+
lines.push('against: ' + pub.against);
|
|
2208
|
+
}
|
|
2209
|
+
if (null != pub.to) {
|
|
2210
|
+
lines.push('to: ' + pub.to);
|
|
2211
|
+
}
|
|
2212
|
+
if (null != pub.write) {
|
|
2213
|
+
lines.push('write: ' + pub.write + pkg_net_1.PUBLISH_PATH);
|
|
2214
|
+
}
|
|
2215
|
+
if ('dry-run' === pub.verdict) {
|
|
2216
|
+
lines.push('dry run: nothing sent (add --yes)');
|
|
2217
|
+
}
|
|
2218
|
+
if ('sent' === pub.verdict) {
|
|
2219
|
+
lines.push('sent');
|
|
2220
|
+
}
|
|
2221
|
+
tail();
|
|
2222
|
+
return lines.join('\n');
|
|
2223
|
+
}
|
|
2224
|
+
if ('pkg outdated' === verb) {
|
|
2225
|
+
const out = report;
|
|
2226
|
+
for (const e of out.locked) {
|
|
2227
|
+
if (0 < (0, pkg_1.versionCompare)(e.newest, e.v)) {
|
|
2228
|
+
lines.push(e.key + ' ' + e.v + ' -> ' + e.newest);
|
|
2229
|
+
for (const m of e.moves) {
|
|
2230
|
+
lines.push(' ' + m);
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
else {
|
|
2234
|
+
lines.push(e.key + ' ' + e.v + ': current');
|
|
2235
|
+
}
|
|
2236
|
+
if (null != e.retracted) {
|
|
2237
|
+
lines.push(e.key + ' ' + e.v + ': retracted by ' + e.retracted);
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
tail();
|
|
2241
|
+
return lines.join('\n');
|
|
2242
|
+
}
|
|
2243
|
+
const sync = report;
|
|
2244
|
+
if (null != sync.change) {
|
|
2245
|
+
lines.push('change: ' + sync.change);
|
|
2246
|
+
}
|
|
2247
|
+
for (const f of sync.fetched) {
|
|
2248
|
+
lines.push('fetched: ' + f);
|
|
2249
|
+
}
|
|
2250
|
+
lines.push(...pkgLockLines(sync.lock));
|
|
2251
|
+
for (const bad of sync.unevaluable) {
|
|
2252
|
+
lines.push(bad + ': does not evaluate on its own; nothing to pin');
|
|
2253
|
+
}
|
|
2254
|
+
lines.push(...pkgForbiddenLines(sync.forbidden), ...pkgMismatchLines(sync.mismatched), ...pkgUnlockedLines(sync.unlocked));
|
|
2255
|
+
for (const miss of sync.missing) {
|
|
2256
|
+
lines.push(miss + ': not fetched (run: aontu sync)');
|
|
2257
|
+
}
|
|
2258
|
+
for (const c of sync.changes) {
|
|
2259
|
+
lines.push('lockfile would change: ' + c);
|
|
2260
|
+
}
|
|
2261
|
+
tail();
|
|
2262
|
+
return lines.join('\n');
|
|
2263
|
+
}
|
|
2264
|
+
const MODEL_HELP = 'aontu model get|why|set ... (try --help)';
|
|
2265
|
+
// One document, interrogated or edited (ADR-039 part 5).
|
|
2266
|
+
function runModel(argv) {
|
|
2267
|
+
const sub = argv[0];
|
|
2268
|
+
if ('-h' === sub || '--help' === sub) {
|
|
2269
|
+
process.stdout.write(HELP);
|
|
2270
|
+
return 0;
|
|
2271
|
+
}
|
|
2272
|
+
if ('get' === sub) {
|
|
2273
|
+
return runGet(argv.slice(1));
|
|
2274
|
+
}
|
|
2275
|
+
if ('why' === sub) {
|
|
2276
|
+
return runWhy(argv.slice(1));
|
|
2277
|
+
}
|
|
2278
|
+
if ('set' === sub) {
|
|
2279
|
+
return runSet(argv.slice(1));
|
|
2280
|
+
}
|
|
2281
|
+
process.stderr.write(`aontu: model needs get, why or set\n${MODEL_HELP}\n`);
|
|
2282
|
+
return 2;
|
|
2283
|
+
}
|
|
1921
2284
|
function vacuous(what, why) {
|
|
1922
2285
|
process.stderr.write(`aontu: ${what}: ${why}\n`);
|
|
1923
2286
|
}
|
|
@@ -1981,6 +2344,108 @@ function runRelations(argv) {
|
|
|
1981
2344
|
}
|
|
1982
2345
|
return RELATIONS_EXIT[report.verdict];
|
|
1983
2346
|
}
|
|
2347
|
+
const TRACE_HELP = 'aontu trace [--at <path>] [--format json] [--marker <token>] ' +
|
|
2348
|
+
'[--profile <file>] <file>';
|
|
2349
|
+
// WHAT WROTE THIS LINE. Every piece a rule stamped, under the
|
|
2350
|
+
// component tree, with the file it reached, the rule set that wrote it
|
|
2351
|
+
// and the model node the dispatch matched.
|
|
2352
|
+
function runTrace(argv) {
|
|
2353
|
+
const trusted = takeTrust(argv);
|
|
2354
|
+
if (null == trusted) {
|
|
2355
|
+
return 2;
|
|
2356
|
+
}
|
|
2357
|
+
argv = trusted.argv;
|
|
2358
|
+
const trust = trusted.trust;
|
|
2359
|
+
const rest = [];
|
|
2360
|
+
const profileFiles = [];
|
|
2361
|
+
let format = 'text';
|
|
2362
|
+
let at = undefined;
|
|
2363
|
+
let marker = undefined;
|
|
2364
|
+
for (let i = 0; i < argv.length; i++) {
|
|
2365
|
+
const arg = argv[i];
|
|
2366
|
+
if ('-h' === arg || '--help' === arg) {
|
|
2367
|
+
process.stdout.write(HELP);
|
|
2368
|
+
return 0;
|
|
2369
|
+
}
|
|
2370
|
+
if ('--format' === arg) {
|
|
2371
|
+
const f = argv[++i];
|
|
2372
|
+
if ('text' !== f && 'json' !== f) {
|
|
2373
|
+
process.stderr.write('aontu: --format needs text or json\n');
|
|
2374
|
+
return 2;
|
|
2375
|
+
}
|
|
2376
|
+
format = f;
|
|
2377
|
+
}
|
|
2378
|
+
else if ('--at' === arg) {
|
|
2379
|
+
at = argv[++i];
|
|
2380
|
+
if (null == at) {
|
|
2381
|
+
process.stderr.write('aontu: --at needs a path\n');
|
|
2382
|
+
return 2;
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
else if ('--marker' === arg) {
|
|
2386
|
+
marker = argv[++i];
|
|
2387
|
+
if (null == marker) {
|
|
2388
|
+
process.stderr.write('aontu: --marker needs a token\n');
|
|
2389
|
+
return 2;
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2392
|
+
else if ('--profile' === arg) {
|
|
2393
|
+
const pf = argv[++i];
|
|
2394
|
+
if (null == pf) {
|
|
2395
|
+
process.stderr.write('aontu: --profile needs a file\n');
|
|
2396
|
+
return 2;
|
|
2397
|
+
}
|
|
2398
|
+
profileFiles.push(pf);
|
|
2399
|
+
}
|
|
2400
|
+
else if (arg.startsWith('-')) {
|
|
2401
|
+
process.stderr.write(`aontu: unknown trace option ${arg} (try --help)\n`);
|
|
2402
|
+
return 2;
|
|
2403
|
+
}
|
|
2404
|
+
else {
|
|
2405
|
+
rest.push(arg);
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
if (1 !== rest.length) {
|
|
2409
|
+
process.stderr.write(`aontu: trace needs one file\n${TRACE_HELP}\n`);
|
|
2410
|
+
return 2;
|
|
2411
|
+
}
|
|
2412
|
+
let src;
|
|
2413
|
+
try {
|
|
2414
|
+
src = (0, node_fs_1.readFileSync)(rest[0], 'utf8');
|
|
2415
|
+
}
|
|
2416
|
+
catch (err) {
|
|
2417
|
+
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2418
|
+
return 2;
|
|
2419
|
+
}
|
|
2420
|
+
const declared = loadProfiles(profileFiles, trust);
|
|
2421
|
+
if ('number' === typeof declared) {
|
|
2422
|
+
return declared;
|
|
2423
|
+
}
|
|
2424
|
+
// A GENERATOR IS AN ENTRY, not a preprocessing step: the file whose
|
|
2425
|
+
// provenance is asked for is the one the author edits.
|
|
2426
|
+
if (!rest[0].endsWith('.aon')) {
|
|
2427
|
+
src = (0, template_1.desugarTemplate)(src, marker ??
|
|
2428
|
+
(0, template_1.markerFromProfiles)(declared, rest[0]) ?? (0, template_1.markerFor)(rest[0]));
|
|
2429
|
+
}
|
|
2430
|
+
const report = (0, trace_1.traceRun)(src, {
|
|
2431
|
+
path: rest[0], at,
|
|
2432
|
+
...verbOpts(trust, entryRootOf(rest[0])),
|
|
2433
|
+
});
|
|
2434
|
+
if ('error' === report.verdict) {
|
|
2435
|
+
// An error report always carries its findings.
|
|
2436
|
+
const errors = report.errors;
|
|
2437
|
+
process.stderr.write(errors.map(renderFinding).join('\n') + '\n');
|
|
2438
|
+
return 4;
|
|
2439
|
+
}
|
|
2440
|
+
if ('json' === format) {
|
|
2441
|
+
process.stdout.write(JSON.stringify({ trace: report.trace }) + '\n');
|
|
2442
|
+
return 0;
|
|
2443
|
+
}
|
|
2444
|
+
for (const e of report.trace) {
|
|
2445
|
+
process.stdout.write([e.file, e.at, e.node, e.rule].join('\t') + '\n');
|
|
2446
|
+
}
|
|
2447
|
+
return 0;
|
|
2448
|
+
}
|
|
1984
2449
|
function runReaches(argv) {
|
|
1985
2450
|
const trusted = takeTrust(argv);
|
|
1986
2451
|
if (null == trusted) {
|
|
@@ -2530,281 +2995,6 @@ function runJsonSchema(argv) {
|
|
|
2530
2995
|
return 'error' === report.verdict ? 4 :
|
|
2531
2996
|
strict && 'lossy' === report.verdict ? 1 : 0;
|
|
2532
2997
|
}
|
|
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
2998
|
const TEMPLATE_HELP = 'aontu template [--resugar] [--check] [--marker <token>] <file> (try --help)';
|
|
2809
2999
|
function runTemplate(argv) {
|
|
2810
3000
|
const trusted = takeTrust(argv);
|
|
@@ -2896,9 +3086,9 @@ function runTemplate(argv) {
|
|
|
2896
3086
|
return 0;
|
|
2897
3087
|
}
|
|
2898
3088
|
// 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
|
-
//
|
|
3089
|
+
// why not. A profile is a language declared as data: `template` and
|
|
3090
|
+
// `fmt` match one to a file by the extensions its `template.ext`
|
|
3091
|
+
// names.
|
|
2902
3092
|
function loadProfiles(profileFiles, trust) {
|
|
2903
3093
|
const profiles = [];
|
|
2904
3094
|
const langs = new Map();
|
|
@@ -2911,7 +3101,7 @@ function loadProfiles(profileFiles, trust) {
|
|
|
2911
3101
|
process.stderr.write(`aontu: cannot read ${err.path}: ${err.message}\n`);
|
|
2912
3102
|
return 2;
|
|
2913
3103
|
}
|
|
2914
|
-
const loaded = (0, aontu_1.
|
|
3104
|
+
const loaded = (0, aontu_1.loadProfile)(text, { path: (0, node_path_1.resolve)(pf), ...verbOpts(trust, entryRootOf(pf)) });
|
|
2915
3105
|
if (undefined !== loaded.errors) {
|
|
2916
3106
|
process.stderr.write(loaded.errors.map(renderFinding).join('\n') + '\n');
|
|
2917
3107
|
return 4;
|
|
@@ -2995,7 +3185,7 @@ function runHash(argv) {
|
|
|
2995
3185
|
process.stdout.write(text + '\n');
|
|
2996
3186
|
return 0;
|
|
2997
3187
|
}
|
|
2998
|
-
const GET_HELP = 'aontu get <path> <file> (try --help)';
|
|
3188
|
+
const GET_HELP = 'aontu model get <path> <file> (try --help)';
|
|
2999
3189
|
function runGet(argv) {
|
|
3000
3190
|
const trusted = takeTrust(argv);
|
|
3001
3191
|
if (null == trusted) {
|
|
@@ -3039,7 +3229,7 @@ function runGet(argv) {
|
|
|
3039
3229
|
format = f;
|
|
3040
3230
|
}
|
|
3041
3231
|
else if (arg.startsWith('-')) {
|
|
3042
|
-
process.stderr.write(`aontu: unknown get option ${arg} (try --help)\n`);
|
|
3232
|
+
process.stderr.write(`aontu: unknown model get option ${arg} (try --help)\n`);
|
|
3043
3233
|
return 2;
|
|
3044
3234
|
}
|
|
3045
3235
|
else {
|
|
@@ -3047,7 +3237,7 @@ function runGet(argv) {
|
|
|
3047
3237
|
}
|
|
3048
3238
|
}
|
|
3049
3239
|
if (2 !== rest.length) {
|
|
3050
|
-
process.stderr.write(`aontu: get needs a path and one file\n${GET_HELP}\n`);
|
|
3240
|
+
process.stderr.write(`aontu: model get needs a path and one file\n${GET_HELP}\n`);
|
|
3051
3241
|
return 2;
|
|
3052
3242
|
}
|
|
3053
3243
|
const [path, file] = rest;
|
|
@@ -3071,7 +3261,7 @@ function runGet(argv) {
|
|
|
3071
3261
|
});
|
|
3072
3262
|
if ('json' === format) {
|
|
3073
3263
|
process.stdout.write((0, aontu_1.exactJSON)({
|
|
3074
|
-
aontu: { version: version(), verb: 'get' },
|
|
3264
|
+
aontu: { version: version(), verb: 'model get' },
|
|
3075
3265
|
findings: report.findings,
|
|
3076
3266
|
ok: report.ok,
|
|
3077
3267
|
out: report.out,
|
|
@@ -3096,7 +3286,7 @@ function runGet(argv) {
|
|
|
3096
3286
|
// contributions that met there, each with the site it was written at.
|
|
3097
3287
|
// The positive twin of the vet report: errors explain what failed to
|
|
3098
3288
|
// unify, this explains what did.
|
|
3099
|
-
const WHY_HELP = 'aontu why <path> <file> (try --help)';
|
|
3289
|
+
const WHY_HELP = 'aontu model why <path> <file> (try --help)';
|
|
3100
3290
|
function runWhy(argv) {
|
|
3101
3291
|
const trusted = takeTrust(argv);
|
|
3102
3292
|
if (null == trusted) {
|
|
@@ -3121,7 +3311,7 @@ function runWhy(argv) {
|
|
|
3121
3311
|
format = f;
|
|
3122
3312
|
}
|
|
3123
3313
|
else if (arg.startsWith('-')) {
|
|
3124
|
-
process.stderr.write(`aontu: unknown why option ${arg} (try --help)\n`);
|
|
3314
|
+
process.stderr.write(`aontu: unknown model why option ${arg} (try --help)\n`);
|
|
3125
3315
|
return 2;
|
|
3126
3316
|
}
|
|
3127
3317
|
else {
|
|
@@ -3129,7 +3319,7 @@ function runWhy(argv) {
|
|
|
3129
3319
|
}
|
|
3130
3320
|
}
|
|
3131
3321
|
if (2 !== rest.length) {
|
|
3132
|
-
process.stderr.write(`aontu: why needs a path and one file\n${WHY_HELP}\n`);
|
|
3322
|
+
process.stderr.write(`aontu: model why needs a path and one file\n${WHY_HELP}\n`);
|
|
3133
3323
|
return 2;
|
|
3134
3324
|
}
|
|
3135
3325
|
const [path, file] = rest;
|
|
@@ -3146,7 +3336,7 @@ function runWhy(argv) {
|
|
|
3146
3336
|
});
|
|
3147
3337
|
if ('json' === format) {
|
|
3148
3338
|
process.stdout.write((0, aontu_1.exactJSON)({
|
|
3149
|
-
aontu: { version: version(), verb: 'why' },
|
|
3339
|
+
aontu: { version: version(), verb: 'model why' },
|
|
3150
3340
|
findings: report.findings,
|
|
3151
3341
|
ok: report.ok,
|
|
3152
3342
|
...(null == report.record ? {} : { record: report.record }),
|
|
@@ -3178,7 +3368,7 @@ function renderWhyText(record) {
|
|
|
3178
3368
|
('literal' === c.role ? '' : ` (${c.role})`);
|
|
3179
3369
|
})).join('\n');
|
|
3180
3370
|
}
|
|
3181
|
-
const SET_HELP = 'aontu set <path>=<value> --entry <file> --overlay <file> (try --help)';
|
|
3371
|
+
const SET_HELP = 'aontu model set <path>=<value> --entry <file> --overlay <file> (try --help)';
|
|
3182
3372
|
function runSet(argv) {
|
|
3183
3373
|
const trusted = takeTrust(argv);
|
|
3184
3374
|
if (null == trusted) {
|
|
@@ -3219,7 +3409,7 @@ function runSet(argv) {
|
|
|
3219
3409
|
format = f;
|
|
3220
3410
|
}
|
|
3221
3411
|
else if (arg.startsWith('-')) {
|
|
3222
|
-
process.stderr.write(`aontu: unknown set option ${arg} (try --help)\n`);
|
|
3412
|
+
process.stderr.write(`aontu: unknown model set option ${arg} (try --help)\n`);
|
|
3223
3413
|
return 2;
|
|
3224
3414
|
}
|
|
3225
3415
|
else {
|
|
@@ -3227,7 +3417,7 @@ function runSet(argv) {
|
|
|
3227
3417
|
}
|
|
3228
3418
|
}
|
|
3229
3419
|
if (0 === assignments.length || null == entry || null == overlayFile) {
|
|
3230
|
-
process.stderr.write(`aontu: set needs assignments, --entry and --overlay\n${SET_HELP}\n`);
|
|
3420
|
+
process.stderr.write(`aontu: model set needs assignments, --entry and --overlay\n${SET_HELP}\n`);
|
|
3231
3421
|
return 2;
|
|
3232
3422
|
}
|
|
3233
3423
|
let entrySrc;
|
|
@@ -3274,7 +3464,7 @@ function runSet(argv) {
|
|
|
3274
3464
|
}
|
|
3275
3465
|
if ('json' === format) {
|
|
3276
3466
|
process.stdout.write((0, aontu_1.exactJSON)({
|
|
3277
|
-
aontu: { version: version(), verb: 'set' },
|
|
3467
|
+
aontu: { version: version(), verb: 'model set' },
|
|
3278
3468
|
appended: report.appended,
|
|
3279
3469
|
findings: report.findings,
|
|
3280
3470
|
overlay: report.overlay,
|
|
@@ -3583,8 +3773,8 @@ function runFmt(argv) {
|
|
|
3583
3773
|
}
|
|
3584
3774
|
else if ('--marker' === arg) {
|
|
3585
3775
|
// THE MARKER SAYS THE FILE IS A GENERATOR, whatever its
|
|
3586
|
-
// extension: `
|
|
3587
|
-
//
|
|
3776
|
+
// extension: `fmt` and `template` take the same option for the
|
|
3777
|
+
// same reason, a language the table has never seen.
|
|
3588
3778
|
marker = argv[++i];
|
|
3589
3779
|
if (null == marker) {
|
|
3590
3780
|
process.stderr.write('aontu: --marker needs a token\n');
|
|
@@ -3711,12 +3901,22 @@ function fmtOne(name, src, flags, marker) {
|
|
|
3711
3901
|
}
|
|
3712
3902
|
return flags.check ? 1 : strict;
|
|
3713
3903
|
}
|
|
3904
|
+
const PROCESS_IO = {
|
|
3905
|
+
out: (s) => void process.stdout.write(s),
|
|
3906
|
+
err: (s) => void process.stderr.write(s),
|
|
3907
|
+
};
|
|
3908
|
+
// `pkg serve` runs until the process is interrupted.
|
|
3909
|
+
function serveUntilInterrupted() {
|
|
3910
|
+
return new Promise((done) => process.once('SIGINT', () => done()));
|
|
3911
|
+
}
|
|
3714
3912
|
// Excluded: the real pair takes the process stdio, so ts/test/cli.test.ts
|
|
3715
3913
|
// drives each server through a child process instead.
|
|
3716
|
-
/* node:coverage ignore next
|
|
3914
|
+
/* node:coverage ignore next 6 */
|
|
3717
3915
|
const SERVERS = {
|
|
3718
3916
|
lsp: () => void (0, lsp_server_1.main)(),
|
|
3719
3917
|
mcp: (argv) => void (0, mcp_server_1.main)(undefined, undefined, undefined, undefined, argv),
|
|
3918
|
+
serve: serveUntilInterrupted,
|
|
3919
|
+
http: pkg_net_1.defaultHttp,
|
|
3720
3920
|
};
|
|
3721
3921
|
// undefined: the server took the process; a number: an answer the CLI
|
|
3722
3922
|
// gives itself, --help or a usage error.
|
|
@@ -3989,10 +4189,10 @@ function runInit(argv) {
|
|
|
3989
4189
|
return 0;
|
|
3990
4190
|
}
|
|
3991
4191
|
const KNOWN_VERBS = [
|
|
3992
|
-
'agentsmd', 'allow', 'breaking', 'explain', 'fmt', 'get', 'hash',
|
|
3993
|
-
'help', 'init', 'jsonschema', 'lsp', 'mcp', '
|
|
3994
|
-
'
|
|
3995
|
-
'view', 'why',
|
|
4192
|
+
'add', 'agentsmd', 'allow', 'breaking', 'explain', 'fmt', 'get', 'hash',
|
|
4193
|
+
'help', 'init', 'jsonschema', 'lsp', 'mcp', 'model', 'pkg', 'publish',
|
|
4194
|
+
'reaches', 'relations', 'remove', 'subsume', 'sync', 'template', 'trace',
|
|
4195
|
+
'trim', 'vet', 'view', 'why',
|
|
3996
4196
|
];
|
|
3997
4197
|
exports.KNOWN_VERBS = KNOWN_VERBS;
|
|
3998
4198
|
// looksLikeVerb reports whether an unreadable argument was meant as a
|
|
@@ -4077,17 +4277,18 @@ function main(argv, servers = SERVERS) {
|
|
|
4077
4277
|
if ('mcp' === argv[2]) {
|
|
4078
4278
|
return servers.mcp(argv.slice(3));
|
|
4079
4279
|
}
|
|
4080
|
-
if ('set' === argv[2]) {
|
|
4081
|
-
return finish(runSet(argv.slice(3)));
|
|
4082
|
-
}
|
|
4083
4280
|
if ('allow' === argv[2]) {
|
|
4084
4281
|
return finish(runAllow(argv.slice(3)));
|
|
4085
4282
|
}
|
|
4086
|
-
if ('
|
|
4087
|
-
return finish(
|
|
4283
|
+
if ('model' === argv[2]) {
|
|
4284
|
+
return finish(runModel(argv.slice(3)));
|
|
4285
|
+
}
|
|
4286
|
+
if ('pkg' === argv[2]) {
|
|
4287
|
+
const r = runPkg(argv.slice(3), servers);
|
|
4288
|
+
return 'number' === typeof r ? finish(r) : void r.then(finish);
|
|
4088
4289
|
}
|
|
4089
|
-
if (
|
|
4090
|
-
return
|
|
4290
|
+
if (PACKAGE_VERBS.includes(argv[2])) {
|
|
4291
|
+
return void runPackageVerb(argv[2], argv.slice(3), servers).then(finish);
|
|
4091
4292
|
}
|
|
4092
4293
|
if ('hash' === argv[2]) {
|
|
4093
4294
|
return finish(runHash(argv.slice(3)));
|
|
@@ -4103,21 +4304,18 @@ function main(argv, servers = SERVERS) {
|
|
|
4103
4304
|
if ('init' === argv[2]) {
|
|
4104
4305
|
return finish(runInit(argv.slice(3)));
|
|
4105
4306
|
}
|
|
4106
|
-
if ('mod' === argv[2]) {
|
|
4107
|
-
return finish(runMod(argv.slice(3)));
|
|
4108
|
-
}
|
|
4109
4307
|
if ('relations' === argv[2]) {
|
|
4110
4308
|
return finish(runRelations(argv.slice(3)));
|
|
4111
4309
|
}
|
|
4112
4310
|
if ('jsonschema' === argv[2]) {
|
|
4113
4311
|
return finish(runJsonSchema(argv.slice(3)));
|
|
4114
4312
|
}
|
|
4115
|
-
if ('render' === argv[2]) {
|
|
4116
|
-
return finish(runRender(argv.slice(3)));
|
|
4117
|
-
}
|
|
4118
4313
|
if ('template' === argv[2]) {
|
|
4119
4314
|
return finish(runTemplate(argv.slice(3)));
|
|
4120
4315
|
}
|
|
4316
|
+
if ('trace' === argv[2]) {
|
|
4317
|
+
return finish(runTrace(argv.slice(3)));
|
|
4318
|
+
}
|
|
4121
4319
|
if ('reaches' === argv[2]) {
|
|
4122
4320
|
return finish(runReaches(argv.slice(3)));
|
|
4123
4321
|
}
|
|
@@ -4212,5 +4410,5 @@ function main(argv, servers = SERVERS) {
|
|
|
4212
4410
|
else {
|
|
4213
4411
|
runStdin(mode, format, trust).then((code) => finish(code));
|
|
4214
4412
|
}
|
|
4215
|
-
} /* node:coverage ignore next
|
|
4413
|
+
} /* node:coverage ignore next 21 */
|
|
4216
4414
|
//# sourceMappingURL=cli.js.map
|