@kaynooo/cli-workspace 0.2.0 → 0.3.0
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/audit-cli.js +279 -113
- package/dist/cli.js +366 -169
- package/dist/repos-cli.js +307 -119
- package/dist/sweep-cli.js +302 -127
- package/package.json +2 -2
package/dist/audit-cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/audit-cli.ts
|
|
5
|
-
import
|
|
5
|
+
import process15 from "process";
|
|
6
6
|
|
|
7
7
|
// ../kit/src/advisory.ts
|
|
8
8
|
var SEVERITIES = ["low", "moderate", "high", "critical"];
|
|
@@ -13,14 +13,14 @@ function isIgnored(advisory, ignore) {
|
|
|
13
13
|
return ignore.includes(advisory.ghsa ?? "") || ignore.includes(String(advisory.id));
|
|
14
14
|
}
|
|
15
15
|
// ../kit/src/args.ts
|
|
16
|
-
import
|
|
16
|
+
import process8 from "process";
|
|
17
17
|
import { parseArgs } from "util";
|
|
18
18
|
|
|
19
19
|
// ../kit/src/format.ts
|
|
20
|
-
import
|
|
20
|
+
import process6 from "process";
|
|
21
21
|
|
|
22
22
|
// ../kit/src/style.ts
|
|
23
|
-
import
|
|
23
|
+
import process5 from "process";
|
|
24
24
|
|
|
25
25
|
// ../../node_modules/.bun/@kaynooo+utils@2.31.2+d0769e28dc4dad16/node_modules/@kaynooo/utils/dist/chunk-mtetydvc.js
|
|
26
26
|
function x(s) {
|
|
@@ -283,52 +283,236 @@ function le(i = {}) {
|
|
|
283
283
|
}
|
|
284
284
|
var t = le();
|
|
285
285
|
|
|
286
|
-
// ../kit/src/
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
286
|
+
// ../kit/src/theme.ts
|
|
287
|
+
import { existsSync as existsSync3, readFileSync, statSync } from "fs";
|
|
288
|
+
import { homedir as homedir2 } from "os";
|
|
289
|
+
import { join as join3, resolve as resolve2 } from "path";
|
|
290
|
+
import process4 from "process";
|
|
291
|
+
|
|
292
|
+
// ../kit/src/config.ts
|
|
293
|
+
import { existsSync } from "fs";
|
|
294
|
+
import { dirname, join, resolve } from "path";
|
|
295
|
+
import process2 from "process";
|
|
296
|
+
function findUp(names, from = process2.cwd(), stop = () => false) {
|
|
297
|
+
const wanted = typeof names === "string" ? [names] : names;
|
|
298
|
+
for (let dir = resolve(from);; dir = dirname(dir)) {
|
|
299
|
+
const found = wanted.map((name) => join(dir, name)).find((path) => existsSync(path));
|
|
300
|
+
if (found !== undefined)
|
|
301
|
+
return found;
|
|
302
|
+
if (stop(dir) || dirname(dir) === dir)
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// ../kit/src/user-config.ts
|
|
308
|
+
import { existsSync as existsSync2 } from "fs";
|
|
309
|
+
import { homedir } from "os";
|
|
310
|
+
import { join as join2 } from "path";
|
|
311
|
+
import process3 from "process";
|
|
312
|
+
function configBase(where = {}) {
|
|
313
|
+
const xdg = where.xdg ?? (where.home === undefined ? process3.env.XDG_CONFIG_HOME : undefined);
|
|
314
|
+
return xdg !== undefined && xdg !== "" ? xdg : join2(where.home ?? homedir(), ".config");
|
|
315
|
+
}
|
|
316
|
+
function userConfigPath(bin, where = {}) {
|
|
317
|
+
return join2(configBase(where), "kaynooo-cli", `${bin}.json`);
|
|
318
|
+
}
|
|
319
|
+
function userConfigReadPath(bin, legacy = [], where = {}) {
|
|
320
|
+
const current = userConfigPath(bin, where);
|
|
321
|
+
if (existsSync2(current))
|
|
322
|
+
return current;
|
|
323
|
+
const base = configBase(where);
|
|
324
|
+
return legacy.map((parts) => join2(base, ...parts)).find((path) => existsSync2(path)) ?? current;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// ../kit/src/theme.ts
|
|
328
|
+
var DEFAULT = {
|
|
329
|
+
colors: { accent: "cyan", id: "yellow", path: "blue", label: "dim", value: "bold", ok: "green", warn: "yellow", problem: "red", note: "dim", passed: "green", failed: "red", running: "cyan", queued: "yellow", skipped: "dim" },
|
|
330
|
+
glyphs: { ok: "\u2713", warn: "\u25B2", problem: "\u2717", note: "\u203A", passed: "\u2713", failed: "\u2717", running: "\u25CF", queued: "\u25CB", skipped: "-", bar: "\u2501" },
|
|
331
|
+
accents: ["cyan", "magenta", "green", "blue", "yellow", "redBright"],
|
|
332
|
+
bins: {}
|
|
292
333
|
};
|
|
293
|
-
|
|
334
|
+
var BRIGHT = { accent: "cyanBright", id: "yellowBright", path: "blueBright", label: "white", value: "bold whiteBright", ok: "greenBright", warn: "yellowBright", problem: "redBright", note: "white", passed: "greenBright", failed: "redBright", running: "cyanBright", queued: "yellowBright", skipped: "white" };
|
|
335
|
+
var MONO = { accent: "bold", id: "bold", path: "underline", label: "dim", value: "bold", ok: "bold", warn: "bold", problem: "bold", note: "dim", passed: "bold", failed: "bold", running: "bold", queued: "dim", skipped: "dim" };
|
|
336
|
+
var ASCII = { ok: "+", warn: "!", problem: "x", note: ">", passed: "+", failed: "x", running: "*", queued: "o", skipped: "-", bar: "#" };
|
|
337
|
+
var PRESETS = {
|
|
338
|
+
default: {},
|
|
339
|
+
"high-contrast": { colors: BRIGHT, accents: ["cyanBright", "magentaBright", "greenBright", "blueBright", "yellowBright", "redBright"] },
|
|
340
|
+
mono: { colors: MONO, accents: ["bold"] },
|
|
341
|
+
ascii: { glyphs: ASCII }
|
|
342
|
+
};
|
|
343
|
+
var STYLES = new Set(["bold", "dim", "italic", "underline", "inverse", "strikethrough", "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "gray", "grey", "blackBright", "redBright", "greenBright", "yellowBright", "blueBright", "magentaBright", "cyanBright", "whiteBright"]);
|
|
344
|
+
var HEX = /^#[0-9a-f]{6}$/i;
|
|
345
|
+
var CONTROL = /\p{Cc}/u;
|
|
346
|
+
var MAX_FILE_BYTES = 64 * 1024;
|
|
347
|
+
var SPACES = /\s+/;
|
|
348
|
+
function isColorSpec(spec) {
|
|
349
|
+
if (typeof spec === "number")
|
|
350
|
+
return Number.isInteger(spec) && spec >= 0 && spec <= 255;
|
|
351
|
+
return typeof spec === "string" && spec.trim() !== "" && spec.trim().split(SPACES).every((token) => STYLES.has(token) || HEX.test(token));
|
|
352
|
+
}
|
|
353
|
+
function tinted(colors, spec) {
|
|
354
|
+
if (typeof spec === "number")
|
|
355
|
+
return colors.ansi256(spec);
|
|
356
|
+
return spec.trim().split(SPACES).reduce((chain, token) => HEX.test(token) ? chain.hex(token) : chain[token] ?? chain, colors);
|
|
357
|
+
}
|
|
358
|
+
function isRecord(value) {
|
|
359
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
360
|
+
}
|
|
361
|
+
function readThemeFile(path, warn) {
|
|
362
|
+
try {
|
|
363
|
+
const stat = statSync(path, { throwIfNoEntry: false });
|
|
364
|
+
if (stat === undefined)
|
|
365
|
+
return;
|
|
366
|
+
if (!stat.isFile() || stat.size > MAX_FILE_BYTES) {
|
|
367
|
+
warn(`${path} is not a regular file under ${MAX_FILE_BYTES / 1024} KiB, theme ignored`);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
371
|
+
if (isRecord(parsed))
|
|
372
|
+
return parsed;
|
|
373
|
+
warn(`${path} is not a JSON object, theme ignored`);
|
|
374
|
+
} catch (error) {
|
|
375
|
+
warn(`${path} does not parse (${error instanceof Error ? error.message : String(error)}), theme ignored`);
|
|
376
|
+
}
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
function applyPreset(theme, name, warn, where) {
|
|
380
|
+
if (name === undefined)
|
|
381
|
+
return;
|
|
382
|
+
if (typeof name !== "string" || !Object.hasOwn(PRESETS, name)) {
|
|
383
|
+
warn(`${where}: no preset ${String(name)}, one of ${Object.keys(PRESETS).join(", ")}`);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
const preset = PRESETS[name];
|
|
387
|
+
Object.assign(theme.colors, preset.colors);
|
|
388
|
+
Object.assign(theme.glyphs, preset.glyphs);
|
|
389
|
+
if (preset.accents !== undefined)
|
|
390
|
+
theme.accents = [...preset.accents];
|
|
391
|
+
return name;
|
|
392
|
+
}
|
|
393
|
+
function applyFile(theme, file, where, warn) {
|
|
394
|
+
if (isRecord(file.colors)) {
|
|
395
|
+
for (const [key, value] of Object.entries(file.colors)) {
|
|
396
|
+
if (!Object.hasOwn(DEFAULT.colors, key))
|
|
397
|
+
warn(`${where}: no colour ${key}, one of ${Object.keys(DEFAULT.colors).join(", ")}`);
|
|
398
|
+
else if (!isColorSpec(value))
|
|
399
|
+
warn(`${where}: colour ${key} is not an ANSI name, \`#rrggbb\` or a number up to 255`);
|
|
400
|
+
else
|
|
401
|
+
theme.colors[key] = value;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (isRecord(file.glyphs)) {
|
|
405
|
+
for (const [key, value] of Object.entries(file.glyphs)) {
|
|
406
|
+
if (!Object.hasOwn(DEFAULT.glyphs, key))
|
|
407
|
+
warn(`${where}: no glyph ${key}, one of ${Object.keys(DEFAULT.glyphs).join(", ")}`);
|
|
408
|
+
else if (typeof value !== "string" || CONTROL.test(value) || Bun.stringWidth(value) !== 1)
|
|
409
|
+
warn(`${where}: glyph ${key} must be one visible character wide, with no control character`);
|
|
410
|
+
else
|
|
411
|
+
theme.glyphs[key] = value;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (Array.isArray(file.accents) && file.accents.length > 0 && file.accents.every(isColorSpec))
|
|
415
|
+
theme.accents = [...file.accents];
|
|
416
|
+
else if (file.accents !== undefined)
|
|
417
|
+
warn(`${where}: accents must be a non-empty list of colours`);
|
|
418
|
+
if (isRecord(file.bins)) {
|
|
419
|
+
for (const [bin, value] of Object.entries(file.bins)) {
|
|
420
|
+
if (isColorSpec(value))
|
|
421
|
+
theme.bins[bin] = value;
|
|
422
|
+
else
|
|
423
|
+
warn(`${where}: bin ${bin} has no valid colour`);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
function endsWalk(home) {
|
|
428
|
+
return (dir) => dir === resolve2(home) || existsSync3(join3(dir, ".git"));
|
|
429
|
+
}
|
|
430
|
+
var warned = new Set;
|
|
431
|
+
function warnOnce(message) {
|
|
432
|
+
if (warned.has(message))
|
|
433
|
+
return;
|
|
434
|
+
warned.add(message);
|
|
435
|
+
console.error(`warning: theme ${message}`);
|
|
436
|
+
}
|
|
437
|
+
function isPath(chosen) {
|
|
438
|
+
return chosen.includes("/") || chosen.endsWith(".json");
|
|
439
|
+
}
|
|
440
|
+
function loadTheme({ env = process4.env, from = process4.cwd(), home = homedir2(), warn = warnOnce } = {}) {
|
|
441
|
+
const theme = { colors: { ...DEFAULT.colors }, glyphs: { ...DEFAULT.glyphs }, accents: [...DEFAULT.accents], bins: Object.create(null) };
|
|
442
|
+
const sources = [];
|
|
443
|
+
const chosen = env.KIT_THEME ?? "";
|
|
444
|
+
const wanted = chosen === "" ? [userConfigPath("theme", { home, xdg: env.XDG_CONFIG_HOME }), findUp(join3(".kaynooo", "theme.json"), from, endsWalk(home))] : [];
|
|
445
|
+
if (isPath(chosen))
|
|
446
|
+
wanted.push(resolve2(from, chosen));
|
|
447
|
+
const files = [];
|
|
448
|
+
for (const path of wanted) {
|
|
449
|
+
const file = path === undefined ? undefined : readThemeFile(path, warn);
|
|
450
|
+
if (path !== undefined && file !== undefined)
|
|
451
|
+
files.push({ path, file });
|
|
452
|
+
}
|
|
453
|
+
let preset = "default";
|
|
454
|
+
if (chosen !== "" && !isPath(chosen)) {
|
|
455
|
+
preset = applyPreset(theme, chosen, warn, "KIT_THEME") ?? preset;
|
|
456
|
+
} else {
|
|
457
|
+
const named = files.findLast(({ file }) => file.preset !== undefined);
|
|
458
|
+
if (named !== undefined)
|
|
459
|
+
preset = applyPreset(theme, named.file.preset, warn, named.path) ?? preset;
|
|
460
|
+
}
|
|
461
|
+
for (const { path, file } of files) {
|
|
462
|
+
applyFile(theme, file, path, warn);
|
|
463
|
+
sources.push(path);
|
|
464
|
+
}
|
|
465
|
+
return { theme, sources, preset };
|
|
466
|
+
}
|
|
467
|
+
var current;
|
|
468
|
+
var currentKey = "";
|
|
469
|
+
function activeTheme() {
|
|
470
|
+
const key = `${process4.cwd()}\x00${process4.env.KIT_THEME ?? ""}\x00${process4.env.XDG_CONFIG_HOME ?? ""}`;
|
|
471
|
+
if (current === undefined || key !== currentKey) {
|
|
472
|
+
current = loadTheme();
|
|
473
|
+
currentKey = key;
|
|
474
|
+
}
|
|
475
|
+
return current;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// ../kit/src/style.ts
|
|
479
|
+
var MARK_WORDS = { ok: "ok:", warn: "warning:", problem: "error:", note: "note:" };
|
|
480
|
+
function takesControlCodes(stream, env = process5.env) {
|
|
294
481
|
return stream.isTTY === true && env.NO_COLOR === undefined && env.NODE_DISABLE_COLORS === undefined && env.TERM !== "dumb";
|
|
295
482
|
}
|
|
296
|
-
function paint(stream, env =
|
|
483
|
+
function paint(stream, env = process5.env) {
|
|
297
484
|
return le({ stream: { isTTY: takesControlCodes(stream, env) }, env });
|
|
298
485
|
}
|
|
299
|
-
function marked(mark, text, stream, detail, env =
|
|
486
|
+
function marked(mark, text, stream, detail, env = process5.env) {
|
|
300
487
|
const colors = paint(stream, env);
|
|
301
|
-
|
|
302
|
-
|
|
488
|
+
let head = MARK_WORDS[mark];
|
|
489
|
+
if (takesControlCodes(stream, env)) {
|
|
490
|
+
const { theme } = activeTheme();
|
|
491
|
+
head = tinted(colors.bold, theme.colors[mark])(theme.glyphs[mark]);
|
|
492
|
+
}
|
|
303
493
|
return `${head} ${text}${detail === undefined ? "" : ` ${colors.dim(detail)}`}`;
|
|
304
494
|
}
|
|
305
495
|
function ok(text, detail) {
|
|
306
|
-
console.log(marked("ok", text,
|
|
496
|
+
console.log(marked("ok", text, process5.stdout, detail));
|
|
307
497
|
}
|
|
308
498
|
function note(text, detail) {
|
|
309
|
-
console.log(marked("note", text,
|
|
499
|
+
console.log(marked("note", text, process5.stdout, detail));
|
|
310
500
|
}
|
|
311
501
|
function problem(text, detail) {
|
|
312
|
-
console.error(marked("problem", text,
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
var STATUSES = {
|
|
325
|
-
passed: { symbol: "\u2713", words: ["passed", "success", "succeeded", "ok"], paint: (colors) => colors.green },
|
|
326
|
-
failed: { symbol: "\u2717", words: ["failed", "failure", "error", "errored"], paint: (colors) => colors.red },
|
|
327
|
-
running: { symbol: "\u25CF", words: ["running", "in_progress", "started"], paint: (colors) => colors.cyan },
|
|
328
|
-
queued: { symbol: "\u25CB", words: ["queued", "waiting", "pending", "created", "blocked", "scheduled"], paint: (colors) => colors.yellow },
|
|
329
|
-
skipped: { symbol: "-", words: ["skipped", "cancelled", "canceled", "manual"], paint: (colors) => colors.dim }
|
|
502
|
+
console.error(marked("problem", text, process5.stderr, detail));
|
|
503
|
+
}
|
|
504
|
+
function role(name, stream, env = process5.env) {
|
|
505
|
+
const colors = paint(stream, env);
|
|
506
|
+
return takesControlCodes(stream, env) ? tinted(colors, activeTheme().theme.colors[name]) : colors;
|
|
507
|
+
}
|
|
508
|
+
var STATUS_WORDS = {
|
|
509
|
+
passed: ["passed", "success", "succeeded", "ok"],
|
|
510
|
+
failed: ["failed", "failure", "error", "errored"],
|
|
511
|
+
running: ["running", "in_progress", "started"],
|
|
512
|
+
queued: ["queued", "waiting", "pending", "created", "blocked", "scheduled"],
|
|
513
|
+
skipped: ["skipped", "cancelled", "canceled", "manual"]
|
|
330
514
|
};
|
|
331
|
-
var STATUS_OF = new Map(Object.entries(
|
|
515
|
+
var STATUS_OF = new Map(Object.entries(STATUS_WORDS).flatMap(([status, words]) => words.map((word) => [word, status])));
|
|
332
516
|
|
|
333
517
|
// ../kit/src/format.ts
|
|
334
518
|
var UNITS = [["d", 86400], ["h", 3600], ["m", 60], ["s", 1]];
|
|
@@ -367,7 +551,7 @@ var ESCAPE = String.fromCharCode(27);
|
|
|
367
551
|
function textWidth(text) {
|
|
368
552
|
return Bun.stringWidth(text);
|
|
369
553
|
}
|
|
370
|
-
function table(rows, { cellWidth, header = false, align = [], fit } = {}) {
|
|
554
|
+
function table(rows, { cellWidth, header = false, align = [], fit, stream = process6.stdout } = {}) {
|
|
371
555
|
const cells = cellWidth === undefined ? rows : rows.map((row) => row.map((cell) => truncate(cell.replaceAll(LINE_BREAKS, " "), cellWidth)));
|
|
372
556
|
const widths = [];
|
|
373
557
|
for (const row of cells) {
|
|
@@ -375,7 +559,7 @@ function table(rows, { cellWidth, header = false, align = [], fit } = {}) {
|
|
|
375
559
|
widths[index] = Math.max(widths[index] ?? 0, textWidth(cell));
|
|
376
560
|
}
|
|
377
561
|
const shown = fit === undefined ? cells : narrow(cells, widths, fit);
|
|
378
|
-
const colors = paint(
|
|
562
|
+
const colors = paint(stream);
|
|
379
563
|
const lines = shown.map((row) => row.map((cell, index) => {
|
|
380
564
|
const width = widths[index] ?? 0;
|
|
381
565
|
const gap = " ".repeat(Math.max(0, width - textWidth(cell)));
|
|
@@ -383,7 +567,8 @@ function table(rows, { cellWidth, header = false, align = [], fit } = {}) {
|
|
|
383
567
|
return `${gap}${cell}`;
|
|
384
568
|
return index === row.length - 1 ? cell : `${cell}${gap}`;
|
|
385
569
|
}).join(" ").trimEnd());
|
|
386
|
-
|
|
570
|
+
const rule = header && takesControlCodes(stream) && lines.length > 1 ? [colors.dim("\u2500".repeat(Math.max(...lines.map(textWidth))))] : [];
|
|
571
|
+
return lines.flatMap((line, index) => header && index === 0 ? [colors.bold(line), ...rule] : [line]).join(`
|
|
387
572
|
`);
|
|
388
573
|
}
|
|
389
574
|
function narrow(rows, widths, limit) {
|
|
@@ -407,27 +592,27 @@ function printJson(value) {
|
|
|
407
592
|
}
|
|
408
593
|
|
|
409
594
|
// ../kit/src/help.ts
|
|
410
|
-
import
|
|
595
|
+
import process7 from "process";
|
|
411
596
|
var OPTIONAL = /\[[^\]]+\]/g;
|
|
412
597
|
var USAGE_PREFIX = /^usage:\s*/i;
|
|
413
598
|
var FULL_STOP = /\.$/;
|
|
414
|
-
function usageLine(usage, colors = paint(
|
|
599
|
+
function usageLine(usage, colors = paint(process7.stdout)) {
|
|
415
600
|
return `${colors.bold("Usage:")} ${usage.replace(USAGE_PREFIX, "").replaceAll(OPTIONAL, (part) => colors.dim(part))}`;
|
|
416
601
|
}
|
|
417
|
-
function helpText(usage, options, colors = paint(
|
|
602
|
+
function helpText(usage, options, colors = paint(process7.stdout), { examples = [], replaces, exits = [] } = {}) {
|
|
418
603
|
return [usageLine(usage, colors), ...replacesRows(replaces, colors), "", colors.bold("Options:"), ...optionRows(options, colors), ...exitRows(exits, colors), ...exampleRows(examples, colors)].join(`
|
|
419
604
|
`);
|
|
420
605
|
}
|
|
421
|
-
function exitRows(exits, colors = paint(
|
|
606
|
+
function exitRows(exits, colors = paint(process7.stdout)) {
|
|
422
607
|
if (exits.length === 0)
|
|
423
608
|
return [];
|
|
424
609
|
const width = Math.max(...exits.map(([code]) => String(code).length));
|
|
425
610
|
return ["", colors.bold("Exits:"), ...exits.map(([code, meaning]) => ` ${colors.cyan(String(code).padEnd(width))} ${meaning}`)];
|
|
426
611
|
}
|
|
427
|
-
function replacesRows(replaces, colors = paint(
|
|
612
|
+
function replacesRows(replaces, colors = paint(process7.stdout)) {
|
|
428
613
|
return replaces === undefined ? [] : ["", `${colors.bold("Instead of:")} ${replaces}`];
|
|
429
614
|
}
|
|
430
|
-
function wantsHelpJson(env =
|
|
615
|
+
function wantsHelpJson(env = process7.env) {
|
|
431
616
|
return env.KIT_HELP === "json";
|
|
432
617
|
}
|
|
433
618
|
function description(usage, { examples = [], replaces, exits } = {}, options) {
|
|
@@ -446,12 +631,12 @@ function description(usage, { examples = [], replaces, exits } = {}, options) {
|
|
|
446
631
|
...options === undefined ? {} : { options: Object.entries(options).map(([name, { short, description }]) => ({ name, ...short === undefined ? {} : { short }, ...description === undefined ? {} : { description } })) }
|
|
447
632
|
};
|
|
448
633
|
}
|
|
449
|
-
function exampleRows(examples, colors = paint(
|
|
634
|
+
function exampleRows(examples, colors = paint(process7.stdout)) {
|
|
450
635
|
if (examples.length === 0)
|
|
451
636
|
return [];
|
|
452
637
|
return ["", colors.bold("Examples:"), ...examples.map((example) => typeof example === "string" ? ` ${example}` : ` ${example[0]} ${colors.dim(`# ${example[1]}`)}`)];
|
|
453
638
|
}
|
|
454
|
-
function optionRows(options, colors = paint(
|
|
639
|
+
function optionRows(options, colors = paint(process7.stdout)) {
|
|
455
640
|
const rows = Object.entries(options).map(([name, option]) => {
|
|
456
641
|
const short = option.short === undefined ? " " : `${colors.cyan(`-${option.short}`)}, `;
|
|
457
642
|
const named = option.choices === undefined ? "<value>" : `<${option.choices.join("|")}>`;
|
|
@@ -544,7 +729,7 @@ var OUTPUT_OPTIONS = {
|
|
|
544
729
|
color: { type: "string", description: "auto (on a terminal alone), always or never" },
|
|
545
730
|
plain: { type: "boolean", description: "plain text, no colour or spinner: --color never" }
|
|
546
731
|
};
|
|
547
|
-
function applyOutput(color, plain, env =
|
|
732
|
+
function applyOutput(color, plain, env = process8.env) {
|
|
548
733
|
const when = plain === true ? "never" : color ?? "auto";
|
|
549
734
|
if (when === "auto")
|
|
550
735
|
return;
|
|
@@ -715,7 +900,7 @@ function nearestOption(message, options, allowNegative) {
|
|
|
715
900
|
}
|
|
716
901
|
// ../kit/src/process.ts
|
|
717
902
|
import { constants } from "os";
|
|
718
|
-
import
|
|
903
|
+
import process9 from "process";
|
|
719
904
|
var KILL_GRACE_MS = 2000;
|
|
720
905
|
function exitCodeOf(code, signal) {
|
|
721
906
|
if (code !== null)
|
|
@@ -735,7 +920,7 @@ async function runCommand(argv, { cwd, env, stdin = "ignore", timeoutMs, signal,
|
|
|
735
920
|
return;
|
|
736
921
|
try {
|
|
737
922
|
if (grouped)
|
|
738
|
-
|
|
923
|
+
process9.kill(-proc.pid, killing);
|
|
739
924
|
else
|
|
740
925
|
proc.kill(killing);
|
|
741
926
|
} catch {}
|
|
@@ -810,10 +995,10 @@ var RESET_STYLE = `${ESC}[0m`;
|
|
|
810
995
|
var CLOSE_LINK = `${ESC}]8;;${ESC}\\`;
|
|
811
996
|
|
|
812
997
|
// ../kit/src/tool.ts
|
|
813
|
-
import
|
|
998
|
+
import process10 from "process";
|
|
814
999
|
function cwdGone() {
|
|
815
1000
|
try {
|
|
816
|
-
|
|
1001
|
+
process10.cwd();
|
|
817
1002
|
return false;
|
|
818
1003
|
} catch {
|
|
819
1004
|
return true;
|
|
@@ -835,7 +1020,7 @@ function spawnFailure(command, error) {
|
|
|
835
1020
|
async function runTool(label, argv, { timeoutMs, cwd, onStart } = {}) {
|
|
836
1021
|
let ran;
|
|
837
1022
|
try {
|
|
838
|
-
ran = await runCommand(argv, { env:
|
|
1023
|
+
ran = await runCommand(argv, { env: process10.env, ...timeoutMs === undefined ? {} : { timeoutMs }, ...cwd === undefined ? {} : { cwd }, ...onStart === undefined ? {} : { onStart } });
|
|
839
1024
|
} catch (error) {
|
|
840
1025
|
throw spawnFailure(label, error);
|
|
841
1026
|
}
|
|
@@ -850,15 +1035,15 @@ async function runTool(label, argv, { timeoutMs, cwd, onStart } = {}) {
|
|
|
850
1035
|
return { code: ran.code, ...streams };
|
|
851
1036
|
}
|
|
852
1037
|
// ../kit/src/cli.ts
|
|
853
|
-
import { readFileSync, realpathSync } from "fs";
|
|
854
|
-
import { dirname as
|
|
855
|
-
import
|
|
1038
|
+
import { readFileSync as readFileSync2, realpathSync } from "fs";
|
|
1039
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
1040
|
+
import process12 from "process";
|
|
856
1041
|
|
|
857
1042
|
// ../kit/src/usage.ts
|
|
858
1043
|
import { appendFileSync, mkdirSync } from "fs";
|
|
859
|
-
import { homedir } from "os";
|
|
860
|
-
import { dirname, isAbsolute, join } from "path";
|
|
861
|
-
import
|
|
1044
|
+
import { homedir as homedir3 } from "os";
|
|
1045
|
+
import { dirname as dirname2, isAbsolute, join as join4 } from "path";
|
|
1046
|
+
import process11 from "process";
|
|
862
1047
|
|
|
863
1048
|
// ../kit/src/logs.ts
|
|
864
1049
|
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
@@ -872,14 +1057,14 @@ var usageError;
|
|
|
872
1057
|
function noteUsageError(message) {
|
|
873
1058
|
usageError = message;
|
|
874
1059
|
}
|
|
875
|
-
function stateHome(env =
|
|
1060
|
+
function stateHome(env = process11.env) {
|
|
876
1061
|
const dir = env.XDG_STATE_HOME;
|
|
877
|
-
return dir !== undefined && isAbsolute(dir) ? dir :
|
|
1062
|
+
return dir !== undefined && isAbsolute(dir) ? dir : join4(homedir3(), ".local", "state");
|
|
878
1063
|
}
|
|
879
|
-
function usagePath(env =
|
|
880
|
-
return
|
|
1064
|
+
function usagePath(env = process11.env) {
|
|
1065
|
+
return join4(stateHome(env), CLI_FOLDER, "usage.jsonl");
|
|
881
1066
|
}
|
|
882
|
-
function usageRecorded(env =
|
|
1067
|
+
function usageRecorded(env = process11.env) {
|
|
883
1068
|
const off = env.KAYNOOO_CLI_NO_USAGE;
|
|
884
1069
|
return env.NODE_ENV !== "test" && (off === undefined || off === "" || off === "0");
|
|
885
1070
|
}
|
|
@@ -893,12 +1078,12 @@ function usageEntry(bin, command, argv, code, now = new Date) {
|
|
|
893
1078
|
usageError = undefined;
|
|
894
1079
|
return { at: now.toISOString(), bin, ...command === undefined ? {} : { command }, flags: flagNames(argv), code, ...unknown === undefined ? {} : { unknown } };
|
|
895
1080
|
}
|
|
896
|
-
function recordUsage(entry, env =
|
|
1081
|
+
function recordUsage(entry, env = process11.env) {
|
|
897
1082
|
if (!usageRecorded(env))
|
|
898
1083
|
return;
|
|
899
1084
|
try {
|
|
900
1085
|
const path = usagePath(env);
|
|
901
|
-
mkdirSync(
|
|
1086
|
+
mkdirSync(dirname2(path), { recursive: true, mode: 448 });
|
|
902
1087
|
appendFileSync(path, `${JSON.stringify(entry)}
|
|
903
1088
|
`, { mode: 384 });
|
|
904
1089
|
} catch {}
|
|
@@ -984,8 +1169,8 @@ async function help2({ path, header, summary: lazySummary, commands, defaultComm
|
|
|
984
1169
|
`);
|
|
985
1170
|
}
|
|
986
1171
|
function printError(prefix, message, hint, cause) {
|
|
987
|
-
const colors = paint(
|
|
988
|
-
const styled = takesControlCodes(
|
|
1172
|
+
const colors = paint(process12.stderr);
|
|
1173
|
+
const styled = takesControlCodes(process12.stderr);
|
|
989
1174
|
const head = styled ? `${colors.red.bold("error")} ${colors.dim(`${prefix}:`)}` : `error: ${prefix}:`;
|
|
990
1175
|
const under = (label, text, tint) => text === undefined ? "" : `
|
|
991
1176
|
${styled ? tint(label) : `${label}:`} ${text}`;
|
|
@@ -1028,11 +1213,11 @@ async function dispatch(level, typed, { version, redact }) {
|
|
|
1028
1213
|
}
|
|
1029
1214
|
}
|
|
1030
1215
|
if (name === undefined && level.path.length > 1) {
|
|
1031
|
-
console.error(await help2(await expand(level, [...level.path.slice(1), ...argv]),
|
|
1216
|
+
console.error(await help2(await expand(level, [...level.path.slice(1), ...argv]), process12.stderr));
|
|
1032
1217
|
return 2;
|
|
1033
1218
|
}
|
|
1034
1219
|
if (name === undefined || name === "help" || name === "--help" || name === "-h") {
|
|
1035
|
-
console.log(await help2(await expand(level, [...level.path.slice(1), ...argv]),
|
|
1220
|
+
console.log(await help2(await expand(level, [...level.path.slice(1), ...argv]), process12.stdout));
|
|
1036
1221
|
return 0;
|
|
1037
1222
|
}
|
|
1038
1223
|
if (level.path.length === 1 && (name === "--version" || name === "-v")) {
|
|
@@ -1149,17 +1334,17 @@ async function printCandidates(found) {
|
|
|
1149
1334
|
return 0;
|
|
1150
1335
|
}
|
|
1151
1336
|
function packageVersion(entry = Bun.main) {
|
|
1152
|
-
for (let dir =
|
|
1337
|
+
for (let dir = dirname3(realpathSync(entry));; dir = dirname3(dir)) {
|
|
1153
1338
|
try {
|
|
1154
|
-
const { version } = JSON.parse(
|
|
1339
|
+
const { version } = JSON.parse(readFileSync2(join5(dir, "package.json"), "utf8"));
|
|
1155
1340
|
if (typeof version === "string")
|
|
1156
1341
|
return version;
|
|
1157
1342
|
} catch {}
|
|
1158
|
-
if (
|
|
1343
|
+
if (dirname3(dir) === dir)
|
|
1159
1344
|
return "0.0.0";
|
|
1160
1345
|
}
|
|
1161
1346
|
}
|
|
1162
|
-
async function runCli(cli, argv =
|
|
1347
|
+
async function runCli(cli, argv = process12.argv.slice(2)) {
|
|
1163
1348
|
const version = cli.version ?? packageVersion();
|
|
1164
1349
|
if (argv[0] === COMPLETE)
|
|
1165
1350
|
return printCandidates(candidates(scopeOf(cli.commands, cli.extraCommands, cli.aliases), cli.defaultCommand, argv.slice(1)));
|
|
@@ -1186,7 +1371,7 @@ function commandPath(scope, argv) {
|
|
|
1186
1371
|
}
|
|
1187
1372
|
return path.length === 0 ? undefined : path.join(" ");
|
|
1188
1373
|
}
|
|
1189
|
-
async function runMain({ name, version, run, redact, usage }, argv =
|
|
1374
|
+
async function runMain({ name, version, run, redact, usage }, argv = process12.argv.slice(2)) {
|
|
1190
1375
|
if (argv[0] === COMPLETE)
|
|
1191
1376
|
return printCandidates(leafCandidates(run, argv.slice(1)));
|
|
1192
1377
|
if (argv.length === 1 && (argv[0] === "--version" || argv[0] === "-v")) {
|
|
@@ -1222,34 +1407,15 @@ function parseSize(text, bareUnit = 1) {
|
|
|
1222
1407
|
const suffix = match[2].toLowerCase();
|
|
1223
1408
|
return Math.round(Number(match[1]) * (suffix === "" ? bareUnit : 1024 ** POWERS[suffix]));
|
|
1224
1409
|
}
|
|
1225
|
-
// ../kit/src/user-config.ts
|
|
1226
|
-
import { existsSync } from "fs";
|
|
1227
|
-
import { homedir as homedir2 } from "os";
|
|
1228
|
-
import { join as join3 } from "path";
|
|
1229
|
-
import process10 from "process";
|
|
1230
|
-
function configBase(where = {}) {
|
|
1231
|
-
const xdg = where.xdg ?? (where.home === undefined ? process10.env.XDG_CONFIG_HOME : undefined);
|
|
1232
|
-
return xdg !== undefined && xdg !== "" ? xdg : join3(where.home ?? homedir2(), ".config");
|
|
1233
|
-
}
|
|
1234
|
-
function userConfigPath(bin, where = {}) {
|
|
1235
|
-
return join3(configBase(where), "kaynooo-cli", `${bin}.json`);
|
|
1236
|
-
}
|
|
1237
|
-
function userConfigReadPath(bin, legacy = [], where = {}) {
|
|
1238
|
-
const current = userConfigPath(bin, where);
|
|
1239
|
-
if (existsSync(current))
|
|
1240
|
-
return current;
|
|
1241
|
-
const base = configBase(where);
|
|
1242
|
-
return legacy.map((parts) => join3(base, ...parts)).find((path) => existsSync(path)) ?? current;
|
|
1243
|
-
}
|
|
1244
1410
|
// src/audit.ts
|
|
1245
|
-
import { existsSync as
|
|
1411
|
+
import { existsSync as existsSync5, readdirSync, statSync as statSync2 } from "fs";
|
|
1246
1412
|
import { readdir } from "fs/promises";
|
|
1247
|
-
import { join as
|
|
1248
|
-
import
|
|
1413
|
+
import { join as join7, relative, resolve as resolve3 } from "path";
|
|
1414
|
+
import process14 from "process";
|
|
1249
1415
|
|
|
1250
1416
|
// src/report.ts
|
|
1251
|
-
import { existsSync as
|
|
1252
|
-
import { join as
|
|
1417
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
1418
|
+
import { join as join6 } from "path";
|
|
1253
1419
|
var UPPER_BOUND = /<\s*(\d[\w.+-]*)/;
|
|
1254
1420
|
var DEPENDENCY_KINDS = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"];
|
|
1255
1421
|
var GHSA = /GHSA-[\w-]+$/;
|
|
@@ -1293,7 +1459,7 @@ function findingsOf(audit, reaching, direct, level, ignore = []) {
|
|
|
1293
1459
|
}
|
|
1294
1460
|
function readManifest(path) {
|
|
1295
1461
|
try {
|
|
1296
|
-
return
|
|
1462
|
+
return existsSync4(path) ? JSON.parse(readFileSync3(path, "utf8")) : {};
|
|
1297
1463
|
} catch {
|
|
1298
1464
|
return {};
|
|
1299
1465
|
}
|
|
@@ -1305,9 +1471,9 @@ function namesIn(manifest) {
|
|
|
1305
1471
|
});
|
|
1306
1472
|
}
|
|
1307
1473
|
function directDependencies(root, workspaces) {
|
|
1308
|
-
const names = new Set(namesIn(readManifest(
|
|
1474
|
+
const names = new Set(namesIn(readManifest(join6(root, "package.json"))));
|
|
1309
1475
|
for (const workspace of workspaces) {
|
|
1310
|
-
for (const name of namesIn(readManifest(
|
|
1476
|
+
for (const name of namesIn(readManifest(join6(root, workspace, "package.json"))))
|
|
1311
1477
|
names.add(name);
|
|
1312
1478
|
}
|
|
1313
1479
|
return names;
|
|
@@ -1319,8 +1485,8 @@ function workspacePatterns(field) {
|
|
|
1319
1485
|
return Array.isArray(packages) ? packages : [];
|
|
1320
1486
|
}
|
|
1321
1487
|
function workspaceFolders(root, children) {
|
|
1322
|
-
const patterns = workspacePatterns(readManifest(
|
|
1323
|
-
return patterns.filter((pattern) => typeof pattern === "string").flatMap((pattern) => pattern.endsWith("/*") ? children(pattern.slice(0, -2)).map((name) =>
|
|
1488
|
+
const patterns = workspacePatterns(readManifest(join6(root, "package.json")).workspaces);
|
|
1489
|
+
return patterns.filter((pattern) => typeof pattern === "string").flatMap((pattern) => pattern.endsWith("/*") ? children(pattern.slice(0, -2)).map((name) => join6(pattern.slice(0, -2), name)) : [pattern]);
|
|
1324
1490
|
}
|
|
1325
1491
|
|
|
1326
1492
|
// src/audit.ts
|
|
@@ -1341,7 +1507,7 @@ var MAX_DEPTH = 3;
|
|
|
1341
1507
|
var CONCURRENCY = 4;
|
|
1342
1508
|
var AUDIT_MS = 60000;
|
|
1343
1509
|
function holdsLock(dir) {
|
|
1344
|
-
return
|
|
1510
|
+
return existsSync5(join7(dir, "bun.lock")) || existsSync5(join7(dir, "bun.lockb"));
|
|
1345
1511
|
}
|
|
1346
1512
|
async function findRepos(root) {
|
|
1347
1513
|
if (holdsLock(root))
|
|
@@ -1357,7 +1523,7 @@ async function findRepos(root) {
|
|
|
1357
1523
|
for (const entry of entries.toSorted((a, b) => a.name.localeCompare(b.name))) {
|
|
1358
1524
|
if (!entry.isDirectory() || entry.name === "node_modules" || entry.name.startsWith("."))
|
|
1359
1525
|
continue;
|
|
1360
|
-
const path =
|
|
1526
|
+
const path = join7(dir, entry.name);
|
|
1361
1527
|
if (holdsLock(path))
|
|
1362
1528
|
found.push(path);
|
|
1363
1529
|
else if (depth < MAX_DEPTH)
|
|
@@ -1382,7 +1548,7 @@ async function pool(items, limit, task) {
|
|
|
1382
1548
|
function children(root) {
|
|
1383
1549
|
return (folder) => {
|
|
1384
1550
|
try {
|
|
1385
|
-
return readdirSync(
|
|
1551
|
+
return readdirSync(join7(root, folder), { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
|
1386
1552
|
} catch {
|
|
1387
1553
|
return [];
|
|
1388
1554
|
}
|
|
@@ -1409,7 +1575,7 @@ function failure(ran) {
|
|
|
1409
1575
|
`).at(-1) ?? `exit ${ran.code}`;
|
|
1410
1576
|
}
|
|
1411
1577
|
function tint(severity) {
|
|
1412
|
-
const colors = paint(
|
|
1578
|
+
const colors = paint(process14.stdout);
|
|
1413
1579
|
if (severity === "critical" || severity === "high")
|
|
1414
1580
|
return colors.red;
|
|
1415
1581
|
return severity === "moderate" ? colors.yellow : colors.dim;
|
|
@@ -1426,8 +1592,8 @@ function rows(findings) {
|
|
|
1426
1592
|
}
|
|
1427
1593
|
async function audit(args) {
|
|
1428
1594
|
const { values, positionals } = parse(args, USAGE, OPTIONS, { positionals: ["[root]"], exits: EXITS, replaces: "a bun audit run in each repository and a read of every advisory to find what is worth fixing", examples: ["audit", "audit ~/Workspace --level high --prod"] });
|
|
1429
|
-
const root =
|
|
1430
|
-
if (!
|
|
1595
|
+
const root = resolve3(positionals[0] ?? ".");
|
|
1596
|
+
if (!existsSync5(root) || !statSync2(root).isDirectory())
|
|
1431
1597
|
fail(`no folder ${root}`);
|
|
1432
1598
|
const level = oneOf(values.level, "level", SEVERITIES);
|
|
1433
1599
|
const paths = await findRepos(root);
|
|
@@ -1444,8 +1610,8 @@ async function audit(args) {
|
|
|
1444
1610
|
return kept.some((each) => each.findings.length > 0) ? 1 : 0;
|
|
1445
1611
|
}
|
|
1446
1612
|
function show(audits, total) {
|
|
1447
|
-
const label = role("label",
|
|
1448
|
-
const path = role("path",
|
|
1613
|
+
const label = role("label", process14.stdout);
|
|
1614
|
+
const path = role("path", process14.stdout);
|
|
1449
1615
|
const flagged = audits.filter((each) => each.error !== undefined || each.findings.length > 0);
|
|
1450
1616
|
if (flagged.length === 0) {
|
|
1451
1617
|
console.log(label(`no advisory in ${total} ${total === 1 ? "repository" : "repositories"}`));
|
|
@@ -1459,4 +1625,4 @@ function show(audits, total) {
|
|
|
1459
1625
|
}
|
|
1460
1626
|
|
|
1461
1627
|
// src/audit-cli.ts
|
|
1462
|
-
|
|
1628
|
+
process15.exitCode = await runMain({ name: "audit", run: audit });
|