@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/sweep-cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/sweep-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
|
// ../../node_modules/.bun/@kaynooo+utils@2.31.2+d0769e28dc4dad16/node_modules/@kaynooo/utils/dist/chunk-hrsswv1w.js
|
|
333
517
|
function $e(t, e = false, i = 1) {
|
|
334
518
|
let n = typeof e === "object" ? e : { units: e ? "si" : "iec", dp: i }, { units: s = "iec", dp: u = 1 } = n, r = s === "si" ? 1000 : 1024;
|
|
@@ -378,7 +562,7 @@ var ESCAPE = String.fromCharCode(27);
|
|
|
378
562
|
function textWidth(text) {
|
|
379
563
|
return Bun.stringWidth(text);
|
|
380
564
|
}
|
|
381
|
-
function table(rows, { cellWidth, header = false, align = [], fit } = {}) {
|
|
565
|
+
function table(rows, { cellWidth, header = false, align = [], fit, stream = process6.stdout } = {}) {
|
|
382
566
|
const cells = cellWidth === undefined ? rows : rows.map((row) => row.map((cell) => truncate(cell.replaceAll(LINE_BREAKS, " "), cellWidth)));
|
|
383
567
|
const widths = [];
|
|
384
568
|
for (const row of cells) {
|
|
@@ -386,7 +570,7 @@ function table(rows, { cellWidth, header = false, align = [], fit } = {}) {
|
|
|
386
570
|
widths[index] = Math.max(widths[index] ?? 0, textWidth(cell));
|
|
387
571
|
}
|
|
388
572
|
const shown = fit === undefined ? cells : narrow(cells, widths, fit);
|
|
389
|
-
const colors = paint(
|
|
573
|
+
const colors = paint(stream);
|
|
390
574
|
const lines = shown.map((row) => row.map((cell, index) => {
|
|
391
575
|
const width = widths[index] ?? 0;
|
|
392
576
|
const gap = " ".repeat(Math.max(0, width - textWidth(cell)));
|
|
@@ -394,7 +578,8 @@ function table(rows, { cellWidth, header = false, align = [], fit } = {}) {
|
|
|
394
578
|
return `${gap}${cell}`;
|
|
395
579
|
return index === row.length - 1 ? cell : `${cell}${gap}`;
|
|
396
580
|
}).join(" ").trimEnd());
|
|
397
|
-
|
|
581
|
+
const rule = header && takesControlCodes(stream) && lines.length > 1 ? [colors.dim("\u2500".repeat(Math.max(...lines.map(textWidth))))] : [];
|
|
582
|
+
return lines.flatMap((line, index) => header && index === 0 ? [colors.bold(line), ...rule] : [line]).join(`
|
|
398
583
|
`);
|
|
399
584
|
}
|
|
400
585
|
function narrow(rows, widths, limit) {
|
|
@@ -418,27 +603,27 @@ function printJson(value) {
|
|
|
418
603
|
}
|
|
419
604
|
|
|
420
605
|
// ../kit/src/help.ts
|
|
421
|
-
import
|
|
606
|
+
import process7 from "process";
|
|
422
607
|
var OPTIONAL = /\[[^\]]+\]/g;
|
|
423
608
|
var USAGE_PREFIX = /^usage:\s*/i;
|
|
424
609
|
var FULL_STOP = /\.$/;
|
|
425
|
-
function usageLine(usage, colors = paint(
|
|
610
|
+
function usageLine(usage, colors = paint(process7.stdout)) {
|
|
426
611
|
return `${colors.bold("Usage:")} ${usage.replace(USAGE_PREFIX, "").replaceAll(OPTIONAL, (part) => colors.dim(part))}`;
|
|
427
612
|
}
|
|
428
|
-
function helpText(usage, options, colors = paint(
|
|
613
|
+
function helpText(usage, options, colors = paint(process7.stdout), { examples = [], replaces, exits = [] } = {}) {
|
|
429
614
|
return [usageLine(usage, colors), ...replacesRows(replaces, colors), "", colors.bold("Options:"), ...optionRows(options, colors), ...exitRows(exits, colors), ...exampleRows(examples, colors)].join(`
|
|
430
615
|
`);
|
|
431
616
|
}
|
|
432
|
-
function exitRows(exits, colors = paint(
|
|
617
|
+
function exitRows(exits, colors = paint(process7.stdout)) {
|
|
433
618
|
if (exits.length === 0)
|
|
434
619
|
return [];
|
|
435
620
|
const width = Math.max(...exits.map(([code]) => String(code).length));
|
|
436
621
|
return ["", colors.bold("Exits:"), ...exits.map(([code, meaning]) => ` ${colors.cyan(String(code).padEnd(width))} ${meaning}`)];
|
|
437
622
|
}
|
|
438
|
-
function replacesRows(replaces, colors = paint(
|
|
623
|
+
function replacesRows(replaces, colors = paint(process7.stdout)) {
|
|
439
624
|
return replaces === undefined ? [] : ["", `${colors.bold("Instead of:")} ${replaces}`];
|
|
440
625
|
}
|
|
441
|
-
function wantsHelpJson(env =
|
|
626
|
+
function wantsHelpJson(env = process7.env) {
|
|
442
627
|
return env.KIT_HELP === "json";
|
|
443
628
|
}
|
|
444
629
|
function description(usage, { examples = [], replaces, exits } = {}, options) {
|
|
@@ -457,12 +642,12 @@ function description(usage, { examples = [], replaces, exits } = {}, options) {
|
|
|
457
642
|
...options === undefined ? {} : { options: Object.entries(options).map(([name, { short, description }]) => ({ name, ...short === undefined ? {} : { short }, ...description === undefined ? {} : { description } })) }
|
|
458
643
|
};
|
|
459
644
|
}
|
|
460
|
-
function exampleRows(examples, colors = paint(
|
|
645
|
+
function exampleRows(examples, colors = paint(process7.stdout)) {
|
|
461
646
|
if (examples.length === 0)
|
|
462
647
|
return [];
|
|
463
648
|
return ["", colors.bold("Examples:"), ...examples.map((example) => typeof example === "string" ? ` ${example}` : ` ${example[0]} ${colors.dim(`# ${example[1]}`)}`)];
|
|
464
649
|
}
|
|
465
|
-
function optionRows(options, colors = paint(
|
|
650
|
+
function optionRows(options, colors = paint(process7.stdout)) {
|
|
466
651
|
const rows = Object.entries(options).map(([name, option]) => {
|
|
467
652
|
const short = option.short === undefined ? " " : `${colors.cyan(`-${option.short}`)}, `;
|
|
468
653
|
const named = option.choices === undefined ? "<value>" : `<${option.choices.join("|")}>`;
|
|
@@ -555,7 +740,7 @@ var OUTPUT_OPTIONS = {
|
|
|
555
740
|
color: { type: "string", description: "auto (on a terminal alone), always or never" },
|
|
556
741
|
plain: { type: "boolean", description: "plain text, no colour or spinner: --color never" }
|
|
557
742
|
};
|
|
558
|
-
function applyOutput(color, plain, env =
|
|
743
|
+
function applyOutput(color, plain, env = process8.env) {
|
|
559
744
|
const when = plain === true ? "never" : color ?? "auto";
|
|
560
745
|
if (when === "auto")
|
|
561
746
|
return;
|
|
@@ -726,7 +911,7 @@ function nearestOption(message, options, allowNegative) {
|
|
|
726
911
|
}
|
|
727
912
|
// ../kit/src/process.ts
|
|
728
913
|
import { constants } from "os";
|
|
729
|
-
import
|
|
914
|
+
import process9 from "process";
|
|
730
915
|
var KILL_GRACE_MS = 2000;
|
|
731
916
|
function exitCodeOf(code, signal) {
|
|
732
917
|
if (code !== null)
|
|
@@ -746,7 +931,7 @@ async function runCommand(argv, { cwd, env, stdin = "ignore", timeoutMs, signal,
|
|
|
746
931
|
return;
|
|
747
932
|
try {
|
|
748
933
|
if (grouped)
|
|
749
|
-
|
|
934
|
+
process9.kill(-proc.pid, killing);
|
|
750
935
|
else
|
|
751
936
|
proc.kill(killing);
|
|
752
937
|
} catch {}
|
|
@@ -821,10 +1006,10 @@ var RESET_STYLE = `${ESC}[0m`;
|
|
|
821
1006
|
var CLOSE_LINK = `${ESC}]8;;${ESC}\\`;
|
|
822
1007
|
|
|
823
1008
|
// ../kit/src/tool.ts
|
|
824
|
-
import
|
|
1009
|
+
import process10 from "process";
|
|
825
1010
|
function cwdGone() {
|
|
826
1011
|
try {
|
|
827
|
-
|
|
1012
|
+
process10.cwd();
|
|
828
1013
|
return false;
|
|
829
1014
|
} catch {
|
|
830
1015
|
return true;
|
|
@@ -846,7 +1031,7 @@ function spawnFailure(command, error) {
|
|
|
846
1031
|
async function runTool(label, argv, { timeoutMs, cwd, onStart } = {}) {
|
|
847
1032
|
let ran;
|
|
848
1033
|
try {
|
|
849
|
-
ran = await runCommand(argv, { env:
|
|
1034
|
+
ran = await runCommand(argv, { env: process10.env, ...timeoutMs === undefined ? {} : { timeoutMs }, ...cwd === undefined ? {} : { cwd }, ...onStart === undefined ? {} : { onStart } });
|
|
850
1035
|
} catch (error) {
|
|
851
1036
|
throw spawnFailure(label, error);
|
|
852
1037
|
}
|
|
@@ -861,15 +1046,15 @@ async function runTool(label, argv, { timeoutMs, cwd, onStart } = {}) {
|
|
|
861
1046
|
return { code: ran.code, ...streams };
|
|
862
1047
|
}
|
|
863
1048
|
// ../kit/src/cli.ts
|
|
864
|
-
import { readFileSync, realpathSync } from "fs";
|
|
865
|
-
import { dirname as
|
|
866
|
-
import
|
|
1049
|
+
import { readFileSync as readFileSync2, realpathSync } from "fs";
|
|
1050
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
1051
|
+
import process12 from "process";
|
|
867
1052
|
|
|
868
1053
|
// ../kit/src/usage.ts
|
|
869
1054
|
import { appendFileSync, mkdirSync } from "fs";
|
|
870
|
-
import { homedir } from "os";
|
|
871
|
-
import { dirname, isAbsolute, join } from "path";
|
|
872
|
-
import
|
|
1055
|
+
import { homedir as homedir3 } from "os";
|
|
1056
|
+
import { dirname as dirname2, isAbsolute, join as join4 } from "path";
|
|
1057
|
+
import process11 from "process";
|
|
873
1058
|
|
|
874
1059
|
// ../kit/src/logs.ts
|
|
875
1060
|
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
@@ -883,14 +1068,14 @@ var usageError;
|
|
|
883
1068
|
function noteUsageError(message) {
|
|
884
1069
|
usageError = message;
|
|
885
1070
|
}
|
|
886
|
-
function stateHome(env =
|
|
1071
|
+
function stateHome(env = process11.env) {
|
|
887
1072
|
const dir = env.XDG_STATE_HOME;
|
|
888
|
-
return dir !== undefined && isAbsolute(dir) ? dir :
|
|
1073
|
+
return dir !== undefined && isAbsolute(dir) ? dir : join4(homedir3(), ".local", "state");
|
|
889
1074
|
}
|
|
890
|
-
function usagePath(env =
|
|
891
|
-
return
|
|
1075
|
+
function usagePath(env = process11.env) {
|
|
1076
|
+
return join4(stateHome(env), CLI_FOLDER, "usage.jsonl");
|
|
892
1077
|
}
|
|
893
|
-
function usageRecorded(env =
|
|
1078
|
+
function usageRecorded(env = process11.env) {
|
|
894
1079
|
const off = env.KAYNOOO_CLI_NO_USAGE;
|
|
895
1080
|
return env.NODE_ENV !== "test" && (off === undefined || off === "" || off === "0");
|
|
896
1081
|
}
|
|
@@ -904,12 +1089,12 @@ function usageEntry(bin, command, argv, code, now = new Date) {
|
|
|
904
1089
|
usageError = undefined;
|
|
905
1090
|
return { at: now.toISOString(), bin, ...command === undefined ? {} : { command }, flags: flagNames(argv), code, ...unknown === undefined ? {} : { unknown } };
|
|
906
1091
|
}
|
|
907
|
-
function recordUsage(entry, env =
|
|
1092
|
+
function recordUsage(entry, env = process11.env) {
|
|
908
1093
|
if (!usageRecorded(env))
|
|
909
1094
|
return;
|
|
910
1095
|
try {
|
|
911
1096
|
const path = usagePath(env);
|
|
912
|
-
mkdirSync(
|
|
1097
|
+
mkdirSync(dirname2(path), { recursive: true, mode: 448 });
|
|
913
1098
|
appendFileSync(path, `${JSON.stringify(entry)}
|
|
914
1099
|
`, { mode: 384 });
|
|
915
1100
|
} catch {}
|
|
@@ -995,8 +1180,8 @@ async function help2({ path, header, summary: lazySummary, commands, defaultComm
|
|
|
995
1180
|
`);
|
|
996
1181
|
}
|
|
997
1182
|
function printError(prefix, message, hint, cause) {
|
|
998
|
-
const colors = paint(
|
|
999
|
-
const styled = takesControlCodes(
|
|
1183
|
+
const colors = paint(process12.stderr);
|
|
1184
|
+
const styled = takesControlCodes(process12.stderr);
|
|
1000
1185
|
const head = styled ? `${colors.red.bold("error")} ${colors.dim(`${prefix}:`)}` : `error: ${prefix}:`;
|
|
1001
1186
|
const under = (label, text, tint) => text === undefined ? "" : `
|
|
1002
1187
|
${styled ? tint(label) : `${label}:`} ${text}`;
|
|
@@ -1039,11 +1224,11 @@ async function dispatch(level, typed, { version, redact }) {
|
|
|
1039
1224
|
}
|
|
1040
1225
|
}
|
|
1041
1226
|
if (name === undefined && level.path.length > 1) {
|
|
1042
|
-
console.error(await help2(await expand(level, [...level.path.slice(1), ...argv]),
|
|
1227
|
+
console.error(await help2(await expand(level, [...level.path.slice(1), ...argv]), process12.stderr));
|
|
1043
1228
|
return 2;
|
|
1044
1229
|
}
|
|
1045
1230
|
if (name === undefined || name === "help" || name === "--help" || name === "-h") {
|
|
1046
|
-
console.log(await help2(await expand(level, [...level.path.slice(1), ...argv]),
|
|
1231
|
+
console.log(await help2(await expand(level, [...level.path.slice(1), ...argv]), process12.stdout));
|
|
1047
1232
|
return 0;
|
|
1048
1233
|
}
|
|
1049
1234
|
if (level.path.length === 1 && (name === "--version" || name === "-v")) {
|
|
@@ -1160,17 +1345,17 @@ async function printCandidates(found) {
|
|
|
1160
1345
|
return 0;
|
|
1161
1346
|
}
|
|
1162
1347
|
function packageVersion(entry = Bun.main) {
|
|
1163
|
-
for (let dir =
|
|
1348
|
+
for (let dir = dirname3(realpathSync(entry));; dir = dirname3(dir)) {
|
|
1164
1349
|
try {
|
|
1165
|
-
const { version } = JSON.parse(
|
|
1350
|
+
const { version } = JSON.parse(readFileSync2(join5(dir, "package.json"), "utf8"));
|
|
1166
1351
|
if (typeof version === "string")
|
|
1167
1352
|
return version;
|
|
1168
1353
|
} catch {}
|
|
1169
|
-
if (
|
|
1354
|
+
if (dirname3(dir) === dir)
|
|
1170
1355
|
return "0.0.0";
|
|
1171
1356
|
}
|
|
1172
1357
|
}
|
|
1173
|
-
async function runCli(cli, argv =
|
|
1358
|
+
async function runCli(cli, argv = process12.argv.slice(2)) {
|
|
1174
1359
|
const version = cli.version ?? packageVersion();
|
|
1175
1360
|
if (argv[0] === COMPLETE)
|
|
1176
1361
|
return printCandidates(candidates(scopeOf(cli.commands, cli.extraCommands, cli.aliases), cli.defaultCommand, argv.slice(1)));
|
|
@@ -1197,7 +1382,7 @@ function commandPath(scope, argv) {
|
|
|
1197
1382
|
}
|
|
1198
1383
|
return path.length === 0 ? undefined : path.join(" ");
|
|
1199
1384
|
}
|
|
1200
|
-
async function runMain({ name, version, run, redact, usage }, argv =
|
|
1385
|
+
async function runMain({ name, version, run, redact, usage }, argv = process12.argv.slice(2)) {
|
|
1201
1386
|
if (argv[0] === COMPLETE)
|
|
1202
1387
|
return printCandidates(leafCandidates(run, argv.slice(1)));
|
|
1203
1388
|
if (argv.length === 1 && (argv[0] === "--version" || argv[0] === "-v")) {
|
|
@@ -1233,37 +1418,18 @@ function parseSize(text, bareUnit = 1) {
|
|
|
1233
1418
|
const suffix = match[2].toLowerCase();
|
|
1234
1419
|
return Math.round(Number(match[1]) * (suffix === "" ? bareUnit : 1024 ** POWERS[suffix]));
|
|
1235
1420
|
}
|
|
1236
|
-
// ../kit/src/user-config.ts
|
|
1237
|
-
import { existsSync } from "fs";
|
|
1238
|
-
import { homedir as homedir2 } from "os";
|
|
1239
|
-
import { join as join3 } from "path";
|
|
1240
|
-
import process10 from "process";
|
|
1241
|
-
function configBase(where = {}) {
|
|
1242
|
-
const xdg = where.xdg ?? (where.home === undefined ? process10.env.XDG_CONFIG_HOME : undefined);
|
|
1243
|
-
return xdg !== undefined && xdg !== "" ? xdg : join3(where.home ?? homedir2(), ".config");
|
|
1244
|
-
}
|
|
1245
|
-
function userConfigPath(bin, where = {}) {
|
|
1246
|
-
return join3(configBase(where), "kaynooo-cli", `${bin}.json`);
|
|
1247
|
-
}
|
|
1248
|
-
function userConfigReadPath(bin, legacy = [], where = {}) {
|
|
1249
|
-
const current = userConfigPath(bin, where);
|
|
1250
|
-
if (existsSync(current))
|
|
1251
|
-
return current;
|
|
1252
|
-
const base = configBase(where);
|
|
1253
|
-
return legacy.map((parts) => join3(base, ...parts)).find((path) => existsSync(path)) ?? current;
|
|
1254
|
-
}
|
|
1255
1421
|
// src/sweep.ts
|
|
1256
|
-
import { existsSync as
|
|
1257
|
-
import { homedir as
|
|
1258
|
-
import { join as
|
|
1422
|
+
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
1423
|
+
import { homedir as homedir5 } from "os";
|
|
1424
|
+
import { join as join9, relative, resolve as resolve3 } from "path";
|
|
1259
1425
|
|
|
1260
1426
|
// ../kit/src/prompt.ts
|
|
1261
|
-
import
|
|
1427
|
+
import process14 from "process";
|
|
1262
1428
|
var KEY_SEQUENCES = /\x1B\[[0-9;]*[A-Z~]|\x1BO[A-Z]|[\s\S]/giu;
|
|
1263
|
-
var
|
|
1429
|
+
var CONTROL2 = /^[\x00-\x1F\x7F]/;
|
|
1264
1430
|
var KEYS = { "\x1B[A": "up", "\x1BOA": "up", "\x1B[B": "down", "\x1BOB": "down", "\r": "enter", "\n": "enter", "\x03": "cancel", "\x1B": "cancel", "\x7F": "erase", "\b": "erase" };
|
|
1265
1431
|
function readKeys(input) {
|
|
1266
|
-
return (input.match(KEY_SEQUENCES) ?? []).flatMap((sequence) => KEYS[sequence] ?? (
|
|
1432
|
+
return (input.match(KEY_SEQUENCES) ?? []).flatMap((sequence) => KEYS[sequence] ?? (CONTROL2.test(sequence) ? [] : [{ text: sequence }]));
|
|
1267
1433
|
}
|
|
1268
1434
|
async function confirm(question, { default: fallback, ...settings } = {}) {
|
|
1269
1435
|
let answered = fallback;
|
|
@@ -1287,7 +1453,7 @@ function asking(colors, question, typed, keys) {
|
|
|
1287
1453
|
function answer(colors, question, state, picked) {
|
|
1288
1454
|
return state === "enter" ? `${colors.green("\u2713")} ${question} ${colors.cyan(picked)}` : `${colors.red("\u2717")} ${question} ${colors.dim("cancelled")}`;
|
|
1289
1455
|
}
|
|
1290
|
-
async function ask(question, { hint, terminal =
|
|
1456
|
+
async function ask(question, { hint, terminal = process14 }, render, press) {
|
|
1291
1457
|
const { stdin, stderr } = terminal;
|
|
1292
1458
|
if (stdin.isTTY !== true || stderr.isTTY !== true)
|
|
1293
1459
|
fail(`cannot ask "${question}" off a terminal`, 2, hint);
|
|
@@ -1338,19 +1504,19 @@ async function ask(question, { hint, terminal = process12 }, render, press) {
|
|
|
1338
1504
|
}
|
|
1339
1505
|
|
|
1340
1506
|
// src/apply.ts
|
|
1341
|
-
import { existsSync as
|
|
1507
|
+
import { existsSync as existsSync5 } from "fs";
|
|
1342
1508
|
import { lstat as lstat3, rm } from "fs/promises";
|
|
1343
|
-
import { basename as basename2, join as
|
|
1509
|
+
import { basename as basename2, join as join8 } from "path";
|
|
1344
1510
|
|
|
1345
1511
|
// src/sweep-scan.ts
|
|
1346
|
-
import { existsSync as
|
|
1512
|
+
import { existsSync as existsSync4 } from "fs";
|
|
1347
1513
|
import { lstat as lstat2, readdir as readdir2, realpath } from "fs/promises";
|
|
1348
|
-
import { homedir as
|
|
1349
|
-
import { basename, dirname as
|
|
1514
|
+
import { homedir as homedir4 } from "os";
|
|
1515
|
+
import { basename, dirname as dirname4, join as join7 } from "path";
|
|
1350
1516
|
|
|
1351
1517
|
// src/size.ts
|
|
1352
1518
|
import { lstat, readdir } from "fs/promises";
|
|
1353
|
-
import { join as
|
|
1519
|
+
import { join as join6 } from "path";
|
|
1354
1520
|
async function pooled(items, limit, work) {
|
|
1355
1521
|
const results = Array.from({ length: items.length });
|
|
1356
1522
|
let next = 0;
|
|
@@ -1387,7 +1553,7 @@ async function sizeOf(folder) {
|
|
|
1387
1553
|
return;
|
|
1388
1554
|
}
|
|
1389
1555
|
await Promise.all(entries.map(async (entry) => {
|
|
1390
|
-
const path =
|
|
1556
|
+
const path = join6(dir, entry.name);
|
|
1391
1557
|
if (entry.isDirectory())
|
|
1392
1558
|
return visit(path);
|
|
1393
1559
|
try {
|
|
@@ -1411,8 +1577,8 @@ var FOLDER_NAMES = new Set(["node_modules", ".nuxt", ".next", ".output", "dist",
|
|
|
1411
1577
|
var MAX_DEPTH = 3;
|
|
1412
1578
|
var PROJECT_CACHE_NAMES = new Set([".turbo", ".nuxt", ".next", ".svelte-kit"]);
|
|
1413
1579
|
var GLOBAL_CACHES = [".bun/install/cache", ".npm/_cacache", ".cache/pip", ".cache/uv", ".cache/ms-playwright", ".cache/puppeteer", ".cache/go-build", ".cache/typescript", ".cargo/registry"];
|
|
1414
|
-
function isCachePath(path, home =
|
|
1415
|
-
return GLOBAL_CACHES.some((cache) =>
|
|
1580
|
+
function isCachePath(path, home = homedir4()) {
|
|
1581
|
+
return GLOBAL_CACHES.some((cache) => join7(home, cache) === path) || basename(path) === ".cache" && basename(dirname4(path)) === "node_modules";
|
|
1416
1582
|
}
|
|
1417
1583
|
async function listing(dir) {
|
|
1418
1584
|
try {
|
|
@@ -1423,7 +1589,7 @@ async function listing(dir) {
|
|
|
1423
1589
|
}
|
|
1424
1590
|
async function addGlobalCaches(found, home) {
|
|
1425
1591
|
for (const cache of GLOBAL_CACHES) {
|
|
1426
|
-
const path =
|
|
1592
|
+
const path = join7(home, cache);
|
|
1427
1593
|
try {
|
|
1428
1594
|
const stat = await lstat2(path);
|
|
1429
1595
|
if (stat.isSymbolicLink())
|
|
@@ -1433,12 +1599,12 @@ async function addGlobalCaches(found, home) {
|
|
|
1433
1599
|
} catch {}
|
|
1434
1600
|
}
|
|
1435
1601
|
}
|
|
1436
|
-
async function findCandidates(root, home =
|
|
1602
|
+
async function findCandidates(root, home = homedir4(), withGlobal = true) {
|
|
1437
1603
|
const found = { candidates: [], skipped: [] };
|
|
1438
1604
|
const visit = async (dir, depth) => {
|
|
1439
1605
|
const entries = await listing(dir);
|
|
1440
1606
|
for (const entry of entries) {
|
|
1441
|
-
const path =
|
|
1607
|
+
const path = join7(dir, entry.name);
|
|
1442
1608
|
if (entry.name === ".git")
|
|
1443
1609
|
continue;
|
|
1444
1610
|
if (entry.name === ".worktrees" || entry.name === "worktrees" && basename(dir) === ".claude") {
|
|
@@ -1448,13 +1614,13 @@ async function findCandidates(root, home = homedir3(), withGlobal = true) {
|
|
|
1448
1614
|
}
|
|
1449
1615
|
for (const worktree of await listing(path)) {
|
|
1450
1616
|
if (worktree.isDirectory())
|
|
1451
|
-
found.candidates.push({ path:
|
|
1617
|
+
found.candidates.push({ path: join7(path, worktree.name), kind: "worktree" });
|
|
1452
1618
|
else if (worktree.isSymbolicLink())
|
|
1453
|
-
found.skipped.push({ path:
|
|
1619
|
+
found.skipped.push({ path: join7(path, worktree.name), reason: "symlink" });
|
|
1454
1620
|
}
|
|
1455
1621
|
continue;
|
|
1456
1622
|
}
|
|
1457
|
-
if (FOLDER_NAMES.has(entry.name) && (entry.name !== "target" ||
|
|
1623
|
+
if (FOLDER_NAMES.has(entry.name) && (entry.name !== "target" || existsSync4(join7(dir, "Cargo.toml")))) {
|
|
1458
1624
|
if (entry.isSymbolicLink()) {
|
|
1459
1625
|
found.skipped.push({ path, reason: "symlink" });
|
|
1460
1626
|
} else if (entry.isDirectory()) {
|
|
@@ -1462,9 +1628,9 @@ async function findCandidates(root, home = homedir3(), withGlobal = true) {
|
|
|
1462
1628
|
if (entry.name === "node_modules") {
|
|
1463
1629
|
const cache = (await listing(path)).find((inner) => inner.name === ".cache");
|
|
1464
1630
|
if (cache?.isSymbolicLink())
|
|
1465
|
-
found.skipped.push({ path:
|
|
1631
|
+
found.skipped.push({ path: join7(path, ".cache"), reason: "symlink" });
|
|
1466
1632
|
else if (cache?.isDirectory())
|
|
1467
|
-
found.candidates.push({ path:
|
|
1633
|
+
found.candidates.push({ path: join7(path, ".cache"), kind: "cache", inside: path });
|
|
1468
1634
|
}
|
|
1469
1635
|
}
|
|
1470
1636
|
continue;
|
|
@@ -1535,12 +1701,12 @@ var worktreesOf = memo(async (repo) => {
|
|
|
1535
1701
|
return branches;
|
|
1536
1702
|
});
|
|
1537
1703
|
async function judgeFolder(path, kind, inside) {
|
|
1538
|
-
const parent =
|
|
1704
|
+
const parent = dirname4(path);
|
|
1539
1705
|
const name = basename(path);
|
|
1540
1706
|
const located = await toplevelOf(parent);
|
|
1541
1707
|
if (located === "failed")
|
|
1542
1708
|
return { skip: "git failed" };
|
|
1543
|
-
if (
|
|
1709
|
+
if (existsSync4(join7(path, ".git")))
|
|
1544
1710
|
return { skip: "holds a git repository" };
|
|
1545
1711
|
if (located === "none")
|
|
1546
1712
|
return name === "node_modules" || inside !== undefined ? { entry: { path, kind, committedAt: undefined, action: "remove", inside } } : { skip: "not in a git repository" };
|
|
@@ -1552,7 +1718,7 @@ async function judgeFolder(path, kind, inside) {
|
|
|
1552
1718
|
return { entry: { path, kind, committedAt: await lastCommitOf(located.top), action: "remove", inside } };
|
|
1553
1719
|
}
|
|
1554
1720
|
async function judgeWorktree(path) {
|
|
1555
|
-
const located = await toplevelOf(
|
|
1721
|
+
const located = await toplevelOf(dirname4(path));
|
|
1556
1722
|
if (located === "failed")
|
|
1557
1723
|
return { skip: "git failed" };
|
|
1558
1724
|
if (located === "none")
|
|
@@ -1608,7 +1774,7 @@ async function removeFolder(entry) {
|
|
|
1608
1774
|
const stat = await lstat3(entry.path);
|
|
1609
1775
|
if (stat.isSymbolicLink() || !stat.isDirectory() || !(FOLDER_NAMES.has(basename2(entry.path)) || entry.kind === "cache" && isCachePath(entry.path)))
|
|
1610
1776
|
return { path: entry.path, removed: false, error: "no longer a plain folder" };
|
|
1611
|
-
if (
|
|
1777
|
+
if (existsSync5(join8(entry.path, ".git")))
|
|
1612
1778
|
return { path: entry.path, removed: false, error: "holds a git repository" };
|
|
1613
1779
|
await rm(entry.path, { recursive: true, force: true });
|
|
1614
1780
|
return { path: entry.path, removed: true };
|
|
@@ -1639,6 +1805,8 @@ async function applyAll(entries, done) {
|
|
|
1639
1805
|
}
|
|
1640
1806
|
|
|
1641
1807
|
// src/sweep.ts
|
|
1808
|
+
var LARGE = 100 * 1024 ** 2;
|
|
1809
|
+
var BIG = 1024 ** 3;
|
|
1642
1810
|
var USAGE = `sweep [options] [root]: lists the regenerable folders (node_modules, .output, dist, build, target beside a Cargo.toml), the caches (.nuxt, .next, .turbo, .svelte-kit and node_modules/.cache per project; ~/.bun/install/cache, ~/.npm/_cacache, ~/.cache/{pip,uv,ms-playwright,puppeteer,go-build,typescript} and ~/.cargo/registry, exact paths only, listed only when no root is given or with --only caches) and the .worktrees/* and .claude/worktrees/* entries under root (~/Workspace by default, ${MAX_DEPTH} levels down), largest first with the age of the repo's last commit; --only worktrees, folders or caches keeps one kind
|
|
1643
1811
|
|
|
1644
1812
|
Dry unless --apply, which deletes after a confirm showing the total (read from the terminal; off one, pass --yes). A folder is deleted for good, not trashed. Never touched: a symlink, a folder git tracks files in, a build folder git does not ignore. A worktree is removed with git worktree remove, never forced, and only when it is clean and every commit of its branch is on another branch or a remote; the others stay listed as kept and count for nothing in the total. With --docker the Docker usage comes after the list, left to dclean.
|
|
@@ -1668,8 +1836,8 @@ async function sweep(args) {
|
|
|
1668
1836
|
const { values, positionals } = parse(args, USAGE, OPTIONS, { positionals: ["[root]"], replaces: "find ~/Workspace -name node_modules, du -sh and rm -rf by hand", examples: ["sweep", "sweep ~/Workspace --older 30d --min 100M --apply", "sweep --only worktrees --apply"] });
|
|
1669
1837
|
if (positionals.length > 1)
|
|
1670
1838
|
badUsage("give one root");
|
|
1671
|
-
const root =
|
|
1672
|
-
if (!
|
|
1839
|
+
const root = resolve3(positionals[0] ?? join9(homedir5(), "Workspace"));
|
|
1840
|
+
if (!existsSync6(root) || !statSync2(root).isDirectory())
|
|
1673
1841
|
fail(`${root} is not a folder`);
|
|
1674
1842
|
if (values.only !== undefined && !Object.hasOwn(ONLY_KINDS, values.only))
|
|
1675
1843
|
badUsage(`--only takes worktrees, folders or caches, not ${values.only}`);
|
|
@@ -1678,7 +1846,7 @@ async function sweep(args) {
|
|
|
1678
1846
|
if (minBytes === undefined)
|
|
1679
1847
|
badUsage(`--min takes a size such as 500K, 10M or 1G, not ${values.min}`);
|
|
1680
1848
|
const now = Date.now();
|
|
1681
|
-
const found = await findCandidates(root,
|
|
1849
|
+
const found = await findCandidates(root, homedir5(), positionals.length === 0 || values.only === "caches");
|
|
1682
1850
|
const wanted = values.only === undefined ? found.candidates : found.candidates.filter((candidate) => candidate.kind === ONLY_KINDS[values.only]);
|
|
1683
1851
|
const { entries: all, skipped } = await inspect({ candidates: wanted, skipped: found.skipped });
|
|
1684
1852
|
const entries = all.filter((entry) => entry.bytes >= minBytes && (olderMs === undefined || entry.committedAt !== undefined && now - entry.committedAt >= olderMs)).sort((a, b) => b.bytes - a.bytes || a.path.localeCompare(b.path));
|
|
@@ -1730,10 +1898,17 @@ function print(root, entries, skipped, reclaimable, now) {
|
|
|
1730
1898
|
console.log("nothing to sweep");
|
|
1731
1899
|
return;
|
|
1732
1900
|
}
|
|
1733
|
-
|
|
1901
|
+
const colors = paint(process.stdout);
|
|
1902
|
+
const path = role("path", process.stdout);
|
|
1903
|
+
const sized = (bytes) => {
|
|
1904
|
+
if (bytes >= BIG)
|
|
1905
|
+
return colors.red($e(bytes));
|
|
1906
|
+
return bytes >= LARGE ? colors.yellow($e(bytes)) : $e(bytes);
|
|
1907
|
+
};
|
|
1908
|
+
console.log(table([["size", "age", "what", "path", "note"], ...entries.map((entry) => [sized(entry.bytes), entry.committedAt === undefined ? colors.dim("-") : colors.dim(formatAge(entry.committedAt, now)), entry.kind, path(relative(root, entry.path)), entry.action === "keep" ? colors.dim(`kept: ${entry.reason}`) : ""])], { header: true, align: ["right", "right", "left", "left", "left"] }));
|
|
1734
1909
|
console.log(`
|
|
1735
1910
|
${$e(reclaimable)} reclaimable${skipped === 0 ? "" : `, ${skipped} skipped (symlinks, tracked or not ignored by git)`}`);
|
|
1736
1911
|
}
|
|
1737
1912
|
|
|
1738
1913
|
// src/sweep-cli.ts
|
|
1739
|
-
|
|
1914
|
+
process15.exitCode = await runMain({ name: "sweep", run: sweep });
|