@yabasha/gex 0.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/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
15
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
16
+ OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,137 @@
1
+ ```
2
+ ________ __
3
+ / _____/ ____ _____/ |_ ____ ____
4
+ / \\ ___ / _ \\ / _ \\ __\\/ __ \\ / \\
5
+ \\ \\_\\ ( <_> | <_> ) | \\ ___/| | \\
6
+ \\______ /\\____/ \\____/|__| \\___ >___| /
7
+ \\/ \\/ \\/
8
+ GEX
9
+
10
+ ```
11
+
12
+ # GEX — Global/local dependency auditing and documentation for Node.js
13
+
14
+ GEX is a focused CLI that generates structured, reproducible reports of your Node.js package environments:
15
+
16
+ - Local project dependencies (default)
17
+ - Globally installed packages
18
+
19
+ Reports can be emitted as machine-readable JSON (default) or human-friendly Markdown. Use GEX to inventory environments, document state for handovers/audits, and keep a versionable dependency log.
20
+
21
+ ## Install
22
+
23
+ - Requirements: Node >= 18.18, npm
24
+ - Global install:
25
+
26
+ ```bash
27
+ npm i -g @yabasha/gex
28
+ ```
29
+
30
+ Or run locally after building this repo:
31
+
32
+ ```bash
33
+ npm i
34
+ npm run build
35
+ node dist/cli.cjs --help
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ Synopsis:
41
+
42
+ ```bash
43
+ gex [options] # defaults to: gex local
44
+ gex local [options]
45
+ gex global [options]
46
+ ```
47
+
48
+ Common options:
49
+
50
+ - f, --output-format <md|json> (default: json)
51
+ - o, --out-file <path>
52
+ - -full-tree Include the full npm ls JSON under `tree` (default uses depth=0)
53
+ - -omit-dev Local only; exclude devDependencies
54
+
55
+ Examples:
56
+
57
+ ```bash
58
+ # Local (default): JSON → stdout or to default file if -f provided without -o
59
+ gex # same as: gex local
60
+ gex -f md -o report.md
61
+
62
+ # Local: exclude devDependencies
63
+ gex local --omit-dev -f json -o deps.json
64
+
65
+ # Global packages
66
+ gex global -f md -o global.md
67
+ ```
68
+
69
+ ## JSON schema (summary)
70
+
71
+ Top-level keys:
72
+
73
+ - report_version, timestamp, tool_version
74
+ - project_name, project_version (omitted for global reports)
75
+ - global_packages: Array<{ name, version, resolved_path }>
76
+ - local_dependencies: Array<{ name, version, resolved_path }>
77
+ - local_dev_dependencies: Array<{ name, version, resolved_path }>
78
+ - tree: raw `npm ls --json` output (when --full-tree)
79
+
80
+ Example (truncated):
81
+
82
+ ```json
83
+ {
84
+ "report_version": "1.0",
85
+ "timestamp": "2025-01-01T12:00:00.000Z",
86
+ "tool_version": "0.1.0",
87
+ "project_name": "my-app",
88
+ "project_version": "1.2.3",
89
+ "global_packages": [],
90
+ "local_dependencies": [
91
+ {
92
+ "name": "commander",
93
+ "version": "12.1.0",
94
+ "resolved_path": "/path/to/project/node_modules/commander"
95
+ }
96
+ ],
97
+ "local_dev_dependencies": [
98
+ {
99
+ "name": "vitest",
100
+ "version": "2.1.1",
101
+ "resolved_path": "/path/to/project/node_modules/vitest"
102
+ }
103
+ ]
104
+ }
105
+ ```
106
+
107
+ ## Production usage
108
+
109
+ - Deterministic output: packages are sorted by name; default uses depth=0 for fast, stable runs.
110
+ - Exit codes: returns 0 on success; non-zero on fatal errors (e.g., npm not found, unreadable output).
111
+ - npm behavior: npm ls may exit non-zero but still produce JSON; GEX parses stdout when available.
112
+ - Paths: resolved_path is best-effort from npm and environment (uses `npm root -g` for global discovery).
113
+
114
+ CI/CD examples:
115
+
116
+ - Using npx (no global install):
117
+
118
+ ```bash
119
+ npx -y @yabasha/gex@latest -f json -o gex-report.json
120
+ ```
121
+
122
+ - GitHub Actions step snippet:
123
+
124
+ ```yaml
125
+ - name: Generate dependency report
126
+ run: npx -y @yabasha/gex@latest -f json -o gex-report.json
127
+ ```
128
+
129
+ ## Development (repo)
130
+
131
+ ```bash
132
+ npm i
133
+ npm run build
134
+ npm test
135
+ npm run dev # watch + shows CLI help on success
136
+ npm run lint
137
+ ```
package/dist/cli.cjs ADDED
@@ -0,0 +1,366 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/cli.ts
32
+ var cli_exports = {};
33
+ __export(cli_exports, {
34
+ run: () => run
35
+ });
36
+ module.exports = __toCommonJS(cli_exports);
37
+ var import_promises2 = require("fs/promises");
38
+ var import_node_path2 = __toESM(require("path"), 1);
39
+ var import_node_url = require("url");
40
+ var import_commander = require("commander");
41
+
42
+ // src/npm.ts
43
+ var import_node_child_process = require("child_process");
44
+ var import_node_util = require("util");
45
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
46
+ async function npmLs(options = {}) {
47
+ const args = ["ls", "--json"];
48
+ if (options.global) args.push("--global");
49
+ if (options.omitDev) args.push("--omit=dev");
50
+ if (options.depth0) args.push("--depth=0");
51
+ try {
52
+ const { stdout } = await execFileAsync("npm", args, {
53
+ cwd: options.cwd,
54
+ maxBuffer: 10 * 1024 * 1024
55
+ });
56
+ if (stdout && stdout.trim()) return JSON.parse(stdout);
57
+ return {};
58
+ } catch (err) {
59
+ const stdout = err?.stdout;
60
+ if (typeof stdout === "string" && stdout.trim()) {
61
+ try {
62
+ return JSON.parse(stdout);
63
+ } catch {
64
+ }
65
+ }
66
+ const stderr = err?.stderr;
67
+ const msg = typeof stderr === "string" && stderr.trim() || err?.message || "npm ls failed";
68
+ throw new Error(`npm ls failed: ${msg}`);
69
+ }
70
+ }
71
+ async function npmRootGlobal() {
72
+ try {
73
+ const { stdout } = await execFileAsync("npm", ["root", "-g"]);
74
+ return stdout.trim();
75
+ } catch (err) {
76
+ const stderr = err?.stderr;
77
+ const msg = typeof stderr === "string" && stderr.trim() || err?.message || "npm root -g failed";
78
+ throw new Error(`npm root -g failed: ${msg}`);
79
+ }
80
+ }
81
+
82
+ // src/transform.ts
83
+ var import_node_path = __toESM(require("path"), 1);
84
+ var import_promises = require("fs/promises");
85
+ function toPkgArray(obj) {
86
+ if (!obj) return [];
87
+ return Object.keys(obj).map((name) => ({ name, node: obj[name] })).filter((p) => p && p.node);
88
+ }
89
+ async function buildReportFromNpmTree(tree, opts) {
90
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
91
+ const report = {
92
+ report_version: "1.0",
93
+ timestamp,
94
+ tool_version: opts.toolVersion,
95
+ global_packages: [],
96
+ local_dependencies: [],
97
+ local_dev_dependencies: []
98
+ };
99
+ if (opts.context === "local") {
100
+ let pkgMeta = null;
101
+ try {
102
+ const pkgJsonPath = import_node_path.default.join(opts.cwd || process.cwd(), "package.json");
103
+ const raw = await (0, import_promises.readFile)(pkgJsonPath, "utf8");
104
+ pkgMeta = JSON.parse(raw);
105
+ } catch {
106
+ }
107
+ if (pkgMeta?.name) report.project_name = pkgMeta.name;
108
+ if (pkgMeta?.version) report.project_version = pkgMeta.version;
109
+ const depsObj = tree?.dependencies;
110
+ const items = toPkgArray(depsObj);
111
+ const devKeys = new Set(Object.keys(pkgMeta?.devDependencies || {}));
112
+ for (const { name, node } of items) {
113
+ const version = node && node.version || "";
114
+ const resolvedPath = node && node.path || import_node_path.default.join(opts.cwd || process.cwd(), "node_modules", name);
115
+ const pkg = { name, version, resolved_path: resolvedPath };
116
+ if (devKeys.has(name)) {
117
+ report.local_dev_dependencies.push(pkg);
118
+ } else {
119
+ report.local_dependencies.push(pkg);
120
+ }
121
+ }
122
+ report.local_dependencies.sort((a, b) => a.name.localeCompare(b.name));
123
+ report.local_dev_dependencies.sort((a, b) => a.name.localeCompare(b.name));
124
+ } else if (opts.context === "global") {
125
+ const depsObj = tree?.dependencies;
126
+ const items = toPkgArray(depsObj);
127
+ for (const { name, node } of items) {
128
+ const version = node && node.version || "";
129
+ const resolvedPath = node && node.path || import_node_path.default.join(opts.globalRoot || "", name);
130
+ const pkg = { name, version, resolved_path: resolvedPath };
131
+ report.global_packages.push(pkg);
132
+ }
133
+ report.global_packages.sort((a, b) => a.name.localeCompare(b.name));
134
+ }
135
+ if (opts.includeTree) {
136
+ report.tree = tree;
137
+ }
138
+ return report;
139
+ }
140
+
141
+ // src/report/json.ts
142
+ function renderJson(report) {
143
+ const r = {
144
+ ...report,
145
+ global_packages: [...report.global_packages].sort((a, b) => a.name.localeCompare(b.name)),
146
+ local_dependencies: [...report.local_dependencies].sort((a, b) => a.name.localeCompare(b.name)),
147
+ local_dev_dependencies: [...report.local_dev_dependencies].sort(
148
+ (a, b) => a.name.localeCompare(b.name)
149
+ )
150
+ };
151
+ return JSON.stringify(r, null, 2);
152
+ }
153
+
154
+ // src/report/md.ts
155
+ function table(headers, rows) {
156
+ const header = `| ${headers.join(" | ")} |`;
157
+ const sep = `| ${headers.map(() => "---").join(" | ")} |`;
158
+ const body = rows.map((r) => `| ${r.join(" | ")} |`).join("\n");
159
+ return [header, sep, body].filter(Boolean).join("\n");
160
+ }
161
+ function renderMarkdown(report) {
162
+ const lines = [];
163
+ lines.push("# GEX Report");
164
+ lines.push("");
165
+ if (report.project_name || report.project_version) {
166
+ lines.push("## Project Metadata");
167
+ if (report.project_name) lines.push(`- Name: ${report.project_name}`);
168
+ if (report.project_version) lines.push(`- Version: ${report.project_version}`);
169
+ if (report.project_description)
170
+ lines.push(`- Description: ${report.project_description}`);
171
+ if (report.project_homepage)
172
+ lines.push(`- Homepage: ${report.project_homepage}`);
173
+ if (report.project_bugs) lines.push(`- Bugs: ${report.project_bugs}`);
174
+ lines.push("");
175
+ }
176
+ if (report.global_packages.length > 0) {
177
+ lines.push("## Global Packages");
178
+ const rows = report.global_packages.map((p) => [p.name, p.version || "", p.resolved_path || ""]);
179
+ lines.push(table(["Name", "Version", "Path"], rows));
180
+ lines.push("");
181
+ }
182
+ if (report.local_dependencies.length > 0) {
183
+ lines.push("## Local Dependencies");
184
+ const rows = report.local_dependencies.map((p) => [
185
+ p.name,
186
+ p.version || "",
187
+ p.resolved_path || ""
188
+ ]);
189
+ lines.push(table(["Name", "Version", "Path"], rows));
190
+ lines.push("");
191
+ }
192
+ if (report.local_dev_dependencies.length > 0) {
193
+ lines.push("## Local Dev Dependencies");
194
+ const rows = report.local_dev_dependencies.map((p) => [
195
+ p.name,
196
+ p.version || "",
197
+ p.resolved_path || ""
198
+ ]);
199
+ lines.push(table(["Name", "Version", "Path"], rows));
200
+ lines.push("");
201
+ }
202
+ lines.push("---");
203
+ lines.push("_Generated by GEX_");
204
+ return lines.join("\n");
205
+ }
206
+
207
+ // src/cli.ts
208
+ var import_meta = {};
209
+ function getPkgJsonPath() {
210
+ try {
211
+ const __filename = (0, import_node_url.fileURLToPath)(import_meta.url);
212
+ const __dirnameLocal = import_node_path2.default.dirname(__filename);
213
+ return import_node_path2.default.resolve(__dirnameLocal, "..", "package.json");
214
+ } catch {
215
+ const dir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
216
+ return import_node_path2.default.resolve(dir, "..", "package.json");
217
+ }
218
+ }
219
+ async function getToolVersion() {
220
+ try {
221
+ const pkgPath = getPkgJsonPath();
222
+ const raw = await (0, import_promises2.readFile)(pkgPath, "utf8");
223
+ const pkg = JSON.parse(raw);
224
+ return pkg.version || "0.0.0";
225
+ } catch {
226
+ return "0.0.0";
227
+ }
228
+ }
229
+ var ASCII_BANNER = String.raw`
230
+ ________ __
231
+ / _____/ ____ _____/ |_ ____ ____
232
+ / \ ___ / _ \ / _ \ __\/ __ \ / \
233
+ \ \_\ ( <_> | <_> ) | \ ___/| | \
234
+ \______ /\____/ \____/|__| \___ >___| /
235
+ \/ \/ \/
236
+ GEX
237
+ `;
238
+ async function produceReport(ctx, options) {
239
+ const toolVersion = await getToolVersion();
240
+ const depth0 = !options.fullTree;
241
+ const cwd = options.cwd || process.cwd();
242
+ const tree = await npmLs({
243
+ global: ctx === "global",
244
+ omitDev: ctx === "local" ? Boolean(options.omitDev) : false,
245
+ depth0,
246
+ cwd
247
+ });
248
+ let project_description;
249
+ let project_homepage;
250
+ let project_bugs;
251
+ if (ctx === "local") {
252
+ try {
253
+ const pkgRaw = await (0, import_promises2.readFile)(import_node_path2.default.join(cwd, "package.json"), "utf8");
254
+ const pkg = JSON.parse(pkgRaw);
255
+ project_description = pkg.description;
256
+ project_homepage = pkg.homepage;
257
+ if (typeof pkg.bugs === "string") project_bugs = pkg.bugs;
258
+ else if (pkg.bugs && typeof pkg.bugs.url === "string") project_bugs = pkg.bugs.url;
259
+ } catch {
260
+ }
261
+ }
262
+ const globalRoot = ctx === "global" ? await npmRootGlobal().catch(() => void 0) : void 0;
263
+ const report = await buildReportFromNpmTree(tree, {
264
+ context: ctx,
265
+ includeTree: Boolean(options.fullTree),
266
+ omitDev: Boolean(options.omitDev),
267
+ cwd,
268
+ toolVersion,
269
+ globalRoot
270
+ });
271
+ const markdownExtras = { project_description, project_homepage, project_bugs };
272
+ return { report, markdownExtras };
273
+ }
274
+ async function outputReport(report, format, outFile, markdownExtras) {
275
+ const content = format === "json" ? renderJson(report) : renderMarkdown({ ...report, ...markdownExtras || {} });
276
+ if (outFile) {
277
+ const outDir = import_node_path2.default.dirname(outFile);
278
+ await (await import("fs/promises")).mkdir(outDir, { recursive: true });
279
+ await (await import("fs/promises")).writeFile(outFile, content, "utf8");
280
+ console.log(`Wrote report to ${outFile}`);
281
+ } else {
282
+ console.log(content);
283
+ }
284
+ }
285
+ async function run(argv = process.argv) {
286
+ const program = new import_commander.Command().name("gex").description("GEX: Dependency auditing and documentation for Node.js (local and global).").version(await getToolVersion());
287
+ program.addHelpText("beforeAll", `
288
+ ${ASCII_BANNER}`);
289
+ const addCommonOptions = (cmd, { allowOmitDev }) => {
290
+ cmd.option(
291
+ "-f, --output-format <format>",
292
+ "Output format: md or json",
293
+ (val) => val === "md" ? "md" : "json",
294
+ "json"
295
+ ).option("-o, --out-file <path>", "Write report to file").option("--full-tree", "Include full npm ls tree (omit depth=0 default)", false);
296
+ if (allowOmitDev) {
297
+ cmd.option("--omit-dev", "Exclude devDependencies (local only)", false);
298
+ }
299
+ return cmd;
300
+ };
301
+ addCommonOptions(program, { allowOmitDev: true });
302
+ program.action(async (opts) => {
303
+ const outputFormat = opts.outputFormat ?? "json";
304
+ const outFile = opts.outFile;
305
+ const fullTree = Boolean(opts.fullTree);
306
+ const omitDev = Boolean(opts.omitDev);
307
+ let finalOutFile = outFile;
308
+ if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
309
+ finalOutFile = `gex-report.${outputFormat}`;
310
+ }
311
+ const { report, markdownExtras } = await produceReport("local", {
312
+ outputFormat,
313
+ outFile: finalOutFile,
314
+ fullTree,
315
+ omitDev
316
+ });
317
+ await outputReport(report, outputFormat, finalOutFile, markdownExtras);
318
+ });
319
+ const localCmd = program.command("local").description("Generate a report for the current project's dependencies");
320
+ addCommonOptions(localCmd, { allowOmitDev: true });
321
+ localCmd.action(async (opts) => {
322
+ const outputFormat = opts.outputFormat ?? "json";
323
+ const outFile = opts.outFile;
324
+ const fullTree = Boolean(opts.fullTree);
325
+ const omitDev = Boolean(opts.omitDev);
326
+ let finalOutFile = outFile;
327
+ if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
328
+ finalOutFile = `gex-report.${outputFormat}`;
329
+ }
330
+ const { report, markdownExtras } = await produceReport("local", {
331
+ outputFormat,
332
+ outFile: finalOutFile,
333
+ fullTree,
334
+ omitDev
335
+ });
336
+ await outputReport(report, outputFormat, finalOutFile, markdownExtras);
337
+ });
338
+ const globalCmd = program.command("global").description("Generate a report of globally installed packages");
339
+ addCommonOptions(globalCmd, { allowOmitDev: false });
340
+ globalCmd.action(async (opts) => {
341
+ const outputFormat = opts.outputFormat ?? "json";
342
+ const outFile = opts.outFile;
343
+ const fullTree = Boolean(opts.fullTree);
344
+ let finalOutFile = outFile;
345
+ if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
346
+ finalOutFile = `gex-report.${outputFormat}`;
347
+ }
348
+ const { report, markdownExtras } = await produceReport("global", {
349
+ outputFormat,
350
+ outFile: finalOutFile,
351
+ fullTree
352
+ });
353
+ await outputReport(report, outputFormat, finalOutFile, markdownExtras);
354
+ });
355
+ await program.parseAsync(argv);
356
+ }
357
+ var isCjsMain = typeof require !== "undefined" && require.main === module;
358
+ var isEsmMain = typeof import_meta !== "undefined" && import_meta.url === `file://${process.argv[1]}`;
359
+ if (isCjsMain || isEsmMain) {
360
+ run();
361
+ }
362
+ // Annotate the CommonJS export names for ESM import in node:
363
+ 0 && (module.exports = {
364
+ run
365
+ });
366
+ //# sourceMappingURL=cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/npm.ts","../src/transform.ts","../src/report/json.ts","../src/report/md.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { Command } from 'commander'\n\nimport { npmLs, npmRootGlobal } from './npm.js'\nimport { buildReportFromNpmTree } from './transform.js'\nimport { renderJson } from './report/json.js'\nimport { renderMarkdown } from './report/md.js'\nimport type { OutputFormat, Report } from './types.js'\n\nfunction getPkgJsonPath(): string {\n // Resolve package.json relative to this file for both ESM and CJS bundles\n try {\n const __filename = fileURLToPath((import.meta as any).url)\n const __dirnameLocal = path.dirname(__filename)\n return path.resolve(__dirnameLocal, '..', 'package.json')\n } catch {\n const dir = typeof __dirname !== 'undefined' ? __dirname : process.cwd()\n return path.resolve(dir, '..', 'package.json')\n }\n}\n\nasync function getToolVersion(): Promise<string> {\n try {\n const pkgPath = getPkgJsonPath()\n const raw = await readFile(pkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n return pkg.version || '0.0.0'\n } catch {\n return '0.0.0'\n }\n}\n\nconst ASCII_BANNER = String.raw`\n ________ __\n / _____/ ____ _____/ |_ ____ ____ \n/ \\ ___ / _ \\ / _ \\ __\\/ __ \\ / \\\n\\ \\_\\ ( <_> | <_> ) | \\ ___/| | \\\n \\______ /\\____/ \\____/|__| \\___ >___| /\n \\/ \\/ \\/ \n GEX\n`\n\nasync function produceReport(\n ctx: 'local' | 'global',\n options: {\n outputFormat: OutputFormat\n outFile?: string\n fullTree?: boolean\n omitDev?: boolean\n cwd?: string\n },\n): Promise<{ report: Report; markdownExtras?: any }> {\n const toolVersion = await getToolVersion()\n const depth0 = !options.fullTree\n const cwd = options.cwd || process.cwd()\n\n const tree = await npmLs({\n global: ctx === 'global',\n omitDev: ctx === 'local' ? Boolean(options.omitDev) : false,\n depth0,\n cwd,\n })\n\n // Get extra metadata for markdown rendering when local\n let project_description: string | undefined\n let project_homepage: string | undefined\n let project_bugs: string | undefined\n if (ctx === 'local') {\n try {\n const pkgRaw = await readFile(path.join(cwd, 'package.json'), 'utf8')\n const pkg = JSON.parse(pkgRaw)\n project_description = pkg.description\n project_homepage = pkg.homepage\n if (typeof pkg.bugs === 'string') project_bugs = pkg.bugs\n else if (pkg.bugs && typeof pkg.bugs.url === 'string') project_bugs = pkg.bugs.url\n } catch {\n // ignore\n }\n }\n\n const globalRoot = ctx === 'global' ? await npmRootGlobal().catch(() => undefined) : undefined\n\n const report = await buildReportFromNpmTree(tree, {\n context: ctx,\n includeTree: Boolean(options.fullTree),\n omitDev: Boolean(options.omitDev),\n cwd,\n toolVersion,\n globalRoot,\n })\n\n const markdownExtras = { project_description, project_homepage, project_bugs }\n return { report, markdownExtras }\n}\n\nasync function outputReport(\n report: Report,\n format: OutputFormat,\n outFile?: string,\n markdownExtras?: any,\n) {\n const content =\n format === 'json'\n ? renderJson(report)\n : renderMarkdown({ ...report, ...(markdownExtras || {}) })\n if (outFile) {\n const outDir = path.dirname(outFile)\n await (await import('node:fs/promises')).mkdir(outDir, { recursive: true })\n await (await import('node:fs/promises')).writeFile(outFile, content, 'utf8')\n \n console.log(`Wrote report to ${outFile}`)\n } else {\n \n console.log(content)\n }\n}\n\nexport async function run(argv = process.argv) {\n const program = new Command()\n .name('gex')\n .description('GEX: Dependency auditing and documentation for Node.js (local and global).')\n .version(await getToolVersion())\n\n program.addHelpText('beforeAll', `\\n${ASCII_BANNER}`)\n\n const addCommonOptions = (cmd: Command, { allowOmitDev }: { allowOmitDev: boolean }) => {\n cmd\n .option(\n '-f, --output-format <format>',\n 'Output format: md or json',\n (val) => (val === 'md' ? 'md' : 'json'),\n 'json',\n )\n .option('-o, --out-file <path>', 'Write report to file')\n .option('--full-tree', 'Include full npm ls tree (omit depth=0 default)', false)\n if (allowOmitDev) {\n cmd.option('--omit-dev', 'Exclude devDependencies (local only)', false)\n }\n return cmd\n }\n\n // Root behaves like `local` by default\n addCommonOptions(program as unknown as Command, { allowOmitDev: true })\n program.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n const omitDev = Boolean(opts.omitDev)\n\n let finalOutFile = outFile\n if (!outFile && opts.outputFormat && typeof opts.outputFormat === 'string') {\n finalOutFile = `gex-report.${outputFormat}`\n }\n\n const { report, markdownExtras } = await produceReport('local', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n omitDev,\n })\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n // gex local\n const localCmd = program\n .command('local')\n .description(\"Generate a report for the current project's dependencies\")\n addCommonOptions(localCmd, { allowOmitDev: true })\n localCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n const omitDev = Boolean(opts.omitDev)\n\n let finalOutFile = outFile\n if (!outFile && opts.outputFormat && typeof opts.outputFormat === 'string') {\n finalOutFile = `gex-report.${outputFormat}`\n }\n\n const { report, markdownExtras } = await produceReport('local', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n omitDev,\n })\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n // gex global\n const globalCmd = program\n .command('global')\n .description('Generate a report of globally installed packages')\n addCommonOptions(globalCmd, { allowOmitDev: false })\n globalCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n\n let finalOutFile = outFile\n if (!outFile && opts.outputFormat && typeof opts.outputFormat === 'string') {\n finalOutFile = `gex-report.${outputFormat}`\n }\n\n const { report, markdownExtras } = await produceReport('global', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n })\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n await program.parseAsync(argv)\n}\n\nconst isCjsMain = typeof require !== 'undefined' && (require as any).main === module\nconst isEsmMain =\n typeof import.meta !== 'undefined' && (import.meta as any).url === `file://${process.argv[1]}`\nif (isCjsMain || isEsmMain) {\n run()\n}\n","import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\n\nconst execFileAsync = promisify(execFile)\n\nexport type NpmLsOptions = {\n global?: boolean\n omitDev?: boolean\n depth0?: boolean\n cwd?: string\n}\n\nexport async function npmLs(options: NpmLsOptions = {}): Promise<any> {\n const args = ['ls', '--json']\n if (options.global) args.push('--global')\n if (options.omitDev) args.push('--omit=dev')\n if (options.depth0) args.push('--depth=0')\n\n try {\n const { stdout } = await execFileAsync('npm', args, {\n cwd: options.cwd,\n maxBuffer: 10 * 1024 * 1024,\n })\n if (stdout && stdout.trim()) return JSON.parse(stdout)\n return {}\n } catch (err: any) {\n const stdout = err?.stdout\n if (typeof stdout === 'string' && stdout.trim()) {\n try {\n return JSON.parse(stdout)\n } catch {\n // fallthrough\n }\n }\n const stderr = err?.stderr\n const msg = (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm ls failed'\n throw new Error(`npm ls failed: ${msg}`)\n }\n}\n\nexport async function npmRootGlobal(): Promise<string> {\n try {\n const { stdout } = await execFileAsync('npm', ['root', '-g'])\n return stdout.trim()\n } catch (err: any) {\n const stderr = err?.stderr\n const msg =\n (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm root -g failed'\n throw new Error(`npm root -g failed: ${msg}`)\n }\n}\n","import path from 'node:path'\nimport { readFile } from 'node:fs/promises'\n\nimport type { PackageInfo, Report } from './types.js'\n\nexport type NormalizeOptions = {\n context: 'local' | 'global'\n includeTree?: boolean\n omitDev?: boolean\n cwd?: string\n toolVersion: string\n globalRoot?: string\n}\n\nfunction toPkgArray(obj: Record<string, any> | undefined | null): { name: string; node: any }[] {\n if (!obj) return []\n return Object.keys(obj)\n .map((name) => ({ name, node: obj[name] }))\n .filter((p) => p && p.node)\n}\n\nexport async function buildReportFromNpmTree(tree: any, opts: NormalizeOptions): Promise<Report> {\n const timestamp = new Date().toISOString()\n const report: Report = {\n report_version: '1.0',\n timestamp,\n tool_version: opts.toolVersion,\n global_packages: [],\n local_dependencies: [],\n local_dev_dependencies: [],\n }\n\n if (opts.context === 'local') {\n let pkgMeta: any = null\n try {\n const pkgJsonPath = path.join(opts.cwd || process.cwd(), 'package.json')\n const raw = await readFile(pkgJsonPath, 'utf8')\n pkgMeta = JSON.parse(raw)\n } catch {\n // ignore; project metadata optional\n }\n if (pkgMeta?.name) report.project_name = pkgMeta.name\n if (pkgMeta?.version) report.project_version = pkgMeta.version\n\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n const devKeys = new Set(Object.keys((pkgMeta?.devDependencies as Record<string, string>) || {}))\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath =\n (node && node.path) || path.join(opts.cwd || process.cwd(), 'node_modules', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n if (devKeys.has(name)) {\n // Only categorize as dev if present in the tree; with --omit-dev they won't appear\n report.local_dev_dependencies.push(pkg)\n } else {\n report.local_dependencies.push(pkg)\n }\n }\n\n // sort\n report.local_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n report.local_dev_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n } else if (opts.context === 'global') {\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath = (node && node.path) || path.join(opts.globalRoot || '', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n report.global_packages.push(pkg)\n }\n\n report.global_packages.sort((a, b) => a.name.localeCompare(b.name))\n }\n\n if (opts.includeTree) {\n report.tree = tree\n }\n\n return report\n}\n","import type { Report } from '../types.js'\n\nexport function renderJson(report: Report): string {\n // Ensure stable ordering (defensive; arrays already sorted)\n const r: Report = {\n ...report,\n global_packages: [...report.global_packages].sort((a, b) => a.name.localeCompare(b.name)),\n local_dependencies: [...report.local_dependencies].sort((a, b) => a.name.localeCompare(b.name)),\n local_dev_dependencies: [...report.local_dev_dependencies].sort((a, b) =>\n a.name.localeCompare(b.name),\n ),\n }\n return JSON.stringify(r, null, 2)\n}\n","import type { Report } from '../types.js'\n\nfunction table(headers: string[], rows: string[][]): string {\n const header = `| ${headers.join(' | ')} |`\n const sep = `| ${headers.map(() => '---').join(' | ')} |`\n const body = rows.map((r) => `| ${r.join(' | ')} |`).join('\\n')\n return [header, sep, body].filter(Boolean).join('\\n')\n}\n\nexport function renderMarkdown(\n report: Report & {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n },\n): string {\n const lines: string[] = []\n lines.push('# GEX Report')\n lines.push('')\n\n if (report.project_name || report.project_version) {\n lines.push('## Project Metadata')\n if (report.project_name) lines.push(`- Name: ${report.project_name}`)\n if (report.project_version) lines.push(`- Version: ${report.project_version}`)\n if ((report as any).project_description)\n lines.push(`- Description: ${(report as any).project_description}`)\n if ((report as any).project_homepage)\n lines.push(`- Homepage: ${(report as any).project_homepage}`)\n if ((report as any).project_bugs) lines.push(`- Bugs: ${(report as any).project_bugs}`)\n lines.push('')\n }\n\n if (report.global_packages.length > 0) {\n lines.push('## Global Packages')\n const rows = report.global_packages.map((p) => [p.name, p.version || '', p.resolved_path || ''])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dependencies.length > 0) {\n lines.push('## Local Dependencies')\n const rows = report.local_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dev_dependencies.length > 0) {\n lines.push('## Local Dev Dependencies')\n const rows = report.local_dev_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n lines.push('---')\n lines.push('_Generated by GEX_')\n\n return lines.join('\\n')\n}\n"],"mappings":"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","names":["import_promises","import_node_path","path","path"]}
package/dist/cli.mjs ADDED
@@ -0,0 +1,337 @@
1
+ #!/usr/bin/env node
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
+ }) : x)(function(x) {
5
+ if (typeof require !== "undefined") return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
9
+ // src/cli.ts
10
+ import { readFile as readFile2 } from "fs/promises";
11
+ import path2 from "path";
12
+ import { fileURLToPath } from "url";
13
+ import { Command } from "commander";
14
+
15
+ // src/npm.ts
16
+ import { execFile } from "child_process";
17
+ import { promisify } from "util";
18
+ var execFileAsync = promisify(execFile);
19
+ async function npmLs(options = {}) {
20
+ const args = ["ls", "--json"];
21
+ if (options.global) args.push("--global");
22
+ if (options.omitDev) args.push("--omit=dev");
23
+ if (options.depth0) args.push("--depth=0");
24
+ try {
25
+ const { stdout } = await execFileAsync("npm", args, {
26
+ cwd: options.cwd,
27
+ maxBuffer: 10 * 1024 * 1024
28
+ });
29
+ if (stdout && stdout.trim()) return JSON.parse(stdout);
30
+ return {};
31
+ } catch (err) {
32
+ const stdout = err?.stdout;
33
+ if (typeof stdout === "string" && stdout.trim()) {
34
+ try {
35
+ return JSON.parse(stdout);
36
+ } catch {
37
+ }
38
+ }
39
+ const stderr = err?.stderr;
40
+ const msg = typeof stderr === "string" && stderr.trim() || err?.message || "npm ls failed";
41
+ throw new Error(`npm ls failed: ${msg}`);
42
+ }
43
+ }
44
+ async function npmRootGlobal() {
45
+ try {
46
+ const { stdout } = await execFileAsync("npm", ["root", "-g"]);
47
+ return stdout.trim();
48
+ } catch (err) {
49
+ const stderr = err?.stderr;
50
+ const msg = typeof stderr === "string" && stderr.trim() || err?.message || "npm root -g failed";
51
+ throw new Error(`npm root -g failed: ${msg}`);
52
+ }
53
+ }
54
+
55
+ // src/transform.ts
56
+ import path from "path";
57
+ import { readFile } from "fs/promises";
58
+ function toPkgArray(obj) {
59
+ if (!obj) return [];
60
+ return Object.keys(obj).map((name) => ({ name, node: obj[name] })).filter((p) => p && p.node);
61
+ }
62
+ async function buildReportFromNpmTree(tree, opts) {
63
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
64
+ const report = {
65
+ report_version: "1.0",
66
+ timestamp,
67
+ tool_version: opts.toolVersion,
68
+ global_packages: [],
69
+ local_dependencies: [],
70
+ local_dev_dependencies: []
71
+ };
72
+ if (opts.context === "local") {
73
+ let pkgMeta = null;
74
+ try {
75
+ const pkgJsonPath = path.join(opts.cwd || process.cwd(), "package.json");
76
+ const raw = await readFile(pkgJsonPath, "utf8");
77
+ pkgMeta = JSON.parse(raw);
78
+ } catch {
79
+ }
80
+ if (pkgMeta?.name) report.project_name = pkgMeta.name;
81
+ if (pkgMeta?.version) report.project_version = pkgMeta.version;
82
+ const depsObj = tree?.dependencies;
83
+ const items = toPkgArray(depsObj);
84
+ const devKeys = new Set(Object.keys(pkgMeta?.devDependencies || {}));
85
+ for (const { name, node } of items) {
86
+ const version = node && node.version || "";
87
+ const resolvedPath = node && node.path || path.join(opts.cwd || process.cwd(), "node_modules", name);
88
+ const pkg = { name, version, resolved_path: resolvedPath };
89
+ if (devKeys.has(name)) {
90
+ report.local_dev_dependencies.push(pkg);
91
+ } else {
92
+ report.local_dependencies.push(pkg);
93
+ }
94
+ }
95
+ report.local_dependencies.sort((a, b) => a.name.localeCompare(b.name));
96
+ report.local_dev_dependencies.sort((a, b) => a.name.localeCompare(b.name));
97
+ } else if (opts.context === "global") {
98
+ const depsObj = tree?.dependencies;
99
+ const items = toPkgArray(depsObj);
100
+ for (const { name, node } of items) {
101
+ const version = node && node.version || "";
102
+ const resolvedPath = node && node.path || path.join(opts.globalRoot || "", name);
103
+ const pkg = { name, version, resolved_path: resolvedPath };
104
+ report.global_packages.push(pkg);
105
+ }
106
+ report.global_packages.sort((a, b) => a.name.localeCompare(b.name));
107
+ }
108
+ if (opts.includeTree) {
109
+ report.tree = tree;
110
+ }
111
+ return report;
112
+ }
113
+
114
+ // src/report/json.ts
115
+ function renderJson(report) {
116
+ const r = {
117
+ ...report,
118
+ global_packages: [...report.global_packages].sort((a, b) => a.name.localeCompare(b.name)),
119
+ local_dependencies: [...report.local_dependencies].sort((a, b) => a.name.localeCompare(b.name)),
120
+ local_dev_dependencies: [...report.local_dev_dependencies].sort(
121
+ (a, b) => a.name.localeCompare(b.name)
122
+ )
123
+ };
124
+ return JSON.stringify(r, null, 2);
125
+ }
126
+
127
+ // src/report/md.ts
128
+ function table(headers, rows) {
129
+ const header = `| ${headers.join(" | ")} |`;
130
+ const sep = `| ${headers.map(() => "---").join(" | ")} |`;
131
+ const body = rows.map((r) => `| ${r.join(" | ")} |`).join("\n");
132
+ return [header, sep, body].filter(Boolean).join("\n");
133
+ }
134
+ function renderMarkdown(report) {
135
+ const lines = [];
136
+ lines.push("# GEX Report");
137
+ lines.push("");
138
+ if (report.project_name || report.project_version) {
139
+ lines.push("## Project Metadata");
140
+ if (report.project_name) lines.push(`- Name: ${report.project_name}`);
141
+ if (report.project_version) lines.push(`- Version: ${report.project_version}`);
142
+ if (report.project_description)
143
+ lines.push(`- Description: ${report.project_description}`);
144
+ if (report.project_homepage)
145
+ lines.push(`- Homepage: ${report.project_homepage}`);
146
+ if (report.project_bugs) lines.push(`- Bugs: ${report.project_bugs}`);
147
+ lines.push("");
148
+ }
149
+ if (report.global_packages.length > 0) {
150
+ lines.push("## Global Packages");
151
+ const rows = report.global_packages.map((p) => [p.name, p.version || "", p.resolved_path || ""]);
152
+ lines.push(table(["Name", "Version", "Path"], rows));
153
+ lines.push("");
154
+ }
155
+ if (report.local_dependencies.length > 0) {
156
+ lines.push("## Local Dependencies");
157
+ const rows = report.local_dependencies.map((p) => [
158
+ p.name,
159
+ p.version || "",
160
+ p.resolved_path || ""
161
+ ]);
162
+ lines.push(table(["Name", "Version", "Path"], rows));
163
+ lines.push("");
164
+ }
165
+ if (report.local_dev_dependencies.length > 0) {
166
+ lines.push("## Local Dev Dependencies");
167
+ const rows = report.local_dev_dependencies.map((p) => [
168
+ p.name,
169
+ p.version || "",
170
+ p.resolved_path || ""
171
+ ]);
172
+ lines.push(table(["Name", "Version", "Path"], rows));
173
+ lines.push("");
174
+ }
175
+ lines.push("---");
176
+ lines.push("_Generated by GEX_");
177
+ return lines.join("\n");
178
+ }
179
+
180
+ // src/cli.ts
181
+ function getPkgJsonPath() {
182
+ try {
183
+ const __filename = fileURLToPath(import.meta.url);
184
+ const __dirnameLocal = path2.dirname(__filename);
185
+ return path2.resolve(__dirnameLocal, "..", "package.json");
186
+ } catch {
187
+ const dir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
188
+ return path2.resolve(dir, "..", "package.json");
189
+ }
190
+ }
191
+ async function getToolVersion() {
192
+ try {
193
+ const pkgPath = getPkgJsonPath();
194
+ const raw = await readFile2(pkgPath, "utf8");
195
+ const pkg = JSON.parse(raw);
196
+ return pkg.version || "0.0.0";
197
+ } catch {
198
+ return "0.0.0";
199
+ }
200
+ }
201
+ var ASCII_BANNER = String.raw`
202
+ ________ __
203
+ / _____/ ____ _____/ |_ ____ ____
204
+ / \ ___ / _ \ / _ \ __\/ __ \ / \
205
+ \ \_\ ( <_> | <_> ) | \ ___/| | \
206
+ \______ /\____/ \____/|__| \___ >___| /
207
+ \/ \/ \/
208
+ GEX
209
+ `;
210
+ async function produceReport(ctx, options) {
211
+ const toolVersion = await getToolVersion();
212
+ const depth0 = !options.fullTree;
213
+ const cwd = options.cwd || process.cwd();
214
+ const tree = await npmLs({
215
+ global: ctx === "global",
216
+ omitDev: ctx === "local" ? Boolean(options.omitDev) : false,
217
+ depth0,
218
+ cwd
219
+ });
220
+ let project_description;
221
+ let project_homepage;
222
+ let project_bugs;
223
+ if (ctx === "local") {
224
+ try {
225
+ const pkgRaw = await readFile2(path2.join(cwd, "package.json"), "utf8");
226
+ const pkg = JSON.parse(pkgRaw);
227
+ project_description = pkg.description;
228
+ project_homepage = pkg.homepage;
229
+ if (typeof pkg.bugs === "string") project_bugs = pkg.bugs;
230
+ else if (pkg.bugs && typeof pkg.bugs.url === "string") project_bugs = pkg.bugs.url;
231
+ } catch {
232
+ }
233
+ }
234
+ const globalRoot = ctx === "global" ? await npmRootGlobal().catch(() => void 0) : void 0;
235
+ const report = await buildReportFromNpmTree(tree, {
236
+ context: ctx,
237
+ includeTree: Boolean(options.fullTree),
238
+ omitDev: Boolean(options.omitDev),
239
+ cwd,
240
+ toolVersion,
241
+ globalRoot
242
+ });
243
+ const markdownExtras = { project_description, project_homepage, project_bugs };
244
+ return { report, markdownExtras };
245
+ }
246
+ async function outputReport(report, format, outFile, markdownExtras) {
247
+ const content = format === "json" ? renderJson(report) : renderMarkdown({ ...report, ...markdownExtras || {} });
248
+ if (outFile) {
249
+ const outDir = path2.dirname(outFile);
250
+ await (await import("fs/promises")).mkdir(outDir, { recursive: true });
251
+ await (await import("fs/promises")).writeFile(outFile, content, "utf8");
252
+ console.log(`Wrote report to ${outFile}`);
253
+ } else {
254
+ console.log(content);
255
+ }
256
+ }
257
+ async function run(argv = process.argv) {
258
+ const program = new Command().name("gex").description("GEX: Dependency auditing and documentation for Node.js (local and global).").version(await getToolVersion());
259
+ program.addHelpText("beforeAll", `
260
+ ${ASCII_BANNER}`);
261
+ const addCommonOptions = (cmd, { allowOmitDev }) => {
262
+ cmd.option(
263
+ "-f, --output-format <format>",
264
+ "Output format: md or json",
265
+ (val) => val === "md" ? "md" : "json",
266
+ "json"
267
+ ).option("-o, --out-file <path>", "Write report to file").option("--full-tree", "Include full npm ls tree (omit depth=0 default)", false);
268
+ if (allowOmitDev) {
269
+ cmd.option("--omit-dev", "Exclude devDependencies (local only)", false);
270
+ }
271
+ return cmd;
272
+ };
273
+ addCommonOptions(program, { allowOmitDev: true });
274
+ program.action(async (opts) => {
275
+ const outputFormat = opts.outputFormat ?? "json";
276
+ const outFile = opts.outFile;
277
+ const fullTree = Boolean(opts.fullTree);
278
+ const omitDev = Boolean(opts.omitDev);
279
+ let finalOutFile = outFile;
280
+ if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
281
+ finalOutFile = `gex-report.${outputFormat}`;
282
+ }
283
+ const { report, markdownExtras } = await produceReport("local", {
284
+ outputFormat,
285
+ outFile: finalOutFile,
286
+ fullTree,
287
+ omitDev
288
+ });
289
+ await outputReport(report, outputFormat, finalOutFile, markdownExtras);
290
+ });
291
+ const localCmd = program.command("local").description("Generate a report for the current project's dependencies");
292
+ addCommonOptions(localCmd, { allowOmitDev: true });
293
+ localCmd.action(async (opts) => {
294
+ const outputFormat = opts.outputFormat ?? "json";
295
+ const outFile = opts.outFile;
296
+ const fullTree = Boolean(opts.fullTree);
297
+ const omitDev = Boolean(opts.omitDev);
298
+ let finalOutFile = outFile;
299
+ if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
300
+ finalOutFile = `gex-report.${outputFormat}`;
301
+ }
302
+ const { report, markdownExtras } = await produceReport("local", {
303
+ outputFormat,
304
+ outFile: finalOutFile,
305
+ fullTree,
306
+ omitDev
307
+ });
308
+ await outputReport(report, outputFormat, finalOutFile, markdownExtras);
309
+ });
310
+ const globalCmd = program.command("global").description("Generate a report of globally installed packages");
311
+ addCommonOptions(globalCmd, { allowOmitDev: false });
312
+ globalCmd.action(async (opts) => {
313
+ const outputFormat = opts.outputFormat ?? "json";
314
+ const outFile = opts.outFile;
315
+ const fullTree = Boolean(opts.fullTree);
316
+ let finalOutFile = outFile;
317
+ if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
318
+ finalOutFile = `gex-report.${outputFormat}`;
319
+ }
320
+ const { report, markdownExtras } = await produceReport("global", {
321
+ outputFormat,
322
+ outFile: finalOutFile,
323
+ fullTree
324
+ });
325
+ await outputReport(report, outputFormat, finalOutFile, markdownExtras);
326
+ });
327
+ await program.parseAsync(argv);
328
+ }
329
+ var isCjsMain = typeof __require !== "undefined" && __require.main === module;
330
+ var isEsmMain = typeof import.meta !== "undefined" && import.meta.url === `file://${process.argv[1]}`;
331
+ if (isCjsMain || isEsmMain) {
332
+ run();
333
+ }
334
+ export {
335
+ run
336
+ };
337
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/npm.ts","../src/transform.ts","../src/report/json.ts","../src/report/md.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { Command } from 'commander'\n\nimport { npmLs, npmRootGlobal } from './npm.js'\nimport { buildReportFromNpmTree } from './transform.js'\nimport { renderJson } from './report/json.js'\nimport { renderMarkdown } from './report/md.js'\nimport type { OutputFormat, Report } from './types.js'\n\nfunction getPkgJsonPath(): string {\n // Resolve package.json relative to this file for both ESM and CJS bundles\n try {\n const __filename = fileURLToPath((import.meta as any).url)\n const __dirnameLocal = path.dirname(__filename)\n return path.resolve(__dirnameLocal, '..', 'package.json')\n } catch {\n const dir = typeof __dirname !== 'undefined' ? __dirname : process.cwd()\n return path.resolve(dir, '..', 'package.json')\n }\n}\n\nasync function getToolVersion(): Promise<string> {\n try {\n const pkgPath = getPkgJsonPath()\n const raw = await readFile(pkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n return pkg.version || '0.0.0'\n } catch {\n return '0.0.0'\n }\n}\n\nconst ASCII_BANNER = String.raw`\n ________ __\n / _____/ ____ _____/ |_ ____ ____ \n/ \\ ___ / _ \\ / _ \\ __\\/ __ \\ / \\\n\\ \\_\\ ( <_> | <_> ) | \\ ___/| | \\\n \\______ /\\____/ \\____/|__| \\___ >___| /\n \\/ \\/ \\/ \n GEX\n`\n\nasync function produceReport(\n ctx: 'local' | 'global',\n options: {\n outputFormat: OutputFormat\n outFile?: string\n fullTree?: boolean\n omitDev?: boolean\n cwd?: string\n },\n): Promise<{ report: Report; markdownExtras?: any }> {\n const toolVersion = await getToolVersion()\n const depth0 = !options.fullTree\n const cwd = options.cwd || process.cwd()\n\n const tree = await npmLs({\n global: ctx === 'global',\n omitDev: ctx === 'local' ? Boolean(options.omitDev) : false,\n depth0,\n cwd,\n })\n\n // Get extra metadata for markdown rendering when local\n let project_description: string | undefined\n let project_homepage: string | undefined\n let project_bugs: string | undefined\n if (ctx === 'local') {\n try {\n const pkgRaw = await readFile(path.join(cwd, 'package.json'), 'utf8')\n const pkg = JSON.parse(pkgRaw)\n project_description = pkg.description\n project_homepage = pkg.homepage\n if (typeof pkg.bugs === 'string') project_bugs = pkg.bugs\n else if (pkg.bugs && typeof pkg.bugs.url === 'string') project_bugs = pkg.bugs.url\n } catch {\n // ignore\n }\n }\n\n const globalRoot = ctx === 'global' ? await npmRootGlobal().catch(() => undefined) : undefined\n\n const report = await buildReportFromNpmTree(tree, {\n context: ctx,\n includeTree: Boolean(options.fullTree),\n omitDev: Boolean(options.omitDev),\n cwd,\n toolVersion,\n globalRoot,\n })\n\n const markdownExtras = { project_description, project_homepage, project_bugs }\n return { report, markdownExtras }\n}\n\nasync function outputReport(\n report: Report,\n format: OutputFormat,\n outFile?: string,\n markdownExtras?: any,\n) {\n const content =\n format === 'json'\n ? renderJson(report)\n : renderMarkdown({ ...report, ...(markdownExtras || {}) })\n if (outFile) {\n const outDir = path.dirname(outFile)\n await (await import('node:fs/promises')).mkdir(outDir, { recursive: true })\n await (await import('node:fs/promises')).writeFile(outFile, content, 'utf8')\n \n console.log(`Wrote report to ${outFile}`)\n } else {\n \n console.log(content)\n }\n}\n\nexport async function run(argv = process.argv) {\n const program = new Command()\n .name('gex')\n .description('GEX: Dependency auditing and documentation for Node.js (local and global).')\n .version(await getToolVersion())\n\n program.addHelpText('beforeAll', `\\n${ASCII_BANNER}`)\n\n const addCommonOptions = (cmd: Command, { allowOmitDev }: { allowOmitDev: boolean }) => {\n cmd\n .option(\n '-f, --output-format <format>',\n 'Output format: md or json',\n (val) => (val === 'md' ? 'md' : 'json'),\n 'json',\n )\n .option('-o, --out-file <path>', 'Write report to file')\n .option('--full-tree', 'Include full npm ls tree (omit depth=0 default)', false)\n if (allowOmitDev) {\n cmd.option('--omit-dev', 'Exclude devDependencies (local only)', false)\n }\n return cmd\n }\n\n // Root behaves like `local` by default\n addCommonOptions(program as unknown as Command, { allowOmitDev: true })\n program.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n const omitDev = Boolean(opts.omitDev)\n\n let finalOutFile = outFile\n if (!outFile && opts.outputFormat && typeof opts.outputFormat === 'string') {\n finalOutFile = `gex-report.${outputFormat}`\n }\n\n const { report, markdownExtras } = await produceReport('local', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n omitDev,\n })\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n // gex local\n const localCmd = program\n .command('local')\n .description(\"Generate a report for the current project's dependencies\")\n addCommonOptions(localCmd, { allowOmitDev: true })\n localCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n const omitDev = Boolean(opts.omitDev)\n\n let finalOutFile = outFile\n if (!outFile && opts.outputFormat && typeof opts.outputFormat === 'string') {\n finalOutFile = `gex-report.${outputFormat}`\n }\n\n const { report, markdownExtras } = await produceReport('local', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n omitDev,\n })\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n // gex global\n const globalCmd = program\n .command('global')\n .description('Generate a report of globally installed packages')\n addCommonOptions(globalCmd, { allowOmitDev: false })\n globalCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n\n let finalOutFile = outFile\n if (!outFile && opts.outputFormat && typeof opts.outputFormat === 'string') {\n finalOutFile = `gex-report.${outputFormat}`\n }\n\n const { report, markdownExtras } = await produceReport('global', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n })\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n await program.parseAsync(argv)\n}\n\nconst isCjsMain = typeof require !== 'undefined' && (require as any).main === module\nconst isEsmMain =\n typeof import.meta !== 'undefined' && (import.meta as any).url === `file://${process.argv[1]}`\nif (isCjsMain || isEsmMain) {\n run()\n}\n","import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\n\nconst execFileAsync = promisify(execFile)\n\nexport type NpmLsOptions = {\n global?: boolean\n omitDev?: boolean\n depth0?: boolean\n cwd?: string\n}\n\nexport async function npmLs(options: NpmLsOptions = {}): Promise<any> {\n const args = ['ls', '--json']\n if (options.global) args.push('--global')\n if (options.omitDev) args.push('--omit=dev')\n if (options.depth0) args.push('--depth=0')\n\n try {\n const { stdout } = await execFileAsync('npm', args, {\n cwd: options.cwd,\n maxBuffer: 10 * 1024 * 1024,\n })\n if (stdout && stdout.trim()) return JSON.parse(stdout)\n return {}\n } catch (err: any) {\n const stdout = err?.stdout\n if (typeof stdout === 'string' && stdout.trim()) {\n try {\n return JSON.parse(stdout)\n } catch {\n // fallthrough\n }\n }\n const stderr = err?.stderr\n const msg = (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm ls failed'\n throw new Error(`npm ls failed: ${msg}`)\n }\n}\n\nexport async function npmRootGlobal(): Promise<string> {\n try {\n const { stdout } = await execFileAsync('npm', ['root', '-g'])\n return stdout.trim()\n } catch (err: any) {\n const stderr = err?.stderr\n const msg =\n (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm root -g failed'\n throw new Error(`npm root -g failed: ${msg}`)\n }\n}\n","import path from 'node:path'\nimport { readFile } from 'node:fs/promises'\n\nimport type { PackageInfo, Report } from './types.js'\n\nexport type NormalizeOptions = {\n context: 'local' | 'global'\n includeTree?: boolean\n omitDev?: boolean\n cwd?: string\n toolVersion: string\n globalRoot?: string\n}\n\nfunction toPkgArray(obj: Record<string, any> | undefined | null): { name: string; node: any }[] {\n if (!obj) return []\n return Object.keys(obj)\n .map((name) => ({ name, node: obj[name] }))\n .filter((p) => p && p.node)\n}\n\nexport async function buildReportFromNpmTree(tree: any, opts: NormalizeOptions): Promise<Report> {\n const timestamp = new Date().toISOString()\n const report: Report = {\n report_version: '1.0',\n timestamp,\n tool_version: opts.toolVersion,\n global_packages: [],\n local_dependencies: [],\n local_dev_dependencies: [],\n }\n\n if (opts.context === 'local') {\n let pkgMeta: any = null\n try {\n const pkgJsonPath = path.join(opts.cwd || process.cwd(), 'package.json')\n const raw = await readFile(pkgJsonPath, 'utf8')\n pkgMeta = JSON.parse(raw)\n } catch {\n // ignore; project metadata optional\n }\n if (pkgMeta?.name) report.project_name = pkgMeta.name\n if (pkgMeta?.version) report.project_version = pkgMeta.version\n\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n const devKeys = new Set(Object.keys((pkgMeta?.devDependencies as Record<string, string>) || {}))\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath =\n (node && node.path) || path.join(opts.cwd || process.cwd(), 'node_modules', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n if (devKeys.has(name)) {\n // Only categorize as dev if present in the tree; with --omit-dev they won't appear\n report.local_dev_dependencies.push(pkg)\n } else {\n report.local_dependencies.push(pkg)\n }\n }\n\n // sort\n report.local_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n report.local_dev_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n } else if (opts.context === 'global') {\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath = (node && node.path) || path.join(opts.globalRoot || '', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n report.global_packages.push(pkg)\n }\n\n report.global_packages.sort((a, b) => a.name.localeCompare(b.name))\n }\n\n if (opts.includeTree) {\n report.tree = tree\n }\n\n return report\n}\n","import type { Report } from '../types.js'\n\nexport function renderJson(report: Report): string {\n // Ensure stable ordering (defensive; arrays already sorted)\n const r: Report = {\n ...report,\n global_packages: [...report.global_packages].sort((a, b) => a.name.localeCompare(b.name)),\n local_dependencies: [...report.local_dependencies].sort((a, b) => a.name.localeCompare(b.name)),\n local_dev_dependencies: [...report.local_dev_dependencies].sort((a, b) =>\n a.name.localeCompare(b.name),\n ),\n }\n return JSON.stringify(r, null, 2)\n}\n","import type { Report } from '../types.js'\n\nfunction table(headers: string[], rows: string[][]): string {\n const header = `| ${headers.join(' | ')} |`\n const sep = `| ${headers.map(() => '---').join(' | ')} |`\n const body = rows.map((r) => `| ${r.join(' | ')} |`).join('\\n')\n return [header, sep, body].filter(Boolean).join('\\n')\n}\n\nexport function renderMarkdown(\n report: Report & {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n },\n): string {\n const lines: string[] = []\n lines.push('# GEX Report')\n lines.push('')\n\n if (report.project_name || report.project_version) {\n lines.push('## Project Metadata')\n if (report.project_name) lines.push(`- Name: ${report.project_name}`)\n if (report.project_version) lines.push(`- Version: ${report.project_version}`)\n if ((report as any).project_description)\n lines.push(`- Description: ${(report as any).project_description}`)\n if ((report as any).project_homepage)\n lines.push(`- Homepage: ${(report as any).project_homepage}`)\n if ((report as any).project_bugs) lines.push(`- Bugs: ${(report as any).project_bugs}`)\n lines.push('')\n }\n\n if (report.global_packages.length > 0) {\n lines.push('## Global Packages')\n const rows = report.global_packages.map((p) => [p.name, p.version || '', p.resolved_path || ''])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dependencies.length > 0) {\n lines.push('## Local Dependencies')\n const rows = report.local_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dev_dependencies.length > 0) {\n lines.push('## Local Dev Dependencies')\n const rows = report.local_dev_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n lines.push('---')\n lines.push('_Generated by GEX_')\n\n return lines.join('\\n')\n}\n"],"mappings":"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","names":["readFile","path","path","readFile"]}
package/dist/index.cjs ADDED
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ greet: () => greet
24
+ });
25
+ module.exports = __toCommonJS(src_exports);
26
+ function greet(name) {
27
+ return `Hello, ${name}!`;
28
+ }
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ greet
32
+ });
33
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Library API entry.\n * Export functions here for consumers who import your package.\n */\n\nexport function greet(name: string): string {\n return `Hello, ${name}!`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKO,SAAS,MAAM,MAAsB;AAC1C,SAAO,UAAU,IAAI;AACvB;","names":[]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Library API entry.
3
+ * Export functions here for consumers who import your package.
4
+ */
5
+ declare function greet(name: string): string;
6
+
7
+ export { greet };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Library API entry.
3
+ * Export functions here for consumers who import your package.
4
+ */
5
+ declare function greet(name: string): string;
6
+
7
+ export { greet };
package/dist/index.mjs ADDED
@@ -0,0 +1,8 @@
1
+ // src/index.ts
2
+ function greet(name) {
3
+ return `Hello, ${name}!`;
4
+ }
5
+ export {
6
+ greet
7
+ };
8
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Library API entry.\n * Export functions here for consumers who import your package.\n */\n\nexport function greet(name: string): string {\n return `Hello, ${name}!`\n}\n"],"mappings":";AAKO,SAAS,MAAM,MAAsB;AAC1C,SAAO,UAAU,IAAI;AACvB;","names":[]}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@yabasha/gex",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "A CLI tool for auditing and documenting your Node.js package environment, generating comprehensive reports of global and local dependencies.",
6
+ "type": "module",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.mjs",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "bin": {
18
+ "gex": "./dist/cli.cjs"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "engines": {
24
+ "node": ">=18.18"
25
+ },
26
+ "scripts": {
27
+ "build": "tsup",
28
+ "dev": "tsup --watch --onSuccess \"node dist/cli.cjs --help\"",
29
+ "lint": "eslint .",
30
+ "format": "prettier --write .",
31
+ "test": "vitest run",
32
+ "test:watch": "vitest",
33
+ "prepare": "husky install || true",
34
+ "release": "changeset publish",
35
+ "version-pack": "npm pack"
36
+ },
37
+ "keywords": [
38
+ "typescript",
39
+ "starter",
40
+ "cli",
41
+ "library",
42
+ "tsup",
43
+ "commander"
44
+ ],
45
+ "author": "",
46
+ "license": "MIT",
47
+ "devDependencies": {
48
+ "@changesets/cli": "^2.27.8",
49
+ "@types/node": "^22.5.4",
50
+ "@typescript-eslint/eslint-plugin": "^8.6.0",
51
+ "@typescript-eslint/parser": "^8.6.0",
52
+ "eslint": "^9.9.1",
53
+ "eslint-config-prettier": "^9.1.0",
54
+ "eslint-plugin-import": "^2.30.0",
55
+ "husky": "^9.1.6",
56
+ "lint-staged": "^15.2.10",
57
+ "prettier": "^3.3.3",
58
+ "tsup": "^8.3.0",
59
+ "typescript": "^5.6.2",
60
+ "vitest": "^2.1.1"
61
+ },
62
+ "dependencies": {
63
+ "commander": "^12.1.0"
64
+ },
65
+ "lint-staged": {
66
+ "*.{ts,tsx,js,jsx,json,md,yml,yaml}": [
67
+ "prettier --write"
68
+ ],
69
+ "*.{ts,tsx,js,jsx}": [
70
+ "eslint --fix"
71
+ ]
72
+ }
73
+ }