@jlcpcb/core 0.1.0

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +474 -0
  3. package/package.json +48 -0
  4. package/src/api/easyeda-community.ts +259 -0
  5. package/src/api/easyeda.ts +153 -0
  6. package/src/api/index.ts +7 -0
  7. package/src/api/jlc.ts +185 -0
  8. package/src/constants/design-rules.ts +119 -0
  9. package/src/constants/footprints.ts +68 -0
  10. package/src/constants/index.ts +7 -0
  11. package/src/constants/kicad.ts +147 -0
  12. package/src/converter/category-router.ts +638 -0
  13. package/src/converter/footprint-mapper.ts +236 -0
  14. package/src/converter/footprint.ts +949 -0
  15. package/src/converter/global-lib-table.ts +394 -0
  16. package/src/converter/index.ts +46 -0
  17. package/src/converter/lib-table.ts +181 -0
  18. package/src/converter/svg-arc.ts +179 -0
  19. package/src/converter/symbol-templates.ts +214 -0
  20. package/src/converter/symbol.ts +1682 -0
  21. package/src/converter/value-normalizer.ts +262 -0
  22. package/src/index.ts +25 -0
  23. package/src/parsers/easyeda-shapes.ts +628 -0
  24. package/src/parsers/http-client.ts +96 -0
  25. package/src/parsers/index.ts +38 -0
  26. package/src/parsers/utils.ts +29 -0
  27. package/src/services/component-service.ts +100 -0
  28. package/src/services/fix-service.ts +50 -0
  29. package/src/services/index.ts +9 -0
  30. package/src/services/library-service.ts +696 -0
  31. package/src/types/component.ts +61 -0
  32. package/src/types/easyeda-community.ts +78 -0
  33. package/src/types/easyeda.ts +356 -0
  34. package/src/types/index.ts +12 -0
  35. package/src/types/jlc.ts +84 -0
  36. package/src/types/kicad.ts +136 -0
  37. package/src/types/mcp.ts +77 -0
  38. package/src/types/project.ts +60 -0
  39. package/src/utils/conversion.ts +104 -0
  40. package/src/utils/file-system.ts +143 -0
  41. package/src/utils/index.ts +8 -0
  42. package/src/utils/logger.ts +96 -0
  43. package/src/utils/validation.ts +110 -0
  44. package/tsconfig.json +9 -0
