@westbayberry/dg 1.0.16 → 1.0.17

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 +40 -97
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -114,6 +114,12 @@ function parseConfig(argv) {
114
114
  const noConfig = values["no-config"];
115
115
  const dgrc = noConfig ? {} : loadDgrc();
116
116
  const apiKey = dgrc.apiKey ?? "";
117
+ if (!apiKey) {
118
+ process.stderr.write(
119
+ "Error: Not logged in. Run `dg login` to authenticate.\n"
120
+ );
121
+ process.exit(1);
122
+ }
117
123
  const modeRaw = values.mode ?? process.env.DG_MODE ?? dgrc.mode ?? "warn";
118
124
  if (!["block", "warn", "off"].includes(modeRaw)) {
119
125
  process.stderr.write(
@@ -125,10 +131,7 @@ function parseConfig(argv) {
125
131
  const allowlistRaw = values.allowlist ?? process.env.DG_ALLOWLIST ?? "";
126
132
  const blockThreshold = Number(values["block-threshold"] ?? dgrc.blockThreshold ?? "70");
127
133
  const warnThreshold = Number(values["warn-threshold"] ?? dgrc.warnThreshold ?? "60");
128
- let maxPackages = Number(values["max-packages"] ?? dgrc.maxPackages ?? "200");
129
- if (!apiKey) {
130
- maxPackages = Math.min(maxPackages, 50);
131
- }
134
+ const maxPackages = Number(values["max-packages"] ?? dgrc.maxPackages ?? "200");
132
135
  const debug = values.debug || process.env.DG_DEBUG === "1";
133
136
  if (isNaN(blockThreshold) || blockThreshold < 0 || blockThreshold > 100) {
134
137
  process.stderr.write("Error: --block-threshold must be a number between 0 and 100\n");
@@ -38914,35 +38917,15 @@ async function callAnalyzeAPI(packages, config, onProgress) {
38914
38917
  for (let i = 0; i < packages.length; i += BATCH_SIZE) {
38915
38918
  batches.push(packages.slice(i, i + BATCH_SIZE));
38916
38919
  }
38917
- const MAX_CONCURRENT_BATCHES = 2;
38918
- const results = new Array(batches.length);
38920
+ const results = [];
38919
38921
  let completed = 0;
38920
- let nextIdx = 0;
38921
- async function runBatch(idx) {
38922
- const result = await callBatchWithRetry(batches[idx], config);
38923
- results[idx] = result;
38924
- completed += batches[idx].length;
38922
+ for (const batch of batches) {
38923
+ const result = await callBatchWithRetry(batch, config);
38924
+ completed += batch.length;
38925
38925
  if (onProgress) {
38926
- onProgress(completed, packages.length, batches[idx].map((p) => p.name));
38927
- }
38928
- }
38929
- const inFlight = /* @__PURE__ */ new Set();
38930
- while (nextIdx < batches.length && inFlight.size < MAX_CONCURRENT_BATCHES) {
38931
- const idx = nextIdx++;
38932
- const p = runBatch(idx).then(() => {
38933
- inFlight.delete(p);
38934
- });
38935
- inFlight.add(p);
38936
- }
38937
- while (inFlight.size > 0) {
38938
- await Promise.race(inFlight);
38939
- while (nextIdx < batches.length && inFlight.size < MAX_CONCURRENT_BATCHES) {
38940
- const idx = nextIdx++;
38941
- const p = runBatch(idx).then(() => {
38942
- inFlight.delete(p);
38943
- });
38944
- inFlight.add(p);
38926
+ onProgress(completed, packages.length, batch.map((p) => p.name));
38945
38927
  }
38928
+ results.push(result);
38946
38929
  }
38947
38930
  return mergeResponses(results, config);
38948
38931
  }
@@ -39001,16 +38984,13 @@ async function callAnalyzeBatch(packages, config) {
39001
38984
  const timeoutId = setTimeout(() => controller.abort(), 12e4);
39002
38985
  let response;
39003
38986
  try {
39004
- const headers = {
39005
- "Content-Type": "application/json",
39006
- "User-Agent": "dependency-guardian-cli/1.0.0"
39007
- };
39008
- if (config.apiKey) {
39009
- headers["Authorization"] = `Bearer ${config.apiKey}`;
39010
- }
39011
38987
  response = await fetch(url, {
39012
38988
  method: "POST",
39013
- headers,
38989
+ headers: {
38990
+ "Content-Type": "application/json",
38991
+ Authorization: `Bearer ${config.apiKey}`,
38992
+ "User-Agent": "dependency-guardian-cli/1.0.0"
38993
+ },
39014
38994
  body: JSON.stringify(payload),
39015
38995
  signal: controller.signal
39016
38996
  });
@@ -39032,14 +39012,6 @@ async function callAnalyzeBatch(packages, config) {
39032
39012
  );
39033
39013
  }
39034
39014
  if (response.status === 429) {
39035
- const body = await response.json().catch(() => ({}));
39036
- if (body.anonymous) {
39037
- throw new APIError(
39038
- "Anonymous scan limit reached. Run `dg login` for 200 free scans/month.",
39039
- 429,
39040
- ""
39041
- );
39042
- }
39043
39015
  throw new APIError(
39044
39016
  "Rate limit exceeded. Upgrade your plan at https://westbayberry.com/pricing",
39045
39017
  429,
@@ -39092,16 +39064,13 @@ async function callPyPIBatch(packages, config) {
39092
39064
  const timeoutId = setTimeout(() => controller.abort(), 12e4);
39093
39065
  let response;
39094
39066
  try {
39095
- const headers = {
39096
- "Content-Type": "application/json",
39097
- "User-Agent": "dependency-guardian-cli/1.0.0"
39098
- };
39099
- if (config.apiKey) {
39100
- headers["Authorization"] = `Bearer ${config.apiKey}`;
39101
- }
39102
39067
  response = await fetch(url, {
39103
39068
  method: "POST",
39104
- headers,
39069
+ headers: {
39070
+ "Content-Type": "application/json",
39071
+ Authorization: `Bearer ${config.apiKey}`,
39072
+ "User-Agent": "dependency-guardian-cli/1.0.0"
39073
+ },
39105
39074
  body: JSON.stringify(payload),
39106
39075
  signal: controller.signal
39107
39076
  });
@@ -39123,14 +39092,6 @@ async function callPyPIBatch(packages, config) {
39123
39092
  );
39124
39093
  }
39125
39094
  if (response.status === 429) {
39126
- const body = await response.json().catch(() => ({}));
39127
- if (body.anonymous) {
39128
- throw new APIError(
39129
- "Anonymous scan limit reached. Run `dg login` for 200 free scans/month.",
39130
- 429,
39131
- ""
39132
- );
39133
- }
39134
39095
  throw new APIError(
39135
39096
  "Rate limit exceeded. Upgrade your plan at https://westbayberry.com/pricing",
39136
39097
  429,
@@ -39155,7 +39116,7 @@ var init_api = __esm({
39155
39116
  this.name = "APIError";
39156
39117
  }
39157
39118
  };
39158
- BATCH_SIZE = 200;
39119
+ BATCH_SIZE = 15;
39159
39120
  MAX_RETRIES = 2;
39160
39121
  RETRY_DELAY_MS = 5e3;
39161
39122
  }
@@ -39794,7 +39755,7 @@ function truncate(s, max) {
39794
39755
  function groupPackages(packages) {
39795
39756
  const map = /* @__PURE__ */ new Map();
39796
39757
  for (const pkg of packages) {
39797
- const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.category}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
39758
+ const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.id}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
39798
39759
  const group = map.get(fingerprint) ?? [];
39799
39760
  group.push(pkg);
39800
39761
  map.set(fingerprint, group);
@@ -39876,7 +39837,7 @@ function renderResultStatic(result, config) {
39876
39837
  const sevLabel = SEVERITY_LABELS[finding.severity] ?? "INFO";
39877
39838
  const colorFn = severityColor(finding.severity);
39878
39839
  lines.push(
39879
- ` ${colorFn(pad(sevLabel, 10))}${finding.category} \u2014 ${finding.title}`
39840
+ ` ${colorFn(pad(sevLabel, 10))}${finding.id} \u2014 ${finding.title}`
39880
39841
  );
39881
39842
  const evidenceLimit = 3;
39882
39843
  for (let i = 0; i < Math.min(finding.evidence.length, evidenceLimit); i++) {
@@ -39983,11 +39944,6 @@ async function runStatic(config) {
39983
39944
  );
39984
39945
  const output = renderResultStatic(result, config);
39985
39946
  process.stdout.write(output + "\n");
39986
- if (!config.apiKey && !config.json) {
39987
- process.stderr.write(
39988
- "\n" + import_chalk4.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n") + import_chalk4.default.cyan(" Want this on every PR? ") + "Run " + import_chalk4.default.white("dg login") + import_chalk4.default.dim(" \u2192 free tier, 200 scans/month\n") + import_chalk4.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n")
39989
- );
39990
- }
39991
39947
  if (result.action === "block" && config.mode === "block") {
39992
39948
  process.exit(2);
39993
39949
  } else if (result.action === "block" || result.action === "warn") {
@@ -40106,11 +40062,6 @@ async function scanAndInstallStatic(resolved, parsed, config) {
40106
40062
  }
40107
40063
  const output = renderResultStatic(result, config);
40108
40064
  process.stdout.write(output + "\n");
40109
- if (!config.apiKey) {
40110
- process.stderr.write(
40111
- "\n" + import_chalk4.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n") + import_chalk4.default.cyan(" Want this on every PR? ") + "Run " + import_chalk4.default.white("dg login") + import_chalk4.default.dim(" \u2192 free tier, 200 scans/month\n") + import_chalk4.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n")
40112
- );
40113
- }
40114
40065
  if (result.action === "warn") {
40115
40066
  process.stderr.write(
40116
40067
  import_chalk4.default.yellow(" Warnings detected. Proceeding with install.\n\n")
@@ -40651,7 +40602,7 @@ var init_DurationLine = __esm({
40651
40602
  function groupPackages2(packages) {
40652
40603
  const map = /* @__PURE__ */ new Map();
40653
40604
  for (const pkg of packages) {
40654
- const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.category}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
40605
+ const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.id}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
40655
40606
  const group = map.get(fingerprint) ?? [];
40656
40607
  group.push(pkg);
40657
40608
  map.set(fingerprint, group);
@@ -40771,7 +40722,7 @@ var init_ResultsView = __esm({
40771
40722
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
40772
40723
  " ",
40773
40724
  colorFn(pad2(sevLabel, 10)),
40774
- finding.category,
40725
+ finding.id,
40775
40726
  " ",
40776
40727
  "\u2014",
40777
40728
  " ",
@@ -40786,7 +40737,7 @@ var init_ResultsView = __esm({
40786
40737
  import_chalk6.default.dim(`... and ${overflow} more`)
40787
40738
  ] }),
40788
40739
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: " " })
40789
- ] }, `${finding.category}-${idx}`);
40740
+ ] }, `${finding.id}-${idx}`);
40790
40741
  }),
40791
40742
  safeVersion && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
40792
40743
  " ",
@@ -41288,7 +41239,7 @@ var init_useTerminalSize = __esm({
41288
41239
  function groupPackages3(packages) {
41289
41240
  const map = /* @__PURE__ */ new Map();
41290
41241
  for (const pkg of packages) {
41291
- const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.category}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
41242
+ const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.id}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
41292
41243
  const group = map.get(fingerprint) ?? [];
41293
41244
  group.push(pkg);
41294
41245
  map.set(fingerprint, group);
@@ -41407,8 +41358,7 @@ var init_InteractiveResultsView = __esm({
41407
41358
  const viewRef = (0, import_react30.useRef)(view);
41408
41359
  viewRef.current = view;
41409
41360
  const { rows: termRows, cols: termCols } = useTerminalSize();
41410
- const chromeHeight = FIXED_CHROME + (config.apiKey ? 0 : 2);
41411
- const availableRows = Math.max(5, termRows - chromeHeight);
41361
+ const availableRows = Math.max(5, termRows - FIXED_CHROME);
41412
41362
  const innerWidth = Math.max(40, termCols - 6);
41413
41363
  const getLevel = (idx) => {
41414
41364
  return view.expandedIndex === idx ? view.expandLevel : null;
@@ -41496,9 +41446,6 @@ var init_InteractiveResultsView = __esm({
41496
41446
  dispatchView({ type: "EXPAND", expandedIndex: newExpIdx, expandLevel: newExpLvl, viewport: newVp });
41497
41447
  } else if (input === "e") {
41498
41448
  if (expIdx === cursor && expLvl === "detail") {
41499
- const newVp = adjustViewport(cursor, cursor, "summary", vpStart);
41500
- dispatchView({ type: "EXPAND", expandedIndex: cursor, expandLevel: "summary", viewport: newVp });
41501
- } else if (expIdx === cursor && expLvl === "summary") {
41502
41449
  const newVp = adjustViewport(cursor, null, null, vpStart);
41503
41450
  dispatchView({ type: "EXPAND", expandedIndex: null, expandLevel: null, viewport: newVp });
41504
41451
  } else {
@@ -41620,12 +41567,6 @@ var init_InteractiveResultsView = __esm({
41620
41567
  ]
41621
41568
  }
41622
41569
  ),
41623
- !config.apiKey && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { paddingLeft: 1, paddingRight: 1, width: "100%", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
41624
- import_chalk10.default.cyan("Want this on every PR?"),
41625
- " Run ",
41626
- import_chalk10.default.white("dg login"),
41627
- import_chalk10.default.dim(" \u2192 free tier, 200 scans/month")
41628
- ] }) }),
41629
41570
  /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, children: [
41630
41571
  " ",
41631
41572
  groups.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
@@ -41678,8 +41619,8 @@ var init_InteractiveResultsView = __esm({
41678
41619
  " ",
41679
41620
  sevColor(pad3(sevLabel, 4)),
41680
41621
  " ",
41681
- import_chalk10.default.dim(f.category)
41682
- ] }, `${f.category}-${idx}`)
41622
+ import_chalk10.default.dim(f.id)
41623
+ ] }, `${f.id}-${idx}`)
41683
41624
  );
41684
41625
  }
41685
41626
  if (hasAffects) {
@@ -41717,15 +41658,15 @@ var init_InteractiveResultsView = __esm({
41717
41658
  " ",
41718
41659
  sevColor(pad3(sevLabel, 4)),
41719
41660
  " ",
41720
- import_chalk10.default.bold(finding.category)
41721
- ] }, `${finding.category}-${idx}-badge`)
41661
+ import_chalk10.default.bold(finding.id)
41662
+ ] }, `${finding.id}-${idx}-badge`)
41722
41663
  );
41723
41664
  allLines.push(
41724
41665
  /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, children: [
41725
41666
  continuation,
41726
41667
  " ",
41727
41668
  finding.title
41728
- ] }, `${finding.category}-${idx}-title`)
41669
+ ] }, `${finding.id}-${idx}-title`)
41729
41670
  );
