@westbayberry/dg 1.0.62 → 1.0.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +889 -599
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1589,6 +1589,49 @@ var require_source = __commonJS({
|
|
|
1589
1589
|
|
|
1590
1590
|
// src/telemetry.ts
|
|
1591
1591
|
import { platform, arch } from "node:os";
|
|
1592
|
+
function telemetryEnabled() {
|
|
1593
|
+
return process.env.DG_TELEMETRY === "1";
|
|
1594
|
+
}
|
|
1595
|
+
function classifyError(err) {
|
|
1596
|
+
const m = (err.message || err.name || "").toLowerCase();
|
|
1597
|
+
if (/http (5\d\d)/.test(m)) {
|
|
1598
|
+
const code = m.match(/http (5\d\d)/)?.[1];
|
|
1599
|
+
return `http_${code ?? "5xx"}`;
|
|
1600
|
+
}
|
|
1601
|
+
if (/timeout|timed out|etimedout/.test(m)) return "network_timeout";
|
|
1602
|
+
if (/socket hang up|econnreset/.test(m)) return "network_reset";
|
|
1603
|
+
if (/enotfound|getaddrinfo/.test(m)) return "dns_failure";
|
|
1604
|
+
if (/certificate|cert_|self.signed/.test(m)) return "tls_failure";
|
|
1605
|
+
if (/econnrefused/.test(m)) return "connection_refused";
|
|
1606
|
+
if (/network|fetch failed/.test(m)) return "network_other";
|
|
1607
|
+
if (/permission denied|eacces/.test(m)) return "permission";
|
|
1608
|
+
if (/enospc/.test(m)) return "disk_full";
|
|
1609
|
+
if (/json|syntax|unexpected token/.test(m)) return "parse_error";
|
|
1610
|
+
if (err.name && err.name !== "Error") return `runtime_${err.name.toLowerCase()}`;
|
|
1611
|
+
return "runtime_error";
|
|
1612
|
+
}
|
|
1613
|
+
function sendCrashEvent(err, ctx) {
|
|
1614
|
+
if (!telemetryEnabled()) return;
|
|
1615
|
+
const apiUrl = process.env.DG_API_URL || "https://api.westbayberry.com";
|
|
1616
|
+
const body = JSON.stringify({
|
|
1617
|
+
error_class: classifyError(err),
|
|
1618
|
+
dg_version: cliVersion || "unknown",
|
|
1619
|
+
node_version: process.version,
|
|
1620
|
+
os_arch: `${platform()} ${arch()}`,
|
|
1621
|
+
command: (process.argv[2] || "unknown").slice(0, 32),
|
|
1622
|
+
batch_size: ctx?.packageCount,
|
|
1623
|
+
duration_ms: void 0
|
|
1624
|
+
});
|
|
1625
|
+
const ctrl = new AbortController();
|
|
1626
|
+
const t = setTimeout(() => ctrl.abort(), 2e3);
|
|
1627
|
+
fetch(`${apiUrl}/v1/cli/error`, {
|
|
1628
|
+
method: "POST",
|
|
1629
|
+
headers: { "Content-Type": "application/json", "User-Agent": `dg-cli/${cliVersion}` },
|
|
1630
|
+
body,
|
|
1631
|
+
signal: ctrl.signal
|
|
1632
|
+
}).catch(() => {
|
|
1633
|
+
}).finally(() => clearTimeout(t));
|
|
1634
|
+
}
|
|
1592
1635
|
function initTelemetry(version) {
|
|
1593
1636
|
if (initialized) return;
|
|
1594
1637
|
initialized = true;
|
|
@@ -1656,17 +1699,42 @@ function buildIssueUrl(error, ctx) {
|
|
|
1656
1699
|
});
|
|
1657
1700
|
return `${GH_ISSUE_URL}?${params.toString()}`;
|
|
1658
1701
|
}
|
|
1702
|
+
function suggestionForClass(klass) {
|
|
1703
|
+
if (klass.startsWith("http_5")) return "Try again in a moment.";
|
|
1704
|
+
if (klass === "network_timeout") return "Try again \u2014 the request timed out.";
|
|
1705
|
+
if (klass === "network_reset" || klass === "connection_refused") return "Try again \u2014 connection was reset.";
|
|
1706
|
+
if (klass === "dns_failure") return "Check your network connection.";
|
|
1707
|
+
if (klass === "tls_failure") return "Check your network's TLS / certificate settings.";
|
|
1708
|
+
if (klass === "permission") return "Check file permissions for the working directory.";
|
|
1709
|
+
if (klass === "disk_full") return "Free up disk space and try again.";
|
|
1710
|
+
if (klass === "parse_error") return "Re-run with DG_DEBUG=1 for details.";
|
|
1711
|
+
return "Re-run with DG_DEBUG=1 for details.";
|
|
1712
|
+
}
|
|
1659
1713
|
function captureError(error, context) {
|
|
1660
1714
|
try {
|
|
1661
1715
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
1716
|
+
sendCrashEvent(err, context);
|
|
1662
1717
|
const chalk18 = chalkOrPlain();
|
|
1663
1718
|
const debug = process.env.DG_DEBUG === "1";
|
|
1719
|
+
const klass = classifyError(err);
|
|
1720
|
+
if (!debug) {
|
|
1721
|
+
const summary = redact(err.message || err.name).slice(0, 120);
|
|
1722
|
+
process.stderr.write(
|
|
1723
|
+
"\n " + chalk18.red.bold("\u2718 dg crashed: ") + chalk18.red(summary) + "\n"
|
|
1724
|
+
);
|
|
1725
|
+
process.stderr.write(
|
|
1726
|
+
" " + chalk18.dim(suggestionForClass(klass)) + "\n\n"
|
|
1727
|
+
);
|
|
1728
|
+
process.exitCode = 1;
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1664
1731
|
const cmd = process.argv.slice(2).join(" ") || "(none)";
|
|
1665
1732
|
process.stderr.write("\n" + chalk18.dim(SEPARATOR) + "\n\n");
|
|
1666
1733
|
process.stderr.write(
|
|
1667
1734
|
" " + chalk18.red.bold("\u2718 dg crashed: ") + chalk18.red(redact(err.message || err.name)) + "\n\n"
|
|
1668
1735
|
);
|
|
1669
1736
|
const rows = [
|
|
1737
|
+
["Class", klass],
|
|
1670
1738
|
["Where", context?.command ?? "(unknown)"],
|
|
1671
1739
|
["CLI", `dg-cli@${cliVersion || "unknown"}`],
|
|
1672
1740
|
["Node", `${process.version} ${platform()} ${arch()}`],
|
|
@@ -1677,22 +1745,16 @@ function captureError(error, context) {
|
|
|
1677
1745
|
process.stderr.write(" " + chalk18.dim(k.padEnd(labelW)) + v + "\n");
|
|
1678
1746
|
}
|
|
1679
1747
|
process.stderr.write("\n");
|
|
1680
|
-
const frames = trimStack(err.stack,
|
|
1748
|
+
const frames = trimStack(err.stack, true);
|
|
1681
1749
|
if (frames.length > 0) {
|
|
1682
1750
|
process.stderr.write(" " + chalk18.dim("Top of stack:") + "\n");
|
|
1683
1751
|
for (const f of frames) process.stderr.write(" " + chalk18.dim(f) + "\n");
|
|
1684
|
-
if (!debug && (err.stack?.split("\n").length ?? 0) > frames.length + 1) {
|
|
1685
|
-
process.stderr.write(" " + chalk18.dim("\u2026 (set DG_DEBUG=1 for the full stack)") + "\n");
|
|
1686
|
-
}
|
|
1687
1752
|
process.stderr.write("\n");
|
|
1688
1753
|
}
|
|
1689
1754
|
if (!suppressNudge()) {
|
|
1690
1755
|
const url = buildIssueUrl(err, context);
|
|
1691
|
-
process.stderr.write(" " + chalk18.dim("
|
|
1756
|
+
process.stderr.write(" " + chalk18.dim("File an issue:") + "\n");
|
|
1692
1757
|
process.stderr.write(" " + chalk18.cyan(url) + "\n");
|
|
1693
|
-
process.stderr.write(
|
|
1694
|
-
" " + chalk18.dim("(version, command, and a redacted stack are pre-filled.") + "\n " + chalk18.dim(" Nothing sent automatically.)") + "\n"
|
|
1695
|
-
);
|
|
1696
1758
|
}
|
|
1697
1759
|
process.stderr.write("\n" + chalk18.dim(SEPARATOR) + "\n\n");
|
|
1698
1760
|
process.exitCode = 1;
|
|
@@ -1782,8 +1844,6 @@ function legacyPaths() {
|
|
|
1782
1844
|
return {
|
|
1783
1845
|
dgrc: join2(home, ".dgrc.json"),
|
|
1784
1846
|
cacheDir: depGuardianDir,
|
|
1785
|
-
cacheSqlite: join2(home, ".dg", "cache.sqlite"),
|
|
1786
|
-
routingHint: join2(home, ".dg", "scan-routing-hint.json"),
|
|
1787
1847
|
updateCheck: join2(home, ".dg-update-check.json"),
|
|
1788
1848
|
trialBannerOld: join2(depGuardianDir, "last-trial-banner"),
|
|
1789
1849
|
aliasesShOld: join2(depGuardianDir, "aliases.sh"),
|
|
@@ -1797,9 +1857,7 @@ function dgPaths() {
|
|
|
1797
1857
|
cacheDir: dgCacheDir(),
|
|
1798
1858
|
stateDir: dgStateDir(),
|
|
1799
1859
|
config: dgConfigPath(),
|
|
1800
|
-
cacheSqlite: dgCachePath("scans.sqlite"),
|
|
1801
1860
|
updateCheck: dgCachePath("update-check.json"),
|
|
1802
|
-
routingHint: dgCachePath("routing-hint.json"),
|
|
1803
1861
|
trialBanner: dgStatePath("trial-banner"),
|
|
1804
1862
|
aliasesSh: dgStatePath("aliases.sh"),
|
|
1805
1863
|
hooksRegistry: dgStatePath("hooks-installed.json"),
|
|
@@ -2278,6 +2336,12 @@ function recordTermsAccepted() {
|
|
|
2278
2336
|
data.termsAcceptedAt = now;
|
|
2279
2337
|
data.privacyAcceptedAt = now;
|
|
2280
2338
|
writeDgrc(data);
|
|
2339
|
+
const verify = readConfig();
|
|
2340
|
+
if (typeof verify.termsAcceptedAt !== "string" || typeof verify.privacyAcceptedAt !== "string") {
|
|
2341
|
+
throw new Error(
|
|
2342
|
+
`wrote ${configPath()} but read-back did not contain termsAcceptedAt/privacyAcceptedAt \u2014 check that the file is on a writable filesystem and not shadowed by a cloud-sync conflict copy`
|
|
2343
|
+
);
|
|
2344
|
+
}
|
|
2281
2345
|
}
|
|
2282
2346
|
function getStackPreference() {
|
|
2283
2347
|
const data = readConfig();
|
|
@@ -2464,18 +2528,11 @@ function loadDgrc() {
|
|
|
2464
2528
|
`);
|
|
2465
2529
|
}
|
|
2466
2530
|
}
|
|
2467
|
-
if (
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
if (k === "apiKey" || k === "apiUrl") continue;
|
|
2473
|
-
if (k in cwd2) config[k] = cwd2[k];
|
|
2474
|
-
}
|
|
2475
|
-
} catch {
|
|
2476
|
-
process.stderr.write(`Warning: Failed to parse ${cwdPath}, ignoring.
|
|
2477
|
-
`);
|
|
2478
|
-
}
|
|
2531
|
+
if (cwdPath !== homePath && cwdPath !== legacyHomePath && existsSync2(cwdPath) && process.env.DG_QUIET !== "1") {
|
|
2532
|
+
process.stderr.write(
|
|
2533
|
+
`dg: note: ./.dgrc.json is ignored (repo-controlled config is no longer honored). Use ~/.dg/.dgrc.json, env vars (DG_MODE, DG_API_URL), or CLI flags.
|
|
2534
|
+
`
|
|
2535
|
+
);
|
|
2479
2536
|
}
|
|
2480
2537
|
return config;
|
|
2481
2538
|
}
|
|
@@ -2646,7 +2703,7 @@ var init_config = __esm({
|
|
|
2646
2703
|
dg pip install <pkg> Same, for pip
|
|
2647
2704
|
dg hook install Block risky lockfile changes at commit time
|
|
2648
2705
|
dg login / dg logout Manage authentication
|
|
2649
|
-
dg update
|
|
2706
|
+
dg update Upgrade dg to the latest version
|
|
2650
2707
|
dg uninstall Remove everything dg has written locally
|
|
2651
2708
|
|
|
2652
2709
|
Common flags:
|
|
@@ -2683,7 +2740,7 @@ var init_config = __esm({
|
|
|
2683
2740
|
uninstall Remove every file dg has written locally (config, cache,
|
|
2684
2741
|
hooks across repos, shell-rc lines)
|
|
2685
2742
|
status Show coverage overview (auth, protect, hook, npm/pip, update)
|
|
2686
|
-
update
|
|
2743
|
+
update Upgrade dg (detects npm/pnpm/yarn/bun; --print to dry-run)
|
|
2687
2744
|
wrap Show instructions to alias npm to dg (manual)
|
|
2688
2745
|
help Show short help (\`dg --help-all\` for this view)
|
|
2689
2746
|
version Show version number
|
|
@@ -2726,6 +2783,7 @@ var init_config = __esm({
|
|
|
2726
2783
|
1 warn \u2014 Risks detected (advisory)
|
|
2727
2784
|
2 block \u2014 High-risk packages detected (or scan refused in block mode)
|
|
2728
2785
|
3 error \u2014 Internal error (API failure, config error)
|
|
2786
|
+
4 analysis_incomplete \u2014 Some packages could not be fully analyzed
|
|
2729
2787
|
|
|
2730
2788
|
What dg actually does:
|
|
2731
2789
|
- \`dg npm install foo\` resolves the FULL dependency tree via
|
|
@@ -3177,15 +3235,29 @@ var init_npm_wrapper = __esm({
|
|
|
3177
3235
|
});
|
|
3178
3236
|
|
|
3179
3237
|
// src/update-check.ts
|
|
3180
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
3238
|
+
import { existsSync as existsSync4, lstatSync as lstatSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
3181
3239
|
import { dirname as dirname3 } from "node:path";
|
|
3182
|
-
import { execFileSync } from "node:child_process";
|
|
3183
3240
|
function cacheFile() {
|
|
3184
3241
|
return dgCachePath("update-check.json");
|
|
3185
3242
|
}
|
|
3186
3243
|
function readCache() {
|
|
3244
|
+
const path2 = cacheFile();
|
|
3245
|
+
let stat = null;
|
|
3246
|
+
try {
|
|
3247
|
+
stat = lstatSync2(path2, { throwIfNoEntry: false }) ?? null;
|
|
3248
|
+
} catch {
|
|
3249
|
+
return null;
|
|
3250
|
+
}
|
|
3251
|
+
if (!stat) return null;
|
|
3252
|
+
if (!stat.isFile() || stat.size > MAX_CACHE_BYTES) {
|
|
3253
|
+
try {
|
|
3254
|
+
unlinkSync2(path2);
|
|
3255
|
+
} catch {
|
|
3256
|
+
}
|
|
3257
|
+
return null;
|
|
3258
|
+
}
|
|
3187
3259
|
try {
|
|
3188
|
-
const raw = readFileSync4(
|
|
3260
|
+
const raw = readFileSync4(path2, "utf-8");
|
|
3189
3261
|
const data = JSON.parse(raw);
|
|
3190
3262
|
if (typeof data.latest === "string" && typeof data.checkedAt === "number") {
|
|
3191
3263
|
return data;
|
|
@@ -3199,7 +3271,9 @@ function writeCache(entry) {
|
|
|
3199
3271
|
const path2 = cacheFile();
|
|
3200
3272
|
const parent = dirname3(path2);
|
|
3201
3273
|
if (!existsSync4(parent)) mkdirSync2(parent, { recursive: true, mode: 448 });
|
|
3202
|
-
|
|
3274
|
+
const serialized = JSON.stringify(entry);
|
|
3275
|
+
if (serialized.length > MAX_CACHE_BYTES) return;
|
|
3276
|
+
writeFileSync3(path2, serialized, { encoding: "utf-8", mode: 384 });
|
|
3203
3277
|
} catch {
|
|
3204
3278
|
}
|
|
3205
3279
|
}
|
|
@@ -3259,47 +3333,14 @@ async function checkForUpdate(currentVersion) {
|
|
|
3259
3333
|
}
|
|
3260
3334
|
return null;
|
|
3261
3335
|
}
|
|
3262
|
-
|
|
3263
|
-
const chalk18 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
|
|
3264
|
-
process.stderr.write(chalk18.dim(" Checking for updates...\n"));
|
|
3265
|
-
const latest = await fetchLatestVersion();
|
|
3266
|
-
if (!latest) {
|
|
3267
|
-
process.stderr.write(chalk18.red(" Could not reach npm registry.\n"));
|
|
3268
|
-
process.exit(1);
|
|
3269
|
-
}
|
|
3270
|
-
if (!isNewer(latest, currentVersion)) {
|
|
3271
|
-
process.stderr.write(
|
|
3272
|
-
chalk18.green(` Already on latest version (${currentVersion}).
|
|
3273
|
-
`)
|
|
3274
|
-
);
|
|
3275
|
-
return;
|
|
3276
|
-
}
|
|
3277
|
-
process.stderr.write(chalk18.dim(` Installing ${PKG_NAME}@${latest}...
|
|
3278
|
-
`));
|
|
3279
|
-
try {
|
|
3280
|
-
execFileSync("npm", ["install", "-g", `${PKG_NAME}@${latest}`], { stdio: "inherit" });
|
|
3281
|
-
writeCache({ latest, checkedAt: Date.now() });
|
|
3282
|
-
process.stderr.write(
|
|
3283
|
-
chalk18.green(`
|
|
3284
|
-
Updated ${currentVersion} \u2192 ${latest}
|
|
3285
|
-
`)
|
|
3286
|
-
);
|
|
3287
|
-
} catch {
|
|
3288
|
-
process.stderr.write(
|
|
3289
|
-
chalk18.red(`
|
|
3290
|
-
Update failed. Try manually: npm i -g ${PKG_NAME}@${latest}
|
|
3291
|
-
`)
|
|
3292
|
-
);
|
|
3293
|
-
process.exit(1);
|
|
3294
|
-
}
|
|
3295
|
-
}
|
|
3296
|
-
var PKG_NAME, CHECK_INTERVAL_MS;
|
|
3336
|
+
var PKG_NAME, CHECK_INTERVAL_MS, MAX_CACHE_BYTES;
|
|
3297
3337
|
var init_update_check = __esm({
|
|
3298
3338
|
"src/update-check.ts"() {
|
|
3299
3339
|
"use strict";
|
|
3300
3340
|
init_paths();
|
|
3301
3341
|
PKG_NAME = "@westbayberry/dg";
|
|
3302
3342
|
CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
3343
|
+
MAX_CACHE_BYTES = 64 * 1024;
|
|
3303
3344
|
}
|
|
3304
3345
|
});
|
|
3305
3346
|
|
|
@@ -37562,6 +37603,45 @@ var init_walker = __esm({
|
|
|
37562
37603
|
}
|
|
37563
37604
|
});
|
|
37564
37605
|
|
|
37606
|
+
// src/security/safe_git.ts
|
|
37607
|
+
import { execFileSync } from "node:child_process";
|
|
37608
|
+
function safeGit(args, opts) {
|
|
37609
|
+
return execFileSync("git", [...HARDENING_ARGS, ...args], {
|
|
37610
|
+
...opts,
|
|
37611
|
+
encoding: "utf-8",
|
|
37612
|
+
stdio: opts.stdio ?? ["pipe", "pipe", "pipe"],
|
|
37613
|
+
env: { ...process.env, ...HARDENING_ENV, ...opts.env ?? {} }
|
|
37614
|
+
});
|
|
37615
|
+
}
|
|
37616
|
+
var HARDENING_ARGS, HARDENING_ENV;
|
|
37617
|
+
var init_safe_git = __esm({
|
|
37618
|
+
"src/security/safe_git.ts"() {
|
|
37619
|
+
"use strict";
|
|
37620
|
+
HARDENING_ARGS = [
|
|
37621
|
+
"-c",
|
|
37622
|
+
"core.fsmonitor=",
|
|
37623
|
+
"-c",
|
|
37624
|
+
"core.hooksPath=/dev/null",
|
|
37625
|
+
"-c",
|
|
37626
|
+
"core.editor=true",
|
|
37627
|
+
"-c",
|
|
37628
|
+
"core.pager=cat",
|
|
37629
|
+
"-c",
|
|
37630
|
+
"core.sshCommand=false",
|
|
37631
|
+
"-c",
|
|
37632
|
+
"protocol.allow=user"
|
|
37633
|
+
];
|
|
37634
|
+
HARDENING_ENV = {
|
|
37635
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
37636
|
+
GIT_OPTIONAL_LOCKS: "0",
|
|
37637
|
+
GIT_ASKPASS: "true",
|
|
37638
|
+
SSH_ASKPASS: "true",
|
|
37639
|
+
GIT_CONFIG_NOSYSTEM: "1",
|
|
37640
|
+
GIT_CONFIG_GLOBAL: "/dev/null"
|
|
37641
|
+
};
|
|
37642
|
+
}
|
|
37643
|
+
});
|
|
37644
|
+
|
|
37565
37645
|
// src/state/hooks_registry.ts
|
|
37566
37646
|
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync5, chmodSync as chmodSync3 } from "node:fs";
|
|
37567
37647
|
import { dirname as dirname5, isAbsolute as isAbsolute2, normalize } from "node:path";
|
|
@@ -37680,21 +37760,20 @@ __export(hook_exports, {
|
|
|
37680
37760
|
uninstallHookFromRepo: () => uninstallHookFromRepo,
|
|
37681
37761
|
verifyHookInstalled: () => verifyHookInstalled
|
|
37682
37762
|
});
|
|
37683
|
-
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
37684
37763
|
import {
|
|
37685
37764
|
existsSync as existsSync8,
|
|
37686
|
-
lstatSync as
|
|
37765
|
+
lstatSync as lstatSync3,
|
|
37687
37766
|
readFileSync as readFileSync8,
|
|
37688
37767
|
writeFileSync as writeFileSync6,
|
|
37689
37768
|
mkdirSync as mkdirSync5,
|
|
37690
37769
|
chmodSync as chmodSync4,
|
|
37691
|
-
unlinkSync as
|
|
37770
|
+
unlinkSync as unlinkSync4
|
|
37692
37771
|
} from "node:fs";
|
|
37693
37772
|
import { join as join6, dirname as dirname6, resolve as resolvePath, isAbsolute as isAbsolute3 } from "node:path";
|
|
37694
37773
|
function assertSafeWriteTarget(target) {
|
|
37695
37774
|
const parent = dirname6(target);
|
|
37696
37775
|
try {
|
|
37697
|
-
const parentStat =
|
|
37776
|
+
const parentStat = lstatSync3(parent);
|
|
37698
37777
|
if (parentStat.isSymbolicLink()) {
|
|
37699
37778
|
throw new Error(
|
|
37700
37779
|
`refusing to write to ${target}: parent dir ${parent} is a symlink (possible path-traversal attack)`
|
|
@@ -37706,7 +37785,7 @@ function assertSafeWriteTarget(target) {
|
|
|
37706
37785
|
}
|
|
37707
37786
|
}
|
|
37708
37787
|
try {
|
|
37709
|
-
const targetStat =
|
|
37788
|
+
const targetStat = lstatSync3(target);
|
|
37710
37789
|
if (targetStat.isSymbolicLink()) {
|
|
37711
37790
|
throw new Error(
|
|
37712
37791
|
`refusing to write to ${target}: target is a symlink (possible path-traversal attack)`
|
|
@@ -37724,20 +37803,14 @@ function safeWriteFileSync(target, content) {
|
|
|
37724
37803
|
}
|
|
37725
37804
|
function findHooksDir() {
|
|
37726
37805
|
try {
|
|
37727
|
-
return
|
|
37728
|
-
encoding: "utf-8",
|
|
37729
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
37730
|
-
}).trim();
|
|
37806
|
+
return safeGit(["rev-parse", "--git-path", "hooks"], { cwd: process.cwd() }).trim();
|
|
37731
37807
|
} catch {
|
|
37732
37808
|
throw new Error("Not a git repository. Run this from inside a git project.");
|
|
37733
37809
|
}
|
|
37734
37810
|
}
|
|
37735
37811
|
function findRepoRoot() {
|
|
37736
37812
|
try {
|
|
37737
|
-
return
|
|
37738
|
-
encoding: "utf-8",
|
|
37739
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
37740
|
-
}).trim();
|
|
37813
|
+
return safeGit(["rev-parse", "--show-toplevel"], { cwd: process.cwd() }).trim();
|
|
37741
37814
|
} catch {
|
|
37742
37815
|
throw new Error("Not a git repository. Run this from inside a git project.");
|
|
37743
37816
|
}
|
|
@@ -37799,7 +37872,7 @@ function verifyHookInstalled(info) {
|
|
|
37799
37872
|
}
|
|
37800
37873
|
if (info.framework === "bare" || info.framework === "husky") {
|
|
37801
37874
|
try {
|
|
37802
|
-
const mode =
|
|
37875
|
+
const mode = lstatSync3(info.targetFile).mode & 511;
|
|
37803
37876
|
if ((mode & 73) === 0) {
|
|
37804
37877
|
return { ok: false, reason: `hook is not executable (mode ${mode.toString(8)})` };
|
|
37805
37878
|
}
|
|
@@ -37951,7 +38024,7 @@ function stripDgFromHookFile(hookPath, framework, repoPath) {
|
|
|
37951
38024
|
return { status: "not-found", hookPath, repoPath };
|
|
37952
38025
|
}
|
|
37953
38026
|
if (framework === "bare" && content.trimStart().startsWith("#!/bin/sh\n" + HOOK_MARKER)) {
|
|
37954
|
-
|
|
38027
|
+
unlinkSync4(hookPath);
|
|
37955
38028
|
removeEntry(repoPath, hookPath);
|
|
37956
38029
|
return { status: "removed", hookPath, repoPath };
|
|
37957
38030
|
}
|
|
@@ -37964,7 +38037,7 @@ function stripDgFromHookFile(hookPath, framework, repoPath) {
|
|
|
37964
38037
|
const after = content.slice(endIdx + MARKER_END.length).trimStart();
|
|
37965
38038
|
const remaining = (before + (after ? "\n" + after : "")).trimEnd() + "\n";
|
|
37966
38039
|
if (remaining.trim() === "" || remaining.trim() === "#!/bin/sh") {
|
|
37967
|
-
|
|
38040
|
+
unlinkSync4(hookPath);
|
|
37968
38041
|
} else {
|
|
37969
38042
|
safeWriteFileSync(hookPath, remaining);
|
|
37970
38043
|
}
|
|
@@ -38012,7 +38085,7 @@ function uninstallHookFromRepo(repoRootOverride) {
|
|
|
38012
38085
|
return { status: "not-found", hookPath, repoPath: root };
|
|
38013
38086
|
}
|
|
38014
38087
|
if (content.trimStart().startsWith("#!/bin/sh\n" + HOOK_MARKER)) {
|
|
38015
|
-
|
|
38088
|
+
unlinkSync4(hookPath);
|
|
38016
38089
|
removeEntry(root, hookPath);
|
|
38017
38090
|
return { status: "removed", hookPath, repoPath: root };
|
|
38018
38091
|
}
|
|
@@ -38026,7 +38099,7 @@ function uninstallHookFromRepo(repoRootOverride) {
|
|
|
38026
38099
|
removeEntry(root, hookPath);
|
|
38027
38100
|
return { status: "removed", hookPath, repoPath: root };
|
|
38028
38101
|
}
|
|
38029
|
-
|
|
38102
|
+
unlinkSync4(hookPath);
|
|
38030
38103
|
removeEntry(root, hookPath);
|
|
38031
38104
|
return { status: "removed", hookPath, repoPath: root };
|
|
38032
38105
|
}
|
|
@@ -38079,6 +38152,7 @@ var HOOK_MARKER, MARKER_START, MARKER_END, LEFTHOOK_MARKER, HOOK_SCRIPT, HOOK_SE
|
|
|
38079
38152
|
var init_hook = __esm({
|
|
38080
38153
|
"src/commands/hook.ts"() {
|
|
38081
38154
|
"use strict";
|
|
38155
|
+
init_safe_git();
|
|
38082
38156
|
init_hooks_registry();
|
|
38083
38157
|
HOOK_MARKER = "# dependency-guardian-hook";
|
|
38084
38158
|
MARKER_START = "# dependency-guardian-hook-start";
|
|
@@ -38167,6 +38241,41 @@ ${MARKER_END}
|
|
|
38167
38241
|
}
|
|
38168
38242
|
});
|
|
38169
38243
|
|
|
38244
|
+
// src/security/sanitize.ts
|
|
38245
|
+
import { stripVTControlCharacters } from "node:util";
|
|
38246
|
+
function sanitize(s) {
|
|
38247
|
+
return stripVTControlCharacters(s);
|
|
38248
|
+
}
|
|
38249
|
+
function sanitizeDeep(value) {
|
|
38250
|
+
if (typeof value === "string") {
|
|
38251
|
+
return stripVTControlCharacters(value);
|
|
38252
|
+
}
|
|
38253
|
+
if (value === null || value === void 0) {
|
|
38254
|
+
return value;
|
|
38255
|
+
}
|
|
38256
|
+
if (Array.isArray(value)) {
|
|
38257
|
+
return value.map((v) => sanitizeDeep(v));
|
|
38258
|
+
}
|
|
38259
|
+
if (typeof value === "object") {
|
|
38260
|
+
const src = value;
|
|
38261
|
+
const out = {};
|
|
38262
|
+
for (const k of Object.keys(src)) {
|
|
38263
|
+
const cleanKey = stripVTControlCharacters(k);
|
|
38264
|
+
out[cleanKey] = sanitizeDeep(src[k]);
|
|
38265
|
+
}
|
|
38266
|
+
return out;
|
|
38267
|
+
}
|
|
38268
|
+
return value;
|
|
38269
|
+
}
|
|
38270
|
+
function sanitizeResponse(response) {
|
|
38271
|
+
return sanitizeDeep(response);
|
|
38272
|
+
}
|
|
38273
|
+
var init_sanitize = __esm({
|
|
38274
|
+
"src/security/sanitize.ts"() {
|
|
38275
|
+
"use strict";
|
|
38276
|
+
}
|
|
38277
|
+
});
|
|
38278
|
+
|
|
38170
38279
|
// src/lockfile/parse_package_lock.ts
|
|
38171
38280
|
function addLockfileEntry(packages, name, entry) {
|
|
38172
38281
|
const existing = packages.get(name);
|
|
@@ -38276,17 +38385,31 @@ var init_parse_package_lock = __esm({
|
|
|
38276
38385
|
});
|
|
38277
38386
|
|
|
38278
38387
|
// src/lockfile/parse_yarn_lock.ts
|
|
38388
|
+
function parseEntryKey(firstSpec) {
|
|
38389
|
+
const npmAliasIdx = firstSpec.indexOf("@npm:");
|
|
38390
|
+
if (npmAliasIdx > 0) {
|
|
38391
|
+
const alias = firstSpec.slice(0, npmAliasIdx);
|
|
38392
|
+
const realSpec = firstSpec.slice(npmAliasIdx + "@npm:".length);
|
|
38393
|
+
const atIdx2 = realSpec.startsWith("@") ? realSpec.indexOf("@", 1) : realSpec.indexOf("@");
|
|
38394
|
+
const name = atIdx2 > 0 ? realSpec.slice(0, atIdx2) : realSpec;
|
|
38395
|
+
return { name: name || null, alias: alias || void 0 };
|
|
38396
|
+
}
|
|
38397
|
+
const atIdx = firstSpec.startsWith("@") ? firstSpec.indexOf("@", 1) : firstSpec.indexOf("@");
|
|
38398
|
+
return { name: atIdx > 0 ? firstSpec.slice(0, atIdx) : null };
|
|
38399
|
+
}
|
|
38279
38400
|
function parseYarnLock(content) {
|
|
38280
38401
|
const packages = /* @__PURE__ */ new Map();
|
|
38281
38402
|
const lines = content.split("\n");
|
|
38282
38403
|
let currentName = null;
|
|
38404
|
+
let currentAlias = void 0;
|
|
38283
38405
|
let currentEntry = {};
|
|
38284
38406
|
const flush2 = () => {
|
|
38285
38407
|
if (currentName && currentEntry.version) {
|
|
38286
38408
|
addLockfileEntry(packages, currentName, {
|
|
38287
38409
|
version: currentEntry.version,
|
|
38288
38410
|
resolved: currentEntry.resolved,
|
|
38289
|
-
integrity: currentEntry.integrity
|
|
38411
|
+
integrity: currentEntry.integrity,
|
|
38412
|
+
alias: currentAlias
|
|
38290
38413
|
});
|
|
38291
38414
|
}
|
|
38292
38415
|
};
|
|
@@ -38294,6 +38417,7 @@ function parseYarnLock(content) {
|
|
|
38294
38417
|
if (line.startsWith("#") || line.trim() === "") {
|
|
38295
38418
|
flush2();
|
|
38296
38419
|
currentName = null;
|
|
38420
|
+
currentAlias = void 0;
|
|
38297
38421
|
currentEntry = {};
|
|
38298
38422
|
continue;
|
|
38299
38423
|
}
|
|
@@ -38301,8 +38425,9 @@ function parseYarnLock(content) {
|
|
|
38301
38425
|
flush2();
|
|
38302
38426
|
const raw = line.slice(0, -1);
|
|
38303
38427
|
const firstSpec = raw.split(",")[0].trim().replace(/^"/, "").replace(/"$/, "");
|
|
38304
|
-
const
|
|
38305
|
-
currentName =
|
|
38428
|
+
const parsed = parseEntryKey(firstSpec);
|
|
38429
|
+
currentName = parsed.name;
|
|
38430
|
+
currentAlias = parsed.alias;
|
|
38306
38431
|
currentEntry = {};
|
|
38307
38432
|
continue;
|
|
38308
38433
|
}
|
|
@@ -38388,7 +38513,8 @@ function diffLockfiles(base, head, maxPackages, directDeps) {
|
|
|
38388
38513
|
oldVersion,
|
|
38389
38514
|
newVersion: headEntry.version,
|
|
38390
38515
|
isDirect: directDeps?.has(name) ?? false,
|
|
38391
|
-
isDev: headEntry.dev ?? false
|
|
38516
|
+
isDev: headEntry.dev ?? false,
|
|
38517
|
+
alias: headEntry.alias
|
|
38392
38518
|
});
|
|
38393
38519
|
}
|
|
38394
38520
|
}
|
|
@@ -38453,7 +38579,6 @@ var init_parse_package_json = __esm({
|
|
|
38453
38579
|
});
|
|
38454
38580
|
|
|
38455
38581
|
// src/lockfile/index.ts
|
|
38456
|
-
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
38457
38582
|
import { readFileSync as readFileSync9, existsSync as existsSync9, statSync as statSync2 } from "node:fs";
|
|
38458
38583
|
import { join as join7 } from "node:path";
|
|
38459
38584
|
function readFileSafe(path2) {
|
|
@@ -38475,7 +38600,12 @@ function discoverChanges(cwd2, config) {
|
|
|
38475
38600
|
const pyPkgs = parsePythonDepFile(cwd2, pyFile);
|
|
38476
38601
|
for (const p of pyPkgs) {
|
|
38477
38602
|
if (p.version === "latest") continue;
|
|
38478
|
-
pythonPackages.push({
|
|
38603
|
+
pythonPackages.push({
|
|
38604
|
+
name: sanitize(p.name),
|
|
38605
|
+
version: sanitize(p.version),
|
|
38606
|
+
previousVersion: null,
|
|
38607
|
+
isNew: true
|
|
38608
|
+
});
|
|
38479
38609
|
}
|
|
38480
38610
|
break;
|
|
38481
38611
|
}
|
|
@@ -38556,8 +38686,8 @@ function discoverChanges(cwd2, config) {
|
|
|
38556
38686
|
continue;
|
|
38557
38687
|
}
|
|
38558
38688
|
packages.push({
|
|
38559
|
-
name,
|
|
38560
|
-
version: entry.version,
|
|
38689
|
+
name: sanitize(name),
|
|
38690
|
+
version: sanitize(entry.version),
|
|
38561
38691
|
previousVersion: null,
|
|
38562
38692
|
isNew: true
|
|
38563
38693
|
});
|
|
@@ -38602,21 +38732,13 @@ function getDirectDeps(cwd2) {
|
|
|
38602
38732
|
}
|
|
38603
38733
|
function getDefaultBranch(cwd2) {
|
|
38604
38734
|
try {
|
|
38605
|
-
const ref =
|
|
38606
|
-
cwd: cwd2,
|
|
38607
|
-
encoding: "utf-8",
|
|
38608
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
38609
|
-
}).trim();
|
|
38735
|
+
const ref = safeGit(["symbolic-ref", "refs/remotes/origin/HEAD"], { cwd: cwd2 }).trim();
|
|
38610
38736
|
const branch = ref.replace(/^refs\/remotes\/origin\//, "");
|
|
38611
38737
|
if (branch) return branch;
|
|
38612
38738
|
} catch {
|
|
38613
38739
|
}
|
|
38614
38740
|
try {
|
|
38615
|
-
|
|
38616
|
-
cwd: cwd2,
|
|
38617
|
-
encoding: "utf-8",
|
|
38618
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
38619
|
-
});
|
|
38741
|
+
safeGit(["rev-parse", "--verify", "refs/remotes/origin/master"], { cwd: cwd2 });
|
|
38620
38742
|
return "master";
|
|
38621
38743
|
} catch {
|
|
38622
38744
|
}
|
|
@@ -38625,19 +38747,11 @@ function getDefaultBranch(cwd2) {
|
|
|
38625
38747
|
function getGitBaseLockfile(cwd2) {
|
|
38626
38748
|
try {
|
|
38627
38749
|
const defaultBranch = getDefaultBranch(cwd2);
|
|
38628
|
-
const mergeBase =
|
|
38629
|
-
cwd: cwd2,
|
|
38630
|
-
encoding: "utf-8",
|
|
38631
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
38632
|
-
}).trim();
|
|
38750
|
+
const mergeBase = safeGit(["merge-base", "HEAD", defaultBranch], { cwd: cwd2 }).trim();
|
|
38633
38751
|
if (!mergeBase) return null;
|
|
38634
38752
|
for (const name of ["package-lock.json", "yarn.lock", "pnpm-lock.yaml"]) {
|
|
38635
38753
|
try {
|
|
38636
|
-
return
|
|
38637
|
-
cwd: cwd2,
|
|
38638
|
-
encoding: "utf-8",
|
|
38639
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
38640
|
-
});
|
|
38754
|
+
return safeGit(["show", `${mergeBase}:${name}`], { cwd: cwd2 });
|
|
38641
38755
|
} catch {
|
|
38642
38756
|
continue;
|
|
38643
38757
|
}
|
|
@@ -38650,27 +38764,20 @@ function getGitBaseLockfile(cwd2) {
|
|
|
38650
38764
|
function getGitBaseFile(cwd2, filename) {
|
|
38651
38765
|
try {
|
|
38652
38766
|
const defaultBranch = getDefaultBranch(cwd2);
|
|
38653
|
-
const mergeBase =
|
|
38654
|
-
cwd: cwd2,
|
|
38655
|
-
encoding: "utf-8",
|
|
38656
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
38657
|
-
}).trim();
|
|
38767
|
+
const mergeBase = safeGit(["merge-base", "HEAD", defaultBranch], { cwd: cwd2 }).trim();
|
|
38658
38768
|
if (!mergeBase) return null;
|
|
38659
|
-
return
|
|
38660
|
-
cwd: cwd2,
|
|
38661
|
-
encoding: "utf-8",
|
|
38662
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
38663
|
-
});
|
|
38769
|
+
return safeGit(["show", `${mergeBase}:${filename}`], { cwd: cwd2 });
|
|
38664
38770
|
} catch {
|
|
38665
38771
|
return null;
|
|
38666
38772
|
}
|
|
38667
38773
|
}
|
|
38668
38774
|
function toPackageInput(change) {
|
|
38669
38775
|
return {
|
|
38670
|
-
name: change.name,
|
|
38671
|
-
version: change.newVersion,
|
|
38672
|
-
previousVersion: change.oldVersion,
|
|
38673
|
-
isNew: change.oldVersion === null
|
|
38776
|
+
name: sanitize(change.name),
|
|
38777
|
+
version: sanitize(change.newVersion),
|
|
38778
|
+
previousVersion: change.oldVersion === null ? null : sanitize(change.oldVersion),
|
|
38779
|
+
isNew: change.oldVersion === null,
|
|
38780
|
+
alias: change.alias ? sanitize(change.alias) : void 0
|
|
38674
38781
|
};
|
|
38675
38782
|
}
|
|
38676
38783
|
function parsePythonDepFile(projectDir, depFile) {
|
|
@@ -38727,6 +38834,8 @@ var MAX_LOCKFILE_BYTES, SELF_PACKAGE;
|
|
|
38727
38834
|
var init_lockfile = __esm({
|
|
38728
38835
|
"src/lockfile/index.ts"() {
|
|
38729
38836
|
"use strict";
|
|
38837
|
+
init_safe_git();
|
|
38838
|
+
init_sanitize();
|
|
38730
38839
|
init_parse_package_lock();
|
|
38731
38840
|
init_parse_yarn_lock();
|
|
38732
38841
|
init_parse_pnpm_lock();
|
|
@@ -38737,44 +38846,6 @@ var init_lockfile = __esm({
|
|
|
38737
38846
|
}
|
|
38738
38847
|
});
|
|
38739
38848
|
|
|
38740
|
-
// src/security/sanitize.ts
|
|
38741
|
-
import { stripVTControlCharacters } from "node:util";
|
|
38742
|
-
function sanitize(s) {
|
|
38743
|
-
return stripVTControlCharacters(s);
|
|
38744
|
-
}
|
|
38745
|
-
function sanitizeFinding(f) {
|
|
38746
|
-
const result = { severity: f.severity };
|
|
38747
|
-
if (f.category !== void 0) result.category = sanitize(f.category);
|
|
38748
|
-
if (f.title !== void 0) result.title = sanitize(f.title);
|
|
38749
|
-
if (f.evidence !== void 0) result.evidence = f.evidence.map(sanitize);
|
|
38750
|
-
return result;
|
|
38751
|
-
}
|
|
38752
|
-
function sanitizeResponse(response) {
|
|
38753
|
-
const packages = response.packages.map((pkg) => ({
|
|
38754
|
-
name: sanitize(pkg.name),
|
|
38755
|
-
version: sanitize(pkg.version),
|
|
38756
|
-
score: pkg.score,
|
|
38757
|
-
findings: (pkg.findings ?? []).map(sanitizeFinding),
|
|
38758
|
-
reasons: (pkg.reasons ?? []).map(sanitize),
|
|
38759
|
-
recommendation: pkg.recommendation ? sanitize(pkg.recommendation) : void 0,
|
|
38760
|
-
cached: pkg.cached,
|
|
38761
|
-
license: pkg.license
|
|
38762
|
-
}));
|
|
38763
|
-
return {
|
|
38764
|
-
score: response.score,
|
|
38765
|
-
action: response.action,
|
|
38766
|
-
packages,
|
|
38767
|
-
safeVersions: response.safeVersions,
|
|
38768
|
-
durationMs: response.durationMs,
|
|
38769
|
-
trialScansRemaining: response.trialScansRemaining
|
|
38770
|
-
};
|
|
38771
|
-
}
|
|
38772
|
-
var init_sanitize = __esm({
|
|
38773
|
-
"src/security/sanitize.ts"() {
|
|
38774
|
-
"use strict";
|
|
38775
|
-
}
|
|
38776
|
-
});
|
|
38777
|
-
|
|
38778
38849
|
// src/api/client.ts
|
|
38779
38850
|
var client_exports = {};
|
|
38780
38851
|
__export(client_exports, {
|
|
@@ -38984,6 +39055,27 @@ function formatApiErrorMessage(status, rawBody, config) {
|
|
|
38984
39055
|
}
|
|
38985
39056
|
return `API returned ${status}: ${truncated}`;
|
|
38986
39057
|
}
|
|
39058
|
+
async function readBoundedJson(response) {
|
|
39059
|
+
const cl = response.headers?.get?.("content-length");
|
|
39060
|
+
if (cl) {
|
|
39061
|
+
const n = Number(cl);
|
|
39062
|
+
if (Number.isFinite(n) && n > MAX_RESPONSE_BYTES) {
|
|
39063
|
+
throw new APIError("API response exceeded size limit", 502, "");
|
|
39064
|
+
}
|
|
39065
|
+
}
|
|
39066
|
+
if (typeof response.text === "function") {
|
|
39067
|
+
const text = await response.text();
|
|
39068
|
+
if (text.length > MAX_RESPONSE_BYTES) {
|
|
39069
|
+
throw new APIError("API response exceeded size limit", 502, "");
|
|
39070
|
+
}
|
|
39071
|
+
try {
|
|
39072
|
+
return JSON.parse(text);
|
|
39073
|
+
} catch {
|
|
39074
|
+
throw new APIError("Invalid JSON in API response", 502, "");
|
|
39075
|
+
}
|
|
39076
|
+
}
|
|
39077
|
+
return await response.json();
|
|
39078
|
+
}
|
|
38987
39079
|
async function callAnalyzeBatch(packages, config, onPackageProgress) {
|
|
38988
39080
|
const url = `${config.apiUrl}/v1/analyze`;
|
|
38989
39081
|
const payload = {
|
|
@@ -39047,7 +39139,7 @@ async function callAnalyzeBatch(packages, config, onPackageProgress) {
|
|
|
39047
39139
|
if (contentType.includes("application/x-ndjson")) {
|
|
39048
39140
|
return readNdjsonAnalyzeResponse(response, onPackageProgress);
|
|
39049
39141
|
}
|
|
39050
|
-
const raw = await response
|
|
39142
|
+
const raw = await readBoundedJson(response);
|
|
39051
39143
|
if (!raw || typeof raw.score !== "number" || !Array.isArray(raw.packages)) {
|
|
39052
39144
|
throw new APIError("Invalid API response format", 0, "");
|
|
39053
39145
|
}
|
|
@@ -39060,8 +39152,12 @@ async function readNdjsonAnalyzeResponse(response, onPackageProgress) {
|
|
|
39060
39152
|
}
|
|
39061
39153
|
const decoder = new TextDecoder();
|
|
39062
39154
|
let buf = "";
|
|
39155
|
+
let totalBytes = 0;
|
|
39063
39156
|
let finalPayload = null;
|
|
39064
39157
|
const processLine = (raw) => {
|
|
39158
|
+
if (raw.length > MAX_NDJSON_LINE_BYTES) {
|
|
39159
|
+
throw new APIError("API response line exceeded size limit", 502, "");
|
|
39160
|
+
}
|
|
39065
39161
|
const line = raw.trim();
|
|
39066
39162
|
if (!line) return;
|
|
39067
39163
|
let event;
|
|
@@ -39087,21 +39183,47 @@ async function readNdjsonAnalyzeResponse(response, onPackageProgress) {
|
|
|
39087
39183
|
break;
|
|
39088
39184
|
case "error": {
|
|
39089
39185
|
const sc = typeof event.statusCode === "number" ? event.statusCode : 500;
|
|
39090
|
-
const msg = typeof event.error === "string" ? event.error : "Streaming scan failed";
|
|
39091
|
-
throw new APIError(msg, sc,
|
|
39186
|
+
const msg = sanitize(typeof event.error === "string" ? event.error : "Streaming scan failed");
|
|
39187
|
+
throw new APIError(msg, sc, "");
|
|
39092
39188
|
}
|
|
39093
39189
|
case "started":
|
|
39094
39190
|
break;
|
|
39095
39191
|
}
|
|
39096
39192
|
};
|
|
39097
|
-
const
|
|
39098
|
-
|
|
39099
|
-
|
|
39100
|
-
|
|
39101
|
-
|
|
39102
|
-
|
|
39103
|
-
|
|
39104
|
-
|
|
39193
|
+
const reader = response.body.getReader();
|
|
39194
|
+
try {
|
|
39195
|
+
while (true) {
|
|
39196
|
+
const { done, value } = await reader.read();
|
|
39197
|
+
if (done) break;
|
|
39198
|
+
if (value) {
|
|
39199
|
+
totalBytes += value.byteLength;
|
|
39200
|
+
if (totalBytes > MAX_RESPONSE_BYTES) {
|
|
39201
|
+
try {
|
|
39202
|
+
await reader.cancel();
|
|
39203
|
+
} catch {
|
|
39204
|
+
}
|
|
39205
|
+
throw new APIError("API response exceeded size limit", 502, "");
|
|
39206
|
+
}
|
|
39207
|
+
buf += decoder.decode(value, { stream: true });
|
|
39208
|
+
let idx;
|
|
39209
|
+
while ((idx = buf.indexOf("\n")) !== -1) {
|
|
39210
|
+
const line = buf.slice(0, idx);
|
|
39211
|
+
buf = buf.slice(idx + 1);
|
|
39212
|
+
processLine(line);
|
|
39213
|
+
}
|
|
39214
|
+
if (buf.length > MAX_NDJSON_LINE_BYTES) {
|
|
39215
|
+
try {
|
|
39216
|
+
await reader.cancel();
|
|
39217
|
+
} catch {
|
|
39218
|
+
}
|
|
39219
|
+
throw new APIError("API response line exceeded size limit", 502, "");
|
|
39220
|
+
}
|
|
39221
|
+
}
|
|
39222
|
+
}
|
|
39223
|
+
} finally {
|
|
39224
|
+
try {
|
|
39225
|
+
reader.releaseLock();
|
|
39226
|
+
} catch {
|
|
39105
39227
|
}
|
|
39106
39228
|
}
|
|
39107
39229
|
buf += decoder.decode();
|
|
@@ -39205,7 +39327,7 @@ async function callPyPIBatch(packages, config) {
|
|
|
39205
39327
|
body
|
|
39206
39328
|
);
|
|
39207
39329
|
}
|
|
39208
|
-
const raw = await response
|
|
39330
|
+
const raw = await readBoundedJson(response);
|
|
39209
39331
|
if (!raw || typeof raw.score !== "number" || !Array.isArray(raw.packages)) {
|
|
39210
39332
|
throw new APIError("Invalid API response format", 0, "");
|
|
39211
39333
|
}
|
|
@@ -39250,7 +39372,7 @@ async function fetchLicensesBatchAt(endpoint, packages, config) {
|
|
|
39250
39372
|
const body = await response.text();
|
|
39251
39373
|
throw new APIError(formatApiErrorMessage(response.status, body, config), response.status, body);
|
|
39252
39374
|
}
|
|
39253
|
-
const data = await response
|
|
39375
|
+
const data = await readBoundedJson(response);
|
|
39254
39376
|
if (!Array.isArray(data.packages)) {
|
|
39255
39377
|
throw new APIError("Invalid licenses response payload", 0, "");
|
|
39256
39378
|
}
|
|
@@ -39290,7 +39412,7 @@ function fetchLicenses(packages, config, onBatchComplete) {
|
|
|
39290
39412
|
function fetchPyPILicenses(packages, config, onBatchComplete) {
|
|
39291
39413
|
return batchLicenseFetch("/v1/pypi/licenses", packages, config, onBatchComplete);
|
|
39292
39414
|
}
|
|
39293
|
-
var APIError, TrialExhaustedError, ClientOutdatedError, BATCH_SIZE, ANON_BATCH_SIZE, MAX_RETRIES, RETRY_DELAY_MS, DEFAULT_BATCH_CONCURRENCY, _currentScanId, BatchPoolPartialError, LICENSE_BATCH_SIZE;
|
|
39415
|
+
var APIError, TrialExhaustedError, ClientOutdatedError, BATCH_SIZE, ANON_BATCH_SIZE, MAX_RETRIES, RETRY_DELAY_MS, MAX_RESPONSE_BYTES, MAX_NDJSON_LINE_BYTES, DEFAULT_BATCH_CONCURRENCY, _currentScanId, BatchPoolPartialError, LICENSE_BATCH_SIZE;
|
|
39294
39416
|
var init_client = __esm({
|
|
39295
39417
|
"src/api/client.ts"() {
|
|
39296
39418
|
"use strict";
|
|
@@ -39328,6 +39450,8 @@ var init_client = __esm({
|
|
|
39328
39450
|
ANON_BATCH_SIZE = 200;
|
|
39329
39451
|
MAX_RETRIES = 2;
|
|
39330
39452
|
RETRY_DELAY_MS = 5e3;
|
|
39453
|
+
MAX_RESPONSE_BYTES = 50 * 1024 * 1024;
|
|
39454
|
+
MAX_NDJSON_LINE_BYTES = 4 * 1024 * 1024;
|
|
39331
39455
|
DEFAULT_BATCH_CONCURRENCY = 4;
|
|
39332
39456
|
_currentScanId = "";
|
|
39333
39457
|
BatchPoolPartialError = class extends Error {
|
|
@@ -39366,28 +39490,29 @@ async function scanProjectAtPath(cwd2, config, onProgress) {
|
|
|
39366
39490
|
result: EMPTY_OK_RESULT(elapsedMs())
|
|
39367
39491
|
};
|
|
39368
39492
|
}
|
|
39493
|
+
let npmDone = 0;
|
|
39494
|
+
let pyDone = 0;
|
|
39495
|
+
const reportProgress = onProgress ? (current) => onProgress({ done: npmDone + pyDone, total: totalDiscovered, current }) : void 0;
|
|
39496
|
+
const npmPromise = npmPackages.length > 0 ? callAnalyzeAPI(
|
|
39497
|
+
npmPackages,
|
|
39498
|
+
config,
|
|
39499
|
+
reportProgress ? (done, _total, currentBatch) => {
|
|
39500
|
+
npmDone = done;
|
|
39501
|
+
reportProgress(currentBatch ?? []);
|
|
39502
|
+
} : void 0
|
|
39503
|
+
) : Promise.resolve(null);
|
|
39504
|
+
const pyPromise = pyPackages.length > 0 ? callPyPIAnalyzeAPI(
|
|
39505
|
+
pyPackages,
|
|
39506
|
+
config,
|
|
39507
|
+
reportProgress ? (done) => {
|
|
39508
|
+
pyDone = done;
|
|
39509
|
+
reportProgress([]);
|
|
39510
|
+
} : void 0
|
|
39511
|
+
) : Promise.resolve(null);
|
|
39512
|
+
const [npmResp, pyResp] = await Promise.all([npmPromise, pyPromise]);
|
|
39369
39513
|
const responses = [];
|
|
39370
|
-
|
|
39371
|
-
if (
|
|
39372
|
-
const npmOnProgress = onProgress ? (done, _total, currentBatch) => {
|
|
39373
|
-
onProgress({
|
|
39374
|
-
done: cumulativeDone + done,
|
|
39375
|
-
total: totalDiscovered,
|
|
39376
|
-
current: currentBatch ?? []
|
|
39377
|
-
});
|
|
39378
|
-
} : void 0;
|
|
39379
|
-
const npmResp = await callAnalyzeAPI(npmPackages, config, npmOnProgress);
|
|
39380
|
-
responses.push(npmResp);
|
|
39381
|
-
cumulativeDone += npmPackages.length;
|
|
39382
|
-
}
|
|
39383
|
-
if (pyPackages.length > 0) {
|
|
39384
|
-
const pyOnProgress = onProgress ? (done, _total) => {
|
|
39385
|
-
onProgress({ done: cumulativeDone + done, total: totalDiscovered, current: [] });
|
|
39386
|
-
} : void 0;
|
|
39387
|
-
const pyResp = await callPyPIAnalyzeAPI(pyPackages, config, pyOnProgress);
|
|
39388
|
-
responses.push(pyResp);
|
|
39389
|
-
cumulativeDone += pyPackages.length;
|
|
39390
|
-
}
|
|
39514
|
+
if (npmResp) responses.push(npmResp);
|
|
39515
|
+
if (pyResp) responses.push(pyResp);
|
|
39391
39516
|
const allPackages = responses.flatMap((r) => r.packages);
|
|
39392
39517
|
if (allPackages.length === 0) {
|
|
39393
39518
|
const elapsed = elapsedMs();
|
|
@@ -39475,7 +39600,7 @@ __export(protect_exports, {
|
|
|
39475
39600
|
stripAliasSourceFromRc: () => stripAliasSourceFromRc,
|
|
39476
39601
|
suggestedShellRc: () => suggestedShellRc
|
|
39477
39602
|
});
|
|
39478
|
-
import { existsSync as existsSync10, readFileSync as readFileSync10, writeFileSync as writeFileSync7, unlinkSync as
|
|
39603
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10, writeFileSync as writeFileSync7, unlinkSync as unlinkSync5, mkdirSync as mkdirSync6, lstatSync as lstatSync4, appendFileSync } from "node:fs";
|
|
39479
39604
|
import { join as join8, dirname as dirname7 } from "node:path";
|
|
39480
39605
|
import { homedir as homedir3 } from "node:os";
|
|
39481
39606
|
function aliasFile() {
|
|
@@ -39483,7 +39608,7 @@ function aliasFile() {
|
|
|
39483
39608
|
}
|
|
39484
39609
|
function safeIsRegularFile(path2) {
|
|
39485
39610
|
try {
|
|
39486
|
-
const st =
|
|
39611
|
+
const st = lstatSync4(path2);
|
|
39487
39612
|
return st.isFile() && !st.isSymbolicLink();
|
|
39488
39613
|
} catch {
|
|
39489
39614
|
return false;
|
|
@@ -39492,7 +39617,7 @@ function safeIsRegularFile(path2) {
|
|
|
39492
39617
|
function safeWriteFileSync2(target, content, mode = 420) {
|
|
39493
39618
|
const parent = dirname7(target);
|
|
39494
39619
|
try {
|
|
39495
|
-
const parentStat =
|
|
39620
|
+
const parentStat = lstatSync4(parent);
|
|
39496
39621
|
if (parentStat.isSymbolicLink()) {
|
|
39497
39622
|
throw new Error(`refusing to write to ${target}: parent dir is a symlink`);
|
|
39498
39623
|
}
|
|
@@ -39500,7 +39625,7 @@ function safeWriteFileSync2(target, content, mode = 420) {
|
|
|
39500
39625
|
if (e instanceof Error && e.message.startsWith("refusing")) throw e;
|
|
39501
39626
|
}
|
|
39502
39627
|
try {
|
|
39503
|
-
const st =
|
|
39628
|
+
const st = lstatSync4(target);
|
|
39504
39629
|
if (st.isSymbolicLink()) {
|
|
39505
39630
|
throw new Error(`refusing to write to ${target}: target is a symlink`);
|
|
39506
39631
|
}
|
|
@@ -39545,7 +39670,7 @@ function appendAliasSourceToRc(rcPathRaw, sourceLine, opts = {}) {
|
|
|
39545
39670
|
try {
|
|
39546
39671
|
const parent = dirname7(rcPath);
|
|
39547
39672
|
if (existsSync10(parent)) {
|
|
39548
|
-
const parentStat =
|
|
39673
|
+
const parentStat = lstatSync4(parent);
|
|
39549
39674
|
if (parentStat.isSymbolicLink()) {
|
|
39550
39675
|
return { status: "failed", rcPath, reason: "parent directory is a symlink" };
|
|
39551
39676
|
}
|
|
@@ -39556,7 +39681,7 @@ function appendAliasSourceToRc(rcPathRaw, sourceLine, opts = {}) {
|
|
|
39556
39681
|
if (existsSync10(rcPath)) {
|
|
39557
39682
|
let st;
|
|
39558
39683
|
try {
|
|
39559
|
-
st =
|
|
39684
|
+
st = lstatSync4(rcPath);
|
|
39560
39685
|
} catch (e) {
|
|
39561
39686
|
return { status: "failed", rcPath, reason: e.message };
|
|
39562
39687
|
}
|
|
@@ -39720,23 +39845,24 @@ async function runProtectInit(cwd2, opts = {}) {
|
|
|
39720
39845
|
process.stderr.write(import_chalk4.default.dim(` Mode: ${cfg.mode}${cfg.strict ? " \xB7 strict" : ""}
|
|
39721
39846
|
`));
|
|
39722
39847
|
process.stderr.write("\n");
|
|
39723
|
-
|
|
39724
|
-
|
|
39725
|
-
|
|
39726
|
-
|
|
39727
|
-
|
|
39848
|
+
let aliasPath = null;
|
|
39849
|
+
try {
|
|
39850
|
+
aliasPath = writeAliasSnippet();
|
|
39851
|
+
} catch (e) {
|
|
39852
|
+
process.stderr.write(import_chalk4.default.yellow(` Could not write alias snippet: ${e.message}
|
|
39728
39853
|
`));
|
|
39729
|
-
|
|
39730
|
-
|
|
39731
|
-
|
|
39854
|
+
}
|
|
39855
|
+
if (!opts.noShell && aliasPath) {
|
|
39856
|
+
process.stderr.write(import_chalk4.default.bold(" Optional \u2014 alias npm/pip to route through DG:\n"));
|
|
39857
|
+
process.stderr.write(import_chalk4.default.dim(` Wrote ${aliasPath}.
|
|
39732
39858
|
`));
|
|
39733
|
-
|
|
39734
|
-
|
|
39735
|
-
|
|
39736
|
-
} catch (e) {
|
|
39737
|
-
process.stderr.write(import_chalk4.default.yellow(` Could not write alias snippet: ${e.message}
|
|
39859
|
+
process.stderr.write(" Add this line to your shell rc (zshrc/bashrc/profile):\n\n");
|
|
39860
|
+
process.stderr.write(import_chalk4.default.cyan(` source ${aliasPath}
|
|
39861
|
+
|
|
39738
39862
|
`));
|
|
39739
|
-
|
|
39863
|
+
process.stderr.write(import_chalk4.default.dim(" Then reload your shell. `npm install` and `pip install` will\n"));
|
|
39864
|
+
process.stderr.write(import_chalk4.default.dim(" be scanned automatically. To turn this off, remove the line.\n"));
|
|
39865
|
+
process.stderr.write(import_chalk4.default.dim(" To turn off DG protection entirely, run `dg protect off`.\n\n"));
|
|
39740
39866
|
}
|
|
39741
39867
|
return 0;
|
|
39742
39868
|
}
|
|
@@ -39767,7 +39893,7 @@ async function runProtectOff(cwd2, opts = {}) {
|
|
|
39767
39893
|
void cwd2;
|
|
39768
39894
|
if (opts.removeShell && aliasSnippetExists()) {
|
|
39769
39895
|
try {
|
|
39770
|
-
|
|
39896
|
+
unlinkSync5(aliasFile());
|
|
39771
39897
|
process.stderr.write(import_chalk4.default.green(" \u2713 ") + `Removed ${aliasFile()}
|
|
39772
39898
|
`);
|
|
39773
39899
|
removed += 1;
|
|
@@ -40277,94 +40403,46 @@ function useInit(opts = {}) {
|
|
|
40277
40403
|
try {
|
|
40278
40404
|
const config = parseConfig([process.argv[0] ?? "node", "init", "--scan-all"], false);
|
|
40279
40405
|
const projects = state.projects.length > 0 ? state.projects : [{ path: opts.cwd ?? process.cwd() }];
|
|
40280
|
-
const
|
|
40281
|
-
const
|
|
40282
|
-
|
|
40283
|
-
|
|
40284
|
-
|
|
40285
|
-
const isFoundProject = proj.ecosystem !== void 0;
|
|
40286
|
-
const eco = isFoundProject ? proj.ecosystem : null;
|
|
40287
|
-
if (eco === "pypi") {
|
|
40288
|
-
try {
|
|
40289
|
-
for (const pkg of parsePythonDepFile(proj.path, proj.depFile)) {
|
|
40290
|
-
const key = `${pkg.name}@${pkg.version}`;
|
|
40291
|
-
if (!seenPy.has(key)) {
|
|
40292
|
-
seenPy.add(key);
|
|
40293
|
-
pypiPackages.push(pkg);
|
|
40294
|
-
}
|
|
40295
|
-
}
|
|
40296
|
-
} catch {
|
|
40297
|
-
}
|
|
40298
|
-
continue;
|
|
40299
|
-
}
|
|
40406
|
+
const allOutcomes = [];
|
|
40407
|
+
const perProject = /* @__PURE__ */ new Map();
|
|
40408
|
+
for (let i = 0; i < projects.length; i++) {
|
|
40409
|
+
const proj = projects[i];
|
|
40410
|
+
let total = 0;
|
|
40300
40411
|
try {
|
|
40301
40412
|
const d = discoverChanges(proj.path, config);
|
|
40302
|
-
|
|
40303
|
-
const key = `${pkg.name}@${pkg.version}`;
|
|
40304
|
-
if (!seenNpm.has(key)) {
|
|
40305
|
-
seenNpm.add(key);
|
|
40306
|
-
npmPackages.push(pkg);
|
|
40307
|
-
}
|
|
40308
|
-
}
|
|
40309
|
-
for (const pkg of d.pythonPackages ?? []) {
|
|
40310
|
-
const key = `${pkg.name}@${pkg.version}`;
|
|
40311
|
-
if (!seenPy.has(key)) {
|
|
40312
|
-
seenPy.add(key);
|
|
40313
|
-
pypiPackages.push(pkg);
|
|
40314
|
-
}
|
|
40315
|
-
}
|
|
40413
|
+
total = d.packages.length + (d.pythonPackages?.length ?? 0);
|
|
40316
40414
|
} catch {
|
|
40317
40415
|
}
|
|
40416
|
+
perProject.set(i, { done: 0, total });
|
|
40318
40417
|
}
|
|
40319
|
-
const
|
|
40320
|
-
|
|
40321
|
-
|
|
40322
|
-
|
|
40323
|
-
|
|
40324
|
-
|
|
40325
|
-
if (npmPackages.length > 0) {
|
|
40326
|
-
const npmResp = await callAnalyzeAPI(npmPackages, config, (done, _t, currentBatch) => {
|
|
40327
|
-
dispatch({
|
|
40328
|
-
type: "scan_progress",
|
|
40329
|
-
progress: {
|
|
40330
|
-
done: Math.min(cumulativeDone + done, totalUnique),
|
|
40331
|
-
total: totalUnique,
|
|
40332
|
-
current: currentBatch ?? []
|
|
40333
|
-
}
|
|
40334
|
-
});
|
|
40335
|
-
});
|
|
40336
|
-
responses.push(npmResp);
|
|
40337
|
-
cumulativeDone += npmPackages.length;
|
|
40338
|
-
}
|
|
40339
|
-
if (pypiPackages.length > 0) {
|
|
40340
|
-
const pyResp = await callPyPIAnalyzeAPI(pypiPackages, config, (done) => {
|
|
40341
|
-
dispatch({
|
|
40342
|
-
type: "scan_progress",
|
|
40343
|
-
progress: {
|
|
40344
|
-
done: Math.min(cumulativeDone + done, totalUnique),
|
|
40345
|
-
total: totalUnique,
|
|
40346
|
-
current: []
|
|
40347
|
-
}
|
|
40348
|
-
});
|
|
40349
|
-
});
|
|
40350
|
-
responses.push(pyResp);
|
|
40351
|
-
cumulativeDone += pypiPackages.length;
|
|
40418
|
+
const aggregate = (current) => {
|
|
40419
|
+
let done = 0;
|
|
40420
|
+
let total = 0;
|
|
40421
|
+
for (const v of perProject.values()) {
|
|
40422
|
+
done += v.done;
|
|
40423
|
+
total += v.total;
|
|
40352
40424
|
}
|
|
40353
|
-
|
|
40354
|
-
|
|
40355
|
-
|
|
40356
|
-
|
|
40357
|
-
|
|
40358
|
-
|
|
40359
|
-
|
|
40360
|
-
|
|
40425
|
+
return { done, total, current };
|
|
40426
|
+
};
|
|
40427
|
+
dispatch({ type: "scan_progress", progress: aggregate([]) });
|
|
40428
|
+
for (let i = 0; i < projects.length; i++) {
|
|
40429
|
+
const proj = projects[i];
|
|
40430
|
+
if (process.env.DG_DEBUG_WIZARD) process.stderr.write(`[wizard] scanning ${proj.path}
|
|
40431
|
+
`);
|
|
40432
|
+
const seeded = perProject.get(i);
|
|
40433
|
+
const outcome = await scanFn(proj.path, config, (p) => {
|
|
40434
|
+
const total = seeded?.total ?? p.total;
|
|
40435
|
+
perProject.set(i, { done: Math.min(p.done, total), total });
|
|
40436
|
+
dispatch({ type: "scan_progress", progress: aggregate(p.current) });
|
|
40361
40437
|
});
|
|
40362
|
-
|
|
40438
|
+
if (process.env.DG_DEBUG_WIZARD) process.stderr.write(`[wizard] scan done ${proj.path} status=${outcome.status}
|
|
40439
|
+
`);
|
|
40440
|
+
allOutcomes.push(outcome);
|
|
40363
40441
|
}
|
|
40364
40442
|
const allPackages = [];
|
|
40365
40443
|
const seen = /* @__PURE__ */ new Set();
|
|
40366
|
-
for (const
|
|
40367
|
-
for (const pkg of
|
|
40444
|
+
for (const outcome of allOutcomes) {
|
|
40445
|
+
for (const pkg of outcome.result?.result.packages ?? []) {
|
|
40368
40446
|
const key = `${pkg.name}@${pkg.version}`;
|
|
40369
40447
|
if (seen.has(key)) continue;
|
|
40370
40448
|
seen.add(key);
|
|
@@ -40372,22 +40450,42 @@ function useInit(opts = {}) {
|
|
|
40372
40450
|
}
|
|
40373
40451
|
}
|
|
40374
40452
|
const totalScanned = seen.size;
|
|
40375
|
-
const totalDuration =
|
|
40453
|
+
const totalDuration = allOutcomes.reduce(
|
|
40454
|
+
(sum, o) => sum + (o.result?.durationMs ?? 0),
|
|
40455
|
+
0
|
|
40456
|
+
);
|
|
40376
40457
|
const maxScore = allPackages.length > 0 ? Math.max(0, ...allPackages.map((p) => p.score)) : 0;
|
|
40377
|
-
const
|
|
40458
|
+
const anyBlock = allPackages.some(
|
|
40459
|
+
(p) => p.action === "block"
|
|
40460
|
+
);
|
|
40461
|
+
const anyWarn = allPackages.some(
|
|
40462
|
+
(p) => p.action === "warn"
|
|
40463
|
+
);
|
|
40464
|
+
const anyIncomplete = allPackages.some(
|
|
40465
|
+
(p) => p.action === "analysis_incomplete"
|
|
40466
|
+
);
|
|
40467
|
+
const action = anyBlock ? "block" : anyWarn ? "warn" : anyIncomplete ? "analysis_incomplete" : "pass";
|
|
40378
40468
|
if (totalScanned === 0) {
|
|
40379
|
-
|
|
40380
|
-
|
|
40381
|
-
|
|
40382
|
-
|
|
40383
|
-
|
|
40384
|
-
|
|
40385
|
-
|
|
40386
|
-
|
|
40387
|
-
|
|
40469
|
+
const errOutcome = allOutcomes.find((o) => o.status === "error");
|
|
40470
|
+
const emptyApiOutcome = allOutcomes.find((o) => o.status === "api_returned_empty");
|
|
40471
|
+
const trialOutcome = allOutcomes.find((o) => o.status === "trial_exhausted");
|
|
40472
|
+
const meaningful = errOutcome ?? emptyApiOutcome ?? trialOutcome;
|
|
40473
|
+
if (meaningful) {
|
|
40474
|
+
dispatch({ type: "scan_done", outcome: meaningful });
|
|
40475
|
+
} else {
|
|
40476
|
+
dispatch({
|
|
40477
|
+
type: "scan_done",
|
|
40478
|
+
outcome: {
|
|
40479
|
+
status: "no_packages",
|
|
40480
|
+
result: {
|
|
40481
|
+
result: { score: 0, action: "pass", packages: [], safeVersions: {}, durationMs: totalDuration },
|
|
40482
|
+
durationMs: totalDuration,
|
|
40483
|
+
scannedCount: 0,
|
|
40484
|
+
skippedCount: 0
|
|
40485
|
+
}
|
|
40388
40486
|
}
|
|
40389
|
-
}
|
|
40390
|
-
}
|
|
40487
|
+
});
|
|
40488
|
+
}
|
|
40391
40489
|
} else {
|
|
40392
40490
|
dispatch({
|
|
40393
40491
|
type: "scan_done",
|
|
@@ -40455,7 +40553,6 @@ var init_useInit = __esm({
|
|
|
40455
40553
|
init_hook();
|
|
40456
40554
|
init_scan();
|
|
40457
40555
|
init_lockfile();
|
|
40458
|
-
init_client();
|
|
40459
40556
|
init_config();
|
|
40460
40557
|
init_protect();
|
|
40461
40558
|
PROJECT_MARKERS = [
|
|
@@ -40586,6 +40683,38 @@ var init_useLogin = __esm({
|
|
|
40586
40683
|
}
|
|
40587
40684
|
});
|
|
40588
40685
|
|
|
40686
|
+
// src/ui/hooks/useTerminalSize.ts
|
|
40687
|
+
function useTerminalSize() {
|
|
40688
|
+
const { stdout } = use_stdout_default();
|
|
40689
|
+
const [size, setSize] = (0, import_react24.useState)({
|
|
40690
|
+
rows: stdout?.rows ?? process.stdout.rows ?? 24,
|
|
40691
|
+
cols: stdout?.columns ?? process.stdout.columns ?? 80
|
|
40692
|
+
});
|
|
40693
|
+
(0, import_react24.useEffect)(() => {
|
|
40694
|
+
const handle = () => {
|
|
40695
|
+
setSize({
|
|
40696
|
+
rows: process.stdout.rows ?? 24,
|
|
40697
|
+
cols: process.stdout.columns ?? 80
|
|
40698
|
+
});
|
|
40699
|
+
};
|
|
40700
|
+
process.stdout.setMaxListeners(process.stdout.getMaxListeners() + 1);
|
|
40701
|
+
process.stdout.on("resize", handle);
|
|
40702
|
+
return () => {
|
|
40703
|
+
process.stdout.off("resize", handle);
|
|
40704
|
+
process.stdout.setMaxListeners(Math.max(0, process.stdout.getMaxListeners() - 1));
|
|
40705
|
+
};
|
|
40706
|
+
}, []);
|
|
40707
|
+
return size;
|
|
40708
|
+
}
|
|
40709
|
+
var import_react24;
|
|
40710
|
+
var init_useTerminalSize = __esm({
|
|
40711
|
+
async "src/ui/hooks/useTerminalSize.ts"() {
|
|
40712
|
+
"use strict";
|
|
40713
|
+
import_react24 = __toESM(require_react());
|
|
40714
|
+
await init_build2();
|
|
40715
|
+
}
|
|
40716
|
+
});
|
|
40717
|
+
|
|
40589
40718
|
// src/ui/ink-controls.ts
|
|
40590
40719
|
var ink_controls_exports = {};
|
|
40591
40720
|
__export(ink_controls_exports, {
|
|
@@ -40593,6 +40722,7 @@ __export(ink_controls_exports, {
|
|
|
40593
40722
|
clearInkOutput: () => clearInkOutput,
|
|
40594
40723
|
forceFullRedraw: () => forceFullRedraw,
|
|
40595
40724
|
initInkInstances: () => initInkInstances,
|
|
40725
|
+
patchInkLogForAbsolutePositioning: () => patchInkLogForAbsolutePositioning,
|
|
40596
40726
|
resetInkClear: () => resetInkClear,
|
|
40597
40727
|
setInkClear: () => setInkClear,
|
|
40598
40728
|
setInkInstance: () => setInkInstance
|
|
@@ -40648,6 +40778,25 @@ function forceFullRedraw() {
|
|
|
40648
40778
|
if (wrapper) wrapper.clear();
|
|
40649
40779
|
resetRealInkLastOutput();
|
|
40650
40780
|
}
|
|
40781
|
+
function makeAbsoluteLog(stdout) {
|
|
40782
|
+
const log = ((str) => {
|
|
40783
|
+
stdout.write("\x1B[H\x1B[J" + str + "\n");
|
|
40784
|
+
});
|
|
40785
|
+
log.clear = () => {
|
|
40786
|
+
stdout.write("\x1B[H\x1B[J");
|
|
40787
|
+
};
|
|
40788
|
+
log.done = () => {
|
|
40789
|
+
};
|
|
40790
|
+
return log;
|
|
40791
|
+
}
|
|
40792
|
+
function patchInkLogForAbsolutePositioning() {
|
|
40793
|
+
if (!realInstances) return;
|
|
40794
|
+
const real = realInstances.get(process.stdout);
|
|
40795
|
+
if (!real) return;
|
|
40796
|
+
const newLog = makeAbsoluteLog(process.stdout);
|
|
40797
|
+
real.log = newLog;
|
|
40798
|
+
real.throttledLog = newLog;
|
|
40799
|
+
}
|
|
40651
40800
|
function resetInkClear() {
|
|
40652
40801
|
wrapper = null;
|
|
40653
40802
|
}
|
|
@@ -40663,41 +40812,6 @@ var init_ink_controls = __esm({
|
|
|
40663
40812
|
}
|
|
40664
40813
|
});
|
|
40665
40814
|
|
|
40666
|
-
// src/ui/hooks/useTerminalSize.ts
|
|
40667
|
-
function useTerminalSize() {
|
|
40668
|
-
const { stdout } = use_stdout_default();
|
|
40669
|
-
const [size, setSize] = (0, import_react24.useState)({
|
|
40670
|
-
rows: stdout?.rows ?? process.stdout.rows ?? 24,
|
|
40671
|
-
cols: stdout?.columns ?? process.stdout.columns ?? 80
|
|
40672
|
-
});
|
|
40673
|
-
(0, import_react24.useEffect)(() => {
|
|
40674
|
-
const handle = () => {
|
|
40675
|
-
clearScreen();
|
|
40676
|
-
forceFullRedraw();
|
|
40677
|
-
const rows = process.stdout.rows ?? 24;
|
|
40678
|
-
const cols = process.stdout.columns ?? 80;
|
|
40679
|
-
setSize({ rows, cols });
|
|
40680
|
-
};
|
|
40681
|
-
process.stdout.setMaxListeners(process.stdout.getMaxListeners() + 1);
|
|
40682
|
-
process.stdout.on("resize", handle);
|
|
40683
|
-
return () => {
|
|
40684
|
-
process.stdout.off("resize", handle);
|
|
40685
|
-
process.stdout.setMaxListeners(Math.max(0, process.stdout.getMaxListeners() - 1));
|
|
40686
|
-
};
|
|
40687
|
-
}, []);
|
|
40688
|
-
return size;
|
|
40689
|
-
}
|
|
40690
|
-
var import_react24;
|
|
40691
|
-
var init_useTerminalSize = __esm({
|
|
40692
|
-
async "src/ui/hooks/useTerminalSize.ts"() {
|
|
40693
|
-
"use strict";
|
|
40694
|
-
import_react24 = __toESM(require_react());
|
|
40695
|
-
await init_build2();
|
|
40696
|
-
init_terminal_state();
|
|
40697
|
-
init_ink_controls();
|
|
40698
|
-
}
|
|
40699
|
-
});
|
|
40700
|
-
|
|
40701
40815
|
// node_modules/cli-spinners/spinners.json
|
|
40702
40816
|
var require_spinners = __commonJS({
|
|
40703
40817
|
"node_modules/cli-spinners/spinners.json"(exports, module) {
|
|
@@ -45236,6 +45350,10 @@ __export(terms_gate_exports, {
|
|
|
45236
45350
|
gateOrExit: () => gateOrExit
|
|
45237
45351
|
});
|
|
45238
45352
|
import * as readline from "node:readline";
|
|
45353
|
+
function previewInput(raw) {
|
|
45354
|
+
const trimmed = raw.length > 80 ? raw.slice(0, 80) + "\u2026" : raw;
|
|
45355
|
+
return JSON.stringify(trimmed);
|
|
45356
|
+
}
|
|
45239
45357
|
async function ensureTermsAccepted() {
|
|
45240
45358
|
if (hasAcceptedTerms()) return { accepted: true };
|
|
45241
45359
|
if (process.env.DG_ACCEPT_TERMS === "1") {
|
|
@@ -45251,6 +45369,7 @@ async function ensureTermsAccepted() {
|
|
|
45251
45369
|
import_chalk6.default.dim(
|
|
45252
45370
|
`
|
|
45253
45371
|
Accepted Terms + Privacy via DG_ACCEPT_TERMS=1.
|
|
45372
|
+
Saved to ${dgConfigPath()}.
|
|
45254
45373
|
${TERMS_URL} \xB7 ${PRIVACY_URL}
|
|
45255
45374
|
|
|
45256
45375
|
`
|
|
@@ -45262,13 +45381,8 @@ async function ensureTermsAccepted() {
|
|
|
45262
45381
|
process.stderr.write(
|
|
45263
45382
|
"\n" + import_chalk6.default.bold(" Terms of Service + Privacy Policy\n\n") + " Dependency Guardian sends your lockfile package names + versions\n to api.westbayberry.com to scan them. To use this CLI, you must\n accept:\n\n \xB7 " + import_chalk6.default.cyan(TERMS_URL) + "\n \xB7 " + import_chalk6.default.cyan(PRIVACY_URL) + "\n\n Type " + import_chalk6.default.bold("agree") + " to accept, anything else to cancel: "
|
|
45264
45383
|
);
|
|
45265
|
-
const
|
|
45266
|
-
|
|
45267
|
-
rl.once("line", (line) => {
|
|
45268
|
-
rl.close();
|
|
45269
|
-
resolve2(line.trim().toLowerCase());
|
|
45270
|
-
});
|
|
45271
|
-
});
|
|
45384
|
+
const raw = await readOneLine();
|
|
45385
|
+
const answer = raw.trim().toLowerCase();
|
|
45272
45386
|
if (answer === "agree") {
|
|
45273
45387
|
try {
|
|
45274
45388
|
recordTermsAccepted();
|
|
@@ -45278,10 +45392,17 @@ async function ensureTermsAccepted() {
|
|
|
45278
45392
|
reason: `Could not record terms acceptance: ${e.message}`
|
|
45279
45393
|
};
|
|
45280
45394
|
}
|
|
45281
|
-
process.stderr.write(
|
|
45395
|
+
process.stderr.write(
|
|
45396
|
+
import_chalk6.default.green("\n Accepted. ") + import_chalk6.default.dim(`Saved to ${dgConfigPath()}.
|
|
45397
|
+
|
|
45398
|
+
`)
|
|
45399
|
+
);
|
|
45282
45400
|
return { accepted: true };
|
|
45283
45401
|
}
|
|
45284
|
-
return {
|
|
45402
|
+
return {
|
|
45403
|
+
accepted: false,
|
|
45404
|
+
reason: `Declined at prompt (received ${previewInput(raw)}; the prompt accepts only the exact word "agree").`
|
|
45405
|
+
};
|
|
45285
45406
|
}
|
|
45286
45407
|
return {
|
|
45287
45408
|
accepted: false,
|
|
@@ -45292,6 +45413,21 @@ async function ensureTermsAccepted() {
|
|
|
45292
45413
|
\xB7 Privacy: ${PRIVACY_URL}`
|
|
45293
45414
|
};
|
|
45294
45415
|
}
|
|
45416
|
+
async function readOneLine() {
|
|
45417
|
+
const wasPaused = process.stdin.isPaused();
|
|
45418
|
+
if (wasPaused) process.stdin.resume();
|
|
45419
|
+
try {
|
|
45420
|
+
return await new Promise((resolve2) => {
|
|
45421
|
+
const rl = readline.createInterface({ input: process.stdin, terminal: false });
|
|
45422
|
+
rl.once("line", (line) => {
|
|
45423
|
+
rl.close();
|
|
45424
|
+
resolve2(line);
|
|
45425
|
+
});
|
|
45426
|
+
});
|
|
45427
|
+
} finally {
|
|
45428
|
+
if (wasPaused) process.stdin.pause();
|
|
45429
|
+
}
|
|
45430
|
+
}
|
|
45295
45431
|
async function gateOrExit() {
|
|
45296
45432
|
const result = await ensureTermsAccepted();
|
|
45297
45433
|
if (!result.accepted) {
|
|
@@ -45305,6 +45441,7 @@ var init_terms_gate = __esm({
|
|
|
45305
45441
|
"use strict";
|
|
45306
45442
|
import_chalk6 = __toESM(require_source());
|
|
45307
45443
|
init_auth();
|
|
45444
|
+
init_paths();
|
|
45308
45445
|
TERMS_URL = "https://westbayberry.com/terms";
|
|
45309
45446
|
PRIVACY_URL = "https://westbayberry.com/privacy";
|
|
45310
45447
|
}
|
|
@@ -45384,7 +45521,6 @@ var init_LoginApp = __esm({
|
|
|
45384
45521
|
"Logged in as ",
|
|
45385
45522
|
state.email
|
|
45386
45523
|
] }),
|
|
45387
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { dimColor: true, children: "Credentials saved." }),
|
|
45388
45524
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: " " }),
|
|
45389
45525
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { children: [
|
|
45390
45526
|
"Run ",
|
|
@@ -45700,8 +45836,8 @@ function compareVer(a, b) {
|
|
|
45700
45836
|
}
|
|
45701
45837
|
return 0;
|
|
45702
45838
|
}
|
|
45703
|
-
async function pipSupportsDryRunReport() {
|
|
45704
|
-
const v = await pipVersion();
|
|
45839
|
+
async function pipSupportsDryRunReport(knownVersion) {
|
|
45840
|
+
const v = knownVersion === void 0 ? await pipVersion() : knownVersion;
|
|
45705
45841
|
if (!v) return { ok: false, version: null, reason: "pip not found" };
|
|
45706
45842
|
if (compareVer(v, "23.0") < 0) {
|
|
45707
45843
|
return { ok: false, version: v, reason: `pip ${v} < 23.0; needs upgrade for transitive scan` };
|
|
@@ -46023,7 +46159,7 @@ function reducer3(state, action) {
|
|
|
46023
46159
|
case "MOVE_BROWSER": {
|
|
46024
46160
|
let viewport = state.browserViewport;
|
|
46025
46161
|
if (action.cursor < viewport) viewport = action.cursor;
|
|
46026
|
-
if (action.cursor >= viewport +
|
|
46162
|
+
if (action.cursor >= viewport + action.visibleRows) viewport = action.cursor - action.visibleRows + 1;
|
|
46027
46163
|
return { ...state, browserCursor: action.cursor, browserViewport: viewport };
|
|
46028
46164
|
}
|
|
46029
46165
|
case "FOCUS":
|
|
@@ -46045,6 +46181,7 @@ var init_FileSavePrompt = __esm({
|
|
|
46045
46181
|
import_react30 = __toESM(require_react());
|
|
46046
46182
|
await init_build2();
|
|
46047
46183
|
import_chalk7 = __toESM(require_source());
|
|
46184
|
+
await init_useTerminalSize();
|
|
46048
46185
|
import_jsx_runtime8 = __toESM(require_jsx_runtime());
|
|
46049
46186
|
VISIBLE_ROWS = 15;
|
|
46050
46187
|
FileSavePrompt = ({
|
|
@@ -46076,9 +46213,11 @@ var init_FileSavePrompt = __esm({
|
|
|
46076
46213
|
const q = state.filterText.toLowerCase();
|
|
46077
46214
|
return dirs.filter((e) => e.name.toLowerCase().includes(q));
|
|
46078
46215
|
}, [state.entries, state.filterText]);
|
|
46216
|
+
const { rows: termRows } = useTerminalSize();
|
|
46217
|
+
const visibleRows = Math.max(5, Math.min(VISIBLE_ROWS, termRows - 10));
|
|
46079
46218
|
const visibleEntries = filteredEntries.slice(
|
|
46080
46219
|
state.browserViewport,
|
|
46081
|
-
state.browserViewport +
|
|
46220
|
+
state.browserViewport + visibleRows
|
|
46082
46221
|
);
|
|
46083
46222
|
use_input_default((input, key) => {
|
|
46084
46223
|
if (key.escape) {
|
|
@@ -46131,7 +46270,7 @@ var init_FileSavePrompt = __esm({
|
|
|
46131
46270
|
}
|
|
46132
46271
|
if (key.upArrow) {
|
|
46133
46272
|
if (state.browserCursor > 0) {
|
|
46134
|
-
dispatch({ type: "MOVE_BROWSER", cursor: state.browserCursor - 1 });
|
|
46273
|
+
dispatch({ type: "MOVE_BROWSER", cursor: state.browserCursor - 1, visibleRows });
|
|
46135
46274
|
} else {
|
|
46136
46275
|
dispatch({ type: "FOCUS", target: "filename" });
|
|
46137
46276
|
}
|
|
@@ -46145,7 +46284,7 @@ var init_FileSavePrompt = __esm({
|
|
|
46145
46284
|
return;
|
|
46146
46285
|
}
|
|
46147
46286
|
if (key.downArrow) {
|
|
46148
|
-
dispatch({ type: "MOVE_BROWSER", cursor: clamp(state.browserCursor + 1, 0, filteredEntries.length - 1) });
|
|
46287
|
+
dispatch({ type: "MOVE_BROWSER", cursor: clamp(state.browserCursor + 1, 0, filteredEntries.length - 1), visibleRows });
|
|
46149
46288
|
return;
|
|
46150
46289
|
}
|
|
46151
46290
|
if (key.return) {
|
|
@@ -46167,11 +46306,7 @@ var init_FileSavePrompt = __esm({
|
|
|
46167
46306
|
const filenameDisplay = state.filename.slice(0, state.cursorPos) + (state.focus === "filename" ? import_chalk7.default.inverse(state.filename[state.cursorPos] || " ") : "") + state.filename.slice(state.cursorPos + 1);
|
|
46168
46307
|
const shortDir = state.directory.replace(process.env.HOME || "", "~");
|
|
46169
46308
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
|
|
46170
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.
|
|
46171
|
-
import_chalk7.default.cyan("\u25C6"),
|
|
46172
|
-
" ",
|
|
46173
|
-
import_chalk7.default.bold("Save Scan Results")
|
|
46174
|
-
] }),
|
|
46309
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: import_chalk7.default.bold("Save Scan Results") }),
|
|
46175
46310
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { children: [
|
|
46176
46311
|
"Score: ",
|
|
46177
46312
|
import_chalk7.default.bold(String(score)),
|
|
@@ -46204,9 +46339,9 @@ var init_FileSavePrompt = __esm({
|
|
|
46204
46339
|
name
|
|
46205
46340
|
] }, `${entry.name}-${i}`);
|
|
46206
46341
|
}),
|
|
46207
|
-
filteredEntries.length >
|
|
46342
|
+
filteredEntries.length > visibleRows && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { dimColor: true, children: [
|
|
46208
46343
|
" ",
|
|
46209
|
-
import_chalk7.default.dim(`\u2191\u2193 ${filteredEntries.length -
|
|
46344
|
+
import_chalk7.default.dim(`\u2191\u2193 ${filteredEntries.length - visibleRows} more`)
|
|
46210
46345
|
] }),
|
|
46211
46346
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: "" }),
|
|
46212
46347
|
state.filterText && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { dimColor: true, children: [
|
|
@@ -46372,13 +46507,13 @@ __export(static_output_exports, {
|
|
|
46372
46507
|
runStaticNpm: () => runStaticNpm,
|
|
46373
46508
|
runStaticPip: () => runStaticPip
|
|
46374
46509
|
});
|
|
46375
|
-
import { writeFileSync as writeFileSync9, readFileSync as readFileSync11, existsSync as existsSync15, mkdirSync as mkdirSync8, lstatSync as
|
|
46510
|
+
import { writeFileSync as writeFileSync9, readFileSync as readFileSync11, existsSync as existsSync15, mkdirSync as mkdirSync8, lstatSync as lstatSync5 } from "node:fs";
|
|
46376
46511
|
import { resolve as resolvePath2, dirname as dirname11 } from "node:path";
|
|
46377
46512
|
function loadPackageLockJson(cwd2 = process.cwd()) {
|
|
46378
46513
|
const path2 = resolvePath2(cwd2, "package-lock.json");
|
|
46379
46514
|
if (!existsSync15(path2)) return null;
|
|
46380
46515
|
try {
|
|
46381
|
-
const st =
|
|
46516
|
+
const st = lstatSync5(path2);
|
|
46382
46517
|
if (!st.isFile()) return null;
|
|
46383
46518
|
if (st.size > MAX_PACKAGE_LOCK_BYTES) return null;
|
|
46384
46519
|
return JSON.parse(readFileSync11(path2, "utf8"));
|
|
@@ -46464,7 +46599,7 @@ function printTrialBanner(result, config) {
|
|
|
46464
46599
|
const now = Date.now();
|
|
46465
46600
|
if (now - lastMs < NUDGE_INTERVAL_MS) return;
|
|
46466
46601
|
mkdirSync8(dirname11(stampPath), { recursive: true, mode: 448 });
|
|
46467
|
-
writeFileSync9(stampPath, String(now) + "\n");
|
|
46602
|
+
writeFileSync9(stampPath, String(now) + "\n", { mode: 384 });
|
|
46468
46603
|
} catch {
|
|
46469
46604
|
return;
|
|
46470
46605
|
}
|
|
@@ -46532,11 +46667,22 @@ function groupPackages(packages) {
|
|
|
46532
46667
|
}
|
|
46533
46668
|
return [...map.values()].map((pkgs) => ({ packages: pkgs, key: pkgs[0].name })).sort((a, b) => b.packages[0].score - a.packages[0].score);
|
|
46534
46669
|
}
|
|
46535
|
-
function actionBadge(
|
|
46536
|
-
|
|
46537
|
-
if (
|
|
46670
|
+
function actionBadge(pkg) {
|
|
46671
|
+
const a = pkg.action;
|
|
46672
|
+
if (a === "block") return { label: "Block", color: import_chalk8.default.red };
|
|
46673
|
+
if (a === "warn") return { label: "Warn", color: import_chalk8.default.yellow };
|
|
46674
|
+
if (a === "pass") return { label: "Pass", color: import_chalk8.default.green };
|
|
46675
|
+
if (a === "analysis_incomplete") return { label: "Unknown", color: import_chalk8.default.cyan };
|
|
46676
|
+
if (pkg.score >= 70) return { label: "Block", color: import_chalk8.default.red };
|
|
46677
|
+
if (pkg.score >= 60) return { label: "Warn", color: import_chalk8.default.yellow };
|
|
46538
46678
|
return { label: "Pass", color: import_chalk8.default.green };
|
|
46539
46679
|
}
|
|
46680
|
+
function isBlocked(p) {
|
|
46681
|
+
return p.action === "block" || p.action === void 0 && p.score >= 70;
|
|
46682
|
+
}
|
|
46683
|
+
function isWarned(p) {
|
|
46684
|
+
return p.action === "warn" || p.action === void 0 && p.score >= 60 && p.score < 70;
|
|
46685
|
+
}
|
|
46540
46686
|
function renderResultClean(result, _config) {
|
|
46541
46687
|
const lines = [];
|
|
46542
46688
|
const total = result.packages.length;
|
|
@@ -46546,8 +46692,8 @@ function renderResultClean(result, _config) {
|
|
|
46546
46692
|
lines.push("");
|
|
46547
46693
|
return lines.join("\n");
|
|
46548
46694
|
}
|
|
46549
|
-
const blocked = result.packages.filter(
|
|
46550
|
-
const warned = result.packages.filter(
|
|
46695
|
+
const blocked = result.packages.filter(isBlocked);
|
|
46696
|
+
const warned = result.packages.filter(isWarned);
|
|
46551
46697
|
if (result.action === "pass" && blocked.length === 0 && warned.length === 0) {
|
|
46552
46698
|
lines.push("");
|
|
46553
46699
|
lines.push(` ${import_chalk8.default.green("\u2713")} ${import_chalk8.default.bold("Dependency Guardian")} checked ${total} package${total !== 1 ? "s" : ""}. ${import_chalk8.default.green("No risky behavior found.")}`);
|
|
@@ -46597,8 +46743,8 @@ function renderResultDetails(result, _config) {
|
|
|
46597
46743
|
)}${colorAction(actionStr)}`
|
|
46598
46744
|
);
|
|
46599
46745
|
lines.push("");
|
|
46600
|
-
const blocked = result.packages.filter(
|
|
46601
|
-
const warned = result.packages.filter(
|
|
46746
|
+
const blocked = result.packages.filter(isBlocked);
|
|
46747
|
+
const warned = result.packages.filter(isWarned);
|
|
46602
46748
|
const passWithScore = result.packages.filter((p) => p.score > 0 && p.score < 60);
|
|
46603
46749
|
const clean = result.packages.filter((p) => p.score === 0);
|
|
46604
46750
|
const total = result.packages.length;
|
|
@@ -46640,7 +46786,7 @@ function renderResultDetails(result, _config) {
|
|
|
46640
46786
|
lines.push(` ${import_chalk8.default.dim("\u2500".repeat(60))}`);
|
|
46641
46787
|
for (const group of groups) {
|
|
46642
46788
|
const rep = group.packages[0];
|
|
46643
|
-
const { label, color } = actionBadge(rep
|
|
46789
|
+
const { label, color } = actionBadge(rep);
|
|
46644
46790
|
const names = group.packages.length === 1 ? rep.name : group.packages.length <= 3 ? group.packages.map((p) => p.name).join(", ") : `${group.packages[0].name} + ${group.packages.length - 1} similar`;
|
|
46645
46791
|
const lcInfo = rep.license;
|
|
46646
46792
|
const lcStr = lcInfo ? truncate(lcInfo.spdx ?? lcInfo.raw ?? "", 14) : "";
|
|
@@ -46691,7 +46837,9 @@ async function runStatic(config) {
|
|
|
46691
46837
|
dbg(`api=${config.apiUrl}`);
|
|
46692
46838
|
process.stderr.write(import_chalk8.default.dim(" Discovering package changes...\n"));
|
|
46693
46839
|
const { discoverProjectsAsync: discoverProjectsAsync2 } = await Promise.resolve().then(() => (init_walker(), walker_exports));
|
|
46840
|
+
const tDiscStart = Date.now();
|
|
46694
46841
|
const subProjects = await discoverProjectsAsync2(process.cwd());
|
|
46842
|
+
if (process.env.DG_PERF) console.error(`[CLI-PERF] walker: ${Date.now() - tDiscStart}ms \u2014 ${subProjects.length} projects`);
|
|
46695
46843
|
let discovery;
|
|
46696
46844
|
if (subProjects.length > 1) {
|
|
46697
46845
|
const totalPkgs = subProjects.reduce((s, p) => s + p.packageCount, 0);
|
|
@@ -46709,6 +46857,7 @@ async function runStatic(config) {
|
|
|
46709
46857
|
const allNpmPkgs = [];
|
|
46710
46858
|
const allPyPkgs = [];
|
|
46711
46859
|
const seen = /* @__PURE__ */ new Set();
|
|
46860
|
+
const tParseStart = Date.now();
|
|
46712
46861
|
for (const proj of subProjects) {
|
|
46713
46862
|
try {
|
|
46714
46863
|
const projDisc = discoverChanges(proj.path, config);
|
|
@@ -46733,6 +46882,7 @@ async function runStatic(config) {
|
|
|
46733
46882
|
process.stderr.write(import_chalk8.default.dim(" No package changes detected across projects.\n"));
|
|
46734
46883
|
process.exit(0);
|
|
46735
46884
|
}
|
|
46885
|
+
if (process.env.DG_PERF) console.error(`[CLI-PERF] parse + dedupe: ${Date.now() - tParseStart}ms \u2014 ${allNpmPkgs.length} npm + ${allPyPkgs.length} pypi`);
|
|
46736
46886
|
discovery = {
|
|
46737
46887
|
packages: allNpmPkgs,
|
|
46738
46888
|
pythonPackages: allPyPkgs,
|
|
@@ -47392,7 +47542,8 @@ async function runStaticLogin() {
|
|
|
47392
47542
|
process.stderr.write(
|
|
47393
47543
|
import_chalk8.default.green(`
|
|
47394
47544
|
Logged in as ${result.email ?? "unknown"}
|
|
47395
|
-
|
|
47545
|
+
|
|
47546
|
+
`)
|
|
47396
47547
|
);
|
|
47397
47548
|
return;
|
|
47398
47549
|
}
|
|
@@ -47498,11 +47649,11 @@ async function handleStatusCommand(cliVersion2) {
|
|
|
47498
47649
|
let hookLine = "no pre-commit hook \u2014 `dg hook install` to gate commits";
|
|
47499
47650
|
let hookOk = false;
|
|
47500
47651
|
try {
|
|
47501
|
-
const { existsSync:
|
|
47652
|
+
const { existsSync: existsSync19, readFileSync: readFileSync13 } = await import("node:fs");
|
|
47502
47653
|
const { join: join13 } = await import("node:path");
|
|
47503
47654
|
const candidates = [join13(cwd2, ".husky", "pre-commit"), join13(cwd2, ".git", "hooks", "pre-commit")];
|
|
47504
47655
|
for (const path2 of candidates) {
|
|
47505
|
-
if (
|
|
47656
|
+
if (existsSync19(path2)) {
|
|
47506
47657
|
const content = readFileSync13(path2, "utf-8");
|
|
47507
47658
|
if (content.includes("dependency-guardian")) {
|
|
47508
47659
|
hookLine = `installed in ${path2}`;
|
|
@@ -47532,17 +47683,19 @@ async function handleStatusCommand(cliVersion2) {
|
|
|
47532
47683
|
} catch {
|
|
47533
47684
|
}
|
|
47534
47685
|
try {
|
|
47535
|
-
const { execFileSync:
|
|
47536
|
-
const npmV = (() => {
|
|
47537
|
-
try {
|
|
47538
|
-
return execFileSync5("npm", ["--version"], { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
47539
|
-
} catch {
|
|
47540
|
-
return null;
|
|
47541
|
-
}
|
|
47542
|
-
})();
|
|
47686
|
+
const { execFileSync: execFileSync2 } = await import("node:child_process");
|
|
47543
47687
|
const { pipVersion: pipVersion2, pipSupportsDryRunReport: pipSupportsDryRunReport2 } = await Promise.resolve().then(() => (init_pip_wrapper(), pip_wrapper_exports));
|
|
47544
|
-
const pipV = await
|
|
47545
|
-
|
|
47688
|
+
const [npmV, pipV] = await Promise.all([
|
|
47689
|
+
Promise.resolve().then(() => {
|
|
47690
|
+
try {
|
|
47691
|
+
return execFileSync2("npm", ["--version"], { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
47692
|
+
} catch {
|
|
47693
|
+
return null;
|
|
47694
|
+
}
|
|
47695
|
+
}),
|
|
47696
|
+
pipVersion2()
|
|
47697
|
+
]);
|
|
47698
|
+
const pipProbe = pipV ? await pipSupportsDryRunReport2(pipV) : null;
|
|
47546
47699
|
const npmLine = npmV ? `npm ${npmV} (transitive scan supported)` : "npm not found on PATH";
|
|
47547
47700
|
const npmGlyph = npmV ? chalk18.green("\u2713") : chalk18.yellow("\xB7");
|
|
47548
47701
|
process.stderr.write(` ${npmGlyph} ${chalk18.bold("npm")} ` + chalk18.dim(npmLine + "\n"));
|
|
@@ -47588,7 +47741,10 @@ function licenseSummary(results) {
|
|
|
47588
47741
|
return [...byRisk.entries()].map(([risk, count]) => ({ risk, count })).sort(riskOrder);
|
|
47589
47742
|
}
|
|
47590
47743
|
function csvCell(v) {
|
|
47591
|
-
|
|
47744
|
+
let s = v === null || v === void 0 ? "" : String(v);
|
|
47745
|
+
if (s.length > 0 && CSV_FORMULA_PREFIXES.has(s[0])) {
|
|
47746
|
+
s = "'" + s;
|
|
47747
|
+
}
|
|
47592
47748
|
if (/[",\n]/.test(s)) return `"${s.replace(/"/g, '""')}"`;
|
|
47593
47749
|
return s;
|
|
47594
47750
|
}
|
|
@@ -47654,12 +47810,13 @@ function formatLicensesText(results) {
|
|
|
47654
47810
|
}
|
|
47655
47811
|
return lines.join("\n");
|
|
47656
47812
|
}
|
|
47657
|
-
var import_chalk9, SINK_RANKS;
|
|
47813
|
+
var import_chalk9, SINK_RANKS, CSV_FORMULA_PREFIXES;
|
|
47658
47814
|
var init_license_export = __esm({
|
|
47659
47815
|
"src/formatters/license-export.ts"() {
|
|
47660
47816
|
"use strict";
|
|
47661
47817
|
import_chalk9 = __toESM(require_source());
|
|
47662
47818
|
SINK_RANKS = { "no-license": 2, unknown: 1 };
|
|
47819
|
+
CSV_FORMULA_PREFIXES = /* @__PURE__ */ new Set(["=", "+", "-", "@", " ", "\r"]);
|
|
47663
47820
|
}
|
|
47664
47821
|
});
|
|
47665
47822
|
|
|
@@ -47679,7 +47836,7 @@ function renderLicenseSummary(entries, maxCols) {
|
|
|
47679
47836
|
if (ra !== rb) return ra - rb;
|
|
47680
47837
|
return b.count - a.count;
|
|
47681
47838
|
});
|
|
47682
|
-
const
|
|
47839
|
+
const sep3 = import_chalk10.default.dim(" \xB7 ");
|
|
47683
47840
|
const segments = [];
|
|
47684
47841
|
let used = "Licenses ".length;
|
|
47685
47842
|
let dropped = 0;
|
|
@@ -47694,8 +47851,8 @@ function renderLicenseSummary(entries, maxCols) {
|
|
|
47694
47851
|
segments.push(colorForRisk(e.risk)(label));
|
|
47695
47852
|
used += segLen;
|
|
47696
47853
|
}
|
|
47697
|
-
let line = `${import_chalk10.default.dim("Licenses")} ${segments.join(
|
|
47698
|
-
if (dropped > 0) line += `${
|
|
47854
|
+
let line = `${import_chalk10.default.dim("Licenses")} ${segments.join(sep3)}`;
|
|
47855
|
+
if (dropped > 0) line += `${sep3}${import_chalk10.default.dim(`+${dropped} more`)}`;
|
|
47699
47856
|
return line;
|
|
47700
47857
|
}
|
|
47701
47858
|
function scoreColor(score, action) {
|
|
@@ -47755,6 +47912,7 @@ var init_ScoreHeader = __esm({
|
|
|
47755
47912
|
"use strict";
|
|
47756
47913
|
await init_build2();
|
|
47757
47914
|
import_chalk10 = __toESM(require_source());
|
|
47915
|
+
await init_useTerminalSize();
|
|
47758
47916
|
import_jsx_runtime9 = __toESM(require_jsx_runtime());
|
|
47759
47917
|
LICENSE_RISK_LABELS = {
|
|
47760
47918
|
permissive: "permissive",
|
|
@@ -47817,7 +47975,7 @@ var init_ScoreHeader = __esm({
|
|
|
47817
47975
|
licenseSummary: licenseSummary2
|
|
47818
47976
|
}) => {
|
|
47819
47977
|
const logo = renderLogo(action);
|
|
47820
|
-
const cols =
|
|
47978
|
+
const { cols } = useTerminalSize();
|
|
47821
47979
|
const showLogo = cols >= 60;
|
|
47822
47980
|
const licenseLine2 = licenseSummary2 && licenseSummary2.length > 0 ? renderLicenseSummary(licenseSummary2, showLogo ? cols - 16 : cols) : "";
|
|
47823
47981
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
@@ -47832,8 +47990,7 @@ var init_ScoreHeader = __esm({
|
|
|
47832
47990
|
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "row", children: [
|
|
47833
47991
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
47834
47992
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { bold: true, children: [
|
|
47835
|
-
|
|
47836
|
-
" Dependency Guardian ",
|
|
47993
|
+
"Dependency Guardian ",
|
|
47837
47994
|
userStatus ? import_chalk10.default.dim(userStatus) : ""
|
|
47838
47995
|
] }),
|
|
47839
47996
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { children: " " }),
|
|
@@ -47988,16 +48145,19 @@ function groupRowHeight(group, level, safeVersions) {
|
|
|
47988
48145
|
if (level === "summary") return 1 + findingsSummaryHeight(group);
|
|
47989
48146
|
return 1 + findingsDetailHeight(group, safeVersions);
|
|
47990
48147
|
}
|
|
48148
|
+
function nameVer(p) {
|
|
48149
|
+
return p.version ? `${p.name}@${p.version}` : p.name;
|
|
48150
|
+
}
|
|
47991
48151
|
function groupNames(group) {
|
|
47992
|
-
if (group.packages.length === 1) return group.packages[0]
|
|
48152
|
+
if (group.packages.length === 1) return nameVer(group.packages[0]);
|
|
47993
48153
|
if (group.packages.length <= 3)
|
|
47994
|
-
return group.packages.map(
|
|
47995
|
-
return `${group.packages[0]
|
|
48154
|
+
return group.packages.map(nameVer).join(", ");
|
|
48155
|
+
return `${nameVer(group.packages[0])} + ${group.packages.length - 1} similar`;
|
|
47996
48156
|
}
|
|
47997
48157
|
function affectsLine(group) {
|
|
47998
|
-
const
|
|
47999
|
-
if (
|
|
48000
|
-
return
|
|
48158
|
+
const labels = group.packages.map(nameVer);
|
|
48159
|
+
if (labels.length <= 5) return labels.join(", ");
|
|
48160
|
+
return labels.slice(0, 5).join(", ") + ` + ${labels.length - 5} more`;
|
|
48001
48161
|
}
|
|
48002
48162
|
function buildDetailLines(group, safeVersion, maxWidth) {
|
|
48003
48163
|
const rep = group.packages[0];
|
|
@@ -48789,27 +48949,28 @@ var init_InteractiveResultsView = __esm({
|
|
|
48789
48949
|
const clampedCursor = groups.length > 0 ? Math.min(view.cursor, groups.length - 1) : 0;
|
|
48790
48950
|
if (exportMenu) {
|
|
48791
48951
|
const SCOPES_RENDER = [
|
|
48792
|
-
{ value: "all", label: "All"
|
|
48793
|
-
{ value: "summary", label: "Summary"
|
|
48794
|
-
{ value: "packages", label: "Packages"
|
|
48795
|
-
{ value: "licenses", label: "Licenses"
|
|
48796
|
-
{ value: "findings", label: "Findings (warn+block)"
|
|
48952
|
+
{ value: "all", label: "All" },
|
|
48953
|
+
{ value: "summary", label: "Summary" },
|
|
48954
|
+
{ value: "packages", label: "Packages" },
|
|
48955
|
+
{ value: "licenses", label: "Licenses" },
|
|
48956
|
+
{ value: "findings", label: "Findings (warn+block)" }
|
|
48797
48957
|
];
|
|
48798
48958
|
if (licenseDetailIdxRef.current !== null) {
|
|
48799
48959
|
const focus = licenseGroups[licenseDetailIdxRef.current];
|
|
48800
48960
|
SCOPES_RENDER.push({
|
|
48801
48961
|
value: "current-license",
|
|
48802
|
-
label: `Current license (${focus?.spdx ?? "\u2014"})
|
|
48803
|
-
hint: `only the ${focus?.count ?? 0} packages under this license`
|
|
48962
|
+
label: `Current license (${focus?.spdx ?? "\u2014"})`
|
|
48804
48963
|
});
|
|
48805
48964
|
}
|
|
48806
48965
|
const FORMATS_RENDER = [
|
|
48807
|
-
{ value: "json", label: "JSON"
|
|
48808
|
-
{ value: "csv", label: "CSV"
|
|
48809
|
-
{ value: "md", label: "Markdown"
|
|
48810
|
-
{ value: "txt", label: "Plain text"
|
|
48966
|
+
{ value: "json", label: "JSON" },
|
|
48967
|
+
{ value: "csv", label: "CSV" },
|
|
48968
|
+
{ value: "md", label: "Markdown" },
|
|
48969
|
+
{ value: "txt", label: "Plain text" }
|
|
48811
48970
|
];
|
|
48812
|
-
const
|
|
48971
|
+
const stackedLayout = termCols < 80;
|
|
48972
|
+
const colWidth = stackedLayout ? void 0 : Math.max(24, Math.floor((termCols - 8) / 2));
|
|
48973
|
+
const renderColumn = (title, rows, current, isActive) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", width: colWidth, flexShrink: 1, marginBottom: stackedLayout ? 1 : 0, children: [
|
|
48813
48974
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
|
|
48814
48975
|
isActive ? import_chalk11.default.cyan("\u258C ") : " ",
|
|
48815
48976
|
isActive ? import_chalk11.default.bold(title) : import_chalk11.default.dim(title)
|
|
@@ -48819,12 +48980,11 @@ var init_InteractiveResultsView = __esm({
|
|
|
48819
48980
|
const bullet = selected ? isActive ? import_chalk11.default.cyan("\u25CF") : import_chalk11.default.green("\u25CF") : import_chalk11.default.dim("\u25CB");
|
|
48820
48981
|
const text = selected ? import_chalk11.default.bold(r.label) : r.label;
|
|
48821
48982
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { children: [
|
|
48822
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: 5, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
|
|
48983
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: 5, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
|
|
48823
48984
|
" ",
|
|
48824
48985
|
bullet
|
|
48825
48986
|
] }) }),
|
|
48826
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, {
|
|
48827
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: r.hint })
|
|
48987
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { flexShrink: 1, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { wrap: "truncate-end", children: text }) })
|
|
48828
48988
|
] }, r.value);
|
|
48829
48989
|
})
|
|
48830
48990
|
] });
|
|
@@ -48842,15 +49002,13 @@ var init_InteractiveResultsView = __esm({
|
|
|
48842
49002
|
licenseSummary: licenseSummary2
|
|
48843
49003
|
}
|
|
48844
49004
|
),
|
|
48845
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingLeft: 2, paddingRight: 2,
|
|
48846
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.
|
|
48847
|
-
import_chalk11.default.cyan("\u25C6"),
|
|
48848
|
-
" Export ",
|
|
48849
|
-
import_chalk11.default.dim("(pick what to export and which format)")
|
|
48850
|
-
] }),
|
|
49005
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingLeft: 2, paddingRight: 2, children: [
|
|
49006
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { bold: true, children: "Export" }),
|
|
48851
49007
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: "" }),
|
|
48852
|
-
|
|
48853
|
-
|
|
49008
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: stackedLayout ? "column" : "row", children: [
|
|
49009
|
+
renderColumn("What", SCOPES_RENDER, exportMenu.scope, exportMenu.activeRow === "scope"),
|
|
49010
|
+
renderColumn("Format", FORMATS_RENDER, exportMenu.format, exportMenu.activeRow === "format")
|
|
49011
|
+
] })
|
|
48854
49012
|
] }),
|
|
48855
49013
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: import_chalk11.default.dim("\u2500".repeat(Math.max(20, termCols - 4))) }),
|
|
48856
49014
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
|
|
@@ -48899,10 +49057,7 @@ var init_InteractiveResultsView = __esm({
|
|
|
48899
49057
|
paddingRight: 2,
|
|
48900
49058
|
width: "100%",
|
|
48901
49059
|
children: [
|
|
48902
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.
|
|
48903
|
-
import_chalk11.default.cyan("\u25C6"),
|
|
48904
|
-
" Keyboard Shortcuts"
|
|
48905
|
-
] }),
|
|
49060
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { bold: true, children: "Keyboard Shortcuts" }),
|
|
48906
49061
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: "" }),
|
|
48907
49062
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { bold: true, children: " Navigation" }),
|
|
48908
49063
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
|
|
@@ -49042,11 +49197,7 @@ var init_InteractiveResultsView = __esm({
|
|
|
49042
49197
|
),
|
|
49043
49198
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingLeft: 2, paddingRight: 2, width: "100%", children: [
|
|
49044
49199
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { children: [
|
|
49045
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.
|
|
49046
|
-
import_chalk11.default.cyan("\u25C6"),
|
|
49047
|
-
" ",
|
|
49048
|
-
color(g.spdx)
|
|
49049
|
-
] }),
|
|
49200
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { bold: true, children: color(g.spdx) }),
|
|
49050
49201
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, children: [
|
|
49051
49202
|
" \xB7 ",
|
|
49052
49203
|
g.risk,
|
|
@@ -49157,17 +49308,17 @@ var init_InteractiveResultsView = __esm({
|
|
|
49157
49308
|
width: "100%",
|
|
49158
49309
|
children: [
|
|
49159
49310
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { bold: true, children: [
|
|
49160
|
-
|
|
49161
|
-
"
|
|
49311
|
+
"Licenses",
|
|
49312
|
+
" ",
|
|
49162
49313
|
import_chalk11.default.dim(`(${licenseGroups.length} unique across ${totalCount} packages)`)
|
|
49163
49314
|
] }),
|
|
49164
49315
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: "" }),
|
|
49165
49316
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { children: [
|
|
49166
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: 2, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: " " }) }),
|
|
49167
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: spdxCol, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: "SPDX" }) }),
|
|
49168
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: riskCol, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: "Risk" }) }),
|
|
49169
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: countCol, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: "Count" }) }),
|
|
49170
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: barCol, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: "Share" }) })
|
|
49317
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: 2, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: " " }) }),
|
|
49318
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: spdxCol, flexShrink: 1, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: "SPDX" }) }),
|
|
49319
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: riskCol, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: "Risk" }) }),
|
|
49320
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: countCol, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: "Count" }) }),
|
|
49321
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { width: barCol, flexShrink: 1, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: "Share" }) })
|
|
49171
49322
|
] }),
|
|
49172
49323
|
hiddenAbove > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: ` \u2191 ${hiddenAbove} more above` }),
|
|
49173
49324
|
licenseGroups.slice(top, bottom).map((g, i) => {
|
|
@@ -50239,110 +50390,273 @@ var init_publish_check = __esm({
|
|
|
50239
50390
|
}
|
|
50240
50391
|
});
|
|
50241
50392
|
|
|
50242
|
-
// src/commands/
|
|
50243
|
-
var
|
|
50244
|
-
__export(
|
|
50245
|
-
|
|
50246
|
-
|
|
50393
|
+
// src/commands/update.ts
|
|
50394
|
+
var update_exports = {};
|
|
50395
|
+
__export(update_exports, {
|
|
50396
|
+
detectInstaller: () => detectInstaller,
|
|
50397
|
+
handleUpdateCommand: () => handleUpdateCommand,
|
|
50398
|
+
installPrefix: () => installPrefix,
|
|
50399
|
+
parseUpdateArgs: () => parseUpdateArgs,
|
|
50400
|
+
runUpdate: () => runUpdate
|
|
50247
50401
|
});
|
|
50248
|
-
import {
|
|
50402
|
+
import { spawnSync } from "node:child_process";
|
|
50403
|
+
import { accessSync, constants as constants2, realpathSync, unlinkSync as unlinkSync6 } from "node:fs";
|
|
50404
|
+
import { sep as sep2 } from "node:path";
|
|
50405
|
+
function parseUpdateArgs(args) {
|
|
50406
|
+
return {
|
|
50407
|
+
assumeYes: args.includes("--yes") || args.includes("-y"),
|
|
50408
|
+
printOnly: args.includes("--print") || args.includes("--dry-run")
|
|
50409
|
+
};
|
|
50410
|
+
}
|
|
50411
|
+
function detectInstaller(binPath) {
|
|
50412
|
+
let resolved;
|
|
50413
|
+
try {
|
|
50414
|
+
resolved = realpathSync(binPath);
|
|
50415
|
+
} catch {
|
|
50416
|
+
return null;
|
|
50417
|
+
}
|
|
50418
|
+
const norm = resolved.split(sep2).join("/");
|
|
50419
|
+
if (norm.includes("/pnpm/") || norm.includes("/.pnpm/") || process.env.PNPM_HOME && resolved.startsWith(process.env.PNPM_HOME)) {
|
|
50420
|
+
return {
|
|
50421
|
+
kind: "pnpm",
|
|
50422
|
+
binary: "pnpm",
|
|
50423
|
+
args: (pkg) => ["add", "-g", pkg]
|
|
50424
|
+
};
|
|
50425
|
+
}
|
|
50426
|
+
if (norm.includes("/.bun/") || norm.includes("/bun/install/") || process.env.BUN_INSTALL && resolved.startsWith(process.env.BUN_INSTALL)) {
|
|
50427
|
+
return {
|
|
50428
|
+
kind: "bun",
|
|
50429
|
+
binary: "bun",
|
|
50430
|
+
args: (pkg) => ["add", "-g", pkg]
|
|
50431
|
+
};
|
|
50432
|
+
}
|
|
50433
|
+
if (norm.includes("/.yarn/") || norm.includes("/yarn/global/")) {
|
|
50434
|
+
return {
|
|
50435
|
+
kind: "yarn",
|
|
50436
|
+
binary: "yarn",
|
|
50437
|
+
args: (pkg) => ["global", "add", pkg]
|
|
50438
|
+
};
|
|
50439
|
+
}
|
|
50440
|
+
if (norm.includes("/node_modules/")) {
|
|
50441
|
+
return {
|
|
50442
|
+
kind: "npm",
|
|
50443
|
+
binary: "npm",
|
|
50444
|
+
args: (pkg) => ["install", "-g", pkg]
|
|
50445
|
+
};
|
|
50446
|
+
}
|
|
50447
|
+
return null;
|
|
50448
|
+
}
|
|
50449
|
+
function installPrefix(resolvedBinPath) {
|
|
50450
|
+
const norm = resolvedBinPath.split(sep2).join("/");
|
|
50451
|
+
const idx = norm.indexOf("/node_modules/");
|
|
50452
|
+
if (idx < 0) return null;
|
|
50453
|
+
return resolvedBinPath.slice(0, idx);
|
|
50454
|
+
}
|
|
50455
|
+
function canWrite(path2) {
|
|
50456
|
+
try {
|
|
50457
|
+
accessSync(path2, constants2.W_OK);
|
|
50458
|
+
return true;
|
|
50459
|
+
} catch {
|
|
50460
|
+
return false;
|
|
50461
|
+
}
|
|
50462
|
+
}
|
|
50463
|
+
async function fetchLatest() {
|
|
50464
|
+
try {
|
|
50465
|
+
const ctl = new AbortController();
|
|
50466
|
+
const timer = setTimeout(() => ctl.abort(), FETCH_TIMEOUT_MS);
|
|
50467
|
+
const res = await fetch(
|
|
50468
|
+
`https://registry.npmjs.org/${encodeURIComponent(PKG_NAME2)}/latest`,
|
|
50469
|
+
{ headers: { Accept: "application/json" }, signal: ctl.signal }
|
|
50470
|
+
);
|
|
50471
|
+
clearTimeout(timer);
|
|
50472
|
+
if (!res.ok) return null;
|
|
50473
|
+
const data = await res.json();
|
|
50474
|
+
return typeof data.version === "string" ? data.version : null;
|
|
50475
|
+
} catch {
|
|
50476
|
+
return null;
|
|
50477
|
+
}
|
|
50478
|
+
}
|
|
50249
50479
|
async function confirm(prompt) {
|
|
50480
|
+
if (!process.stdin.isTTY) return false;
|
|
50250
50481
|
process.stderr.write(prompt);
|
|
50251
50482
|
return new Promise((resolve2) => {
|
|
50252
50483
|
let buf = "";
|
|
50253
50484
|
const onData = (chunk) => {
|
|
50254
50485
|
buf += chunk.toString("utf8");
|
|
50255
50486
|
const idx = buf.indexOf("\n");
|
|
50256
|
-
if (idx
|
|
50257
|
-
|
|
50258
|
-
|
|
50259
|
-
|
|
50260
|
-
}
|
|
50487
|
+
if (idx < 0) return;
|
|
50488
|
+
process.stdin.off("data", onData);
|
|
50489
|
+
const ans = buf.slice(0, idx).trim().toLowerCase();
|
|
50490
|
+
resolve2(ans === "y" || ans === "yes");
|
|
50261
50491
|
};
|
|
50262
50492
|
process.stdin.on("data", onData);
|
|
50263
50493
|
});
|
|
50264
50494
|
}
|
|
50265
|
-
|
|
50495
|
+
function printUpgradeCommand(latest, kind) {
|
|
50496
|
+
const cmd = (() => {
|
|
50497
|
+
switch (kind) {
|
|
50498
|
+
case "pnpm":
|
|
50499
|
+
return `pnpm add -g ${PKG_NAME2}@${latest}`;
|
|
50500
|
+
case "yarn":
|
|
50501
|
+
return `yarn global add ${PKG_NAME2}@${latest}`;
|
|
50502
|
+
case "bun":
|
|
50503
|
+
return `bun add -g ${PKG_NAME2}@${latest}`;
|
|
50504
|
+
default:
|
|
50505
|
+
return `npm install -g ${PKG_NAME2}@${latest}`;
|
|
50506
|
+
}
|
|
50507
|
+
})();
|
|
50508
|
+
process.stderr.write(` Run: ${import_chalk12.default.cyan(cmd)}
|
|
50509
|
+
|
|
50510
|
+
`);
|
|
50511
|
+
}
|
|
50512
|
+
function invalidateUpdateCache() {
|
|
50266
50513
|
try {
|
|
50267
|
-
|
|
50268
|
-
const resp = await fetch(`${config.apiUrl}/v1/auth/revoke`, {
|
|
50269
|
-
method: "POST",
|
|
50270
|
-
headers: { Authorization: `Bearer ${apiKey}` },
|
|
50271
|
-
signal: AbortSignal.timeout(5e3)
|
|
50272
|
-
});
|
|
50273
|
-
return resp.ok;
|
|
50514
|
+
unlinkSync6(dgCachePath("update-check.json"));
|
|
50274
50515
|
} catch {
|
|
50275
|
-
return false;
|
|
50276
50516
|
}
|
|
50277
50517
|
}
|
|
50278
|
-
async function
|
|
50279
|
-
|
|
50280
|
-
|
|
50281
|
-
|
|
50282
|
-
|
|
50283
|
-
|
|
50284
|
-
process.stderr.write("
|
|
50285
|
-
|
|
50286
|
-
|
|
50518
|
+
async function runUpdate(args, currentVersion) {
|
|
50519
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
50520
|
+
process.stdout.write(USAGE4);
|
|
50521
|
+
return 0;
|
|
50522
|
+
}
|
|
50523
|
+
const opts = parseUpdateArgs(args);
|
|
50524
|
+
process.stderr.write(import_chalk12.default.dim(" Checking npm registry...\n"));
|
|
50525
|
+
const latest = await fetchLatest();
|
|
50526
|
+
if (!latest) {
|
|
50527
|
+
process.stderr.write(import_chalk12.default.red(" Could not reach npm registry.\n"));
|
|
50528
|
+
return 1;
|
|
50529
|
+
}
|
|
50530
|
+
if (!isNewer(latest, currentVersion)) {
|
|
50531
|
+
process.stderr.write(
|
|
50532
|
+
import_chalk12.default.green(` Already on latest version (${currentVersion}).
|
|
50533
|
+
`)
|
|
50534
|
+
);
|
|
50535
|
+
invalidateUpdateCache();
|
|
50536
|
+
return 0;
|
|
50537
|
+
}
|
|
50538
|
+
process.stderr.write(
|
|
50539
|
+
`
|
|
50540
|
+
${import_chalk12.default.bold("Update available:")} ${currentVersion} ${import_chalk12.default.dim("\u2192")} ${import_chalk12.default.cyan(latest)}
|
|
50541
|
+
`
|
|
50542
|
+
);
|
|
50543
|
+
const installer = detectInstaller(process.argv[1] ?? "");
|
|
50544
|
+
if (!installer || opts.printOnly) {
|
|
50545
|
+
printUpgradeCommand(latest, installer?.kind ?? null);
|
|
50546
|
+
return 0;
|
|
50547
|
+
}
|
|
50548
|
+
let resolvedBin;
|
|
50549
|
+
try {
|
|
50550
|
+
resolvedBin = realpathSync(process.argv[1]);
|
|
50551
|
+
} catch {
|
|
50552
|
+
printUpgradeCommand(latest, installer.kind);
|
|
50553
|
+
return 0;
|
|
50554
|
+
}
|
|
50555
|
+
if (process.platform === "win32") {
|
|
50556
|
+
process.stderr.write(
|
|
50557
|
+
import_chalk12.default.dim(" Detected installer: ") + import_chalk12.default.bold(installer.kind) + "\n"
|
|
50558
|
+
);
|
|
50559
|
+
process.stderr.write(
|
|
50560
|
+
import_chalk12.default.yellow(" Auto-upgrade not supported on Windows \u2014 run the command below.\n")
|
|
50561
|
+
);
|
|
50562
|
+
printUpgradeCommand(latest, installer.kind);
|
|
50563
|
+
return 0;
|
|
50564
|
+
}
|
|
50565
|
+
if (installer.kind === "npm") {
|
|
50566
|
+
const prefix = installPrefix(resolvedBin);
|
|
50567
|
+
if (prefix && !canWrite(prefix)) {
|
|
50568
|
+
process.stderr.write(
|
|
50569
|
+
import_chalk12.default.dim(" Detected installer: ") + import_chalk12.default.bold("npm") + import_chalk12.default.dim(` (prefix: ${prefix})
|
|
50570
|
+
`)
|
|
50571
|
+
);
|
|
50572
|
+
process.stderr.write(
|
|
50573
|
+
import_chalk12.default.yellow(" Prefix is not writable \u2014 needs elevated permissions.\n")
|
|
50574
|
+
);
|
|
50575
|
+
process.stderr.write(` Run: ${import_chalk12.default.cyan(`sudo npm install -g ${PKG_NAME2}@${latest}`)}
|
|
50576
|
+
|
|
50287
50577
|
`);
|
|
50288
|
-
|
|
50289
|
-
|
|
50290
|
-
|
|
50291
|
-
process.stderr.write(
|
|
50578
|
+
return 0;
|
|
50579
|
+
}
|
|
50580
|
+
}
|
|
50581
|
+
process.stderr.write(
|
|
50582
|
+
import_chalk12.default.dim(" Detected installer: ") + import_chalk12.default.bold(installer.kind) + "\n"
|
|
50583
|
+
);
|
|
50584
|
+
const fullCmd = `${installer.binary} ${installer.args(`${PKG_NAME2}@${latest}`).join(" ")}`;
|
|
50585
|
+
process.stderr.write(import_chalk12.default.dim(` Command: ${fullCmd}
|
|
50586
|
+
|
|
50587
|
+
`));
|
|
50292
50588
|
if (!opts.assumeYes) {
|
|
50293
50589
|
if (!process.stdin.isTTY) {
|
|
50294
|
-
process.stderr.write(
|
|
50590
|
+
process.stderr.write(
|
|
50591
|
+
import_chalk12.default.yellow(" Non-interactive shell \u2014 pass --yes to proceed, or copy the command above.\n\n")
|
|
50592
|
+
);
|
|
50295
50593
|
return 1;
|
|
50296
50594
|
}
|
|
50297
|
-
const ok = await confirm("
|
|
50595
|
+
const ok = await confirm(" Proceed? [y/N] ");
|
|
50596
|
+
process.stderr.write("\n");
|
|
50298
50597
|
if (!ok) {
|
|
50299
|
-
process.stderr.write(import_chalk12.default.dim("
|
|
50598
|
+
process.stderr.write(import_chalk12.default.dim(" Cancelled.\n\n"));
|
|
50300
50599
|
return 0;
|
|
50301
50600
|
}
|
|
50302
|
-
process.stderr.write("\n");
|
|
50303
50601
|
}
|
|
50304
|
-
const
|
|
50305
|
-
|
|
50306
|
-
|
|
50307
|
-
|
|
50308
|
-
|
|
50309
|
-
|
|
50310
|
-
|
|
50311
|
-
|
|
50312
|
-
|
|
50313
|
-
|
|
50602
|
+
const result = spawnSync(
|
|
50603
|
+
installer.binary,
|
|
50604
|
+
installer.args(`${PKG_NAME2}@${latest}`),
|
|
50605
|
+
{ stdio: "inherit" }
|
|
50606
|
+
);
|
|
50607
|
+
if (result.error && result.error.code === "ENOENT") {
|
|
50608
|
+
process.stderr.write(
|
|
50609
|
+
import_chalk12.default.red(`
|
|
50610
|
+
Installer not found in PATH: ${installer.binary}
|
|
50611
|
+
`)
|
|
50612
|
+
);
|
|
50613
|
+
printUpgradeCommand(latest, installer.kind);
|
|
50614
|
+
return 1;
|
|
50314
50615
|
}
|
|
50315
|
-
|
|
50316
|
-
|
|
50317
|
-
|
|
50318
|
-
|
|
50319
|
-
|
|
50320
|
-
|
|
50321
|
-
|
|
50322
|
-
process.stderr.write(import_chalk12.default.red(" \u2718 ") + `Couldn't remove ${p}: ${e.message}
|
|
50323
|
-
`);
|
|
50324
|
-
}
|
|
50325
|
-
}
|
|
50616
|
+
if (result.status !== 0) {
|
|
50617
|
+
process.stderr.write(
|
|
50618
|
+
import_chalk12.default.red(`
|
|
50619
|
+
Upgrade failed (${installer.binary} exited ${result.status ?? "with signal"}).
|
|
50620
|
+
`)
|
|
50621
|
+
);
|
|
50622
|
+
return result.status ?? 1;
|
|
50326
50623
|
}
|
|
50327
|
-
|
|
50328
|
-
|
|
50329
|
-
|
|
50330
|
-
|
|
50624
|
+
invalidateUpdateCache();
|
|
50625
|
+
process.stderr.write(
|
|
50626
|
+
"\n" + import_chalk12.default.bold.green(` Updated to ${latest}.
|
|
50627
|
+
`) + import_chalk12.default.dim(" Re-run any in-progress dg commands to pick up the new version.\n\n")
|
|
50628
|
+
);
|
|
50331
50629
|
return 0;
|
|
50332
50630
|
}
|
|
50333
|
-
|
|
50334
|
-
|
|
50335
|
-
return runCleanup({ assumeYes });
|
|
50631
|
+
function handleUpdateCommand(args, currentVersion) {
|
|
50632
|
+
return runUpdate(args, currentVersion);
|
|
50336
50633
|
}
|
|
50337
|
-
var import_chalk12;
|
|
50338
|
-
var
|
|
50339
|
-
"src/commands/
|
|
50634
|
+
var import_chalk12, PKG_NAME2, FETCH_TIMEOUT_MS, USAGE4;
|
|
50635
|
+
var init_update = __esm({
|
|
50636
|
+
"src/commands/update.ts"() {
|
|
50340
50637
|
"use strict";
|
|
50341
50638
|
import_chalk12 = __toESM(require_source());
|
|
50342
|
-
init_protect();
|
|
50343
|
-
init_auth();
|
|
50344
|
-
init_config();
|
|
50345
50639
|
init_paths();
|
|
50640
|
+
init_update_check();
|
|
50641
|
+
PKG_NAME2 = "@westbayberry/dg";
|
|
50642
|
+
FETCH_TIMEOUT_MS = 5e3;
|
|
50643
|
+
USAGE4 = `
|
|
50644
|
+
dg update \u2014 upgrade dg to the latest version
|
|
50645
|
+
|
|
50646
|
+
Detects the package manager dg was installed with (npm / pnpm / yarn / bun)
|
|
50647
|
+
and runs the matching global-upgrade command. Falls back to printing the
|
|
50648
|
+
command on Windows or when the installer can't be detected.
|
|
50649
|
+
|
|
50650
|
+
Usage:
|
|
50651
|
+
dg update [options]
|
|
50652
|
+
|
|
50653
|
+
Options:
|
|
50654
|
+
--yes, -y Skip the confirmation prompt
|
|
50655
|
+
--print Show the upgrade command without running it
|
|
50656
|
+
--dry-run Alias for --print
|
|
50657
|
+
--help, -h Show this help
|
|
50658
|
+
|
|
50659
|
+
`;
|
|
50346
50660
|
}
|
|
50347
50661
|
});
|
|
50348
50662
|
|
|
@@ -50353,7 +50667,7 @@ __export(uninstall_exports, {
|
|
|
50353
50667
|
parseUninstallArgs: () => parseUninstallArgs,
|
|
50354
50668
|
runUninstall: () => runUninstall
|
|
50355
50669
|
});
|
|
50356
|
-
import { existsSync as
|
|
50670
|
+
import { existsSync as existsSync17, rmSync as rmSync3, unlinkSync as unlinkSync7, statSync as statSync5 } from "node:fs";
|
|
50357
50671
|
function parseUninstallArgs(args) {
|
|
50358
50672
|
return {
|
|
50359
50673
|
assumeYes: args.includes("--yes") || args.includes("-y"),
|
|
@@ -50364,7 +50678,7 @@ function parseUninstallArgs(args) {
|
|
|
50364
50678
|
}
|
|
50365
50679
|
function safeExists(p) {
|
|
50366
50680
|
try {
|
|
50367
|
-
return
|
|
50681
|
+
return existsSync17(p);
|
|
50368
50682
|
} catch {
|
|
50369
50683
|
return false;
|
|
50370
50684
|
}
|
|
@@ -50480,7 +50794,7 @@ async function revokeApiKey(apiKey) {
|
|
|
50480
50794
|
}
|
|
50481
50795
|
function rmFile(path2) {
|
|
50482
50796
|
try {
|
|
50483
|
-
|
|
50797
|
+
unlinkSync7(path2);
|
|
50484
50798
|
return { ok: true };
|
|
50485
50799
|
} catch (e) {
|
|
50486
50800
|
const code = e.code;
|
|
@@ -50506,7 +50820,7 @@ function isWritableTarget(path2) {
|
|
|
50506
50820
|
}
|
|
50507
50821
|
async function runUninstall(args) {
|
|
50508
50822
|
if (args.includes("--help") || args.includes("-h")) {
|
|
50509
|
-
process.stdout.write(
|
|
50823
|
+
process.stdout.write(USAGE5);
|
|
50510
50824
|
return 0;
|
|
50511
50825
|
}
|
|
50512
50826
|
const opts = parseUninstallArgs(args);
|
|
@@ -50544,7 +50858,7 @@ async function runUninstall(args) {
|
|
|
50544
50858
|
}
|
|
50545
50859
|
if (!opts.keepHooks && !opts.soft) {
|
|
50546
50860
|
for (const h of plan.hooks) {
|
|
50547
|
-
if (!
|
|
50861
|
+
if (!existsSync17(h.repoPath)) {
|
|
50548
50862
|
process.stderr.write(import_chalk13.default.dim(` \xB7 ${h.repoPath} no longer exists \u2014 skipping registered hook
|
|
50549
50863
|
`));
|
|
50550
50864
|
continue;
|
|
@@ -50630,7 +50944,7 @@ async function runUninstall(args) {
|
|
|
50630
50944
|
function handleUninstallCommand(args) {
|
|
50631
50945
|
return runUninstall(args);
|
|
50632
50946
|
}
|
|
50633
|
-
var import_chalk13, REVOKE_TIMEOUT_MS,
|
|
50947
|
+
var import_chalk13, REVOKE_TIMEOUT_MS, USAGE5;
|
|
50634
50948
|
var init_uninstall = __esm({
|
|
50635
50949
|
"src/commands/uninstall.ts"() {
|
|
50636
50950
|
"use strict";
|
|
@@ -50642,7 +50956,7 @@ var init_uninstall = __esm({
|
|
|
50642
50956
|
init_auth();
|
|
50643
50957
|
init_config();
|
|
50644
50958
|
REVOKE_TIMEOUT_MS = 5e3;
|
|
50645
|
-
|
|
50959
|
+
USAGE5 = `
|
|
50646
50960
|
dg uninstall \u2014 remove every file dg has written locally
|
|
50647
50961
|
|
|
50648
50962
|
Usage:
|
|
@@ -50678,10 +50992,9 @@ __export(init_exports, {
|
|
|
50678
50992
|
parseInitArgs: () => parseInitArgs,
|
|
50679
50993
|
runInit: () => runInit2
|
|
50680
50994
|
});
|
|
50681
|
-
import { existsSync as
|
|
50995
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
50682
50996
|
import { join as join12 } from "node:path";
|
|
50683
50997
|
import * as readline2 from "node:readline";
|
|
50684
|
-
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
50685
50998
|
function parseInitArgs(args) {
|
|
50686
50999
|
const opts = {
|
|
50687
51000
|
assumeYes: false,
|
|
@@ -50730,23 +51043,20 @@ async function confirm3(prompt, defaultYes, assumeYes) {
|
|
|
50730
51043
|
});
|
|
50731
51044
|
}
|
|
50732
51045
|
function detectEcosystem(cwd2) {
|
|
50733
|
-
const npm =
|
|
50734
|
-
const pypi =
|
|
51046
|
+
const npm = existsSync18(join12(cwd2, "package.json")) || existsSync18(join12(cwd2, "package-lock.json")) || existsSync18(join12(cwd2, "pnpm-lock.yaml")) || existsSync18(join12(cwd2, "yarn.lock"));
|
|
51047
|
+
const pypi = existsSync18(join12(cwd2, "pyproject.toml")) || existsSync18(join12(cwd2, "setup.py")) || existsSync18(join12(cwd2, "requirements.txt")) || existsSync18(join12(cwd2, "Pipfile")) || existsSync18(join12(cwd2, "poetry.lock"));
|
|
50735
51048
|
return { npm, pypi };
|
|
50736
51049
|
}
|
|
50737
51050
|
function findRepoRootOrNull(cwd2) {
|
|
50738
51051
|
try {
|
|
50739
|
-
return
|
|
50740
|
-
encoding: "utf-8",
|
|
50741
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
50742
|
-
}).trim();
|
|
51052
|
+
return safeGit(["rev-parse", "--show-toplevel"], { cwd: cwd2 }).trim();
|
|
50743
51053
|
} catch {
|
|
50744
51054
|
return null;
|
|
50745
51055
|
}
|
|
50746
51056
|
}
|
|
50747
51057
|
async function runInit2(args) {
|
|
50748
51058
|
if (args.includes("--help") || args.includes("-h")) {
|
|
50749
|
-
process.stdout.write(
|
|
51059
|
+
process.stdout.write(USAGE6);
|
|
50750
51060
|
return 0;
|
|
50751
51061
|
}
|
|
50752
51062
|
const opts = parseInitArgs(args);
|
|
@@ -50974,7 +51284,7 @@ async function runInit2(args) {
|
|
|
50974
51284
|
function handleInitCommand(args) {
|
|
50975
51285
|
return runInit2(args);
|
|
50976
51286
|
}
|
|
50977
|
-
var import_chalk14,
|
|
51287
|
+
var import_chalk14, USAGE6;
|
|
50978
51288
|
var init_init = __esm({
|
|
50979
51289
|
"src/commands/init.ts"() {
|
|
50980
51290
|
"use strict";
|
|
@@ -50984,7 +51294,8 @@ var init_init = __esm({
|
|
|
50984
51294
|
init_hooks_registry();
|
|
50985
51295
|
init_protect();
|
|
50986
51296
|
init_paths();
|
|
50987
|
-
|
|
51297
|
+
init_safe_git();
|
|
51298
|
+
USAGE6 = `
|
|
50988
51299
|
dg init \u2014 fast per-project setup
|
|
50989
51300
|
|
|
50990
51301
|
Usage:
|
|
@@ -51410,10 +51721,12 @@ var init_ProjectSelector = __esm({
|
|
|
51410
51721
|
await init_build2();
|
|
51411
51722
|
import_chalk17 = __toESM(require_source());
|
|
51412
51723
|
init_sanitize();
|
|
51724
|
+
await init_useTerminalSize();
|
|
51413
51725
|
import_jsx_runtime13 = __toESM(require_jsx_runtime());
|
|
51414
51726
|
ProjectSelector = ({ projects, onConfirm, onCancel, userStatus }) => {
|
|
51415
51727
|
const [cursor, setCursor] = (0, import_react35.useState)(0);
|
|
51416
51728
|
const [selected, setSelected] = (0, import_react35.useState)(() => new Set(projects.map((_, i) => i)));
|
|
51729
|
+
const { cols: termCols } = useTerminalSize();
|
|
51417
51730
|
use_input_default((input, key) => {
|
|
51418
51731
|
if (key.upArrow) {
|
|
51419
51732
|
setCursor((c) => Math.max(0, c - 1));
|
|
@@ -51441,8 +51754,6 @@ var init_ProjectSelector = __esm({
|
|
|
51441
51754
|
const ecosystemLabel = (eco) => eco === "npm" ? import_chalk17.default.magenta("npm") : import_chalk17.default.blue("pip");
|
|
51442
51755
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
|
|
51443
51756
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { children: [
|
|
51444
|
-
import_chalk17.default.cyan("\u25C6"),
|
|
51445
|
-
" ",
|
|
51446
51757
|
import_chalk17.default.bold("Dependency Guardian"),
|
|
51447
51758
|
" ",
|
|
51448
51759
|
userStatus ? import_chalk17.default.dim(userStatus) : ""
|
|
@@ -51460,8 +51771,20 @@ var init_ProjectSelector = __esm({
|
|
|
51460
51771
|
const isSelected = selected.has(i);
|
|
51461
51772
|
const prefix = isCursor ? import_chalk17.default.cyan("\u258C") : " ";
|
|
51462
51773
|
const check = isSelected ? import_chalk17.default.green("\u25C9") : import_chalk17.default.dim("\u25CB");
|
|
51463
|
-
const
|
|
51464
|
-
|
|
51774
|
+
const ecoCount = `${ecosystemLabel(proj.ecosystem)} ${proj.packageCount} packages`;
|
|
51775
|
+
const ecoCountPlainLen = `${proj.ecosystem} ${proj.packageCount} packages`.length;
|
|
51776
|
+
const fixedPrefixLen = 4;
|
|
51777
|
+
const pathColWidth = Math.max(20, termCols - fixedPrefixLen - ecoCountPlainLen - 3);
|
|
51778
|
+
const path2 = sanitize(proj.relativePath);
|
|
51779
|
+
const pathTruncated = path2.length > pathColWidth ? path2.slice(0, Math.max(1, pathColWidth - 1)) + "\u2026" : path2.padEnd(pathColWidth);
|
|
51780
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { backgroundColor: isCursor ? "#1a1a2e" : void 0, wrap: "truncate-end", children: [
|
|
51781
|
+
prefix,
|
|
51782
|
+
check,
|
|
51783
|
+
" ",
|
|
51784
|
+
pathTruncated,
|
|
51785
|
+
" ",
|
|
51786
|
+
ecoCount
|
|
51787
|
+
] }, i);
|
|
51465
51788
|
}),
|
|
51466
51789
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { children: "" }),
|
|
51467
51790
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { dimColor: true, children: selected.size === 0 ? import_chalk17.default.yellow("Select at least 1 project to scan") : `${selected.size} of ${projects.length} selected` }),
|
|
@@ -51507,7 +51830,7 @@ var init_SetupBanner = __esm({
|
|
|
51507
51830
|
paddingRight: 1,
|
|
51508
51831
|
width: "100%",
|
|
51509
51832
|
children: [
|
|
51510
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Text, { children: [
|
|
51833
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Text, { wrap: "truncate-end", children: [
|
|
51511
51834
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { color: "yellow", bold: true, children: "! Setup incomplete" }),
|
|
51512
51835
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Text, { dimColor: true, children: [
|
|
51513
51836
|
" \u2014 ",
|
|
@@ -51515,7 +51838,7 @@ var init_SetupBanner = __esm({
|
|
|
51515
51838
|
" you haven't set up yet"
|
|
51516
51839
|
] })
|
|
51517
51840
|
] }),
|
|
51518
|
-
issues.map((issue) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Text, { children: [
|
|
51841
|
+
issues.map((issue) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Text, { wrap: "truncate-end", children: [
|
|
51519
51842
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { dimColor: true, children: " \xB7 " }),
|
|
51520
51843
|
issue.label,
|
|
51521
51844
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Text, { dimColor: true, children: " \u2192 " }),
|
|
@@ -51625,7 +51948,7 @@ var init_App2 = __esm({
|
|
|
51625
51948
|
return () => clearTimeout(timer);
|
|
51626
51949
|
}
|
|
51627
51950
|
if (state.phase === "trial_exhausted") {
|
|
51628
|
-
let msg = "You've used your 5 free anonymous scans. Run `dg login` to
|
|
51951
|
+
let msg = "You've used your 5 free anonymous scans. Run `dg login` to access Dependency Guardian for free.\n";
|
|
51629
51952
|
try {
|
|
51630
51953
|
if (getStoredApiKey()) {
|
|
51631
51954
|
msg = "Your session expired. Run `dg logout` then `dg login` to re-authenticate.\n";
|
|
@@ -51708,28 +52031,10 @@ var init_App2 = __esm({
|
|
|
51708
52031
|
] })
|
|
51709
52032
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
51710
52033
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: "yellow", bold: true, children: "You've used your 5 free anonymous scans." }),
|
|
51711
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { children: " " }),
|
|
51712
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { children: "Sign in (free, 10 seconds) to unlock:" }),
|
|
51713
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Text, { children: [
|
|
51714
|
-
" ",
|
|
51715
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: "green", children: "\u2713" }),
|
|
51716
|
-
" unlimited scans"
|
|
51717
|
-
] }),
|
|
51718
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Text, { children: [
|
|
51719
|
-
" ",
|
|
51720
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: "green", children: "\u2713" }),
|
|
51721
|
-
" scan history + saved reports"
|
|
51722
|
-
] }),
|
|
51723
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Text, { children: [
|
|
51724
|
-
" ",
|
|
51725
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: "green", children: "\u2713" }),
|
|
51726
|
-
" GitHub App for team / PR scanning"
|
|
51727
|
-
] }),
|
|
51728
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { children: " " }),
|
|
51729
52034
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Text, { children: [
|
|
51730
52035
|
"Run ",
|
|
51731
52036
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
|
|
51732
|
-
"
|
|
52037
|
+
" to access Dependency Guardian for free."
|
|
51733
52038
|
] })
|
|
51734
52039
|
] }) });
|
|
51735
52040
|
}
|
|
@@ -52656,7 +52961,7 @@ import {
|
|
|
52656
52961
|
readFileSync as readFileSync5,
|
|
52657
52962
|
writeFileSync as writeFileSync4,
|
|
52658
52963
|
copyFileSync,
|
|
52659
|
-
unlinkSync as
|
|
52964
|
+
unlinkSync as unlinkSync3,
|
|
52660
52965
|
rmSync as rmSync2,
|
|
52661
52966
|
chmodSync as chmodSync2,
|
|
52662
52967
|
statSync,
|
|
@@ -52667,12 +52972,12 @@ import {
|
|
|
52667
52972
|
import { dirname as dirname4 } from "node:path";
|
|
52668
52973
|
var README = `dependency-guardian \u2014 local state for the dg CLI.
|
|
52669
52974
|
|
|
52670
|
-
config.json
|
|
52671
|
-
cache/
|
|
52672
|
-
|
|
52673
|
-
|
|
52674
|
-
state/
|
|
52675
|
-
state/
|
|
52975
|
+
config.json your account + preferences (mode 0600)
|
|
52976
|
+
cache/update-check.json latest-version probe (24h TTL)
|
|
52977
|
+
state/aliases.sh optional shell aliases (npm/pip wrappers)
|
|
52978
|
+
state/auth-status.json 60s cache of /v1/auth/status
|
|
52979
|
+
state/trial-banner throttle stamp for the trial nudge
|
|
52980
|
+
state/bypass-log.jsonl append-only log of install-wrapper bypasses
|
|
52676
52981
|
state/hooks-installed.json registry of git hooks dg installed
|
|
52677
52982
|
|
|
52678
52983
|
To remove everything dg has written to your machine, run:
|
|
@@ -52700,7 +53005,7 @@ function moveFile(from, to, mode) {
|
|
|
52700
53005
|
if (statSync(to).size !== statSync(from).size) {
|
|
52701
53006
|
throw new Error(`size mismatch after copy: ${from} -> ${to}`);
|
|
52702
53007
|
}
|
|
52703
|
-
|
|
53008
|
+
unlinkSync3(from);
|
|
52704
53009
|
}
|
|
52705
53010
|
function isPidAlive(pid) {
|
|
52706
53011
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -52728,7 +53033,7 @@ function acquireLock(lockPath) {
|
|
|
52728
53033
|
}
|
|
52729
53034
|
if (!stale) return "held";
|
|
52730
53035
|
try {
|
|
52731
|
-
|
|
53036
|
+
unlinkSync3(lockPath);
|
|
52732
53037
|
} catch {
|
|
52733
53038
|
}
|
|
52734
53039
|
}
|
|
@@ -52752,7 +53057,7 @@ function releaseLock(state) {
|
|
|
52752
53057
|
}
|
|
52753
53058
|
}
|
|
52754
53059
|
try {
|
|
52755
|
-
|
|
53060
|
+
unlinkSync3(state.lockPath);
|
|
52756
53061
|
} catch {
|
|
52757
53062
|
}
|
|
52758
53063
|
}
|
|
@@ -52761,7 +53066,7 @@ function rollback(moves) {
|
|
|
52761
53066
|
try {
|
|
52762
53067
|
if (existsSync5(m.to) && !existsSync5(m.from)) {
|
|
52763
53068
|
copyFileSync(m.to, m.from);
|
|
52764
|
-
|
|
53069
|
+
unlinkSync3(m.to);
|
|
52765
53070
|
}
|
|
52766
53071
|
} catch {
|
|
52767
53072
|
}
|
|
@@ -52769,7 +53074,7 @@ function rollback(moves) {
|
|
|
52769
53074
|
}
|
|
52770
53075
|
function detectLegacy() {
|
|
52771
53076
|
const legacy = legacyPaths();
|
|
52772
|
-
return existsSync5(legacy.dgrc) || existsSync5(legacy.
|
|
53077
|
+
return existsSync5(legacy.dgrc) || existsSync5(legacy.updateCheck) || existsSync5(legacy.trialBannerOld) || existsSync5(legacy.aliasesShOld) || existsSync5(legacy.depGuardianDir);
|
|
52773
53078
|
}
|
|
52774
53079
|
function validateLegacyConfig(path2) {
|
|
52775
53080
|
let raw;
|
|
@@ -52826,23 +53131,13 @@ function runMigrationIfNeeded() {
|
|
|
52826
53131
|
} catch {
|
|
52827
53132
|
}
|
|
52828
53133
|
try {
|
|
52829
|
-
|
|
53134
|
+
unlinkSync3(legacy.dgrc);
|
|
52830
53135
|
} catch {
|
|
52831
53136
|
}
|
|
52832
53137
|
moves.push({ from: legacy.dgrc, to: p.config });
|
|
52833
53138
|
movedCount++;
|
|
52834
53139
|
}
|
|
52835
53140
|
ensureDir(p.cacheDir, 448);
|
|
52836
|
-
if (existsSync5(legacy.cacheSqlite)) {
|
|
52837
|
-
moveFile(legacy.cacheSqlite, p.cacheSqlite, 384);
|
|
52838
|
-
moves.push({ from: legacy.cacheSqlite, to: p.cacheSqlite });
|
|
52839
|
-
movedCount++;
|
|
52840
|
-
}
|
|
52841
|
-
if (existsSync5(legacy.routingHint)) {
|
|
52842
|
-
moveFile(legacy.routingHint, p.routingHint, 384);
|
|
52843
|
-
moves.push({ from: legacy.routingHint, to: p.routingHint });
|
|
52844
|
-
movedCount++;
|
|
52845
|
-
}
|
|
52846
53141
|
if (existsSync5(legacy.updateCheck)) {
|
|
52847
53142
|
moveFile(legacy.updateCheck, p.updateCheck, 384);
|
|
52848
53143
|
moves.push({ from: legacy.updateCheck, to: p.updateCheck });
|
|
@@ -52862,9 +53157,7 @@ function runMigrationIfNeeded() {
|
|
|
52862
53157
|
if (existsSync5(legacy.depGuardianDir) && legacy.depGuardianDir !== p.root) {
|
|
52863
53158
|
const candidates = [
|
|
52864
53159
|
{ from: join(legacy.depGuardianDir, "config.json"), to: p.config, mode: 384 },
|
|
52865
|
-
{ from: join(legacy.depGuardianDir, "cache", "scans.sqlite"), to: p.cacheSqlite, mode: 384 },
|
|
52866
53160
|
{ from: join(legacy.depGuardianDir, "cache", "update-check.json"), to: p.updateCheck, mode: 384 },
|
|
52867
|
-
{ from: join(legacy.depGuardianDir, "cache", "routing-hint.json"), to: p.routingHint, mode: 384 },
|
|
52868
53161
|
{ from: join(legacy.depGuardianDir, "state", "aliases.sh"), to: p.aliasesSh, mode: 420 },
|
|
52869
53162
|
{ from: join(legacy.depGuardianDir, "state", "trial-banner"), to: p.trialBanner, mode: 384 },
|
|
52870
53163
|
{ from: join(legacy.depGuardianDir, "state", "hooks-installed.json"), to: p.hooksRegistry, mode: 384 },
|
|
@@ -52941,8 +53234,8 @@ var isInteractive = process.stdout.isTTY === true && !process.env.CI && !process
|
|
|
52941
53234
|
async function main() {
|
|
52942
53235
|
const rawCommand = process.argv[2];
|
|
52943
53236
|
if (!rawCommand || rawCommand === "help" || rawCommand === "--help" || rawCommand === "-h") {
|
|
52944
|
-
const { USAGE:
|
|
52945
|
-
process.stdout.write(
|
|
53237
|
+
const { USAGE: USAGE7 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
53238
|
+
process.stdout.write(USAGE7);
|
|
52946
53239
|
return;
|
|
52947
53240
|
}
|
|
52948
53241
|
if (rawCommand === "--help-all" || rawCommand === "help-all") {
|
|
@@ -52955,7 +53248,7 @@ async function main() {
|
|
|
52955
53248
|
`);
|
|
52956
53249
|
return;
|
|
52957
53250
|
}
|
|
52958
|
-
const KNOWN_COMMANDS = ["init", "scan", "licenses", "npm", "pip", "wrap", "login", "logout", "status", "hook", "update", "help", "version", "protect", "publish-check", "
|
|
53251
|
+
const KNOWN_COMMANDS = ["init", "scan", "licenses", "npm", "pip", "wrap", "login", "logout", "status", "hook", "update", "help", "version", "protect", "publish-check", "uninstall"];
|
|
52959
53252
|
if (rawCommand && !rawCommand.startsWith("-") && !KNOWN_COMMANDS.includes(rawCommand)) {
|
|
52960
53253
|
const chalk18 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
|
|
52961
53254
|
const best = closestCommand(rawCommand, KNOWN_COMMANDS);
|
|
@@ -53019,11 +53312,11 @@ async function main() {
|
|
|
53019
53312
|
if (v === "npm" || v === "pypi") ecosystem = v;
|
|
53020
53313
|
}
|
|
53021
53314
|
const { runNpmPublishCheck: runNpmPublishCheck2, runPypiPublishCheck: runPypiPublishCheck2, renderPublishCheckResult: renderPublishCheckResult2 } = await Promise.resolve().then(() => (init_publish_check(), publish_check_exports));
|
|
53022
|
-
const { existsSync:
|
|
53315
|
+
const { existsSync: existsSync19 } = await import("node:fs");
|
|
53023
53316
|
const { join: join13 } = await import("node:path");
|
|
53024
53317
|
if (ecosystem === "auto") {
|
|
53025
|
-
if (
|
|
53026
|
-
else if (
|
|
53318
|
+
if (existsSync19(join13(process.cwd(), "package.json"))) ecosystem = "npm";
|
|
53319
|
+
else if (existsSync19(join13(process.cwd(), "pyproject.toml")) || existsSync19(join13(process.cwd(), "setup.py"))) ecosystem = "pypi";
|
|
53027
53320
|
else {
|
|
53028
53321
|
process.stderr.write("\n publish-check: no package.json, pyproject.toml, or setup.py in current directory.\n Pass --ecosystem npm|pypi explicitly if your project layout differs.\n\n");
|
|
53029
53322
|
process.exit(3);
|
|
@@ -53084,12 +53377,8 @@ async function main() {
|
|
|
53084
53377
|
return;
|
|
53085
53378
|
}
|
|
53086
53379
|
if (rawCommand === "update") {
|
|
53087
|
-
await
|
|
53088
|
-
|
|
53089
|
-
}
|
|
53090
|
-
if (rawCommand === "cleanup") {
|
|
53091
|
-
const { handleCleanupCommand: handleCleanupCommand2 } = await Promise.resolve().then(() => (init_cleanup(), cleanup_exports));
|
|
53092
|
-
const code = await handleCleanupCommand2(process.argv.slice(3));
|
|
53380
|
+
const { handleUpdateCommand: handleUpdateCommand2 } = await Promise.resolve().then(() => (init_update(), update_exports));
|
|
53381
|
+
const code = await handleUpdateCommand2(process.argv.slice(3), CLI_VERSION);
|
|
53093
53382
|
process.exit(code);
|
|
53094
53383
|
}
|
|
53095
53384
|
if (rawCommand === "uninstall") {
|
|
@@ -53213,10 +53502,11 @@ async function main() {
|
|
|
53213
53502
|
const { render: render3 } = await init_build2().then(() => build_exports);
|
|
53214
53503
|
const React23 = await Promise.resolve().then(() => __toESM(require_react()));
|
|
53215
53504
|
const { App: App3 } = await init_App2().then(() => App_exports);
|
|
53216
|
-
const { setInkInstance: setInkInstance2, resetInkClear: resetInkClear2, initInkInstances: initInkInstances2 } = await Promise.resolve().then(() => (init_ink_controls(), ink_controls_exports));
|
|
53505
|
+
const { setInkInstance: setInkInstance2, resetInkClear: resetInkClear2, initInkInstances: initInkInstances2, patchInkLogForAbsolutePositioning: patchInkLogForAbsolutePositioning2 } = await Promise.resolve().then(() => (init_ink_controls(), ink_controls_exports));
|
|
53217
53506
|
await initInkInstances2();
|
|
53218
53507
|
const inst = render3(React23.createElement(App3, { config, userStatus, scanUsage, setupIssues }));
|
|
53219
53508
|
setInkInstance2(inst);
|
|
53509
|
+
patchInkLogForAbsolutePositioning2();
|
|
53220
53510
|
try {
|
|
53221
53511
|
await inst.waitUntilExit();
|
|
53222
53512
|
} finally {
|