@hozu/cli 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.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/bin/hozu.js +4 -0
  4. package/dist/commands/build.d.ts +4 -0
  5. package/dist/commands/build.d.ts.map +1 -0
  6. package/dist/commands/build.js +81 -0
  7. package/dist/commands/build.js.map +1 -0
  8. package/dist/commands/explain.d.ts +5 -0
  9. package/dist/commands/explain.d.ts.map +1 -0
  10. package/dist/commands/explain.js +135 -0
  11. package/dist/commands/explain.js.map +1 -0
  12. package/dist/commands/graph.d.ts +7 -0
  13. package/dist/commands/graph.d.ts.map +1 -0
  14. package/dist/commands/graph.js +137 -0
  15. package/dist/commands/graph.js.map +1 -0
  16. package/dist/commands/impact.d.ts +5 -0
  17. package/dist/commands/impact.d.ts.map +1 -0
  18. package/dist/commands/impact.js +27 -0
  19. package/dist/commands/impact.js.map +1 -0
  20. package/dist/commands/inspect.d.ts +4 -0
  21. package/dist/commands/inspect.d.ts.map +1 -0
  22. package/dist/commands/inspect.js +31 -0
  23. package/dist/commands/inspect.js.map +1 -0
  24. package/dist/commands/plan.d.ts +5 -0
  25. package/dist/commands/plan.d.ts.map +1 -0
  26. package/dist/commands/plan.js +30 -0
  27. package/dist/commands/plan.js.map +1 -0
  28. package/dist/commands/skill.d.ts +3 -0
  29. package/dist/commands/skill.d.ts.map +1 -0
  30. package/dist/commands/skill.js +27 -0
  31. package/dist/commands/skill.js.map +1 -0
  32. package/dist/commands/validate.d.ts +4 -0
  33. package/dist/commands/validate.d.ts.map +1 -0
  34. package/dist/commands/validate.js +96 -0
  35. package/dist/commands/validate.js.map +1 -0
  36. package/dist/contract.d.ts +107 -0
  37. package/dist/contract.d.ts.map +1 -0
  38. package/dist/contract.js +2 -0
  39. package/dist/contract.js.map +1 -0
  40. package/dist/errors.d.ts +8 -0
  41. package/dist/errors.d.ts.map +1 -0
  42. package/dist/errors.js +13 -0
  43. package/dist/errors.js.map +1 -0
  44. package/dist/index.d.ts +4 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +3 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/load.d.ts +9 -0
  49. package/dist/load.d.ts.map +1 -0
  50. package/dist/load.js +52 -0
  51. package/dist/load.js.map +1 -0
  52. package/dist/main.d.ts +2 -0
  53. package/dist/main.d.ts.map +1 -0
  54. package/dist/main.js +120 -0
  55. package/dist/main.js.map +1 -0
  56. package/dist/output.d.ts +5 -0
  57. package/dist/output.d.ts.map +1 -0
  58. package/dist/output.js +28 -0
  59. package/dist/output.js.map +1 -0
  60. package/dist/render.d.ts +5 -0
  61. package/dist/render.d.ts.map +1 -0
  62. package/dist/render.js +47 -0
  63. package/dist/render.js.map +1 -0
  64. package/dist/styles.d.ts +3 -0
  65. package/dist/styles.d.ts.map +1 -0
  66. package/dist/styles.js +41 -0
  67. package/dist/styles.js.map +1 -0
  68. package/package.json +54 -0
  69. package/schema/build.schema.json +29 -0
  70. package/schema/explain.schema.json +158 -0
  71. package/schema/graph.schema.json +109 -0
  72. package/schema/impact.schema.json +115 -0
  73. package/schema/inspect.schema.json +1658 -0
  74. package/schema/plan.schema.json +177 -0
  75. package/schema/skill.schema.json +21 -0
  76. package/schema/validate.schema.json +337 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 olevatorr
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/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # @hozu/cli
2
+
3
+ The hozu command: validate, inspect, graph, explain, impact, plan, build and skill (all with --json).
4
+
5
+ Part of [Hozu](https://github.com/olevatorr/Hozu#readme), an AI-first web framework. Most apps start from
6
+ `npm create hozu@latest`, which installs the right packages and sets up Claude Code or `AGENTS.md` agents.
7
+
8
+ ```sh
9
+ npm install @hozu/cli
10
+ ```
11
+
12
+ Requires Node 22.18 or newer. Documentation: the [README](https://github.com/olevatorr/Hozu#readme) and the
13
+ agent skill that `create-hozu` writes into each app.
14
+
15
+ MIT © olevatorr
package/bin/hozu.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { main } from '../dist/main.js'
3
+
4
+ process.exitCode = await main(process.argv.slice(2))
@@ -0,0 +1,4 @@
1
+ import type { BuildOutput } from '../contract.ts';
2
+ import type { Loaded } from '../load.ts';
3
+ export declare function runBuild(loaded: Loaded, out: string | undefined, cwd: string): Promise<BuildOutput>;
4
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAsBxC,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAqEzG"}
@@ -0,0 +1,81 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import { copyFile, mkdir, writeFile } from 'node:fs/promises';
10
+ import { createRequire } from 'node:module';
11
+ import { dirname, join, resolve } from 'node:path';
12
+ import { pathToFileURL } from 'node:url';
13
+ import { hashJson } from '@hozu/core/ir';
14
+ import { HozuCliError } from '../errors.js';
15
+ export async function runBuild(loaded, out, cwd) {
16
+ const build = loaded.build(false);
17
+ const errors = build.diagnostics.filter((d) => d.severity === 'error');
18
+ if (errors.length)
19
+ throw new HozuCliError('build', `The project has ${errors.length} build errors`, ['Run hozu validate']);
20
+ const require = createRequire(loaded.path);
21
+ const optional = async (id) => {
22
+ try {
23
+ return (await import(__rewriteRelativeImportExtension(pathToFileURL(require.resolve(id)).href)));
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ };
29
+ const from = async (id) => {
30
+ try {
31
+ return (await import(__rewriteRelativeImportExtension(pathToFileURL(require.resolve(id)).href)));
32
+ }
33
+ catch {
34
+ throw new HozuCliError('build', `hozu build needs ${id} installed in the project`, [`pnpm add ${id}`]);
35
+ }
36
+ };
37
+ const base = dirname(loaded.path);
38
+ const styles = build.bindings.styles.entry
39
+ ? await (await from('@hozu/css')).compileStyles(build, { base })
40
+ : null;
41
+ const widgets = Object.keys(build.bindings.widgets).length
42
+ ? await (await from('@hozu/bundle')).bundleWidgets(build)
43
+ : null;
44
+ const images = await optional('@hozu/image').then((m) => (m ? m.optimizeImages(build) : null));
45
+ const server = await from('@hozu/runtime-server');
46
+ const dir = resolve(cwd, out ?? 'dist');
47
+ const files = [];
48
+ for (const f of server.staticFiles(build, { styles, widgets, client: true })) {
49
+ const file = join(dir, 'public', f.path.replace(/^\//, ''));
50
+ await mkdir(dirname(file), { recursive: true });
51
+ if (f.file)
52
+ await copyFile(f.file, file);
53
+ else
54
+ await writeFile(file, f.text ?? '');
55
+ files.push(file);
56
+ }
57
+ for (const [href, bytes] of Object.entries(images?.files ?? {})) {
58
+ const file = join(dir, 'public', href.replace(/^\//, ''));
59
+ await mkdir(dirname(file), { recursive: true });
60
+ await writeFile(file, bytes);
61
+ files.push(file);
62
+ }
63
+ const manifest = {
64
+ irHash: hashJson(build.ir),
65
+ images: images && Object.keys(images.variants).length ? images.variants : null,
66
+ assets: build.bindings.assetOrder,
67
+ widgets: Object.fromEntries(Object.entries(widgets?.urls ?? {}).map(([ref, url]) => {
68
+ const [feature, symbol] = ref.split('.');
69
+ return [ref, { hash: build.ir.features[feature]?.widgets[symbol]?.sourceHash ?? '', url }];
70
+ })),
71
+ styles: styles ? { href: styles.href, preload: styles.preload } : null,
72
+ };
73
+ const renderFile = join(dir, 'server', 'render.js');
74
+ await mkdir(dirname(renderFile), { recursive: true });
75
+ await writeFile(renderFile, server.generateRender(build, manifest.images));
76
+ files.push(renderFile);
77
+ const manifestFile = join(dir, 'manifest.json');
78
+ await writeFile(manifestFile, `${JSON.stringify(manifest, null, 2)}\n`);
79
+ return { out: dir, manifest: manifestFile, files };
80
+ }
81
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { ExplainOutput } from '../contract.ts';
2
+ import { type Loaded } from '../load.ts';
3
+ export declare function runExplain(loaded: Loaded, target: string | undefined): ExplainOutput;
4
+ export declare function describeExplain(out: ExplainOutput): string;
5
+ //# sourceMappingURL=explain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain.d.ts","sourceRoot":"","sources":["../../src/commands/explain.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAkC,MAAM,gBAAgB,CAAA;AAEnF,OAAO,EAAE,KAAK,MAAM,EAAkB,MAAM,YAAY,CAAA;AAqExD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAuCpF;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAwB1D"}
@@ -0,0 +1,135 @@
1
+ import { closest, verify } from '@hozu/validator';
2
+ import { HozuCliError } from '../errors.js';
3
+ import { requireFeature } from '../load.js';
4
+ import { renderAssign, renderGuard, renderValue } from '../render.js';
5
+ const local = (ref) => ref.slice(ref.indexOf('.') + 1);
6
+ function transitionsOf(feature, coveredBy) {
7
+ const out = [];
8
+ const add = (from, id, trigger, t) => out.push({
9
+ id,
10
+ from,
11
+ to: t.target,
12
+ trigger,
13
+ guard: t.guard ? renderGuard(t.guard) : null,
14
+ assign: t.assign.map(renderAssign),
15
+ navigate: t.navigate && 'link' in t.navigate ? t.navigate.link : null,
16
+ coveredBy: coveredBy(id),
17
+ });
18
+ for (const [name, s] of Object.entries(feature.machine?.states ?? {})) {
19
+ for (const [event, list] of Object.entries(s.on))
20
+ list.forEach((t, i) => add(name, `${name}/on/${event}/${i}`, `on ${local(event)}`, t));
21
+ s.invoke?.done.forEach((t, i) => add(name, `${name}/invoke/done/${i}`, 'done', t));
22
+ for (const [error, list] of Object.entries(s.invoke?.failed ?? {}))
23
+ list.forEach((t, i) => add(name, `${name}/invoke/failed/${error}/${i}`, `failed.${error}`, t));
24
+ s.after.forEach((a, i) => add(name, `${name}/after/${i}`, `after ${a.ms}ms`, a.transition));
25
+ }
26
+ return out;
27
+ }
28
+ function sendsIn(feature, state) {
29
+ const out = [];
30
+ const states = feature.machine.states;
31
+ const walk = (node, view, visible) => {
32
+ if (!visible)
33
+ return;
34
+ switch (node.kind) {
35
+ case 'if':
36
+ for (const c of [...node.ifTrue, ...node.ifFalse])
37
+ walk(c, view, visible);
38
+ return;
39
+ case 'el':
40
+ case 'widget':
41
+ case 'global':
42
+ for (const send of Object.values(node.on))
43
+ out.push({
44
+ view,
45
+ node: node.id,
46
+ event: send.event,
47
+ handled: Boolean(states[state].on[send.event]?.length),
48
+ });
49
+ if (node.kind !== 'global')
50
+ for (const c of node.children)
51
+ walk(c, view, visible);
52
+ return;
53
+ case 'when':
54
+ for (const c of node.children)
55
+ walk(c, view, node.states.includes(state));
56
+ return;
57
+ case 'each':
58
+ walk(node.item, view, visible);
59
+ return;
60
+ case 'query':
61
+ for (const c of [node.ready, ...(node.pending ? [node.pending] : []), ...Object.values(node.failed)])
62
+ walk(c, view, visible);
63
+ return;
64
+ default:
65
+ return;
66
+ }
67
+ };
68
+ for (const [vid, view] of Object.entries(feature.views))
69
+ if (view.machine === feature.id)
70
+ walk(view.root, `${feature.id}.${vid}`, true);
71
+ return out;
72
+ }
73
+ export function runExplain(loaded, target) {
74
+ if (!target?.includes('.'))
75
+ throw new HozuCliError('usage', 'Expected <feature>.<state>, e.g. hozu explain cart.idle');
76
+ const [fid, state] = [target.slice(0, target.indexOf('.')), target.slice(target.indexOf('.') + 1)];
77
+ const build = loaded.build();
78
+ const feature = requireFeature(build.ir, fid);
79
+ const m = feature.machine;
80
+ if (!m)
81
+ throw new HozuCliError('unknown-feature', `Feature "${fid}" has no machine`);
82
+ const s = m.states[state];
83
+ if (!s) {
84
+ const guess = closest(state, Object.keys(m.states));
85
+ throw new HozuCliError('unknown-feature', `Unknown state "${state}" in ${fid}`, guess ? [`${fid}.${guess}`] : Object.keys(m.states).map((n) => `${fid}.${n}`));
86
+ }
87
+ const { lock } = verify(build.ir, { bindings: build.bindings });
88
+ const entries = lock?.features[fid] ?? {};
89
+ const all = transitionsOf(feature, (id) => Object.keys(entries[id]?.contracts ?? {}));
90
+ const effect = s.invoke ? build.ir.features[s.invoke.effect.split('.')[0]] : undefined;
91
+ const effectSymbol = s.invoke ? local(s.invoke.effect) : '';
92
+ const declared = effect?.queries[effectSymbol]?.errors ?? effect?.mutations[effectSymbol]?.errors ?? {};
93
+ return {
94
+ feature: fid,
95
+ state,
96
+ initial: m.initial === state,
97
+ final: s.final,
98
+ invoke: s.invoke
99
+ ? {
100
+ effect: s.invoke.effect,
101
+ input: renderValue(s.invoke.input),
102
+ errors: [...Object.keys(declared), 'Unexpected'],
103
+ }
104
+ : null,
105
+ outgoing: all.filter((t) => t.from === state),
106
+ incoming: all.filter((t) => t.to === state),
107
+ sends: sendsIn(feature, state),
108
+ };
109
+ }
110
+ export function describeExplain(out) {
111
+ const line = (t, dir) => {
112
+ const guard = t.guard ? ` [${t.guard}]` : '';
113
+ const effects = [...t.assign, ...(t.navigate ? [`navigate(${t.navigate})`] : [])];
114
+ const body = effects.length ? ` { ${effects.join('; ')} }` : '';
115
+ const covered = t.coveredBy.length ? ` ✓ ${t.coveredBy.join(', ')}` : ' ✗ uncovered';
116
+ return dir === 'out'
117
+ ? ` ${t.trigger}${guard} → ${t.to}${body}${covered}`
118
+ : ` ${t.from} --${t.trigger}${guard}--> ${out.state}`;
119
+ };
120
+ const flags = [out.initial && 'initial', out.final && 'final'].filter(Boolean).join(', ');
121
+ return [
122
+ `${out.feature}.${out.state}${flags ? ` (${flags})` : ''}`,
123
+ `invoke: ${out.invoke ? `${out.invoke.effect}(${out.invoke.input}) errors: ${out.invoke.errors.join(', ')}` : 'none'}`,
124
+ 'outgoing:',
125
+ ...(out.outgoing.length ? out.outgoing.map((t) => line(t, 'out')) : [' (none)']),
126
+ 'incoming:',
127
+ ...(out.incoming.length ? out.incoming.map((t) => line(t, 'in')) : [' (none)']),
128
+ 'views can send:',
129
+ ...(out.sends.length
130
+ ? out.sends.map((s) => ` ${local(s.event)} from ${s.node}${s.handled ? '' : ' ✗ not handled here'}`)
131
+ : [' (nothing)']),
132
+ '',
133
+ ].join('\n');
134
+ }
135
+ //# sourceMappingURL=explain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/commands/explain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { FeatureIR } from '@hozu/core/ir';
2
+ import type { GraphOutput } from '../contract.ts';
3
+ import { type Loaded } from '../load.ts';
4
+ export declare function graphOf(feature: FeatureIR): GraphOutput;
5
+ export declare const runGraph: (loaded: Loaded, id: string | undefined) => GraphOutput;
6
+ export declare function mermaid(graph: GraphOutput): string;
7
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/commands/graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,eAAe,CAAA;AACxD,OAAO,KAAK,EAAwB,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACvE,OAAO,EAAE,KAAK,MAAM,EAAkB,MAAM,YAAY,CAAA;AAoDxD,wBAAgB,OAAO,CAAC,OAAO,EAAE,SAAS,GAAG,WAAW,CAiEvD;AAED,eAAO,MAAM,QAAQ,WAAY,MAAM,MAAM,MAAM,GAAG,SAAS,KAAG,WAClB,CAAA;AAEhD,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAUlD"}
@@ -0,0 +1,137 @@
1
+ import { requireFeature } from '../load.js';
2
+ const local = (ref) => ref.slice(ref.indexOf('.') + 1);
3
+ function collectViewEdges(node, from, edges, nodes) {
4
+ const add = (id, kind, label) => {
5
+ if (!nodes.has(id))
6
+ nodes.set(id, { id, kind, label, initial: false, final: false });
7
+ };
8
+ switch (node.kind) {
9
+ case 'if':
10
+ for (const child of [...node.ifTrue, ...node.ifFalse])
11
+ collectViewEdges(child, from, edges, nodes);
12
+ return;
13
+ case 'el':
14
+ case 'widget':
15
+ case 'global':
16
+ for (const send of Object.values(node.on)) {
17
+ add(`event:${send.event}`, 'event', send.event);
18
+ edges.push({
19
+ from,
20
+ to: `event:${send.event}`,
21
+ kind: 'send',
22
+ label: node.kind === 'el' ? node.tag : node.kind === 'widget' ? node.widget : node.target,
23
+ });
24
+ }
25
+ if (node.kind !== 'global')
26
+ for (const child of node.children)
27
+ collectViewEdges(child, from, edges, nodes);
28
+ return;
29
+ case 'when':
30
+ for (const child of node.children)
31
+ collectViewEdges(child, from, edges, nodes);
32
+ return;
33
+ case 'each':
34
+ collectViewEdges(node.item, from, edges, nodes);
35
+ return;
36
+ case 'query':
37
+ add(`query:${node.query}`, 'query', node.query);
38
+ edges.push({ from, to: `query:${node.query}`, kind: 'reads', label: '' });
39
+ for (const child of [
40
+ node.ready,
41
+ ...(node.pending ? [node.pending] : []),
42
+ ...Object.values(node.failed),
43
+ ])
44
+ collectViewEdges(child, from, edges, nodes);
45
+ return;
46
+ case 'embed':
47
+ add(`view:${node.view}`, 'view', node.view);
48
+ edges.push({ from, to: `view:${node.view}`, kind: 'embeds', label: '' });
49
+ return;
50
+ default:
51
+ return;
52
+ }
53
+ }
54
+ export function graphOf(feature) {
55
+ const nodes = new Map();
56
+ const edges = [];
57
+ const m = feature.machine;
58
+ for (const [state, s] of Object.entries(m?.states ?? {})) {
59
+ const id = `state:${state}`;
60
+ nodes.set(id, { id, kind: 'state', label: state, initial: m?.initial === state, final: s.final });
61
+ const guarded = (g) => (g ? ' [guard]' : '');
62
+ for (const [event, list] of Object.entries(s.on))
63
+ for (const t of list)
64
+ edges.push({
65
+ from: id,
66
+ to: `state:${t.target}`,
67
+ kind: 'on',
68
+ label: `${local(event)}${guarded(t.guard)}`,
69
+ });
70
+ if (s.invoke) {
71
+ const effect = `effect:${s.invoke.effect}`;
72
+ if (!nodes.has(effect))
73
+ nodes.set(effect, {
74
+ id: effect,
75
+ kind: 'effect',
76
+ label: s.invoke.effect,
77
+ initial: false,
78
+ final: false,
79
+ });
80
+ edges.push({ from: id, to: effect, kind: 'invoke', label: '' });
81
+ for (const t of s.invoke.done)
82
+ edges.push({ from: id, to: `state:${t.target}`, kind: 'done', label: `done${guarded(t.guard)}` });
83
+ for (const [error, list] of Object.entries(s.invoke.failed))
84
+ for (const t of list)
85
+ edges.push({
86
+ from: id,
87
+ to: `state:${t.target}`,
88
+ kind: 'failed',
89
+ label: `failed.${error}${guarded(t.guard)}`,
90
+ });
91
+ }
92
+ for (const a of s.after)
93
+ edges.push({
94
+ from: id,
95
+ to: `state:${a.transition.target}`,
96
+ kind: 'after',
97
+ label: `after ${a.ms}ms${guarded(a.transition.guard)}`,
98
+ });
99
+ }
100
+ for (const [vid, view] of Object.entries(feature.views)) {
101
+ const id = `view:${feature.id}.${vid}`;
102
+ nodes.set(id, { id, kind: 'view', label: `${feature.id}.${vid}`, initial: false, final: false });
103
+ collectViewEdges(view.root, id, edges, nodes);
104
+ }
105
+ for (const imported of feature.imports) {
106
+ const id = `feature:${imported}`;
107
+ nodes.set(id, { id, kind: 'feature', label: imported, initial: false, final: false });
108
+ edges.push({ from: `feature:${feature.id}`, to: id, kind: 'import', label: '' });
109
+ }
110
+ if (feature.imports.length)
111
+ nodes.set(`feature:${feature.id}`, {
112
+ id: `feature:${feature.id}`,
113
+ kind: 'feature',
114
+ label: feature.id,
115
+ initial: false,
116
+ final: false,
117
+ });
118
+ return { feature: feature.id, nodes: [...nodes.values()].sort((a, b) => a.id.localeCompare(b.id)), edges };
119
+ }
120
+ export const runGraph = (loaded, id) => graphOf(requireFeature(loaded.build().ir, id));
121
+ export function mermaid(graph) {
122
+ const states = graph.nodes.filter((n) => n.kind === 'state');
123
+ if (!states.length)
124
+ return `stateDiagram-v2\n note "${graph.feature} has no machine"\n`;
125
+ const lines = ['stateDiagram-v2'];
126
+ for (const s of states)
127
+ if (s.initial)
128
+ lines.push(` [*] --> ${s.label}`);
129
+ for (const e of graph.edges)
130
+ if (e.from.startsWith('state:') && e.to.startsWith('state:'))
131
+ lines.push(` ${e.from.slice(6)} --> ${e.to.slice(6)}: ${e.label}`);
132
+ for (const s of states)
133
+ if (s.final)
134
+ lines.push(` ${s.label} --> [*]`);
135
+ return `${lines.join('\n')}\n`;
136
+ }
137
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/commands/graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { ImpactOutput } from '../contract.ts';
2
+ import type { Loaded } from '../load.ts';
3
+ export declare function runImpact(loaded: Loaded, target: string | undefined): ImpactOutput;
4
+ export declare function describeImpact(out: ImpactOutput): string;
5
+ //# sourceMappingURL=impact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact.d.ts","sourceRoot":"","sources":["../../src/commands/impact.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAElD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAUlF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAcxD"}
@@ -0,0 +1,27 @@
1
+ import { impact, UnknownSymbolError } from '@hozu/validator';
2
+ import { HozuCliError } from '../errors.js';
3
+ export function runImpact(loaded, target) {
4
+ if (!target?.includes('.'))
5
+ throw new HozuCliError('usage', 'Expected <feature>.<symbol>, e.g. hozu impact cart.addItem');
6
+ try {
7
+ return impact(loaded.build().ir, target);
8
+ }
9
+ catch (error) {
10
+ if (error instanceof UnknownSymbolError)
11
+ throw new HozuCliError('unknown-feature', error.message, error.suggestions);
12
+ throw error;
13
+ }
14
+ }
15
+ export function describeImpact(out) {
16
+ const lines = [`${out.target} (${out.kind})`];
17
+ if (out.tags.length)
18
+ lines.push(`tags: ${out.tags.join(', ')}`);
19
+ if (out.queries.length)
20
+ lines.push('affects queries:', ...out.queries.map((q) => ` ${q.ref} via ${q.tag}${q.precision === 'exact' ? '' : ' (param-dependent)'}`));
21
+ if (out.invalidatedBy.length)
22
+ lines.push(`invalidated by: ${out.invalidatedBy.join(', ')}`);
23
+ lines.push('uses:', ...(out.uses.length ? out.uses.map((u) => ` ${u.via}`) : [' (none)']));
24
+ lines.push(`features: ${out.features.join(', ')}`, '');
25
+ return lines.join('\n');
26
+ }
27
+ //# sourceMappingURL=impact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact.js","sourceRoot":"","sources":["../../src/commands/impact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAG3C,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,MAA0B;IAClE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC;QACxB,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,4DAA4D,CAAC,CAAA;IAC/F,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,kBAAkB;YACrC,MAAM,IAAI,YAAY,CAAC,iBAAiB,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAA;QAC7E,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAiB;IAC9C,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,CAAA;IAC9C,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC/D,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM;QACpB,KAAK,CAAC,IAAI,CACR,kBAAkB,EAClB,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAChB,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,EAAE,CACxF,CACF,CAAA;IACH,IAAI,GAAG,CAAC,aAAa,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC3F,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;IAC5F,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACtD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { InspectOutput } from '../contract.ts';
2
+ import { type Loaded } from '../load.ts';
3
+ export declare function runInspect(loaded: Loaded, id: string | undefined): InspectOutput;
4
+ //# sourceMappingURL=inspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/commands/inspect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,KAAK,MAAM,EAAkB,MAAM,YAAY,CAAA;AAExD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CA+BhF"}
@@ -0,0 +1,31 @@
1
+ import { hashJson } from '@hozu/core/ir';
2
+ import { requireFeature } from '../load.js';
3
+ export function runInspect(loaded, id) {
4
+ const { ir } = loaded.build();
5
+ const feature = requireFeature(ir, id);
6
+ const states = Object.values(feature.machine?.states ?? {});
7
+ const transitions = states.reduce((n, s) => n +
8
+ Object.values(s.on).reduce((m, l) => m + l.length, 0) +
9
+ (s.invoke
10
+ ? s.invoke.done.length + Object.values(s.invoke.failed).reduce((m, l) => m + l.length, 0)
11
+ : 0) +
12
+ s.after.length, 0);
13
+ return {
14
+ feature: feature.id,
15
+ hash: hashJson(feature),
16
+ summary: {
17
+ states: states.length,
18
+ transitions,
19
+ events: Object.keys(feature.events).length,
20
+ queries: Object.keys(feature.queries).length,
21
+ mutations: Object.keys(feature.mutations).length,
22
+ views: Object.keys(feature.views).length,
23
+ contracts: Object.keys(feature.contracts).length,
24
+ hydrates: Object.values(feature.views).some((v) => v.machine !== null),
25
+ imports: feature.imports,
26
+ exports: feature.exports,
27
+ },
28
+ ir: feature,
29
+ };
30
+ }
31
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/commands/inspect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,OAAO,EAAe,cAAc,EAAE,MAAM,YAAY,CAAA;AAExD,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,EAAsB;IAC/D,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAA;IAC7B,MAAM,OAAO,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACtC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC,CAAA;IAC3D,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAC/B,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC,MAAM;YACP,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YACzF,CAAC,CAAC,CAAC,CAAC;QACN,CAAC,CAAC,KAAK,CAAC,MAAM,EAChB,CAAC,CACF,CAAA;IACD,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,EAAE;QACnB,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC;QACvB,OAAO,EAAE;YACP,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,WAAW;YACX,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM;YAC1C,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM;YAC5C,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM;YAChD,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM;YACxC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM;YAChD,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC;YACtE,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB;QACD,EAAE,EAAE,OAAO;KACZ,CAAA;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { PlanOutput } from '../contract.ts';
2
+ import type { Loaded } from '../load.ts';
3
+ export declare function runPlan(loaded: Loaded, route: string | undefined): PlanOutput;
4
+ export declare function describePlan(plan: PlanOutput): string;
5
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/commands/plan.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEhD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAS7E;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAiBrD"}
@@ -0,0 +1,30 @@
1
+ import { planRoute, softTargets } from '@hozu/compiler';
2
+ import { closest } from '@hozu/validator';
3
+ import { HozuCliError } from '../errors.js';
4
+ export function runPlan(loaded, route) {
5
+ const { ir } = loaded.build();
6
+ const routes = Object.keys(ir.pages);
7
+ if (!route)
8
+ throw new HozuCliError('usage', 'Missing <route> argument', routes);
9
+ if (!ir.pages[route]) {
10
+ const guess = closest(route, routes);
11
+ throw new HozuCliError('unknown-feature', `No page renders route "${route}"`, guess ? [guess] : routes);
12
+ }
13
+ return { ...planRoute(ir, route).plan, soft: softTargets(ir, route) };
14
+ }
15
+ export function describePlan(plan) {
16
+ const width = Math.max(...plan.regions.map((r) => r.id.length));
17
+ return [
18
+ `${plan.route} ${plan.path} · js: ${plan.js ? `${plan.islands.length} islands` : 'none (0 bytes)'} · cacheable: ${plan.cacheable ? 'yes' : 'no'}${plan.assert ? ` · asserts ${plan.assert}` : ''}`,
19
+ 'regions:',
20
+ ...plan.regions.map((r) => ` ${r.id.padEnd(width)} ${r.mode}${r.seconds === null ? '' : ` ${r.seconds}s`}${r.query ? ` ${r.query} (${r.scope})` : ''}`),
21
+ 'islands:',
22
+ ...(plan.islands.length ? plan.islands.map((i) => ` ${i}`) : [' (none)']),
23
+ 'soft navigation (target route → kept views):',
24
+ ...(Object.keys(plan.soft).length
25
+ ? Object.entries(plan.soft).map(([r, views]) => ` ${r} → ${views.join(', ')}`)
26
+ : [' (none: links from this page are document navigations)']),
27
+ '',
28
+ ].join('\n');
29
+ }
30
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/commands/plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { SkillOutput } from '../contract.ts';
2
+ export declare function runSkill(cwd: string, requested: string | undefined): Promise<SkillOutput>;
3
+ //# sourceMappingURL=skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AASjD,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAoB/F"}