@yabasha/gex 0.3.2 → 0.4.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/README.md +16 -5
- package/dist/cli.cjs +281 -221
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +279 -222
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +410 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +189 -4
- package/dist/index.d.ts +189 -4
- package/dist/index.mjs +393 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -55,15 +55,20 @@ Common options:
|
|
|
55
55
|
Examples:
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
# Local (default): JSON
|
|
59
|
-
gex # same as: gex local
|
|
60
|
-
gex -
|
|
58
|
+
# Local (default): JSON output to console
|
|
59
|
+
gex # prints JSON to console (same as: gex local)
|
|
60
|
+
gex -o report.json # writes JSON to file
|
|
61
|
+
gex -f md # prints markdown to console
|
|
62
|
+
gex -f md -o report.md # writes markdown to file
|
|
61
63
|
|
|
62
64
|
# Local: exclude devDependencies
|
|
63
|
-
gex local --omit-dev
|
|
65
|
+
gex local --omit-dev # prints JSON to console
|
|
66
|
+
gex local --omit-dev -o deps.json # writes JSON to file
|
|
64
67
|
|
|
65
68
|
# Global packages
|
|
66
|
-
gex global
|
|
69
|
+
gex global # prints JSON to console
|
|
70
|
+
gex global -o global.json # writes JSON to file
|
|
71
|
+
gex global -f md # prints markdown to console
|
|
67
72
|
|
|
68
73
|
# Read a previous report (JSON or Markdown)
|
|
69
74
|
# Default prints names@versions; add -i to install
|
|
@@ -74,8 +79,14 @@ gex read -r path/to/report.json -i
|
|
|
74
79
|
# Markdown
|
|
75
80
|
gex read global.md
|
|
76
81
|
gex read global.md -i
|
|
82
|
+
|
|
83
|
+
# Shell redirection (alternative to -o flag)
|
|
84
|
+
gex > report.json # redirect JSON output to file
|
|
85
|
+
gex global | jq '.global_packages' # pipe output to jq for processing
|
|
77
86
|
```
|
|
78
87
|
|
|
88
|
+
> **Note**: Starting from v0.4.0, GEX outputs to console by default instead of creating files automatically. Use the `-o/--out-file` flag to write to a file.
|
|
89
|
+
|
|
79
90
|
## JSON schema (summary)
|
|
80
91
|
|
|
81
92
|
Top-level keys:
|
package/dist/cli.cjs
CHANGED
|
@@ -34,23 +34,216 @@ __export(cli_exports, {
|
|
|
34
34
|
run: () => run
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(cli_exports);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
var
|
|
40
|
-
var import_node_child_process2 = require("child_process");
|
|
41
|
-
var import_node_util2 = require("util");
|
|
37
|
+
|
|
38
|
+
// src/cli/commands.ts
|
|
39
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
42
40
|
var import_commander = require("commander");
|
|
43
41
|
|
|
42
|
+
// src/cli/install.ts
|
|
43
|
+
async function getExecFileAsync() {
|
|
44
|
+
const { execFile } = await import("child_process");
|
|
45
|
+
const { promisify } = await import("util");
|
|
46
|
+
return promisify(execFile);
|
|
47
|
+
}
|
|
48
|
+
async function installFromReport(report, cwd) {
|
|
49
|
+
const globalPkgs = report.global_packages.map((p) => `${p.name}@${p.version}`).filter(Boolean);
|
|
50
|
+
const localPkgs = report.local_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean);
|
|
51
|
+
const devPkgs = report.local_dev_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean);
|
|
52
|
+
if (globalPkgs.length === 0 && localPkgs.length === 0 && devPkgs.length === 0) {
|
|
53
|
+
console.log("No packages to install from report.");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const execFileAsync = await getExecFileAsync();
|
|
57
|
+
if (globalPkgs.length > 0) {
|
|
58
|
+
console.log(`Installing global: ${globalPkgs.join(" ")}`);
|
|
59
|
+
await execFileAsync("npm", ["i", "-g", ...globalPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 });
|
|
60
|
+
}
|
|
61
|
+
if (localPkgs.length > 0) {
|
|
62
|
+
console.log(`Installing local deps: ${localPkgs.join(" ")}`);
|
|
63
|
+
await execFileAsync("npm", ["i", ...localPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 });
|
|
64
|
+
}
|
|
65
|
+
if (devPkgs.length > 0) {
|
|
66
|
+
console.log(`Installing local devDeps: ${devPkgs.join(" ")}`);
|
|
67
|
+
await execFileAsync("npm", ["i", "-D", ...devPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function printFromReport(report) {
|
|
71
|
+
const lines = [];
|
|
72
|
+
if (report.global_packages.length > 0) {
|
|
73
|
+
lines.push("Global Packages:");
|
|
74
|
+
for (const p of report.global_packages) {
|
|
75
|
+
lines.push(`- ${p.name}@${p.version}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (report.local_dependencies.length > 0) {
|
|
79
|
+
if (lines.length) lines.push("");
|
|
80
|
+
lines.push("Local Dependencies:");
|
|
81
|
+
for (const p of report.local_dependencies) {
|
|
82
|
+
lines.push(`- ${p.name}@${p.version}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (report.local_dev_dependencies.length > 0) {
|
|
86
|
+
if (lines.length) lines.push("");
|
|
87
|
+
lines.push("Local Dev Dependencies:");
|
|
88
|
+
for (const p of report.local_dev_dependencies) {
|
|
89
|
+
lines.push(`- ${p.name}@${p.version}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (lines.length === 0) {
|
|
93
|
+
lines.push("(no packages found in report)");
|
|
94
|
+
}
|
|
95
|
+
console.log(lines.join("\n"));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/cli/output.ts
|
|
99
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
100
|
+
|
|
101
|
+
// src/report/json.ts
|
|
102
|
+
function renderJson(report) {
|
|
103
|
+
const r = {
|
|
104
|
+
...report,
|
|
105
|
+
global_packages: [...report.global_packages].sort((a, b) => a.name.localeCompare(b.name)),
|
|
106
|
+
local_dependencies: [...report.local_dependencies].sort((a, b) => a.name.localeCompare(b.name)),
|
|
107
|
+
local_dev_dependencies: [...report.local_dev_dependencies].sort(
|
|
108
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
109
|
+
)
|
|
110
|
+
};
|
|
111
|
+
return JSON.stringify(r, null, 2);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/report/md.ts
|
|
115
|
+
function table(headers, rows) {
|
|
116
|
+
const header = `| ${headers.join(" | ")} |`;
|
|
117
|
+
const sep = `| ${headers.map(() => "---").join(" | ")} |`;
|
|
118
|
+
const body = rows.map((r) => `| ${r.join(" | ")} |`).join("\n");
|
|
119
|
+
return [header, sep, body].filter(Boolean).join("\n");
|
|
120
|
+
}
|
|
121
|
+
function renderMarkdown(report) {
|
|
122
|
+
const lines = [];
|
|
123
|
+
lines.push("# GEX Report");
|
|
124
|
+
lines.push("");
|
|
125
|
+
if (report.project_name || report.project_version || report.project_description || report.project_homepage || report.project_bugs) {
|
|
126
|
+
lines.push("## Project Metadata");
|
|
127
|
+
if (report.project_name) lines.push(`- Name: ${report.project_name}`);
|
|
128
|
+
if (report.project_version) lines.push(`- Version: ${report.project_version}`);
|
|
129
|
+
if (report.project_description)
|
|
130
|
+
lines.push(`- Description: ${report.project_description}`);
|
|
131
|
+
if (report.project_homepage)
|
|
132
|
+
lines.push(`- Homepage: ${report.project_homepage}`);
|
|
133
|
+
if (report.project_bugs) lines.push(`- Bugs: ${report.project_bugs}`);
|
|
134
|
+
lines.push("");
|
|
135
|
+
}
|
|
136
|
+
if (report.global_packages.length > 0) {
|
|
137
|
+
lines.push("## Global Packages");
|
|
138
|
+
const rows = report.global_packages.map((p) => [p.name, p.version || "", p.resolved_path || ""]);
|
|
139
|
+
lines.push(table(["Name", "Version", "Path"], rows));
|
|
140
|
+
lines.push("");
|
|
141
|
+
}
|
|
142
|
+
if (report.local_dependencies.length > 0) {
|
|
143
|
+
lines.push("## Local Dependencies");
|
|
144
|
+
const rows = report.local_dependencies.map((p) => [
|
|
145
|
+
p.name,
|
|
146
|
+
p.version || "",
|
|
147
|
+
p.resolved_path || ""
|
|
148
|
+
]);
|
|
149
|
+
lines.push(table(["Name", "Version", "Path"], rows));
|
|
150
|
+
lines.push("");
|
|
151
|
+
}
|
|
152
|
+
if (report.local_dev_dependencies.length > 0) {
|
|
153
|
+
lines.push("## Local Dev Dependencies");
|
|
154
|
+
const rows = report.local_dev_dependencies.map((p) => [
|
|
155
|
+
p.name,
|
|
156
|
+
p.version || "",
|
|
157
|
+
p.resolved_path || ""
|
|
158
|
+
]);
|
|
159
|
+
lines.push(table(["Name", "Version", "Path"], rows));
|
|
160
|
+
lines.push("");
|
|
161
|
+
}
|
|
162
|
+
lines.push("---");
|
|
163
|
+
lines.push("_Generated by GEX_");
|
|
164
|
+
return lines.join("\n");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/cli/output.ts
|
|
168
|
+
async function outputReport(report, format, outFile, markdownExtras) {
|
|
169
|
+
const content = format === "json" ? renderJson(report) : renderMarkdown({ ...report, ...markdownExtras || {} });
|
|
170
|
+
if (outFile) {
|
|
171
|
+
const outDir = import_node_path.default.dirname(outFile);
|
|
172
|
+
const { mkdir, writeFile } = await import("fs/promises");
|
|
173
|
+
await mkdir(outDir, { recursive: true });
|
|
174
|
+
await writeFile(outFile, content, "utf8");
|
|
175
|
+
console.log(`Wrote report to ${outFile}`);
|
|
176
|
+
} else {
|
|
177
|
+
console.log(content);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/cli/parser.ts
|
|
182
|
+
var import_promises = require("fs/promises");
|
|
183
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
184
|
+
function isMarkdownReportFile(filePath) {
|
|
185
|
+
const ext = import_node_path2.default.extname(filePath).toLowerCase();
|
|
186
|
+
return ext === ".md" || ext === ".markdown";
|
|
187
|
+
}
|
|
188
|
+
function parseMarkdownPackagesTable(lines, startIndex) {
|
|
189
|
+
const rows = [];
|
|
190
|
+
if (!lines[startIndex] || !lines[startIndex].trim().startsWith("|")) return rows;
|
|
191
|
+
let i = startIndex + 2;
|
|
192
|
+
while (i < lines.length && lines[i].trim().startsWith("|")) {
|
|
193
|
+
const cols = lines[i].split("|").map((c) => c.trim()).filter((_, idx, arr) => !(idx === 0 || idx === arr.length - 1));
|
|
194
|
+
const [name = "", version = "", resolved_path = ""] = cols;
|
|
195
|
+
if (name) rows.push({ name, version, resolved_path });
|
|
196
|
+
i++;
|
|
197
|
+
}
|
|
198
|
+
return rows;
|
|
199
|
+
}
|
|
200
|
+
function parseMarkdownReport(md) {
|
|
201
|
+
const lines = md.split(/\r?\n/);
|
|
202
|
+
const findSection = (title) => lines.findIndex((l) => l.trim().toLowerCase() === `## ${title}`.toLowerCase());
|
|
203
|
+
const parseSection = (idx) => {
|
|
204
|
+
if (idx < 0) return [];
|
|
205
|
+
let i = idx + 1;
|
|
206
|
+
while (i < lines.length && !lines[i].trim().startsWith("|")) i++;
|
|
207
|
+
return parseMarkdownPackagesTable(lines, i);
|
|
208
|
+
};
|
|
209
|
+
const global_packages = parseSection(findSection("Global Packages"));
|
|
210
|
+
const local_dependencies = parseSection(findSection("Local Dependencies"));
|
|
211
|
+
const local_dev_dependencies = parseSection(findSection("Local Dev Dependencies"));
|
|
212
|
+
const report = {
|
|
213
|
+
report_version: "1.0",
|
|
214
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
215
|
+
tool_version: "unknown",
|
|
216
|
+
global_packages,
|
|
217
|
+
local_dependencies,
|
|
218
|
+
local_dev_dependencies
|
|
219
|
+
};
|
|
220
|
+
return report;
|
|
221
|
+
}
|
|
222
|
+
async function loadReportFromFile(reportPath) {
|
|
223
|
+
const raw = await (0, import_promises.readFile)(reportPath, "utf8");
|
|
224
|
+
if (isMarkdownReportFile(reportPath) || raw.startsWith("# GEX Report")) {
|
|
225
|
+
return parseMarkdownReport(raw);
|
|
226
|
+
}
|
|
227
|
+
return JSON.parse(raw);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/cli/report.ts
|
|
231
|
+
var import_promises4 = require("fs/promises");
|
|
232
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
233
|
+
|
|
44
234
|
// src/npm.ts
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
235
|
+
async function getExecFileAsync2() {
|
|
236
|
+
const { execFile } = await import("child_process");
|
|
237
|
+
const { promisify } = await import("util");
|
|
238
|
+
return promisify(execFile);
|
|
239
|
+
}
|
|
48
240
|
async function npmLs(options = {}) {
|
|
49
241
|
const args = ["ls", "--json"];
|
|
50
242
|
if (options.global) args.push("--global");
|
|
51
243
|
if (options.omitDev) args.push("--omit=dev");
|
|
52
244
|
if (options.depth0) args.push("--depth=0");
|
|
53
245
|
try {
|
|
246
|
+
const execFileAsync = await getExecFileAsync2();
|
|
54
247
|
const { stdout } = await execFileAsync("npm", args, {
|
|
55
248
|
cwd: options.cwd,
|
|
56
249
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -62,7 +255,10 @@ async function npmLs(options = {}) {
|
|
|
62
255
|
if (typeof stdout === "string" && stdout.trim()) {
|
|
63
256
|
try {
|
|
64
257
|
return JSON.parse(stdout);
|
|
65
|
-
} catch {
|
|
258
|
+
} catch (parseErr) {
|
|
259
|
+
if (process.env.DEBUG?.includes("gex")) {
|
|
260
|
+
console.warn("npm ls stdout parse failed:", parseErr);
|
|
261
|
+
}
|
|
66
262
|
}
|
|
67
263
|
}
|
|
68
264
|
const stderr = err?.stderr;
|
|
@@ -72,6 +268,7 @@ async function npmLs(options = {}) {
|
|
|
72
268
|
}
|
|
73
269
|
async function npmRootGlobal() {
|
|
74
270
|
try {
|
|
271
|
+
const execFileAsync = await getExecFileAsync2();
|
|
75
272
|
const { stdout } = await execFileAsync("npm", ["root", "-g"]);
|
|
76
273
|
return stdout.trim();
|
|
77
274
|
} catch (err) {
|
|
@@ -82,8 +279,8 @@ async function npmRootGlobal() {
|
|
|
82
279
|
}
|
|
83
280
|
|
|
84
281
|
// src/transform.ts
|
|
85
|
-
var
|
|
86
|
-
var
|
|
282
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
283
|
+
var import_promises2 = require("fs/promises");
|
|
87
284
|
function toPkgArray(obj) {
|
|
88
285
|
if (!obj) return [];
|
|
89
286
|
return Object.keys(obj).map((name) => ({ name, node: obj[name] })).filter((p) => p && p.node);
|
|
@@ -101,8 +298,8 @@ async function buildReportFromNpmTree(tree, opts) {
|
|
|
101
298
|
if (opts.context === "local") {
|
|
102
299
|
let pkgMeta = null;
|
|
103
300
|
try {
|
|
104
|
-
const pkgJsonPath =
|
|
105
|
-
const raw = await (0,
|
|
301
|
+
const pkgJsonPath = import_node_path3.default.join(opts.cwd || process.cwd(), "package.json");
|
|
302
|
+
const raw = await (0, import_promises2.readFile)(pkgJsonPath, "utf8");
|
|
106
303
|
pkgMeta = JSON.parse(raw);
|
|
107
304
|
} catch {
|
|
108
305
|
}
|
|
@@ -113,7 +310,7 @@ async function buildReportFromNpmTree(tree, opts) {
|
|
|
113
310
|
const devKeys = new Set(Object.keys(pkgMeta?.devDependencies || {}));
|
|
114
311
|
for (const { name, node } of items) {
|
|
115
312
|
const version = node && node.version || "";
|
|
116
|
-
const resolvedPath = node && node.path ||
|
|
313
|
+
const resolvedPath = node && node.path || import_node_path3.default.join(opts.cwd || process.cwd(), "node_modules", name);
|
|
117
314
|
const pkg = { name, version, resolved_path: resolvedPath };
|
|
118
315
|
if (devKeys.has(name)) {
|
|
119
316
|
report.local_dev_dependencies.push(pkg);
|
|
@@ -128,7 +325,7 @@ async function buildReportFromNpmTree(tree, opts) {
|
|
|
128
325
|
const items = toPkgArray(depsObj);
|
|
129
326
|
for (const { name, node } of items) {
|
|
130
327
|
const version = node && node.version || "";
|
|
131
|
-
const resolvedPath = node && node.path ||
|
|
328
|
+
const resolvedPath = node && node.path || import_node_path3.default.join(opts.globalRoot || "", name);
|
|
132
329
|
const pkg = { name, version, resolved_path: resolvedPath };
|
|
133
330
|
report.global_packages.push(pkg);
|
|
134
331
|
}
|
|
@@ -140,104 +337,42 @@ async function buildReportFromNpmTree(tree, opts) {
|
|
|
140
337
|
return report;
|
|
141
338
|
}
|
|
142
339
|
|
|
143
|
-
// src/
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
global_packages: [...report.global_packages].sort((a, b) => a.name.localeCompare(b.name)),
|
|
148
|
-
local_dependencies: [...report.local_dependencies].sort((a, b) => a.name.localeCompare(b.name)),
|
|
149
|
-
local_dev_dependencies: [...report.local_dev_dependencies].sort(
|
|
150
|
-
(a, b) => a.name.localeCompare(b.name)
|
|
151
|
-
)
|
|
152
|
-
};
|
|
153
|
-
return JSON.stringify(r, null, 2);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// src/report/md.ts
|
|
157
|
-
function table(headers, rows) {
|
|
158
|
-
const header = `| ${headers.join(" | ")} |`;
|
|
159
|
-
const sep = `| ${headers.map(() => "---").join(" | ")} |`;
|
|
160
|
-
const body = rows.map((r) => `| ${r.join(" | ")} |`).join("\n");
|
|
161
|
-
return [header, sep, body].filter(Boolean).join("\n");
|
|
162
|
-
}
|
|
163
|
-
function renderMarkdown(report) {
|
|
164
|
-
const lines = [];
|
|
165
|
-
lines.push("# GEX Report");
|
|
166
|
-
lines.push("");
|
|
167
|
-
if (report.project_name || report.project_version) {
|
|
168
|
-
lines.push("## Project Metadata");
|
|
169
|
-
if (report.project_name) lines.push(`- Name: ${report.project_name}`);
|
|
170
|
-
if (report.project_version) lines.push(`- Version: ${report.project_version}`);
|
|
171
|
-
if (report.project_description)
|
|
172
|
-
lines.push(`- Description: ${report.project_description}`);
|
|
173
|
-
if (report.project_homepage)
|
|
174
|
-
lines.push(`- Homepage: ${report.project_homepage}`);
|
|
175
|
-
if (report.project_bugs) lines.push(`- Bugs: ${report.project_bugs}`);
|
|
176
|
-
lines.push("");
|
|
177
|
-
}
|
|
178
|
-
if (report.global_packages.length > 0) {
|
|
179
|
-
lines.push("## Global Packages");
|
|
180
|
-
const rows = report.global_packages.map((p) => [p.name, p.version || "", p.resolved_path || ""]);
|
|
181
|
-
lines.push(table(["Name", "Version", "Path"], rows));
|
|
182
|
-
lines.push("");
|
|
183
|
-
}
|
|
184
|
-
if (report.local_dependencies.length > 0) {
|
|
185
|
-
lines.push("## Local Dependencies");
|
|
186
|
-
const rows = report.local_dependencies.map((p) => [
|
|
187
|
-
p.name,
|
|
188
|
-
p.version || "",
|
|
189
|
-
p.resolved_path || ""
|
|
190
|
-
]);
|
|
191
|
-
lines.push(table(["Name", "Version", "Path"], rows));
|
|
192
|
-
lines.push("");
|
|
193
|
-
}
|
|
194
|
-
if (report.local_dev_dependencies.length > 0) {
|
|
195
|
-
lines.push("## Local Dev Dependencies");
|
|
196
|
-
const rows = report.local_dev_dependencies.map((p) => [
|
|
197
|
-
p.name,
|
|
198
|
-
p.version || "",
|
|
199
|
-
p.resolved_path || ""
|
|
200
|
-
]);
|
|
201
|
-
lines.push(table(["Name", "Version", "Path"], rows));
|
|
202
|
-
lines.push("");
|
|
203
|
-
}
|
|
204
|
-
lines.push("---");
|
|
205
|
-
lines.push("_Generated by GEX_");
|
|
206
|
-
return lines.join("\n");
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// src/cli.ts
|
|
340
|
+
// src/cli/utils.ts
|
|
341
|
+
var import_promises3 = require("fs/promises");
|
|
342
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
343
|
+
var import_node_url = require("url");
|
|
210
344
|
var import_meta = {};
|
|
211
345
|
function getPkgJsonPath() {
|
|
212
346
|
try {
|
|
213
347
|
const __filename = (0, import_node_url.fileURLToPath)(import_meta.url);
|
|
214
|
-
const __dirnameLocal =
|
|
215
|
-
return
|
|
348
|
+
const __dirnameLocal = import_node_path4.default.dirname(__filename);
|
|
349
|
+
return import_node_path4.default.resolve(__dirnameLocal, "..", "..", "package.json");
|
|
216
350
|
} catch {
|
|
217
351
|
const dir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
218
|
-
return
|
|
352
|
+
return import_node_path4.default.resolve(dir, "..", "package.json");
|
|
219
353
|
}
|
|
220
354
|
}
|
|
221
355
|
async function getToolVersion() {
|
|
222
356
|
try {
|
|
223
357
|
const pkgPath = getPkgJsonPath();
|
|
224
|
-
const raw = await (0,
|
|
358
|
+
const raw = await (0, import_promises3.readFile)(pkgPath, "utf8");
|
|
225
359
|
const pkg = JSON.parse(raw);
|
|
226
360
|
return pkg.version || "0.0.0";
|
|
227
361
|
} catch {
|
|
228
362
|
return "0.0.0";
|
|
229
363
|
}
|
|
230
364
|
}
|
|
231
|
-
var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
|
|
232
365
|
var ASCII_BANNER = String.raw`
|
|
233
366
|
________ __
|
|
234
|
-
/ _____/ ____ _____/ |_ ____ ____
|
|
367
|
+
/ _____/ ____ _____/ |_ ____ ____
|
|
235
368
|
/ \ ___ / _ \ / _ \ __\/ __ \ / \
|
|
236
369
|
\ \_\ ( <_> | <_> ) | \ ___/| | \
|
|
237
370
|
\______ /\____/ \____/|__| \___ >___| /
|
|
238
|
-
\/ \/ \/
|
|
371
|
+
\/ \/ \/
|
|
239
372
|
GEX
|
|
240
373
|
`;
|
|
374
|
+
|
|
375
|
+
// src/cli/report.ts
|
|
241
376
|
async function produceReport(ctx, options) {
|
|
242
377
|
const toolVersion = await getToolVersion();
|
|
243
378
|
const depth0 = !options.fullTree;
|
|
@@ -253,7 +388,7 @@ async function produceReport(ctx, options) {
|
|
|
253
388
|
let project_bugs;
|
|
254
389
|
if (ctx === "local") {
|
|
255
390
|
try {
|
|
256
|
-
const pkgRaw = await (0,
|
|
391
|
+
const pkgRaw = await (0, import_promises4.readFile)(import_node_path5.default.join(cwd, "package.json"), "utf8");
|
|
257
392
|
const pkg = JSON.parse(pkgRaw);
|
|
258
393
|
project_description = pkg.description;
|
|
259
394
|
project_homepage = pkg.homepage;
|
|
@@ -274,126 +409,21 @@ async function produceReport(ctx, options) {
|
|
|
274
409
|
const markdownExtras = { project_description, project_homepage, project_bugs };
|
|
275
410
|
return { report, markdownExtras };
|
|
276
411
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
for (const p of report.local_dependencies) {
|
|
289
|
-
lines.push(`- ${p.name}@${p.version}`);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
if (report.local_dev_dependencies.length > 0) {
|
|
293
|
-
if (lines.length) lines.push("");
|
|
294
|
-
lines.push("Local Dev Dependencies:");
|
|
295
|
-
for (const p of report.local_dev_dependencies) {
|
|
296
|
-
lines.push(`- ${p.name}@${p.version}`);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
if (lines.length === 0) {
|
|
300
|
-
lines.push("(no packages found in report)");
|
|
301
|
-
}
|
|
302
|
-
console.log(lines.join("\n"));
|
|
303
|
-
}
|
|
304
|
-
async function installFromReport(report, cwd) {
|
|
305
|
-
const globalPkgs = report.global_packages.map((p) => `${p.name}@${p.version}`).filter(Boolean);
|
|
306
|
-
const localPkgs = report.local_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean);
|
|
307
|
-
const devPkgs = report.local_dev_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean);
|
|
308
|
-
if (globalPkgs.length === 0 && localPkgs.length === 0 && devPkgs.length === 0) {
|
|
309
|
-
console.log("No packages to install from report.");
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
if (globalPkgs.length > 0) {
|
|
313
|
-
console.log(`Installing global: ${globalPkgs.join(" ")}`);
|
|
314
|
-
await execFileAsync2("npm", ["i", "-g", ...globalPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 });
|
|
315
|
-
}
|
|
316
|
-
if (localPkgs.length > 0) {
|
|
317
|
-
console.log(`Installing local deps: ${localPkgs.join(" ")}`);
|
|
318
|
-
await execFileAsync2("npm", ["i", ...localPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 });
|
|
319
|
-
}
|
|
320
|
-
if (devPkgs.length > 0) {
|
|
321
|
-
console.log(`Installing local devDeps: ${devPkgs.join(" ")}`);
|
|
322
|
-
await execFileAsync2("npm", ["i", "-D", ...devPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 });
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
async function outputReport(report, format, outFile, markdownExtras) {
|
|
326
|
-
const content = format === "json" ? renderJson(report) : renderMarkdown({ ...report, ...markdownExtras || {} });
|
|
327
|
-
if (outFile) {
|
|
328
|
-
const outDir = import_node_path2.default.dirname(outFile);
|
|
329
|
-
await (await import("fs/promises")).mkdir(outDir, { recursive: true });
|
|
330
|
-
await (await import("fs/promises")).writeFile(outFile, content, "utf8");
|
|
331
|
-
console.log(`Wrote report to ${outFile}`);
|
|
332
|
-
} else {
|
|
333
|
-
console.log(content);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
function isMarkdownReportFile(filePath) {
|
|
337
|
-
const ext = import_node_path2.default.extname(filePath).toLowerCase();
|
|
338
|
-
return ext === ".md" || ext === ".markdown";
|
|
339
|
-
}
|
|
340
|
-
function parseMarkdownPackagesTable(lines, startIndex) {
|
|
341
|
-
const rows = [];
|
|
342
|
-
if (!lines[startIndex] || !lines[startIndex].trim().startsWith("|")) return rows;
|
|
343
|
-
let i = startIndex + 2;
|
|
344
|
-
while (i < lines.length && lines[i].trim().startsWith("|")) {
|
|
345
|
-
const cols = lines[i].split("|").map((c) => c.trim()).filter((_, idx, arr) => !(idx === 0 || idx === arr.length - 1));
|
|
346
|
-
const [name = "", version = "", resolved_path = ""] = cols;
|
|
347
|
-
if (name) rows.push({ name, version, resolved_path });
|
|
348
|
-
i++;
|
|
349
|
-
}
|
|
350
|
-
return rows;
|
|
351
|
-
}
|
|
352
|
-
function parseMarkdownReport(md) {
|
|
353
|
-
const lines = md.split(/\r?\n/);
|
|
354
|
-
const findSection = (title) => lines.findIndex((l) => l.trim().toLowerCase() === `## ${title}`.toLowerCase());
|
|
355
|
-
const parseSection = (idx) => {
|
|
356
|
-
if (idx < 0) return [];
|
|
357
|
-
let i = idx + 1;
|
|
358
|
-
while (i < lines.length && !lines[i].trim().startsWith("|")) i++;
|
|
359
|
-
return parseMarkdownPackagesTable(lines, i);
|
|
360
|
-
};
|
|
361
|
-
const global_packages = parseSection(findSection("Global Packages"));
|
|
362
|
-
const local_dependencies = parseSection(findSection("Local Dependencies"));
|
|
363
|
-
const local_dev_dependencies = parseSection(findSection("Local Dev Dependencies"));
|
|
364
|
-
const report = {
|
|
365
|
-
report_version: "1.0",
|
|
366
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
367
|
-
tool_version: "unknown",
|
|
368
|
-
global_packages,
|
|
369
|
-
local_dependencies,
|
|
370
|
-
local_dev_dependencies
|
|
371
|
-
};
|
|
372
|
-
return report;
|
|
373
|
-
}
|
|
374
|
-
async function loadReportFromFile(reportPath) {
|
|
375
|
-
const raw = await (0, import_promises2.readFile)(reportPath, "utf8");
|
|
376
|
-
if (isMarkdownReportFile(reportPath) || raw.startsWith("# GEX Report")) {
|
|
377
|
-
return parseMarkdownReport(raw);
|
|
412
|
+
|
|
413
|
+
// src/cli/commands.ts
|
|
414
|
+
function addCommonOptions(cmd, { allowOmitDev }) {
|
|
415
|
+
cmd.option(
|
|
416
|
+
"-f, --output-format <format>",
|
|
417
|
+
"Output format: md or json",
|
|
418
|
+
(val) => val === "md" ? "md" : "json",
|
|
419
|
+
"json"
|
|
420
|
+
).option("-o, --out-file <path>", "Write report to file").option("--full-tree", "Include full npm ls tree (omit depth=0 default)", false);
|
|
421
|
+
if (allowOmitDev) {
|
|
422
|
+
cmd.option("--omit-dev", "Exclude devDependencies (local only)", false);
|
|
378
423
|
}
|
|
379
|
-
return
|
|
424
|
+
return cmd;
|
|
380
425
|
}
|
|
381
|
-
|
|
382
|
-
const program = new import_commander.Command().name("gex").description("GEX: Dependency auditing and documentation for Node.js (local and global).").version(await getToolVersion());
|
|
383
|
-
program.addHelpText("beforeAll", `
|
|
384
|
-
${ASCII_BANNER}`);
|
|
385
|
-
const addCommonOptions = (cmd, { allowOmitDev }) => {
|
|
386
|
-
cmd.option(
|
|
387
|
-
"-f, --output-format <format>",
|
|
388
|
-
"Output format: md or json",
|
|
389
|
-
(val) => val === "md" ? "md" : "json",
|
|
390
|
-
"json"
|
|
391
|
-
).option("-o, --out-file <path>", "Write report to file").option("--full-tree", "Include full npm ls tree (omit depth=0 default)", false);
|
|
392
|
-
if (allowOmitDev) {
|
|
393
|
-
cmd.option("--omit-dev", "Exclude devDependencies (local only)", false);
|
|
394
|
-
}
|
|
395
|
-
return cmd;
|
|
396
|
-
};
|
|
426
|
+
function createLocalCommand(program) {
|
|
397
427
|
const localCmd = program.command("local", { isDefault: true }).description("Generate a report for the current project's dependencies");
|
|
398
428
|
addCommonOptions(localCmd, { allowOmitDev: true });
|
|
399
429
|
localCmd.action(async (opts) => {
|
|
@@ -401,10 +431,7 @@ ${ASCII_BANNER}`);
|
|
|
401
431
|
const outFile = opts.outFile;
|
|
402
432
|
const fullTree = Boolean(opts.fullTree);
|
|
403
433
|
const omitDev = Boolean(opts.omitDev);
|
|
404
|
-
|
|
405
|
-
if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
|
|
406
|
-
finalOutFile = `gex-report.${outputFormat}`;
|
|
407
|
-
}
|
|
434
|
+
const finalOutFile = outFile;
|
|
408
435
|
const { report, markdownExtras } = await produceReport("local", {
|
|
409
436
|
outputFormat,
|
|
410
437
|
outFile: finalOutFile,
|
|
@@ -413,16 +440,16 @@ ${ASCII_BANNER}`);
|
|
|
413
440
|
});
|
|
414
441
|
await outputReport(report, outputFormat, finalOutFile, markdownExtras);
|
|
415
442
|
});
|
|
443
|
+
return localCmd;
|
|
444
|
+
}
|
|
445
|
+
function createGlobalCommand(program) {
|
|
416
446
|
const globalCmd = program.command("global").description("Generate a report of globally installed packages");
|
|
417
447
|
addCommonOptions(globalCmd, { allowOmitDev: false });
|
|
418
448
|
globalCmd.action(async (opts) => {
|
|
419
449
|
const outputFormat = opts.outputFormat ?? "json";
|
|
420
450
|
const outFile = opts.outFile;
|
|
421
451
|
const fullTree = Boolean(opts.fullTree);
|
|
422
|
-
|
|
423
|
-
if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
|
|
424
|
-
finalOutFile = `gex-report.${outputFormat}`;
|
|
425
|
-
}
|
|
452
|
+
const finalOutFile = outFile;
|
|
426
453
|
const { report, markdownExtras } = await produceReport("global", {
|
|
427
454
|
outputFormat,
|
|
428
455
|
outFile: finalOutFile,
|
|
@@ -430,12 +457,15 @@ ${ASCII_BANNER}`);
|
|
|
430
457
|
});
|
|
431
458
|
await outputReport(report, outputFormat, finalOutFile, markdownExtras);
|
|
432
459
|
});
|
|
460
|
+
return globalCmd;
|
|
461
|
+
}
|
|
462
|
+
function createReadCommand(program) {
|
|
433
463
|
const readCmd = program.command("read").description(
|
|
434
464
|
"Read a previously generated report (JSON or Markdown) and either print package names or install them"
|
|
435
465
|
).argument("[report]", "Path to report file (JSON or Markdown)", "gex-report.json").option("-r, --report <path>", "Path to report file (JSON or Markdown)").option("-p, --print", "Print package names/versions from the report (default)", false).option("-i, --install", "Install packages from the report", false);
|
|
436
466
|
readCmd.action(async (reportArg, opts) => {
|
|
437
467
|
const chosen = opts.report || reportArg || "gex-report.json";
|
|
438
|
-
const reportPath =
|
|
468
|
+
const reportPath = import_node_path6.default.resolve(process.cwd(), chosen);
|
|
439
469
|
try {
|
|
440
470
|
const parsed = await loadReportFromFile(reportPath);
|
|
441
471
|
const doInstall = Boolean(opts.install);
|
|
@@ -454,12 +484,42 @@ ${ASCII_BANNER}`);
|
|
|
454
484
|
process.exitCode = 1;
|
|
455
485
|
}
|
|
456
486
|
});
|
|
487
|
+
return readCmd;
|
|
488
|
+
}
|
|
489
|
+
async function createProgram() {
|
|
490
|
+
const program = new import_commander.Command().name("gex").description("GEX: Dependency auditing and documentation for Node.js (local and global).").version(await getToolVersion());
|
|
491
|
+
program.addHelpText("beforeAll", `
|
|
492
|
+
${ASCII_BANNER}`);
|
|
493
|
+
createLocalCommand(program);
|
|
494
|
+
createGlobalCommand(program);
|
|
495
|
+
createReadCommand(program);
|
|
496
|
+
return program;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// src/cli.ts
|
|
500
|
+
var import_meta2 = {};
|
|
501
|
+
async function run(argv = process.argv) {
|
|
502
|
+
const program = await createProgram();
|
|
457
503
|
await program.parseAsync(argv);
|
|
458
504
|
}
|
|
459
|
-
var
|
|
460
|
-
|
|
461
|
-
if (
|
|
462
|
-
|
|
505
|
+
var isMainModule = (() => {
|
|
506
|
+
try {
|
|
507
|
+
if (typeof require !== "undefined" && typeof module !== "undefined") {
|
|
508
|
+
return require.main === module;
|
|
509
|
+
}
|
|
510
|
+
if (typeof import_meta2 !== "undefined") {
|
|
511
|
+
return import_meta2.url === `file://${process.argv[1]}`;
|
|
512
|
+
}
|
|
513
|
+
return false;
|
|
514
|
+
} catch {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
})();
|
|
518
|
+
if (isMainModule) {
|
|
519
|
+
run().catch((error) => {
|
|
520
|
+
console.error("CLI error:", error);
|
|
521
|
+
process.exitCode = 1;
|
|
522
|
+
});
|
|
463
523
|
}
|
|
464
524
|
// Annotate the CommonJS export names for ESM import in node:
|
|
465
525
|
0 && (module.exports = {
|