@jlcpcb/cli 0.1.0 → 0.2.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.
- package/CHANGELOG.md +41 -0
- package/README.md +2 -0
- package/dist/assets/search.html +528 -0
- package/dist/index.js +1029 -177
- package/package.json +2 -2
- package/src/app/App.tsx +3 -0
- package/src/app/components/EasyEDADetailView.tsx +132 -0
- package/src/app/navigation/types.ts +8 -2
- package/src/app/screens/EasyEDAInfoScreen.tsx +150 -0
- package/src/commands/easyeda.ts +151 -0
- package/src/commands/install.ts +12 -0
- package/src/index.ts +31 -0
package/dist/index.js
CHANGED
|
@@ -2693,7 +2693,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
2693
2693
|
|
|
2694
2694
|
// ../../node_modules/react/index.js
|
|
2695
2695
|
var require_react = __commonJS((exports, module) => {
|
|
2696
|
-
var react_development = __toESM(require_react_development()
|
|
2696
|
+
var react_development = __toESM(require_react_development());
|
|
2697
2697
|
if (false) {} else {
|
|
2698
2698
|
module.exports = react_development;
|
|
2699
2699
|
}
|
|
@@ -3145,7 +3145,7 @@ var require_scheduler_development = __commonJS((exports) => {
|
|
|
3145
3145
|
|
|
3146
3146
|
// ../../node_modules/scheduler/index.js
|
|
3147
3147
|
var require_scheduler = __commonJS((exports, module) => {
|
|
3148
|
-
var scheduler_development = __toESM(require_scheduler_development()
|
|
3148
|
+
var scheduler_development = __toESM(require_scheduler_development());
|
|
3149
3149
|
if (false) {} else {
|
|
3150
3150
|
module.exports = scheduler_development;
|
|
3151
3151
|
}
|
|
@@ -3153,8 +3153,8 @@ var require_scheduler = __commonJS((exports, module) => {
|
|
|
3153
3153
|
|
|
3154
3154
|
// ../../node_modules/react-reconciler/cjs/react-reconciler.development.js
|
|
3155
3155
|
var require_react_reconciler_development = __commonJS((exports, module) => {
|
|
3156
|
-
var React = __toESM(require_react()
|
|
3157
|
-
var Scheduler = __toESM(require_scheduler()
|
|
3156
|
+
var React = __toESM(require_react());
|
|
3157
|
+
var Scheduler = __toESM(require_scheduler());
|
|
3158
3158
|
module.exports = function($$$config) {
|
|
3159
3159
|
function findHook(fiber, id) {
|
|
3160
3160
|
for (fiber = fiber.memoizedState;fiber !== null && 0 < id; )
|
|
@@ -33706,7 +33706,7 @@ var require_stack_utils = __commonJS((exports, module) => {
|
|
|
33706
33706
|
|
|
33707
33707
|
// ../../node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
|
33708
33708
|
var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
|
|
33709
|
-
var React10 = __toESM(require_react()
|
|
33709
|
+
var React10 = __toESM(require_react());
|
|
33710
33710
|
(function() {
|
|
33711
33711
|
function getComponentNameFromType(type) {
|
|
33712
33712
|
if (type == null)
|
|
@@ -33921,7 +33921,7 @@ React keys must be passed directly to JSX without using spread:
|
|
|
33921
33921
|
|
|
33922
33922
|
// ../../node_modules/react/jsx-dev-runtime.js
|
|
33923
33923
|
var require_jsx_dev_runtime = __commonJS((exports, module) => {
|
|
33924
|
-
var react_jsx_dev_runtime_development = __toESM(require_react_jsx_dev_runtime_development()
|
|
33924
|
+
var react_jsx_dev_runtime_development = __toESM(require_react_jsx_dev_runtime_development());
|
|
33925
33925
|
if (false) {} else {
|
|
33926
33926
|
module.exports = react_jsx_dev_runtime_development;
|
|
33927
33927
|
}
|
|
@@ -34086,6 +34086,10 @@ import { existsSync as existsSync3 } from "fs";
|
|
|
34086
34086
|
import { readFile as readFile4, readdir as readdir2 } from "fs/promises";
|
|
34087
34087
|
import { homedir as homedir2, platform as platform2 } from "os";
|
|
34088
34088
|
import { join as join4 } from "path";
|
|
34089
|
+
import { createServer } from "http";
|
|
34090
|
+
import { readFileSync } from "fs";
|
|
34091
|
+
import { join as join5, dirname as dirname3 } from "path";
|
|
34092
|
+
import { fileURLToPath } from "url";
|
|
34089
34093
|
var __defProp2 = Object.defineProperty;
|
|
34090
34094
|
var __export2 = (target, all) => {
|
|
34091
34095
|
for (var name in all)
|
|
@@ -34693,7 +34697,8 @@ var DEFAULT_LIBRARY_DESCRIPTION = "JLC-MCP Component Library (LCSC/EasyEDA)";
|
|
|
34693
34697
|
var init_lib_table = () => {};
|
|
34694
34698
|
var exports_global_lib_table = {};
|
|
34695
34699
|
__export2(exports_global_lib_table, {
|
|
34696
|
-
ensureGlobalLibraryTables: () => ensureGlobalLibraryTables
|
|
34700
|
+
ensureGlobalLibraryTables: () => ensureGlobalLibraryTables,
|
|
34701
|
+
ensureGlobalEasyEDALibrary: () => ensureGlobalEasyEDALibrary
|
|
34697
34702
|
});
|
|
34698
34703
|
function detectKicadVersion() {
|
|
34699
34704
|
const home = homedir();
|
|
@@ -34870,6 +34875,51 @@ async function ensureLibraryStubs(version) {
|
|
|
34870
34875
|
}
|
|
34871
34876
|
return { symbolsCreated, directoriesCreated };
|
|
34872
34877
|
}
|
|
34878
|
+
function getEasyEDASymbolLibUri() {
|
|
34879
|
+
return `${KICAD_3RD_PARTY_VAR}/${LIBRARY_NAMESPACE}/symbols/${EASYEDA_SYMBOL_LIBRARY_NAME}`;
|
|
34880
|
+
}
|
|
34881
|
+
function getEasyEDAFootprintLibUri() {
|
|
34882
|
+
return `${KICAD_3RD_PARTY_VAR}/${LIBRARY_NAMESPACE}/footprints/${EASYEDA_FOOTPRINT_LIBRARY_NAME}`;
|
|
34883
|
+
}
|
|
34884
|
+
async function ensureGlobalEasyEDALibrary() {
|
|
34885
|
+
const version = detectKicadVersion();
|
|
34886
|
+
const configDir = getKicadConfigDir(version);
|
|
34887
|
+
await mkdir2(configDir, { recursive: true });
|
|
34888
|
+
const symTablePath = join3(configDir, "sym-lib-table");
|
|
34889
|
+
if (existsSync2(symTablePath)) {
|
|
34890
|
+
let content = await readFile3(symTablePath, "utf-8");
|
|
34891
|
+
if (!libraryExistsInTable(content, EASYEDA_LIBRARY_NAME)) {
|
|
34892
|
+
const uri = getEasyEDASymbolLibUri();
|
|
34893
|
+
content = addLibraryToTable(content, EASYEDA_LIBRARY_NAME, uri, "sym", EASYEDA_LIBRARY_DESCRIPTION);
|
|
34894
|
+
await writeFile3(symTablePath, content, "utf-8");
|
|
34895
|
+
}
|
|
34896
|
+
} else {
|
|
34897
|
+
const uri = getEasyEDASymbolLibUri();
|
|
34898
|
+
const content = `(sym_lib_table
|
|
34899
|
+
(version 7)
|
|
34900
|
+
(lib (name "${EASYEDA_LIBRARY_NAME}")(type "KiCad")(uri "${uri}")(options "")(descr "${EASYEDA_LIBRARY_DESCRIPTION}"))
|
|
34901
|
+
)
|
|
34902
|
+
`;
|
|
34903
|
+
await writeFile3(symTablePath, content, "utf-8");
|
|
34904
|
+
}
|
|
34905
|
+
const fpTablePath = join3(configDir, "fp-lib-table");
|
|
34906
|
+
if (existsSync2(fpTablePath)) {
|
|
34907
|
+
let content = await readFile3(fpTablePath, "utf-8");
|
|
34908
|
+
if (!libraryExistsInTable(content, EASYEDA_LIBRARY_NAME)) {
|
|
34909
|
+
const uri = getEasyEDAFootprintLibUri();
|
|
34910
|
+
content = addLibraryToTable(content, EASYEDA_LIBRARY_NAME, uri, "fp", EASYEDA_LIBRARY_DESCRIPTION);
|
|
34911
|
+
await writeFile3(fpTablePath, content, "utf-8");
|
|
34912
|
+
}
|
|
34913
|
+
} else {
|
|
34914
|
+
const uri = getEasyEDAFootprintLibUri();
|
|
34915
|
+
const content = `(fp_lib_table
|
|
34916
|
+
(version 7)
|
|
34917
|
+
(lib (name "${EASYEDA_LIBRARY_NAME}")(type "KiCad")(uri "${uri}")(options "")(descr "${EASYEDA_LIBRARY_DESCRIPTION}"))
|
|
34918
|
+
)
|
|
34919
|
+
`;
|
|
34920
|
+
await writeFile3(fpTablePath, content, "utf-8");
|
|
34921
|
+
}
|
|
34922
|
+
}
|
|
34873
34923
|
async function ensureGlobalLibraryTables() {
|
|
34874
34924
|
const errors2 = [];
|
|
34875
34925
|
const version = detectKicadVersion();
|
|
@@ -34922,6 +34972,10 @@ var LIBRARY_PREFIX2 = "JLC-MCP";
|
|
|
34922
34972
|
var LIBRARY_NAMESPACE = "jlc_mcp";
|
|
34923
34973
|
var KICAD_3RD_PARTY_VAR = "${KICAD9_3RD_PARTY}";
|
|
34924
34974
|
var LIBRARY_DESCRIPTION = "Autogenerated by JLC-MCP";
|
|
34975
|
+
var EASYEDA_LIBRARY_NAME = "EasyEDA";
|
|
34976
|
+
var EASYEDA_SYMBOL_LIBRARY_NAME = "EasyEDA.kicad_sym";
|
|
34977
|
+
var EASYEDA_FOOTPRINT_LIBRARY_NAME = "EasyEDA.pretty";
|
|
34978
|
+
var EASYEDA_LIBRARY_DESCRIPTION = "EasyEDA Community Component Library";
|
|
34925
34979
|
var init_global_lib_table = __esm2(() => {
|
|
34926
34980
|
init_category_router();
|
|
34927
34981
|
init_lib_table();
|
|
@@ -39658,7 +39712,7 @@ function parseFootprintShapes(shapes) {
|
|
|
39658
39712
|
}
|
|
39659
39713
|
}
|
|
39660
39714
|
}
|
|
39661
|
-
const type = pads.some((p) => p.holeRadius > 0) ? "tht" : "smd";
|
|
39715
|
+
const type = pads.some((p) => p.holeRadius > 0 || p.shape === "POLYGON" && p.isPlated) ? "tht" : "smd";
|
|
39662
39716
|
return {
|
|
39663
39717
|
name: "Unknown",
|
|
39664
39718
|
type,
|
|
@@ -41644,7 +41698,6 @@ ${template.bodyGraphics}
|
|
|
41644
41698
|
}
|
|
41645
41699
|
}
|
|
41646
41700
|
var symbolConverter = new SymbolConverter;
|
|
41647
|
-
init_category_router();
|
|
41648
41701
|
var SMD_SIZES = {
|
|
41649
41702
|
"0201": { metric: "0603", imperialMm: "0.6x0.3" },
|
|
41650
41703
|
"0402": { metric: "1005", imperialMm: "1.0x0.5" },
|
|
@@ -41661,57 +41714,7 @@ var PASSIVE_LIBRARIES = {
|
|
|
41661
41714
|
C: "Capacitor_SMD",
|
|
41662
41715
|
L: "Inductor_SMD"
|
|
41663
41716
|
};
|
|
41664
|
-
var
|
|
41665
|
-
var DIODE_LIBRARY = "Diode_SMD";
|
|
41666
|
-
var CATEGORY_TO_PREFIX2 = {
|
|
41667
|
-
Resistors: "R",
|
|
41668
|
-
Capacitors: "C",
|
|
41669
|
-
Inductors: "L",
|
|
41670
|
-
Diodes: "D"
|
|
41671
|
-
};
|
|
41672
|
-
var SOIC_MAPPINGS = {
|
|
41673
|
-
"SOIC-8": "SOIC-8_3.9x4.9mm_P1.27mm",
|
|
41674
|
-
"SOP-8": "SOIC-8_3.9x4.9mm_P1.27mm",
|
|
41675
|
-
"SOIC-14": "SOIC-14_3.9x8.7mm_P1.27mm",
|
|
41676
|
-
"SOIC-16": "SOIC-16_3.9x9.9mm_P1.27mm",
|
|
41677
|
-
"SOIC-16W": "SOIC-16W_7.5x10.3mm_P1.27mm",
|
|
41678
|
-
"SOIC-20": "SOIC-20W_7.5x12.8mm_P1.27mm",
|
|
41679
|
-
"SOIC-24": "SOIC-24W_7.5x15.4mm_P1.27mm",
|
|
41680
|
-
"SOIC-28": "SOIC-28W_7.5x17.9mm_P1.27mm"
|
|
41681
|
-
};
|
|
41682
|
-
var TSSOP_MAPPINGS = {
|
|
41683
|
-
"TSSOP-8": "TSSOP-8_3x3mm_P0.65mm",
|
|
41684
|
-
"TSSOP-14": "TSSOP-14_4.4x5mm_P0.65mm",
|
|
41685
|
-
"TSSOP-16": "TSSOP-16_4.4x5mm_P0.65mm",
|
|
41686
|
-
"TSSOP-20": "TSSOP-20_4.4x6.5mm_P0.65mm",
|
|
41687
|
-
"TSSOP-24": "TSSOP-24_4.4x7.8mm_P0.65mm",
|
|
41688
|
-
"TSSOP-28": "TSSOP-28_4.4x9.7mm_P0.65mm"
|
|
41689
|
-
};
|
|
41690
|
-
var SOT_MAPPINGS = {
|
|
41691
|
-
"SOT-23": { library: "Package_TO_SOT_SMD", footprint: "SOT-23" },
|
|
41692
|
-
"SOT-23-3": { library: "Package_TO_SOT_SMD", footprint: "SOT-23" },
|
|
41693
|
-
"SOT-23-5": { library: "Package_TO_SOT_SMD", footprint: "SOT-23-5" },
|
|
41694
|
-
"SOT-23-6": { library: "Package_TO_SOT_SMD", footprint: "SOT-23-6" },
|
|
41695
|
-
"SOT-89": { library: "Package_TO_SOT_SMD", footprint: "SOT-89-3" },
|
|
41696
|
-
"SOT-223": { library: "Package_TO_SOT_SMD", footprint: "SOT-223-3_TabPin2" }
|
|
41697
|
-
};
|
|
41698
|
-
var SOD_MAPPINGS = {
|
|
41699
|
-
"SOD-123": { library: "Diode_SMD", footprint: "D_SOD-123" },
|
|
41700
|
-
"SOD-123F": { library: "Diode_SMD", footprint: "D_SOD-123F" },
|
|
41701
|
-
"SOD-323": { library: "Diode_SMD", footprint: "D_SOD-323" },
|
|
41702
|
-
"SOD-523": { library: "Diode_SMD", footprint: "D_SOD-523" },
|
|
41703
|
-
"SOD-923": { library: "Diode_SMD", footprint: "D_SOD-923" },
|
|
41704
|
-
"SOD-128": { library: "Diode_SMD", footprint: "D_SOD-128" },
|
|
41705
|
-
"SOD-80": { library: "Diode_SMD", footprint: "D_SOD-80" }
|
|
41706
|
-
};
|
|
41707
|
-
var DIODE_PACKAGE_MAPPINGS = {
|
|
41708
|
-
SMA: { library: "Diode_SMD", footprint: "D_SMA" },
|
|
41709
|
-
SMB: { library: "Diode_SMD", footprint: "D_SMB" },
|
|
41710
|
-
SMC: { library: "Diode_SMD", footprint: "D_SMC" },
|
|
41711
|
-
MELF: { library: "Diode_SMD", footprint: "D_MELF" },
|
|
41712
|
-
MINIMELF: { library: "Diode_SMD", footprint: "D_MiniMELF" },
|
|
41713
|
-
MICROMELF: { library: "Diode_SMD", footprint: "D_MicroMELF" }
|
|
41714
|
-
};
|
|
41717
|
+
var PASSIVE_PAD_COUNT = 2;
|
|
41715
41718
|
function normalizePackageName(name) {
|
|
41716
41719
|
return name.toUpperCase().replace(/[_\s-]+/g, "-").replace(/\(.*?\)/g, "").trim();
|
|
41717
41720
|
}
|
|
@@ -41726,58 +41729,23 @@ function extractSmdSize(packageName) {
|
|
|
41726
41729
|
const match = normalized.match(sizePattern);
|
|
41727
41730
|
return match ? match[1] : null;
|
|
41728
41731
|
}
|
|
41729
|
-
function mapToKicadFootprint(packageName, componentPrefix,
|
|
41730
|
-
const
|
|
41731
|
-
|
|
41732
|
-
|
|
41733
|
-
if (!isKnownPrefix && (category || description)) {
|
|
41734
|
-
const detectedCategory = getLibraryCategory(prefix, category, description);
|
|
41735
|
-
const categoryPrefix = CATEGORY_TO_PREFIX2[detectedCategory];
|
|
41736
|
-
if (categoryPrefix) {
|
|
41737
|
-
prefix = categoryPrefix;
|
|
41738
|
-
}
|
|
41732
|
+
function mapToKicadFootprint(packageName, componentPrefix, _category, _description) {
|
|
41733
|
+
const prefix = componentPrefix.toUpperCase();
|
|
41734
|
+
if (!PASSIVE_LIBRARIES[prefix]) {
|
|
41735
|
+
return null;
|
|
41739
41736
|
}
|
|
41740
41737
|
const smdSize = extractSmdSize(packageName);
|
|
41741
|
-
if (smdSize
|
|
41738
|
+
if (smdSize) {
|
|
41742
41739
|
const sizeInfo = SMD_SIZES[smdSize];
|
|
41743
41740
|
const library = PASSIVE_LIBRARIES[prefix];
|
|
41744
41741
|
const footprint = `${prefix}_${smdSize}_${sizeInfo.metric}Metric`;
|
|
41745
41742
|
return { library, footprint };
|
|
41746
41743
|
}
|
|
41747
|
-
|
|
41748
|
-
|
|
41749
|
-
|
|
41750
|
-
|
|
41751
|
-
|
|
41752
|
-
if (smdSize && prefix === "D") {
|
|
41753
|
-
const sizeInfo = SMD_SIZES[smdSize];
|
|
41754
|
-
const footprint = `D_${smdSize}_${sizeInfo.metric}Metric`;
|
|
41755
|
-
return { library: DIODE_LIBRARY, footprint };
|
|
41756
|
-
}
|
|
41757
|
-
for (const [pattern, mapping] of Object.entries(SOD_MAPPINGS)) {
|
|
41758
|
-
if (normalized.includes(pattern) || normalized.startsWith(pattern.replace(/-/g, ""))) {
|
|
41759
|
-
return mapping;
|
|
41760
|
-
}
|
|
41761
|
-
}
|
|
41762
|
-
for (const [pattern, mapping] of Object.entries(DIODE_PACKAGE_MAPPINGS)) {
|
|
41763
|
-
if (normalized === pattern || normalized.startsWith(pattern + "-") || normalized.startsWith(pattern + "_")) {
|
|
41764
|
-
return mapping;
|
|
41765
|
-
}
|
|
41766
|
-
}
|
|
41767
|
-
for (const [pattern, footprint] of Object.entries(SOIC_MAPPINGS)) {
|
|
41768
|
-
if (normalized.includes(pattern) || normalized.startsWith(pattern.replace(/-/g, ""))) {
|
|
41769
|
-
return { library: "Package_SO", footprint };
|
|
41770
|
-
}
|
|
41771
|
-
}
|
|
41772
|
-
for (const [pattern, footprint] of Object.entries(TSSOP_MAPPINGS)) {
|
|
41773
|
-
if (normalized.includes(pattern) || normalized.startsWith(pattern.replace(/-/g, ""))) {
|
|
41774
|
-
return { library: "Package_SO", footprint };
|
|
41775
|
-
}
|
|
41776
|
-
}
|
|
41777
|
-
for (const [pattern, mapping] of Object.entries(SOT_MAPPINGS)) {
|
|
41778
|
-
if (normalized.includes(pattern) || normalized === pattern.replace(/-/g, "")) {
|
|
41779
|
-
return mapping;
|
|
41780
|
-
}
|
|
41744
|
+
return null;
|
|
41745
|
+
}
|
|
41746
|
+
function getExpectedPadCount(mapping) {
|
|
41747
|
+
if (mapping.library === "Resistor_SMD" || mapping.library === "Capacitor_SMD" || mapping.library === "Inductor_SMD") {
|
|
41748
|
+
return PASSIVE_PAD_COUNT;
|
|
41781
41749
|
}
|
|
41782
41750
|
return null;
|
|
41783
41751
|
}
|
|
@@ -41808,8 +41776,8 @@ var KI_PAD_LAYER_SMD = {
|
|
|
41808
41776
|
11: '"*.Cu" "*.Paste" "*.Mask"'
|
|
41809
41777
|
};
|
|
41810
41778
|
var KI_PAD_LAYER_THT = {
|
|
41811
|
-
1: '"
|
|
41812
|
-
2: '"
|
|
41779
|
+
1: '"*.Cu" "*.Mask"',
|
|
41780
|
+
2: '"*.Cu" "*.Mask"',
|
|
41813
41781
|
11: '"*.Cu" "*.Mask"'
|
|
41814
41782
|
};
|
|
41815
41783
|
var KI_PAD_SHAPE = {
|
|
@@ -41955,13 +41923,19 @@ class FootprintConverter {
|
|
|
41955
41923
|
const { info, footprint } = component;
|
|
41956
41924
|
const packageName = footprint.name;
|
|
41957
41925
|
const prefix = info.prefix;
|
|
41926
|
+
const actualPadCount = footprint.pads.length;
|
|
41958
41927
|
const mapping = mapToKicadFootprint(packageName, prefix, info.category, info.description);
|
|
41959
41928
|
if (mapping) {
|
|
41960
|
-
|
|
41961
|
-
|
|
41962
|
-
|
|
41963
|
-
|
|
41964
|
-
|
|
41929
|
+
const expectedPadCount = getExpectedPadCount(mapping);
|
|
41930
|
+
if (expectedPadCount !== null && expectedPadCount !== actualPadCount) {
|
|
41931
|
+
console.warn(`[footprint] Pad count mismatch for ${packageName}: expected ${expectedPadCount}, got ${actualPadCount}. Generating custom footprint.`);
|
|
41932
|
+
} else {
|
|
41933
|
+
return {
|
|
41934
|
+
type: "reference",
|
|
41935
|
+
reference: getKicadFootprintRef(mapping),
|
|
41936
|
+
name: mapping.footprint
|
|
41937
|
+
};
|
|
41938
|
+
}
|
|
41965
41939
|
}
|
|
41966
41940
|
const content = this.convert(component, options);
|
|
41967
41941
|
const name = this.sanitizeName(footprint.name);
|
|
@@ -42013,15 +41987,20 @@ class FootprintConverter {
|
|
|
42013
41987
|
`;
|
|
42014
41988
|
return output;
|
|
42015
41989
|
}
|
|
42016
|
-
generatePolygonPad(pad, origin,
|
|
41990
|
+
generatePolygonPad(pad, origin, _layers) {
|
|
42017
41991
|
const x = convertX(pad.centerX, origin.x);
|
|
42018
41992
|
const y = convertY(pad.centerY, origin.y);
|
|
42019
41993
|
const points = parsePoints(pad.points);
|
|
42020
41994
|
if (points.length < 3) {
|
|
42021
41995
|
return this.generatePad({ ...pad, shape: "RECT", points: "" }, origin);
|
|
42022
41996
|
}
|
|
42023
|
-
|
|
41997
|
+
let holeRadius = pad.holeRadius;
|
|
41998
|
+
if (holeRadius === 0 && pad.isPlated && pad.shape === "POLYGON") {
|
|
41999
|
+
holeRadius = this.calculateDrillRadiusFromPolygon(points, pad.centerX, pad.centerY);
|
|
42000
|
+
}
|
|
42001
|
+
const isSmd = holeRadius === 0;
|
|
42024
42002
|
const padType = isSmd ? "smd" : "thru_hole";
|
|
42003
|
+
const layers = getPadLayers(pad.layerId, isSmd);
|
|
42025
42004
|
const polyPoints = points.map((p) => ({
|
|
42026
42005
|
x: roundTo(toMM(p.x - pad.centerX), 2),
|
|
42027
42006
|
y: roundTo(toMM(p.y - pad.centerY), 2)
|
|
@@ -42033,7 +42012,7 @@ class FootprintConverter {
|
|
|
42033
42012
|
output += ` (size 0.01 0.01)
|
|
42034
42013
|
`;
|
|
42035
42014
|
if (!isSmd) {
|
|
42036
|
-
const drillDiameter = roundTo(toMM(
|
|
42015
|
+
const drillDiameter = roundTo(toMM(holeRadius * 2), 4);
|
|
42037
42016
|
if (pad.holeLength && pad.holeLength > 0) {
|
|
42038
42017
|
const holeH = roundTo(toMM(pad.holeLength), 4);
|
|
42039
42018
|
output += ` (drill oval ${drillDiameter} ${holeH})
|
|
@@ -42067,6 +42046,25 @@ class FootprintConverter {
|
|
|
42067
42046
|
`;
|
|
42068
42047
|
return output;
|
|
42069
42048
|
}
|
|
42049
|
+
calculateDrillRadiusFromPolygon(points, centerX, centerY) {
|
|
42050
|
+
if (points.length < 3)
|
|
42051
|
+
return 0;
|
|
42052
|
+
let minX = Infinity, maxX = -Infinity;
|
|
42053
|
+
let minY = Infinity, maxY = -Infinity;
|
|
42054
|
+
for (const pt of points) {
|
|
42055
|
+
const relX = pt.x - centerX;
|
|
42056
|
+
const relY = pt.y - centerY;
|
|
42057
|
+
minX = Math.min(minX, relX);
|
|
42058
|
+
maxX = Math.max(maxX, relX);
|
|
42059
|
+
minY = Math.min(minY, relY);
|
|
42060
|
+
maxY = Math.max(maxY, relY);
|
|
42061
|
+
}
|
|
42062
|
+
const width = maxX - minX;
|
|
42063
|
+
const height = maxY - minY;
|
|
42064
|
+
const minDim = Math.min(width, height);
|
|
42065
|
+
const drillDiameter = minDim * 0.6;
|
|
42066
|
+
return drillDiameter / 2;
|
|
42067
|
+
}
|
|
42070
42068
|
generateHole(hole, origin) {
|
|
42071
42069
|
const x = convertX(hole.centerX, origin.x);
|
|
42072
42070
|
const y = convertY(hole.centerY, origin.y);
|
|
@@ -42193,9 +42191,9 @@ class FootprintConverter {
|
|
|
42193
42191
|
const fontSize = roundTo(toMM(text.fontSize), 2);
|
|
42194
42192
|
const rotation = text.rotation || 0;
|
|
42195
42193
|
let justify = "";
|
|
42196
|
-
if (
|
|
42194
|
+
if (text.type === "L") {
|
|
42197
42195
|
justify = "left";
|
|
42198
|
-
} else if (
|
|
42196
|
+
} else if (text.type === "R") {
|
|
42199
42197
|
justify = "right";
|
|
42200
42198
|
}
|
|
42201
42199
|
return ` (fp_text user "${this.escapeString(text.text)}"
|
|
@@ -42212,6 +42210,9 @@ ${justify ? ` (justify ${justify})
|
|
|
42212
42210
|
`;
|
|
42213
42211
|
}
|
|
42214
42212
|
generateSolidRegion(region, origin) {
|
|
42213
|
+
if (region.layerId === 99 || region.layerId === 100 || region.layerId === 101) {
|
|
42214
|
+
return "";
|
|
42215
|
+
}
|
|
42215
42216
|
const layer = getLayer(region.layerId);
|
|
42216
42217
|
const points = this.parseSvgPathToPoints(region.path, origin);
|
|
42217
42218
|
if (points.length < 3)
|
|
@@ -42244,15 +42245,111 @@ ${justify ? ` (justify ${justify})
|
|
|
42244
42245
|
}
|
|
42245
42246
|
parseSvgPathToPoints(path, origin) {
|
|
42246
42247
|
const points = [];
|
|
42247
|
-
|
|
42248
|
+
let currentX = 0, currentY = 0;
|
|
42249
|
+
let startX = 0, startY = 0;
|
|
42250
|
+
const commandRegex = /([MLHVCSQTAZ])\s*([^MLHVCSQTAZ]*)/gi;
|
|
42248
42251
|
let match;
|
|
42249
42252
|
while ((match = commandRegex.exec(path)) !== null) {
|
|
42250
|
-
const
|
|
42251
|
-
const
|
|
42252
|
-
|
|
42253
|
-
|
|
42254
|
-
|
|
42255
|
-
|
|
42253
|
+
const cmd = match[1].toUpperCase();
|
|
42254
|
+
const args = match[2].trim().split(/[\s,]+/).map(parseFloat).filter((n) => !isNaN(n));
|
|
42255
|
+
switch (cmd) {
|
|
42256
|
+
case "M":
|
|
42257
|
+
if (args.length >= 2) {
|
|
42258
|
+
currentX = args[0];
|
|
42259
|
+
currentY = args[1];
|
|
42260
|
+
if (points.length === 0) {
|
|
42261
|
+
startX = currentX;
|
|
42262
|
+
startY = currentY;
|
|
42263
|
+
}
|
|
42264
|
+
points.push({
|
|
42265
|
+
x: convertX(currentX, origin.x),
|
|
42266
|
+
y: convertY(currentY, origin.y)
|
|
42267
|
+
});
|
|
42268
|
+
}
|
|
42269
|
+
break;
|
|
42270
|
+
case "L":
|
|
42271
|
+
if (args.length >= 2) {
|
|
42272
|
+
currentX = args[0];
|
|
42273
|
+
currentY = args[1];
|
|
42274
|
+
points.push({
|
|
42275
|
+
x: convertX(currentX, origin.x),
|
|
42276
|
+
y: convertY(currentY, origin.y)
|
|
42277
|
+
});
|
|
42278
|
+
}
|
|
42279
|
+
break;
|
|
42280
|
+
case "H":
|
|
42281
|
+
if (args.length >= 1) {
|
|
42282
|
+
currentX = args[0];
|
|
42283
|
+
points.push({
|
|
42284
|
+
x: convertX(currentX, origin.x),
|
|
42285
|
+
y: convertY(currentY, origin.y)
|
|
42286
|
+
});
|
|
42287
|
+
}
|
|
42288
|
+
break;
|
|
42289
|
+
case "V":
|
|
42290
|
+
if (args.length >= 1) {
|
|
42291
|
+
currentY = args[0];
|
|
42292
|
+
points.push({
|
|
42293
|
+
x: convertX(currentX, origin.x),
|
|
42294
|
+
y: convertY(currentY, origin.y)
|
|
42295
|
+
});
|
|
42296
|
+
}
|
|
42297
|
+
break;
|
|
42298
|
+
case "C":
|
|
42299
|
+
if (args.length >= 6) {
|
|
42300
|
+
currentX = args[4];
|
|
42301
|
+
currentY = args[5];
|
|
42302
|
+
points.push({
|
|
42303
|
+
x: convertX(currentX, origin.x),
|
|
42304
|
+
y: convertY(currentY, origin.y)
|
|
42305
|
+
});
|
|
42306
|
+
}
|
|
42307
|
+
break;
|
|
42308
|
+
case "S":
|
|
42309
|
+
if (args.length >= 4) {
|
|
42310
|
+
currentX = args[2];
|
|
42311
|
+
currentY = args[3];
|
|
42312
|
+
points.push({
|
|
42313
|
+
x: convertX(currentX, origin.x),
|
|
42314
|
+
y: convertY(currentY, origin.y)
|
|
42315
|
+
});
|
|
42316
|
+
}
|
|
42317
|
+
break;
|
|
42318
|
+
case "Q":
|
|
42319
|
+
if (args.length >= 4) {
|
|
42320
|
+
currentX = args[2];
|
|
42321
|
+
currentY = args[3];
|
|
42322
|
+
points.push({
|
|
42323
|
+
x: convertX(currentX, origin.x),
|
|
42324
|
+
y: convertY(currentY, origin.y)
|
|
42325
|
+
});
|
|
42326
|
+
}
|
|
42327
|
+
break;
|
|
42328
|
+
case "T":
|
|
42329
|
+
if (args.length >= 2) {
|
|
42330
|
+
currentX = args[0];
|
|
42331
|
+
currentY = args[1];
|
|
42332
|
+
points.push({
|
|
42333
|
+
x: convertX(currentX, origin.x),
|
|
42334
|
+
y: convertY(currentY, origin.y)
|
|
42335
|
+
});
|
|
42336
|
+
}
|
|
42337
|
+
break;
|
|
42338
|
+
case "A":
|
|
42339
|
+
if (args.length >= 7) {
|
|
42340
|
+
currentX = args[5];
|
|
42341
|
+
currentY = args[6];
|
|
42342
|
+
points.push({
|
|
42343
|
+
x: convertX(currentX, origin.x),
|
|
42344
|
+
y: convertY(currentY, origin.y)
|
|
42345
|
+
});
|
|
42346
|
+
}
|
|
42347
|
+
break;
|
|
42348
|
+
case "Z":
|
|
42349
|
+
currentX = startX;
|
|
42350
|
+
currentY = startY;
|
|
42351
|
+
break;
|
|
42352
|
+
}
|
|
42256
42353
|
}
|
|
42257
42354
|
return points;
|
|
42258
42355
|
}
|
|
@@ -42420,10 +42517,14 @@ var FOOTPRINT_LIBRARY_NAME = getFootprintDirName();
|
|
|
42420
42517
|
var MODELS_3D_NAME = get3DModelsDirName();
|
|
42421
42518
|
var LIBRARY_NAMESPACE2 = "jlc_mcp";
|
|
42422
42519
|
var KICAD_VERSIONS3 = ["9.0", "8.0"];
|
|
42423
|
-
var
|
|
42424
|
-
var
|
|
42425
|
-
var
|
|
42426
|
-
var
|
|
42520
|
+
var EASYEDA_LIBRARY_NAME2 = "EasyEDA";
|
|
42521
|
+
var EASYEDA_SYMBOL_LIBRARY_NAME2 = "EasyEDA.kicad_sym";
|
|
42522
|
+
var EASYEDA_FOOTPRINT_LIBRARY_NAME2 = "EasyEDA.pretty";
|
|
42523
|
+
var EASYEDA_LIBRARY_DESCRIPTION2 = "EasyEDA Community Component Library";
|
|
42524
|
+
var EASYEDA_LOCAL_LIBRARY_NAME = "EasyEDA-local";
|
|
42525
|
+
var EASYEDA_LOCAL_SYMBOL_LIBRARY_NAME = "EasyEDA-local.kicad_sym";
|
|
42526
|
+
var EASYEDA_LOCAL_FOOTPRINT_LIBRARY_NAME = "EasyEDA-local.pretty";
|
|
42527
|
+
var EASYEDA_LOCAL_LIBRARY_DESCRIPTION = "EasyEDA Community Component Library (Project-local)";
|
|
42427
42528
|
function detectKicadVersion2() {
|
|
42428
42529
|
const home = homedir2();
|
|
42429
42530
|
const baseDir = join4(home, "Documents", "KiCad");
|
|
@@ -42564,10 +42665,7 @@ function createLibraryService() {
|
|
|
42564
42665
|
return {
|
|
42565
42666
|
async install(id, options = {}) {
|
|
42566
42667
|
const isCommunityComponent = !isLcscId2(id);
|
|
42567
|
-
|
|
42568
|
-
throw new Error("EasyEDA community components require projectPath for local storage");
|
|
42569
|
-
}
|
|
42570
|
-
const isGlobal = !isCommunityComponent && !options.projectPath;
|
|
42668
|
+
const isGlobal = !options.projectPath;
|
|
42571
42669
|
const paths = isGlobal ? getGlobalLibraryPaths() : getProjectLibraryPaths(options.projectPath);
|
|
42572
42670
|
let component = null;
|
|
42573
42671
|
if (isLcscId2(id)) {
|
|
@@ -42610,13 +42708,27 @@ function createLibraryService() {
|
|
|
42610
42708
|
let category;
|
|
42611
42709
|
let modelPath;
|
|
42612
42710
|
if (isCommunityComponent) {
|
|
42613
|
-
const
|
|
42614
|
-
const
|
|
42615
|
-
|
|
42616
|
-
|
|
42711
|
+
const libName = isGlobal ? EASYEDA_LIBRARY_NAME2 : EASYEDA_LOCAL_LIBRARY_NAME;
|
|
42712
|
+
const symLibFile = isGlobal ? EASYEDA_SYMBOL_LIBRARY_NAME2 : EASYEDA_LOCAL_SYMBOL_LIBRARY_NAME;
|
|
42713
|
+
const fpLibDir = isGlobal ? EASYEDA_FOOTPRINT_LIBRARY_NAME2 : EASYEDA_LOCAL_FOOTPRINT_LIBRARY_NAME;
|
|
42714
|
+
const libDesc = isGlobal ? EASYEDA_LIBRARY_DESCRIPTION2 : EASYEDA_LOCAL_LIBRARY_DESCRIPTION;
|
|
42715
|
+
const models3dDirName = isGlobal ? "EasyEDA.3dshapes" : "EasyEDA-local.3dshapes";
|
|
42716
|
+
let symbolsDir;
|
|
42717
|
+
let easyedaModelsDir;
|
|
42718
|
+
if (isGlobal) {
|
|
42719
|
+
symbolsDir = paths.symbolsDir;
|
|
42720
|
+
footprintDir = join4(paths.footprintsDir, fpLibDir);
|
|
42721
|
+
easyedaModelsDir = join4(paths.models3dDir, models3dDirName);
|
|
42722
|
+
} else {
|
|
42723
|
+
const librariesDir = join4(options.projectPath, "libraries");
|
|
42724
|
+
symbolsDir = join4(librariesDir, "symbols");
|
|
42725
|
+
footprintDir = join4(librariesDir, "footprints", fpLibDir);
|
|
42726
|
+
easyedaModelsDir = join4(librariesDir, "3dmodels", models3dDirName);
|
|
42727
|
+
}
|
|
42728
|
+
models3dDir = easyedaModelsDir;
|
|
42617
42729
|
await ensureDir(symbolsDir);
|
|
42618
42730
|
await ensureDir(footprintDir);
|
|
42619
|
-
symbolFile = join4(symbolsDir,
|
|
42731
|
+
symbolFile = join4(symbolsDir, symLibFile);
|
|
42620
42732
|
symbolName = component.info.name.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
42621
42733
|
const include3d = options.include3d ?? true;
|
|
42622
42734
|
let modelRelativePath;
|
|
@@ -42627,21 +42739,30 @@ function createLibraryService() {
|
|
|
42627
42739
|
const modelFilename = `${symbolName}.step`;
|
|
42628
42740
|
modelPath = join4(models3dDir, modelFilename);
|
|
42629
42741
|
await writeBinary(modelPath, model);
|
|
42630
|
-
|
|
42742
|
+
if (isGlobal) {
|
|
42743
|
+
modelRelativePath = `\${KICAD9_3RD_PARTY}/${LIBRARY_NAMESPACE2}/3dmodels/${models3dDirName}/${modelFilename}`;
|
|
42744
|
+
} else {
|
|
42745
|
+
modelRelativePath = `\${KIPRJMOD}/libraries/3dmodels/${models3dDirName}/${modelFilename}`;
|
|
42746
|
+
}
|
|
42631
42747
|
}
|
|
42632
42748
|
}
|
|
42633
42749
|
const footprint = footprintConverter.convert(component, {
|
|
42634
|
-
libraryName:
|
|
42750
|
+
libraryName: libName,
|
|
42635
42751
|
include3DModel: !!modelRelativePath,
|
|
42636
42752
|
modelPath: modelRelativePath
|
|
42637
42753
|
});
|
|
42638
42754
|
footprintPath = join4(footprintDir, `${symbolName}.kicad_mod`);
|
|
42639
|
-
footprintRef = `${
|
|
42755
|
+
footprintRef = `${libName}:${symbolName}`;
|
|
42640
42756
|
await writeText(footprintPath, footprint);
|
|
42641
42757
|
component.info.package = footprintRef;
|
|
42642
|
-
|
|
42643
|
-
|
|
42644
|
-
|
|
42758
|
+
if (isGlobal) {
|
|
42759
|
+
const { ensureGlobalEasyEDALibrary: ensureGlobalEasyEDALibrary2 } = await Promise.resolve().then(() => (init_global_lib_table(), exports_global_lib_table));
|
|
42760
|
+
await ensureGlobalEasyEDALibrary2();
|
|
42761
|
+
} else {
|
|
42762
|
+
await ensureSymLibTable(options.projectPath, symbolFile, libName, libDesc);
|
|
42763
|
+
await ensureFpLibTable(options.projectPath, footprintDir, libName, libDesc);
|
|
42764
|
+
}
|
|
42765
|
+
symbolRef = `${libName}:${symbolName}`;
|
|
42645
42766
|
} else {
|
|
42646
42767
|
category = getLibraryCategory(component.info.prefix, component.info.category, component.info.description);
|
|
42647
42768
|
const symbolLibraryFilename = getLibraryFilename(category);
|
|
@@ -42688,7 +42809,7 @@ function createLibraryService() {
|
|
|
42688
42809
|
if (symbolConverter.symbolExistsInLibrary(existingContent, component.info.name)) {
|
|
42689
42810
|
if (options.force) {
|
|
42690
42811
|
symbolContent = symbolConverter.replaceInLibrary(existingContent, component, {
|
|
42691
|
-
libraryName: isCommunityComponent ?
|
|
42812
|
+
libraryName: isCommunityComponent ? EASYEDA_LIBRARY_NAME2 : undefined,
|
|
42692
42813
|
symbolName: isCommunityComponent ? symbolName : undefined
|
|
42693
42814
|
});
|
|
42694
42815
|
symbolAction = "replaced";
|
|
@@ -42698,14 +42819,14 @@ function createLibraryService() {
|
|
|
42698
42819
|
}
|
|
42699
42820
|
} else {
|
|
42700
42821
|
symbolContent = symbolConverter.appendToLibrary(existingContent, component, {
|
|
42701
|
-
libraryName: isCommunityComponent ?
|
|
42822
|
+
libraryName: isCommunityComponent ? EASYEDA_LIBRARY_NAME2 : undefined,
|
|
42702
42823
|
symbolName: isCommunityComponent ? symbolName : undefined
|
|
42703
42824
|
});
|
|
42704
42825
|
symbolAction = "appended";
|
|
42705
42826
|
}
|
|
42706
42827
|
} else {
|
|
42707
42828
|
symbolContent = symbolConverter.convert(component, {
|
|
42708
|
-
libraryName: isCommunityComponent ?
|
|
42829
|
+
libraryName: isCommunityComponent ? EASYEDA_LIBRARY_NAME2 : undefined,
|
|
42709
42830
|
symbolName: isCommunityComponent ? symbolName : undefined
|
|
42710
42831
|
});
|
|
42711
42832
|
symbolAction = "created";
|
|
@@ -42830,12 +42951,243 @@ function createLibraryService() {
|
|
|
42830
42951
|
fpLibTable: fpLibTablePath
|
|
42831
42952
|
}
|
|
42832
42953
|
};
|
|
42954
|
+
},
|
|
42955
|
+
async isEasyEDAInstalled(componentName) {
|
|
42956
|
+
const paths = getGlobalLibraryPaths();
|
|
42957
|
+
const easyedaLibPath = join4(paths.symbolsDir, EASYEDA_SYMBOL_LIBRARY_NAME2);
|
|
42958
|
+
if (!existsSync3(easyedaLibPath)) {
|
|
42959
|
+
return false;
|
|
42960
|
+
}
|
|
42961
|
+
try {
|
|
42962
|
+
const content = await readFile4(easyedaLibPath, "utf-8");
|
|
42963
|
+
const sanitizedName = componentName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
42964
|
+
const pattern = new RegExp(`\\(symbol\\s+"${sanitizedName}"`, "m");
|
|
42965
|
+
return pattern.test(content);
|
|
42966
|
+
} catch {
|
|
42967
|
+
return false;
|
|
42968
|
+
}
|
|
42833
42969
|
}
|
|
42834
42970
|
};
|
|
42835
42971
|
}
|
|
42836
42972
|
init_lib_table();
|
|
42837
42973
|
init_category_router();
|
|
42838
42974
|
init_global_lib_table();
|
|
42975
|
+
var logger7 = createLogger("http-routes");
|
|
42976
|
+
var __filename2 = fileURLToPath(import.meta.url);
|
|
42977
|
+
var __dirname2 = dirname3(__filename2);
|
|
42978
|
+
var htmlCache = null;
|
|
42979
|
+
function getHtmlPage() {
|
|
42980
|
+
if (htmlCache)
|
|
42981
|
+
return htmlCache;
|
|
42982
|
+
try {
|
|
42983
|
+
const possiblePaths = [
|
|
42984
|
+
join5(__dirname2, "assets/search.html"),
|
|
42985
|
+
join5(__dirname2, "../dist/assets/search.html"),
|
|
42986
|
+
join5(__dirname2, "../assets/search.html"),
|
|
42987
|
+
join5(__dirname2, "../assets/search-built.html"),
|
|
42988
|
+
join5(process.cwd(), "dist/assets/search.html"),
|
|
42989
|
+
join5(process.cwd(), "packages/core/dist/assets/search.html"),
|
|
42990
|
+
join5(__dirname2, "../../dist/assets/search.html"),
|
|
42991
|
+
join5(__dirname2, "../../../core/dist/assets/search.html"),
|
|
42992
|
+
join5(__dirname2, "../../../../packages/core/dist/assets/search.html"),
|
|
42993
|
+
join5(__dirname2, "../../node_modules/@jlcpcb/core/dist/assets/search.html")
|
|
42994
|
+
];
|
|
42995
|
+
for (const path of possiblePaths) {
|
|
42996
|
+
try {
|
|
42997
|
+
htmlCache = readFileSync(path, "utf-8");
|
|
42998
|
+
logger7.debug(`Loaded HTML from: ${path}`);
|
|
42999
|
+
return htmlCache;
|
|
43000
|
+
} catch {}
|
|
43001
|
+
}
|
|
43002
|
+
throw new Error("HTML file not found");
|
|
43003
|
+
} catch (error) {
|
|
43004
|
+
logger7.error("Failed to load HTML page:", error);
|
|
43005
|
+
return `<!DOCTYPE html>
|
|
43006
|
+
<html>
|
|
43007
|
+
<head><title>Error</title></head>
|
|
43008
|
+
<body>
|
|
43009
|
+
<h1>Error: Search page not found</h1>
|
|
43010
|
+
<p>The search page has not been built. Run: bun run build</p>
|
|
43011
|
+
</body>
|
|
43012
|
+
</html>`;
|
|
43013
|
+
}
|
|
43014
|
+
}
|
|
43015
|
+
async function handleRequest(req, res) {
|
|
43016
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
43017
|
+
const pathname = url.pathname;
|
|
43018
|
+
logger7.debug(`${req.method} ${pathname}`);
|
|
43019
|
+
if (pathname === "/" || pathname === "/index.html") {
|
|
43020
|
+
const query = url.searchParams.get("q") || undefined;
|
|
43021
|
+
serveHtml(res, query);
|
|
43022
|
+
} else if (pathname === "/api/search") {
|
|
43023
|
+
await handleSearch(url, res);
|
|
43024
|
+
} else if (pathname.startsWith("/api/component/")) {
|
|
43025
|
+
const uuid = pathname.replace("/api/component/", "");
|
|
43026
|
+
await handleComponent(uuid, res);
|
|
43027
|
+
} else if (pathname === "/health") {
|
|
43028
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
43029
|
+
res.end(JSON.stringify({ status: "ok" }));
|
|
43030
|
+
} else {
|
|
43031
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
43032
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
43033
|
+
}
|
|
43034
|
+
}
|
|
43035
|
+
function serveHtml(res, initialQuery) {
|
|
43036
|
+
let html = getHtmlPage();
|
|
43037
|
+
if (initialQuery) {
|
|
43038
|
+
const script = `<script>window.__INITIAL_QUERY__ = ${JSON.stringify(initialQuery)};</script>`;
|
|
43039
|
+
html = html.replace("</head>", `${script}</head>`);
|
|
43040
|
+
}
|
|
43041
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
43042
|
+
res.end(html);
|
|
43043
|
+
}
|
|
43044
|
+
async function handleSearch(url, res) {
|
|
43045
|
+
const query = url.searchParams.get("q") || "";
|
|
43046
|
+
const source = url.searchParams.get("source") || "user";
|
|
43047
|
+
const page = parseInt(url.searchParams.get("page") || "1", 10);
|
|
43048
|
+
const limit = parseInt(url.searchParams.get("limit") || "20", 10);
|
|
43049
|
+
if (!query) {
|
|
43050
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
43051
|
+
res.end(JSON.stringify({ error: "Missing query parameter" }));
|
|
43052
|
+
return;
|
|
43053
|
+
}
|
|
43054
|
+
try {
|
|
43055
|
+
const allResults = await easyedaCommunityClient.search({
|
|
43056
|
+
query,
|
|
43057
|
+
source,
|
|
43058
|
+
limit: Math.min(limit * page + limit, 100)
|
|
43059
|
+
});
|
|
43060
|
+
const startIndex = (page - 1) * limit;
|
|
43061
|
+
const endIndex = startIndex + limit;
|
|
43062
|
+
const results = allResults.slice(startIndex, endIndex);
|
|
43063
|
+
const totalPages = Math.ceil(allResults.length / limit);
|
|
43064
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
43065
|
+
res.end(JSON.stringify({
|
|
43066
|
+
results,
|
|
43067
|
+
pagination: {
|
|
43068
|
+
page,
|
|
43069
|
+
limit,
|
|
43070
|
+
total: allResults.length,
|
|
43071
|
+
totalPages,
|
|
43072
|
+
hasNext: page < totalPages,
|
|
43073
|
+
hasPrev: page > 1
|
|
43074
|
+
}
|
|
43075
|
+
}));
|
|
43076
|
+
} catch (error) {
|
|
43077
|
+
logger7.error("Search error:", error);
|
|
43078
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
43079
|
+
res.end(JSON.stringify({ error: "Search failed" }));
|
|
43080
|
+
}
|
|
43081
|
+
}
|
|
43082
|
+
function communityToComponentData(community) {
|
|
43083
|
+
const cPara = community.symbol.head?.c_para ?? {};
|
|
43084
|
+
const fpCPara = community.footprint.head?.c_para ?? {};
|
|
43085
|
+
return {
|
|
43086
|
+
info: {
|
|
43087
|
+
name: community.title || cPara.name || "Unknown",
|
|
43088
|
+
prefix: cPara.pre || cPara.Prefix || "U",
|
|
43089
|
+
package: fpCPara.package || community.footprint.name,
|
|
43090
|
+
manufacturer: cPara.Manufacturer || cPara.BOM_Manufacturer,
|
|
43091
|
+
description: community.description || cPara.BOM_Manufacturer_Part,
|
|
43092
|
+
category: cPara.package
|
|
43093
|
+
},
|
|
43094
|
+
symbol: community.symbol,
|
|
43095
|
+
footprint: community.footprint,
|
|
43096
|
+
model3d: community.model3d,
|
|
43097
|
+
rawData: community.rawData
|
|
43098
|
+
};
|
|
43099
|
+
}
|
|
43100
|
+
async function handleComponent(uuid, res) {
|
|
43101
|
+
if (!uuid) {
|
|
43102
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
43103
|
+
res.end(JSON.stringify({ error: "Missing UUID" }));
|
|
43104
|
+
return;
|
|
43105
|
+
}
|
|
43106
|
+
try {
|
|
43107
|
+
const component2 = await easyedaCommunityClient.getComponent(uuid);
|
|
43108
|
+
if (!component2) {
|
|
43109
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
43110
|
+
res.end(JSON.stringify({ error: "Component not found" }));
|
|
43111
|
+
return;
|
|
43112
|
+
}
|
|
43113
|
+
const componentData = communityToComponentData(component2);
|
|
43114
|
+
let symbolSexpr = "";
|
|
43115
|
+
let footprintSexpr = "";
|
|
43116
|
+
try {
|
|
43117
|
+
symbolSexpr = symbolConverter.convertToSymbolEntry(componentData);
|
|
43118
|
+
} catch (e) {
|
|
43119
|
+
logger7.warn("Symbol conversion failed:", e);
|
|
43120
|
+
}
|
|
43121
|
+
try {
|
|
43122
|
+
footprintSexpr = footprintConverter.convert(componentData);
|
|
43123
|
+
} catch (e) {
|
|
43124
|
+
logger7.warn("Footprint conversion failed:", e);
|
|
43125
|
+
}
|
|
43126
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
43127
|
+
res.end(JSON.stringify({
|
|
43128
|
+
uuid: component2.uuid,
|
|
43129
|
+
title: component2.title,
|
|
43130
|
+
description: component2.description,
|
|
43131
|
+
owner: component2.owner,
|
|
43132
|
+
symbolSexpr,
|
|
43133
|
+
footprintSexpr,
|
|
43134
|
+
model3d: component2.model3d
|
|
43135
|
+
}));
|
|
43136
|
+
} catch (error) {
|
|
43137
|
+
logger7.error("Component fetch error:", error);
|
|
43138
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
43139
|
+
res.end(JSON.stringify({ error: "Failed to fetch component" }));
|
|
43140
|
+
}
|
|
43141
|
+
}
|
|
43142
|
+
var logger8 = createLogger("http-server");
|
|
43143
|
+
var DEFAULT_PORT = 3847;
|
|
43144
|
+
var serverInstance = null;
|
|
43145
|
+
function startHttpServer(options = {}) {
|
|
43146
|
+
if (serverInstance) {
|
|
43147
|
+
logger8.debug("HTTP server already running");
|
|
43148
|
+
const port2 = options.port ?? parseInt(process.env.JLC_MCP_HTTP_PORT || String(DEFAULT_PORT), 10);
|
|
43149
|
+
options.onReady?.(`http://localhost:${port2}`);
|
|
43150
|
+
return port2;
|
|
43151
|
+
}
|
|
43152
|
+
const port = options.port ?? parseInt(process.env.JLC_MCP_HTTP_PORT || String(DEFAULT_PORT), 10);
|
|
43153
|
+
serverInstance = createServer(async (req, res) => {
|
|
43154
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
43155
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
43156
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
43157
|
+
if (req.method === "OPTIONS") {
|
|
43158
|
+
res.writeHead(204);
|
|
43159
|
+
res.end();
|
|
43160
|
+
return;
|
|
43161
|
+
}
|
|
43162
|
+
try {
|
|
43163
|
+
await handleRequest(req, res);
|
|
43164
|
+
} catch (error) {
|
|
43165
|
+
logger8.error("Request error:", error);
|
|
43166
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
43167
|
+
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
43168
|
+
}
|
|
43169
|
+
});
|
|
43170
|
+
serverInstance.listen(port, () => {
|
|
43171
|
+
const url = `http://localhost:${port}`;
|
|
43172
|
+
logger8.info(`HTTP server listening on ${url}`);
|
|
43173
|
+
options.onReady?.(url);
|
|
43174
|
+
});
|
|
43175
|
+
serverInstance.on("error", (error) => {
|
|
43176
|
+
if (error.code === "EADDRINUSE") {
|
|
43177
|
+
logger8.warn(`Port ${port} already in use, HTTP server not started`);
|
|
43178
|
+
} else {
|
|
43179
|
+
logger8.error("HTTP server error:", error);
|
|
43180
|
+
}
|
|
43181
|
+
});
|
|
43182
|
+
return port;
|
|
43183
|
+
}
|
|
43184
|
+
function stopHttpServer() {
|
|
43185
|
+
if (serverInstance) {
|
|
43186
|
+
serverInstance.close();
|
|
43187
|
+
serverInstance = null;
|
|
43188
|
+
logger8.info("HTTP server stopped");
|
|
43189
|
+
}
|
|
43190
|
+
}
|
|
42839
43191
|
|
|
42840
43192
|
// ../../node_modules/ink/build/render.js
|
|
42841
43193
|
import { Stream } from "node:stream";
|
|
@@ -49075,7 +49427,7 @@ var import_react30 = __toESM(require_react(), 1);
|
|
|
49075
49427
|
// ../../node_modules/open/index.js
|
|
49076
49428
|
import process19 from "node:process";
|
|
49077
49429
|
import path from "node:path";
|
|
49078
|
-
import { fileURLToPath } from "node:url";
|
|
49430
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
49079
49431
|
import childProcess3 from "node:child_process";
|
|
49080
49432
|
import fs6, { constants as fsConstants2 } from "node:fs/promises";
|
|
49081
49433
|
|
|
@@ -49386,8 +49738,8 @@ var is_in_ssh_default = isInSsh;
|
|
|
49386
49738
|
|
|
49387
49739
|
// ../../node_modules/open/index.js
|
|
49388
49740
|
var fallbackAttemptSymbol = Symbol("fallbackAttempt");
|
|
49389
|
-
var
|
|
49390
|
-
var localXdgOpenPath = path.join(
|
|
49741
|
+
var __dirname3 = import.meta.url ? path.dirname(fileURLToPath2(import.meta.url)) : "";
|
|
49742
|
+
var localXdgOpenPath = path.join(__dirname3, "xdg-open");
|
|
49391
49743
|
var { platform: platform5, arch } = process19;
|
|
49392
49744
|
var tryEachApp = async (apps, opener) => {
|
|
49393
49745
|
if (apps.length === 0) {
|
|
@@ -49531,7 +49883,7 @@ var baseOpen = async (options) => {
|
|
|
49531
49883
|
if (app) {
|
|
49532
49884
|
command = app;
|
|
49533
49885
|
} else {
|
|
49534
|
-
const isBundled = !
|
|
49886
|
+
const isBundled = !__dirname3 || __dirname3 === "/";
|
|
49535
49887
|
let exeLocalXdgOpen = false;
|
|
49536
49888
|
try {
|
|
49537
49889
|
await fs6.access(localXdgOpenPath, fsConstants2.X_OK);
|
|
@@ -50923,23 +51275,416 @@ function LibrarySetupScreen() {
|
|
|
50923
51275
|
}, undefined, true, undefined, this);
|
|
50924
51276
|
}
|
|
50925
51277
|
|
|
50926
|
-
// src/app/
|
|
51278
|
+
// src/app/screens/EasyEDAInfoScreen.tsx
|
|
51279
|
+
var import_react34 = __toESM(require_react(), 1);
|
|
51280
|
+
|
|
51281
|
+
// src/app/components/EasyEDADetailView.tsx
|
|
50927
51282
|
var jsx_dev_runtime13 = __toESM(require_jsx_dev_runtime(), 1);
|
|
51283
|
+
function truncate4(str, len) {
|
|
51284
|
+
if (!str)
|
|
51285
|
+
return "";
|
|
51286
|
+
return str.length > len ? str.slice(0, len - 1) + "…" : str;
|
|
51287
|
+
}
|
|
51288
|
+
function formatDate(timestamp) {
|
|
51289
|
+
if (!timestamp)
|
|
51290
|
+
return "N/A";
|
|
51291
|
+
const date = new Date(timestamp * 1000);
|
|
51292
|
+
return date.toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" });
|
|
51293
|
+
}
|
|
51294
|
+
function EasyEDADetailView({ component, terminalWidth, isInstalled, statusMessage }) {
|
|
51295
|
+
const isWide2 = terminalWidth >= 80;
|
|
51296
|
+
const labelWidth = 16;
|
|
51297
|
+
const colWidth = isWide2 ? Math.floor((terminalWidth - 4) / 2) : terminalWidth - 2;
|
|
51298
|
+
const valueWidth = colWidth - labelWidth - 1;
|
|
51299
|
+
const description = /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51300
|
+
flexDirection: "column",
|
|
51301
|
+
marginBottom: 1,
|
|
51302
|
+
width: terminalWidth - 2,
|
|
51303
|
+
children: [
|
|
51304
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51305
|
+
dimColor: true,
|
|
51306
|
+
children: "Description"
|
|
51307
|
+
}, undefined, false, undefined, this),
|
|
51308
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51309
|
+
wrap: "wrap",
|
|
51310
|
+
children: component.description || "No description"
|
|
51311
|
+
}, undefined, false, undefined, this)
|
|
51312
|
+
]
|
|
51313
|
+
}, undefined, true, undefined, this);
|
|
51314
|
+
const partInfo = /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51315
|
+
flexDirection: "column",
|
|
51316
|
+
width: colWidth,
|
|
51317
|
+
children: [
|
|
51318
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51319
|
+
bold: true,
|
|
51320
|
+
underline: true,
|
|
51321
|
+
color: "cyan",
|
|
51322
|
+
children: "Component Info"
|
|
51323
|
+
}, undefined, false, undefined, this),
|
|
51324
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51325
|
+
marginTop: 1,
|
|
51326
|
+
flexDirection: "column",
|
|
51327
|
+
children: [
|
|
51328
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51329
|
+
children: [
|
|
51330
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51331
|
+
dimColor: true,
|
|
51332
|
+
children: "Title".padEnd(labelWidth)
|
|
51333
|
+
}, undefined, false, undefined, this),
|
|
51334
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51335
|
+
bold: true,
|
|
51336
|
+
children: truncate4(component.title || "N/A", valueWidth)
|
|
51337
|
+
}, undefined, false, undefined, this)
|
|
51338
|
+
]
|
|
51339
|
+
}, undefined, true, undefined, this),
|
|
51340
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51341
|
+
children: [
|
|
51342
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51343
|
+
dimColor: true,
|
|
51344
|
+
children: "UUID".padEnd(labelWidth)
|
|
51345
|
+
}, undefined, false, undefined, this),
|
|
51346
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51347
|
+
color: "cyan",
|
|
51348
|
+
children: truncate4(component.uuid, valueWidth)
|
|
51349
|
+
}, undefined, false, undefined, this)
|
|
51350
|
+
]
|
|
51351
|
+
}, undefined, true, undefined, this),
|
|
51352
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51353
|
+
children: [
|
|
51354
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51355
|
+
dimColor: true,
|
|
51356
|
+
children: "Package".padEnd(labelWidth)
|
|
51357
|
+
}, undefined, false, undefined, this),
|
|
51358
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51359
|
+
children: truncate4(component.footprint?.name || "N/A", valueWidth)
|
|
51360
|
+
}, undefined, false, undefined, this)
|
|
51361
|
+
]
|
|
51362
|
+
}, undefined, true, undefined, this),
|
|
51363
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51364
|
+
children: [
|
|
51365
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51366
|
+
dimColor: true,
|
|
51367
|
+
children: "Pins".padEnd(labelWidth)
|
|
51368
|
+
}, undefined, false, undefined, this),
|
|
51369
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51370
|
+
children: component.symbol?.pins?.length || 0
|
|
51371
|
+
}, undefined, false, undefined, this)
|
|
51372
|
+
]
|
|
51373
|
+
}, undefined, true, undefined, this),
|
|
51374
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51375
|
+
children: [
|
|
51376
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51377
|
+
dimColor: true,
|
|
51378
|
+
children: "Pads".padEnd(labelWidth)
|
|
51379
|
+
}, undefined, false, undefined, this),
|
|
51380
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51381
|
+
children: component.footprint?.pads?.length || 0
|
|
51382
|
+
}, undefined, false, undefined, this)
|
|
51383
|
+
]
|
|
51384
|
+
}, undefined, true, undefined, this),
|
|
51385
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51386
|
+
children: [
|
|
51387
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51388
|
+
dimColor: true,
|
|
51389
|
+
children: "3D Model".padEnd(labelWidth)
|
|
51390
|
+
}, undefined, false, undefined, this),
|
|
51391
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51392
|
+
color: component.model3d ? "green" : "yellow",
|
|
51393
|
+
children: component.model3d ? "Yes" : "No"
|
|
51394
|
+
}, undefined, false, undefined, this)
|
|
51395
|
+
]
|
|
51396
|
+
}, undefined, true, undefined, this),
|
|
51397
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51398
|
+
children: [
|
|
51399
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51400
|
+
dimColor: true,
|
|
51401
|
+
children: "Verified".padEnd(labelWidth)
|
|
51402
|
+
}, undefined, false, undefined, this),
|
|
51403
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51404
|
+
color: component.verify ? "green" : "yellow",
|
|
51405
|
+
children: component.verify ? "Yes" : "No"
|
|
51406
|
+
}, undefined, false, undefined, this)
|
|
51407
|
+
]
|
|
51408
|
+
}, undefined, true, undefined, this)
|
|
51409
|
+
]
|
|
51410
|
+
}, undefined, true, undefined, this)
|
|
51411
|
+
]
|
|
51412
|
+
}, undefined, true, undefined, this);
|
|
51413
|
+
const communityInfo = /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51414
|
+
flexDirection: "column",
|
|
51415
|
+
marginLeft: isWide2 ? 2 : 0,
|
|
51416
|
+
marginTop: isWide2 ? 0 : 1,
|
|
51417
|
+
width: colWidth,
|
|
51418
|
+
children: [
|
|
51419
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51420
|
+
bold: true,
|
|
51421
|
+
underline: true,
|
|
51422
|
+
color: "cyan",
|
|
51423
|
+
children: "Community"
|
|
51424
|
+
}, undefined, false, undefined, this),
|
|
51425
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51426
|
+
marginTop: 1,
|
|
51427
|
+
flexDirection: "column",
|
|
51428
|
+
children: [
|
|
51429
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51430
|
+
children: [
|
|
51431
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51432
|
+
dimColor: true,
|
|
51433
|
+
children: "Owner".padEnd(labelWidth)
|
|
51434
|
+
}, undefined, false, undefined, this),
|
|
51435
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51436
|
+
children: truncate4(component.owner?.nickname || component.owner?.username || "N/A", valueWidth)
|
|
51437
|
+
}, undefined, false, undefined, this)
|
|
51438
|
+
]
|
|
51439
|
+
}, undefined, true, undefined, this),
|
|
51440
|
+
component.creator && component.creator.uuid !== component.owner?.uuid && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51441
|
+
children: [
|
|
51442
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51443
|
+
dimColor: true,
|
|
51444
|
+
children: "Creator".padEnd(labelWidth)
|
|
51445
|
+
}, undefined, false, undefined, this),
|
|
51446
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51447
|
+
children: truncate4(component.creator.nickname || component.creator.username || "N/A", valueWidth)
|
|
51448
|
+
}, undefined, false, undefined, this)
|
|
51449
|
+
]
|
|
51450
|
+
}, undefined, true, undefined, this),
|
|
51451
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51452
|
+
children: [
|
|
51453
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51454
|
+
dimColor: true,
|
|
51455
|
+
children: "Updated".padEnd(labelWidth)
|
|
51456
|
+
}, undefined, false, undefined, this),
|
|
51457
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51458
|
+
children: formatDate(component.updateTime)
|
|
51459
|
+
}, undefined, false, undefined, this)
|
|
51460
|
+
]
|
|
51461
|
+
}, undefined, true, undefined, this),
|
|
51462
|
+
component.tags && component.tags.length > 0 && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51463
|
+
children: [
|
|
51464
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51465
|
+
dimColor: true,
|
|
51466
|
+
children: "Tags".padEnd(labelWidth)
|
|
51467
|
+
}, undefined, false, undefined, this),
|
|
51468
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51469
|
+
children: truncate4(component.tags.slice(0, 3).join(", "), valueWidth)
|
|
51470
|
+
}, undefined, false, undefined, this)
|
|
51471
|
+
]
|
|
51472
|
+
}, undefined, true, undefined, this)
|
|
51473
|
+
]
|
|
51474
|
+
}, undefined, true, undefined, this)
|
|
51475
|
+
]
|
|
51476
|
+
}, undefined, true, undefined, this);
|
|
51477
|
+
const footerText = isInstalled ? "R Regenerate • Esc Back" : "Enter Install • Esc Back";
|
|
51478
|
+
return /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51479
|
+
flexDirection: "column",
|
|
51480
|
+
width: "100%",
|
|
51481
|
+
children: [
|
|
51482
|
+
description,
|
|
51483
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51484
|
+
flexDirection: isWide2 ? "row" : "column",
|
|
51485
|
+
width: "100%",
|
|
51486
|
+
children: [
|
|
51487
|
+
partInfo,
|
|
51488
|
+
communityInfo
|
|
51489
|
+
]
|
|
51490
|
+
}, undefined, true, undefined, this),
|
|
51491
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51492
|
+
marginTop: 1,
|
|
51493
|
+
flexDirection: "column",
|
|
51494
|
+
width: "100%",
|
|
51495
|
+
children: [
|
|
51496
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Divider, {
|
|
51497
|
+
width: terminalWidth
|
|
51498
|
+
}, undefined, false, undefined, this),
|
|
51499
|
+
statusMessage && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51500
|
+
paddingY: 0,
|
|
51501
|
+
children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51502
|
+
color: statusMessage.startsWith("✓") ? "green" : statusMessage.startsWith("✗") ? "red" : "yellow",
|
|
51503
|
+
children: statusMessage
|
|
51504
|
+
}, undefined, false, undefined, this)
|
|
51505
|
+
}, undefined, false, undefined, this),
|
|
51506
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
51507
|
+
paddingY: 0,
|
|
51508
|
+
children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
51509
|
+
dimColor: true,
|
|
51510
|
+
children: footerText
|
|
51511
|
+
}, undefined, false, undefined, this)
|
|
51512
|
+
}, undefined, false, undefined, this),
|
|
51513
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Divider, {
|
|
51514
|
+
width: terminalWidth
|
|
51515
|
+
}, undefined, false, undefined, this)
|
|
51516
|
+
]
|
|
51517
|
+
}, undefined, true, undefined, this)
|
|
51518
|
+
]
|
|
51519
|
+
}, undefined, true, undefined, this);
|
|
51520
|
+
}
|
|
51521
|
+
|
|
51522
|
+
// src/app/screens/EasyEDAInfoScreen.tsx
|
|
51523
|
+
var jsx_dev_runtime14 = __toESM(require_jsx_dev_runtime(), 1);
|
|
51524
|
+
var componentService4 = createComponentService();
|
|
51525
|
+
var libraryService5 = createLibraryService();
|
|
51526
|
+
function EasyEDAInfoScreen() {
|
|
51527
|
+
const { replace } = useNavigation();
|
|
51528
|
+
const { params } = useCurrentScreen();
|
|
51529
|
+
const { columns: terminalWidth } = useTerminalSize();
|
|
51530
|
+
const [component, setComponent] = import_react34.useState(null);
|
|
51531
|
+
const [isLoading, setIsLoading] = import_react34.useState(true);
|
|
51532
|
+
const [error, setError] = import_react34.useState(null);
|
|
51533
|
+
const [isInstalling, setIsInstalling] = import_react34.useState(false);
|
|
51534
|
+
const [statusMessage, setStatusMessage] = import_react34.useState(null);
|
|
51535
|
+
const [isInstalled, setIsInstalled] = import_react34.useState(false);
|
|
51536
|
+
const installingRef = import_react34.useRef(false);
|
|
51537
|
+
import_react34.useEffect(() => {
|
|
51538
|
+
const init = async () => {
|
|
51539
|
+
if (!params.uuid) {
|
|
51540
|
+
setError("No UUID provided");
|
|
51541
|
+
setIsLoading(false);
|
|
51542
|
+
return;
|
|
51543
|
+
}
|
|
51544
|
+
try {
|
|
51545
|
+
await libraryService5.ensureGlobalTables();
|
|
51546
|
+
const fetched = await componentService4.fetchCommunity(params.uuid);
|
|
51547
|
+
if (fetched) {
|
|
51548
|
+
setComponent(fetched);
|
|
51549
|
+
const installed = await libraryService5.isEasyEDAInstalled(fetched.title);
|
|
51550
|
+
setIsInstalled(installed);
|
|
51551
|
+
} else {
|
|
51552
|
+
setError("Component not found");
|
|
51553
|
+
}
|
|
51554
|
+
} catch (err) {
|
|
51555
|
+
setError(err instanceof Error ? err.message : "Failed to fetch component");
|
|
51556
|
+
} finally {
|
|
51557
|
+
setIsLoading(false);
|
|
51558
|
+
}
|
|
51559
|
+
};
|
|
51560
|
+
init();
|
|
51561
|
+
}, [params.uuid]);
|
|
51562
|
+
use_input_default((input, key) => {
|
|
51563
|
+
if (isLoading || !component || isInstalling)
|
|
51564
|
+
return;
|
|
51565
|
+
const lowerInput = input.toLowerCase();
|
|
51566
|
+
if (lowerInput === "r") {
|
|
51567
|
+
if (installingRef.current)
|
|
51568
|
+
return;
|
|
51569
|
+
installingRef.current = true;
|
|
51570
|
+
setIsInstalling(true);
|
|
51571
|
+
setStatusMessage("Regenerating symbol and footprint...");
|
|
51572
|
+
libraryService5.install(params.uuid, { force: true }).then((result) => {
|
|
51573
|
+
setStatusMessage(`✓ Reinstalled: ${result.symbolRef}`);
|
|
51574
|
+
setIsInstalled(true);
|
|
51575
|
+
setTimeout(() => setStatusMessage(null), 3000);
|
|
51576
|
+
}).catch((err) => {
|
|
51577
|
+
setStatusMessage(`✗ Failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
51578
|
+
setTimeout(() => setStatusMessage(null), 3000);
|
|
51579
|
+
}).finally(() => {
|
|
51580
|
+
setIsInstalling(false);
|
|
51581
|
+
installingRef.current = false;
|
|
51582
|
+
});
|
|
51583
|
+
return;
|
|
51584
|
+
}
|
|
51585
|
+
if (key.return) {
|
|
51586
|
+
if (installingRef.current)
|
|
51587
|
+
return;
|
|
51588
|
+
installingRef.current = true;
|
|
51589
|
+
setIsInstalling(true);
|
|
51590
|
+
setStatusMessage("Installing component...");
|
|
51591
|
+
libraryService5.ensureGlobalTables().then(() => libraryService5.install(params.uuid, {})).then((result) => {
|
|
51592
|
+
if (result.symbolAction === "exists") {
|
|
51593
|
+
setStatusMessage(`⚡ Already installed (use R to reinstall)`);
|
|
51594
|
+
} else {
|
|
51595
|
+
setStatusMessage(`✓ Installed: ${result.symbolRef}`);
|
|
51596
|
+
setIsInstalled(true);
|
|
51597
|
+
}
|
|
51598
|
+
setTimeout(() => setStatusMessage(null), 3000);
|
|
51599
|
+
}).catch((err) => {
|
|
51600
|
+
setStatusMessage(`✗ Failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
51601
|
+
setTimeout(() => setStatusMessage(null), 3000);
|
|
51602
|
+
}).finally(() => {
|
|
51603
|
+
setIsInstalling(false);
|
|
51604
|
+
installingRef.current = false;
|
|
51605
|
+
});
|
|
51606
|
+
}
|
|
51607
|
+
});
|
|
51608
|
+
if (isLoading) {
|
|
51609
|
+
return /* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Box_default, {
|
|
51610
|
+
flexDirection: "column",
|
|
51611
|
+
children: /* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Text, {
|
|
51612
|
+
color: "yellow",
|
|
51613
|
+
children: [
|
|
51614
|
+
"⏳ Loading component ",
|
|
51615
|
+
params.uuid,
|
|
51616
|
+
"..."
|
|
51617
|
+
]
|
|
51618
|
+
}, undefined, true, undefined, this)
|
|
51619
|
+
}, undefined, false, undefined, this);
|
|
51620
|
+
}
|
|
51621
|
+
if (error || !component) {
|
|
51622
|
+
return /* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Box_default, {
|
|
51623
|
+
flexDirection: "column",
|
|
51624
|
+
children: [
|
|
51625
|
+
/* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Text, {
|
|
51626
|
+
color: "red",
|
|
51627
|
+
children: [
|
|
51628
|
+
"✗ ",
|
|
51629
|
+
error || "Component not found"
|
|
51630
|
+
]
|
|
51631
|
+
}, undefined, true, undefined, this),
|
|
51632
|
+
/* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Text, {
|
|
51633
|
+
dimColor: true,
|
|
51634
|
+
children: "Press Esc to go back"
|
|
51635
|
+
}, undefined, false, undefined, this)
|
|
51636
|
+
]
|
|
51637
|
+
}, undefined, true, undefined, this);
|
|
51638
|
+
}
|
|
51639
|
+
return /* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Box_default, {
|
|
51640
|
+
flexDirection: "column",
|
|
51641
|
+
children: [
|
|
51642
|
+
/* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Box_default, {
|
|
51643
|
+
marginBottom: 1,
|
|
51644
|
+
children: /* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Text, {
|
|
51645
|
+
bold: true,
|
|
51646
|
+
children: [
|
|
51647
|
+
"Component: ",
|
|
51648
|
+
/* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Text, {
|
|
51649
|
+
color: "cyan",
|
|
51650
|
+
children: component.title
|
|
51651
|
+
}, undefined, false, undefined, this),
|
|
51652
|
+
isInstalled && /* @__PURE__ */ jsx_dev_runtime14.jsxDEV(Text, {
|
|
51653
|
+
color: "green",
|
|
51654
|
+
children: " ✓ Installed"
|
|
51655
|
+
}, undefined, false, undefined, this)
|
|
51656
|
+
]
|
|
51657
|
+
}, undefined, true, undefined, this)
|
|
51658
|
+
}, undefined, false, undefined, this),
|
|
51659
|
+
/* @__PURE__ */ jsx_dev_runtime14.jsxDEV(EasyEDADetailView, {
|
|
51660
|
+
component,
|
|
51661
|
+
terminalWidth,
|
|
51662
|
+
isInstalled,
|
|
51663
|
+
statusMessage
|
|
51664
|
+
}, undefined, false, undefined, this)
|
|
51665
|
+
]
|
|
51666
|
+
}, undefined, true, undefined, this);
|
|
51667
|
+
}
|
|
51668
|
+
|
|
51669
|
+
// src/app/App.tsx
|
|
51670
|
+
var jsx_dev_runtime15 = __toESM(require_jsx_dev_runtime(), 1);
|
|
50928
51671
|
function ScreenRouter() {
|
|
50929
51672
|
const { screen } = useCurrentScreen();
|
|
50930
51673
|
switch (screen) {
|
|
50931
51674
|
case "search":
|
|
50932
|
-
return /* @__PURE__ */
|
|
51675
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(SearchScreen, {}, undefined, false, undefined, this);
|
|
50933
51676
|
case "info":
|
|
50934
|
-
return /* @__PURE__ */
|
|
51677
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(InfoScreen, {}, undefined, false, undefined, this);
|
|
50935
51678
|
case "install":
|
|
50936
|
-
return /* @__PURE__ */
|
|
51679
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(InstallScreen, {}, undefined, false, undefined, this);
|
|
50937
51680
|
case "installed":
|
|
50938
|
-
return /* @__PURE__ */
|
|
51681
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(InstalledScreen, {}, undefined, false, undefined, this);
|
|
50939
51682
|
case "library":
|
|
50940
|
-
return /* @__PURE__ */
|
|
51683
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(LibraryScreen, {}, undefined, false, undefined, this);
|
|
50941
51684
|
case "library-setup":
|
|
50942
|
-
return /* @__PURE__ */
|
|
51685
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(LibrarySetupScreen, {}, undefined, false, undefined, this);
|
|
51686
|
+
case "easyeda-info":
|
|
51687
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(EasyEDAInfoScreen, {}, undefined, false, undefined, this);
|
|
50943
51688
|
default:
|
|
50944
51689
|
return null;
|
|
50945
51690
|
}
|
|
@@ -50961,34 +51706,34 @@ function AppContent() {
|
|
|
50961
51706
|
exit();
|
|
50962
51707
|
}
|
|
50963
51708
|
});
|
|
50964
|
-
return /* @__PURE__ */
|
|
51709
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
50965
51710
|
flexDirection: "column",
|
|
50966
51711
|
padding: 1,
|
|
50967
|
-
children: /* @__PURE__ */
|
|
51712
|
+
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(ScreenRouter, {}, undefined, false, undefined, this)
|
|
50968
51713
|
}, undefined, false, undefined, this);
|
|
50969
51714
|
}
|
|
50970
51715
|
function App2({ initialScreen, initialParams }) {
|
|
50971
|
-
return /* @__PURE__ */
|
|
51716
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(NavigationProvider, {
|
|
50972
51717
|
initialScreen,
|
|
50973
51718
|
initialParams,
|
|
50974
|
-
children: /* @__PURE__ */
|
|
50975
|
-
children: /* @__PURE__ */
|
|
51719
|
+
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(AppStateProvider, {
|
|
51720
|
+
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(AppContent, {}, undefined, false, undefined, this)
|
|
50976
51721
|
}, undefined, false, undefined, this)
|
|
50977
51722
|
}, undefined, false, undefined, this);
|
|
50978
51723
|
}
|
|
50979
51724
|
function renderApp(initialScreen, initialParams) {
|
|
50980
|
-
render_default(/* @__PURE__ */
|
|
51725
|
+
render_default(/* @__PURE__ */ jsx_dev_runtime15.jsxDEV(App2, {
|
|
50981
51726
|
initialScreen,
|
|
50982
51727
|
initialParams
|
|
50983
51728
|
}, undefined, false, undefined, this));
|
|
50984
51729
|
}
|
|
50985
51730
|
|
|
50986
51731
|
// src/commands/search.ts
|
|
50987
|
-
var
|
|
51732
|
+
var componentService5 = createComponentService();
|
|
50988
51733
|
async function searchCommand(query, options) {
|
|
50989
51734
|
console.log(`Searching for "${query}"...`);
|
|
50990
51735
|
try {
|
|
50991
|
-
let results = await
|
|
51736
|
+
let results = await componentService5.search(query, options);
|
|
50992
51737
|
if (!options.basicOnly) {
|
|
50993
51738
|
results = results.sort((a, b) => {
|
|
50994
51739
|
if (a.libraryType === "basic" && b.libraryType !== "basic")
|
|
@@ -51099,7 +51844,7 @@ var r = { modifier: { reset: [0, 0], bold: [1, 22], dim: [2, 22], italic: [3, 23
|
|
|
51099
51844
|
Object.keys(r.modifier);
|
|
51100
51845
|
var tD = Object.keys(r.color);
|
|
51101
51846
|
var eD = Object.keys(r.bgColor);
|
|
51102
|
-
[...tD];
|
|
51847
|
+
[...tD, ...eD];
|
|
51103
51848
|
function sD() {
|
|
51104
51849
|
const t = new Map;
|
|
51105
51850
|
for (const [u, F] of Object.entries(r)) {
|
|
@@ -51519,13 +52264,13 @@ var L2 = () => {
|
|
|
51519
52264
|
};
|
|
51520
52265
|
|
|
51521
52266
|
// src/commands/info.ts
|
|
51522
|
-
var
|
|
52267
|
+
var componentService6 = createComponentService();
|
|
51523
52268
|
async function infoCommand(id, options) {
|
|
51524
52269
|
if (options.json) {
|
|
51525
52270
|
const spinner = L2();
|
|
51526
52271
|
spinner.start(`Fetching component ${id}...`);
|
|
51527
52272
|
try {
|
|
51528
|
-
const details = await
|
|
52273
|
+
const details = await componentService6.getDetails(id);
|
|
51529
52274
|
spinner.stop("Component found");
|
|
51530
52275
|
console.log(JSON.stringify(details, null, 2));
|
|
51531
52276
|
} catch (error) {
|
|
@@ -51539,15 +52284,23 @@ async function infoCommand(id, options) {
|
|
|
51539
52284
|
}
|
|
51540
52285
|
|
|
51541
52286
|
// src/commands/install.ts
|
|
51542
|
-
var
|
|
51543
|
-
var
|
|
52287
|
+
var componentService7 = createComponentService();
|
|
52288
|
+
var libraryService6 = createLibraryService();
|
|
52289
|
+
function isLcscId3(id) {
|
|
52290
|
+
return /^C\d+$/i.test(id);
|
|
52291
|
+
}
|
|
51544
52292
|
async function installCommand(id, options) {
|
|
52293
|
+
if (id && !isLcscId3(id)) {
|
|
52294
|
+
v2.error(`"${id}" is not an LCSC part number (e.g., C2040).`);
|
|
52295
|
+
v2.info(`For EasyEDA community components, use: ${source_default.cyan(`jlc easyeda install ${id}`)}`);
|
|
52296
|
+
process.exit(1);
|
|
52297
|
+
}
|
|
51545
52298
|
if (id && options.force) {
|
|
51546
52299
|
const spinner2 = L2();
|
|
51547
52300
|
spinner2.start(`Installing component ${id}...`);
|
|
51548
52301
|
try {
|
|
51549
|
-
await
|
|
51550
|
-
const result = await
|
|
52302
|
+
await libraryService6.ensureGlobalTables();
|
|
52303
|
+
const result = await libraryService6.install(id, {
|
|
51551
52304
|
projectPath: options.projectPath,
|
|
51552
52305
|
include3d: options.include3d,
|
|
51553
52306
|
force: true
|
|
@@ -51573,7 +52326,7 @@ async function installCommand(id, options) {
|
|
|
51573
52326
|
const spinner2 = L2();
|
|
51574
52327
|
spinner2.start(`Fetching component ${id}...`);
|
|
51575
52328
|
try {
|
|
51576
|
-
const details = await
|
|
52329
|
+
const details = await componentService7.getDetails(id);
|
|
51577
52330
|
spinner2.stop("Component found");
|
|
51578
52331
|
renderApp("info", { componentId: id, component: details });
|
|
51579
52332
|
} catch (error) {
|
|
@@ -51599,7 +52352,7 @@ async function installCommand(id, options) {
|
|
|
51599
52352
|
const spinner = L2();
|
|
51600
52353
|
spinner.start(`Searching for "${query}"...`);
|
|
51601
52354
|
const searchOptions = { limit: 20 };
|
|
51602
|
-
let results = await
|
|
52355
|
+
let results = await componentService7.search(query, searchOptions);
|
|
51603
52356
|
results = results.sort((a2, b2) => {
|
|
51604
52357
|
if (a2.libraryType === "basic" && b2.libraryType !== "basic")
|
|
51605
52358
|
return -1;
|
|
@@ -51616,15 +52369,15 @@ async function installCommand(id, options) {
|
|
|
51616
52369
|
}
|
|
51617
52370
|
|
|
51618
52371
|
// src/commands/library.ts
|
|
51619
|
-
var
|
|
52372
|
+
var libraryService7 = createLibraryService();
|
|
51620
52373
|
async function libraryCommand(options) {
|
|
51621
52374
|
if (options.json) {
|
|
51622
52375
|
const spinner = L2();
|
|
51623
52376
|
spinner.start("Loading library status...");
|
|
51624
52377
|
try {
|
|
51625
52378
|
const [status, components] = await Promise.all([
|
|
51626
|
-
|
|
51627
|
-
|
|
52379
|
+
libraryService7.getStatus(),
|
|
52380
|
+
libraryService7.listInstalled({})
|
|
51628
52381
|
]);
|
|
51629
52382
|
spinner.stop(`Found ${components.length} installed components`);
|
|
51630
52383
|
console.log(JSON.stringify({
|
|
@@ -51647,6 +52400,91 @@ async function libraryCommand(options) {
|
|
|
51647
52400
|
renderApp("library", {});
|
|
51648
52401
|
}
|
|
51649
52402
|
|
|
52403
|
+
// src/commands/easyeda.ts
|
|
52404
|
+
var componentService8 = createComponentService();
|
|
52405
|
+
var libraryService8 = createLibraryService();
|
|
52406
|
+
async function easyedaSearchCommand(query, options) {
|
|
52407
|
+
const port = options.port ?? 3847;
|
|
52408
|
+
console.log("Starting component browser...");
|
|
52409
|
+
startHttpServer({
|
|
52410
|
+
port,
|
|
52411
|
+
onReady: async (url) => {
|
|
52412
|
+
const searchUrl = query ? `${url}?q=${encodeURIComponent(query)}` : url;
|
|
52413
|
+
console.log(`Browser opened at ${searchUrl}`);
|
|
52414
|
+
await open_default(searchUrl);
|
|
52415
|
+
console.log("Press Ctrl+C to stop the server and exit");
|
|
52416
|
+
}
|
|
52417
|
+
});
|
|
52418
|
+
await new Promise((resolve) => {
|
|
52419
|
+
process.on("SIGINT", () => {
|
|
52420
|
+
console.log(`
|
|
52421
|
+
Shutting down server...`);
|
|
52422
|
+
stopHttpServer();
|
|
52423
|
+
resolve();
|
|
52424
|
+
process.exit(0);
|
|
52425
|
+
});
|
|
52426
|
+
});
|
|
52427
|
+
}
|
|
52428
|
+
async function easyedaInstallCommand(uuid, options) {
|
|
52429
|
+
if (uuid && options.force) {
|
|
52430
|
+
const spinner2 = L2();
|
|
52431
|
+
spinner2.start(`Installing EasyEDA component ${uuid}...`);
|
|
52432
|
+
try {
|
|
52433
|
+
await libraryService8.ensureGlobalTables();
|
|
52434
|
+
const result = await libraryService8.install(uuid, {
|
|
52435
|
+
projectPath: options.projectPath,
|
|
52436
|
+
include3d: options.include3d,
|
|
52437
|
+
force: true
|
|
52438
|
+
});
|
|
52439
|
+
spinner2.stop(source_default.green("✓ Component installed"));
|
|
52440
|
+
console.log();
|
|
52441
|
+
console.log(source_default.cyan("Symbol: "), result.symbolRef);
|
|
52442
|
+
console.log(source_default.cyan("Footprint: "), result.footprintRef);
|
|
52443
|
+
console.log(source_default.cyan("Action: "), result.symbolAction);
|
|
52444
|
+
if (result.files.model3d) {
|
|
52445
|
+
console.log(source_default.cyan("3D Model: "), result.files.model3d);
|
|
52446
|
+
}
|
|
52447
|
+
console.log();
|
|
52448
|
+
console.log(source_default.dim(`Library: ${result.files.symbolLibrary}`));
|
|
52449
|
+
} catch (error) {
|
|
52450
|
+
spinner2.stop(source_default.red("✗ Installation failed"));
|
|
52451
|
+
v2.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
52452
|
+
process.exit(1);
|
|
52453
|
+
}
|
|
52454
|
+
return;
|
|
52455
|
+
}
|
|
52456
|
+
if (uuid) {
|
|
52457
|
+
renderApp("easyeda-info", { uuid });
|
|
52458
|
+
return;
|
|
52459
|
+
}
|
|
52460
|
+
const query = await ue({
|
|
52461
|
+
message: "Search EasyEDA community library:",
|
|
52462
|
+
placeholder: "e.g., STM32F103, ESP32, Arduino Nano",
|
|
52463
|
+
validate: (value) => {
|
|
52464
|
+
if (!value)
|
|
52465
|
+
return "Please enter a search term";
|
|
52466
|
+
return;
|
|
52467
|
+
}
|
|
52468
|
+
});
|
|
52469
|
+
if (BD(query)) {
|
|
52470
|
+
ve("Installation cancelled");
|
|
52471
|
+
process.exit(0);
|
|
52472
|
+
}
|
|
52473
|
+
const spinner = L2();
|
|
52474
|
+
spinner.start(`Searching EasyEDA community for "${query}"...`);
|
|
52475
|
+
const searchOptions = {
|
|
52476
|
+
limit: 20,
|
|
52477
|
+
source: "easyeda-community"
|
|
52478
|
+
};
|
|
52479
|
+
const results = await componentService8.search(query, searchOptions);
|
|
52480
|
+
spinner.stop(`Found ${results.length} results`);
|
|
52481
|
+
if (results.length === 0) {
|
|
52482
|
+
v2.warn("No components found. Try a different search term.");
|
|
52483
|
+
return;
|
|
52484
|
+
}
|
|
52485
|
+
renderApp("search", { query, results });
|
|
52486
|
+
}
|
|
52487
|
+
|
|
51650
52488
|
// src/index.ts
|
|
51651
52489
|
var program2 = new Command;
|
|
51652
52490
|
program2.name("jlc").description("JLC/EasyEDA component sourcing and KiCad library management").version("0.1.0");
|
|
@@ -51674,4 +52512,18 @@ program2.command("library").description("View JLC-MCP library status and install
|
|
|
51674
52512
|
json: options.json
|
|
51675
52513
|
});
|
|
51676
52514
|
});
|
|
52515
|
+
var easyeda = program2.command("easyeda").description("EasyEDA community component browser");
|
|
52516
|
+
easyeda.command("search <query...>").description("Open browser-based component search").option("-p, --port <number>", "HTTP server port", "3847").action(async (queryParts, options) => {
|
|
52517
|
+
const query = queryParts.join(" ");
|
|
52518
|
+
await easyedaSearchCommand(query, {
|
|
52519
|
+
port: options.port ? parseInt(options.port, 10) : undefined
|
|
52520
|
+
});
|
|
52521
|
+
});
|
|
52522
|
+
easyeda.command("install [uuid]").description("Install EasyEDA community component to KiCad libraries").option("-p, --project <path>", "Install to project-local library").option("--with-3d", "Include 3D model").option("-f, --force", "Force reinstall (regenerate symbol and footprint)").action(async (uuid, options) => {
|
|
52523
|
+
await easyedaInstallCommand(uuid, {
|
|
52524
|
+
projectPath: options.project,
|
|
52525
|
+
include3d: options.with3d,
|
|
52526
|
+
force: options.force
|
|
52527
|
+
});
|
|
52528
|
+
});
|
|
51677
52529
|
program2.parse();
|