@westbayberry/dg 1.0.14 → 1.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +239 -137
- package/package.json +5 -1
package/dist/index.mjs
CHANGED
|
@@ -114,12 +114,6 @@ 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
|
-
}
|
|
123
117
|
const modeRaw = values.mode ?? process.env.DG_MODE ?? dgrc.mode ?? "warn";
|
|
124
118
|
if (!["block", "warn", "off"].includes(modeRaw)) {
|
|
125
119
|
process.stderr.write(
|
|
@@ -131,7 +125,10 @@ function parseConfig(argv) {
|
|
|
131
125
|
const allowlistRaw = values.allowlist ?? process.env.DG_ALLOWLIST ?? "";
|
|
132
126
|
const blockThreshold = Number(values["block-threshold"] ?? dgrc.blockThreshold ?? "70");
|
|
133
127
|
const warnThreshold = Number(values["warn-threshold"] ?? dgrc.warnThreshold ?? "60");
|
|
134
|
-
|
|
128
|
+
let maxPackages = Number(values["max-packages"] ?? dgrc.maxPackages ?? "200");
|
|
129
|
+
if (!apiKey) {
|
|
130
|
+
maxPackages = Math.min(maxPackages, 50);
|
|
131
|
+
}
|
|
135
132
|
const debug = values.debug || process.env.DG_DEBUG === "1";
|
|
136
133
|
if (isNaN(blockThreshold) || blockThreshold < 0 || blockThreshold > 100) {
|
|
137
134
|
process.stderr.write("Error: --block-threshold must be a number between 0 and 100\n");
|
|
@@ -3296,7 +3293,7 @@ var require_react_development = __commonJS({
|
|
|
3296
3293
|
}
|
|
3297
3294
|
return dispatcher.useContext(Context);
|
|
3298
3295
|
}
|
|
3299
|
-
function
|
|
3296
|
+
function useState7(initialState) {
|
|
3300
3297
|
var dispatcher = resolveDispatcher();
|
|
3301
3298
|
return dispatcher.useState(initialState);
|
|
3302
3299
|
}
|
|
@@ -3304,7 +3301,7 @@ var require_react_development = __commonJS({
|
|
|
3304
3301
|
var dispatcher = resolveDispatcher();
|
|
3305
3302
|
return dispatcher.useReducer(reducer4, initialArg, init);
|
|
3306
3303
|
}
|
|
3307
|
-
function
|
|
3304
|
+
function useRef7(initialValue) {
|
|
3308
3305
|
var dispatcher = resolveDispatcher();
|
|
3309
3306
|
return dispatcher.useRef(initialValue);
|
|
3310
3307
|
}
|
|
@@ -4098,8 +4095,8 @@ var require_react_development = __commonJS({
|
|
|
4098
4095
|
exports.useLayoutEffect = useLayoutEffect2;
|
|
4099
4096
|
exports.useMemo = useMemo4;
|
|
4100
4097
|
exports.useReducer = useReducer5;
|
|
4101
|
-
exports.useRef =
|
|
4102
|
-
exports.useState =
|
|
4098
|
+
exports.useRef = useRef7;
|
|
4099
|
+
exports.useState = useState7;
|
|
4103
4100
|
exports.useSyncExternalStore = useSyncExternalStore;
|
|
4104
4101
|
exports.useTransition = useTransition;
|
|
4105
4102
|
exports.version = ReactVersion;
|
|
@@ -38917,15 +38914,35 @@ async function callAnalyzeAPI(packages, config, onProgress) {
|
|
|
38917
38914
|
for (let i = 0; i < packages.length; i += BATCH_SIZE) {
|
|
38918
38915
|
batches.push(packages.slice(i, i + BATCH_SIZE));
|
|
38919
38916
|
}
|
|
38920
|
-
const
|
|
38917
|
+
const MAX_CONCURRENT_BATCHES = 2;
|
|
38918
|
+
const results = new Array(batches.length);
|
|
38921
38919
|
let completed = 0;
|
|
38922
|
-
|
|
38923
|
-
|
|
38924
|
-
|
|
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;
|
|
38925
38925
|
if (onProgress) {
|
|
38926
|
-
onProgress(completed, packages.length,
|
|
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);
|
|
38927
38945
|
}
|
|
38928
|
-
results.push(result);
|
|
38929
38946
|
}
|
|
38930
38947
|
return mergeResponses(results, config);
|
|
38931
38948
|
}
|
|
@@ -38984,13 +39001,16 @@ async function callAnalyzeBatch(packages, config) {
|
|
|
38984
39001
|
const timeoutId = setTimeout(() => controller.abort(), 12e4);
|
|
38985
39002
|
let response;
|
|
38986
39003
|
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
|
+
}
|
|
38987
39011
|
response = await fetch(url, {
|
|
38988
39012
|
method: "POST",
|
|
38989
|
-
headers
|
|
38990
|
-
"Content-Type": "application/json",
|
|
38991
|
-
Authorization: `Bearer ${config.apiKey}`,
|
|
38992
|
-
"User-Agent": "dependency-guardian-cli/1.0.0"
|
|
38993
|
-
},
|
|
39013
|
+
headers,
|
|
38994
39014
|
body: JSON.stringify(payload),
|
|
38995
39015
|
signal: controller.signal
|
|
38996
39016
|
});
|
|
@@ -39012,6 +39032,14 @@ async function callAnalyzeBatch(packages, config) {
|
|
|
39012
39032
|
);
|
|
39013
39033
|
}
|
|
39014
39034
|
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
|
+
}
|
|
39015
39043
|
throw new APIError(
|
|
39016
39044
|
"Rate limit exceeded. Upgrade your plan at https://westbayberry.com/pricing",
|
|
39017
39045
|
429,
|
|
@@ -39064,13 +39092,16 @@ async function callPyPIBatch(packages, config) {
|
|
|
39064
39092
|
const timeoutId = setTimeout(() => controller.abort(), 12e4);
|
|
39065
39093
|
let response;
|
|
39066
39094
|
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
|
+
}
|
|
39067
39102
|
response = await fetch(url, {
|
|
39068
39103
|
method: "POST",
|
|
39069
|
-
headers
|
|
39070
|
-
"Content-Type": "application/json",
|
|
39071
|
-
Authorization: `Bearer ${config.apiKey}`,
|
|
39072
|
-
"User-Agent": "dependency-guardian-cli/1.0.0"
|
|
39073
|
-
},
|
|
39104
|
+
headers,
|
|
39074
39105
|
body: JSON.stringify(payload),
|
|
39075
39106
|
signal: controller.signal
|
|
39076
39107
|
});
|
|
@@ -39092,6 +39123,14 @@ async function callPyPIBatch(packages, config) {
|
|
|
39092
39123
|
);
|
|
39093
39124
|
}
|
|
39094
39125
|
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
|
+
}
|
|
39095
39134
|
throw new APIError(
|
|
39096
39135
|
"Rate limit exceeded. Upgrade your plan at https://westbayberry.com/pricing",
|
|
39097
39136
|
429,
|
|
@@ -39116,7 +39155,7 @@ var init_api = __esm({
|
|
|
39116
39155
|
this.name = "APIError";
|
|
39117
39156
|
}
|
|
39118
39157
|
};
|
|
39119
|
-
BATCH_SIZE =
|
|
39158
|
+
BATCH_SIZE = 200;
|
|
39120
39159
|
MAX_RETRIES = 2;
|
|
39121
39160
|
RETRY_DELAY_MS = 5e3;
|
|
39122
39161
|
}
|
|
@@ -39755,7 +39794,7 @@ function truncate(s, max) {
|
|
|
39755
39794
|
function groupPackages(packages) {
|
|
39756
39795
|
const map = /* @__PURE__ */ new Map();
|
|
39757
39796
|
for (const pkg of packages) {
|
|
39758
|
-
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.
|
|
39797
|
+
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.category}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
|
|
39759
39798
|
const group = map.get(fingerprint) ?? [];
|
|
39760
39799
|
group.push(pkg);
|
|
39761
39800
|
map.set(fingerprint, group);
|
|
@@ -39837,7 +39876,7 @@ function renderResultStatic(result, config) {
|
|
|
39837
39876
|
const sevLabel = SEVERITY_LABELS[finding.severity] ?? "INFO";
|
|
39838
39877
|
const colorFn = severityColor(finding.severity);
|
|
39839
39878
|
lines.push(
|
|
39840
|
-
` ${colorFn(pad(sevLabel, 10))}${finding.
|
|
39879
|
+
` ${colorFn(pad(sevLabel, 10))}${finding.category} \u2014 ${finding.title}`
|
|
39841
39880
|
);
|
|
39842
39881
|
const evidenceLimit = 3;
|
|
39843
39882
|
for (let i = 0; i < Math.min(finding.evidence.length, evidenceLimit); i++) {
|
|
@@ -39944,6 +39983,11 @@ async function runStatic(config) {
|
|
|
39944
39983
|
);
|
|
39945
39984
|
const output = renderResultStatic(result, config);
|
|
39946
39985
|
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
|
+
}
|
|
39947
39991
|
if (result.action === "block" && config.mode === "block") {
|
|
39948
39992
|
process.exit(2);
|
|
39949
39993
|
} else if (result.action === "block" || result.action === "warn") {
|
|
@@ -40062,6 +40106,11 @@ async function scanAndInstallStatic(resolved, parsed, config) {
|
|
|
40062
40106
|
}
|
|
40063
40107
|
const output = renderResultStatic(result, config);
|
|
40064
40108
|
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
|
+
}
|
|
40065
40114
|
if (result.action === "warn") {
|
|
40066
40115
|
process.stderr.write(
|
|
40067
40116
|
import_chalk4.default.yellow(" Warnings detected. Proceeding with install.\n\n")
|
|
@@ -40602,7 +40651,7 @@ var init_DurationLine = __esm({
|
|
|
40602
40651
|
function groupPackages2(packages) {
|
|
40603
40652
|
const map = /* @__PURE__ */ new Map();
|
|
40604
40653
|
for (const pkg of packages) {
|
|
40605
|
-
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.
|
|
40654
|
+
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.category}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
|
|
40606
40655
|
const group = map.get(fingerprint) ?? [];
|
|
40607
40656
|
group.push(pkg);
|
|
40608
40657
|
map.set(fingerprint, group);
|
|
@@ -40722,7 +40771,7 @@ var init_ResultsView = __esm({
|
|
|
40722
40771
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
|
|
40723
40772
|
" ",
|
|
40724
40773
|
colorFn(pad2(sevLabel, 10)),
|
|
40725
|
-
finding.
|
|
40774
|
+
finding.category,
|
|
40726
40775
|
" ",
|
|
40727
40776
|
"\u2014",
|
|
40728
40777
|
" ",
|
|
@@ -40737,7 +40786,7 @@ var init_ResultsView = __esm({
|
|
|
40737
40786
|
import_chalk6.default.dim(`... and ${overflow} more`)
|
|
40738
40787
|
] }),
|
|
40739
40788
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: " " })
|
|
40740
|
-
] }, `${finding.
|
|
40789
|
+
] }, `${finding.category}-${idx}`);
|
|
40741
40790
|
}),
|
|
40742
40791
|
safeVersion && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
|
|
40743
40792
|
" ",
|
|
@@ -40990,14 +41039,14 @@ function useScan(config) {
|
|
|
40990
41039
|
started.current = true;
|
|
40991
41040
|
const projects = discoverProjects(process.cwd());
|
|
40992
41041
|
if (projects.length > 1) setMultiProjects(projects);
|
|
41042
|
+
if (projects.length > 1) {
|
|
41043
|
+
dispatch({ type: "PROJECTS_FOUND", projects });
|
|
41044
|
+
return;
|
|
41045
|
+
}
|
|
40993
41046
|
try {
|
|
40994
41047
|
const discovery = discoverChanges(process.cwd(), config);
|
|
40995
41048
|
const packages = discovery.packages.filter((p) => !config.allowlist.includes(p.name));
|
|
40996
41049
|
if (packages.length === 0) {
|
|
40997
|
-
if (discovery.packages.length === 0 && projects.length > 0) {
|
|
40998
|
-
dispatch({ type: "PROJECTS_FOUND", projects });
|
|
40999
|
-
return;
|
|
41000
|
-
}
|
|
41001
41050
|
const message = discovery.packages.length === 0 ? "No package changes detected." : "All changed packages are allowlisted.";
|
|
41002
41051
|
dispatch({ type: "DISCOVERY_EMPTY", message });
|
|
41003
41052
|
return;
|
|
@@ -41009,12 +41058,8 @@ function useScan(config) {
|
|
|
41009
41058
|
dispatch({ type: "DISCOVERY_EMPTY", message: "No dependency files found." });
|
|
41010
41059
|
return;
|
|
41011
41060
|
}
|
|
41012
|
-
|
|
41013
|
-
|
|
41014
|
-
scanProjects(projects, config, dispatch);
|
|
41015
|
-
return;
|
|
41016
|
-
}
|
|
41017
|
-
dispatch({ type: "PROJECTS_FOUND", projects });
|
|
41061
|
+
dispatch({ type: "DISCOVERY_COMPLETE", packages: [], skippedCount: 0 });
|
|
41062
|
+
scanProjects(projects, config, dispatch);
|
|
41018
41063
|
}
|
|
41019
41064
|
}, [config]);
|
|
41020
41065
|
const scanSelectedProjects = (0, import_react27.useCallback)((projects) => {
|
|
@@ -41205,11 +41250,45 @@ var init_useExpandAnimation = __esm({
|
|
|
41205
41250
|
}
|
|
41206
41251
|
});
|
|
41207
41252
|
|
|
41253
|
+
// src/ui/hooks/useTerminalSize.ts
|
|
41254
|
+
function useTerminalSize() {
|
|
41255
|
+
const { stdout } = use_stdout_default();
|
|
41256
|
+
const [size, setSize] = (0, import_react29.useState)({
|
|
41257
|
+
rows: stdout?.rows ?? process.stdout.rows ?? 24,
|
|
41258
|
+
cols: stdout?.columns ?? process.stdout.columns ?? 80
|
|
41259
|
+
});
|
|
41260
|
+
(0, import_react29.useEffect)(() => {
|
|
41261
|
+
const handle = () => {
|
|
41262
|
+
const rows = process.stdout.rows ?? 24;
|
|
41263
|
+
const cols = process.stdout.columns ?? 80;
|
|
41264
|
+
if (process.stdout.isTTY) {
|
|
41265
|
+
process.stdout.write("\x1B[2J\x1B[H");
|
|
41266
|
+
}
|
|
41267
|
+
setSize({ rows, cols });
|
|
41268
|
+
};
|
|
41269
|
+
process.stdout.setMaxListeners(process.stdout.getMaxListeners() + 1);
|
|
41270
|
+
process.stdout.on("resize", handle);
|
|
41271
|
+
return () => {
|
|
41272
|
+
process.stdout.off("resize", handle);
|
|
41273
|
+
process.stdout.setMaxListeners(Math.max(0, process.stdout.getMaxListeners() - 1));
|
|
41274
|
+
};
|
|
41275
|
+
}, []);
|
|
41276
|
+
return size;
|
|
41277
|
+
}
|
|
41278
|
+
var import_react29;
|
|
41279
|
+
var init_useTerminalSize = __esm({
|
|
41280
|
+
async "src/ui/hooks/useTerminalSize.ts"() {
|
|
41281
|
+
"use strict";
|
|
41282
|
+
import_react29 = __toESM(require_react());
|
|
41283
|
+
await init_build2();
|
|
41284
|
+
}
|
|
41285
|
+
});
|
|
41286
|
+
|
|
41208
41287
|
// src/ui/components/InteractiveResultsView.tsx
|
|
41209
41288
|
function groupPackages3(packages) {
|
|
41210
41289
|
const map = /* @__PURE__ */ new Map();
|
|
41211
41290
|
for (const pkg of packages) {
|
|
41212
|
-
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.
|
|
41291
|
+
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.category}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
|
|
41213
41292
|
const group = map.get(fingerprint) ?? [];
|
|
41214
41293
|
group.push(pkg);
|
|
41215
41294
|
map.set(fingerprint, group);
|
|
@@ -41275,15 +41354,16 @@ function viewReducer(_state, action) {
|
|
|
41275
41354
|
return { cursor: action.cursor, expandedIndex: action.expandedIndex, expandLevel: action.expandLevel, viewport: action.viewport };
|
|
41276
41355
|
}
|
|
41277
41356
|
}
|
|
41278
|
-
var
|
|
41357
|
+
var import_react30, import_chalk10, import_jsx_runtime10, SEVERITY_LABELS3, SEVERITY_COLORS, EVIDENCE_LIMIT2, FIXED_CHROME, InteractiveResultsView, T, FindingsSummary, FindingsDetail;
|
|
41279
41358
|
var init_InteractiveResultsView = __esm({
|
|
41280
41359
|
async "src/ui/components/InteractiveResultsView.tsx"() {
|
|
41281
41360
|
"use strict";
|
|
41282
|
-
|
|
41361
|
+
import_react30 = __toESM(require_react());
|
|
41283
41362
|
await init_build2();
|
|
41284
41363
|
import_chalk10 = __toESM(require_source());
|
|
41285
41364
|
await init_ScoreHeader();
|
|
41286
41365
|
init_useExpandAnimation();
|
|
41366
|
+
await init_useTerminalSize();
|
|
41287
41367
|
import_jsx_runtime10 = __toESM(require_jsx_runtime());
|
|
41288
41368
|
SEVERITY_LABELS3 = {
|
|
41289
41369
|
5: "CRIT",
|
|
@@ -41308,40 +41388,32 @@ var init_InteractiveResultsView = __esm({
|
|
|
41308
41388
|
onExit,
|
|
41309
41389
|
onBack
|
|
41310
41390
|
}) => {
|
|
41311
|
-
(0,
|
|
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)(
|
|
41391
|
+
const flagged = (0, import_react30.useMemo)(
|
|
41319
41392
|
() => result.packages.filter((p) => p.score > 0),
|
|
41320
41393
|
[result.packages]
|
|
41321
41394
|
);
|
|
41322
|
-
const clean = (0,
|
|
41395
|
+
const clean = (0, import_react30.useMemo)(
|
|
41323
41396
|
() => result.packages.filter((p) => p.score === 0),
|
|
41324
41397
|
[result.packages]
|
|
41325
41398
|
);
|
|
41326
41399
|
const total = result.packages.length;
|
|
41327
|
-
const groups = (0,
|
|
41328
|
-
const [view, dispatchView] = (0,
|
|
41400
|
+
const groups = (0, import_react30.useMemo)(() => groupPackages3(flagged), [flagged]);
|
|
41401
|
+
const [view, dispatchView] = (0, import_react30.useReducer)(viewReducer, {
|
|
41329
41402
|
cursor: 0,
|
|
41330
41403
|
expandLevel: null,
|
|
41331
41404
|
expandedIndex: null,
|
|
41332
41405
|
viewport: 0
|
|
41333
41406
|
});
|
|
41334
|
-
const viewRef = (0,
|
|
41407
|
+
const viewRef = (0, import_react30.useRef)(view);
|
|
41335
41408
|
viewRef.current = view;
|
|
41336
|
-
const {
|
|
41337
|
-
const
|
|
41338
|
-
const
|
|
41339
|
-
const availableRows = Math.max(5, termRows - FIXED_CHROME);
|
|
41409
|
+
const { rows: termRows, cols: termCols } = useTerminalSize();
|
|
41410
|
+
const chromeHeight = FIXED_CHROME + (config.apiKey ? 0 : 2);
|
|
41411
|
+
const availableRows = Math.max(5, termRows - chromeHeight);
|
|
41340
41412
|
const innerWidth = Math.max(40, termCols - 6);
|
|
41341
41413
|
const getLevel = (idx) => {
|
|
41342
41414
|
return view.expandedIndex === idx ? view.expandLevel : null;
|
|
41343
41415
|
};
|
|
41344
|
-
const expandTargetHeight = (0,
|
|
41416
|
+
const expandTargetHeight = (0, import_react30.useMemo)(() => {
|
|
41345
41417
|
if (view.expandedIndex === null || view.expandLevel === null) return 0;
|
|
41346
41418
|
const group = groups[view.expandedIndex];
|
|
41347
41419
|
if (!group) return 0;
|
|
@@ -41357,7 +41429,7 @@ var init_InteractiveResultsView = __esm({
|
|
|
41357
41429
|
if (idx === view.expandedIndex) return 1 + animVisibleLines;
|
|
41358
41430
|
return groupRowHeight(group, level, result.safeVersions);
|
|
41359
41431
|
};
|
|
41360
|
-
const visibleEnd = (0,
|
|
41432
|
+
const visibleEnd = (0, import_react30.useMemo)(() => {
|
|
41361
41433
|
let consumed = 0;
|
|
41362
41434
|
let end = view.viewport;
|
|
41363
41435
|
while (end < groups.length) {
|
|
@@ -41389,6 +41461,13 @@ var init_InteractiveResultsView = __esm({
|
|
|
41389
41461
|
}
|
|
41390
41462
|
return newStart;
|
|
41391
41463
|
};
|
|
41464
|
+
(0, import_react30.useEffect)(() => {
|
|
41465
|
+
if (groups.length === 0) return;
|
|
41466
|
+
const { cursor, expandedIndex, expandLevel, viewport } = viewRef.current;
|
|
41467
|
+
const clamped = Math.min(viewport, Math.max(0, groups.length - 1));
|
|
41468
|
+
const newVp = adjustViewport(cursor, expandedIndex, expandLevel, clamped);
|
|
41469
|
+
dispatchView({ type: "MOVE", cursor, viewport: newVp });
|
|
41470
|
+
}, [availableRows]);
|
|
41392
41471
|
use_input_default((input, key) => {
|
|
41393
41472
|
if (groups.length === 0) {
|
|
41394
41473
|
if (input === "q" || key.return) onExit();
|
|
@@ -41416,13 +41495,15 @@ var init_InteractiveResultsView = __esm({
|
|
|
41416
41495
|
const newVp = adjustViewport(cursor, newExpIdx, newExpLvl, vpStart);
|
|
41417
41496
|
dispatchView({ type: "EXPAND", expandedIndex: newExpIdx, expandLevel: newExpLvl, viewport: newVp });
|
|
41418
41497
|
} else if (input === "e") {
|
|
41419
|
-
if (expIdx === cursor && expLvl === "detail")
|
|
41420
|
-
|
|
41421
|
-
|
|
41422
|
-
|
|
41423
|
-
if (expIdx !== null && expLvl !== null) {
|
|
41498
|
+
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") {
|
|
41424
41502
|
const newVp = adjustViewport(cursor, null, null, vpStart);
|
|
41425
41503
|
dispatchView({ type: "EXPAND", expandedIndex: null, expandLevel: null, viewport: newVp });
|
|
41504
|
+
} else {
|
|
41505
|
+
const newVp = adjustViewport(cursor, cursor, "detail", vpStart);
|
|
41506
|
+
dispatchView({ type: "EXPAND", expandedIndex: cursor, expandLevel: "detail", viewport: newVp });
|
|
41426
41507
|
}
|
|
41427
41508
|
} else if (input === "b" && onBack) {
|
|
41428
41509
|
onBack();
|
|
@@ -41539,6 +41620,12 @@ var init_InteractiveResultsView = __esm({
|
|
|
41539
41620
|
]
|
|
41540
41621
|
}
|
|
41541
41622
|
),
|
|
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
|
+
] }) }),
|
|
41542
41629
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, children: [
|
|
41543
41630
|
" ",
|
|
41544
41631
|
groups.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
@@ -41549,10 +41636,7 @@ var init_InteractiveResultsView = __esm({
|
|
|
41549
41636
|
" toggle",
|
|
41550
41637
|
" ",
|
|
41551
41638
|
import_chalk10.default.cyan("e"),
|
|
41552
|
-
" expand",
|
|
41553
|
-
" ",
|
|
41554
|
-
import_chalk10.default.cyan("c"),
|
|
41555
|
-
" collapse",
|
|
41639
|
+
" expand/collapse",
|
|
41556
41640
|
" ",
|
|
41557
41641
|
onBack && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
41558
41642
|
import_chalk10.default.cyan("b"),
|
|
@@ -41594,8 +41678,8 @@ var init_InteractiveResultsView = __esm({
|
|
|
41594
41678
|
" ",
|
|
41595
41679
|
sevColor(pad3(sevLabel, 4)),
|
|
41596
41680
|
" ",
|
|
41597
|
-
import_chalk10.default.dim(f.
|
|
41598
|
-
] }, `${f.
|
|
41681
|
+
import_chalk10.default.dim(f.category)
|
|
41682
|
+
] }, `${f.category}-${idx}`)
|
|
41599
41683
|
);
|
|
41600
41684
|
}
|
|
41601
41685
|
if (hasAffects) {
|
|
@@ -41633,15 +41717,15 @@ var init_InteractiveResultsView = __esm({
|
|
|
41633
41717
|
" ",
|
|
41634
41718
|
sevColor(pad3(sevLabel, 4)),
|
|
41635
41719
|
" ",
|
|
41636
|
-
import_chalk10.default.bold(finding.
|
|
41637
|
-
] }, `${finding.
|
|
41720
|
+
import_chalk10.default.bold(finding.category)
|
|
41721
|
+
] }, `${finding.category}-${idx}-badge`)
|
|
41638
41722
|
);
|
|
41639
41723
|
allLines.push(
|
|
41640
41724
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, children: [
|
|
41641
41725
|
continuation,
|
|
41642
41726
|
" ",
|
|
41643
41727
|
finding.title
|
|
41644
|
-
] }, `${finding.
|
|
41728
|
+
] }, `${finding.category}-${idx}-title`)
|
|
41645
41729
|
);
|
|
41646
41730
|
for (let i = 0; i < evidenceSlice.length; i++) {
|
|
41647
41731
|
allLines.push(
|
|
@@ -41651,7 +41735,7 @@ var init_InteractiveResultsView = __esm({
|
|
|
41651
41735
|
import_chalk10.default.dim("\u203A"),
|
|
41652
41736
|
" ",
|
|
41653
41737
|
truncate3(evidenceSlice[i], evidenceWidth)
|
|
41654
|
-
] }, `${finding.
|
|
41738
|
+
] }, `${finding.category}-${idx}-ev-${i}`)
|
|
41655
41739
|
);
|
|
41656
41740
|
}
|
|
41657
41741
|
if (overflow > 0) {
|
|
@@ -41660,7 +41744,7 @@ var init_InteractiveResultsView = __esm({
|
|
|
41660
41744
|
continuation,
|
|
41661
41745
|
" ",
|
|
41662
41746
|
import_chalk10.default.dim(`+${overflow} more`)
|
|
41663
|
-
] }, `${finding.
|
|
41747
|
+
] }, `${finding.category}-${idx}-overflow`)
|
|
41664
41748
|
);
|
|
41665
41749
|
}
|
|
41666
41750
|
}
|
|
@@ -41689,19 +41773,16 @@ var init_InteractiveResultsView = __esm({
|
|
|
41689
41773
|
});
|
|
41690
41774
|
|
|
41691
41775
|
// src/ui/components/ProjectSelector.tsx
|
|
41692
|
-
var
|
|
41776
|
+
var import_react31, import_jsx_runtime11, ProjectSelector;
|
|
41693
41777
|
var init_ProjectSelector = __esm({
|
|
41694
41778
|
async "src/ui/components/ProjectSelector.tsx"() {
|
|
41695
41779
|
"use strict";
|
|
41696
|
-
|
|
41780
|
+
import_react31 = __toESM(require_react());
|
|
41697
41781
|
await init_build2();
|
|
41698
41782
|
import_jsx_runtime11 = __toESM(require_jsx_runtime());
|
|
41699
41783
|
ProjectSelector = ({ projects, onConfirm, onCancel }) => {
|
|
41700
|
-
const [cursor, setCursor] = (0,
|
|
41701
|
-
(0,
|
|
41702
|
-
process.stdout.write("\x1B[2J\x1B[H");
|
|
41703
|
-
}, []);
|
|
41704
|
-
const [selected, setSelected] = (0, import_react30.useState)(() => new Set(projects.map((_, i) => i)));
|
|
41784
|
+
const [cursor, setCursor] = (0, import_react31.useState)(0);
|
|
41785
|
+
const [selected, setSelected] = (0, import_react31.useState)(() => new Set(projects.map((_, i) => i)));
|
|
41705
41786
|
use_input_default((input, key) => {
|
|
41706
41787
|
if (key.upArrow) {
|
|
41707
41788
|
setCursor((c) => Math.max(0, c - 1));
|
|
@@ -41755,11 +41836,11 @@ var App_exports = {};
|
|
|
41755
41836
|
__export(App_exports, {
|
|
41756
41837
|
App: () => App2
|
|
41757
41838
|
});
|
|
41758
|
-
var
|
|
41839
|
+
var import_react32, import_jsx_runtime12, App2;
|
|
41759
41840
|
var init_App2 = __esm({
|
|
41760
41841
|
async "src/ui/App.tsx"() {
|
|
41761
41842
|
"use strict";
|
|
41762
|
-
|
|
41843
|
+
import_react32 = __toESM(require_react());
|
|
41763
41844
|
await init_build2();
|
|
41764
41845
|
init_useScan();
|
|
41765
41846
|
await init_Spinner();
|
|
@@ -41767,11 +41848,29 @@ var init_App2 = __esm({
|
|
|
41767
41848
|
await init_InteractiveResultsView();
|
|
41768
41849
|
await init_ErrorView();
|
|
41769
41850
|
await init_ProjectSelector();
|
|
41851
|
+
await init_useTerminalSize();
|
|
41770
41852
|
import_jsx_runtime12 = __toESM(require_jsx_runtime());
|
|
41771
41853
|
App2 = ({ config }) => {
|
|
41772
41854
|
const { state, scanSelectedProjects, restartSelection } = useScan(config);
|
|
41773
41855
|
const { exit } = use_app_default();
|
|
41774
|
-
const
|
|
41856
|
+
const { rows: termRows } = useTerminalSize();
|
|
41857
|
+
const prevPhaseRef = (0, import_react32.useRef)(state.phase);
|
|
41858
|
+
(0, import_react32.useEffect)(() => {
|
|
41859
|
+
if (!process.stdout.isTTY) return;
|
|
41860
|
+
process.stdout.write("\x1B[?1049h");
|
|
41861
|
+
process.stdout.write("\x1B[2J\x1B[H");
|
|
41862
|
+
return () => {
|
|
41863
|
+
process.stdout.write("\x1B[?1049l");
|
|
41864
|
+
process.stdout.write("\x1B[?25h");
|
|
41865
|
+
};
|
|
41866
|
+
}, []);
|
|
41867
|
+
(0, import_react32.useEffect)(() => {
|
|
41868
|
+
if (prevPhaseRef.current !== state.phase && process.stdout.isTTY) {
|
|
41869
|
+
process.stdout.write("\x1B[2J\x1B[H");
|
|
41870
|
+
}
|
|
41871
|
+
prevPhaseRef.current = state.phase;
|
|
41872
|
+
}, [state.phase]);
|
|
41873
|
+
const handleResultsExit = (0, import_react32.useCallback)(() => {
|
|
41775
41874
|
if (state.phase === "results") {
|
|
41776
41875
|
const { result } = state;
|
|
41777
41876
|
if (result.action === "block" && config.mode === "block") {
|
|
@@ -41784,7 +41883,7 @@ var init_App2 = __esm({
|
|
|
41784
41883
|
}
|
|
41785
41884
|
exit();
|
|
41786
41885
|
}, [state, config, exit]);
|
|
41787
|
-
(0,
|
|
41886
|
+
(0, import_react32.useEffect)(() => {
|
|
41788
41887
|
if (state.phase === "empty") {
|
|
41789
41888
|
process.exitCode = 0;
|
|
41790
41889
|
const timer = setTimeout(() => exit(), 0);
|
|
@@ -41796,55 +41895,58 @@ var init_App2 = __esm({
|
|
|
41796
41895
|
return () => clearTimeout(timer);
|
|
41797
41896
|
}
|
|
41798
41897
|
}, [state, config, exit]);
|
|
41799
|
-
|
|
41800
|
-
|
|
41801
|
-
|
|
41802
|
-
|
|
41803
|
-
|
|
41804
|
-
|
|
41805
|
-
|
|
41806
|
-
|
|
41807
|
-
|
|
41808
|
-
|
|
41809
|
-
|
|
41810
|
-
|
|
41898
|
+
const content = (() => {
|
|
41899
|
+
switch (state.phase) {
|
|
41900
|
+
case "discovering":
|
|
41901
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Spinner2, { label: "Searching for dependencies..." });
|
|
41902
|
+
case "selecting":
|
|
41903
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
41904
|
+
ProjectSelector,
|
|
41905
|
+
{
|
|
41906
|
+
projects: state.projects,
|
|
41907
|
+
onConfirm: scanSelectedProjects,
|
|
41908
|
+
onCancel: () => {
|
|
41909
|
+
process.exitCode = 0;
|
|
41910
|
+
exit();
|
|
41911
|
+
}
|
|
41811
41912
|
}
|
|
41812
|
-
|
|
41813
|
-
|
|
41814
|
-
|
|
41815
|
-
|
|
41816
|
-
|
|
41817
|
-
|
|
41913
|
+
);
|
|
41914
|
+
case "scanning":
|
|
41915
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
41916
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
41917
|
+
ProgressBar,
|
|
41918
|
+
{
|
|
41919
|
+
value: state.done,
|
|
41920
|
+
total: state.total,
|
|
41921
|
+
label: state.currentBatch.length > 0 ? state.currentBatch[state.currentBatch.length - 1] : void 0
|
|
41922
|
+
}
|
|
41923
|
+
),
|
|
41924
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { dimColor: true, children: [
|
|
41925
|
+
"Scanning ",
|
|
41926
|
+
state.done,
|
|
41927
|
+
"/",
|
|
41928
|
+
state.total,
|
|
41929
|
+
" packages..."
|
|
41930
|
+
] })
|
|
41931
|
+
] });
|
|
41932
|
+
case "results":
|
|
41933
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
41934
|
+
InteractiveResultsView,
|
|
41818
41935
|
{
|
|
41819
|
-
|
|
41820
|
-
|
|
41821
|
-
|
|
41936
|
+
result: state.result,
|
|
41937
|
+
config,
|
|
41938
|
+
durationMs: state.durationMs,
|
|
41939
|
+
onExit: handleResultsExit,
|
|
41940
|
+
onBack: restartSelection ?? void 0
|
|
41822
41941
|
}
|
|
41823
|
-
)
|
|
41824
|
-
|
|
41825
|
-
|
|
41826
|
-
|
|
41827
|
-
|
|
41828
|
-
|
|
41829
|
-
|
|
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
|
-
}
|
|
41942
|
+
);
|
|
41943
|
+
case "empty":
|
|
41944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { dimColor: true, children: state.message });
|
|
41945
|
+
case "error":
|
|
41946
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ErrorView, { error: state.error });
|
|
41947
|
+
}
|
|
41948
|
+
})();
|
|
41949
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Box_default, { flexDirection: "column", height: termRows, children: content });
|
|
41848
41950
|
};
|
|
41849
41951
|
}
|
|
41850
41952
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@westbayberry/dg",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
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",
|