@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.
- package/lib/footprint-translators/get-footprinter-string-from-kicad.ts +21 -0
- package/lib/footprint-translators/get-jlc-package-from-footprinter-string.ts +12 -0
- package/lib/footprint-translators/index.ts +25 -0
- package/lib/jlc-parts-engine.ts +19 -21
- package/package.json +1 -1
- package/tests/jlc-parts-engine.test.ts +38 -1
|
@@ -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
|
+
}
|
package/lib/jlc-parts-engine.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
@@ -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: "
|
|
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",
|