@mantaq/inspect 0.3.0 → 0.5.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 +25 -12
- package/dist/index.d.mts +38 -5
- package/dist/index.mjs +98 -3
- package/dist/{vite-BBW0CmYr.mjs → inspect-B7ZQCNM2.mjs} +155 -289
- package/dist/{inspect-DvQtAcwv.d.mts → inspect-vSdt2qtL.d.mts} +3 -3
- package/dist/live-entry.mjs +84 -2
- package/dist/load-CWubcSZU.mjs +131 -0
- package/dist/record.d.mts +14 -0
- package/dist/record.mjs +154 -0
- package/dist/vite.d.mts +1 -1
- package/dist/vite.mjs +233 -1
- package/package.json +19 -12
- package/dist/cli.d.mts +0 -1
- package/dist/cli.mjs +0 -152
- package/dist/live-embedded.d.mts +0 -1
- package/dist/live-embedded.mjs +0 -16
- package/dist/live-page-DEDl_Nio.mjs +0 -85
- package/dist/page-CK7-IsLJ.mjs +0 -41
package/dist/cli.mjs
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { a as targetsSource, d as vizDocument, o as inlineConfig, r as TARGETS_RESOLVED, s as inspectFile } from "./vite-BBW0CmYr.mjs";
|
|
3
|
-
import { t as htmlPage } from "./page-CK7-IsLJ.mjs";
|
|
4
|
-
import { serializeViz } from "@mantaq/viz";
|
|
5
|
-
import { Either } from "@mantaq/utils";
|
|
6
|
-
import { basename, resolve } from "node:path";
|
|
7
|
-
import { SEED_ENV, parseSeed } from "@mantaq/pbt";
|
|
8
|
-
import { writeFileSync } from "node:fs";
|
|
9
|
-
import { fileURLToPath } from "node:url";
|
|
10
|
-
import { build } from "vite";
|
|
11
|
-
import { spawn } from "node:child_process";
|
|
12
|
-
import { parseArgs } from "node:util";
|
|
13
|
-
// src/live-html.ts
|
|
14
|
-
/**
|
|
15
|
-
* The live page as one classic script: the viewer, the driver and every
|
|
16
|
-
* exported factory of `files`, built with the project's Vite config.
|
|
17
|
-
*/
|
|
18
|
-
async function liveBundle(files, load) {
|
|
19
|
-
const entry = fileURLToPath(import.meta.resolve(import.meta.url.endsWith(".ts") ? "./live-embedded.ts" : "./live-embedded.mjs"));
|
|
20
|
-
const targets = {
|
|
21
|
-
name: "mantaq-live-targets",
|
|
22
|
-
resolveId: (id) => id === "virtual:mantaq/targets" ? TARGETS_RESOLVED : null,
|
|
23
|
-
load: (id) => id === "\0virtual:mantaq/targets" ? targetsSource(files) : null
|
|
24
|
-
};
|
|
25
|
-
const inline = await inlineConfig(load);
|
|
26
|
-
const output = await build({
|
|
27
|
-
...inline,
|
|
28
|
-
logLevel: "silent",
|
|
29
|
-
plugins: [...inline.plugins ?? [], targets],
|
|
30
|
-
build: {
|
|
31
|
-
write: false,
|
|
32
|
-
minify: true,
|
|
33
|
-
cssCodeSplit: false,
|
|
34
|
-
lib: {
|
|
35
|
-
entry,
|
|
36
|
-
formats: ["iife"],
|
|
37
|
-
name: "MantaqLive",
|
|
38
|
-
fileName: () => "live.js"
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
return (Array.isArray(output) ? output : [output]).flatMap((each) => "output" in each ? each.output : []).flatMap((file) => file.type === "chunk" ? [file.code] : []).join("\n");
|
|
43
|
-
}
|
|
44
|
-
// src/cli.ts
|
|
45
|
-
/**
|
|
46
|
-
* mantaq-inspect: draw the machines a file exports.
|
|
47
|
-
*
|
|
48
|
-
* mantaq-inspect <file.ts>... [--out FILE] [--json] [--live] [--no-fuzz] [--iterations N] [--config FILE]
|
|
49
|
-
* [--mode MODE] [--no-open] [--check]
|
|
50
|
-
*
|
|
51
|
-
* Finds every exported actor or actor factory from the file's types, reads
|
|
52
|
-
* handler explanations and sample payloads from the source, fuzzes each
|
|
53
|
-
* machine that runs on a VirtualClock, and writes one self-contained HTML page
|
|
54
|
-
* (default `mantaq-viz.html`) that opens without a server. `--json` writes the
|
|
55
|
-
* viz document instead. `--live` bundles the machine files into the page, so its
|
|
56
|
-
* steps run the real actors (factories on a VirtualClock) with no server. `--config` loads the files with that Vite config (env,
|
|
57
|
-
* aliases, plugins) and `--mode` picks its mode. `--check` exits 1 if any warning was printed or
|
|
58
|
-
* fuzzing found a handler error (each printed as `error:`). Seed: MANTAQ_SEED (default from @mantaq/pbt).
|
|
59
|
-
*/
|
|
60
|
-
const USAGE = "usage: mantaq-inspect <file.ts>... [--out FILE] [--json] [--live] [--no-fuzz] [--iterations N] [--config FILE] [--mode MODE] [--no-open] [--check]\n";
|
|
61
|
-
function loadOptions(config, mode) {
|
|
62
|
-
return {
|
|
63
|
-
...config === void 0 ? {} : { config: resolve(config) },
|
|
64
|
-
...mode === void 0 ? {} : { mode }
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
function fuzzSettings(iterationsArg, off) {
|
|
68
|
-
const iterations = Number(iterationsArg ?? 2e3);
|
|
69
|
-
if (!Number.isInteger(iterations) || iterations < 0) return Either.left("bad --iterations");
|
|
70
|
-
const seed = parseSeed(process.env[SEED_ENV]);
|
|
71
|
-
if (Either.isLeft(seed)) return Either.left(seed[0].message);
|
|
72
|
-
const settings = off ? false : {
|
|
73
|
-
seed: seed[1],
|
|
74
|
-
iterations
|
|
75
|
-
};
|
|
76
|
-
return Either.right(settings);
|
|
77
|
-
}
|
|
78
|
-
function parse() {
|
|
79
|
-
const parsed = Either.from(() => parseArgs({
|
|
80
|
-
allowPositionals: true,
|
|
81
|
-
options: {
|
|
82
|
-
out: { type: "string" },
|
|
83
|
-
json: { type: "boolean" },
|
|
84
|
-
live: { type: "boolean" },
|
|
85
|
-
iterations: { type: "string" },
|
|
86
|
-
config: { type: "string" },
|
|
87
|
-
mode: { type: "string" },
|
|
88
|
-
"no-fuzz": { type: "boolean" },
|
|
89
|
-
"no-open": { type: "boolean" },
|
|
90
|
-
check: { type: "boolean" }
|
|
91
|
-
}
|
|
92
|
-
}));
|
|
93
|
-
if (Either.isLeft(parsed)) return Either.left(String(parsed[0]));
|
|
94
|
-
const { positionals, values } = parsed[1];
|
|
95
|
-
if (positionals.length === 0) return Either.left("no file given");
|
|
96
|
-
const json = values.json === true;
|
|
97
|
-
const live = values.live === true;
|
|
98
|
-
if (live && json) return Either.left("--live and --json cannot be combined");
|
|
99
|
-
const fuzz = fuzzSettings(values.iterations, values["no-fuzz"] === true);
|
|
100
|
-
if (Either.isLeft(fuzz)) return Either.left(fuzz[0]);
|
|
101
|
-
return Either.right({
|
|
102
|
-
files: positionals.map((file) => resolve(file)),
|
|
103
|
-
out: resolve(values.out ?? (json ? "mantaq-viz.json" : "mantaq-viz.html")),
|
|
104
|
-
json,
|
|
105
|
-
live,
|
|
106
|
-
fuzz: fuzz[1],
|
|
107
|
-
check: values.check === true,
|
|
108
|
-
load: loadOptions(values.config, values.mode),
|
|
109
|
-
open: values["no-open"] !== true && !json && process.stdout.isTTY === true
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
function openInBrowser(path) {
|
|
113
|
-
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "explorer" : "xdg-open";
|
|
114
|
-
spawn(command, [path], {
|
|
115
|
-
stdio: "ignore",
|
|
116
|
-
detached: true
|
|
117
|
-
}).on("error", () => {}).unref();
|
|
118
|
-
}
|
|
119
|
-
function checkFails(results, machines) {
|
|
120
|
-
const errors = machines.flatMap((machine) => (machine.fuzz?.errors ?? []).map((error) => `${machine.id}: ${error.from} -${error.event}-> ${error.message}`));
|
|
121
|
-
for (const error of errors) process.stderr.write(`error: ${error}\n`);
|
|
122
|
-
return errors.length > 0 || results.some((result) => result.warnings.length > 0);
|
|
123
|
-
}
|
|
124
|
-
async function main() {
|
|
125
|
-
const options = parse();
|
|
126
|
-
if (Either.isLeft(options)) {
|
|
127
|
-
process.stderr.write(`${options[0]}\n${USAGE}`);
|
|
128
|
-
process.exitCode = 1;
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const { files, out, json, live, fuzz, open, check, load } = options[1];
|
|
132
|
-
const results = [];
|
|
133
|
-
for (const file of files) results.push(await inspectFile(file, { fuzz }, load));
|
|
134
|
-
for (const warning of results.flatMap((result) => result.warnings)) process.stderr.write(`warning: ${warning}\n`);
|
|
135
|
-
const failed = results.some((result) => result.failed);
|
|
136
|
-
if (failed) process.exitCode = 1;
|
|
137
|
-
const machines = results.flatMap((result) => result.machines);
|
|
138
|
-
if (check && checkFails(results, machines)) process.exitCode = 1;
|
|
139
|
-
if (machines.length === 0) {
|
|
140
|
-
if (!failed) process.stderr.write("no machines found\n");
|
|
141
|
-
process.exitCode = 1;
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
const document = vizDocument(machines);
|
|
145
|
-
const title = `${files.map((file) => basename(file)).join(", ")} · mantaq viz`;
|
|
146
|
-
const liveScript = live ? await liveBundle(files, load) : void 0;
|
|
147
|
-
writeFileSync(out, json ? serializeViz(document) : await htmlPage(document, title, liveScript));
|
|
148
|
-
process.stdout.write(`wrote ${out} (${machines.map((machine) => machine.id).join(", ")})\n`);
|
|
149
|
-
if (open) openInBrowser(out);
|
|
150
|
-
}
|
|
151
|
-
main();
|
|
152
|
-
export {};
|
package/dist/live-embedded.d.mts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {}
|
package/dist/live-embedded.mjs
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { t as mountDriven } from "./live-page-DEDl_Nio.mjs";
|
|
2
|
-
import { DOCUMENT_ELEMENT_ID } from "@mantaq/viz";
|
|
3
|
-
import { targets } from "virtual:mantaq/targets";
|
|
4
|
-
// src/live-embedded.ts
|
|
5
|
-
/**
|
|
6
|
-
* Entry of the standalone live page `mantaq-inspect --live` writes: the viz
|
|
7
|
-
* document sits in the page, the machines are bundled in, nothing is fetched.
|
|
8
|
-
*/
|
|
9
|
-
const root = document.querySelector("#app");
|
|
10
|
-
const text = document.getElementById(DOCUMENT_ELEMENT_ID)?.textContent;
|
|
11
|
-
if (root && text) mountDriven(root, {
|
|
12
|
-
source: "this page",
|
|
13
|
-
text,
|
|
14
|
-
targets
|
|
15
|
-
});
|
|
16
|
-
export {};
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { createDriver } from "./drive.mjs";
|
|
2
|
-
import { parseViz } from "@mantaq/viz";
|
|
3
|
-
import { Either } from "@mantaq/utils";
|
|
4
|
-
import { mountViewer, showIssues } from "@mantaq/viz/viewer";
|
|
5
|
-
import { linkOptions } from "@mantaq/viz/page";
|
|
6
|
-
// src/live-page.ts
|
|
7
|
-
/**
|
|
8
|
-
* The live page of the Vite plugin: the served document, with each machine
|
|
9
|
-
* that has a target running for real behind the viewer. The walk lives in the
|
|
10
|
-
* address bar (`?machine=&step=`), so a redraw after a save replays it on the
|
|
11
|
-
* new code.
|
|
12
|
-
*/
|
|
13
|
-
/** A document holding only `machine`, so the viewer shows the machine its driver runs. */
|
|
14
|
-
function only(viz, machine) {
|
|
15
|
-
const chosen = viz.machines.find((each) => each.id === machine) ?? viz.machines[0];
|
|
16
|
-
return {
|
|
17
|
-
...viz,
|
|
18
|
-
machines: chosen === void 0 ? [] : [chosen]
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
/** Mount the document at `text`; machines with a target run live, the rest stay static walks. */
|
|
22
|
-
function mountDriven(root, context) {
|
|
23
|
-
const parsed = parseViz(context.text);
|
|
24
|
-
if (Either.isLeft(parsed)) {
|
|
25
|
-
showIssues(root, {
|
|
26
|
-
source: context.source,
|
|
27
|
-
issues: parsed[0]
|
|
28
|
-
});
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
const options = linkOptions();
|
|
32
|
-
const viz = parsed[1];
|
|
33
|
-
const shown = only(viz, options.machine ?? null);
|
|
34
|
-
const id = shown.machines[0]?.id ?? "";
|
|
35
|
-
const target = context.targets[id];
|
|
36
|
-
const create = target !== void 0 && typeof Reflect.get(target().clock, "advance") === "function" ? target : void 0;
|
|
37
|
-
const picker = viz.machines.length > 1;
|
|
38
|
-
const select = (machine) => {
|
|
39
|
-
const next = new URLSearchParams(location.search);
|
|
40
|
-
next.set("machine", machine);
|
|
41
|
-
next.delete("step");
|
|
42
|
-
history.replaceState(null, "", `?${next.toString()}`);
|
|
43
|
-
mountDriven(root, context);
|
|
44
|
-
};
|
|
45
|
-
const doc = root.ownerDocument;
|
|
46
|
-
const bar = doc.createElement("nav");
|
|
47
|
-
bar.className = "machines";
|
|
48
|
-
if (picker) for (const machine of viz.machines) {
|
|
49
|
-
const button = doc.createElement("button");
|
|
50
|
-
button.type = "button";
|
|
51
|
-
button.textContent = machine.id;
|
|
52
|
-
button.disabled = machine.id === id;
|
|
53
|
-
button.addEventListener("click", () => select(machine.id));
|
|
54
|
-
bar.append(button);
|
|
55
|
-
}
|
|
56
|
-
const viewer = doc.createElement("div");
|
|
57
|
-
root.replaceChildren(...picker ? [bar] : [], viewer);
|
|
58
|
-
mountViewer(viewer, shown, {
|
|
59
|
-
...options,
|
|
60
|
-
...create === void 0 ? {} : { driver: createDriver({
|
|
61
|
-
id,
|
|
62
|
-
create
|
|
63
|
-
}) }
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
/** Fetch the document from `source` and mount it; call again to redraw, keeping the walk. */
|
|
67
|
-
async function mountLiveDriven(root, context) {
|
|
68
|
-
const response = await fetch(context.source).catch(() => null);
|
|
69
|
-
if (response === null || !response.ok) {
|
|
70
|
-
const status = response === null ? "network error" : `HTTP ${response.status}`;
|
|
71
|
-
showIssues(root, {
|
|
72
|
-
source: context.source,
|
|
73
|
-
issues: [{
|
|
74
|
-
path: "$",
|
|
75
|
-
message: status
|
|
76
|
-
}]
|
|
77
|
-
});
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
mountDriven(root, {
|
|
81
|
-
...context,
|
|
82
|
-
text: await response.text()
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
export { mountLiveDriven as n, mountDriven as t };
|
package/dist/page-CK7-IsLJ.mjs
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { t as STYLESHEETS } from "./vite-BBW0CmYr.mjs";
|
|
2
|
-
import { serializeViz, standaloneHtml } from "@mantaq/viz";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { build } from "vite";
|
|
6
|
-
// src/page.ts
|
|
7
|
-
/** The viewer as one classic script, built from `@mantaq/viz/standalone`. */
|
|
8
|
-
async function viewerScript() {
|
|
9
|
-
const entry = fileURLToPath(import.meta.resolve("@mantaq/viz/standalone"));
|
|
10
|
-
const output = await build({
|
|
11
|
-
configFile: false,
|
|
12
|
-
logLevel: "silent",
|
|
13
|
-
build: {
|
|
14
|
-
write: false,
|
|
15
|
-
minify: true,
|
|
16
|
-
cssCodeSplit: false,
|
|
17
|
-
lib: {
|
|
18
|
-
entry,
|
|
19
|
-
formats: ["iife"],
|
|
20
|
-
name: "MantaqViz",
|
|
21
|
-
fileName: () => "viz.js"
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
return (Array.isArray(output) ? output : [output]).flatMap((each) => "output" in each ? each.output : []).flatMap((file) => file.type === "chunk" ? [file.code] : []).join("\n");
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* A self-contained HTML page for `document`: open it from disk, attach it, commit it.
|
|
29
|
-
* With `live` (a built script that drives the machines), that script replaces the static viewer.
|
|
30
|
-
*/
|
|
31
|
-
async function htmlPage(document, title, live) {
|
|
32
|
-
const css = STYLESHEETS.map((id) => readFileSync(fileURLToPath(import.meta.resolve(id)), "utf8")).join("\n");
|
|
33
|
-
const script = live ?? await viewerScript();
|
|
34
|
-
return standaloneHtml({
|
|
35
|
-
title,
|
|
36
|
-
script,
|
|
37
|
-
css,
|
|
38
|
-
document: serializeViz(document)
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
export { htmlPage as t };
|