@archdoc/cli 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +6 -0
- package/dist/bin.js.map +1 -0
- package/dist/commands/check.d.ts +23 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +58 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/code.d.ts +24 -0
- package/dist/commands/code.d.ts.map +1 -0
- package/dist/commands/code.js +92 -0
- package/dist/commands/code.js.map +1 -0
- package/dist/commands/context.d.ts +26 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +117 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/data.d.ts +12 -0
- package/dist/commands/data.d.ts.map +1 -0
- package/dist/commands/data.js +63 -0
- package/dist/commands/data.js.map +1 -0
- package/dist/commands/diff.d.ts +17 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +79 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/federation.d.ts +20 -0
- package/dist/commands/federation.d.ts.map +1 -0
- package/dist/commands/federation.js +96 -0
- package/dist/commands/federation.js.map +1 -0
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +24 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/landscape.d.ts +14 -0
- package/dist/commands/landscape.d.ts.map +1 -0
- package/dist/commands/landscape.js +52 -0
- package/dist/commands/landscape.js.map +1 -0
- package/dist/commands/migrate.d.ts +8 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +38 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/report.d.ts +16 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/report.js +77 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/schema.d.ts +5 -0
- package/dist/commands/schema.d.ts.map +1 -0
- package/dist/commands/schema.js +15 -0
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/seal.d.ts +25 -0
- package/dist/commands/seal.d.ts.map +1 -0
- package/dist/commands/seal.js +64 -0
- package/dist/commands/seal.js.map +1 -0
- package/dist/commands/site.d.ts +14 -0
- package/dist/commands/site.d.ts.map +1 -0
- package/dist/commands/site.js +42 -0
- package/dist/commands/site.js.map +1 -0
- package/dist/commands/trace.d.ts +5 -0
- package/dist/commands/trace.d.ts.map +1 -0
- package/dist/commands/trace.js +39 -0
- package/dist/commands/trace.js.map +1 -0
- package/dist/commands/validate.d.ts +8 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +49 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/view.d.ts +17 -0
- package/dist/commands/view.d.ts.map +1 -0
- package/dist/commands/view.js +50 -0
- package/dist/commands/view.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +7 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +6 -0
- package/dist/io.js.map +1 -0
- package/dist/landscape.d.ts +28 -0
- package/dist/landscape.d.ts.map +1 -0
- package/dist/landscape.js +34 -0
- package/dist/landscape.js.map +1 -0
- package/dist/model-path.d.ts +7 -0
- package/dist/model-path.d.ts.map +1 -0
- package/dist/model-path.js +17 -0
- package/dist/model-path.js.map +1 -0
- package/dist/program.d.ts +7 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +197 -0
- package/dist/program.js.map +1 -0
- package/dist/server.d.ts +297 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +348 -0
- package/dist/server.js.map +1 -0
- package/package.json +35 -3
- package/web/assets/index-CDAgYSBW.js +210 -0
- package/web/assets/index-k7lSjazl.css +1 -0
- package/web/favicon.svg +1 -0
- package/web/index.html +14 -0
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 ArchDoc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
|
package/dist/bin.js
ADDED
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAChC,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACvC,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Io } from "../io.js";
|
|
2
|
+
export interface CheckOptions {
|
|
3
|
+
model?: string;
|
|
4
|
+
/** Mark findings that the change since this ref introduced, and fail only on those. */
|
|
5
|
+
base?: string;
|
|
6
|
+
format?: string;
|
|
7
|
+
failOn?: string;
|
|
8
|
+
/** Skip code analysis and check only the model. */
|
|
9
|
+
code?: boolean;
|
|
10
|
+
/** List every finding, not only the change's (or the first few). */
|
|
11
|
+
all?: boolean;
|
|
12
|
+
/** Only the facts whose sealed code changed: exits 1 while there are any. */
|
|
13
|
+
seals?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/** Runs analyzers and checks the model against the code and its rules. */
|
|
16
|
+
export declare function runCheck(options: CheckOptions, cwd: string): Promise<import("@archdoc/analyzers").CheckRepositoryResult>;
|
|
17
|
+
/**
|
|
18
|
+
* `archdoc check`: everything wrong or stale (the model's own problems,
|
|
19
|
+
* drift from the code, rules, sealed facts whose code changed, traces), and
|
|
20
|
+
* with --base, what the change does. The text is what archdoc_check answers.
|
|
21
|
+
*/
|
|
22
|
+
export declare function check(options: CheckOptions, io: Io): Promise<number>;
|
|
23
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAGnC,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,oEAAoE;IACpE,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,6EAA6E;IAC7E,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,0EAA0E;AAC1E,wBAAgB,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,+DAE1D;AAED;;;;GAIG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkD1E"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { checkAnswer, checkRepository } from "@archdoc/analyzers";
|
|
2
|
+
import { formatAnnotations, formatFindings } from "@archdoc/core";
|
|
3
|
+
import { checkSeals } from "./seal.js";
|
|
4
|
+
/** Runs analyzers and checks the model against the code and its rules. */
|
|
5
|
+
export function runCheck(options, cwd) {
|
|
6
|
+
return checkRepository({ model: options.model, cwd, base: options.base, code: options.code });
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* `archdoc check`: everything wrong or stale (the model's own problems,
|
|
10
|
+
* drift from the code, rules, sealed facts whose code changed, traces), and
|
|
11
|
+
* with --base, what the change does. The text is what archdoc_check answers.
|
|
12
|
+
*/
|
|
13
|
+
export async function check(options, io) {
|
|
14
|
+
if (options.seals) {
|
|
15
|
+
return checkSeals({ model: options.model, format: options.format === "json" ? "json" : "text" }, io);
|
|
16
|
+
}
|
|
17
|
+
const format = options.format ?? "text";
|
|
18
|
+
if (!["text", "markdown", "json", "github"].includes(format)) {
|
|
19
|
+
io.err("--format must be text, markdown, json, or github.");
|
|
20
|
+
return 2;
|
|
21
|
+
}
|
|
22
|
+
const failOn = options.failOn ?? "error";
|
|
23
|
+
if (!["error", "warning", "never"].includes(failOn)) {
|
|
24
|
+
io.err("--fail-on must be error, warning, or never.");
|
|
25
|
+
return 2;
|
|
26
|
+
}
|
|
27
|
+
let findings;
|
|
28
|
+
try {
|
|
29
|
+
if (format === "text") {
|
|
30
|
+
const answer = await checkAnswer({ model: options.model, cwd: io.cwd }, { base: options.base, all: options.all, code: options.code });
|
|
31
|
+
findings = answer.findings;
|
|
32
|
+
io.out(answer.text);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
findings = (await runCheck(options, io.cwd)).findings;
|
|
36
|
+
if (format === "github") {
|
|
37
|
+
// Workflow commands put the findings on the diff; the text keeps the log readable.
|
|
38
|
+
const annotations = formatAnnotations(findings);
|
|
39
|
+
if (annotations)
|
|
40
|
+
io.out(annotations);
|
|
41
|
+
io.out(formatFindings(findings, "text"));
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
io.out(format === "json"
|
|
45
|
+
? JSON.stringify(findings, null, 2)
|
|
46
|
+
: formatFindings(findings, format));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
io.err(err instanceof Error ? err.message : String(err));
|
|
52
|
+
return 2;
|
|
53
|
+
}
|
|
54
|
+
const counted = options.base ? findings.filter((f) => f.introduced) : findings;
|
|
55
|
+
const failing = counted.filter((f) => f.severity === "error" || (failOn === "warning" && f.severity === "warning"));
|
|
56
|
+
return failOn !== "never" && failing.length > 0 ? 1 : 0;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type LoadedModel } from "@archdoc/core";
|
|
2
|
+
import type { Io } from "../io.js";
|
|
3
|
+
export interface ModelOptions {
|
|
4
|
+
/** Repository, .archdoc directory, or model file. */
|
|
5
|
+
model?: string;
|
|
6
|
+
json?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function load(options: ModelOptions, io: Io): Promise<LoadedModel | undefined>;
|
|
9
|
+
export declare function map(options: ModelOptions & {
|
|
10
|
+
unmapped?: boolean;
|
|
11
|
+
}, io: Io): Promise<number>;
|
|
12
|
+
/** Prints the details of an element, actor, or journey by ID. */
|
|
13
|
+
/**
|
|
14
|
+
* `archdoc show <id>`: one thing in the model, whatever kind of ID names it:
|
|
15
|
+
* an element, actor, journey (with --sample, run on it), data entry,
|
|
16
|
+
* Entry.field (its lineage), trace, or a sealed fact. What archdoc_show answers.
|
|
17
|
+
*/
|
|
18
|
+
export declare function show(id: string, options: ModelOptions & {
|
|
19
|
+
code?: boolean;
|
|
20
|
+
sample?: string;
|
|
21
|
+
}, io: Io): Promise<number>;
|
|
22
|
+
/** A file in the repository, or undefined when there's none (or it's outside it). */
|
|
23
|
+
export declare function readRepoFile(baseDir: string, path: string): string | undefined;
|
|
24
|
+
//# sourceMappingURL=code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../src/commands/code.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,WAAW,EAIjB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAEnC,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAU1F;AAED,wBAAsB,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuDjG;AAED,iEAAiE;AACjE;;;;GAIG;AACH,wBAAsB,IAAI,CACxB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,YAAY,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3D,EAAE,EAAE,EAAE,GACL,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQ9E"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { relative, resolve } from "node:path";
|
|
3
|
+
import { showAnswer } from "@archdoc/analyzers";
|
|
4
|
+
import { filesUnder, hasErrors, listRepoFiles, loadModel, resolveCodeMap, } from "@archdoc/core";
|
|
5
|
+
export async function load(options, io) {
|
|
6
|
+
const model = await loadModel(options.model ?? ".", { cwd: io.cwd });
|
|
7
|
+
if (model.diagnostics.some((d) => d.code === "model/not-found")) {
|
|
8
|
+
io.err(model.diagnostics[0]?.message ?? "No model found.");
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
if (hasErrors(model.diagnostics)) {
|
|
12
|
+
io.err('warning: the model has errors, so answers may be incomplete. Run "archdoc validate".');
|
|
13
|
+
}
|
|
14
|
+
return model;
|
|
15
|
+
}
|
|
16
|
+
export async function map(options, io) {
|
|
17
|
+
const model = await load(options, io);
|
|
18
|
+
if (!model)
|
|
19
|
+
return 1;
|
|
20
|
+
const files = await listRepoFiles(model.baseDir);
|
|
21
|
+
const codemap = resolveCodeMap(model, files);
|
|
22
|
+
const top = [...model.elements.values()].filter((e) => e.depth === 0);
|
|
23
|
+
const mapped = files.length - codemap.unmapped.length;
|
|
24
|
+
if (options.json) {
|
|
25
|
+
io.out(JSON.stringify({
|
|
26
|
+
files: files.length,
|
|
27
|
+
mapped,
|
|
28
|
+
elements: Object.fromEntries([...model.elements.keys()].map((id) => [id, filesUnder(model, codemap, id).length])),
|
|
29
|
+
unmapped: codemap.unmapped,
|
|
30
|
+
stale: codemap.stale,
|
|
31
|
+
}, null, 2));
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
const lines = [`${mapped} of ${files.length} files map to an element.`, ""];
|
|
35
|
+
const walk = (id, indent) => {
|
|
36
|
+
const e = model.elements.get(id);
|
|
37
|
+
if (!e)
|
|
38
|
+
return;
|
|
39
|
+
const n = filesUnder(model, codemap, id).length;
|
|
40
|
+
const note = e.spec.status === "planned"
|
|
41
|
+
? " (planned)"
|
|
42
|
+
: e.code.length === 0 && n === 0
|
|
43
|
+
? " (no code paths)"
|
|
44
|
+
: "";
|
|
45
|
+
lines.push(`${indent}${e.key} ${n} file${n === 1 ? "" : "s"}${note}`);
|
|
46
|
+
for (const c of e.childIds)
|
|
47
|
+
walk(c, `${indent} `);
|
|
48
|
+
};
|
|
49
|
+
for (const e of top)
|
|
50
|
+
walk(e.id, " ");
|
|
51
|
+
if (codemap.stale.length) {
|
|
52
|
+
lines.push("", "Code paths that match no files:");
|
|
53
|
+
for (const s of codemap.stale)
|
|
54
|
+
lines.push(` ${s.element}: ${s.pattern}`);
|
|
55
|
+
}
|
|
56
|
+
if (codemap.unmapped.length) {
|
|
57
|
+
lines.push("", `${codemap.unmapped.length} unmapped file${codemap.unmapped.length === 1 ? "" : "s"}${options.unmapped ? ":" : " (list them with --unmapped)"}`);
|
|
58
|
+
if (options.unmapped)
|
|
59
|
+
for (const f of codemap.unmapped)
|
|
60
|
+
lines.push(` ${f}`);
|
|
61
|
+
}
|
|
62
|
+
io.out(lines.join("\n"));
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
/** Prints the details of an element, actor, or journey by ID. */
|
|
66
|
+
/**
|
|
67
|
+
* `archdoc show <id>`: one thing in the model, whatever kind of ID names it:
|
|
68
|
+
* an element, actor, journey (with --sample, run on it), data entry,
|
|
69
|
+
* Entry.field (its lineage), trace, or a sealed fact. What archdoc_show answers.
|
|
70
|
+
*/
|
|
71
|
+
export async function show(id, options, io) {
|
|
72
|
+
const r = await showAnswer({ model: options.model, cwd: io.cwd }, { id, code: options.code, sample: options.sample });
|
|
73
|
+
if (!r.ok) {
|
|
74
|
+
io.err(r.text);
|
|
75
|
+
return 1;
|
|
76
|
+
}
|
|
77
|
+
io.out(r.text);
|
|
78
|
+
return r.failing ? 1 : 0;
|
|
79
|
+
}
|
|
80
|
+
/** A file in the repository, or undefined when there's none (or it's outside it). */
|
|
81
|
+
export function readRepoFile(baseDir, path) {
|
|
82
|
+
const absolute = resolve(baseDir, path);
|
|
83
|
+
if (relative(baseDir, absolute).startsWith(".."))
|
|
84
|
+
return undefined;
|
|
85
|
+
try {
|
|
86
|
+
return readFileSync(absolute, "utf8");
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/commands/code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Io } from "../io.js";
|
|
2
|
+
export interface ContextOptions {
|
|
3
|
+
model?: string;
|
|
4
|
+
format?: string;
|
|
5
|
+
json?: boolean;
|
|
6
|
+
/** A file with the error to place, or - for stdin. */
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* `archdoc context <words…|paths…>`: where to start a task. Arguments that
|
|
11
|
+
* are paths (they contain a slash, or exist) are taken relative to where the
|
|
12
|
+
* command runs; the rest are the task in words.
|
|
13
|
+
*/
|
|
14
|
+
export declare function context(args: string[], options: ContextOptions, io: Io, stdin?: () => Promise<string>): Promise<number>;
|
|
15
|
+
export interface EvalOptions extends ContextOptions {
|
|
16
|
+
commits?: string;
|
|
17
|
+
minRecall?: string;
|
|
18
|
+
verbose?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* `archdoc eval [ref]`: replays recent commits through `context` and reports
|
|
22
|
+
* how many of the files they changed the brief pointed at. Read-only: it
|
|
23
|
+
* reads the history with git log, and the model and code as they are now.
|
|
24
|
+
*/
|
|
25
|
+
export declare function evalCommand(ref: string | undefined, options: EvalOptions, io: Io): Promise<number>;
|
|
26
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAGnC,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuBD;;;;GAIG;AACH,wBAAsB,OAAO,CAC3B,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,cAAc,EACvB,EAAE,EAAE,EAAE,EACN,KAAK,GAAE,MAAM,OAAO,CAAC,MAAM,CAAa,GACvC,OAAO,CAAC,MAAM,CAAC,CA+CjB;AAED,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,EAAE,GACL,OAAO,CAAC,MAAM,CAAC,CAiCjB"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
4
|
+
import { contextAnswer, indexRepository } from "@archdoc/analyzers";
|
|
5
|
+
import { context as contextOf, evaluate, formatContext, formatEval, hasErrors, loadModel, recentCommits, resolveGitRef, } from "@archdoc/core";
|
|
6
|
+
import { readStdin } from "./trace.js";
|
|
7
|
+
async function load(model, io) {
|
|
8
|
+
const m = await loadModel(model ?? ".", { cwd: io.cwd });
|
|
9
|
+
if (m.diagnostics.some((d) => d.code === "model/not-found")) {
|
|
10
|
+
io.err(m.diagnostics[0]?.message ?? "No model found.");
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
if (hasErrors(m.diagnostics)) {
|
|
14
|
+
io.err('warning: the model has errors, so answers may be incomplete. Run "archdoc validate".');
|
|
15
|
+
}
|
|
16
|
+
return m;
|
|
17
|
+
}
|
|
18
|
+
function formatOf(options, io) {
|
|
19
|
+
const format = options.json ? "json" : (options.format ?? "text");
|
|
20
|
+
if (format !== "text" && format !== "json") {
|
|
21
|
+
io.err("--format must be text or json.");
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
return format;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* `archdoc context <words…|paths…>`: where to start a task. Arguments that
|
|
28
|
+
* are paths (they contain a slash, or exist) are taken relative to where the
|
|
29
|
+
* command runs; the rest are the task in words.
|
|
30
|
+
*/
|
|
31
|
+
export async function context(args, options, io, stdin = readStdin) {
|
|
32
|
+
const format = formatOf(options, io);
|
|
33
|
+
if (!format)
|
|
34
|
+
return 2;
|
|
35
|
+
// An error to place, or nothing (the overview): what archdoc_context answers.
|
|
36
|
+
if (options.error !== undefined || !args.length) {
|
|
37
|
+
if (format === "json") {
|
|
38
|
+
io.err("--format json works with a task or paths, not with --error or no arguments.");
|
|
39
|
+
return 2;
|
|
40
|
+
}
|
|
41
|
+
let error;
|
|
42
|
+
try {
|
|
43
|
+
if (options.error !== undefined) {
|
|
44
|
+
error =
|
|
45
|
+
options.error === "-"
|
|
46
|
+
? await stdin()
|
|
47
|
+
: await readFile(resolve(io.cwd, options.error), "utf8");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
io.err(err instanceof Error ? err.message : String(err));
|
|
52
|
+
return 2;
|
|
53
|
+
}
|
|
54
|
+
const words = args.filter((a) => !(a.includes("/") || a.includes("\\") || existsSync(resolve(io.cwd, a))));
|
|
55
|
+
const r = await contextAnswer({ model: options.model, cwd: io.cwd }, { task: words.join(" "), paths: args.filter((a) => !words.includes(a)), error });
|
|
56
|
+
(r.ok ? io.out : io.err)(r.text);
|
|
57
|
+
return r.ok ? 0 : 1;
|
|
58
|
+
}
|
|
59
|
+
const model = await load(options.model, io);
|
|
60
|
+
if (!model)
|
|
61
|
+
return 1;
|
|
62
|
+
const words = [];
|
|
63
|
+
const paths = [];
|
|
64
|
+
for (const arg of args) {
|
|
65
|
+
const absolute = isAbsolute(arg) ? arg : resolve(io.cwd, arg);
|
|
66
|
+
if (arg.includes("/") || arg.includes("\\") || existsSync(absolute)) {
|
|
67
|
+
paths.push(relative(model.baseDir, absolute).replace(/\\/g, "/"));
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
words.push(arg);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const index = await indexRepository(model.baseDir);
|
|
74
|
+
const brief = contextOf(model, words.join(" "), { index, paths });
|
|
75
|
+
io.out(format === "json" ? JSON.stringify(brief, null, 2) : formatContext(brief));
|
|
76
|
+
return brief.start.length ? 0 : 1;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* `archdoc eval [ref]`: replays recent commits through `context` and reports
|
|
80
|
+
* how many of the files they changed the brief pointed at. Read-only: it
|
|
81
|
+
* reads the history with git log, and the model and code as they are now.
|
|
82
|
+
*/
|
|
83
|
+
export async function evalCommand(ref, options, io) {
|
|
84
|
+
const format = formatOf(options, io);
|
|
85
|
+
if (!format)
|
|
86
|
+
return 2;
|
|
87
|
+
const count = Number(options.commits ?? 50);
|
|
88
|
+
if (!Number.isInteger(count) || count < 1) {
|
|
89
|
+
io.err("--commits must be a positive whole number.");
|
|
90
|
+
return 2;
|
|
91
|
+
}
|
|
92
|
+
const min = options.minRecall === undefined ? undefined : Number(options.minRecall);
|
|
93
|
+
if (min !== undefined && !(min >= 0 && min <= 1)) {
|
|
94
|
+
io.err("--min-recall must be a number from 0 to 1, such as 0.5.");
|
|
95
|
+
return 2;
|
|
96
|
+
}
|
|
97
|
+
const model = await load(options.model, io);
|
|
98
|
+
if (!model)
|
|
99
|
+
return 1;
|
|
100
|
+
const at = ref ?? "HEAD";
|
|
101
|
+
if (!(await resolveGitRef(model.baseDir, at))) {
|
|
102
|
+
io.err(`${at} is not a commit, branch, or tag.`);
|
|
103
|
+
return 2;
|
|
104
|
+
}
|
|
105
|
+
const [commits, index] = await Promise.all([
|
|
106
|
+
recentCommits(model.baseDir, at, count),
|
|
107
|
+
indexRepository(model.baseDir),
|
|
108
|
+
]);
|
|
109
|
+
const report = evaluate(model, index, commits);
|
|
110
|
+
io.out(format === "json" ? JSON.stringify(report, null, 2) : formatEval(report, options.verbose));
|
|
111
|
+
if (min !== undefined && report.recall < min) {
|
|
112
|
+
io.err(`Recall ${Math.round(report.recall * 100)}% is below --min-recall ${Math.round(min * 100)}%.`);
|
|
113
|
+
return 1;
|
|
114
|
+
}
|
|
115
|
+
return 0;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Io } from "../io.js";
|
|
2
|
+
export interface DataOptions {
|
|
3
|
+
model?: string;
|
|
4
|
+
json?: boolean;
|
|
5
|
+
}
|
|
6
|
+
/** `archdoc lineage <entry.field>`: where a field's value comes from and goes, across repos. */
|
|
7
|
+
export declare function lineageCommand(field: string, options: DataOptions, io: Io): Promise<number>;
|
|
8
|
+
/** `archdoc simulate <journey> --sample <file>`: the path a sample takes, and the records it writes. */
|
|
9
|
+
export declare function simulateCommand(journey: string, options: DataOptions & {
|
|
10
|
+
sample?: string;
|
|
11
|
+
}, io: Io): Promise<number>;
|
|
12
|
+
//# sourceMappingURL=data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../src/commands/data.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAEnC,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAcD,gGAAgG;AAChG,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBjG;AAED,wGAAwG;AACxG,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAC1C,EAAE,EAAE,EAAE,GACL,OAAO,CAAC,MAAM,CAAC,CA8BjB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { formatLineage, formatSimulation, hasErrors, lineage, loadModel, simulate, } from "@archdoc/core";
|
|
4
|
+
import { parse } from "yaml";
|
|
5
|
+
async function load(options, io) {
|
|
6
|
+
const model = await loadModel(options.model ?? ".", { cwd: io.cwd });
|
|
7
|
+
if (model.diagnostics.some((d) => d.code === "model/not-found")) {
|
|
8
|
+
io.err(model.diagnostics[0]?.message ?? "No model found.");
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
if (hasErrors(model.diagnostics)) {
|
|
12
|
+
io.err('warning: the model has errors, so answers may be incomplete. Run "archdoc validate".');
|
|
13
|
+
}
|
|
14
|
+
return model;
|
|
15
|
+
}
|
|
16
|
+
/** `archdoc lineage <entry.field>`: where a field's value comes from and goes, across repos. */
|
|
17
|
+
export async function lineageCommand(field, options, io) {
|
|
18
|
+
const model = await load(options, io);
|
|
19
|
+
if (!model)
|
|
20
|
+
return 1;
|
|
21
|
+
const l = lineage(model, field);
|
|
22
|
+
if (!l) {
|
|
23
|
+
io.err(`No data entry for "${field}". Name a field as Entry.field, such as Refund.amount_cents or payments.Refund.amount_cents.`);
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
io.out(options.json
|
|
27
|
+
? JSON.stringify({
|
|
28
|
+
...l,
|
|
29
|
+
stored: Object.fromEntries(l.stored),
|
|
30
|
+
classifications: Object.fromEntries(l.classifications),
|
|
31
|
+
}, null, 2)
|
|
32
|
+
: formatLineage(l));
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
/** `archdoc simulate <journey> --sample <file>`: the path a sample takes, and the records it writes. */
|
|
36
|
+
export async function simulateCommand(journey, options, io) {
|
|
37
|
+
const model = await load(options, io);
|
|
38
|
+
if (!model)
|
|
39
|
+
return 1;
|
|
40
|
+
let sample = {};
|
|
41
|
+
if (options.sample) {
|
|
42
|
+
try {
|
|
43
|
+
const parsed = parse(await readFile(resolve(io.cwd, options.sample), "utf8"));
|
|
44
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
45
|
+
throw new Error("it should map data entries to records, such as { RefundRequest: { amount_cents: 400 } }");
|
|
46
|
+
}
|
|
47
|
+
sample = parsed;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
io.err(`Couldn't read ${options.sample}: ${err instanceof Error ? err.message : String(err)}`);
|
|
51
|
+
return 2;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const result = simulate(model, journey, sample);
|
|
55
|
+
if (!result) {
|
|
56
|
+
io.err(`No journey "${journey}". List them with "archdoc search <words>" or "archdoc show <journey>".`);
|
|
57
|
+
return 1;
|
|
58
|
+
}
|
|
59
|
+
io.out(options.json ? JSON.stringify(result, null, 2) : formatSimulation(result));
|
|
60
|
+
// Problems (a missing input, an expression that failed) fail the run, so CI can use it.
|
|
61
|
+
return result.steps.some((s) => s.problems.length) ? 1 : 0;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../../src/commands/data.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Io } from "../io.js";
|
|
2
|
+
export interface DiffOptions {
|
|
3
|
+
model?: string;
|
|
4
|
+
format?: string;
|
|
5
|
+
/** Exit 1 when the model changed, like `git diff --exit-code`. */
|
|
6
|
+
exitCode?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* `archdoc diff [range]`. No range: HEAD against the working tree. `main`:
|
|
10
|
+
* main against the working tree. `a..b`: a against b. `a...b`: the merge base
|
|
11
|
+
* of a and b against b, which is what a pull request shows. Two model
|
|
12
|
+
* files: the first against the second.
|
|
13
|
+
*/
|
|
14
|
+
export declare function diff(range: string | undefined, options: DiffOptions, io: Io,
|
|
15
|
+
/** With a model path as `range`, the model to compare it with; else --model. */
|
|
16
|
+
after?: string): Promise<number>;
|
|
17
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAGnC,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAID;;;;;GAKG;AACH,wBAAsB,IAAI,CACxB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,EAAE;AACN,gFAAgF;AAChF,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CA6CjB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { loadRevision } from "@archdoc/analyzers";
|
|
2
|
+
import { diffModels, formatDiff, isEmptyDiff, loadModel, mergeBase, } from "@archdoc/core";
|
|
3
|
+
import { isModelPath } from "../model-path.js";
|
|
4
|
+
const FORMATS = ["text", "markdown", "mermaid", "json"];
|
|
5
|
+
/**
|
|
6
|
+
* `archdoc diff [range]`. No range: HEAD against the working tree. `main`:
|
|
7
|
+
* main against the working tree. `a..b`: a against b. `a...b`: the merge base
|
|
8
|
+
* of a and b against b, which is what a pull request shows. Two model
|
|
9
|
+
* files: the first against the second.
|
|
10
|
+
*/
|
|
11
|
+
export async function diff(range, options, io,
|
|
12
|
+
/** With a model path as `range`, the model to compare it with; else --model. */
|
|
13
|
+
after) {
|
|
14
|
+
const format = (options.format ?? "text");
|
|
15
|
+
if (!FORMATS.includes(format)) {
|
|
16
|
+
io.err(`--format must be one of ${FORMATS.join(", ")}.`);
|
|
17
|
+
return 1;
|
|
18
|
+
}
|
|
19
|
+
const target = options.model ?? ".";
|
|
20
|
+
try {
|
|
21
|
+
// Two models on disk, such as an example and its variant: the first against the second.
|
|
22
|
+
if (range && isModelPath(io.cwd, range)) {
|
|
23
|
+
const other = after ?? target;
|
|
24
|
+
const [base, model] = await Promise.all([
|
|
25
|
+
loadModel(range, { cwd: io.cwd }),
|
|
26
|
+
loadModel(other, { cwd: io.cwd }),
|
|
27
|
+
]);
|
|
28
|
+
warnOnErrors(base, range, io);
|
|
29
|
+
warnOnErrors(model, other, io);
|
|
30
|
+
const d = diffModels(base, model);
|
|
31
|
+
io.out(formatDiff(d, format, `${range} → ${other}`));
|
|
32
|
+
return options.exitCode && !isEmptyDiff(d) ? 1 : 0;
|
|
33
|
+
}
|
|
34
|
+
if (after) {
|
|
35
|
+
io.err(`${range} isn't a model file. Compare two model files, or give a git range.`);
|
|
36
|
+
return 2;
|
|
37
|
+
}
|
|
38
|
+
const sides = await resolveRange(range ?? "HEAD", io.cwd);
|
|
39
|
+
// Both sides as every surface reads them: schema sources and other repos' models included.
|
|
40
|
+
const at = async (ref) => {
|
|
41
|
+
const rev = await loadRevision(target, { cwd: io.cwd, ref });
|
|
42
|
+
if (!rev)
|
|
43
|
+
throw new Error(`No ArchDoc model at ${target}. Expected .archdoc/archdoc.yaml. Run archdoc init to start one.`);
|
|
44
|
+
return rev.model;
|
|
45
|
+
};
|
|
46
|
+
const [base, head] = await Promise.all([at(sides.base), at(sides.head)]);
|
|
47
|
+
warnOnErrors(base, `${sides.base}`, io);
|
|
48
|
+
warnOnErrors(head, sides.head ?? "working tree", io);
|
|
49
|
+
const d = diffModels(base, head);
|
|
50
|
+
io.out(formatDiff(d, format, `${sides.label} → ${sides.head ?? "working tree"}`));
|
|
51
|
+
return options.exitCode && !isEmptyDiff(d) ? 1 : 0;
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
io.err(err instanceof Error ? err.message : String(err));
|
|
55
|
+
return 2;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function resolveRange(range, cwd) {
|
|
59
|
+
const three = range.split("...");
|
|
60
|
+
if (three.length === 2) {
|
|
61
|
+
const [a, b] = three;
|
|
62
|
+
const base = await mergeBase(cwd, a || "HEAD", b || "HEAD");
|
|
63
|
+
if (!base)
|
|
64
|
+
throw new Error(`No common ancestor for ${a} and ${b}.`);
|
|
65
|
+
return { base, head: b || "HEAD", label: `merge base with ${a || "HEAD"}` };
|
|
66
|
+
}
|
|
67
|
+
const two = range.split("..");
|
|
68
|
+
if (two.length === 2) {
|
|
69
|
+
const [a, b] = two;
|
|
70
|
+
return { base: a || "HEAD", head: b || "HEAD", label: a || "HEAD" };
|
|
71
|
+
}
|
|
72
|
+
return { base: range, label: range };
|
|
73
|
+
}
|
|
74
|
+
function warnOnErrors(model, side, io) {
|
|
75
|
+
const errors = model.diagnostics.filter((d) => d.severity === "error" && d.code !== "model/not-found");
|
|
76
|
+
if (errors.length)
|
|
77
|
+
io.err(`warning: the model at ${side} has ${errors.length} error(s); the diff may be incomplete.`);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
|