@tscircuit/cli 0.1.1052 → 0.1.1054

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/dist/cli/main.js CHANGED
@@ -68605,18 +68605,18 @@ globstar while`, file, fr, pattern, pr, swallowee);
68605
68605
  abs = abs.replace(/\\/g, "/");
68606
68606
  return abs;
68607
68607
  }
68608
- function isIgnored(self2, path46) {
68608
+ function isIgnored(self2, path47) {
68609
68609
  if (!self2.ignore.length)
68610
68610
  return false;
68611
68611
  return self2.ignore.some(function(item) {
68612
- return item.matcher.match(path46) || !!(item.gmatcher && item.gmatcher.match(path46));
68612
+ return item.matcher.match(path47) || !!(item.gmatcher && item.gmatcher.match(path47));
68613
68613
  });
68614
68614
  }
68615
- function childrenIgnored(self2, path46) {
68615
+ function childrenIgnored(self2, path47) {
68616
68616
  if (!self2.ignore.length)
68617
68617
  return false;
68618
68618
  return self2.ignore.some(function(item) {
68619
- return !!(item.gmatcher && item.gmatcher.match(path46));
68619
+ return !!(item.gmatcher && item.gmatcher.match(path47));
68620
68620
  });
68621
68621
  }
68622
68622
  }
@@ -71664,7 +71664,7 @@ var registerStaticAssetLoaders = () => {
71664
71664
  // cli/main.ts
71665
71665
  var import_perfect_cli = __toESM2(require_dist2(), 1);
71666
71666
  // package.json
71667
- var version = "0.1.1051";
71667
+ var version = "0.1.1053";
71668
71668
  var package_default = {
71669
71669
  name: "@tscircuit/cli",
71670
71670
  version,
@@ -81871,42 +81871,27 @@ var exitBuild = (code, reason) => {
81871
81871
  // cli/build/worker-pool.ts
81872
81872
  import fs36 from "node:fs";
81873
81873
  import path38 from "node:path";
81874
+
81875
+ // lib/shared/thread-worker-pool.ts
81874
81876
  import { Worker } from "node:worker_threads";
81875
- var getWorkerEntrypointPath = () => {
81876
- const tsPath = path38.join(import.meta.dir, "build-worker-entrypoint.ts");
81877
- if (fs36.existsSync(tsPath)) {
81878
- return tsPath;
81879
- }
81880
- const jsBundledPath = path38.join(import.meta.dir, "build", "build-worker-entrypoint.js");
81881
- if (fs36.existsSync(jsBundledPath)) {
81882
- return jsBundledPath;
81883
- }
81884
- return path38.join(import.meta.dir, "build-worker-entrypoint.js");
81885
- };
81886
81877
 
81887
- class WorkerPool {
81878
+ class ThreadWorkerPool {
81888
81879
  workers = [];
81889
81880
  jobQueue = [];
81890
81881
  concurrency;
81891
- onLog;
81892
- workerEntrypointPath;
81882
+ options;
81893
81883
  initialized = false;
81894
81884
  stopped = false;
81895
81885
  stopReason = null;
81896
- stopOnFatal = false;
81897
- cancellationError = null;
81898
81886
  constructor(options) {
81887
+ this.options = options;
81899
81888
  this.concurrency = options.concurrency;
81900
- this.onLog = options.onLog;
81901
- this.workerEntrypointPath = getWorkerEntrypointPath();
81902
- this.stopOnFatal = options.stopOnFatal ?? false;
81903
- this.cancellationError = options.cancellationError ?? null;
81904
81889
  }
81905
81890
  async initWorkers() {
81906
81891
  if (this.initialized)
81907
81892
  return;
81908
81893
  for (let i = 0;i < this.concurrency; i++) {
81909
- const worker = new Worker(this.workerEntrypointPath);
81894
+ const worker = new Worker(this.options.workerEntrypointPath);
81910
81895
  const threadWorker = {
81911
81896
  worker,
81912
81897
  busy: false,
@@ -81920,38 +81905,24 @@ class WorkerPool {
81920
81905
  }
81921
81906
  setupWorkerMessageHandling(threadWorker) {
81922
81907
  threadWorker.worker.on("message", (message) => {
81923
- if (message.message_type === "worker_log") {
81924
- const logMsg = message;
81925
- if (this.onLog) {
81926
- this.onLog(logMsg.log_lines);
81927
- }
81928
- } else if (message.message_type === "build_completed") {
81929
- const completedMsg = message;
81930
- const job = threadWorker.currentJob;
81931
- if (job) {
81932
- if (this.stopOnFatal && completedMsg.isFatalError && this.cancellationError) {
81933
- this.stop(this.cancellationError);
81934
- }
81935
- job.resolve({
81936
- filePath: completedMsg.file_path,
81937
- outputPath: completedMsg.output_path,
81938
- glbOutputPath: completedMsg.glb_output_path,
81939
- previewOutputDir: completedMsg.preview_output_dir,
81940
- glbOk: completedMsg.glb_ok,
81941
- glbError: completedMsg.glb_error,
81942
- previewOk: completedMsg.preview_ok,
81943
- previewError: completedMsg.preview_error,
81944
- ok: completedMsg.ok,
81945
- isFatalError: completedMsg.isFatalError,
81946
- errors: completedMsg.errors,
81947
- warnings: completedMsg.warnings,
81948
- durationMs: completedMsg.durationMs
81949
- });
81950
- threadWorker.currentJob = null;
81951
- threadWorker.busy = false;
81952
- this.processQueue();
81953
- }
81908
+ if (this.options.isLogMessage(message)) {
81909
+ this.options.onLog?.(this.options.getLogLines(message));
81910
+ return;
81911
+ }
81912
+ if (!this.options.isCompletionMessage(message)) {
81913
+ return;
81954
81914
  }
81915
+ const job = threadWorker.currentJob;
81916
+ if (!job) {
81917
+ return;
81918
+ }
81919
+ if (this.options.shouldStopOnMessage?.(message) && this.options.cancellationError) {
81920
+ this.stop(this.options.cancellationError);
81921
+ }
81922
+ job.resolve(this.options.getResult(message));
81923
+ threadWorker.currentJob = null;
81924
+ threadWorker.busy = false;
81925
+ this.processQueue();
81955
81926
  });
81956
81927
  }
81957
81928
  setupWorkerErrorHandling(threadWorker) {
@@ -81961,11 +81932,9 @@ class WorkerPool {
81961
81932
  threadWorker.currentJob = null;
81962
81933
  threadWorker.busy = false;
81963
81934
  }
81964
- if (this.onLog) {
81965
- this.onLog([
81966
- `Worker error: ${error instanceof Error ? error.message : String(error)}`
81967
- ]);
81968
- }
81935
+ this.options.onLog?.([
81936
+ `Worker error: ${error instanceof Error ? error.message : String(error)}`
81937
+ ]);
81969
81938
  });
81970
81939
  threadWorker.worker.on("exit", (code) => {
81971
81940
  if (code !== 0 && threadWorker.currentJob) {
@@ -81976,28 +81945,20 @@ class WorkerPool {
81976
81945
  });
81977
81946
  }
81978
81947
  processQueue() {
81979
- if (this.stopped)
81948
+ if (this.stopped || this.jobQueue.length === 0) {
81980
81949
  return;
81981
- if (this.jobQueue.length === 0)
81982
- return;
81983
- const availableWorker = this.workers.find((w) => !w.busy);
81984
- if (!availableWorker)
81950
+ }
81951
+ const availableWorker = this.workers.find((worker) => !worker.busy);
81952
+ if (!availableWorker) {
81985
81953
  return;
81986
- const job = this.jobQueue.shift();
81987
- if (!job)
81954
+ }
81955
+ const queuedJob = this.jobQueue.shift();
81956
+ if (!queuedJob) {
81988
81957
  return;
81958
+ }
81989
81959
  availableWorker.busy = true;
81990
- availableWorker.currentJob = job;
81991
- const message = {
81992
- message_type: "build_file",
81993
- file_path: job.filePath,
81994
- output_path: job.outputPath,
81995
- glb_output_path: job.glbOutputPath,
81996
- preview_output_dir: job.previewOutputDir,
81997
- project_dir: job.projectDir,
81998
- options: job.options
81999
- };
82000
- availableWorker.worker.postMessage(message);
81960
+ availableWorker.currentJob = queuedJob;
81961
+ availableWorker.worker.postMessage(this.options.createMessage(queuedJob.job));
82001
81962
  }
82002
81963
  async queueJob(job) {
82003
81964
  if (this.stopped) {
@@ -82005,12 +81966,7 @@ class WorkerPool {
82005
81966
  }
82006
81967
  await this.initWorkers();
82007
81968
  return new Promise((resolve4, reject) => {
82008
- const queuedJob = {
82009
- ...job,
82010
- resolve: resolve4,
82011
- reject
82012
- };
82013
- this.jobQueue.push(queuedJob);
81969
+ this.jobQueue.push({ job, resolve: resolve4, reject });
82014
81970
  this.processQueue();
82015
81971
  });
82016
81972
  }
@@ -82024,35 +81980,70 @@ class WorkerPool {
82024
81980
  }
82025
81981
  this.jobQueue = [];
82026
81982
  }
82027
- async runUntilComplete() {
82028
- return new Promise((resolve4) => {
82029
- const checkComplete = () => {
82030
- const allIdle = this.workers.every((w) => !w.busy);
82031
- const queueEmpty = this.jobQueue.length === 0;
82032
- if (allIdle && queueEmpty) {
82033
- resolve4();
82034
- } else {
82035
- setTimeout(checkComplete, 50);
82036
- }
82037
- };
82038
- checkComplete();
82039
- });
82040
- }
82041
81983
  async terminate() {
82042
- const terminatePromises = this.workers.map((w) => w.worker.terminate());
82043
- await Promise.all(terminatePromises);
81984
+ await Promise.all(this.workers.map((worker) => worker.worker.terminate()));
82044
81985
  this.workers = [];
82045
81986
  this.initialized = false;
82046
81987
  }
82047
81988
  }
81989
+
81990
+ // cli/build/worker-pool.ts
81991
+ var getWorkerEntrypointPath = () => {
81992
+ const tsPath = path38.join(import.meta.dir, "build.worker.ts");
81993
+ if (fs36.existsSync(tsPath)) {
81994
+ return tsPath;
81995
+ }
81996
+ const jsBundledPath = path38.join(import.meta.dir, "build", "build.worker.js");
81997
+ if (fs36.existsSync(jsBundledPath)) {
81998
+ return jsBundledPath;
81999
+ }
82000
+ return path38.join(import.meta.dir, "build.worker.js");
82001
+ };
82048
82002
  async function buildFilesWithWorkerPool(options) {
82049
82003
  const cancellationError = new Error("Build cancelled due fatal error");
82050
82004
  const poolConcurrency = Math.max(1, Math.min(options.concurrency, options.files.length));
82051
- const pool = new WorkerPool({
82005
+ const pool = new ThreadWorkerPool({
82052
82006
  concurrency: poolConcurrency,
82053
- onLog: options.onLog,
82054
- stopOnFatal: options.stopOnFatal,
82055
- cancellationError
82007
+ workerEntrypointPath: getWorkerEntrypointPath(),
82008
+ createMessage: (job) => ({
82009
+ message_type: "build_file",
82010
+ file_path: job.filePath,
82011
+ output_path: job.outputPath,
82012
+ glb_output_path: job.glbOutputPath,
82013
+ preview_output_dir: job.previewOutputDir,
82014
+ project_dir: job.projectDir,
82015
+ options: job.options
82016
+ }),
82017
+ isLogMessage: (message) => message.message_type === "worker_log",
82018
+ getLogLines: (message) => message.message_type === "worker_log" ? message.log_lines : [],
82019
+ isCompletionMessage: (message) => message.message_type === "build_completed",
82020
+ getResult: (message) => {
82021
+ const completedMessage = message;
82022
+ return {
82023
+ filePath: completedMessage.file_path,
82024
+ outputPath: completedMessage.output_path,
82025
+ glbOutputPath: completedMessage.glb_output_path,
82026
+ previewOutputDir: completedMessage.preview_output_dir,
82027
+ glbOk: completedMessage.glb_ok,
82028
+ glbError: completedMessage.glb_error,
82029
+ previewOk: completedMessage.preview_ok,
82030
+ previewError: completedMessage.preview_error,
82031
+ ok: completedMessage.ok,
82032
+ hasErrors: completedMessage.hasErrors,
82033
+ isFatalError: completedMessage.isFatalError,
82034
+ errors: completedMessage.errors,
82035
+ warnings: completedMessage.warnings,
82036
+ durationMs: completedMessage.durationMs
82037
+ };
82038
+ },
82039
+ shouldStopOnMessage: (message) => {
82040
+ if (!options.stopOnFatal || message.message_type !== "build_completed") {
82041
+ return false;
82042
+ }
82043
+ return Boolean(message.isFatalError);
82044
+ },
82045
+ cancellationError,
82046
+ onLog: options.onLog
82056
82047
  });
82057
82048
  const results = [];
82058
82049
  const promises = [];
@@ -82563,16 +82554,293 @@ var registerBuild = (program2) => {
82563
82554
  });
82564
82555
  };
82565
82556
 
82557
+ // node_modules/circuit-json-to-readable-netlist/dist/index.js
82558
+ import { su as su3 } from "@tscircuit/circuit-json-util";
82559
+ import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map";
82560
+ import { su as su2 } from "@tscircuit/circuit-json-util";
82561
+ import { su } from "@tscircuit/circuit-json-util";
82562
+ var wordQualityScore = {
82563
+ MISO: 1.2,
82564
+ MOSI: 1.2,
82565
+ SCLK: 1.2,
82566
+ SDA: 1.2,
82567
+ SCL: 1.2,
82568
+ RX: 1.15,
82569
+ TX: 1.15,
82570
+ GPIO: 1.1,
82571
+ cathode: 0.5,
82572
+ anode: 0.5,
82573
+ GND: 1.1,
82574
+ VDD: 1.1,
82575
+ AGND: 1.1,
82576
+ V5: 1.1,
82577
+ V3: 1.1,
82578
+ V1: 1.1,
82579
+ neg: 0.9,
82580
+ pos: 0.9,
82581
+ pin: 0.5,
82582
+ left: 0.3,
82583
+ right: 0.3
82584
+ };
82585
+ var wordQualityScoreEntries = Object.entries(wordQualityScore).sort((a, b) => b[1] - a[1]);
82586
+ var scorePhrase = (phrase) => {
82587
+ if (phrase.match(/\d+/)) {
82588
+ return 0.5;
82589
+ }
82590
+ for (const [word, score] of wordQualityScoreEntries) {
82591
+ if (phrase.includes(word)) {
82592
+ return score;
82593
+ }
82594
+ }
82595
+ return 1;
82596
+ };
82597
+ var getReadableNameForPin = ({
82598
+ circuitJson,
82599
+ source_port_id
82600
+ }) => {
82601
+ const source_ports = su(circuitJson).source_port.list();
82602
+ const source_components = su(circuitJson).source_component.list();
82603
+ const port = source_ports.find((p) => p.source_port_id === source_port_id);
82604
+ if (!port)
82605
+ return "";
82606
+ const component = source_components.find((c) => c.source_component_id === port.source_component_id);
82607
+ if (!component)
82608
+ return "";
82609
+ const isPositive = port.port_hints?.some((hint) => ["anode", "pos", "positive"].includes(hint.toLowerCase()));
82610
+ const isNegative = port.port_hints?.some((hint) => ["cathode", "neg", "negative"].includes(hint.toLowerCase()));
82611
+ const mainPinName = port.name ? port.name : `Pin${port.pin_number}`;
82612
+ const additionalPinLabels = [];
82613
+ if (isPositive && component.ftype !== "simple_resistor") {
82614
+ additionalPinLabels.push("+");
82615
+ } else if (isNegative && component.ftype !== "simple_resistor") {
82616
+ additionalPinLabels.push("-");
82617
+ }
82618
+ for (const port_hint of port.port_hints ?? []) {
82619
+ if (port_hint === mainPinName)
82620
+ continue;
82621
+ const score = scorePhrase(port_hint);
82622
+ if (score > 1) {
82623
+ additionalPinLabels.push(port_hint);
82624
+ }
82625
+ }
82626
+ const displayValue = component.display_value ? ` (${component.display_value})` : "";
82627
+ return `${component.name} ${mainPinName}${additionalPinLabels.length > 0 ? ` (${additionalPinLabels.join(",")})` : ""}${displayValue}`;
82628
+ };
82629
+ var scoreComponentOrder = (component) => {
82630
+ if (!("ftype" in component))
82631
+ return 0;
82632
+ if (component.ftype === "simple_resistor")
82633
+ return 0;
82634
+ if (component.ftype === "simple_capacitor")
82635
+ return 1;
82636
+ return 2;
82637
+ };
82638
+ var generateNetName = ({
82639
+ circuitJson,
82640
+ connectedIds
82641
+ }) => {
82642
+ const all_source_components = su2(circuitJson).source_component.list();
82643
+ const sourceComponentIdToScore = /* @__PURE__ */ new Map;
82644
+ for (const component of all_source_components) {
82645
+ sourceComponentIdToScore.set(component.source_component_id, scoreComponentOrder(component));
82646
+ }
82647
+ all_source_components.sort((a, b) => sourceComponentIdToScore.get(b.source_component_id) - sourceComponentIdToScore.get(a.source_component_id));
82648
+ const all_source_ports = su2(circuitJson).source_port.list().sort((a, b) => sourceComponentIdToScore.get(b.source_component_id) - sourceComponentIdToScore.get(a.source_component_id));
82649
+ const all_source_nets = su2(circuitJson).source_net.list();
82650
+ const all_source_traces = su2(circuitJson).source_trace.list();
82651
+ const ports = all_source_ports.filter((p) => connectedIds.includes(p.source_port_id));
82652
+ const nets = all_source_nets.filter((n) => connectedIds.includes(n.source_net_id));
82653
+ const traces = all_source_traces.filter((t) => connectedIds.includes(t.source_trace_id));
82654
+ const possibleNames = ports.flatMap((p) => Array.from(/* @__PURE__ */ new Set([...p.name ? [p.name] : [], ...p.port_hints ?? []]))).concat(nets.map((n) => n.name));
82655
+ const phrases = possibleNames.map((name) => ({
82656
+ name,
82657
+ score: scorePhrase(name)
82658
+ }));
82659
+ const bestPortName = phrases.sort((a, b) => b.score - a.score)[0].name;
82660
+ const bestPort = ports.find((p) => p.name === bestPortName || p.port_hints?.includes(bestPortName));
82661
+ const componentWithBestPort = all_source_components.find((c) => c.source_component_id === bestPort?.source_component_id);
82662
+ return [componentWithBestPort?.name, bestPortName].filter(Boolean).join("_");
82663
+ };
82664
+ var convertCircuitJsonToReadableNetlist = (circuitJson) => {
82665
+ const connectivityMap = getFullConnectivityMapFromCircuitJson(circuitJson.filter((e) => e.type.startsWith("source_")));
82666
+ const netMap = connectivityMap.netMap;
82667
+ const source_ports = su3(circuitJson).source_port.list();
82668
+ const source_components = su3(circuitJson).source_component.list();
82669
+ const source_nets = su3(circuitJson).source_net.list();
82670
+ const source_traces = su3(circuitJson).source_trace.list();
82671
+ const netlist = [];
82672
+ netlist.push("COMPONENTS:");
82673
+ for (const component of source_components) {
82674
+ let componentDescription = "";
82675
+ const cadComponent = su3(circuitJson).cad_component.getWhere({
82676
+ source_component_id: component.source_component_id
82677
+ });
82678
+ const footprint = cadComponent?.footprinter_string;
82679
+ if (component.ftype === "simple_resistor") {
82680
+ componentDescription = `${component.display_resistance}${footprint ? ` ${footprint}` : ""} resistor`;
82681
+ } else if (component.ftype === "simple_capacitor") {
82682
+ componentDescription = `${component.display_capacitance}${footprint ? ` ${footprint}` : ""} capacitor`;
82683
+ } else if (component.ftype === "simple_chip") {
82684
+ const manufacturerPartNumber = component.manufacturer_part_number;
82685
+ componentDescription = [manufacturerPartNumber, footprint].filter(Boolean).join(", ");
82686
+ } else {
82687
+ componentDescription = [component.name, component.type].filter(Boolean).join(", ");
82688
+ }
82689
+ netlist.push(` - ${component.name}: ${componentDescription}`);
82690
+ }
82691
+ netlist.push("");
82692
+ for (const [netId, connectedIds] of Object.entries(netMap)) {
82693
+ const net = source_nets.find((n) => connectedIds.includes(n.source_net_id));
82694
+ let netName = net?.name;
82695
+ if (!netName) {
82696
+ netName = generateNetName({ circuitJson, connectedIds });
82697
+ }
82698
+ const connectedPortCount = connectedIds.filter((id) => id.startsWith("source_port")).length;
82699
+ if (connectedPortCount <= 1)
82700
+ continue;
82701
+ netlist.push(`NET: ${netName}`);
82702
+ for (const id of connectedIds) {
82703
+ const pinName = getReadableNameForPin({
82704
+ circuitJson,
82705
+ source_port_id: id
82706
+ });
82707
+ if (pinName) {
82708
+ netlist.push(` - ${pinName}`);
82709
+ }
82710
+ }
82711
+ netlist.push("");
82712
+ }
82713
+ let hasEmptyNets = false;
82714
+ for (const [netId, connectedIds] of Object.entries(netMap)) {
82715
+ const connectedPortCount = connectedIds.filter((id) => id.startsWith("source_port")).length;
82716
+ if (connectedPortCount === 1) {
82717
+ if (!hasEmptyNets) {
82718
+ netlist.push("");
82719
+ netlist.push("EMPTY NET PINS:");
82720
+ hasEmptyNets = true;
82721
+ }
82722
+ const source_port_id = netMap[netId].find((id) => id.startsWith("source_port"));
82723
+ const pinName = getReadableNameForPin({
82724
+ circuitJson,
82725
+ source_port_id
82726
+ });
82727
+ if (pinName) {
82728
+ netlist.push(` - ${pinName}`);
82729
+ }
82730
+ }
82731
+ }
82732
+ const portIdToNetNames = {};
82733
+ for (const [netId, connectedIds] of Object.entries(netMap)) {
82734
+ const portIds = connectedIds.filter((id) => id.startsWith("source_port"));
82735
+ if (portIds.length === 0)
82736
+ continue;
82737
+ const net = source_nets.find((n) => connectedIds.includes(n.source_net_id));
82738
+ let netName = net?.name;
82739
+ if (!netName) {
82740
+ netName = generateNetName({ circuitJson, connectedIds });
82741
+ }
82742
+ for (const portId of portIds) {
82743
+ if (!portIdToNetNames[portId])
82744
+ portIdToNetNames[portId] = [];
82745
+ portIdToNetNames[portId].push(netName);
82746
+ }
82747
+ }
82748
+ if (source_components.length > 0) {
82749
+ netlist.push("");
82750
+ netlist.push("COMPONENT_PINS:");
82751
+ for (const component of source_components) {
82752
+ const cadComponent = su3(circuitJson).cad_component.getWhere({
82753
+ source_component_id: component.source_component_id
82754
+ });
82755
+ const footprint = cadComponent?.footprinter_string;
82756
+ let header = component.name;
82757
+ if (component.ftype === "simple_resistor") {
82758
+ header = `${component.name} (${component.display_resistance} ${footprint})`;
82759
+ } else if (component.ftype === "simple_capacitor") {
82760
+ header = `${component.name} (${component.display_capacitance} ${footprint})`;
82761
+ } else if (component.manufacturer_part_number) {
82762
+ header = `${component.name} (${component.manufacturer_part_number})`;
82763
+ }
82764
+ netlist.push(header);
82765
+ const ports = source_ports.filter((p) => p.source_component_id === component.source_component_id).sort((a, b) => (a.pin_number ?? 0) - (b.pin_number ?? 0));
82766
+ for (const port of ports) {
82767
+ const mainPin = port.pin_number !== undefined ? `pin${port.pin_number}` : port.name;
82768
+ const aliases = [];
82769
+ if (port.name && port.name !== mainPin)
82770
+ aliases.push(port.name);
82771
+ for (const hint of port.port_hints ?? []) {
82772
+ if (hint === String(port.pin_number))
82773
+ continue;
82774
+ if (hint !== mainPin && hint !== port.name)
82775
+ aliases.push(hint);
82776
+ }
82777
+ const aliasPart = aliases.length > 0 ? `(${Array.from(new Set(aliases)).join(", ")})` : "";
82778
+ const nets = portIdToNetNames[port.source_port_id] ?? [];
82779
+ const netsPart = nets.length > 0 ? `NETS(${nets.join(", ")})` : "NOT_CONNECTED";
82780
+ netlist.push(`- ${mainPin}${aliasPart}: ${netsPart}`);
82781
+ }
82782
+ netlist.push("");
82783
+ }
82784
+ }
82785
+ return netlist.join(`
82786
+ `);
82787
+ };
82788
+
82566
82789
  // cli/check/netlist/register.ts
82790
+ import path40 from "node:path";
82791
+ var resolveInputFilePath = async (file) => {
82792
+ if (file) {
82793
+ return path40.isAbsolute(file) ? file : path40.resolve(process.cwd(), file);
82794
+ }
82795
+ const entrypoint = await getEntrypoint({
82796
+ projectDir: process.cwd()
82797
+ });
82798
+ if (!entrypoint) {
82799
+ throw new Error("No input file provided and no entrypoint found");
82800
+ }
82801
+ return entrypoint;
82802
+ };
82803
+ var checkNetlist = async (file) => {
82804
+ const resolvedInputFilePath = await resolveInputFilePath(file);
82805
+ const completePlatformConfig = getCompletePlatformConfig({
82806
+ routingDrcChecksDisabled: true,
82807
+ placementDrcChecksDisabled: true
82808
+ });
82809
+ const { circuitJson } = await generateCircuitJson({
82810
+ filePath: resolvedInputFilePath,
82811
+ platformConfig: completePlatformConfig
82812
+ });
82813
+ const typedCircuitJson = circuitJson;
82814
+ const diagnostics = analyzeCircuitJson(typedCircuitJson);
82815
+ const readableNetlist = convertCircuitJsonToReadableNetlist(typedCircuitJson);
82816
+ const diagnosticsLines = [
82817
+ `Errors: ${diagnostics.errors.length}`,
82818
+ `Warnings: ${diagnostics.warnings.length}`
82819
+ ];
82820
+ if (diagnostics.errors.length > 0) {
82821
+ diagnosticsLines.push(...diagnostics.errors.map((err) => `- ${err.type}: ${err.message ?? ""}`));
82822
+ }
82823
+ return `${diagnosticsLines.join(`
82824
+ `)}
82825
+
82826
+ Readable Netlist:
82827
+ ${readableNetlist}`;
82828
+ };
82567
82829
  var registerCheckNetlist = (program2) => {
82568
- program2.commands.find((c) => c.name() === "check").command("netlist").description("Partially build and validate the netlist").argument("[refdeses]", "Optional refdeses to scope the check").action(() => {
82569
- throw new Error("Not implemented");
82830
+ program2.commands.find((c) => c.name() === "check").command("netlist").description("Partially build and validate the netlist").argument("[file]", "Path to the entry file").action(async (file) => {
82831
+ try {
82832
+ const output = await checkNetlist(file);
82833
+ console.log(output);
82834
+ } catch (error) {
82835
+ console.error(error instanceof Error ? error.message : String(error));
82836
+ process.exit(1);
82837
+ }
82570
82838
  });
82571
82839
  };
82572
82840
 
82573
82841
  // cli/check/placement/register.ts
82574
82842
  import fs38 from "node:fs";
82575
- import path40 from "node:path";
82843
+ import path41 from "node:path";
82576
82844
 
82577
82845
  // node_modules/@tscircuit/circuit-json-placement-analysis/dist/index.js
82578
82846
  var CENTER_ANCHOR = "center";
@@ -82887,9 +83155,9 @@ var isPrebuiltCircuitJsonFile = (filePath) => {
82887
83155
  const normalizedInputPath = filePath.toLowerCase().replaceAll("\\", "/");
82888
83156
  return normalizedInputPath.endsWith(".circuit.json") || normalizedInputPath.endsWith("/circuit.json");
82889
83157
  };
82890
- var resolveInputFilePath = async (file) => {
83158
+ var resolveInputFilePath2 = async (file) => {
82891
83159
  if (file) {
82892
- return path40.isAbsolute(file) ? file : path40.resolve(process.cwd(), file);
83160
+ return path41.isAbsolute(file) ? file : path41.resolve(process.cwd(), file);
82893
83161
  }
82894
83162
  const entrypoint = await getEntrypoint({
82895
83163
  projectDir: process.cwd()
@@ -82915,7 +83183,7 @@ var getCircuitJsonForPlacementCheck = async (filePath) => {
82915
83183
  return circuitJson;
82916
83184
  };
82917
83185
  var checkPlacement = async (file, refdes) => {
82918
- const resolvedInputFilePath = await resolveInputFilePath(file);
83186
+ const resolvedInputFilePath = await resolveInputFilePath2(file);
82919
83187
  const circuitJson = await getCircuitJsonForPlacementCheck(resolvedInputFilePath);
82920
83188
  const analysis = refdes ? analyzeComponentPlacement(circuitJson, refdes) : analyzeAllPlacements(circuitJson);
82921
83189
  return analysis.getString();
@@ -82946,25 +83214,25 @@ var registerCheckRouting = (program2) => {
82946
83214
 
82947
83215
  // cli/clone/register.ts
82948
83216
  import * as fs41 from "node:fs";
82949
- import * as path43 from "node:path";
83217
+ import * as path44 from "node:path";
82950
83218
 
82951
83219
  // cli/clone/clone-bug-report.ts
82952
83220
  var import_jszip2 = __toESM2(require_lib4(), 1);
82953
83221
  var import_prompts4 = __toESM2(require_prompts3(), 1);
82954
83222
  import * as fs40 from "node:fs";
82955
- import * as path42 from "node:path";
83223
+ import * as path43 from "node:path";
82956
83224
 
82957
83225
  // cli/clone/handle-existing-directory.ts
82958
83226
  var import_prompts3 = __toESM2(require_prompts3(), 1);
82959
83227
  import * as fs39 from "node:fs";
82960
- import * as path41 from "node:path";
83228
+ import * as path42 from "node:path";
82961
83229
  var handleExistingDirectory = async (dirPath) => {
82962
83230
  if (!fs39.existsSync(dirPath))
82963
83231
  return;
82964
83232
  const response = await import_prompts3.default({
82965
83233
  type: "select",
82966
83234
  name: "action",
82967
- message: `Directory "${path41.basename(dirPath)}" already exists. What would you like to do?`,
83235
+ message: `Directory "${path42.basename(dirPath)}" already exists. What would you like to do?`,
82968
83236
  choices: [
82969
83237
  { title: "Merge files into existing directory", value: "merge" },
82970
83238
  {
@@ -83005,12 +83273,12 @@ var getCommonDirectoryPrefix = (paths) => {
83005
83273
  return commonSegments.join("/");
83006
83274
  };
83007
83275
  var sanitizeRelativePath = (relativePath) => {
83008
- const normalizedPath = path42.normalize(relativePath);
83276
+ const normalizedPath = path43.normalize(relativePath);
83009
83277
  if (!normalizedPath)
83010
83278
  return null;
83011
- if (path42.isAbsolute(normalizedPath))
83279
+ if (path43.isAbsolute(normalizedPath))
83012
83280
  return null;
83013
- const segments = normalizedPath.split(path42.sep);
83281
+ const segments = normalizedPath.split(path43.sep);
83014
83282
  if (segments.some((segment) => segment === ".." || segment === "")) {
83015
83283
  return null;
83016
83284
  }
@@ -83025,7 +83293,7 @@ var cloneBugReport = async ({
83025
83293
  console.error("Bug report ID must not be empty.");
83026
83294
  process.exit(1);
83027
83295
  }
83028
- let dirPath = path42.resolve(`bug-report-${trimmedBugReportId}`);
83296
+ let dirPath = path43.resolve(`bug-report-${trimmedBugReportId}`);
83029
83297
  await handleExistingDirectory(dirPath);
83030
83298
  const ky2 = getRegistryApiKy();
83031
83299
  let zipBuffer;
@@ -83055,25 +83323,25 @@ var cloneBugReport = async ({
83055
83323
  console.warn(`Skipping potentially unsafe path: ${fileName}`);
83056
83324
  continue;
83057
83325
  }
83058
- const fullPath = path42.join(dirPath, sanitizedRelativePath);
83059
- fs40.mkdirSync(path42.dirname(fullPath), { recursive: true });
83326
+ const fullPath = path43.join(dirPath, sanitizedRelativePath);
83327
+ fs40.mkdirSync(path43.dirname(fullPath), { recursive: true });
83060
83328
  const fileContent = await entry.async("nodebuffer");
83061
83329
  fs40.writeFileSync(fullPath, fileContent);
83062
83330
  }
83063
- const packageJsonPath = path42.join(dirPath, "package.json");
83331
+ const packageJsonPath = path43.join(dirPath, "package.json");
83064
83332
  if (fs40.existsSync(packageJsonPath)) {
83065
83333
  try {
83066
83334
  const packageJson = JSON.parse(fs40.readFileSync(packageJsonPath, "utf-8"));
83067
83335
  const packageName = packageJson?.name;
83068
83336
  if (typeof packageName === "string" && packageName.trim()) {
83069
83337
  const sanitizedName = packageName.replace(/[^a-zA-Z0-9]/g, "_");
83070
- const suggestedDirPath = path42.resolve(`${sanitizedName}_${trimmedBugReportId.slice(7)}`);
83338
+ const suggestedDirPath = path43.resolve(`${sanitizedName}_${trimmedBugReportId.slice(7)}`);
83071
83339
  if (suggestedDirPath !== dirPath) {
83072
83340
  const response = await import_prompts4.default({
83073
83341
  type: "confirm",
83074
83342
  name: "rename",
83075
83343
  initial: true,
83076
- message: `Rename the directory to "${path42.basename(suggestedDirPath)}"?`
83344
+ message: `Rename the directory to "${path43.basename(suggestedDirPath)}"?`
83077
83345
  });
83078
83346
  if (response.rename) {
83079
83347
  await handleExistingDirectory(suggestedDirPath);
@@ -83086,9 +83354,9 @@ var cloneBugReport = async ({
83086
83354
  console.warn("Unable to read package name for renaming:", error);
83087
83355
  }
83088
83356
  }
83089
- fs40.writeFileSync(path42.join(dirPath, ".npmrc"), "@tsci:registry=https://npm.tscircuit.com");
83357
+ fs40.writeFileSync(path43.join(dirPath, ".npmrc"), "@tsci:registry=https://npm.tscircuit.com");
83090
83358
  generateTsConfig(dirPath);
83091
- const relativeDirPath = path42.relative(originalCwd, dirPath);
83359
+ const relativeDirPath = path43.relative(originalCwd, dirPath);
83092
83360
  console.log(kleur_default.green(`