41730
41671
  for (let i = 0; i < evidenceSlice.length; i++) {
41731
41672
  allLines.push(
@@ -41735,7 +41676,7 @@ var init_InteractiveResultsView = __esm({
41735
41676
  import_chalk10.default.dim("\u203A"),
41736
41677
  " ",
41737
41678
  truncate3(evidenceSlice[i], evidenceWidth)
41738
- ] }, `${finding.category}-${idx}-ev-${i}`)
41679
+ ] }, `${finding.id}-${idx}-ev-${i}`)
41739
41680
  );
41740
41681
  }
41741
41682
  if (overflow > 0) {
@@ -41744,7 +41685,7 @@ var init_InteractiveResultsView = __esm({
41744
41685
  continuation,
41745
41686
  " ",
41746
41687
  import_chalk10.default.dim(`+${overflow} more`)
41747
- ] }, `${finding.category}-${idx}-overflow`)
41688
+ ] }, `${finding.id}-${idx}-overflow`)
41748
41689
  );
41749
41690
  }
41750
41691
  }
@@ -41858,8 +41799,10 @@ var init_App2 = __esm({
41858
41799
  (0, import_react32.useEffect)(() => {
41859
41800
  if (!process.stdout.isTTY) return;
41860
41801
  process.stdout.write("\x1B[?1049h");
41802
+ process.stdout.write("\x1B[?1003h");
41861
41803
  process.stdout.write("\x1B[2J\x1B[H");
41862
41804
  return () => {
41805
+ process.stdout.write("\x1B[?1003l");
41863
41806
  process.stdout.write("\x1B[?1049l");
41864
41807
  process.stdout.write("\x1B[?25h");
41865
41808
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@westbayberry/dg",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "description": "Supply chain security scanner for npm and Python dependencies — detects malicious packages, typosquatting, dependency confusion, and 26+ attack patterns",
5
5
  "bin": {
6
6
  "dependency-guardian": "dist/index.mjs",