@tscircuit/cli 0.1.1787 → 0.1.1788
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 +24 -0
- package/dist/cli/build/build.worker.js +31 -8
- package/dist/cli/main.js +33 -10
- package/dist/cli/snapshot/snapshot.worker.js +31 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,6 +80,30 @@ The `build` command also accepts the following options:
|
|
|
80
80
|
- `--ignore-placement-drc` - suppress placement DRC diagnostics
|
|
81
81
|
- `--ignore-routing-drc` - suppress routing DRC diagnostics
|
|
82
82
|
|
|
83
|
+
### Debug autorouting stages
|
|
84
|
+
|
|
85
|
+
Use `--autorouter-debug` to log each autorouting stage and write visual
|
|
86
|
+
artifacts while the circuit is being routed:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
tsci build index.circuit.tsx \
|
|
90
|
+
--autorouter-debug \
|
|
91
|
+
--autorouter-debug-dir dist/autorouter-debug \
|
|
92
|
+
--autorouter-dump-srj all
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The debug directory contains:
|
|
96
|
+
|
|
97
|
+
- `placement-unrouted.png` — PCB placement before routing starts.
|
|
98
|
+
- `phase-N-routed.png` — cumulative PCB routing after each zero-indexed stage.
|
|
99
|
+
A fanout router and its downstream router appear as separate stages.
|
|
100
|
+
- `phase-N.input.simple-route.json` and `phase-N.output.traces.json` when
|
|
101
|
+
`--autorouter-dump-srj all` is enabled.
|
|
102
|
+
- `board.meta.json` — phase timing and connection-count summary.
|
|
103
|
+
|
|
104
|
+
Use `--autorouter-dump-srj failed` to keep only failed-stage routing data, or
|
|
105
|
+
`--autorouter-dump-srj phase:N` to capture a single stage.
|
|
106
|
+
|
|
83
107
|
## Development
|
|
84
108
|
|
|
85
109
|
This command will open the `index.tsx` file for editing.
|
|
@@ -12347,13 +12347,18 @@ class AutorouterDiagnostics {
|
|
|
12347
12347
|
return filePath;
|
|
12348
12348
|
}
|
|
12349
12349
|
writePngSnapshot(fileName, circuitJson) {
|
|
12350
|
-
|
|
12351
|
-
|
|
12352
|
-
|
|
12353
|
-
|
|
12354
|
-
|
|
12355
|
-
|
|
12356
|
-
|
|
12350
|
+
try {
|
|
12351
|
+
const pcbSvg = convertCircuitJsonToPcbSvg(circuitJson);
|
|
12352
|
+
const png = convertSvgToPngBuffer(pcbSvg);
|
|
12353
|
+
const debugDir = path2.resolve(this.options.debugDir ?? DEFAULT_DEBUG_DIR);
|
|
12354
|
+
fs2.mkdirSync(debugDir, { recursive: true });
|
|
12355
|
+
const filePath = path2.join(debugDir, fileName);
|
|
12356
|
+
fs2.writeFileSync(filePath, png);
|
|
12357
|
+
this.logArtifact(filePath);
|
|
12358
|
+
} catch (error) {
|
|
12359
|
+
const serializedError = this.serializeError(error instanceof Error ? error : String(error));
|
|
12360
|
+
this.log(kleur_default.yellow(`Could not write autorouter debug image ${fileName}: ${serializedError.message}`));
|
|
12361
|
+
}
|
|
12357
12362
|
}
|
|
12358
12363
|
logArtifact(filePath) {
|
|
12359
12364
|
this.log(`Wrote debug artifact: ${path2.relative(process.cwd(), filePath)}`);
|
|
@@ -12366,7 +12371,8 @@ class AutorouterDiagnostics {
|
|
|
12366
12371
|
if (id)
|
|
12367
12372
|
elementIndexById.set(id, index);
|
|
12368
12373
|
}
|
|
12369
|
-
for (const
|
|
12374
|
+
for (const autorouterTrace of this.completedPhaseTraces) {
|
|
12375
|
+
const trace = this.normalizeTraceForPcbSnapshot(autorouterTrace);
|
|
12370
12376
|
if (!trace || typeof trace !== "object")
|
|
12371
12377
|
continue;
|
|
12372
12378
|
const id = this.getCircuitElementId(trace);
|
|
@@ -12381,6 +12387,23 @@ class AutorouterDiagnostics {
|
|
|
12381
12387
|
}
|
|
12382
12388
|
return circuitJson;
|
|
12383
12389
|
}
|
|
12390
|
+
normalizeTraceForPcbSnapshot(trace) {
|
|
12391
|
+
return {
|
|
12392
|
+
...trace,
|
|
12393
|
+
route: trace.route.map((point) => {
|
|
12394
|
+
if (point.route_type !== "through_obstacle")
|
|
12395
|
+
return point;
|
|
12396
|
+
return {
|
|
12397
|
+
route_type: "through_pad",
|
|
12398
|
+
start: point.start,
|
|
12399
|
+
end: point.end,
|
|
12400
|
+
start_layer: point.from_layer,
|
|
12401
|
+
end_layer: point.to_layer,
|
|
12402
|
+
width: point.width
|
|
12403
|
+
};
|
|
12404
|
+
})
|
|
12405
|
+
};
|
|
12406
|
+
}
|
|
12384
12407
|
getCircuitElementId(element) {
|
|
12385
12408
|
const idEntry = Object.entries(element).find(([key, value]) => key === `${element.type}_id` && typeof value === "string");
|
|
12386
12409
|
const id = idEntry?.[1];
|
package/dist/cli/main.js
CHANGED
|
@@ -123144,13 +123144,18 @@ class AutorouterDiagnostics {
|
|
|
123144
123144
|
return filePath;
|
|
123145
123145
|
}
|
|
123146
123146
|
writePngSnapshot(fileName, circuitJson) {
|
|
123147
|
-
|
|
123148
|
-
|
|
123149
|
-
|
|
123150
|
-
|
|
123151
|
-
|
|
123152
|
-
|
|
123153
|
-
|
|
123147
|
+
try {
|
|
123148
|
+
const pcbSvg = convertCircuitJsonToPcbSvg(circuitJson);
|
|
123149
|
+
const png = convertSvgToPngBuffer(pcbSvg);
|
|
123150
|
+
const debugDir = path17.resolve(this.options.debugDir ?? DEFAULT_DEBUG_DIR);
|
|
123151
|
+
fs17.mkdirSync(debugDir, { recursive: true });
|
|
123152
|
+
const filePath = path17.join(debugDir, fileName);
|
|
123153
|
+
fs17.writeFileSync(filePath, png);
|
|
123154
|
+
this.logArtifact(filePath);
|
|
123155
|
+
} catch (error) {
|
|
123156
|
+
const serializedError = this.serializeError(error instanceof Error ? error : String(error));
|
|
123157
|
+
this.log(kleur_default.yellow(`Could not write autorouter debug image ${fileName}: ${serializedError.message}`));
|
|
123158
|
+
}
|
|
123154
123159
|
}
|
|
123155
123160
|
logArtifact(filePath) {
|
|
123156
123161
|
this.log(`Wrote debug artifact: ${path17.relative(process.cwd(), filePath)}`);
|
|
@@ -123163,7 +123168,8 @@ class AutorouterDiagnostics {
|
|
|
123163
123168
|
if (id)
|
|
123164
123169
|
elementIndexById.set(id, index);
|
|
123165
123170
|
}
|
|
123166
|
-
for (const
|
|
123171
|
+
for (const autorouterTrace of this.completedPhaseTraces) {
|
|
123172
|
+
const trace = this.normalizeTraceForPcbSnapshot(autorouterTrace);
|
|
123167
123173
|
if (!trace || typeof trace !== "object")
|
|
123168
123174
|
continue;
|
|
123169
123175
|
const id = this.getCircuitElementId(trace);
|
|
@@ -123178,6 +123184,23 @@ class AutorouterDiagnostics {
|
|
|
123178
123184
|
}
|
|
123179
123185
|
return circuitJson;
|
|
123180
123186
|
}
|
|
123187
|
+
normalizeTraceForPcbSnapshot(trace) {
|
|
123188
|
+
return {
|
|
123189
|
+
...trace,
|
|
123190
|
+
route: trace.route.map((point) => {
|
|
123191
|
+
if (point.route_type !== "through_obstacle")
|
|
123192
|
+
return point;
|
|
123193
|
+
return {
|
|
123194
|
+
route_type: "through_pad",
|
|
123195
|
+
start: point.start,
|
|
123196
|
+
end: point.end,
|
|
123197
|
+
start_layer: point.from_layer,
|
|
123198
|
+
end_layer: point.to_layer,
|
|
123199
|
+
width: point.width
|
|
123200
|
+
};
|
|
123201
|
+
})
|
|
123202
|
+
};
|
|
123203
|
+
}
|
|
123181
123204
|
getCircuitElementId(element) {
|
|
123182
123205
|
const idEntry = Object.entries(element).find(([key, value]) => key === `${element.type}_id` && typeof value === "string");
|
|
123183
123206
|
const id = idEntry?.[1];
|
|
@@ -135250,7 +135273,7 @@ var parseInjectedProps = ({
|
|
|
135250
135273
|
return parsed;
|
|
135251
135274
|
};
|
|
135252
135275
|
var registerBuild = (program2) => {
|
|
135253
|
-
program2.command("build").description("Run tscircuit eval and output circuit json").argument("[file]", "Path to the entry file").option("--ci", "Run install and optional prebuild/build commands (or default CI build)").option("--ignore-errors", "Do not exit with code 1 on errors").option("--ignore-warnings", "Do not log warnings").option("--ignore-netlist-drc", "Ignore netlist DRC errors/warnings").option("--ignore-pin-specification-drc", "Ignore pin-specification DRC errors/warnings").option("--ignore-placement-drc", "Ignore placement DRC errors/warnings").option("--ignore-routing-drc", "Ignore routing DRC errors/warnings").option("--ignore-config", "Ignore options from tscircuit.config.json").option("--disable-pcb", "Disable PCB outputs").option("--routing-disabled", "Disable routing during circuit generation").option("--disable-parts-engine", "Disable the parts engine").option("--site", "Generate a static site in the dist directory").option("--transpile", "Transpile the entry file to JavaScript").option("--preview-images", "Generate preview images in the dist directory").option("--all-images", "Generate preview images for every successful build output").option("--pngs", "Generate PNG outputs during build generation").option("--pcb-png", "Generate PCB PNG outputs during build generation").option("--schematic-png", "Generate schematic PNG outputs during build generation").option("--svgs", "Generate SVG outputs during build generation").option("--pcb-svgs", "Generate PCB SVG outputs during build generation").option("--schematic-svgs", "Generate schematic SVG outputs during build generation").option("--simulation-svgs", "Generate simulation graph SVG outputs during build generation").option("--simulation-schematic-svgs", "Generate schematic simulation SVG outputs during build generation").option("--3d-png", "Generate 3D PNG outputs during build generation").option("--3d", "Generate 3D PNG outputs during build generation").option("--pcb-only", "Generate only PCB SVG outputs during build generation").option("--schematic-only", "Generate only schematic SVG outputs during build generation").option("--kicad-project", "Generate KiCad project directories for each successful build output").option("--kicad-project-zip", "Generate a zipped KiCad project for each successful build output").option("--kicad-library", "Generate KiCad library in dist/kicad-library").option("--kicad-library-name <name>", "Specify the name of the KiCad library").option("--preview-gltf", "Generate a GLTF file from the preview entrypoint").option("--show-courtyards", "Show courtyard outlines in PCB SVG outputs").option("--glbs", "Generate GLB 3D model files for every successful build").option("--step", "Generate STEP 3D model files for every successful build").option("--profile", "Log per-circuit circuit.json generation time during build").option("--autorouter-debug", "Log autorouting
|
|
135276
|
+
program2.command("build").description("Run tscircuit eval and output circuit json").argument("[file]", "Path to the entry file").option("--ci", "Run install and optional prebuild/build commands (or default CI build)").option("--ignore-errors", "Do not exit with code 1 on errors").option("--ignore-warnings", "Do not log warnings").option("--ignore-netlist-drc", "Ignore netlist DRC errors/warnings").option("--ignore-pin-specification-drc", "Ignore pin-specification DRC errors/warnings").option("--ignore-placement-drc", "Ignore placement DRC errors/warnings").option("--ignore-routing-drc", "Ignore routing DRC errors/warnings").option("--ignore-config", "Ignore options from tscircuit.config.json").option("--disable-pcb", "Disable PCB outputs").option("--routing-disabled", "Disable routing during circuit generation").option("--disable-parts-engine", "Disable the parts engine").option("--site", "Generate a static site in the dist directory").option("--transpile", "Transpile the entry file to JavaScript").option("--preview-images", "Generate preview images in the dist directory").option("--all-images", "Generate preview images for every successful build output").option("--pngs", "Generate PNG outputs during build generation").option("--pcb-png", "Generate PCB PNG outputs during build generation").option("--schematic-png", "Generate schematic PNG outputs during build generation").option("--svgs", "Generate SVG outputs during build generation").option("--pcb-svgs", "Generate PCB SVG outputs during build generation").option("--schematic-svgs", "Generate schematic SVG outputs during build generation").option("--simulation-svgs", "Generate simulation graph SVG outputs during build generation").option("--simulation-schematic-svgs", "Generate schematic simulation SVG outputs during build generation").option("--3d-png", "Generate 3D PNG outputs during build generation").option("--3d", "Generate 3D PNG outputs during build generation").option("--pcb-only", "Generate only PCB SVG outputs during build generation").option("--schematic-only", "Generate only schematic SVG outputs during build generation").option("--kicad-project", "Generate KiCad project directories for each successful build output").option("--kicad-project-zip", "Generate a zipped KiCad project for each successful build output").option("--kicad-library", "Generate KiCad library in dist/kicad-library").option("--kicad-library-name <name>", "Specify the name of the KiCad library").option("--preview-gltf", "Generate a GLTF file from the preview entrypoint").option("--show-courtyards", "Show courtyard outlines in PCB SVG outputs").option("--glbs", "Generate GLB 3D model files for every successful build").option("--step", "Generate STEP 3D model files for every successful build").option("--profile", "Log per-circuit circuit.json generation time during build").option("--autorouter-debug", "Log autorouting phases and write unrouted/per-phase PNG artifacts").option("--autorouter-timeout <duration>", 'Abort an autorouting phase after a duration, e.g. "120s" or "2m"').option("--autorouter-debug-dir <path>", "Directory for autorouting debug artifacts (default: dist/autorouter-debug)").option("--autorouter-dump-srj [mode]", 'Dump SimpleRouteJson inputs/outputs: "all", "failed", or "phase:<index>" (default: failed)').option("--kicad-pcm", "Generate KiCad PCM (Plugin and Content Manager) assets in dist/pcm").option("--use-cdn-javascript", "Use CDN-hosted JavaScript instead of bundled standalone file for --site").option("--concurrency <number>", "Number of files to build in parallel (default: 1)", "1").option("--inject-props <json>", "Inject JSON props into the built file's default export").option("--inject-props-file <path>", "Inject JSON props from a file into the built file's default export").action(async (file, options) => {
|
|
135254
135277
|
try {
|
|
135255
135278
|
const transpileExplicitlyRequested = options?.transpile === true;
|
|
135256
135279
|
const resolvedRoot = path44.resolve(process.cwd());
|
|
@@ -284937,7 +284960,7 @@ var checkTraceLength = async (pinOrNetRef, file, options = {}) => {
|
|
|
284937
284960
|
return analysis.toString();
|
|
284938
284961
|
};
|
|
284939
284962
|
var registerCheckTraceLength = (program2) => {
|
|
284940
|
-
program2.commands.find((c3) => c3.name() === "check").command("trace-length").description("Analyze trace length for a pin or net").argument("<pinOrNetRef>", "Pin or net target to analyze").argument("[file]", "Path to the entry file").option("--autorouter-debug", "Log autorouting
|
|
284963
|
+
program2.commands.find((c3) => c3.name() === "check").command("trace-length").description("Analyze trace length for a pin or net").argument("<pinOrNetRef>", "Pin or net target to analyze").argument("[file]", "Path to the entry file").option("--autorouter-debug", "Log autorouting phases and write unrouted/per-phase PNG artifacts").option("--autorouter-timeout <duration>", 'Abort an autorouting phase after a duration, e.g. "120s" or "2m"').option("--autorouter-debug-dir <path>", "Directory for autorouting debug artifacts (default: dist/autorouter-debug)").option("--autorouter-dump-srj [mode]", 'Dump SimpleRouteJson inputs/outputs: "all", "failed", or "phase:<index>" (default: failed)').action(async (pinOrNetRef, file, options) => {
|
|
284941
284964
|
try {
|
|
284942
284965
|
const output = await checkTraceLength(pinOrNetRef, file, options);
|
|
284943
284966
|
console.log(output);
|
|
@@ -3300,13 +3300,18 @@ class AutorouterDiagnostics {
|
|
|
3300
3300
|
return filePath;
|
|
3301
3301
|
}
|
|
3302
3302
|
writePngSnapshot(fileName, circuitJson) {
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3303
|
+
try {
|
|
3304
|
+
const pcbSvg = convertCircuitJsonToPcbSvg(circuitJson);
|
|
3305
|
+
const png = convertSvgToPngBuffer(pcbSvg);
|
|
3306
|
+
const debugDir = path2.resolve(this.options.debugDir ?? DEFAULT_DEBUG_DIR);
|
|
3307
|
+
fs2.mkdirSync(debugDir, { recursive: true });
|
|
3308
|
+
const filePath = path2.join(debugDir, fileName);
|
|
3309
|
+
fs2.writeFileSync(filePath, png);
|
|
3310
|
+
this.logArtifact(filePath);
|
|
3311
|
+
} catch (error) {
|
|
3312
|
+
const serializedError = this.serializeError(error instanceof Error ? error : String(error));
|
|
3313
|
+
this.log(kleur_default.yellow(`Could not write autorouter debug image ${fileName}: ${serializedError.message}`));
|
|
3314
|
+
}
|
|
3310
3315
|
}
|
|
3311
3316
|
logArtifact(filePath) {
|
|
3312
3317
|
this.log(`Wrote debug artifact: ${path2.relative(process.cwd(), filePath)}`);
|
|
@@ -3319,7 +3324,8 @@ class AutorouterDiagnostics {
|
|
|
3319
3324
|
if (id)
|
|
3320
3325
|
elementIndexById.set(id, index);
|
|
3321
3326
|
}
|
|
3322
|
-
for (const
|
|
3327
|
+
for (const autorouterTrace of this.completedPhaseTraces) {
|
|
3328
|
+
const trace = this.normalizeTraceForPcbSnapshot(autorouterTrace);
|
|
3323
3329
|
if (!trace || typeof trace !== "object")
|
|
3324
3330
|
continue;
|
|
3325
3331
|
const id = this.getCircuitElementId(trace);
|
|
@@ -3334,6 +3340,23 @@ class AutorouterDiagnostics {
|
|
|
3334
3340
|
}
|
|
3335
3341
|
return circuitJson;
|
|
3336
3342
|
}
|
|
3343
|
+
normalizeTraceForPcbSnapshot(trace) {
|
|
3344
|
+
return {
|
|
3345
|
+
...trace,
|
|
3346
|
+
route: trace.route.map((point) => {
|
|
3347
|
+
if (point.route_type !== "through_obstacle")
|
|
3348
|
+
return point;
|
|
3349
|
+
return {
|
|
3350
|
+
route_type: "through_pad",
|
|
3351
|
+
start: point.start,
|
|
3352
|
+
end: point.end,
|
|
3353
|
+
start_layer: point.from_layer,
|
|
3354
|
+
end_layer: point.to_layer,
|
|
3355
|
+
width: point.width
|
|
3356
|
+
};
|
|
3357
|
+
})
|
|
3358
|
+
};
|
|
3359
|
+
}
|
|
3337
3360
|
getCircuitElementId(element) {
|
|
3338
3361
|
const idEntry = Object.entries(element).find(([key, value]) => key === `${element.type}_id` && typeof value === "string");
|
|
3339
3362
|
const id = idEntry?.[1];
|