@westbayberry/dg 1.0.37 → 1.0.39

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.
Files changed (2) hide show
  1. package/dist/index.mjs +898 -1993
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -264,6 +264,7 @@ function parseConfig(argv, strictFlags = true) {
264
264
  "scan-all": { type: "boolean", default: false },
265
265
  "base-lockfile": { type: "string" },
266
266
  workspace: { type: "string", short: "w" },
267
+ output: { type: "string", short: "o" },
267
268
  debug: { type: "boolean", default: false },
268
269
  help: { type: "boolean", default: false },
269
270
  version: { type: "boolean", default: false },
@@ -329,6 +330,7 @@ function parseConfig(argv, strictFlags = true) {
329
330
  scanAll: values["scan-all"],
330
331
  baseLockfile: values["base-lockfile"] ?? null,
331
332
  workspace: values.workspace ?? process.env.DG_WORKSPACE ?? null,
333
+ outputFile: values.output ?? null,
332
334
  command,
333
335
  debug
334
336
  };
@@ -367,6 +369,7 @@ var init_config = __esm({
367
369
  --scan-all Scan all packages, not just changed
368
370
  --base-lockfile <path> Path to base lockfile for explicit diff
369
371
  --workspace <dir> Scan a specific workspace subdirectory
372
+ --output, -o <file> Save JSON results to file (use with --json)
370
373
  --debug Show diagnostic output (discovery, batches, timing)
371
374
  --help Show this help message
372
375
  --version Show version number
@@ -1457,15 +1460,15 @@ var require_route = __commonJS({
1457
1460
  };
1458
1461
  }
1459
1462
  function wrapConversion(toModel, graph) {
1460
- const path = [graph[toModel].parent, toModel];
1463
+ const path2 = [graph[toModel].parent, toModel];
1461
1464
  let fn = conversions[graph[toModel].parent][toModel];
1462
1465
  let cur = graph[toModel].parent;
1463
1466
  while (graph[cur].parent) {
1464
- path.unshift(graph[cur].parent);
1467
+ path2.unshift(graph[cur].parent);
1465
1468
  fn = link2(conversions[graph[cur].parent][cur], fn);
1466
1469
  cur = graph[cur].parent;
1467
1470
  }
1468
- fn.conversion = path;
1471
+ fn.conversion = path2;
1469
1472
  return fn;
1470
1473
  }
1471
1474
  module.exports = function(fromModel) {
@@ -1904,14 +1907,14 @@ var require_templates = __commonJS({
1904
1907
  }
1905
1908
  return results;
1906
1909
  }
1907
- function buildStyle(chalk10, styles8) {
1910
+ function buildStyle(chalk8, styles8) {
1908
1911
  const enabled = {};
1909
1912
  for (const layer of styles8) {
1910
1913
  for (const style of layer.styles) {
1911
1914
  enabled[style[0]] = layer.inverse ? null : style.slice(1);
1912
1915
  }
1913
1916
  }
1914
- let current = chalk10;
1917
+ let current = chalk8;
1915
1918
  for (const [styleName, styles9] of Object.entries(enabled)) {
1916
1919
  if (!Array.isArray(styles9)) {
1917
1920
  continue;
@@ -1923,7 +1926,7 @@ var require_templates = __commonJS({
1923
1926
  }
1924
1927
  return current;
1925
1928
  }
1926
- module.exports = (chalk10, temporary) => {
1929
+ module.exports = (chalk8, temporary) => {
1927
1930
  const styles8 = [];
1928
1931
  const chunks = [];
1929
1932
  let chunk = [];
@@ -1933,13 +1936,13 @@ var require_templates = __commonJS({
1933
1936
  } else if (style) {
1934
1937
  const string = chunk.join("");
1935
1938
  chunk = [];
1936
- chunks.push(styles8.length === 0 ? string : buildStyle(chalk10, styles8)(string));
1939
+ chunks.push(styles8.length === 0 ? string : buildStyle(chalk8, styles8)(string));
1937
1940
  styles8.push({ inverse, styles: parseStyle(style) });
1938
1941
  } else if (close) {
1939
1942
  if (styles8.length === 0) {
1940
1943
  throw new Error("Found extraneous } in Chalk template literal");
1941
1944
  }
1942
- chunks.push(buildStyle(chalk10, styles8)(chunk.join("")));
1945
+ chunks.push(buildStyle(chalk8, styles8)(chunk.join("")));
1943
1946
  chunk = [];
1944
1947
  styles8.pop();
1945
1948
  } else {
@@ -1987,16 +1990,16 @@ var require_source = __commonJS({
1987
1990
  }
1988
1991
  };
1989
1992
  var chalkFactory2 = (options) => {
1990
- const chalk11 = {};
1991
- applyOptions2(chalk11, options);
1992
- chalk11.template = (...arguments_) => chalkTag(chalk11.template, ...arguments_);
1993
- Object.setPrototypeOf(chalk11, Chalk.prototype);
1994
- Object.setPrototypeOf(chalk11.template, chalk11);
1995
- chalk11.template.constructor = () => {
1993
+ const chalk9 = {};
1994
+ applyOptions2(chalk9, options);
1995
+ chalk9.template = (...arguments_) => chalkTag(chalk9.template, ...arguments_);
1996
+ Object.setPrototypeOf(chalk9, Chalk.prototype);
1997
+ Object.setPrototypeOf(chalk9.template, chalk9);
1998
+ chalk9.template.constructor = () => {
1996
1999
  throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.");
1997
2000
  };
1998
- chalk11.template.Instance = ChalkClass;
1999
- return chalk11.template;
2001
+ chalk9.template.Instance = ChalkClass;
2002
+ return chalk9.template;
2000
2003
  };
2001
2004
  function Chalk(options) {
2002
2005
  return chalkFactory2(options);
@@ -2107,7 +2110,7 @@ var require_source = __commonJS({
2107
2110
  return openAll + string + closeAll;
2108
2111
  };
2109
2112
  var template;
2110
- var chalkTag = (chalk11, ...strings) => {
2113
+ var chalkTag = (chalk9, ...strings) => {
2111
2114
  const [firstString] = strings;
2112
2115
  if (!isArray(firstString) || !isArray(firstString.raw)) {
2113
2116
  return strings.join(" ");
@@ -2123,14 +2126,14 @@ var require_source = __commonJS({
2123
2126
  if (template === void 0) {
2124
2127
  template = require_templates();
2125
2128
  }
2126
- return template(chalk11, parts.join(""));
2129
+ return template(chalk9, parts.join(""));
2127
2130
  };
2128
2131
  Object.defineProperties(Chalk.prototype, styles8);
2129
- var chalk10 = Chalk();
2130
- chalk10.supportsColor = stdoutColor2;
2131
- chalk10.stderr = Chalk({ level: stderrColor2 ? stderrColor2.level : 0 });
2132
- chalk10.stderr.supportsColor = stderrColor2;
2133
- module.exports = chalk10;
2132
+ var chalk8 = Chalk();
2133
+ chalk8.supportsColor = stdoutColor2;
2134
+ chalk8.stderr = Chalk({ level: stderrColor2 ? stderrColor2.level : 0 });
2135
+ chalk8.stderr.supportsColor = stderrColor2;
2136
+ module.exports = chalk8;
2134
2137
  }
2135
2138
  });
2136
2139
 
@@ -2261,7 +2264,7 @@ var require_react_production_min = __commonJS({
2261
2264
  });
2262
2265
  return d;
2263
2266
  }
2264
- function T2(a) {
2267
+ function T(a) {
2265
2268
  if (-1 === a._status) {
2266
2269
  var b = a._result;
2267
2270
  b = b();
@@ -2344,7 +2347,7 @@ var require_react_production_min = __commonJS({
2344
2347
  };
2345
2348
  exports.isValidElement = O;
2346
2349
  exports.lazy = function(a) {
2347
- return { $$typeof: y, _payload: { _status: -1, _result: a }, _init: T2 };
2350
+ return { $$typeof: y, _payload: { _status: -1, _result: a }, _init: T };
2348
2351
  };
2349
2352
  exports.memo = function(a, b) {
2350
2353
  return { $$typeof: x, type: a, compare: void 0 === b ? null : b };
@@ -3466,19 +3469,19 @@ var require_react_development = __commonJS({
3466
3469
  }
3467
3470
  return dispatcher.useContext(Context);
3468
3471
  }
3469
- function useState9(initialState) {
3472
+ function useState3(initialState) {
3470
3473
  var dispatcher = resolveDispatcher();
3471
3474
  return dispatcher.useState(initialState);
3472
3475
  }
3473
- function useReducer6(reducer5, initialArg, init) {
3476
+ function useReducer5(reducer5, initialArg, init) {
3474
3477
  var dispatcher = resolveDispatcher();
3475
3478
  return dispatcher.useReducer(reducer5, initialArg, init);
3476
3479
  }
3477
- function useRef9(initialValue) {
3480
+ function useRef4(initialValue) {
3478
3481
  var dispatcher = resolveDispatcher();
3479
3482
  return dispatcher.useRef(initialValue);
3480
3483
  }
3481
- function useEffect16(create2, deps) {
3484
+ function useEffect10(create2, deps) {
3482
3485
  var dispatcher = resolveDispatcher();
3483
3486
  return dispatcher.useEffect(create2, deps);
3484
3487
  }
@@ -3490,7 +3493,7 @@ var require_react_development = __commonJS({
3490
3493
  var dispatcher = resolveDispatcher();
3491
3494
  return dispatcher.useLayoutEffect(create2, deps);
3492
3495
  }
3493
- function useCallback6(callback, deps) {
3496
+ function useCallback4(callback, deps) {
3494
3497
  var dispatcher = resolveDispatcher();
3495
3498
  return dispatcher.useCallback(callback, deps);
3496
3499
  }
@@ -4257,19 +4260,19 @@ var require_react_development = __commonJS({
4257
4260
  exports.memo = memo;
4258
4261
  exports.startTransition = startTransition;
4259
4262
  exports.unstable_act = act;
4260
- exports.useCallback = useCallback6;
4263
+ exports.useCallback = useCallback4;
4261
4264
  exports.useContext = useContext7;
4262
4265
  exports.useDebugValue = useDebugValue;
4263
4266
  exports.useDeferredValue = useDeferredValue;
4264
- exports.useEffect = useEffect16;
4267
+ exports.useEffect = useEffect10;
4265
4268
  exports.useId = useId;
4266
4269
  exports.useImperativeHandle = useImperativeHandle;
4267
4270
  exports.useInsertionEffect = useInsertionEffect;
4268
4271
  exports.useLayoutEffect = useLayoutEffect2;
4269
4272
  exports.useMemo = useMemo4;
4270
- exports.useReducer = useReducer6;
4271
- exports.useRef = useRef9;
4272
- exports.useState = useState9;
4273
+ exports.useReducer = useReducer5;
4274
+ exports.useRef = useRef4;
4275
+ exports.useState = useState3;
4273
4276
  exports.useSyncExternalStore = useSyncExternalStore;
4274
4277
  exports.useTransition = useTransition;
4275
4278
  exports.version = ReactVersion;
@@ -5162,14 +5165,14 @@ var init_yoga_wasm_base64_esm = __esm({
5162
5165
  b.P && b.O || Ta("makeClassHandle requires ptr and ptrType");
5163
5166
  !!b.U !== !!b.T && Ta("Both smartPtrType and smartPtr must be specified");
5164
5167
  b.count = { value: 1 };
5165
- return T2(Object.create(a, { M: { value: b } }));
5168
+ return T(Object.create(a, { M: { value: b } }));
5166
5169
  }
5167
- function T2(a) {
5168
- if ("undefined" === typeof FinalizationRegistry) return T2 = (b) => b, a;
5170
+ function T(a) {
5171
+ if ("undefined" === typeof FinalizationRegistry) return T = (b) => b, a;
5169
5172
  Na = new FinalizationRegistry((b) => {
5170
5173
  Oa(b.M);
5171
5174
  });
5172
- T2 = (b) => {
5175
+ T = (b) => {
5173
5176
  var c = b.M;
5174
5177
  c.T && Na.register(b, { M: c }, b);
5175
5178
  return b;
@@ -5177,7 +5180,7 @@ var init_yoga_wasm_base64_esm = __esm({
5177
5180
  Ma = (b) => {
5178
5181
  Na.unregister(b);
5179
5182
  };
5180
- return T2(a);
5183
+ return T(a);
5181
5184
  }
5182
5185
  var Va = {};
5183
5186
  function Wa(a) {
@@ -5546,7 +5549,7 @@ var init_yoga_wasm_base64_esm = __esm({
5546
5549
  X.prototype.clone = function() {
5547
5550
  this.M.O || $a(this);
5548
5551
  if (this.M.aa) return this.M.count.value += 1, this;
5549
- var a = T2, b = Object, c = b.create, d = Object.getPrototypeOf(this), e = this.M;
5552
+ var a = T, b = Object, c = b.create, d = Object.getPrototypeOf(this), e = this.M;
5550
5553
  a = a(c.call(b, d, { M: { value: { count: e.count, $: e.$, aa: e.aa, O: e.O, P: e.P, T: e.T, U: e.U } } }));
5551
5554
  a.M.count.value += 1;
5552
5555
  a.M.$ = false;
@@ -5643,7 +5646,7 @@ var init_yoga_wasm_base64_esm = __esm({
5643
5646
  l.notifyOnDestruction();
5644
5647
  n.aa = true;
5645
5648
  Object.defineProperties(this, { M: { value: n } });
5646
- T2(this);
5649
+ T(this);
5647
5650
  l = n.O;
5648
5651
  l = Ia(e, l);
5649
5652
  Q.hasOwnProperty(l) ? L("Tried to register registered instance: " + l) : Q[l] = this;
@@ -6471,7 +6474,7 @@ function wrapAssembly(lib) {
6471
6474
  lib.Node.destroy(this);
6472
6475
  });
6473
6476
  patch(lib.Node.prototype, "freeRecursive", function() {
6474
- for (let t = 0, T2 = this.getChildCount(); t < T2; ++t) {
6477
+ for (let t = 0, T = this.getChildCount(); t < T; ++t) {
6475
6478
  this.getChild(0).freeRecursive();
6476
6479
  }
6477
6480
  this.free();
@@ -6639,15 +6642,15 @@ var require_scheduler_production_min = __commonJS({
6639
6642
  F(R);
6640
6643
  };
6641
6644
  else if ("undefined" !== typeof MessageChannel) {
6642
- T2 = new MessageChannel(), U = T2.port2;
6643
- T2.port1.onmessage = R;
6645
+ T = new MessageChannel(), U = T.port2;
6646
+ T.port1.onmessage = R;
6644
6647
  S = function() {
6645
6648
  U.postMessage(null);
6646
6649
  };
6647
6650
  } else S = function() {
6648
6651
  D(R, 0);
6649
6652
  };
6650
- var T2;
6653
+ var T;
6651
6654
  var U;
6652
6655
  function I(a) {
6653
6656
  O = a;
@@ -9817,7 +9820,7 @@ var require_react_reconciler_production_min = __commonJS({
9817
9820
  return null;
9818
9821
  }
9819
9822
  }
9820
- var Gg = false, S = false, Hg = "function" === typeof WeakSet ? WeakSet : Set, T2 = null;
9823
+ var Gg = false, S = false, Hg = "function" === typeof WeakSet ? WeakSet : Set, T = null;
9821
9824
  function Ig(a, b) {
9822
9825
  var c = a.ref;
9823
9826
  if (null !== c) if ("function" === typeof c) try {
@@ -9837,9 +9840,9 @@ var require_react_reconciler_production_min = __commonJS({
9837
9840
  var Kg = false;
9838
9841
  function Lg(a, b) {
9839
9842
  Ha(a.containerInfo);
9840
- for (T2 = b; null !== T2; ) if (a = T2, b = a.child, 0 !== (a.subtreeFlags & 1028) && null !== b) b.return = a, T2 = b;
9841
- else for (; null !== T2; ) {
9842
- a = T2;
9843
+ for (T = b; null !== T; ) if (a = T, b = a.child, 0 !== (a.subtreeFlags & 1028) && null !== b) b.return = a, T = b;
9844
+ else for (; null !== T; ) {
9845
+ a = T;
9843
9846
  try {
9844
9847
  var c = a.alternate;
9845
9848
  if (0 !== (a.flags & 1024)) switch (a.tag) {
@@ -9870,10 +9873,10 @@ var require_react_reconciler_production_min = __commonJS({
9870
9873
  b = a.sibling;
9871
9874
  if (null !== b) {
9872
9875
  b.return = a.return;
9873
- T2 = b;
9876
+ T = b;
9874
9877
  break;
9875
9878
  }
9876
- T2 = a.return;
9879
+ T = a.return;
9877
9880
  }
9878
9881
  c = Kg;
9879
9882
  Kg = false;
@@ -10201,9 +10204,9 @@ var require_react_reconciler_production_min = __commonJS({
10201
10204
  ah(a);
10202
10205
  if (d & 8192) {
10203
10206
  c = null !== a.memoizedState;
10204
- if ((a.stateNode.isHidden = c) && !g && 0 !== (a.mode & 1)) for (T2 = a, d = a.child; null !== d; ) {
10205
- for (b = T2 = d; null !== T2; ) {
10206
- g = T2;
10207
+ if ((a.stateNode.isHidden = c) && !g && 0 !== (a.mode & 1)) for (T = a, d = a.child; null !== d; ) {
10208
+ for (b = T = d; null !== T; ) {
10209
+ g = T;
10207
10210
  var h = g.child;
10208
10211
  switch (g.tag) {
10209
10212
  case 0:
@@ -10236,7 +10239,7 @@ var require_react_reconciler_production_min = __commonJS({
10236
10239
  continue;
10237
10240
  }
10238
10241
  }
10239
- null !== h ? (h.return = g, T2 = h) : ch(b);
10242
+ null !== h ? (h.return = g, T = h) : ch(b);
10240
10243
  }
10241
10244
  d = d.sibling;
10242
10245
  }
@@ -10325,12 +10328,12 @@ var require_react_reconciler_production_min = __commonJS({
10325
10328
  b & 4096 && (a.flags &= -4097);
10326
10329
  }
10327
10330
  function dh(a, b, c) {
10328
- T2 = a;
10331
+ T = a;
10329
10332
  eh(a, b, c);
10330
10333
  }
10331
10334
  function eh(a, b, c) {
10332
- for (var d = 0 !== (a.mode & 1); null !== T2; ) {
10333
- var e = T2, f = e.child;
10335
+ for (var d = 0 !== (a.mode & 1); null !== T; ) {
10336
+ var e = T, f = e.child;
10334
10337
  if (22 === e.tag && d) {
10335
10338
  var g = null !== e.memoizedState || Gg;
10336
10339
  if (!g) {
@@ -10338,19 +10341,19 @@ var require_react_reconciler_production_min = __commonJS({
10338
10341
  h = Gg;
10339
10342
  var l = S;
10340
10343
  Gg = g;
10341
- if ((S = k) && !l) for (T2 = e; null !== T2; ) g = T2, k = g.child, 22 === g.tag && null !== g.memoizedState ? fh(e) : null !== k ? (k.return = g, T2 = k) : fh(e);
10342
- for (; null !== f; ) T2 = f, eh(f, b, c), f = f.sibling;
10343
- T2 = e;
10344
+ if ((S = k) && !l) for (T = e; null !== T; ) g = T, k = g.child, 22 === g.tag && null !== g.memoizedState ? fh(e) : null !== k ? (k.return = g, T = k) : fh(e);
10345
+ for (; null !== f; ) T = f, eh(f, b, c), f = f.sibling;
10346
+ T = e;
10344
10347
  Gg = h;
10345
10348
  S = l;
10346
10349
  }
10347
10350
  gh(a, b, c);
10348
- } else 0 !== (e.subtreeFlags & 8772) && null !== f ? (f.return = e, T2 = f) : gh(a, b, c);
10351
+ } else 0 !== (e.subtreeFlags & 8772) && null !== f ? (f.return = e, T = f) : gh(a, b, c);
10349
10352
  }
10350
10353
  }
10351
10354
  function gh(a) {
10352
- for (; null !== T2; ) {
10353
- var b = T2;
10355
+ for (; null !== T; ) {
10356
+ var b = T;
10354
10357
  if (0 !== (b.flags & 8772)) {
10355
10358
  var c = b.alternate;
10356
10359
  try {
@@ -10422,37 +10425,37 @@ var require_react_reconciler_production_min = __commonJS({
10422
10425
  }
10423
10426
  }
10424
10427
  if (b === a) {
10425
- T2 = null;
10428
+ T = null;
10426
10429
  break;
10427
10430
  }
10428
10431
  c = b.sibling;
10429
10432
  if (null !== c) {
10430
10433
  c.return = b.return;
10431
- T2 = c;
10434
+ T = c;
10432
10435
  break;
10433
10436
  }
10434
- T2 = b.return;
10437
+ T = b.return;
10435
10438
  }
10436
10439
  }
10437
10440
  function ch(a) {
10438
- for (; null !== T2; ) {
10439
- var b = T2;
10441
+ for (; null !== T; ) {
10442
+ var b = T;
10440
10443
  if (b === a) {
10441
- T2 = null;
10444
+ T = null;
10442
10445
  break;
10443
10446
  }
10444
10447
  var c = b.sibling;
10445
10448
  if (null !== c) {
10446
10449
  c.return = b.return;
10447
- T2 = c;
10450
+ T = c;
10448
10451
  break;
10449
10452
  }
10450
- T2 = b.return;
10453
+ T = b.return;
10451
10454
  }
10452
10455
  }
10453
10456
  function fh(a) {
10454
- for (; null !== T2; ) {
10455
- var b = T2;
10457
+ for (; null !== T; ) {
10458
+ var b = T;
10456
10459
  try {
10457
10460
  switch (b.tag) {
10458
10461
  case 0:
@@ -10494,16 +10497,16 @@ var require_react_reconciler_production_min = __commonJS({
10494
10497
  U(b, b.return, k);
10495
10498
  }
10496
10499
  if (b === a) {
10497
- T2 = null;
10500
+ T = null;
10498
10501
  break;
10499
10502
  }
10500
10503
  var h = b.sibling;
10501
10504
  if (null !== h) {
10502
10505
  h.return = b.return;
10503
- T2 = h;
10506
+ T = h;
10504
10507
  break;
10505
10508
  }
10506
- T2 = b.return;
10509
+ T = b.return;
10507
10510
  }
10508
10511
  }
10509
10512
  var hh = 0, ih = 1, jh = 2, kh = 3, lh = 4;
@@ -11145,15 +11148,15 @@ var require_react_reconciler_production_min = __commonJS({
11145
11148
  if (0 !== (H & 6)) throw Error(n(331));
11146
11149
  var e = H;
11147
11150
  H |= 4;
11148
- for (T2 = a.current; null !== T2; ) {
11149
- var f = T2, g = f.child;
11150
- if (0 !== (T2.flags & 16)) {
11151
+ for (T = a.current; null !== T; ) {
11152
+ var f = T, g = f.child;
11153
+ if (0 !== (T.flags & 16)) {
11151
11154
  var h = f.deletions;
11152
11155
  if (null !== h) {
11153
11156
  for (var k = 0; k < h.length; k++) {
11154
11157
  var l = h[k];
11155
- for (T2 = l; null !== T2; ) {
11156
- var m = T2;
11158
+ for (T = l; null !== T; ) {
11159
+ var m = T;
11157
11160
  switch (m.tag) {
11158
11161
  case 0:
11159
11162
  case 11:
@@ -11161,21 +11164,21 @@ var require_react_reconciler_production_min = __commonJS({
11161
11164
  Mg(8, m, f);
11162
11165
  }
11163
11166
  var r = m.child;
11164
- if (null !== r) r.return = m, T2 = r;
11165
- else for (; null !== T2; ) {
11166
- m = T2;
11167
+ if (null !== r) r.return = m, T = r;
11168
+ else for (; null !== T; ) {
11169
+ m = T;
11167
11170
  var p = m.sibling, B = m.return;
11168
11171
  Pg(m);
11169
11172
  if (m === l) {
11170
- T2 = null;
11173
+ T = null;
11171
11174
  break;
11172
11175
  }
11173
11176
  if (null !== p) {
11174
11177
  p.return = B;
11175
- T2 = p;
11178
+ T = p;
11176
11179
  break;
11177
11180
  }
11178
- T2 = B;
11181
+ T = B;
11179
11182
  }
11180
11183
  }
11181
11184
  }
@@ -11191,12 +11194,12 @@ var require_react_reconciler_production_min = __commonJS({
11191
11194
  } while (null !== Y);
11192
11195
  }
11193
11196
  }
11194
- T2 = f;
11197
+ T = f;
11195
11198
  }
11196
11199
  }
11197
- if (0 !== (f.subtreeFlags & 2064) && null !== g) g.return = f, T2 = g;
11198
- else b: for (; null !== T2; ) {
11199
- f = T2;
11200
+ if (0 !== (f.subtreeFlags & 2064) && null !== g) g.return = f, T = g;
11201
+ else b: for (; null !== T; ) {
11202
+ f = T;
11200
11203
  if (0 !== (f.flags & 2048)) switch (f.tag) {
11201
11204
  case 0:
11202
11205
  case 11:
@@ -11206,19 +11209,19 @@ var require_react_reconciler_production_min = __commonJS({
11206
11209
  var E = f.sibling;
11207
11210
  if (null !== E) {
11208
11211
  E.return = f.return;
11209
- T2 = E;
11212
+ T = E;
11210
11213
  break b;
11211
11214
  }
11212
- T2 = f.return;
11215
+ T = f.return;
11213
11216
  }
11214
11217
  }
11215
11218
  var u = a.current;
11216
- for (T2 = u; null !== T2; ) {
11217
- g = T2;
11219
+ for (T = u; null !== T; ) {
11220
+ g = T;
11218
11221
  var t = g.child;
11219
- if (0 !== (g.subtreeFlags & 2064) && null !== t) t.return = g, T2 = t;
11220
- else b: for (g = u; null !== T2; ) {
11221
- h = T2;
11222
+ if (0 !== (g.subtreeFlags & 2064) && null !== t) t.return = g, T = t;
11223
+ else b: for (g = u; null !== T; ) {
11224
+ h = T;
11222
11225
  if (0 !== (h.flags & 2048)) try {
11223
11226
  switch (h.tag) {
11224
11227
  case 0:
@@ -11230,16 +11233,16 @@ var require_react_reconciler_production_min = __commonJS({
11230
11233
  U(h, h.return, lc);
11231
11234
  }
11232
11235
  if (h === g) {
11233
- T2 = null;
11236
+ T = null;
11234
11237
  break b;
11235
11238
  }
11236
11239
  var Db = h.sibling;
11237
11240
  if (null !== Db) {
11238
11241
  Db.return = h.return;
11239
- T2 = Db;
11242
+ T = Db;
11240
11243
  break b;
11241
11244
  }
11242
- T2 = h.return;
11245
+ T = h.return;
11243
11246
  }
11244
11247
  }
11245
11248
  H = e;
@@ -11979,9 +11982,9 @@ var require_react_reconciler_development = __commonJS({
11979
11982
  module.exports = function $$$reconciler($$$hostConfig) {
11980
11983
  var exports2 = {};
11981
11984
  "use strict";
11982
- var React18 = require_react();
11985
+ var React15 = require_react();
11983
11986
  var Scheduler = require_scheduler();
11984
- var ReactSharedInternals = React18.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
11987
+ var ReactSharedInternals = React15.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
11985
11988
  var suppressWarning = false;
11986
11989
  function setSuppressWarning(newSuppressWarning) {
11987
11990
  {
@@ -12045,7 +12048,7 @@ var require_react_reconciler_development = __commonJS({
12045
12048
  var HostPortal = 4;
12046
12049
  var HostComponent = 5;
12047
12050
  var HostText = 6;
12048
- var Fragment7 = 7;
12051
+ var Fragment5 = 7;
12049
12052
  var Mode = 8;
12050
12053
  var ContextConsumer = 9;
12051
12054
  var ContextProvider = 10;
@@ -12185,7 +12188,7 @@ var require_react_reconciler_development = __commonJS({
12185
12188
  return "DehydratedFragment";
12186
12189
  case ForwardRef:
12187
12190
  return getWrappedName$1(type, type.render, "ForwardRef");
12188
- case Fragment7:
12191
+ case Fragment5:
12189
12192
  return "Fragment";
12190
12193
  case HostComponent:
12191
12194
  return type;
@@ -15319,7 +15322,7 @@ var require_react_reconciler_development = __commonJS({
15319
15322
  }
15320
15323
  }
15321
15324
  function updateFragment2(returnFiber, current2, fragment, lanes, key) {
15322
- if (current2 === null || current2.tag !== Fragment7) {
15325
+ if (current2 === null || current2.tag !== Fragment5) {
15323
15326
  var created = createFiberFromFragment(fragment, returnFiber.mode, lanes, key);
15324
15327
  created.return = returnFiber;
15325
15328
  return created;
@@ -15722,7 +15725,7 @@ var require_react_reconciler_development = __commonJS({
15722
15725
  if (child.key === key) {
15723
15726
  var elementType = element.type;
15724
15727
  if (elementType === REACT_FRAGMENT_TYPE) {
15725
- if (child.tag === Fragment7) {
15728
+ if (child.tag === Fragment5) {
15726
15729
  deleteRemainingChildren(returnFiber, child.sibling);
15727
15730
  var existing = useFiber(child, element.props.children);
15728
15731
  existing.return = returnFiber;
@@ -21213,7 +21216,7 @@ var require_react_reconciler_development = __commonJS({
21213
21216
  var _resolvedProps2 = workInProgress2.elementType === type ? _unresolvedProps2 : resolveDefaultProps(type, _unresolvedProps2);
21214
21217
  return updateForwardRef(current2, workInProgress2, type, _resolvedProps2, renderLanes2);
21215
21218
  }
21216
- case Fragment7:
21219
+ case Fragment5:
21217
21220
  return updateFragment(current2, workInProgress2, renderLanes2);
21218
21221
  case Mode:
21219
21222
  return updateMode(current2, workInProgress2, renderLanes2);
@@ -21650,7 +21653,7 @@ var require_react_reconciler_development = __commonJS({
21650
21653
  case SimpleMemoComponent:
21651
21654
  case FunctionComponent:
21652
21655
  case ForwardRef:
21653
- case Fragment7:
21656
+ case Fragment5:
21654
21657
  case Mode:
21655
21658
  case Profiler:
21656
21659
  case ContextConsumer:
@@ -26418,7 +26421,7 @@ var require_react_reconciler_development = __commonJS({
26418
26421
  return fiber;
26419
26422
  }
26420
26423
  function createFiberFromFragment(elements, mode, lanes, key) {
26421
- var fiber = createFiber(Fragment7, elements, key, mode);
26424
+ var fiber = createFiber(Fragment5, elements, key, mode);
26422
26425
  fiber.lanes = lanes;
26423
26426
  return fiber;
26424
26427
  }
@@ -26858,10 +26861,10 @@ var require_react_reconciler_development = __commonJS({
26858
26861
  var setErrorHandler = null;
26859
26862
  var setSuspenseHandler = null;
26860
26863
  {
26861
- var copyWithDeleteImpl = function(obj, path, index2) {
26862
- var key = path[index2];
26864
+ var copyWithDeleteImpl = function(obj, path2, index2) {
26865
+ var key = path2[index2];
26863
26866
  var updated = isArray(obj) ? obj.slice() : assign({}, obj);
26864
- if (index2 + 1 === path.length) {
26867
+ if (index2 + 1 === path2.length) {
26865
26868
  if (isArray(updated)) {
26866
26869
  updated.splice(key, 1);
26867
26870
  } else {
@@ -26869,11 +26872,11 @@ var require_react_reconciler_development = __commonJS({
26869
26872
  }
26870
26873
  return updated;
26871
26874
  }
26872
- updated[key] = copyWithDeleteImpl(obj[key], path, index2 + 1);
26875
+ updated[key] = copyWithDeleteImpl(obj[key], path2, index2 + 1);
26873
26876
  return updated;
26874
26877
  };
26875
- var copyWithDelete = function(obj, path) {
26876
- return copyWithDeleteImpl(obj, path, 0);
26878
+ var copyWithDelete = function(obj, path2) {
26879
+ return copyWithDeleteImpl(obj, path2, 0);
26877
26880
  };
26878
26881
  var copyWithRenameImpl = function(obj, oldPath, newPath, index2) {
26879
26882
  var oldKey = oldPath[index2];
@@ -26911,17 +26914,17 @@ var require_react_reconciler_development = __commonJS({
26911
26914
  }
26912
26915
  return copyWithRenameImpl(obj, oldPath, newPath, 0);
26913
26916
  };
26914
- var copyWithSetImpl = function(obj, path, index2, value) {
26915
- if (index2 >= path.length) {
26917
+ var copyWithSetImpl = function(obj, path2, index2, value) {
26918
+ if (index2 >= path2.length) {
26916
26919
  return value;
26917
26920
  }
26918
- var key = path[index2];
26921
+ var key = path2[index2];
26919
26922
  var updated = isArray(obj) ? obj.slice() : assign({}, obj);
26920
- updated[key] = copyWithSetImpl(obj[key], path, index2 + 1, value);
26923
+ updated[key] = copyWithSetImpl(obj[key], path2, index2 + 1, value);
26921
26924
  return updated;
26922
26925
  };
26923
- var copyWithSet = function(obj, path, value) {
26924
- return copyWithSetImpl(obj, path, 0, value);
26926
+ var copyWithSet = function(obj, path2, value) {
26927
+ return copyWithSetImpl(obj, path2, 0, value);
26925
26928
  };
26926
26929
  var findHook = function(fiber, id) {
26927
26930
  var currentHook2 = fiber.memoizedState;
@@ -26931,10 +26934,10 @@ var require_react_reconciler_development = __commonJS({
26931
26934
  }
26932
26935
  return currentHook2;
26933
26936
  };
26934
- overrideHookState = function(fiber, id, path, value) {
26937
+ overrideHookState = function(fiber, id, path2, value) {
26935
26938
  var hook = findHook(fiber, id);
26936
26939
  if (hook !== null) {
26937
- var newState = copyWithSet(hook.memoizedState, path, value);
26940
+ var newState = copyWithSet(hook.memoizedState, path2, value);
26938
26941
  hook.memoizedState = newState;
26939
26942
  hook.baseState = newState;
26940
26943
  fiber.memoizedProps = assign({}, fiber.memoizedProps);
@@ -26944,10 +26947,10 @@ var require_react_reconciler_development = __commonJS({
26944
26947
  }
26945
26948
  }
26946
26949
  };
26947
- overrideHookStateDeletePath = function(fiber, id, path) {
26950
+ overrideHookStateDeletePath = function(fiber, id, path2) {
26948
26951
  var hook = findHook(fiber, id);
26949
26952
  if (hook !== null) {
26950
- var newState = copyWithDelete(hook.memoizedState, path);
26953
+ var newState = copyWithDelete(hook.memoizedState, path2);
26951
26954
  hook.memoizedState = newState;
26952
26955
  hook.baseState = newState;
26953
26956
  fiber.memoizedProps = assign({}, fiber.memoizedProps);
@@ -26970,8 +26973,8 @@ var require_react_reconciler_development = __commonJS({
26970
26973
  }
26971
26974
  }
26972
26975
  };
26973
- overrideProps = function(fiber, path, value) {
26974
- fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value);
26976
+ overrideProps = function(fiber, path2, value) {
26977
+ fiber.pendingProps = copyWithSet(fiber.memoizedProps, path2, value);
26975
26978
  if (fiber.alternate) {
26976
26979
  fiber.alternate.pendingProps = fiber.pendingProps;
26977
26980
  }
@@ -26980,8 +26983,8 @@ var require_react_reconciler_development = __commonJS({
26980
26983
  scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
26981
26984
  }
26982
26985
  };
26983
- overridePropsDeletePath = function(fiber, path) {
26984
- fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path);
26986
+ overridePropsDeletePath = function(fiber, path2) {
26987
+ fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path2);
26985
26988
  if (fiber.alternate) {
26986
26989
  fiber.alternate.pendingProps = fiber.pendingProps;
26987
26990
  }
@@ -33042,10 +33045,10 @@ var init_source = __esm({
33042
33045
  object.level = options.level === void 0 ? colorLevel : options.level;
33043
33046
  };
33044
33047
  chalkFactory = (options) => {
33045
- const chalk10 = (...strings) => strings.join(" ");
33046
- applyOptions(chalk10, options);
33047
- Object.setPrototypeOf(chalk10, createChalk.prototype);
33048
- return chalk10;
33048
+ const chalk8 = (...strings) => strings.join(" ");
33049
+ applyOptions(chalk8, options);
33050
+ Object.setPrototypeOf(chalk8, createChalk.prototype);
33051
+ return chalk8;
33049
33052
  };
33050
33053
  Object.setPrototypeOf(createChalk.prototype, Function.prototype);
33051
33054
  for (const [styleName, style] of Object.entries(ansi_styles_default3)) {
@@ -35049,8 +35052,8 @@ var init_ErrorOverview = __esm({
35049
35052
  init_dist3();
35050
35053
  init_Box();
35051
35054
  init_Text();
35052
- cleanupPath = (path) => {
35053
- return path?.replace(`file://${cwd()}/`, "");
35055
+ cleanupPath = (path2) => {
35056
+ return path2?.replace(`file://${cwd()}/`, "");
35054
35057
  };
35055
35058
  stackUtils = new import_stack_utils.default({
35056
35059
  cwd: cwd(),
@@ -37932,7 +37935,7 @@ var require_react_jsx_runtime_development = __commonJS({
37932
37935
  if (process.env.NODE_ENV !== "production") {
37933
37936
  (function() {
37934
37937
  "use strict";
37935
- var React18 = require_react();
37938
+ var React15 = require_react();
37936
37939
  var REACT_ELEMENT_TYPE = Symbol.for("react.element");
37937
37940
  var REACT_PORTAL_TYPE = Symbol.for("react.portal");
37938
37941
  var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
@@ -37958,7 +37961,7 @@ var require_react_jsx_runtime_development = __commonJS({
37958
37961
  }
37959
37962
  return null;
37960
37963
  }
37961
- var ReactSharedInternals = React18.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
37964
+ var ReactSharedInternals = React15.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
37962
37965
  function error(format) {
37963
37966
  {
37964
37967
  {
@@ -38808,11 +38811,11 @@ var require_react_jsx_runtime_development = __commonJS({
38808
38811
  return jsxWithValidation(type, props, key, false);
38809
38812
  }
38810
38813
  }
38811
- var jsx12 = jsxWithValidationDynamic;
38812
- var jsxs14 = jsxWithValidationStatic;
38814
+ var jsx9 = jsxWithValidationDynamic;
38815
+ var jsxs11 = jsxWithValidationStatic;
38813
38816
  exports.Fragment = REACT_FRAGMENT_TYPE;
38814
- exports.jsx = jsx12;
38815
- exports.jsxs = jsxs14;
38817
+ exports.jsx = jsx9;
38818
+ exports.jsxs = jsxs11;
38816
38819
  })();
38817
38820
  }
38818
38821
  }
@@ -38955,25 +38958,29 @@ function sanitize(s) {
38955
38958
  return stripVTControlCharacters(s);
38956
38959
  }
38957
38960
  function sanitizeResponse(response) {
38958
- return {
38959
- ...response,
38960
- packages: response.packages.map((pkg) => ({
38961
- ...pkg,
38962
- name: sanitize(pkg.name),
38963
- version: sanitize(pkg.version),
38964
- findings: pkg.findings.map((f) => ({
38965
- ...f,
38966
- id: sanitize(f.id ?? ""),
38967
- title: sanitize(f.title),
38968
- evidence: f.evidence.map(sanitize)
38969
- })),
38970
- reasons: (pkg.reasons ?? []).map(sanitize),
38971
- recommendation: pkg.recommendation ? sanitize(pkg.recommendation) : void 0
38972
- })),
38973
- safeVersions: Object.fromEntries(
38974
- Object.entries(response.safeVersions).map(([k, v]) => [sanitize(k), sanitize(v)])
38975
- )
38961
+ const sanitized = {
38962
+ score: response.score,
38963
+ action: response.action,
38964
+ packages: response.packages.map((pkg) => {
38965
+ const clean = {
38966
+ name: sanitize(pkg.name),
38967
+ version: sanitize(pkg.version),
38968
+ score: pkg.score,
38969
+ findings: pkg.findings.map((f) => ({
38970
+ ...f,
38971
+ id: sanitize(f.id ?? ""),
38972
+ title: sanitize(f.title),
38973
+ evidence: f.evidence.map(sanitize)
38974
+ })),
38975
+ reasons: (pkg.reasons ?? []).map(sanitize)
38976
+ };
38977
+ if (pkg.recommendation) clean.recommendation = sanitize(pkg.recommendation);
38978
+ if (pkg.license) clean.license = pkg.license;
38979
+ return clean;
38980
+ })
38976
38981
  };
38982
+ if (response.durationMs) sanitized.durationMs = response.durationMs;
38983
+ return sanitized;
38977
38984
  }
38978
38985
  var init_sanitize = __esm({
38979
38986
  "src/sanitize.ts"() {
@@ -39237,9 +39244,9 @@ function parseLockfile(content) {
39237
39244
  const lockfileVersion = json.lockfileVersion ?? 1;
39238
39245
  const packages = /* @__PURE__ */ new Map();
39239
39246
  if (lockfileVersion >= 2 && json.packages) {
39240
- for (const [path, entry] of Object.entries(json.packages)) {
39241
- if (path === "") continue;
39242
- const name = extractPackageName(path);
39247
+ for (const [path2, entry] of Object.entries(json.packages)) {
39248
+ if (path2 === "") continue;
39249
+ const name = extractPackageName(path2);
39243
39250
  if (name && !packages.has(name)) {
39244
39251
  const e = entry;
39245
39252
  const deps = e.dependencies;
@@ -39475,23 +39482,38 @@ var init_parse_package_json = __esm({
39475
39482
  import { execFileSync as execFileSync2 } from "node:child_process";
39476
39483
  import { readFileSync as readFileSync6, existsSync as existsSync5, statSync } from "node:fs";
39477
39484
  import { join as join5 } from "node:path";
39478
- function readFileSafe(path) {
39479
- const size = statSync(path).size;
39485
+ function readFileSafe(path2) {
39486
+ const size = statSync(path2).size;
39480
39487
  if (size > MAX_LOCKFILE_BYTES) {
39481
- throw new Error(`Lockfile too large (${(size / 1024 / 1024).toFixed(0)} MB, max 50 MB): ${path}`);
39488
+ throw new Error(`Lockfile too large (${(size / 1024 / 1024).toFixed(0)} MB, max 50 MB): ${path2}`);
39482
39489
  }
39483
- return readFileSync6(path, "utf-8");
39490
+ return readFileSync6(path2, "utf-8");
39484
39491
  }
39485
39492
  function discoverChanges(cwd2, config) {
39486
39493
  if (config.workspace) {
39487
39494
  cwd2 = join5(cwd2, config.workspace);
39488
39495
  }
39489
39496
  const lockfileInfo = findLockfile(cwd2);
39497
+ const pythonDepFiles = ["requirements.txt", "Pipfile.lock", "poetry.lock"];
39498
+ let pythonPackages = [];
39499
+ for (const pyFile of pythonDepFiles) {
39500
+ if (existsSync5(join5(cwd2, pyFile))) {
39501
+ const pyPkgs = parsePythonDepFile(cwd2, pyFile);
39502
+ for (const p of pyPkgs) {
39503
+ if (p.version === "latest") continue;
39504
+ pythonPackages.push({ name: p.name, version: p.version, previousVersion: null, isNew: true });
39505
+ }
39506
+ break;
39507
+ }
39508
+ }
39490
39509
  if (!lockfileInfo) {
39491
- const pythonFiles = ["requirements.txt", "Pipfile.lock", "poetry.lock"];
39492
- const hasPython = pythonFiles.some((f) => existsSync5(join5(cwd2, f)));
39493
- if (hasPython) {
39494
- return { packages: [], method: "fallback", skipped: [] };
39510
+ if (pythonPackages.length > 0) {
39511
+ const skipped = [];
39512
+ if (pythonPackages.length > config.maxPackages) {
39513
+ skipped.push(...pythonPackages.slice(config.maxPackages).map((p) => `${p.name}@${p.version}`));
39514
+ pythonPackages = pythonPackages.slice(0, config.maxPackages);
39515
+ }
39516
+ return { packages: [], pythonPackages, method: "scan-all", skipped };
39495
39517
  }
39496
39518
  throw new Error(
39497
39519
  "No lockfile found (package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Pipfile.lock, or poetry.lock). Run from your project root or use --base-lockfile."
@@ -39513,7 +39535,7 @@ function discoverChanges(cwd2, config) {
39513
39535
  isNew: true
39514
39536
  });
39515
39537
  }
39516
- return { packages: packages2, method: "scan-all", skipped: [] };
39538
+ return { packages: packages2, pythonPackages, method: "scan-all", skipped: [] };
39517
39539
  }
39518
39540
  if (config.baseLockfile) {
39519
39541
  if (!existsSync5(config.baseLockfile)) {
@@ -39524,6 +39546,7 @@ function discoverChanges(cwd2, config) {
39524
39546
  const diff2 = diffLockfiles(baseParsed, headParsed, config.maxPackages, directDeps);
39525
39547
  return {
39526
39548
  packages: diff2.changes.map(toPackageInput).filter((p) => p.name !== SELF_PACKAGE),
39549
+ pythonPackages,
39527
39550
  method: "base-lockfile",
39528
39551
  skipped: diff2.skipped
39529
39552
  };
@@ -39534,6 +39557,7 @@ function discoverChanges(cwd2, config) {
39534
39557
  const diff2 = diffLockfiles(baseParsed, headParsed, config.maxPackages, directDeps);
39535
39558
  return {
39536
39559
  packages: diff2.changes.map(toPackageInput).filter((p) => p.name !== SELF_PACKAGE),
39560
+ pythonPackages,
39537
39561
  method: "git-diff",
39538
39562
  skipped: diff2.skipped
39539
39563
  };
@@ -39553,6 +39577,7 @@ function discoverChanges(cwd2, config) {
39553
39577
  });
39554
39578
  return {
39555
39579
  packages: resolved.map(toPackageInput).filter((p) => p.name !== SELF_PACKAGE),
39580
+ pythonPackages,
39556
39581
  method: "fallback",
39557
39582
  skipped: []
39558
39583
  };
@@ -39570,7 +39595,7 @@ function discoverChanges(cwd2, config) {
39570
39595
  isNew: true
39571
39596
  });
39572
39597
  }
39573
- return { packages, method: "fallback", skipped: [] };
39598
+ return { packages, pythonPackages, method: "fallback", skipped: [] };
39574
39599
  }
39575
39600
  function findLockfile(cwd2) {
39576
39601
  const candidates = [
@@ -39919,13 +39944,272 @@ var init_pip_wrapper = __esm({
39919
39944
  }
39920
39945
  });
39921
39946
 
39947
+ // src/ui/components/FileSavePrompt.tsx
39948
+ var FileSavePrompt_exports = {};
39949
+ __export(FileSavePrompt_exports, {
39950
+ FileSavePrompt: () => FileSavePrompt
39951
+ });
39952
+ import * as fs2 from "fs";
39953
+ import * as path from "path";
39954
+ function listDirectory(dir) {
39955
+ try {
39956
+ const raw = fs2.readdirSync(dir, { withFileTypes: true });
39957
+ const entries = raw.map((e) => ({ name: e.name, isDirectory: e.isDirectory() })).sort((a, b) => {
39958
+ if (a.isDirectory !== b.isDirectory) return a.isDirectory ? -1 : 1;
39959
+ return a.name.localeCompare(b.name);
39960
+ });
39961
+ if (path.dirname(dir) !== dir) {
39962
+ entries.unshift({ name: "..", isDirectory: true });
39963
+ }
39964
+ return entries;
39965
+ } catch {
39966
+ return [{ name: "..", isDirectory: true }];
39967
+ }
39968
+ }
39969
+ function ensureJsonExtension(name) {
39970
+ if (!name) return "scan.json";
39971
+ if (name.endsWith(".json")) return name;
39972
+ return name + ".json";
39973
+ }
39974
+ function clamp(n, min, max) {
39975
+ return Math.max(min, Math.min(max, n));
39976
+ }
39977
+ function reducer2(state, action) {
39978
+ switch (action.type) {
39979
+ case "SET_FILENAME":
39980
+ return { ...state, filename: action.filename, cursorPos: action.cursorPos, focus: "filename", confirmOverwrite: false, error: null };
39981
+ case "EDIT_FILENAME":
39982
+ return { ...state, filename: action.filename, cursorPos: action.cursorPos, confirmOverwrite: false, error: null };
39983
+ case "SET_DIRECTORY":
39984
+ return { ...state, directory: action.directory, entries: action.entries, browserCursor: 0, browserViewport: 0, filterText: "", error: null };
39985
+ case "MOVE_BROWSER": {
39986
+ let viewport = state.browserViewport;
39987
+ if (action.cursor < viewport) viewport = action.cursor;
39988
+ if (action.cursor >= viewport + VISIBLE_ROWS) viewport = action.cursor - VISIBLE_ROWS + 1;
39989
+ return { ...state, browserCursor: action.cursor, browserViewport: viewport };
39990
+ }
39991
+ case "FOCUS":
39992
+ return { ...state, focus: action.target, filterText: action.target === "filename" ? "" : state.filterText };
39993
+ case "FILTER":
39994
+ return { ...state, filterText: action.text, browserCursor: 0, browserViewport: 0 };
39995
+ case "CONFIRM_OVERWRITE":
39996
+ return { ...state, confirmOverwrite: true };
39997
+ case "RESET_OVERWRITE":
39998
+ return { ...state, confirmOverwrite: false };
39999
+ case "SET_ERROR":
40000
+ return { ...state, error: action.error };
40001
+ }
40002
+ }
40003
+ var import_react25, import_chalk4, import_jsx_runtime3, VISIBLE_ROWS, FileSavePrompt;
40004
+ var init_FileSavePrompt = __esm({
40005
+ async "src/ui/components/FileSavePrompt.tsx"() {
40006
+ "use strict";
40007
+ import_react25 = __toESM(require_react());
40008
+ await init_build2();
40009
+ import_chalk4 = __toESM(require_source());
40010
+ import_jsx_runtime3 = __toESM(require_jsx_runtime());
40011
+ VISIBLE_ROWS = 15;
40012
+ FileSavePrompt = ({
40013
+ defaultName,
40014
+ directory: initialDir,
40015
+ score,
40016
+ action: scanAction,
40017
+ packageCount,
40018
+ onSave,
40019
+ onCancel
40020
+ }) => {
40021
+ const initialEntries = (0, import_react25.useMemo)(() => listDirectory(initialDir), [initialDir]);
40022
+ const [state, dispatch] = (0, import_react25.useReducer)(reducer2, {
40023
+ filename: defaultName,
40024
+ cursorPos: defaultName.length,
40025
+ directory: initialDir,
40026
+ entries: initialEntries,
40027
+ browserCursor: 0,
40028
+ browserViewport: 0,
40029
+ focus: "filename",
40030
+ filterText: "",
40031
+ confirmOverwrite: false,
40032
+ error: null
40033
+ });
40034
+ const filteredEntries = (0, import_react25.useMemo)(() => {
40035
+ const dirs = state.entries.filter((e) => e.isDirectory);
40036
+ if (!state.filterText) return dirs;
40037
+ const q = state.filterText.toLowerCase();
40038
+ return dirs.filter((e) => e.name.toLowerCase().includes(q));
40039
+ }, [state.entries, state.filterText]);
40040
+ const visibleEntries = filteredEntries.slice(
40041
+ state.browserViewport,
40042
+ state.browserViewport + VISIBLE_ROWS
40043
+ );
40044
+ use_input_default((input, key) => {
40045
+ if (key.escape) {
40046
+ onCancel();
40047
+ return;
40048
+ }
40049
+ if (state.focus === "filename") {
40050
+ if (key.return) {
40051
+ const fullName = ensureJsonExtension(state.filename);
40052
+ const fullPath = path.join(state.directory, fullName);
40053
+ if (!state.confirmOverwrite && fs2.existsSync(fullPath)) {
40054
+ dispatch({ type: "CONFIRM_OVERWRITE" });
40055
+ return;
40056
+ }
40057
+ onSave(fullPath);
40058
+ return;
40059
+ }
40060
+ if (key.downArrow) {
40061
+ dispatch({ type: "FOCUS", target: "browser" });
40062
+ return;
40063
+ }
40064
+ if (key.backspace || key.delete) {
40065
+ if (state.cursorPos > 0) {
40066
+ const next = state.filename.slice(0, state.cursorPos - 1) + state.filename.slice(state.cursorPos);
40067
+ dispatch({ type: "EDIT_FILENAME", filename: next, cursorPos: state.cursorPos - 1 });
40068
+ }
40069
+ return;
40070
+ }
40071
+ if (key.leftArrow) {
40072
+ dispatch({ type: "EDIT_FILENAME", filename: state.filename, cursorPos: Math.max(0, state.cursorPos - 1) });
40073
+ return;
40074
+ }
40075
+ if (key.rightArrow) {
40076
+ dispatch({ type: "EDIT_FILENAME", filename: state.filename, cursorPos: Math.min(state.filename.length, state.cursorPos + 1) });
40077
+ return;
40078
+ }
40079
+ if (input && /^[\x20-\x7e]+$/.test(input)) {
40080
+ const next = state.filename.slice(0, state.cursorPos) + input + state.filename.slice(state.cursorPos);
40081
+ dispatch({ type: "EDIT_FILENAME", filename: next, cursorPos: state.cursorPos + input.length });
40082
+ return;
40083
+ }
40084
+ return;
40085
+ }
40086
+ if (key.upArrow) {
40087
+ if (state.browserCursor > 0) {
40088
+ dispatch({ type: "MOVE_BROWSER", cursor: state.browserCursor - 1 });
40089
+ } else {
40090
+ dispatch({ type: "FOCUS", target: "filename" });
40091
+ }
40092
+ return;
40093
+ }
40094
+ if ((key.backspace || key.delete) && !state.filterText) {
40095
+ const parentDir = path.dirname(state.directory);
40096
+ if (parentDir !== state.directory) {
40097
+ dispatch({ type: "SET_DIRECTORY", directory: parentDir, entries: listDirectory(parentDir) });
40098
+ }
40099
+ return;
40100
+ }
40101
+ if (key.downArrow) {
40102
+ dispatch({ type: "MOVE_BROWSER", cursor: clamp(state.browserCursor + 1, 0, filteredEntries.length - 1) });
40103
+ return;
40104
+ }
40105
+ if (key.return) {
40106
+ const entry = filteredEntries[state.browserCursor];
40107
+ if (!entry || !entry.isDirectory) return;
40108
+ const newDir = entry.name === ".." ? path.dirname(state.directory) : path.join(state.directory, entry.name);
40109
+ dispatch({ type: "SET_DIRECTORY", directory: newDir, entries: listDirectory(newDir) });
40110
+ return;
40111
+ }
40112
+ if (key.backspace || key.delete) {
40113
+ dispatch({ type: "FILTER", text: state.filterText.slice(0, -1) });
40114
+ return;
40115
+ }
40116
+ if (input && /^[\x20-\x7e]+$/.test(input)) {
40117
+ dispatch({ type: "FILTER", text: state.filterText + input });
40118
+ }
40119
+ });
40120
+ const actionColor2 = scanAction === "block" ? import_chalk4.default.red : scanAction === "warn" ? import_chalk4.default.yellow : import_chalk4.default.green;
40121
+ const filenameDisplay = state.filename.slice(0, state.cursorPos) + (state.focus === "filename" ? import_chalk4.default.inverse(state.filename[state.cursorPos] || " ") : "") + state.filename.slice(state.cursorPos + 1);
40122
+ const shortDir = state.directory.replace(process.env.HOME || "", "~");
40123
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
40124
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { children: [
40125
+ import_chalk4.default.cyan("\u25C6"),
40126
+ " ",
40127
+ import_chalk4.default.bold("Save Scan Results")
40128
+ ] }),
40129
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { children: [
40130
+ "Score: ",
40131
+ import_chalk4.default.bold(String(score)),
40132
+ " ",
40133
+ actionColor2(scanAction.toUpperCase()),
40134
+ " ",
40135
+ import_chalk4.default.dim("\u2502"),
40136
+ " ",
40137
+ packageCount,
40138
+ " packages scanned"
40139
+ ] }),
40140
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: "" }),
40141
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { children: [
40142
+ state.focus === "filename" ? import_chalk4.default.cyan("\u258C") : " ",
40143
+ import_chalk4.default.bold("File:"),
40144
+ " ",
40145
+ filenameDisplay,
40146
+ import_chalk4.default.dim(".json")
40147
+ ] }),
40148
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: import_chalk4.default.dim(` \u2500\u2500\u2500 ${shortDir} \u2500\u2500\u2500 [${state.browserCursor + 1}/${filteredEntries.length}]`) }),
40149
+ visibleEntries.map((entry, i) => {
40150
+ const realIdx = state.browserViewport + i;
40151
+ const isCursor = state.focus === "browser" && realIdx === state.browserCursor;
40152
+ const prefix = isCursor ? import_chalk4.default.cyan("\u258C") : " ";
40153
+ const icon = entry.isDirectory ? "\u{1F4C1} " : " ";
40154
+ const name = entry.isDirectory ? import_chalk4.default.bold(entry.name + "/") : entry.name;
40155
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { children: [
40156
+ prefix,
40157
+ icon,
40158
+ name
40159
+ ] }, `${entry.name}-${i}`);
40160
+ }),
40161
+ filteredEntries.length > VISIBLE_ROWS && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { dimColor: true, children: [
40162
+ " ",
40163
+ import_chalk4.default.dim(`\u2191\u2193 ${filteredEntries.length - VISIBLE_ROWS} more`)
40164
+ ] }),
40165
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: "" }),
40166
+ state.filterText && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { dimColor: true, children: [
40167
+ ' filter: "',
40168
+ state.filterText,
40169
+ '" (',
40170
+ filteredEntries.length,
40171
+ " matches)"
40172
+ ] }),
40173
+ state.confirmOverwrite && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "yellow", children: [
40174
+ " ",
40175
+ import_chalk4.default.yellow("\u26A0"),
40176
+ " ",
40177
+ ensureJsonExtension(state.filename),
40178
+ " exists ",
40179
+ import_chalk4.default.dim("\u2014"),
40180
+ " Enter again to overwrite"
40181
+ ] }),
40182
+ state.error && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "red", children: [
40183
+ " ",
40184
+ import_chalk4.default.red("\u2717"),
40185
+ " ",
40186
+ state.error
40187
+ ] }),
40188
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { children: [
40189
+ import_chalk4.default.bold.hex("#FFD700")("\u23CE"),
40190
+ " ",
40191
+ import_chalk4.default.bold.hex("#FFD700")("save"),
40192
+ " ",
40193
+ import_chalk4.default.bold.cyan("\u2191\u2193"),
40194
+ " ",
40195
+ import_chalk4.default.dim("browse"),
40196
+ " ",
40197
+ import_chalk4.default.bold.cyan("esc"),
40198
+ " ",
40199
+ import_chalk4.default.dim("cancel")
40200
+ ] })
40201
+ ] });
40202
+ };
40203
+ }
40204
+ });
40205
+
39922
40206
  // src/discover.ts
39923
40207
  var discover_exports = {};
39924
40208
  __export(discover_exports, {
39925
40209
  discoverProjects: () => discoverProjects
39926
40210
  });
39927
- import { existsSync as existsSync7, readFileSync as readFileSync8, readdirSync, lstatSync } from "node:fs";
39928
- import { join as join6, relative, basename } from "node:path";
40211
+ import { existsSync as existsSync8, readFileSync as readFileSync8, readdirSync as readdirSync2, lstatSync } from "node:fs";
40212
+ import { join as join7, relative, basename } from "node:path";
39929
40213
  function discoverProjects(root) {
39930
40214
  const projects = [];
39931
40215
  walk(root, root, 0, projects);
@@ -39934,8 +40218,8 @@ function discoverProjects(root) {
39934
40218
  function walk(dir, root, depth, out) {
39935
40219
  if (depth > MAX_DEPTH) return;
39936
40220
  for (const lockfile of NPM_LOCKFILES) {
39937
- const lockPath = join6(dir, lockfile);
39938
- if (existsSync7(lockPath)) {
40221
+ const lockPath = join7(dir, lockfile);
40222
+ if (existsSync8(lockPath)) {
39939
40223
  const count = countNpmPackages(lockPath);
39940
40224
  if (count > 0) {
39941
40225
  out.push({
@@ -39950,8 +40234,8 @@ function walk(dir, root, depth, out) {
39950
40234
  }
39951
40235
  }
39952
40236
  for (const depFile of PYTHON_DEPFILES) {
39953
- const depPath = join6(dir, depFile);
39954
- if (existsSync7(depPath)) {
40237
+ const depPath = join7(dir, depFile);
40238
+ if (existsSync8(depPath)) {
39955
40239
  const count = countPythonPackages(depPath, depFile);
39956
40240
  if (count > 0) {
39957
40241
  out.push({
@@ -39967,13 +40251,13 @@ function walk(dir, root, depth, out) {
39967
40251
  }
39968
40252
  let entries;
39969
40253
  try {
39970
- entries = readdirSync(dir);
40254
+ entries = readdirSync2(dir);
39971
40255
  } catch {
39972
40256
  return;
39973
40257
  }
39974
40258
  for (const entry of entries) {
39975
40259
  if (SKIP_DIRS.has(entry) || entry.startsWith(".")) continue;
39976
- const full = join6(dir, entry);
40260
+ const full = join7(dir, entry);
39977
40261
  try {
39978
40262
  const st = lstatSync(full);
39979
40263
  if (st.isDirectory() && !st.isSymbolicLink()) {
@@ -40067,10 +40351,72 @@ __export(static_output_exports, {
40067
40351
  runStaticNpm: () => runStaticNpm,
40068
40352
  runStaticPip: () => runStaticPip
40069
40353
  });
40354
+ function writeJsonFile(filepath, json) {
40355
+ const fs3 = __require("fs");
40356
+ const path2 = __require("path");
40357
+ const resolved = path2.resolve(filepath);
40358
+ try {
40359
+ fs3.writeFileSync(resolved, json + "\n");
40360
+ process.stderr.write(import_chalk5.default.green(` \u2713 Saved to ${resolved}
40361
+
40362
+ `));
40363
+ } catch (err) {
40364
+ const msg = err instanceof Error ? err.message : String(err);
40365
+ process.stderr.write(import_chalk5.default.red(` Error saving file: ${msg}
40366
+
40367
+ `));
40368
+ }
40369
+ }
40370
+ async function handleJsonOutput(result, config) {
40371
+ if (!config.json) return false;
40372
+ const json = JSON.stringify(result, null, 2);
40373
+ if (config.outputFile) {
40374
+ writeJsonFile(config.outputFile, json);
40375
+ return true;
40376
+ }
40377
+ if (!process.stdout.isTTY) {
40378
+ process.stdout.write(json + "\n");
40379
+ return true;
40380
+ }
40381
+ const localDate = (/* @__PURE__ */ new Date()).toLocaleDateString("sv-SE");
40382
+ const defaultName = `dg-scan-${localDate}`;
40383
+ const { render: render2 } = await init_build2().then(() => build_exports);
40384
+ const React15 = await Promise.resolve().then(() => __toESM(require_react()));
40385
+ const { FileSavePrompt: FileSavePrompt2 } = await init_FileSavePrompt().then(() => FileSavePrompt_exports);
40386
+ await new Promise((resolve) => {
40387
+ const inkInstance = render2(
40388
+ React15.createElement(FileSavePrompt2, {
40389
+ defaultName,
40390
+ directory: process.cwd(),
40391
+ score: result.score,
40392
+ action: result.action,
40393
+ packageCount: result.packages.length,
40394
+ onSave: (filepath) => {
40395
+ const fs3 = __require("fs");
40396
+ try {
40397
+ fs3.writeFileSync(filepath, json + "\n");
40398
+ inkInstance.unmount();
40399
+ process.stderr.write(import_chalk5.default.green(` \u2713 Saved to ${filepath}
40400
+
40401
+ `));
40402
+ } catch (err) {
40403
+ }
40404
+ resolve();
40405
+ },
40406
+ onCancel: () => {
40407
+ inkInstance.unmount();
40408
+ process.stderr.write(import_chalk5.default.dim(" Cancelled.\n\n"));
40409
+ resolve();
40410
+ }
40411
+ })
40412
+ );
40413
+ });
40414
+ return true;
40415
+ }
40070
40416
  function printTrialBanner(result) {
40071
40417
  if (result.trialScansRemaining === void 0) return;
40072
40418
  process.stderr.write(
40073
- import_chalk4.default.dim(` Free tier \xB7 Run \`dg login\` for higher scan limits.
40419
+ import_chalk5.default.dim(` Free tier \xB7 Run \`dg login\` for higher scan limits.
40074
40420
  `)
40075
40421
  );
40076
40422
  }
@@ -40093,13 +40439,13 @@ function handleTrialExhausted2(error, jsonMode = false) {
40093
40439
  }, null, 2) + "\n");
40094
40440
  } else {
40095
40441
  if (hasKey) {
40096
- process.stderr.write(import_chalk4.default.yellow(`
40442
+ process.stderr.write(import_chalk5.default.yellow(`
40097
40443
  ${message}
40098
40444
 
40099
40445
  `));
40100
40446
  } else {
40101
40447
  process.stderr.write(
40102
- import_chalk4.default.yellow("\n Monthly scan limit reached (200 scans/month on free tier).\n") + import_chalk4.default.white(" Run `dg login` for higher limits, or upgrade at westbayberry.com/pricing\n\n")
40448
+ import_chalk5.default.yellow("\n Monthly scan limit reached (200 scans/month on free tier).\n") + import_chalk5.default.white(" Run `dg login` for higher limits, or upgrade at westbayberry.com/pricing\n\n")
40103
40449
  );
40104
40450
  }
40105
40451
  }
@@ -40109,9 +40455,9 @@ function handleTrialExhausted2(error, jsonMode = false) {
40109
40455
  return false;
40110
40456
  }
40111
40457
  function actionColor(action) {
40112
- if (action === "block") return import_chalk4.default.red;
40113
- if (action === "warn") return import_chalk4.default.yellow;
40114
- return import_chalk4.default.green;
40458
+ if (action === "block") return import_chalk5.default.red;
40459
+ if (action === "warn") return import_chalk5.default.yellow;
40460
+ return import_chalk5.default.green;
40115
40461
  }
40116
40462
  function pad(s, len) {
40117
40463
  return s + " ".repeat(Math.max(0, len - s.length));
@@ -40131,29 +40477,18 @@ function groupPackages(packages) {
40131
40477
  return [...map.values()].map((pkgs) => ({ packages: pkgs, key: pkgs[0].name })).sort((a, b) => b.packages[0].score - a.packages[0].score);
40132
40478
  }
40133
40479
  function actionBadge(score) {
40134
- if (score >= 70) return { label: "BLOCK", color: import_chalk4.default.red };
40135
- if (score >= 60) return { label: "WARN", color: import_chalk4.default.yellow };
40136
- return { label: "pass", color: import_chalk4.default.green };
40480
+ if (score >= 70) return { label: "BLOCK", color: import_chalk5.default.red };
40481
+ if (score >= 60) return { label: "WARN", color: import_chalk5.default.yellow };
40482
+ return { label: "pass", color: import_chalk5.default.green };
40137
40483
  }
40138
- function renderResultStatic(result, config) {
40139
- if (config.json) {
40140
- const json = JSON.stringify(result, null, 2);
40141
- const fs2 = __require("fs");
40142
- const path = __require("path");
40143
- const filename = `dg-scan-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.json`;
40144
- const filepath = path.resolve(process.cwd(), filename);
40145
- fs2.writeFileSync(filepath, json + "\n");
40146
- process.stderr.write(import_chalk4.default.green(` Scan results saved to ${filename}
40147
- `));
40148
- return json;
40149
- }
40484
+ function renderResultStatic(result, _config) {
40150
40485
  const lines = [];
40151
40486
  const actionStr = result.action.toUpperCase();
40152
40487
  const colorAction = actionColor(result.action);
40153
40488
  lines.push("");
40154
- lines.push(` ${import_chalk4.default.bold("Dependency Guardian")}`);
40489
+ lines.push(` ${import_chalk5.default.bold("Dependency Guardian")}`);
40155
40490
  lines.push(
40156
- ` Score: ${import_chalk4.default.bold(String(result.score))}${" ".repeat(
40491
+ ` Score: ${import_chalk5.default.bold(String(result.score))}${" ".repeat(
40157
40492
  Math.max(1, 50 - String(result.score).length)
40158
40493
  )}${colorAction(actionStr)}`
40159
40494
  );
@@ -40163,11 +40498,11 @@ function renderResultStatic(result, config) {
40163
40498
  const total = result.packages.length;
40164
40499
  if (flagged.length > 0) {
40165
40500
  lines.push(
40166
- ` ${total} package${total !== 1 ? "s" : ""} scanned ${import_chalk4.default.dim("\u2502")} ${import_chalk4.default.yellow(`${flagged.length} flagged`)} \u2502 ${import_chalk4.default.green(`${clean.length} clean`)}`
40501
+ ` ${total} package${total !== 1 ? "s" : ""} scanned ${import_chalk5.default.dim("\u2502")} ${import_chalk5.default.yellow(`${flagged.length} flagged`)} \u2502 ${import_chalk5.default.green(`${clean.length} clean`)}`
40167
40502
  );
40168
40503
  } else {
40169
40504
  lines.push(
40170
- ` ${total} package${total !== 1 ? "s" : ""} scanned ${import_chalk4.default.dim("\u2502")} ${import_chalk4.default.green("all clean")}`
40505
+ ` ${total} package${total !== 1 ? "s" : ""} scanned ${import_chalk5.default.dim("\u2502")} ${import_chalk5.default.green("all clean")}`
40171
40506
  );
40172
40507
  }
40173
40508
  const licensedPkgs = result.packages.filter((p) => p.license);
@@ -40176,7 +40511,7 @@ function renderResultStatic(result, config) {
40176
40511
  );
40177
40512
  if (licenseIssues.length > 0) {
40178
40513
  lines.push(
40179
- ` ${import_chalk4.default.dim("Licenses:")} ${import_chalk4.default.yellow(`${licenseIssues.length} need review`)} \u2502 ${import_chalk4.default.green(`${licensedPkgs.length - licenseIssues.length} permissive`)}`
40514
+ ` ${import_chalk5.default.dim("Licenses:")} ${import_chalk5.default.yellow(`${licenseIssues.length} need review`)} \u2502 ${import_chalk5.default.green(`${licensedPkgs.length - licenseIssues.length} permissive`)}`
40180
40515
  );
40181
40516
  }
40182
40517
  lines.push("");
@@ -40187,30 +40522,30 @@ function renderResultStatic(result, config) {
40187
40522
  }
40188
40523
  const groups = groupPackages(flagged);
40189
40524
  if (flagged.length > 0) {
40190
- lines.push(` ${import_chalk4.default.bold("Flagged Packages")}`);
40191
- lines.push(` ${import_chalk4.default.dim("\u2500".repeat(60))}`);
40525
+ lines.push(` ${import_chalk5.default.bold("Flagged Packages")}`);
40526
+ lines.push(` ${import_chalk5.default.dim("\u2500".repeat(60))}`);
40192
40527
  for (const group of groups) {
40193
40528
  const rep = group.packages[0];
40194
40529
  const { label, color } = actionBadge(rep.score);
40195
40530
  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`;
40196
40531
  const lcInfo = rep.license;
40197
40532
  const lcStr = lcInfo ? truncate(lcInfo.spdx ?? lcInfo.raw ?? "", 14) : "";
40198
- const lcColor = !lcInfo ? import_chalk4.default.dim : lcInfo.riskCategory === "permissive" ? import_chalk4.default.green : lcInfo.riskCategory === "no-license" || lcInfo.riskCategory === "unlicensed" || lcInfo.riskCategory === "network-copyleft" ? import_chalk4.default.red : import_chalk4.default.yellow;
40533
+ const lcColor = !lcInfo ? import_chalk5.default.dim : lcInfo.riskCategory === "permissive" ? import_chalk5.default.green : lcInfo.riskCategory === "no-license" || lcInfo.riskCategory === "unlicensed" || lcInfo.riskCategory === "network-copyleft" ? import_chalk5.default.red : import_chalk5.default.yellow;
40199
40534
  lines.push(
40200
- ` ${color(pad(label, 7))}${import_chalk4.default.bold(pad(truncate(names, 36), 38))}${lcColor(pad(lcStr, 16))}${import_chalk4.default.dim(`score ${rep.score}`)}`
40535
+ ` ${color(pad(label, 7))}${import_chalk5.default.bold(pad(truncate(names, 36), 38))}${lcColor(pad(lcStr, 16))}${import_chalk5.default.dim(`score ${rep.score}`)}`
40201
40536
  );
40202
40537
  }
40203
40538
  lines.push("");
40204
40539
  }
40205
40540
  if (clean.length > 0) {
40206
40541
  lines.push(
40207
- ` ${import_chalk4.default.green("\u2713")} ${import_chalk4.default.dim(`${clean.length} package${clean.length !== 1 ? "s" : ""} passed with score 0`)}`
40542
+ ` ${import_chalk5.default.green("\u2713")} ${import_chalk5.default.dim(`${clean.length} package${clean.length !== 1 ? "s" : ""} passed with score 0`)}`
40208
40543
  );
40209
40544
  lines.push("");
40210
40545
  }
40211
40546
  if (result.durationMs) {
40212
40547
  lines.push(
40213
- ` ${import_chalk4.default.dim(`Completed in ${(result.durationMs / 1e3).toFixed(1)}s`)}`
40548
+ ` ${import_chalk5.default.dim(`Completed in ${(result.durationMs / 1e3).toFixed(1)}s`)}`
40214
40549
  );
40215
40550
  lines.push("");
40216
40551
  }
@@ -40219,12 +40554,12 @@ function renderResultStatic(result, config) {
40219
40554
  async function runStatic(config) {
40220
40555
  const dbg = (msg) => {
40221
40556
  if (config.debug)
40222
- process.stderr.write(import_chalk4.default.dim(` [debug] ${msg}
40557
+ process.stderr.write(import_chalk5.default.dim(` [debug] ${msg}
40223
40558
  `));
40224
40559
  };
40225
40560
  if (config.mode === "off") {
40226
40561
  process.stderr.write(
40227
- import_chalk4.default.dim(" Dependency Guardian: mode is off \u2014 skipping.\n")
40562
+ import_chalk5.default.dim(" Dependency Guardian: mode is off \u2014 skipping.\n")
40228
40563
  );
40229
40564
  process.exit(0);
40230
40565
  }
@@ -40232,40 +40567,44 @@ async function runStatic(config) {
40232
40567
  `mode=${config.mode} max=${config.maxPackages}`
40233
40568
  );
40234
40569
  dbg(`api=${config.apiUrl}`);
40235
- process.stderr.write(import_chalk4.default.dim(" Discovering package changes...\n"));
40570
+ process.stderr.write(import_chalk5.default.dim(" Discovering package changes...\n"));
40236
40571
  const discovery = discoverChanges(process.cwd(), config);
40237
40572
  dbg(`discovery method: ${discovery.method}`);
40238
- if (discovery.packages.length === 0) {
40573
+ if (discovery.pythonPackages.length > 0) {
40574
+ dbg(`python packages: ${discovery.pythonPackages.length}`);
40575
+ }
40576
+ if (discovery.packages.length === 0 && discovery.pythonPackages.length === 0) {
40239
40577
  const { discoverProjects: discoverProjects2 } = await Promise.resolve().then(() => (init_discover(), discover_exports));
40240
40578
  const subProjects = discoverProjects2(process.cwd());
40241
40579
  if (subProjects.length > 0) {
40242
- process.stderr.write(import_chalk4.default.yellow(" No packages found in current directory, but found projects in subdirectories:\n\n"));
40580
+ process.stderr.write(import_chalk5.default.yellow(" No packages found in current directory, but found projects in subdirectories:\n\n"));
40243
40581
  for (const proj of subProjects) {
40244
40582
  const pkgLabel = proj.packageCount === 1 ? "package" : "packages";
40245
40583
  process.stderr.write(
40246
- import_chalk4.default.white(` ${proj.ecosystem} `) + import_chalk4.default.cyan(proj.relativePath) + import_chalk4.default.dim(` (${proj.packageCount} ${pkgLabel})
40584
+ import_chalk5.default.white(` ${proj.ecosystem} `) + import_chalk5.default.cyan(proj.relativePath) + import_chalk5.default.dim(` (${proj.packageCount} ${pkgLabel})
40247
40585
  `)
40248
40586
  );
40249
40587
  }
40250
- process.stderr.write(import_chalk4.default.dim("\n Use --workspace to scan a specific project:\n"));
40251
- process.stderr.write(import_chalk4.default.dim(` dg scan --workspace ${subProjects[0].relativePath}${config.scanAll ? " --scan-all" : ""}
40588
+ process.stderr.write(import_chalk5.default.dim("\n Use --workspace to scan a specific project:\n"));
40589
+ process.stderr.write(import_chalk5.default.dim(` dg scan --workspace ${subProjects[0].relativePath}${config.scanAll ? " --scan-all" : ""}
40252
40590
 
40253
40591
  `));
40254
40592
  } else {
40255
- process.stderr.write(import_chalk4.default.dim(" No package changes detected.\n"));
40593
+ process.stderr.write(import_chalk5.default.dim(" No package changes detected.\n"));
40256
40594
  }
40257
40595
  process.exit(0);
40258
40596
  }
40259
40597
  const packages = discovery.packages;
40598
+ const totalToScan = packages.length + discovery.pythonPackages.length;
40260
40599
  process.stderr.write(
40261
- import_chalk4.default.dim(
40262
- ` Scanning ${packages.length} package${packages.length !== 1 ? "s" : ""} (${discovery.method})...
40600
+ import_chalk5.default.dim(
40601
+ ` Scanning ${totalToScan} package${totalToScan !== 1 ? "s" : ""}${discovery.pythonPackages.length > 0 ? ` (${packages.length} npm + ${discovery.pythonPackages.length} Python)` : ""} (${discovery.method})...
40263
40602
  `
40264
40603
  )
40265
40604
  );
40266
40605
  if (discovery.skipped.length > 0) {
40267
40606
  process.stderr.write(
40268
- import_chalk4.default.yellow(
40607
+ import_chalk5.default.yellow(
40269
40608
  ` Warning: ${discovery.skipped.length} package(s) skipped (max-packages=${config.maxPackages})
40270
40609
  `
40271
40610
  )
@@ -40277,10 +40616,29 @@ async function runStatic(config) {
40277
40616
  let result;
40278
40617
  try {
40279
40618
  const startMs = Date.now();
40280
- result = await callAnalyzeAPI(packages, config, (done, total) => {
40281
- process.stderr.write(import_chalk4.default.dim(` Analyzed ${done}/${total}...
40619
+ if (packages.length > 0) {
40620
+ result = await callAnalyzeAPI(packages, config, (done, total) => {
40621
+ process.stderr.write(import_chalk5.default.dim(` Analyzed ${done}/${total}...
40282
40622
  `));
40283
- });
40623
+ });
40624
+ } else {
40625
+ result = { score: 0, action: "pass", packages: [], safeVersions: {} };
40626
+ }
40627
+ if (discovery.pythonPackages.length > 0) {
40628
+ process.stderr.write(
40629
+ import_chalk5.default.dim(` Scanning ${discovery.pythonPackages.length} Python package${discovery.pythonPackages.length !== 1 ? "s" : ""}...
40630
+ `)
40631
+ );
40632
+ const pyResult = await callPyPIAnalyzeAPI(discovery.pythonPackages, config);
40633
+ result.packages.push(...pyResult.packages);
40634
+ result.score = Math.max(result.score, pyResult.score);
40635
+ if (pyResult.action === "block" || pyResult.action === "warn" && result.action === "pass") {
40636
+ result.action = pyResult.action;
40637
+ }
40638
+ if (pyResult.trialScansRemaining !== void 0) {
40639
+ result.trialScansRemaining = pyResult.trialScansRemaining;
40640
+ }
40641
+ }
40284
40642
  dbg(
40285
40643
  `API responded in ${Date.now() - startMs}ms, action=${result.action}, score=${result.score}`
40286
40644
  );
@@ -40288,6 +40646,13 @@ async function runStatic(config) {
40288
40646
  if (handleTrialExhausted2(error, config.json)) return;
40289
40647
  throw error;
40290
40648
  }
40649
+ const jsonHandled = await handleJsonOutput(result, config);
40650
+ if (jsonHandled) {
40651
+ printTrialBanner(result);
40652
+ if (result.action === "block" && config.mode === "block") process.exit(2);
40653
+ else if (result.action === "block" || result.action === "warn") process.exit(1);
40654
+ process.exit(0);
40655
+ }
40291
40656
  const output = renderResultStatic(result, config);
40292
40657
  process.stdout.write(output + "\n");
40293
40658
  printTrialBanner(result);
@@ -40308,7 +40673,7 @@ async function runStaticNpm(npmArgs, config) {
40308
40673
  const bareSpecs = readBareInstallPackages(process.cwd());
40309
40674
  if (bareSpecs.length === 0) {
40310
40675
  process.stderr.write(
40311
- import_chalk4.default.dim(
40676
+ import_chalk5.default.dim(
40312
40677
  " Dependency Guardian: no packages to scan, passing through to npm.\n"
40313
40678
  )
40314
40679
  );
@@ -40316,7 +40681,7 @@ async function runStaticNpm(npmArgs, config) {
40316
40681
  process.exit(code);
40317
40682
  }
40318
40683
  process.stderr.write(
40319
- import_chalk4.default.dim(
40684
+ import_chalk5.default.dim(
40320
40685
  ` Resolving ${bareSpecs.length} package${bareSpecs.length !== 1 ? "s" : ""} from package.json...
40321
40686
  `
40322
40687
  )
@@ -40324,7 +40689,7 @@ async function runStaticNpm(npmArgs, config) {
40324
40689
  const { resolved: resolved2, failed: failed2 } = await resolvePackages(bareSpecs);
40325
40690
  if (failed2.length > 0 && config.debug) {
40326
40691
  process.stderr.write(
40327
- import_chalk4.default.dim(
40692
+ import_chalk5.default.dim(
40328
40693
  ` [debug] Could not resolve: ${failed2.slice(0, 5).join(", ")}${failed2.length > 5 ? ` (+${failed2.length - 5} more)` : ""}
40329
40694
  `
40330
40695
  )
@@ -40333,7 +40698,7 @@ async function runStaticNpm(npmArgs, config) {
40333
40698
  return scanAndInstallStatic(resolved2, parsed, config);
40334
40699
  }
40335
40700
  process.stderr.write(
40336
- import_chalk4.default.dim(
40701
+ import_chalk5.default.dim(
40337
40702
  ` Resolving ${parsed.packages.length} package${parsed.packages.length !== 1 ? "s" : ""}...
40338
40703
  `
40339
40704
  )
@@ -40341,7 +40706,7 @@ async function runStaticNpm(npmArgs, config) {
40341
40706
  const { resolved, failed } = await resolvePackages(parsed.packages);
40342
40707
  if (failed.length > 0) {
40343
40708
  process.stderr.write(
40344
- import_chalk4.default.yellow(
40709
+ import_chalk5.default.yellow(
40345
40710
  ` Warning: Could not resolve versions for: ${failed.join(", ")}
40346
40711
  `
40347
40712
  )
@@ -40349,7 +40714,7 @@ async function runStaticNpm(npmArgs, config) {
40349
40714
  }
40350
40715
  if (resolved.length === 0) {
40351
40716
  process.stderr.write(
40352
- import_chalk4.default.dim(" No packages to scan. Passing through to npm.\n")
40717
+ import_chalk5.default.dim(" No packages to scan. Passing through to npm.\n")
40353
40718
  );
40354
40719
  const code = await runNpm(parsed.rawArgs);
40355
40720
  process.exit(code);
@@ -40358,7 +40723,7 @@ async function runStaticNpm(npmArgs, config) {
40358
40723
  }
40359
40724
  async function scanAndInstallStatic(resolved, parsed, config) {
40360
40725
  process.stderr.write(
40361
- import_chalk4.default.dim(
40726
+ import_chalk5.default.dim(
40362
40727
  ` Scanning ${resolved.length} package${resolved.length !== 1 ? "s" : ""}...
40363
40728
  `
40364
40729
  )
@@ -40370,7 +40735,7 @@ async function scanAndInstallStatic(resolved, parsed, config) {
40370
40735
  const elapsed = Date.now() - startMs;
40371
40736
  if (config.debug) {
40372
40737
  process.stderr.write(
40373
- import_chalk4.default.dim(
40738
+ import_chalk5.default.dim(
40374
40739
  ` [debug] API responded in ${elapsed}ms, action=${result.action}, score=${result.score}
40375
40740
  `
40376
40741
  )
@@ -40380,7 +40745,7 @@ async function scanAndInstallStatic(resolved, parsed, config) {
40380
40745
  if (handleTrialExhausted2(error, config.json)) return;
40381
40746
  const msg = error instanceof Error ? error.message : String(error);
40382
40747
  process.stderr.write(
40383
- import_chalk4.default.yellow(
40748
+ import_chalk5.default.yellow(
40384
40749
  ` Warning: Scan failed (${msg}). Proceeding with install.
40385
40750
  `
40386
40751
  )
@@ -40391,8 +40756,8 @@ async function scanAndInstallStatic(resolved, parsed, config) {
40391
40756
  }
40392
40757
  if (result.action === "pass") {
40393
40758
  process.stderr.write(
40394
- import_chalk4.default.green(
40395
- ` ${import_chalk4.default.bold("\u2713")} ${resolved.length} package${resolved.length !== 1 ? "s" : ""} scanned \u2014 all clear
40759
+ import_chalk5.default.green(
40760
+ ` ${import_chalk5.default.bold("\u2713")} ${resolved.length} package${resolved.length !== 1 ? "s" : ""} scanned \u2014 all clear
40396
40761
  `
40397
40762
  )
40398
40763
  );
@@ -40406,7 +40771,7 @@ async function scanAndInstallStatic(resolved, parsed, config) {
40406
40771
  printTrialBanner(result);
40407
40772
  if (result.action === "warn") {
40408
40773
  process.stderr.write(
40409
- import_chalk4.default.yellow(" Warnings detected. Proceeding with install.\n\n")
40774
+ import_chalk5.default.yellow(" Warnings detected. Proceeding with install.\n\n")
40410
40775
  );
40411
40776
  const code = await runNpm(parsed.rawArgs);
40412
40777
  process.exit(code);
@@ -40414,8 +40779,8 @@ async function scanAndInstallStatic(resolved, parsed, config) {
40414
40779
  if (result.action === "block") {
40415
40780
  if (parsed.dgForce) {
40416
40781
  process.stderr.write(
40417
- import_chalk4.default.yellow(
40418
- import_chalk4.default.bold(
40782
+ import_chalk5.default.yellow(
40783
+ import_chalk5.default.bold(
40419
40784
  " --dg-force: Bypassing block. Install at your own risk.\n\n"
40420
40785
  )
40421
40786
  )
@@ -40424,10 +40789,10 @@ async function scanAndInstallStatic(resolved, parsed, config) {
40424
40789
  process.exit(code);
40425
40790
  }
40426
40791
  process.stderr.write(
40427
- import_chalk4.default.red(import_chalk4.default.bold(" BLOCKED: ")) + import_chalk4.default.red("High-risk packages detected. Install aborted.\n")
40792
+ import_chalk5.default.red(import_chalk5.default.bold(" BLOCKED: ")) + import_chalk5.default.red("High-risk packages detected. Install aborted.\n")
40428
40793
  );
40429
40794
  process.stderr.write(
40430
- import_chalk4.default.dim(" Use --dg-force to bypass this check.\n\n")
40795
+ import_chalk5.default.dim(" Use --dg-force to bypass this check.\n\n")
40431
40796
  );
40432
40797
  process.exit(2);
40433
40798
  }
@@ -40444,13 +40809,13 @@ async function runStaticPip(pipArgs, config) {
40444
40809
  }
40445
40810
  if (specs.length === 0) {
40446
40811
  process.stderr.write(
40447
- import_chalk4.default.dim(" Dependency Guardian: no packages to scan, passing through to pip.\n")
40812
+ import_chalk5.default.dim(" Dependency Guardian: no packages to scan, passing through to pip.\n")
40448
40813
  );
40449
40814
  const code = await runPip(parsed.rawArgs);
40450
40815
  process.exit(code);
40451
40816
  }
40452
40817
  process.stderr.write(
40453
- import_chalk4.default.dim(
40818
+ import_chalk5.default.dim(
40454
40819
  ` Resolving ${specs.length} package${specs.length !== 1 ? "s" : ""} from PyPI...
40455
40820
  `
40456
40821
  )
@@ -40458,19 +40823,19 @@ async function runStaticPip(pipArgs, config) {
40458
40823
  const { resolved, failed } = await resolvePackages2(specs);
40459
40824
  if (failed.length > 0) {
40460
40825
  process.stderr.write(
40461
- import_chalk4.default.yellow(` Warning: Could not resolve versions for: ${failed.join(", ")}
40826
+ import_chalk5.default.yellow(` Warning: Could not resolve versions for: ${failed.join(", ")}
40462
40827
  `)
40463
40828
  );
40464
40829
  }
40465
40830
  if (resolved.length === 0) {
40466
40831
  process.stderr.write(
40467
- import_chalk4.default.dim(" No packages to scan. Passing through to pip.\n")
40832
+ import_chalk5.default.dim(" No packages to scan. Passing through to pip.\n")
40468
40833
  );
40469
40834
  const code = await runPip(parsed.rawArgs);
40470
40835
  process.exit(code);
40471
40836
  }
40472
40837
  process.stderr.write(
40473
- import_chalk4.default.dim(
40838
+ import_chalk5.default.dim(
40474
40839
  ` Scanning ${resolved.length} Python package${resolved.length !== 1 ? "s" : ""}...
40475
40840
  `
40476
40841
  )
@@ -40482,7 +40847,7 @@ async function runStaticPip(pipArgs, config) {
40482
40847
  if (handleTrialExhausted2(error, config.json)) return;
40483
40848
  const msg = error instanceof Error ? error.message : String(error);
40484
40849
  process.stderr.write(
40485
- import_chalk4.default.yellow(` Warning: Scan failed (${msg}). Proceeding with install.
40850
+ import_chalk5.default.yellow(` Warning: Scan failed (${msg}). Proceeding with install.
40486
40851
  `)
40487
40852
  );
40488
40853
  const code = await runPip(parsed.rawArgs);
@@ -40491,8 +40856,8 @@ async function runStaticPip(pipArgs, config) {
40491
40856
  }
40492
40857
  if (result.action === "pass") {
40493
40858
  process.stderr.write(
40494
- import_chalk4.default.green(
40495
- ` ${import_chalk4.default.bold("\u2713")} ${resolved.length} package${resolved.length !== 1 ? "s" : ""} scanned \u2014 all clear
40859
+ import_chalk5.default.green(
40860
+ ` ${import_chalk5.default.bold("\u2713")} ${resolved.length} package${resolved.length !== 1 ? "s" : ""} scanned \u2014 all clear
40496
40861
  `
40497
40862
  )
40498
40863
  );
@@ -40506,7 +40871,7 @@ async function runStaticPip(pipArgs, config) {
40506
40871
  printTrialBanner(result);
40507
40872
  if (result.action === "warn") {
40508
40873
  process.stderr.write(
40509
- import_chalk4.default.yellow(" Warnings detected. Proceeding with install.\n\n")
40874
+ import_chalk5.default.yellow(" Warnings detected. Proceeding with install.\n\n")
40510
40875
  );
40511
40876
  const code = await runPip(parsed.rawArgs);
40512
40877
  process.exit(code);
@@ -40514,16 +40879,16 @@ async function runStaticPip(pipArgs, config) {
40514
40879
  if (result.action === "block") {
40515
40880
  if (parsed.dgForce) {
40516
40881
  process.stderr.write(
40517
- import_chalk4.default.yellow(import_chalk4.default.bold(" --dg-force: Bypassing block. Install at your own risk.\n\n"))
40882
+ import_chalk5.default.yellow(import_chalk5.default.bold(" --dg-force: Bypassing block. Install at your own risk.\n\n"))
40518
40883
  );
40519
40884
  const code = await runPip(parsed.rawArgs);
40520
40885
  process.exit(code);
40521
40886
  }
40522
40887
  process.stderr.write(
40523
- import_chalk4.default.red(import_chalk4.default.bold(" BLOCKED: ")) + import_chalk4.default.red("High-risk packages detected. Install aborted.\n")
40888
+ import_chalk5.default.red(import_chalk5.default.bold(" BLOCKED: ")) + import_chalk5.default.red("High-risk packages detected. Install aborted.\n")
40524
40889
  );
40525
40890
  process.stderr.write(
40526
- import_chalk4.default.dim(" Use --dg-force to bypass this check.\n\n")
40891
+ import_chalk5.default.dim(" Use --dg-force to bypass this check.\n\n")
40527
40892
  );
40528
40893
  process.exit(2);
40529
40894
  }
@@ -40539,17 +40904,17 @@ async function runStaticLogin() {
40539
40904
  const existing = getStoredApiKey2();
40540
40905
  if (existing) {
40541
40906
  process.stderr.write(
40542
- import_chalk4.default.yellow(" Already authenticated.\n") + import_chalk4.default.dim(" Run `dg logout` first to re-authenticate.\n")
40907
+ import_chalk5.default.yellow(" Already authenticated.\n") + import_chalk5.default.dim(" Run `dg logout` first to re-authenticate.\n")
40543
40908
  );
40544
40909
  return;
40545
40910
  }
40546
- process.stderr.write(import_chalk4.default.dim(" Creating login session...\n"));
40911
+ process.stderr.write(import_chalk5.default.dim(" Creating login session...\n"));
40547
40912
  let session;
40548
40913
  try {
40549
40914
  session = await createAuthSession2();
40550
40915
  } catch (err) {
40551
40916
  process.stderr.write(
40552
- import_chalk4.default.red(` Error: ${err instanceof Error ? err.message : String(err)}
40917
+ import_chalk5.default.red(` Error: ${err instanceof Error ? err.message : String(err)}
40553
40918
  `)
40554
40919
  );
40555
40920
  process.exit(1);
@@ -40557,10 +40922,10 @@ async function runStaticLogin() {
40557
40922
  process.stderr.write(`
40558
40923
  Authenticate your account at:
40559
40924
  `);
40560
- process.stderr.write(` ${import_chalk4.default.cyan(session.verifyUrl)}
40925
+ process.stderr.write(` ${import_chalk5.default.cyan(session.verifyUrl)}
40561
40926
 
40562
40927
  `);
40563
- process.stderr.write(import_chalk4.default.dim(" Press ENTER to open in the browser...\n"));
40928
+ process.stderr.write(import_chalk5.default.dim(" Press ENTER to open in the browser...\n"));
40564
40929
  await new Promise((resolve) => {
40565
40930
  const onData = () => {
40566
40931
  process.stdin.removeListener("data", onData);
@@ -40575,7 +40940,7 @@ async function runStaticLogin() {
40575
40940
  openBrowser2(session.verifyUrl);
40576
40941
  } catch {
40577
40942
  }
40578
- process.stderr.write(import_chalk4.default.dim(" Waiting for authorization...\n"));
40943
+ process.stderr.write(import_chalk5.default.dim(" Waiting for authorization...\n"));
40579
40944
  const POLL_INTERVAL = 2e3;
40580
40945
  const MAX_ATTEMPTS = 150;
40581
40946
  for (let i = 0; i < MAX_ATTEMPTS; i++) {
@@ -40585,15 +40950,15 @@ async function runStaticLogin() {
40585
40950
  if (result.status === "complete" && result.apiKey) {
40586
40951
  saveCredentials2(result.apiKey);
40587
40952
  process.stderr.write(
40588
- import_chalk4.default.green(`
40953
+ import_chalk5.default.green(`
40589
40954
  Logged in as ${result.email ?? "unknown"}
40590
- `) + import_chalk4.default.dim(" Credentials saved.\n\n")
40955
+ `) + import_chalk5.default.dim(" Credentials saved.\n\n")
40591
40956
  );
40592
40957
  return;
40593
40958
  }
40594
40959
  if (result.status === "expired") {
40595
40960
  process.stderr.write(
40596
- import_chalk4.default.yellow("\n Session expired. Run `dg login` to try again.\n")
40961
+ import_chalk5.default.yellow("\n Session expired. Run `dg login` to try again.\n")
40597
40962
  );
40598
40963
  process.exit(1);
40599
40964
  }
@@ -40601,15 +40966,15 @@ async function runStaticLogin() {
40601
40966
  }
40602
40967
  }
40603
40968
  process.stderr.write(
40604
- import_chalk4.default.yellow("\n Timed out waiting for authorization.\n")
40969
+ import_chalk5.default.yellow("\n Timed out waiting for authorization.\n")
40605
40970
  );
40606
40971
  process.exit(1);
40607
40972
  }
40608
- var import_chalk4;
40973
+ var import_chalk5;
40609
40974
  var init_static_output = __esm({
40610
40975
  "src/static-output.ts"() {
40611
40976
  "use strict";
40612
- import_chalk4 = __toESM(require_source());
40977
+ import_chalk5 = __toESM(require_source());
40613
40978
  init_api();
40614
40979
  init_lockfile();
40615
40980
  init_npm_wrapper();
@@ -40624,14 +40989,14 @@ __export(hook_exports, {
40624
40989
  });
40625
40990
  import { execFileSync as execFileSync3 } from "node:child_process";
40626
40991
  import {
40627
- existsSync as existsSync8,
40992
+ existsSync as existsSync9,
40628
40993
  readFileSync as readFileSync9,
40629
40994
  writeFileSync as writeFileSync3,
40630
40995
  mkdirSync,
40631
40996
  chmodSync as chmodSync2,
40632
40997
  unlinkSync as unlinkSync2
40633
40998
  } from "node:fs";
40634
- import { join as join7 } from "node:path";
40999
+ import { join as join8 } from "node:path";
40635
41000
  function findGitDir() {
40636
41001
  try {
40637
41002
  return execFileSync3("git", ["rev-parse", "--git-dir"], {
@@ -40644,10 +41009,10 @@ function findGitDir() {
40644
41009
  }
40645
41010
  function installHook() {
40646
41011
  const gitDir = findGitDir();
40647
- const hooksDir = join7(gitDir, "hooks");
40648
- const hookPath = join7(hooksDir, "pre-commit");
41012
+ const hooksDir = join8(gitDir, "hooks");
41013
+ const hookPath = join8(hooksDir, "pre-commit");
40649
41014
  mkdirSync(hooksDir, { recursive: true });
40650
- if (existsSync8(hookPath)) {
41015
+ if (existsSync9(hookPath)) {
40651
41016
  const existing = readFileSync9(hookPath, "utf-8");
40652
41017
  if (existing.includes(HOOK_MARKER)) {
40653
41018
  process.stderr.write(" Hook already installed.\n");
@@ -40668,8 +41033,8 @@ function installHook() {
40668
41033
  }
40669
41034
  function uninstallHook() {
40670
41035
  const gitDir = findGitDir();
40671
- const hookPath = join7(gitDir, "hooks", "pre-commit");
40672
- if (!existsSync8(hookPath)) {
41036
+ const hookPath = join8(gitDir, "hooks", "pre-commit");
41037
+ if (!existsSync9(hookPath)) {
40673
41038
  process.stderr.write(" No hook to remove.\n");
40674
41039
  return;
40675
41040
  }
@@ -40792,7 +41157,7 @@ ${HOOK_SCRIPT.split("\n").slice(1).join("\n")}${MARKER_END}
40792
41157
  });
40793
41158
 
40794
41159
  // src/ui/hooks/useNpmWrapper.ts
40795
- function reducer2(_state, action) {
41160
+ function reducer3(_state, action) {
40796
41161
  switch (action.type) {
40797
41162
  case "PASSTHROUGH":
40798
41163
  return { phase: "passthrough" };
@@ -40816,12 +41181,12 @@ function reducer2(_state, action) {
40816
41181
  return { phase: "trial_exhausted" };
40817
41182
  }
40818
41183
  }
40819
- function useNpmWrapper(npmArgs, config) {
40820
- const [state, dispatch] = (0, import_react25.useReducer)(reducer2, { phase: "resolving", count: 0 });
40821
- const started = (0, import_react25.useRef)(false);
40822
- const parsedRef = (0, import_react25.useRef)(parseNpmArgs(npmArgs));
40823
- const pendingInstall = (0, import_react25.useRef)(null);
40824
- const rejectRef = (0, import_react25.useRef)(null);
41184
+ function useNpmWrapper(npmArgs, config, exit) {
41185
+ const [state, dispatch] = (0, import_react26.useReducer)(reducer3, { phase: "resolving", count: 0 });
41186
+ const started = (0, import_react26.useRef)(false);
41187
+ const parsedRef = (0, import_react26.useRef)(parseNpmArgs(npmArgs));
41188
+ const pendingInstall = (0, import_react26.useRef)(null);
41189
+ const rejectRef = (0, import_react26.useRef)(null);
40825
41190
  const confirmInstall = () => {
40826
41191
  if (pendingInstall.current) {
40827
41192
  pendingInstall.current();
@@ -40836,7 +41201,7 @@ function useNpmWrapper(npmArgs, config) {
40836
41201
  rejectRef.current = null;
40837
41202
  }
40838
41203
  };
40839
- (0, import_react25.useEffect)(() => {
41204
+ (0, import_react26.useEffect)(() => {
40840
41205
  if (started.current) return;
40841
41206
  started.current = true;
40842
41207
  const parsed = parsedRef.current;
@@ -40871,18 +41236,24 @@ function useNpmWrapper(npmArgs, config) {
40871
41236
  dispatch({ type: "SCANNING", count: resolved.length });
40872
41237
  const result = await callAnalyzeAPI(resolved, config);
40873
41238
  if (result.action === "pass") {
40874
- dispatch({ type: "PASS", count: resolved.length });
40875
- dispatch({ type: "INSTALLING" });
41239
+ if (exit) exit();
41240
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
41241
+ process.stderr.write(
41242
+ chalk8.green(` \u2713 ${resolved.length} package${resolved.length !== 1 ? "s" : ""} scanned \u2014 all clear
41243
+ `)
41244
+ );
41245
+ process.stderr.write("\n");
40876
41246
  const code = await runNpm(parsed.rawArgs);
40877
- dispatch({ type: "DONE", exitCode: code });
41247
+ process.exit(code);
40878
41248
  return;
40879
41249
  }
40880
41250
  if (result.action === "warn") {
40881
- dispatch({ type: "WARN", result });
41251
+ if (exit) exit();
40882
41252
  process.stdout.write(renderResultStatic(result, config) + "\n");
40883
- dispatch({ type: "INSTALLING" });
41253
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
41254
+ process.stderr.write(chalk8.yellow(" Warnings detected. Proceeding with install.\n\n"));
40884
41255
  const code = await runNpm(parsed.rawArgs);
40885
- dispatch({ type: "DONE", exitCode: code });
41256
+ process.exit(code);
40886
41257
  return;
40887
41258
  }
40888
41259
  if (result.action === "block") {
@@ -40923,11 +41294,11 @@ function useNpmWrapper(npmArgs, config) {
40923
41294
  }, [npmArgs, config]);
40924
41295
  return { state, confirmInstall, rejectInstall };
40925
41296
  }
40926
- var import_react25;
41297
+ var import_react26;
40927
41298
  var init_useNpmWrapper = __esm({
40928
41299
  "src/ui/hooks/useNpmWrapper.ts"() {
40929
41300
  "use strict";
40930
- import_react25 = __toESM(require_react());
41301
+ import_react26 = __toESM(require_react());
40931
41302
  init_npm_wrapper();
40932
41303
  init_api();
40933
41304
  init_static_output();
@@ -40936,7 +41307,7 @@ var init_useNpmWrapper = __esm({
40936
41307
 
40937
41308
  // src/ui/components/ScoreHeader.tsx
40938
41309
  function scoreColor(score, action) {
40939
- const colorFn = action === "block" ? import_chalk5.default.red.bold : action === "warn" ? import_chalk5.default.yellow.bold : import_chalk5.default.green.bold;
41310
+ const colorFn = action === "block" ? import_chalk6.default.red.bold : action === "warn" ? import_chalk6.default.yellow.bold : import_chalk6.default.green.bold;
40940
41311
  return colorFn(String(score));
40941
41312
  }
40942
41313
  function severityBar(counts) {
@@ -40950,7 +41321,7 @@ function severityBar(counts) {
40950
41321
  if (count === 0) continue;
40951
41322
  const width = Math.max(2, Math.round(count / total * BAR_WIDTH));
40952
41323
  const bar = "\u2501".repeat(width);
40953
- const colorFn = SEV_COLORS[lv] ?? import_chalk5.default.dim;
41324
+ const colorFn = SEV_COLORS[lv] ?? import_chalk6.default.dim;
40954
41325
  parts.push(`${colorFn(bar)} ${count} ${SEV_LABELS[lv] ?? ""}`);
40955
41326
  }
40956
41327
  return parts.join(" ");
@@ -40984,10 +41355,10 @@ function fillCircle(grid, cx, cy, r, type) {
40984
41355
  }
40985
41356
  function renderLogo(action) {
40986
41357
  const colors = {
40987
- 1: import_chalk5.default.dim,
40988
- 2: import_chalk5.default.white,
40989
- 3: (s) => import_chalk5.default.bold.white(s),
40990
- 4: action === "block" ? import_chalk5.default.red : action === "warn" ? import_chalk5.default.yellow : import_chalk5.default.green
41358
+ 1: import_chalk6.default.dim,
41359
+ 2: import_chalk6.default.white,
41360
+ 3: (s) => import_chalk6.default.bold.white(s),
41361
+ 4: action === "block" ? import_chalk6.default.red : action === "warn" ? import_chalk6.default.yellow : import_chalk6.default.green
40991
41362
  };
40992
41363
  const result = [];
40993
41364
  const { chars, types, cols } = LOGO_DATA;
@@ -40996,24 +41367,24 @@ function renderLogo(action) {
40996
41367
  for (let j = 0; j < cols; j++) {
40997
41368
  const ch = chars[i + j];
40998
41369
  const t = types[i + j];
40999
- row += t > 0 ? (colors[t] ?? import_chalk5.default.dim)(ch) : ch;
41370
+ row += t > 0 ? (colors[t] ?? import_chalk6.default.dim)(ch) : ch;
41000
41371
  }
41001
41372
  result.push(row);
41002
41373
  }
41003
41374
  return result;
41004
41375
  }
41005
- var import_chalk5, import_jsx_runtime3, SEV_COLORS, SEV_LABELS, LOGO_DATA, ScoreHeader;
41376
+ var import_chalk6, import_jsx_runtime4, SEV_COLORS, SEV_LABELS, LOGO_DATA, ScoreHeader;
41006
41377
  var init_ScoreHeader = __esm({
41007
41378
  async "src/ui/components/ScoreHeader.tsx"() {
41008
41379
  "use strict";
41009
41380
  await init_build2();
41010
- import_chalk5 = __toESM(require_source());
41011
- import_jsx_runtime3 = __toESM(require_jsx_runtime());
41381
+ import_chalk6 = __toESM(require_source());
41382
+ import_jsx_runtime4 = __toESM(require_jsx_runtime());
41012
41383
  SEV_COLORS = {
41013
- 5: (s) => import_chalk5.default.red(s),
41014
- 4: (s) => import_chalk5.default.magenta(s),
41015
- 3: (s) => import_chalk5.default.yellow(s),
41016
- 2: (s) => import_chalk5.default.dim(s)
41384
+ 5: (s) => import_chalk6.default.red(s),
41385
+ 4: (s) => import_chalk6.default.magenta(s),
41386
+ 3: (s) => import_chalk6.default.yellow(s),
41387
+ 2: (s) => import_chalk6.default.dim(s)
41017
41388
  };
41018
41389
  SEV_LABELS = {
41019
41390
  5: "crit",
@@ -41071,7 +41442,7 @@ var init_ScoreHeader = __esm({
41071
41442
  }) => {
41072
41443
  const logo = renderLogo(action);
41073
41444
  const showLogo = (process.stdout.columns ?? 80) >= 60;
41074
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
41445
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
41075
41446
  Box_default,
41076
41447
  {
41077
41448
  flexDirection: "column",
@@ -41080,37 +41451,37 @@ var init_ScoreHeader = __esm({
41080
41451
  paddingLeft: 1,
41081
41452
  paddingRight: 1,
41082
41453
  width: "100%",
41083
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "row", children: [
41084
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, children: [
41085
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { bold: true, children: [
41086
- import_chalk5.default.cyan("\u25C6"),
41454
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "row", children: [
41455
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, children: [
41456
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { bold: true, children: [
41457
+ import_chalk6.default.cyan("\u25C6"),
41087
41458
  " Dependency Guardian"
41088
41459
  ] }),
41089
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: " " }),
41090
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { children: [
41091
- import_chalk5.default.dim("Score"),
41460
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { children: " " }),
41461
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { children: [
41462
+ import_chalk6.default.dim("Score"),
41092
41463
  " ",
41093
41464
  scoreColor(score, action)
41094
41465
  ] }),
41095
- total !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
41096
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: " " }),
41097
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { children: [
41098
- import_chalk5.default.dim(`${total} package${total !== 1 ? "s" : ""} scanned`),
41099
- flagged !== void 0 && flagged > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
41466
+ total !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
41467
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { children: " " }),
41468
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { children: [
41469
+ import_chalk6.default.dim(`${total} package${total !== 1 ? "s" : ""} scanned`),
41470
+ flagged !== void 0 && flagged > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
41100
41471
  " ",
41101
- import_chalk5.default.yellow(`${flagged} flagged`),
41472
+ import_chalk6.default.yellow(`${flagged} flagged`),
41102
41473
  " ",
41103
- import_chalk5.default.green(`${clean ?? 0} clean`)
41104
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
41474
+ import_chalk6.default.green(`${clean ?? 0} clean`)
41475
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
41105
41476
  " ",
41106
- import_chalk5.default.green("all clean")
41477
+ import_chalk6.default.green("all clean")
41107
41478
  ] })
41108
41479
  ] }),
41109
- severityCounts && Object.values(severityCounts).some((v) => v > 0) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: severityBar(severityCounts) }),
41110
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: `\x1B]8;;https://westbayberry.com\x07westbayberry.com\x1B]8;;\x07` })
41480
+ severityCounts && Object.values(severityCounts).some((v) => v > 0) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { children: severityBar(severityCounts) }),
41481
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, children: `\x1B]8;;https://westbayberry.com\x07westbayberry.com\x1B]8;;\x07` })
41111
41482
  ] })
41112
41483
  ] }),
41113
- showLogo && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { flexDirection: "column", marginLeft: 2, children: logo.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: line }, i)) })
41484
+ showLogo && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { flexDirection: "column", marginLeft: 2, children: logo.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { children: line }, i)) })
41114
41485
  ] })
41115
41486
  }
41116
41487
  );
@@ -41119,13 +41490,13 @@ var init_ScoreHeader = __esm({
41119
41490
  });
41120
41491
 
41121
41492
  // src/ui/components/DurationLine.tsx
41122
- var import_jsx_runtime4, DurationLine;
41493
+ var import_jsx_runtime5, DurationLine;
41123
41494
  var init_DurationLine = __esm({
41124
41495
  async "src/ui/components/DurationLine.tsx"() {
41125
41496
  "use strict";
41126
41497
  await init_build2();
41127
- import_jsx_runtime4 = __toESM(require_jsx_runtime());
41128
- DurationLine = ({ ms }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { dimColor: true, children: [
41498
+ import_jsx_runtime5 = __toESM(require_jsx_runtime());
41499
+ DurationLine = ({ ms }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
41129
41500
  "Completed in ",
41130
41501
  (ms / 1e3).toFixed(1),
41131
41502
  "s"
@@ -41145,16 +41516,16 @@ function groupPackages2(packages) {
41145
41516
  return [...map.values()].map((pkgs) => ({ packages: pkgs, key: pkgs[0].name })).sort((a, b) => b.packages[0].score - a.packages[0].score);
41146
41517
  }
41147
41518
  function severityColor(sev) {
41148
- if (sev >= 5) return (s) => import_chalk6.default.bold.red(s);
41149
- if (sev >= 4) return import_chalk6.default.magenta;
41150
- if (sev >= 3) return import_chalk6.default.yellow;
41151
- if (sev >= 2) return import_chalk6.default.dim;
41152
- return import_chalk6.default.dim;
41519
+ if (sev >= 5) return (s) => import_chalk7.default.bold.red(s);
41520
+ if (sev >= 4) return import_chalk7.default.magenta;
41521
+ if (sev >= 3) return import_chalk7.default.yellow;
41522
+ if (sev >= 2) return import_chalk7.default.dim;
41523
+ return import_chalk7.default.dim;
41153
41524
  }
41154
41525
  function actionBadge2(score) {
41155
- if (score >= 70) return { label: "BLOCK", color: import_chalk6.default.red };
41156
- if (score >= 60) return { label: "WARN", color: import_chalk6.default.yellow };
41157
- return { label: "PASS", color: import_chalk6.default.green };
41526
+ if (score >= 70) return { label: "BLOCK", color: import_chalk7.default.red };
41527
+ if (score >= 60) return { label: "WARN", color: import_chalk7.default.yellow };
41528
+ return { label: "PASS", color: import_chalk7.default.green };
41158
41529
  }
41159
41530
  function truncate2(s, max) {
41160
41531
  return s.length <= max ? s : s.slice(0, max - 1) + "\u2026";
@@ -41162,15 +41533,15 @@ function truncate2(s, max) {
41162
41533
  function pad2(s, len) {
41163
41534
  return s + " ".repeat(Math.max(0, len - s.length));
41164
41535
  }
41165
- var import_chalk6, import_jsx_runtime5, SEVERITY_LABELS, EVIDENCE_LIMIT, ResultsView;
41536
+ var import_chalk7, import_jsx_runtime6, SEVERITY_LABELS, EVIDENCE_LIMIT, ResultsView;
41166
41537
  var init_ResultsView = __esm({
41167
41538
  async "src/ui/components/ResultsView.tsx"() {
41168
41539
  "use strict";
41169
41540
  await init_build2();
41170
- import_chalk6 = __toESM(require_source());
41541
+ import_chalk7 = __toESM(require_source());
41171
41542
  await init_ScoreHeader();
41172
41543
  await init_DurationLine();
41173
- import_jsx_runtime5 = __toESM(require_jsx_runtime());
41544
+ import_jsx_runtime6 = __toESM(require_jsx_runtime());
41174
41545
  SEVERITY_LABELS = {
41175
41546
  5: "CRITICAL",
41176
41547
  4: "HIGH",
@@ -41188,70 +41559,70 @@ var init_ResultsView = __esm({
41188
41559
  const clean = result.packages.filter((p) => p.score === 0);
41189
41560
  const total = result.packages.length;
41190
41561
  const groups = groupPackages2(flagged);
41191
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, children: [
41192
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Newline, {}),
41193
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ScoreHeader, { score: result.score, action: result.action }),
41194
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Newline, {}),
41195
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
41196
- import_chalk6.default.dim(`${total} package${total !== 1 ? "s" : ""} scanned`),
41197
- flagged.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
41562
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, children: [
41563
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Newline, {}),
41564
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ScoreHeader, { score: result.score, action: result.action }),
41565
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Newline, {}),
41566
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
41567
+ import_chalk7.default.dim(`${total} package${total !== 1 ? "s" : ""} scanned`),
41568
+ flagged.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
41198
41569
  " ",
41199
- import_chalk6.default.yellow(`${flagged.length} flagged`),
41570
+ import_chalk7.default.yellow(`${flagged.length} flagged`),
41200
41571
  " ",
41201
- import_chalk6.default.green(`${clean.length} clean`)
41202
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
41572
+ import_chalk7.default.green(`${clean.length} clean`)
41573
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
41203
41574
  " ",
41204
- import_chalk6.default.green("all clean")
41575
+ import_chalk7.default.green("all clean")
41205
41576
  ] })
41206
41577
  ] }),
41207
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Newline, {}),
41208
- flagged.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", children: [
41209
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { bold: true, children: "Flagged Packages" }),
41210
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "\u2500".repeat(60) }),
41578
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Newline, {}),
41579
+ flagged.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", children: [
41580
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { bold: true, children: "Flagged Packages" }),
41581
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { dimColor: true, children: "\u2500".repeat(60) }),
41211
41582
  groups.map((group) => {
41212
41583
  const rep = group.packages[0];
41213
41584
  const { label, color } = actionBadge2(rep.score);
41214
41585
  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`;
41215
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
41586
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
41216
41587
  " ",
41217
41588
  color(pad2(label, 7)),
41218
- import_chalk6.default.bold(pad2(truncate2(names, 50), 52)),
41219
- import_chalk6.default.dim(`score ${rep.score}`)
41589
+ import_chalk7.default.bold(pad2(truncate2(names, 50), 52)),
41590
+ import_chalk7.default.dim(`score ${rep.score}`)
41220
41591
  ] }, group.key);
41221
41592
  }),
41222
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Newline, {})
41593
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Newline, {})
41223
41594
  ] }),
41224
- clean.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
41225
- import_chalk6.default.green("\u2713"),
41595
+ clean.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
41596
+ import_chalk7.default.green("\u2713"),
41226
41597
  " ",
41227
- import_chalk6.default.green.bold(String(clean.length)),
41598
+ import_chalk7.default.green.bold(String(clean.length)),
41228
41599
  " ",
41229
- import_chalk6.default.dim(`package${clean.length !== 1 ? "s" : ""} passed with score 0`)
41600
+ import_chalk7.default.dim(`package${clean.length !== 1 ? "s" : ""} passed with score 0`)
41230
41601
  ] }),
41231
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Newline, {}),
41602
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Newline, {}),
41232
41603
  groups.filter((g) => g.packages[0].score > 0).map((group) => {
41233
41604
  const rep = group.packages[0];
41234
41605
  const names = group.packages.length === 1 ? `${rep.name}@${rep.version}` : group.packages.length <= 3 ? group.packages.map((p) => `${p.name}@${p.version}`).join(", ") : `${rep.name}@${rep.version} + ${group.packages.length - 1} identical packages`;
41235
41606
  const visibleFindings = rep.findings.filter((f) => f.severity > 1 || f.critical).sort((a, b) => b.severity - a.severity);
41236
41607
  const safeVersion = result.safeVersions[rep.name];
41237
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", children: [
41238
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
41239
- import_chalk6.default.dim("\u2500\u2500"),
41608
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", children: [
41609
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
41610
+ import_chalk7.default.dim("\u2500\u2500"),
41240
41611
  " ",
41241
- import_chalk6.default.bold(`${names} (score: ${rep.score})`)
41612
+ import_chalk7.default.bold(`${names} (score: ${rep.score})`)
41242
41613
  ] }),
41243
- group.packages.length > 3 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { dimColor: true, children: [
41614
+ group.packages.length > 3 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { dimColor: true, children: [
41244
41615
  " Affects: ",
41245
41616
  group.packages.map((p) => p.name).join(", ")
41246
41617
  ] }),
41247
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: " " }),
41618
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { children: " " }),
41248
41619
  visibleFindings.map((finding, idx) => {
41249
41620
  const sevLabel = SEVERITY_LABELS[finding.severity] ?? "INFO";
41250
41621
  const colorFn = severityColor(finding.severity);
41251
41622
  const evidenceSlice = finding.evidence.slice(0, EVIDENCE_LIMIT);
41252
41623
  const overflow = finding.evidence.length - EVIDENCE_LIMIT;
41253
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", children: [
41254
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
41624
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", children: [
41625
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
41255
41626
  " ",
41256
41627
  colorFn(pad2(sevLabel, 10)),
41257
41628
  finding.id,
@@ -41260,40 +41631,40 @@ var init_ResultsView = __esm({
41260
41631
  " ",
41261
41632
  finding.title
41262
41633
  ] }),
41263
- evidenceSlice.map((ev, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
41634
+ evidenceSlice.map((ev, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
41264
41635
  " ",
41265
- import_chalk6.default.dim(truncate2(ev, 76))
41636
+ import_chalk7.default.dim(truncate2(ev, 76))
41266
41637
  ] }, i)),
41267
- overflow > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
41638
+ overflow > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
41268
41639
  " ",
41269
- import_chalk6.default.dim(`... and ${overflow} more`)
41640
+ import_chalk7.default.dim(`... and ${overflow} more`)
41270
41641
  ] }),
41271
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: " " })
41642
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { children: " " })
41272
41643
  ] }, `${finding.id}-${idx}`);
41273
41644
  }),
41274
- safeVersion && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
41645
+ safeVersion && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
41275
41646
  " ",
41276
- import_chalk6.default.green(`Safe version: ${rep.name}@${safeVersion}`)
41647
+ import_chalk7.default.green(`Safe version: ${rep.name}@${safeVersion}`)
41277
41648
  ] }),
41278
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Newline, {})
41649
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Newline, {})
41279
41650
  ] }, group.key);
41280
41651
  }),
41281
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DurationLine, { ms: durationMs }),
41282
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Newline, {})
41652
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DurationLine, { ms: durationMs }),
41653
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Newline, {})
41283
41654
  ] });
41284
41655
  };
41285
41656
  }
41286
41657
  });
41287
41658
 
41288
41659
  // src/ui/components/ConfirmPrompt.tsx
41289
- var import_chalk7, import_jsx_runtime6, ConfirmPrompt;
41660
+ var import_chalk8, import_jsx_runtime7, ConfirmPrompt;
41290
41661
  var init_ConfirmPrompt = __esm({
41291
41662
  async "src/ui/components/ConfirmPrompt.tsx"() {
41292
41663
  "use strict";
41293
41664
  await init_build2();
41294
41665
  await init_build2();
41295
- import_chalk7 = __toESM(require_source());
41296
- import_jsx_runtime6 = __toESM(require_jsx_runtime());
41666
+ import_chalk8 = __toESM(require_source());
41667
+ import_jsx_runtime7 = __toESM(require_jsx_runtime());
41297
41668
  ConfirmPrompt = ({
41298
41669
  message,
41299
41670
  onConfirm,
@@ -41306,17 +41677,17 @@ var init_ConfirmPrompt = __esm({
41306
41677
  onReject();
41307
41678
  }
41308
41679
  });
41309
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", children: [
41310
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
41311
- import_chalk7.default.red.bold("\u26A0"),
41680
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { flexDirection: "column", children: [
41681
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { children: [
41682
+ import_chalk8.default.red.bold("\u26A0"),
41312
41683
  " ",
41313
- import_chalk7.default.bold(message)
41684
+ import_chalk8.default.bold(message)
41314
41685
  ] }),
41315
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Text, { children: [
41686
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { children: [
41316
41687
  "Install anyway? [",
41317
- import_chalk7.default.bold.green("y"),
41688
+ import_chalk8.default.bold.green("y"),
41318
41689
  "es / ",
41319
- import_chalk7.default.bold.red("N"),
41690
+ import_chalk8.default.bold.red("N"),
41320
41691
  "o]"
41321
41692
  ] })
41322
41693
  ] });
@@ -41339,17 +41710,17 @@ function getHint(error) {
41339
41710
  return null;
41340
41711
  }
41341
41712
  }
41342
- var import_chalk8, import_jsx_runtime7, ErrorView;
41713
+ var import_chalk9, import_jsx_runtime8, ErrorView;
41343
41714
  var init_ErrorView = __esm({
41344
41715
  async "src/ui/components/ErrorView.tsx"() {
41345
41716
  "use strict";
41346
41717
  await init_build2();
41347
- import_chalk8 = __toESM(require_source());
41718
+ import_chalk9 = __toESM(require_source());
41348
41719
  init_sanitize();
41349
- import_jsx_runtime7 = __toESM(require_jsx_runtime());
41720
+ import_jsx_runtime8 = __toESM(require_jsx_runtime());
41350
41721
  ErrorView = ({ error }) => {
41351
41722
  const hint = getHint(error);
41352
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
41723
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
41353
41724
  Box_default,
41354
41725
  {
41355
41726
  flexDirection: "column",
@@ -41358,10 +41729,10 @@ var init_ErrorView = __esm({
41358
41729
  paddingLeft: 1,
41359
41730
  paddingRight: 1,
41360
41731
  children: [
41361
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: import_chalk8.default.red.bold("\u2718 Error") }),
41362
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: sanitize(error.message) }),
41363
- hint && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { children: [
41364
- import_chalk8.default.yellow("\u2192"),
41732
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: import_chalk9.default.red.bold("\u2718 Error") }),
41733
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: sanitize(error.message) }),
41734
+ hint && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { children: [
41735
+ import_chalk9.default.yellow("\u2192"),
41365
41736
  " ",
41366
41737
  hint
41367
41738
  ] })
@@ -41377,25 +41748,25 @@ var NpmWrapperApp_exports = {};
41377
41748
  __export(NpmWrapperApp_exports, {
41378
41749
  NpmWrapperApp: () => NpmWrapperApp
41379
41750
  });
41380
- var import_react26, import_jsx_runtime8, NpmWrapperApp;
41751
+ var import_react27, import_jsx_runtime9, NpmWrapperApp;
41381
41752
  var init_NpmWrapperApp = __esm({
41382
41753
  async "src/ui/NpmWrapperApp.tsx"() {
41383
41754
  "use strict";
41384
- import_react26 = __toESM(require_react());
41755
+ import_react27 = __toESM(require_react());
41385
41756
  await init_build2();
41386
41757
  init_useNpmWrapper();
41387
41758
  await init_Spinner();
41388
41759
  await init_ResultsView();
41389
41760
  await init_ConfirmPrompt();
41390
41761
  await init_ErrorView();
41391
- import_jsx_runtime8 = __toESM(require_jsx_runtime());
41762
+ import_jsx_runtime9 = __toESM(require_jsx_runtime());
41392
41763
  NpmWrapperApp = ({
41393
41764
  npmArgs,
41394
41765
  config
41395
41766
  }) => {
41396
- const { state, confirmInstall, rejectInstall } = useNpmWrapper(npmArgs, config);
41397
41767
  const { exit } = use_app_default();
41398
- (0, import_react26.useEffect)(() => {
41768
+ const { state, confirmInstall, rejectInstall } = useNpmWrapper(npmArgs, config, exit);
41769
+ (0, import_react27.useEffect)(() => {
41399
41770
  if (state.phase === "done") {
41400
41771
  process.exitCode = state.exitCode;
41401
41772
  const timer = setTimeout(() => exit(), 0);
@@ -41409,29 +41780,29 @@ var init_NpmWrapperApp = __esm({
41409
41780
  if (state.phase === "passthrough") {
41410
41781
  }
41411
41782
  }, [state, exit]);
41412
- const handleConfirm = (0, import_react26.useCallback)(() => {
41783
+ const handleConfirm = (0, import_react27.useCallback)(() => {
41413
41784
  confirmInstall();
41414
41785
  }, [confirmInstall]);
41415
- const handleReject = (0, import_react26.useCallback)(() => {
41786
+ const handleReject = (0, import_react27.useCallback)(() => {
41416
41787
  rejectInstall();
41417
41788
  }, [rejectInstall]);
41418
41789
  switch (state.phase) {
41419
41790
  case "resolving":
41420
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
41791
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
41421
41792
  Spinner2,
41422
41793
  {
41423
41794
  label: `Resolving ${state.count} package${state.count !== 1 ? "s" : ""}...`
41424
41795
  }
41425
41796
  );
41426
41797
  case "scanning":
41427
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
41798
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
41428
41799
  Spinner2,
41429
41800
  {
41430
41801
  label: `Scanning ${state.count} package${state.count !== 1 ? "s" : ""}...`
41431
41802
  }
41432
41803
  );
41433
41804
  case "pass":
41434
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { color: "green", children: [
41805
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { color: "green", children: [
41435
41806
  "\u2713",
41436
41807
  " ",
41437
41808
  state.count,
@@ -41442,8 +41813,8 @@ var init_NpmWrapperApp = __esm({
41442
41813
  "all clear"
41443
41814
  ] });
41444
41815
  case "warn":
41445
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { flexDirection: "column", children: [
41446
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
41816
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "column", children: [
41817
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
41447
41818
  ResultsView,
41448
41819
  {
41449
41820
  result: state.result,
@@ -41451,12 +41822,12 @@ var init_NpmWrapperApp = __esm({
41451
41822
  durationMs: state.result.durationMs
41452
41823
  }
41453
41824
  ),
41454
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "yellow", children: "Warnings detected. Proceeding with install..." })
41825
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "yellow", children: "Warnings detected. Proceeding with install..." })
41455
41826
  ] });
41456
41827
  case "blocked":
41457
41828
  if (state.dgForce) {
41458
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { flexDirection: "column", children: [
41459
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
41829
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "column", children: [
41830
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
41460
41831
  ResultsView,
41461
41832
  {
41462
41833
  result: state.result,
@@ -41464,11 +41835,11 @@ var init_NpmWrapperApp = __esm({
41464
41835
  durationMs: state.result.durationMs
41465
41836
  }
41466
41837
  ),
41467
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "yellow", bold: true, children: "--dg-force: Bypassing block. Install at your own risk." })
41838
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "yellow", bold: true, children: "--dg-force: Bypassing block. Install at your own risk." })
41468
41839
  ] });
41469
41840
  }
41470
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { flexDirection: "column", children: [
41471
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
41841
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "column", children: [
41842
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
41472
41843
  ResultsView,
41473
41844
  {
41474
41845
  result: state.result,
@@ -41476,12 +41847,12 @@ var init_NpmWrapperApp = __esm({
41476
41847
  durationMs: state.result.durationMs
41477
41848
  }
41478
41849
  ),
41479
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { color: "red", bold: true, children: [
41850
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { color: "red", bold: true, children: [
41480
41851
  "BLOCKED:",
41481
41852
  " ",
41482
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "red", children: "High-risk packages detected." })
41853
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "red", children: "High-risk packages detected." })
41483
41854
  ] }),
41484
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
41855
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
41485
41856
  ConfirmPrompt,
41486
41857
  {
41487
41858
  message: "Proceed with install anyway?",
@@ -41491,18 +41862,18 @@ var init_NpmWrapperApp = __esm({
41491
41862
  )
41492
41863
  ] });
41493
41864
  case "installing":
41494
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Spinner2, { label: "Installing..." });
41865
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Spinner2, { label: "Installing..." });
41495
41866
  case "done":
41496
41867
  return null;
41497
41868
  case "error":
41498
41869
  if (state.proceed) {
41499
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { color: "yellow", children: [
41870
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { color: "yellow", children: [
41500
41871
  "Warning: Scan failed (",
41501
41872
  state.message,
41502
41873
  "). Proceeding with install."
41503
41874
  ] });
41504
41875
  }
41505
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorView, { error: new Error(state.message) });
41876
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ErrorView, { error: new Error(state.message) });
41506
41877
  case "passthrough":
41507
41878
  return null;
41508
41879
  case "trial_exhausted": {
@@ -41512,20 +41883,20 @@ var init_NpmWrapperApp = __esm({
41512
41883
  hasKey = !!getStoredApiKey2();
41513
41884
  } catch {
41514
41885
  }
41515
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Box_default, { flexDirection: "column", paddingLeft: 2, children: hasKey ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
41516
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "yellow", bold: true, children: "Your API key may be invalid or expired." }),
41517
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { children: [
41886
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box_default, { flexDirection: "column", paddingLeft: 2, children: hasKey ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
41887
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "yellow", bold: true, children: "Your API key may be invalid or expired." }),
41888
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { children: [
41518
41889
  "Run ",
41519
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "cyan", bold: true, children: "dg logout" }),
41890
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "cyan", bold: true, children: "dg logout" }),
41520
41891
  " then ",
41521
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
41892
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
41522
41893
  " to re-authenticate."
41523
41894
  ] })
41524
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
41525
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "yellow", bold: true, children: "Free trial scans used up." }),
41526
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { children: [
41895
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
41896
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "yellow", bold: true, children: "Free trial scans used up." }),
41897
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { children: [
41527
41898
  "Run ",
41528
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
41899
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
41529
41900
  " to create a free account and continue scanning."
41530
41901
  ] })
41531
41902
  ] }) });
@@ -41536,7 +41907,7 @@ var init_NpmWrapperApp = __esm({
41536
41907
  });
41537
41908
 
41538
41909
  // src/ui/hooks/usePipWrapper.ts
41539
- function reducer3(_state, action) {
41910
+ function reducer4(_state, action) {
41540
41911
  switch (action.type) {
41541
41912
  case "PASSTHROUGH":
41542
41913
  return { phase: "passthrough" };
@@ -41560,12 +41931,12 @@ function reducer3(_state, action) {
41560
41931
  return { phase: "trial_exhausted" };
41561
41932
  }
41562
41933
  }
41563
- function usePipWrapper(pipArgs, config) {
41564
- const [state, dispatch] = (0, import_react27.useReducer)(reducer3, { phase: "resolving", count: 0 });
41565
- const started = (0, import_react27.useRef)(false);
41566
- const parsedRef = (0, import_react27.useRef)(parsePipArgs(pipArgs));
41567
- const pendingInstall = (0, import_react27.useRef)(null);
41568
- const rejectRef = (0, import_react27.useRef)(null);
41934
+ function usePipWrapper(pipArgs, config, exit) {
41935
+ const [state, dispatch] = (0, import_react28.useReducer)(reducer4, { phase: "resolving", count: 0 });
41936
+ const started = (0, import_react28.useRef)(false);
41937
+ const parsedRef = (0, import_react28.useRef)(parsePipArgs(pipArgs));
41938
+ const pendingInstall = (0, import_react28.useRef)(null);
41939
+ const rejectRef = (0, import_react28.useRef)(null);
41569
41940
  const confirmInstall = () => {
41570
41941
  if (pendingInstall.current) {
41571
41942
  pendingInstall.current();
@@ -41580,7 +41951,7 @@ function usePipWrapper(pipArgs, config) {
41580
41951
  rejectRef.current = null;
41581
41952
  }
41582
41953
  };
41583
- (0, import_react27.useEffect)(() => {
41954
+ (0, import_react28.useEffect)(() => {
41584
41955
  if (started.current) return;
41585
41956
  started.current = true;
41586
41957
  const parsed = parsedRef.current;
@@ -41620,18 +41991,24 @@ function usePipWrapper(pipArgs, config) {
41620
41991
  dispatch({ type: "SCANNING", count: resolved.length });
41621
41992
  const result = await callPyPIAnalyzeAPI(resolved, config);
41622
41993
  if (result.action === "pass") {
41623
- dispatch({ type: "PASS", count: resolved.length });
41624
- dispatch({ type: "INSTALLING" });
41994
+ if (exit) exit();
41995
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
41996
+ process.stderr.write(
41997
+ chalk8.green(` \u2713 ${resolved.length} package${resolved.length !== 1 ? "s" : ""} scanned \u2014 all clear
41998
+ `)
41999
+ );
42000
+ process.stderr.write("\n");
41625
42001
  const code = await runPip(parsed.rawArgs);
41626
- dispatch({ type: "DONE", exitCode: code });
42002
+ process.exit(code);
41627
42003
  return;
41628
42004
  }
41629
42005
  if (result.action === "warn") {
41630
- dispatch({ type: "WARN", result });
42006
+ if (exit) exit();
41631
42007
  process.stdout.write(renderResultStatic(result, config) + "\n");
41632
- dispatch({ type: "INSTALLING" });
42008
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
42009
+ process.stderr.write(chalk8.yellow(" Warnings detected. Proceeding with install.\n\n"));
41633
42010
  const code = await runPip(parsed.rawArgs);
41634
- dispatch({ type: "DONE", exitCode: code });
42011
+ process.exit(code);
41635
42012
  return;
41636
42013
  }
41637
42014
  if (result.action === "block") {
@@ -41672,11 +42049,11 @@ function usePipWrapper(pipArgs, config) {
41672
42049
  }, [pipArgs, config]);
41673
42050
  return { state, confirmInstall, rejectInstall };
41674
42051
  }
41675
- var import_react27;
42052
+ var import_react28;
41676
42053
  var init_usePipWrapper = __esm({
41677
42054
  "src/ui/hooks/usePipWrapper.ts"() {
41678
42055
  "use strict";
41679
- import_react27 = __toESM(require_react());
42056
+ import_react28 = __toESM(require_react());
41680
42057
  init_pip_wrapper();
41681
42058
  init_api();
41682
42059
  init_static_output();
@@ -41688,25 +42065,25 @@ var PipWrapperApp_exports = {};
41688
42065
  __export(PipWrapperApp_exports, {
41689
42066
  PipWrapperApp: () => PipWrapperApp
41690
42067
  });
41691
- var import_react28, import_jsx_runtime9, PipWrapperApp;
42068
+ var import_react29, import_jsx_runtime10, PipWrapperApp;
41692
42069
  var init_PipWrapperApp = __esm({
41693
42070
  async "src/ui/PipWrapperApp.tsx"() {
41694
42071
  "use strict";
41695
- import_react28 = __toESM(require_react());
42072
+ import_react29 = __toESM(require_react());
41696
42073
  await init_build2();
41697
42074
  init_usePipWrapper();
41698
42075
  await init_Spinner();
41699
42076
  await init_ResultsView();
41700
42077
  await init_ConfirmPrompt();
41701
42078
  await init_ErrorView();
41702
- import_jsx_runtime9 = __toESM(require_jsx_runtime());
42079
+ import_jsx_runtime10 = __toESM(require_jsx_runtime());
41703
42080
  PipWrapperApp = ({
41704
42081
  pipArgs,
41705
42082
  config
41706
42083
  }) => {
41707
- const { state, confirmInstall, rejectInstall } = usePipWrapper(pipArgs, config);
41708
42084
  const { exit } = use_app_default();
41709
- (0, import_react28.useEffect)(() => {
42085
+ const { state, confirmInstall, rejectInstall } = usePipWrapper(pipArgs, config, exit);
42086
+ (0, import_react29.useEffect)(() => {
41710
42087
  if (state.phase === "done") {
41711
42088
  process.exitCode = state.exitCode;
41712
42089
  const timer = setTimeout(() => exit(), 0);
@@ -41720,29 +42097,29 @@ var init_PipWrapperApp = __esm({
41720
42097
  if (state.phase === "passthrough") {
41721
42098
  }
41722
42099
  }, [state, exit]);
41723
- const handleConfirm = (0, import_react28.useCallback)(() => {
42100
+ const handleConfirm = (0, import_react29.useCallback)(() => {
41724
42101
  confirmInstall();
41725
42102
  }, [confirmInstall]);
41726
- const handleReject = (0, import_react28.useCallback)(() => {
42103
+ const handleReject = (0, import_react29.useCallback)(() => {
41727
42104
  rejectInstall();
41728
42105
  }, [rejectInstall]);
41729
42106
  switch (state.phase) {
41730
42107
  case "resolving":
41731
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
42108
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
41732
42109
  Spinner2,
41733
42110
  {
41734
42111
  label: `Resolving ${state.count} package${state.count !== 1 ? "s" : ""} from PyPI...`
41735
42112
  }
41736
42113
  );
41737
42114
  case "scanning":
41738
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
42115
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
41739
42116
  Spinner2,
41740
42117
  {
41741
42118
  label: `Scanning ${state.count} Python package${state.count !== 1 ? "s" : ""}...`
41742
42119
  }
41743
42120
  );
41744
42121
  case "pass":
41745
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { color: "green", children: [
42122
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: "green", children: [
41746
42123
  "\u2713",
41747
42124
  " ",
41748
42125
  state.count,
@@ -41753,8 +42130,8 @@ var init_PipWrapperApp = __esm({
41753
42130
  "all clear"
41754
42131
  ] });
41755
42132
  case "warn":
41756
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "column", children: [
41757
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
42133
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", children: [
42134
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
41758
42135
  ResultsView,
41759
42136
  {
41760
42137
  result: state.result,
@@ -41762,12 +42139,12 @@ var init_PipWrapperApp = __esm({
41762
42139
  durationMs: state.result.durationMs
41763
42140
  }
41764
42141
  ),
41765
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "yellow", children: "Warnings detected. Proceeding with install..." })
42142
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "yellow", children: "Warnings detected. Proceeding with install..." })
41766
42143
  ] });
41767
42144
  case "blocked":
41768
42145
  if (state.dgForce) {
41769
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "column", children: [
41770
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
42146
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", children: [
42147
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
41771
42148
  ResultsView,
41772
42149
  {
41773
42150
  result: state.result,
@@ -41775,11 +42152,11 @@ var init_PipWrapperApp = __esm({
41775
42152
  durationMs: state.result.durationMs
41776
42153
  }
41777
42154
  ),
41778
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "yellow", bold: true, children: "--dg-force: Bypassing block. Install at your own risk." })
42155
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "yellow", bold: true, children: "--dg-force: Bypassing block. Install at your own risk." })
41779
42156
  ] });
41780
42157
  }
41781
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { flexDirection: "column", children: [
41782
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
42158
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", children: [
42159
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
41783
42160
  ResultsView,
41784
42161
  {
41785
42162
  result: state.result,
@@ -41787,12 +42164,12 @@ var init_PipWrapperApp = __esm({
41787
42164
  durationMs: state.result.durationMs
41788
42165
  }
41789
42166
  ),
41790
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { color: "red", bold: true, children: [
42167
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: "red", bold: true, children: [
41791
42168
  "BLOCKED:",
41792
42169
  " ",
41793
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "red", children: "High-risk packages detected." })
42170
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "red", children: "High-risk packages detected." })
41794
42171
  ] }),
41795
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
42172
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
41796
42173
  ConfirmPrompt,
41797
42174
  {
41798
42175
  message: "Proceed with install anyway?",
@@ -41802,18 +42179,18 @@ var init_PipWrapperApp = __esm({
41802
42179
  )
41803
42180
  ] });
41804
42181
  case "installing":
41805
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Spinner2, { label: "Installing with pip..." });
42182
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Spinner2, { label: "Installing with pip..." });
41806
42183
  case "done":
41807
42184
  return null;
41808
42185
  case "error":
41809
42186
  if (state.proceed) {
41810
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { color: "yellow", children: [
42187
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { color: "yellow", children: [
41811
42188
  "Warning: Scan failed (",
41812
42189
  state.message,
41813
42190
  "). Proceeding with install."
41814
42191
  ] });
41815
42192
  }
41816
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ErrorView, { error: new Error(state.message) });
42193
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ErrorView, { error: new Error(state.message) });
41817
42194
  case "passthrough":
41818
42195
  return null;
41819
42196
  case "trial_exhausted": {
@@ -41823,20 +42200,20 @@ var init_PipWrapperApp = __esm({
41823
42200
  hasKey = !!getStoredApiKey2();
41824
42201
  } catch {
41825
42202
  }
41826
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box_default, { flexDirection: "column", paddingLeft: 2, children: hasKey ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
41827
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "yellow", bold: true, children: "Your API key may be invalid or expired." }),
41828
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { children: [
42203
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { flexDirection: "column", paddingLeft: 2, children: hasKey ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
42204
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "yellow", bold: true, children: "Your API key may be invalid or expired." }),
42205
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
41829
42206
  "Run ",
41830
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "cyan", bold: true, children: "dg logout" }),
42207
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "cyan", bold: true, children: "dg logout" }),
41831
42208
  " then ",
41832
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
42209
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
41833
42210
  " to re-authenticate."
41834
42211
  ] })
41835
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
41836
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "yellow", bold: true, children: "Free trial scans used up." }),
41837
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { children: [
42212
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
42213
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "yellow", bold: true, children: "Free trial scans used up." }),
42214
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
41838
42215
  "Run ",
41839
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
42216
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
41840
42217
  " to create a free account and continue scanning."
41841
42218
  ] })
41842
42219
  ] }) });
@@ -41846,1474 +42223,6 @@ var init_PipWrapperApp = __esm({
41846
42223
  }
41847
42224
  });
41848
42225
 
41849
- // src/ui/hooks/useScan.ts
41850
- function reducer4(_state, action) {
41851
- switch (action.type) {
41852
- case "PROJECTS_FOUND":
41853
- return { phase: "selecting", projects: action.projects };
41854
- case "RESTART_SELECTION":
41855
- return { phase: "selecting", projects: action.projects };
41856
- case "DISCOVERY_COMPLETE":
41857
- return { phase: "scanning", done: 0, total: action.packages.length, currentBatch: [] };
41858
- case "DISCOVERY_EMPTY":
41859
- return { phase: "empty", message: action.message };
41860
- case "SCAN_PROGRESS":
41861
- return { phase: "scanning", done: action.done, total: action.total, currentBatch: action.currentBatch };
41862
- case "SCAN_COMPLETE":
41863
- return { phase: "results", result: action.result, durationMs: action.durationMs, skippedCount: action.skippedCount, discoveredTotal: action.discoveredTotal };
41864
- case "ERROR":
41865
- return { phase: "error", error: action.error };
41866
- case "TRIAL_EXHAUSTED":
41867
- return { phase: "trial_exhausted", scansUsed: action.scansUsed, maxScans: action.maxScans };
41868
- }
41869
- }
41870
- function useScan(config) {
41871
- const [state, dispatch] = (0, import_react29.useReducer)(reducer4, { phase: "discovering" });
41872
- const started = (0, import_react29.useRef)(false);
41873
- const [multiProjects, setMultiProjects] = (0, import_react29.useState)(null);
41874
- (0, import_react29.useEffect)(() => {
41875
- if (started.current) return;
41876
- started.current = true;
41877
- const projects = discoverProjects(process.cwd());
41878
- if (projects.length > 1) setMultiProjects(projects);
41879
- if (projects.length > 1) {
41880
- dispatch({ type: "PROJECTS_FOUND", projects });
41881
- return;
41882
- }
41883
- try {
41884
- const discovery = discoverChanges(process.cwd(), config);
41885
- const packages = discovery.packages;
41886
- if (packages.length === 0) {
41887
- dispatch({ type: "DISCOVERY_EMPTY", message: "No package changes detected." });
41888
- return;
41889
- }
41890
- dispatch({ type: "DISCOVERY_COMPLETE", packages, skippedCount: discovery.skipped.length });
41891
- runNpmScan(packages, discovery.skipped.length, config, dispatch);
41892
- } catch {
41893
- if (projects.length === 0) {
41894
- dispatch({ type: "DISCOVERY_EMPTY", message: "No dependency files found." });
41895
- return;
41896
- }
41897
- dispatch({ type: "DISCOVERY_COMPLETE", packages: [], skippedCount: 0 });
41898
- scanProjects(projects, config, dispatch);
41899
- }
41900
- }, [config]);
41901
- const scanSelectedProjects = (0, import_react29.useCallback)((projects) => {
41902
- dispatch({ type: "DISCOVERY_COMPLETE", packages: [], skippedCount: 0 });
41903
- scanProjects(projects, config, dispatch);
41904
- }, [config]);
41905
- const restartSelection = (0, import_react29.useCallback)(() => {
41906
- if (!multiProjects) return;
41907
- dispatch({ type: "RESTART_SELECTION", projects: multiProjects });
41908
- }, [multiProjects]);
41909
- return {
41910
- state,
41911
- scanSelectedProjects,
41912
- restartSelection: multiProjects ? restartSelection : null
41913
- };
41914
- }
41915
- async function runNpmScan(packages, skippedCount, config, dispatch) {
41916
- try {
41917
- const startMs = Date.now();
41918
- const result = await callAnalyzeAPI(packages, config, (done, total) => {
41919
- const batchStart = Math.max(0, done - 15);
41920
- const currentBatch = packages.slice(batchStart, done).map((p) => p.name);
41921
- dispatch({ type: "SCAN_PROGRESS", done, total, currentBatch });
41922
- });
41923
- dispatch({ type: "SCAN_COMPLETE", result, durationMs: Date.now() - startMs, skippedCount });
41924
- } catch (error) {
41925
- if (error instanceof TrialExhaustedError) {
41926
- dispatch({ type: "TRIAL_EXHAUSTED", scansUsed: error.scansUsed, maxScans: error.maxScans });
41927
- return;
41928
- }
41929
- dispatch({ type: "ERROR", error: error instanceof Error ? error : new Error(String(error)) });
41930
- }
41931
- }
41932
- async function scanProjects(projects, config, dispatch) {
41933
- try {
41934
- const npmProjects = projects.filter((p) => p.ecosystem === "npm");
41935
- const pypiProjects = projects.filter((p) => p.ecosystem === "pypi");
41936
- const fullScanConfig = { ...config, scanAll: true };
41937
- const npmPackages = [];
41938
- const pypiPackages = [];
41939
- const seenNpm = /* @__PURE__ */ new Set();
41940
- const seenPypi = /* @__PURE__ */ new Set();
41941
- for (const proj of npmProjects) {
41942
- try {
41943
- const discovery = discoverChanges(proj.path, fullScanConfig);
41944
- for (const pkg of discovery.packages) {
41945
- const key = `${pkg.name}@${pkg.version}`;
41946
- if (!seenNpm.has(key)) {
41947
- seenNpm.add(key);
41948
- npmPackages.push(pkg);
41949
- }
41950
- }
41951
- } catch {
41952
- }
41953
- }
41954
- for (const proj of pypiProjects) {
41955
- try {
41956
- const packages = parsePythonDepFile(proj.path, proj.depFile);
41957
- for (const pkg of packages) {
41958
- const key = `${pkg.name}@${pkg.version}`;
41959
- if (!seenPypi.has(key)) {
41960
- seenPypi.add(key);
41961
- pypiPackages.push(pkg);
41962
- }
41963
- }
41964
- } catch {
41965
- }
41966
- }
41967
- const discoveredTotal = npmPackages.length + pypiPackages.length;
41968
- if (!config.apiKey) {
41969
- const anonLimit = 50;
41970
- if (npmPackages.length > anonLimit) npmPackages.length = anonLimit;
41971
- const pypiSlots = Math.max(0, anonLimit - npmPackages.length);
41972
- if (pypiPackages.length > pypiSlots) pypiPackages.length = pypiSlots;
41973
- }
41974
- const totalPackages = npmPackages.length + pypiPackages.length;
41975
- if (totalPackages === 0) {
41976
- dispatch({ type: "DISCOVERY_EMPTY", message: "No packages to scan." });
41977
- return;
41978
- }
41979
- const startMs = Date.now();
41980
- const results = [];
41981
- let completed = 0;
41982
- if (npmPackages.length > 0) {
41983
- const npmResult = await callAnalyzeAPI(npmPackages, config, (done, total) => {
41984
- completed = done;
41985
- dispatch({
41986
- type: "SCAN_PROGRESS",
41987
- done: completed,
41988
- total: totalPackages,
41989
- currentBatch: npmPackages.slice(Math.max(0, done - 15), done).map((p) => p.name)
41990
- });
41991
- });
41992
- completed = npmPackages.length;
41993
- results.push(npmResult);
41994
- }
41995
- if (pypiPackages.length > 0) {
41996
- const pypiResult = await callPyPIAnalyzeAPI(pypiPackages, config, (done) => {
41997
- dispatch({
41998
- type: "SCAN_PROGRESS",
41999
- done: completed + done,
42000
- total: totalPackages,
42001
- currentBatch: pypiPackages.slice(Math.max(0, done - 15), done).map((p) => p.name)
42002
- });
42003
- });
42004
- results.push(pypiResult);
42005
- }
42006
- const allPackages = results.flatMap((r) => r.packages);
42007
- const maxScore = Math.max(0, ...allPackages.map((p) => p.score));
42008
- const action = maxScore >= 70 ? "block" : maxScore >= 60 ? "warn" : "pass";
42009
- const safeVersions = {};
42010
- for (const r of results) Object.assign(safeVersions, r.safeVersions);
42011
- const merged = {
42012
- score: maxScore,
42013
- action,
42014
- packages: allPackages,
42015
- safeVersions,
42016
- durationMs: Date.now() - startMs
42017
- };
42018
- dispatch({ type: "SCAN_COMPLETE", result: merged, durationMs: merged.durationMs, skippedCount: 0, discoveredTotal });
42019
- } catch (error) {
42020
- if (error instanceof TrialExhaustedError) {
42021
- dispatch({ type: "TRIAL_EXHAUSTED", scansUsed: error.scansUsed, maxScans: error.maxScans });
42022
- return;
42023
- }
42024
- dispatch({ type: "ERROR", error: error instanceof Error ? error : new Error(String(error)) });
42025
- }
42026
- }
42027
- var import_react29;
42028
- var init_useScan = __esm({
42029
- "src/ui/hooks/useScan.ts"() {
42030
- "use strict";
42031
- import_react29 = __toESM(require_react());
42032
- init_lockfile();
42033
- init_api();
42034
- init_discover();
42035
- init_lockfile();
42036
- }
42037
- });
42038
-
42039
- // src/ui/components/ProgressBar.tsx
42040
- function estimateScanSeconds(packageCount) {
42041
- return Math.ceil(Math.max(5, packageCount * 0.35 - 10));
42042
- }
42043
- function formatTime(seconds) {
42044
- if (seconds < 60) return `${seconds}s`;
42045
- const m = Math.floor(seconds / 60);
42046
- const s = seconds % 60;
42047
- return s > 0 ? `${m}m ${s}s` : `${m}m`;
42048
- }
42049
- var import_react30, import_chalk9, import_jsx_runtime10, ProgressBar;
42050
- var init_ProgressBar = __esm({
42051
- async "src/ui/components/ProgressBar.tsx"() {
42052
- "use strict";
42053
- import_react30 = __toESM(require_react());
42054
- await init_build2();
42055
- await init_build3();
42056
- import_chalk9 = __toESM(require_source());
42057
- import_jsx_runtime10 = __toESM(require_jsx_runtime());
42058
- ProgressBar = ({
42059
- value,
42060
- total,
42061
- label
42062
- }) => {
42063
- const startRef = (0, import_react30.useRef)(Date.now());
42064
- const [elapsed, setElapsed] = (0, import_react30.useState)(0);
42065
- (0, import_react30.useEffect)(() => {
42066
- const timer = setInterval(() => {
42067
- setElapsed(Math.floor((Date.now() - startRef.current) / 1e3));
42068
- }, 1e3);
42069
- return () => clearInterval(timer);
42070
- }, []);
42071
- const termWidth = process.stdout.columns || 80;
42072
- const percent = total > 0 ? Math.round(value / total * 100) : 0;
42073
- const estimate = estimateScanSeconds(total);
42074
- const timeInfo = `${formatTime(elapsed)} / ~${formatTime(estimate)}`;
42075
- const counter = `${value}/${total} ${percent}%`;
42076
- const barWidth = Math.max(10, termWidth - counter.length - 8);
42077
- const fraction = total > 0 ? Math.min(1, value / total) : 0;
42078
- const filled = Math.round(fraction * barWidth);
42079
- const empty = barWidth - filled;
42080
- const filledBar = "\u2501".repeat(filled);
42081
- const emptyBar = "\u2501".repeat(empty);
42082
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 2, children: [
42083
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
42084
- import_chalk9.default.cyan("\u25C6"),
42085
- " ",
42086
- import_chalk9.default.bold("Dependency Guardian")
42087
- ] }),
42088
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: "" }),
42089
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { children: [
42090
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "cyan", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(build_default, { type: "dots" }) }),
42091
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
42092
- " Scanning ",
42093
- total,
42094
- " packages... "
42095
- ] }),
42096
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: timeInfo })
42097
- ] }),
42098
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { children: [
42099
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: " " }),
42100
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "green", children: filledBar }),
42101
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { dimColor: true, children: emptyBar }),
42102
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
42103
- " ",
42104
- counter
42105
- ] })
42106
- ] }),
42107
- label && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, children: [
42108
- " ",
42109
- import_chalk9.default.dim("\u203A"),
42110
- " ",
42111
- label
42112
- ] }) })
42113
- ] });
42114
- };
42115
- }
42116
- });
42117
-
42118
- // src/ui/hooks/useExpandAnimation.ts
42119
- function useExpandAnimation(targetHeight, active, durationMs = 180) {
42120
- const [visibleLines, setVisibleLines] = (0, import_react31.useState)(0);
42121
- const timerRef = (0, import_react31.useRef)(null);
42122
- (0, import_react31.useEffect)(() => {
42123
- if (timerRef.current) {
42124
- clearInterval(timerRef.current);
42125
- timerRef.current = null;
42126
- }
42127
- if (!active || targetHeight <= 0) {
42128
- setVisibleLines(0);
42129
- return;
42130
- }
42131
- const intervalMs = Math.max(16, Math.floor(durationMs / targetHeight));
42132
- let current = 1;
42133
- setVisibleLines(1);
42134
- timerRef.current = setInterval(() => {
42135
- current++;
42136
- if (current >= targetHeight) {
42137
- setVisibleLines(targetHeight);
42138
- if (timerRef.current) clearInterval(timerRef.current);
42139
- timerRef.current = null;
42140
- } else {
42141
- setVisibleLines(current);
42142
- }
42143
- }, intervalMs);
42144
- return () => {
42145
- if (timerRef.current) {
42146
- clearInterval(timerRef.current);
42147
- timerRef.current = null;
42148
- }
42149
- };
42150
- }, [active, targetHeight, durationMs]);
42151
- return {
42152
- visibleLines: active ? visibleLines : 0,
42153
- isAnimating: active && visibleLines > 0 && visibleLines < targetHeight
42154
- };
42155
- }
42156
- var import_react31;
42157
- var init_useExpandAnimation = __esm({
42158
- "src/ui/hooks/useExpandAnimation.ts"() {
42159
- "use strict";
42160
- import_react31 = __toESM(require_react());
42161
- }
42162
- });
42163
-
42164
- // src/ui/hooks/useTerminalSize.ts
42165
- function useTerminalSize() {
42166
- const { stdout } = use_stdout_default();
42167
- const [size, setSize] = (0, import_react32.useState)({
42168
- rows: stdout?.rows ?? process.stdout.rows ?? 24,
42169
- cols: stdout?.columns ?? process.stdout.columns ?? 80
42170
- });
42171
- (0, import_react32.useEffect)(() => {
42172
- const handle = () => {
42173
- const rows = process.stdout.rows ?? 24;
42174
- const cols = process.stdout.columns ?? 80;
42175
- if (process.stdout.isTTY) {
42176
- process.stdout.write("\x1B[2J\x1B[H");
42177
- }
42178
- setSize({ rows, cols });
42179
- };
42180
- process.stdout.setMaxListeners(process.stdout.getMaxListeners() + 1);
42181
- process.stdout.on("resize", handle);
42182
- return () => {
42183
- process.stdout.off("resize", handle);
42184
- process.stdout.setMaxListeners(Math.max(0, process.stdout.getMaxListeners() - 1));
42185
- };
42186
- }, []);
42187
- return size;
42188
- }
42189
- var import_react32;
42190
- var init_useTerminalSize = __esm({
42191
- async "src/ui/hooks/useTerminalSize.ts"() {
42192
- "use strict";
42193
- import_react32 = __toESM(require_react());
42194
- await init_build2();
42195
- }
42196
- });
42197
-
42198
- // src/ui/components/InteractiveResultsView.tsx
42199
- function groupPackages3(packages) {
42200
- const map = /* @__PURE__ */ new Map();
42201
- for (const pkg of packages) {
42202
- const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.id ?? f.category ?? "unknown"}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
42203
- const group = map.get(fingerprint) ?? [];
42204
- group.push(pkg);
42205
- map.set(fingerprint, group);
42206
- }
42207
- return [...map.entries()].map(([fingerprint, pkgs]) => ({ packages: pkgs, key: fingerprint })).sort((a, b) => b.packages[0].score - a.packages[0].score);
42208
- }
42209
- function actionBadge3(score) {
42210
- if (score >= 70)
42211
- return { label: "BLOCK", color: import_chalk10.default.red };
42212
- if (score >= 60)
42213
- return { label: "WARN", color: import_chalk10.default.yellow };
42214
- return { label: "PASS", color: import_chalk10.default.green };
42215
- }
42216
- function truncate3(s, max) {
42217
- return s.length <= max ? s : s.slice(0, max - 1) + "\u2026";
42218
- }
42219
- function pad3(s, len) {
42220
- return s + " ".repeat(Math.max(0, len - s.length));
42221
- }
42222
- function findingsSummaryHeight(group) {
42223
- const rep = group.packages[0];
42224
- const visibleFindings = rep.findings.filter((f) => f.severity > 1 || f.critical);
42225
- let h = visibleFindings.length;
42226
- if (rep.license) h += 1;
42227
- if (visibleFindings.length === 0 && rep.score > 0) {
42228
- h += (rep.reasons ?? []).length;
42229
- h += 1;
42230
- }
42231
- if (group.packages.length > 3) h += 1;
42232
- return h;
42233
- }
42234
- function findingsDetailHeight(group, safeVersions) {
42235
- const rep = group.packages[0];
42236
- const visibleFindings = rep.findings.filter((f) => f.severity > 1 || f.critical).sort((a, b) => b.severity - a.severity);
42237
- let h = 0;
42238
- if (rep.license) h += 1;
42239
- if (group.packages.length > 3) h += 1;
42240
- if (visibleFindings.length === 0 && rep.score > 0) {
42241
- h += (rep.reasons ?? []).length;
42242
- h += 1;
42243
- }
42244
- const hasEvidence = visibleFindings.some((f) => f.evidence && f.evidence.length > 0);
42245
- for (const finding of visibleFindings) {
42246
- h += 1;
42247
- h += 1;
42248
- const evidence = finding.evidence ?? [];
42249
- h += Math.min(evidence.length, EVIDENCE_LIMIT2);
42250
- if (evidence.length > EVIDENCE_LIMIT2) h += 1;
42251
- }
42252
- if (visibleFindings.length > 0 && !hasEvidence) h += 1;
42253
- if (rep.recommendation) h += 1;
42254
- if (safeVersions[rep.name]) h += 1;
42255
- return h;
42256
- }
42257
- function groupRowHeight(group, level, safeVersions) {
42258
- if (level === null) return 1;
42259
- if (level === "summary") return 1 + findingsSummaryHeight(group);
42260
- return 1 + findingsDetailHeight(group, safeVersions);
42261
- }
42262
- function groupNames(group) {
42263
- if (group.packages.length === 1) return group.packages[0].name;
42264
- if (group.packages.length <= 3)
42265
- return group.packages.map((p) => p.name).join(", ");
42266
- return `${group.packages[0].name} + ${group.packages.length - 1} similar`;
42267
- }
42268
- function affectsLine(group) {
42269
- const names = group.packages.map((p) => p.name);
42270
- if (names.length <= 5) return names.join(", ");
42271
- return names.slice(0, 5).join(", ") + ` + ${names.length - 5} more`;
42272
- }
42273
- function buildDetailLines(group, safeVersion, maxWidth) {
42274
- const rep = group.packages[0];
42275
- const visibleFindings = rep.findings.filter((f) => f.severity > 1 || f.critical).sort((a, b) => b.severity - a.severity);
42276
- const lines = [];
42277
- const evidenceWidth = Math.max(30, maxWidth - 12);
42278
- if (group.packages.length > 3) {
42279
- lines.push(
42280
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
42281
- "Affects: ",
42282
- affectsLine(group)
42283
- ] }, "affects")
42284
- );
42285
- lines.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { children: "" }, "affects-gap"));
42286
- }
42287
- if (rep.score > 0) {
42288
- lines.push(
42289
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
42290
- "Score: ",
42291
- rep.score,
42292
- "/100"
42293
- ] }, "score-info")
42294
- );
42295
- }
42296
- if (rep.recommendation) {
42297
- lines.push(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { children: "" }, "rec-gap"));
42298
- lines.push(
42299
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42300
- import_chalk10.default.dim("Rec:"),
42301
- " ",
42302
- import_chalk10.default.cyan(truncate3(rep.recommendation, maxWidth - 8))
42303
- ] }, "recommendation")
42304
- );
42305
- }
42306
- if (safeVersion) {
42307
- lines.push(
42308
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { children: import_chalk10.default.green(`Safe: ${rep.name}@${safeVersion}`) }, "safe")
42309
- );
42310
- }
42311
- return lines;
42312
- }
42313
- function viewReducer(_state, action) {
42314
- switch (action.type) {
42315
- case "MOVE":
42316
- return { ..._state, cursor: action.cursor, viewport: action.viewport };
42317
- case "EXPAND":
42318
- return { ..._state, expandedIndex: action.expandedIndex, expandLevel: action.expandLevel, viewport: action.viewport };
42319
- case "MOVE_EXPAND":
42320
- return { cursor: action.cursor, expandedIndex: action.expandedIndex, expandLevel: action.expandLevel, viewport: action.viewport };
42321
- }
42322
- }
42323
- function licenseLine(rep) {
42324
- const lc = rep.license;
42325
- if (!lc) return null;
42326
- const spdx = lc.spdx ?? lc.raw ?? "";
42327
- const desc = LICENSE_DESCRIPTIONS[lc.riskCategory] ?? "";
42328
- const lcColor = lc.riskCategory === "permissive" ? import_chalk10.default.green : lc.riskCategory === "no-license" || lc.riskCategory === "unlicensed" || lc.riskCategory === "network-copyleft" ? import_chalk10.default.red : import_chalk10.default.yellow;
42329
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42330
- T.branch,
42331
- " ",
42332
- lcColor(spdx),
42333
- " ",
42334
- import_chalk10.default.dim("\u2014"),
42335
- " ",
42336
- import_chalk10.default.dim(desc)
42337
- ] }, "license-info");
42338
- }
42339
- var import_react33, import_chalk10, import_jsx_runtime11, SEVERITY_LABELS2, SEVERITY_COLORS, EVIDENCE_LIMIT2, FIXED_CHROME, DETAIL_PANE_CHROME, InteractiveResultsView, T, LICENSE_DESCRIPTIONS, FindingsSummary;
42340
- var init_InteractiveResultsView = __esm({
42341
- async "src/ui/components/InteractiveResultsView.tsx"() {
42342
- "use strict";
42343
- import_react33 = __toESM(require_react());
42344
- await init_build2();
42345
- import_chalk10 = __toESM(require_source());
42346
- await init_ScoreHeader();
42347
- init_useExpandAnimation();
42348
- await init_useTerminalSize();
42349
- import_jsx_runtime11 = __toESM(require_jsx_runtime());
42350
- SEVERITY_LABELS2 = {
42351
- 5: "CRIT",
42352
- 4: "HIGH",
42353
- 3: "MED",
42354
- 2: "LOW",
42355
- 1: "INFO"
42356
- };
42357
- SEVERITY_COLORS = {
42358
- 5: (s) => import_chalk10.default.red.bold(s),
42359
- 4: (s) => import_chalk10.default.magenta(s),
42360
- 3: (s) => import_chalk10.default.yellow(s),
42361
- 2: (s) => import_chalk10.default.dim(s),
42362
- 1: (s) => import_chalk10.default.gray(s)
42363
- };
42364
- EVIDENCE_LIMIT2 = 2;
42365
- FIXED_CHROME = 21;
42366
- DETAIL_PANE_CHROME = 20;
42367
- InteractiveResultsView = ({
42368
- result,
42369
- config,
42370
- durationMs,
42371
- onExit,
42372
- onBack,
42373
- discoveredTotal
42374
- }) => {
42375
- const flagged = (0, import_react33.useMemo)(
42376
- () => result.packages.filter((p) => p.score > 0),
42377
- [result.packages]
42378
- );
42379
- const clean = (0, import_react33.useMemo)(
42380
- () => result.packages.filter((p) => p.score === 0),
42381
- [result.packages]
42382
- );
42383
- const total = result.packages.length;
42384
- const [searchQuery, setSearchQuery] = (0, import_react33.useState)("");
42385
- const allGroups = (0, import_react33.useMemo)(() => groupPackages3(flagged), [flagged]);
42386
- const allGroupCount = allGroups.length;
42387
- const groups = (0, import_react33.useMemo)(() => {
42388
- if (!searchQuery) return allGroups;
42389
- const q = searchQuery.toLowerCase();
42390
- return allGroups.filter((g) => g.packages.some((p) => p.name.toLowerCase().includes(q)));
42391
- }, [allGroups, searchQuery]);
42392
- const severityCounts = (0, import_react33.useMemo)(() => {
42393
- const counts = {};
42394
- for (const pkg of flagged) {
42395
- const maxSev = pkg.findings.reduce((m, f) => Math.max(m, f.severity), 0);
42396
- if (maxSev >= 2) counts[maxSev] = (counts[maxSev] ?? 0) + 1;
42397
- }
42398
- return counts;
42399
- }, [flagged]);
42400
- const [view, dispatchView] = (0, import_react33.useReducer)(viewReducer, {
42401
- cursor: 0,
42402
- expandLevel: null,
42403
- expandedIndex: null,
42404
- viewport: 0
42405
- });
42406
- const viewRef = (0, import_react33.useRef)(view);
42407
- viewRef.current = view;
42408
- const [detailPane, setDetailPane] = (0, import_react33.useState)(null);
42409
- const detailPaneRef = (0, import_react33.useRef)(detailPane);
42410
- detailPaneRef.current = detailPane;
42411
- const [showHelp, setShowHelp] = (0, import_react33.useState)(false);
42412
- const showHelpRef = (0, import_react33.useRef)(showHelp);
42413
- showHelpRef.current = showHelp;
42414
- const [searchMode, setSearchMode] = (0, import_react33.useState)(false);
42415
- const searchModeRef = (0, import_react33.useRef)(searchMode);
42416
- searchModeRef.current = searchMode;
42417
- const { rows: termRows, cols: termCols } = useTerminalSize();
42418
- const availableRows = Math.max(5, termRows - FIXED_CHROME);
42419
- const innerWidth = Math.max(40, termCols - 6);
42420
- const detailGroupIdx = detailPane?.groupIndex ?? -1;
42421
- const detailLines = (0, import_react33.useMemo)(() => {
42422
- if (detailGroupIdx < 0) return [];
42423
- const group = groups[detailGroupIdx];
42424
- if (!group) return [];
42425
- return buildDetailLines(group, result.safeVersions[group.packages[0].name], innerWidth);
42426
- }, [detailGroupIdx, groups, result.safeVersions, innerWidth]);
42427
- const detailContentRows = Math.max(3, termRows - DETAIL_PANE_CHROME);
42428
- const getLevel = (idx) => {
42429
- return view.expandedIndex === idx ? view.expandLevel : null;
42430
- };
42431
- const expandTargetHeight = (0, import_react33.useMemo)(() => {
42432
- if (view.expandedIndex === null || view.expandLevel === null) return 0;
42433
- const group = groups[view.expandedIndex];
42434
- if (!group) return 0;
42435
- if (view.expandLevel === "summary") return findingsSummaryHeight(group);
42436
- return findingsDetailHeight(group, result.safeVersions);
42437
- }, [view.expandedIndex, view.expandLevel, groups, result.safeVersions]);
42438
- const { visibleLines: animVisibleLines } = useExpandAnimation(
42439
- expandTargetHeight,
42440
- view.expandedIndex !== null
42441
- );
42442
- const animatedGroupHeight = (group, level, idx) => {
42443
- if (level === null) return 1;
42444
- if (idx === view.expandedIndex) return 1 + animVisibleLines;
42445
- return groupRowHeight(group, level, result.safeVersions);
42446
- };
42447
- const visibleEnd = (0, import_react33.useMemo)(() => {
42448
- let consumed = 0;
42449
- let end = view.viewport;
42450
- while (end < groups.length) {
42451
- const level = getLevel(end);
42452
- const h = animatedGroupHeight(groups[end], level, end);
42453
- if (consumed + h > availableRows) break;
42454
- consumed += h;
42455
- end++;
42456
- }
42457
- if (end === view.viewport && groups.length > 0) end = view.viewport + 1;
42458
- return end;
42459
- }, [view.viewport, groups, view.expandedIndex, view.expandLevel, animVisibleLines, availableRows, result.safeVersions]);
42460
- const adjustViewport = (cursor, expIdx, expLvl, currentStart) => {
42461
- if (cursor < currentStart) return cursor;
42462
- const getLvl = (i) => expIdx === i ? expLvl : null;
42463
- let consumed = 0;
42464
- for (let i = currentStart; i <= cursor && i < groups.length; i++) {
42465
- consumed += groupRowHeight(groups[i], getLvl(i), result.safeVersions);
42466
- }
42467
- if (consumed <= availableRows) return currentStart;
42468
- let newStart = currentStart;
42469
- while (newStart < cursor) {
42470
- newStart++;
42471
- consumed = 0;
42472
- for (let i = newStart; i <= cursor; i++) {
42473
- consumed += groupRowHeight(groups[i], getLvl(i), result.safeVersions);
42474
- }
42475
- if (consumed <= availableRows) break;
42476
- }
42477
- return newStart;
42478
- };
42479
- (0, import_react33.useEffect)(() => {
42480
- if (groups.length === 0) return;
42481
- const { cursor, expandedIndex, expandLevel, viewport } = viewRef.current;
42482
- const clamped = Math.min(viewport, Math.max(0, groups.length - 1));
42483
- const newVp = adjustViewport(cursor, expandedIndex, expandLevel, clamped);
42484
- dispatchView({ type: "MOVE", cursor, viewport: newVp });
42485
- }, [availableRows]);
42486
- (0, import_react33.useEffect)(() => {
42487
- const dp = detailPaneRef.current;
42488
- if (dp && detailLines.length > 0) {
42489
- const maxScroll = Math.max(0, detailLines.length - detailContentRows);
42490
- if (dp.scroll > maxScroll) {
42491
- setDetailPane({ groupIndex: dp.groupIndex, scroll: maxScroll });
42492
- }
42493
- }
42494
- }, [detailContentRows, detailLines.length]);
42495
- use_input_default((input, key) => {
42496
- if (groups.length === 0) {
42497
- if (input === "q" || key.return) onExit();
42498
- return;
42499
- }
42500
- if (showHelpRef.current) {
42501
- if (input === "?" || key.escape) setShowHelp(false);
42502
- else if (input === "q") onExit();
42503
- return;
42504
- }
42505
- if (input === "?") {
42506
- setShowHelp(true);
42507
- return;
42508
- }
42509
- if (searchModeRef.current) {
42510
- if (key.escape) {
42511
- setSearchMode(false);
42512
- setSearchQuery("");
42513
- dispatchView({ type: "MOVE", cursor: 0, viewport: 0 });
42514
- } else if (key.return) {
42515
- setSearchMode(false);
42516
- } else if (key.backspace || key.delete) {
42517
- setSearchQuery((prev) => prev.slice(0, -1));
42518
- dispatchView({ type: "MOVE", cursor: 0, viewport: 0 });
42519
- } else if (input && !key.upArrow && !key.downArrow && /^[\x20-\x7e]+$/.test(input)) {
42520
- setSearchQuery((prev) => prev + input);
42521
- dispatchView({ type: "MOVE", cursor: 0, viewport: 0 });
42522
- }
42523
- return;
42524
- }
42525
- const dp = detailPaneRef.current;
42526
- if (dp !== null) {
42527
- const maxScroll = Math.max(0, detailLines.length - detailContentRows);
42528
- if (key.upArrow || input === "k") {
42529
- setDetailPane({ groupIndex: dp.groupIndex, scroll: Math.max(0, dp.scroll - 1) });
42530
- } else if (key.downArrow || input === "j") {
42531
- setDetailPane({ groupIndex: dp.groupIndex, scroll: Math.min(maxScroll, dp.scroll + 1) });
42532
- } else if (input === "g") {
42533
- setDetailPane({ groupIndex: dp.groupIndex, scroll: 0 });
42534
- } else if (input === "G") {
42535
- setDetailPane({ groupIndex: dp.groupIndex, scroll: maxScroll });
42536
- } else if (input === " " || input === "e" || input === "b" || key.escape) {
42537
- setDetailPane(null);
42538
- } else if (input === "q") {
42539
- onExit();
42540
- }
42541
- return;
42542
- }
42543
- if (groups.length === 0) {
42544
- if (input === "q") onExit();
42545
- else if (input === "/") setSearchMode(true);
42546
- return;
42547
- }
42548
- const { cursor, expandLevel: expLvl, expandedIndex: expIdx, viewport: vpStart } = viewRef.current;
42549
- if (key.upArrow || input === "k") {
42550
- const next = Math.max(0, cursor - 1);
42551
- const newVp = adjustViewport(next, expIdx, expLvl, vpStart < next ? vpStart : next);
42552
- dispatchView({ type: "MOVE", cursor: next, viewport: newVp });
42553
- } else if (key.downArrow || input === "j") {
42554
- const next = Math.min(groups.length - 1, cursor + 1);
42555
- const newVp = adjustViewport(next, expIdx, expLvl, vpStart);
42556
- dispatchView({ type: "MOVE", cursor: next, viewport: newVp });
42557
- } else if (input === "g") {
42558
- const newVp = adjustViewport(0, expIdx, expLvl, 0);
42559
- dispatchView({ type: "MOVE", cursor: 0, viewport: newVp });
42560
- } else if (input === "G") {
42561
- const last = groups.length - 1;
42562
- const newVp = adjustViewport(last, expIdx, expLvl, vpStart);
42563
- dispatchView({ type: "MOVE", cursor: last, viewport: newVp });
42564
- } else if (key.pageDown) {
42565
- const next = Math.min(groups.length - 1, cursor + availableRows);
42566
- const newVp = adjustViewport(next, expIdx, expLvl, vpStart);
42567
- dispatchView({ type: "MOVE", cursor: next, viewport: newVp });
42568
- } else if (key.pageUp) {
42569
- const next = Math.max(0, cursor - availableRows);
42570
- const newVp = adjustViewport(next, expIdx, expLvl, next);
42571
- dispatchView({ type: "MOVE", cursor: next, viewport: newVp });
42572
- } else if (key.return) {
42573
- let newExpIdx;
42574
- let newExpLvl;
42575
- if (expIdx === cursor && expLvl !== null) {
42576
- newExpIdx = null;
42577
- newExpLvl = null;
42578
- } else {
42579
- newExpIdx = cursor;
42580
- newExpLvl = "summary";
42581
- }
42582
- const newVp = adjustViewport(cursor, newExpIdx, newExpLvl, vpStart);
42583
- dispatchView({ type: "EXPAND", expandedIndex: newExpIdx, expandLevel: newExpLvl, viewport: newVp });
42584
- } else if (input === " " || input === "e") {
42585
- setDetailPane({ groupIndex: view.cursor, scroll: 0 });
42586
- } else if (input === "/") {
42587
- setSearchMode(true);
42588
- } else if (input === "b" && onBack) {
42589
- onBack();
42590
- } else if (input === "q") {
42591
- onExit();
42592
- }
42593
- });
42594
- const visibleGroups = groups.slice(view.viewport, visibleEnd);
42595
- const aboveCount = view.viewport;
42596
- const belowCount = groups.length - visibleEnd;
42597
- const lcCol = 16;
42598
- const nameCol = Math.max(20, innerWidth - 22 - lcCol);
42599
- const clampedCursor = groups.length > 0 ? Math.min(view.cursor, groups.length - 1) : 0;
42600
- if (showHelp) {
42601
- const isDetail = detailPane !== null;
42602
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { flexDirection: "column", children: [
42603
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
42604
- ScoreHeader,
42605
- {
42606
- score: result.score,
42607
- action: result.action,
42608
- total,
42609
- flagged: flagged.length,
42610
- clean: clean.length,
42611
- severityCounts
42612
- }
42613
- ),
42614
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
42615
- Box_default,
42616
- {
42617
- flexDirection: "column",
42618
- borderStyle: "round",
42619
- borderColor: "cyan",
42620
- paddingLeft: 2,
42621
- paddingRight: 2,
42622
- width: "100%",
42623
- children: [
42624
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { bold: true, children: [
42625
- import_chalk10.default.cyan("\u25C6"),
42626
- " Keyboard Shortcuts"
42627
- ] }),
42628
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { children: "" }),
42629
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { bold: true, children: " Navigation" }),
42630
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42631
- " ",
42632
- import_chalk10.default.cyan("\u2191 k"),
42633
- " ",
42634
- import_chalk10.default.dim("Move up")
42635
- ] }),
42636
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42637
- " ",
42638
- import_chalk10.default.cyan("\u2193 j"),
42639
- " ",
42640
- import_chalk10.default.dim("Move down")
42641
- ] }),
42642
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42643
- " ",
42644
- import_chalk10.default.cyan("g"),
42645
- " ",
42646
- import_chalk10.default.dim("Jump to top")
42647
- ] }),
42648
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42649
- " ",
42650
- import_chalk10.default.cyan("G"),
42651
- " ",
42652
- import_chalk10.default.dim("Jump to bottom")
42653
- ] }),
42654
- !isDetail && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42655
- " ",
42656
- import_chalk10.default.cyan("PgUp"),
42657
- " ",
42658
- import_chalk10.default.dim("Page up")
42659
- ] }),
42660
- !isDetail && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42661
- " ",
42662
- import_chalk10.default.cyan("PgDn"),
42663
- " ",
42664
- import_chalk10.default.dim("Page down")
42665
- ] }),
42666
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { children: "" }),
42667
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { bold: true, children: " Actions" }),
42668
- !isDetail && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42669
- " ",
42670
- import_chalk10.default.cyan("\u23CE"),
42671
- " ",
42672
- import_chalk10.default.dim("Toggle summary")
42673
- ] }),
42674
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42675
- " ",
42676
- import_chalk10.default.cyan("space"),
42677
- " ",
42678
- import_chalk10.default.dim(isDetail ? "Back to list" : "Open detail view")
42679
- ] }),
42680
- !isDetail && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42681
- " ",
42682
- import_chalk10.default.cyan("/"),
42683
- " ",
42684
- import_chalk10.default.dim("Search packages")
42685
- ] }),
42686
- !isDetail && onBack && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42687
- " ",
42688
- import_chalk10.default.cyan("b"),
42689
- " ",
42690
- import_chalk10.default.dim("Back to project selector")
42691
- ] }),
42692
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42693
- " ",
42694
- import_chalk10.default.cyan("q"),
42695
- " ",
42696
- import_chalk10.default.dim("Quit")
42697
- ] }),
42698
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { children: "" }),
42699
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
42700
- " Press ",
42701
- import_chalk10.default.bold.cyan("?"),
42702
- " or ",
42703
- import_chalk10.default.bold.cyan("Esc"),
42704
- " to close"
42705
- ] })
42706
- ]
42707
- }
42708
- )
42709
- ] });
42710
- }
42711
- if (detailPane !== null) {
42712
- const dpGroup = groups[detailPane.groupIndex];
42713
- if (!dpGroup) {
42714
- setDetailPane(null);
42715
- } else {
42716
- const dpRep = dpGroup.packages[0];
42717
- const { color: dpColor } = actionBadge3(dpRep.score);
42718
- const dpScroll = detailPane.scroll;
42719
- const dpAbove = dpScroll;
42720
- const dpBelow = Math.max(0, detailLines.length - dpScroll - detailContentRows);
42721
- const dpVisible = detailLines.slice(dpScroll, dpScroll + detailContentRows);
42722
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { flexDirection: "column", children: [
42723
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
42724
- ScoreHeader,
42725
- {
42726
- score: result.score,
42727
- action: result.action,
42728
- total,
42729
- flagged: flagged.length,
42730
- clean: clean.length,
42731
- severityCounts
42732
- }
42733
- ),
42734
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
42735
- Box_default,
42736
- {
42737
- flexDirection: "column",
42738
- borderStyle: "round",
42739
- borderColor: "gray",
42740
- paddingLeft: 1,
42741
- paddingRight: 1,
42742
- width: "100%",
42743
- children: [
42744
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { justifyContent: "space-between", children: [
42745
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { bold: true, children: [
42746
- groupNames(dpGroup),
42747
- dpRep.license ? import_chalk10.default.dim(" \xB7 ") + (dpRep.license.riskCategory === "permissive" ? import_chalk10.default.green(dpRep.license.spdx ?? dpRep.license.raw ?? "") : dpRep.license.riskCategory === "no-license" || dpRep.license.riskCategory === "network-copyleft" ? import_chalk10.default.red(dpRep.license.spdx ?? dpRep.license.raw ?? "No license") : import_chalk10.default.yellow(dpRep.license.spdx ?? dpRep.license.raw ?? "")) : ""
42748
- ] }),
42749
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { children: dpColor(`score ${dpRep.score}`) })
42750
- ] }),
42751
- dpAbove > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
42752
- import_chalk10.default.cyan(" \u2191"),
42753
- " ",
42754
- dpAbove,
42755
- " more above"
42756
- ] }),
42757
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { flexDirection: "column", marginLeft: 2, children: dpVisible }),
42758
- dpBelow > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
42759
- import_chalk10.default.cyan(" \u2193"),
42760
- " ",
42761
- dpBelow,
42762
- " more below"
42763
- ] })
42764
- ]
42765
- }
42766
- ),
42767
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
42768
- Box_default,
42769
- {
42770
- flexDirection: "column",
42771
- borderStyle: "round",
42772
- borderColor: "gray",
42773
- paddingLeft: 1,
42774
- paddingRight: 1,
42775
- width: "100%",
42776
- children: [
42777
- clean.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42778
- import_chalk10.default.green("\u2713"),
42779
- " ",
42780
- import_chalk10.default.green.bold(String(clean.length)),
42781
- " ",
42782
- import_chalk10.default.dim(`package${clean.length !== 1 ? "s" : ""} passed with score 0`)
42783
- ] }),
42784
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { justifyContent: "space-between", children: [
42785
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
42786
- (durationMs / 1e3).toFixed(1),
42787
- "s"
42788
- ] }),
42789
- result.trialScansRemaining !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, children: "Free tier \xB7 dg login for higher scan limits" })
42790
- ] })
42791
- ]
42792
- }
42793
- ),
42794
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, children: import_chalk10.default.dim("\u2500".repeat(Math.min(60, termCols - 4))) }),
42795
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42796
- " ",
42797
- import_chalk10.default.bold.cyan("\u2191\u2193"),
42798
- " ",
42799
- import_chalk10.default.dim("scroll"),
42800
- " ",
42801
- import_chalk10.default.bold.cyan("space"),
42802
- " ",
42803
- import_chalk10.default.dim("back"),
42804
- " ",
42805
- import_chalk10.default.bold.cyan("q"),
42806
- " ",
42807
- import_chalk10.default.dim("quit")
42808
- ] })
42809
- ] });
42810
- }
42811
- }
42812
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { flexDirection: "column", children: [
42813
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
42814
- ScoreHeader,
42815
- {
42816
- score: result.score,
42817
- action: result.action,
42818
- total,
42819
- flagged: flagged.length,
42820
- clean: clean.length,
42821
- severityCounts
42822
- }
42823
- ),
42824
- groups.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
42825
- Box_default,
42826
- {
42827
- flexDirection: "column",
42828
- borderStyle: "round",
42829
- borderColor: "gray",
42830
- paddingLeft: 1,
42831
- paddingRight: 1,
42832
- width: "100%",
42833
- children: [
42834
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { justifyContent: "space-between", children: [
42835
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { bold: true, children: "Flagged Packages" }),
42836
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, children: searchQuery ? `${groups.length} of ${allGroupCount}` : `${clampedCursor + 1}/${groups.length}` })
42837
- ] }),
42838
- aboveCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
42839
- import_chalk10.default.cyan(" \u2191"),
42840
- " ",
42841
- aboveCount,
42842
- " more above"
42843
- ] }),
42844
- visibleGroups.map((group, visIdx) => {
42845
- const globalIdx = view.viewport + visIdx;
42846
- const isCursor = globalIdx === clampedCursor;
42847
- const level = getLevel(globalIdx);
42848
- const rep = group.packages[0];
42849
- const { label, color } = actionBadge3(rep.score);
42850
- const names = groupNames(group);
42851
- const chevron = level !== null ? "\u25BE" : "\u25B8";
42852
- const scoreStr = String(rep.score);
42853
- const lcInfo = rep.license;
42854
- const lcStr = lcInfo ? truncate3(lcInfo.spdx ?? lcInfo.raw ?? "", lcCol - 2) : "";
42855
- const lcColor = !lcInfo ? import_chalk10.default.dim : lcInfo.riskCategory === "permissive" ? import_chalk10.default.green : lcInfo.riskCategory === "no-license" || lcInfo.riskCategory === "unlicensed" || lcInfo.riskCategory === "network-copyleft" ? import_chalk10.default.red : import_chalk10.default.yellow;
42856
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { flexDirection: "column", children: [
42857
- isCursor ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42858
- import_chalk10.default.cyan("\u258C"),
42859
- ` ${chevron} `,
42860
- color(pad3(label, 6)),
42861
- import_chalk10.default.bold(pad3(truncate3(names, nameCol - 2), nameCol)),
42862
- lcColor(pad3(lcStr, lcCol)),
42863
- color(scoreStr.padStart(3))
42864
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42865
- ` ${import_chalk10.default.dim(chevron)} `,
42866
- color(pad3(label, 6)),
42867
- pad3(truncate3(names, nameCol - 2), nameCol),
42868
- lcColor(pad3(lcStr, lcCol)),
42869
- color(scoreStr.padStart(3))
42870
- ] }),
42871
- level === "summary" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
42872
- FindingsSummary,
42873
- {
42874
- group,
42875
- maxWidth: innerWidth - 8,
42876
- maxLines: globalIdx === view.expandedIndex ? animVisibleLines : void 0
42877
- }
42878
- )
42879
- ] }, group.key);
42880
- }),
42881
- belowCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
42882
- import_chalk10.default.cyan(" \u2193"),
42883
- " ",
42884
- belowCount,
42885
- " more below"
42886
- ] })
42887
- ]
42888
- }
42889
- ),
42890
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
42891
- Box_default,
42892
- {
42893
- flexDirection: "column",
42894
- borderStyle: "round",
42895
- borderColor: "gray",
42896
- paddingLeft: 1,
42897
- paddingRight: 1,
42898
- width: "100%",
42899
- children: [
42900
- clean.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42901
- import_chalk10.default.green("\u2713"),
42902
- " ",
42903
- import_chalk10.default.green.bold(String(clean.length)),
42904
- " ",
42905
- import_chalk10.default.dim(`package${clean.length !== 1 ? "s" : ""} passed with score 0`)
42906
- ] }),
42907
- discoveredTotal !== void 0 && discoveredTotal > total && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
42908
- "Scanned ",
42909
- total,
42910
- " of ",
42911
- discoveredTotal,
42912
- " packages ",
42913
- import_chalk10.default.dim("\u2014 increase --max-packages for full scans")
42914
- ] }),
42915
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Box_default, { justifyContent: "space-between", children: [
42916
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
42917
- (durationMs / 1e3).toFixed(1),
42918
- "s"
42919
- ] }),
42920
- result.trialScansRemaining !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, children: "Free tier \xB7 dg login for higher scan limits" })
42921
- ] })
42922
- ]
42923
- }
42924
- ),
42925
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { dimColor: true, children: import_chalk10.default.dim("\u2500".repeat(Math.min(60, termCols - 4))) }),
42926
- searchMode ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42927
- " ",
42928
- import_chalk10.default.bold.cyan("/"),
42929
- " ",
42930
- searchQuery,
42931
- import_chalk10.default.cyan("\u2588"),
42932
- " ",
42933
- import_chalk10.default.dim("Esc clear")
42934
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
42935
- " ",
42936
- groups.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
42937
- import_chalk10.default.bold.cyan("\u2191\u2193"),
42938
- " ",
42939
- import_chalk10.default.dim("navigate"),
42940
- " ",
42941
- import_chalk10.default.bold.cyan("\u23CE"),
42942
- " ",
42943
- import_chalk10.default.dim("toggle"),
42944
- " ",
42945
- import_chalk10.default.bold.cyan("space"),
42946
- " ",
42947
- import_chalk10.default.dim("detail"),
42948
- " ",
42949
- import_chalk10.default.bold.cyan("/"),
42950
- " ",
42951
- import_chalk10.default.dim("search"),
42952
- " ",
42953
- import_chalk10.default.bold.cyan("?"),
42954
- " ",
42955
- import_chalk10.default.dim("help"),
42956
- " ",
42957
- onBack && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
42958
- import_chalk10.default.bold.cyan("b"),
42959
- " ",
42960
- import_chalk10.default.dim("back"),
42961
- " "
42962
- ] }),
42963
- import_chalk10.default.bold.cyan("q"),
42964
- " ",
42965
- import_chalk10.default.dim("quit")
42966
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
42967
- "Press ",
42968
- import_chalk10.default.bold.cyan("q"),
42969
- " or ",
42970
- import_chalk10.default.bold.cyan("Enter"),
42971
- " ",
42972
- import_chalk10.default.dim("to exit")
42973
- ] })
42974
- ] })
42975
- ] });
42976
- };
42977
- T = {
42978
- branch: import_chalk10.default.dim("\u251C\u2500\u2500"),
42979
- last: import_chalk10.default.dim("\u2514\u2500\u2500"),
42980
- pipe: import_chalk10.default.dim("\u2502"),
42981
- blank: " "
42982
- };
42983
- LICENSE_DESCRIPTIONS = {
42984
- "permissive": "Permissive \u2014 free to use, modify, and distribute. Include the copyright notice.",
42985
- "weak-copyleft": "Weak copyleft \u2014 changes to this library must be shared, but your code stays private.",
42986
- "strong-copyleft": "Strong copyleft \u2014 your entire project must be open-sourced under the same license.",
42987
- "network-copyleft": "Network copyleft \u2014 even SaaS/server use requires releasing your source code.",
42988
- "no-license": "No license found \u2014 legally all rights reserved. Use may require permission from the author.",
42989
- "unlicensed": "Explicitly unlicensed \u2014 proprietary software. A commercial agreement is required.",
42990
- "unknown": "Unrecognized license \u2014 have your legal team review before using.",
42991
- "deferred": "License declared in a file \u2014 check the LICENSE file in the package."
42992
- };
42993
- FindingsSummary = ({ group, maxWidth, maxLines }) => {
42994
- const rep = group.packages[0];
42995
- const visibleFindings = rep.findings.filter((f) => f.severity > 1 || f.critical).sort((a, b) => b.severity - a.severity);
42996
- const hasAffects = group.packages.length > 3;
42997
- const allLines = [];
42998
- const lcLine = licenseLine(rep);
42999
- if (lcLine) allLines.push(lcLine);
43000
- if (visibleFindings.length === 0 && rep.score > 0) {
43001
- const reasons = rep.reasons ?? [];
43002
- for (let i = 0; i < reasons.length; i++) {
43003
- allLines.push(
43004
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
43005
- i < reasons.length - 1 || hasAffects ? T.branch : T.branch,
43006
- " ",
43007
- truncate3(reasons[i], maxWidth - 8)
43008
- ] }, `reason-${i}`)
43009
- );
43010
- }
43011
- }
43012
- for (let idx = 0; idx < visibleFindings.length; idx++) {
43013
- const f = visibleFindings[idx];
43014
- const isLast = !hasAffects && idx === visibleFindings.length - 1;
43015
- const connector = isLast ? T.last : T.branch;
43016
- const sevLabel = SEVERITY_LABELS2[f.severity] ?? "INFO";
43017
- const sevColor = SEVERITY_COLORS[f.severity] ?? SEVERITY_COLORS[1];
43018
- allLines.push(
43019
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { children: [
43020
- connector,
43021
- " ",
43022
- sevColor(pad3(sevLabel, 5)),
43023
- " ",
43024
- import_chalk10.default.dim(f.id ?? f.category ?? "")
43025
- ] }, `${f.id ?? f.category}-${idx}`)
43026
- );
43027
- }
43028
- if (hasAffects) {
43029
- allLines.push(
43030
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Text, { dimColor: true, children: [
43031
- T.last,
43032
- " ",
43033
- truncate3(affectsLine(group), maxWidth - 8)
43034
- ] }, "affects")
43035
- );
43036
- }
43037
- const linesToShow = maxLines !== void 0 ? allLines.slice(0, maxLines) : allLines;
43038
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { flexDirection: "column", marginLeft: 5, children: linesToShow });
43039
- };
43040
- }
43041
- });
43042
-
43043
- // src/ui/components/ProjectSelector.tsx
43044
- var import_react34, import_chalk11, import_jsx_runtime12, ProjectSelector;
43045
- var init_ProjectSelector = __esm({
43046
- async "src/ui/components/ProjectSelector.tsx"() {
43047
- "use strict";
43048
- import_react34 = __toESM(require_react());
43049
- await init_build2();
43050
- import_chalk11 = __toESM(require_source());
43051
- init_sanitize();
43052
- import_jsx_runtime12 = __toESM(require_jsx_runtime());
43053
- ProjectSelector = ({ projects, onConfirm, onCancel }) => {
43054
- const [cursor, setCursor] = (0, import_react34.useState)(0);
43055
- const [selected, setSelected] = (0, import_react34.useState)(() => new Set(projects.map((_, i) => i)));
43056
- use_input_default((input, key) => {
43057
- if (key.upArrow) {
43058
- setCursor((c) => Math.max(0, c - 1));
43059
- } else if (key.downArrow) {
43060
- setCursor((c) => Math.min(projects.length - 1, c + 1));
43061
- } else if (input === " ") {
43062
- setSelected((prev) => {
43063
- const next = new Set(prev);
43064
- if (next.has(cursor)) next.delete(cursor);
43065
- else next.add(cursor);
43066
- return next;
43067
- });
43068
- } else if (input === "a") {
43069
- setSelected((prev) => {
43070
- if (prev.size === projects.length) return /* @__PURE__ */ new Set();
43071
- return new Set(projects.map((_, i) => i));
43072
- });
43073
- } else if (key.return) {
43074
- const picked = projects.filter((_, i) => selected.has(i));
43075
- if (picked.length > 0) onConfirm(picked);
43076
- } else if (input === "q") {
43077
- onCancel();
43078
- }
43079
- });
43080
- const ecosystemLabel = (eco) => eco === "npm" ? import_chalk11.default.magenta("npm") : import_chalk11.default.blue("pip");
43081
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
43082
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { children: [
43083
- import_chalk11.default.cyan("\u25C6"),
43084
- " ",
43085
- import_chalk11.default.bold("Dependency Guardian")
43086
- ] }),
43087
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { children: "" }),
43088
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { bold: true, children: [
43089
- "Found ",
43090
- projects.length,
43091
- " project",
43092
- projects.length !== 1 ? "s" : ""
43093
- ] }),
43094
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { children: "" }),
43095
- projects.map((proj, i) => {
43096
- const isCursor = i === cursor;
43097
- const isSelected = selected.has(i);
43098
- const prefix = isCursor ? import_chalk11.default.cyan("\u258C") : " ";
43099
- const check = isSelected ? import_chalk11.default.green("\u25C9") : import_chalk11.default.dim("\u25CB");
43100
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { children: [
43101
- prefix,
43102
- check,
43103
- " ",
43104
- sanitize(proj.relativePath).padEnd(40),
43105
- " ",
43106
- ecosystemLabel(proj.ecosystem).padEnd(5),
43107
- " ",
43108
- proj.packageCount,
43109
- " packages"
43110
- ] }, i);
43111
- }),
43112
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { children: "" }),
43113
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: selected.size === 0 ? import_chalk11.default.yellow("Select at least 1 project to scan") : `${selected.size} of ${projects.length} selected` }),
43114
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { children: "" }),
43115
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { children: [
43116
- import_chalk11.default.bold.cyan("space"),
43117
- " ",
43118
- import_chalk11.default.dim("toggle"),
43119
- " ",
43120
- import_chalk11.default.bold.cyan("a"),
43121
- " ",
43122
- import_chalk11.default.dim("all"),
43123
- " ",
43124
- import_chalk11.default.bold.hex("#FFD700")("\u23CE"),
43125
- " ",
43126
- import_chalk11.default.bold.hex("#FFD700")("scan"),
43127
- " ",
43128
- import_chalk11.default.bold.cyan("q"),
43129
- " ",
43130
- import_chalk11.default.dim("quit")
43131
- ] })
43132
- ] });
43133
- };
43134
- }
43135
- });
43136
-
43137
- // src/ui/App.tsx
43138
- var App_exports = {};
43139
- __export(App_exports, {
43140
- App: () => App2
43141
- });
43142
- var import_react35, import_jsx_runtime13, App2;
43143
- var init_App2 = __esm({
43144
- async "src/ui/App.tsx"() {
43145
- "use strict";
43146
- import_react35 = __toESM(require_react());
43147
- await init_build2();
43148
- init_useScan();
43149
- await init_Spinner();
43150
- await init_ProgressBar();
43151
- await init_InteractiveResultsView();
43152
- await init_ErrorView();
43153
- await init_ProjectSelector();
43154
- await init_useTerminalSize();
43155
- import_jsx_runtime13 = __toESM(require_jsx_runtime());
43156
- App2 = ({ config }) => {
43157
- const { state, scanSelectedProjects, restartSelection } = useScan(config);
43158
- const { exit } = use_app_default();
43159
- useTerminalSize();
43160
- const prevPhaseRef = (0, import_react35.useRef)(state.phase);
43161
- const altScreenActiveRef = (0, import_react35.useRef)(false);
43162
- (0, import_react35.useEffect)(() => {
43163
- if (!process.stdout.isTTY) return;
43164
- process.stdout.write("\x1B[?1049h");
43165
- process.stdout.write("\x1B[2J\x1B[H");
43166
- process.stdout.write("\x1B[?1003l");
43167
- process.stdout.write("\x1B[?1000l");
43168
- altScreenActiveRef.current = true;
43169
- return () => {
43170
- if (altScreenActiveRef.current) {
43171
- process.stdout.write("\x1B[?1049l");
43172
- altScreenActiveRef.current = false;
43173
- }
43174
- process.stdout.write("\x1B[?25h");
43175
- };
43176
- }, []);
43177
- (0, import_react35.useEffect)(() => {
43178
- if (prevPhaseRef.current !== state.phase && process.stdout.isTTY) {
43179
- process.stdout.write("\x1B[2J\x1B[H");
43180
- }
43181
- prevPhaseRef.current = state.phase;
43182
- }, [state.phase]);
43183
- const leaveAltScreen = (0, import_react35.useCallback)(() => {
43184
- if (altScreenActiveRef.current && process.stdout.isTTY) {
43185
- process.stdout.write("\x1B[?1049l");
43186
- altScreenActiveRef.current = false;
43187
- }
43188
- process.stdout.write("\x1B[?25h");
43189
- }, []);
43190
- const handleResultsExit = (0, import_react35.useCallback)(() => {
43191
- if (state.phase === "results") {
43192
- const { result } = state;
43193
- if (result.action === "block" && config.mode === "block") {
43194
- process.exitCode = 2;
43195
- } else if (result.action === "block" || result.action === "warn") {
43196
- process.exitCode = 1;
43197
- } else {
43198
- process.exitCode = 0;
43199
- }
43200
- }
43201
- leaveAltScreen();
43202
- exit();
43203
- }, [state, config, exit, leaveAltScreen]);
43204
- const exitWithMessage = (0, import_react35.useCallback)((message, exitCode) => {
43205
- process.exitCode = exitCode;
43206
- leaveAltScreen();
43207
- process.stderr.write(message);
43208
- return setTimeout(() => exit(), 0);
43209
- }, [exit, leaveAltScreen]);
43210
- (0, import_react35.useEffect)(() => {
43211
- if (state.phase === "empty") {
43212
- const timer = exitWithMessage(`${state.message}
43213
- `, 0);
43214
- return () => clearTimeout(timer);
43215
- }
43216
- if (state.phase === "error") {
43217
- const timer = exitWithMessage(`Error: ${state.error.message}
43218
- `, 3);
43219
- return () => clearTimeout(timer);
43220
- }
43221
- if (state.phase === "trial_exhausted") {
43222
- let msg = "Free trial scans used up. Run `dg login` to create a free account and continue scanning.\n";
43223
- try {
43224
- const { getStoredApiKey: getStoredApiKey2 } = (init_auth(), __toCommonJS(auth_exports));
43225
- if (getStoredApiKey2()) {
43226
- msg = "Your API key may be invalid or expired. Run `dg logout` then `dg login` to re-authenticate.\n";
43227
- }
43228
- } catch {
43229
- }
43230
- const timer = exitWithMessage(msg, 1);
43231
- return () => clearTimeout(timer);
43232
- }
43233
- }, [state, exitWithMessage]);
43234
- use_input_default((input, key) => {
43235
- if (state.phase === "discovering" || state.phase === "scanning") {
43236
- if (input === "q" || key.escape) {
43237
- process.exitCode = 0;
43238
- leaveAltScreen();
43239
- exit();
43240
- }
43241
- }
43242
- });
43243
- const content = (() => {
43244
- switch (state.phase) {
43245
- case "discovering":
43246
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Spinner2, { label: `Searching for dependencies in ${process.cwd()} ...` });
43247
- case "selecting":
43248
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
43249
- ProjectSelector,
43250
- {
43251
- projects: state.projects,
43252
- onConfirm: scanSelectedProjects,
43253
- onCancel: () => {
43254
- process.exitCode = 0;
43255
- leaveAltScreen();
43256
- exit();
43257
- }
43258
- }
43259
- );
43260
- case "scanning":
43261
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
43262
- ProgressBar,
43263
- {
43264
- value: state.done,
43265
- total: state.total,
43266
- label: state.currentBatch.length > 0 ? state.currentBatch[state.currentBatch.length - 1] : void 0
43267
- }
43268
- );
43269
- case "results":
43270
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
43271
- InteractiveResultsView,
43272
- {
43273
- result: state.result,
43274
- config,
43275
- durationMs: state.durationMs,
43276
- onExit: handleResultsExit,
43277
- onBack: restartSelection ?? void 0,
43278
- discoveredTotal: state.discoveredTotal
43279
- }
43280
- );
43281
- case "empty":
43282
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { dimColor: true, children: state.message });
43283
- case "error":
43284
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ErrorView, { error: state.error });
43285
- case "trial_exhausted": {
43286
- let hasKey = false;
43287
- try {
43288
- const { getStoredApiKey: getStoredApiKey2 } = (init_auth(), __toCommonJS(auth_exports));
43289
- hasKey = !!getStoredApiKey2();
43290
- } catch {
43291
- }
43292
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Box_default, { flexDirection: "column", paddingLeft: 2, children: hasKey ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
43293
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { color: "yellow", bold: true, children: "Your API key may be invalid or expired." }),
43294
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { children: [
43295
- "Run ",
43296
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { color: "cyan", bold: true, children: "dg logout" }),
43297
- " then ",
43298
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
43299
- " to re-authenticate."
43300
- ] })
43301
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
43302
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { color: "yellow", bold: true, children: "Free trial scans used up." }),
43303
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Text, { children: [
43304
- "Run ",
43305
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { color: "cyan", bold: true, children: "dg login" }),
43306
- " to create a free account and continue scanning."
43307
- ] })
43308
- ] }) });
43309
- }
43310
- }
43311
- })();
43312
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Box_default, { flexDirection: "column", children: content });
43313
- };
43314
- }
43315
- });
43316
-
43317
42226
  // src/bin.ts
43318
42227
  init_config();
43319
42228
  init_npm_wrapper();
@@ -43404,33 +42313,33 @@ async function checkForUpdate(currentVersion) {
43404
42313
  return null;
43405
42314
  }
43406
42315
  async function runUpdate(currentVersion) {
43407
- const chalk10 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
43408
- process.stderr.write(chalk10.dim(" Checking for updates...\n"));
42316
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
42317
+ process.stderr.write(chalk8.dim(" Checking for updates...\n"));
43409
42318
  const latest = await fetchLatestVersion();
43410
42319
  if (!latest) {
43411
- process.stderr.write(chalk10.red(" Could not reach npm registry.\n"));
42320
+ process.stderr.write(chalk8.red(" Could not reach npm registry.\n"));
43412
42321
  process.exit(1);
43413
42322
  }
43414
42323
  if (!isNewer(latest, currentVersion)) {
43415
42324
  process.stderr.write(
43416
- chalk10.green(` Already on latest version (${currentVersion}).
42325
+ chalk8.green(` Already on latest version (${currentVersion}).
43417
42326
  `)
43418
42327
  );
43419
42328
  return;
43420
42329
  }
43421
- process.stderr.write(chalk10.dim(` Installing ${PKG_NAME}@${latest}...
42330
+ process.stderr.write(chalk8.dim(` Installing ${PKG_NAME}@${latest}...
43422
42331
  `));
43423
42332
  try {
43424
42333
  execFileSync("npm", ["install", "-g", `${PKG_NAME}@${latest}`], { stdio: "inherit" });
43425
42334
  writeCache({ latest, checkedAt: Date.now() });
43426
42335
  process.stderr.write(
43427
- chalk10.green(`
42336
+ chalk8.green(`
43428
42337
  Updated ${currentVersion} \u2192 ${latest}
43429
42338
  `)
43430
42339
  );
43431
42340
  } catch {
43432
42341
  process.stderr.write(
43433
- chalk10.red(`
42342
+ chalk8.red(`
43434
42343
  Update failed. Try manually: npm i -g ${PKG_NAME}@${latest}
43435
42344
  `)
43436
42345
  );
@@ -43481,9 +42390,9 @@ async function main() {
43481
42390
  if (rawCommand === "login") {
43482
42391
  if (isInteractive) {
43483
42392
  const { render: render3 } = await init_build2().then(() => build_exports);
43484
- const React19 = await Promise.resolve().then(() => __toESM(require_react()));
42393
+ const React16 = await Promise.resolve().then(() => __toESM(require_react()));
43485
42394
  const { LoginApp: LoginApp2 } = await init_LoginApp().then(() => LoginApp_exports);
43486
- const { waitUntilExit } = render3(React19.createElement(LoginApp2));
42395
+ const { waitUntilExit } = render3(React16.createElement(LoginApp2));
43487
42396
  await waitUntilExit();
43488
42397
  } else {
43489
42398
  const { runStaticLogin: runStaticLogin2 } = await Promise.resolve().then(() => (init_static_output(), static_output_exports));
@@ -43493,13 +42402,13 @@ async function main() {
43493
42402
  }
43494
42403
  if (rawCommand === "status") {
43495
42404
  const { getStoredApiKey: getStoredApiKey2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
43496
- const chalk10 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
42405
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
43497
42406
  const apiKey = getStoredApiKey2();
43498
42407
  if (apiKey) {
43499
- process.stderr.write(chalk10.green(` Authenticated`) + chalk10.dim(` (key: ${apiKey.slice(0, 12)}...)
42408
+ process.stderr.write(chalk8.green(` Authenticated`) + chalk8.dim(` (key: ${apiKey.slice(0, 12)}...)
43500
42409
  `));
43501
42410
  } else {
43502
- process.stderr.write(chalk10.yellow(` Not authenticated.`) + chalk10.dim(` Run \`dg login\` to sign in.
42411
+ process.stderr.write(chalk8.yellow(` Not authenticated.`) + chalk8.dim(` Run \`dg login\` to sign in.
43503
42412
  `));
43504
42413
  }
43505
42414
  return;
@@ -43515,7 +42424,7 @@ async function main() {
43515
42424
  }
43516
42425
  if (rawCommand === "logout") {
43517
42426
  const { getStoredApiKey: getStoredApiKey2, clearCredentials: clearCredentials2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
43518
- const chalk10 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
42427
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
43519
42428
  const apiKey = getStoredApiKey2();
43520
42429
  if (apiKey) {
43521
42430
  try {
@@ -43528,18 +42437,18 @@ async function main() {
43528
42437
  }
43529
42438
  }
43530
42439
  clearCredentials2();
43531
- process.stderr.write(chalk10.green(" Logged out.\n"));
42440
+ process.stderr.write(chalk8.green(" Logged out.\n"));
43532
42441
  return;
43533
42442
  }
43534
42443
  const KNOWN_COMMANDS = ["scan", "npm", "pip", "wrap", "login", "logout", "status", "hook", "update"];
43535
42444
  if (rawCommand && !rawCommand.startsWith("-") && !KNOWN_COMMANDS.includes(rawCommand)) {
43536
- const chalk10 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
42445
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
43537
42446
  const best = closestCommand(rawCommand, KNOWN_COMMANDS);
43538
42447
  const hint = best ? ` Did you mean '${best}'?` : "";
43539
42448
  process.stderr.write(`
43540
- ${chalk10.bold.red("Error:")} Unknown command '${rawCommand}'.${hint}
42449
+ ${chalk8.bold.red("Error:")} Unknown command '${rawCommand}'.${hint}
43541
42450
  `);
43542
- process.stderr.write(chalk10.dim(` Run 'dg --help' for available commands.
42451
+ process.stderr.write(chalk8.dim(` Run 'dg --help' for available commands.
43543
42452
 
43544
42453
  `));
43545
42454
  process.exit(1);
@@ -43547,54 +42456,50 @@ async function main() {
43547
42456
  const strictFlags = rawCommand !== "npm" && rawCommand !== "pip";
43548
42457
  const config = parseConfig(process.argv, strictFlags);
43549
42458
  const updatePromise = checkForUpdate(CLI_VERSION).catch(() => null);
42459
+ if (rawCommand !== "npm" && rawCommand !== "pip") {
42460
+ const { runStatic: runStatic2 } = await Promise.resolve().then(() => (init_static_output(), static_output_exports));
42461
+ await runStatic2(config);
42462
+ const updateMsg2 = await updatePromise;
42463
+ if (updateMsg2) {
42464
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
42465
+ process.stderr.write(chalk8.dim(updateMsg2));
42466
+ }
42467
+ return;
42468
+ }
43550
42469
  if (config.json || !isInteractive) {
43551
42470
  if (rawCommand === "npm") {
43552
42471
  const { runStaticNpm: runStaticNpm2 } = await Promise.resolve().then(() => (init_static_output(), static_output_exports));
43553
42472
  await runStaticNpm2(process.argv.slice(3), config);
43554
- } else if (rawCommand === "pip") {
42473
+ } else {
43555
42474
  const { runStaticPip: runStaticPip2 } = await Promise.resolve().then(() => (init_static_output(), static_output_exports));
43556
42475
  await runStaticPip2(process.argv.slice(3), config);
43557
- } else {
43558
- const { runStatic: runStatic2 } = await Promise.resolve().then(() => (init_static_output(), static_output_exports));
43559
- await runStatic2(config);
43560
42476
  }
43561
42477
  const updateMsg2 = await updatePromise;
43562
42478
  if (updateMsg2) {
43563
- const chalk10 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
43564
- process.stderr.write(chalk10.dim(updateMsg2));
42479
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
42480
+ process.stderr.write(chalk8.dim(updateMsg2));
43565
42481
  }
43566
42482
  return;
43567
42483
  }
43568
42484
  const { render: render2 } = await init_build2().then(() => build_exports);
43569
- const React18 = await Promise.resolve().then(() => __toESM(require_react()));
42485
+ const React15 = await Promise.resolve().then(() => __toESM(require_react()));
43570
42486
  if (rawCommand === "npm") {
43571
42487
  const { NpmWrapperApp: NpmWrapperApp2 } = await init_NpmWrapperApp().then(() => NpmWrapperApp_exports);
43572
42488
  const { waitUntilExit } = render2(
43573
- React18.createElement(NpmWrapperApp2, { config, npmArgs: process.argv.slice(3) })
43574
- );
43575
- await waitUntilExit();
43576
- } else if (rawCommand === "pip") {
43577
- const { PipWrapperApp: PipWrapperApp2 } = await init_PipWrapperApp().then(() => PipWrapperApp_exports);
43578
- const { waitUntilExit } = render2(
43579
- React18.createElement(PipWrapperApp2, { config, pipArgs: process.argv.slice(3) })
42489
+ React15.createElement(NpmWrapperApp2, { config, npmArgs: process.argv.slice(3) })
43580
42490
  );
43581
42491
  await waitUntilExit();
43582
42492
  } else {
43583
- if (config.mode === "off") {
43584
- const chalk10 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
43585
- process.stderr.write(chalk10.dim(" Dependency Guardian: mode is off \u2014 skipping.\n"));
43586
- process.exit(0);
43587
- }
43588
- const { App: App3 } = await init_App2().then(() => App_exports);
42493
+ const { PipWrapperApp: PipWrapperApp2 } = await init_PipWrapperApp().then(() => PipWrapperApp_exports);
43589
42494
  const { waitUntilExit } = render2(
43590
- React18.createElement(App3, { config })
42495
+ React15.createElement(PipWrapperApp2, { config, pipArgs: process.argv.slice(3) })
43591
42496
  );
43592
42497
  await waitUntilExit();
43593
42498
  }
43594
42499
  const updateMsg = await updatePromise;
43595
42500
  if (updateMsg) {
43596
- const chalk10 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
43597
- process.stderr.write(chalk10.dim(updateMsg));
42501
+ const chalk8 = (await Promise.resolve().then(() => __toESM(require_source()))).default;
42502
+ process.stderr.write(chalk8.dim(updateMsg));
43598
42503
  }
43599
42504
  }
43600
42505
  main().catch((err) => {
@@ -43606,9 +42511,9 @@ main().catch((err) => {
43606
42511
  }, null, 2) + "\n");
43607
42512
  } else {
43608
42513
  try {
43609
- const chalk10 = require_source();
42514
+ const chalk8 = require_source();
43610
42515
  process.stderr.write(`
43611
- ${chalk10.bold.red("Error:")} ${err.message}
42516
+ ${chalk8.bold.red("Error:")} ${err.message}
43612
42517
 
43613
42518
  `);
43614
42519
  } catch {