@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,262 @@
1
+ /**
2
+ * Component Value Normalizer
3
+ * Extracts and normalizes component values from descriptions
4
+ * "16k Ohm ±1% 0.1W" → "16k"
5
+ * "100nF 50V X7R" → "100n/50V"
6
+ */
7
+
8
+ export type ComponentType = 'resistor' | 'capacitor' | 'inductor' | 'diode' | 'transistor' | 'ic' | 'other';
9
+
10
+ export interface NormalizedValue {
11
+ displayValue: string; // For symbol Value property
12
+ originalValue: string; // Keep for Description
13
+ params?: {
14
+ value?: string; // Core value (e.g., "16k", "100n")
15
+ tolerance?: string; // e.g., "1%"
16
+ voltage?: string; // e.g., "50V"
17
+ power?: string; // e.g., "0.25W"
18
+ current?: string; // e.g., "2A"
19
+ };
20
+ }
21
+
22
+ // Regex patterns for value extraction
23
+ const PATTERNS = {
24
+ // Resistors: Match value with optional multiplier and unit
25
+ // "16k", "16kOhm", "16K OHM", "16000", "4.7k", "0R1" (0.1 ohm)
26
+ resistor: /(\d+(?:\.\d+)?)\s*([kKmMgGrR]?)\s*(?:ohm|Ohm|OHM|Ω|R)?/i,
27
+
28
+ // Capacitors: Match value with unit and optional voltage
29
+ // "100nF 50V", "10uF", "100pF", "1000uF/16V"
30
+ capacitor: /(\d+(?:\.\d+)?)\s*([pnuμmM]?)[Ff]?\s*(?:[\/\s]*(\d+)\s*[Vv])?/i,
31
+
32
+ // Inductors: Match value with unit and optional current
33
+ // "10uH 2A", "100nH", "4.7mH"
34
+ inductor: /(\d+(?:\.\d+)?)\s*([nμumM]?)[Hh]\s*(?:[\/\s]*(\d+(?:\.\d+)?)\s*[Aa])?/i,
35
+
36
+ // Voltage rating extraction
37
+ voltage: /(\d+(?:\.\d+)?)\s*[Vv]/,
38
+
39
+ // Tolerance extraction
40
+ tolerance: /[±]?\s*(\d+(?:\.\d+)?)\s*%/,
41
+
42
+ // Power rating extraction
43
+ power: /(\d+(?:\.\d+)?)\s*[Ww]/,
44
+
45
+ // Current rating extraction
46
+ current: /(\d+(?:\.\d+)?)\s*[Aa]/,
47
+ };
48
+
49
+ // Multiplier normalization
50
+ const MULTIPLIER_MAP: Record<string, string> = {
51
+ '': '',
52
+ 'r': '', // 0R1 style (0.1 ohm)
53
+ 'R': '',
54
+ 'k': 'k',
55
+ 'K': 'k',
56
+ 'm': 'm', // milli for caps/inductors, mega for resistors (context dependent)
57
+ 'M': 'M',
58
+ 'g': 'G',
59
+ 'G': 'G',
60
+ 'p': 'p',
61
+ 'n': 'n',
62
+ 'u': 'u',
63
+ 'μ': 'u',
64
+ };
65
+
66
+ /**
67
+ * Detect component type from prefix and category
68
+ */
69
+ export function detectComponentType(prefix: string, category?: string): ComponentType {
70
+ const p = prefix.toUpperCase();
71
+
72
+ switch (p) {
73
+ case 'R':
74
+ return 'resistor';
75
+ case 'C':
76
+ return 'capacitor';
77
+ case 'L':
78
+ return 'inductor';
79
+ case 'D':
80
+ return 'diode';
81
+ case 'Q':
82
+ return 'transistor';
83
+ case 'U':
84
+ return 'ic';
85
+ default:
86
+ // Fallback to category-based detection
87
+ if (category) {
88
+ const cat = category.toLowerCase();
89
+ if (cat.includes('resistor')) return 'resistor';
90
+ if (cat.includes('capacitor')) return 'capacitor';
91
+ if (cat.includes('inductor')) return 'inductor';
92
+ if (cat.includes('diode')) return 'diode';
93
+ if (cat.includes('transistor')) return 'transistor';
94
+ if (cat.includes('ic') || cat.includes('microcontroller')) return 'ic';
95
+ }
96
+ return 'other';
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Normalize resistor value
102
+ */
103
+ function normalizeResistor(description: string): NormalizedValue {
104
+ const match = description.match(PATTERNS.resistor);
105
+
106
+ if (!match) {
107
+ return { displayValue: description, originalValue: description };
108
+ }
109
+
110
+ const [, value, multiplier] = match;
111
+ const normalizedMultiplier = MULTIPLIER_MAP[multiplier] || '';
112
+
113
+ // Handle "0R1" style notation (0.1 ohm)
114
+ if (multiplier.toLowerCase() === 'r') {
115
+ const numValue = parseFloat(value);
116
+ if (numValue === 0) {
117
+ // "0R1" = 0.1 ohm - extract the digit after R from original
118
+ const zeroRMatch = description.match(/0[rR](\d)/);
119
+ if (zeroRMatch) {
120
+ return {
121
+ displayValue: `0.${zeroRMatch[1]}`,
122
+ originalValue: description,
123
+ params: { value: `0.${zeroRMatch[1]}` },
124
+ };
125
+ }
126
+ }
127
+ }
128
+
129
+ const displayValue = `${value}${normalizedMultiplier}`;
130
+
131
+ // Extract additional params
132
+ const toleranceMatch = description.match(PATTERNS.tolerance);
133
+ const powerMatch = description.match(PATTERNS.power);
134
+
135
+ return {
136
+ displayValue,
137
+ originalValue: description,
138
+ params: {
139
+ value: displayValue,
140
+ tolerance: toleranceMatch ? `${toleranceMatch[1]}%` : undefined,
141
+ power: powerMatch ? `${powerMatch[1]}W` : undefined,
142
+ },
143
+ };
144
+ }
145
+
146
+ /**
147
+ * Normalize capacitor value
148
+ */
149
+ function normalizeCapacitor(description: string): NormalizedValue {
150
+ const match = description.match(PATTERNS.capacitor);
151
+
152
+ if (!match) {
153
+ return { displayValue: description, originalValue: description };
154
+ }
155
+
156
+ const [, value, unit, voltage] = match;
157
+ const normalizedUnit = MULTIPLIER_MAP[unit] || unit;
158
+
159
+ let displayValue = `${value}${normalizedUnit}`;
160
+
161
+ // Add voltage if present
162
+ if (voltage) {
163
+ displayValue += `/${voltage}V`;
164
+ }
165
+
166
+ return {
167
+ displayValue,
168
+ originalValue: description,
169
+ params: {
170
+ value: `${value}${normalizedUnit}`,
171
+ voltage: voltage ? `${voltage}V` : undefined,
172
+ },
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Normalize inductor value
178
+ */
179
+ function normalizeInductor(description: string): NormalizedValue {
180
+ const match = description.match(PATTERNS.inductor);
181
+
182
+ if (!match) {
183
+ return { displayValue: description, originalValue: description };
184
+ }
185
+
186
+ const [, value, unit, current] = match;
187
+ const normalizedUnit = MULTIPLIER_MAP[unit] || unit;
188
+
189
+ let displayValue = `${value}${normalizedUnit}H`;
190
+
191
+ // Add current if present
192
+ if (current) {
193
+ displayValue += `/${current}A`;
194
+ }
195
+
196
+ return {
197
+ displayValue,
198
+ originalValue: description,
199
+ params: {
200
+ value: `${value}${normalizedUnit}H`,
201
+ current: current ? `${current}A` : undefined,
202
+ },
203
+ };
204
+ }
205
+
206
+ /**
207
+ * Main normalization function
208
+ * Returns normalized value based on component type
209
+ */
210
+ export function normalizeValue(
211
+ description: string,
212
+ type: ComponentType
213
+ ): NormalizedValue {
214
+ // Clean input
215
+ const cleaned = description.trim();
216
+
217
+ // Skip normalization for ICs and complex parts - keep original name
218
+ if (type === 'ic' || type === 'other') {
219
+ return { displayValue: cleaned, originalValue: cleaned };
220
+ }
221
+
222
+ switch (type) {
223
+ case 'resistor':
224
+ return normalizeResistor(cleaned);
225
+ case 'capacitor':
226
+ return normalizeCapacitor(cleaned);
227
+ case 'inductor':
228
+ return normalizeInductor(cleaned);
229
+ case 'diode':
230
+ case 'transistor':
231
+ // For diodes and transistors, keep the part number but clean it up
232
+ // Remove common prefixes/suffixes that aren't part of the name
233
+ return { displayValue: cleaned, originalValue: cleaned };
234
+ default:
235
+ return { displayValue: cleaned, originalValue: cleaned };
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Extract value from component name or description
241
+ * Tries multiple strategies to find a meaningful value
242
+ */
243
+ export function extractDisplayValue(
244
+ name: string,
245
+ description: string | undefined,
246
+ prefix: string,
247
+ category?: string
248
+ ): string {
249
+ const type = detectComponentType(prefix, category);
250
+
251
+ // For passives, prefer to extract from description which has more detail
252
+ if (description && (type === 'resistor' || type === 'capacitor' || type === 'inductor')) {
253
+ const normalized = normalizeValue(description, type);
254
+ if (normalized.displayValue !== description) {
255
+ return normalized.displayValue;
256
+ }
257
+ }
258
+
259
+ // Fallback to name
260
+ const normalized = normalizeValue(name, type);
261
+ return normalized.displayValue;
262
+ }
package/src/index.ts ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * jlc-core
3
+ * Core library for JLC/EasyEDA component sourcing and KiCad conversion
4
+ */
5
+
6
+ // Services (high-level API)
7
+ export * from './services/index.js';
8
+
9
+ // API clients (low-level)
10
+ export * from './api/index.js';
11
+
12
+ // Converters (low-level)
13
+ export * from './converter/index.js';
14
+
15
+ // Types
16
+ export * from './types/index.js';
17
+
18
+ // Utils
19
+ export * from './utils/index.js';
20
+
21
+ // Constants
22
+ export * from './constants/index.js';
23
+
24
+ // Parsers
25
+ export * from './parsers/index.js';