@tscircuit/cli 0.1.2086 → 0.1.2088
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/dist/cli/main.js +101 -26
- package/dist/lib/index.js +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -182,6 +182,24 @@ the solver can be reproduced independently. Values that JSON cannot represent
|
|
|
182
182
|
directly, such as `undefined`, `NaN`, maps, sets, or circular references, use
|
|
183
183
|
explicit `value_type` records instead of being silently discarded.
|
|
184
184
|
|
|
185
|
+
## Searching DigiKey and Mouser parts
|
|
186
|
+
|
|
187
|
+
Use `--digikey` or `--mouser` for distributor stock and supplier part numbers:
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
tsci search --digikey LM358
|
|
191
|
+
tsci search --mouser --json "buck converter"
|
|
192
|
+
tsci search --digikey --mouser LM358
|
|
193
|
+
tsci search --ti --digikey --mouser --json TPS62160
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Results come from [DigiKey Search](https://digikeysearch.tscircuit.com) and
|
|
197
|
+
[Mouser Search](https://mousersearch.tscircuit.com), without requiring distributor
|
|
198
|
+
API credentials. Text output includes supplier part numbers; JSON preserves
|
|
199
|
+
returned part metadata with `source: "digikey"` or `source: "mouser"`.
|
|
200
|
+
Stock and pricing reflect the services' cached responses. These flags provide
|
|
201
|
+
part discovery, not direct TSX import from distributors.
|
|
202
|
+
|
|
185
203
|
## Searching Texas Instruments parts
|
|
186
204
|
|
|
187
205
|
Use `--ti` to search the TI catalog indexed by [tisearch](https://tisearch.tscircuit.com):
|
package/dist/cli/main.js
CHANGED
|
@@ -79831,7 +79831,7 @@ class BitmapCanvasContext {
|
|
|
79831
79831
|
pathParts = [];
|
|
79832
79832
|
currentPolygon = null;
|
|
79833
79833
|
constructor(width, height) {
|
|
79834
|
-
this.canvas =
|
|
79834
|
+
this.canvas = createBitmapCanvasSurface(width, height);
|
|
79835
79835
|
this.pixels = new Uint8Array(width * height);
|
|
79836
79836
|
}
|
|
79837
79837
|
beginPath() {
|
|
@@ -80380,7 +80380,7 @@ var import_gerber_to_svg, renderTscircuitRepro = async (tsx, options = {}) => {
|
|
|
80380
80380
|
const svg = await renderGerberToSvg(gerber);
|
|
80381
80381
|
const boardSvg = forceSvgViewport({ svg, bounds, width, height });
|
|
80382
80382
|
return getMaskFromPng(renderSvgToPng(boardSvg));
|
|
80383
|
-
}, transformPoint = (matrix, point) => applyToPoint34(matrix, point), getBounds2 = (parts) => {
|
|
80383
|
+
}, createBitmapCanvasSurface = (width, height) => Object.assign(Object.create(null), { width, height }), transformPoint = (matrix, point) => applyToPoint34(matrix, point), getBounds2 = (parts) => {
|
|
80384
80384
|
let minX = Number.POSITIVE_INFINITY;
|
|
80385
80385
|
let minY = Number.POSITIVE_INFINITY;
|
|
80386
80386
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -80498,9 +80498,9 @@ var import_gerber_to_svg, renderTscircuitRepro = async (tsx, options = {}) => {
|
|
|
80498
80498
|
let bounds = null;
|
|
80499
80499
|
for (const point of element.route) {
|
|
80500
80500
|
if ("start" in point && "end" in point) {
|
|
80501
|
-
const
|
|
80502
|
-
bounds = includePointInBounds(bounds, point.start,
|
|
80503
|
-
bounds = includePointInBounds(bounds, point.end,
|
|
80501
|
+
const margin = (point.width ?? 0) / 2;
|
|
80502
|
+
bounds = includePointInBounds(bounds, point.start, margin);
|
|
80503
|
+
bounds = includePointInBounds(bounds, point.end, margin);
|
|
80504
80504
|
continue;
|
|
80505
80505
|
}
|
|
80506
80506
|
if (!("x" in point) || !("y" in point))
|
|
@@ -80775,10 +80775,25 @@ var import_gerber_to_svg, renderTscircuitRepro = async (tsx, options = {}) => {
|
|
|
80775
80775
|
const localX = i % bitmapMask.rect.width;
|
|
80776
80776
|
const localY = Math.floor(i / bitmapMask.rect.width);
|
|
80777
80777
|
const globalPixelIndex = (bitmapMask.rect.y + localY) * width + bitmapMask.rect.x + localX;
|
|
80778
|
-
const
|
|
80779
|
-
|
|
80778
|
+
const x = bitmapMask.rect.x + localX;
|
|
80779
|
+
const y = bitmapMask.rect.y + localY;
|
|
80780
|
+
const contactingOwners = new Set;
|
|
80781
|
+
for (let dy = -1;dy <= 1; dy++) {
|
|
80782
|
+
const ny = y + dy;
|
|
80783
|
+
if (ny < 0 || ny >= height)
|
|
80784
|
+
continue;
|
|
80785
|
+
for (let dx = -1;dx <= 1; dx++) {
|
|
80786
|
+
const nx = x + dx;
|
|
80787
|
+
if (nx < 0 || nx >= width)
|
|
80788
|
+
continue;
|
|
80789
|
+
const owner = pixelOwners[ny * width + nx];
|
|
80790
|
+
if (owner && owner !== key)
|
|
80791
|
+
contactingOwners.add(owner);
|
|
80792
|
+
}
|
|
80793
|
+
}
|
|
80794
|
+
for (const owner of contactingOwners) {
|
|
80780
80795
|
const [firstConnectivityKey, secondConnectivityKey] = [
|
|
80781
|
-
|
|
80796
|
+
owner,
|
|
80782
80797
|
key
|
|
80783
80798
|
].sort();
|
|
80784
80799
|
const shortKey = `${layer}:${firstConnectivityKey}:${secondConnectivityKey}`;
|
|
@@ -80798,7 +80813,8 @@ var import_gerber_to_svg, renderTscircuitRepro = async (tsx, options = {}) => {
|
|
|
80798
80813
|
secondOwnerLabels: getUniqueOwnerLabels(secondElements, db)
|
|
80799
80814
|
});
|
|
80800
80815
|
}
|
|
80801
|
-
}
|
|
80816
|
+
}
|
|
80817
|
+
if (!pixelOwners[globalPixelIndex]) {
|
|
80802
80818
|
pixelOwners[globalPixelIndex] = key;
|
|
80803
80819
|
}
|
|
80804
80820
|
}
|
|
@@ -80990,10 +81006,30 @@ var import_gerber_to_svg, renderTscircuitRepro = async (tsx, options = {}) => {
|
|
|
80990
81006
|
createChunk("IDAT", deflateSync2(scanlines, { level: 1 })),
|
|
80991
81007
|
createChunk("IEND", new Uint8Array)
|
|
80992
81008
|
]);
|
|
80993
|
-
},
|
|
80994
|
-
|
|
80995
|
-
|
|
80996
|
-
|
|
81009
|
+
}, markerLegend, getGlyphAdvance = (character) => glyphAdvanceRatio3[character] ?? (character === " " ? spaceWidthRatio2 : glyphWidthRatio2), getAlphabetTextWidth = (text, size) => {
|
|
81010
|
+
let width = 0;
|
|
81011
|
+
for (const character of text) {
|
|
81012
|
+
width += getGlyphAdvance(character) * size;
|
|
81013
|
+
}
|
|
81014
|
+
return width;
|
|
81015
|
+
}, getLegendLabel = (entry, maxWidth, size = 16) => {
|
|
81016
|
+
const label = entry.labels.length > 0 ? entry.labels.join(",") : entry.connectivityKey;
|
|
81017
|
+
if (getAlphabetTextWidth(label, size) <= maxWidth)
|
|
81018
|
+
return label;
|
|
81019
|
+
const ellipsis = "...";
|
|
81020
|
+
let fittedLabel = "";
|
|
81021
|
+
let fittedWidth = getAlphabetTextWidth(ellipsis, size);
|
|
81022
|
+
if (fittedWidth > maxWidth)
|
|
81023
|
+
return "";
|
|
81024
|
+
for (const character of label) {
|
|
81025
|
+
const characterWidth = getGlyphAdvance(character) * size;
|
|
81026
|
+
if (fittedWidth + characterWidth > maxWidth)
|
|
81027
|
+
break;
|
|
81028
|
+
fittedLabel += character;
|
|
81029
|
+
fittedWidth += characterWidth;
|
|
81030
|
+
}
|
|
81031
|
+
return `${fittedLabel}${ellipsis}`;
|
|
81032
|
+
}, createAlphabetTextSvg = ({
|
|
80997
81033
|
text,
|
|
80998
81034
|
x,
|
|
80999
81035
|
top,
|
|
@@ -81007,7 +81043,7 @@ var import_gerber_to_svg, renderTscircuitRepro = async (tsx, options = {}) => {
|
|
|
81007
81043
|
if (path) {
|
|
81008
81044
|
paths.push(`<path d="${path}" transform="translate(${cursorX} 0)"/>`);
|
|
81009
81045
|
}
|
|
81010
|
-
cursorX +=
|
|
81046
|
+
cursorX += getGlyphAdvance(character);
|
|
81011
81047
|
}
|
|
81012
81048
|
const renderedSize = maxWidth === undefined || cursorX === 0 ? size : Math.min(size, maxWidth / cursorX);
|
|
81013
81049
|
return `<g fill="none" stroke="#111" stroke-width="${strokeWidthRatio2}" stroke-linecap="round" stroke-linejoin="round" transform="translate(${x} ${top - 0.24 * renderedSize}) scale(${renderedSize})">${paths.join("")}</g>`;
|
|
@@ -81028,15 +81064,19 @@ var import_gerber_to_svg, renderTscircuitRepro = async (tsx, options = {}) => {
|
|
|
81028
81064
|
size: 16,
|
|
81029
81065
|
maxWidth: width - 42
|
|
81030
81066
|
})}`),
|
|
81031
|
-
...legend.map((entry, index) =>
|
|
81067
|
+
...legend.map((entry, index) => {
|
|
81068
|
+
const labelMaxWidth = width - 42;
|
|
81069
|
+
const labelSize = 16;
|
|
81070
|
+
return `
|
|
81032
81071
|
<rect x="10" y="${headerHeight + (markerLegend.length + index) * rowHeight + 3}" width="14" height="10" rx="1" fill="rgb(${entry.color.join(",")})"/>
|
|
81033
81072
|
${createAlphabetTextSvg({
|
|
81034
|
-
|
|
81035
|
-
|
|
81036
|
-
|
|
81037
|
-
|
|
81038
|
-
|
|
81039
|
-
|
|
81073
|
+
text: getLegendLabel(entry, labelMaxWidth, labelSize),
|
|
81074
|
+
x: 32,
|
|
81075
|
+
top: headerHeight + (markerLegend.length + index) * rowHeight + 2,
|
|
81076
|
+
size: labelSize,
|
|
81077
|
+
maxWidth: labelMaxWidth
|
|
81078
|
+
})}`;
|
|
81079
|
+
})
|
|
81040
81080
|
].join("");
|
|
81041
81081
|
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
|
81042
81082
|
<rect width="100%" height="100%" fill="white"/>
|
|
@@ -153438,7 +153478,7 @@ var import_perfect_cli = __toESM3(require_dist3(), 1);
|
|
|
153438
153478
|
// lib/getVersion.ts
|
|
153439
153479
|
import { createRequire as createRequire2 } from "node:module";
|
|
153440
153480
|
// package.json
|
|
153441
|
-
var version = "0.1.
|
|
153481
|
+
var version = "0.1.2087";
|
|
153442
153482
|
var package_default = {
|
|
153443
153483
|
name: "@tscircuit/cli",
|
|
153444
153484
|
version,
|
|
@@ -153454,7 +153494,7 @@ var package_default = {
|
|
|
153454
153494
|
devDependencies: {
|
|
153455
153495
|
"@babel/standalone": "^7.26.9",
|
|
153456
153496
|
"@biomejs/biome": "^1.9.4",
|
|
153457
|
-
"@tscircuit/check-shorts": "https://jscdn.tscircuit.com/@tscircuit/check-shorts/0.0.
|
|
153497
|
+
"@tscircuit/check-shorts": "https://jscdn.tscircuit.com/@tscircuit/check-shorts/0.0.24.tgz",
|
|
153458
153498
|
"@tscircuit/circuit-json-placement-analysis": "^0.0.15",
|
|
153459
153499
|
"@tscircuit/circuit-json-routing-analysis": "^0.0.8",
|
|
153460
153500
|
"@tscircuit/circuit-json-schematic-placement-analysis": "github:tscircuit/circuit-json-schematic-placement-analysis#41260fc05b736c0f3fdc33892b6da0ece40107b9",
|
|
@@ -366857,15 +366897,20 @@ var entry_default = Fuse2;
|
|
|
366857
366897
|
|
|
366858
366898
|
// cli/search/register.ts
|
|
366859
366899
|
var registerSearch = (program) => {
|
|
366860
|
-
program.command("search").description("Search for footprints, CAD models or packages in the tscircuit ecosystem").argument("<query...>", "Search query (e.g. keyword, author, or package name)").option("--kicad", "Search KiCad footprints").option("--jlcpcb", "Search JLCPCB components").option("--lcsc", "Alias for --jlcpcb").option("--ti", "Search Texas Instruments components").option("--tscircuit", "Search tscircuit registry packages").option("--json", "Output search results as JSON").action(async (queryParts, opts) => {
|
|
366900
|
+
program.command("search").description("Search for footprints, CAD models or packages in the tscircuit ecosystem").argument("<query...>", "Search query (e.g. keyword, author, or package name)").option("--kicad", "Search KiCad footprints").option("--jlcpcb", "Search JLCPCB components").option("--lcsc", "Alias for --jlcpcb").option("--ti", "Search Texas Instruments components").option("--digikey", "Search DigiKey components").option("--mouser", "Search Mouser components").option("--tscircuit", "Search tscircuit registry packages").option("--json", "Output search results as JSON").action(async (queryParts, opts) => {
|
|
366861
366901
|
const query = getQueryFromParts(queryParts);
|
|
366862
|
-
const hasFilters = opts.kicad || opts.jlcpcb || opts.lcsc || opts.ti || opts.tscircuit;
|
|
366902
|
+
const hasFilters = opts.kicad || opts.jlcpcb || opts.lcsc || opts.ti || opts.digikey || opts.mouser || opts.tscircuit;
|
|
366863
366903
|
const searchKicad = opts.kicad;
|
|
366864
366904
|
const searchJlc = opts.jlcpcb || opts.lcsc || !hasFilters;
|
|
366865
366905
|
const searchTscircuit = opts.tscircuit;
|
|
366866
366906
|
let results = { packages: [] };
|
|
366867
366907
|
let jlcResults = [];
|
|
366868
366908
|
let tiResults = [];
|
|
366909
|
+
const distributors = [
|
|
366910
|
+
{ source: "digikey", label: "DigiKey", enabled: opts.digikey },
|
|
366911
|
+
{ source: "mouser", label: "Mouser", enabled: opts.mouser }
|
|
366912
|
+
];
|
|
366913
|
+
const distributorResults = [];
|
|
366869
366914
|
let kicadResults = [];
|
|
366870
366915
|
try {
|
|
366871
366916
|
if (searchTscircuit) {
|
|
@@ -366889,6 +366934,23 @@ var registerSearch = (program) => {
|
|
|
366889
366934
|
throw new Error("TI search returned an invalid response");
|
|
366890
366935
|
tiResults = data.components;
|
|
366891
366936
|
}
|
|
366937
|
+
for (const distributor of distributors) {
|
|
366938
|
+
if (!distributor.enabled)
|
|
366939
|
+
continue;
|
|
366940
|
+
const url = `https://${distributor.source}search.tscircuit.com/api/search?limit=10&q=${encodeURIComponent(query)}`;
|
|
366941
|
+
const response = await fetch(url, {
|
|
366942
|
+
headers: { accept: "application/json" }
|
|
366943
|
+
});
|
|
366944
|
+
if (!response.ok)
|
|
366945
|
+
throw new Error(`${distributor.label} search failed (HTTP ${response.status})`);
|
|
366946
|
+
const data = await response.json();
|
|
366947
|
+
if (!Array.isArray(data?.components))
|
|
366948
|
+
throw new Error(`${distributor.label} search returned an invalid response`);
|
|
366949
|
+
distributorResults.push({
|
|
366950
|
+
...distributor,
|
|
366951
|
+
components: data.components
|
|
366952
|
+
});
|
|
366953
|
+
}
|
|
366892
366954
|
if (searchKicad) {
|
|
366893
366955
|
const kicadFiles = await fetch("https://kicad-mod-cache.tscircuit.com/kicad_files.json").then((r) => r.json());
|
|
366894
366956
|
const fuse = new entry_default(kicadFiles);
|
|
@@ -366912,6 +366974,7 @@ var registerSearch = (program) => {
|
|
|
366912
366974
|
...comp,
|
|
366913
366975
|
source: "ti"
|
|
366914
366976
|
})),
|
|
366977
|
+
...distributorResults.flatMap(({ source, components }) => components.map((comp) => ({ ...comp, source }))),
|
|
366915
366978
|
...jlcResults.map((comp) => ({
|
|
366916
366979
|
source: "jlcpcb",
|
|
366917
366980
|
...comp
|
|
@@ -366923,11 +366986,12 @@ var registerSearch = (program) => {
|
|
|
366923
366986
|
}, null, 2));
|
|
366924
366987
|
return;
|
|
366925
366988
|
}
|
|
366926
|
-
if (!kicadResults.length && !results.packages.length && !jlcResults.length && !tiResults.length) {
|
|
366989
|
+
if (!kicadResults.length && !results.packages.length && !jlcResults.length && !tiResults.length && !distributorResults.some(({ components }) => components.length)) {
|
|
366927
366990
|
const sources = [
|
|
366928
366991
|
searchTscircuit && "tscircuit registry",
|
|
366929
366992
|
searchJlc && "JLCPCB",
|
|
366930
366993
|
opts.ti && "Texas Instruments",
|
|
366994
|
+
...distributors.filter((d) => d.enabled).map((d) => d.label),
|
|
366931
366995
|
searchKicad && "KiCad"
|
|
366932
366996
|
].filter(Boolean);
|
|
366933
366997
|
console.log(kleur_default.yellow(`No results found for "${query}" in ${sources.join(", ")}.`));
|
|
@@ -366961,6 +367025,17 @@ var registerSearch = (program) => {
|
|
|
366961
367025
|
console.log(`${idx + 1}. ${comp.mfr} - ${comp.description} (stock: ${comp.stock.toLocaleString("en-US")})`);
|
|
366962
367026
|
});
|
|
366963
367027
|
}
|
|
367028
|
+
for (const { source, label, components } of distributorResults) {
|
|
367029
|
+
if (!components.length)
|
|
367030
|
+
continue;
|
|
367031
|
+
console.log();
|
|
367032
|
+
console.log(kleur_default.bold().underline(`Found ${components.length} component(s) in ${label} search:`));
|
|
367033
|
+
components.forEach((comp, idx) => {
|
|
367034
|
+
const supplierNumber = comp.supplier_part_number || comp[`${source}_product_number`];
|
|
367035
|
+
const identity = supplierNumber ? `${comp.mfr} (${supplierNumber})` : comp.mfr;
|
|
367036
|
+
console.log(`${idx + 1}. ${identity} - ${comp.description} (stock: ${comp.stock.toLocaleString("en-US")})`);
|
|
367037
|
+
});
|
|
367038
|
+
}
|
|
366964
367039
|
console.log(`
|
|
366965
367040
|
`);
|
|
366966
367041
|
});
|
package/dist/lib/index.js
CHANGED
|
@@ -69109,7 +69109,7 @@ var getNodeHandler = (winterSpec, { port, middleware = [] }) => {
|
|
|
69109
69109
|
}));
|
|
69110
69110
|
};
|
|
69111
69111
|
// package.json
|
|
69112
|
-
var version = "0.1.
|
|
69112
|
+
var version = "0.1.2087";
|
|
69113
69113
|
var package_default = {
|
|
69114
69114
|
name: "@tscircuit/cli",
|
|
69115
69115
|
version,
|
|
@@ -69125,7 +69125,7 @@ var package_default = {
|
|
|
69125
69125
|
devDependencies: {
|
|
69126
69126
|
"@babel/standalone": "^7.26.9",
|
|
69127
69127
|
"@biomejs/biome": "^1.9.4",
|
|
69128
|
-
"@tscircuit/check-shorts": "https://jscdn.tscircuit.com/@tscircuit/check-shorts/0.0.
|
|
69128
|
+
"@tscircuit/check-shorts": "https://jscdn.tscircuit.com/@tscircuit/check-shorts/0.0.24.tgz",
|
|
69129
69129
|
"@tscircuit/circuit-json-placement-analysis": "^0.0.15",
|
|
69130
69130
|
"@tscircuit/circuit-json-routing-analysis": "^0.0.8",
|
|
69131
69131
|
"@tscircuit/circuit-json-schematic-placement-analysis": "github:tscircuit/circuit-json-schematic-placement-analysis#41260fc05b736c0f3fdc33892b6da0ece40107b9",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2088",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/tscircuit/cli"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@babel/standalone": "^7.26.9",
|
|
15
15
|
"@biomejs/biome": "^1.9.4",
|
|
16
|
-
"@tscircuit/check-shorts": "https://jscdn.tscircuit.com/@tscircuit/check-shorts/0.0.
|
|
16
|
+
"@tscircuit/check-shorts": "https://jscdn.tscircuit.com/@tscircuit/check-shorts/0.0.24.tgz",
|
|
17
17
|
"@tscircuit/circuit-json-placement-analysis": "^0.0.15",
|
|
18
18
|
"@tscircuit/circuit-json-routing-analysis": "^0.0.8",
|
|
19
19
|
"@tscircuit/circuit-json-schematic-placement-analysis": "github:tscircuit/circuit-json-schematic-placement-analysis#41260fc05b736c0f3fdc33892b6da0ece40107b9",
|