@vizij/node-graph-authoring 0.0.2 → 0.0.5

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.
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ MACHINE_REPORT_VERSION,
4
+ buildMachineReport,
5
+ buildRigGraphSpec,
6
+ diffMachineReports
7
+ } from "../chunk-XYPRZPXJ.js";
8
+
9
+ // src/cli/reportIr.ts
10
+ import { readFileSync, writeFileSync } from "fs";
11
+ import { resolve } from "path";
12
+ function usage() {
13
+ console.error(
14
+ [
15
+ "Usage: vizij-ir-report --input <path/to/buildGraphOptions.json> [options]",
16
+ "",
17
+ "Options:",
18
+ " --dump <path|-> Write normalized machine-readable report (use '-' for stdout).",
19
+ " --diff <path|-> Compare against a dumped report (use '-' or 'stdin').",
20
+ " --diff-limit <number> Maximum diff entries to emit (default 50).",
21
+ " -h, --help Show this message."
22
+ ].join("\n")
23
+ );
24
+ process.exit(1);
25
+ throw new Error("Unreachable");
26
+ }
27
+ function parseArgs(argv) {
28
+ const args = [...argv];
29
+ let inputPath = "";
30
+ let dumpPath;
31
+ let diffPath;
32
+ let diffLimit;
33
+ while (args.length > 0) {
34
+ const token = args.shift();
35
+ if (!token) {
36
+ break;
37
+ }
38
+ if (token === "--input" || token === "-i") {
39
+ const value = args.shift();
40
+ if (!value) {
41
+ usage();
42
+ }
43
+ inputPath = value;
44
+ } else if (token === "--help" || token === "-h") {
45
+ usage();
46
+ } else if (token === "--dump" || token === "--dump-json") {
47
+ const value = args.shift();
48
+ if (!value) {
49
+ usage();
50
+ }
51
+ dumpPath = normalizeStreamToken(value);
52
+ } else if (token === "--diff") {
53
+ const value = args.shift();
54
+ if (!value) {
55
+ usage();
56
+ }
57
+ diffPath = normalizeStreamToken(value);
58
+ } else if (token === "--diff-limit") {
59
+ const value = args.shift();
60
+ if (!value) {
61
+ usage();
62
+ }
63
+ diffLimit = parsePositiveInteger(value, "--diff-limit");
64
+ } else if (!token.startsWith("--") && !inputPath) {
65
+ inputPath = token;
66
+ }
67
+ }
68
+ if (!inputPath) {
69
+ usage();
70
+ }
71
+ return {
72
+ inputPath: resolve(process.cwd(), inputPath),
73
+ dumpPath: resolveOptionalPath(dumpPath),
74
+ diffPath: resolveOptionalPath(diffPath),
75
+ diffLimit
76
+ };
77
+ }
78
+ function loadCliInput(path) {
79
+ const raw = JSON.parse(readFileSync(path, "utf-8"));
80
+ const inputs = raw.inputs ?? [];
81
+ const inputsById = new Map(inputs.map((input) => [input.id, input]));
82
+ const inputMetadata = raw.inputMetadata ? new Map(
83
+ raw.inputMetadata.map((entry) => ({
84
+ id: entry.id,
85
+ value: entry
86
+ })).filter(
87
+ (entry) => Boolean(entry.id)
88
+ ).map((entry) => [entry.id, entry.value])
89
+ ) : void 0;
90
+ return {
91
+ faceId: raw.faceId,
92
+ animatables: raw.animatables,
93
+ components: raw.components,
94
+ bindings: raw.bindings,
95
+ inputsById,
96
+ inputBindings: raw.inputBindings ?? {},
97
+ inputMetadata
98
+ };
99
+ }
100
+ function printIssues(result) {
101
+ console.log(`
102
+ IR Diagnostics for face "${result.summary.faceId}"`);
103
+ if (result.issues.fatal.length === 0) {
104
+ console.log("\u2022 No fatal binding issues detected.");
105
+ } else {
106
+ console.log("\u2022 Fatal issues:");
107
+ result.issues.fatal.forEach((issue) => console.log(` - ${issue}`));
108
+ }
109
+ const targets = Object.entries(result.issues.byTarget);
110
+ if (targets.length > 0) {
111
+ console.log("\nPer-binding issues:");
112
+ targets.forEach(([targetId, issues]) => {
113
+ issues.forEach((issue) => {
114
+ console.log(` - ${targetId}: ${issue}`);
115
+ });
116
+ });
117
+ }
118
+ const irIssues = result.ir?.graph.issues ?? [];
119
+ if (irIssues.length > 0) {
120
+ console.log("\nIR issues:");
121
+ irIssues.forEach((issue) => {
122
+ console.log(
123
+ ` - (${issue.severity}) ${issue.message}${issue.targetId ? ` [${issue.targetId}]` : ""}`
124
+ );
125
+ });
126
+ }
127
+ }
128
+ function printBindingSummary(result, _options) {
129
+ console.log("\nBinding summary:");
130
+ result.summary.bindings.forEach((binding) => {
131
+ console.log(
132
+ ` - ${binding.targetId} (${binding.slotAlias}): expr="${binding.expression}"`
133
+ );
134
+ if (binding.issues && binding.issues.length > 0) {
135
+ binding.issues.forEach((issue) => {
136
+ console.log(` \u2022 ${issue}`);
137
+ });
138
+ }
139
+ });
140
+ }
141
+ async function main() {
142
+ const { inputPath, dumpPath, diffPath, diffLimit } = parseArgs(
143
+ process.argv.slice(2)
144
+ );
145
+ const options = loadCliInput(inputPath);
146
+ const result = buildRigGraphSpec(options);
147
+ const machineReport = buildMachineReport(result);
148
+ if (diffPath && dumpPath && diffPath !== "-" && dumpPath !== "-" && diffPath === dumpPath) {
149
+ throw new Error(
150
+ "Cannot reuse the same file path for --dump and --diff. Provide separate files."
151
+ );
152
+ }
153
+ if (diffPath) {
154
+ if (dumpPath === "-") {
155
+ throw new Error("Cannot dump to stdout while running --diff.");
156
+ }
157
+ if (dumpPath) {
158
+ writeMachineDump(machineReport, dumpPath);
159
+ }
160
+ const baseline = loadMachineDump(diffPath);
161
+ validateReportVersion(baseline.reportVersion);
162
+ const diffResult = diffMachineReports(machineReport, baseline, {
163
+ limit: diffLimit
164
+ });
165
+ const diffPayload = {
166
+ mode: "diff",
167
+ reportVersion: MACHINE_REPORT_VERSION,
168
+ faceId: machineReport.faceId,
169
+ inputPath,
170
+ baselinePath: diffPath,
171
+ equal: diffResult.equal,
172
+ differenceCount: diffResult.differences.length,
173
+ limitReached: diffResult.limitReached,
174
+ differences: diffResult.differences
175
+ };
176
+ console.log(JSON.stringify(diffPayload, null, 2));
177
+ process.exitCode = diffResult.equal ? 0 : 1;
178
+ return;
179
+ }
180
+ if (dumpPath) {
181
+ writeMachineDump(machineReport, dumpPath);
182
+ return;
183
+ }
184
+ console.log(
185
+ `Loaded ${options.components.length} components / ${options.faceId} from ${inputPath}`
186
+ );
187
+ printIssues(result);
188
+ printBindingSummary(result, options);
189
+ console.log("\nDone.");
190
+ }
191
+ main().catch((error) => {
192
+ console.error("[vizij-ir-report] Failed:", error);
193
+ process.exit(1);
194
+ });
195
+ function resolveOptionalPath(path) {
196
+ if (!path || path === "-") {
197
+ return path;
198
+ }
199
+ return resolve(process.cwd(), path);
200
+ }
201
+ function normalizeStreamToken(value) {
202
+ const lower = value.toLowerCase();
203
+ if (lower === "-" || lower === "stdout" || lower === "stdin") {
204
+ return "-";
205
+ }
206
+ return value;
207
+ }
208
+ function parsePositiveInteger(value, flag) {
209
+ const parsed = Number.parseInt(value, 10);
210
+ if (!Number.isFinite(parsed) || parsed <= 0) {
211
+ console.error(`Invalid value for ${flag}: ${value}`);
212
+ usage();
213
+ }
214
+ return parsed;
215
+ }
216
+ function writeMachineDump(report, target) {
217
+ const payload = `${JSON.stringify(report, null, 2)}
218
+ `;
219
+ if (target === "-") {
220
+ process.stdout.write(payload);
221
+ return;
222
+ }
223
+ writeFileSync(target, payload, "utf-8");
224
+ }
225
+ function loadMachineDump(path) {
226
+ const content = path === "-" ? readFileSync(0, "utf-8") : readFileSync(path, "utf-8");
227
+ try {
228
+ const parsed = JSON.parse(content);
229
+ if (typeof parsed !== "object" || parsed === null || typeof parsed.reportVersion !== "number") {
230
+ throw new Error("Invalid machine report structure.");
231
+ }
232
+ return parsed;
233
+ } catch (error) {
234
+ if (error instanceof SyntaxError) {
235
+ throw new Error("Failed to parse machine-readable report JSON.");
236
+ }
237
+ throw error;
238
+ }
239
+ }
240
+ function validateReportVersion(version) {
241
+ if (version !== MACHINE_REPORT_VERSION) {
242
+ throw new Error(
243
+ `Machine report version mismatch (expected ${MACHINE_REPORT_VERSION}, received ${version}).`
244
+ );
245
+ }
246
+ }