@tscircuit/cli 0.1.730 → 0.1.732

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/main.js CHANGED
@@ -73245,6 +73245,7 @@ var projectConfigSchema = z.object({
73245
73245
  ignoredFiles: z.array(z.string()).optional(),
73246
73246
  includeBoardFiles: z.array(z.string()).optional(),
73247
73247
  snapshotsDir: z.string().optional(),
73248
+ prebuildCommand: z.string().optional(),
73248
73249
  buildCommand: z.string().optional(),
73249
73250
  build: z.object({
73250
73251
  circuitJson: z.boolean().optional(),
@@ -74124,7 +74125,7 @@ var getGlobalDepsInstallCommand = (packageManager, deps) => {
74124
74125
  import { execSync as execSync2 } from "node:child_process";
74125
74126
  var import_semver2 = __toESM2(require_semver2(), 1);
74126
74127
  // package.json
74127
- var version = "0.1.729";
74128
+ var version = "0.1.731";
74128
74129
  var package_default = {
74129
74130
  name: "@tscircuit/cli",
74130
74131
  version,
@@ -84815,11 +84816,12 @@ var availableGlobalConfigKeys = [
84815
84816
  var availableProjectConfigKeys = [
84816
84817
  "mainEntrypoint",
84817
84818
  "previewComponentPath",
84819
+ "prebuildCommand",
84818
84820
  "buildCommand"
84819
84821
  ];
84820
84822
  var registerConfigSet = (program3) => {
84821
84823
  const configCommand = program3.commands.find((c) => c.name() === "config");
84822
- configCommand.command("set").description("Set a configuration value (global or project-specific)").argument("<key>", "Configuration key (e.g., alwaysCloneWithAuthorName, mainEntrypoint, previewComponentPath, buildCommand)").argument("<value>", "Value to set").action((key, value) => {
84824
+ configCommand.command("set").description("Set a configuration value (global or project-specific)").argument("<key>", "Configuration key (e.g., alwaysCloneWithAuthorName, mainEntrypoint, previewComponentPath, prebuildCommand, buildCommand)").argument("<value>", "Value to set").action((key, value) => {
84823
84825
  if (availableGlobalConfigKeys.some((k) => k === key)) {
84824
84826
  if (key === "alwaysCloneWithAuthorName") {
84825
84827
  const booleanValue = value.toLowerCase() === "true";
@@ -84828,7 +84830,7 @@ var registerConfigSet = (program3) => {
84828
84830
  }
84829
84831
  } else if (availableProjectConfigKeys.some((k) => k === key)) {
84830
84832
  const projectDir = process.cwd();
84831
- if (key === "mainEntrypoint" || key === "previewComponentPath" || key === "buildCommand") {
84833
+ if (key === "mainEntrypoint" || key === "previewComponentPath" || key === "prebuildCommand" || key === "buildCommand") {
84832
84834
  const projectConfig = loadProjectConfig(projectDir) ?? {};
84833
84835
  projectConfig[key] = value;
84834
84836
  if (saveProjectConfig(projectConfig, projectDir)) {
@@ -187290,8 +187292,8 @@ var registerRemove = (program3) => {
187290
187292
  };
187291
187293
 
187292
187294
  // cli/build/register.ts
187293
- import path42 from "node:path";
187294
- import fs41 from "node:fs";
187295
+ import path44 from "node:path";
187296
+ import fs43 from "node:fs";
187295
187297
 
187296
187298
  // cli/build/build-file.ts
187297
187299
  import path34 from "node:path";
@@ -187425,21 +187427,156 @@ var logTypeReexportHint = (error, entryFilePath) => {
187425
187427
  `));
187426
187428
  };
187427
187429
 
187428
- // cli/build/get-build-entrypoints.ts
187430
+ // cli/build/build-ci.ts
187431
+ import { execSync as execSync3 } from "node:child_process";
187432
+
187433
+ // lib/shared/install-project-dependencies.ts
187434
+ import fs35 from "node:fs";
187435
+ import path36 from "node:path";
187436
+
187437
+ // lib/shared/collect-tsci-dependencies.ts
187429
187438
  import fs34 from "node:fs";
187430
187439
  import path35 from "node:path";
187440
+ var DEFAULT_PATTERNS = ["**/*.{ts,tsx,js,jsx}"];
187441
+ var DEFAULT_IGNORES = [
187442
+ "**/node_modules/**",
187443
+ "**/.git/**",
187444
+ "**/dist/**",
187445
+ "**/build/**",
187446
+ "**/.tsci/**"
187447
+ ];
187448
+ var IMPORT_PATTERN = /["'`](@tsci\/[A-Za-z0-9._/-]+)["'`]/g;
187449
+ function collectTsciDependencies({
187450
+ cwd = process.cwd(),
187451
+ patterns = DEFAULT_PATTERNS,
187452
+ ignore = DEFAULT_IGNORES
187453
+ } = {}) {
187454
+ const searchRoot = path35.resolve(cwd);
187455
+ const files = globbySync(patterns, {
187456
+ cwd: searchRoot,
187457
+ absolute: true,
187458
+ ignore,
187459
+ gitignore: true
187460
+ });
187461
+ const dependencies2 = new Set;
187462
+ for (const filePath of files) {
187463
+ try {
187464
+ const fileContents = fs34.readFileSync(filePath, "utf-8");
187465
+ let match;
187466
+ while (true) {
187467
+ match = IMPORT_PATTERN.exec(fileContents);
187468
+ if (match === null)
187469
+ break;
187470
+ dependencies2.add(match[1]);
187471
+ }
187472
+ } catch (error) {}
187473
+ }
187474
+ return Array.from(dependencies2);
187475
+ }
187476
+
187477
+ // lib/shared/install-project-dependencies.ts
187478
+ async function installProjectDependencies({
187479
+ cwd = process.cwd()
187480
+ } = {}) {
187481
+ const projectRoot = path36.resolve(cwd);
187482
+ const packageJsonPath = path36.join(projectRoot, "package.json");
187483
+ const npmrcPath = path36.join(projectRoot, ".npmrc");
187484
+ const packageManager = getPackageManager();
187485
+ if (!fs35.existsSync(projectRoot)) {
187486
+ throw new Error(`Directory not found: ${projectRoot}`);
187487
+ }
187488
+ let packageJsonCreated = false;
187489
+ if (!fs35.existsSync(packageJsonPath)) {
187490
+ console.log("No package.json found. Generating a new one.");
187491
+ generatePackageJson(projectRoot);
187492
+ packageJsonCreated = true;
187493
+ } else {
187494
+ console.log("Found existing package.json.");
187495
+ }
187496
+ if (!fs35.existsSync(npmrcPath)) {
187497
+ console.log("Creating .npmrc with tscircuit registry configuration.");
187498
+ fs35.writeFileSync(npmrcPath, "@tsci:registry=https://npm.tscircuit.com");
187499
+ }
187500
+ const packageJson = JSON.parse(fs35.readFileSync(packageJsonPath, "utf-8"));
187501
+ if (packageJsonCreated) {
187502
+ const tsciDependencies = collectTsciDependencies({ cwd: projectRoot });
187503
+ if (tsciDependencies.length > 0) {
187504
+ packageJson.dependencies = packageJson.dependencies || {};
187505
+ for (const dependency of tsciDependencies) {
187506
+ if (!packageJson.dependencies[dependency]) {
187507
+ packageJson.dependencies[dependency] = "latest";
187508
+ }
187509
+ }
187510
+ console.log(`Added ${tsciDependencies.length} @tsci dependencies to package.json.`);
187511
+ } else {
187512
+ console.log("No @tsci dependencies detected in circuit files.");
187513
+ }
187514
+ }
187515
+ fs35.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
187516
+ `);
187517
+ console.log(`Installing dependencies using ${kleur_default.bold(packageManager.name)}...`);
187518
+ try {
187519
+ packageManager.installAll({ cwd: projectRoot });
187520
+ console.log("Dependencies installed successfully.");
187521
+ } catch (error) {
187522
+ console.warn("Failed to automatically install dependencies.");
187523
+ console.warn(`Please run \`${packageManager.getInstallAllCommand()}\` manually.`);
187524
+ handleRegistryAuthError({ error, projectDir: projectRoot });
187525
+ throw error;
187526
+ }
187527
+ }
187528
+
187529
+ // cli/build/build-ci.ts
187530
+ var runCommand = (command, cwd) => {
187531
+ console.log(kleur_default.cyan(`Running: ${command}`));
187532
+ execSync3(command, { stdio: "inherit", cwd });
187533
+ };
187534
+ var applyCiBuildOptions = async ({
187535
+ projectDir,
187536
+ options
187537
+ }) => {
187538
+ if (!options?.ci) {
187539
+ return { resolvedOptions: options, handled: false };
187540
+ }
187541
+ await installProjectDependencies({ cwd: projectDir });
187542
+ const projectConfig = loadProjectConfig(projectDir);
187543
+ const prebuildCommand = projectConfig?.prebuildCommand?.trim();
187544
+ const buildCommand = projectConfig?.buildCommand?.trim();
187545
+ if (prebuildCommand) {
187546
+ runCommand(prebuildCommand, projectDir);
187547
+ }
187548
+ if (buildCommand) {
187549
+ runCommand(buildCommand, projectDir);
187550
+ return { resolvedOptions: options, handled: true };
187551
+ }
187552
+ return {
187553
+ resolvedOptions: {
187554
+ ...options,
187555
+ previewImages: options?.previewImages ?? true,
187556
+ transpile: options?.transpile ?? true,
187557
+ site: options?.site ?? true,
187558
+ useCdnJavascript: options?.useCdnJavascript ?? true,
187559
+ ignoreErrors: options?.ignoreErrors ?? true
187560
+ },
187561
+ handled: false
187562
+ };
187563
+ };
187564
+
187565
+ // cli/build/get-build-entrypoints.ts
187566
+ import fs36 from "node:fs";
187567
+ import path37 from "node:path";
187431
187568
  var isSubPath2 = (maybeChild, maybeParent) => {
187432
- const relative10 = path35.relative(maybeParent, maybeChild);
187433
- return relative10 === "" || !relative10.startsWith("..") && !path35.isAbsolute(relative10);
187569
+ const relative10 = path37.relative(maybeParent, maybeChild);
187570
+ return relative10 === "" || !relative10.startsWith("..") && !path37.isAbsolute(relative10);
187434
187571
  };
187435
187572
  var findProjectRoot = (startDir) => {
187436
187573
  let currentDir = startDir;
187437
- while (currentDir !== path35.dirname(currentDir)) {
187438
- const packageJsonPath = path35.join(currentDir, "package.json");
187439
- if (fs34.existsSync(packageJsonPath)) {
187574
+ while (currentDir !== path37.dirname(currentDir)) {
187575
+ const packageJsonPath = path37.join(currentDir, "package.json");
187576
+ if (fs36.existsSync(packageJsonPath)) {
187440
187577
  return currentDir;
187441
187578
  }
187442
- currentDir = path35.dirname(currentDir);
187579
+ currentDir = path37.dirname(currentDir);
187443
187580
  }
187444
187581
  return startDir;
187445
187582
  };
@@ -187448,11 +187585,11 @@ async function getBuildEntrypoints({
187448
187585
  rootDir = process.cwd(),
187449
187586
  includeBoardFiles = true
187450
187587
  }) {
187451
- const resolvedRoot = path35.resolve(rootDir);
187588
+ const resolvedRoot = path37.resolve(rootDir);
187452
187589
  const includeBoardFilePatterns = includeBoardFiles ? getBoardFilePatterns(resolvedRoot) : [];
187453
187590
  const buildFromProjectDir = async () => {
187454
187591
  const projectConfig = loadProjectConfig(resolvedRoot);
187455
- const resolvedPreviewComponentPath = projectConfig?.previewComponentPath ? path35.resolve(resolvedRoot, projectConfig.previewComponentPath) : undefined;
187592
+ const resolvedPreviewComponentPath = projectConfig?.previewComponentPath ? path37.resolve(resolvedRoot, projectConfig.previewComponentPath) : undefined;
187456
187593
  if (includeBoardFiles) {
187457
187594
  const files = findBoardFiles({ projectDir: resolvedRoot });
187458
187595
  if (files.length > 0) {
@@ -187487,10 +187624,10 @@ async function getBuildEntrypoints({
187487
187624
  };
187488
187625
  };
187489
187626
  if (fileOrDir) {
187490
- const resolved = path35.resolve(resolvedRoot, fileOrDir);
187491
- if (fs34.existsSync(resolved) && fs34.statSync(resolved).isDirectory()) {
187627
+ const resolved = path37.resolve(resolvedRoot, fileOrDir);
187628
+ if (fs36.existsSync(resolved) && fs36.statSync(resolved).isDirectory()) {
187492
187629
  const projectConfig2 = loadProjectConfig(resolvedRoot);
187493
- const resolvedPreviewComponentPath2 = projectConfig2?.previewComponentPath ? path35.resolve(resolvedRoot, projectConfig2.previewComponentPath) : undefined;
187630
+ const resolvedPreviewComponentPath2 = projectConfig2?.previewComponentPath ? path37.resolve(resolvedRoot, projectConfig2.previewComponentPath) : undefined;
187494
187631
  if (includeBoardFiles) {
187495
187632
  const circuitFiles = findBoardFiles({
187496
187633
  projectDir: resolvedRoot,
@@ -187522,10 +187659,10 @@ async function getBuildEntrypoints({
187522
187659
  circuitFiles: mainEntrypoint ? [mainEntrypoint] : []
187523
187660
  };
187524
187661
  }
187525
- const fileDir = path35.dirname(resolved);
187662
+ const fileDir = path37.dirname(resolved);
187526
187663
  const projectDir = findProjectRoot(fileDir);
187527
187664
  const projectConfig = loadProjectConfig(projectDir);
187528
- const resolvedPreviewComponentPath = projectConfig?.previewComponentPath ? path35.resolve(projectDir, projectConfig.previewComponentPath) : undefined;
187665
+ const resolvedPreviewComponentPath = projectConfig?.previewComponentPath ? path37.resolve(projectDir, projectConfig.previewComponentPath) : undefined;
187529
187666
  return {
187530
187667
  projectDir,
187531
187668
  previewComponentPath: resolvedPreviewComponentPath,
@@ -187567,8 +187704,8 @@ ${scriptBlock} <script src="https://cdn.tailwindcss.com"></script>
187567
187704
  };
187568
187705
 
187569
187706
  // cli/build/build-preview-images.ts
187570
- import fs35 from "node:fs";
187571
- import path36 from "node:path";
187707
+ import fs37 from "node:fs";
187708
+ import path38 from "node:path";
187572
187709
  import {
187573
187710
  convertCircuitJsonToPcbSvg as convertCircuitJsonToPcbSvg2,
187574
187711
  convertCircuitJsonToSchematicSvg as convertCircuitJsonToSchematicSvg2
@@ -187644,21 +187781,21 @@ var generatePreviewAssets = async ({
187644
187781
  outputDir,
187645
187782
  distDir
187646
187783
  }) => {
187647
- const prefixRelative = path36.relative(distDir, outputDir) || ".";
187784
+ const prefixRelative = path38.relative(distDir, outputDir) || ".";
187648
187785
  const prefix = prefixRelative === "." ? "" : `[${prefixRelative}] `;
187649
187786
  let circuitJson;
187650
187787
  try {
187651
- const circuitJsonRaw = fs35.readFileSync(build.outputPath, "utf-8");
187788
+ const circuitJsonRaw = fs37.readFileSync(build.outputPath, "utf-8");
187652
187789
  circuitJson = JSON.parse(circuitJsonRaw);
187653
187790
  } catch (error) {
187654
187791
  console.error(`${prefix}Failed to read circuit JSON:`, error);
187655
187792
  return;
187656
187793
  }
187657
- fs35.mkdirSync(outputDir, { recursive: true });
187794
+ fs37.mkdirSync(outputDir, { recursive: true });
187658
187795
  try {
187659
187796
  console.log(`${prefix}Generating PCB SVG...`);
187660
187797
  const pcbSvg = convertCircuitJsonToPcbSvg2(circuitJson);
187661
- fs35.writeFileSync(path36.join(outputDir, "pcb.svg"), pcbSvg, "utf-8");
187798
+ fs37.writeFileSync(path38.join(outputDir, "pcb.svg"), pcbSvg, "utf-8");
187662
187799
  console.log(`${prefix}Written pcb.svg`);
187663
187800
  } catch (error) {
187664
187801
  console.error(`${prefix}Failed to generate PCB SVG:`, error);
@@ -187666,7 +187803,7 @@ var generatePreviewAssets = async ({
187666
187803
  try {
187667
187804
  console.log(`${prefix}Generating schematic SVG...`);
187668
187805
  const schematicSvg = convertCircuitJsonToSchematicSvg2(circuitJson);
187669
- fs35.writeFileSync(path36.join(outputDir, "schematic.svg"), schematicSvg, "utf-8");
187806
+ fs37.writeFileSync(path38.join(outputDir, "schematic.svg"), schematicSvg, "utf-8");
187670
187807
  console.log(`${prefix}Written schematic.svg`);
187671
187808
  } catch (error) {
187672
187809
  console.error(`${prefix}Failed to generate schematic SVG:`, error);
@@ -187683,7 +187820,7 @@ var generatePreviewAssets = async ({
187683
187820
  camPos: [10, 10, 10],
187684
187821
  lookAt: [0, 0, 0]
187685
187822
  });
187686
- fs35.writeFileSync(path36.join(outputDir, "3d.png"), Buffer.from(normalizeToUint8Array(pngBuffer)));
187823
+ fs37.writeFileSync(path38.join(outputDir, "3d.png"), Buffer.from(normalizeToUint8Array(pngBuffer)));
187687
187824
  console.log(`${prefix}Written 3d.png`);
187688
187825
  } catch (error) {
187689
187826
  console.error(`${prefix}Failed to generate 3D PNG:`, error);
@@ -187698,14 +187835,14 @@ var buildPreviewImages = async ({
187698
187835
  }) => {
187699
187836
  const successfulBuilds = builtFiles.filter((file) => file.ok);
187700
187837
  const previewEntrypoint = previewComponentPath || mainEntrypoint;
187701
- const resolvedPreviewEntrypoint = previewEntrypoint ? path36.resolve(previewEntrypoint) : undefined;
187838
+ const resolvedPreviewEntrypoint = previewEntrypoint ? path38.resolve(previewEntrypoint) : undefined;
187702
187839
  if (allImages) {
187703
187840
  if (successfulBuilds.length === 0) {
187704
187841
  console.warn("No successful build output available for preview image generation.");
187705
187842
  return;
187706
187843
  }
187707
187844
  for (const build of successfulBuilds) {
187708
- const outputDir = path36.dirname(build.outputPath);
187845
+ const outputDir = path38.dirname(build.outputPath);
187709
187846
  await generatePreviewAssets({
187710
187847
  build,
187711
187848
  outputDir,
@@ -187716,7 +187853,7 @@ var buildPreviewImages = async ({
187716
187853
  }
187717
187854
  const previewBuild = (() => {
187718
187855
  if (resolvedPreviewEntrypoint) {
187719
- const match = successfulBuilds.find((built) => path36.resolve(built.sourcePath) === resolvedPreviewEntrypoint);
187856
+ const match = successfulBuilds.find((built) => path38.resolve(built.sourcePath) === resolvedPreviewEntrypoint);
187720
187857
  if (match)
187721
187858
  return match;
187722
187859
  }
@@ -187734,8 +187871,8 @@ var buildPreviewImages = async ({
187734
187871
  };
187735
187872
 
187736
187873
  // cli/build/build-preview-gltf.ts
187737
- import fs36 from "node:fs";
187738
- import path37 from "node:path";
187874
+ import fs38 from "node:fs";
187875
+ import path39 from "node:path";
187739
187876
  import { convertCircuitJsonToGltf as convertCircuitJsonToGltf3 } from "circuit-json-to-gltf";
187740
187877
  var buildPreviewGltf = async ({
187741
187878
  builtFiles,
@@ -187745,10 +187882,10 @@ var buildPreviewGltf = async ({
187745
187882
  }) => {
187746
187883
  const successfulBuilds = builtFiles.filter((file) => file.ok);
187747
187884
  const previewEntrypoint = previewComponentPath || mainEntrypoint;
187748
- const resolvedPreviewEntrypoint = previewEntrypoint ? path37.resolve(previewEntrypoint) : undefined;
187885
+ const resolvedPreviewEntrypoint = previewEntrypoint ? path39.resolve(previewEntrypoint) : undefined;
187749
187886
  const previewBuild = (() => {
187750
187887
  if (resolvedPreviewEntrypoint) {
187751
- const match = successfulBuilds.find((built) => path37.resolve(built.sourcePath) === resolvedPreviewEntrypoint);
187888
+ const match = successfulBuilds.find((built) => path39.resolve(built.sourcePath) === resolvedPreviewEntrypoint);
187752
187889
  if (match)
187753
187890
  return match;
187754
187891
  }
@@ -187760,16 +187897,16 @@ var buildPreviewGltf = async ({
187760
187897
  }
187761
187898
  let circuitJson;
187762
187899
  try {
187763
- const circuitJsonRaw = fs36.readFileSync(previewBuild.outputPath, "utf-8");
187900
+ const circuitJsonRaw = fs38.readFileSync(previewBuild.outputPath, "utf-8");
187764
187901
  circuitJson = JSON.parse(circuitJsonRaw);
187765
187902
  } catch (error) {
187766
187903
  console.error("Failed to read circuit JSON:", error);
187767
187904
  return;
187768
187905
  }
187769
187906
  const sourcePath = previewBuild.sourcePath;
187770
- const sourceBasename = path37.basename(sourcePath);
187907
+ const sourceBasename = path39.basename(sourcePath);
187771
187908
  const gltfFilename = sourceBasename.replace(/(\.(board|circuit))?\.tsx?$/, ".gltf");
187772
- const outputPath = path37.join(distDir, gltfFilename);
187909
+ const outputPath = path39.join(distDir, gltfFilename);
187773
187910
  try {
187774
187911
  console.log("Converting circuit to GLTF...");
187775
187912
  const circuitJsonWithFileUrls = convertModelUrlsToFileUrls(circuitJson);
@@ -187777,7 +187914,7 @@ var buildPreviewGltf = async ({
187777
187914
  format: "gltf"
187778
187915
  });
187779
187916
  const gltfContent = JSON.stringify(gltfData, null, 2);
187780
- fs36.writeFileSync(outputPath, gltfContent, "utf-8");
187917
+ fs38.writeFileSync(outputPath, gltfContent, "utf-8");
187781
187918
  console.log(`Written ${gltfFilename}`);
187782
187919
  } catch (error) {
187783
187920
  console.error("Failed to generate GLTF:", error);
@@ -187785,8 +187922,8 @@ var buildPreviewGltf = async ({
187785
187922
  };
187786
187923
 
187787
187924
  // cli/build/generate-kicad-project.ts
187788
- import fs37 from "node:fs";
187789
- import path38 from "node:path";
187925
+ import fs39 from "node:fs";
187926
+ import path40 from "node:path";
187790
187927
  var createKicadProContent = ({
187791
187928
  projectName,
187792
187929
  schematicFileName,
@@ -187826,10 +187963,10 @@ var generateKicadProject = async ({
187826
187963
  boardFileName
187827
187964
  });
187828
187965
  if (writeFiles) {
187829
- fs37.mkdirSync(outputDir, { recursive: true });
187830
- fs37.writeFileSync(path38.join(outputDir, schematicFileName), schContent);
187831
- fs37.writeFileSync(path38.join(outputDir, boardFileName), pcbContent);
187832
- fs37.writeFileSync(path38.join(outputDir, projectFileName), proContent);
187966
+ fs39.mkdirSync(outputDir, { recursive: true });
187967
+ fs39.writeFileSync(path40.join(outputDir, schematicFileName), schContent);
187968
+ fs39.writeFileSync(path40.join(outputDir, boardFileName), pcbContent);
187969
+ fs39.writeFileSync(path40.join(outputDir, projectFileName), proContent);
187833
187970
  }
187834
187971
  return {
187835
187972
  pcbContent,
@@ -187841,8 +187978,8 @@ var generateKicadProject = async ({
187841
187978
  };
187842
187979
 
187843
187980
  // cli/build/transpile/index.ts
187844
- import path40 from "node:path";
187845
- import fs39 from "node:fs";
187981
+ import path42 from "node:path";
187982
+ import fs41 from "node:fs";
187846
187983
  import { rollup } from "rollup";
187847
187984
  import typescript from "@rollup/plugin-typescript";
187848
187985
  import resolve11 from "@rollup/plugin-node-resolve";
@@ -187851,11 +187988,11 @@ import json from "@rollup/plugin-json";
187851
187988
  import dts from "rollup-plugin-dts";
187852
187989
 
187853
187990
  // cli/build/transpile/static-asset-plugin.ts
187854
- import fs38 from "node:fs";
187855
- import path39 from "node:path";
187991
+ import fs40 from "node:fs";
187992
+ import path41 from "node:path";
187856
187993
  import { createHash } from "node:crypto";
187857
187994
  function normalizePathSeparators(filePath) {
187858
- return filePath.split(path39.sep).join("/");
187995
+ return filePath.split(path41.sep).join("/");
187859
187996
  }
187860
187997
  var STATIC_ASSET_EXTENSIONS = new Set([
187861
187998
  ".glb",
@@ -187886,24 +188023,24 @@ var createStaticAssetPlugin = ({
187886
188023
  return {
187887
188024
  name: "tsci-static-assets",
187888
188025
  resolveId(source, importer) {
187889
- const ext = path39.extname(source).toLowerCase();
188026
+ const ext = path41.extname(source).toLowerCase();
187890
188027
  if (!STATIC_ASSET_EXTENSIONS.has(ext))
187891
188028
  return null;
187892
- if (path39.isAbsolute(source)) {
187893
- return fs38.existsSync(source) ? { id: normalizePathSeparators(source), external: true } : null;
188029
+ if (path41.isAbsolute(source)) {
188030
+ return fs40.existsSync(source) ? { id: normalizePathSeparators(source), external: true } : null;
187894
188031
  }
187895
188032
  if (importer) {
187896
- const importerNative = importer.split("/").join(path39.sep);
187897
- const resolvedFromImporter = path39.resolve(path39.dirname(importerNative), source);
187898
- if (fs38.existsSync(resolvedFromImporter)) {
188033
+ const importerNative = importer.split("/").join(path41.sep);
188034
+ const resolvedFromImporter = path41.resolve(path41.dirname(importerNative), source);
188035
+ if (fs40.existsSync(resolvedFromImporter)) {
187899
188036
  return {
187900
188037
  id: normalizePathSeparators(resolvedFromImporter),
187901
188038
  external: true
187902
188039
  };
187903
188040
  }
187904
188041
  }
187905
- const resolvedFromProject = path39.resolve(resolvedBaseUrl, source);
187906
- if (fs38.existsSync(resolvedFromProject)) {
188042
+ const resolvedFromProject = path41.resolve(resolvedBaseUrl, source);
188043
+ if (fs40.existsSync(resolvedFromProject)) {
187907
188044
  return {
187908
188045
  id: normalizePathSeparators(resolvedFromProject),
187909
188046
  external: true
@@ -187916,8 +188053,8 @@ var createStaticAssetPlugin = ({
187916
188053
  const wildcard = isWildcard ? source.slice(patternPrefix.length) : "";
187917
188054
  for (const target of targets) {
187918
188055
  const targetPath = isWildcard ? target.replace("*", wildcard) : target;
187919
- const resolvedTarget = path39.resolve(resolvedBaseUrl, targetPath);
187920
- if (fs38.existsSync(resolvedTarget)) {
188056
+ const resolvedTarget = path41.resolve(resolvedBaseUrl, targetPath);
188057
+ if (fs40.existsSync(resolvedTarget)) {
187921
188058
  return {
187922
188059
  id: normalizePathSeparators(resolvedTarget),
187923
188060
  external: true
@@ -187943,18 +188080,18 @@ var createStaticAssetPlugin = ({
187943
188080
  if (chunk.type !== "chunk")
187944
188081
  continue;
187945
188082
  for (const importedId of chunk.imports) {
187946
- const ext = path39.extname(importedId).toLowerCase();
188083
+ const ext = path41.extname(importedId).toLowerCase();
187947
188084
  if (!STATIC_ASSET_EXTENSIONS.has(ext))
187948
188085
  continue;
187949
188086
  if (!copiedAssets.has(importedId)) {
187950
- const assetDir = path39.join(outputDir, "assets");
187951
- fs38.mkdirSync(assetDir, { recursive: true });
187952
- const nativePath = importedId.split("/").join(path39.sep);
187953
- const fileBuffer = fs38.readFileSync(nativePath);
188087
+ const assetDir = path41.join(outputDir, "assets");
188088
+ fs40.mkdirSync(assetDir, { recursive: true });
188089
+ const nativePath = importedId.split("/").join(path41.sep);
188090
+ const fileBuffer = fs40.readFileSync(nativePath);
187954
188091
  const hash = createHash("sha1").update(fileBuffer).digest("hex").slice(0, 8);
187955
- const fileName = `${path39.basename(importedId, ext)}-${hash}${ext}`;
187956
- const outputFilePath = path39.join(assetDir, fileName);
187957
- fs38.writeFileSync(outputFilePath, fileBuffer);
188092
+ const fileName = `${path41.basename(importedId, ext)}-${hash}${ext}`;
188093
+ const outputFilePath = path41.join(assetDir, fileName);
188094
+ fs40.writeFileSync(outputFilePath, fileBuffer);
187958
188095
  copiedAssets.set(importedId, `./assets/${fileName}`);
187959
188096
  assetIdToOutputPath.set(importedId, `./assets/${fileName}`);
187960
188097
  }
@@ -187976,17 +188113,17 @@ function escapeRegExp(string) {
187976
188113
 
187977
188114
  // cli/build/transpile/index.ts
187978
188115
  var createExternalFunction = (projectDir, tsconfigPath) => (id2) => {
187979
- if (id2.startsWith(".") || id2.startsWith("/") || path40.isAbsolute(id2)) {
188116
+ if (id2.startsWith(".") || id2.startsWith("/") || path42.isAbsolute(id2)) {
187980
188117
  return false;
187981
188118
  }
187982
188119
  let baseUrl = projectDir;
187983
188120
  let pathMappings = {};
187984
- if (tsconfigPath && fs39.existsSync(tsconfigPath)) {
188121
+ if (tsconfigPath && fs41.existsSync(tsconfigPath)) {
187985
188122
  try {
187986
- const tsconfigContent = fs39.readFileSync(tsconfigPath, "utf-8");
188123
+ const tsconfigContent = fs41.readFileSync(tsconfigPath, "utf-8");
187987
188124
  const tsconfig = JSON.parse(tsconfigContent);
187988
188125
  if (tsconfig.compilerOptions?.baseUrl) {
187989
- baseUrl = path40.resolve(path40.dirname(tsconfigPath), tsconfig.compilerOptions.baseUrl);
188126
+ baseUrl = path42.resolve(path42.dirname(tsconfigPath), tsconfig.compilerOptions.baseUrl);
187990
188127
  }
187991
188128
  if (tsconfig.compilerOptions?.paths) {
187992
188129
  pathMappings = tsconfig.compilerOptions.paths;
@@ -188000,17 +188137,17 @@ var createExternalFunction = (projectDir, tsconfigPath) => (id2) => {
188000
188137
  }
188001
188138
  }
188002
188139
  const potentialPaths = [
188003
- path40.join(baseUrl, id2),
188004
- path40.join(baseUrl, `${id2}.ts`),
188005
- path40.join(baseUrl, `${id2}.tsx`),
188006
- path40.join(baseUrl, `${id2}.js`),
188007
- path40.join(baseUrl, `${id2}.jsx`),
188008
- path40.join(baseUrl, id2, "index.ts"),
188009
- path40.join(baseUrl, id2, "index.tsx"),
188010
- path40.join(baseUrl, id2, "index.js"),
188011
- path40.join(baseUrl, id2, "index.jsx")
188140
+ path42.join(baseUrl, id2),
188141
+ path42.join(baseUrl, `${id2}.ts`),
188142
+ path42.join(baseUrl, `${id2}.tsx`),
188143
+ path42.join(baseUrl, `${id2}.js`),
188144
+ path42.join(baseUrl, `${id2}.jsx`),
188145
+ path42.join(baseUrl, id2, "index.ts"),
188146
+ path42.join(baseUrl, id2, "index.tsx"),
188147
+ path42.join(baseUrl, id2, "index.js"),
188148
+ path42.join(baseUrl, id2, "index.jsx")
188012
188149
  ];
188013
- if (potentialPaths.some((p) => fs39.existsSync(p))) {
188150
+ if (potentialPaths.some((p) => fs41.existsSync(p))) {
188014
188151
  return false;
188015
188152
  }
188016
188153
  return true;
@@ -188021,17 +188158,17 @@ var transpileFile = async ({
188021
188158
  projectDir
188022
188159
  }) => {
188023
188160
  try {
188024
- fs39.mkdirSync(outputDir, { recursive: true });
188025
- const tsconfigPath = path40.join(projectDir, "tsconfig.json");
188026
- const hasTsConfig = fs39.existsSync(tsconfigPath);
188161
+ fs41.mkdirSync(outputDir, { recursive: true });
188162
+ const tsconfigPath = path42.join(projectDir, "tsconfig.json");
188163
+ const hasTsConfig = fs41.existsSync(tsconfigPath);
188027
188164
  let tsconfigBaseUrl = projectDir;
188028
188165
  let tsconfigPathMappings;
188029
188166
  if (hasTsConfig) {
188030
188167
  try {
188031
- const tsconfigContent = fs39.readFileSync(tsconfigPath, "utf-8");
188168
+ const tsconfigContent = fs41.readFileSync(tsconfigPath, "utf-8");
188032
188169
  const tsconfig = JSON.parse(tsconfigContent);
188033
188170
  if (tsconfig.compilerOptions?.baseUrl) {
188034
- tsconfigBaseUrl = path40.resolve(path40.dirname(tsconfigPath), tsconfig.compilerOptions.baseUrl);
188171
+ tsconfigBaseUrl = path42.resolve(path42.dirname(tsconfigPath), tsconfig.compilerOptions.baseUrl);
188035
188172
  }
188036
188173
  if (tsconfig.compilerOptions?.paths) {
188037
188174
  tsconfigPathMappings = tsconfig.compilerOptions.paths;
@@ -188086,27 +188223,27 @@ var transpileFile = async ({
188086
188223
  external: createExternalFunction(projectDir, hasTsConfig ? tsconfigPath : undefined),
188087
188224
  plugins: getPlugins()
188088
188225
  });
188089
- const esmOutputPath = path40.join(outputDir, "index.js");
188226
+ const esmOutputPath = path42.join(outputDir, "index.js");
188090
188227
  await esmBundle.write({
188091
188228
  file: esmOutputPath,
188092
188229
  format: "es",
188093
188230
  sourcemap: false
188094
188231
  });
188095
- console.log(`ESM bundle written to ${path40.relative(projectDir, esmOutputPath)}`);
188232
+ console.log(`ESM bundle written to ${path42.relative(projectDir, esmOutputPath)}`);
188096
188233
  console.log("Building CommonJS bundle...");
188097
188234
  const cjsBundle = await rollup({
188098
188235
  input,
188099
188236
  external: createExternalFunction(projectDir, hasTsConfig ? tsconfigPath : undefined),
188100
188237
  plugins: getPlugins()
188101
188238
  });
188102
- const cjsOutputPath = path40.join(outputDir, "index.cjs");
188239
+ const cjsOutputPath = path42.join(outputDir, "index.cjs");
188103
188240
  console.log("Writing CJS bundle to:", cjsOutputPath);
188104
188241
  await cjsBundle.write({
188105
188242
  file: cjsOutputPath,
188106
188243
  format: "cjs",
188107
188244
  sourcemap: false
188108
188245
  });
188109
- console.log(`CommonJS bundle written to ${path40.relative(projectDir, cjsOutputPath)}`);
188246
+ console.log(`CommonJS bundle written to ${path42.relative(projectDir, cjsOutputPath)}`);
188110
188247
  console.log("Generating type declarations...");
188111
188248
  const dtsBundle = await rollup({
188112
188249
  input,
@@ -188131,9 +188268,9 @@ var transpileFile = async ({
188131
188268
  dtsContent = dtsContent.replace(/import \* as [\w_]+ from ['"]react\/jsx-runtime['"];?\s*\n?/g, "");
188132
188269
  dtsContent = dtsContent.replace(/[\w_]+\.JSX\.Element/g, "any");
188133
188270
  dtsContent = dtsContent.replace(/export\s*{\s*};\s*$/gm, "").trim();
188134
- const dtsOutputPath = path40.join(outputDir, "index.d.ts");
188135
- fs39.writeFileSync(dtsOutputPath, dtsContent);
188136
- console.log(`Type declarations written to ${path40.relative(projectDir, dtsOutputPath)}`);
188271
+ const dtsOutputPath = path42.join(outputDir, "index.d.ts");
188272
+ fs41.writeFileSync(dtsOutputPath, dtsContent);
188273
+ console.log(`Type declarations written to ${path42.relative(projectDir, dtsOutputPath)}`);
188137
188274
  console.log(kleur_default.green("Transpilation complete!"));
188138
188275
  return true;
188139
188276
  } catch (err) {
@@ -188146,17 +188283,17 @@ var transpileFile = async ({
188146
188283
  };
188147
188284
 
188148
188285
  // cli/utils/validate-main-in-dist.ts
188149
- import fs40 from "node:fs";
188150
- import path41 from "node:path";
188286
+ import fs42 from "node:fs";
188287
+ import path43 from "node:path";
188151
188288
  var validateMainInDist = (projectDir, distDir) => {
188152
- const packageJsonPath = path41.join(projectDir, "package.json");
188153
- if (!fs40.existsSync(packageJsonPath))
188289
+ const packageJsonPath = path43.join(projectDir, "package.json");
188290
+ if (!fs42.existsSync(packageJsonPath))
188154
188291
  return;
188155
- const packageJson = JSON.parse(fs40.readFileSync(packageJsonPath, "utf-8"));
188292
+ const packageJson = JSON.parse(fs42.readFileSync(packageJsonPath, "utf-8"));
188156
188293
  if (typeof packageJson.main !== "string")
188157
188294
  return;
188158
- const resolvedMainPath = path41.resolve(projectDir, packageJson.main);
188159
- const isMainInDist = resolvedMainPath === distDir || resolvedMainPath.startsWith(`${distDir}${path41.sep}`);
188295
+ const resolvedMainPath = path43.resolve(projectDir, packageJson.main);
188296
+ const isMainInDist = resolvedMainPath === distDir || resolvedMainPath.startsWith(`${distDir}${path43.sep}`);
188160
188297
  if (!isMainInDist) {
188161
188298
  console.warn('When using transpilation, your package\'s "main" field should point inside the `dist/*` directory, usually to "dist/index.js"');
188162
188299
  }
@@ -188179,7 +188316,7 @@ async function getLatestTscircuitCdnUrl() {
188179
188316
 
188180
188317
  // cli/build/register.ts
188181
188318
  var registerBuild = (program3) => {
188182
- program3.command("build").description("Run tscircuit eval and output circuit json").argument("[file]", "Path to the entry file").option("--ignore-errors", "Do not exit with code 1 on errors").option("--ignore-warnings", "Do not log warnings").option("--disable-pcb", "Disable PCB outputs").option("--disable-parts-engine", "Disable the parts engine").option("--site", "Generate a static site in the dist directory").option("--transpile", "Transpile the entry file to JavaScript").option("--preview-images", "Generate preview images in the dist directory").option("--all-images", "Generate preview images for every successful build output").option("--kicad", "Generate KiCad project directories for each successful build output").option("--preview-gltf", "Generate a GLTF file from the preview entrypoint").option("--use-cdn-javascript", "Use CDN-hosted JavaScript instead of bundled standalone file for --site").action(async (file, options) => {
188319
+ program3.command("build").description("Run tscircuit eval and output circuit json").argument("[file]", "Path to the entry file").option("--ci", "Run install and optional prebuild/build commands (or default CI build)").option("--ignore-errors", "Do not exit with code 1 on errors").option("--ignore-warnings", "Do not log warnings").option("--disable-pcb", "Disable PCB outputs").option("--disable-parts-engine", "Disable the parts engine").option("--site", "Generate a static site in the dist directory").option("--transpile", "Transpile the entry file to JavaScript").option("--preview-images", "Generate preview images in the dist directory").option("--all-images", "Generate preview images for every successful build output").option("--kicad", "Generate KiCad project directories for each successful build output").option("--preview-gltf", "Generate a GLTF file from the preview entrypoint").option("--use-cdn-javascript", "Use CDN-hosted JavaScript instead of bundled standalone file for --site").action(async (file, options) => {
188183
188320
  try {
188184
188321
  const {
188185
188322
  projectDir,
@@ -188189,34 +188326,42 @@ var registerBuild = (program3) => {
188189
188326
  } = await getBuildEntrypoints({
188190
188327
  fileOrDir: file
188191
188328
  });
188329
+ const { resolvedOptions, handled } = await applyCiBuildOptions({
188330
+ projectDir,
188331
+ options
188332
+ });
188333
+ if (handled) {
188334
+ return;
188335
+ }
188192
188336
  const platformConfig2 = (() => {
188193
- if (!options?.disablePcb && !options?.disablePartsEngine)
188337
+ if (!resolvedOptions?.disablePcb && !resolvedOptions?.disablePartsEngine) {
188194
188338
  return;
188339
+ }
188195
188340
  const config = {};
188196
- if (options?.disablePcb) {
188341
+ if (resolvedOptions?.disablePcb) {
188197
188342
  config.pcbDisabled = true;
188198
188343
  }
188199
- if (options?.disablePartsEngine) {
188344
+ if (resolvedOptions?.disablePartsEngine) {
188200
188345
  config.partsEngineDisabled = true;
188201
188346
  }
188202
188347
  return config;
188203
188348
  })();
188204
- const distDir = path42.join(projectDir, "dist");
188205
- fs41.mkdirSync(distDir, { recursive: true });
188349
+ const distDir = path44.join(projectDir, "dist");
188350
+ fs43.mkdirSync(distDir, { recursive: true });
188206
188351
  console.log(`Building ${circuitFiles.length} file(s)...`);
188207
188352
  let hasErrors = false;
188208
188353
  const staticFileReferences = [];
188209
188354
  const builtFiles = [];
188210
188355
  const kicadProjects = [];
188211
- const shouldGenerateKicad = options?.kicad || options?.kicadFootprintLibrary;
188356
+ const shouldGenerateKicad = resolvedOptions?.kicad || resolvedOptions?.kicadFootprintLibrary;
188212
188357
  for (const filePath of circuitFiles) {
188213
- const relative10 = path42.relative(projectDir, filePath);
188358
+ const relative10 = path44.relative(projectDir, filePath);
188214
188359
  console.log(`Building ${relative10}...`);
188215
188360
  const outputDirName = relative10.replace(/(\.board|\.circuit)?\.tsx$/, "");
188216
- const outputPath = path42.join(distDir, outputDirName, "circuit.json");
188361
+ const outputPath = path44.join(distDir, outputDirName, "circuit.json");
188217
188362
  const buildOutcome = await buildFile(filePath, outputPath, projectDir, {
188218
- ignoreErrors: options?.ignoreErrors,
188219
- ignoreWarnings: options?.ignoreWarnings,
188363
+ ignoreErrors: resolvedOptions?.ignoreErrors,
188364
+ ignoreWarnings: resolvedOptions?.ignoreWarnings,
188220
188365
  platformConfig: platformConfig2
188221
188366
  });
188222
188367
  builtFiles.push({
@@ -188226,23 +188371,23 @@ var registerBuild = (program3) => {
188226
188371
  });
188227
188372
  if (!buildOutcome.ok) {
188228
188373
  hasErrors = true;
188229
- } else if (options?.site) {
188230
- const normalizedSourcePath = relative10.split(path42.sep).join("/");
188231
- const relativeOutputPath = path42.join(outputDirName, "circuit.json");
188232
- const normalizedOutputPath = relativeOutputPath.split(path42.sep).join("/");
188374
+ } else if (resolvedOptions?.site) {
188375
+ const normalizedSourcePath = relative10.split(path44.sep).join("/");
188376
+ const relativeOutputPath = path44.join(outputDirName, "circuit.json");
188377
+ const normalizedOutputPath = relativeOutputPath.split(path44.sep).join("/");
188233
188378
  staticFileReferences.push({
188234
188379
  filePath: normalizedSourcePath,
188235
188380
  fileStaticAssetUrl: `./${normalizedOutputPath}`
188236
188381
  });
188237
188382
  }
188238
188383
  if (buildOutcome.ok && shouldGenerateKicad && buildOutcome.circuitJson) {
188239
- const projectOutputDir = path42.join(distDir, outputDirName, "kicad");
188240
- const projectName = path42.basename(outputDirName);
188384
+ const projectOutputDir = path44.join(distDir, outputDirName, "kicad");
188385
+ const projectName = path44.basename(outputDirName);
188241
188386
  const project = await generateKicadProject({
188242
188387
  circuitJson: buildOutcome.circuitJson,
188243
188388
  outputDir: projectOutputDir,
188244
188389
  projectName,
188245
- writeFiles: Boolean(options?.kicad)
188390
+ writeFiles: Boolean(resolvedOptions?.kicad)
188246
188391
  });
188247
188392
  kicadProjects.push({
188248
188393
  ...project,
@@ -188250,21 +188395,21 @@ var registerBuild = (program3) => {
188250
188395
  });
188251
188396
  }
188252
188397
  }
188253
- if (hasErrors && !options?.ignoreErrors) {
188398
+ if (hasErrors && !resolvedOptions?.ignoreErrors) {
188254
188399
  process.exit(1);
188255
188400
  }
188256
- const shouldGeneratePreviewImages = options?.previewImages || options?.allImages;
188401
+ const shouldGeneratePreviewImages = resolvedOptions?.previewImages || resolvedOptions?.allImages;
188257
188402
  if (shouldGeneratePreviewImages) {
188258
- console.log(options?.allImages ? "Generating preview images for all builds..." : "Generating preview images...");
188403
+ console.log(resolvedOptions?.allImages ? "Generating preview images for all builds..." : "Generating preview images...");
188259
188404
  await buildPreviewImages({
188260
188405
  builtFiles,
188261
188406
  distDir,
188262
188407
  mainEntrypoint,
188263
188408
  previewComponentPath,
188264
- allImages: options?.allImages
188409
+ allImages: resolvedOptions?.allImages
188265
188410
  });
188266
188411
  }
188267
- if (options?.previewGltf) {
188412
+ if (resolvedOptions?.previewGltf) {
188268
188413
  console.log("Generating preview GLTF...");
188269
188414
  await buildPreviewGltf({
188270
188415
  builtFiles,
@@ -188273,7 +188418,7 @@ var registerBuild = (program3) => {
188273
188418
  previewComponentPath
188274
188419
  });
188275
188420
  }
188276
- if (options?.transpile) {
188421
+ if (resolvedOptions?.transpile) {
188277
188422
  validateMainInDist(projectDir, distDir);
188278
188423
  console.log("Transpiling entry file...");
188279
188424
  const { mainEntrypoint: transpileEntrypoint } = await getBuildEntrypoints({
@@ -188295,28 +188440,28 @@ var registerBuild = (program3) => {
188295
188440
  process.exit(1);
188296
188441
  }
188297
188442
  }
188298
- if (options?.site) {
188443
+ if (resolvedOptions?.site) {
188299
188444
  let standaloneScriptSrc = "./standalone.min.js";
188300
- if (options?.useCdnJavascript) {
188445
+ if (resolvedOptions?.useCdnJavascript) {
188301
188446
  standaloneScriptSrc = await getLatestTscircuitCdnUrl();
188302
188447
  } else {
188303
- fs41.writeFileSync(path42.join(distDir, "standalone.min.js"), standalone_min_default);
188448
+ fs43.writeFileSync(path44.join(distDir, "standalone.min.js"), standalone_min_default);
188304
188449
  }
188305
188450
  const indexHtml = getStaticIndexHtmlFile({
188306
188451
  files: staticFileReferences,
188307
188452
  standaloneScriptSrc
188308
188453
  });
188309
- fs41.writeFileSync(path42.join(distDir, "index.html"), indexHtml);
188454
+ fs43.writeFileSync(path44.join(distDir, "index.html"), indexHtml);
188310
188455
  }
188311
188456
  const successCount = builtFiles.filter((f) => f.ok).length;
188312
188457
  const failCount = builtFiles.length - successCount;
188313
188458
  const enabledOpts = [
188314
- options?.site && "site",
188315
- options?.transpile && "transpile",
188316
- options?.previewImages && "preview-images",
188317
- options?.allImages && "all-images",
188318
- options?.kicad && "kicad",
188319
- options?.previewGltf && "preview-gltf"
188459
+ resolvedOptions?.site && "site",
188460
+ resolvedOptions?.transpile && "transpile",
188461
+ resolvedOptions?.previewImages && "preview-images",
188462
+ resolvedOptions?.allImages && "all-images",
188463
+ resolvedOptions?.kicad && "kicad",
188464
+ resolvedOptions?.previewGltf && "preview-gltf"
188320
188465
  ].filter(Boolean);
188321
188466
  console.log("");
188322
188467
  console.log(kleur_default.bold("Build complete"));
@@ -188324,7 +188469,7 @@ var registerBuild = (program3) => {
188324
188469
  if (enabledOpts.length > 0) {
188325
188470
  console.log(` Options ${kleur_default.cyan(enabledOpts.join(", "))}`);
188326
188471
  }
188327
- console.log(` Output ${kleur_default.dim(path42.relative(process.cwd(), distDir) || "dist")}`);
188472
+ console.log(` Output ${kleur_default.dim(path44.relative(process.cwd(), distDir) || "dist")}`);
188328
188473
  console.log(hasErrors ? kleur_default.yellow(`
188329
188474
  ⚠ Build completed with errors`) : kleur_default.green(`
188330
188475
  ✓ Done`));
@@ -188338,8 +188483,8 @@ var registerBuild = (program3) => {
188338
188483
  };
188339
188484
 
188340
188485
  // lib/shared/snapshot-project.ts
188341
- import fs43 from "node:fs";
188342
- import path43 from "node:path";
188486
+ import fs45 from "node:fs";
188487
+ import path45 from "node:path";
188343
188488
  import looksSame2 from "looks-same";
188344
188489
  import {
188345
188490
  convertCircuitJsonToPcbSvg as convertCircuitJsonToPcbSvg3,
@@ -188350,7 +188495,7 @@ import { renderGLTFToPNGBufferFromGLBBuffer as renderGLTFToPNGBufferFromGLBBuffe
188350
188495
 
188351
188496
  // lib/shared/compare-images.ts
188352
188497
  import looksSame from "looks-same";
188353
- import fs42 from "node:fs/promises";
188498
+ import fs44 from "node:fs/promises";
188354
188499
  var compareAndCreateDiff = async (buffer1, buffer2, diffPath) => {
188355
188500
  const { equal: equal2 } = await looksSame(buffer1, buffer2, {
188356
188501
  strict: false,
@@ -188366,7 +188511,7 @@ var compareAndCreateDiff = async (buffer1, buffer2, diffPath) => {
188366
188511
  tolerance: 2
188367
188512
  });
188368
188513
  } else {
188369
- await fs42.writeFile(diffPath, buffer2);
188514
+ await fs44.writeFile(diffPath, buffer2);
188370
188515
  }
188371
188516
  }
188372
188517
  return { equal: equal2 };
@@ -188391,7 +188536,7 @@ var snapshotProject = async ({
188391
188536
  ...DEFAULT_IGNORED_PATTERNS,
188392
188537
  ...ignored.map(normalizeIgnorePattern)
188393
188538
  ];
188394
- const resolvedPaths = filePaths.map((f) => path43.resolve(projectDir, f));
188539
+ const resolvedPaths = filePaths.map((f) => path45.resolve(projectDir, f));
188395
188540
  const boardFiles = findBoardFiles({
188396
188541
  projectDir,
188397
188542
  ignore,
@@ -188405,7 +188550,7 @@ var snapshotProject = async ({
188405
188550
  const mismatches = [];
188406
188551
  let didUpdate = false;
188407
188552
  for (const file of boardFiles) {
188408
- const relativeFilePath = path43.relative(projectDir, file);
188553
+ const relativeFilePath = path45.relative(projectDir, file);
188409
188554
  let circuitJson;
188410
188555
  let pcbSvg;
188411
188556
  let schSvg;
@@ -188460,17 +188605,17 @@ var snapshotProject = async ({
188460
188605
  } catch (error) {
188461
188606
  const errorMessage = error instanceof Error ? error.message : String(error);
188462
188607
  if (errorMessage.includes("No pcb_board found in circuit JSON")) {
188463
- const fileDir = path43.dirname(file);
188464
- const relativeDir = path43.relative(projectDir, fileDir);
188465
- const snapDir2 = snapshotsDirName ? path43.join(projectDir, snapshotsDirName, relativeDir) : path43.join(fileDir, "__snapshots__");
188466
- const base2 = path43.basename(file).replace(/\.tsx$/, "");
188467
- const snap3dPath = path43.join(snapDir2, `${base2}-3d.snap.png`);
188468
- const existing3dSnapshot = fs43.existsSync(snap3dPath);
188608
+ const fileDir = path45.dirname(file);
188609
+ const relativeDir = path45.relative(projectDir, fileDir);
188610
+ const snapDir2 = snapshotsDirName ? path45.join(projectDir, snapshotsDirName, relativeDir) : path45.join(fileDir, "__snapshots__");
188611
+ const base2 = path45.basename(file).replace(/\.tsx$/, "");
188612
+ const snap3dPath = path45.join(snapDir2, `${base2}-3d.snap.png`);
188613
+ const existing3dSnapshot = fs45.existsSync(snap3dPath);
188469
188614
  if (existing3dSnapshot) {
188470
188615
  onError(kleur_default.red(`
188471
188616
  ❌ Failed to generate 3D snapshot for ${relativeFilePath}:
188472
188617
  `) + kleur_default.red(` No pcb_board found in circuit JSON
188473
- `) + kleur_default.red(` Existing snapshot: ${path43.relative(projectDir, snap3dPath)}
188618
+ `) + kleur_default.red(` Existing snapshot: ${path45.relative(projectDir, snap3dPath)}
188474
188619
  `));
188475
188620
  return onExit2(1);
188476
188621
  } else {
@@ -188486,9 +188631,9 @@ var snapshotProject = async ({
188486
188631
  }
188487
188632
  }
188488
188633
  }
188489
- const snapDir = snapshotsDirName ? path43.join(projectDir, snapshotsDirName, path43.relative(projectDir, path43.dirname(file))) : path43.join(path43.dirname(file), "__snapshots__");
188490
- fs43.mkdirSync(snapDir, { recursive: true });
188491
- const base = path43.basename(file).replace(/\.tsx$/, "");
188634
+ const snapDir = snapshotsDirName ? path45.join(projectDir, snapshotsDirName, path45.relative(projectDir, path45.dirname(file))) : path45.join(path45.dirname(file), "__snapshots__");
188635
+ fs45.mkdirSync(snapDir, { recursive: true });
188636
+ const base = path45.basename(file).replace(/\.tsx$/, "");
188492
188637
  const snapshots = [];
188493
188638
  if (pcbOnly || !schematicOnly) {
188494
188639
  snapshots.push({ type: "pcb", content: pcbSvg, isBinary: false });
@@ -188506,31 +188651,31 @@ var snapshotProject = async ({
188506
188651
  for (const snapshot of snapshots) {
188507
188652
  const { type } = snapshot;
188508
188653
  const is3d = type === "3d";
188509
- const snapPath = path43.join(snapDir, `${base}-${type}.snap.${is3d ? "png" : "svg"}`);
188510
- const existing = fs43.existsSync(snapPath);
188654
+ const snapPath = path45.join(snapDir, `${base}-${type}.snap.${is3d ? "png" : "svg"}`);
188655
+ const existing = fs45.existsSync(snapPath);
188511
188656
  const newContentBuffer = snapshot.isBinary ? snapshot.content : Buffer.from(snapshot.content, "utf8");
188512
188657
  const newContentForFile = snapshot.content;
188513
188658
  if (!existing) {
188514
- fs43.writeFileSync(snapPath, newContentForFile);
188515
- console.log("✅", kleur_default.gray(path43.relative(projectDir, snapPath)));
188659
+ fs45.writeFileSync(snapPath, newContentForFile);
188660
+ console.log("✅", kleur_default.gray(path45.relative(projectDir, snapPath)));
188516
188661
  didUpdate = true;
188517
188662
  continue;
188518
188663
  }
188519
- const oldContentBuffer = fs43.readFileSync(snapPath);
188664
+ const oldContentBuffer = fs45.readFileSync(snapPath);
188520
188665
  const diffPath = snapPath.replace(is3d ? ".snap.png" : ".snap.svg", is3d ? ".diff.png" : ".diff.svg");
188521
188666
  const { equal: equal2 } = await compareAndCreateDiff(oldContentBuffer, newContentBuffer, diffPath);
188522
188667
  if (update) {
188523
188668
  if (!forceUpdate && equal2) {
188524
- console.log("✅", kleur_default.gray(path43.relative(projectDir, snapPath)));
188669
+ console.log("✅", kleur_default.gray(path45.relative(projectDir, snapPath)));
188525
188670
  } else {
188526
- fs43.writeFileSync(snapPath, newContentForFile);
188527
- console.log("✅", kleur_default.gray(path43.relative(projectDir, snapPath)));
188671
+ fs45.writeFileSync(snapPath, newContentForFile);
188672
+ console.log("✅", kleur_default.gray(path45.relative(projectDir, snapPath)));
188528
188673
  didUpdate = true;
188529
188674
  }
188530
188675
  } else if (!equal2) {
188531
188676
  mismatches.push(`${snapPath} (diff: ${diffPath})`);
188532
188677
  } else {
188533
- console.log("✅", kleur_default.gray(path43.relative(projectDir, snapPath)));
188678
+ console.log("✅", kleur_default.gray(path45.relative(projectDir, snapPath)));
188534
188679
  }
188535
188680
  }
188536
188681
  }
@@ -188569,22 +188714,22 @@ var registerSnapshot = (program3) => {
188569
188714
  };
188570
188715
 
188571
188716
  // lib/shared/setup-github-actions.ts
188572
- import fs44 from "node:fs";
188573
- import path44 from "node:path";
188717
+ import fs46 from "node:fs";
188718
+ import path46 from "node:path";
188574
188719
  var setupGithubActions = (projectDir = process.cwd()) => {
188575
188720
  const findGitRoot = (startDir) => {
188576
- let dir = path44.resolve(startDir);
188577
- while (dir !== path44.parse(dir).root) {
188578
- if (fs44.existsSync(path44.join(dir, ".git"))) {
188721
+ let dir = path46.resolve(startDir);
188722
+ while (dir !== path46.parse(dir).root) {
188723
+ if (fs46.existsSync(path46.join(dir, ".git"))) {
188579
188724
  return dir;
188580
188725
  }
188581
- dir = path44.dirname(dir);
188726
+ dir = path46.dirname(dir);
188582
188727
  }
188583
188728
  return null;
188584
188729
  };
188585
188730
  const gitRoot = findGitRoot(projectDir) ?? projectDir;
188586
- const workflowsDir = path44.join(gitRoot, ".github", "workflows");
188587
- fs44.mkdirSync(workflowsDir, { recursive: true });
188731
+ const workflowsDir = path46.join(gitRoot, ".github", "workflows");
188732
+ fs46.mkdirSync(workflowsDir, { recursive: true });
188588
188733
  const buildWorkflow = `name: tscircuit Build
188589
188734
 
188590
188735
  on:
@@ -188623,8 +188768,8 @@ jobs:
188623
188768
  - run: bun install
188624
188769
  - run: bunx tsci snapshot
188625
188770
  `;
188626
- writeFileIfNotExists(path44.join(workflowsDir, "tscircuit-build.yml"), buildWorkflow);
188627
- writeFileIfNotExists(path44.join(workflowsDir, "tscircuit-snapshot.yml"), snapshotWorkflow);
188771
+ writeFileIfNotExists(path46.join(workflowsDir, "tscircuit-build.yml"), buildWorkflow);
188772
+ writeFileIfNotExists(path46.join(workflowsDir, "tscircuit-snapshot.yml"), snapshotWorkflow);
188628
188773
  };
188629
188774
 
188630
188775
  // cli/setup/register.ts
@@ -188662,8 +188807,8 @@ function registerAuthSetupNpmrc(program3) {
188662
188807
  }
188663
188808
 
188664
188809
  // cli/convert/register.ts
188665
- import fs45 from "node:fs/promises";
188666
- import path45 from "node:path";
188810
+ import fs47 from "node:fs/promises";
188811
+ import path47 from "node:path";
188667
188812
  import { parseKicadModToCircuitJson } from "kicad-component-converter";
188668
188813
 
188669
188814
  // node_modules/@tscircuit/mm/dist/index.js
@@ -188783,15 +188928,15 @@ var convertCircuitJsonToTscircuit = (circuitJson, opts) => {
188783
188928
  var registerConvert = (program3) => {
188784
188929
  program3.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) => {
188785
188930
  try {
188786
- const inputPath = path45.resolve(file);
188787
- const modContent = await fs45.readFile(inputPath, "utf-8");
188931
+ const inputPath = path47.resolve(file);
188932
+ const modContent = await fs47.readFile(inputPath, "utf-8");
188788
188933
  const circuitJson = await parseKicadModToCircuitJson(modContent);
188789
- const componentName = options.name ?? path45.basename(inputPath, ".kicad_mod");
188934
+ const componentName = options.name ?? path47.basename(inputPath, ".kicad_mod");
188790
188935
  const tsx = convertCircuitJsonToTscircuit(circuitJson, {
188791
188936
  componentName
188792
188937
  });
188793
- const outputPath = options.output ? path45.resolve(options.output) : path45.join(path45.dirname(inputPath), `${componentName}.tsx`);
188794
- await fs45.writeFile(outputPath, tsx);
188938
+ const outputPath = options.output ? path47.resolve(options.output) : path47.join(path47.dirname(inputPath), `${componentName}.tsx`);
188939
+ await fs47.writeFile(outputPath, tsx);
188795
188940
  console.log(kleur_default.green(`Converted ${outputPath}`));
188796
188941
  } catch (error) {
188797
188942
  console.error(kleur_default.red("Failed to convert footprint:"), error instanceof Error ? error.message : error);
@@ -188886,102 +189031,6 @@ var registerSimulate = (program3) => {
188886
189031
  });
188887
189032
  };
188888
189033
 
188889
- // lib/shared/install-project-dependencies.ts
188890
- import fs47 from "node:fs";
188891
- import path47 from "node:path";
188892
-
188893
- // lib/shared/collect-tsci-dependencies.ts
188894
- import fs46 from "node:fs";
188895
- import path46 from "node:path";
188896
- var DEFAULT_PATTERNS = ["**/*.{ts,tsx,js,jsx}"];
188897
- var DEFAULT_IGNORES = [
188898
- "**/node_modules/**",
188899
- "**/.git/**",
188900
- "**/dist/**",
188901
- "**/build/**",
188902
- "**/.tsci/**"
188903
- ];
188904
- var IMPORT_PATTERN = /["'`](@tsci\/[A-Za-z0-9._/-]+)["'`]/g;
188905
- function collectTsciDependencies({
188906
- cwd = process.cwd(),
188907
- patterns = DEFAULT_PATTERNS,
188908
- ignore = DEFAULT_IGNORES
188909
- } = {}) {
188910
- const searchRoot = path46.resolve(cwd);
188911
- const files = globbySync(patterns, {
188912
- cwd: searchRoot,
188913
- absolute: true,
188914
- ignore,
188915
- gitignore: true
188916
- });
188917
- const dependencies2 = new Set;
188918
- for (const filePath of files) {
188919
- try {
188920
- const fileContents = fs46.readFileSync(filePath, "utf-8");
188921
- let match;
188922
- while (true) {
188923
- match = IMPORT_PATTERN.exec(fileContents);
188924
- if (match === null)
188925
- break;
188926
- dependencies2.add(match[1]);
188927
- }
188928
- } catch (error) {}
188929
- }
188930
- return Array.from(dependencies2);
188931
- }
188932
-
188933
- // lib/shared/install-project-dependencies.ts
188934
- async function installProjectDependencies({
188935
- cwd = process.cwd()
188936
- } = {}) {
188937
- const projectRoot = path47.resolve(cwd);
188938
- const packageJsonPath = path47.join(projectRoot, "package.json");
188939
- const npmrcPath = path47.join(projectRoot, ".npmrc");
188940
- const packageManager = getPackageManager();
188941
- if (!fs47.existsSync(projectRoot)) {
188942
- throw new Error(`Directory not found: ${projectRoot}`);
188943
- }
188944
- let packageJsonCreated = false;
188945
- if (!fs47.existsSync(packageJsonPath)) {
188946
- console.log("No package.json found. Generating a new one.");
188947
- generatePackageJson(projectRoot);
188948
- packageJsonCreated = true;
188949
- } else {
188950
- console.log("Found existing package.json.");
188951
- }
188952
- if (!fs47.existsSync(npmrcPath)) {
188953
- console.log("Creating .npmrc with tscircuit registry configuration.");
188954
- fs47.writeFileSync(npmrcPath, "@tsci:registry=https://npm.tscircuit.com");
188955
- }
188956
- const packageJson = JSON.parse(fs47.readFileSync(packageJsonPath, "utf-8"));
188957
- if (packageJsonCreated) {
188958
- const tsciDependencies = collectTsciDependencies({ cwd: projectRoot });
188959
- if (tsciDependencies.length > 0) {
188960
- packageJson.dependencies = packageJson.dependencies || {};
188961
- for (const dependency of tsciDependencies) {
188962
- if (!packageJson.dependencies[dependency]) {
188963
- packageJson.dependencies[dependency] = "latest";
188964
- }
188965
- }
188966
- console.log(`Added ${tsciDependencies.length} @tsci dependencies to package.json.`);
188967
- } else {
188968
- console.log("No @tsci dependencies detected in circuit files.");
188969
- }
188970
- }
188971
- fs47.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
188972
- `);
188973
- console.log(`Installing dependencies using ${kleur_default.bold(packageManager.name)}...`);
188974
- try {
188975
- packageManager.installAll({ cwd: projectRoot });
188976
- console.log("Dependencies installed successfully.");
188977
- } catch (error) {
188978
- console.warn("Failed to automatically install dependencies.");
188979
- console.warn(`Please run \`${packageManager.getInstallAllCommand()}\` manually.`);
188980
- handleRegistryAuthError({ error, projectDir: projectRoot });
188981
- throw error;
188982
- }
188983
- }
188984
-
188985
189034
  // cli/install/register.ts
188986
189035
  var registerInstall = (program3) => {
188987
189036
  program3.command("install [packageSpec]").description("Install project dependencies, or install a specific package (e.g., tsci install https://github.com/espressif/kicad-libraries)").action(async (packageSpec) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/cli",
3
- "version": "0.1.730",
3
+ "version": "0.1.732",
4
4
  "main": "dist/main.js",
5
5
  "devDependencies": {
6
6
  "@babel/standalone": "^7.26.9",
@@ -36,6 +36,10 @@
36
36
  "type": "string",
37
37
  "description": "Directory path for storing snapshots."
38
38
  },
39
+ "prebuildCommand": {
40
+ "type": "string",
41
+ "description": "Command to run before builds."
42
+ },
39
43
  "buildCommand": {
40
44
  "type": "string",
41
45
  "description": "Override command used for cloud builds."