@jlcpcb/cli 0.1.1 → 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 +28 -0
- package/dist/assets/search.html +528 -0
- package/dist/index.js +1000 -68
- 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
|
@@ -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,
|
|
@@ -41722,8 +41776,8 @@ var KI_PAD_LAYER_SMD = {
|
|
|
41722
41776
|
11: '"*.Cu" "*.Paste" "*.Mask"'
|
|
41723
41777
|
};
|
|
41724
41778
|
var KI_PAD_LAYER_THT = {
|
|
41725
|
-
1: '"
|
|
41726
|
-
2: '"
|
|
41779
|
+
1: '"*.Cu" "*.Mask"',
|
|
41780
|
+
2: '"*.Cu" "*.Mask"',
|
|
41727
41781
|
11: '"*.Cu" "*.Mask"'
|
|
41728
41782
|
};
|
|
41729
41783
|
var KI_PAD_SHAPE = {
|
|
@@ -41933,15 +41987,20 @@ class FootprintConverter {
|
|
|
41933
41987
|
`;
|
|
41934
41988
|
return output;
|
|
41935
41989
|
}
|
|
41936
|
-
generatePolygonPad(pad, origin,
|
|
41990
|
+
generatePolygonPad(pad, origin, _layers) {
|
|
41937
41991
|
const x = convertX(pad.centerX, origin.x);
|
|
41938
41992
|
const y = convertY(pad.centerY, origin.y);
|
|
41939
41993
|
const points = parsePoints(pad.points);
|
|
41940
41994
|
if (points.length < 3) {
|
|
41941
41995
|
return this.generatePad({ ...pad, shape: "RECT", points: "" }, origin);
|
|
41942
41996
|
}
|
|
41943
|
-
|
|
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;
|
|
41944
42002
|
const padType = isSmd ? "smd" : "thru_hole";
|
|
42003
|
+
const layers = getPadLayers(pad.layerId, isSmd);
|
|
41945
42004
|
const polyPoints = points.map((p) => ({
|
|
41946
42005
|
x: roundTo(toMM(p.x - pad.centerX), 2),
|
|
41947
42006
|
y: roundTo(toMM(p.y - pad.centerY), 2)
|
|
@@ -41953,7 +42012,7 @@ class FootprintConverter {
|
|
|
41953
42012
|
output += ` (size 0.01 0.01)
|
|
41954
42013
|
`;
|
|
41955
42014
|
if (!isSmd) {
|
|
41956
|
-
const drillDiameter = roundTo(toMM(
|
|
42015
|
+
const drillDiameter = roundTo(toMM(holeRadius * 2), 4);
|
|
41957
42016
|
if (pad.holeLength && pad.holeLength > 0) {
|
|
41958
42017
|
const holeH = roundTo(toMM(pad.holeLength), 4);
|
|
41959
42018
|
output += ` (drill oval ${drillDiameter} ${holeH})
|
|
@@ -41987,6 +42046,25 @@ class FootprintConverter {
|
|
|
41987
42046
|
`;
|
|
41988
42047
|
return output;
|
|
41989
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
|
+
}
|
|
41990
42068
|
generateHole(hole, origin) {
|
|
41991
42069
|
const x = convertX(hole.centerX, origin.x);
|
|
41992
42070
|
const y = convertY(hole.centerY, origin.y);
|
|
@@ -42113,9 +42191,9 @@ class FootprintConverter {
|
|
|
42113
42191
|
const fontSize = roundTo(toMM(text.fontSize), 2);
|
|
42114
42192
|
const rotation = text.rotation || 0;
|
|
42115
42193
|
let justify = "";
|
|
42116
|
-
if (
|
|
42194
|
+
if (text.type === "L") {
|
|
42117
42195
|
justify = "left";
|
|
42118
|
-
} else if (
|
|
42196
|
+
} else if (text.type === "R") {
|
|
42119
42197
|
justify = "right";
|
|
42120
42198
|
}
|
|
42121
42199
|
return ` (fp_text user "${this.escapeString(text.text)}"
|
|
@@ -42132,6 +42210,9 @@ ${justify ? ` (justify ${justify})
|
|
|
42132
42210
|
`;
|
|
42133
42211
|
}
|
|
42134
42212
|
generateSolidRegion(region, origin) {
|
|
42213
|
+
if (region.layerId === 99 || region.layerId === 100 || region.layerId === 101) {
|
|
42214
|
+
return "";
|
|
42215
|
+
}
|
|
42135
42216
|
const layer = getLayer(region.layerId);
|
|
42136
42217
|
const points = this.parseSvgPathToPoints(region.path, origin);
|
|
42137
42218
|
if (points.length < 3)
|
|
@@ -42164,15 +42245,111 @@ ${justify ? ` (justify ${justify})
|
|
|
42164
42245
|
}
|
|
42165
42246
|
parseSvgPathToPoints(path, origin) {
|
|
42166
42247
|
const points = [];
|
|
42167
|
-
|
|
42248
|
+
let currentX = 0, currentY = 0;
|
|
42249
|
+
let startX = 0, startY = 0;
|
|
42250
|
+
const commandRegex = /([MLHVCSQTAZ])\s*([^MLHVCSQTAZ]*)/gi;
|
|
42168
42251
|
let match;
|
|
42169
42252
|
while ((match = commandRegex.exec(path)) !== null) {
|
|
42170
|
-
const
|
|
42171
|
-
const
|
|
42172
|
-
|
|
42173
|
-
|
|
42174
|
-
|
|
42175
|
-
|
|
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
|
+
}
|
|
42176
42353
|
}
|
|
42177
42354
|
return points;
|
|
42178
42355
|
}
|
|
@@ -42340,10 +42517,14 @@ var FOOTPRINT_LIBRARY_NAME = getFootprintDirName();
|
|
|
42340
42517
|
var MODELS_3D_NAME = get3DModelsDirName();
|
|
42341
42518
|
var LIBRARY_NAMESPACE2 = "jlc_mcp";
|
|
42342
42519
|
var KICAD_VERSIONS3 = ["9.0", "8.0"];
|
|
42343
|
-
var
|
|
42344
|
-
var
|
|
42345
|
-
var
|
|
42346
|
-
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)";
|
|
42347
42528
|
function detectKicadVersion2() {
|
|
42348
42529
|
const home = homedir2();
|
|
42349
42530
|
const baseDir = join4(home, "Documents", "KiCad");
|
|
@@ -42484,10 +42665,7 @@ function createLibraryService() {
|
|
|
42484
42665
|
return {
|
|
42485
42666
|
async install(id, options = {}) {
|
|
42486
42667
|
const isCommunityComponent = !isLcscId2(id);
|
|
42487
|
-
|
|
42488
|
-
throw new Error("EasyEDA community components require projectPath for local storage");
|
|
42489
|
-
}
|
|
42490
|
-
const isGlobal = !isCommunityComponent && !options.projectPath;
|
|
42668
|
+
const isGlobal = !options.projectPath;
|
|
42491
42669
|
const paths = isGlobal ? getGlobalLibraryPaths() : getProjectLibraryPaths(options.projectPath);
|
|
42492
42670
|
let component = null;
|
|
42493
42671
|
if (isLcscId2(id)) {
|
|
@@ -42530,13 +42708,27 @@ function createLibraryService() {
|
|
|
42530
42708
|
let category;
|
|
42531
42709
|
let modelPath;
|
|
42532
42710
|
if (isCommunityComponent) {
|
|
42533
|
-
const
|
|
42534
|
-
const
|
|
42535
|
-
|
|
42536
|
-
|
|
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;
|
|
42537
42729
|
await ensureDir(symbolsDir);
|
|
42538
42730
|
await ensureDir(footprintDir);
|
|
42539
|
-
symbolFile = join4(symbolsDir,
|
|
42731
|
+
symbolFile = join4(symbolsDir, symLibFile);
|
|
42540
42732
|
symbolName = component.info.name.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
42541
42733
|
const include3d = options.include3d ?? true;
|
|
42542
42734
|
let modelRelativePath;
|
|
@@ -42547,21 +42739,30 @@ function createLibraryService() {
|
|
|
42547
42739
|
const modelFilename = `${symbolName}.step`;
|
|
42548
42740
|
modelPath = join4(models3dDir, modelFilename);
|
|
42549
42741
|
await writeBinary(modelPath, model);
|
|
42550
|
-
|
|
42742
|
+
if (isGlobal) {
|
|
42743
|
+
modelRelativePath = `\${KICAD9_3RD_PARTY}/${LIBRARY_NAMESPACE2}/3dmodels/${models3dDirName}/${modelFilename}`;
|
|
42744
|
+
} else {
|
|
42745
|
+
modelRelativePath = `\${KIPRJMOD}/libraries/3dmodels/${models3dDirName}/${modelFilename}`;
|
|
42746
|
+
}
|
|
42551
42747
|
}
|
|
42552
42748
|
}
|
|
42553
42749
|
const footprint = footprintConverter.convert(component, {
|
|
42554
|
-
libraryName:
|
|
42750
|
+
libraryName: libName,
|
|
42555
42751
|
include3DModel: !!modelRelativePath,
|
|
42556
42752
|
modelPath: modelRelativePath
|
|
42557
42753
|
});
|
|
42558
42754
|
footprintPath = join4(footprintDir, `${symbolName}.kicad_mod`);
|
|
42559
|
-
footprintRef = `${
|
|
42755
|
+
footprintRef = `${libName}:${symbolName}`;
|
|
42560
42756
|
await writeText(footprintPath, footprint);
|
|
42561
42757
|
component.info.package = footprintRef;
|
|
42562
|
-
|
|
42563
|
-
|
|
42564
|
-
|
|
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}`;
|
|
42565
42766
|
} else {
|
|
42566
42767
|
category = getLibraryCategory(component.info.prefix, component.info.category, component.info.description);
|
|
42567
42768
|
const symbolLibraryFilename = getLibraryFilename(category);
|
|
@@ -42608,7 +42809,7 @@ function createLibraryService() {
|
|
|
42608
42809
|
if (symbolConverter.symbolExistsInLibrary(existingContent, component.info.name)) {
|
|
42609
42810
|
if (options.force) {
|
|
42610
42811
|
symbolContent = symbolConverter.replaceInLibrary(existingContent, component, {
|
|
42611
|
-
libraryName: isCommunityComponent ?
|
|
42812
|
+
libraryName: isCommunityComponent ? EASYEDA_LIBRARY_NAME2 : undefined,
|
|
42612
42813
|
symbolName: isCommunityComponent ? symbolName : undefined
|
|
42613
42814
|
});
|
|
42614
42815
|
symbolAction = "replaced";
|
|
@@ -42618,14 +42819,14 @@ function createLibraryService() {
|
|
|
42618
42819
|
}
|
|
42619
42820
|
} else {
|
|
42620
42821
|
symbolContent = symbolConverter.appendToLibrary(existingContent, component, {
|
|
42621
|
-
libraryName: isCommunityComponent ?
|
|
42822
|
+
libraryName: isCommunityComponent ? EASYEDA_LIBRARY_NAME2 : undefined,
|
|
42622
42823
|
symbolName: isCommunityComponent ? symbolName : undefined
|
|
42623
42824
|
});
|
|
42624
42825
|
symbolAction = "appended";
|
|
42625
42826
|
}
|
|
42626
42827
|
} else {
|
|
42627
42828
|
symbolContent = symbolConverter.convert(component, {
|
|
42628
|
-
libraryName: isCommunityComponent ?
|
|
42829
|
+
libraryName: isCommunityComponent ? EASYEDA_LIBRARY_NAME2 : undefined,
|
|
42629
42830
|
symbolName: isCommunityComponent ? symbolName : undefined
|
|
42630
42831
|
});
|
|
42631
42832
|
symbolAction = "created";
|
|
@@ -42750,12 +42951,243 @@ function createLibraryService() {
|
|
|
42750
42951
|
fpLibTable: fpLibTablePath
|
|
42751
42952
|
}
|
|
42752
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
|
+
}
|
|
42753
42969
|
}
|
|
42754
42970
|
};
|
|
42755
42971
|
}
|
|
42756
42972
|
init_lib_table();
|
|
42757
42973
|
init_category_router();
|
|
42758
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
|
+
}
|
|
42759
43191
|
|
|
42760
43192
|
// ../../node_modules/ink/build/render.js
|
|
42761
43193
|
import { Stream } from "node:stream";
|
|
@@ -48995,7 +49427,7 @@ var import_react30 = __toESM(require_react(), 1);
|
|
|
48995
49427
|
// ../../node_modules/open/index.js
|
|
48996
49428
|
import process19 from "node:process";
|
|
48997
49429
|
import path from "node:path";
|
|
48998
|
-
import { fileURLToPath } from "node:url";
|
|
49430
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
48999
49431
|
import childProcess3 from "node:child_process";
|
|
49000
49432
|
import fs6, { constants as fsConstants2 } from "node:fs/promises";
|
|
49001
49433
|
|
|
@@ -49306,8 +49738,8 @@ var is_in_ssh_default = isInSsh;
|
|
|
49306
49738
|
|
|
49307
49739
|
// ../../node_modules/open/index.js
|
|
49308
49740
|
var fallbackAttemptSymbol = Symbol("fallbackAttempt");
|
|
49309
|
-
var
|
|
49310
|
-
var localXdgOpenPath = path.join(
|
|
49741
|
+
var __dirname3 = import.meta.url ? path.dirname(fileURLToPath2(import.meta.url)) : "";
|
|
49742
|
+
var localXdgOpenPath = path.join(__dirname3, "xdg-open");
|
|
49311
49743
|
var { platform: platform5, arch } = process19;
|
|
49312
49744
|
var tryEachApp = async (apps, opener) => {
|
|
49313
49745
|
if (apps.length === 0) {
|
|
@@ -49451,7 +49883,7 @@ var baseOpen = async (options) => {
|
|
|
49451
49883
|
if (app) {
|
|
49452
49884
|
command = app;
|
|
49453
49885
|
} else {
|
|
49454
|
-
const isBundled = !
|
|
49886
|
+
const isBundled = !__dirname3 || __dirname3 === "/";
|
|
49455
49887
|
let exeLocalXdgOpen = false;
|
|
49456
49888
|
try {
|
|
49457
49889
|
await fs6.access(localXdgOpenPath, fsConstants2.X_OK);
|
|
@@ -50843,23 +51275,416 @@ function LibrarySetupScreen() {
|
|
|
50843
51275
|
}, undefined, true, undefined, this);
|
|
50844
51276
|
}
|
|
50845
51277
|
|
|
50846
|
-
// src/app/
|
|
51278
|
+
// src/app/screens/EasyEDAInfoScreen.tsx
|
|
51279
|
+
var import_react34 = __toESM(require_react(), 1);
|
|
51280
|
+
|
|
51281
|
+
// src/app/components/EasyEDADetailView.tsx
|
|
50847
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);
|
|
50848
51671
|
function ScreenRouter() {
|
|
50849
51672
|
const { screen } = useCurrentScreen();
|
|
50850
51673
|
switch (screen) {
|
|
50851
51674
|
case "search":
|
|
50852
|
-
return /* @__PURE__ */
|
|
51675
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(SearchScreen, {}, undefined, false, undefined, this);
|
|
50853
51676
|
case "info":
|
|
50854
|
-
return /* @__PURE__ */
|
|
51677
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(InfoScreen, {}, undefined, false, undefined, this);
|
|
50855
51678
|
case "install":
|
|
50856
|
-
return /* @__PURE__ */
|
|
51679
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(InstallScreen, {}, undefined, false, undefined, this);
|
|
50857
51680
|
case "installed":
|
|
50858
|
-
return /* @__PURE__ */
|
|
51681
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(InstalledScreen, {}, undefined, false, undefined, this);
|
|
50859
51682
|
case "library":
|
|
50860
|
-
return /* @__PURE__ */
|
|
51683
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(LibraryScreen, {}, undefined, false, undefined, this);
|
|
50861
51684
|
case "library-setup":
|
|
50862
|
-
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);
|
|
50863
51688
|
default:
|
|
50864
51689
|
return null;
|
|
50865
51690
|
}
|
|
@@ -50881,34 +51706,34 @@ function AppContent() {
|
|
|
50881
51706
|
exit();
|
|
50882
51707
|
}
|
|
50883
51708
|
});
|
|
50884
|
-
return /* @__PURE__ */
|
|
51709
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
50885
51710
|
flexDirection: "column",
|
|
50886
51711
|
padding: 1,
|
|
50887
|
-
children: /* @__PURE__ */
|
|
51712
|
+
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(ScreenRouter, {}, undefined, false, undefined, this)
|
|
50888
51713
|
}, undefined, false, undefined, this);
|
|
50889
51714
|
}
|
|
50890
51715
|
function App2({ initialScreen, initialParams }) {
|
|
50891
|
-
return /* @__PURE__ */
|
|
51716
|
+
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(NavigationProvider, {
|
|
50892
51717
|
initialScreen,
|
|
50893
51718
|
initialParams,
|
|
50894
|
-
children: /* @__PURE__ */
|
|
50895
|
-
children: /* @__PURE__ */
|
|
51719
|
+
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(AppStateProvider, {
|
|
51720
|
+
children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(AppContent, {}, undefined, false, undefined, this)
|
|
50896
51721
|
}, undefined, false, undefined, this)
|
|
50897
51722
|
}, undefined, false, undefined, this);
|
|
50898
51723
|
}
|
|
50899
51724
|
function renderApp(initialScreen, initialParams) {
|
|
50900
|
-
render_default(/* @__PURE__ */
|
|
51725
|
+
render_default(/* @__PURE__ */ jsx_dev_runtime15.jsxDEV(App2, {
|
|
50901
51726
|
initialScreen,
|
|
50902
51727
|
initialParams
|
|
50903
51728
|
}, undefined, false, undefined, this));
|
|
50904
51729
|
}
|
|
50905
51730
|
|
|
50906
51731
|
// src/commands/search.ts
|
|
50907
|
-
var
|
|
51732
|
+
var componentService5 = createComponentService();
|
|
50908
51733
|
async function searchCommand(query, options) {
|
|
50909
51734
|
console.log(`Searching for "${query}"...`);
|
|
50910
51735
|
try {
|
|
50911
|
-
let results = await
|
|
51736
|
+
let results = await componentService5.search(query, options);
|
|
50912
51737
|
if (!options.basicOnly) {
|
|
50913
51738
|
results = results.sort((a, b) => {
|
|
50914
51739
|
if (a.libraryType === "basic" && b.libraryType !== "basic")
|
|
@@ -51439,13 +52264,13 @@ var L2 = () => {
|
|
|
51439
52264
|
};
|
|
51440
52265
|
|
|
51441
52266
|
// src/commands/info.ts
|
|
51442
|
-
var
|
|
52267
|
+
var componentService6 = createComponentService();
|
|
51443
52268
|
async function infoCommand(id, options) {
|
|
51444
52269
|
if (options.json) {
|
|
51445
52270
|
const spinner = L2();
|
|
51446
52271
|
spinner.start(`Fetching component ${id}...`);
|
|
51447
52272
|
try {
|
|
51448
|
-
const details = await
|
|
52273
|
+
const details = await componentService6.getDetails(id);
|
|
51449
52274
|
spinner.stop("Component found");
|
|
51450
52275
|
console.log(JSON.stringify(details, null, 2));
|
|
51451
52276
|
} catch (error) {
|
|
@@ -51459,15 +52284,23 @@ async function infoCommand(id, options) {
|
|
|
51459
52284
|
}
|
|
51460
52285
|
|
|
51461
52286
|
// src/commands/install.ts
|
|
51462
|
-
var
|
|
51463
|
-
var
|
|
52287
|
+
var componentService7 = createComponentService();
|
|
52288
|
+
var libraryService6 = createLibraryService();
|
|
52289
|
+
function isLcscId3(id) {
|
|
52290
|
+
return /^C\d+$/i.test(id);
|
|
52291
|
+
}
|
|
51464
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
|
+
}
|
|
51465
52298
|
if (id && options.force) {
|
|
51466
52299
|
const spinner2 = L2();
|
|
51467
52300
|
spinner2.start(`Installing component ${id}...`);
|
|
51468
52301
|
try {
|
|
51469
|
-
await
|
|
51470
|
-
const result = await
|
|
52302
|
+
await libraryService6.ensureGlobalTables();
|
|
52303
|
+
const result = await libraryService6.install(id, {
|
|
51471
52304
|
projectPath: options.projectPath,
|
|
51472
52305
|
include3d: options.include3d,
|
|
51473
52306
|
force: true
|
|
@@ -51493,7 +52326,7 @@ async function installCommand(id, options) {
|
|
|
51493
52326
|
const spinner2 = L2();
|
|
51494
52327
|
spinner2.start(`Fetching component ${id}...`);
|
|
51495
52328
|
try {
|
|
51496
|
-
const details = await
|
|
52329
|
+
const details = await componentService7.getDetails(id);
|
|
51497
52330
|
spinner2.stop("Component found");
|
|
51498
52331
|
renderApp("info", { componentId: id, component: details });
|
|
51499
52332
|
} catch (error) {
|
|
@@ -51519,7 +52352,7 @@ async function installCommand(id, options) {
|
|
|
51519
52352
|
const spinner = L2();
|
|
51520
52353
|
spinner.start(`Searching for "${query}"...`);
|
|
51521
52354
|
const searchOptions = { limit: 20 };
|
|
51522
|
-
let results = await
|
|
52355
|
+
let results = await componentService7.search(query, searchOptions);
|
|
51523
52356
|
results = results.sort((a2, b2) => {
|
|
51524
52357
|
if (a2.libraryType === "basic" && b2.libraryType !== "basic")
|
|
51525
52358
|
return -1;
|
|
@@ -51536,15 +52369,15 @@ async function installCommand(id, options) {
|
|
|
51536
52369
|
}
|
|
51537
52370
|
|
|
51538
52371
|
// src/commands/library.ts
|
|
51539
|
-
var
|
|
52372
|
+
var libraryService7 = createLibraryService();
|
|
51540
52373
|
async function libraryCommand(options) {
|
|
51541
52374
|
if (options.json) {
|
|
51542
52375
|
const spinner = L2();
|
|
51543
52376
|
spinner.start("Loading library status...");
|
|
51544
52377
|
try {
|
|
51545
52378
|
const [status, components] = await Promise.all([
|
|
51546
|
-
|
|
51547
|
-
|
|
52379
|
+
libraryService7.getStatus(),
|
|
52380
|
+
libraryService7.listInstalled({})
|
|
51548
52381
|
]);
|
|
51549
52382
|
spinner.stop(`Found ${components.length} installed components`);
|
|
51550
52383
|
console.log(JSON.stringify({
|
|
@@ -51567,6 +52400,91 @@ async function libraryCommand(options) {
|
|
|
51567
52400
|
renderApp("library", {});
|
|
51568
52401
|
}
|
|
51569
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
|
+
|
|
51570
52488
|
// src/index.ts
|
|
51571
52489
|
var program2 = new Command;
|
|
51572
52490
|
program2.name("jlc").description("JLC/EasyEDA component sourcing and KiCad library management").version("0.1.0");
|
|
@@ -51594,4 +52512,18 @@ program2.command("library").description("View JLC-MCP library status and install
|
|
|
51594
52512
|
json: options.json
|
|
51595
52513
|
});
|
|
51596
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
|
+
});
|
|
51597
52529
|
program2.parse();
|