@yabasha/gex 0.3.1 → 0.3.3
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 +30 -3
- package/dist/cli.cjs +279 -213
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +277 -214
- 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
|
@@ -65,11 +65,15 @@ gex local --omit-dev -f json -o deps.json
|
|
|
65
65
|
# Global packages
|
|
66
66
|
gex global -f md -o global.md
|
|
67
67
|
|
|
68
|
-
# Read a previous report (
|
|
69
|
-
#
|
|
68
|
+
# Read a previous report (JSON or Markdown)
|
|
69
|
+
# Default prints names@versions; add -i to install
|
|
70
|
+
# Positional path or -r/--report are accepted
|
|
71
|
+
# JSON
|
|
70
72
|
gex read
|
|
71
|
-
# or specify a file and install
|
|
72
73
|
gex read -r path/to/report.json -i
|
|
74
|
+
# Markdown
|
|
75
|
+
gex read global.md
|
|
76
|
+
gex read global.md -i
|
|
73
77
|
```
|
|
74
78
|
|
|
75
79
|
## JSON schema (summary)
|
|
@@ -141,3 +145,26 @@ npm test
|
|
|
141
145
|
npm run dev # watch + shows CLI help on success
|
|
142
146
|
npm run lint
|
|
143
147
|
```
|
|
148
|
+
|
|
149
|
+
## Contribute
|
|
150
|
+
|
|
151
|
+
We welcome contributions! A quick guide to getting productive:
|
|
152
|
+
|
|
153
|
+
- Setup
|
|
154
|
+
- Fork and clone this repo, then: `npm i`
|
|
155
|
+
- Dev loop: `npm run dev` (rebuilds and prints CLI help on successful build)
|
|
156
|
+
- One-off build: `npm run build`, then run: `node dist/cli.cjs --help`
|
|
157
|
+
- Test, lint, format
|
|
158
|
+
- Run tests: `npm test` (or `npm run test:watch`) — uses Vitest
|
|
159
|
+
- Lint: `npm run lint`; Format: `npm run format`
|
|
160
|
+
- Adding features/fixes
|
|
161
|
+
- Create a branch (e.g., `feat/read-reports`, `fix/option-parsing`)
|
|
162
|
+
- Make changes and add tests when reasonable
|
|
163
|
+
- If the change is user-facing, add a changeset: `npx changeset` (choose bump; write a summary)
|
|
164
|
+
- Open a PR (use `gh` CLI per workspace convention)
|
|
165
|
+
- Example: `gh pr create --fill` (ensure your branch is pushed)
|
|
166
|
+
- CI will run tests and build; the Release workflow will open a "Version Packages" PR for changesets
|
|
167
|
+
- Merge the "Version Packages" PR to publish to npm automatically
|
|
168
|
+
- Quick local verification
|
|
169
|
+
- Generate a report: `gex -f json -o gex-report.json`
|
|
170
|
+
- Read a report: `gex read` (JSON) or `gex read global.md` (Markdown); add `-i` to install
|
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) => {
|
|
@@ -413,6 +443,9 @@ ${ASCII_BANNER}`);
|
|
|
413
443
|
});
|
|
414
444
|
await outputReport(report, outputFormat, finalOutFile, markdownExtras);
|
|
415
445
|
});
|
|
446
|
+
return localCmd;
|
|
447
|
+
}
|
|
448
|
+
function createGlobalCommand(program) {
|
|
416
449
|
const globalCmd = program.command("global").description("Generate a report of globally installed packages");
|
|
417
450
|
addCommonOptions(globalCmd, { allowOmitDev: false });
|
|
418
451
|
globalCmd.action(async (opts) => {
|
|
@@ -430,12 +463,15 @@ ${ASCII_BANNER}`);
|
|
|
430
463
|
});
|
|
431
464
|
await outputReport(report, outputFormat, finalOutFile, markdownExtras);
|
|
432
465
|
});
|
|
466
|
+
return globalCmd;
|
|
467
|
+
}
|
|
468
|
+
function createReadCommand(program) {
|
|
433
469
|
const readCmd = program.command("read").description(
|
|
434
470
|
"Read a previously generated report (JSON or Markdown) and either print package names or install them"
|
|
435
471
|
).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
472
|
readCmd.action(async (reportArg, opts) => {
|
|
437
473
|
const chosen = opts.report || reportArg || "gex-report.json";
|
|
438
|
-
const reportPath =
|
|
474
|
+
const reportPath = import_node_path6.default.resolve(process.cwd(), chosen);
|
|
439
475
|
try {
|
|
440
476
|
const parsed = await loadReportFromFile(reportPath);
|
|
441
477
|
const doInstall = Boolean(opts.install);
|
|
@@ -454,12 +490,42 @@ ${ASCII_BANNER}`);
|
|
|
454
490
|
process.exitCode = 1;
|
|
455
491
|
}
|
|
456
492
|
});
|
|
493
|
+
return readCmd;
|
|
494
|
+
}
|
|
495
|
+
async function createProgram() {
|
|
496
|
+
const program = new import_commander.Command().name("gex").description("GEX: Dependency auditing and documentation for Node.js (local and global).").version(await getToolVersion());
|
|
497
|
+
program.addHelpText("beforeAll", `
|
|
498
|
+
${ASCII_BANNER}`);
|
|
499
|
+
createLocalCommand(program);
|
|
500
|
+
createGlobalCommand(program);
|
|
501
|
+
createReadCommand(program);
|
|
502
|
+
return program;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// src/cli.ts
|
|
506
|
+
var import_meta2 = {};
|
|
507
|
+
async function run(argv = process.argv) {
|
|
508
|
+
const program = await createProgram();
|
|
457
509
|
await program.parseAsync(argv);
|
|
458
510
|
}
|
|
459
|
-
var
|
|
460
|
-
|
|
461
|
-
if (
|
|
462
|
-
|
|
511
|
+
var isMainModule = (() => {
|
|
512
|
+
try {
|
|
513
|
+
if (typeof require !== "undefined" && typeof module !== "undefined") {
|
|
514
|
+
return require.main === module;
|
|
515
|
+
}
|
|
516
|
+
if (typeof import_meta2 !== "undefined") {
|
|
517
|
+
return import_meta2.url === `file://${process.argv[1]}`;
|
|
518
|
+
}
|
|
519
|
+
return false;
|
|
520
|
+
} catch {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
})();
|
|
524
|
+
if (isMainModule) {
|
|
525
|
+
run().catch((error) => {
|
|
526
|
+
console.error("CLI error:", error);
|
|
527
|
+
process.exitCode = 1;
|
|
528
|
+
});
|
|
463
529
|
}
|
|
464
530
|
// Annotate the CommonJS export names for ESM import in node:
|
|
465
531
|
0 && (module.exports = {
|