@westbayberry/dg 1.0.2 → 1.0.4
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/README.md +1 -1
- package/dist/index.mjs +40885 -0
- package/package.json +13 -5
- package/dist/index.js +0 -892
package/dist/index.js
DELETED
|
@@ -1,892 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/******/ (() => { // webpackBootstrap
|
|
3
|
-
/******/ "use strict";
|
|
4
|
-
/******/ var __webpack_modules__ = ({
|
|
5
|
-
|
|
6
|
-
/***/ 879:
|
|
7
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
11
|
-
exports.APIError = void 0;
|
|
12
|
-
exports.callAnalyzeAPI = callAnalyzeAPI;
|
|
13
|
-
class APIError extends Error {
|
|
14
|
-
constructor(message, statusCode, body) {
|
|
15
|
-
super(message);
|
|
16
|
-
this.statusCode = statusCode;
|
|
17
|
-
this.body = body;
|
|
18
|
-
this.name = "APIError";
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
exports.APIError = APIError;
|
|
22
|
-
const BATCH_SIZE = 15;
|
|
23
|
-
const MAX_RETRIES = 2;
|
|
24
|
-
const RETRY_DELAY_MS = 5000;
|
|
25
|
-
async function callAnalyzeAPI(packages, config, onProgress) {
|
|
26
|
-
if (packages.length <= BATCH_SIZE) {
|
|
27
|
-
return callAnalyzeBatch(packages, config);
|
|
28
|
-
}
|
|
29
|
-
const batches = [];
|
|
30
|
-
for (let i = 0; i < packages.length; i += BATCH_SIZE) {
|
|
31
|
-
batches.push(packages.slice(i, i + BATCH_SIZE));
|
|
32
|
-
}
|
|
33
|
-
// Process batches sequentially — parallel batches overload the server on cold scans
|
|
34
|
-
const results = [];
|
|
35
|
-
let completed = 0;
|
|
36
|
-
for (const batch of batches) {
|
|
37
|
-
const result = await callBatchWithRetry(batch, config);
|
|
38
|
-
completed += batch.length;
|
|
39
|
-
if (onProgress) {
|
|
40
|
-
onProgress(completed, packages.length);
|
|
41
|
-
}
|
|
42
|
-
results.push(result);
|
|
43
|
-
}
|
|
44
|
-
return mergeResponses(results, config);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Retry a batch on 504 (gateway timeout). The server continues processing
|
|
48
|
-
* during a timeout, so retries find previously-analyzed packages cached
|
|
49
|
-
* in Redis — fewer cold packages means faster response.
|
|
50
|
-
*/
|
|
51
|
-
async function callBatchWithRetry(packages, config) {
|
|
52
|
-
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
53
|
-
try {
|
|
54
|
-
return await callAnalyzeBatch(packages, config);
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
const is504 = error instanceof APIError && error.statusCode === 504;
|
|
58
|
-
const isTimeout = error instanceof APIError && error.statusCode === 408;
|
|
59
|
-
if ((is504 || isTimeout) && attempt < MAX_RETRIES) {
|
|
60
|
-
// Server is still working — wait, then retry.
|
|
61
|
-
// Packages that finished before the timeout are now cached.
|
|
62
|
-
const delay = RETRY_DELAY_MS * (attempt + 1);
|
|
63
|
-
process.stderr.write(` Batch timed out, retrying in ${delay / 1000}s (attempt ${attempt + 2}/${MAX_RETRIES + 1})...\n`);
|
|
64
|
-
await new Promise((r) => setTimeout(r, delay));
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
throw error;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
// Unreachable, but TypeScript needs it
|
|
71
|
-
throw new Error("Exhausted retries");
|
|
72
|
-
}
|
|
73
|
-
function mergeResponses(results, config) {
|
|
74
|
-
const allPackages = results.flatMap((r) => r.packages);
|
|
75
|
-
const maxScore = Math.max(0, ...allPackages.map((p) => p.score));
|
|
76
|
-
const action = maxScore >= config.blockThreshold
|
|
77
|
-
? "block"
|
|
78
|
-
: maxScore >= config.warnThreshold
|
|
79
|
-
? "warn"
|
|
80
|
-
: "pass";
|
|
81
|
-
const safeVersions = {};
|
|
82
|
-
for (const r of results) {
|
|
83
|
-
Object.assign(safeVersions, r.safeVersions);
|
|
84
|
-
}
|
|
85
|
-
return {
|
|
86
|
-
score: maxScore,
|
|
87
|
-
action: action,
|
|
88
|
-
packages: allPackages,
|
|
89
|
-
safeVersions,
|
|
90
|
-
durationMs: Math.max(0, ...results.map((r) => r.durationMs)),
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
async function callAnalyzeBatch(packages, config) {
|
|
94
|
-
const url = `${config.apiUrl}/v1/analyze`;
|
|
95
|
-
const payload = {
|
|
96
|
-
packages: packages.map((p) => ({
|
|
97
|
-
name: p.name,
|
|
98
|
-
version: p.version,
|
|
99
|
-
previousVersion: p.previousVersion,
|
|
100
|
-
isNew: p.isNew,
|
|
101
|
-
})),
|
|
102
|
-
config: {
|
|
103
|
-
blockThreshold: config.blockThreshold,
|
|
104
|
-
warnThreshold: config.warnThreshold,
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
const controller = new AbortController();
|
|
108
|
-
const timeoutId = setTimeout(() => controller.abort(), 120000);
|
|
109
|
-
let response;
|
|
110
|
-
try {
|
|
111
|
-
response = await fetch(url, {
|
|
112
|
-
method: "POST",
|
|
113
|
-
headers: {
|
|
114
|
-
"Content-Type": "application/json",
|
|
115
|
-
Authorization: `Bearer ${config.apiKey}`,
|
|
116
|
-
"User-Agent": "dependency-guardian-cli/1.0.0",
|
|
117
|
-
},
|
|
118
|
-
body: JSON.stringify(payload),
|
|
119
|
-
signal: controller.signal,
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
clearTimeout(timeoutId);
|
|
124
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
125
|
-
throw new APIError("Request timed out after 120s. Try scanning fewer packages.", 408, "");
|
|
126
|
-
}
|
|
127
|
-
// Node.js fetch wraps the real error in .cause
|
|
128
|
-
const cause = error instanceof Error && error.cause;
|
|
129
|
-
const detail = cause ? `: ${cause.message || cause}` : "";
|
|
130
|
-
throw new Error(`fetch failed${detail}`);
|
|
131
|
-
}
|
|
132
|
-
clearTimeout(timeoutId);
|
|
133
|
-
if (response.status === 401) {
|
|
134
|
-
throw new APIError("Invalid API key. Check your --api-key or DG_API_KEY value.\n" +
|
|
135
|
-
"Get your key at https://westbayberry.com/dashboard", 401, "");
|
|
136
|
-
}
|
|
137
|
-
if (response.status === 429) {
|
|
138
|
-
throw new APIError("Rate limit exceeded. Upgrade your plan at https://westbayberry.com/pricing", 429, "");
|
|
139
|
-
}
|
|
140
|
-
if (!response.ok) {
|
|
141
|
-
const body = await response.text();
|
|
142
|
-
throw new APIError(`API returned ${response.status}: ${body}`, response.status, body);
|
|
143
|
-
}
|
|
144
|
-
return (await response.json());
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
/***/ }),
|
|
149
|
-
|
|
150
|
-
/***/ 988:
|
|
151
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Zero-dependency ANSI color helpers.
|
|
156
|
-
* Disabled when stdout is not a TTY or NO_COLOR is set.
|
|
157
|
-
*/
|
|
158
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
159
|
-
exports.cyan = exports.yellow = exports.green = exports.red = exports.dim = exports.bold = void 0;
|
|
160
|
-
const enabled = process.stdout.isTTY === true && !process.env.NO_COLOR;
|
|
161
|
-
const wrap = (code, reset) => enabled ? (s) => `\x1b[${code}m${s}\x1b[${reset}m` : (s) => s;
|
|
162
|
-
exports.bold = wrap("1", "22");
|
|
163
|
-
exports.dim = wrap("2", "22");
|
|
164
|
-
exports.red = wrap("31", "39");
|
|
165
|
-
exports.green = wrap("32", "39");
|
|
166
|
-
exports.yellow = wrap("33", "39");
|
|
167
|
-
exports.cyan = wrap("36", "39");
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
/***/ }),
|
|
171
|
-
|
|
172
|
-
/***/ 973:
|
|
173
|
-
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
177
|
-
exports.USAGE = void 0;
|
|
178
|
-
exports.parseConfig = parseConfig;
|
|
179
|
-
exports.getVersion = getVersion;
|
|
180
|
-
const node_util_1 = __nccwpck_require__(975);
|
|
181
|
-
const node_fs_1 = __nccwpck_require__(24);
|
|
182
|
-
const node_path_1 = __nccwpck_require__(760);
|
|
183
|
-
const USAGE = `
|
|
184
|
-
Dependency Guardian — Supply chain security scanner
|
|
185
|
-
|
|
186
|
-
Usage:
|
|
187
|
-
dependency-guardian scan [options]
|
|
188
|
-
dg scan [options]
|
|
189
|
-
|
|
190
|
-
Commands:
|
|
191
|
-
scan Scan dependencies for security risks (default)
|
|
192
|
-
|
|
193
|
-
Options:
|
|
194
|
-
--api-key <key> API key (or set DG_API_KEY env var)
|
|
195
|
-
--api-url <url> API base URL (default: https://api.westbayberry.com)
|
|
196
|
-
--mode <mode> block | warn | off (default: warn)
|
|
197
|
-
--block-threshold <n> Score threshold for blocking (default: 70)
|
|
198
|
-
--warn-threshold <n> Score threshold for warnings (default: 60)
|
|
199
|
-
--max-packages <n> Max packages per scan (default: 200)
|
|
200
|
-
--allowlist <pkgs> Comma-separated package names to skip
|
|
201
|
-
--json Output JSON for CI parsing
|
|
202
|
-
--scan-all Scan all packages, not just changed
|
|
203
|
-
--base-lockfile <path> Path to base lockfile for explicit diff
|
|
204
|
-
--help Show this help message
|
|
205
|
-
--version Show version number
|
|
206
|
-
|
|
207
|
-
Environment Variables:
|
|
208
|
-
DG_API_KEY API key
|
|
209
|
-
DG_API_URL API base URL
|
|
210
|
-
DG_MODE Mode (block/warn/off)
|
|
211
|
-
DG_ALLOWLIST Comma-separated allowlist
|
|
212
|
-
|
|
213
|
-
Exit Codes:
|
|
214
|
-
0 pass — No risks detected
|
|
215
|
-
1 warn — Risks detected (advisory)
|
|
216
|
-
2 block — High-risk packages detected
|
|
217
|
-
|
|
218
|
-
Examples:
|
|
219
|
-
DG_API_KEY=dg_live_xxx dg scan
|
|
220
|
-
dg scan --api-key dg_live_xxx --json
|
|
221
|
-
dg scan --scan-all --mode block
|
|
222
|
-
dg scan --base-lockfile ./main-lockfile.json
|
|
223
|
-
`.trimStart();
|
|
224
|
-
exports.USAGE = USAGE;
|
|
225
|
-
function getVersion() {
|
|
226
|
-
try {
|
|
227
|
-
const pkg = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, "..", "package.json"), "utf-8"));
|
|
228
|
-
return pkg.version ?? "1.0.0";
|
|
229
|
-
}
|
|
230
|
-
catch {
|
|
231
|
-
return "1.0.0";
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
function parseConfig(argv) {
|
|
235
|
-
const { values, positionals } = (0, node_util_1.parseArgs)({
|
|
236
|
-
args: argv.slice(2),
|
|
237
|
-
options: {
|
|
238
|
-
"api-key": { type: "string" },
|
|
239
|
-
"api-url": { type: "string" },
|
|
240
|
-
mode: { type: "string" },
|
|
241
|
-
"block-threshold": { type: "string" },
|
|
242
|
-
"warn-threshold": { type: "string" },
|
|
243
|
-
"max-packages": { type: "string" },
|
|
244
|
-
allowlist: { type: "string" },
|
|
245
|
-
json: { type: "boolean", default: false },
|
|
246
|
-
"scan-all": { type: "boolean", default: false },
|
|
247
|
-
"base-lockfile": { type: "string" },
|
|
248
|
-
help: { type: "boolean", default: false },
|
|
249
|
-
version: { type: "boolean", default: false },
|
|
250
|
-
},
|
|
251
|
-
allowPositionals: true,
|
|
252
|
-
strict: false,
|
|
253
|
-
});
|
|
254
|
-
if (values.help) {
|
|
255
|
-
process.stdout.write(USAGE);
|
|
256
|
-
process.exit(0);
|
|
257
|
-
}
|
|
258
|
-
if (values.version) {
|
|
259
|
-
process.stdout.write(`dependency-guardian v${getVersion()}\n`);
|
|
260
|
-
process.exit(0);
|
|
261
|
-
}
|
|
262
|
-
const command = positionals[0] ?? "scan";
|
|
263
|
-
if (values["api-key"]) {
|
|
264
|
-
process.stderr.write("Warning: --api-key is deprecated (visible in process list). Use DG_API_KEY env var instead.\n");
|
|
265
|
-
}
|
|
266
|
-
const apiKey = values["api-key"] ??
|
|
267
|
-
process.env.DG_API_KEY ??
|
|
268
|
-
"";
|
|
269
|
-
if (!apiKey) {
|
|
270
|
-
process.stderr.write("Error: API key required. Set DG_API_KEY environment variable.\n" +
|
|
271
|
-
"Do NOT pass keys via --api-key (visible in process list).\n" +
|
|
272
|
-
"Get your key at https://westbayberry.com/dashboard\n");
|
|
273
|
-
process.exit(1);
|
|
274
|
-
}
|
|
275
|
-
const modeRaw = values.mode ??
|
|
276
|
-
process.env.DG_MODE ??
|
|
277
|
-
"warn";
|
|
278
|
-
if (!["block", "warn", "off"].includes(modeRaw)) {
|
|
279
|
-
process.stderr.write(`Error: Invalid mode "${modeRaw}". Must be block, warn, or off.\n`);
|
|
280
|
-
process.exit(1);
|
|
281
|
-
}
|
|
282
|
-
const allowlistRaw = values.allowlist ??
|
|
283
|
-
process.env.DG_ALLOWLIST ??
|
|
284
|
-
"";
|
|
285
|
-
return {
|
|
286
|
-
apiKey,
|
|
287
|
-
apiUrl: values["api-url"] ??
|
|
288
|
-
process.env.DG_API_URL ??
|
|
289
|
-
"https://api.westbayberry.com",
|
|
290
|
-
mode: modeRaw,
|
|
291
|
-
blockThreshold: Number(values["block-threshold"] ?? "70"),
|
|
292
|
-
warnThreshold: Number(values["warn-threshold"] ?? "60"),
|
|
293
|
-
maxPackages: Number(values["max-packages"] ?? "200"),
|
|
294
|
-
allowlist: allowlistRaw
|
|
295
|
-
.split(",")
|
|
296
|
-
.map((s) => s.trim())
|
|
297
|
-
.filter(Boolean),
|
|
298
|
-
json: values.json,
|
|
299
|
-
scanAll: values["scan-all"],
|
|
300
|
-
baseLockfile: values["base-lockfile"] ?? null,
|
|
301
|
-
command,
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
/***/ }),
|
|
307
|
-
|
|
308
|
-
/***/ 746:
|
|
309
|
-
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
313
|
-
exports.discoverChanges = discoverChanges;
|
|
314
|
-
const node_child_process_1 = __nccwpck_require__(421);
|
|
315
|
-
const node_fs_1 = __nccwpck_require__(24);
|
|
316
|
-
const node_path_1 = __nccwpck_require__(760);
|
|
317
|
-
const parse_package_lock_1 = __nccwpck_require__(88);
|
|
318
|
-
const diff_1 = __nccwpck_require__(229);
|
|
319
|
-
const parse_package_json_1 = __nccwpck_require__(417);
|
|
320
|
-
/**
|
|
321
|
-
* Discover changed (or all) packages by reading the local lockfile
|
|
322
|
-
* and comparing against a base.
|
|
323
|
-
*/
|
|
324
|
-
function discoverChanges(cwd, config) {
|
|
325
|
-
const lockfilePath = findLockfile(cwd);
|
|
326
|
-
if (!lockfilePath) {
|
|
327
|
-
throw new Error("No package-lock.json found. Run from your project root or use --base-lockfile.");
|
|
328
|
-
}
|
|
329
|
-
const headContent = (0, node_fs_1.readFileSync)(lockfilePath, "utf-8");
|
|
330
|
-
const headParsed = (0, parse_package_lock_1.parseLockfile)(headContent);
|
|
331
|
-
const directDeps = getDirectDeps(cwd);
|
|
332
|
-
// 1. --scan-all: treat everything as new
|
|
333
|
-
if (config.scanAll) {
|
|
334
|
-
const packages = [];
|
|
335
|
-
for (const [name, entry] of headParsed.packages) {
|
|
336
|
-
if (packages.length >= config.maxPackages)
|
|
337
|
-
break;
|
|
338
|
-
packages.push({
|
|
339
|
-
name,
|
|
340
|
-
version: entry.version,
|
|
341
|
-
previousVersion: null,
|
|
342
|
-
isNew: true,
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
return { packages, method: "scan-all", skipped: [] };
|
|
346
|
-
}
|
|
347
|
-
// 2. --base-lockfile: explicit diff
|
|
348
|
-
if (config.baseLockfile) {
|
|
349
|
-
if (!(0, node_fs_1.existsSync)(config.baseLockfile)) {
|
|
350
|
-
throw new Error(`Base lockfile not found: ${config.baseLockfile}`);
|
|
351
|
-
}
|
|
352
|
-
const baseContent = (0, node_fs_1.readFileSync)(config.baseLockfile, "utf-8");
|
|
353
|
-
const baseParsed = (0, parse_package_lock_1.parseLockfile)(baseContent);
|
|
354
|
-
const diff = (0, diff_1.diffLockfiles)(baseParsed, headParsed, config.maxPackages, directDeps);
|
|
355
|
-
return {
|
|
356
|
-
packages: diff.changes.map(toPackageInput),
|
|
357
|
-
method: "base-lockfile",
|
|
358
|
-
skipped: diff.skipped,
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
// 3. Git auto-diff
|
|
362
|
-
const baseContent = getGitBaseLockfile(cwd);
|
|
363
|
-
if (baseContent !== null) {
|
|
364
|
-
const baseParsed = (0, parse_package_lock_1.parseLockfile)(baseContent);
|
|
365
|
-
const diff = (0, diff_1.diffLockfiles)(baseParsed, headParsed, config.maxPackages, directDeps);
|
|
366
|
-
return {
|
|
367
|
-
packages: diff.changes.map(toPackageInput),
|
|
368
|
-
method: "git-diff",
|
|
369
|
-
skipped: diff.skipped,
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
// 4. Fallback: try package.json diff, resolve ranges via lockfile
|
|
373
|
-
const pkgJsonPath = (0, node_path_1.join)(cwd, "package.json");
|
|
374
|
-
if ((0, node_fs_1.existsSync)(pkgJsonPath)) {
|
|
375
|
-
const headPkgJson = (0, node_fs_1.readFileSync)(pkgJsonPath, "utf-8");
|
|
376
|
-
const basePkgJson = getGitBaseFile(cwd, "package.json");
|
|
377
|
-
if (basePkgJson !== null) {
|
|
378
|
-
const diff = (0, parse_package_json_1.diffPackageJsons)(basePkgJson, headPkgJson, config.maxPackages);
|
|
379
|
-
// Resolve semver ranges (e.g. "^3.0.1") to exact versions from the lockfile
|
|
380
|
-
const resolved = diff.changes.map((change) => {
|
|
381
|
-
const lockEntry = headParsed.packages.get(change.name);
|
|
382
|
-
return {
|
|
383
|
-
...change,
|
|
384
|
-
newVersion: lockEntry?.version ?? change.newVersion,
|
|
385
|
-
};
|
|
386
|
-
});
|
|
387
|
-
return {
|
|
388
|
-
packages: resolved.map(toPackageInput),
|
|
389
|
-
method: "fallback",
|
|
390
|
-
skipped: [],
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
// Ultimate fallback: scan everything
|
|
395
|
-
const packages = [];
|
|
396
|
-
for (const [name, entry] of headParsed.packages) {
|
|
397
|
-
if (packages.length >= config.maxPackages)
|
|
398
|
-
break;
|
|
399
|
-
packages.push({
|
|
400
|
-
name,
|
|
401
|
-
version: entry.version,
|
|
402
|
-
previousVersion: null,
|
|
403
|
-
isNew: true,
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
return { packages, method: "fallback", skipped: [] };
|
|
407
|
-
}
|
|
408
|
-
function findLockfile(cwd) {
|
|
409
|
-
const candidates = ["package-lock.json", "npm-shrinkwrap.json"];
|
|
410
|
-
for (const name of candidates) {
|
|
411
|
-
const p = (0, node_path_1.join)(cwd, name);
|
|
412
|
-
if ((0, node_fs_1.existsSync)(p))
|
|
413
|
-
return p;
|
|
414
|
-
}
|
|
415
|
-
return null;
|
|
416
|
-
}
|
|
417
|
-
function getDirectDeps(cwd) {
|
|
418
|
-
try {
|
|
419
|
-
const content = (0, node_fs_1.readFileSync)((0, node_path_1.join)(cwd, "package.json"), "utf-8");
|
|
420
|
-
const pkg = JSON.parse(content);
|
|
421
|
-
return new Set([
|
|
422
|
-
...Object.keys(pkg.dependencies ?? {}),
|
|
423
|
-
...Object.keys(pkg.devDependencies ?? {}),
|
|
424
|
-
]);
|
|
425
|
-
}
|
|
426
|
-
catch {
|
|
427
|
-
return new Set();
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
function getGitBaseLockfile(cwd) {
|
|
431
|
-
try {
|
|
432
|
-
const mergeBase = (0, node_child_process_1.execSync)("git merge-base HEAD main", {
|
|
433
|
-
cwd,
|
|
434
|
-
encoding: "utf-8",
|
|
435
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
436
|
-
}).trim();
|
|
437
|
-
if (!mergeBase)
|
|
438
|
-
return null;
|
|
439
|
-
return (0, node_child_process_1.execSync)(`git show ${mergeBase}:package-lock.json`, {
|
|
440
|
-
cwd,
|
|
441
|
-
encoding: "utf-8",
|
|
442
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
catch {
|
|
446
|
-
// Not a git repo, no main branch, or file doesn't exist at base
|
|
447
|
-
return null;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
function getGitBaseFile(cwd, filename) {
|
|
451
|
-
try {
|
|
452
|
-
const mergeBase = (0, node_child_process_1.execSync)("git merge-base HEAD main", {
|
|
453
|
-
cwd,
|
|
454
|
-
encoding: "utf-8",
|
|
455
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
456
|
-
}).trim();
|
|
457
|
-
if (!mergeBase)
|
|
458
|
-
return null;
|
|
459
|
-
return (0, node_child_process_1.execSync)(`git show ${mergeBase}:${filename}`, {
|
|
460
|
-
cwd,
|
|
461
|
-
encoding: "utf-8",
|
|
462
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
catch {
|
|
466
|
-
return null;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
function toPackageInput(change) {
|
|
470
|
-
return {
|
|
471
|
-
name: change.name,
|
|
472
|
-
version: change.newVersion,
|
|
473
|
-
previousVersion: change.oldVersion,
|
|
474
|
-
isNew: change.oldVersion === null,
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
/***/ }),
|
|
480
|
-
|
|
481
|
-
/***/ 202:
|
|
482
|
-
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
486
|
-
exports.renderResult = renderResult;
|
|
487
|
-
const color_1 = __nccwpck_require__(988);
|
|
488
|
-
const SEVERITY_LABELS = {
|
|
489
|
-
5: "CRITICAL",
|
|
490
|
-
4: "HIGH",
|
|
491
|
-
3: "MEDIUM",
|
|
492
|
-
2: "LOW",
|
|
493
|
-
1: "INFO",
|
|
494
|
-
};
|
|
495
|
-
function severityColor(sev) {
|
|
496
|
-
if (sev >= 5)
|
|
497
|
-
return (s) => (0, color_1.bold)((0, color_1.red)(s));
|
|
498
|
-
if (sev >= 4)
|
|
499
|
-
return color_1.red;
|
|
500
|
-
if (sev >= 3)
|
|
501
|
-
return color_1.yellow;
|
|
502
|
-
if (sev >= 2)
|
|
503
|
-
return color_1.cyan;
|
|
504
|
-
return color_1.dim;
|
|
505
|
-
}
|
|
506
|
-
function actionColor(action) {
|
|
507
|
-
if (action === "block")
|
|
508
|
-
return color_1.red;
|
|
509
|
-
if (action === "warn")
|
|
510
|
-
return color_1.yellow;
|
|
511
|
-
return color_1.green;
|
|
512
|
-
}
|
|
513
|
-
function pad(s, len) {
|
|
514
|
-
return s + " ".repeat(Math.max(0, len - s.length));
|
|
515
|
-
}
|
|
516
|
-
function rpad(s, len) {
|
|
517
|
-
return " ".repeat(Math.max(0, len - s.length)) + s;
|
|
518
|
-
}
|
|
519
|
-
function renderResult(result, config) {
|
|
520
|
-
if (config.json) {
|
|
521
|
-
return JSON.stringify(result, null, 2);
|
|
522
|
-
}
|
|
523
|
-
const lines = [];
|
|
524
|
-
const actionStr = result.action.toUpperCase();
|
|
525
|
-
const colorAction = actionColor(result.action);
|
|
526
|
-
// Header
|
|
527
|
-
lines.push("");
|
|
528
|
-
lines.push(` ${(0, color_1.bold)("Dependency Guardian")}`);
|
|
529
|
-
lines.push(` Score: ${(0, color_1.bold)(String(result.score))}${" ".repeat(Math.max(1, 50 - String(result.score).length))}${colorAction(actionStr)}`);
|
|
530
|
-
lines.push("");
|
|
531
|
-
// Summary
|
|
532
|
-
const flagged = result.packages.filter((p) => p.score > 0).length;
|
|
533
|
-
const total = result.packages.length;
|
|
534
|
-
lines.push(` ${total} package${total !== 1 ? "s" : ""} scanned, ${flagged} flagged`);
|
|
535
|
-
lines.push("");
|
|
536
|
-
if (total === 0) {
|
|
537
|
-
lines.push(" No packages to scan.");
|
|
538
|
-
lines.push("");
|
|
539
|
-
return lines.join("\n");
|
|
540
|
-
}
|
|
541
|
-
// Package table
|
|
542
|
-
const COL_NAME = 22;
|
|
543
|
-
const COL_VER = 22;
|
|
544
|
-
const COL_SCORE = 7;
|
|
545
|
-
lines.push(` ${(0, color_1.dim)(pad("Package", COL_NAME))}${(0, color_1.dim)(pad("Version", COL_VER))}${(0, color_1.dim)(pad("Score", COL_SCORE))}${(0, color_1.dim)("Action")}`);
|
|
546
|
-
lines.push(` ${(0, color_1.dim)(pad("\u2500".repeat(COL_NAME - 2), COL_NAME))}${(0, color_1.dim)(pad("\u2500".repeat(COL_VER - 2), COL_VER))}${(0, color_1.dim)(pad("\u2500".repeat(COL_SCORE - 2), COL_SCORE))}${(0, color_1.dim)("\u2500".repeat(6))}`);
|
|
547
|
-
// Sort: flagged first, then by score desc
|
|
548
|
-
const sorted = [...result.packages].sort((a, b) => b.score - a.score);
|
|
549
|
-
for (const pkg of sorted) {
|
|
550
|
-
const versionStr = pkg.version;
|
|
551
|
-
const safe = result.safeVersions[pkg.name];
|
|
552
|
-
const verDisplay = safe ? `${(0, color_1.dim)(safe + " \u2192 ")}${versionStr}` : versionStr;
|
|
553
|
-
const pkgAction = pkg.score >= config.blockThreshold
|
|
554
|
-
? "BLOCK"
|
|
555
|
-
: pkg.score >= config.warnThreshold
|
|
556
|
-
? "WARN"
|
|
557
|
-
: "pass";
|
|
558
|
-
const pkgColor = actionColor(pkg.score >= config.blockThreshold
|
|
559
|
-
? "block"
|
|
560
|
-
: pkg.score >= config.warnThreshold
|
|
561
|
-
? "warn"
|
|
562
|
-
: "pass");
|
|
563
|
-
lines.push(` ${pad(truncate(pkg.name, COL_NAME - 2), COL_NAME)}${pad(verDisplay, COL_VER)}${rpad(String(pkg.score), COL_SCORE - 2)} ${pkgColor(pkgAction)}`);
|
|
564
|
-
}
|
|
565
|
-
lines.push("");
|
|
566
|
-
// Detailed findings for flagged packages
|
|
567
|
-
const flaggedPkgs = sorted.filter((p) => p.score > 0);
|
|
568
|
-
for (const pkg of flaggedPkgs) {
|
|
569
|
-
lines.push(renderPackageDetail(pkg, result.safeVersions[pkg.name]));
|
|
570
|
-
}
|
|
571
|
-
// Duration
|
|
572
|
-
if (result.durationMs) {
|
|
573
|
-
lines.push(` ${(0, color_1.dim)(`Completed in ${(result.durationMs / 1000).toFixed(1)}s`)}`);
|
|
574
|
-
lines.push("");
|
|
575
|
-
}
|
|
576
|
-
return lines.join("\n");
|
|
577
|
-
}
|
|
578
|
-
function renderPackageDetail(pkg, safeVersion) {
|
|
579
|
-
const lines = [];
|
|
580
|
-
const header = `${pkg.name}@${pkg.version} (score: ${pkg.score})`;
|
|
581
|
-
const rule = "\u2500".repeat(Math.max(0, 50 - header.length));
|
|
582
|
-
lines.push(` ${(0, color_1.dim)("\u2500\u2500")} ${(0, color_1.bold)(header)} ${(0, color_1.dim)(rule)}`);
|
|
583
|
-
lines.push("");
|
|
584
|
-
for (const finding of pkg.findings) {
|
|
585
|
-
// Skip low-severity informational findings in detail view
|
|
586
|
-
if (finding.severity <= 1 && !finding.critical)
|
|
587
|
-
continue;
|
|
588
|
-
const sevLabel = SEVERITY_LABELS[finding.severity] ?? "INFO";
|
|
589
|
-
const colorFn = severityColor(finding.severity);
|
|
590
|
-
lines.push(` ${colorFn(pad(sevLabel, 10))}${finding.id} \u2014 ${finding.title} (sev ${finding.severity}, conf ${finding.confidence.toFixed(2)})`);
|
|
591
|
-
// Show up to 3 evidence lines
|
|
592
|
-
const evidenceLimit = 3;
|
|
593
|
-
for (let i = 0; i < Math.min(finding.evidence.length, evidenceLimit); i++) {
|
|
594
|
-
lines.push(` ${" ".repeat(10)}${(0, color_1.dim)(truncate(finding.evidence[i], 80))}`);
|
|
595
|
-
}
|
|
596
|
-
if (finding.evidence.length > evidenceLimit) {
|
|
597
|
-
lines.push(` ${" ".repeat(10)}${(0, color_1.dim)(`... and ${finding.evidence.length - evidenceLimit} more`)}`);
|
|
598
|
-
}
|
|
599
|
-
lines.push("");
|
|
600
|
-
}
|
|
601
|
-
if (safeVersion) {
|
|
602
|
-
lines.push(` ${(0, color_1.green)(`Safe version: ${pkg.name}@${safeVersion}`)}`);
|
|
603
|
-
lines.push("");
|
|
604
|
-
}
|
|
605
|
-
return lines.join("\n");
|
|
606
|
-
}
|
|
607
|
-
function truncate(s, max) {
|
|
608
|
-
if (s.length <= max)
|
|
609
|
-
return s;
|
|
610
|
-
return s.slice(0, max - 1) + "\u2026";
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
/***/ }),
|
|
615
|
-
|
|
616
|
-
/***/ 229:
|
|
617
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
621
|
-
exports.diffLockfiles = diffLockfiles;
|
|
622
|
-
function diffLockfiles(base, head, maxPackages, directDeps) {
|
|
623
|
-
const allChanges = [];
|
|
624
|
-
for (const [name, headEntry] of head.packages) {
|
|
625
|
-
const baseEntry = base?.packages.get(name);
|
|
626
|
-
if (!baseEntry) {
|
|
627
|
-
allChanges.push({
|
|
628
|
-
name,
|
|
629
|
-
oldVersion: null,
|
|
630
|
-
newVersion: headEntry.version,
|
|
631
|
-
isDirect: directDeps?.has(name) ?? false,
|
|
632
|
-
isDev: headEntry.dev ?? false,
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
else if (baseEntry.version !== headEntry.version) {
|
|
636
|
-
allChanges.push({
|
|
637
|
-
name,
|
|
638
|
-
oldVersion: baseEntry.version,
|
|
639
|
-
newVersion: headEntry.version,
|
|
640
|
-
isDirect: directDeps?.has(name) ?? false,
|
|
641
|
-
isDev: headEntry.dev ?? false,
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
allChanges.sort((a, b) => {
|
|
646
|
-
if (a.isDirect !== b.isDirect)
|
|
647
|
-
return a.isDirect ? -1 : 1;
|
|
648
|
-
return a.name.localeCompare(b.name);
|
|
649
|
-
});
|
|
650
|
-
if (allChanges.length <= maxPackages) {
|
|
651
|
-
return { changes: allChanges, skipped: [] };
|
|
652
|
-
}
|
|
653
|
-
const changes = allChanges.slice(0, maxPackages);
|
|
654
|
-
const skipped = allChanges.slice(maxPackages).map((c) => c.name);
|
|
655
|
-
return { changes, skipped };
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
/***/ }),
|
|
660
|
-
|
|
661
|
-
/***/ 417:
|
|
662
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
666
|
-
exports.diffPackageJsons = diffPackageJsons;
|
|
667
|
-
function diffPackageJsons(baseContent, headContent, maxPackages) {
|
|
668
|
-
const head = JSON.parse(headContent);
|
|
669
|
-
const headDeps = {
|
|
670
|
-
...head.dependencies,
|
|
671
|
-
...head.devDependencies,
|
|
672
|
-
};
|
|
673
|
-
let baseDeps = {};
|
|
674
|
-
if (baseContent) {
|
|
675
|
-
const base = JSON.parse(baseContent);
|
|
676
|
-
baseDeps = { ...base.dependencies, ...base.devDependencies };
|
|
677
|
-
}
|
|
678
|
-
const changes = [];
|
|
679
|
-
for (const [name, version] of Object.entries(headDeps)) {
|
|
680
|
-
if (changes.length >= maxPackages)
|
|
681
|
-
break;
|
|
682
|
-
const baseVersion = baseDeps[name];
|
|
683
|
-
const isDev = !!(head.devDependencies && head.devDependencies[name]);
|
|
684
|
-
if (!baseVersion) {
|
|
685
|
-
changes.push({
|
|
686
|
-
name,
|
|
687
|
-
oldVersion: null,
|
|
688
|
-
newVersion: version,
|
|
689
|
-
isDirect: true,
|
|
690
|
-
isDev,
|
|
691
|
-
});
|
|
692
|
-
}
|
|
693
|
-
else if (baseVersion !== version) {
|
|
694
|
-
changes.push({
|
|
695
|
-
name,
|
|
696
|
-
oldVersion: baseVersion,
|
|
697
|
-
newVersion: version,
|
|
698
|
-
isDirect: true,
|
|
699
|
-
isDev,
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
return { changes };
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
/***/ }),
|
|
708
|
-
|
|
709
|
-
/***/ 88:
|
|
710
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
714
|
-
exports.parseLockfile = parseLockfile;
|
|
715
|
-
function parseLockfile(content) {
|
|
716
|
-
const json = JSON.parse(content);
|
|
717
|
-
const lockfileVersion = json.lockfileVersion ?? 1;
|
|
718
|
-
const packages = new Map();
|
|
719
|
-
if (lockfileVersion >= 2 && json.packages) {
|
|
720
|
-
for (const [path, entry] of Object.entries(json.packages)) {
|
|
721
|
-
if (path === "")
|
|
722
|
-
continue;
|
|
723
|
-
const name = extractPackageName(path);
|
|
724
|
-
if (name) {
|
|
725
|
-
const e = entry;
|
|
726
|
-
packages.set(name, {
|
|
727
|
-
version: e.version ?? "",
|
|
728
|
-
resolved: e.resolved,
|
|
729
|
-
integrity: e.integrity,
|
|
730
|
-
dev: e.dev,
|
|
731
|
-
});
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
else if (json.dependencies) {
|
|
736
|
-
parseLegacyDeps(json.dependencies, packages);
|
|
737
|
-
}
|
|
738
|
-
return { lockfileVersion, packages };
|
|
739
|
-
}
|
|
740
|
-
function extractPackageName(nodePath) {
|
|
741
|
-
const prefix = "node_modules/";
|
|
742
|
-
const lastIdx = nodePath.lastIndexOf(prefix);
|
|
743
|
-
if (lastIdx === -1)
|
|
744
|
-
return null;
|
|
745
|
-
const name = nodePath.slice(lastIdx + prefix.length);
|
|
746
|
-
return name || null;
|
|
747
|
-
}
|
|
748
|
-
function parseLegacyDeps(deps, packages, parentPrefix = "") {
|
|
749
|
-
for (const [name, value] of Object.entries(deps)) {
|
|
750
|
-
const fullName = parentPrefix ? `${parentPrefix}/${name}` : name;
|
|
751
|
-
const entry = value;
|
|
752
|
-
packages.set(fullName, {
|
|
753
|
-
version: entry.version ?? "",
|
|
754
|
-
resolved: entry.resolved,
|
|
755
|
-
integrity: entry.integrity,
|
|
756
|
-
dev: entry.dev,
|
|
757
|
-
});
|
|
758
|
-
if (entry.dependencies) {
|
|
759
|
-
parseLegacyDeps(entry.dependencies, packages);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
/***/ }),
|
|
766
|
-
|
|
767
|
-
/***/ 421:
|
|
768
|
-
/***/ ((module) => {
|
|
769
|
-
|
|
770
|
-
module.exports = require("node:child_process");
|
|
771
|
-
|
|
772
|
-
/***/ }),
|
|
773
|
-
|
|
774
|
-
/***/ 24:
|
|
775
|
-
/***/ ((module) => {
|
|
776
|
-
|
|
777
|
-
module.exports = require("node:fs");
|
|
778
|
-
|
|
779
|
-
/***/ }),
|
|
780
|
-
|
|
781
|
-
/***/ 760:
|
|
782
|
-
/***/ ((module) => {
|
|
783
|
-
|
|
784
|
-
module.exports = require("node:path");
|
|
785
|
-
|
|
786
|
-
/***/ }),
|
|
787
|
-
|
|
788
|
-
/***/ 975:
|
|
789
|
-
/***/ ((module) => {
|
|
790
|
-
|
|
791
|
-
module.exports = require("node:util");
|
|
792
|
-
|
|
793
|
-
/***/ })
|
|
794
|
-
|
|
795
|
-
/******/ });
|
|
796
|
-
/************************************************************************/
|
|
797
|
-
/******/ // The module cache
|
|
798
|
-
/******/ var __webpack_module_cache__ = {};
|
|
799
|
-
/******/
|
|
800
|
-
/******/ // The require function
|
|
801
|
-
/******/ function __nccwpck_require__(moduleId) {
|
|
802
|
-
/******/ // Check if module is in cache
|
|
803
|
-
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
804
|
-
/******/ if (cachedModule !== undefined) {
|
|
805
|
-
/******/ return cachedModule.exports;
|
|
806
|
-
/******/ }
|
|
807
|
-
/******/ // Create a new module (and put it into the cache)
|
|
808
|
-
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
809
|
-
/******/ // no module.id needed
|
|
810
|
-
/******/ // no module.loaded needed
|
|
811
|
-
/******/ exports: {}
|
|
812
|
-
/******/ };
|
|
813
|
-
/******/
|
|
814
|
-
/******/ // Execute the module function
|
|
815
|
-
/******/ var threw = true;
|
|
816
|
-
/******/ try {
|
|
817
|
-
/******/ __webpack_modules__[moduleId](module, module.exports, __nccwpck_require__);
|
|
818
|
-
/******/ threw = false;
|
|
819
|
-
/******/ } finally {
|
|
820
|
-
/******/ if(threw) delete __webpack_module_cache__[moduleId];
|
|
821
|
-
/******/ }
|
|
822
|
-
/******/
|
|
823
|
-
/******/ // Return the exports of the module
|
|
824
|
-
/******/ return module.exports;
|
|
825
|
-
/******/ }
|
|
826
|
-
/******/
|
|
827
|
-
/************************************************************************/
|
|
828
|
-
/******/ /* webpack/runtime/compat */
|
|
829
|
-
/******/
|
|
830
|
-
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";
|
|
831
|
-
/******/
|
|
832
|
-
/************************************************************************/
|
|
833
|
-
var __webpack_exports__ = {};
|
|
834
|
-
// This entry need to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
|
|
835
|
-
(() => {
|
|
836
|
-
var exports = __webpack_exports__;
|
|
837
|
-
|
|
838
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
839
|
-
const config_1 = __nccwpck_require__(973);
|
|
840
|
-
const lockfile_1 = __nccwpck_require__(746);
|
|
841
|
-
const api_1 = __nccwpck_require__(879);
|
|
842
|
-
const output_1 = __nccwpck_require__(202);
|
|
843
|
-
const color_1 = __nccwpck_require__(988);
|
|
844
|
-
async function main() {
|
|
845
|
-
const config = (0, config_1.parseConfig)(process.argv);
|
|
846
|
-
if (config.mode === "off") {
|
|
847
|
-
process.stderr.write((0, color_1.dim)(" Dependency Guardian: mode is off — skipping.\n"));
|
|
848
|
-
process.exit(0);
|
|
849
|
-
}
|
|
850
|
-
// Discover packages
|
|
851
|
-
process.stderr.write((0, color_1.dim)(" Discovering package changes...\n"));
|
|
852
|
-
const discovery = (0, lockfile_1.discoverChanges)(process.cwd(), config);
|
|
853
|
-
if (discovery.packages.length === 0) {
|
|
854
|
-
process.stderr.write((0, color_1.dim)(" No package changes detected.\n"));
|
|
855
|
-
process.exit(0);
|
|
856
|
-
}
|
|
857
|
-
// Filter allowlist
|
|
858
|
-
const packages = discovery.packages.filter((p) => !config.allowlist.includes(p.name));
|
|
859
|
-
if (packages.length === 0) {
|
|
860
|
-
process.stderr.write((0, color_1.dim)(" All changed packages are allowlisted.\n"));
|
|
861
|
-
process.exit(0);
|
|
862
|
-
}
|
|
863
|
-
process.stderr.write((0, color_1.dim)(` Scanning ${packages.length} package${packages.length !== 1 ? "s" : ""} (${discovery.method})...\n`));
|
|
864
|
-
if (discovery.skipped.length > 0) {
|
|
865
|
-
process.stderr.write((0, color_1.yellow)(` Warning: ${discovery.skipped.length} package(s) skipped (max-packages=${config.maxPackages})\n`));
|
|
866
|
-
}
|
|
867
|
-
// Call Detection API
|
|
868
|
-
const result = await (0, api_1.callAnalyzeAPI)(packages, config, (done, total) => {
|
|
869
|
-
process.stderr.write((0, color_1.dim)(` Analyzed ${done}/${total}...\n`));
|
|
870
|
-
});
|
|
871
|
-
// Render output
|
|
872
|
-
const output = (0, output_1.renderResult)(result, config);
|
|
873
|
-
process.stdout.write(output + "\n");
|
|
874
|
-
// Exit code
|
|
875
|
-
if (result.action === "block" && config.mode === "block") {
|
|
876
|
-
process.exit(2);
|
|
877
|
-
}
|
|
878
|
-
else if (result.action === "block" || result.action === "warn") {
|
|
879
|
-
process.exit(1);
|
|
880
|
-
}
|
|
881
|
-
process.exit(0);
|
|
882
|
-
}
|
|
883
|
-
main().catch((err) => {
|
|
884
|
-
process.stderr.write(`\n ${(0, color_1.bold)((0, color_1.red)("Error:"))} ${err.message}\n\n`);
|
|
885
|
-
process.exit(1);
|
|
886
|
-
});
|
|
887
|
-
|
|
888
|
-
})();
|
|
889
|
-
|
|
890
|
-
module.exports = __webpack_exports__;
|
|
891
|
-
/******/ })()
|
|
892
|
-
;
|