@yabasha/gex 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-bun.mjs +660 -0
- package/dist/cli-bun.mjs.map +1 -0
- package/dist/cli-node.cjs +572 -0
- package/dist/cli-node.cjs.map +1 -0
- package/dist/cli-node.mjs +540 -0
- package/dist/cli-node.mjs.map +1 -0
- package/dist/cli.cjs +173 -310
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +171 -309
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +18 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +18 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/dist/cli.mjs
CHANGED
|
@@ -6,36 +6,56 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
// src/
|
|
9
|
+
// src/runtimes/node/commands.ts
|
|
10
10
|
import path6 from "path";
|
|
11
11
|
import { Command } from "commander";
|
|
12
12
|
|
|
13
|
-
// src/cli/install.ts
|
|
13
|
+
// src/shared/cli/install.ts
|
|
14
|
+
var INSTALL_COMMANDS = {
|
|
15
|
+
npm: {
|
|
16
|
+
global: ["i", "-g"],
|
|
17
|
+
local: ["i"],
|
|
18
|
+
dev: ["i", "-D"]
|
|
19
|
+
},
|
|
20
|
+
bun: {
|
|
21
|
+
global: ["add", "-g"],
|
|
22
|
+
local: ["add"],
|
|
23
|
+
dev: ["add", "-d"]
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var MAX_BUFFER = 10 * 1024 * 1024;
|
|
27
|
+
function formatSpec(pkg) {
|
|
28
|
+
return pkg.version ? `${pkg.name}@${pkg.version}` : pkg.name;
|
|
29
|
+
}
|
|
14
30
|
async function getExecFileAsync() {
|
|
15
31
|
const { execFile } = await import("child_process");
|
|
16
32
|
const { promisify } = await import("util");
|
|
17
33
|
return promisify(execFile);
|
|
18
34
|
}
|
|
19
|
-
async function installFromReport(report,
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
35
|
+
async function installFromReport(report, options) {
|
|
36
|
+
const opts = typeof options === "string" ? { cwd: options } : options;
|
|
37
|
+
const { cwd, packageManager = "npm" } = opts;
|
|
38
|
+
const globalPkgs = report.global_packages.map(formatSpec).filter(Boolean);
|
|
39
|
+
const localPkgs = report.local_dependencies.map(formatSpec).filter(Boolean);
|
|
40
|
+
const devPkgs = report.local_dev_dependencies.map(formatSpec).filter(Boolean);
|
|
23
41
|
if (globalPkgs.length === 0 && localPkgs.length === 0 && devPkgs.length === 0) {
|
|
24
42
|
console.log("No packages to install from report.");
|
|
25
43
|
return;
|
|
26
44
|
}
|
|
27
45
|
const execFileAsync = await getExecFileAsync();
|
|
46
|
+
const cmd = INSTALL_COMMANDS[packageManager];
|
|
47
|
+
const binary = packageManager === "bun" ? "bun" : "npm";
|
|
28
48
|
if (globalPkgs.length > 0) {
|
|
29
49
|
console.log(`Installing global: ${globalPkgs.join(" ")}`);
|
|
30
|
-
await execFileAsync(
|
|
50
|
+
await execFileAsync(binary, [...cmd.global, ...globalPkgs], { cwd, maxBuffer: MAX_BUFFER });
|
|
31
51
|
}
|
|
32
52
|
if (localPkgs.length > 0) {
|
|
33
53
|
console.log(`Installing local deps: ${localPkgs.join(" ")}`);
|
|
34
|
-
await execFileAsync(
|
|
54
|
+
await execFileAsync(binary, [...cmd.local, ...localPkgs], { cwd, maxBuffer: MAX_BUFFER });
|
|
35
55
|
}
|
|
36
56
|
if (devPkgs.length > 0) {
|
|
37
57
|
console.log(`Installing local devDeps: ${devPkgs.join(" ")}`);
|
|
38
|
-
await execFileAsync(
|
|
58
|
+
await execFileAsync(binary, [...cmd.dev, ...devPkgs], { cwd, maxBuffer: MAX_BUFFER });
|
|
39
59
|
}
|
|
40
60
|
}
|
|
41
61
|
function printFromReport(report) {
|
|
@@ -66,10 +86,10 @@ function printFromReport(report) {
|
|
|
66
86
|
console.log(lines.join("\n"));
|
|
67
87
|
}
|
|
68
88
|
|
|
69
|
-
// src/cli/output.ts
|
|
89
|
+
// src/shared/cli/output.ts
|
|
70
90
|
import path from "path";
|
|
71
91
|
|
|
72
|
-
// src/report/json.ts
|
|
92
|
+
// src/shared/report/json.ts
|
|
73
93
|
function renderJson(report) {
|
|
74
94
|
const r = {
|
|
75
95
|
...report,
|
|
@@ -82,7 +102,7 @@ function renderJson(report) {
|
|
|
82
102
|
return JSON.stringify(r, null, 2);
|
|
83
103
|
}
|
|
84
104
|
|
|
85
|
-
// src/report/md.ts
|
|
105
|
+
// src/shared/report/md.ts
|
|
86
106
|
function table(headers, rows) {
|
|
87
107
|
const header = `| ${headers.join(" | ")} |`;
|
|
88
108
|
const sep = `| ${headers.map(() => "---").join(" | ")} |`;
|
|
@@ -135,211 +155,9 @@ function renderMarkdown(report) {
|
|
|
135
155
|
return lines.join("\n");
|
|
136
156
|
}
|
|
137
157
|
|
|
138
|
-
// src/
|
|
139
|
-
function table2(headers, rows) {
|
|
140
|
-
const headerHtml = `<tr>${headers.map((h) => `<th>${h}</th>`).join("")}</tr>`;
|
|
141
|
-
const bodyHtml = rows.map((row) => `<tr>${row.map((cell) => `<td>${cell}</td>`).join("")}</tr>`).join("");
|
|
142
|
-
return `<table><thead>${headerHtml}</thead><tbody>${bodyHtml}</tbody></table>`;
|
|
143
|
-
}
|
|
144
|
-
function escapeHtml(text) {
|
|
145
|
-
const htmlEntities = {
|
|
146
|
-
"&": "&",
|
|
147
|
-
"<": "<",
|
|
148
|
-
">": ">",
|
|
149
|
-
'"': """,
|
|
150
|
-
"'": "'"
|
|
151
|
-
};
|
|
152
|
-
return text.replace(/[&<>"']/g, (char) => htmlEntities[char]);
|
|
153
|
-
}
|
|
154
|
-
function renderHtml(report) {
|
|
155
|
-
const hasProjectMeta = report.project_name || report.project_version || report.project_description || report.project_homepage || report.project_bugs;
|
|
156
|
-
return `<!DOCTYPE html>
|
|
157
|
-
<html lang="en">
|
|
158
|
-
<head>
|
|
159
|
-
<meta charset="UTF-8">
|
|
160
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
161
|
-
<title>GEX Report - ${report.project_name || "Dependency Audit"}</title>
|
|
162
|
-
<style>
|
|
163
|
-
body {
|
|
164
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
165
|
-
line-height: 1.6;
|
|
166
|
-
color: #333;
|
|
167
|
-
max-width: 1200px;
|
|
168
|
-
margin: 0 auto;
|
|
169
|
-
padding: 20px;
|
|
170
|
-
background-color: #f5f5f5;
|
|
171
|
-
}
|
|
172
|
-
.container {
|
|
173
|
-
background: white;
|
|
174
|
-
border-radius: 8px;
|
|
175
|
-
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
176
|
-
padding: 30px;
|
|
177
|
-
}
|
|
178
|
-
h1 {
|
|
179
|
-
color: #2c3e50;
|
|
180
|
-
border-bottom: 3px solid #3498db;
|
|
181
|
-
padding-bottom: 10px;
|
|
182
|
-
margin-top: 0;
|
|
183
|
-
}
|
|
184
|
-
h2 {
|
|
185
|
-
color: #34495e;
|
|
186
|
-
border-bottom: 2px solid #bdc3c7;
|
|
187
|
-
padding-bottom: 8px;
|
|
188
|
-
margin-top: 40px;
|
|
189
|
-
margin-bottom: 20px;
|
|
190
|
-
}
|
|
191
|
-
.metadata {
|
|
192
|
-
background: #ecf0f1;
|
|
193
|
-
border-radius: 6px;
|
|
194
|
-
padding: 20px;
|
|
195
|
-
margin-bottom: 20px;
|
|
196
|
-
}
|
|
197
|
-
.metadata dl {
|
|
198
|
-
margin: 0;
|
|
199
|
-
}
|
|
200
|
-
.metadata dt {
|
|
201
|
-
font-weight: bold;
|
|
202
|
-
color: #2c3e50;
|
|
203
|
-
margin-top: 10px;
|
|
204
|
-
}
|
|
205
|
-
.metadata dt:first-child {
|
|
206
|
-
margin-top: 0;
|
|
207
|
-
}
|
|
208
|
-
.metadata dd {
|
|
209
|
-
margin: 5px 0 0 20px;
|
|
210
|
-
color: #555;
|
|
211
|
-
}
|
|
212
|
-
.metadata dd a {
|
|
213
|
-
color: #3498db;
|
|
214
|
-
text-decoration: none;
|
|
215
|
-
}
|
|
216
|
-
.metadata dd a:hover {
|
|
217
|
-
text-decoration: underline;
|
|
218
|
-
}
|
|
219
|
-
table {
|
|
220
|
-
width: 100%;
|
|
221
|
-
border-collapse: collapse;
|
|
222
|
-
margin-bottom: 30px;
|
|
223
|
-
background: white;
|
|
224
|
-
border-radius: 6px;
|
|
225
|
-
overflow: hidden;
|
|
226
|
-
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
|
227
|
-
}
|
|
228
|
-
th {
|
|
229
|
-
background: #3498db;
|
|
230
|
-
color: white;
|
|
231
|
-
padding: 12px;
|
|
232
|
-
text-align: left;
|
|
233
|
-
font-weight: 600;
|
|
234
|
-
}
|
|
235
|
-
td {
|
|
236
|
-
padding: 12px;
|
|
237
|
-
border-bottom: 1px solid #ecf0f1;
|
|
238
|
-
font-family: 'SFMono-Regular', Consolas, monospace;
|
|
239
|
-
font-size: 14px;
|
|
240
|
-
}
|
|
241
|
-
tr:nth-child(even) {
|
|
242
|
-
background: #f8f9fa;
|
|
243
|
-
}
|
|
244
|
-
tr:hover {
|
|
245
|
-
background: #e8f4fd;
|
|
246
|
-
}
|
|
247
|
-
.footer {
|
|
248
|
-
text-align: center;
|
|
249
|
-
color: #7f8c8d;
|
|
250
|
-
font-size: 14px;
|
|
251
|
-
margin-top: 40px;
|
|
252
|
-
padding-top: 20px;
|
|
253
|
-
border-top: 1px solid #ecf0f1;
|
|
254
|
-
}
|
|
255
|
-
.footer strong {
|
|
256
|
-
color: #2c3e50;
|
|
257
|
-
}
|
|
258
|
-
.no-data {
|
|
259
|
-
text-align: center;
|
|
260
|
-
color: #7f8c8d;
|
|
261
|
-
font-style: italic;
|
|
262
|
-
padding: 40px;
|
|
263
|
-
}
|
|
264
|
-
.timestamp {
|
|
265
|
-
color: #95a5a6;
|
|
266
|
-
font-size: 14px;
|
|
267
|
-
margin-top: 10px;
|
|
268
|
-
}
|
|
269
|
-
</style>
|
|
270
|
-
</head>
|
|
271
|
-
<body>
|
|
272
|
-
<div class="container">
|
|
273
|
-
<h1>GEX Dependency Report</h1>
|
|
274
|
-
|
|
275
|
-
${hasProjectMeta ? `
|
|
276
|
-
<section class="metadata">
|
|
277
|
-
<h2>Project Information</h2>
|
|
278
|
-
<dl>
|
|
279
|
-
${report.project_name ? `<dt>Project Name</dt><dd>${escapeHtml(report.project_name)}</dd>` : ""}
|
|
280
|
-
${report.project_version ? `<dt>Version</dt><dd>${escapeHtml(report.project_version)}</dd>` : ""}
|
|
281
|
-
${report.project_description ? `<dt>Description</dt><dd>${escapeHtml(report.project_description)}</dd>` : ""}
|
|
282
|
-
${report.project_homepage ? `<dt>Homepage</dt><dd><a href="${escapeHtml(report.project_homepage)}" target="_blank">${escapeHtml(report.project_homepage)}</a></dd>` : ""}
|
|
283
|
-
${report.project_bugs ? `<dt>Bugs</dt><dd><a href="${escapeHtml(report.project_bugs)}" target="_blank">${escapeHtml(report.project_bugs)}</a></dd>` : ""}
|
|
284
|
-
<dt>Report Generated</dt><dd>${new Date(report.timestamp).toLocaleString()}</dd>
|
|
285
|
-
</dl>
|
|
286
|
-
</section>
|
|
287
|
-
` : ""}
|
|
288
|
-
|
|
289
|
-
${report.global_packages.length > 0 ? `
|
|
290
|
-
<section>
|
|
291
|
-
<h2>Global Packages <small>(${report.global_packages.length})</small></h2>
|
|
292
|
-
${table2(
|
|
293
|
-
["Name", "Version", "Path"],
|
|
294
|
-
report.global_packages.map((p) => [
|
|
295
|
-
escapeHtml(p.name),
|
|
296
|
-
escapeHtml(p.version || ""),
|
|
297
|
-
escapeHtml(p.resolved_path || "")
|
|
298
|
-
])
|
|
299
|
-
)}
|
|
300
|
-
</section>
|
|
301
|
-
` : '<section><h2>Global Packages</h2><div class="no-data">No global packages found</div></section>'}
|
|
302
|
-
|
|
303
|
-
${report.local_dependencies.length > 0 ? `
|
|
304
|
-
<section>
|
|
305
|
-
<h2>Local Dependencies <small>(${report.local_dependencies.length})</small></h2>
|
|
306
|
-
${table2(
|
|
307
|
-
["Name", "Version", "Path"],
|
|
308
|
-
report.local_dependencies.map((p) => [
|
|
309
|
-
escapeHtml(p.name),
|
|
310
|
-
escapeHtml(p.version || ""),
|
|
311
|
-
escapeHtml(p.resolved_path || "")
|
|
312
|
-
])
|
|
313
|
-
)}
|
|
314
|
-
</section>
|
|
315
|
-
` : '<section><h2>Local Dependencies</h2><div class="no-data">No local dependencies found</div></section>'}
|
|
316
|
-
|
|
317
|
-
${report.local_dev_dependencies.length > 0 ? `
|
|
318
|
-
<section>
|
|
319
|
-
<h2>Local Dev Dependencies <small>(${report.local_dev_dependencies.length})</small></h2>
|
|
320
|
-
${table2(
|
|
321
|
-
["Name", "Version", "Path"],
|
|
322
|
-
report.local_dev_dependencies.map((p) => [
|
|
323
|
-
escapeHtml(p.name),
|
|
324
|
-
escapeHtml(p.version || ""),
|
|
325
|
-
escapeHtml(p.resolved_path || "")
|
|
326
|
-
])
|
|
327
|
-
)}
|
|
328
|
-
</section>
|
|
329
|
-
` : '<section><h2>Local Dev Dependencies</h2><div class="no-data">No local dev dependencies found</div></section>'}
|
|
330
|
-
|
|
331
|
-
<footer class="footer">
|
|
332
|
-
<p>Generated by <strong>GEX v${escapeHtml(report.tool_version)}</strong> on ${new Date(report.timestamp).toLocaleString()}</p>
|
|
333
|
-
<p>Report format version: ${escapeHtml(report.report_version)}</p>
|
|
334
|
-
</footer>
|
|
335
|
-
</div>
|
|
336
|
-
</body>
|
|
337
|
-
</html>`;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// src/cli/output.ts
|
|
158
|
+
// src/shared/cli/output.ts
|
|
341
159
|
async function outputReport(report, format, outFile, markdownExtras) {
|
|
342
|
-
const content = format === "json" ? renderJson(report) :
|
|
160
|
+
const content = format === "json" ? renderJson(report) : renderMarkdown({ ...report, ...markdownExtras || {} });
|
|
343
161
|
if (outFile) {
|
|
344
162
|
const outDir = path.dirname(outFile);
|
|
345
163
|
const { mkdir, writeFile } = await import("fs/promises");
|
|
@@ -351,7 +169,7 @@ async function outputReport(report, format, outFile, markdownExtras) {
|
|
|
351
169
|
}
|
|
352
170
|
}
|
|
353
171
|
|
|
354
|
-
// src/cli/parser.ts
|
|
172
|
+
// src/shared/cli/parser.ts
|
|
355
173
|
import { readFile } from "fs/promises";
|
|
356
174
|
import path2 from "path";
|
|
357
175
|
function isMarkdownReportFile(filePath) {
|
|
@@ -400,60 +218,62 @@ async function loadReportFromFile(reportPath) {
|
|
|
400
218
|
return JSON.parse(raw);
|
|
401
219
|
}
|
|
402
220
|
|
|
403
|
-
// src/cli/
|
|
404
|
-
import {
|
|
405
|
-
import
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
const { promisify } = await import("util");
|
|
411
|
-
return promisify(execFile);
|
|
412
|
-
}
|
|
413
|
-
async function npmLs(options = {}) {
|
|
414
|
-
const args = ["ls", "--json"];
|
|
415
|
-
if (options.global) args.push("--global");
|
|
416
|
-
if (options.omitDev) args.push("--omit=dev");
|
|
417
|
-
if (options.depth0) args.push("--depth=0");
|
|
221
|
+
// src/shared/cli/utils.ts
|
|
222
|
+
import { existsSync } from "fs";
|
|
223
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
224
|
+
import path3 from "path";
|
|
225
|
+
import { fileURLToPath } from "url";
|
|
226
|
+
function getPkgJsonPath() {
|
|
227
|
+
let startDir;
|
|
418
228
|
try {
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
console.warn("npm ls stdout parse failed:", parseErr);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
229
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
230
|
+
startDir = path3.dirname(__filename);
|
|
231
|
+
} catch {
|
|
232
|
+
startDir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
233
|
+
}
|
|
234
|
+
return findPackageJson(startDir);
|
|
235
|
+
}
|
|
236
|
+
function findPackageJson(startDir) {
|
|
237
|
+
let current = startDir;
|
|
238
|
+
const maxDepth = 6;
|
|
239
|
+
for (let i = 0; i < maxDepth; i++) {
|
|
240
|
+
const candidate = path3.resolve(current, "package.json");
|
|
241
|
+
if (existsSync(candidate)) {
|
|
242
|
+
return candidate;
|
|
436
243
|
}
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
|
|
244
|
+
const parent = path3.dirname(current);
|
|
245
|
+
if (parent === current) break;
|
|
246
|
+
current = parent;
|
|
440
247
|
}
|
|
248
|
+
return path3.resolve(process.cwd(), "package.json");
|
|
441
249
|
}
|
|
442
|
-
async function
|
|
250
|
+
async function getToolVersion() {
|
|
443
251
|
try {
|
|
444
|
-
const
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
throw new Error(`npm root -g failed: ${msg}`);
|
|
252
|
+
const pkgPath = getPkgJsonPath();
|
|
253
|
+
const raw = await readFile2(pkgPath, "utf8");
|
|
254
|
+
const pkg = JSON.parse(raw);
|
|
255
|
+
return pkg.version || "0.0.0";
|
|
256
|
+
} catch {
|
|
257
|
+
return "0.0.0";
|
|
451
258
|
}
|
|
452
259
|
}
|
|
260
|
+
var ASCII_BANNER = String.raw`
|
|
261
|
+
________ __
|
|
262
|
+
/ _____/ ____ _____/ |_ ____ ____
|
|
263
|
+
/ \ ___ / _ \ / _ \ __\/ __ \ / \
|
|
264
|
+
\ \_\ ( <_> | <_> ) | \ ___/| | \
|
|
265
|
+
\______ /\____/ \____/|__| \___ >___| /
|
|
266
|
+
\/ \/ \/
|
|
267
|
+
GEX
|
|
268
|
+
`;
|
|
453
269
|
|
|
454
|
-
// src/
|
|
455
|
-
import
|
|
456
|
-
import
|
|
270
|
+
// src/runtimes/node/report.ts
|
|
271
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
272
|
+
import path5 from "path";
|
|
273
|
+
|
|
274
|
+
// src/shared/transform.ts
|
|
275
|
+
import path4 from "path";
|
|
276
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
457
277
|
function toPkgArray(obj) {
|
|
458
278
|
if (!obj) return [];
|
|
459
279
|
return Object.keys(obj).map((name) => ({ name, node: obj[name] })).filter((p) => p && p.node);
|
|
@@ -471,21 +291,30 @@ async function buildReportFromNpmTree(tree, opts) {
|
|
|
471
291
|
if (opts.context === "local") {
|
|
472
292
|
let pkgMeta = null;
|
|
473
293
|
try {
|
|
474
|
-
const pkgJsonPath =
|
|
475
|
-
const raw = await
|
|
294
|
+
const pkgJsonPath = path4.join(opts.cwd || process.cwd(), "package.json");
|
|
295
|
+
const raw = await readFile3(pkgJsonPath, "utf8");
|
|
476
296
|
pkgMeta = JSON.parse(raw);
|
|
477
297
|
} catch {
|
|
478
298
|
}
|
|
479
299
|
if (pkgMeta?.name) report.project_name = pkgMeta.name;
|
|
480
300
|
if (pkgMeta?.version) report.project_version = pkgMeta.version;
|
|
481
301
|
const depsObj = tree?.dependencies;
|
|
482
|
-
const
|
|
483
|
-
const
|
|
484
|
-
|
|
302
|
+
const devDepsObj = tree?.devDependencies;
|
|
303
|
+
const prodItems = toPkgArray(depsObj);
|
|
304
|
+
const treeDevItems = toPkgArray(devDepsObj);
|
|
305
|
+
if (treeDevItems.length > 0) {
|
|
306
|
+
for (const { name, node } of treeDevItems) {
|
|
307
|
+
const version = node && node.version || "";
|
|
308
|
+
const resolvedPath = node && node.path || path4.join(opts.cwd || process.cwd(), "node_modules", name);
|
|
309
|
+
report.local_dev_dependencies.push({ name, version, resolved_path: resolvedPath });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
const devKeys = treeDevItems.length > 0 ? new Set(treeDevItems.map((entry) => entry.name)) : new Set(Object.keys(pkgMeta?.devDependencies || {}));
|
|
313
|
+
for (const { name, node } of prodItems) {
|
|
485
314
|
const version = node && node.version || "";
|
|
486
|
-
const resolvedPath = node && node.path ||
|
|
315
|
+
const resolvedPath = node && node.path || path4.join(opts.cwd || process.cwd(), "node_modules", name);
|
|
487
316
|
const pkg = { name, version, resolved_path: resolvedPath };
|
|
488
|
-
if (devKeys.has(name)) {
|
|
317
|
+
if (!treeDevItems.length && devKeys.has(name)) {
|
|
489
318
|
report.local_dev_dependencies.push(pkg);
|
|
490
319
|
} else {
|
|
491
320
|
report.local_dependencies.push(pkg);
|
|
@@ -498,7 +327,7 @@ async function buildReportFromNpmTree(tree, opts) {
|
|
|
498
327
|
const items = toPkgArray(depsObj);
|
|
499
328
|
for (const { name, node } of items) {
|
|
500
329
|
const version = node && node.version || "";
|
|
501
|
-
const resolvedPath = node && node.path ||
|
|
330
|
+
const resolvedPath = node && node.path || path4.join(opts.globalRoot || "", name);
|
|
502
331
|
const pkg = { name, version, resolved_path: resolvedPath };
|
|
503
332
|
report.global_packages.push(pkg);
|
|
504
333
|
}
|
|
@@ -510,41 +339,54 @@ async function buildReportFromNpmTree(tree, opts) {
|
|
|
510
339
|
return report;
|
|
511
340
|
}
|
|
512
341
|
|
|
513
|
-
// src/
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
342
|
+
// src/runtimes/node/package-manager.ts
|
|
343
|
+
async function getExecFileAsync2() {
|
|
344
|
+
const { execFile } = await import("child_process");
|
|
345
|
+
const { promisify } = await import("util");
|
|
346
|
+
return promisify(execFile);
|
|
347
|
+
}
|
|
348
|
+
async function npmLs(options = {}) {
|
|
349
|
+
const args = ["ls", "--json"];
|
|
350
|
+
if (options.global) args.push("--global");
|
|
351
|
+
if (options.omitDev) args.push("--omit=dev");
|
|
352
|
+
if (options.depth0) args.push("--depth=0");
|
|
518
353
|
try {
|
|
519
|
-
const
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
354
|
+
const execFileAsync = await getExecFileAsync2();
|
|
355
|
+
const { stdout } = await execFileAsync("npm", args, {
|
|
356
|
+
cwd: options.cwd,
|
|
357
|
+
maxBuffer: 10 * 1024 * 1024
|
|
358
|
+
});
|
|
359
|
+
if (stdout && stdout.trim()) return JSON.parse(stdout);
|
|
360
|
+
return {};
|
|
361
|
+
} catch (err) {
|
|
362
|
+
const stdout = err?.stdout;
|
|
363
|
+
if (typeof stdout === "string" && stdout.trim()) {
|
|
364
|
+
try {
|
|
365
|
+
return JSON.parse(stdout);
|
|
366
|
+
} catch (parseErr) {
|
|
367
|
+
if (process.env.DEBUG?.includes("gex")) {
|
|
368
|
+
console.warn("npm ls stdout parse failed:", parseErr);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
const stderr = err?.stderr;
|
|
373
|
+
const msg = typeof stderr === "string" && stderr.trim() || err?.message || "npm ls failed";
|
|
374
|
+
throw new Error(`npm ls failed: ${msg}`);
|
|
525
375
|
}
|
|
526
376
|
}
|
|
527
|
-
async function
|
|
377
|
+
async function npmRootGlobal() {
|
|
528
378
|
try {
|
|
529
|
-
const
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
379
|
+
const execFileAsync = await getExecFileAsync2();
|
|
380
|
+
const { stdout } = await execFileAsync("npm", ["root", "-g"]);
|
|
381
|
+
return stdout.trim();
|
|
382
|
+
} catch (err) {
|
|
383
|
+
const stderr = err?.stderr;
|
|
384
|
+
const msg = typeof stderr === "string" && stderr.trim() || err?.message || "npm root -g failed";
|
|
385
|
+
throw new Error(`npm root -g failed: ${msg}`);
|
|
535
386
|
}
|
|
536
387
|
}
|
|
537
|
-
var ASCII_BANNER = String.raw`
|
|
538
|
-
________ __
|
|
539
|
-
/ _____/ ____ _____/ |_ ____ ____
|
|
540
|
-
/ \ ___ / _ \ / _ \ __\/ __ \ / \
|
|
541
|
-
\ \_\ ( <_> | <_> ) | \ ___/| | \
|
|
542
|
-
\______ /\____/ \____/|__| \___ >___| /
|
|
543
|
-
\/ \/ \/
|
|
544
|
-
GEX
|
|
545
|
-
`;
|
|
546
388
|
|
|
547
|
-
// src/
|
|
389
|
+
// src/runtimes/node/report.ts
|
|
548
390
|
async function produceReport(ctx, options) {
|
|
549
391
|
const toolVersion = await getToolVersion();
|
|
550
392
|
const depth0 = !options.fullTree;
|
|
@@ -582,16 +424,12 @@ async function produceReport(ctx, options) {
|
|
|
582
424
|
return { report, markdownExtras };
|
|
583
425
|
}
|
|
584
426
|
|
|
585
|
-
// src/
|
|
427
|
+
// src/runtimes/node/commands.ts
|
|
586
428
|
function addCommonOptions(cmd, { allowOmitDev }) {
|
|
587
429
|
cmd.option(
|
|
588
430
|
"-f, --output-format <format>",
|
|
589
|
-
"Output format:
|
|
590
|
-
(val) =>
|
|
591
|
-
if (val === "md") return "md";
|
|
592
|
-
if (val === "html") return "html";
|
|
593
|
-
return "json";
|
|
594
|
-
},
|
|
431
|
+
"Output format: md or json",
|
|
432
|
+
(val) => val === "md" ? "md" : "json",
|
|
595
433
|
"json"
|
|
596
434
|
).option("-o, --out-file <path>", "Write report to file").option("--full-tree", "Include full npm ls tree (omit depth=0 default)", false);
|
|
597
435
|
if (allowOmitDev) {
|
|
@@ -650,7 +488,7 @@ function createReadCommand(program) {
|
|
|
650
488
|
printFromReport(parsed);
|
|
651
489
|
}
|
|
652
490
|
if (doInstall) {
|
|
653
|
-
await installFromReport(parsed, process.cwd());
|
|
491
|
+
await installFromReport(parsed, { cwd: process.cwd(), packageManager: "npm" });
|
|
654
492
|
}
|
|
655
493
|
} catch (err) {
|
|
656
494
|
const isMd = isMarkdownReportFile(reportPath);
|
|
@@ -672,7 +510,7 @@ ${ASCII_BANNER}`);
|
|
|
672
510
|
return program;
|
|
673
511
|
}
|
|
674
512
|
|
|
675
|
-
// src/cli.ts
|
|
513
|
+
// src/runtimes/node/cli.ts
|
|
676
514
|
async function run(argv = process.argv) {
|
|
677
515
|
const program = await createProgram();
|
|
678
516
|
await program.parseAsync(argv);
|
|
@@ -696,7 +534,31 @@ if (isMainModule) {
|
|
|
696
534
|
process.exitCode = 1;
|
|
697
535
|
});
|
|
698
536
|
}
|
|
537
|
+
|
|
538
|
+
// src/cli.ts
|
|
539
|
+
async function run2(argv = process.argv) {
|
|
540
|
+
return run(argv);
|
|
541
|
+
}
|
|
542
|
+
var isMainModule2 = (() => {
|
|
543
|
+
try {
|
|
544
|
+
if (typeof __require !== "undefined" && typeof module !== "undefined") {
|
|
545
|
+
return __require.main === module;
|
|
546
|
+
}
|
|
547
|
+
if (typeof import.meta !== "undefined") {
|
|
548
|
+
return import.meta.url === `file://${process.argv[1]}`;
|
|
549
|
+
}
|
|
550
|
+
return false;
|
|
551
|
+
} catch {
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
})();
|
|
555
|
+
if (isMainModule2) {
|
|
556
|
+
run2().catch((error) => {
|
|
557
|
+
console.error("CLI error:", error);
|
|
558
|
+
process.exitCode = 1;
|
|
559
|
+
});
|
|
560
|
+
}
|
|
699
561
|
export {
|
|
700
|
-
run
|
|
562
|
+
run2 as run
|
|
701
563
|
};
|
|
702
564
|
//# sourceMappingURL=cli.mjs.map
|