@@ -0,0 +1,638 @@
1
+ /**
2
+ * Category Router
3
+ * Routes components to category-based symbol libraries with robust keyword matching
4
+ * JLC-MCP-Resistors.kicad_sym, JLC-MCP-MCUs.kicad_sym, etc.
5
+ */
6
+
7
+ export type LibraryCategory =
8
+ | 'Resistors'
9
+ | 'Capacitors'
10
+ | 'Inductors'
11
+ | 'Diodes'
12
+ | 'Transistors'
13
+ | 'Crystals'
14
+ | 'Power'
15
+ | 'MCUs'
16
+ | 'Memory'
17
+ | 'Sensors'
18
+ | 'Interface'
19
+ | 'Optocouplers'
20
+ | 'Connectors'
21
+ | 'ICs'
22
+ | 'Misc';
23
+
24
+ // Library naming prefix - used for KiCad library names and references
25
+ const LIBRARY_PREFIX = 'JLC-MCP';
26
+
27
+ // Prefix to category mapping (for passives and common components)
28
+ // Note: U is intentionally NOT mapped - use keyword detection for ICs/MCUs/Power/etc.
29
+ const PREFIX_CATEGORY_MAP: Record<string, LibraryCategory> = {
30
+ R: 'Resistors',
31
+ C: 'Capacitors',
32
+ L: 'Inductors',
33
+ FB: 'Inductors',
34
+ D: 'Diodes',
35
+ Q: 'Transistors',
36
+ Y: 'Crystals',
37
+ X: 'Crystals',
38
+ J: 'Connectors',
39
+ P: 'Connectors',
40
+ K: 'Misc', // Relays
41
+ F: 'Misc', // Fuses
42
+ };
43
+
44
+ // Ordered by specificity - check most specific categories first
45
+ const CATEGORY_KEYWORD_RULES: Array<{ category: LibraryCategory; keywords: string[] }> = [
46
+ // Most specific first - these override more general categories
47
+ {
48
+ category: 'MCUs',
49
+ keywords: [
50
+ 'mcu',
51
+ 'microcontroller',
52
+ 'microprocessor',
53
+ 'stm32',
54
+ 'stm8',
55
+ 'esp32',
56
+ 'esp8266',
57
+ 'atmega',
58
+ 'attiny',
59
+ 'pic16',
60
+ 'pic18',
61
+ 'pic32',
62
+ 'nrf52',
63
+ 'nrf51',
64
+ 'rp2040',
65
+ 'arm cortex',
66
+ 'risc-v',
67
+ 'riscv',
68
+ 'arduino',
69
+ 'samd',
70
+ 'sam3',
71
+ 'sam4',
72
+ 'lpc',
73
+ 'gd32',
74
+ 'ch32',
75
+ 'n76e',
76
+ 'nuvoton',
77
+ 'renesas',
78
+ 'cy8c',
79
+ 'psoc',
80
+ ],
81
+ },
82
+ {
83
+ category: 'Memory',
84
+ keywords: [
85
+ 'memory',
86
+ 'flash memory',
87
+ 'eeprom',
88
+ 'sram',
89
+ 'dram',
90
+ 'sdram',
91
+ 'fram',
92
+ 'nvram',
93
+ 'nand',
94
+ 'nor flash',
95
+ 'w25q',
96
+ 'w25n',
97
+ 'at24c',
98
+ 'at25',
99
+ 'is62',
100
+ 'is61',
101
+ 'as4c',
102
+ 'm24c',
103
+ 'mx25',
104
+ 'gd25',
105
+ 's25fl',
106
+ 'mt48',
107
+ 'cy62',
108
+ ],
109
+ },
110
+ {
111
+ category: 'Power',
112
+ keywords: [
113
+ 'voltage regulator',
114
+ 'regulator',
115
+ 'ldo',
116
+ 'dcdc',
117
+ 'dc-dc',
118
+ 'dc/dc',
119
+ 'buck converter',
120
+ 'boost converter',
121
+ 'buck-boost',
122
+ 'pmic',
123
+ 'voltage reference',
124
+ 'power management',
125
+ 'battery charger',
126
+ 'charge controller',
127
+ 'power switch',
128
+ 'load switch',
129
+ 'hot swap',
130
+ 'ams1117',
131
+ 'lm7805',
132
+ 'lm317',
133
+ 'ap2112',
134
+ 'mp1584',
135
+ 'mp2359',
136
+ 'tps6',
137
+ 'tps7',
138
+ 'rt8059',
139
+ 'xl4015',
140
+ 'lm2596',
141
+ 'ap3216',
142
+ 'sy8088',
143
+ 'me6211',
144
+ 'ht7333',
145
+ 'ht7533',
146
+ 'xc6206',
147
+ ],
148
+ },
149
+ {
150
+ category: 'Sensors',
151
+ keywords: [
152
+ 'sensor',
153
+ 'accelerometer',
154
+ 'gyroscope',
155
+ 'magnetometer',
156
+ 'imu',
157
+ 'temperature sensor',
158
+ 'humidity sensor',
159
+ 'pressure sensor',
160
+ 'proximity sensor',
161
+ 'hall effect',
162
+ 'hall sensor',
163
+ 'current sense',
164
+ 'current sensor',
165
+ 'light sensor',
166
+ 'ambient light',
167
+ 'color sensor',
168
+ 'gas sensor',
169
+ 'bme280',
170
+ 'bmp280',
171
+ 'bme680',
172
+ 'mpu6050',
173
+ 'mpu9250',
174
+ 'lis3dh',
175
+ 'adxl345',
176
+ 'hmc5883',
177
+ 'qmc5883',
178
+ 'dht11',
179
+ 'dht22',
180
+ 'ds18b20',
181
+ 'sht30',
182
+ 'sht40',
183
+ 'ina219',
184
+ 'ina226',
185
+ 'apds9960',
186
+ 'tsl2561',
187
+ 'veml6070',
188
+ 'max30102',
189
+ 'mlx90614',
190
+ ],
191
+ },
192
+ {
193
+ category: 'Interface',
194
+ keywords: [
195
+ 'interface ic',
196
+ 'transceiver',
197
+ 'level shifter',
198
+ 'level translator',
199
+ 'uart',
200
+ 'usart',
201
+ 'usb controller',
202
+ 'usb hub',
203
+ 'usb switch',
204
+ 'usb protection',
205
+ 'i2c expander',
206
+ 'io expander',
207
+ 'spi',
208
+ 'can transceiver',
209
+ 'can controller',
210
+ 'rs485',
211
+ 'rs-485',
212
+ 'rs232',
213
+ 'rs-232',
214
+ 'ethernet phy',
215
+ 'phy',
216
+ 'hdmi',
217
+ 'lvds',
218
+ 'ch340',
219
+ 'ch341',
220
+ 'cp2102',
221
+ 'cp2104',
222
+ 'ft232',
223
+ 'ft2232',
224
+ 'max485',
225
+ 'max3485',
226
+ 'max232',
227
+ 'sp3485',
228
+ 'sn65hvd',
229
+ 'tja1050',
230
+ 'mcp2515',
231
+ 'mcp2551',
232
+ 'pca9685',
233
+ 'tca9548',
234
+ 'pcf8574',
235
+ 'mcp23017',
236
+ 'enc28j60',
237
+ 'w5500',
238
+ 'lan8720',
239
+ 'dp83848',
240
+ 'usb3300',
241
+ 'tusb',
242
+ ],
243
+ },
244
+ {
245
+ category: 'Optocouplers',
246
+ keywords: [
247
+ 'optocoupler',
248
+ 'optoisolator',
249
+ 'photocoupler',
250
+ 'opto-isolator',
251
+ 'opto isolator',
252
+ 'optical isolator',
253
+ 'pc817',
254
+ 'pc357',
255
+ 'el817',
256
+ 'tlp181',
257
+ 'tlp281',
258
+ 'tlp291',
259
+ '6n137',
260
+ '6n136',
261
+ 'hcpl',
262
+ 'acpl',
263
+ 'vo617',
264
+ 'ps2801',
265
+ 'ps2501',
266
+ 'moc3021',
267
+ 'moc3041',
268
+ '4n25',
269
+ '4n35',
270
+ ],
271
+ },
272
+ {
273
+ category: 'Crystals',
274
+ keywords: [
275
+ 'crystal',
276
+ 'oscillator',
277
+ 'resonator',
278
+ 'xtal',
279
+ 'tcxo',
280
+ 'vcxo',
281
+ 'ocxo',
282
+ 'mems oscillator',
283
+ 'clock generator',
284
+ 'rtc crystal',
285
+ 'ceramic resonator',
286
+ ],
287
+ },
288
+ // Less specific categories - checked after more specific ones
289
+ {
290
+ category: 'Transistors',
291
+ keywords: [
292
+ 'transistor',
293
+ 'mosfet',
294
+ 'bjt',
295
+ 'jfet',
296
+ 'igbt',
297
+ 'darlington',
298
+ 'n-channel',
299
+ 'p-channel',
300
+ 'n channel',
301
+ 'p channel',
302
+ 'npn',
303
+ 'pnp',
304
+ '2n2222',
305
+ '2n3904',
306
+ '2n3906',
307
+ '2n7002',
308
+ 'irf',
309
+ 'irfz',
310
+ 'ao3400',
311
+ 'ao3401',
312
+ 'si2301',
313
+ 'si2302',
314
+ 'bss138',
315
+ 'bc847',
316
+ 'bc857',
317
+ 's8050',
318
+ 's8550',
319
+ 'tip120',
320
+ 'tip122',
321
+ ],
322
+ },
323
+ {
324
+ category: 'Diodes',
325
+ keywords: [
326
+ 'diode',
327
+ 'led',
328
+ 'zener',
329
+ 'schottky',
330
+ 'tvs',
331
+ 'esd protection',
332
+ 'esd diode',
333
+ 'rectifier',
334
+ 'bridge rectifier',
335
+ 'photodiode',
336
+ 'laser diode',
337
+ 'varactor',
338
+ '1n4148',
339
+ '1n4007',
340
+ '1n5819',
341
+ 'ss14',
342
+ 'ss34',
343
+ 'ss54',
344
+ 'bat54',
345
+ 'b5819',
346
+ 'ws2812',
347
+ 'sk6812',
348
+ 'apa102',
349
+ 'smaj',
350
+ 'smbj',
351
+ 'pesd',
352
+ 'usblc6',
353
+ 'prtr5v0',
354
+ ],
355
+ },
356
+ {
357
+ category: 'Inductors',
358
+ keywords: ['inductor', 'ferrite bead', 'ferrite', 'choke', 'coil', 'transformer', 'common mode'],
359
+ },
360
+ {
361
+ category: 'Capacitors',
362
+ keywords: [
363
+ 'capacitor',
364
+ 'supercap',
365
+ 'ultracap',
366
+ 'mlcc',
367
+ 'electrolytic',
368
+ 'tantalum',
369
+ 'ceramic cap',
370
+ 'film cap',
371
+ 'polymer cap',
372
+ ],
373
+ },
374
+ {
375
+ category: 'Resistors',
376
+ keywords: [
377
+ 'resistor',
378
+ 'thermistor',
379
+ 'ntc',
380
+ 'ptc',
381
+ 'potentiometer',
382
+ 'varistor',
383
+ 'rheostat',
384
+ 'shunt resistor',
385
+ 'current sense resistor',
386
+ 'chip resistor',
387
+ ],
388
+ },
389
+ {
390
+ category: 'Connectors',
391
+ keywords: [
392
+ 'connector',
393
+ 'header',
394
+ 'socket',
395
+ 'terminal',
396
+ 'terminal block',
397
+ 'jack',
398
+ 'plug',
399
+ 'receptacle',
400
+ 'usb-c',
401
+ 'usb type-c',
402
+ 'micro usb',
403
+ 'mini usb',
404
+ 'usb-a',
405
+ 'usb-b',
406
+ 'hdmi connector',
407
+ 'rj45',
408
+ 'rj11',
409
+ 'barrel jack',
410
+ 'dc jack',
411
+ 'audio jack',
412
+ 'jst',
413
+ 'jst-xh',
414
+ 'jst-ph',
415
+ 'molex',
416
+ 'dupont',
417
+ 'pin header',
418
+ 'female header',
419
+ 'fpc',
420
+ 'ffc',
421
+ 'sim card',
422
+ 'sd card',
423
+ 'microsd',
424
+ 'pogo pin',
425
+ 'spring contact',
426
+ 'test point',
427
+ ],
428
+ },
429
+ // Catch-all for remaining ICs - must be last
430
+ {
431
+ category: 'ICs',
432
+ keywords: [
433
+ 'ic',
434
+ 'integrated circuit',
435
+ 'op amp',
436
+ 'opamp',
437
+ 'operational amplifier',
438
+ 'comparator',
439
+ 'amplifier',
440
+ 'audio amplifier',
441
+ 'adc',
442
+ 'dac',
443
+ 'analog to digital',
444
+ 'digital to analog',
445
+ 'timer',
446
+ '555 timer',
447
+ 'ne555',
448
+ 'logic gate',
449
+ 'flip-flop',
450
+ 'shift register',
451
+ 'multiplexer',
452
+ 'demux',
453
+ 'demultiplexer',
454
+ 'buffer',
455
+ 'driver',
456
+ 'gate driver',
457
+ 'motor driver',
458
+ 'led driver',
459
+ 'display driver',
460
+ 'codec',
461
+ 'mixer',
462
+ 'pll',
463
+ 'phase lock',
464
+ 'dds',
465
+ 'fpga',
466
+ 'cpld',
467
+ 'asic',
468
+ 'logic ic',
469
+ '74hc',
470
+ '74ls',
471
+ '74ahc',
472
+ 'cd4',
473
+ 'lm358',
474
+ 'lm324',
475
+ 'ne5532',
476
+ 'tl072',
477
+ 'tl084',
478
+ 'opa2134',
479
+ 'ad8',
480
+ 'max9',
481
+ 'uln2003',
482
+ 'l293',
483
+ 'drv8',
484
+ 'a4988',
485
+ 'tmc2',
486
+ ],
487
+ },
488
+ ];
489
+
490
+ /**
491
+ * Normalize text for fuzzy matching
492
+ * - lowercase
493
+ * - convert separators to spaces
494
+ * - remove special characters
495
+ * - normalize whitespace
496
+ */
497
+ function normalizeForMatching(text: string): string {
498
+ return text
499
+ .toLowerCase()
500
+ .replace(/[-_/\\]/g, ' ') // Convert separators to spaces
501
+ .replace(/[^a-z0-9\s]/g, '') // Remove special chars
502
+ .replace(/\s+/g, ' ') // Normalize whitespace
503
+ .trim();
504
+ }
505
+
506
+ /**
507
+ * Check if text contains keyword with fuzzy matching
508
+ */
509
+ function containsKeyword(text: string, keyword: string): boolean {
510
+ const normalizedText = normalizeForMatching(text);
511
+ const normalizedKeyword = normalizeForMatching(keyword);
512
+
513
+ // Direct substring match
514
+ if (normalizedText.includes(normalizedKeyword)) {
515
+ return true;
516
+ }
517
+
518
+ // Word boundary match (for short keywords like "led", "adc")
519
+ const words = normalizedText.split(' ');
520
+ if (words.includes(normalizedKeyword)) {
521
+ return true;
522
+ }
523
+
524
+ return false;
525
+ }
526
+
527
+ /**
528
+ * Determine library category from component prefix, LCSC category, and description
529
+ * Uses priority-ordered keyword matching with fuzzy detection
530
+ */
531
+ export function getLibraryCategory(
532
+ prefix: string,
533
+ category?: string,
534
+ description?: string
535
+ ): LibraryCategory {
536
+ // 1. Check prefix first (most reliable for passives)
537
+ const normalizedPrefix = prefix.toUpperCase();
538
+ if (PREFIX_CATEGORY_MAP[normalizedPrefix]) {
539
+ return PREFIX_CATEGORY_MAP[normalizedPrefix];
540
+ }
541
+
542
+ // 2. Combine category and description for keyword search
543
+ const searchText = [category || '', description || ''].join(' ');
544
+
545
+ if (searchText.trim()) {
546
+ // Check rules in order (most specific first)
547
+ for (const rule of CATEGORY_KEYWORD_RULES) {
548
+ for (const keyword of rule.keywords) {
549
+ if (containsKeyword(searchText, keyword)) {
550
+ return rule.category;
551
+ }
552
+ }
553
+ }
554
+ }
555
+
556
+ // 3. Default to Misc
557
+ return 'Misc';
558
+ }
559
+
560
+ /**
561
+ * Get symbol library filename for a category
562
+ * Returns: "JLC-MCP-Resistors.kicad_sym"
563
+ */
564
+ export function getLibraryFilename(category: LibraryCategory): string {
565
+ return `${LIBRARY_PREFIX}-${category}.kicad_sym`;
566
+ }
567
+
568
+ /**
569
+ * Get footprint library directory name
570
+ * All footprints go in a single directory
571
+ * Returns: "JLC-MCP.pretty"
572
+ */
573
+ export function getFootprintDirName(): string {
574
+ return `${LIBRARY_PREFIX}.pretty`;
575
+ }
576
+
577
+ /**
578
+ * Get 3D models directory name
579
+ * Returns: "JLC-MCP.3dshapes"
580
+ */
581
+ export function get3DModelsDirName(): string {
582
+ return `${LIBRARY_PREFIX}.3dshapes`;
583
+ }
584
+
585
+ /**
586
+ * Get full symbol reference for use in schematics
587
+ * Format: "JLC-MCP-Resistors:SymbolName"
588
+ */
589
+ export function getSymbolReference(category: LibraryCategory, symbolName: string): string {
590
+ const libraryName = `${LIBRARY_PREFIX}-${category}`;
591
+ return `${libraryName}:${symbolName}`;
592
+ }
593
+
594
+ /**
595
+ * Get full footprint reference for use in schematics/boards
596
+ * Format: "JLC-MCP:FootprintName"
597
+ */
598
+ export function getFootprintReference(footprintName: string): string {
599
+ return `${LIBRARY_PREFIX}:${footprintName}`;
600
+ }
601
+
602
+ /**
603
+ * Get all possible library categories
604
+ */
605
+ export function getAllCategories(): LibraryCategory[] {
606
+ return [
607
+ 'Resistors',
608
+ 'Capacitors',
609
+ 'Inductors',
610
+ 'Diodes',
611
+ 'Transistors',
612
+ 'Crystals',
613
+ 'Power',
614
+ 'MCUs',
615
+ 'Memory',
616
+ 'Sensors',
617
+ 'Interface',
618
+ 'Optocouplers',
619
+ 'Connectors',
620
+ 'ICs',
621
+ 'Misc',
622
+ ];
623
+ }
624
+
625
+ /**
626
+ * Parse library name to extract category
627
+ * "JLC-MCP-Resistors" -> "Resistors"
628
+ */
629
+ export function parseLibraryName(libraryName: string): LibraryCategory | null {
630
+ const match = libraryName.match(/^JLC-MCP-(\w+)$/);
631
+ if (match) {
632
+ const category = match[1] as LibraryCategory;
633
+ if (getAllCategories().includes(category)) {
634
+ return category;
635
+ }
636
+ }
637
+ return null;
638
+ }