@yabasha/gex 1.3.3 → 1.3.5
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 +49 -26
- package/dist/cli.cjs +516 -7
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +517 -7
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -6,6 +6,9 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
+
// src/cli.ts
|
|
10
|
+
import readline from "readline";
|
|
11
|
+
|
|
9
12
|
// src/runtimes/node/commands.ts
|
|
10
13
|
import path6 from "path";
|
|
11
14
|
import { Command } from "commander";
|
|
@@ -29,8 +32,8 @@ function formatSpec(pkg) {
|
|
|
29
32
|
}
|
|
30
33
|
async function getExecFileAsync() {
|
|
31
34
|
const { execFile } = await import("child_process");
|
|
32
|
-
const { promisify:
|
|
33
|
-
return
|
|
35
|
+
const { promisify: promisify3 } = await import("util");
|
|
36
|
+
return promisify3(execFile);
|
|
34
37
|
}
|
|
35
38
|
async function installFromReport(report, options) {
|
|
36
39
|
const opts = typeof options === "string" ? { cwd: options } : options;
|
|
@@ -278,6 +281,20 @@ function formatNpmError(error, commandLabel) {
|
|
|
278
281
|
const message = stderr || error?.message || `${commandLabel} failed`;
|
|
279
282
|
return new Error(`${commandLabel} failed: ${message}`);
|
|
280
283
|
}
|
|
284
|
+
async function npmViewVersion(packageName) {
|
|
285
|
+
try {
|
|
286
|
+
const execFileAsync = await getExecFileAsync2();
|
|
287
|
+
const { stdout } = await execFileAsync("npm", ["view", packageName, "version", "--json"], {
|
|
288
|
+
maxBuffer: 5 * 1024 * 1024
|
|
289
|
+
});
|
|
290
|
+
const parsed = JSON.parse(stdout);
|
|
291
|
+
if (typeof parsed === "string") return parsed;
|
|
292
|
+
if (Array.isArray(parsed)) return parsed[parsed.length - 1] ?? "";
|
|
293
|
+
return "";
|
|
294
|
+
} catch (error) {
|
|
295
|
+
throw formatNpmError(error, `npm view ${packageName}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
281
298
|
|
|
282
299
|
// src/shared/cli/loader.ts
|
|
283
300
|
var frames = ["-", "\\", "|", "/"];
|
|
@@ -373,6 +390,26 @@ async function handleOutdatedWorkflow(opts) {
|
|
|
373
390
|
const proceed = !((opts.checkOutdated || opts.selection.shouldUpdate) && !opts.outFile);
|
|
374
391
|
return { proceed, outdated };
|
|
375
392
|
}
|
|
393
|
+
async function resolveOutdatedWithNpmView(packages) {
|
|
394
|
+
const results = [];
|
|
395
|
+
for (const pkg of packages) {
|
|
396
|
+
try {
|
|
397
|
+
const latest = await npmViewVersion(pkg.name);
|
|
398
|
+
if (latest && pkg.current && latest !== pkg.current) {
|
|
399
|
+
results.push({
|
|
400
|
+
name: pkg.name,
|
|
401
|
+
current: pkg.current,
|
|
402
|
+
wanted: pkg.declared || latest,
|
|
403
|
+
latest,
|
|
404
|
+
type: pkg.type
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
} catch {
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return results;
|
|
412
|
+
}
|
|
376
413
|
|
|
377
414
|
// src/shared/cli/utils.ts
|
|
378
415
|
import { existsSync } from "fs";
|
|
@@ -498,8 +535,8 @@ async function buildReportFromNpmTree(tree, opts) {
|
|
|
498
535
|
// src/runtimes/node/package-manager.ts
|
|
499
536
|
async function getExecFileAsync3() {
|
|
500
537
|
const { execFile } = await import("child_process");
|
|
501
|
-
const { promisify:
|
|
502
|
-
return
|
|
538
|
+
const { promisify: promisify3 } = await import("util");
|
|
539
|
+
return promisify3(execFile);
|
|
503
540
|
}
|
|
504
541
|
async function npmLs(options = {}) {
|
|
505
542
|
const args = ["ls", "--json"];
|
|
@@ -728,9 +765,423 @@ if (isMainModule) {
|
|
|
728
765
|
});
|
|
729
766
|
}
|
|
730
767
|
|
|
731
|
-
// src/
|
|
768
|
+
// src/runtimes/bun/commands.ts
|
|
769
|
+
import path9 from "path";
|
|
770
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
771
|
+
import { Command as Command2 } from "commander";
|
|
772
|
+
|
|
773
|
+
// src/runtimes/bun/report.ts
|
|
774
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
775
|
+
import path8 from "path";
|
|
776
|
+
|
|
777
|
+
// src/runtimes/bun/package-manager.ts
|
|
778
|
+
import path7 from "path";
|
|
779
|
+
import { constants as fsConstants } from "fs";
|
|
780
|
+
import { access, readFile as readFile5, readdir, stat } from "fs/promises";
|
|
781
|
+
import { promisify as promisify2 } from "util";
|
|
782
|
+
var IGNORED_ENTRIES = /* @__PURE__ */ new Set([".bin"]);
|
|
783
|
+
async function bunPmLs(options = {}) {
|
|
784
|
+
if (options.global) {
|
|
785
|
+
const root = await bunPmRootGlobal();
|
|
786
|
+
const manifest2 = await readJson(path7.join(path7.dirname(root), "package.json"));
|
|
787
|
+
const selections2 = buildSelections(manifest2, { includeDev: false });
|
|
788
|
+
const dependencies2 = selections2.prod.size > 0 ? await collectPackagesForNames(root, mapSelections(selections2.prod)) : await collectPackagesFromNodeModules(root);
|
|
789
|
+
return { dependencies: dependencies2, node_modules_path: root };
|
|
790
|
+
}
|
|
791
|
+
const cwd = options.cwd || process.cwd();
|
|
792
|
+
const nodeModulesPath = await bunPmRootLocal(cwd);
|
|
793
|
+
const manifest = await readJson(path7.join(cwd, "package.json"));
|
|
794
|
+
const includeDev = !options.omitDev;
|
|
795
|
+
const selections = buildSelections(manifest, { includeDev });
|
|
796
|
+
const dependencies = selections.prod.size > 0 ? await collectPackagesForNames(nodeModulesPath, mapSelections(selections.prod)) : await collectPackagesFromNodeModules(nodeModulesPath);
|
|
797
|
+
let devDependencies;
|
|
798
|
+
if (includeDev) {
|
|
799
|
+
if (selections.dev.size > 0) {
|
|
800
|
+
devDependencies = await collectPackagesForNames(
|
|
801
|
+
nodeModulesPath,
|
|
802
|
+
mapSelections(selections.dev)
|
|
803
|
+
);
|
|
804
|
+
} else {
|
|
805
|
+
devDependencies = {};
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
return { dependencies, devDependencies, node_modules_path: nodeModulesPath };
|
|
809
|
+
}
|
|
810
|
+
async function bunPmRootGlobal() {
|
|
811
|
+
if (process.env.GEX_BUN_GLOBAL_ROOT) {
|
|
812
|
+
return process.env.GEX_BUN_GLOBAL_ROOT;
|
|
813
|
+
}
|
|
814
|
+
const candidates = getGlobalRootCandidates();
|
|
815
|
+
for (const candidate of candidates) {
|
|
816
|
+
if (candidate && await pathExists(candidate)) {
|
|
817
|
+
return candidate;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
return candidates.find((c) => Boolean(c)) || path7.join(process.env.HOME || process.cwd(), ".bun", "install", "global", "node_modules");
|
|
821
|
+
}
|
|
822
|
+
async function bunPmRootLocal(cwd = process.cwd()) {
|
|
823
|
+
if (process.env.GEX_BUN_LOCAL_ROOT) {
|
|
824
|
+
return process.env.GEX_BUN_LOCAL_ROOT;
|
|
825
|
+
}
|
|
826
|
+
return path7.join(cwd, "node_modules");
|
|
827
|
+
}
|
|
828
|
+
async function bunUpdate(options) {
|
|
829
|
+
const execFileAsync = await getExecFileAsync4();
|
|
830
|
+
const packages = options.packages && options.packages.length > 0 ? options.packages : [];
|
|
831
|
+
if (options.global) {
|
|
832
|
+
const targets = packages.length > 0 ? packages : [];
|
|
833
|
+
const list = targets.length > 0 ? targets : [];
|
|
834
|
+
const cmdPackages = list.map((name) => `${name}@latest`);
|
|
835
|
+
try {
|
|
836
|
+
await execFileAsync("bun", ["add", "-g", ...cmdPackages], {
|
|
837
|
+
cwd: options.cwd,
|
|
838
|
+
maxBuffer: 10 * 1024 * 1024
|
|
839
|
+
});
|
|
840
|
+
} catch (error) {
|
|
841
|
+
const stderr = typeof error?.stderr === "string" ? error.stderr.trim() : "";
|
|
842
|
+
throw new Error(`bun add -g failed: ${stderr || error?.message || "unknown error"}`);
|
|
843
|
+
}
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
846
|
+
const args = ["update"];
|
|
847
|
+
if (packages.length > 0) args.push(...packages);
|
|
848
|
+
try {
|
|
849
|
+
await execFileAsync("bun", args, {
|
|
850
|
+
cwd: options.cwd,
|
|
851
|
+
maxBuffer: 10 * 1024 * 1024
|
|
852
|
+
});
|
|
853
|
+
} catch (error) {
|
|
854
|
+
const stderr = typeof error?.stderr === "string" ? error.stderr.trim() : "";
|
|
855
|
+
throw new Error(`bun update failed: ${stderr || error?.message || "unknown error"}`);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
async function collectPackagesForNames(nodeModulesPath, packages) {
|
|
859
|
+
const result = {};
|
|
860
|
+
await Promise.all(
|
|
861
|
+
packages.map(async ({ name, declared }) => {
|
|
862
|
+
const pkgDir = packageDir(nodeModulesPath, name);
|
|
863
|
+
const manifest = await readJson(path7.join(pkgDir, "package.json"));
|
|
864
|
+
const pkgName = typeof manifest?.name === "string" ? manifest.name : name;
|
|
865
|
+
const version = typeof manifest?.version === "string" ? manifest.version : declared || "";
|
|
866
|
+
result[pkgName] = { version, path: pkgDir };
|
|
867
|
+
})
|
|
868
|
+
);
|
|
869
|
+
return result;
|
|
870
|
+
}
|
|
871
|
+
async function collectPackagesFromNodeModules(root) {
|
|
872
|
+
const result = {};
|
|
873
|
+
const entries = await safeReadDir(root);
|
|
874
|
+
for (const entry of entries) {
|
|
875
|
+
if (!entry || !entry.name || entry.name.startsWith(".") || IGNORED_ENTRIES.has(entry.name)) {
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
const entryPath = path7.join(root, entry.name);
|
|
879
|
+
if (!await isDir(entry, entryPath)) continue;
|
|
880
|
+
if (entry.name.startsWith("@")) {
|
|
881
|
+
const scopedEntries = await safeReadDir(entryPath);
|
|
882
|
+
for (const scopedEntry of scopedEntries) {
|
|
883
|
+
if (!scopedEntry || !scopedEntry.name || scopedEntry.name.startsWith(".")) continue;
|
|
884
|
+
const scopedPath = path7.join(entryPath, scopedEntry.name);
|
|
885
|
+
if (!await isDir(scopedEntry, scopedPath)) continue;
|
|
886
|
+
const manifest = await readJson(path7.join(scopedPath, "package.json"));
|
|
887
|
+
const pkgName = typeof manifest?.name === "string" ? manifest.name : `${entry.name}/${scopedEntry.name}`;
|
|
888
|
+
const version = typeof manifest?.version === "string" ? manifest.version : "";
|
|
889
|
+
result[pkgName] = { version, path: scopedPath };
|
|
890
|
+
}
|
|
891
|
+
} else {
|
|
892
|
+
const manifest = await readJson(path7.join(entryPath, "package.json"));
|
|
893
|
+
const pkgName = typeof manifest?.name === "string" ? manifest.name : entry.name;
|
|
894
|
+
const version = typeof manifest?.version === "string" ? manifest.version : "";
|
|
895
|
+
result[pkgName] = { version, path: entryPath };
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
return result;
|
|
899
|
+
}
|
|
900
|
+
async function readJson(file) {
|
|
901
|
+
try {
|
|
902
|
+
const raw = await readFile5(file, "utf8");
|
|
903
|
+
return JSON.parse(raw);
|
|
904
|
+
} catch {
|
|
905
|
+
return null;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
function packageDir(root, packageName) {
|
|
909
|
+
const segments = packageName.startsWith("@") ? packageName.split("/") : [packageName];
|
|
910
|
+
return path7.join(root, ...segments);
|
|
911
|
+
}
|
|
912
|
+
function buildSelections(manifest, { includeDev }) {
|
|
913
|
+
const prod = /* @__PURE__ */ new Map();
|
|
914
|
+
const dev = /* @__PURE__ */ new Map();
|
|
915
|
+
const addAll = (target, record) => {
|
|
916
|
+
if (!record) return;
|
|
917
|
+
for (const [name, range] of Object.entries(record)) {
|
|
918
|
+
if (!target.has(name)) {
|
|
919
|
+
target.set(name, range);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
addAll(prod, manifest?.dependencies);
|
|
924
|
+
addAll(prod, manifest?.optionalDependencies);
|
|
925
|
+
if (includeDev) addAll(dev, manifest?.devDependencies);
|
|
926
|
+
return { prod, dev };
|
|
927
|
+
}
|
|
928
|
+
function mapSelections(map) {
|
|
929
|
+
return Array.from(map.entries()).map(([name, declared]) => ({ name, declared }));
|
|
930
|
+
}
|
|
931
|
+
async function safeReadDir(dir) {
|
|
932
|
+
try {
|
|
933
|
+
return await readdir(dir, { withFileTypes: true });
|
|
934
|
+
} catch {
|
|
935
|
+
return [];
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
async function isDir(entry, fullPath) {
|
|
939
|
+
if (entry.isDirectory()) return true;
|
|
940
|
+
if (entry.isSymbolicLink()) {
|
|
941
|
+
try {
|
|
942
|
+
const stats = await stat(fullPath);
|
|
943
|
+
return stats.isDirectory();
|
|
944
|
+
} catch {
|
|
945
|
+
return false;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
return false;
|
|
949
|
+
}
|
|
950
|
+
async function pathExists(target) {
|
|
951
|
+
try {
|
|
952
|
+
await access(target, fsConstants.R_OK);
|
|
953
|
+
return true;
|
|
954
|
+
} catch {
|
|
955
|
+
return false;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
function getGlobalRootCandidates() {
|
|
959
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
960
|
+
const bunInstall = process.env.BUN_INSTALL || (process.env.HOME ? path7.join(process.env.HOME, ".bun") : void 0);
|
|
961
|
+
const maybeAdd = (value) => {
|
|
962
|
+
if (value) candidates.add(value);
|
|
963
|
+
};
|
|
964
|
+
if (bunInstall) {
|
|
965
|
+
maybeAdd(path7.join(bunInstall, "install", "global", "node_modules"));
|
|
966
|
+
maybeAdd(path7.join(bunInstall, "global", "node_modules"));
|
|
967
|
+
}
|
|
968
|
+
if (process.env.XDG_DATA_HOME) {
|
|
969
|
+
maybeAdd(path7.join(process.env.XDG_DATA_HOME, "bun", "install", "global", "node_modules"));
|
|
970
|
+
}
|
|
971
|
+
maybeAdd("/usr/local/share/bun/global/node_modules");
|
|
972
|
+
maybeAdd("/opt/homebrew/var/bun/install/global/node_modules");
|
|
973
|
+
return Array.from(candidates);
|
|
974
|
+
}
|
|
975
|
+
async function getExecFileAsync4() {
|
|
976
|
+
const { execFile } = await import("child_process");
|
|
977
|
+
return promisify2(execFile);
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// src/runtimes/bun/report.ts
|
|
981
|
+
async function produceReport2(ctx, options) {
|
|
982
|
+
const toolVersion = await getToolVersion();
|
|
983
|
+
const cwd = options.cwd || process.cwd();
|
|
984
|
+
const tree = await bunPmLs({
|
|
985
|
+
global: ctx === "global",
|
|
986
|
+
omitDev: ctx === "local" ? Boolean(options.omitDev) : false,
|
|
987
|
+
cwd
|
|
988
|
+
});
|
|
989
|
+
const nodeModulesPath = tree?.node_modules_path;
|
|
990
|
+
let project_description;
|
|
991
|
+
let project_homepage;
|
|
992
|
+
let project_bugs;
|
|
993
|
+
if (ctx === "local") {
|
|
994
|
+
try {
|
|
995
|
+
const pkgRaw = await readFile6(path8.join(cwd, "package.json"), "utf8");
|
|
996
|
+
const pkg = JSON.parse(pkgRaw);
|
|
997
|
+
project_description = pkg.description;
|
|
998
|
+
project_homepage = pkg.homepage;
|
|
999
|
+
if (typeof pkg.bugs === "string") project_bugs = pkg.bugs;
|
|
1000
|
+
else if (pkg.bugs && typeof pkg.bugs.url === "string") project_bugs = pkg.bugs.url;
|
|
1001
|
+
} catch {
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
const resolvedRoot = nodeModulesPath ? nodeModulesPath : ctx === "global" ? await bunPmRootGlobal().catch(() => void 0) : await bunPmRootLocal(cwd).catch(() => `${cwd}/node_modules`);
|
|
1005
|
+
const report = await buildReportFromNpmTree(tree, {
|
|
1006
|
+
context: ctx,
|
|
1007
|
+
includeTree: Boolean(options.fullTree),
|
|
1008
|
+
omitDev: Boolean(options.omitDev),
|
|
1009
|
+
cwd,
|
|
1010
|
+
toolVersion,
|
|
1011
|
+
globalRoot: resolvedRoot
|
|
1012
|
+
});
|
|
1013
|
+
const markdownExtras = { project_description, project_homepage, project_bugs };
|
|
1014
|
+
return { report, markdownExtras };
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// src/runtimes/bun/commands.ts
|
|
1018
|
+
function addCommonOptions2(cmd, { allowOmitDev }) {
|
|
1019
|
+
cmd.option(
|
|
1020
|
+
"-f, --output-format <format>",
|
|
1021
|
+
"Output format: md or json",
|
|
1022
|
+
(val) => val === "md" ? "md" : "json",
|
|
1023
|
+
"json"
|
|
1024
|
+
).option("-o, --out-file <path>", "Write report to file").option("--full-tree", "Include full bun pm ls tree (when available)", false).option("-c, --check-outdated", "List outdated packages instead of printing the report", false).option(
|
|
1025
|
+
"-u, --update-outdated [packages...]",
|
|
1026
|
+
"Update outdated packages (omit package names to update every package)"
|
|
1027
|
+
);
|
|
1028
|
+
if (allowOmitDev) {
|
|
1029
|
+
cmd.option("--omit-dev", "Exclude devDependencies (local only)", false);
|
|
1030
|
+
}
|
|
1031
|
+
return cmd;
|
|
1032
|
+
}
|
|
1033
|
+
function createLocalCommand2(program) {
|
|
1034
|
+
const localCmd = program.command("local", { isDefault: true }).description("Generate a report for the current Bun project's dependencies");
|
|
1035
|
+
addCommonOptions2(localCmd, { allowOmitDev: true });
|
|
1036
|
+
localCmd.action(async (opts) => {
|
|
1037
|
+
const outputFormat = opts.outputFormat ?? "json";
|
|
1038
|
+
const outFile = opts.outFile;
|
|
1039
|
+
const fullTree = Boolean(opts.fullTree);
|
|
1040
|
+
const omitDev = Boolean(opts.omitDev);
|
|
1041
|
+
const cwd = process.cwd();
|
|
1042
|
+
const selection = normalizeUpdateSelection(opts.updateOutdated);
|
|
1043
|
+
const result = await handleOutdatedWorkflow({
|
|
1044
|
+
checkOutdated: Boolean(opts.checkOutdated),
|
|
1045
|
+
selection,
|
|
1046
|
+
contextLabel: "local",
|
|
1047
|
+
outFile,
|
|
1048
|
+
fetchOutdated: async () => {
|
|
1049
|
+
const tree = await bunPmLs({ cwd, omitDev });
|
|
1050
|
+
const manifest = await readPackageManifest(cwd);
|
|
1051
|
+
const declared = {
|
|
1052
|
+
...manifest?.dependencies || {},
|
|
1053
|
+
...manifest?.optionalDependencies || {},
|
|
1054
|
+
...manifest?.devDependencies || {}
|
|
1055
|
+
};
|
|
1056
|
+
const packages = Object.entries(tree.dependencies).map(([name, node]) => ({
|
|
1057
|
+
name,
|
|
1058
|
+
current: node.version,
|
|
1059
|
+
declared: declared[name],
|
|
1060
|
+
type: "prod"
|
|
1061
|
+
}));
|
|
1062
|
+
if (tree.devDependencies) {
|
|
1063
|
+
for (const [name, node] of Object.entries(tree.devDependencies)) {
|
|
1064
|
+
packages.push({
|
|
1065
|
+
name,
|
|
1066
|
+
current: node.version,
|
|
1067
|
+
declared: declared[name],
|
|
1068
|
+
type: "dev"
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
return resolveOutdatedWithNpmView(packages);
|
|
1073
|
+
},
|
|
1074
|
+
updateRunner: selection.shouldUpdate ? async (packages) => {
|
|
1075
|
+
await bunUpdate({ cwd, packages });
|
|
1076
|
+
} : void 0
|
|
1077
|
+
});
|
|
1078
|
+
if (opts.checkOutdated) {
|
|
1079
|
+
if (result.outdated.length === 0) console.log("All local packages are up to date.");
|
|
1080
|
+
else console.log(formatOutdatedTable(result.outdated));
|
|
1081
|
+
}
|
|
1082
|
+
if (!result.proceed) return;
|
|
1083
|
+
const finalOutFile = outFile;
|
|
1084
|
+
const { report, markdownExtras } = await produceReport2("local", {
|
|
1085
|
+
outputFormat,
|
|
1086
|
+
outFile: finalOutFile,
|
|
1087
|
+
fullTree,
|
|
1088
|
+
omitDev
|
|
1089
|
+
});
|
|
1090
|
+
await outputReport(report, outputFormat, finalOutFile, markdownExtras);
|
|
1091
|
+
});
|
|
1092
|
+
return localCmd;
|
|
1093
|
+
}
|
|
1094
|
+
function createGlobalCommand2(program) {
|
|
1095
|
+
const globalCmd = program.command("global").description("Generate a report of globally installed Bun packages");
|
|
1096
|
+
addCommonOptions2(globalCmd, { allowOmitDev: false });
|
|
1097
|
+
globalCmd.action(async (opts) => {
|
|
1098
|
+
const outputFormat = opts.outputFormat ?? "json";
|
|
1099
|
+
const outFile = opts.outFile;
|
|
1100
|
+
const fullTree = Boolean(opts.fullTree);
|
|
1101
|
+
const cwd = process.cwd();
|
|
1102
|
+
const selection = normalizeUpdateSelection(opts.updateOutdated);
|
|
1103
|
+
const result = await handleOutdatedWorkflow({
|
|
1104
|
+
checkOutdated: Boolean(opts.checkOutdated),
|
|
1105
|
+
selection,
|
|
1106
|
+
contextLabel: "global",
|
|
1107
|
+
outFile,
|
|
1108
|
+
fetchOutdated: async () => {
|
|
1109
|
+
const tree = await bunPmLs({ global: true });
|
|
1110
|
+
const packages = Object.entries(tree.dependencies).map(([name, node]) => ({
|
|
1111
|
+
name,
|
|
1112
|
+
current: node.version,
|
|
1113
|
+
type: "global"
|
|
1114
|
+
}));
|
|
1115
|
+
return resolveOutdatedWithNpmView(packages);
|
|
1116
|
+
},
|
|
1117
|
+
updateRunner: selection.shouldUpdate ? async (packages) => {
|
|
1118
|
+
await bunUpdate({ cwd, global: true, packages });
|
|
1119
|
+
} : void 0
|
|
1120
|
+
});
|
|
1121
|
+
if (opts.checkOutdated) {
|
|
1122
|
+
if (result.outdated.length === 0) console.log("All global packages are up to date.");
|
|
1123
|
+
else console.log(formatOutdatedTable(result.outdated));
|
|
1124
|
+
}
|
|
1125
|
+
if (!result.proceed) return;
|
|
1126
|
+
const finalOutFile = outFile;
|
|
1127
|
+
const { report, markdownExtras } = await produceReport2("global", {
|
|
1128
|
+
outputFormat,
|
|
1129
|
+
outFile: finalOutFile,
|
|
1130
|
+
fullTree
|
|
1131
|
+
});
|
|
1132
|
+
await outputReport(report, outputFormat, finalOutFile, markdownExtras);
|
|
1133
|
+
});
|
|
1134
|
+
return globalCmd;
|
|
1135
|
+
}
|
|
1136
|
+
function createReadCommand2(program) {
|
|
1137
|
+
const readCmd = program.command("read").description(
|
|
1138
|
+
"Read a previously generated report (JSON or Markdown) and either print package names or install them"
|
|
1139
|
+
).argument("[report]", "Path to report file (JSON or Markdown)", "bun-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 using Bun", false);
|
|
1140
|
+
readCmd.action(async (reportArg, opts) => {
|
|
1141
|
+
const chosen = opts.report || reportArg || "bun-report.json";
|
|
1142
|
+
const reportPath = path9.resolve(process.cwd(), chosen);
|
|
1143
|
+
try {
|
|
1144
|
+
const parsed = await loadReportFromFile(reportPath);
|
|
1145
|
+
const doInstall = Boolean(opts.install);
|
|
1146
|
+
const doPrint = Boolean(opts.print) || !doInstall;
|
|
1147
|
+
if (doPrint) {
|
|
1148
|
+
printFromReport(parsed);
|
|
1149
|
+
}
|
|
1150
|
+
if (doInstall) {
|
|
1151
|
+
await installFromReport(parsed, { cwd: process.cwd(), packageManager: "bun" });
|
|
1152
|
+
}
|
|
1153
|
+
} catch (err) {
|
|
1154
|
+
const isMd = isMarkdownReportFile(reportPath);
|
|
1155
|
+
const hint = isMd ? "Try generating a JSON report with: gex-bun global -f json -o global.json, then: gex-bun read global.json" : "Specify a report path with: gex-bun read <path-to-report.json>";
|
|
1156
|
+
console.error(`Failed to read report at ${reportPath}: ${err?.message || err}`);
|
|
1157
|
+
console.error(hint);
|
|
1158
|
+
process.exitCode = 1;
|
|
1159
|
+
}
|
|
1160
|
+
});
|
|
1161
|
+
return readCmd;
|
|
1162
|
+
}
|
|
1163
|
+
async function createProgram2() {
|
|
1164
|
+
const program = new Command2().name("gex-bun").description("GEX: Dependency auditing and documentation for Bun (local and global).").version(await getToolVersion());
|
|
1165
|
+
program.addHelpText("beforeAll", `
|
|
1166
|
+
${ASCII_BANNER}`);
|
|
1167
|
+
createLocalCommand2(program);
|
|
1168
|
+
createGlobalCommand2(program);
|
|
1169
|
+
createReadCommand2(program);
|
|
1170
|
+
return program;
|
|
1171
|
+
}
|
|
1172
|
+
async function readPackageManifest(cwd) {
|
|
1173
|
+
try {
|
|
1174
|
+
const raw = await readFile7(path9.join(cwd, "package.json"), "utf8");
|
|
1175
|
+
return JSON.parse(raw);
|
|
1176
|
+
} catch {
|
|
1177
|
+
return null;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
// src/runtimes/bun/cli.ts
|
|
732
1182
|
async function run2(argv = process.argv) {
|
|
733
|
-
|
|
1183
|
+
const program = await createProgram2();
|
|
1184
|
+
await program.parseAsync(argv);
|
|
734
1185
|
}
|
|
735
1186
|
var isMainModule2 = (() => {
|
|
736
1187
|
try {
|
|
@@ -747,11 +1198,70 @@ var isMainModule2 = (() => {
|
|
|
747
1198
|
})();
|
|
748
1199
|
if (isMainModule2) {
|
|
749
1200
|
run2().catch((error) => {
|
|
1201
|
+
console.error("Bun CLI error:", error);
|
|
1202
|
+
process.exitCode = 1;
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
// src/cli.ts
|
|
1207
|
+
async function promptRuntimeSelection(io = {}) {
|
|
1208
|
+
const input = io.input ?? process.stdin;
|
|
1209
|
+
const output = io.output ?? process.stdout;
|
|
1210
|
+
return new Promise((resolve) => {
|
|
1211
|
+
const rl = readline.createInterface({ input, output });
|
|
1212
|
+
output.write("\nSelect a runtime to use:\n");
|
|
1213
|
+
output.write(" 1) gex-bun (Bun package manager)\n");
|
|
1214
|
+
output.write(" 2) gex-npm (npm / Node.js package manager)\n\n");
|
|
1215
|
+
rl.question("Enter your choice (1-2): ", (answer) => {
|
|
1216
|
+
rl.close();
|
|
1217
|
+
const choice = answer.trim().toLowerCase();
|
|
1218
|
+
if (choice === "1" || choice === "gex-bun" || choice === "bun") {
|
|
1219
|
+
resolve("bun");
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
if (choice === "2" || choice === "gex-npm" || choice === "gex-node" || choice === "npm" || choice === "node") {
|
|
1223
|
+
resolve("npm");
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
resolve(null);
|
|
1227
|
+
});
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
async function run3(argv = process.argv, io = {}) {
|
|
1231
|
+
const effectiveArgv = argv ?? process.argv;
|
|
1232
|
+
const choice = await promptRuntimeSelection(io);
|
|
1233
|
+
if (choice === "bun") {
|
|
1234
|
+
await run2(effectiveArgv);
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
if (choice === "npm") {
|
|
1238
|
+
await run(effectiveArgv);
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
const output = io.output ?? process.stdout;
|
|
1242
|
+
output.write("Invalid selection. Please run `gex` again and choose 1 or 2.\n");
|
|
1243
|
+
process.exitCode = 1;
|
|
1244
|
+
}
|
|
1245
|
+
var isMainModule3 = (() => {
|
|
1246
|
+
try {
|
|
1247
|
+
if (typeof __require !== "undefined" && typeof module !== "undefined") {
|
|
1248
|
+
return __require.main === module;
|
|
1249
|
+
}
|
|
1250
|
+
if (typeof import.meta !== "undefined") {
|
|
1251
|
+
return import.meta.url === `file://${process.argv[1]}`;
|
|
1252
|
+
}
|
|
1253
|
+
return false;
|
|
1254
|
+
} catch {
|
|
1255
|
+
return false;
|
|
1256
|
+
}
|
|
1257
|
+
})();
|
|
1258
|
+
if (isMainModule3) {
|
|
1259
|
+
run3().catch((error) => {
|
|
750
1260
|
console.error("CLI error:", error);
|
|
751
1261
|
process.exitCode = 1;
|
|
752
1262
|
});
|
|
753
1263
|
}
|
|
754
1264
|
export {
|
|
755
|
-
|
|
1265
|
+
run3 as run
|
|
756
1266
|
};
|
|
757
1267
|
//# sourceMappingURL=cli.mjs.map
|