@tscircuit/cli 0.1.1051 → 0.1.1053
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
|
@@ -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.
|
|
71667
|
+
var version = "0.1.1052";
|
|
71668
71668
|
var package_default = {
|
|
71669
71669
|
name: "@tscircuit/cli",
|
|
71670
71670
|
version,
|
|
@@ -80669,15 +80669,11 @@ var buildFile = async (input, output, projectDir, options) => {
|
|
|
80669
80669
|
}
|
|
80670
80670
|
}
|
|
80671
80671
|
}
|
|
80672
|
-
|
|
80673
|
-
|
|
80674
|
-
|
|
80675
|
-
|
|
80676
|
-
|
|
80677
|
-
ok: true,
|
|
80678
|
-
circuitJson
|
|
80679
|
-
};
|
|
80680
|
-
}
|
|
80672
|
+
return {
|
|
80673
|
+
ok: true,
|
|
80674
|
+
circuitJson,
|
|
80675
|
+
hasErrors: errors.length > 0 && !options?.ignoreErrors
|
|
80676
|
+
};
|
|
80681
80677
|
} catch (err) {
|
|
80682
80678
|
console.error(err);
|
|
80683
80679
|
if (err instanceof Error) {
|
|
@@ -81875,42 +81871,27 @@ var exitBuild = (code, reason) => {
|
|
|
81875
81871
|
// cli/build/worker-pool.ts
|
|
81876
81872
|
import fs36 from "node:fs";
|
|
81877
81873
|
import path38 from "node:path";
|
|
81874
|
+
|
|
81875
|
+
// lib/shared/thread-worker-pool.ts
|
|
81878
81876
|
import { Worker } from "node:worker_threads";
|
|
81879
|
-
var getWorkerEntrypointPath = () => {
|
|
81880
|
-
const tsPath = path38.join(import.meta.dir, "build-worker-entrypoint.ts");
|
|
81881
|
-
if (fs36.existsSync(tsPath)) {
|
|
81882
|
-
return tsPath;
|
|
81883
|
-
}
|
|
81884
|
-
const jsBundledPath = path38.join(import.meta.dir, "build", "build-worker-entrypoint.js");
|
|
81885
|
-
if (fs36.existsSync(jsBundledPath)) {
|
|
81886
|
-
return jsBundledPath;
|
|
81887
|
-
}
|
|
81888
|
-
return path38.join(import.meta.dir, "build-worker-entrypoint.js");
|
|
81889
|
-
};
|
|
81890
81877
|
|
|
81891
|
-
class
|
|
81878
|
+
class ThreadWorkerPool {
|
|
81892
81879
|
workers = [];
|
|
81893
81880
|
jobQueue = [];
|
|
81894
81881
|
concurrency;
|
|
81895
|
-
|
|
81896
|
-
workerEntrypointPath;
|
|
81882
|
+
options;
|
|
81897
81883
|
initialized = false;
|
|
81898
81884
|
stopped = false;
|
|
81899
81885
|
stopReason = null;
|
|
81900
|
-
stopOnFatal = false;
|
|
81901
|
-
cancellationError = null;
|
|
81902
81886
|
constructor(options) {
|
|
81887
|
+
this.options = options;
|
|
81903
81888
|
this.concurrency = options.concurrency;
|
|
81904
|
-
this.onLog = options.onLog;
|
|
81905
|
-
this.workerEntrypointPath = getWorkerEntrypointPath();
|
|
81906
|
-
this.stopOnFatal = options.stopOnFatal ?? false;
|
|
81907
|
-
this.cancellationError = options.cancellationError ?? null;
|
|
81908
81889
|
}
|
|
81909
81890
|
async initWorkers() {
|
|
81910
81891
|
if (this.initialized)
|
|
81911
81892
|
return;
|
|
81912
81893
|
for (let i = 0;i < this.concurrency; i++) {
|
|
81913
|
-
const worker = new Worker(this.workerEntrypointPath);
|
|
81894
|
+
const worker = new Worker(this.options.workerEntrypointPath);
|
|
81914
81895
|
const threadWorker = {
|
|
81915
81896
|
worker,
|
|
81916
81897
|
busy: false,
|
|
@@ -81924,38 +81905,24 @@ class WorkerPool {
|
|
|
81924
81905
|
}
|
|
81925
81906
|
setupWorkerMessageHandling(threadWorker) {
|
|
81926
81907
|
threadWorker.worker.on("message", (message) => {
|
|
81927
|
-
if (message
|
|
81928
|
-
|
|
81929
|
-
|
|
81930
|
-
|
|
81931
|
-
|
|
81932
|
-
|
|
81933
|
-
|
|
81934
|
-
|
|
81935
|
-
|
|
81936
|
-
|
|
81937
|
-
|
|
81938
|
-
|
|
81939
|
-
|
|
81940
|
-
filePath: completedMsg.file_path,
|
|
81941
|
-
outputPath: completedMsg.output_path,
|
|
81942
|
-
glbOutputPath: completedMsg.glb_output_path,
|
|
81943
|
-
previewOutputDir: completedMsg.preview_output_dir,
|
|
81944
|
-
glbOk: completedMsg.glb_ok,
|
|
81945
|
-
glbError: completedMsg.glb_error,
|
|
81946
|
-
previewOk: completedMsg.preview_ok,
|
|
81947
|
-
previewError: completedMsg.preview_error,
|
|
81948
|
-
ok: completedMsg.ok,
|
|
81949
|
-
isFatalError: completedMsg.isFatalError,
|
|
81950
|
-
errors: completedMsg.errors,
|
|
81951
|
-
warnings: completedMsg.warnings,
|
|
81952
|
-
durationMs: completedMsg.durationMs
|
|
81953
|
-
});
|
|
81954
|
-
threadWorker.currentJob = null;
|
|
81955
|
-
threadWorker.busy = false;
|
|
81956
|
-
this.processQueue();
|
|
81957
|
-
}
|
|
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;
|
|
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);
|
|
81958
81921
|
}
|
|
81922
|
+
job.resolve(this.options.getResult(message));
|
|
81923
|
+
threadWorker.currentJob = null;
|
|
81924
|
+
threadWorker.busy = false;
|
|
81925
|
+
this.processQueue();
|
|
81959
81926
|
});
|
|
81960
81927
|
}
|
|
81961
81928
|
setupWorkerErrorHandling(threadWorker) {
|
|
@@ -81965,11 +81932,9 @@ class WorkerPool {
|
|
|
81965
81932
|
threadWorker.currentJob = null;
|
|
81966
81933
|
threadWorker.busy = false;
|
|
81967
81934
|
}
|
|
81968
|
-
|
|
81969
|
-
|
|
81970
|
-
|
|
81971
|
-
]);
|
|
81972
|
-
}
|
|
81935
|
+
this.options.onLog?.([
|
|
81936
|
+
`Worker error: ${error instanceof Error ? error.message : String(error)}`
|
|
81937
|
+
]);
|
|
81973
81938
|
});
|
|
81974
81939
|
threadWorker.worker.on("exit", (code) => {
|
|
81975
81940
|
if (code !== 0 && threadWorker.currentJob) {
|
|
@@ -81980,28 +81945,20 @@ class WorkerPool {
|
|
|
81980
81945
|
});
|
|
81981
81946
|
}
|
|
81982
81947
|
processQueue() {
|
|
81983
|
-
if (this.stopped)
|
|
81984
|
-
return;
|
|
81985
|
-
if (this.jobQueue.length === 0)
|
|
81948
|
+
if (this.stopped || this.jobQueue.length === 0) {
|
|
81986
81949
|
return;
|
|
81987
|
-
|
|
81988
|
-
|
|
81950
|
+
}
|
|
81951
|
+
const availableWorker = this.workers.find((worker) => !worker.busy);
|
|
81952
|
+
if (!availableWorker) {
|
|
81989
81953
|
return;
|
|
81990
|
-
|
|
81991
|
-
|
|
81954
|
+
}
|
|
81955
|
+
const queuedJob = this.jobQueue.shift();
|
|
81956
|
+
if (!queuedJob) {
|
|
81992
81957
|
return;
|
|
81958
|
+
}
|
|
81993
81959
|
availableWorker.busy = true;
|
|
81994
|
-
availableWorker.currentJob =
|
|
81995
|
-
|
|
81996
|
-
message_type: "build_file",
|
|
81997
|
-
file_path: job.filePath,
|
|
81998
|
-
output_path: job.outputPath,
|
|
81999
|
-
glb_output_path: job.glbOutputPath,
|
|
82000
|
-
preview_output_dir: job.previewOutputDir,
|
|
82001
|
-
project_dir: job.projectDir,
|
|
82002
|
-
options: job.options
|
|
82003
|
-
};
|
|
82004
|
-
availableWorker.worker.postMessage(message);
|
|
81960
|
+
availableWorker.currentJob = queuedJob;
|
|
81961
|
+
availableWorker.worker.postMessage(this.options.createMessage(queuedJob.job));
|
|
82005
81962
|
}
|
|
82006
81963
|
async queueJob(job) {
|
|
82007
81964
|
if (this.stopped) {
|
|
@@ -82009,12 +81966,7 @@ class WorkerPool {
|
|
|
82009
81966
|
}
|
|
82010
81967
|
await this.initWorkers();
|
|
82011
81968
|
return new Promise((resolve4, reject) => {
|
|
82012
|
-
|
|
82013
|
-
...job,
|
|
82014
|
-
resolve: resolve4,
|
|
82015
|
-
reject
|
|
82016
|
-
};
|
|
82017
|
-
this.jobQueue.push(queuedJob);
|
|
81969
|
+
this.jobQueue.push({ job, resolve: resolve4, reject });
|
|
82018
81970
|
this.processQueue();
|
|
82019
81971
|
});
|
|
82020
81972
|
}
|
|
@@ -82028,35 +81980,70 @@ class WorkerPool {
|
|
|
82028
81980
|
}
|
|
82029
81981
|
this.jobQueue = [];
|
|
82030
81982
|
}
|
|
82031
|
-
async runUntilComplete() {
|
|
82032
|
-
return new Promise((resolve4) => {
|
|
82033
|
-
const checkComplete = () => {
|
|
82034
|
-
const allIdle = this.workers.every((w) => !w.busy);
|
|
82035
|
-
const queueEmpty = this.jobQueue.length === 0;
|
|
82036
|
-
if (allIdle && queueEmpty) {
|
|
82037
|
-
resolve4();
|
|
82038
|
-
} else {
|
|
82039
|
-
setTimeout(checkComplete, 50);
|
|
82040
|
-
}
|
|
82041
|
-
};
|
|
82042
|
-
checkComplete();
|
|
82043
|
-
});
|
|
82044
|
-
}
|
|
82045
81983
|
async terminate() {
|
|
82046
|
-
|
|
82047
|
-
await Promise.all(terminatePromises);
|
|
81984
|
+
await Promise.all(this.workers.map((worker) => worker.worker.terminate()));
|
|
82048
81985
|
this.workers = [];
|
|
82049
81986
|
this.initialized = false;
|
|
82050
81987
|
}
|
|
82051
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
|
+
};
|
|
82052
82002
|
async function buildFilesWithWorkerPool(options) {
|
|
82053
82003
|
const cancellationError = new Error("Build cancelled due fatal error");
|
|
82054
82004
|
const poolConcurrency = Math.max(1, Math.min(options.concurrency, options.files.length));
|
|
82055
|
-
const pool = new
|
|
82005
|
+
const pool = new ThreadWorkerPool({
|
|
82056
82006
|
concurrency: poolConcurrency,
|
|
82057
|
-
|
|
82058
|
-
|
|
82059
|
-
|
|
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
|
|
82060
82047
|
});
|
|
82061
82048
|
const results = [];
|
|
82062
82049
|
const promises = [];
|
|
@@ -82235,6 +82222,9 @@ var registerBuild = (program2) => {
|
|
|
82235
82222
|
outputPath,
|
|
82236
82223
|
ok: buildOutcome.ok
|
|
82237
82224
|
});
|
|
82225
|
+
if (buildOutcome.hasErrors) {
|
|
82226
|
+
hasErrors = true;
|
|
82227
|
+
}
|
|
82238
82228
|
if (!buildOutcome.ok) {
|
|
82239
82229
|
hasErrors = true;
|
|
82240
82230
|
if (buildOutcome.isFatalError) {
|
|
@@ -82331,7 +82321,11 @@ var registerBuild = (program2) => {
|
|
|
82331
82321
|
onJobComplete: async (result) => {
|
|
82332
82322
|
const relative3 = path39.relative(projectDir, result.filePath);
|
|
82333
82323
|
if (result.ok) {
|
|
82334
|
-
|
|
82324
|
+
if (result.hasErrors) {
|
|
82325
|
+
console.log(kleur_default.yellow(`⚠ ${relative3} (${result.errors.length} error(s))`));
|
|
82326
|
+
} else {
|
|
82327
|
+
console.log(kleur_default.green(`✓ ${relative3}`));
|
|
82328
|
+
}
|
|
82335
82329
|
} else {
|
|
82336
82330
|
console.log(kleur_default.red(`✗ ${relative3}`));
|
|
82337
82331
|
for (const error of result.errors) {
|
|
@@ -82347,6 +82341,7 @@ var registerBuild = (program2) => {
|
|
|
82347
82341
|
}
|
|
82348
82342
|
await processBuildResult(result.filePath, result.outputPath, {
|
|
82349
82343
|
ok: result.ok,
|
|
82344
|
+
hasErrors: result.hasErrors,
|
|
82350
82345
|
isFatalError: result.isFatalError
|
|
82351
82346
|
});
|
|
82352
82347
|
if (resolvedOptions?.glbs && result.ok) {
|
|
@@ -82511,7 +82506,7 @@ var registerBuild = (program2) => {
|
|
|
82511
82506
|
}
|
|
82512
82507
|
}
|
|
82513
82508
|
}
|
|
82514
|
-
const shouldExitNonZero = hasFatalErrors
|
|
82509
|
+
const shouldExitNonZero = hasFatalErrors;
|
|
82515
82510
|
const successCount = builtFiles.filter((f) => f.ok).length;
|
|
82516
82511
|
const failCount = builtFiles.length - successCount;
|
|
82517
82512
|
const enabledOpts = [
|
|
@@ -82548,7 +82543,7 @@ var registerBuild = (program2) => {
|
|
|
82548
82543
|
⚠ Build completed with errors`) : kleur_default.green(`
|
|
82549
82544
|
✓ Done`));
|
|
82550
82545
|
if (shouldExitNonZero) {
|
|
82551
|
-
exitBuild(1,
|
|
82546
|
+
exitBuild(1, "fatal circuit build errors occurred");
|
|
82552
82547
|
}
|
|
82553
82548
|
exitBuild(0, "build finished successfully");
|
|
82554
82549
|
} catch (error) {
|
|
@@ -177556,8 +177551,89 @@ function applyCameraPreset(preset, cam) {
|
|
|
177556
177551
|
}
|
|
177557
177552
|
|
|
177558
177553
|
// lib/shared/snapshot-project.ts
|
|
177559
|
-
import
|
|
177554
|
+
import path64 from "node:path";
|
|
177555
|
+
|
|
177556
|
+
// cli/snapshot/worker-pool.ts
|
|
177557
|
+
import fs60 from "node:fs";
|
|
177560
177558
|
import path62 from "node:path";
|
|
177559
|
+
var getWorkerEntrypointPath2 = () => {
|
|
177560
|
+
const tsPath = path62.join(import.meta.dir, "snapshot.worker.ts");
|
|
177561
|
+
if (fs60.existsSync(tsPath)) {
|
|
177562
|
+
return tsPath;
|
|
177563
|
+
}
|
|
177564
|
+
const jsBundledPath = path62.join(import.meta.dir, "snapshot", "snapshot.worker.js");
|
|
177565
|
+
if (fs60.existsSync(jsBundledPath)) {
|
|
177566
|
+
return jsBundledPath;
|
|
177567
|
+
}
|
|
177568
|
+
return path62.join(import.meta.dir, "snapshot.worker.js");
|
|
177569
|
+
};
|
|
177570
|
+
var snapshotFilesWithWorkerPool = async (options) => {
|
|
177571
|
+
const cancellationError = new Error("Snapshot cancelled due to file failure");
|
|
177572
|
+
const poolConcurrency = Math.max(1, Math.min(options.concurrency, options.files.length));
|
|
177573
|
+
const pool = new ThreadWorkerPool({
|
|
177574
|
+
concurrency: poolConcurrency,
|
|
177575
|
+
workerEntrypointPath: getWorkerEntrypointPath2(),
|
|
177576
|
+
createMessage: (job) => ({
|
|
177577
|
+
message_type: "snapshot_file",
|
|
177578
|
+
file_path: job.filePath,
|
|
177579
|
+
project_dir: job.projectDir,
|
|
177580
|
+
snapshots_dir_name: job.snapshotsDirName,
|
|
177581
|
+
options: {
|
|
177582
|
+
update: job.options.update,
|
|
177583
|
+
threeD: job.options.threeD,
|
|
177584
|
+
pcbOnly: job.options.pcbOnly,
|
|
177585
|
+
schematicOnly: job.options.schematicOnly,
|
|
177586
|
+
forceUpdate: job.options.forceUpdate,
|
|
177587
|
+
platformConfig: job.options.platformConfig,
|
|
177588
|
+
createDiff: job.options.createDiff,
|
|
177589
|
+
cameraPreset: job.options.cameraPreset
|
|
177590
|
+
}
|
|
177591
|
+
}),
|
|
177592
|
+
isLogMessage: (message) => message.message_type === "worker_log",
|
|
177593
|
+
getLogLines: (message) => message.message_type === "worker_log" ? message.log_lines : [],
|
|
177594
|
+
isCompletionMessage: (message) => message.message_type === "snapshot_completed",
|
|
177595
|
+
getResult: (message) => {
|
|
177596
|
+
const completedMessage = message;
|
|
177597
|
+
return {
|
|
177598
|
+
filePath: completedMessage.file_path,
|
|
177599
|
+
result: completedMessage.result
|
|
177600
|
+
};
|
|
177601
|
+
},
|
|
177602
|
+
shouldStopOnMessage: (message) => {
|
|
177603
|
+
if (!options.stopOnFailure || message.message_type !== "snapshot_completed") {
|
|
177604
|
+
return false;
|
|
177605
|
+
}
|
|
177606
|
+
return !message.result.ok;
|
|
177607
|
+
},
|
|
177608
|
+
cancellationError,
|
|
177609
|
+
onLog: options.onLog
|
|
177610
|
+
});
|
|
177611
|
+
const results = [];
|
|
177612
|
+
const jobs = options.files.map((filePath) => pool.queueJob({
|
|
177613
|
+
filePath,
|
|
177614
|
+
projectDir: options.projectDir,
|
|
177615
|
+
snapshotsDirName: options.snapshotsDirName,
|
|
177616
|
+
options: options.snapshotOptions
|
|
177617
|
+
}).then(async (result) => {
|
|
177618
|
+
results.push(result);
|
|
177619
|
+
await options.onJobComplete?.(result);
|
|
177620
|
+
return result;
|
|
177621
|
+
}));
|
|
177622
|
+
const settledResults = await Promise.allSettled(jobs);
|
|
177623
|
+
for (const settledResult of settledResults) {
|
|
177624
|
+
if (settledResult.status === "rejected" && settledResult.reason !== cancellationError) {
|
|
177625
|
+
throw settledResult.reason;
|
|
177626
|
+
}
|
|
177627
|
+
}
|
|
177628
|
+
if (typeof Bun === "undefined") {
|
|
177629
|
+
await pool.terminate();
|
|
177630
|
+
}
|
|
177631
|
+
return results;
|
|
177632
|
+
};
|
|
177633
|
+
|
|
177634
|
+
// lib/shared/process-snapshot-file.ts
|
|
177635
|
+
import fs62 from "node:fs";
|
|
177636
|
+
import path63 from "node:path";
|
|
177561
177637
|
import {
|
|
177562
177638
|
convertCircuitJsonToGltf as convertCircuitJsonToGltf5,
|
|
177563
177639
|
getBestCameraPosition
|
|
@@ -177566,12 +177642,11 @@ import {
|
|
|
177566
177642
|
convertCircuitJsonToPcbSvg as convertCircuitJsonToPcbSvg3,
|
|
177567
177643
|
convertCircuitJsonToSchematicSvg as convertCircuitJsonToSchematicSvg3
|
|
177568
177644
|
} from "circuit-to-svg";
|
|
177569
|
-
import looksSame2 from "looks-same";
|
|
177570
177645
|
import { renderGLTFToPNGBufferFromGLBBuffer as renderGLTFToPNGBufferFromGLBBuffer2 } from "poppygl";
|
|
177571
177646
|
|
|
177572
177647
|
// lib/shared/compare-images.ts
|
|
177573
177648
|
import looksSame from "looks-same";
|
|
177574
|
-
import
|
|
177649
|
+
import fs61 from "node:fs/promises";
|
|
177575
177650
|
var compareAndCreateDiff = async (buffer1, buffer2, diffPath, createDiff = true) => {
|
|
177576
177651
|
const { equal: equal2 } = await looksSame(buffer1, buffer2, {
|
|
177577
177652
|
strict: false,
|
|
@@ -177587,12 +177662,200 @@ var compareAndCreateDiff = async (buffer1, buffer2, diffPath, createDiff = true)
|
|
|
177587
177662
|
tolerance: 2
|
|
177588
177663
|
});
|
|
177589
177664
|
} else {
|
|
177590
|
-
await
|
|
177665
|
+
await fs61.writeFile(diffPath, buffer2);
|
|
177591
177666
|
}
|
|
177592
177667
|
}
|
|
177593
177668
|
return { equal: equal2 };
|
|
177594
177669
|
};
|
|
177595
177670
|
|
|
177671
|
+
// lib/shared/process-snapshot-file.ts
|
|
177672
|
+
var isCircuitJsonFile = (filePath) => {
|
|
177673
|
+
const normalizedPath = filePath.toLowerCase().replaceAll("\\", "/");
|
|
177674
|
+
return normalizedPath.endsWith(".circuit.json") || normalizedPath.endsWith("/circuit.json");
|
|
177675
|
+
};
|
|
177676
|
+
var processSnapshotFile = async ({
|
|
177677
|
+
file,
|
|
177678
|
+
projectDir,
|
|
177679
|
+
snapshotsDirName,
|
|
177680
|
+
update,
|
|
177681
|
+
threeD,
|
|
177682
|
+
pcbOnly,
|
|
177683
|
+
schematicOnly,
|
|
177684
|
+
forceUpdate,
|
|
177685
|
+
platformConfig: platformConfig2,
|
|
177686
|
+
createDiff,
|
|
177687
|
+
cameraPreset
|
|
177688
|
+
}) => {
|
|
177689
|
+
const relativeFilePath = path63.relative(projectDir, file);
|
|
177690
|
+
const successPaths = [];
|
|
177691
|
+
const warningMessages = [];
|
|
177692
|
+
const mismatches = [];
|
|
177693
|
+
let didUpdate = false;
|
|
177694
|
+
let circuitJson;
|
|
177695
|
+
let pcbSvg;
|
|
177696
|
+
let schSvg;
|
|
177697
|
+
try {
|
|
177698
|
+
if (isCircuitJsonFile(file)) {
|
|
177699
|
+
const parsed = JSON.parse(fs62.readFileSync(file, "utf-8"));
|
|
177700
|
+
circuitJson = Array.isArray(parsed) ? parsed : [];
|
|
177701
|
+
} else {
|
|
177702
|
+
const completePlatformConfig = getCompletePlatformConfig(platformConfig2);
|
|
177703
|
+
const result = await generateCircuitJson({
|
|
177704
|
+
filePath: file,
|
|
177705
|
+
platformConfig: completePlatformConfig
|
|
177706
|
+
});
|
|
177707
|
+
circuitJson = result.circuitJson;
|
|
177708
|
+
}
|
|
177709
|
+
} catch (error) {
|
|
177710
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
177711
|
+
return {
|
|
177712
|
+
ok: false,
|
|
177713
|
+
didUpdate: false,
|
|
177714
|
+
successPaths,
|
|
177715
|
+
warningMessages,
|
|
177716
|
+
mismatches,
|
|
177717
|
+
errorMessage: kleur_default.red(`
|
|
177718
|
+
❌ Failed to generate circuit JSON for ${relativeFilePath}:
|
|
177719
|
+
`) + kleur_default.red(` ${errorMessage}
|
|
177720
|
+
`)
|
|
177721
|
+
};
|
|
177722
|
+
}
|
|
177723
|
+
try {
|
|
177724
|
+
pcbSvg = convertCircuitJsonToPcbSvg3(circuitJson);
|
|
177725
|
+
} catch (error) {
|
|
177726
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
177727
|
+
return {
|
|
177728
|
+
ok: false,
|
|
177729
|
+
didUpdate: false,
|
|
177730
|
+
successPaths,
|
|
177731
|
+
warningMessages,
|
|
177732
|
+
mismatches,
|
|
177733
|
+
errorMessage: kleur_default.red(`
|
|
177734
|
+
❌ Failed to generate PCB SVG for ${relativeFilePath}:
|
|
177735
|
+
`) + kleur_default.red(` ${errorMessage}
|
|
177736
|
+
`)
|
|
177737
|
+
};
|
|
177738
|
+
}
|
|
177739
|
+
try {
|
|
177740
|
+
schSvg = convertCircuitJsonToSchematicSvg3(circuitJson);
|
|
177741
|
+
} catch (error) {
|
|
177742
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
177743
|
+
return {
|
|
177744
|
+
ok: false,
|
|
177745
|
+
didUpdate: false,
|
|
177746
|
+
successPaths,
|
|
177747
|
+
warningMessages,
|
|
177748
|
+
mismatches,
|
|
177749
|
+
errorMessage: kleur_default.red(`
|
|
177750
|
+
❌ Failed to generate schematic SVG for ${relativeFilePath}:
|
|
177751
|
+
`) + kleur_default.red(` ${errorMessage}
|
|
177752
|
+
`)
|
|
177753
|
+
};
|
|
177754
|
+
}
|
|
177755
|
+
let png3d = null;
|
|
177756
|
+
if (threeD) {
|
|
177757
|
+
try {
|
|
177758
|
+
const glbBuffer = await convertCircuitJsonToGltf5(circuitJson, getCircuitJsonToGltfOptions({ format: "glb" }));
|
|
177759
|
+
if (!(glbBuffer instanceof ArrayBuffer)) {
|
|
177760
|
+
throw new Error("Expected ArrayBuffer from convertCircuitJsonToGltf with glb format");
|
|
177761
|
+
}
|
|
177762
|
+
let cameraOptions = getBestCameraPosition(circuitJson);
|
|
177763
|
+
if (cameraPreset) {
|
|
177764
|
+
cameraOptions = applyCameraPreset(cameraPreset, cameraOptions);
|
|
177765
|
+
}
|
|
177766
|
+
png3d = await renderGLTFToPNGBufferFromGLBBuffer2(glbBuffer, cameraOptions);
|
|
177767
|
+
} catch (error) {
|
|
177768
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
177769
|
+
if (errorMessage.includes("No pcb_board found in circuit JSON")) {
|
|
177770
|
+
const fileDir = path63.dirname(file);
|
|
177771
|
+
const relativeDir = path63.relative(projectDir, fileDir);
|
|
177772
|
+
const snapDir2 = snapshotsDirName ? path63.join(projectDir, snapshotsDirName, relativeDir) : path63.join(fileDir, "__snapshots__");
|
|
177773
|
+
const base2 = path63.basename(file).replace(/\.[^.]+$/, "");
|
|
177774
|
+
const snap3dPath = path63.join(snapDir2, `${base2}-3d.snap.png`);
|
|
177775
|
+
const existing3dSnapshot = fs62.existsSync(snap3dPath);
|
|
177776
|
+
if (existing3dSnapshot) {
|
|
177777
|
+
return {
|
|
177778
|
+
ok: false,
|
|
177779
|
+
didUpdate: false,
|
|
177780
|
+
successPaths,
|
|
177781
|
+
warningMessages,
|
|
177782
|
+
mismatches,
|
|
177783
|
+
errorMessage: kleur_default.red(`
|
|
177784
|
+
❌ Failed to generate 3D snapshot for ${relativeFilePath}:
|
|
177785
|
+
`) + kleur_default.red(` No pcb_board found in circuit JSON
|
|
177786
|
+
`) + kleur_default.red(` Existing snapshot: ${path63.relative(projectDir, snap3dPath)}
|
|
177787
|
+
`)
|
|
177788
|
+
};
|
|
177789
|
+
}
|
|
177790
|
+
warningMessages.push(kleur_default.red(`⚠️ Skipping 3D snapshot for ${relativeFilePath}:`) + kleur_default.red(` No pcb_board found in circuit JSON`));
|
|
177791
|
+
png3d = null;
|
|
177792
|
+
} else {
|
|
177793
|
+
return {
|
|
177794
|
+
ok: false,
|
|
177795
|
+
didUpdate: false,
|
|
177796
|
+
successPaths,
|
|
177797
|
+
warningMessages,
|
|
177798
|
+
mismatches,
|
|
177799
|
+
errorMessage: kleur_default.red(`
|
|
177800
|
+
❌ Failed to generate 3D snapshot for ${relativeFilePath}:
|
|
177801
|
+
`) + kleur_default.red(` ${errorMessage}
|
|
177802
|
+
`)
|
|
177803
|
+
};
|
|
177804
|
+
}
|
|
177805
|
+
}
|
|
177806
|
+
}
|
|
177807
|
+
const snapDir = snapshotsDirName ? path63.join(projectDir, snapshotsDirName, path63.relative(projectDir, path63.dirname(file))) : path63.join(path63.dirname(file), "__snapshots__");
|
|
177808
|
+
fs62.mkdirSync(snapDir, { recursive: true });
|
|
177809
|
+
const base = path63.basename(file).replace(/\.[^.]+$/, "");
|
|
177810
|
+
const snapshots = [];
|
|
177811
|
+
if (pcbOnly || !schematicOnly) {
|
|
177812
|
+
snapshots.push({ type: "pcb", content: pcbSvg, isBinary: false });
|
|
177813
|
+
}
|
|
177814
|
+
if (schematicOnly || !pcbOnly) {
|
|
177815
|
+
snapshots.push({ type: "schematic", content: schSvg, isBinary: false });
|
|
177816
|
+
}
|
|
177817
|
+
if (threeD && png3d) {
|
|
177818
|
+
snapshots.push({ type: "3d", content: png3d, isBinary: true });
|
|
177819
|
+
}
|
|
177820
|
+
for (const snapshot of snapshots) {
|
|
177821
|
+
const { type } = snapshot;
|
|
177822
|
+
const is3d = type === "3d";
|
|
177823
|
+
const snapPath = path63.join(snapDir, `${base}-${type}.snap.${is3d ? "png" : "svg"}`);
|
|
177824
|
+
const existing = fs62.existsSync(snapPath);
|
|
177825
|
+
const newContentBuffer = snapshot.isBinary ? snapshot.content : Buffer.from(snapshot.content, "utf8");
|
|
177826
|
+
const newContentForFile = snapshot.content;
|
|
177827
|
+
if (!existing) {
|
|
177828
|
+
fs62.writeFileSync(snapPath, newContentForFile);
|
|
177829
|
+
successPaths.push(path63.relative(projectDir, snapPath));
|
|
177830
|
+
didUpdate = true;
|
|
177831
|
+
continue;
|
|
177832
|
+
}
|
|
177833
|
+
const oldContentBuffer = fs62.readFileSync(snapPath);
|
|
177834
|
+
const diffPath = snapPath.replace(is3d ? ".snap.png" : ".snap.svg", is3d ? ".diff.png" : ".diff.svg");
|
|
177835
|
+
const { equal: equal2 } = await compareAndCreateDiff(oldContentBuffer, newContentBuffer, diffPath, createDiff);
|
|
177836
|
+
if (update) {
|
|
177837
|
+
if (!forceUpdate && equal2) {
|
|
177838
|
+
successPaths.push(path63.relative(projectDir, snapPath));
|
|
177839
|
+
} else {
|
|
177840
|
+
fs62.writeFileSync(snapPath, newContentForFile);
|
|
177841
|
+
successPaths.push(path63.relative(projectDir, snapPath));
|
|
177842
|
+
didUpdate = true;
|
|
177843
|
+
}
|
|
177844
|
+
} else if (!equal2) {
|
|
177845
|
+
mismatches.push(createDiff ? `${snapPath} (diff: ${diffPath})` : snapPath);
|
|
177846
|
+
} else {
|
|
177847
|
+
successPaths.push(path63.relative(projectDir, snapPath));
|
|
177848
|
+
}
|
|
177849
|
+
}
|
|
177850
|
+
return {
|
|
177851
|
+
ok: true,
|
|
177852
|
+
didUpdate,
|
|
177853
|
+
successPaths,
|
|
177854
|
+
warningMessages,
|
|
177855
|
+
mismatches
|
|
177856
|
+
};
|
|
177857
|
+
};
|
|
177858
|
+
|
|
177596
177859
|
// lib/shared/snapshot-project.ts
|
|
177597
177860
|
var snapshotProject = async ({
|
|
177598
177861
|
update = false,
|
|
@@ -177607,7 +177870,8 @@ var snapshotProject = async ({
|
|
|
177607
177870
|
onSuccess = (msg) => console.log(msg),
|
|
177608
177871
|
platformConfig: platformConfig2,
|
|
177609
177872
|
createDiff = false,
|
|
177610
|
-
cameraPreset
|
|
177873
|
+
cameraPreset,
|
|
177874
|
+
concurrency = 1
|
|
177611
177875
|
} = {}) => {
|
|
177612
177876
|
if (cameraPreset) {
|
|
177613
177877
|
threeD = true;
|
|
@@ -177617,7 +177881,7 @@ var snapshotProject = async ({
|
|
|
177617
177881
|
...DEFAULT_IGNORED_PATTERNS,
|
|
177618
177882
|
...ignored.map(normalizeIgnorePattern)
|
|
177619
177883
|
];
|
|
177620
|
-
const resolvedPaths = filePaths.map((f2) =>
|
|
177884
|
+
const resolvedPaths = filePaths.map((f2) => path64.resolve(projectDir, f2));
|
|
177621
177885
|
const boardFiles = findBoardFiles({
|
|
177622
177886
|
projectDir,
|
|
177623
177887
|
ignore,
|
|
@@ -177630,141 +177894,78 @@ var snapshotProject = async ({
|
|
|
177630
177894
|
const snapshotsDirName = getSnapshotsDir(projectDir);
|
|
177631
177895
|
const mismatches = [];
|
|
177632
177896
|
let didUpdate = false;
|
|
177633
|
-
const
|
|
177634
|
-
|
|
177635
|
-
|
|
177636
|
-
|
|
177637
|
-
for (const file of boardFiles) {
|
|
177638
|
-
const relativeFilePath = path62.relative(projectDir, file);
|
|
177639
|
-
let circuitJson;
|
|
177640
|
-
let pcbSvg;
|
|
177641
|
-
let schSvg;
|
|
177642
|
-
try {
|
|
177643
|
-
if (isCircuitJsonFile(file)) {
|
|
177644
|
-
const parsed = JSON.parse(fs61.readFileSync(file, "utf-8"));
|
|
177645
|
-
circuitJson = Array.isArray(parsed) ? parsed : [];
|
|
177646
|
-
} else {
|
|
177647
|
-
const completePlatformConfig = getCompletePlatformConfig(platformConfig2);
|
|
177648
|
-
const result = await generateCircuitJson({
|
|
177649
|
-
filePath: file,
|
|
177650
|
-
platformConfig: completePlatformConfig
|
|
177651
|
-
});
|
|
177652
|
-
circuitJson = result.circuitJson;
|
|
177653
|
-
}
|
|
177654
|
-
} catch (error) {
|
|
177655
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
177656
|
-
onError(kleur_default.red(`
|
|
177657
|
-
❌ Failed to generate circuit JSON for ${relativeFilePath}:
|
|
177658
|
-
`) + kleur_default.red(` ${errorMessage}
|
|
177659
|
-
`));
|
|
177660
|
-
return onExit2(1);
|
|
177897
|
+
const concurrencyValue = Math.max(1, concurrency);
|
|
177898
|
+
const processResult = (result) => {
|
|
177899
|
+
for (const warningMessage of result.warningMessages) {
|
|
177900
|
+
console.log(warningMessage);
|
|
177661
177901
|
}
|
|
177662
|
-
|
|
177663
|
-
|
|
177664
|
-
} catch (error) {
|
|
177665
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
177666
|
-
onError(kleur_default.red(`
|
|
177667
|
-
❌ Failed to generate PCB SVG for ${relativeFilePath}:
|
|
177668
|
-
`) + kleur_default.red(` ${errorMessage}
|
|
177669
|
-
`));
|
|
177670
|
-
return onExit2(1);
|
|
177902
|
+
for (const successPath of result.successPaths) {
|
|
177903
|
+
console.log("✅", kleur_default.gray(successPath));
|
|
177671
177904
|
}
|
|
177905
|
+
didUpdate = didUpdate || result.didUpdate;
|
|
177906
|
+
mismatches.push(...result.mismatches);
|
|
177907
|
+
};
|
|
177908
|
+
if (concurrencyValue > 1 && boardFiles.length > 1) {
|
|
177909
|
+
console.log(`Generating snapshots for ${boardFiles.length} file(s) with concurrency ${concurrencyValue}...`);
|
|
177910
|
+
let firstErrorMessage;
|
|
177672
177911
|
try {
|
|
177673
|
-
|
|
177912
|
+
await snapshotFilesWithWorkerPool({
|
|
177913
|
+
files: boardFiles,
|
|
177914
|
+
projectDir,
|
|
177915
|
+
snapshotsDirName,
|
|
177916
|
+
concurrency: concurrencyValue,
|
|
177917
|
+
snapshotOptions: {
|
|
177918
|
+
update,
|
|
177919
|
+
threeD,
|
|
177920
|
+
pcbOnly,
|
|
177921
|
+
schematicOnly,
|
|
177922
|
+
forceUpdate,
|
|
177923
|
+
platformConfig: platformConfig2,
|
|
177924
|
+
createDiff,
|
|
177925
|
+
cameraPreset
|
|
177926
|
+
},
|
|
177927
|
+
stopOnFailure: true,
|
|
177928
|
+
onLog: (lines) => {
|
|
177929
|
+
for (const line2 of lines) {
|
|
177930
|
+
console.log(line2);
|
|
177931
|
+
}
|
|
177932
|
+
},
|
|
177933
|
+
onJobComplete: (jobResult) => {
|
|
177934
|
+
const { result } = jobResult;
|
|
177935
|
+
processResult(result);
|
|
177936
|
+
if (!result.ok && !firstErrorMessage) {
|
|
177937
|
+
firstErrorMessage = result.errorMessage ?? "Snapshot generation failed";
|
|
177938
|
+
}
|
|
177939
|
+
}
|
|
177940
|
+
});
|
|
177674
177941
|
} catch (error) {
|
|
177675
177942
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
177676
|
-
onError(kleur_default.red(
|
|
177677
|
-
❌ Failed to generate schematic SVG for ${relativeFilePath}:
|
|
177678
|
-
`) + kleur_default.red(` ${errorMessage}
|
|
177679
|
-
`));
|
|
177943
|
+
onError(kleur_default.red(errorMessage));
|
|
177680
177944
|
return onExit2(1);
|
|
177681
177945
|
}
|
|
177682
|
-
|
|
177683
|
-
|
|
177684
|
-
try {
|
|
177685
|
-
const glbBuffer = await convertCircuitJsonToGltf5(circuitJson, getCircuitJsonToGltfOptions({ format: "glb" }));
|
|
177686
|
-
if (!(glbBuffer instanceof ArrayBuffer)) {
|
|
177687
|
-
throw new Error("Expected ArrayBuffer from convertCircuitJsonToGltf with glb format");
|
|
177688
|
-
}
|
|
177689
|
-
let cameraOptions = getBestCameraPosition(circuitJson);
|
|
177690
|
-
if (cameraPreset) {
|
|
177691
|
-
cameraOptions = applyCameraPreset(cameraPreset, cameraOptions);
|
|
177692
|
-
}
|
|
177693
|
-
png3d = await renderGLTFToPNGBufferFromGLBBuffer2(glbBuffer, cameraOptions);
|
|
177694
|
-
} catch (error) {
|
|
177695
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
177696
|
-
if (errorMessage.includes("No pcb_board found in circuit JSON")) {
|
|
177697
|
-
const fileDir = path62.dirname(file);
|
|
177698
|
-
const relativeDir = path62.relative(projectDir, fileDir);
|
|
177699
|
-
const snapDir2 = snapshotsDirName ? path62.join(projectDir, snapshotsDirName, relativeDir) : path62.join(fileDir, "__snapshots__");
|
|
177700
|
-
const base2 = path62.basename(file).replace(/\.[^.]+$/, "");
|
|
177701
|
-
const snap3dPath = path62.join(snapDir2, `${base2}-3d.snap.png`);
|
|
177702
|
-
const existing3dSnapshot = fs61.existsSync(snap3dPath);
|
|
177703
|
-
if (existing3dSnapshot) {
|
|
177704
|
-
onError(kleur_default.red(`
|
|
177705
|
-
❌ Failed to generate 3D snapshot for ${relativeFilePath}:
|
|
177706
|
-
`) + kleur_default.red(` No pcb_board found in circuit JSON
|
|
177707
|
-
`) + kleur_default.red(` Existing snapshot: ${path62.relative(projectDir, snap3dPath)}
|
|
177708
|
-
`));
|
|
177709
|
-
return onExit2(1);
|
|
177710
|
-
} else {
|
|
177711
|
-
console.log(kleur_default.red(`⚠️ Skipping 3D snapshot for ${relativeFilePath}:`) + kleur_default.red(` No pcb_board found in circuit JSON`));
|
|
177712
|
-
png3d = null;
|
|
177713
|
-
}
|
|
177714
|
-
} else {
|
|
177715
|
-
onError(kleur_default.red(`
|
|
177716
|
-
❌ Failed to generate 3D snapshot for ${relativeFilePath}:
|
|
177717
|
-
`) + kleur_default.red(` ${errorMessage}
|
|
177718
|
-
`));
|
|
177719
|
-
return onExit2(1);
|
|
177720
|
-
}
|
|
177721
|
-
}
|
|
177722
|
-
}
|
|
177723
|
-
const snapDir = snapshotsDirName ? path62.join(projectDir, snapshotsDirName, path62.relative(projectDir, path62.dirname(file))) : path62.join(path62.dirname(file), "__snapshots__");
|
|
177724
|
-
fs61.mkdirSync(snapDir, { recursive: true });
|
|
177725
|
-
const base = path62.basename(file).replace(/\.[^.]+$/, "");
|
|
177726
|
-
const snapshots = [];
|
|
177727
|
-
if (pcbOnly || !schematicOnly) {
|
|
177728
|
-
snapshots.push({ type: "pcb", content: pcbSvg, isBinary: false });
|
|
177729
|
-
}
|
|
177730
|
-
if (schematicOnly || !pcbOnly) {
|
|
177731
|
-
snapshots.push({ type: "schematic", content: schSvg, isBinary: false });
|
|
177732
|
-
}
|
|
177733
|
-
if (threeD && png3d) {
|
|
177734
|
-
snapshots.push({ type: "3d", content: png3d, isBinary: true });
|
|
177735
|
-
}
|
|
177736
|
-
if (!looksSame2) {
|
|
177737
|
-
console.error("looks-same is required. Install it with 'bun add -d looks-same'");
|
|
177946
|
+
if (firstErrorMessage) {
|
|
177947
|
+
onError(firstErrorMessage);
|
|
177738
177948
|
return onExit2(1);
|
|
177739
177949
|
}
|
|
177740
|
-
|
|
177741
|
-
|
|
177742
|
-
const
|
|
177743
|
-
|
|
177744
|
-
|
|
177745
|
-
|
|
177746
|
-
|
|
177747
|
-
|
|
177748
|
-
|
|
177749
|
-
|
|
177750
|
-
|
|
177751
|
-
|
|
177752
|
-
|
|
177753
|
-
|
|
177754
|
-
|
|
177755
|
-
|
|
177756
|
-
if (
|
|
177757
|
-
|
|
177758
|
-
|
|
177759
|
-
} else {
|
|
177760
|
-
fs61.writeFileSync(snapPath, newContentForFile);
|
|
177761
|
-
console.log("✅", kleur_default.gray(path62.relative(projectDir, snapPath)));
|
|
177762
|
-
didUpdate = true;
|
|
177763
|
-
}
|
|
177764
|
-
} else if (!equal2) {
|
|
177765
|
-
mismatches.push(createDiff ? `${snapPath} (diff: ${diffPath})` : snapPath);
|
|
177766
|
-
} else {
|
|
177767
|
-
console.log("✅", kleur_default.gray(path62.relative(projectDir, snapPath)));
|
|
177950
|
+
} else {
|
|
177951
|
+
for (const file of boardFiles) {
|
|
177952
|
+
const result = await processSnapshotFile({
|
|
177953
|
+
file,
|
|
177954
|
+
projectDir,
|
|
177955
|
+
snapshotsDirName,
|
|
177956
|
+
update,
|
|
177957
|
+
threeD,
|
|
177958
|
+
pcbOnly,
|
|
177959
|
+
schematicOnly,
|
|
177960
|
+
forceUpdate,
|
|
177961
|
+
platformConfig: platformConfig2,
|
|
177962
|
+
createDiff,
|
|
177963
|
+
cameraPreset
|
|
177964
|
+
});
|
|
177965
|
+
processResult(result);
|
|
177966
|
+
if (!result.ok) {
|
|
177967
|
+
onError(result.errorMessage ?? "Snapshot generation failed");
|
|
177968
|
+
return onExit2(1);
|
|
177768
177969
|
}
|
|
177769
177970
|
}
|
|
177770
177971
|
}
|
|
@@ -177786,12 +177987,13 @@ Run with --update to fix.`);
|
|
|
177786
177987
|
|
|
177787
177988
|
// cli/snapshot/register.ts
|
|
177788
177989
|
var registerSnapshot = (program3) => {
|
|
177789
|
-
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) => {
|
|
177990
|
+
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) => {
|
|
177790
177991
|
if (options.cameraPreset && !CAMERA_PRESET_NAMES.includes(options.cameraPreset)) {
|
|
177791
177992
|
console.error(`Unknown camera preset "${options.cameraPreset}". Valid presets: ${CAMERA_PRESET_NAMES.join(", ")}`);
|
|
177792
177993
|
process.exit(1);
|
|
177793
177994
|
}
|
|
177794
177995
|
await snapshotProject({
|
|
177996
|
+
concurrency: Math.max(1, Number.parseInt(options.concurrency || "1", 10)),
|
|
177795
177997
|
update: options.update ?? false,
|
|
177796
177998
|
threeD: options["3d"] ?? false,
|
|
177797
177999
|
pcbOnly: options.pcbOnly ?? false,
|
|
@@ -177809,7 +178011,7 @@ var registerSnapshot = (program3) => {
|
|
|
177809
178011
|
};
|
|
177810
178012
|
|
|
177811
178013
|
// cli/transpile/register.ts
|
|
177812
|
-
import
|
|
178014
|
+
import path65 from "node:path";
|
|
177813
178015
|
var registerTranspile = (program3) => {
|
|
177814
178016
|
program3.command("transpile").description("Transpile TypeScript/TSX to JavaScript (ESM, CommonJS, and type declarations)").argument("[file]", "Path to the entry file").action(async (file) => {
|
|
177815
178017
|
try {
|
|
@@ -177817,7 +178019,7 @@ var registerTranspile = (program3) => {
|
|
|
177817
178019
|
fileOrDir: file,
|
|
177818
178020
|
includeBoardFiles: false
|
|
177819
178021
|
});
|
|
177820
|
-
const distDir =
|
|
178022
|
+
const distDir = path65.join(projectDir, "dist");
|
|
177821
178023
|
validateMainInDist(projectDir, distDir);
|
|
177822
178024
|
console.log("Transpiling entry file...");
|
|
177823
178025
|
const entryFile = mainEntrypoint || circuitFiles[0];
|