@tscircuit/cli 0.1.980 → 0.1.982

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
@@ -74395,7 +74395,7 @@ var getGlobalDepsInstallCommand = (packageManager, deps) => {
74395
74395
  import { execSync as execSync2 } from "node:child_process";
74396
74396
  var import_semver2 = __toESM2(require_semver2(), 1);
74397
74397
  // package.json
74398
- var version = "0.1.978";
74398
+ var version = "0.1.981";
74399
74399
  var package_default = {
74400
74400
  name: "@tscircuit/cli",
74401
74401
  main: "dist/cli/main.js",
@@ -174707,8 +174707,8 @@ var applyCiBuildOptions = async ({
174707
174707
  };
174708
174708
 
174709
174709
  // cli/build/build-file.ts
174710
- import path45 from "node:path";
174711
174710
  import fs45 from "node:fs";
174711
+ import path45 from "node:path";
174712
174712
 
174713
174713
  // lib/shared/circuit-json-diagnostics.ts
174714
174714
  function analyzeCircuitJson(circuitJson) {
@@ -174808,15 +174808,24 @@ function getCompletePlatformConfig(userConfig) {
174808
174808
  var buildFile = async (input, output, projectDir, options) => {
174809
174809
  try {
174810
174810
  console.log("Generating circuit JSON...");
174811
+ const isPrebuiltCircuitJson = input.toLowerCase().endsWith(".circuit.json");
174812
+ let circuitJson = [];
174813
+ if (isPrebuiltCircuitJson) {
174814
+ const parsed = JSON.parse(fs45.readFileSync(input, "utf-8"));
174815
+ circuitJson = Array.isArray(parsed) ? parsed : [];
174816
+ }
174811
174817
  const completePlatformConfig = getCompletePlatformConfig(options?.platformConfig);
174812
- const result = await generateCircuitJson({
174813
- filePath: input,
174814
- platformConfig: completePlatformConfig
174815
- });
174818
+ if (!isPrebuiltCircuitJson) {
174819
+ const result = await generateCircuitJson({
174820
+ filePath: input,
174821
+ platformConfig: completePlatformConfig
174822
+ });
174823
+ circuitJson = result.circuitJson;
174824
+ }
174816
174825
  fs45.mkdirSync(path45.dirname(output), { recursive: true });
174817
- fs45.writeFileSync(output, JSON.stringify(result.circuitJson, null, 2));
174826
+ fs45.writeFileSync(output, JSON.stringify(circuitJson, null, 2));
174818
174827
  console.log(`Circuit JSON written to ${path45.relative(projectDir, output)}`);
174819
- const { errors, warnings } = analyzeCircuitJson(result.circuitJson);
174828
+ const { errors, warnings } = analyzeCircuitJson(circuitJson);
174820
174829
  if (!options?.ignoreWarnings) {
174821
174830
  for (const warn of warnings) {
174822
174831
  const msg = warn.message || JSON.stringify(warn);
@@ -174838,7 +174847,7 @@ var buildFile = async (input, output, projectDir, options) => {
174838
174847
  } else {
174839
174848
  return {
174840
174849
  ok: true,
174841
- circuitJson: result.circuitJson
174850
+ circuitJson
174842
174851
  };
174843
174852
  }
174844
174853
  } catch (err) {
@@ -175165,6 +175174,17 @@ var buildPreviewImages = async ({
175165
175174
  });
175166
175175
  };
175167
175176
 
175177
+ // cli/build/utils/exit-build.ts
175178
+ var exitBuild = (code, reason) => {
175179
+ const message = `Build exiting with code ${code}: ${reason}`;
175180
+ if (code === 0) {
175181
+ console.log(kleur_default.dim(message));
175182
+ } else {
175183
+ console.error(kleur_default.yellow(message));
175184
+ }
175185
+ process.exit(code);
175186
+ };
175187
+
175168
175188
  // cli/build/generate-kicad-project.ts
175169
175189
  import fs49 from "node:fs";
175170
175190
  import path50 from "node:path";
@@ -175248,6 +175268,7 @@ async function getBuildEntrypoints({
175248
175268
  const includeBoardFilePatterns = includeBoardFiles ? getBoardFilePatterns(resolvedRoot) : [];
175249
175269
  const buildFromProjectDir = async () => {
175250
175270
  const projectConfig2 = loadProjectConfig(resolvedRoot);
175271
+ const hasConfiguredIncludeBoardFiles = Boolean(projectConfig2?.includeBoardFiles?.some((pattern) => pattern.trim()));
175251
175272
  const resolvedPreviewComponentPath = projectConfig2?.previewComponentPath ? path51.resolve(resolvedRoot, projectConfig2.previewComponentPath) : undefined;
175252
175273
  const resolvedSiteDefaultComponentPath = projectConfig2?.siteDefaultComponentPath ? path51.resolve(resolvedRoot, projectConfig2.siteDefaultComponentPath) : undefined;
175253
175274
  if (includeBoardFiles) {
@@ -175260,6 +175281,14 @@ async function getBuildEntrypoints({
175260
175281
  circuitFiles: files
175261
175282
  };
175262
175283
  }
175284
+ if (hasConfiguredIncludeBoardFiles) {
175285
+ return {
175286
+ projectDir: resolvedRoot,
175287
+ previewComponentPath: resolvedPreviewComponentPath,
175288
+ siteDefaultComponentPath: resolvedSiteDefaultComponentPath,
175289
+ circuitFiles: []
175290
+ };
175291
+ }
175263
175292
  }
175264
175293
  const mainEntrypoint = await getEntrypoint({
175265
175294
  projectDir: resolvedRoot,
@@ -175711,10 +175740,14 @@ class WorkerPool {
175711
175740
  initialized = false;
175712
175741
  stopped = false;
175713
175742
  stopReason = null;
175743
+ stopOnFatal = false;
175744
+ cancellationError = null;
175714
175745
  constructor(options) {
175715
175746
  this.concurrency = options.concurrency;
175716
175747
  this.onLog = options.onLog;
175717
175748
  this.workerEntrypointPath = getWorkerEntrypointPath();
175749
+ this.stopOnFatal = options.stopOnFatal ?? false;
175750
+ this.cancellationError = options.cancellationError ?? null;
175718
175751
  }
175719
175752
  async initWorkers() {
175720
175753
  if (this.initialized)
@@ -175743,6 +175776,9 @@ class WorkerPool {
175743
175776
  const completedMsg = message;
175744
175777
  const job = threadWorker.currentJob;
175745
175778
  if (job) {
175779
+ if (this.stopOnFatal && completedMsg.isFatalError && this.cancellationError) {
175780
+ this.stop(this.cancellationError);
175781
+ }
175746
175782
  job.resolve({
175747
175783
  filePath: completedMsg.file_path,
175748
175784
  outputPath: completedMsg.output_path,
@@ -175849,13 +175885,15 @@ class WorkerPool {
175849
175885
  }
175850
175886
  }
175851
175887
  async function buildFilesWithWorkerPool(options) {
175888
+ const cancellationError = new Error("Build cancelled due fatal error");
175852
175889
  const pool = new WorkerPool({
175853
175890
  concurrency: options.concurrency,
175854
- onLog: options.onLog
175891
+ onLog: options.onLog,
175892
+ stopOnFatal: options.stopOnFatal,
175893
+ cancellationError
175855
175894
  });
175856
175895
  const results = [];
175857
175896
  const promises = [];
175858
- const cancellationError = new Error("Build cancelled due fatal error");
175859
175897
  for (const file of options.files) {
175860
175898
  const promise = pool.queueJob({
175861
175899
  filePath: file.filePath,
@@ -175867,9 +175905,6 @@ async function buildFilesWithWorkerPool(options) {
175867
175905
  if (options.onJobComplete) {
175868
175906
  await options.onJobComplete(result);
175869
175907
  }
175870
- if (options.stopOnFatal && result.isFatalError) {
175871
- await pool.stop(cancellationError);
175872
- }
175873
175908
  return result;
175874
175909
  });
175875
175910
  promises.push(promise);
@@ -175886,9 +175921,11 @@ async function buildFilesWithWorkerPool(options) {
175886
175921
 
175887
175922
  // cli/build/register.ts
175888
175923
  var normalizeRelativePath = (projectDir, targetPath) => path55.relative(projectDir, targetPath).split(path55.sep).join("/");
175924
+ var getOutputDirName = (relativePath) => relativePath.replace(/(\.board|\.circuit)?\.tsx$/, "").replace(/\.circuit\.json$/, "");
175889
175925
  var registerBuild = (program3) => {
175890
175926
  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("--ignore-config", "Ignore options from tscircuit.config.json").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-project", "Generate KiCad project directories for each successful build output").option("--kicad-library", "Generate KiCad library in dist/kicad-library").option("--kicad-library-name <name>", "Specify the name of the KiCad library").option("--preview-gltf", "Generate a GLTF file from the preview entrypoint").option("--glbs", "Generate GLB 3D model files for every successful build").option("--profile", "Log per-circuit circuit.json generation time during build").option("--kicad-pcm", "Generate KiCad PCM (Plugin and Content Manager) assets in dist/pcm").option("--use-cdn-javascript", "Use CDN-hosted JavaScript instead of bundled standalone file for --site").option("--concurrency <number>", "Number of files to build in parallel (default: 1)", "1").action(async (file, options) => {
175891
175927
  try {
175928
+ const transpileExplicitlyRequested = options?.transpile === true;
175892
175929
  const resolvedRoot = path55.resolve(process.cwd());
175893
175930
  let projectDir;
175894
175931
  if (file) {
@@ -175968,7 +176005,7 @@ var registerBuild = (program3) => {
175968
176005
  };
175969
176006
  const processBuildResult = async (filePath, outputPath, buildOutcome) => {
175970
176007
  const relative10 = path55.relative(projectDir, filePath);
175971
- const outputDirName = relative10.replace(/(\.board|\.circuit)?\.tsx$/, "");
176008
+ const outputDirName = getOutputDirName(relative10);
175972
176009
  builtFiles.push({
175973
176010
  sourcePath: filePath,
175974
176011
  outputPath,
@@ -176014,7 +176051,7 @@ var registerBuild = (program3) => {
176014
176051
  for (const filePath of circuitFiles) {
176015
176052
  const relative10 = path55.relative(projectDir, filePath);
176016
176053
  console.log(`Building ${relative10}...`);
176017
- const outputDirName = relative10.replace(/(\.board|\.circuit)?\.tsx$/, "");
176054
+ const outputDirName = getOutputDirName(relative10);
176018
176055
  const outputPath = path55.join(distDir, outputDirName, "circuit.json");
176019
176056
  const startedAt = resolvedOptions?.profile ? performance.now() : 0;
176020
176057
  const buildOutcome = await buildFile(filePath, outputPath, projectDir, buildOptions);
@@ -176032,7 +176069,7 @@ var registerBuild = (program3) => {
176032
176069
  const buildWithWorkers = async () => {
176033
176070
  const filesToBuild = circuitFiles.map((filePath) => {
176034
176071
  const relative10 = path55.relative(projectDir, filePath);
176035
- const outputDirName = relative10.replace(/(\.board|\.circuit)?\.tsx$/, "");
176072
+ const outputDirName = getOutputDirName(relative10);
176036
176073
  const outputPath = path55.join(distDir, outputDirName, "circuit.json");
176037
176074
  return { filePath, outputPath };
176038
176075
  });
@@ -176068,9 +176105,6 @@ var registerBuild = (program3) => {
176068
176105
  ok: result.ok,
176069
176106
  isFatalError: result.isFatalError
176070
176107
  });
176071
- if (result.isFatalError) {
176072
- process.exit(1);
176073
- }
176074
176108
  }
176075
176109
  });
176076
176110
  };
@@ -176079,9 +176113,6 @@ var registerBuild = (program3) => {
176079
176113
  } else {
176080
176114
  await buildSequentially();
176081
176115
  }
176082
- if (hasFatalErrors || hasErrors && !resolvedOptions?.ignoreErrors) {
176083
- process.exit(1);
176084
- }
176085
176116
  const shouldGeneratePreviewImages = resolvedOptions?.previewImages || resolvedOptions?.allImages;
176086
176117
  if (shouldGeneratePreviewImages) {
176087
176118
  console.log(resolvedOptions?.allImages ? "Generating preview images for all builds..." : "Generating preview images...");
@@ -176110,25 +176141,34 @@ var registerBuild = (program3) => {
176110
176141
  });
176111
176142
  }
176112
176143
  if (resolvedOptions?.transpile) {
176144
+ const includeBoardPatterns = projectConfig2?.includeBoardFiles?.filter((pattern) => pattern.trim()) ?? [];
176145
+ const hasConfiguredIncludeBoardFiles = includeBoardPatterns.length > 0;
176113
176146
  validateMainInDist(projectDir, distDir);
176114
176147
  console.log("Transpiling entry file...");
176115
176148
  const { mainEntrypoint: transpileEntrypoint } = await getBuildEntrypoints({
176116
176149
  fileOrDir: file,
176117
176150
  includeBoardFiles: false
176118
176151
  });
176119
- const entryFile = transpileEntrypoint;
176152
+ const resolvedFileArgPath = file ? path55.resolve(projectDir, file) : undefined;
176153
+ const fileArgIsDirectFile = Boolean(resolvedFileArgPath && fs54.existsSync(resolvedFileArgPath) && fs54.statSync(resolvedFileArgPath).isFile());
176154
+ const entryFile = fileArgIsDirectFile ? resolvedFileArgPath : transpileEntrypoint;
176120
176155
  if (!entryFile) {
176121
- console.error("No entry file found for transpilation. Make sure you have a lib/index.ts or set mainEntrypoint in tscircuit.config.json");
176122
- process.exit(1);
176123
- }
176124
- const transpileSuccess = await transpileFile({
176125
- input: entryFile,
176126
- outputDir: distDir,
176127
- projectDir
176128
- });
176129
- if (!transpileSuccess) {
176130
- console.error("Transpilation failed");
176131
- process.exit(1);
176156
+ if (hasConfiguredIncludeBoardFiles && !transpileExplicitlyRequested) {
176157
+ console.log("Skipping transpilation because includeBoardFiles is configured and no library entrypoint was found.");
176158
+ } else {
176159
+ console.error("No entry file found for transpilation. Make sure you have a lib/index.ts or set mainEntrypoint in tscircuit.config.json");
176160
+ exitBuild(1, "transpile entry file not found");
176161
+ }
176162
+ } else {
176163
+ const transpileSuccess = await transpileFile({
176164
+ input: entryFile,
176165
+ outputDir: distDir,
176166
+ projectDir
176167
+ });
176168
+ if (!transpileSuccess) {
176169
+ console.error("Transpilation failed");
176170
+ exitBuild(1, "transpile command failed");
176171
+ }
176132
176172
  }
176133
176173
  }
176134
176174
  if (resolvedOptions?.site) {
@@ -176162,7 +176202,7 @@ var registerBuild = (program3) => {
176162
176202
  if (!entryFile) {
176163
176203
  console.error("No entry file found for KiCad library generation. Make sure you have a lib/index.ts or set mainEntrypoint/kicadLibraryEntrypointPath in tscircuit.config.json");
176164
176204
  if (!resolvedOptions?.ignoreErrors) {
176165
- process.exit(1);
176205
+ exitBuild(1, "kicad-library entry file not found");
176166
176206
  }
176167
176207
  } else {
176168
176208
  const libraryName = resolvedOptions?.kicadLibraryName || resolveKicadLibraryName({ projectDir });
@@ -176177,7 +176217,7 @@ var registerBuild = (program3) => {
176177
176217
  } catch (err) {
176178
176218
  console.error(`Error generating KiCad library: ${err instanceof Error ? err.message : err}`);
176179
176219
  if (!resolvedOptions?.ignoreErrors) {
176180
- process.exit(1);
176220
+ exitBuild(1, "kicad-library generation failed");
176181
176221
  }
176182
176222
  }
176183
176223
  }
@@ -176196,7 +176236,7 @@ var registerBuild = (program3) => {
176196
176236
  if (!entryFile) {
176197
176237
  console.error("No entry file found for KiCad PCM generation. Make sure you have a lib/index.ts or set mainEntrypoint/kicadLibraryEntrypointPath in tscircuit.config.json");
176198
176238
  if (!resolvedOptions?.ignoreErrors) {
176199
- process.exit(1);
176239
+ exitBuild(1, "kicad-pcm entry file not found");
176200
176240
  }
176201
176241
  } else {
176202
176242
  try {
@@ -176209,11 +176249,12 @@ var registerBuild = (program3) => {
176209
176249
  } catch (err) {
176210
176250
  console.error(`Error generating KiCad PCM assets: ${err instanceof Error ? err.message : err}`);
176211
176251
  if (!resolvedOptions?.ignoreErrors) {
176212
- process.exit(1);
176252
+ exitBuild(1, "kicad-pcm generation failed");
176213
176253
  }
176214
176254
  }
176215
176255
  }
176216
176256
  }
176257
+ const shouldExitNonZero = hasFatalErrors || hasErrors && !resolvedOptions?.ignoreErrors;
176217
176258
  const successCount = builtFiles.filter((f2) => f2.ok).length;
176218
176259
  const failCount = builtFiles.length - successCount;
176219
176260
  const enabledOpts = [
@@ -176233,7 +176274,7 @@ var registerBuild = (program3) => {
176233
176274
  console.log(kleur_default.bold("Profile Summary (slowest first)"));
176234
176275
  const sortedProfileEntries = [...profileEntries].sort((a3, b3) => b3.durationMs - a3.durationMs);
176235
176276
  for (const profileEntry of sortedProfileEntries) {
176236
- console.log(` ${kleur_default.cyan(profileEntry.durationMs.toFixed(1) + "ms")} ${profileEntry.filePath}`);
176277
+ console.log(` ${kleur_default.cyan(`${profileEntry.durationMs.toFixed(1)}ms`)} ${profileEntry.filePath}`);
176237
176278
  }
176238
176279
  }
176239
176280
  console.log("");
@@ -176249,11 +176290,14 @@ var registerBuild = (program3) => {
176249
176290
  console.log(hasErrors ? kleur_default.yellow(`
176250
176291
  ⚠ Build completed with errors`) : kleur_default.green(`
176251
176292
  ✓ Done`));
176252
- process.exit(0);
176293
+ if (shouldExitNonZero) {
176294
+ exitBuild(1, hasFatalErrors ? "fatal circuit build errors occurred" : "build errors occurred and --ignore-errors was not enabled");
176295
+ }
176296
+ exitBuild(0, "build finished successfully");
176253
176297
  } catch (error) {
176254
176298
  const message = error instanceof Error ? error.message : String(error);
176255
176299
  console.error(message);
176256
- process.exit(1);
176300
+ exitBuild(1, "unexpected exception");
176257
176301
  }
176258
176302
  });
176259
176303
  };
package/dist/lib/index.js CHANGED
@@ -60414,7 +60414,7 @@ var getNodeHandler = (winterSpec, { port, middleware = [] }) => {
60414
60414
  }));
60415
60415
  };
60416
60416
  // package.json
60417
- var version = "0.1.978";
60417
+ var version = "0.1.981";
60418
60418
  var package_default = {
60419
60419
  name: "@tscircuit/cli",
60420
60420
  main: "dist/cli/main.js",
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  ".": "./dist/cli/main.js",
6
6
  "./lib": "./dist/lib/index.js"
7
7
  },
8
- "version": "0.1.980",
8
+ "version": "0.1.982",
9
9
  "devDependencies": {
10
10
  "@babel/standalone": "^7.26.9",
11
11
  "@biomejs/biome": "^1.9.4",