@westbayberry/dg 1.0.14 → 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 +144 -99
  2. package/package.json +5 -1
package/dist/index.mjs CHANGED
@@ -3296,7 +3296,7 @@ var require_react_development = __commonJS({
3296
3296
  }
3297
3297
  return dispatcher.useContext(Context);
3298
3298
  }
3299
- function useState6(initialState) {
3299
+ function useState7(initialState) {
3300
3300
  var dispatcher = resolveDispatcher();
3301
3301
  return dispatcher.useState(initialState);
3302
3302
  }
@@ -3304,7 +3304,7 @@ var require_react_development = __commonJS({
3304
3304
  var dispatcher = resolveDispatcher();
3305
3305
  return dispatcher.useReducer(reducer4, initialArg, init);
3306
3306
  }
3307
- function useRef6(initialValue) {
3307
+ function useRef7(initialValue) {
3308
3308
  var dispatcher = resolveDispatcher();
3309
3309
  return dispatcher.useRef(initialValue);
3310
3310
  }
@@ -4098,8 +4098,8 @@ var require_react_development = __commonJS({
4098
4098
  exports.useLayoutEffect = useLayoutEffect2;
4099
4099
  exports.useMemo = useMemo4;
4100
4100
  exports.useReducer = useReducer5;
4101
- exports.useRef = useRef6;
4102
- exports.useState = useState6;
4101
+ exports.useRef = useRef7;
4102
+ exports.useState = useState7;
4103
4103
  exports.useSyncExternalStore = useSyncExternalStore;
4104
4104
  exports.useTransition = useTransition;
4105
4105
  exports.version = ReactVersion;
@@ -40990,14 +40990,14 @@ function useScan(config) {
40990
40990
  started.current = true;
40991
40991
  const projects = discoverProjects(process.cwd());
40992
40992
  if (projects.length > 1) setMultiProjects(projects);
40993
+ if (projects.length > 1) {
40994
+ dispatch({ type: "PROJECTS_FOUND", projects });
40995
+ return;
40996
+ }
40993
40997
  try {
40994
40998
  const discovery = discoverChanges(process.cwd(), config);
40995
40999
  const packages = discovery.packages.filter((p) => !config.allowlist.includes(p.name));
40996
41000
  if (packages.length === 0) {
40997
- if (discovery.packages.length === 0 && projects.length > 0) {
40998
- dispatch({ type: "PROJECTS_FOUND", projects });
40999
- return;
41000
- }
41001
41001
  const message = discovery.packages.length === 0 ? "No package changes detected." : "All changed packages are allowlisted.";
41002
41002
  dispatch({ type: "DISCOVERY_EMPTY", message });
41003
41003
  return;
@@ -41009,12 +41009,8 @@ function useScan(config) {
41009
41009
  dispatch({ type: "DISCOVERY_EMPTY", message: "No dependency files found." });
41010
41010
  return;
41011
41011
  }
41012
- if (projects.length === 1) {
41013
- dispatch({ type: "DISCOVERY_COMPLETE", packages: [], skippedCount: 0 });
41014
- scanProjects(projects, config, dispatch);
41015
- return;
41016
- }
41017
- dispatch({ type: "PROJECTS_FOUND", projects });
41012
+ dispatch({ type: "DISCOVERY_COMPLETE", packages: [], skippedCount: 0 });
41013
+ scanProjects(projects, config, dispatch);
41018
41014
  }
41019
41015
  }, [config]);
41020
41016
  const scanSelectedProjects = (0, import_react27.useCallback)((projects) => {
@@ -41205,6 +41201,40 @@ var init_useExpandAnimation = __esm({
41205
41201
  }
41206
41202
  });
41207
41203
 
41204
+ // src/ui/hooks/useTerminalSize.ts
41205
+ function useTerminalSize() {
41206
+ const { stdout } = use_stdout_default();
41207
+ const [size, setSize] = (0, import_react29.useState)({
41208
+ rows: stdout?.rows ?? process.stdout.rows ?? 24,
41209
+ cols: stdout?.columns ?? process.stdout.columns ?? 80
41210
+ });
41211
+ (0, import_react29.useEffect)(() => {
41212
+ const handle = () => {
41213
+ const rows = process.stdout.rows ?? 24;
41214
+ const cols = process.stdout.columns ?? 80;
41215
+ if (process.stdout.isTTY) {
41216
+ process.stdout.write("\x1B[2J\x1B[H");
41217
+ }
41218
+ setSize({ rows, cols });
41219
+ };
41220
+ process.stdout.setMaxListeners(process.stdout.getMaxListeners() + 1);
41221
+ process.stdout.on("resize", handle);
41222
+ return () => {
41223
+ process.stdout.off("resize", handle);
41224
+ process.stdout.setMaxListeners(Math.max(0, process.stdout.getMaxListeners() - 1));
41225
+ };
41226
+ }, []);
41227
+ return size;
41228
+ }
41229
+ var import_react29;
41230
+ var init_useTerminalSize = __esm({
41231
+ async "src/ui/hooks/useTerminalSize.ts"() {
41232
+ "use strict";
41233
+ import_react29 = __toESM(require_react());
41234
+ await init_build2();
41235
+ }
41236
+ });
41237
+
41208
41238
  // src/ui/components/InteractiveResultsView.tsx
41209
41239
  function groupPackages3(packages) {
41210
41240
  const map = /* @__PURE__ */ new Map();
@@ -41275,15 +41305,16 @@ function viewReducer(_state, action) {
41275
41305
  return { cursor: action.cursor, expandedIndex: action.expandedIndex, expandLevel: action.expandLevel, viewport: action.viewport };
41276
41306
  }
41277
41307
  }
41278
- var import_react29, import_chalk10, import_jsx_runtime10, SEVERITY_LABELS3, SEVERITY_COLORS, EVIDENCE_LIMIT2, FIXED_CHROME, InteractiveResultsView, T, FindingsSummary, FindingsDetail;
41308
+ var import_react30, import_chalk10, import_jsx_runtime10, SEVERITY_LABELS3, SEVERITY_COLORS, EVIDENCE_LIMIT2, FIXED_CHROME, InteractiveResultsView, T, FindingsSummary, FindingsDetail;
41279
41309
  var init_InteractiveResultsView = __esm({
41280
41310
  async "src/ui/components/InteractiveResultsView.tsx"() {
41281
41311
  "use strict";
41282
- import_react29 = __toESM(require_react());
41312
+ import_react30 = __toESM(require_react());
41283
41313
  await init_build2();
41284
41314
  import_chalk10 = __toESM(require_source());
41285
41315
  await init_ScoreHeader();
41286
41316
  init_useExpandAnimation();
41317
+ await init_useTerminalSize();
41287
41318
  import_jsx_runtime10 = __toESM(require_jsx_runtime());
41288
41319
  SEVERITY_LABELS3 = {
41289
41320
  5: "CRIT",
@@ -41308,40 +41339,31 @@ var init_InteractiveResultsView = __esm({
41308
41339
  onExit,
41309
41340
  onBack
41310
41341
  }) => {
41311
- (0, import_react29.useEffect)(() => {
41312
- if (!process.stdout.isTTY) return;
41313
- process.stdout.write("\x1B[?1049h");
41314
- return () => {
41315
- process.stdout.write("\x1B[?1049l");
41316
- };
41317
- }, []);
41318
- const flagged = (0, import_react29.useMemo)(
41342
+ const flagged = (0, import_react30.useMemo)(
41319
41343
  () => result.packages.filter((p) => p.score > 0),
41320
41344
  [result.packages]
41321
41345
  );
41322
- const clean = (0, import_react29.useMemo)(
41346
+ const clean = (0, import_react30.useMemo)(
41323
41347
  () => result.packages.filter((p) => p.score === 0),
41324
41348
  [result.packages]
41325
41349
  );
41326
41350
  const total = result.packages.length;
41327
- const groups = (0, import_react29.useMemo)(() => groupPackages3(flagged), [flagged]);
41328
- const [view, dispatchView] = (0, import_react29.useReducer)(viewReducer, {
41351
+ const groups = (0, import_react30.useMemo)(() => groupPackages3(flagged), [flagged]);
41352
+ const [view, dispatchView] = (0, import_react30.useReducer)(viewReducer, {
41329
41353
  cursor: 0,
41330
41354
  expandLevel: null,
41331
41355
  expandedIndex: null,
41332
41356
  viewport: 0
41333
41357
  });
41334
- const viewRef = (0, import_react29.useRef)(view);
41358
+ const viewRef = (0, import_react30.useRef)(view);
41335
41359
  viewRef.current = view;
41336
- const { stdout } = use_stdout_default();
41337
- const termCols = stdout?.columns ?? process.stdout.columns ?? 80;
41338
- const termRows = stdout?.rows ?? process.stdout.rows ?? 24;
41360
+ const { rows: termRows, cols: termCols } = useTerminalSize();
41339
41361
  const availableRows = Math.max(5, termRows - FIXED_CHROME);
41340
41362
  const innerWidth = Math.max(40, termCols - 6);
41341
41363
  const getLevel = (idx) => {
41342
41364
  return view.expandedIndex === idx ? view.expandLevel : null;
41343
41365
  };
41344
- const expandTargetHeight = (0, import_react29.useMemo)(() => {
41366
+ const expandTargetHeight = (0, import_react30.useMemo)(() => {
41345
41367
  if (view.expandedIndex === null || view.expandLevel === null) return 0;
41346
41368
  const group = groups[view.expandedIndex];
41347
41369
  if (!group) return 0;
@@ -41357,7 +41379,7 @@ var init_InteractiveResultsView = __esm({
41357
41379
  if (idx === view.expandedIndex) return 1 + animVisibleLines;
41358
41380
  return groupRowHeight(group, level, result.safeVersions);
41359
41381
  };
41360
- const visibleEnd = (0, import_react29.useMemo)(() => {
41382
+ const visibleEnd = (0, import_react30.useMemo)(() => {
41361
41383
  let consumed = 0;
41362
41384
  let end = view.viewport;
41363
41385
  while (end < groups.length) {
@@ -41389,6 +41411,13 @@ var init_InteractiveResultsView = __esm({
41389
41411
  }
41390
41412
  return newStart;
41391
41413
  };
41414
+ (0, import_react30.useEffect)(() => {
41415
+ if (groups.length === 0) return;
41416
+ const { cursor, expandedIndex, expandLevel, viewport } = viewRef.current;
41417
+ const clamped = Math.min(viewport, Math.max(0, groups.length - 1));
41418
+ const newVp = adjustViewport(cursor, expandedIndex, expandLevel, clamped);
41419
+ dispatchView({ type: "MOVE", cursor, viewport: newVp });
41420
+ }, [availableRows]);
41392
41421
  use_input_default((input, key) => {
41393
41422
  if (groups.length === 0) {
41394
41423
  if (input === "q" || key.return) onExit();
@@ -41416,13 +41445,12 @@ var init_InteractiveResultsView = __esm({
41416
41445
  const newVp = adjustViewport(cursor, newExpIdx, newExpLvl, vpStart);
41417
41446
  dispatchView({ type: "EXPAND", expandedIndex: newExpIdx, expandLevel: newExpLvl, viewport: newVp });
41418
41447
  } else if (input === "e") {
41419
- if (expIdx === cursor && expLvl === "detail") return;
41420
- const newVp = adjustViewport(cursor, cursor, "detail", vpStart);
41421
- dispatchView({ type: "EXPAND", expandedIndex: cursor, expandLevel: "detail", viewport: newVp });
41422
- } else if (input === "c") {
41423
- if (expIdx !== null && expLvl !== null) {
41448
+ if (expIdx === cursor && expLvl === "detail") {
41424
41449
  const newVp = adjustViewport(cursor, null, null, vpStart);
41425
41450
  dispatchView({ type: "EXPAND", expandedIndex: null, expandLevel: null, viewport: newVp });
41451
+ } else {
41452
+ const newVp = adjustViewport(cursor, cursor, "detail", vpStart);
41453
+ dispatchView({ type: "EXPAND", expandedIndex: cursor, expandLevel: "detail", viewport: newVp });
41426
41454
  }
41427
41455
  } else if (input === "b" && onBack) {
41428
41456
  onBack();
@@ -41549,10 +41577,7 @@ var init_InteractiveResultsView = __esm({
41549
41577
  " toggle",
41550
41578
  " ",
41551
41579
  import_chalk10.default.cyan("e"),
41552
- " expand",
41553
- " ",
41554
- import_chalk10.default.cyan("c"),
41555
- " collapse",
41580
+ " expand/collapse",
41556
41581
  " ",
41557
41582
  onBack && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
41558
41583
  import_chalk10.default.cyan("b"),
@@ -41689,19 +41714,16 @@ var init_InteractiveResultsView = __esm({
41689
41714
  });
41690
41715
 
41691
41716
  // src/ui/components/ProjectSelector.tsx
41692
- var import_react30, import_jsx_runtime11, ProjectSelector;
41717
+ var import_react31, import_jsx_runtime11, ProjectSelector;
41693
41718
  var init_ProjectSelector = __esm({
41694
41719
  async "src/ui/components/ProjectSelector.tsx"() {
41695
41720
  "use strict";
41696
- import_react30 = __toESM(require_react());
41721
+ import_react31 = __toESM(require_react());
41697
41722
  await init_build2();
41698
41723
  import_jsx_runtime11 = __toESM(require_jsx_runtime());
41699
41724
  ProjectSelector = ({ projects, onConfirm, onCancel }) => {
41700
- const [cursor, setCursor] = (0, import_react30.useState)(0);
41701
- (0, import_react30.useEffect)(() => {
41702
- process.stdout.write("\x1B[2J\x1B[H");
41703
- }, []);
41704
- const [selected, setSelected] = (0, import_react30.useState)(() => new Set(projects.map((_, i) => i)));
41725
+ const [cursor, setCursor] = (0, import_react31.useState)(0);
41726
+ const [selected, setSelected] = (0, import_react31.useState)(() => new Set(projects.map((_, i) => i)));
41705
41727
  use_input_default((input, key) => {
41706
41728
  if (key.upArrow) {
41707
41729
  setCursor((c) => Math.max(0, c - 1));
@@ -41755,11 +41777,11 @@ var App_exports = {};
41755
41777
  __export(App_exports, {
41756
41778
  App: () => App2
41757
41779
  });
41758
- var import_react31, import_jsx_runtime12, App2;
41780
+ var import_react32, import_jsx_runtime12, App2;
41759
41781
  var init_App2 = __esm({
41760
41782
  async "src/ui/App.tsx"() {
41761
41783
  "use strict";
41762
- import_react31 = __toESM(require_react());
41784
+ import_react32 = __toESM(require_react());
41763
41785
  await init_build2();
41764
41786
  init_useScan();
41765
41787
  await init_Spinner();
@@ -41767,11 +41789,31 @@ var init_App2 = __esm({
41767
41789
  await init_InteractiveResultsView();
41768
41790
  await init_ErrorView();
41769
41791
  await init_ProjectSelector();
41792
+ await init_useTerminalSize();
41770
41793
  import_jsx_runtime12 = __toESM(require_jsx_runtime());
41771
41794
  App2 = ({ config }) => {
41772
41795
  const { state, scanSelectedProjects, restartSelection } = useScan(config);
41773
41796
  const { exit } = use_app_default();
41774
- const handleResultsExit = (0, import_react31.useCallback)(() => {
41797
+ const { rows: termRows } = useTerminalSize();
41798
+ const prevPhaseRef = (0, import_react32.useRef)(state.phase);
41799
+ (0, import_react32.useEffect)(() => {
41800
+ if (!process.stdout.isTTY) return;
41801
+ process.stdout.write("\x1B[?1049h");
41802
+ process.stdout.write("\x1B[?1003h");
41803
+ process.stdout.write("\x1B[2J\x1B[H");
41804
+ return () => {
41805
+ process.stdout.write("\x1B[?1003l");
41806
+ process.stdout.write("\x1B[?1049l");
41807
+ process.stdout.write("\x1B[?25h");
41808
+ };
41809
+ }, []);
41810
+ (0, import_react32.useEffect)(() => {
41811
+ if (prevPhaseRef.current !== state.phase && process.stdout.isTTY) {
41812
+ process.stdout.write("\x1B[2J\x1B[H");
41813
+ }
41814
+ prevPhaseRef.current = state.phase;
41815
+ }, [state.phase]);
41816
+ const handleResultsExit = (0, import_react32.useCallback)(() => {
41775
41817
  if (state.phase === "results") {
41776
41818
  const { result } = state;
41777
41819
  if (result.action === "block" && config.mode === "block") {
@@ -41784,7 +41826,7 @@ var init_App2 = __esm({
41784
41826
  }
41785
41827
  exit();
41786
41828
  }, [state, config, exit]);
41787
- (0, import_react31.useEffect)(() => {
41829
+ (0, import_react32.useEffect)(() => {
41788
41830
  if (state.phase === "empty") {
41789
41831
  process.exitCode = 0;
41790
41832
  const timer = setTimeout(() => exit(), 0);
@@ -41796,55 +41838,58 @@ var init_App2 = __esm({
41796
41838
  return () => clearTimeout(timer);
41797
41839
  }
41798
41840
  }, [state, config, exit]);
41799
- switch (state.phase) {
41800
- case "discovering":
41801
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Spinner2, { label: "Searching for dependencies..." });
41802
- case "selecting":
41803
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
41804
- ProjectSelector,
41805
- {
41806
- projects: state.projects,
41807
- onConfirm: scanSelectedProjects,
41808
- onCancel: () => {
41809
- process.exitCode = 0;
41810
- exit();
41841
+ const content = (() => {
41842
+ switch (state.phase) {
41843
+ case "discovering":
41844
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Spinner2, { label: "Searching for dependencies..." });
41845
+ case "selecting":
41846
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
41847
+ ProjectSelector,
41848
+ {
41849
+ projects: state.projects,
41850
+ onConfirm: scanSelectedProjects,
41851
+ onCancel: () => {
41852
+ process.exitCode = 0;
41853
+ exit();
41854
+ }
41811
41855
  }
41812
- }
41813
- );
41814
- case "scanning":
41815
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { flexDirection: "column", children: [
41816
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
41817
- ProgressBar,
41856
+ );
41857
+ case "scanning":
41858
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { flexDirection: "column", children: [
41859
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
41860
+ ProgressBar,
41861
+ {
41862
+ value: state.done,
41863
+ total: state.total,
41864
+ label: state.currentBatch.length > 0 ? state.currentBatch[state.currentBatch.length - 1] : void 0
41865
+ }
41866
+ ),
41867
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { dimColor: true, children: [
41868
+ "Scanning ",
41869
+ state.done,
41870
+ "/",
41871
+ state.total,
41872
+ " packages..."
41873
+ ] })
41874
+ ] });
41875
+ case "results":
41876
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
41877
+ InteractiveResultsView,
41818
41878
  {
41819
- value: state.done,
41820
- total: state.total,
41821
- label: state.currentBatch.length > 0 ? state.currentBatch[state.currentBatch.length - 1] : void 0
41879
+ result: state.result,
41880
+ config,
41881
+ durationMs: state.durationMs,
41882
+ onExit: handleResultsExit,
41883
+ onBack: restartSelection ?? void 0
41822
41884
  }
41823
- ),
41824
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { dimColor: true, children: [
41825
- "Scanning ",
41826
- state.done,
41827
- "/",
41828
- state.total,
41829
- " packages..."
41830
- ] })
41831
- ] });
41832
- case "results":
41833
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
41834
- InteractiveResultsView,
41835
- {
41836
- result: state.result,
41837
- config,
41838
- durationMs: state.durationMs,
41839
- onExit: handleResultsExit,
41840
- onBack: restartSelection ?? void 0
41841
- }
41842
- );
41843
- case "empty":
41844
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: state.message });
41845
- case "error":
41846
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ErrorView, { error: state.error });
41847
- }
41885
+ );
41886
+ case "empty":
41887
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: state.message });
41888
+ case "error":
41889
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ErrorView, { error: state.error });
41890
+ }
41891
+ })();
41892
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Box_default, { flexDirection: "column", height: termRows, children: content });
41848
41893
  };
41849
41894
  }
41850
41895
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@westbayberry/dg",
3
- "version": "1.0.14",
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",
@@ -12,6 +12,10 @@
12
12
  "license": "UNLICENSED",
13
13
  "author": "WestBayBerry",
14
14
  "homepage": "https://westbayberry.com",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/WestBayBerry/dependency-guardian-action.git"
18
+ },
15
19
  "keywords": [
16
20
  "security",
17
21
  "npm",