@tscircuit/parts-engine 0.0.8 → 0.0.10

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.
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Transforms a KiCad footprint string into a generic "footprinter string".
3
+ * For now, this is a simplified conversion to a standard package name.
4
+ * e.g. "kicad:Resistor_SMD:R_0603_1608Metric" -> "0603"
5
+ */
6
+ export const getFootprinterStringFromKicad = (
7
+ kicadFootprint: string,
8
+ ): string | undefined => {
9
+ // kicad:Resistor_SMD:R_0603_1608Metric -> 0603
10
+ let match = kicadFootprint.match(/:[RC]_(\d{4})_/)
11
+ if (match) return match[1]
12
+
13
+ // kicad:Package_SO:SOIC-8_3.9x4.9mm_P1.27mm -> SOIC-8
14
+ // kicad:Package_TO_SOT_SMD:SOT-23 -> SOT-23
15
+ match = kicadFootprint.match(
16
+ /:(SOIC-\d+|SOT-\d+|SOD-\d+|SSOP-\d+|TSSOP-\d+|QFP-\d+|QFN-\d+)/,
17
+ )
18
+ if (match) return match[1]
19
+
20
+ return undefined
21
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Transforms a generic "footprinter string" into a JLC-compatible package name.
3
+ * e.g. "cap0603" -> "0603"
4
+ */
5
+ export const getJlcPackageFromFootprinterString = (
6
+ footprinterString: string,
7
+ ): string => {
8
+ if (footprinterString.includes("cap")) {
9
+ return footprinterString.replace(/cap/g, "")
10
+ }
11
+ return footprinterString
12
+ }
@@ -0,0 +1,25 @@
1
+ import { getFootprinterStringFromKicad } from "./get-footprinter-string-from-kicad"
2
+ import { getJlcPackageFromFootprinterString } from "./get-jlc-package-from-footprinter-string"
3
+
4
+ /**
5
+ * Get a JLC-compatible package name from a footprint string, which could be
6
+ * a KiCad footprint or a generic "footprinter string".
7
+ */
8
+ export const getJlcpcbPackageName = (
9
+ footprint: string | undefined,
10
+ ): string | undefined => {
11
+ if (!footprint) return undefined
12
+
13
+ if (footprint.startsWith("kicad:")) {
14
+ const footprinterString = getFootprinterStringFromKicad(footprint)
15
+ if (footprinterString) {
16
+ return getJlcPackageFromFootprinterString(footprinterString)
17
+ }
18
+
19
+ // Fallback for un-matched KiCad strings
20
+ return footprint
21
+ }
22
+
23
+ // Not a KiCad string, assume it's a footprinter string
24
+ return getJlcPackageFromFootprinterString(footprint)
25
+ }
@@ -1,4 +1,5 @@
1
1
  import type { PartsEngine, SupplierPartNumbers } from "@tscircuit/props"
2
+ import { getJlcpcbPackageName } from "./footprint-translators/index"
2
3
 
3
4
  const cache = new Map<string, any>()
4
5
 
@@ -23,14 +24,15 @@ export const jlcPartsEngine: PartsEngine = {
23
24
  sourceComponent,
24
25
  footprinterString,
25
26
  }): Promise<SupplierPartNumbers> => {
27
+ const jlcpcbPackage = getJlcpcbPackageName(footprinterString)
28
+
26
29
  if (
27
30
  sourceComponent.type === "source_component" &&
28
31
  sourceComponent.ftype === "simple_resistor"
29
32
  ) {
30
33
  const { resistors } = await getJlcPartsCached("resistors", {
31
- resistance:
32
- sourceComponent.display_resistance ?? sourceComponent.resistance,
33
- package: footprinterString,
34
+ resistance: sourceComponent.resistance,
35
+ package: jlcpcbPackage,
34
36
  })
35
37
 
36
38
  return {
@@ -40,13 +42,9 @@ export const jlcPartsEngine: PartsEngine = {
40
42
  sourceComponent.type === "source_component" &&
41
43
  sourceComponent.ftype === "simple_capacitor"
42
44
  ) {
43
- if (footprinterString?.includes("cap")) {
44
- footprinterString = footprinterString.replace("cap", "")
45
- }
46
45
  const { capacitors } = await getJlcPartsCached("capacitors", {
47
- capacitance:
48
- sourceComponent.display_capacitance ?? sourceComponent.capacitance,
49
- package: footprinterString,
46
+ capacitance: sourceComponent.capacitance,
47
+ package: jlcpcbPackage,
50
48
  })
51
49
 
52
50
  return {
@@ -82,7 +80,7 @@ export const jlcPartsEngine: PartsEngine = {
82
80
  ) {
83
81
  const { potentiometers } = await getJlcPartsCached("potentiometers", {
84
82
  resistance: sourceComponent.max_resistance,
85
- package: footprinterString,
83
+ package: jlcpcbPackage,
86
84
  })
87
85
  return {
88
86
  jlcpcb: (potentiometers ?? [])
@@ -94,7 +92,7 @@ export const jlcPartsEngine: PartsEngine = {
94
92
  sourceComponent.ftype === "simple_diode"
95
93
  ) {
96
94
  const { diodes } = await getJlcPartsCached("diodes", {
97
- package: footprinterString,
95
+ package: jlcpcbPackage,
98
96
  })
99
97
  return {
100
98
  jlcpcb: (diodes ?? []).map((d: any) => `C${d.lcsc}`).slice(0, 3),
@@ -104,7 +102,7 @@ export const jlcPartsEngine: PartsEngine = {
104
102
  sourceComponent.ftype === "simple_chip"
105
103
  ) {
106
104
  const { chips } = await getJlcPartsCached("chips", {
107
- package: footprinterString,
105
+ package: jlcpcbPackage,
108
106
  })
109
107
  return {
110
108
  jlcpcb: (chips ?? []).map((c: any) => `C${c.lcsc}`).slice(0, 3),
@@ -114,7 +112,7 @@ export const jlcPartsEngine: PartsEngine = {
114
112
  sourceComponent.ftype === "simple_transistor"
115
113
  ) {
116
114
  const { transistors } = await getJlcPartsCached("transistors", {
117
- package: footprinterString,
115
+ package: jlcpcbPackage,
118
116
  transistor_type: sourceComponent.transistor_type,
119
117
  })
120
118
  return {
@@ -126,7 +124,7 @@ export const jlcPartsEngine: PartsEngine = {
126
124
  ) {
127
125
  const { power_sources } = await getJlcPartsCached("power_sources", {
128
126
  voltage: sourceComponent.voltage,
129
- package: footprinterString,
127
+ package: jlcpcbPackage,
130
128
  })
131
129
  return {
132
130
  jlcpcb: (power_sources ?? []).map((p: any) => `C${p.lcsc}`).slice(0, 3),
@@ -137,7 +135,7 @@ export const jlcPartsEngine: PartsEngine = {
137
135
  ) {
138
136
  const { inductors } = await getJlcPartsCached("inductors", {
139
137
  inductance: sourceComponent.inductance,
140
- package: footprinterString,
138
+ package: jlcpcbPackage,
141
139
  })
142
140
  return {
143
141
  jlcpcb: (inductors ?? []).map((i: any) => `C${i.lcsc}`).slice(0, 3),
@@ -149,7 +147,7 @@ export const jlcPartsEngine: PartsEngine = {
149
147
  const { crystals } = await getJlcPartsCached("crystals", {
150
148
  frequency: sourceComponent.frequency,
151
149
  load_capacitance: sourceComponent.load_capacitance,
152
- package: footprinterString,
150
+ package: jlcpcbPackage,
153
151
  })
154
152
  return {
155
153
  jlcpcb: (crystals ?? []).map((c: any) => `C${c.lcsc}`).slice(0, 3),
@@ -159,7 +157,7 @@ export const jlcPartsEngine: PartsEngine = {
159
157
  sourceComponent.ftype === "simple_mosfet"
160
158
  ) {
161
159
  const { mosfets } = await getJlcPartsCached("mosfets", {
162
- package: footprinterString,
160
+ package: jlcpcbPackage,
163
161
  mosfet_mode: sourceComponent.mosfet_mode,
164
162
  channel_type: sourceComponent.channel_type,
165
163
  })
@@ -172,7 +170,7 @@ export const jlcPartsEngine: PartsEngine = {
172
170
  ) {
173
171
  const { resonators } = await getJlcPartsCached("resonators", {
174
172
  frequency: sourceComponent.frequency,
175
- package: footprinterString,
173
+ package: jlcpcbPackage,
176
174
  })
177
175
  return {
178
176
  jlcpcb: (resonators ?? []).map((r: any) => `C${r.lcsc}`).slice(0, 3),
@@ -183,7 +181,7 @@ export const jlcPartsEngine: PartsEngine = {
183
181
  ) {
184
182
  const { switches } = await getJlcPartsCached("switches", {
185
183
  switch_type: sourceComponent.type,
186
- package: footprinterString,
184
+ package: jlcpcbPackage,
187
185
  })
188
186
  return {
189
187
  jlcpcb: (switches ?? []).map((s: any) => `C${s.lcsc}`).slice(0, 3),
@@ -193,7 +191,7 @@ export const jlcPartsEngine: PartsEngine = {
193
191
  sourceComponent.ftype === "simple_led"
194
192
  ) {
195
193
  const { leds } = await getJlcPartsCached("leds", {
196
- package: footprinterString,
194
+ package: jlcpcbPackage,
197
195
  })
198
196
  return {
199
197
  jlcpcb: (leds ?? []).map((l: any) => `C${l.lcsc}`).slice(0, 3),
@@ -203,7 +201,7 @@ export const jlcPartsEngine: PartsEngine = {
203
201
  sourceComponent.ftype === "simple_fuse"
204
202
  ) {
205
203
  const { fuses } = await getJlcPartsCached("fuses", {
206
- package: footprinterString,
204
+ package: jlcpcbPackage,
207
205
  })
208
206
  return {
209
207
  jlcpcb: (fuses ?? []).map((l: any) => `C${l.lcsc}`).slice(0, 3),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/parts-engine",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "devDependencies": {
@@ -127,6 +127,25 @@ describe("jlcPartsEngine", () => {
127
127
  })
128
128
  })
129
129
 
130
+ test("should find resistor parts with kicad footprint", async () => {
131
+ const resistor: AnySourceComponent = {
132
+ type: "source_component",
133
+ ftype: "simple_resistor",
134
+ resistance: 10000,
135
+ source_component_id: "source_component_0",
136
+ name: "R1",
137
+ }
138
+
139
+ const result = await jlcPartsEngine.findPart({
140
+ sourceComponent: resistor,
141
+ footprinterString: "kicad:Resistor_SMD:R_0603_1608Metric",
142
+ })
143
+
144
+ expect(result).toEqual({
145
+ jlcpcb: ["C1234", "C5678", "C9012"],
146
+ })
147
+ })
148
+
130
149
  test("should find capacitor parts", async () => {
131
150
  const capacitor: AnySourceComponent = {
132
151
  type: "source_component",
@@ -138,7 +157,7 @@ describe("jlcPartsEngine", () => {
138
157
 
139
158
  const result = await jlcPartsEngine.findPart({
140
159
  sourceComponent: capacitor,
141
- footprinterString: "0603cap",
160
+ footprinterString: "cap0603",
142
161
  })
143
162
 
144
163
  expect(result).toEqual({
@@ -222,6 +241,24 @@ describe("jlcPartsEngine", () => {
222
241
  })
223
242
  })
224
243
 
244
+ test("should find chip parts with kicad footprint", async () => {
245
+ const chip: AnySourceComponent = {
246
+ type: "source_component",
247
+ ftype: "simple_chip",
248
+ source_component_id: "source_component_0",
249
+ name: "U1",
250
+ }
251
+
252
+ const result = await jlcPartsEngine.findPart({
253
+ sourceComponent: chip,
254
+ footprinterString: "kicad:Package_SO:SOIC-8_3.9x4.9mm_P1.27mm",
255
+ })
256
+
257
+ expect(result).toEqual({
258
+ jlcpcb: ["C5678", "C9012", "C3456"],
259
+ })
260
+ })
261
+
225
262
  test("should find transistor parts", async () => {
226
263
  const transistor: AnySourceComponent = {
227
264
  type: "source_component",