83093
83361
  Successfully cloned bug report to:`));
83094
83362
  console.log(` ${dirPath}/
@@ -83127,7 +83395,7 @@ var registerClone = (program2) => {
83127
83395
  const [, author, packageName] = match;
83128
83396
  console.log(`Cloning ${author}/${packageName}...`);
83129
83397
  const userSettingToIncludeAuthor = options.includeAuthor || cliConfig.get("alwaysCloneWithAuthorName");
83130
- const dirPath = userSettingToIncludeAuthor ? path43.resolve(`${author}.${packageName}`) : path43.resolve(packageName);
83398
+ const dirPath = userSettingToIncludeAuthor ? path44.resolve(`${author}.${packageName}`) : path44.resolve(packageName);
83131
83399
  await handleExistingDirectory(dirPath);
83132
83400
  const ky2 = getRegistryApiKy();
83133
83401
  let packageFileList = {
@@ -83153,8 +83421,8 @@ var registerClone = (program2) => {
83153
83421
  const filePath = fileInfo.file_path.replace(/^\/+/, "");
83154
83422
  if (!filePath)
83155
83423
  continue;
83156
- const fullPath = path43.join(dirPath, filePath);
83157
- fs41.mkdirSync(path43.dirname(fullPath), { recursive: true });
83424
+ const fullPath = path44.join(dirPath, filePath);
83425
+ fs41.mkdirSync(path44.dirname(fullPath), { recursive: true });
83158
83426
  try {
83159
83427
  const fileContent = await ky2.get("package_files/get", {
83160
83428
  searchParams: {
@@ -83180,10 +83448,10 @@ var registerClone = (program2) => {
83180
83448
  console.warn(`Skipping ${filePath} due to error:`, error instanceof Error ? error.message : error);
83181
83449
  }
83182
83450
  }
83183
- fs41.writeFileSync(path43.join(dirPath, ".npmrc"), "@tsci:registry=https://npm.tscircuit.com");
83451
+ fs41.writeFileSync(path44.join(dirPath, ".npmrc"), "@tsci:registry=https://npm.tscircuit.com");
83184
83452
  generateTsConfig(dirPath);
83185
83453
  await setupTsciProject(dirPath);
83186
- const relativeDirPath = path43.relative(originalCwd, dirPath);
83454
+ const relativeDirPath = path44.relative(originalCwd, dirPath);
83187
83455
  console.log(kleur_default.green(`
83188
83456
  Successfully cloned to:`));
83189
83457
  console.log(` ${dirPath}/
@@ -83251,7 +83519,7 @@ var registerConfigSet = (program2) => {
83251
83519
 
83252
83520
  // cli/convert/register.ts
83253
83521
  import fs42 from "node:fs/promises";
83254
- import path44 from "node:path";
83522
+ import path45 from "node:path";
83255
83523
  import { parseKicadModToCircuitJson } from "kicad-component-converter";
83256
83524
 
83257
83525
  // node_modules/@tscircuit/mm/dist/index.js
@@ -83280,14 +83548,14 @@ var mmStr = (n) => {
83280
83548
  };
83281
83549
 
83282
83550
  // node_modules/circuit-json-to-tscircuit/dist/chunk-EX2F3BMQ.js
83283
- import { su } from "@tscircuit/soup-util";
83551
+ import { su as su4 } from "@tscircuit/soup-util";
83284
83552
  var generateFootprintTsx = (circuitJson) => {
83285
- const holes = su(circuitJson).pcb_hole.list();
83286
- const platedHoles = su(circuitJson).pcb_plated_hole.list();
83287
- const smtPads = su(circuitJson).pcb_smtpad.list();
83288
- const silkscreenPaths = su(circuitJson).pcb_silkscreen_path.list();
83289
- const fabricationNotePaths = su(circuitJson).pcb_fabrication_note_path.list();
83290
- const silkscreenTexts = su(circuitJson).pcb_silkscreen_text.list();
83553
+ const holes = su4(circuitJson).pcb_hole.list();
83554
+ const platedHoles = su4(circuitJson).pcb_plated_hole.list();
83555
+ const smtPads = su4(circuitJson).pcb_smtpad.list();
83556
+ const silkscreenPaths = su4(circuitJson).pcb_silkscreen_path.list();
83557
+ const fabricationNotePaths = su4(circuitJson).pcb_fabrication_note_path.list();
83558
+ const silkscreenTexts = su4(circuitJson).pcb_silkscreen_text.list();
83291
83559
  const elementStrings = [];
83292
83560
  for (const hole of holes) {
83293
83561
  if (hole.hole_shape === "circle") {
@@ -83372,14 +83640,14 @@ var convertCircuitJsonToTscircuit = (circuitJson, opts) => {
83372
83640
  var registerConvert = (program2) => {
83373
83641
  program2.command("convert").description("Convert a .kicad_mod footprint to a tscircuit component").argument("<file>", "Path to the .kicad_mod file").option("-o, --output <path>", "Output TSX file path").option("-n, --name <component>", "Component name for export").action(async (file, options) => {
83374
83642
  try {
83375
- const inputPath = path44.resolve(file);
83643
+ const inputPath = path45.resolve(file);
83376
83644
  const modContent = await fs42.readFile(inputPath, "utf-8");
83377
83645
  const circuitJson = await parseKicadModToCircuitJson(modContent);
83378
- const componentName = options.name ?? path44.basename(inputPath, ".kicad_mod");
83646
+ const componentName = options.name ?? path45.basename(inputPath, ".kicad_mod");
83379
83647
  const tsx = convertCircuitJsonToTscircuit(circuitJson, {
83380
83648
  componentName
83381
83649
  });
83382
- const outputPath = options.output ? path44.resolve(options.output) : path44.join(path44.dirname(inputPath), `${componentName}.tsx`);
83650
+ const outputPath = options.output ? path45.resolve(options.output) : path45.join(path45.dirname(inputPath), `${componentName}.tsx`);
83383
83651
  await fs42.writeFile(outputPath, tsx);
83384
83652
  console.log(kleur_default.green(`Converted ${outputPath}`));
83385
83653
  } catch (error) {
@@ -83392,11 +83660,11 @@ var registerConvert = (program2) => {
83392
83660
  // cli/dev/register.ts
83393
83661
  import * as fs49 from "node:fs";
83394
83662
  import * as net from "node:net";
83395
- import * as path52 from "node:path";
83663
+ import * as path53 from "node:path";
83396
83664
 
83397
83665
  // cli/dev/DevServer.ts
83398
83666
  import fs47 from "node:fs";
83399
- import path50 from "node:path";
83667
+ import path51 from "node:path";
83400
83668
 
83401
83669
  // node_modules/chokidar/esm/index.js
83402
83670
  import { stat as statcb } from "fs";
@@ -83475,7 +83743,7 @@ class ReaddirpStream extends Readable {
83475
83743
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
83476
83744
  const statMethod = opts.lstat ? lstat : stat;
83477
83745
  if (wantBigintFsStats) {
83478
- this._stat = (path45) => statMethod(path45, { bigint: true });
83746
+ this._stat = (path46) => statMethod(path46, { bigint: true });
83479
83747
  } else {
83480
83748
  this._stat = statMethod;
83481
83749
  }
@@ -83500,8 +83768,8 @@ class ReaddirpStream extends Readable {
83500
83768
  const par = this.parent;
83501
83769
  const fil = par && par.files;
83502
83770
  if (fil && fil.length > 0) {
83503
- const { path: path45, depth } = par;
83504
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path45));
83771
+ const { path: path46, depth } = par;
83772
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path46));
83505
83773
  const awaited = await Promise.all(slice);
83506
83774
  for (const entry of awaited) {
83507
83775
  if (!entry)
@@ -83541,20 +83809,20 @@ class ReaddirpStream extends Readable {
83541
83809
  this.reading = false;
83542
83810
  }
83543
83811
  }
83544
- async _exploreDir(path45, depth) {
83812
+ async _exploreDir(path46, depth) {
83545
83813
  let files;
83546
83814
  try {
83547
- files = await readdir(path45, this._rdOptions);
83815
+ files = await readdir(path46, this._rdOptions);
83548
83816
  } catch (error) {
83549
83817
  this._onError(error);
83550
83818
  }
83551
- return { files, depth, path: path45 };
83819
+ return { files, depth, path: path46 };
83552
83820
  }
83553
- async _formatEntry(dirent, path45) {
83821
+ async _formatEntry(dirent, path46) {
83554
83822
  let entry;
83555
83823
  const basename4 = this._isDirent ? dirent.name : dirent;
83556
83824
  try {
83557
- const fullPath = presolve(pjoin(path45, basename4));
83825
+ const fullPath = presolve(pjoin(path46, basename4));
83558
83826
  entry = { path: prelative(this._root, fullPath), fullPath, basename: basename4 };
83559
83827
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
83560
83828
  } catch (err) {
@@ -83952,16 +84220,16 @@ var delFromSet = (main, prop, item) => {
83952
84220
  };
83953
84221
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
83954
84222
  var FsWatchInstances = new Map;
83955
- function createFsWatchInstance(path45, options, listener, errHandler, emitRaw) {
84223
+ function createFsWatchInstance(path46, options, listener, errHandler, emitRaw) {
83956
84224
  const handleEvent = (rawEvent, evPath) => {
83957
- listener(path45);
83958
- emitRaw(rawEvent, evPath, { watchedPath: path45 });
83959
- if (evPath && path45 !== evPath) {
83960
- fsWatchBroadcast(sysPath.resolve(path45, evPath), KEY_LISTENERS, sysPath.join(path45, evPath));
84225
+ listener(path46);
84226
+ emitRaw(rawEvent, evPath, { watchedPath: path46 });
84227
+ if (evPath && path46 !== evPath) {
84228
+ fsWatchBroadcast(sysPath.resolve(path46, evPath), KEY_LISTENERS, sysPath.join(path46, evPath));
83961
84229
  }
83962
84230
  };
83963
84231
  try {
83964
- return fs_watch(path45, {
84232
+ return fs_watch(path46, {
83965
84233
  persistent: options.persistent
83966
84234
  }, handleEvent);
83967
84235
  } catch (error) {
@@ -83977,12 +84245,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
83977
84245
  listener(val1, val2, val3);
83978
84246
  });
83979
84247
  };
83980
- var setFsWatchListener = (path45, fullPath, options, handlers) => {
84248
+ var setFsWatchListener = (path46, fullPath, options, handlers) => {
83981
84249
  const { listener, errHandler, rawEmitter } = handlers;
83982
84250
  let cont = FsWatchInstances.get(fullPath);
83983
84251
  let watcher;
83984
84252
  if (!options.persistent) {
83985
- watcher = createFsWatchInstance(path45, options, listener, errHandler, rawEmitter);
84253
+ watcher = createFsWatchInstance(path46, options, listener, errHandler, rawEmitter);
83986
84254
  if (!watcher)
83987
84255
  return;
83988
84256
  return watcher.close.bind(watcher);
@@ -83992,7 +84260,7 @@ var setFsWatchListener = (path45, fullPath, options, handlers) => {
83992
84260
  addAndConvert(cont, KEY_ERR, errHandler);
83993
84261
  addAndConvert(cont, KEY_RAW, rawEmitter);
83994
84262
  } else {
83995
- watcher = createFsWatchInstance(path45, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
84263
+ watcher = createFsWatchInstance(path46, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
83996
84264
  if (!watcher)
83997
84265
  return;
83998
84266
  watcher.on(EV.ERROR, async (error) => {
@@ -84001,7 +84269,7 @@ var setFsWatchListener = (path45, fullPath, options, handlers) => {
84001
84269
  cont.watcherUnusable = true;
84002
84270
  if (isWindows && error.code === "EPERM") {
84003
84271
  try {
84004
- const fd = await open(path45, "r");
84272
+ const fd = await open(path46, "r");
84005
84273
  await fd.close();
84006
84274
  broadcastErr(error);
84007
84275
  } catch (err) {}
@@ -84031,7 +84299,7 @@ var setFsWatchListener = (path45, fullPath, options, handlers) => {
84031
84299
  };
84032
84300
  };
84033
84301
  var FsWatchFileInstances = new Map;
84034
- var setFsWatchFileListener = (path45, fullPath, options, handlers) => {
84302
+ var setFsWatchFileListener = (path46, fullPath, options, handlers) => {
84035
84303
  const { listener, rawEmitter } = handlers;
84036
84304
  let cont = FsWatchFileInstances.get(fullPath);
84037
84305
  const copts = cont && cont.options;
@@ -84053,7 +84321,7 @@ var setFsWatchFileListener = (path45, fullPath, options, handlers) => {
84053
84321
  });
84054
84322
  const currmtime = curr.mtimeMs;
84055
84323
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
84056
- foreach(cont.listeners, (listener2) => listener2(path45, curr));
84324
+ foreach(cont.listeners, (listener2) => listener2(path46, curr));
84057
84325
  }
84058
84326
  })
84059
84327
  };
@@ -84076,13 +84344,13 @@ class NodeFsHandler {
84076
84344
  this.fsw = fsW;
84077
84345
  this._boundHandleError = (error) => fsW._handleError(error);
84078
84346
  }
84079
- _watchWithNodeFs(path45, listener) {
84347
+ _watchWithNodeFs(path46, listener) {
84080
84348
  const opts = this.fsw.options;
84081
- const directory = sysPath.dirname(path45);
84082
- const basename5 = sysPath.basename(path45);
84349
+ const directory = sysPath.dirname(path46);
84350
+ const basename5 = sysPath.basename(path46);
84083
84351
  const parent = this.fsw._getWatchedDir(directory);
84084
84352
  parent.add(basename5);
84085
- const absolutePath = sysPath.resolve(path45);
84353
+ const absolutePath = sysPath.resolve(path46);
84086
84354
  const options = {
84087
84355
  persistent: opts.persistent
84088
84356
  };
@@ -84092,12 +84360,12 @@ class NodeFsHandler {
84092
84360
  if (opts.usePolling) {
84093
84361
  const enableBin = opts.interval !== opts.binaryInterval;
84094
84362
  options.interval = enableBin && isBinaryPath(basename5) ? opts.binaryInterval : opts.interval;
84095
- closer = setFsWatchFileListener(path45, absolutePath, options, {
84363
+ closer = setFsWatchFileListener(path46, absolutePath, options, {
84096
84364
  listener,
84097
84365
  rawEmitter: this.fsw._emitRaw
84098
84366
  });
84099
84367
  } else {
84100
- closer = setFsWatchListener(path45, absolutePath, options, {
84368
+ closer = setFsWatchListener(path46, absolutePath, options, {
84101
84369
  listener,
84102
84370
  errHandler: this._boundHandleError,
84103
84371
  rawEmitter: this.fsw._emitRaw
@@ -84115,7 +84383,7 @@ class NodeFsHandler {
84115
84383
  let prevStats = stats;
84116
84384
  if (parent.has(basename5))
84117
84385
  return;
84118
- const listener = async (path45, newStats) => {
84386
+ const listener = async (path46, newStats) => {
84119
84387
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
84120
84388
  return;
84121
84389
  if (!newStats || newStats.mtimeMs === 0) {
@@ -84129,11 +84397,11 @@ class NodeFsHandler {
84129
84397
  this.fsw._emit(EV.CHANGE, file, newStats2);
84130
84398
  }
84131
84399
  if ((isMacos || isLinux) && prevStats.ino !== newStats2.ino) {
84132
- this.fsw._closeFile(path45);
84400
+ this.fsw._closeFile(path46);
84133
84401
  prevStats = newStats2;
84134
84402
  const closer2 = this._watchWithNodeFs(file, listener);
84135
84403
  if (closer2)
84136
- this.fsw._addPathCloser(path45, closer2);
84404
+ this.fsw._addPathCloser(path46, closer2);
84137
84405
  } else {
84138
84406
  prevStats = newStats2;
84139
84407
  }
@@ -84157,7 +84425,7 @@ class NodeFsHandler {
84157
84425
  }
84158
84426
  return closer;
84159
84427
  }
84160
- async _handleSymlink(entry, directory, path45, item) {
84428
+ async _handleSymlink(entry, directory, path46, item) {
84161
84429
  if (this.fsw.closed) {
84162
84430
  return;
84163
84431
  }
@@ -84167,7 +84435,7 @@ class NodeFsHandler {
84167
84435
  this.fsw._incrReadyCount();
84168
84436
  let linkPath;
84169
84437
  try {
84170
- linkPath = await fsrealpath(path45);
84438
+ linkPath = await fsrealpath(path46);
84171
84439
  } catch (e) {
84172
84440
  this.fsw._emitReady();
84173
84441
  return true;
@@ -84177,12 +84445,12 @@ class NodeFsHandler {
84177
84445
  if (dir.has(item)) {
84178
84446
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
84179
84447
  this.fsw._symlinkPaths.set(full, linkPath);
84180
- this.fsw._emit(EV.CHANGE, path45, entry.stats);
84448
+ this.fsw._emit(EV.CHANGE, path46, entry.stats);
84181
84449
  }
84182
84450
  } else {
84183
84451
  dir.add(item);
84184
84452
  this.fsw._symlinkPaths.set(full, linkPath);
84185
- this.fsw._emit(EV.ADD, path45, entry.stats);
84453
+ this.fsw._emit(EV.ADD, path46, entry.stats);
84186
84454
  }
84187
84455
  this.fsw._emitReady();
84188
84456
  return true;
@@ -84211,9 +84479,9 @@ class NodeFsHandler {
84211
84479
  return;
84212
84480
  }
84213
84481
  const item = entry.path;
84214
- let path45 = sysPath.join(directory, item);
84482
+ let path46 = sysPath.join(directory, item);
84215
84483
  current.add(item);
84216
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path45, item)) {
84484
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path46, item)) {
84217
84485
  return;
84218
84486
  }
84219
84487
  if (this.fsw.closed) {
@@ -84222,8 +84490,8 @@ class NodeFsHandler {
84222
84490
  }
84223
84491
  if (item === target || !target && !previous.has(item)) {
84224
84492
  this.fsw._incrReadyCount();
84225
- path45 = sysPath.join(dir, sysPath.relative(dir, path45));
84226
- this._addToNodeFs(path45, initialAdd, wh, depth + 1);
84493
+ path46 = sysPath.join(dir, sysPath.relative(dir, path46));
84494
+ this._addToNodeFs(path46, initialAdd, wh, depth + 1);
84227
84495
  }
84228
84496
  }).on(EV.ERROR, this._boundHandleError);
84229
84497
  return new Promise((resolve7, reject) => {
@@ -84272,13 +84540,13 @@ class NodeFsHandler {
84272
84540
  }
84273
84541
  return closer;
84274
84542
  }
84275
- async _addToNodeFs(path45, initialAdd, priorWh, depth, target) {
84543
+ async _addToNodeFs(path46, initialAdd, priorWh, depth, target) {
84276
84544
  const ready = this.fsw._emitReady;
84277
- if (this.fsw._isIgnored(path45) || this.fsw.closed) {
84545
+ if (this.fsw._isIgnored(path46) || this.fsw.closed) {
84278
84546
  ready();
84279
84547
  return false;
84280
84548
  }
84281
- const wh = this.fsw._getWatchHelpers(path45);
84549
+ const wh = this.fsw._getWatchHelpers(path46);
84282
84550
  if (priorWh) {
84283
84551
  wh.filterPath = (entry) => priorWh.filterPath(entry);
84284
84552
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -84294,8 +84562,8 @@ class NodeFsHandler {
84294
84562
  const follow = this.fsw.options.followSymlinks;
84295
84563
  let closer;
84296
84564
  if (stats.isDirectory()) {
84297
- const absPath = sysPath.resolve(path45);
84298
- const targetPath = follow ? await fsrealpath(path45) : path45;
84565
+ const absPath = sysPath.resolve(path46);
84566
+ const targetPath = follow ? await fsrealpath(path46) : path46;
84299
84567
  if (this.fsw.closed)
84300
84568
  return;
84301
84569
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -84305,29 +84573,29 @@ class NodeFsHandler {
84305
84573
  this.fsw._symlinkPaths.set(absPath, targetPath);
84306
84574
  }
84307
84575
  } else if (stats.isSymbolicLink()) {
84308
- const targetPath = follow ? await fsrealpath(path45) : path45;
84576
+ const targetPath = follow ? await fsrealpath(path46) : path46;
84309
84577
  if (this.fsw.closed)
84310
84578
  return;
84311
84579
  const parent = sysPath.dirname(wh.watchPath);
84312
84580
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
84313
84581
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
84314
- closer = await this._handleDir(parent, stats, initialAdd, depth, path45, wh, targetPath);
84582
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path46, wh, targetPath);
84315
84583
  if (this.fsw.closed)
84316
84584
  return;
84317
84585
  if (targetPath !== undefined) {
84318
- this.fsw._symlinkPaths.set(sysPath.resolve(path45), targetPath);
84586
+ this.fsw._symlinkPaths.set(sysPath.resolve(path46), targetPath);
84319
84587
  }
84320
84588
  } else {
84321
84589
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
84322
84590
  }
84323
84591
  ready();
84324
84592
  if (closer)
84325
- this.fsw._addPathCloser(path45, closer);
84593
+ this.fsw._addPathCloser(path46, closer);
84326
84594
  return false;
84327
84595
  } catch (error) {
84328
84596
  if (this.fsw._handleError(error)) {
84329
84597
  ready();
84330
- return path45;
84598
+ return path46;
84331
84599
  }
84332
84600
  }
84333
84601
  }
@@ -84370,26 +84638,26 @@ function createPattern(matcher) {
84370
84638
  }
84371
84639
  return () => false;
84372
84640
  }
84373
- function normalizePath(path45) {
84374
- if (typeof path45 !== "string")
84641
+ function normalizePath(path46) {
84642
+ if (typeof path46 !== "string")
84375
84643
  throw new Error("string expected");
84376
- path45 = sysPath2.normalize(path45);
84377
- path45 = path45.replace(/\\/g, "/");
84644
+ path46 = sysPath2.normalize(path46);
84645
+ path46 = path46.replace(/\\/g, "/");
84378
84646
  let prepend = false;
84379
- if (path45.startsWith("//"))
84647
+ if (path46.startsWith("//"))
84380
84648
  prepend = true;
84381
84649
  const DOUBLE_SLASH_RE2 = /\/\//;
84382
- while (path45.match(DOUBLE_SLASH_RE2))
84383
- path45 = path45.replace(DOUBLE_SLASH_RE2, "/");
84650
+ while (path46.match(DOUBLE_SLASH_RE2))
84651
+ path46 = path46.replace(DOUBLE_SLASH_RE2, "/");
84384
84652
  if (prepend)
84385
- path45 = "/" + path45;
84386
- return path45;
84653
+ path46 = "/" + path46;
84654
+ return path46;
84387
84655
  }
84388
84656
  function matchPatterns(patterns, testString, stats) {
84389
- const path45 = normalizePath(testString);
84657
+ const path46 = normalizePath(testString);
84390
84658
  for (let index = 0;index < patterns.length; index++) {
84391
84659
  const pattern = patterns[index];
84392
- if (pattern(path45, stats)) {
84660
+ if (pattern(path46, stats)) {
84393
84661
  return true;
84394
84662
  }
84395
84663
  }
@@ -84429,19 +84697,19 @@ var toUnix = (string) => {
84429
84697
  }
84430
84698
  return str;
84431
84699
  };
84432
- var normalizePathToUnix = (path45) => toUnix(sysPath2.normalize(toUnix(path45)));
84433
- var normalizeIgnored = (cwd = "") => (path45) => {
84434
- if (typeof path45 === "string") {
84435
- return normalizePathToUnix(sysPath2.isAbsolute(path45) ? path45 : sysPath2.join(cwd, path45));
84700
+ var normalizePathToUnix = (path46) => toUnix(sysPath2.normalize(toUnix(path46)));
84701
+ var normalizeIgnored = (cwd = "") => (path46) => {
84702
+ if (typeof path46 === "string") {
84703
+ return normalizePathToUnix(sysPath2.isAbsolute(path46) ? path46 : sysPath2.join(cwd, path46));
84436
84704
  } else {
84437
- return path45;
84705
+ return path46;
84438
84706
  }
84439
84707
  };
84440
- var getAbsolutePath = (path45, cwd) => {
84441
- if (sysPath2.isAbsolute(path45)) {
84442
- return path45;
84708
+ var getAbsolutePath = (path46, cwd) => {
84709
+ if (sysPath2.isAbsolute(path46)) {
84710
+ return path46;
84443
84711
  }
84444
- return sysPath2.join(cwd, path45);
84712
+ return sysPath2.join(cwd, path46);
84445
84713
  };
84446
84714
  var EMPTY_SET = Object.freeze(new Set);
84447
84715
 
@@ -84498,10 +84766,10 @@ var STAT_METHOD_F = "stat";
84498
84766
  var STAT_METHOD_L = "lstat";
84499
84767
 
84500
84768
  class WatchHelper {
84501
- constructor(path45, follow, fsw) {
84769
+ constructor(path46, follow, fsw) {
84502
84770
  this.fsw = fsw;
84503
- const watchPath = path45;
84504
- this.path = path45 = path45.replace(REPLACER_RE, "");
84771
+ const watchPath = path46;
84772
+ this.path = path46 = path46.replace(REPLACER_RE, "");
84505
84773
  this.watchPath = watchPath;
84506
84774
  this.fullWatchPath = sysPath2.resolve(watchPath);
84507
84775
  this.dirParts = [];
@@ -84614,20 +84882,20 @@ class FSWatcher extends EventEmitter {
84614
84882
  this._closePromise = undefined;
84615
84883
  let paths = unifyPaths(paths_);
84616
84884
  if (cwd) {
84617
- paths = paths.map((path45) => {
84618
- const absPath = getAbsolutePath(path45, cwd);
84885
+ paths = paths.map((path46) => {
84886
+ const absPath = getAbsolutePath(path46, cwd);
84619
84887
  return absPath;
84620
84888
  });
84621
84889
  }
84622
- paths.forEach((path45) => {
84623
- this._removeIgnoredPath(path45);
84890
+ paths.forEach((path46) => {
84891
+ this._removeIgnoredPath(path46);
84624
84892
  });
84625
84893
  this._userIgnored = undefined;
84626
84894
  if (!this._readyCount)
84627
84895
  this._readyCount = 0;
84628
84896
  this._readyCount += paths.length;
84629
- Promise.all(paths.map(async (path45) => {
84630
- const res = await this._nodeFsHandler._addToNodeFs(path45, !_internal, undefined, 0, _origAdd);
84897
+ Promise.all(paths.map(async (path46) => {
84898
+ const res = await this._nodeFsHandler._addToNodeFs(path46, !_internal, undefined, 0, _origAdd);
84631
84899
  if (res)
84632
84900
  this._emitReady();
84633
84901
  return res;
@@ -84646,17 +84914,17 @@ class FSWatcher extends EventEmitter {
84646
84914
  return this;
84647
84915
  const paths = unifyPaths(paths_);
84648
84916
  const { cwd } = this.options;
84649
- paths.forEach((path45) => {
84650
- if (!sysPath2.isAbsolute(path45) && !this._closers.has(path45)) {
84917
+ paths.forEach((path46) => {
84918
+ if (!sysPath2.isAbsolute(path46) && !this._closers.has(path46)) {
84651
84919
  if (cwd)
84652
- path45 = sysPath2.join(cwd, path45);
84653
- path45 = sysPath2.resolve(path45);
84920
+ path46 = sysPath2.join(cwd, path46);
84921
+ path46 = sysPath2.resolve(path46);
84654
84922
  }
84655
- this._closePath(path45);
84656
- this._addIgnoredPath(path45);
84657
- if (this._watched.has(path45)) {
84923
+ this._closePath(path46);
84924
+ this._addIgnoredPath(path46);
84925
+ if (this._watched.has(path46)) {
84658
84926
  this._addIgnoredPath({
84659
- path: path45,
84927
+ path: path46,
84660
84928
  recursive: true
84661
84929
  });
84662
84930
  }
@@ -84705,38 +84973,38 @@ class FSWatcher extends EventEmitter {
84705
84973
  if (event !== EVENTS.ERROR)
84706
84974
  this.emit(EVENTS.ALL, ...args);
84707
84975
  }
84708
- async _emit(event, path45, stats) {
84976
+ async _emit(event, path46, stats) {
84709
84977
  if (this.closed)
84710
84978
  return;
84711
84979
  const opts = this.options;
84712
84980
  if (isWindows)
84713
- path45 = sysPath2.normalize(path45);
84981
+ path46 = sysPath2.normalize(path46);
84714
84982
  if (opts.cwd)
84715
- path45 = sysPath2.relative(opts.cwd, path45);
84716
- const args = [event, path45];
84983
+ path46 = sysPath2.relative(opts.cwd, path46);
84984
+ const args = [event, path46];
84717
84985
  if (stats != null)
84718
84986
  args.push(stats);
84719
84987
  const awf = opts.awaitWriteFinish;
84720
84988
  let pw;
84721
- if (awf && (pw = this._pendingWrites.get(path45))) {
84989
+ if (awf && (pw = this._pendingWrites.get(path46))) {
84722
84990
  pw.lastChange = new Date;
84723
84991
  return this;
84724
84992
  }
84725
84993
  if (opts.atomic) {
84726
84994
  if (event === EVENTS.UNLINK) {
84727
- this._pendingUnlinks.set(path45, args);
84995
+ this._pendingUnlinks.set(path46, args);
84728
84996
  setTimeout(() => {
84729
- this._pendingUnlinks.forEach((entry, path46) => {
84997
+ this._pendingUnlinks.forEach((entry, path47) => {
84730
84998
  this.emit(...entry);
84731
84999
  this.emit(EVENTS.ALL, ...entry);
84732
- this._pendingUnlinks.delete(path46);
85000
+ this._pendingUnlinks.delete(path47);
84733
85001
  });
84734
85002
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
84735
85003
  return this;
84736
85004
  }
84737
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path45)) {
85005
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path46)) {
84738
85006
  event = args[0] = EVENTS.CHANGE;
84739
- this._pendingUnlinks.delete(path45);
85007
+ this._pendingUnlinks.delete(path46);
84740
85008
  }
84741
85009
  }
84742
85010
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -84754,16 +85022,16 @@ class FSWatcher extends EventEmitter {
84754
85022
  this.emitWithAll(event, args);
84755
85023
  }
84756
85024
  };
84757
- this._awaitWriteFinish(path45, awf.stabilityThreshold, event, awfEmit);
85025
+ this._awaitWriteFinish(path46, awf.stabilityThreshold, event, awfEmit);
84758
85026
  return this;
84759
85027
  }
84760
85028
  if (event === EVENTS.CHANGE) {
84761
- const isThrottled = !this._throttle(EVENTS.CHANGE, path45, 50);
85029
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path46, 50);
84762
85030
  if (isThrottled)
84763
85031
  return this;
84764
85032
  }
84765
85033
  if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
84766
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path45) : path45;
85034
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path46) : path46;
84767
85035
  let stats2;
84768
85036
  try {
84769
85037
  stats2 = await stat3(fullPath);
@@ -84782,23 +85050,23 @@ class FSWatcher extends EventEmitter {
84782
85050
  }
84783
85051
  return error || this.closed;
84784
85052
  }
84785
- _throttle(actionType, path45, timeout2) {
85053
+ _throttle(actionType, path46, timeout2) {
84786
85054
  if (!this._throttled.has(actionType)) {
84787
85055
  this._throttled.set(actionType, new Map);
84788
85056
  }
84789
85057
  const action = this._throttled.get(actionType);
84790
85058
  if (!action)
84791
85059
  throw new Error("invalid throttle");
84792
- const actionPath = action.get(path45);
85060
+ const actionPath = action.get(path46);
84793
85061
  if (actionPath) {
84794
85062
  actionPath.count++;
84795
85063
  return false;
84796
85064
  }
84797
85065
  let timeoutObject;
84798
85066
  const clear = () => {
84799
- const item = action.get(path45);
85067
+ const item = action.get(path46);
84800
85068
  const count = item ? item.count : 0;
84801
- action.delete(path45);
85069
+ action.delete(path46);
84802
85070
  clearTimeout(timeoutObject);
84803
85071
  if (item)
84804
85072
  clearTimeout(item.timeoutObject);
@@ -84806,50 +85074,50 @@ class FSWatcher extends EventEmitter {
84806
85074
  };
84807
85075
  timeoutObject = setTimeout(clear, timeout2);
84808
85076
  const thr = { timeoutObject, clear, count: 0 };
84809
- action.set(path45, thr);
85077
+ action.set(path46, thr);
84810
85078
  return thr;
84811
85079
  }
84812
85080
  _incrReadyCount() {
84813
85081
  return this._readyCount++;
84814
85082
  }
84815
- _awaitWriteFinish(path45, threshold, event, awfEmit) {
85083
+ _awaitWriteFinish(path46, threshold, event, awfEmit) {
84816
85084
  const awf = this.options.awaitWriteFinish;
84817
85085
  if (typeof awf !== "object")
84818
85086
  return;
84819
85087
  const pollInterval = awf.pollInterval;
84820
85088
  let timeoutHandler;
84821
- let fullPath = path45;
84822
- if (this.options.cwd && !sysPath2.isAbsolute(path45)) {
84823
- fullPath = sysPath2.join(this.options.cwd, path45);
85089
+ let fullPath = path46;
85090
+ if (this.options.cwd && !sysPath2.isAbsolute(path46)) {
85091
+ fullPath = sysPath2.join(this.options.cwd, path46);
84824
85092
  }
84825
85093
  const now = new Date;
84826
85094
  const writes = this._pendingWrites;
84827
85095
  function awaitWriteFinishFn(prevStat) {
84828
85096
  statcb(fullPath, (err, curStat) => {
84829
- if (err || !writes.has(path45)) {
85097
+ if (err || !writes.has(path46)) {
84830
85098
  if (err && err.code !== "ENOENT")
84831
85099
  awfEmit(err);
84832
85100
  return;
84833
85101
  }
84834
85102
  const now2 = Number(new Date);
84835
85103
  if (prevStat && curStat.size !== prevStat.size) {
84836
- writes.get(path45).lastChange = now2;
85104
+ writes.get(path46).lastChange = now2;
84837
85105
  }
84838
- const pw = writes.get(path45);
85106
+ const pw = writes.get(path46);
84839
85107
  const df = now2 - pw.lastChange;
84840
85108
  if (df >= threshold) {
84841
- writes.delete(path45);
85109
+ writes.delete(path46);
84842
85110
  awfEmit(undefined, curStat);
84843
85111
  } else {
84844
85112
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
84845
85113
  }
84846
85114
  });
84847
85115
  }
84848
- if (!writes.has(path45)) {
84849
- writes.set(path45, {
85116
+ if (!writes.has(path46)) {
85117
+ writes.set(path46, {
84850
85118
  lastChange: now,
84851
85119
  cancelWait: () => {
84852
- writes.delete(path45);
85120
+ writes.delete(path46);
84853
85121
  clearTimeout(timeoutHandler);
84854
85122
  return event;
84855
85123
  }
@@ -84857,8 +85125,8 @@ class FSWatcher extends EventEmitter {
84857
85125
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
84858
85126
  }
84859
85127
  }
84860
- _isIgnored(path45, stats) {
84861
- if (this.options.atomic && DOT_RE.test(path45))
85128
+ _isIgnored(path46, stats) {
85129
+ if (this.options.atomic && DOT_RE.test(path46))
84862
85130
  return true;
84863
85131
  if (!this._userIgnored) {
84864
85132
  const { cwd } = this.options;
@@ -84868,13 +85136,13 @@ class FSWatcher extends EventEmitter {
84868
85136
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
84869
85137
  this._userIgnored = anymatch(list, undefined);
84870
85138
  }
84871
- return this._userIgnored(path45, stats);
85139
+ return this._userIgnored(path46, stats);
84872
85140
  }
84873
- _isntIgnored(path45, stat4) {
84874
- return !this._isIgnored(path45, stat4);
85141
+ _isntIgnored(path46, stat4) {
85142
+ return !this._isIgnored(path46, stat4);
84875
85143
  }
84876
- _getWatchHelpers(path45) {
84877
- return new WatchHelper(path45, this.options.followSymlinks, this);
85144
+ _getWatchHelpers(path46) {
85145
+ return new WatchHelper(path46, this.options.followSymlinks, this);
84878
85146
  }
84879
85147
  _getWatchedDir(directory) {
84880
85148
  const dir = sysPath2.resolve(directory);
@@ -84888,57 +85156,57 @@ class FSWatcher extends EventEmitter {
84888
85156
  return Boolean(Number(stats.mode) & 256);
84889
85157
  }
84890
85158
  _remove(directory, item, isDirectory2) {
84891
- const path45 = sysPath2.join(directory, item);
84892
- const fullPath = sysPath2.resolve(path45);
84893
- isDirectory2 = isDirectory2 != null ? isDirectory2 : this._watched.has(path45) || this._watched.has(fullPath);
84894
- if (!this._throttle("remove", path45, 100))
85159
+ const path46 = sysPath2.join(directory, item);
85160
+ const fullPath = sysPath2.resolve(path46);
85161
+ isDirectory2 = isDirectory2 != null ? isDirectory2 : this._watched.has(path46) || this._watched.has(fullPath);
85162
+ if (!this._throttle("remove", path46, 100))
84895
85163
  return;
84896
85164
  if (!isDirectory2 && this._watched.size === 1) {
84897
85165
  this.add(directory, item, true);
84898
85166
  }
84899
- const wp = this._getWatchedDir(path45);
85167
+ const wp = this._getWatchedDir(path46);
84900
85168
  const nestedDirectoryChildren = wp.getChildren();
84901
- nestedDirectoryChildren.forEach((nested) => this._remove(path45, nested));
85169
+ nestedDirectoryChildren.forEach((nested) => this._remove(path46, nested));
84902
85170
  const parent = this._getWatchedDir(directory);
84903
85171
  const wasTracked = parent.has(item);
84904
85172
  parent.remove(item);
84905
85173
  if (this._symlinkPaths.has(fullPath)) {
84906
85174
  this._symlinkPaths.delete(fullPath);
84907
85175
  }
84908
- let relPath = path45;
85176
+ let relPath = path46;
84909
85177
  if (this.options.cwd)
84910
- relPath = sysPath2.relative(this.options.cwd, path45);
85178
+ relPath = sysPath2.relative(this.options.cwd, path46);
84911
85179
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
84912
85180
  const event = this._pendingWrites.get(relPath).cancelWait();
84913
85181
  if (event === EVENTS.ADD)
84914
85182
  return;
84915
85183
  }
84916
- this._watched.delete(path45);
85184
+ this._watched.delete(path46);
84917
85185
  this._watched.delete(fullPath);
84918
85186
  const eventName = isDirectory2 ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
84919
- if (wasTracked && !this._isIgnored(path45))
84920
- this._emit(eventName, path45);
84921
- this._closePath(path45);
85187
+ if (wasTracked && !this._isIgnored(path46))
85188
+ this._emit(eventName, path46);
85189
+ this._closePath(path46);
84922
85190
  }
84923
- _closePath(path45) {
84924
- this._closeFile(path45);
84925
- const dir = sysPath2.dirname(path45);
84926
- this._getWatchedDir(dir).remove(sysPath2.basename(path45));
85191
+ _closePath(path46) {
85192
+ this._closeFile(path46);
85193
+ const dir = sysPath2.dirname(path46);
85194
+ this._getWatchedDir(dir).remove(sysPath2.basename(path46));
84927
85195
  }
84928
- _closeFile(path45) {
84929
- const closers = this._closers.get(path45);
85196
+ _closeFile(path46) {
85197
+ const closers = this._closers.get(path46);
84930
85198
  if (!closers)
84931
85199
  return;
84932
85200
  closers.forEach((closer) => closer());
84933
- this._closers.delete(path45);
85201
+ this._closers.delete(path46);
84934
85202
  }
84935
- _addPathCloser(path45, closer) {
85203
+ _addPathCloser(path46, closer) {
84936
85204
  if (!closer)
84937
85205
  return;
84938
- let list = this._closers.get(path45);
85206
+ let list = this._closers.get(path46);
84939
85207
  if (!list) {
84940
85208
  list = [];
84941
- this._closers.set(path45, list);
85209
+ this._closers.set(path46, list);
84942
85210
  }
84943
85211
  list.push(closer);
84944
85212
  }
@@ -84971,10 +85239,10 @@ import Debug3 from "debug";
84971
85239
 
84972
85240
  // lib/dependency-analysis/getNodeModuleDependencies.ts
84973
85241
  import * as ts from "typescript";
84974
- import * as path45 from "path";
85242
+ import * as path46 from "path";
84975
85243
  import * as fs43 from "fs";
84976
85244
  function getAllDependencyPackages(projectDir) {
84977
- const packageJsonPath = path45.join(projectDir, "package.json");
85245
+ const packageJsonPath = path46.join(projectDir, "package.json");
84978
85246
  const allPackages = new Set;
84979
85247
  if (!fs43.existsSync(packageJsonPath)) {
84980
85248
  return allPackages;
@@ -84995,7 +85263,7 @@ function getAllDependencyPackages(projectDir) {
84995
85263
  return allPackages;
84996
85264
  }
84997
85265
  function getNodeModuleImports(filePath) {
84998
- const absolutePath = path45.resolve(filePath);
85266
+ const absolutePath = path46.resolve(filePath);
84999
85267
  if (!fs43.existsSync(absolutePath)) {
85000
85268
  return [];
85001
85269
  }
@@ -85049,17 +85317,17 @@ function resolveNodeModuleImport({
85049
85317
  }) {
85050
85318
  const packageName = getPackageNameFromImport(importPath);
85051
85319
  const searchPaths = [
85052
- path45.join(projectDir, "node_modules", packageName)
85320
+ path46.join(projectDir, "node_modules", packageName)
85053
85321
  ];
85054
85322
  if (searchFromDir) {
85055
- let currentDir = path45.dirname(searchFromDir);
85056
- const projectDirNormalized = path45.normalize(projectDir);
85323
+ let currentDir = path46.dirname(searchFromDir);
85324
+ const projectDirNormalized = path46.normalize(projectDir);
85057
85325
  while (currentDir.startsWith(projectDirNormalized)) {
85058
- const candidatePath = path45.join(currentDir, "node_modules", packageName);
85326
+ const candidatePath = path46.join(currentDir, "node_modules", packageName);
85059
85327
  if (!searchPaths.includes(candidatePath)) {
85060
85328
  searchPaths.push(candidatePath);
85061
85329
  }
85062
- const parentDir = path45.dirname(currentDir);
85330
+ const parentDir = path46.dirname(currentDir);
85063
85331
  if (parentDir === currentDir)
85064
85332
  break;
85065
85333
  currentDir = parentDir;
@@ -85075,22 +85343,22 @@ function resolveNodeModuleImport({
85075
85343
  if (!packageDir) {
85076
85344
  return [];
85077
85345
  }
85078
- const packageJsonPath = path45.join(packageDir, "package.json");
85346
+ const packageJsonPath = path46.join(packageDir, "package.json");
85079
85347
  const hasPackageJson = fs43.existsSync(packageJsonPath);
85080
85348
  const packageJson = hasPackageJson ? JSON.parse(fs43.readFileSync(packageJsonPath, "utf-8")) : null;
85081
85349
  const resolvedFiles = [];
85082
85350
  if (importPath !== packageName) {
85083
85351
  const subpath = importPath.slice(packageName.length + 1);
85084
85352
  const possiblePaths = [
85085
- path45.join(packageDir, subpath),
85086
- path45.join(packageDir, `${subpath}.js`),
85087
- path45.join(packageDir, `${subpath}.mjs`),
85088
- path45.join(packageDir, `${subpath}.ts`),
85089
- path45.join(packageDir, `${subpath}.tsx`),
85090
- path45.join(packageDir, subpath, "index.js"),
85091
- path45.join(packageDir, subpath, "index.mjs"),
85092
- path45.join(packageDir, subpath, "index.ts"),
85093
- path45.join(packageDir, subpath, "index.tsx")
85353
+ path46.join(packageDir, subpath),
85354
+ path46.join(packageDir, `${subpath}.js`),
85355
+ path46.join(packageDir, `${subpath}.mjs`),
85356
+ path46.join(packageDir, `${subpath}.ts`),
85357
+ path46.join(packageDir, `${subpath}.tsx`),
85358
+ path46.join(packageDir, subpath, "index.js"),
85359
+ path46.join(packageDir, subpath, "index.mjs"),
85360
+ path46.join(packageDir, subpath, "index.ts"),
85361
+ path46.join(packageDir, subpath, "index.tsx")
85094
85362
  ];
85095
85363
  for (const p of possiblePaths) {
85096
85364
  if (fs43.existsSync(p) && fs43.statSync(p).isFile()) {
@@ -85125,22 +85393,22 @@ function resolveNodeModuleImport({
85125
85393
  resolveExportValue(packageJson.exports?.["."]?.require)
85126
85394
  ].filter((entry) => typeof entry === "string");
85127
85395
  for (const entry of entryPoints) {
85128
- const entryPath = path45.join(packageDir, entry);
85396
+ const entryPath = path46.join(packageDir, entry);
85129
85397
  if (fs43.existsSync(entryPath) && fs43.statSync(entryPath).isFile()) {
85130
85398
  resolvedFiles.push(entryPath);
85131
85399
  }
85132
85400
  }
85133
85401
  if (resolvedFiles.length === 0) {
85134
85402
  const fallbackPaths = [
85135
- path45.join(packageDir, "index.js"),
85136
- path45.join(packageDir, "index.mjs"),
85137
- path45.join(packageDir, "index.ts"),
85138
- path45.join(packageDir, "index.tsx"),
85139
- path45.join(packageDir, "dist", "index.js"),
85140
- path45.join(packageDir, "dist", "index.mjs"),
85141
- path45.join(packageDir, "lib", "index.js"),
85142
- path45.join(packageDir, "src", "index.ts"),
85143
- path45.join(packageDir, "src", "index.tsx")
85403
+ path46.join(packageDir, "index.js"),
85404
+ path46.join(packageDir, "index.mjs"),
85405
+ path46.join(packageDir, "index.ts"),
85406
+ path46.join(packageDir, "index.tsx"),
85407
+ path46.join(packageDir, "dist", "index.js"),
85408
+ path46.join(packageDir, "dist", "index.mjs"),
85409
+ path46.join(packageDir, "lib", "index.js"),
85410
+ path46.join(packageDir, "src", "index.ts"),
85411
+ path46.join(packageDir, "src", "index.tsx")
85144
85412
  ];
85145
85413
  for (const p of fallbackPaths) {
85146
85414
  if (fs43.existsSync(p) && fs43.statSync(p).isFile()) {
@@ -85181,8 +85449,8 @@ function collectAllNodeModuleDependencies(entryFilePath, projectDir, maxDepth =
85181
85449
  }
85182
85450
  }
85183
85451
  function getLocalDependencies(filePath) {
85184
- const absolutePath = path45.resolve(filePath);
85185
- const baseDir = path45.dirname(absolutePath);
85452
+ const absolutePath = path46.resolve(filePath);
85453
+ const baseDir = path46.dirname(absolutePath);
85186
85454
  if (!fs43.existsSync(absolutePath)) {
85187
85455
  return [];
85188
85456
  }
@@ -85208,7 +85476,7 @@ function collectAllNodeModuleDependencies(entryFilePath, projectDir, maxDepth =
85208
85476
  }
85209
85477
  function resolveLocalImport(importPath, baseDir) {
85210
85478
  const extensions = [".tsx", ".ts", ".jsx", ".js", ".mjs"];
85211
- const resolvedPath = path45.resolve(baseDir, importPath);
85479
+ const resolvedPath = path46.resolve(baseDir, importPath);
85212
85480
  if (fs43.existsSync(resolvedPath) && fs43.statSync(resolvedPath).isFile()) {
85213
85481
  return resolvedPath;
85214
85482
  }
@@ -85220,7 +85488,7 @@ function collectAllNodeModuleDependencies(entryFilePath, projectDir, maxDepth =
85220
85488
  }
85221
85489
  if (fs43.existsSync(resolvedPath) && fs43.statSync(resolvedPath).isDirectory()) {
85222
85490
  for (const ext of extensions) {
85223
- const indexPath = path45.join(resolvedPath, `index${ext}`);
85491
+ const indexPath = path46.join(resolvedPath, `index${ext}`);
85224
85492
  if (fs43.existsSync(indexPath)) {
85225
85493
  return indexPath;
85226
85494
  }
@@ -85246,11 +85514,11 @@ var EXCLUDED_PACKAGE_DIRECTORIES = new Set([
85246
85514
  function collectLocalPackageFiles(packageDir) {
85247
85515
  const buildDirs = ["dist", "build"];
85248
85516
  for (const dirName of buildDirs) {
85249
- const dirPath = path45.join(packageDir, dirName);
85517
+ const dirPath = path46.join(packageDir, dirName);
85250
85518
  if (fs43.existsSync(dirPath)) {
85251
85519
  const files = walkDirectory(dirPath, new Set);
85252
85520
  if (files.length > 0) {
85253
- const packageJsonPath = path45.join(packageDir, "package.json");
85521
+ const packageJsonPath = path46.join(packageDir, "package.json");
85254
85522
  if (fs43.existsSync(packageJsonPath)) {
85255
85523
  files.push(packageJsonPath);
85256
85524
  }
@@ -85266,7 +85534,7 @@ function walkDirectory(dir, excludedDirs) {
85266
85534
  return files;
85267
85535
  const entries = fs43.readdirSync(dir, { withFileTypes: true });
85268
85536
  for (const entry of entries) {
85269
- const fullPath = path45.join(dir, entry.name);
85537
+ const fullPath = path46.join(dir, entry.name);
85270
85538
  if (entry.isDirectory()) {
85271
85539
  if (excludedDirs.has(entry.name)) {
85272
85540
  continue;
@@ -85327,10 +85595,10 @@ function getAllNodeModuleFilePaths(entryFilePath, projectDir) {
85327
85595
  processedPackages.add(packageName);
85328
85596
  if (resolvedFiles.length > 0) {
85329
85597
  const firstResolvedFile = resolvedFiles[0];
85330
- let packageDir = path45.dirname(firstResolvedFile);
85598
+ let packageDir = path46.dirname(firstResolvedFile);
85331
85599
  let hasPackageJson = false;
85332
85600
  while (packageDir.includes("node_modules")) {
85333
- const packageJsonPath = path45.join(packageDir, "package.json");
85601
+ const packageJsonPath = path46.join(packageDir, "package.json");
85334
85602
  if (fs43.existsSync(packageJsonPath)) {
85335
85603
  try {
85336
85604
  const pkgJson = JSON.parse(fs43.readFileSync(packageJsonPath, "utf-8"));
@@ -85341,10 +85609,10 @@ function getAllNodeModuleFilePaths(entryFilePath, projectDir) {
85341
85609
  } catch {}
85342
85610
  }
85343
85611
  const expectedPackagePath = packageName.startsWith("@") ? `node_modules/${packageName}` : `node_modules/${packageName}`;
85344
- if (packageDir.endsWith(expectedPackagePath) || packageDir.endsWith(expectedPackagePath.replace(/\//g, path45.sep))) {
85612
+ if (packageDir.endsWith(expectedPackagePath) || packageDir.endsWith(expectedPackagePath.replace(/\//g, path46.sep))) {
85345
85613
  break;
85346
85614
  }
85347
- const parentDir = path45.dirname(packageDir);
85615
+ const parentDir = path46.dirname(packageDir);
85348
85616
  if (parentDir === packageDir)
85349
85617
  break;
85350
85618
  packageDir = parentDir;
@@ -86118,10 +86386,10 @@ var databaseSchema = z5.object({
86118
86386
  files: z5.array(fileSchema).default([]),
86119
86387
  events: z5.array(eventSchema).default([])
86120
86388
  });
86121
- function normalizePath2(path46) {
86122
- if (!path46 || path46 === "/")
86389
+ function normalizePath2(path47) {
86390
+ if (!path47 || path47 === "/")
86123
86391
  return "";
86124
- let normalized = path46.replace(/\\+/g, "/").replace(/\/\/+/, "/");
86392
+ let normalized = path47.replace(/\\+/g, "/").replace(/\/\/+/, "/");
86125
86393
  if (normalized.startsWith("/")) {
86126
86394
  normalized = normalized.slice(1);
86127
86395
  }
@@ -86979,13 +87247,13 @@ var getIndex = async (mainComponentPath, fileServerApiBaseUrl) => {
86979
87247
 
86980
87248
  // lib/server/kicad-pcm-proxy.ts
86981
87249
  import * as fs44 from "node:fs";
86982
- import * as path46 from "node:path";
87250
+ import * as path47 from "node:path";
86983
87251
  var getSourceFilesChecksum = (projectDir) => {
86984
87252
  const sourceFiles = globbySync(["**/*.tsx", "**/*.ts", "**/*.json", "!node_modules/**", "!dist/**"], { cwd: projectDir });
86985
87253
  let checksum = "";
86986
87254
  for (const file of sourceFiles) {
86987
87255
  try {
86988
- const stat4 = fs44.statSync(path46.join(projectDir, file));
87256
+ const stat4 = fs44.statSync(path47.join(projectDir, file));
86989
87257
  checksum += `${file}:${stat4.mtimeMs};`;
86990
87258
  } catch {}
86991
87259
  }
@@ -87005,9 +87273,9 @@ var createKicadPcmProxy = ({
87005
87273
  };
87006
87274
  const handleRequest = async (url, res) => {
87007
87275
  const requestedFile = url.pathname.replace(/^\/pcm\/?/, "") || "repository.json";
87008
- const distDir = path46.join(projectDir, "dist");
87009
- const pcmDir = path46.join(distDir, "pcm");
87010
- const filePath = path46.join(pcmDir, requestedFile);
87276
+ const distDir = path47.join(projectDir, "dist");
87277
+ const pcmDir = path47.join(distDir, "pcm");
87278
+ const filePath = path47.join(pcmDir, requestedFile);
87011
87279
  const currentChecksum = getSourceFilesChecksum(projectDir);
87012
87280
  const needsRebuild = currentChecksum !== pcmState.lastFileChecksum;
87013
87281
  if (needsRebuild) {
@@ -87057,7 +87325,7 @@ Rebuilding KiCad PCM assets...`));
87057
87325
  res.end(`PCM file not found: ${requestedFile}`);
87058
87326
  return;
87059
87327
  }
87060
- const ext = path46.extname(filePath).toLowerCase();
87328
+ const ext = path47.extname(filePath).toLowerCase();
87061
87329
  let contentType = "application/octet-stream";
87062
87330
  if (ext === ".json") {
87063
87331
  contentType = "application/json";
@@ -87189,7 +87457,7 @@ var createHttpServer = async ({
87189
87457
  // lib/shared/push-snippet.ts
87190
87458
  var import_semver3 = __toESM2(require_semver2(), 1);
87191
87459
  import * as fs46 from "node:fs";
87192
- import * as path49 from "node:path";
87460
+ import * as path50 from "node:path";
87193
87461
  import Debug2 from "debug";
87194
87462
 
87195
87463
  // lib/utils/validate-package-name.ts
@@ -87207,7 +87475,7 @@ var validatePackageName = (name) => {
87207
87475
  };
87208
87476
 
87209
87477
  // cli/dev/get-package-file-paths.ts
87210
- import * as path47 from "node:path";
87478
+ import * as path48 from "node:path";
87211
87479
  var getPackageFilePaths = (projectDir, ignored = []) => {
87212
87480
  const ignorePatterns = [
87213
87481
  ...DEFAULT_IGNORED_PATTERNS,
@@ -87218,7 +87486,7 @@ var getPackageFilePaths = (projectDir, ignored = []) => {
87218
87486
  ignore: ignorePatterns
87219
87487
  });
87220
87488
  fileNames.sort();
87221
- return fileNames.map((fileName) => path47.join(projectDir, fileName));
87489
+ return fileNames.map((fileName) => path48.join(projectDir, fileName));
87222
87490
  };
87223
87491
 
87224
87492
  // lib/utils/check-org-access.ts
@@ -87234,7 +87502,7 @@ var checkOrgAccess = async (ky2, orgTscircuitHandle) => {
87234
87502
  };
87235
87503
 
87236
87504
  // lib/shared/is-binary-file.ts
87237
- import * as path48 from "node:path";
87505
+ import * as path49 from "node:path";
87238
87506
  var BINARY_FILE_EXTENSIONS = new Set([
87239
87507
  ".glb",
87240
87508
  ".gltf",
@@ -87250,7 +87518,7 @@ var BINARY_FILE_EXTENSIONS = new Set([
87250
87518
  ".tar"
87251
87519
  ]);
87252
87520
  var isBinaryFile = (filePath) => {
87253
- const ext = path48.extname(filePath).toLowerCase();
87521
+ const ext = path49.extname(filePath).toLowerCase();
87254
87522
  return BINARY_FILE_EXTENSIONS.has(ext);
87255
87523
  };
87256
87524
 
@@ -87276,7 +87544,7 @@ var debug2 = Debug2("tsci:push-snippet");
87276
87544
  var getArchivePayload = async (filePaths, projectDir, packageNameWithVersion) => {
87277
87545
  const zip = new import_jszip3.default;
87278
87546
  for (const fullFilePath of filePaths) {
87279
- const relativeFilePath = path49.relative(projectDir, fullFilePath);
87547
+ const relativeFilePath = path50.relative(projectDir, fullFilePath);
87280
87548
  zip.file(relativeFilePath, fs46.readFileSync(fullFilePath));
87281
87549
  }
87282
87550
  const archive = await zip.generateAsync({
@@ -87314,10 +87582,10 @@ var pushSnippet = async ({
87314
87582
  return onExit(1);
87315
87583
  }
87316
87584
  const packageJsonPath = [
87317
- path49.resolve(path49.join(path49.dirname(snippetFilePath), "package.json")),
87318
- path49.resolve(path49.join(process.cwd(), "package.json"))
87319
- ].find((path50) => fs46.existsSync(path50));
87320
- const projectDir = packageJsonPath ? path49.dirname(packageJsonPath) : path49.dirname(snippetFilePath);
87585
+ path50.resolve(path50.join(path50.dirname(snippetFilePath), "package.json")),
87586
+ path50.resolve(path50.join(process.cwd(), "package.json"))
87587
+ ].find((path51) => fs46.existsSync(path51));
87588
+ const projectDir = packageJsonPath ? path50.dirname(packageJsonPath) : path50.dirname(snippetFilePath);
87321
87589
  if (!packageJsonPath) {
87322
87590
  onError("No package.json found, try running 'tsci init' to bootstrap the project");
87323
87591
  return onExit(1);
@@ -87511,7 +87779,7 @@ var pushSnippet = async ({
87511
87779
  json: archivePayload
87512
87780
  });
87513
87781
  for (const fullFilePath of filePaths) {
87514
- const relativeFilePath = path49.relative(projectDir, fullFilePath);
87782
+ const relativeFilePath = path50.relative(projectDir, fullFilePath);
87515
87783
  uploadResults.succeeded.push(relativeFilePath);
87516
87784
  }
87517
87785
  log(kleur_default.gray(`\uD83D\uDCE6 Uploaded archive with ${filePaths.length} files`));
@@ -87521,7 +87789,7 @@ var pushSnippet = async ({
87521
87789
  }
87522
87790
  if (uploadResults.succeeded.length === 0) {
87523
87791
  for (const fullFilePath of filePaths) {
87524
- const relativeFilePath = path49.relative(projectDir, fullFilePath);
87792
+ const relativeFilePath = path50.relative(projectDir, fullFilePath);
87525
87793
  const fileBuffer = fs46.readFileSync(fullFilePath);
87526
87794
  const isBinary = isBinaryFile(relativeFilePath) || hasBinaryContent(fileBuffer);
87527
87795
  const payload = {
@@ -87611,7 +87879,7 @@ class DevServer {
87611
87879
  }) {
87612
87880
  this.port = port;
87613
87881
  this.componentFilePath = componentFilePath;
87614
- this.projectDir = projectDir ?? path50.dirname(componentFilePath);
87882
+ this.projectDir = projectDir ?? path51.dirname(componentFilePath);
87615
87883
  this.kicadPcm = kicadPcm ?? false;
87616
87884
  const projectConfig = loadProjectConfig(this.projectDir);
87617
87885
  this.ignoredFiles = projectConfig?.ignoredFiles ?? [];
@@ -87622,7 +87890,7 @@ class DevServer {
87622
87890
  async start() {
87623
87891
  const { server } = await createHttpServer({
87624
87892
  port: this.port,
87625
- defaultMainComponentPath: path50.relative(this.projectDir, this.componentFilePath),
87893
+ defaultMainComponentPath: path51.relative(this.projectDir, this.componentFilePath),
87626
87894
  kicadPcm: this.kicadPcm,
87627
87895
  projectDir: this.projectDir,
87628
87896
  entryFile: this.componentFilePath
@@ -87638,7 +87906,7 @@ class DevServer {
87638
87906
  this.filesystemWatcher = watch(this.projectDir, {
87639
87907
  persistent: true,
87640
87908
  ignoreInitial: true,
87641
- ignored: (p) => shouldIgnorePath(path50.relative(this.projectDir, p), this.ignoredFiles)
87909
+ ignored: (p) => shouldIgnorePath(path51.relative(this.projectDir, p), this.ignoredFiles)
87642
87910
  });
87643
87911
  this.filesystemWatcher.on("change", (filePath) => this.handleFileChangedOnFilesystem(filePath));
87644
87912
  this.filesystemWatcher.on("add", (filePath) => this.handleFileChangedOnFilesystem(filePath));
@@ -87653,8 +87921,8 @@ class DevServer {
87653
87921
  const { file } = await this.fsKy.get("api/files/get", {
87654
87922
  searchParams: { file_path: ev.file_path }
87655
87923
  }).json();
87656
- const fullPath = path50.join(this.projectDir, ev.file_path);
87657
- const dirPath = path50.dirname(fullPath);
87924
+ const fullPath = path51.join(this.projectDir, ev.file_path);
87925
+ const dirPath = path51.dirname(fullPath);
87658
87926
  if (!fs47.existsSync(dirPath)) {
87659
87927
  fs47.mkdirSync(dirPath, { recursive: true });
87660
87928
  }
@@ -87666,14 +87934,14 @@ class DevServer {
87666
87934
  }
87667
87935
  }
87668
87936
  async handleFileDeletedEventFromServer(ev) {
87669
- const fullPath = path50.join(this.projectDir, ev.file_path);
87937
+ const fullPath = path51.join(this.projectDir, ev.file_path);
87670
87938
  if (fs47.existsSync(fullPath)) {
87671
87939
  debug3(`Deleting file ${ev.file_path} from filesystem`);
87672
87940
  fs47.unlinkSync(fullPath);
87673
87941
  }
87674
87942
  }
87675
87943
  async handleFileChangedOnFilesystem(absoluteFilePath) {
87676
- const relativeFilePath = path50.relative(this.projectDir, absoluteFilePath);
87944
+ const relativeFilePath = path51.relative(this.projectDir, absoluteFilePath);
87677
87945
  if (relativeFilePath.includes("manual-edits.json"))
87678
87946
  return;
87679
87947
  if (shouldIgnorePath(relativeFilePath, this.ignoredFiles))
@@ -87688,14 +87956,14 @@ class DevServer {
87688
87956
  await this.checkAndUploadNewNodeModules(absoluteFilePath);
87689
87957
  }
87690
87958
  async checkAndUploadNewNodeModules(filePath) {
87691
- const ext = path50.extname(filePath).toLowerCase();
87959
+ const ext = path51.extname(filePath).toLowerCase();
87692
87960
  const isSourceFile = [".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext);
87693
87961
  if (!isSourceFile)
87694
87962
  return;
87695
87963
  try {
87696
87964
  const nodeModuleFiles = getAllNodeModuleFilePaths(filePath, this.projectDir);
87697
87965
  const newFiles = nodeModuleFiles.filter((file) => {
87698
- const relativePath = path50.relative(this.projectDir, file);
87966
+ const relativePath = path51.relative(this.projectDir, file);
87699
87967
  return !this.uploadedNodeModules.has(relativePath);
87700
87968
  });
87701
87969
  if (newFiles.length === 0)
@@ -87708,7 +87976,7 @@ class DevServer {
87708
87976
  }
87709
87977
  }
87710
87978
  async handleFileRemovedFromFilesystem(absoluteFilePath) {
87711
- const relativeFilePath = path50.relative(this.projectDir, absoluteFilePath);
87979
+ const relativeFilePath = path51.relative(this.projectDir, absoluteFilePath);
87712
87980
  if (shouldIgnorePath(relativeFilePath, this.ignoredFiles))
87713
87981
  return;
87714
87982
  if (!relativeFilePath || relativeFilePath.trim() === "") {
@@ -87746,8 +88014,8 @@ class DevServer {
87746
88014
  debug3(`Successfully deleted file ${relativeFilePath} from server`);
87747
88015
  }
87748
88016
  async handleFileRename(oldPath, newPath) {
87749
- const oldRelativePath = path50.relative(this.projectDir, oldPath);
87750
- const newRelativePath = path50.relative(this.projectDir, newPath);
88017
+ const oldRelativePath = path51.relative(this.projectDir, oldPath);
88018
+ const newRelativePath = path51.relative(this.projectDir, newPath);
87751
88019
  if (shouldIgnorePath(oldRelativePath, this.ignoredFiles) || shouldIgnorePath(newRelativePath, this.ignoredFiles))
87752
88020
  return;
87753
88021
  await this.handleFileRemovedFromFilesystem(oldPath);
@@ -87765,7 +88033,7 @@ class DevServer {
87765
88033
  });
87766
88034
  const filePaths = getPackageFilePaths(this.projectDir, this.ignoredFiles);
87767
88035
  for (const filePath of filePaths) {
87768
- const relativeFilePath = path50.relative(this.projectDir, filePath);
88036
+ const relativeFilePath = path51.relative(this.projectDir, filePath);
87769
88037
  const filePayload = this.createFileUploadPayload(filePath, relativeFilePath);
87770
88038
  await this.postFileUpsert({
87771
88039
  filePath: relativeFilePath,
@@ -87797,7 +88065,7 @@ class DevServer {
87797
88065
  }
87798
88066
  async uploadNodeModuleFiles(files) {
87799
88067
  for (const nodeModuleFile of files) {
87800
- const relativeFilePath = path50.relative(this.projectDir, nodeModuleFile);
88068
+ const relativeFilePath = path51.relative(this.projectDir, nodeModuleFile);
87801
88069
  this.uploadedNodeModules.add(relativeFilePath);
87802
88070
  const filePayload = this.createFileUploadPayload(nodeModuleFile, relativeFilePath);
87803
88071
  await this.postFileUpsert({
@@ -87842,7 +88110,7 @@ class DevServer {
87842
88110
  formData.set("file_path", filePath);
87843
88111
  formData.set("initiator", initiator);
87844
88112
  const binaryBytes = Uint8Array.from(binaryContent);
87845
- formData.set("binary_file", new Blob([binaryBytes]), path50.basename(filePath));
88113
+ formData.set("binary_file", new Blob([binaryBytes]), path51.basename(filePath));
87846
88114
  const response = await fetch(`http://localhost:${this.port}/api/files/upsert-multipart`, {
87847
88115
  method: "POST",
87848
88116
  body: formData
@@ -87882,7 +88150,7 @@ class DevServer {
87882
88150
  await this.filesystemWatcher?.close();
87883
88151
  }
87884
88152
  createFileUploadPayload(absoluteFilePath, relativeFilePath) {
87885
- const ext = path50.extname(relativeFilePath).toLowerCase();
88153
+ const ext = path51.extname(relativeFilePath).toLowerCase();
87886
88154
  if (BINARY_FILE_EXTENSIONS2.has(ext)) {
87887
88155
  const fileBuffer = fs47.readFileSync(absoluteFilePath);
87888
88156
  return { binary_content: fileBuffer };
@@ -87918,7 +88186,7 @@ class DevServer {
87918
88186
 
87919
88187
  // cli/dev/resolve-dev-target.ts
87920
88188
  import * as fs48 from "node:fs";
87921
- import * as path51 from "node:path";
88189
+ import * as path52 from "node:path";
87922
88190
  var findSelectableFiles = (projectDir) => {
87923
88191
  const boardFiles = findBoardFiles({ projectDir }).filter((file) => fs48.existsSync(file)).sort();
87924
88192
  if (boardFiles.length > 0) {
@@ -87928,7 +88196,7 @@ var findSelectableFiles = (projectDir) => {
87928
88196
  cwd: projectDir,
87929
88197
  ignore: DEFAULT_IGNORED_PATTERNS
87930
88198
  });
87931
- return files.map((file) => path51.resolve(projectDir, file)).filter((file) => fs48.existsSync(file)).sort();
88199
+ return files.map((file) => path52.resolve(projectDir, file)).filter((file) => fs48.existsSync(file)).sort();
87932
88200
  };
87933
88201
  var isValidDevFile = (filePath) => {
87934
88202
  return filePath.endsWith(".tsx") || filePath.endsWith(".ts") || filePath.endsWith(".circuit.json");
@@ -87936,7 +88204,7 @@ var isValidDevFile = (filePath) => {
87936
88204
  var resolveDevTarget = async (file) => {
87937
88205
  let projectDir = process.cwd();
87938
88206
  if (file) {
87939
- const resolvedPath = path51.resolve(file);
88207
+ const resolvedPath = path52.resolve(file);
87940
88208
  if (fs48.existsSync(resolvedPath) && fs48.statSync(resolvedPath).isDirectory()) {
87941
88209
  projectDir = resolvedPath;
87942
88210
  const availableFiles2 = findSelectableFiles(projectDir);
@@ -87944,7 +88212,7 @@ var resolveDevTarget = async (file) => {
87944
88212
  console.log(`No .tsx, .ts, or .circuit.json files found in ${projectDir}. Run 'tsci init' to bootstrap a basic project.`);
87945
88213
  return null;
87946
88214
  }
87947
- console.log("Selected file:", path51.relative(projectDir, availableFiles2[0]));
88215
+ console.log("Selected file:", path52.relative(projectDir, availableFiles2[0]));
87948
88216
  return { absolutePath: availableFiles2[0], projectDir };
87949
88217
  }
87950
88218
  if (!fs48.existsSync(resolvedPath)) {
@@ -87967,7 +88235,7 @@ var resolveDevTarget = async (file) => {
87967
88235
  console.log("No .tsx, .ts, or .circuit.json files found in the project. Run 'tsci init' to bootstrap a basic project.");
87968
88236
  return null;
87969
88237
  }
87970
- console.log("Selected file:", path51.relative(projectDir, availableFiles[0]));
88238
+ console.log("Selected file:", path52.relative(projectDir, availableFiles[0]));
87971
88239
  return { absolutePath: availableFiles[0], projectDir };
87972
88240
  };
87973
88241
 
@@ -87983,7 +88251,7 @@ var isPortAvailable = (port) => {
87983
88251
  });
87984
88252
  };
87985
88253
  var warnIfTsconfigMissingTscircuitType = (projectDir) => {
87986
- const tsconfigPath = path52.join(projectDir, "tsconfig.json");
88254
+ const tsconfigPath = path53.join(projectDir, "tsconfig.json");
87987
88255
  if (!fs49.existsSync(tsconfigPath)) {
87988
88256
  return;
87989
88257
  }
@@ -88020,7 +88288,7 @@ var registerDev = (program2) => {
88020
88288
 
88021
88289
  ${kleur_default.green(`@tscircuit/cli@${getVersion()}`)} ${kleur_default.gray("ready in")} ${kleur_default.white(`${Math.round(timeToStart)}ms`)}`);
88022
88290
  console.log(`
88023
- ${kleur_default.bold("➜ Local:")} ${kleur_default.underline(kleur_default.cyan(`http://localhost:${port}`))}${server.componentFilePath ? kleur_default.underline(kleur_default.cyan(`/#file=${encodeURIComponent(path52.relative(process.cwd(), server.componentFilePath).replaceAll("\\", "/"))}`)) : ""}
88291
+ ${kleur_default.bold("➜ Local:")} ${kleur_default.underline(kleur_default.cyan(`http://localhost:${port}`))}${server.componentFilePath ? kleur_default.underline(kleur_default.cyan(`/#file=${encodeURIComponent(path53.relative(process.cwd(), server.componentFilePath).replaceAll("\\", "/"))}`)) : ""}
88024
88292
 
88025
88293
  `);
88026
88294
  console.log(kleur_default.gray(`Watching ${kleur_default.underline(server.projectDir.split("/").slice(-2).join("/"))} for changes...`));
@@ -88050,13 +88318,13 @@ var checkLoggedIn = () => {
88050
88318
  import { spawnSync } from "node:child_process";
88051
88319
  import fs50 from "node:fs";
88052
88320
  import os5 from "node:os";
88053
- import path53 from "node:path";
88321
+ import path54 from "node:path";
88054
88322
  var hasBunInstalled = () => {
88055
88323
  const result = spawnSync("bun", ["--version"], { stdio: "ignore" });
88056
88324
  return result.status === 0;
88057
88325
  };
88058
88326
  var createTempProject = (tempDir) => {
88059
- const packageJsonPath = path53.join(tempDir, "package.json");
88327
+ const packageJsonPath = path54.join(tempDir, "package.json");
88060
88328
  const packageJson = {
88061
88329
  name: "tsci-doctor-check",
88062
88330
  version: "0.0.0",
@@ -88076,7 +88344,7 @@ var checkGlobalNpmrcRegistry = async () => {
88076
88344
  details: "Bun is required to verify registry settings. Install Bun and rerun `tsci doctor`."
88077
88345
  };
88078
88346
  }
88079
- const tempDir = fs50.mkdtempSync(path53.join(os5.tmpdir(), "tsci-doctor-"));
88347
+ const tempDir = fs50.mkdtempSync(path54.join(os5.tmpdir(), "tsci-doctor-"));
88080
88348
  try {
88081
88349
  createTempProject(tempDir);
88082
88350
  const result = spawnSync("bun", ["install"], {
@@ -88148,243 +88416,9 @@ var registerDoctor = (program2) => {
88148
88416
 
88149
88417
  // lib/shared/export-snippet.ts
88150
88418
  import fs51 from "node:fs";
88151
- import path54 from "node:path";
88419
+ import path55 from "node:path";
88152
88420
  import { promisify as promisify3 } from "node:util";
88153
88421
  import { convertCircuitJsonToGltf as convertCircuitJsonToGltf4 } from "circuit-json-to-gltf";
88154
-
88155
- // node_modules/circuit-json-to-readable-netlist/dist/index.js
88156
- import { su as su3 } from "@tscircuit/circuit-json-util";
88157
- import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map";
88158
- import { su as su2 } from "@tscircuit/circuit-json-util";
88159
- import { su as su4 } from "@tscircuit/circuit-json-util";
88160
- var wordQualityScore = {
88161
- MISO: 1.2,
88162
- MOSI: 1.2,
88163
- SCLK: 1.2,
88164
- SDA: 1.2,
88165
- SCL: 1.2,
88166
- RX: 1.15,
88167
- TX: 1.15,
88168
- GPIO: 1.1,
88169
- cathode: 0.5,
88170
- anode: 0.5,
88171
- GND: 1.1,
88172
- VDD: 1.1,
88173
- AGND: 1.1,
88174
- V5: 1.1,
88175
- V3: 1.1,
88176
- V1: 1.1,
88177
- neg: 0.9,
88178
- pos: 0.9,
88179
- pin: 0.5,
88180
- left: 0.3,
88181
- right: 0.3
88182
- };
88183
- var wordQualityScoreEntries = Object.entries(wordQualityScore).sort((a, b) => b[1] - a[1]);
88184
- var scorePhrase = (phrase) => {
88185
- if (phrase.match(/\d+/)) {
88186
- return 0.5;
88187
- }
88188
- for (const [word, score] of wordQualityScoreEntries) {
88189
- if (phrase.includes(word)) {
88190
- return score;
88191
- }
88192
- }
88193
- return 1;
88194
- };
88195
- var getReadableNameForPin = ({
88196
- circuitJson,
88197
- source_port_id
88198
- }) => {
88199
- const source_ports = su4(circuitJson).source_port.list();
88200
- const source_components = su4(circuitJson).source_component.list();
88201
- const port = source_ports.find((p) => p.source_port_id === source_port_id);
88202
- if (!port)
88203
- return "";
88204
- const component = source_components.find((c) => c.source_component_id === port.source_component_id);
88205
- if (!component)
88206
- return "";
88207
- const isPositive = port.port_hints?.some((hint) => ["anode", "pos", "positive"].includes(hint.toLowerCase()));
88208
- const isNegative = port.port_hints?.some((hint) => ["cathode", "neg", "negative"].includes(hint.toLowerCase()));
88209
- const mainPinName = port.name ? port.name : `Pin${port.pin_number}`;
88210
- const additionalPinLabels = [];
88211
- if (isPositive && component.ftype !== "simple_resistor") {
88212
- additionalPinLabels.push("+");
88213
- } else if (isNegative && component.ftype !== "simple_resistor") {
88214
- additionalPinLabels.push("-");
88215
- }
88216
- for (const port_hint of port.port_hints ?? []) {
88217
- if (port_hint === mainPinName)
88218
- continue;
88219
- const score = scorePhrase(port_hint);
88220
- if (score > 1) {
88221
- additionalPinLabels.push(port_hint);
88222
- }
88223
- }
88224
- const displayValue = component.display_value ? ` (${component.display_value})` : "";
88225
- return `${component.name} ${mainPinName}${additionalPinLabels.length > 0 ? ` (${additionalPinLabels.join(",")})` : ""}${displayValue}`;
88226
- };
88227
- var scoreComponentOrder = (component) => {
88228
- if (!("ftype" in component))
88229
- return 0;
88230
- if (component.ftype === "simple_resistor")
88231
- return 0;
88232
- if (component.ftype === "simple_capacitor")
88233
- return 1;
88234
- return 2;
88235
- };
88236
- var generateNetName = ({
88237
- circuitJson,
88238
- connectedIds
88239
- }) => {
88240
- const all_source_components = su2(circuitJson).source_component.list();
88241
- const sourceComponentIdToScore = /* @__PURE__ */ new Map;
88242
- for (const component of all_source_components) {
88243
- sourceComponentIdToScore.set(component.source_component_id, scoreComponentOrder(component));
88244
- }
88245
- all_source_components.sort((a, b) => sourceComponentIdToScore.get(b.source_component_id) - sourceComponentIdToScore.get(a.source_component_id));
88246
- const all_source_ports = su2(circuitJson).source_port.list().sort((a, b) => sourceComponentIdToScore.get(b.source_component_id) - sourceComponentIdToScore.get(a.source_component_id));
88247
- const all_source_nets = su2(circuitJson).source_net.list();
88248
- const all_source_traces = su2(circuitJson).source_trace.list();
88249
- const ports = all_source_ports.filter((p) => connectedIds.includes(p.source_port_id));
88250
- const nets = all_source_nets.filter((n) => connectedIds.includes(n.source_net_id));
88251
- const traces = all_source_traces.filter((t) => connectedIds.includes(t.source_trace_id));
88252
- const possibleNames = ports.flatMap((p) => Array.from(/* @__PURE__ */ new Set([...p.name ? [p.name] : [], ...p.port_hints ?? []]))).concat(nets.map((n) => n.name));
88253
- const phrases = possibleNames.map((name) => ({
88254
- name,
88255
- score: scorePhrase(name)
88256
- }));
88257
- const bestPortName = phrases.sort((a, b) => b.score - a.score)[0].name;
88258
- const bestPort = ports.find((p) => p.name === bestPortName || p.port_hints?.includes(bestPortName));
88259
- const componentWithBestPort = all_source_components.find((c) => c.source_component_id === bestPort?.source_component_id);
88260
- return [componentWithBestPort?.name, bestPortName].filter(Boolean).join("_");
88261
- };
88262
- var convertCircuitJsonToReadableNetlist = (circuitJson) => {
88263
- const connectivityMap = getFullConnectivityMapFromCircuitJson(circuitJson.filter((e) => e.type.startsWith("source_")));
88264
- const netMap = connectivityMap.netMap;
88265
- const source_ports = su3(circuitJson).source_port.list();
88266
- const source_components = su3(circuitJson).source_component.list();
88267
- const source_nets = su3(circuitJson).source_net.list();
88268
- const source_traces = su3(circuitJson).source_trace.list();
88269
- const netlist = [];
88270
- netlist.push("COMPONENTS:");
88271
- for (const component of source_components) {
88272
- let componentDescription = "";
88273
- const cadComponent = su3(circuitJson).cad_component.getWhere({
88274
- source_component_id: component.source_component_id
88275
- });
88276
- const footprint = cadComponent?.footprinter_string;
88277
- if (component.ftype === "simple_resistor") {
88278
- componentDescription = `${component.display_resistance}${footprint ? ` ${footprint}` : ""} resistor`;
88279
- } else if (component.ftype === "simple_capacitor") {
88280
- componentDescription = `${component.display_capacitance}${footprint ? ` ${footprint}` : ""} capacitor`;
88281
- } else if (component.ftype === "simple_chip") {
88282
- const manufacturerPartNumber = component.manufacturer_part_number;
88283
- componentDescription = [manufacturerPartNumber, footprint].filter(Boolean).join(", ");
88284
- } else {
88285
- componentDescription = [component.name, component.type].filter(Boolean).join(", ");
88286
- }
88287
- netlist.push(` - ${component.name}: ${componentDescription}`);
88288
- }
88289
- netlist.push("");
88290
- for (const [netId, connectedIds] of Object.entries(netMap)) {
88291
- const net2 = source_nets.find((n) => connectedIds.includes(n.source_net_id));
88292
- let netName = net2?.name;
88293
- if (!netName) {
88294
- netName = generateNetName({ circuitJson, connectedIds });
88295
- }
88296
- const connectedPortCount = connectedIds.filter((id) => id.startsWith("source_port")).length;
88297
- if (connectedPortCount <= 1)
88298
- continue;
88299
- netlist.push(`NET: ${netName}`);
88300
- for (const id of connectedIds) {
88301
- const pinName = getReadableNameForPin({
88302
- circuitJson,
88303
- source_port_id: id
88304
- });
88305
- if (pinName) {
88306
- netlist.push(` - ${pinName}`);
88307
- }
88308
- }
88309
- netlist.push("");
88310
- }
88311
- let hasEmptyNets = false;
88312
- for (const [netId, connectedIds] of Object.entries(netMap)) {
88313
- const connectedPortCount = connectedIds.filter((id) => id.startsWith("source_port")).length;
88314
- if (connectedPortCount === 1) {
88315
- if (!hasEmptyNets) {
88316
- netlist.push("");
88317
- netlist.push("EMPTY NET PINS:");
88318
- hasEmptyNets = true;
88319
- }
88320
- const source_port_id = netMap[netId].find((id) => id.startsWith("source_port"));
88321
- const pinName = getReadableNameForPin({
88322
- circuitJson,
88323
- source_port_id
88324
- });
88325
- if (pinName) {
88326
- netlist.push(` - ${pinName}`);
88327
- }
88328
- }
88329
- }
88330
- const portIdToNetNames = {};
88331
- for (const [netId, connectedIds] of Object.entries(netMap)) {
88332
- const portIds = connectedIds.filter((id) => id.startsWith("source_port"));
88333
- if (portIds.length === 0)
88334
- continue;
88335
- const net2 = source_nets.find((n) => connectedIds.includes(n.source_net_id));
88336
- let netName = net2?.name;
88337
- if (!netName) {
88338
- netName = generateNetName({ circuitJson, connectedIds });
88339
- }
88340
- for (const portId of portIds) {
88341
- if (!portIdToNetNames[portId])
88342
- portIdToNetNames[portId] = [];
88343
- portIdToNetNames[portId].push(netName);
88344
- }
88345
- }
88346
- if (source_components.length > 0) {
88347
- netlist.push("");
88348
- netlist.push("COMPONENT_PINS:");
88349
- for (const component of source_components) {
88350
- const cadComponent = su3(circuitJson).cad_component.getWhere({
88351
- source_component_id: component.source_component_id
88352
- });
88353
- const footprint = cadComponent?.footprinter_string;
88354
- let header = component.name;
88355
- if (component.ftype === "simple_resistor") {
88356
- header = `${component.name} (${component.display_resistance} ${footprint})`;
88357
- } else if (component.ftype === "simple_capacitor") {
88358
- header = `${component.name} (${component.display_capacitance} ${footprint})`;
88359
- } else if (component.manufacturer_part_number) {
88360
- header = `${component.name} (${component.manufacturer_part_number})`;
88361
- }
88362
- netlist.push(header);
88363
- const ports = source_ports.filter((p) => p.source_component_id === component.source_component_id).sort((a, b) => (a.pin_number ?? 0) - (b.pin_number ?? 0));
88364
- for (const port of ports) {
88365
- const mainPin = port.pin_number !== undefined ? `pin${port.pin_number}` : port.name;
88366
- const aliases = [];
88367
- if (port.name && port.name !== mainPin)
88368
- aliases.push(port.name);
88369
- for (const hint of port.port_hints ?? []) {
88370
- if (hint === String(port.pin_number))
88371
- continue;
88372
- if (hint !== mainPin && hint !== port.name)
88373
- aliases.push(hint);
88374
- }
88375
- const aliasPart = aliases.length > 0 ? `(${Array.from(new Set(aliases)).join(", ")})` : "";
88376
- const nets = portIdToNetNames[port.source_port_id] ?? [];
88377
- const netsPart = nets.length > 0 ? `NETS(${nets.join(", ")})` : "NOT_CONNECTED";
88378
- netlist.push(`- ${mainPin}${aliasPart}: ${netsPart}`);
88379
- }
88380
- netlist.push("");
88381
- }
88382
- }
88383
- return netlist.join(`
88384
- `);
88385
- };
88386
-
88387
- // lib/shared/export-snippet.ts
88388
88422
  import {
88389
88423
  convertCircuitJsonToPcbSvg as convertCircuitJsonToPcbSvg2,
88390
88424
  convertCircuitJsonToSchematicSvg as convertCircuitJsonToSchematicSvg2
@@ -89221,9 +89255,9 @@ var stringifyDsnJson = (dsnJson) => {
89221
89255
  const stringifyCoordinates = (coordinates) => {
89222
89256
  return coordinates.join(" ");
89223
89257
  };
89224
- const stringifyPath = (path54, level) => {
89258
+ const stringifyPath = (path55, level) => {
89225
89259
  const padding = indent.repeat(level);
89226
- return `${padding}(path ${path54.layer} ${path54.width} ${stringifyCoordinates(path54.coordinates)})`;
89260
+ return `${padding}(path ${path55.layer} ${path55.width} ${stringifyCoordinates(path55.coordinates)})`;
89227
89261
  };
89228
89262
  result += `(pcb ${dsnJson.filename ? dsnJson.filename : "./converted_dsn.dsn"}
89229
89263
  `;
@@ -89450,10 +89484,10 @@ var exportSnippet = async ({
89450
89484
  onError(`Invalid format: ${format}`);
89451
89485
  return onExit(1);
89452
89486
  }
89453
- const projectDir = path54.dirname(filePath);
89454
- const outputBaseName = path54.basename(filePath).replace(/\.[^.]+$/, "");
89487
+ const projectDir = path55.dirname(filePath);
89488
+ const outputBaseName = path55.basename(filePath).replace(/\.[^.]+$/, "");
89455
89489
  const outputFileName = `${outputBaseName}${OUTPUT_EXTENSIONS[format]}`;
89456
- const outputDestination = path54.join(projectDir, outputPath ?? outputFileName);
89490
+ const outputDestination = path55.join(projectDir, outputPath ?? outputFileName);
89457
89491
  if (format === "kicad-library") {
89458
89492
  try {
89459
89493
  const result = await convertToKicadLibrary({
@@ -89651,11 +89685,11 @@ var getSpiceWithPaddedSim = (circuitJson, options) => {
89651
89685
 
89652
89686
  // lib/eecircuit-engine/run-simulation.ts
89653
89687
  import { promises as fs52, existsSync as existsSync13 } from "node:fs";
89654
- import path55 from "node:path";
89688
+ import path56 from "node:path";
89655
89689
  import os6 from "node:os";
89656
89690
  var sim = null;
89657
89691
  var fetchSimulation = async () => {
89658
- const tempFilePath = path55.join(os6.tmpdir(), "eecircuit-engine-1.5.2.mjs");
89692
+ const tempFilePath = path56.join(os6.tmpdir(), "eecircuit-engine-1.5.2.mjs");
89659
89693
  if (!existsSync13(tempFilePath)) {
89660
89694
  const url = "https://cdn.jsdelivr.net/npm/eecircuit-engine@1.5.2/+esm";
89661
89695
  const response = await fetch(url);
@@ -89752,7 +89786,7 @@ var resultToCsv = (result) => {
89752
89786
  };
89753
89787
 
89754
89788
  // cli/export/register.ts
89755
- import path56 from "node:path";
89789
+ import path57 from "node:path";
89756
89790
  import { promises as fs53 } from "node:fs";
89757
89791
  var registerExport = (program2) => {
89758
89792
  program2.command("export").description("Export tscircuit code to various formats").argument("<file>", "Path to the package file").option("-f, --format <format>", `Output format (${ALLOWED_EXPORT_FORMATS.join(", ")})`).option("-o, --output <path>", "Output file path").option("--disable-parts-engine", "Disable the parts engine").action(async (file, options) => {
@@ -89765,7 +89799,7 @@ var registerExport = (program2) => {
89765
89799
  });
89766
89800
  if (circuitJson) {
89767
89801
  const spiceString = getSpiceWithPaddedSim(circuitJson);
89768
- const outputSpicePath = options.output ?? path56.join(path56.dirname(file), `${path56.basename(file, path56.extname(file))}.spice.cir`);
89802
+ const outputSpicePath = options.output ?? path57.join(path57.dirname(file), `${path57.basename(file, path57.extname(file))}.spice.cir`);
89769
89803
  await fs53.writeFile(outputSpicePath, spiceString);
89770
89804
  const { result } = await runSimulation(spiceString);
89771
89805
  const csvContent = resultToCsv(result);
@@ -91238,8 +91272,8 @@ function getErrorMap() {
91238
91272
  return overrideErrorMap;
91239
91273
  }
91240
91274
  var makeIssue = (params2) => {
91241
- const { data, path: path57, errorMaps, issueData } = params2;
91242
- const fullPath = [...path57, ...issueData.path || []];
91275
+ const { data, path: path58, errorMaps, issueData } = params2;
91276
+ const fullPath = [...path58, ...issueData.path || []];
91243
91277
  const fullIssue = {
91244
91278
  ...issueData,
91245
91279
  path: fullPath
@@ -91347,11 +91381,11 @@ var errorUtil;
91347
91381
  errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
91348
91382
  })(errorUtil || (errorUtil = {}));
91349
91383
  var ParseInputLazyPath = class {
91350
- constructor(parent, value, path57, key) {
91384
+ constructor(parent, value, path58, key) {
91351
91385
  this._cachedPath = [];
91352
91386
  this.parent = parent;
91353
91387
  this.data = value;
91354
- this._path = path57;
91388
+ this._path = path58;
91355
91389
  this._key = key;
91356
91390
  }
91357
91391
  get path() {
@@ -102449,11 +102483,11 @@ var require_react_reconciler_development = __commonJS2({
102449
102483
  fiber = fiber.next, id--;
102450
102484
  return fiber;
102451
102485
  }
102452
- function copyWithSetImpl(obj, path57, index, value) {
102453
- if (index >= path57.length)
102486
+ function copyWithSetImpl(obj, path58, index, value) {
102487
+ if (index >= path58.length)
102454
102488
  return value;
102455
- var key = path57[index], updated = isArrayImpl(obj) ? obj.slice() : assign2({}, obj);
102456
- updated[key] = copyWithSetImpl(obj[key], path57, index + 1, value);
102489
+ var key = path58[index], updated = isArrayImpl(obj) ? obj.slice() : assign2({}, obj);
102490
+ updated[key] = copyWithSetImpl(obj[key], path58, index + 1, value);
102457
102491
  return updated;
102458
102492
  }
102459
102493
  function copyWithRename(obj, oldPath, newPath) {
@@ -102473,11 +102507,11 @@ var require_react_reconciler_development = __commonJS2({
102473
102507
  index + 1 === oldPath.length ? (updated[newPath[index]] = updated[oldKey], isArrayImpl(updated) ? updated.splice(oldKey, 1) : delete updated[oldKey]) : updated[oldKey] = copyWithRenameImpl(obj[oldKey], oldPath, newPath, index + 1);
102474
102508
  return updated;
102475
102509
  }
102476
- function copyWithDeleteImpl(obj, path57, index) {
102477
- var key = path57[index], updated = isArrayImpl(obj) ? obj.slice() : assign2({}, obj);
102478
- if (index + 1 === path57.length)
102510
+ function copyWithDeleteImpl(obj, path58, index) {
102511
+ var key = path58[index], updated = isArrayImpl(obj) ? obj.slice() : assign2({}, obj);
102512
+ if (index + 1 === path58.length)
102479
102513
  return isArrayImpl(updated) ? updated.splice(key, 1) : delete updated[key], updated;
102480
- updated[key] = copyWithDeleteImpl(obj[key], path57, index + 1);
102514
+ updated[key] = copyWithDeleteImpl(obj[key], path58, index + 1);
102481
102515
  return updated;
102482
102516
  }
102483
102517
  function shouldSuspendImpl() {
@@ -111503,29 +111537,29 @@ Check the top-level render call using <` + componentName2 + ">.");
111503
111537
  var didWarnAboutNestedUpdates = false;
111504
111538
  var didWarnAboutFindNodeInStrictMode = {};
111505
111539
  var overrideHookState = null, overrideHookStateDeletePath = null, overrideHookStateRenamePath = null, overrideProps = null, overridePropsDeletePath = null, overridePropsRenamePath = null, scheduleUpdate = null, setErrorHandler = null, setSuspenseHandler = null;
111506
- overrideHookState = function(fiber, id, path57, value) {
111540
+ overrideHookState = function(fiber, id, path58, value) {
111507
111541
  id = findHook(fiber, id);
111508
- id !== null && (path57 = copyWithSetImpl(id.memoizedState, path57, 0, value), id.memoizedState = path57, id.baseState = path57, fiber.memoizedProps = assign2({}, fiber.memoizedProps), path57 = enqueueConcurrentRenderForLane(fiber, 2), path57 !== null && scheduleUpdateOnFiber(path57, fiber, 2));
111542
+ id !== null && (path58 = copyWithSetImpl(id.memoizedState, path58, 0, value), id.memoizedState = path58, id.baseState = path58, fiber.memoizedProps = assign2({}, fiber.memoizedProps), path58 = enqueueConcurrentRenderForLane(fiber, 2), path58 !== null && scheduleUpdateOnFiber(path58, fiber, 2));
111509
111543
  };
111510
- overrideHookStateDeletePath = function(fiber, id, path57) {
111544
+ overrideHookStateDeletePath = function(fiber, id, path58) {
111511
111545
  id = findHook(fiber, id);
111512
- id !== null && (path57 = copyWithDeleteImpl(id.memoizedState, path57, 0), id.memoizedState = path57, id.baseState = path57, fiber.memoizedProps = assign2({}, fiber.memoizedProps), path57 = enqueueConcurrentRenderForLane(fiber, 2), path57 !== null && scheduleUpdateOnFiber(path57, fiber, 2));
111546
+ id !== null && (path58 = copyWithDeleteImpl(id.memoizedState, path58, 0), id.memoizedState = path58, id.baseState = path58, fiber.memoizedProps = assign2({}, fiber.memoizedProps), path58 = enqueueConcurrentRenderForLane(fiber, 2), path58 !== null && scheduleUpdateOnFiber(path58, fiber, 2));
111513
111547
  };
111514
111548
  overrideHookStateRenamePath = function(fiber, id, oldPath, newPath) {
111515
111549
  id = findHook(fiber, id);
111516
111550
  id !== null && (oldPath = copyWithRename(id.memoizedState, oldPath, newPath), id.memoizedState = oldPath, id.baseState = oldPath, fiber.memoizedProps = assign2({}, fiber.memoizedProps), oldPath = enqueueConcurrentRenderForLane(fiber, 2), oldPath !== null && scheduleUpdateOnFiber(oldPath, fiber, 2));
111517
111551
  };
111518
- overrideProps = function(fiber, path57, value) {
111519
- fiber.pendingProps = copyWithSetImpl(fiber.memoizedProps, path57, 0, value);
111552
+ overrideProps = function(fiber, path58, value) {
111553
+ fiber.pendingProps = copyWithSetImpl(fiber.memoizedProps, path58, 0, value);
111520
111554
  fiber.alternate && (fiber.alternate.pendingProps = fiber.pendingProps);
111521
- path57 = enqueueConcurrentRenderForLane(fiber, 2);
111522
- path57 !== null && scheduleUpdateOnFiber(path57, fiber, 2);
111555
+ path58 = enqueueConcurrentRenderForLane(fiber, 2);
111556
+ path58 !== null && scheduleUpdateOnFiber(path58, fiber, 2);
111523
111557
  };
111524
- overridePropsDeletePath = function(fiber, path57) {
111525
- fiber.pendingProps = copyWithDeleteImpl(fiber.memoizedProps, path57, 0);
111558
+ overridePropsDeletePath = function(fiber, path58) {
111559
+ fiber.pendingProps = copyWithDeleteImpl(fiber.memoizedProps, path58, 0);
111526
111560
  fiber.alternate && (fiber.alternate.pendingProps = fiber.pendingProps);
111527
- path57 = enqueueConcurrentRenderForLane(fiber, 2);
111528
- path57 !== null && scheduleUpdateOnFiber(path57, fiber, 2);
111561
+ path58 = enqueueConcurrentRenderForLane(fiber, 2);
111562
+ path58 !== null && scheduleUpdateOnFiber(path58, fiber, 2);
111529
111563
  };
111530
111564
  overridePropsRenamePath = function(fiber, oldPath, newPath) {
111531
111565
  fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath);
@@ -117828,7 +117862,7 @@ var parsePin = (pinString) => {
117828
117862
  const colorMatch = pinString.match(/#[0-9A-F]{6}/);
117829
117863
  const labelColor = colorMatch ? colorMatch[0] : "";
117830
117864
  const pathMatch = pinString.match(/\^\^([^~]+)/);
117831
- const path57 = pathMatch ? pathMatch[1] : "";
117865
+ const path58 = pathMatch ? pathMatch[1] : "";
117832
117866
  const arrowMatch = pinString.match(/\^\^0~(.+)$/);
117833
117867
  const arrow = arrowMatch ? arrowMatch[1] : "";
117834
117868
  const r2 = Number.parseFloat(rotation4);
@@ -117842,7 +117876,7 @@ var parsePin = (pinString) => {
117842
117876
  rotation: Number.isNaN(r2) ? 0 : r2,
117843
117877
  label,
117844
117878
  labelColor,
117845
- path: path57,
117879
+ path: path58,
117846
117880
  arrow
117847
117881
  };
117848
117882
  };
@@ -118282,15 +118316,15 @@ function generateArcFromSweep(startX, startY, endX, endY, radius, largeArcFlag,
118282
118316
  }
118283
118317
  }
118284
118318
  const numPoints = Math.max(2, Math.ceil(Math.abs(endAngle - startAngle) * radius));
118285
- const path57 = [];
118319
+ const path58 = [];
118286
118320
  for (let i22 = 0;i22 <= numPoints; i22++) {
118287
118321
  const t3 = i22 / numPoints;
118288
118322
  const angle2 = startAngle + t3 * (endAngle - startAngle);
118289
118323
  const x22 = centerX + radius * Math.cos(angle2);
118290
118324
  const y22 = centerY + radius * Math.sin(angle2);
118291
- path57.push({ x: x22, y: y22 });
118325
+ path58.push({ x: x22, y: y22 });
118292
118326
  }
118293
- return path57;
118327
+ return path58;
118294
118328
  }
118295
118329
  var __defProp4 = Object.defineProperty;
118296
118330
  var __export22 = (target, all) => {
@@ -127369,17 +127403,17 @@ var ObstacleList = class {
127369
127403
  return obstacles;
127370
127404
  }
127371
127405
  };
127372
- function removePathLoops(path57) {
127373
- if (path57.length < 4)
127374
- return path57;
127375
- const result = [{ ...path57[0] }];
127376
- let currentLayer = path57[0].layer;
127377
- for (let i22 = 1;i22 < path57.length; i22++) {
127378
- const currentSegment = { start: path57[i22 - 1], end: path57[i22] };
127379
- const isVia = path57[i22].route_type === "via" || path57[i22 - 1].route_type === "via";
127380
- if (path57[i22].layer !== currentLayer || isVia) {
127381
- result.push({ ...path57[i22] });
127382
- currentLayer = path57[i22].layer;
127406
+ function removePathLoops(path58) {
127407
+ if (path58.length < 4)
127408
+ return path58;
127409
+ const result = [{ ...path58[0] }];
127410
+ let currentLayer = path58[0].layer;
127411
+ for (let i22 = 1;i22 < path58.length; i22++) {
127412
+ const currentSegment = { start: path58[i22 - 1], end: path58[i22] };
127413
+ const isVia = path58[i22].route_type === "via" || path58[i22 - 1].route_type === "via";
127414
+ if (path58[i22].layer !== currentLayer || isVia) {
127415
+ result.push({ ...path58[i22] });
127416
+ currentLayer = path58[i22].layer;
127383
127417
  continue;
127384
127418
  }
127385
127419
  let intersectionFound = false;
@@ -127408,8 +127442,8 @@ function removePathLoops(path57) {
127408
127442
  result.push(intersectionPoint);
127409
127443
  }
127410
127444
  const lastPoint = result[result.length - 1];
127411
- if (lastPoint.x !== path57[i22].x || lastPoint.y !== path57[i22].y) {
127412
- result.push(path57[i22]);
127445
+ if (lastPoint.x !== path58[i22].x || lastPoint.y !== path58[i22].y) {
127446
+ result.push(path58[i22]);
127413
127447
  }
127414
127448
  }
127415
127449
  return result;
@@ -127898,10 +127932,10 @@ var GeneralizedAstarAutorouter = class {
127898
127932
  });
127899
127933
  }
127900
127934
  if (current2.parent) {
127901
- const path57 = [];
127935
+ const path58 = [];
127902
127936
  let p22 = current2;
127903
127937
  while (p22) {
127904
- path57.unshift(p22);
127938
+ path58.unshift(p22);
127905
127939
  p22 = p22.parent;
127906
127940
  }
127907
127941
  debugSolution.push({
@@ -127909,7 +127943,7 @@ var GeneralizedAstarAutorouter = class {
127909
127943
  pcb_component_id: "",
127910
127944
  pcb_fabrication_note_path_id: `note_path_${current2.x}_${current2.y}`,
127911
127945
  layer: "top",
127912
- route: path57,
127946
+ route: path58,
127913
127947
  stroke_width: 0.01
127914
127948
  });
127915
127949
  }
@@ -152354,10 +152388,10 @@ var findFirstCollision = (pts, rects, opts = {}) => {
152354
152388
  }
152355
152389
  return null;
152356
152390
  };
152357
- var isPathCollidingWithObstacles = (path57, obstacles) => {
152358
- for (let i22 = 0;i22 < path57.length - 1; i22++) {
152391
+ var isPathCollidingWithObstacles = (path58, obstacles) => {
152392
+ for (let i22 = 0;i22 < path58.length - 1; i22++) {
152359
152393
  for (const obstacle of obstacles) {
152360
- if (segmentIntersectsRect(path57[i22], path57[i22 + 1], obstacle)) {
152394
+ if (segmentIntersectsRect(path58[i22], path58[i22 + 1], obstacle)) {
152361
152395
  return true;
152362
152396
  }
152363
152397
  }
@@ -152551,36 +152585,36 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver3 {
152551
152585
  this.error = "No collision-free path found";
152552
152586
  return;
152553
152587
  }
152554
- const { path: path57, collisionChipIds } = state;
152588
+ const { path: path58, collisionChipIds } = state;
152555
152589
  const [PA, PB] = this.pins;
152556
- const collision = findFirstCollision(path57, this.obstacles);
152590
+ const collision = findFirstCollision(path58, this.obstacles);
152557
152591
  if (!collision) {
152558
- const first = path57[0];
152559
- const last = path57[path57.length - 1];
152592
+ const first = path58[0];
152593
+ const last = path58[path58.length - 1];
152560
152594
  const EPS42 = 0.000000001;
152561
152595
  const samePoint = (p22, q22) => Math.abs(p22.x - q22.x) < EPS42 && Math.abs(p22.y - q22.y) < EPS42;
152562
152596
  if (samePoint(first, { x: PA.x, y: PA.y }) && samePoint(last, { x: PB.x, y: PB.y })) {
152563
- this.solvedTracePath = path57;
152597
+ this.solvedTracePath = path58;
152564
152598
  this.solved = true;
152565
152599
  }
152566
152600
  return;
152567
152601
  }
152568
152602
  let { segIndex, rect } = collision;
152569
152603
  const isFirstSegment = segIndex === 0;
152570
- const isLastSegment = segIndex === path57.length - 2;
152604
+ const isLastSegment = segIndex === path58.length - 2;
152571
152605
  if (isFirstSegment) {
152572
- if (path57.length < 3) {
152606
+ if (path58.length < 3) {
152573
152607
  return;
152574
152608
  }
152575
152609
  segIndex = 1;
152576
152610
  } else if (isLastSegment) {
152577
- if (path57.length < 3) {
152611
+ if (path58.length < 3) {
152578
152612
  return;
152579
152613
  }
152580
- segIndex = path57.length - 3;
152614
+ segIndex = path58.length - 3;
152581
152615
  }
152582
- const a22 = path57[segIndex];
152583
- const b22 = path57[segIndex + 1];
152616
+ const a22 = path58[segIndex];
152617
+ const b22 = path58[segIndex + 1];
152584
152618
  const axis = this.axisOfSegment(a22, b22);
152585
152619
  if (!axis) {
152586
152620
  return;
@@ -152598,7 +152632,7 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver3 {
152598
152632
  }
152599
152633
  const newStates = [];
152600
152634
  for (const coord of candidates) {
152601
- const newPath = shiftSegmentOrth(path57, segIndex, axis, coord);
152635
+ const newPath = shiftSegmentOrth(path58, segIndex, axis, coord);
152602
152636
  if (!newPath)
152603
152637
  continue;
152604
152638
  const key = pathKey(newPath);
@@ -152634,8 +152668,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver3 {
152634
152668
  strokeColor: "blue",
152635
152669
  strokeDash: "5 5"
152636
152670
  });
152637
- for (const { path: path57, collisionChipIds: collisionRectIds } of this.queue) {
152638
- g22.lines.push({ points: path57, strokeColor: "teal", strokeDash: "2 2" });
152671
+ for (const { path: path58, collisionChipIds: collisionRectIds } of this.queue) {
152672
+ g22.lines.push({ points: path58, strokeColor: "teal", strokeDash: "2 2" });
152639
152673
  }
152640
152674
  if (this.solvedTracePath) {
152641
152675
  g22.lines.push({ points: this.solvedTracePath, strokeColor: "green" });
@@ -152872,9 +152906,9 @@ var TraceOverlapIssueSolver = class extends BaseSolver3 {
152872
152906
  solvedTracePathIndex,
152873
152907
  traceSegmentIndex
152874
152908
  } of group.pathsWithOverlap) {
152875
- const path57 = this.traceNetIslands[group.connNetId][solvedTracePathIndex];
152876
- const segStart = path57.tracePath[traceSegmentIndex];
152877
- const segEnd = path57.tracePath[traceSegmentIndex + 1];
152909
+ const path58 = this.traceNetIslands[group.connNetId][solvedTracePathIndex];
152910
+ const segStart = path58.tracePath[traceSegmentIndex];
152911
+ const segEnd = path58.tracePath[traceSegmentIndex + 1];
152878
152912
  graphics.lines.push({
152879
152913
  points: [segStart, segEnd],
152880
152914
  strokeColor: "red"
@@ -152918,11 +152952,11 @@ var TraceOverlapShiftSolver = class extends BaseSolver3 {
152918
152952
  computeTraceNetIslands() {
152919
152953
  const islands = {};
152920
152954
  for (const original of this.inputTracePaths) {
152921
- const path57 = this.correctedTraceMap[original.mspPairId] ?? original;
152922
- const key = path57.globalConnNetId;
152955
+ const path58 = this.correctedTraceMap[original.mspPairId] ?? original;
152956
+ const key = path58.globalConnNetId;
152923
152957
  if (!islands[key])
152924
152958
  islands[key] = [];
152925
- islands[key].push(path57);
152959
+ islands[key].push(path58);
152926
152960
  }
152927
152961
  return islands;
152928
152962
  }
@@ -153170,9 +153204,9 @@ function rectIntersectsAnyTrace(bounds, inputTraceMap, hostPathId, hostSegIndex)
153170
153204
  }
153171
153205
  return { hasIntersection: false };
153172
153206
  }
153173
- function lengthOfTrace(path57) {
153207
+ function lengthOfTrace(path58) {
153174
153208
  let sum = 0;
153175
- const pts = path57.tracePath;
153209
+ const pts = path58.tracePath;
153176
153210
  for (let i22 = 0;i22 < pts.length - 1; i22++) {
153177
153211
  sum += Math.abs(pts[i22 + 1].x - pts[i22].x) + Math.abs(pts[i22 + 1].y - pts[i22].y);
153178
153212
  }
@@ -153701,9 +153735,9 @@ var NetLabelPlacementSolver = class extends BaseSolver3 {
153701
153735
  }
153702
153736
  const compTraces = (byGlobal[globalConnNetId] ?? []).filter((t3) => component.has(t3.pins[0].pinId) && component.has(t3.pins[1].pinId));
153703
153737
  if (compTraces.length > 0) {
153704
- const lengthOf = (path57) => {
153738
+ const lengthOf = (path58) => {
153705
153739
  let sum = 0;
153706
- const pts = path57.tracePath;
153740
+ const pts = path58.tracePath;
153707
153741
  for (let i22 = 0;i22 < pts.length - 1; i22++) {
153708
153742
  sum += Math.abs(pts[i22 + 1].x - pts[i22].x) + Math.abs(pts[i22 + 1].y - pts[i22].y);
153709
153743
  }
@@ -153848,12 +153882,12 @@ var detectTraceLabelOverlap = (traces, netLabels) => {
153848
153882
  }
153849
153883
  return overlaps;
153850
153884
  };
153851
- var findTraceViolationZone = (path57, labelBounds) => {
153885
+ var findTraceViolationZone = (path58, labelBounds) => {
153852
153886
  const isPointInside = (p22) => p22.x > labelBounds.minX && p22.x < labelBounds.maxX && p22.y > labelBounds.minY && p22.y < labelBounds.maxY;
153853
153887
  let firstInsideIndex = -1;
153854
153888
  let lastInsideIndex = -1;
153855
- for (let i22 = 0;i22 < path57.length; i22++) {
153856
- if (isPointInside(path57[i22])) {
153889
+ for (let i22 = 0;i22 < path58.length; i22++) {
153890
+ if (isPointInside(path58[i22])) {
153857
153891
  if (firstInsideIndex === -1) {
153858
153892
  firstInsideIndex = i22;
153859
153893
  }
@@ -153862,20 +153896,20 @@ var findTraceViolationZone = (path57, labelBounds) => {
153862
153896
  }
153863
153897
  return { firstInsideIndex, lastInsideIndex };
153864
153898
  };
153865
- var simplifyPath = (path57) => {
153866
- if (path57.length < 3)
153867
- return path57;
153868
- const newPath = [path57[0]];
153869
- for (let i22 = 1;i22 < path57.length - 1; i22++) {
153899
+ var simplifyPath = (path58) => {
153900
+ if (path58.length < 3)
153901
+ return path58;
153902
+ const newPath = [path58[0]];
153903
+ for (let i22 = 1;i22 < path58.length - 1; i22++) {
153870
153904
  const p12 = newPath[newPath.length - 1];
153871
- const p22 = path57[i22];
153872
- const p32 = path57[i22 + 1];
153905
+ const p22 = path58[i22];
153906
+ const p32 = path58[i22 + 1];
153873
153907
  if (isVertical(p12, p22) && isVertical(p22, p32) || isHorizontal(p12, p22) && isHorizontal(p22, p32)) {
153874
153908
  continue;
153875
153909
  }
153876
153910
  newPath.push(p22);
153877
153911
  }
153878
- newPath.push(path57[path57.length - 1]);
153912
+ newPath.push(path58[path58.length - 1]);
153879
153913
  if (newPath.length < 3)
153880
153914
  return newPath;
153881
153915
  const finalPath = [newPath[0]];
@@ -154135,12 +154169,12 @@ var hasCollisionsWithLabels = (pathSegments, labels) => {
154135
154169
  return false;
154136
154170
  };
154137
154171
  var minimizeTurns = ({
154138
- path: path57,
154172
+ path: path58,
154139
154173
  obstacles,
154140
154174
  labelBounds
154141
154175
  }) => {
154142
- if (path57.length <= 2) {
154143
- return path57;
154176
+ if (path58.length <= 2) {
154177
+ return path58;
154144
154178
  }
154145
154179
  const recognizeStairStepPattern = (pathToCheck, startIdx) => {
154146
154180
  if (startIdx >= pathToCheck.length - 3)
@@ -154172,7 +154206,7 @@ var minimizeTurns = ({
154172
154206
  }
154173
154207
  return isStairStep && endIdx - startIdx >= 3 ? endIdx : -1;
154174
154208
  };
154175
- let optimizedPath = [...path57];
154209
+ let optimizedPath = [...path58];
154176
154210
  let currentTurns = countTurns(optimizedPath);
154177
154211
  let improved = true;
154178
154212
  while (improved) {
@@ -161777,9 +161811,9 @@ var getFileExtension = (filename) => {
161777
161811
  const extension = lastSegment.split(".").pop();
161778
161812
  return extension?.toLowerCase() ?? null;
161779
161813
  };
161780
- var joinUrlPath = (base, path57) => {
161814
+ var joinUrlPath = (base, path58) => {
161781
161815
  const trimmedBase = base.replace(/\/+$/, "");
161782
- const trimmedPath = path57.replace(/^\/+/, "");
161816
+ const trimmedPath = path58.replace(/^\/+/, "");
161783
161817
  return `${trimmedBase}/${trimmedPath}`;
161784
161818
  };
161785
161819
  var constructAssetUrl = (targetUrl, baseUrl) => {
@@ -163093,7 +163127,7 @@ var Trace_doInitialSchematicTraceRender = (trace) => {
163093
163127
  for (let i22 = 0;i22 < portsWithPosition.length - 1; i22++) {
163094
163128
  const start = portsWithPosition[i22];
163095
163129
  const end = portsWithPosition[i22 + 1];
163096
- const path57 = calculateElbow({
163130
+ const path58 = calculateElbow({
163097
163131
  x: start.position.x,
163098
163132
  y: start.position.y,
163099
163133
  facingDirection: convertFacingDirectionToElbowDirection(start.facingDirection)
@@ -163102,8 +163136,8 @@ var Trace_doInitialSchematicTraceRender = (trace) => {
163102
163136
  y: end.position.y,
163103
163137
  facingDirection: convertFacingDirectionToElbowDirection(end.facingDirection)
163104
163138
  });
163105
- for (let j22 = 0;j22 < path57.length - 1; j22++) {
163106
- elbowEdges.push({ from: path57[j22], to: path57[j22 + 1] });
163139
+ for (let j22 = 0;j22 < path58.length - 1; j22++) {
163140
+ elbowEdges.push({ from: path58[j22], to: path58[j22 + 1] });
163107
163141
  }
163108
163142
  }
163109
163143
  const doesSegmentIntersectRect2 = (edge, rect) => {
@@ -164296,20 +164330,20 @@ var parseLibraryFootprintRef = (s22) => {
164296
164330
  };
164297
164331
  var isStaticAssetPath = (s22) => s22.startsWith("/");
164298
164332
  var resolveStaticFileImportDebug = (0, import_debug92.default)("tscircuit:core:resolveStaticFileImport");
164299
- async function resolveStaticFileImport(path57, platform) {
164300
- if (!path57)
164301
- return path57;
164333
+ async function resolveStaticFileImport(path58, platform) {
164334
+ if (!path58)
164335
+ return path58;
164302
164336
  const resolver = platform?.resolveProjectStaticFileImportUrl;
164303
- if (resolver && path57.startsWith("/")) {
164337
+ if (resolver && path58.startsWith("/")) {
164304
164338
  try {
164305
- const resolved = await resolver(path57);
164339
+ const resolved = await resolver(path58);
164306
164340
  if (resolved)
164307
164341
  return resolved;
164308
164342
  } catch (error) {
164309
164343
  resolveStaticFileImportDebug("failed to resolve static file via platform resolver", error);
164310
164344
  }
164311
164345
  }
164312
- return constructAssetUrl(path57, platform?.projectBaseUrl);
164346
+ return constructAssetUrl(path58, platform?.projectBaseUrl);
164313
164347
  }
164314
164348
  function NormalComponent_doInitialPcbFootprintStringRender(component, queueAsyncEffect) {
164315
164349
  let { footprint } = component.props;
@@ -171956,7 +171990,7 @@ var NetLabel = class extends PrimitiveComponent2 {
171956
171990
  }
171957
171991
  const portPos = port._getGlobalSchematicPositionAfterLayout();
171958
171992
  const portFacing = convertFacingDirectionToElbowDirection(port.facingDirection ?? "right") ?? "x+";
171959
- const path57 = calculateElbow({
171993
+ const path58 = calculateElbow({
171960
171994
  x: portPos.x,
171961
171995
  y: portPos.y,
171962
171996
  facingDirection: portFacing
@@ -171965,13 +171999,13 @@ var NetLabel = class extends PrimitiveComponent2 {
171965
171999
  y: anchorPos.y,
171966
172000
  facingDirection: anchorFacing
171967
172001
  });
171968
- if (!Array.isArray(path57) || path57.length < 2)
172002
+ if (!Array.isArray(path58) || path58.length < 2)
171969
172003
  continue;
171970
172004
  const edges = [];
171971
- for (let i22 = 0;i22 < path57.length - 1; i22++) {
172005
+ for (let i22 = 0;i22 < path58.length - 1; i22++) {
171972
172006
  edges.push({
171973
- from: { x: path57[i22].x, y: path57[i22].y },
171974
- to: { x: path57[i22 + 1].x, y: path57[i22 + 1].y }
172007
+ from: { x: path58[i22].x, y: path58[i22].y },
172008
+ to: { x: path58[i22 + 1].x, y: path58[i22 + 1].y }
171975
172009
  });
171976
172010
  }
171977
172011
  let source_trace_id;
@@ -174284,7 +174318,7 @@ react/cjs/react-jsx-runtime.development.js:
174284
174318
 
174285
174319
  // lib/import/import-component-from-jlcpcb.ts
174286
174320
  import fs56 from "node:fs/promises";
174287
- import path57 from "node:path";
174321
+ import path58 from "node:path";
174288
174322
  var importComponentFromJlcpcb = async (jlcpcbPartNumber, projectDir = process.cwd()) => {
174289
174323
  const component = await fetchEasyEDAComponent(jlcpcbPartNumber);
174290
174324
  const tsx = await convertRawEasyToTsx(component);
@@ -174292,9 +174326,9 @@ var importComponentFromJlcpcb = async (jlcpcbPartNumber, projectDir = process.cw
174292
174326
  if (!fileName) {
174293
174327
  throw new Error("Could not determine file name of converted component");
174294
174328
  }
174295
- const importsDir = path57.join(projectDir, "imports");
174329
+ const importsDir = path58.join(projectDir, "imports");
174296
174330
  await fs56.mkdir(importsDir, { recursive: true });
174297
- const filePath = path57.join(importsDir, `${fileName}.tsx`);
174331
+ const filePath = path58.join(importsDir, `${fileName}.tsx`);
174298
174332
  await fs56.writeFile(filePath, tsx);
174299
174333
  return { filePath };
174300
174334
  };
@@ -175640,12 +175674,12 @@ var registerImport = (program2) => {
175640
175674
 
175641
175675
  // cli/init/register.ts
175642
175676
  import * as fs58 from "node:fs";
175643
- import * as path60 from "node:path";
175677
+ import * as path61 from "node:path";
175644
175678
 
175645
175679
  // lib/shared/generate-gitignore-file.ts
175646
- import path58 from "node:path";
175680
+ import path59 from "node:path";
175647
175681
  var generateGitIgnoreFile = (dir) => {
175648
- const gitignorePath = path58.join(dir, ".gitignore");
175682
+ const gitignorePath = path59.join(dir, ".gitignore");
175649
175683
  const gitignoreContent = `# Dependencies
175650
175684
  node_modules/
175651
175685
 
@@ -175681,7 +175715,7 @@ yarn-error.log*
175681
175715
 
175682
175716
  // lib/shared/setup-tscircuit-skill.ts
175683
175717
  import * as fs57 from "node:fs";
175684
- import * as path59 from "node:path";
175718
+ import * as path60 from "node:path";
175685
175719
  var SKILL_REPO_API_URL = "https://api.github.com/repos/tscircuit/skill/contents";
175686
175720
  var SKILL_INSTALL_PATHS = [
175687
175721
  ".claude/skills/tscircuit",
@@ -175704,7 +175738,7 @@ async function fetchFileContent(downloadUrl) {
175704
175738
  async function downloadDirectory(apiUrl, targetDir) {
175705
175739
  const contents = await fetchGitHubContents(apiUrl);
175706
175740
  for (const item of contents) {
175707
- const targetPath = path59.join(targetDir, item.name);
175741
+ const targetPath = path60.join(targetDir, item.name);
175708
175742
  if (item.type === "dir") {
175709
175743
  fs57.mkdirSync(targetPath, { recursive: true });
175710
175744
  await downloadDirectory(`${apiUrl}/${item.name}`, targetPath);
@@ -175721,7 +175755,7 @@ async function downloadSkillRepo(targetDir) {
175721
175755
  if (item.name === ".git" || item.name === ".github") {
175722
175756
  continue;
175723
175757
  }
175724
- const targetPath = path59.join(targetDir, item.name);
175758
+ const targetPath = path60.join(targetDir, item.name);
175725
175759
  if (item.type === "dir") {
175726
175760
  fs57.mkdirSync(targetPath, { recursive: true });
175727
175761
  await downloadDirectory(`${SKILL_REPO_API_URL}/${item.name}`, targetPath);
@@ -175732,7 +175766,7 @@ async function downloadSkillRepo(targetDir) {
175732
175766
  }
175733
175767
  }
175734
175768
  async function setupTscircuitSkill(projectDir, skipPrompt = false) {
175735
- const missingSkillPaths = SKILL_INSTALL_PATHS.filter((skillPath) => !fs57.existsSync(path59.join(projectDir, skillPath, "SKILL.md")));
175769
+ const missingSkillPaths = SKILL_INSTALL_PATHS.filter((skillPath) => !fs57.existsSync(path60.join(projectDir, skillPath, "SKILL.md")));
175736
175770
  if (missingSkillPaths.length === 0) {
175737
175771
  console.log("TSCircuit AI skills already exist, skipping...");
175738
175772
  return true;
@@ -175752,7 +175786,7 @@ async function setupTscircuitSkill(projectDir, skipPrompt = false) {
175752
175786
  console.info("Setting up tscircuit AI skills...");
175753
175787
  try {
175754
175788
  for (const skillPath of missingSkillPaths) {
175755
- const targetDir = path59.join(projectDir, skillPath);
175789
+ const targetDir = path60.join(projectDir, skillPath);
175756
175790
  await downloadSkillRepo(targetDir);
175757
175791
  console.info(`tscircuit skill installed at ${skillPath}`);
175758
175792
  }
@@ -175856,7 +175890,7 @@ var registerInit = (program3) => {
175856
175890
  }
175857
175891
  }
175858
175892
  }
175859
- const projectDir = directory ? path60.resolve(process.cwd(), directory) : process.cwd();
175893
+ const projectDir = directory ? path61.resolve(process.cwd(), directory) : process.cwd();
175860
175894
  let tsciHandle = null;
175861
175895
  const token = getSessionToken();
175862
175896
  if (token) {
@@ -175867,7 +175901,7 @@ var registerInit = (program3) => {
175867
175901
  }
175868
175902
  } catch {}
175869
175903
  }
175870
- const dirName = path60.basename(projectDir);
175904
+ const dirName = path61.basename(projectDir);
175871
175905
  let defaultPackageName = dirName;
175872
175906
  if (tsciHandle) {
175873
175907
  defaultPackageName = `@tsci/${tsciHandle}.${dirName}`;
@@ -175886,7 +175920,7 @@ var registerInit = (program3) => {
175886
175920
  }
175887
175921
  }
175888
175922
  fs58.mkdirSync(projectDir, { recursive: true });
175889
- writeFileIfNotExists(path60.join(projectDir, "index.circuit.tsx"), `
175923
+ writeFileIfNotExists(path61.join(projectDir, "index.circuit.tsx"), `
175890
175924
  export default () => (
175891
175925
  <board>
175892
175926
  <resistor resistance="1k" footprint="0402" name="R1" />
@@ -175898,7 +175932,7 @@ export default () => (
175898
175932
  if (saveProjectConfig(null, projectDir)) {
175899
175933
  console.log("Created tscircuit.config.json with schema");
175900
175934
  }
175901
- writeFileIfNotExists(path60.join(projectDir, ".npmrc"), `
175935
+ writeFileIfNotExists(path61.join(projectDir, ".npmrc"), `
175902
175936
  @tsci:registry=https://npm.tscircuit.com
175903
175937
  `);
175904
175938
  console.log("Generating package.json");
@@ -176049,14 +176083,14 @@ class KeyStore {
176049
176083
  }
176050
176084
  }
176051
176085
  function createKey(key) {
176052
- let path61 = null;
176086
+ let path62 = null;
176053
176087
  let id = null;
176054
176088
  let src = null;
176055
176089
  let weight = 1;
176056
176090
  let getFn = null;
176057
176091
  if (isString2(key) || isArray(key)) {
176058
176092
  src = key;
176059
- path61 = createKeyPath(key);
176093
+ path62 = createKeyPath(key);
176060
176094
  id = createKeyId(key);
176061
176095
  } else {
176062
176096
  if (!hasOwn.call(key, "name")) {
@@ -176070,11 +176104,11 @@ function createKey(key) {
176070
176104
  throw new Error(INVALID_KEY_WEIGHT_VALUE(name));
176071
176105
  }
176072
176106
  }
176073
- path61 = createKeyPath(name);
176107
+ path62 = createKeyPath(name);
176074
176108
  id = createKeyId(name);
176075
176109
  getFn = key.getFn;
176076
176110
  }
176077
- return { path: path61, id, weight, src, getFn };
176111
+ return { path: path62, id, weight, src, getFn };
176078
176112
  }
176079
176113
  function createKeyPath(key) {
176080
176114
  return isArray(key) ? key : key.split(".");
@@ -176082,34 +176116,34 @@ function createKeyPath(key) {
176082
176116
  function createKeyId(key) {
176083
176117
  return isArray(key) ? key.join(".") : key;
176084
176118
  }
176085
- function get(obj, path61) {
176119
+ function get(obj, path62) {
176086
176120
  let list = [];
176087
176121
  let arr = false;
176088
- const deepGet = (obj2, path62, index) => {
176122
+ const deepGet = (obj2, path63, index) => {
176089
176123
  if (!isDefined(obj2)) {
176090
176124
  return;
176091
176125
  }
176092
- if (!path62[index]) {
176126
+ if (!path63[index]) {
176093
176127
  list.push(obj2);
176094
176128
  } else {
176095
- let key = path62[index];
176129
+ let key = path63[index];
176096
176130
  const value = obj2[key];
176097
176131
  if (!isDefined(value)) {
176098
176132
  return;
176099
176133
  }
176100
- if (index === path62.length - 1 && (isString2(value) || isNumber2(value) || isBoolean(value))) {
176134
+ if (index === path63.length - 1 && (isString2(value) || isNumber2(value) || isBoolean(value))) {
176101
176135
  list.push(toString(value));
176102
176136
  } else if (isArray(value)) {
176103
176137
  arr = true;
176104
176138
  for (let i3 = 0, len = value.length;i3 < len; i3 += 1) {
176105
- deepGet(value[i3], path62, index + 1);
176139
+ deepGet(value[i3], path63, index + 1);
176106
176140
  }
176107
- } else if (path62.length) {
176108
- deepGet(value, path62, index + 1);
176141
+ } else if (path63.length) {
176142
+ deepGet(value, path63, index + 1);
176109
176143
  }
176110
176144
  }
176111
176145
  };
176112
- deepGet(obj, isString2(path61) ? path61.split(".") : path61, 0);
176146
+ deepGet(obj, isString2(path62) ? path62.split(".") : path62, 0);
176113
176147
  return arr ? list : list[0];
176114
176148
  }
176115
176149
  var MatchOptions = {
@@ -177313,8 +177347,8 @@ var registerSearch = (program3) => {
177313
177347
  }
177314
177348
  if (kicadResults.length) {
177315
177349
  console.log(kleur_default.bold().underline(`Found ${kicadResults.length} footprint(s) from KiCad:`));
177316
- kicadResults.forEach((path61, idx) => {
177317
- console.log(`${(idx + 1).toString().padStart(2, " ")}. kicad:${path61.replace(".kicad_mod", "").replace(".pretty", "")}`);
177350
+ kicadResults.forEach((path62, idx) => {
177351
+ console.log(`${(idx + 1).toString().padStart(2, " ")}. kicad:${path62.replace(".kicad_mod", "").replace(".pretty", "")}`);
177318
177352
  });
177319
177353
  }
177320
177354
  if (results.packages.length) {
@@ -177339,20 +177373,20 @@ var registerSearch = (program3) => {
177339
177373
 
177340
177374
  // lib/shared/setup-github-actions.ts
177341
177375
  import fs59 from "node:fs";
177342
- import path61 from "node:path";
177376
+ import path62 from "node:path";
177343
177377
  var setupGithubActions = (projectDir = process.cwd()) => {
177344
177378
  const findGitRoot = (startDir) => {
177345
- let dir = path61.resolve(startDir);
177346
- while (dir !== path61.parse(dir).root) {
177347
- if (fs59.existsSync(path61.join(dir, ".git"))) {
177379
+ let dir = path62.resolve(startDir);
177380
+ while (dir !== path62.parse(dir).root) {
177381
+ if (fs59.existsSync(path62.join(dir, ".git"))) {
177348
177382
  return dir;
177349
177383
  }
177350
- dir = path61.dirname(dir);
177384
+ dir = path62.dirname(dir);
177351
177385
  }
177352
177386
  return null;
177353
177387
  };
177354
177388
  const gitRoot = findGitRoot(projectDir) ?? projectDir;
177355
- const workflowsDir = path61.join(gitRoot, ".github", "workflows");
177389
+ const workflowsDir = path62.join(gitRoot, ".github", "workflows");
177356
177390
  fs59.mkdirSync(workflowsDir, { recursive: true });
177357
177391
  const buildWorkflow = `name: tscircuit Build
177358
177392
 
@@ -177392,8 +177426,8 @@ jobs:
177392
177426
  - run: bun install
177393
177427
  - run: bunx tsci snapshot
177394
177428
  `;
177395
- writeFileIfNotExists(path61.join(workflowsDir, "tscircuit-build.yml"), buildWorkflow);
177396
- writeFileIfNotExists(path61.join(workflowsDir, "tscircuit-snapshot.yml"), snapshotWorkflow);
177429
+ writeFileIfNotExists(path62.join(workflowsDir, "tscircuit-build.yml"), buildWorkflow);
177430
+ writeFileIfNotExists(path62.join(workflowsDir, "tscircuit-snapshot.yml"), snapshotWorkflow);
177397
177431
  };
177398
177432
 
177399
177433
  // cli/setup/register.ts
@@ -177560,8 +177594,89 @@ function applyCameraPreset(preset, cam) {
177560
177594
  }
177561
177595
 
177562
177596
  // lib/shared/snapshot-project.ts
177563
- import fs61 from "node:fs";
177564
- import path62 from "node:path";
177597
+ import path65 from "node:path";
177598
+
177599
+ // cli/snapshot/worker-pool.ts
177600
+ import fs60 from "node:fs";
177601
+ import path63 from "node:path";
177602
+ var getWorkerEntrypointPath2 = () => {
177603
+ const tsPath = path63.join(import.meta.dir, "snapshot.worker.ts");
177604
+ if (fs60.existsSync(tsPath)) {
177605
+ return tsPath;
177606
+ }
177607
+ const jsBundledPath = path63.join(import.meta.dir, "snapshot", "snapshot.worker.js");
177608
+ if (fs60.existsSync(jsBundledPath)) {
177609
+ return jsBundledPath;
177610
+ }
177611
+ return path63.join(import.meta.dir, "snapshot.worker.js");
177612
+ };
177613
+ var snapshotFilesWithWorkerPool = async (options) => {
177614
+ const cancellationError = new Error("Snapshot cancelled due to file failure");
177615
+ const poolConcurrency = Math.max(1, Math.min(options.concurrency, options.files.length));
177616
+ const pool = new ThreadWorkerPool({
177617
+ concurrency: poolConcurrency,
177618
+ workerEntrypointPath: getWorkerEntrypointPath2(),
177619
+ createMessage: (job) => ({
177620
+ message_type: "snapshot_file",
177621
+ file_path: job.filePath,
177622
+ project_dir: job.projectDir,
177623
+ snapshots_dir_name: job.snapshotsDirName,
177624
+ options: {
177625
+ update: job.options.update,
177626
+ threeD: job.options.threeD,
177627
+ pcbOnly: job.options.pcbOnly,
177628
+ schematicOnly: job.options.schematicOnly,
177629
+ forceUpdate: job.options.forceUpdate,
177630
+ platformConfig: job.options.platformConfig,
177631
+ createDiff: job.options.createDiff,
177632
+ cameraPreset: job.options.cameraPreset
177633
+ }
177634
+ }),
177635
+ isLogMessage: (message) => message.message_type === "worker_log",
177636
+ getLogLines: (message) => message.message_type === "worker_log" ? message.log_lines : [],
177637
+ isCompletionMessage: (message) => message.message_type === "snapshot_completed",
177638
+ getResult: (message) => {
177639
+ const completedMessage = message;
177640
+ return {
177641
+ filePath: completedMessage.file_path,
177642
+ result: completedMessage.result
177643
+ };
177644
+ },
177645
+ shouldStopOnMessage: (message) => {
177646
+ if (!options.stopOnFailure || message.message_type !== "snapshot_completed") {
177647
+ return false;
177648
+ }
177649
+ return !message.result.ok;
177650
+ },
177651
+ cancellationError,
177652
+ onLog: options.onLog
177653
+ });
177654
+ const results = [];
177655
+ const jobs = options.files.map((filePath) => pool.queueJob({
177656
+ filePath,
177657
+ projectDir: options.projectDir,
177658
+ snapshotsDirName: options.snapshotsDirName,
177659
+ options: options.snapshotOptions
177660
+ }).then(async (result) => {
177661
+ results.push(result);
177662
+ await options.onJobComplete?.(result);
177663
+ return result;
177664
+ }));
177665
+ const settledResults = await Promise.allSettled(jobs);
177666
+ for (const settledResult of settledResults) {
177667
+ if (settledResult.status === "rejected" && settledResult.reason !== cancellationError) {
177668
+ throw settledResult.reason;
177669
+ }
177670
+ }
177671
+ if (typeof Bun === "undefined") {
177672
+ await pool.terminate();
177673
+ }
177674
+ return results;
177675
+ };
177676
+
177677
+ // lib/shared/process-snapshot-file.ts
177678
+ import fs62 from "node:fs";
177679
+ import path64 from "node:path";
177565
177680
  import {
177566
177681
  convertCircuitJsonToGltf as convertCircuitJsonToGltf5,
177567
177682
  getBestCameraPosition
@@ -177570,12 +177685,11 @@ import {
177570
177685
  convertCircuitJsonToPcbSvg as convertCircuitJsonToPcbSvg3,
177571
177686
  convertCircuitJsonToSchematicSvg as convertCircuitJsonToSchematicSvg3
177572
177687
  } from "circuit-to-svg";
177573
- import looksSame2 from "looks-same";
177574
177688
  import { renderGLTFToPNGBufferFromGLBBuffer as renderGLTFToPNGBufferFromGLBBuffer2 } from "poppygl";
177575
177689
 
177576
177690
  // lib/shared/compare-images.ts
177577
177691
  import looksSame from "looks-same";
177578
- import fs60 from "node:fs/promises";
177692
+ import fs61 from "node:fs/promises";
177579
177693
  var compareAndCreateDiff = async (buffer1, buffer2, diffPath, createDiff = true) => {
177580
177694
  const { equal: equal2 } = await looksSame(buffer1, buffer2, {
177581
177695
  strict: false,
@@ -177591,12 +177705,200 @@ var compareAndCreateDiff = async (buffer1, buffer2, diffPath, createDiff = true)
177591
177705
  tolerance: 2
177592
177706
  });
177593
177707
  } else {
177594
- await fs60.writeFile(diffPath, buffer2);
177708
+ await fs61.writeFile(diffPath, buffer2);
177595
177709
  }
177596
177710
  }
177597
177711
  return { equal: equal2 };
177598
177712
  };
177599
177713
 
177714
+ // lib/shared/process-snapshot-file.ts
177715
+ var isCircuitJsonFile = (filePath) => {
177716
+ const normalizedPath = filePath.toLowerCase().replaceAll("\\", "/");
177717
+ return normalizedPath.endsWith(".circuit.json") || normalizedPath.endsWith("/circuit.json");
177718
+ };
177719
+ var processSnapshotFile = async ({
177720
+ file,
177721
+ projectDir,
177722
+ snapshotsDirName,
177723
+ update,
177724
+ threeD,
177725
+ pcbOnly,
177726
+ schematicOnly,
177727
+ forceUpdate,
177728
+ platformConfig: platformConfig2,
177729
+ createDiff,
177730
+ cameraPreset
177731
+ }) => {
177732
+ const relativeFilePath = path64.relative(projectDir, file);
177733
+ const successPaths = [];
177734
+ const warningMessages = [];
177735
+ const mismatches = [];
177736
+ let didUpdate = false;
177737
+ let circuitJson;
177738
+ let pcbSvg;
177739
+ let schSvg;
177740
+ try {
177741
+ if (isCircuitJsonFile(file)) {
177742
+ const parsed = JSON.parse(fs62.readFileSync(file, "utf-8"));
177743
+ circuitJson = Array.isArray(parsed) ? parsed : [];
177744
+ } else {
177745
+ const completePlatformConfig = getCompletePlatformConfig(platformConfig2);
177746
+ const result = await generateCircuitJson({
177747
+ filePath: file,
177748
+ platformConfig: completePlatformConfig
177749
+ });
177750
+ circuitJson = result.circuitJson;
177751
+ }
177752
+ } catch (error) {
177753
+ const errorMessage = error instanceof Error ? error.message : String(error);
177754
+ return {
177755
+ ok: false,
177756
+ didUpdate: false,
177757
+ successPaths,
177758
+ warningMessages,
177759
+ mismatches,
177760
+ errorMessage: kleur_default.red(`
177761
+ ❌ Failed to generate circuit JSON for ${relativeFilePath}:
177762
+ `) + kleur_default.red(` ${errorMessage}
177763
+ `)
177764
+ };
177765
+ }
177766
+ try {
177767
+ pcbSvg = convertCircuitJsonToPcbSvg3(circuitJson);
177768
+ } catch (error) {
177769
+ const errorMessage = error instanceof Error ? error.message : String(error);
177770
+ return {
177771
+ ok: false,
177772
+ didUpdate: false,
177773
+ successPaths,
177774
+ warningMessages,
177775
+ mismatches,
177776
+ errorMessage: kleur_default.red(`
177777
+ ❌ Failed to generate PCB SVG for ${relativeFilePath}:
177778
+ `) + kleur_default.red(` ${errorMessage}
177779
+ `)
177780
+ };
177781
+ }
177782
+ try {
177783
+ schSvg = convertCircuitJsonToSchematicSvg3(circuitJson);
177784
+ } catch (error) {
177785
+ const errorMessage = error instanceof Error ? error.message : String(error);
177786
+ return {
177787
+ ok: false,
177788
+ didUpdate: false,
177789
+ successPaths,
177790
+ warningMessages,
177791
+ mismatches,
177792
+ errorMessage: kleur_default.red(`
177793
+ ❌ Failed to generate schematic SVG for ${relativeFilePath}:
177794
+ `) + kleur_default.red(` ${errorMessage}
177795
+ `)
177796
+ };
177797
+ }
177798
+ let png3d = null;
177799
+ if (threeD) {
177800
+ try {
177801
+ const glbBuffer = await convertCircuitJsonToGltf5(circuitJson, getCircuitJsonToGltfOptions({ format: "glb" }));
177802
+ if (!(glbBuffer instanceof ArrayBuffer)) {
177803
+ throw new Error("Expected ArrayBuffer from convertCircuitJsonToGltf with glb format");
177804
+ }
177805
+ let cameraOptions = getBestCameraPosition(circuitJson);
177806
+ if (cameraPreset) {
177807
+ cameraOptions = applyCameraPreset(cameraPreset, cameraOptions);
177808
+ }
177809
+ png3d = await renderGLTFToPNGBufferFromGLBBuffer2(glbBuffer, cameraOptions);
177810
+ } catch (error) {
177811
+ const errorMessage = error instanceof Error ? error.message : String(error);
177812
+ if (errorMessage.includes("No pcb_board found in circuit JSON")) {
177813
+ const fileDir = path64.dirname(file);
177814
+ const relativeDir = path64.relative(projectDir, fileDir);
177815
+ const snapDir2 = snapshotsDirName ? path64.join(projectDir, snapshotsDirName, relativeDir) : path64.join(fileDir, "__snapshots__");
177816
+ const base2 = path64.basename(file).replace(/\.[^.]+$/, "");
177817
+ const snap3dPath = path64.join(snapDir2, `${base2}-3d.snap.png`);
177818
+ const existing3dSnapshot = fs62.existsSync(snap3dPath);
177819
+ if (existing3dSnapshot) {
177820
+ return {
177821
+ ok: false,
177822
+ didUpdate: false,
177823
+ successPaths,
177824
+ warningMessages,
177825
+ mismatches,
177826
+ errorMessage: kleur_default.red(`
177827
+ ❌ Failed to generate 3D snapshot for ${relativeFilePath}:
177828
+ `) + kleur_default.red(` No pcb_board found in circuit JSON
177829
+ `) + kleur_default.red(` Existing snapshot: ${path64.relative(projectDir, snap3dPath)}
177830
+ `)
177831
+ };
177832
+ }
177833
+ warningMessages.push(kleur_default.red(`⚠️ Skipping 3D snapshot for ${relativeFilePath}:`) + kleur_default.red(` No pcb_board found in circuit JSON`));
177834
+ png3d = null;
177835
+ } else {
177836
+ return {
177837
+ ok: false,
177838
+ didUpdate: false,
177839
+ successPaths,
177840
+ warningMessages,
177841
+ mismatches,
177842
+ errorMessage: kleur_default.red(`
177843
+ ❌ Failed to generate 3D snapshot for ${relativeFilePath}:
177844
+ `) + kleur_default.red(` ${errorMessage}
177845
+ `)
177846
+ };
177847
+ }
177848
+ }
177849
+ }
177850
+ const snapDir = snapshotsDirName ? path64.join(projectDir, snapshotsDirName, path64.relative(projectDir, path64.dirname(file))) : path64.join(path64.dirname(file), "__snapshots__");
177851
+ fs62.mkdirSync(snapDir, { recursive: true });
177852
+ const base = path64.basename(file).replace(/\.[^.]+$/, "");
177853
+ const snapshots = [];
177854
+ if (pcbOnly || !schematicOnly) {
177855
+ snapshots.push({ type: "pcb", content: pcbSvg, isBinary: false });
177856
+ }
177857
+ if (schematicOnly || !pcbOnly) {
177858
+ snapshots.push({ type: "schematic", content: schSvg, isBinary: false });
177859
+ }
177860
+ if (threeD && png3d) {
177861
+ snapshots.push({ type: "3d", content: png3d, isBinary: true });
177862
+ }
177863
+ for (const snapshot of snapshots) {
177864
+ const { type } = snapshot;
177865
+ const is3d = type === "3d";
177866
+ const snapPath = path64.join(snapDir, `${base}-${type}.snap.${is3d ? "png" : "svg"}`);
177867
+ const existing = fs62.existsSync(snapPath);
177868
+ const newContentBuffer = snapshot.isBinary ? snapshot.content : Buffer.from(snapshot.content, "utf8");
177869
+ const newContentForFile = snapshot.content;
177870
+ if (!existing) {
177871
+ fs62.writeFileSync(snapPath, newContentForFile);
177872
+ successPaths.push(path64.relative(projectDir, snapPath));
177873
+ didUpdate = true;
177874
+ continue;
177875
+ }
177876
+ const oldContentBuffer = fs62.readFileSync(snapPath);
177877
+ const diffPath = snapPath.replace(is3d ? ".snap.png" : ".snap.svg", is3d ? ".diff.png" : ".diff.svg");
177878
+ const { equal: equal2 } = await compareAndCreateDiff(oldContentBuffer, newContentBuffer, diffPath, createDiff);
177879
+ if (update) {
177880
+ if (!forceUpdate && equal2) {
177881
+ successPaths.push(path64.relative(projectDir, snapPath));
177882
+ } else {
177883
+ fs62.writeFileSync(snapPath, newContentForFile);
177884
+ successPaths.push(path64.relative(projectDir, snapPath));
177885
+ didUpdate = true;
177886
+ }
177887
+ } else if (!equal2) {
177888
+ mismatches.push(createDiff ? `${snapPath} (diff: ${diffPath})` : snapPath);
177889
+ } else {
177890
+ successPaths.push(path64.relative(projectDir, snapPath));
177891
+ }
177892
+ }
177893
+ return {
177894
+ ok: true,
177895
+ didUpdate,
177896
+ successPaths,
177897
+ warningMessages,
177898
+ mismatches
177899
+ };
177900
+ };
177901
+
177600
177902
  // lib/shared/snapshot-project.ts
177601
177903
  var snapshotProject = async ({
177602
177904
  update = false,
@@ -177611,7 +177913,8 @@ var snapshotProject = async ({
177611
177913
  onSuccess = (msg) => console.log(msg),
177612
177914
  platformConfig: platformConfig2,
177613
177915
  createDiff = false,
177614
- cameraPreset
177916
+ cameraPreset,
177917
+ concurrency = 1
177615
177918
  } = {}) => {
177616
177919
  if (cameraPreset) {
177617
177920
  threeD = true;
@@ -177621,7 +177924,7 @@ var snapshotProject = async ({
177621
177924
  ...DEFAULT_IGNORED_PATTERNS,
177622
177925
  ...ignored.map(normalizeIgnorePattern)
177623
177926
  ];
177624
- const resolvedPaths = filePaths.map((f2) => path62.resolve(projectDir, f2));
177927
+ const resolvedPaths = filePaths.map((f2) => path65.resolve(projectDir, f2));
177625
177928
  const boardFiles = findBoardFiles({
177626
177929
  projectDir,
177627
177930
  ignore,
@@ -177634,141 +177937,78 @@ var snapshotProject = async ({
177634
177937
  const snapshotsDirName = getSnapshotsDir(projectDir);
177635
177938
  const mismatches = [];
177636
177939
  let didUpdate = false;
177637
- const isCircuitJsonFile = (filePath) => {
177638
- const normalizedPath = filePath.toLowerCase().replaceAll("\\", "/");
177639
- return normalizedPath.endsWith(".circuit.json") || normalizedPath.endsWith("/circuit.json");
177640
- };
177641
- for (const file of boardFiles) {
177642
- const relativeFilePath = path62.relative(projectDir, file);
177643
- let circuitJson;
177644
- let pcbSvg;
177645
- let schSvg;
177646
- try {
177647
- if (isCircuitJsonFile(file)) {
177648
- const parsed = JSON.parse(fs61.readFileSync(file, "utf-8"));
177649
- circuitJson = Array.isArray(parsed) ? parsed : [];
177650
- } else {
177651
- const completePlatformConfig = getCompletePlatformConfig(platformConfig2);
177652
- const result = await generateCircuitJson({
177653
- filePath: file,
177654
- platformConfig: completePlatformConfig
177655
- });
177656
- circuitJson = result.circuitJson;
177657
- }
177658
- } catch (error) {
177659
- const errorMessage = error instanceof Error ? error.message : String(error);
177660
- onError(kleur_default.red(`
177661
- ❌ Failed to generate circuit JSON for ${relativeFilePath}:
177662
- `) + kleur_default.red(` ${errorMessage}
177663
- `));
177664
- return onExit2(1);
177940
+ const concurrencyValue = Math.max(1, concurrency);
177941
+ const processResult = (result) => {
177942
+ for (const warningMessage of result.warningMessages) {
177943
+ console.log(warningMessage);
177665
177944
  }
177666
- try {
177667
- pcbSvg = convertCircuitJsonToPcbSvg3(circuitJson);
177668
- } catch (error) {
177669
- const errorMessage = error instanceof Error ? error.message : String(error);
177670
- onError(kleur_default.red(`
177671
- ❌ Failed to generate PCB SVG for ${relativeFilePath}:
177672
- `) + kleur_default.red(` ${errorMessage}
177673
- `));
177674
- return onExit2(1);
177945
+ for (const successPath of result.successPaths) {
177946
+ console.log("✅", kleur_default.gray(successPath));
177675
177947
  }
177948
+ didUpdate = didUpdate || result.didUpdate;
177949
+ mismatches.push(...result.mismatches);
177950
+ };
177951
+ if (concurrencyValue > 1 && boardFiles.length > 1) {
177952
+ console.log(`Generating snapshots for ${boardFiles.length} file(s) with concurrency ${concurrencyValue}...`);
177953
+ let firstErrorMessage;
177676
177954
  try {
177677
- schSvg = convertCircuitJsonToSchematicSvg3(circuitJson);
177955
+ await snapshotFilesWithWorkerPool({
177956
+ files: boardFiles,
177957
+ projectDir,
177958
+ snapshotsDirName,
177959
+ concurrency: concurrencyValue,
177960
+ snapshotOptions: {
177961
+ update,
177962
+ threeD,
177963
+ pcbOnly,
177964
+ schematicOnly,
177965
+ forceUpdate,
177966
+ platformConfig: platformConfig2,
177967
+ createDiff,
177968
+ cameraPreset
177969
+ },
177970
+ stopOnFailure: true,
177971
+ onLog: (lines) => {
177972
+ for (const line2 of lines) {
177973
+ console.log(line2);
177974
+ }
177975
+ },
177976
+ onJobComplete: (jobResult) => {
177977
+ const { result } = jobResult;
177978
+ processResult(result);
177979
+ if (!result.ok && !firstErrorMessage) {
177980
+ firstErrorMessage = result.errorMessage ?? "Snapshot generation failed";
177981
+ }
177982
+ }
177983
+ });
177678
177984
  } catch (error) {
177679
177985
  const errorMessage = error instanceof Error ? error.message : String(error);
177680
- onError(kleur_default.red(`
177681
- ❌ Failed to generate schematic SVG for ${relativeFilePath}:
177682
- `) + kleur_default.red(` ${errorMessage}
177683
- `));
177986
+ onError(kleur_default.red(errorMessage));
177684
177987
  return onExit2(1);
177685
177988
  }
177686
- let png3d = null;
177687
- if (threeD) {
177688
- try {
177689
- const glbBuffer = await convertCircuitJsonToGltf5(circuitJson, getCircuitJsonToGltfOptions({ format: "glb" }));
177690
- if (!(glbBuffer instanceof ArrayBuffer)) {
177691
- throw new Error("Expected ArrayBuffer from convertCircuitJsonToGltf with glb format");
177692
- }
177693
- let cameraOptions = getBestCameraPosition(circuitJson);
177694
- if (cameraPreset) {
177695
- cameraOptions = applyCameraPreset(cameraPreset, cameraOptions);
177696
- }
177697
- png3d = await renderGLTFToPNGBufferFromGLBBuffer2(glbBuffer, cameraOptions);
177698
- } catch (error) {
177699
- const errorMessage = error instanceof Error ? error.message : String(error);
177700
- if (errorMessage.includes("No pcb_board found in circuit JSON")) {
177701
- const fileDir = path62.dirname(file);
177702
- const relativeDir = path62.relative(projectDir, fileDir);
177703
- const snapDir2 = snapshotsDirName ? path62.join(projectDir, snapshotsDirName, relativeDir) : path62.join(fileDir, "__snapshots__");
177704
- const base2 = path62.basename(file).replace(/\.[^.]+$/, "");
177705
- const snap3dPath = path62.join(snapDir2, `${base2}-3d.snap.png`);
177706
- const existing3dSnapshot = fs61.existsSync(snap3dPath);
177707
- if (existing3dSnapshot) {
177708
- onError(kleur_default.red(`
177709
- ❌ Failed to generate 3D snapshot for ${relativeFilePath}:
177710
- `) + kleur_default.red(` No pcb_board found in circuit JSON
177711
- `) + kleur_default.red(` Existing snapshot: ${path62.relative(projectDir, snap3dPath)}
177712
- `));
177713
- return onExit2(1);
177714
- } else {
177715
- console.log(kleur_default.red(`⚠️ Skipping 3D snapshot for ${relativeFilePath}:`) + kleur_default.red(` No pcb_board found in circuit JSON`));
177716
- png3d = null;
177717
- }
177718
- } else {
177719
- onError(kleur_default.red(`
177720
- ❌ Failed to generate 3D snapshot for ${relativeFilePath}:
177721
- `) + kleur_default.red(` ${errorMessage}
177722
- `));
177723
- return onExit2(1);
177724
- }
177725
- }
177726
- }
177727
- const snapDir = snapshotsDirName ? path62.join(projectDir, snapshotsDirName, path62.relative(projectDir, path62.dirname(file))) : path62.join(path62.dirname(file), "__snapshots__");
177728
- fs61.mkdirSync(snapDir, { recursive: true });
177729
- const base = path62.basename(file).replace(/\.[^.]+$/, "");
177730
- const snapshots = [];
177731
- if (pcbOnly || !schematicOnly) {
177732
- snapshots.push({ type: "pcb", content: pcbSvg, isBinary: false });
177733
- }
177734
- if (schematicOnly || !pcbOnly) {
177735
- snapshots.push({ type: "schematic", content: schSvg, isBinary: false });
177736
- }
177737
- if (threeD && png3d) {
177738
- snapshots.push({ type: "3d", content: png3d, isBinary: true });
177739
- }
177740
- if (!looksSame2) {
177741
- console.error("looks-same is required. Install it with 'bun add -d looks-same'");
177989
+ if (firstErrorMessage) {
177990
+ onError(firstErrorMessage);
177742
177991
  return onExit2(1);
177743
177992
  }
177744
- for (const snapshot of snapshots) {
177745
- const { type } = snapshot;
177746
- const is3d = type === "3d";
177747
- const snapPath = path62.join(snapDir, `${base}-${type}.snap.${is3d ? "png" : "svg"}`);
177748
- const existing = fs61.existsSync(snapPath);
177749
- const newContentBuffer = snapshot.isBinary ? snapshot.content : Buffer.from(snapshot.content, "utf8");
177750
- const newContentForFile = snapshot.content;
177751
- if (!existing) {
177752
- fs61.writeFileSync(snapPath, newContentForFile);
177753
- console.log("✅", kleur_default.gray(path62.relative(projectDir, snapPath)));
177754
- didUpdate = true;
177755
- continue;
177756
- }
177757
- const oldContentBuffer = fs61.readFileSync(snapPath);
177758
- const diffPath = snapPath.replace(is3d ? ".snap.png" : ".snap.svg", is3d ? ".diff.png" : ".diff.svg");
177759
- const { equal: equal2 } = await compareAndCreateDiff(oldContentBuffer, newContentBuffer, diffPath, createDiff);
177760
- if (update) {
177761
- if (!forceUpdate && equal2) {
177762
- console.log("✅", kleur_default.gray(path62.relative(projectDir, snapPath)));
177763
- } else {
177764
- fs61.writeFileSync(snapPath, newContentForFile);
177765
- console.log("✅", kleur_default.gray(path62.relative(projectDir, snapPath)));
177766
- didUpdate = true;
177767
- }
177768
- } else if (!equal2) {
177769
- mismatches.push(createDiff ? `${snapPath} (diff: ${diffPath})` : snapPath);
177770
- } else {
177771
- console.log("✅", kleur_default.gray(path62.relative(projectDir, snapPath)));
177993
+ } else {
177994
+ for (const file of boardFiles) {
177995
+ const result = await processSnapshotFile({
177996
+ file,
177997
+ projectDir,
177998
+ snapshotsDirName,
177999
+ update,
178000
+ threeD,
178001
+ pcbOnly,
178002
+ schematicOnly,
178003
+ forceUpdate,
178004
+ platformConfig: platformConfig2,
178005
+ createDiff,
178006
+ cameraPreset
178007
+ });
178008
+ processResult(result);
178009
+ if (!result.ok) {
178010
+ onError(result.errorMessage ?? "Snapshot generation failed");
178011
+ return onExit2(1);
177772
178012
  }
177773
178013
  }
177774
178014
  }
@@ -177790,12 +178030,13 @@ Run with --update to fix.`);
177790
178030
 
177791
178031
  // cli/snapshot/register.ts
177792
178032
  var registerSnapshot = (program3) => {
177793
- program3.command("snapshot").argument("[path]", "Path to file, directory, or glob pattern (e.g., 'examples/**/*.tsx')").description("Generate schematic and PCB snapshots (add --3d for 3d preview)").option("-u, --update", "Update snapshots on disk").option("--force-update", "Force update snapshots even if they match").option("--3d", "Generate 3d preview snapshots").option("--pcb-only", "Generate only PCB snapshots").option("--schematic-only", "Generate only schematic snapshots").option("--disable-parts-engine", "Disable the parts engine").option("--camera-preset <preset>", `Camera angle preset for 3D snapshots (implies --3d). Valid presets: ${CAMERA_PRESET_NAMES.join(", ")}`).option("--ci", "Enable CI mode with snapshot diff artifacts").option("--test", "Enable test mode with snapshot diff artifacts").action(async (target, options) => {
178033
+ program3.command("snapshot").argument("[path]", "Path to file, directory, or glob pattern (e.g., 'examples/**/*.tsx')").description("Generate schematic and PCB snapshots (add --3d for 3d preview)").option("-u, --update", "Update snapshots on disk").option("--force-update", "Force update snapshots even if they match").option("--3d", "Generate 3d preview snapshots").option("--pcb-only", "Generate only PCB snapshots").option("--schematic-only", "Generate only schematic snapshots").option("--disable-parts-engine", "Disable the parts engine").option("--camera-preset <preset>", `Camera angle preset for 3D snapshots (implies --3d). Valid presets: ${CAMERA_PRESET_NAMES.join(", ")}`).option("--ci", "Enable CI mode with snapshot diff artifacts").option("--test", "Enable test mode with snapshot diff artifacts").option("--concurrency <number>", "Number of files to snapshot in parallel (default: 1)", "1").action(async (target, options) => {
177794
178034
  if (options.cameraPreset && !CAMERA_PRESET_NAMES.includes(options.cameraPreset)) {
177795
178035
  console.error(`Unknown camera preset "${options.cameraPreset}". Valid presets: ${CAMERA_PRESET_NAMES.join(", ")}`);
177796
178036
  process.exit(1);
177797
178037
  }
177798
178038
  await snapshotProject({
178039
+ concurrency: Math.max(1, Number.parseInt(options.concurrency || "1", 10)),
177799
178040
  update: options.update ?? false,
177800
178041
  threeD: options["3d"] ?? false,
177801
178042
  pcbOnly: options.pcbOnly ?? false,
@@ -177813,7 +178054,7 @@ var registerSnapshot = (program3) => {
177813
178054
  };
177814
178055
 
177815
178056
  // cli/transpile/register.ts
177816
- import path63 from "node:path";
178057
+ import path66 from "node:path";
177817
178058
  var registerTranspile = (program3) => {
177818
178059
  program3.command("transpile").description("Transpile TypeScript/TSX to JavaScript (ESM, CommonJS, and type declarations)").argument("[file]", "Path to the entry file").action(async (file) => {
177819
178060
  try {
@@ -177821,7 +178062,7 @@ var registerTranspile = (program3) => {
177821
178062
  fileOrDir: file,
177822
178063
  includeBoardFiles: false
177823
178064
  });
177824
- const distDir = path63.join(projectDir, "dist");
178065
+ const distDir = path66.join(projectDir, "dist");
177825
178066
  validateMainInDist(projectDir, distDir);
177826
178067
  console.log("Transpiling entry file...");
177827
178068
  const entryFile = mainEntrypoint || circuitFiles[0];