@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 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 = { width, height };
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 margin2 = (point.width ?? 0) / 2;
80502
- bounds = includePointInBounds(bounds, point.start, margin2);
80503
- bounds = includePointInBounds(bounds, point.end, margin2);
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 existingOwner = pixelOwners[globalPixelIndex];
80779
- if (existingOwner && existingOwner !== key) {
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
- existingOwner,
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
- } else if (!existingOwner) {
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
- }, getLegendLabel = (entry) => {
80994
- const labels = entry.labels.length > 0 ? entry.labels.join(",") : entry.connectivityKey;
80995
- return labels.length > 36 ? `${labels.slice(0, 33)}...` : labels;
80996
- }, markerLegend, createAlphabetTextSvg = ({
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 += glyphAdvanceRatio3[character] ?? (character === " " ? spaceWidthRatio2 : glyphWidthRatio2);
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
- text: getLegendLabel(entry),
81035
- x: 32,
81036
- top: headerHeight + (markerLegend.length + index) * rowHeight + 2,
81037
- size: 16,
81038
- maxWidth: width - 42
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.2084";
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.19.tgz",
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.2084";
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.19.tgz",
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.2086",
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.19.tgz",
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",