@kaynooo/cli-pkg 0.0.0-stage → 0.7.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/LICENSE +21 -0
- package/README.md +63 -2
- package/dist/cli.js +2799 -0
- package/package.json +33 -4
package/dist/cli.js
ADDED
|
@@ -0,0 +1,2799 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __returnValue = (v) => v;
|
|
5
|
+
function __exportSetter(name, newValue) {
|
|
6
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
7
|
+
}
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, {
|
|
11
|
+
get: all[name],
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
set: __exportSetter.bind(all, name)
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
var __esm = (fn, res, err) => () => {
|
|
18
|
+
if (fn)
|
|
19
|
+
try {
|
|
20
|
+
res = fn(fn = 0);
|
|
21
|
+
} catch (e) {
|
|
22
|
+
err = [e];
|
|
23
|
+
}
|
|
24
|
+
if (err)
|
|
25
|
+
throw err[0];
|
|
26
|
+
return res;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// ../../node_modules/.bun/@kaynooo+utils@2.31.0+d0769e28dc4dad16/node_modules/@kaynooo/utils/dist/chunk-mtetydvc.js
|
|
30
|
+
function x(s) {
|
|
31
|
+
let r = s.startsWith("#") ? s.slice(1).toLowerCase() : s.toLowerCase();
|
|
32
|
+
if (!/^[a-f0-9]+$/.test(r))
|
|
33
|
+
return [0, 0, 0];
|
|
34
|
+
let t = r.length, n = (c) => Number.parseInt(c, 16);
|
|
35
|
+
if (t === 3 || t === 4) {
|
|
36
|
+
let c = n(r[0] + r[0]), u = n(r[1] + r[1]), h = n(r[2] + r[2]), g = t === 4 ? n(r[3] + r[3]) : undefined;
|
|
37
|
+
return g !== undefined ? [c, u, h, g] : [c, u, h];
|
|
38
|
+
}
|
|
39
|
+
if (t !== 6 && t !== 8)
|
|
40
|
+
throw Error(`Invalid hex color length: ${t}`);
|
|
41
|
+
let a = n(r.slice(0, 2)), b = n(r.slice(2, 4)), o = n(r.slice(4, 6)), y = t === 8 ? n(r.slice(6, 8)) : undefined;
|
|
42
|
+
if ([a, b, o].some(Number.isNaN) || y !== undefined && Number.isNaN(y))
|
|
43
|
+
throw Error(`Invalid hex color value: ${s}`);
|
|
44
|
+
return y !== undefined ? [a, b, o, y] : [a, b, o];
|
|
45
|
+
}
|
|
46
|
+
function A(s) {
|
|
47
|
+
let [r, t, n, a] = s;
|
|
48
|
+
if (a)
|
|
49
|
+
return `#${(r << 24 | t << 16 | n << 8 | Math.round((a ?? 1) * 255)).toString(16).padStart(8, "0").toUpperCase()}`;
|
|
50
|
+
return `#${(r << 16 | t << 8 | n).toString(16).padStart(6, "0").toUpperCase()}`;
|
|
51
|
+
}
|
|
52
|
+
function R(s, r, t) {
|
|
53
|
+
s = (s % 360 + 360) % 360, t /= 100;
|
|
54
|
+
let n = r * Math.min(t, 1 - t) / 100, a = (b) => {
|
|
55
|
+
let o = (b + s / 30) % 12, y = t - n * Math.max(Math.min(o - 3, 9 - o, 1), -1);
|
|
56
|
+
return Math.round(255 * y);
|
|
57
|
+
};
|
|
58
|
+
return [a(0), a(8), a(4)];
|
|
59
|
+
}
|
|
60
|
+
function k(s) {
|
|
61
|
+
let [r, t, n] = s;
|
|
62
|
+
r /= 255, t /= 255, n /= 255;
|
|
63
|
+
let a = Math.max(r, t, n), b = Math.min(r, t, n), o = 0, y = 0, c = (a + b) / 2;
|
|
64
|
+
if (a !== b) {
|
|
65
|
+
let u = a - b;
|
|
66
|
+
if (y = c > 0 && c < 1 ? u / (1 - Math.abs(2 * c - 1)) : 0, a === r)
|
|
67
|
+
o = (t - n) / u + (t < n ? 6 : 0);
|
|
68
|
+
else if (a === t)
|
|
69
|
+
o = (n - r) / u + 2;
|
|
70
|
+
else
|
|
71
|
+
o = (r - t) / u + 4;
|
|
72
|
+
o /= 6;
|
|
73
|
+
}
|
|
74
|
+
return [Math.round(o * 360), Math.round(y * 100), Math.round(c * 100)];
|
|
75
|
+
}
|
|
76
|
+
function H(s, r, t) {
|
|
77
|
+
s = (s % 360 + 360) % 360, r /= 100, t /= 100;
|
|
78
|
+
let n = (a) => {
|
|
79
|
+
let b = (a + s / 60) % 6, o = t - t * r * Math.max(Math.min(b, 4 - b, 1), 0);
|
|
80
|
+
return Math.round(255 * o);
|
|
81
|
+
};
|
|
82
|
+
return [n(5), n(3), n(1)];
|
|
83
|
+
}
|
|
84
|
+
function f(s) {
|
|
85
|
+
let [r, t, n] = s;
|
|
86
|
+
r /= 255, t /= 255, n /= 255;
|
|
87
|
+
let a = Math.max(r, t, n), b = Math.min(r, t, n), o = a - b, y = 0, c = a === 0 ? 0 : o / a, u = a;
|
|
88
|
+
if (o !== 0) {
|
|
89
|
+
if (a === r)
|
|
90
|
+
y = (t - n) / o + (t < n ? 6 : 0);
|
|
91
|
+
else if (a === t)
|
|
92
|
+
y = (n - r) / o + 2;
|
|
93
|
+
else
|
|
94
|
+
y = (r - t) / o + 4;
|
|
95
|
+
y /= 6;
|
|
96
|
+
}
|
|
97
|
+
return [Math.round(y * 360), Math.round(c * 100), Math.round(u * 100)];
|
|
98
|
+
}
|
|
99
|
+
function O(s) {
|
|
100
|
+
let r = s[0] / 255, t = s[1] / 255, n = s[2] / 255, a = 1 - Math.max(r, t, n);
|
|
101
|
+
if (a === 1)
|
|
102
|
+
return [0, 0, 0, 100];
|
|
103
|
+
let b = (1 - r - a) / (1 - a), o = (1 - t - a) / (1 - a), y = (1 - n - a) / (1 - a);
|
|
104
|
+
return [Math.round(b * 100), Math.round(o * 100), Math.round(y * 100), Math.round(a * 100)];
|
|
105
|
+
}
|
|
106
|
+
function v(s, r, t, n) {
|
|
107
|
+
return s /= 100, r /= 100, t /= 100, n /= 100, [Math.round(255 * (1 - s) * (1 - n)), Math.round(255 * (1 - r) * (1 - n)), Math.round(255 * (1 - t) * (1 - n))];
|
|
108
|
+
}
|
|
109
|
+
function T(s) {
|
|
110
|
+
let r = m(s[0] / 255), t = m(s[1] / 255), n = m(s[2] / 255), a = Math.cbrt(0.4122214708 * r + 0.5363325363 * t + 0.0514459929 * n), b = Math.cbrt(0.2119034982 * r + 0.6806995451 * t + 0.1073969566 * n), o = Math.cbrt(0.0883024619 * r + 0.2817188376 * t + 0.6299787005 * n);
|
|
111
|
+
return [i(0.2104542553 * a + 0.793617785 * b - 0.0040720468 * o, 4), i(1.9779984951 * a - 2.428592205 * b + 0.4505937099 * o, 4), i(0.0259040371 * a + 0.7827717662 * b - 0.808675766 * o, 4)];
|
|
112
|
+
}
|
|
113
|
+
function M(s, r, t) {
|
|
114
|
+
let n = (s + 0.3963377774 * r + 0.2158037573 * t) ** 3, a = (s - 0.1055613458 * r - 0.0638541728 * t) ** 3, b = (s - 0.0894841775 * r - 1.291485548 * t) ** 3, o = p(4.0767416621 * n - 3.3077115913 * a + 0.2309699292 * b), y = p(-1.2684380046 * n + 2.6097574011 * a - 0.3413193965 * b), c = p(-0.0041960863 * n - 0.7034186147 * a + 1.707614701 * b), u = (h) => Math.min(255, Math.max(0, Math.round(h * 255)));
|
|
115
|
+
return [u(o), u(y), u(c)];
|
|
116
|
+
}
|
|
117
|
+
function d(s) {
|
|
118
|
+
let [r, t, n] = T(s), a = Math.sqrt(t * t + n * n), b = (Math.atan2(n, t) * 180 / Math.PI + 360) % 360;
|
|
119
|
+
return [i(r, 4), i(a, 4), i(b, 2)];
|
|
120
|
+
}
|
|
121
|
+
function C(s, r, t) {
|
|
122
|
+
let n = t * Math.PI / 180;
|
|
123
|
+
return M(s, r * Math.cos(n), r * Math.sin(n));
|
|
124
|
+
}
|
|
125
|
+
function l(s) {
|
|
126
|
+
let r = s / 255;
|
|
127
|
+
return r <= 0.03928 ? r / 12.92 : ((r + 0.055) / 1.055) ** 2.4;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
class e {
|
|
131
|
+
r;
|
|
132
|
+
g;
|
|
133
|
+
b;
|
|
134
|
+
a;
|
|
135
|
+
constructor(s, r, t, n = 1) {
|
|
136
|
+
this.r = s, this.g = r, this.b = t, this.a = n;
|
|
137
|
+
}
|
|
138
|
+
static from(s, r) {
|
|
139
|
+
if (s === "hex") {
|
|
140
|
+
let [t, n, a, b] = x(r);
|
|
141
|
+
return new e(t, n, a, b);
|
|
142
|
+
}
|
|
143
|
+
if (s === "rgb") {
|
|
144
|
+
if (Array.isArray(r)) {
|
|
145
|
+
let [o, y, c, u] = r;
|
|
146
|
+
return new e(o, y, c, u);
|
|
147
|
+
}
|
|
148
|
+
let { r: t, g: n, b: a, a: b } = r;
|
|
149
|
+
return new e(t, n, a, b);
|
|
150
|
+
}
|
|
151
|
+
if (s === "hsl") {
|
|
152
|
+
let t, n, a, b;
|
|
153
|
+
if (Array.isArray(r))
|
|
154
|
+
[t, n, a, b] = r;
|
|
155
|
+
else
|
|
156
|
+
({ h: t, s: n, l: a, a: b } = r);
|
|
157
|
+
let [o, y, c] = R(t, n, a);
|
|
158
|
+
return new e(o, y, c, b);
|
|
159
|
+
}
|
|
160
|
+
if (s === "hsv") {
|
|
161
|
+
let t, n, a, b;
|
|
162
|
+
if (Array.isArray(r))
|
|
163
|
+
[t, n, a, b] = r;
|
|
164
|
+
else
|
|
165
|
+
({ h: t, s: n, v: a, a: b } = r);
|
|
166
|
+
let [o, y, c] = H(t, n, a);
|
|
167
|
+
return new e(o, y, c, b);
|
|
168
|
+
}
|
|
169
|
+
if (s === "cmyk") {
|
|
170
|
+
let t, n, a, b, o;
|
|
171
|
+
if (Array.isArray(r))
|
|
172
|
+
[t, n, a, b, o] = r;
|
|
173
|
+
else
|
|
174
|
+
({ c: t, m: n, y: a, k: b, a: o } = r);
|
|
175
|
+
let [y, c, u] = v(t, n, a, b);
|
|
176
|
+
return new e(y, c, u, o);
|
|
177
|
+
}
|
|
178
|
+
if (s === "oklch") {
|
|
179
|
+
let t, n, a, b;
|
|
180
|
+
if (Array.isArray(r))
|
|
181
|
+
[t, n, a, b] = r;
|
|
182
|
+
else
|
|
183
|
+
({ l: t, c: n, h: a, a: b } = r);
|
|
184
|
+
let [o, y, c] = C(t, n, a);
|
|
185
|
+
return new e(o, y, c, b);
|
|
186
|
+
}
|
|
187
|
+
if (s === "oklab") {
|
|
188
|
+
let t, n, a, b;
|
|
189
|
+
if (Array.isArray(r))
|
|
190
|
+
[t, n, a, b] = r;
|
|
191
|
+
else
|
|
192
|
+
({ l: t, a: n, b: a, alpha: b } = r);
|
|
193
|
+
let [o, y, c] = M(t, n, a);
|
|
194
|
+
return new e(o, y, c, b);
|
|
195
|
+
}
|
|
196
|
+
throw Error("Invalid input");
|
|
197
|
+
}
|
|
198
|
+
to(s) {
|
|
199
|
+
switch (s) {
|
|
200
|
+
case "rgb":
|
|
201
|
+
return [this.r, this.g, this.b];
|
|
202
|
+
case "rgba":
|
|
203
|
+
return [this.r, this.g, this.b, this.a];
|
|
204
|
+
case "hex":
|
|
205
|
+
return A([this.r, this.g, this.b]);
|
|
206
|
+
case "hexa":
|
|
207
|
+
return A([this.r, this.g, this.b, this.a]);
|
|
208
|
+
case "hsl":
|
|
209
|
+
return k([this.r, this.g, this.b]);
|
|
210
|
+
case "hsla":
|
|
211
|
+
return [...k([this.r, this.g, this.b]), this.a];
|
|
212
|
+
case "hsv":
|
|
213
|
+
return f([this.r, this.g, this.b]);
|
|
214
|
+
case "hsva":
|
|
215
|
+
return [...f([this.r, this.g, this.b]), this.a];
|
|
216
|
+
case "cmyk":
|
|
217
|
+
return O([this.r, this.g, this.b]);
|
|
218
|
+
case "cmyka":
|
|
219
|
+
return [...O([this.r, this.g, this.b]), this.a];
|
|
220
|
+
case "oklch":
|
|
221
|
+
return d([this.r, this.g, this.b]);
|
|
222
|
+
case "oklcha":
|
|
223
|
+
return [...d([this.r, this.g, this.b]), this.a];
|
|
224
|
+
case "oklab":
|
|
225
|
+
return T([this.r, this.g, this.b]);
|
|
226
|
+
case "oklaba":
|
|
227
|
+
return [...T([this.r, this.g, this.b]), this.a];
|
|
228
|
+
default:
|
|
229
|
+
return [this.r, this.g, this.b];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
getLuminance() {
|
|
233
|
+
let s = l(this.r), r = l(this.g), t = l(this.b);
|
|
234
|
+
return 0.2126 * s + 0.7152 * r + 0.0722 * t;
|
|
235
|
+
}
|
|
236
|
+
contrastRatio(s) {
|
|
237
|
+
let r = this.getLuminance(), t = s.getLuminance(), [n, a] = r >= t ? [r, t] : [t, r];
|
|
238
|
+
return (n + 0.05) / (a + 0.05);
|
|
239
|
+
}
|
|
240
|
+
bestContrastForeground() {
|
|
241
|
+
let s = new e(255, 255, 255, 1), r = new e(0, 0, 0, 1), t = this.contrastRatio(s), n = this.contrastRatio(r);
|
|
242
|
+
return t >= n ? s : r;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
var m = (s) => s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4, p = (s) => s <= 0.0031308 ? 12.92 * s : 1.055 * s ** 0.4166666666666667 - 0.055, i = (s, r) => Math.round(s * 10 ** r) / 10 ** r;
|
|
246
|
+
var init_chunk_mtetydvc = () => {};
|
|
247
|
+
|
|
248
|
+
// ../../node_modules/.bun/@kaynooo+utils@2.31.0+d0769e28dc4dad16/node_modules/@kaynooo/utils/dist/chunk-y1msbssb.js
|
|
249
|
+
function h(i, n = globalThis.process?.env ?? {}) {
|
|
250
|
+
if (n.FORCE_COLOR !== undefined)
|
|
251
|
+
return b.has(n.FORCE_COLOR);
|
|
252
|
+
if (n.NO_COLOR !== undefined || n.NODE_DISABLE_COLORS !== undefined || n.TERM === "dumb")
|
|
253
|
+
return false;
|
|
254
|
+
return i?.isTTY === true;
|
|
255
|
+
}
|
|
256
|
+
function d2(i, n, a) {
|
|
257
|
+
if (!h(a.stream ?? globalThis.process?.stdout, a.env))
|
|
258
|
+
return n;
|
|
259
|
+
let l = "", s = "";
|
|
260
|
+
for (let g = 0, y = i.length;g < y; g++) {
|
|
261
|
+
let [c, p] = i[g];
|
|
262
|
+
l += `${f2}${c}m`, s = `${f2}${p}m${s}`;
|
|
263
|
+
}
|
|
264
|
+
return l + n + s;
|
|
265
|
+
}
|
|
266
|
+
function u(i, n = []) {
|
|
267
|
+
return new Proxy((l) => d2(n, l, i), { get(l, s) {
|
|
268
|
+
let g = C2[s];
|
|
269
|
+
if (Array.isArray(g))
|
|
270
|
+
return u(i, [...n, g]);
|
|
271
|
+
if (typeof g === "function")
|
|
272
|
+
return (...y) => u(i, [...n, g(...y)]);
|
|
273
|
+
throw Error(`Unknown style: ${String(s)}`);
|
|
274
|
+
} });
|
|
275
|
+
}
|
|
276
|
+
function le(i = {}) {
|
|
277
|
+
return u(i);
|
|
278
|
+
}
|
|
279
|
+
var r = 39, o = 49, f2 = "\x1B[", C2, b, t;
|
|
280
|
+
var init_chunk_y1msbssb = __esm(() => {
|
|
281
|
+
init_chunk_mtetydvc();
|
|
282
|
+
C2 = { reset: [0, 0], bold: [1, 22], dim: [2, 22], italic: [3, 23], underline: [4, 24], inverse: [7, 27], hidden: [8, 28], strikethrough: [9, 29], black: [30, r], red: [31, r], green: [32, r], yellow: [33, r], blue: [34, r], magenta: [35, r], cyan: [36, r], white: [37, r], gray: [90, r], grey: [90, r], blackBright: [90, r], redBright: [91, r], greenBright: [92, r], yellowBright: [93, r], blueBright: [94, r], magentaBright: [95, r], cyanBright: [96, r], whiteBright: [97, r], bgBlack: [40, o], bgRed: [41, o], bgGreen: [42, o], bgYellow: [43, o], bgBlue: [44, o], bgMagenta: [45, o], bgCyan: [46, o], bgWhite: [47, o], bgBlackBright: [100, o], bgRedBright: [101, o], bgGreenBright: [102, o], bgYellowBright: [103, o], bgBlueBright: [104, o], bgMagentaBright: [105, o], bgCyanBright: [106, o], bgWhiteBright: [107, o], rgb: (i, n, a, l = "fg") => [`${l === "fg" ? 38 : 48};2;${i};${n};${a}`, l === "fg" ? r : o], hex: (i, n = "fg") => {
|
|
283
|
+
let [a, l, s] = e.from("hex", i).to("rgb");
|
|
284
|
+
return [`${n === "fg" ? 38 : 48};2;${a};${l};${s}`, n === "fg" ? r : o];
|
|
285
|
+
}, ansi256: (i, n = "fg") => [`${n === "fg" ? 38 : 48};5;${i}`, n === "fg" ? r : o] };
|
|
286
|
+
b = new Set(["", "1", "2", "3", "true"]);
|
|
287
|
+
t = le();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// ../../node_modules/.bun/@kaynooo+utils@2.31.0+d0769e28dc4dad16/node_modules/@kaynooo/utils/dist/tools/colors.js
|
|
291
|
+
var init_colors = __esm(() => {
|
|
292
|
+
init_chunk_y1msbssb();
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// ../kit/src/style.ts
|
|
296
|
+
import process from "process";
|
|
297
|
+
function takesControlCodes(stream, env = process.env) {
|
|
298
|
+
return stream.isTTY === true && env.NO_COLOR === undefined && env.NODE_DISABLE_COLORS === undefined && env.TERM !== "dumb";
|
|
299
|
+
}
|
|
300
|
+
function paint(stream, env = process.env) {
|
|
301
|
+
return le({ stream: { isTTY: takesControlCodes(stream, env) }, env });
|
|
302
|
+
}
|
|
303
|
+
function marked(mark, text, stream, detail, env = process.env) {
|
|
304
|
+
const colors = paint(stream, env);
|
|
305
|
+
const { symbol, word, paint: tint } = MARKS[mark];
|
|
306
|
+
const head = takesControlCodes(stream, env) ? tint(colors)(symbol) : word;
|
|
307
|
+
return `${head} ${text}${detail === undefined ? "" : ` ${colors.dim(detail)}`}`;
|
|
308
|
+
}
|
|
309
|
+
function ok(text, detail) {
|
|
310
|
+
console.log(marked("ok", text, process.stdout, detail));
|
|
311
|
+
}
|
|
312
|
+
function note(text, detail) {
|
|
313
|
+
console.log(marked("note", text, process.stdout, detail));
|
|
314
|
+
}
|
|
315
|
+
function warn(text, detail) {
|
|
316
|
+
console.error(marked("warn", text, process.stderr, detail));
|
|
317
|
+
}
|
|
318
|
+
function problem(text, detail) {
|
|
319
|
+
console.error(marked("problem", text, process.stderr, detail));
|
|
320
|
+
}
|
|
321
|
+
var MARKS, STATUSES, STATUS_OF;
|
|
322
|
+
var init_style = __esm(() => {
|
|
323
|
+
init_colors();
|
|
324
|
+
MARKS = {
|
|
325
|
+
ok: { symbol: "\u2713", word: "ok:", paint: (colors) => colors.green },
|
|
326
|
+
warn: { symbol: "!", word: "warning:", paint: (colors) => colors.yellow },
|
|
327
|
+
problem: { symbol: "\u2717", word: "error:", paint: (colors) => colors.red },
|
|
328
|
+
note: { symbol: "\xB7", word: "note:", paint: (colors) => colors.dim }
|
|
329
|
+
};
|
|
330
|
+
STATUSES = {
|
|
331
|
+
passed: { symbol: "\u2713", words: ["passed", "success", "succeeded", "ok"], paint: (colors) => colors.green },
|
|
332
|
+
failed: { symbol: "\u2717", words: ["failed", "failure", "error", "errored"], paint: (colors) => colors.red },
|
|
333
|
+
running: { symbol: "\u25CF", words: ["running", "in_progress", "started"], paint: (colors) => colors.cyan },
|
|
334
|
+
queued: { symbol: "\u25CB", words: ["queued", "waiting", "pending", "created", "blocked", "scheduled"], paint: (colors) => colors.yellow },
|
|
335
|
+
skipped: { symbol: "-", words: ["skipped", "cancelled", "canceled", "manual"], paint: (colors) => colors.dim }
|
|
336
|
+
};
|
|
337
|
+
STATUS_OF = new Map(Object.entries(STATUSES).flatMap(([status, { words }]) => words.map((word) => [word, status])));
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// ../kit/src/format.ts
|
|
341
|
+
import process2 from "process";
|
|
342
|
+
function formatSeconds(total) {
|
|
343
|
+
let rest = Math.max(0, Math.round(total));
|
|
344
|
+
const amounts = UNITS.map(([unit, size]) => {
|
|
345
|
+
const amount = Math.floor(rest / size);
|
|
346
|
+
rest -= amount * size;
|
|
347
|
+
return `${amount}${unit}`;
|
|
348
|
+
});
|
|
349
|
+
const first = amounts.findIndex((amount) => !amount.startsWith("0"));
|
|
350
|
+
if (first === -1)
|
|
351
|
+
return "0s";
|
|
352
|
+
const next = amounts[first + 1];
|
|
353
|
+
return next === undefined || next.startsWith("0") ? amounts[first] ?? "0s" : `${amounts[first]} ${next}`;
|
|
354
|
+
}
|
|
355
|
+
function formatDuration(ms) {
|
|
356
|
+
return ms < 60000 ? `${(Math.max(0, ms) / 1000).toFixed(1)}s` : formatSeconds(ms / 1000);
|
|
357
|
+
}
|
|
358
|
+
function formatElapsed(ms) {
|
|
359
|
+
return formatSeconds(Math.floor(Math.max(0, ms) / 1000));
|
|
360
|
+
}
|
|
361
|
+
function upTo(text, separator) {
|
|
362
|
+
const end = text.indexOf(separator);
|
|
363
|
+
return end === -1 ? text : text.slice(0, end);
|
|
364
|
+
}
|
|
365
|
+
function formatAge(date, now = Date.now()) {
|
|
366
|
+
const at = typeof date === "number" ? date : Date.parse(date);
|
|
367
|
+
if (Number.isNaN(at))
|
|
368
|
+
return "-";
|
|
369
|
+
const seconds = (now - at) / 1000;
|
|
370
|
+
return seconds < 60 ? "just now" : `${upTo(formatSeconds(seconds), " ")} ago`;
|
|
371
|
+
}
|
|
372
|
+
function truncate(text, width) {
|
|
373
|
+
return text.length <= width ? text : `${text.slice(0, Math.max(0, width - 1))}\u2026`;
|
|
374
|
+
}
|
|
375
|
+
function textWidth(text) {
|
|
376
|
+
return Bun.stringWidth(text);
|
|
377
|
+
}
|
|
378
|
+
function table(rows, { cellWidth, header = false, align = [], fit } = {}) {
|
|
379
|
+
const cells = cellWidth === undefined ? rows : rows.map((row) => row.map((cell) => truncate(cell.replaceAll(LINE_BREAKS, " "), cellWidth)));
|
|
380
|
+
const widths = [];
|
|
381
|
+
for (const row of cells) {
|
|
382
|
+
for (const [index, cell] of row.entries())
|
|
383
|
+
widths[index] = Math.max(widths[index] ?? 0, textWidth(cell));
|
|
384
|
+
}
|
|
385
|
+
const shown = fit === undefined ? cells : narrow(cells, widths, fit);
|
|
386
|
+
const colors = paint(process2.stdout);
|
|
387
|
+
const lines = shown.map((row) => row.map((cell, index) => {
|
|
388
|
+
const width = widths[index] ?? 0;
|
|
389
|
+
const gap = " ".repeat(Math.max(0, width - textWidth(cell)));
|
|
390
|
+
if (align[index] === "right")
|
|
391
|
+
return `${gap}${cell}`;
|
|
392
|
+
return index === row.length - 1 ? cell : `${cell}${gap}`;
|
|
393
|
+
}).join(" ").trimEnd());
|
|
394
|
+
return lines.map((line, index) => header && index === 0 ? colors.bold(line) : line).join(`
|
|
395
|
+
`);
|
|
396
|
+
}
|
|
397
|
+
function narrow(rows, widths, limit) {
|
|
398
|
+
const used = () => widths.reduce((sum, width) => sum + width, 0) + 2 * Math.max(0, widths.length - 1);
|
|
399
|
+
const cuttable = (index) => rows.every((row) => !(row[index] ?? "").includes(ESCAPE));
|
|
400
|
+
const floor = 8;
|
|
401
|
+
while (used() > limit) {
|
|
402
|
+
let widest = -1;
|
|
403
|
+
for (const [index, width] of widths.entries()) {
|
|
404
|
+
if (cuttable(index) && width > floor && width > (widths[widest] ?? 0))
|
|
405
|
+
widest = index;
|
|
406
|
+
}
|
|
407
|
+
if (widest === -1)
|
|
408
|
+
break;
|
|
409
|
+
widths[widest] = Math.max(floor, (widths[widest] ?? 0) - (used() - limit));
|
|
410
|
+
}
|
|
411
|
+
return rows.map((row) => row.map((cell, index) => textWidth(cell) > (widths[index] ?? 0) ? truncate(cell, widths[index] ?? 0) : cell));
|
|
412
|
+
}
|
|
413
|
+
function printJson(value) {
|
|
414
|
+
console.log(JSON.stringify(value, undefined, 2));
|
|
415
|
+
}
|
|
416
|
+
var UNITS, LINE_BREAKS, ESCAPE;
|
|
417
|
+
var init_format = __esm(() => {
|
|
418
|
+
init_style();
|
|
419
|
+
UNITS = [["d", 86400], ["h", 3600], ["m", 60], ["s", 1]];
|
|
420
|
+
LINE_BREAKS = /\s*\n\s*/g;
|
|
421
|
+
ESCAPE = String.fromCharCode(27);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
// ../kit/src/text.ts
|
|
425
|
+
function distance(a, b) {
|
|
426
|
+
let previous = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
427
|
+
for (const [i, left] of [...a].entries()) {
|
|
428
|
+
const current = [i + 1];
|
|
429
|
+
for (const [j, right] of [...b].entries())
|
|
430
|
+
current.push(Math.min((previous[j + 1] ?? 0) + 1, (current[j] ?? 0) + 1, (previous[j] ?? 0) + (left === right ? 0 : 1)));
|
|
431
|
+
previous = current;
|
|
432
|
+
}
|
|
433
|
+
return previous[b.length] ?? 0;
|
|
434
|
+
}
|
|
435
|
+
function closest(name, names) {
|
|
436
|
+
const started = names.find((known) => known.startsWith(name));
|
|
437
|
+
if (started !== undefined)
|
|
438
|
+
return started;
|
|
439
|
+
const [best] = names.map((known) => ({ known, far: distance(name, known) })).sort((a, b) => a.far - b.far);
|
|
440
|
+
return best !== undefined && best.far <= (name.length < 4 ? 1 : 2) ? best.known : undefined;
|
|
441
|
+
}
|
|
442
|
+
var ANSI;
|
|
443
|
+
var init_text = __esm(() => {
|
|
444
|
+
ANSI = new RegExp(`${String.fromCharCode(27)}\\[[\\d;?]*[a-z]`, "gi");
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
// ../kit/src/args.ts
|
|
448
|
+
import process3 from "process";
|
|
449
|
+
import { parseArgs } from "util";
|
|
450
|
+
function jsonOption(holds) {
|
|
451
|
+
return { type: "boolean", description: holds === undefined ? "print JSON" : `print JSON: ${holds}` };
|
|
452
|
+
}
|
|
453
|
+
function fail(message, code = 2, hint) {
|
|
454
|
+
throw new Exit(message, code, hint);
|
|
455
|
+
}
|
|
456
|
+
function badUsage(message) {
|
|
457
|
+
throw new UsageError(message);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
class Completing {
|
|
461
|
+
options;
|
|
462
|
+
constructor(options) {
|
|
463
|
+
this.options = options;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
function usageLine(usage, colors = paint(process3.stdout)) {
|
|
467
|
+
return `${colors.bold("Usage:")} ${usage.replace(USAGE_PREFIX, "").replaceAll(OPTIONAL, (part) => colors.dim(part))}`;
|
|
468
|
+
}
|
|
469
|
+
function helpText(usage, options, colors = paint(process3.stdout), { examples = [], replaces } = {}) {
|
|
470
|
+
return [usageLine(usage, colors), ...replacesRows(replaces, colors), "", colors.bold("Options:"), ...optionRows(options, colors), ...exampleRows(examples, colors)].join(`
|
|
471
|
+
`);
|
|
472
|
+
}
|
|
473
|
+
function replacesRows(replaces, colors = paint(process3.stdout)) {
|
|
474
|
+
return replaces === undefined ? [] : ["", `${colors.bold("Instead of:")} ${replaces}`];
|
|
475
|
+
}
|
|
476
|
+
function wantsHelpJson(env = process3.env) {
|
|
477
|
+
return env.KIT_HELP === "json";
|
|
478
|
+
}
|
|
479
|
+
function description(usage, { examples = [], replaces } = {}) {
|
|
480
|
+
const lines = usage.replace(USAGE_PREFIX, "").split(`
|
|
481
|
+
`);
|
|
482
|
+
const first = lines[0];
|
|
483
|
+
const colon = first.indexOf(": ");
|
|
484
|
+
const prose = lines[lines.indexOf("") + 1] ?? "";
|
|
485
|
+
const fallback = lines.includes("") ? `${prose.charAt(0).toLowerCase()}${prose.slice(1)}`.replace(FULL_STOP, "") : "";
|
|
486
|
+
return {
|
|
487
|
+
synopsis: colon === -1 ? first : first.slice(0, colon),
|
|
488
|
+
summary: colon === -1 ? fallback : first.slice(colon + 2),
|
|
489
|
+
...replaces === undefined ? {} : { replaces },
|
|
490
|
+
examples: examples.map((example) => typeof example === "string" ? { line: example } : { line: example[0], note: example[1] })
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
function exampleRows(examples, colors = paint(process3.stdout)) {
|
|
494
|
+
if (examples.length === 0)
|
|
495
|
+
return [];
|
|
496
|
+
return ["", colors.bold("Examples:"), ...examples.map((example) => typeof example === "string" ? ` ${example}` : ` ${example[0]} ${colors.dim(`# ${example[1]}`)}`)];
|
|
497
|
+
}
|
|
498
|
+
function optionRows(options, colors = paint(process3.stdout)) {
|
|
499
|
+
const rows = Object.entries(options).map(([name, option]) => {
|
|
500
|
+
const short = option.short === undefined ? " " : `${colors.cyan(`-${option.short}`)}, `;
|
|
501
|
+
const value = option.type === "string" ? ` ${colors.dim("<value>")}` : "";
|
|
502
|
+
return { flag: `${short}${colors.cyan(`--${name}`)}${value}`, width: `-x, --${name}`.length + (option.type === "string" ? " <value>".length : 0), description: option.description ?? "" };
|
|
503
|
+
});
|
|
504
|
+
const width = Math.max(0, ...rows.map((row) => row.width));
|
|
505
|
+
return rows.map((row) => row.description === "" ? ` ${row.flag}` : ` ${row.flag}${" ".repeat(width - row.width)} ${colors.dim(row.description)}`);
|
|
506
|
+
}
|
|
507
|
+
function applyOutput(color, plain, env = process3.env) {
|
|
508
|
+
const when = plain === true ? "never" : color ?? "auto";
|
|
509
|
+
if (when === "auto")
|
|
510
|
+
return;
|
|
511
|
+
if (when !== "always" && when !== "never")
|
|
512
|
+
badUsage(`--color takes auto, always or never, not ${when}`);
|
|
513
|
+
if (when === "always") {
|
|
514
|
+
env.FORCE_COLOR = "1";
|
|
515
|
+
delete env.NO_COLOR;
|
|
516
|
+
} else {
|
|
517
|
+
env.NO_COLOR = "1";
|
|
518
|
+
delete env.FORCE_COLOR;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
function parse(args, usage, options, settings = {}) {
|
|
522
|
+
const output = Object.fromEntries(Object.entries(OUTPUT_OPTIONS).filter(([name]) => !(name in options)));
|
|
523
|
+
const all = { ...options, ...output, help: { type: "boolean", short: "h", description: "show this help" } };
|
|
524
|
+
if (completion.active)
|
|
525
|
+
throw new Completing(all);
|
|
526
|
+
const separator = settings.rest === true ? args.indexOf("--") : -1;
|
|
527
|
+
const own = separator === -1 ? args : args.slice(0, separator);
|
|
528
|
+
const rest = separator === -1 ? undefined : args.slice(separator + 1);
|
|
529
|
+
let parsed;
|
|
530
|
+
try {
|
|
531
|
+
parsed = parseArgs({ args: joinDashValues(own, all), options: all, allowPositionals: true, allowNegative: settings.allowNegative === true, strict: true });
|
|
532
|
+
} catch (error) {
|
|
533
|
+
const message = parseError(error);
|
|
534
|
+
throw new UsageError(message, nearestOption(message, all, settings.allowNegative === true));
|
|
535
|
+
}
|
|
536
|
+
const values = parsed.values;
|
|
537
|
+
applyOutput("color" in output ? values.color : undefined, "plain" in output ? values.plain : undefined);
|
|
538
|
+
if (values.help === true) {
|
|
539
|
+
console.log(wantsHelpJson() ? JSON.stringify(description(usage, settings)) : helpText(usage, all, undefined, settings));
|
|
540
|
+
throw new HelpShown;
|
|
541
|
+
}
|
|
542
|
+
if (settings.positionals !== undefined)
|
|
543
|
+
checkPositionals(parsed.positionals, settings.positionals);
|
|
544
|
+
return { ...parsed, positionals: parsed.positionals, rest };
|
|
545
|
+
}
|
|
546
|
+
function checkPositionals(given, names) {
|
|
547
|
+
const variadic = names.at(-1)?.replace("]", "").endsWith("...") === true;
|
|
548
|
+
const required = names.filter((name) => !name.startsWith("[")).length;
|
|
549
|
+
if (given.length < required)
|
|
550
|
+
badUsage(`missing ${names[given.length]}`);
|
|
551
|
+
if (!variadic && given.length > names.length)
|
|
552
|
+
badUsage(`unexpected argument ${given[names.length]}`);
|
|
553
|
+
}
|
|
554
|
+
function joinDashValues(args, options) {
|
|
555
|
+
const longOf = new Map(Object.entries(options).flatMap(([name, option]) => option.short === undefined ? [[`--${name}`, name]] : [[`--${name}`, name], [`-${option.short}`, name]]));
|
|
556
|
+
const isOption = (arg) => arg === "--" || longOf.has(arg.includes("=") ? arg.slice(0, arg.indexOf("=")) : arg);
|
|
557
|
+
const joined = [];
|
|
558
|
+
for (let i = 0;i < args.length; i++) {
|
|
559
|
+
const arg = args[i] ?? "";
|
|
560
|
+
if (arg === "--")
|
|
561
|
+
return [...joined, ...args.slice(i)];
|
|
562
|
+
const name = longOf.get(arg);
|
|
563
|
+
const next = args[i + 1];
|
|
564
|
+
if (name !== undefined && options[name]?.type === "string" && next !== undefined && next.startsWith("-") && next !== "-" && !isOption(next)) {
|
|
565
|
+
joined.push(`--${name}=${next}`);
|
|
566
|
+
i++;
|
|
567
|
+
} else {
|
|
568
|
+
joined.push(arg);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return joined;
|
|
572
|
+
}
|
|
573
|
+
function parseError(error) {
|
|
574
|
+
const message = upTo(error instanceof Error ? error.message : String(error), ". ");
|
|
575
|
+
return `${message.charAt(0).toLowerCase()}${message.slice(1)}`;
|
|
576
|
+
}
|
|
577
|
+
function nearestOption(message, options, allowNegative) {
|
|
578
|
+
const typed = UNKNOWN_OPTION.exec(message)?.[1];
|
|
579
|
+
if (typed === undefined)
|
|
580
|
+
return;
|
|
581
|
+
const word = typed.replace(DASHES, "");
|
|
582
|
+
if (word.length < 2 && !typed.startsWith("--"))
|
|
583
|
+
return;
|
|
584
|
+
const known = Object.entries(options).flatMap(([name, option]) => [
|
|
585
|
+
...option.short === undefined ? [] : [`-${option.short}`],
|
|
586
|
+
`--${name}`,
|
|
587
|
+
...allowNegative && option.type === "boolean" ? [`--no-${name}`] : []
|
|
588
|
+
]);
|
|
589
|
+
const meant = closest(word, known.map((flag) => flag.replace(DASHES, "")));
|
|
590
|
+
return meant === undefined ? undefined : `did you mean ${known.find((flag) => flag.replace(DASHES, "") === meant)}?`;
|
|
591
|
+
}
|
|
592
|
+
function wholeNumber(value, name, fallback, min = 1) {
|
|
593
|
+
if (value === undefined)
|
|
594
|
+
return fallback;
|
|
595
|
+
const number = Number(value);
|
|
596
|
+
if (!WHOLE.test(value) || !Number.isSafeInteger(number) || number < min)
|
|
597
|
+
badUsage(`${name.startsWith("<") ? name : `--${name}`} takes a whole number from ${min}, not ${value}`);
|
|
598
|
+
return number;
|
|
599
|
+
}
|
|
600
|
+
function duration(value, name, fallback, unit = "s") {
|
|
601
|
+
if (value === undefined)
|
|
602
|
+
return fallback;
|
|
603
|
+
const match = DURATION.exec(value.trim());
|
|
604
|
+
const ms = match === null ? 0 : Number(match[1]) * UNIT_MS[match[2] ?? unit];
|
|
605
|
+
if (ms < 1)
|
|
606
|
+
badUsage(`--${name} takes a duration such as 30s, 5m, 1h or 7d, not ${value}`);
|
|
607
|
+
return ms;
|
|
608
|
+
}
|
|
609
|
+
var Exit, UsageError, HelpShown, completion, OPTIONAL, USAGE_PREFIX, FULL_STOP, DASHES, OUTPUT_OPTIONS, UNKNOWN_OPTION, WHOLE, DURATION, UNIT_MS;
|
|
610
|
+
var init_args = __esm(() => {
|
|
611
|
+
init_format();
|
|
612
|
+
init_style();
|
|
613
|
+
init_text();
|
|
614
|
+
Exit = class Exit extends Error {
|
|
615
|
+
code;
|
|
616
|
+
hint;
|
|
617
|
+
constructor(message, code, hint) {
|
|
618
|
+
super(message);
|
|
619
|
+
this.code = code;
|
|
620
|
+
this.hint = hint;
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
UsageError = class UsageError extends Exit {
|
|
624
|
+
constructor(message, hint) {
|
|
625
|
+
super(message, 2, hint);
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
HelpShown = class HelpShown extends Exit {
|
|
629
|
+
constructor() {
|
|
630
|
+
super("help shown", 0);
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
completion = { active: false };
|
|
634
|
+
OPTIONAL = /\[[^\]]+\]/g;
|
|
635
|
+
USAGE_PREFIX = /^usage:\s*/i;
|
|
636
|
+
FULL_STOP = /\.$/;
|
|
637
|
+
DASHES = /^-+/;
|
|
638
|
+
OUTPUT_OPTIONS = {
|
|
639
|
+
color: { type: "string", description: "auto (on a terminal alone), always or never" },
|
|
640
|
+
plain: { type: "boolean", description: "plain text, no colour or spinner: --color never" }
|
|
641
|
+
};
|
|
642
|
+
UNKNOWN_OPTION = /^unknown option '(-[^']+)'/;
|
|
643
|
+
WHOLE = /^\d+$/;
|
|
644
|
+
DURATION = /^(\d+(?:\.\d+)?)(ms|[smhd])?$/;
|
|
645
|
+
UNIT_MS = { ms: 1, s: 1000, m: 60000, h: 3600000, d: 86400000 };
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
// ../kit/src/chart.ts
|
|
649
|
+
var init_chart = __esm(() => {
|
|
650
|
+
init_format();
|
|
651
|
+
init_style();
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
// ../kit/src/process.ts
|
|
655
|
+
import { constants } from "os";
|
|
656
|
+
import process4 from "process";
|
|
657
|
+
function exitCodeOf(code, signal) {
|
|
658
|
+
if (code !== null)
|
|
659
|
+
return code;
|
|
660
|
+
if (typeof signal === "number")
|
|
661
|
+
return 128 + signal;
|
|
662
|
+
return signal === null ? 129 : 128 + constants.signals[signal];
|
|
663
|
+
}
|
|
664
|
+
function holdSignals(cleanup) {
|
|
665
|
+
let received;
|
|
666
|
+
let child;
|
|
667
|
+
const held = {
|
|
668
|
+
get signal() {
|
|
669
|
+
return received;
|
|
670
|
+
},
|
|
671
|
+
forward: (to) => {
|
|
672
|
+
child = to;
|
|
673
|
+
},
|
|
674
|
+
release: () => {
|
|
675
|
+
for (const signal of SIGNALS)
|
|
676
|
+
process4.off(signal, onSignal);
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
function onSignal(signal) {
|
|
680
|
+
received = signal;
|
|
681
|
+
if (child !== undefined) {
|
|
682
|
+
child.kill(signal);
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
if (cleanup === undefined)
|
|
686
|
+
return;
|
|
687
|
+
held.release();
|
|
688
|
+
cleanup(signal);
|
|
689
|
+
process4.kill(process4.pid, signal);
|
|
690
|
+
}
|
|
691
|
+
for (const signal of SIGNALS)
|
|
692
|
+
process4.on(signal, onSignal);
|
|
693
|
+
return held;
|
|
694
|
+
}
|
|
695
|
+
async function runCommand(argv, { cwd, env, stdin = "ignore", timeoutMs, signal, maxBytes = Infinity, onChunk, onStart } = {}) {
|
|
696
|
+
const chunks = [];
|
|
697
|
+
const grouped = timeoutMs !== undefined || signal !== undefined || onStart !== undefined || onChunk !== undefined;
|
|
698
|
+
const proc = Bun.spawn(argv, { ...cwd === undefined ? {} : { cwd }, ...env === undefined ? {} : { env }, stdin, stdout: "pipe", stderr: "pipe", ...grouped ? { detached: true } : {} });
|
|
699
|
+
const state = { kept: 0, truncated: false, timedOut: false, failure: undefined, done: false };
|
|
700
|
+
const timers = [];
|
|
701
|
+
const killGroup = (killing) => {
|
|
702
|
+
if (state.done)
|
|
703
|
+
return;
|
|
704
|
+
try {
|
|
705
|
+
if (grouped)
|
|
706
|
+
process4.kill(-proc.pid, killing);
|
|
707
|
+
else
|
|
708
|
+
proc.kill(killing);
|
|
709
|
+
} catch {}
|
|
710
|
+
};
|
|
711
|
+
const stop = () => {
|
|
712
|
+
killGroup("SIGTERM");
|
|
713
|
+
timers.push(setTimeout(killGroup, KILL_GRACE_MS, "SIGKILL"));
|
|
714
|
+
};
|
|
715
|
+
const onAbort = () => stop();
|
|
716
|
+
if (timeoutMs !== undefined) {
|
|
717
|
+
timers.push(setTimeout(() => {
|
|
718
|
+
state.timedOut = true;
|
|
719
|
+
stop();
|
|
720
|
+
}, timeoutMs));
|
|
721
|
+
}
|
|
722
|
+
if (signal?.aborted === true)
|
|
723
|
+
onAbort();
|
|
724
|
+
else
|
|
725
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
726
|
+
onStart?.({ kill: (killing) => killGroup(killing) });
|
|
727
|
+
const drain = async (stream, name) => {
|
|
728
|
+
for await (const data of stream) {
|
|
729
|
+
if (state.failure !== undefined)
|
|
730
|
+
continue;
|
|
731
|
+
try {
|
|
732
|
+
onChunk?.({ stream: name, data });
|
|
733
|
+
} catch (error) {
|
|
734
|
+
state.failure = error;
|
|
735
|
+
stop();
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
if (state.kept + data.length > maxBytes) {
|
|
739
|
+
state.truncated = true;
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
state.kept += data.length;
|
|
743
|
+
chunks.push({ stream: name, data });
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
try {
|
|
747
|
+
await Promise.all([drain(proc.stdout, "stdout"), drain(proc.stderr, "stderr")]);
|
|
748
|
+
await proc.exited;
|
|
749
|
+
} finally {
|
|
750
|
+
state.done = true;
|
|
751
|
+
for (const timer of timers)
|
|
752
|
+
clearTimeout(timer);
|
|
753
|
+
signal?.removeEventListener("abort", onAbort);
|
|
754
|
+
}
|
|
755
|
+
if (state.failure !== undefined)
|
|
756
|
+
throw state.failure;
|
|
757
|
+
const joined = () => Buffer.concat(chunks.map(({ data }) => data));
|
|
758
|
+
let output;
|
|
759
|
+
let text;
|
|
760
|
+
return {
|
|
761
|
+
code: exitCodeOf(proc.exitCode, proc.signalCode),
|
|
762
|
+
chunks,
|
|
763
|
+
timedOut: state.timedOut,
|
|
764
|
+
truncated: state.truncated,
|
|
765
|
+
get output() {
|
|
766
|
+
return output ??= joined();
|
|
767
|
+
},
|
|
768
|
+
get text() {
|
|
769
|
+
return text ??= (output ??= joined()).toString();
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
var KILL_GRACE_MS = 2000, SIGNALS;
|
|
774
|
+
var init_process = __esm(() => {
|
|
775
|
+
SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
// ../kit/src/progress.ts
|
|
779
|
+
import process5 from "process";
|
|
780
|
+
function liveRegion(render, stream = process5.stderr, env = process5.env) {
|
|
781
|
+
if (!takesControlCodes(stream, env))
|
|
782
|
+
return { redraw: () => {
|
|
783
|
+
return;
|
|
784
|
+
}, print: (text) => void stream.write(`${text}
|
|
785
|
+
`), stop: () => {
|
|
786
|
+
return;
|
|
787
|
+
} };
|
|
788
|
+
const write = stream.write.bind(stream);
|
|
789
|
+
let frame = 0;
|
|
790
|
+
let drawn = 0;
|
|
791
|
+
const clear = () => {
|
|
792
|
+
if (drawn > 0)
|
|
793
|
+
write(`${CLEAR_LINE}${LINE_UP.repeat(drawn - 1)}`);
|
|
794
|
+
drawn = 0;
|
|
795
|
+
};
|
|
796
|
+
const draw = () => {
|
|
797
|
+
const width = (stream.columns === undefined || stream.columns === 0 ? 80 : stream.columns) - 1;
|
|
798
|
+
const height = stream.rows === undefined || stream.rows === 0 ? 24 : stream.rows;
|
|
799
|
+
const lines = render(FRAMES[frame++ % FRAMES.length]).slice(0, Math.max(1, height - 1)).map((line) => cutToWidth(line, width));
|
|
800
|
+
if (lines.length === 0) {
|
|
801
|
+
clear();
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
write(`${drawn > 0 ? `${CLEAR_LINE}${LINE_UP.repeat(drawn - 1)}` : CLEAR_LINE}${lines.join(`
|
|
805
|
+
`)}`);
|
|
806
|
+
drawn = lines.length;
|
|
807
|
+
};
|
|
808
|
+
const timer = setInterval(draw, FRAME_MS);
|
|
809
|
+
const restore = interceptOutput(clear);
|
|
810
|
+
const release = swallowInput();
|
|
811
|
+
const onExit = () => {
|
|
812
|
+
clear();
|
|
813
|
+
release();
|
|
814
|
+
};
|
|
815
|
+
const signals = holdSignals(stop);
|
|
816
|
+
function stop() {
|
|
817
|
+
clearInterval(timer);
|
|
818
|
+
clear();
|
|
819
|
+
restore();
|
|
820
|
+
release();
|
|
821
|
+
process5.off("exit", onExit);
|
|
822
|
+
signals.release();
|
|
823
|
+
}
|
|
824
|
+
timer.unref();
|
|
825
|
+
process5.on("exit", onExit);
|
|
826
|
+
return {
|
|
827
|
+
redraw: draw,
|
|
828
|
+
print: (text) => {
|
|
829
|
+
clear();
|
|
830
|
+
write(`${text}
|
|
831
|
+
`);
|
|
832
|
+
draw();
|
|
833
|
+
},
|
|
834
|
+
stop
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
function cutToWidth(line, width) {
|
|
838
|
+
if (Bun.stringWidth(line) <= width)
|
|
839
|
+
return line;
|
|
840
|
+
let room = width;
|
|
841
|
+
let kept = "";
|
|
842
|
+
let index = 0;
|
|
843
|
+
let linked = false;
|
|
844
|
+
while (index < line.length) {
|
|
845
|
+
ESCAPE_CODE.lastIndex = index;
|
|
846
|
+
const escape = ESCAPE_CODE.exec(line);
|
|
847
|
+
if (escape !== null) {
|
|
848
|
+
kept += escape[0];
|
|
849
|
+
linked ||= escape[0].startsWith(`${ESC}]`);
|
|
850
|
+
index = ESCAPE_CODE.lastIndex;
|
|
851
|
+
continue;
|
|
852
|
+
}
|
|
853
|
+
const char = String.fromCodePoint(line.codePointAt(index));
|
|
854
|
+
const columns = Bun.stringWidth(char);
|
|
855
|
+
if (columns > room)
|
|
856
|
+
break;
|
|
857
|
+
kept += char;
|
|
858
|
+
room -= columns;
|
|
859
|
+
index += char.length;
|
|
860
|
+
}
|
|
861
|
+
return `${kept}${RESET_STYLE}${linked ? CLOSE_LINK : ""}`;
|
|
862
|
+
}
|
|
863
|
+
function swallowInput() {
|
|
864
|
+
const input = process5.stdin;
|
|
865
|
+
if (!input.isTTY)
|
|
866
|
+
return () => {
|
|
867
|
+
return;
|
|
868
|
+
};
|
|
869
|
+
const onData = (data) => {
|
|
870
|
+
if (data.includes(CTRL_C))
|
|
871
|
+
process5.kill(process5.pid, "SIGINT");
|
|
872
|
+
};
|
|
873
|
+
input.setRawMode(true);
|
|
874
|
+
input.on("data", onData);
|
|
875
|
+
input.resume();
|
|
876
|
+
let released = false;
|
|
877
|
+
return () => {
|
|
878
|
+
if (released)
|
|
879
|
+
return;
|
|
880
|
+
released = true;
|
|
881
|
+
input.off("data", onData);
|
|
882
|
+
input.pause();
|
|
883
|
+
input.setRawMode(false);
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
function interceptOutput(clear) {
|
|
887
|
+
const targets = [...CONSOLE_METHODS.map((name) => [console, name]), [process5.stdout, "write"], [process5.stderr, "write"]];
|
|
888
|
+
const wrapped = targets.map(([target, name]) => {
|
|
889
|
+
const original = Reflect.get(target, name);
|
|
890
|
+
const wrapper = (...args) => {
|
|
891
|
+
clear();
|
|
892
|
+
return original.apply(target, args);
|
|
893
|
+
};
|
|
894
|
+
Reflect.set(target, name, wrapper);
|
|
895
|
+
return { target, name, original, wrapper };
|
|
896
|
+
});
|
|
897
|
+
return () => {
|
|
898
|
+
for (const { target, name, original, wrapper } of wrapped) {
|
|
899
|
+
if (Reflect.get(target, name) === wrapper)
|
|
900
|
+
Reflect.set(target, name, original);
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
var FRAMES, FRAME_MS = 200, CLEAR_LINE = "\r\x1B[2K", LINE_UP = "\x1B[1A\x1B[2K", ESC, ESCAPE_CODE, RESET_STYLE, CTRL_C = 3, CLOSE_LINK, CONSOLE_METHODS;
|
|
905
|
+
var init_progress = __esm(() => {
|
|
906
|
+
init_format();
|
|
907
|
+
init_process();
|
|
908
|
+
init_style();
|
|
909
|
+
FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
910
|
+
ESC = String.fromCharCode(27);
|
|
911
|
+
ESCAPE_CODE = new RegExp(`${ESC}(?:\\[[\\x30-\\x3F]*[\\x20-\\x2F]*[\\x40-\\x7E]|\\][^\\u0007${ESC}]*(?:\\u0007|${ESC}\\\\))`, "y");
|
|
912
|
+
RESET_STYLE = `${ESC}[0m`;
|
|
913
|
+
CLOSE_LINK = `${ESC}]8;;${ESC}\\`;
|
|
914
|
+
CONSOLE_METHODS = ["log", "info", "warn", "error", "debug", "dir", "dirxml", "table", "trace", "group", "groupCollapsed", "count", "timeEnd", "timeLog", "assert"];
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
// ../kit/src/tool.ts
|
|
918
|
+
var init_tool = __esm(() => {
|
|
919
|
+
init_format();
|
|
920
|
+
init_process();
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
// ../kit/src/ci.ts
|
|
924
|
+
var init_ci = __esm(() => {
|
|
925
|
+
init_args();
|
|
926
|
+
init_format();
|
|
927
|
+
init_progress();
|
|
928
|
+
init_tool();
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
// ../kit/src/cli.ts
|
|
932
|
+
import process6 from "process";
|
|
933
|
+
async function commandRows(commands, colors) {
|
|
934
|
+
const width = Math.max(...Object.keys(commands).map((name) => name.length));
|
|
935
|
+
const groups = new Map([["Commands:", []]]);
|
|
936
|
+
const summaries = await Promise.all(Object.values(commands).map(async ({ summary }) => resolveSummary(summary)));
|
|
937
|
+
for (const [index, [name, { group }]] of Object.entries(commands).entries()) {
|
|
938
|
+
const heading = group === undefined ? "Commands:" : `${group}:`;
|
|
939
|
+
const rows = groups.get(heading) ?? [];
|
|
940
|
+
rows.push(` ${colors.cyan(name.padEnd(width))} ${colors.dim(summaries[index])}`);
|
|
941
|
+
groups.set(heading, rows);
|
|
942
|
+
}
|
|
943
|
+
return [...groups].filter(([, rows]) => rows.length > 0).flatMap(([heading, rows], index) => [...index === 0 ? [] : [""], colors.bold(heading), ...rows]);
|
|
944
|
+
}
|
|
945
|
+
function takeOutputFlags(argv) {
|
|
946
|
+
let index = 0;
|
|
947
|
+
for (;index < argv.length; index++) {
|
|
948
|
+
const word = argv[index];
|
|
949
|
+
if (word === "--plain")
|
|
950
|
+
applyOutput(undefined, true);
|
|
951
|
+
else if (word.startsWith("--color="))
|
|
952
|
+
applyOutput(word.slice("--color=".length), undefined);
|
|
953
|
+
else if (word === "--color" && argv[index + 1] !== undefined)
|
|
954
|
+
applyOutput(argv[++index], undefined);
|
|
955
|
+
else
|
|
956
|
+
break;
|
|
957
|
+
}
|
|
958
|
+
return argv.slice(index);
|
|
959
|
+
}
|
|
960
|
+
async function resolveSummary(summary) {
|
|
961
|
+
return typeof summary === "string" ? summary : summary();
|
|
962
|
+
}
|
|
963
|
+
function scopeOf(commands, extra, aliases) {
|
|
964
|
+
return { commands: typeof commands === "function" ? {} : commands, lazy: [...typeof commands === "function" ? [commands] : [], ...extra === undefined ? [] : [extra]], aliases };
|
|
965
|
+
}
|
|
966
|
+
async function expand(scope, words) {
|
|
967
|
+
if (scope.lazy.length === 0)
|
|
968
|
+
return scope;
|
|
969
|
+
const commands = { ...scope.commands };
|
|
970
|
+
for (const added of await Promise.all(scope.lazy.map(async (lazy) => lazy(words)))) {
|
|
971
|
+
for (const [name, command] of Object.entries(added))
|
|
972
|
+
commands[name] ??= command;
|
|
973
|
+
}
|
|
974
|
+
return { ...scope, commands, lazy: [] };
|
|
975
|
+
}
|
|
976
|
+
async function help({ path, header, summary: lazySummary, commands, defaultCommand, examples, replaces }, stream) {
|
|
977
|
+
const colors = paint(stream);
|
|
978
|
+
const prefix = path.join(" ");
|
|
979
|
+
const summary = await resolveSummary(lazySummary);
|
|
980
|
+
if (wantsHelpJson())
|
|
981
|
+
return JSON.stringify(description(`${prefix} <command> [options]: ${summary}`, { examples, replaces }));
|
|
982
|
+
const fallback = defaultCommand === undefined ? undefined : commands[defaultCommand];
|
|
983
|
+
const options = fallback !== undefined && "run" in fallback ? await optionsOf(fallback.run) : undefined;
|
|
984
|
+
const own = Object.entries(options ?? {}).filter(([name]) => !(name in TOP_OPTIONS));
|
|
985
|
+
return [
|
|
986
|
+
header(colors, summary),
|
|
987
|
+
"",
|
|
988
|
+
usageLine(`${prefix} ${defaultCommand === undefined ? colors.cyan("<command>") : `[${colors.cyan("<command>")}]`} [options]`, colors),
|
|
989
|
+
...replacesRows(replaces, colors),
|
|
990
|
+
"",
|
|
991
|
+
...await commandRows(commands, colors),
|
|
992
|
+
...own.length === 0 ? [] : ["", `${colors.bold(`Options of ${defaultCommand}:`)} ${colors.dim("the command run when none is named")}`, ...optionRows(Object.fromEntries(own), colors)],
|
|
993
|
+
"",
|
|
994
|
+
colors.bold("Options:"),
|
|
995
|
+
...optionRows(path.length === 1 ? TOP_OPTIONS : LEVEL_OPTIONS, colors),
|
|
996
|
+
...exampleRows(examples ?? [], colors),
|
|
997
|
+
"",
|
|
998
|
+
`${colors.dim("Run")} ${prefix} ${colors.cyan("<command>")} --help ${colors.dim("for its options.")}`
|
|
999
|
+
].join(`
|
|
1000
|
+
`);
|
|
1001
|
+
}
|
|
1002
|
+
function printError(prefix, message, hint, cause) {
|
|
1003
|
+
const colors = paint(process6.stderr);
|
|
1004
|
+
const styled = takesControlCodes(process6.stderr);
|
|
1005
|
+
const head = styled ? `${colors.red.bold("error")} ${colors.dim(`${prefix}:`)}` : `error: ${prefix}:`;
|
|
1006
|
+
const under = (label, text, tint) => text === undefined ? "" : `
|
|
1007
|
+
${styled ? tint(label) : `${label}:`} ${text}`;
|
|
1008
|
+
console.error(`${head} ${message}${under("cause", cause, colors.dim)}${under("hint", hint, colors.yellow)}`);
|
|
1009
|
+
}
|
|
1010
|
+
function printJsonError(message, hint, cause) {
|
|
1011
|
+
console.error(JSON.stringify({ error: message, ...hint === undefined ? {} : { hint }, ...cause === undefined ? {} : { cause } }));
|
|
1012
|
+
}
|
|
1013
|
+
function wantsJson(argv) {
|
|
1014
|
+
const end = argv.indexOf("--");
|
|
1015
|
+
return (end === -1 ? argv : argv.slice(0, end)).includes("--json");
|
|
1016
|
+
}
|
|
1017
|
+
function reportThrown(prefix, error, redact = (text) => text, json = false) {
|
|
1018
|
+
if (error instanceof HelpShown)
|
|
1019
|
+
return 0;
|
|
1020
|
+
const help = error instanceof UsageError ? `run ${prefix} --help for its options` : undefined;
|
|
1021
|
+
const named = error instanceof Error && !(error instanceof Exit) && error.name !== "Error" ? `${error.name}: ${error.message}` : undefined;
|
|
1022
|
+
const cause = error instanceof Error && error.cause instanceof Error ? redact(error.cause.message) : undefined;
|
|
1023
|
+
const report = json ? printJsonError : (message, hint, causeText) => printError(prefix, message, hint, causeText);
|
|
1024
|
+
report(redact(named ?? (error instanceof Error ? error.message : String(error))), error instanceof Exit ? error.hint ?? help : undefined, cause);
|
|
1025
|
+
return error instanceof Exit ? error.code : 1;
|
|
1026
|
+
}
|
|
1027
|
+
async function dispatch(level, typed, { version, redact }) {
|
|
1028
|
+
const prefix = level.path.join(" ");
|
|
1029
|
+
let argv;
|
|
1030
|
+
try {
|
|
1031
|
+
argv = takeOutputFlags(typed);
|
|
1032
|
+
} catch (error) {
|
|
1033
|
+
return reportThrown(prefix, error);
|
|
1034
|
+
}
|
|
1035
|
+
const [name, ...args] = argv;
|
|
1036
|
+
if (name === undefined && level.path.length > 1) {
|
|
1037
|
+
console.error(await help(await expand(level, [...level.path.slice(1), ...argv]), process6.stderr));
|
|
1038
|
+
return 2;
|
|
1039
|
+
}
|
|
1040
|
+
if (name === undefined || name === "help" || name === "--help" || name === "-h") {
|
|
1041
|
+
console.log(await help(await expand(level, [...level.path.slice(1), ...argv]), process6.stdout));
|
|
1042
|
+
return 0;
|
|
1043
|
+
}
|
|
1044
|
+
if (level.path.length === 1 && (name === "--version" || name === "-v")) {
|
|
1045
|
+
console.log(version);
|
|
1046
|
+
return 0;
|
|
1047
|
+
}
|
|
1048
|
+
let command = level.commands[level.aliases?.[name] ?? name];
|
|
1049
|
+
let rest = args;
|
|
1050
|
+
if (command === undefined && level.lazy.length > 0) {
|
|
1051
|
+
level = await expand(level, [...level.path.slice(1), ...argv]);
|
|
1052
|
+
command = level.commands[level.aliases?.[name] ?? name];
|
|
1053
|
+
}
|
|
1054
|
+
if (command === undefined && level.defaultCommand !== undefined) {
|
|
1055
|
+
command = level.commands[level.defaultCommand];
|
|
1056
|
+
rest = argv;
|
|
1057
|
+
}
|
|
1058
|
+
if (command === undefined) {
|
|
1059
|
+
const meant = closest(name, Object.keys(level.commands));
|
|
1060
|
+
printError(prefix, `no command ${name}`, meant === undefined ? `run ${prefix} --help for its commands` : `did you mean ${meant}?`);
|
|
1061
|
+
return 2;
|
|
1062
|
+
}
|
|
1063
|
+
if ("commands" in command) {
|
|
1064
|
+
const { summary } = command;
|
|
1065
|
+
return dispatch({ path: [...level.path, name], header: (colors, text) => `${colors.bold(`${prefix} ${name}`)} ${text}`, summary, ...scopeOf(command.commands, command.extraCommands, command.aliases), defaultCommand: undefined, examples: command.examples, replaces: undefined }, rest, { version, redact });
|
|
1066
|
+
}
|
|
1067
|
+
try {
|
|
1068
|
+
return await command.run(rest);
|
|
1069
|
+
} catch (error) {
|
|
1070
|
+
return reportThrown(`${prefix} ${name}`, error, redact, wantsJson(rest));
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
async function optionsOf(run) {
|
|
1074
|
+
completion.active = true;
|
|
1075
|
+
try {
|
|
1076
|
+
await run([]);
|
|
1077
|
+
} catch (error) {
|
|
1078
|
+
if (error instanceof Completing)
|
|
1079
|
+
return error.options;
|
|
1080
|
+
} finally {
|
|
1081
|
+
completion.active = false;
|
|
1082
|
+
}
|
|
1083
|
+
return {};
|
|
1084
|
+
}
|
|
1085
|
+
async function leafCandidates(run, words) {
|
|
1086
|
+
if (!(words.at(-1) ?? "").startsWith("-"))
|
|
1087
|
+
return [FILES];
|
|
1088
|
+
return Object.entries(await optionsOf(run)).map(([name, option]) => option.description === undefined ? `--${name}` : `--${name} ${option.description}`);
|
|
1089
|
+
}
|
|
1090
|
+
async function candidates(scope, defaultCommand, words, before = []) {
|
|
1091
|
+
const [word = "", ...rest] = words;
|
|
1092
|
+
const listing = rest.length === 0 && !word.startsWith("-");
|
|
1093
|
+
let { commands, aliases } = scope;
|
|
1094
|
+
let command = commands[aliases?.[word] ?? word];
|
|
1095
|
+
if (listing || command === undefined) {
|
|
1096
|
+
({ commands, aliases } = await expand(scope, [...before, ...words]));
|
|
1097
|
+
command = commands[aliases?.[word] ?? word];
|
|
1098
|
+
}
|
|
1099
|
+
if (listing)
|
|
1100
|
+
return Promise.all(Object.entries(commands).map(async ([name, { summary }]) => `${name} ${await resolveSummary(summary)}`));
|
|
1101
|
+
if (command === undefined) {
|
|
1102
|
+
const fallback = defaultCommand === undefined ? undefined : commands[defaultCommand];
|
|
1103
|
+
return fallback !== undefined && "run" in fallback ? leafCandidates(fallback.run, words) : [];
|
|
1104
|
+
}
|
|
1105
|
+
return "commands" in command ? candidates(scopeOf(command.commands, command.extraCommands, command.aliases), undefined, rest, [...before, word]) : leafCandidates(command.run, rest);
|
|
1106
|
+
}
|
|
1107
|
+
async function printCandidates(found) {
|
|
1108
|
+
for (const line of await found)
|
|
1109
|
+
console.log(line);
|
|
1110
|
+
return 0;
|
|
1111
|
+
}
|
|
1112
|
+
async function runCli(cli, argv = process6.argv.slice(2)) {
|
|
1113
|
+
if (argv[0] === COMPLETE)
|
|
1114
|
+
return printCandidates(candidates(scopeOf(cli.commands, cli.extraCommands, cli.aliases), cli.defaultCommand, argv.slice(1)));
|
|
1115
|
+
return dispatch({ path: [cli.name], header: (colors, about) => `${colors.bold(cli.name)} ${colors.dim(cli.version)} ${about}`, summary: cli.about, ...scopeOf(cli.commands, cli.extraCommands, cli.aliases), defaultCommand: cli.defaultCommand, examples: cli.examples, replaces: cli.replaces }, argv, { version: cli.version, redact: cli.redact });
|
|
1116
|
+
}
|
|
1117
|
+
var LEVEL_OPTIONS, TOP_OPTIONS, COMPLETE = "__complete", FILES = "__files__";
|
|
1118
|
+
var init_cli = __esm(() => {
|
|
1119
|
+
init_args();
|
|
1120
|
+
init_style();
|
|
1121
|
+
init_text();
|
|
1122
|
+
LEVEL_OPTIONS = {
|
|
1123
|
+
...OUTPUT_OPTIONS,
|
|
1124
|
+
help: { type: "boolean", short: "h", description: "show this help" }
|
|
1125
|
+
};
|
|
1126
|
+
TOP_OPTIONS = { ...LEVEL_OPTIONS, version: { type: "boolean", short: "v", description: "print the version" } };
|
|
1127
|
+
});
|
|
1128
|
+
|
|
1129
|
+
// ../kit/src/config.ts
|
|
1130
|
+
var init_config = __esm(() => {
|
|
1131
|
+
init_args();
|
|
1132
|
+
});
|
|
1133
|
+
|
|
1134
|
+
// ../kit/src/git.ts
|
|
1135
|
+
var init_git = __esm(() => {
|
|
1136
|
+
init_args();
|
|
1137
|
+
init_tool();
|
|
1138
|
+
});
|
|
1139
|
+
|
|
1140
|
+
// ../kit/src/limit.ts
|
|
1141
|
+
function limitOptions(fallback) {
|
|
1142
|
+
return {
|
|
1143
|
+
limit: { type: "string", description: `show at most this many rows, the rest counted (${fallback})` },
|
|
1144
|
+
full: { type: "boolean", description: "show every row" }
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
function limitOf(values, fallback) {
|
|
1148
|
+
if (values.full === true && values.limit !== undefined)
|
|
1149
|
+
badUsage("--limit and --full exclude each other");
|
|
1150
|
+
if (values.full === true || values.json === true && values.limit === undefined)
|
|
1151
|
+
return Number.POSITIVE_INFINITY;
|
|
1152
|
+
return wholeNumber(values.limit, "limit", fallback);
|
|
1153
|
+
}
|
|
1154
|
+
function moreFooter(more) {
|
|
1155
|
+
return `${more} more, rerun with --full`;
|
|
1156
|
+
}
|
|
1157
|
+
function capped(rows, limit) {
|
|
1158
|
+
const more = rows.length - limit;
|
|
1159
|
+
return more > 0 ? { shown: rows.slice(0, limit), footer: moreFooter(more) } : { shown: [...rows], footer: undefined };
|
|
1160
|
+
}
|
|
1161
|
+
var init_limit = __esm(() => {
|
|
1162
|
+
init_args();
|
|
1163
|
+
});
|
|
1164
|
+
|
|
1165
|
+
// ../kit/src/logs.ts
|
|
1166
|
+
var DAY_MS;
|
|
1167
|
+
var init_logs = __esm(() => {
|
|
1168
|
+
DAY_MS = 24 * 60 * 60 * 1000;
|
|
1169
|
+
});
|
|
1170
|
+
|
|
1171
|
+
// ../kit/src/secrets.ts
|
|
1172
|
+
var SECRET_WORDS;
|
|
1173
|
+
var init_secrets = __esm(() => {
|
|
1174
|
+
SECRET_WORDS = new Set(["key", "pass", "pwd", "auth", "salt", "cookie", "session", "jwt", "ssn", "iban", "card", "cvv", "otp"]);
|
|
1175
|
+
});
|
|
1176
|
+
|
|
1177
|
+
// ../kit/src/sessions.ts
|
|
1178
|
+
var {Glob } = globalThis.Bun;
|
|
1179
|
+
var SESSION_FILES, ACCOUNT_DIRS;
|
|
1180
|
+
var init_sessions = __esm(() => {
|
|
1181
|
+
SESSION_FILES = new Glob("*.json");
|
|
1182
|
+
ACCOUNT_DIRS = new Glob("*/sessions");
|
|
1183
|
+
});
|
|
1184
|
+
|
|
1185
|
+
// ../kit/src/index.ts
|
|
1186
|
+
var init_src = __esm(() => {
|
|
1187
|
+
init_args();
|
|
1188
|
+
init_chart();
|
|
1189
|
+
init_ci();
|
|
1190
|
+
init_cli();
|
|
1191
|
+
init_config();
|
|
1192
|
+
init_format();
|
|
1193
|
+
init_git();
|
|
1194
|
+
init_limit();
|
|
1195
|
+
init_logs();
|
|
1196
|
+
init_process();
|
|
1197
|
+
init_secrets();
|
|
1198
|
+
init_sessions();
|
|
1199
|
+
init_style();
|
|
1200
|
+
init_text();
|
|
1201
|
+
init_tool();
|
|
1202
|
+
});
|
|
1203
|
+
|
|
1204
|
+
// src/registry.ts
|
|
1205
|
+
function isPublic(registry) {
|
|
1206
|
+
return registry.url.replace(TRAILING_SLASHES, "") === PUBLIC_REGISTRY;
|
|
1207
|
+
}
|
|
1208
|
+
function unreachable(message) {
|
|
1209
|
+
return fail(`could not check: ${message}`, 2);
|
|
1210
|
+
}
|
|
1211
|
+
function requestInit(token) {
|
|
1212
|
+
return { headers: { accept: "application/json", ...token === undefined ? {} : { authorization: `Bearer ${token}` } }, signal: AbortSignal.timeout(REQUEST_TIMEOUT) };
|
|
1213
|
+
}
|
|
1214
|
+
async function get(fetcher, url, token) {
|
|
1215
|
+
try {
|
|
1216
|
+
return await fetcher(url, requestInit(token));
|
|
1217
|
+
} catch (error) {
|
|
1218
|
+
return unreachable(`cannot reach ${new URL(url).host}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
function isValidName(name) {
|
|
1222
|
+
return PACKAGE_NAME.test(name) && name.length <= 214;
|
|
1223
|
+
}
|
|
1224
|
+
async function fetchPackument(name, registry, fetcher = fetch) {
|
|
1225
|
+
if (!isValidName(name))
|
|
1226
|
+
fail(`${name} is not a valid npm package name`);
|
|
1227
|
+
const response = await get(fetcher, `${registry.url.replace(TRAILING_SLASHES, "")}/${encodeURIComponent(name).replace("%40", "@").replace("%2F", "%2f")}`, registry.token);
|
|
1228
|
+
if (response.status === 404)
|
|
1229
|
+
return;
|
|
1230
|
+
if (!response.ok)
|
|
1231
|
+
unreachable(`${new URL(registry.url).host} answered ${response.status} for ${name}`);
|
|
1232
|
+
let packument;
|
|
1233
|
+
try {
|
|
1234
|
+
packument = await response.json();
|
|
1235
|
+
} catch {
|
|
1236
|
+
return unreachable(`${new URL(registry.url).host} answered ${name} with something that is not JSON`);
|
|
1237
|
+
}
|
|
1238
|
+
if (packument?.name !== name)
|
|
1239
|
+
unreachable(`${new URL(registry.url).host} answered ${name} with the metadata of ${String(packument?.name)}`);
|
|
1240
|
+
return packument;
|
|
1241
|
+
}
|
|
1242
|
+
async function fetchDownloads(name, fetcher = fetch) {
|
|
1243
|
+
const response = await get(fetcher, `${DOWNLOADS_API}/${encodeURIComponent(name)}`);
|
|
1244
|
+
if (!response.ok)
|
|
1245
|
+
return;
|
|
1246
|
+
try {
|
|
1247
|
+
return (await response.json()).downloads;
|
|
1248
|
+
} catch {
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
var PUBLIC_REGISTRY = "https://registry.npmjs.org", DOWNLOADS_API = "https://api.npmjs.org/downloads/point/last-week", TRAILING_SLASHES, REQUEST_TIMEOUT = 1e4, PACKAGE_NAME;
|
|
1253
|
+
var init_registry = __esm(() => {
|
|
1254
|
+
init_src();
|
|
1255
|
+
TRAILING_SLASHES = /\/+$/;
|
|
1256
|
+
PACKAGE_NAME = /^(?:@[\w~-][\w.~-]*\/)?[\w~-][\w.~-]*$/;
|
|
1257
|
+
});
|
|
1258
|
+
|
|
1259
|
+
// src/config.ts
|
|
1260
|
+
import { homedir } from "os";
|
|
1261
|
+
import { dirname, join } from "path";
|
|
1262
|
+
import process8 from "process";
|
|
1263
|
+
function expand2(value, env) {
|
|
1264
|
+
let missing = false;
|
|
1265
|
+
const expanded = value.replace(ENV_REFERENCE, (_, braced, bare) => {
|
|
1266
|
+
const found = env[braced ?? bare ?? ""];
|
|
1267
|
+
missing ||= found === undefined;
|
|
1268
|
+
return found ?? "";
|
|
1269
|
+
});
|
|
1270
|
+
return missing ? undefined : expanded;
|
|
1271
|
+
}
|
|
1272
|
+
function literal(value) {
|
|
1273
|
+
return expand2(value, {}) === value ? value : undefined;
|
|
1274
|
+
}
|
|
1275
|
+
function parseNpmrc(text, env) {
|
|
1276
|
+
const config = { scopes: {}, tokens: {}, scopeTokens: {} };
|
|
1277
|
+
for (const line of text.split(`
|
|
1278
|
+
`)) {
|
|
1279
|
+
const at = line.indexOf("=");
|
|
1280
|
+
if (at === -1 || COMMENT.test(line))
|
|
1281
|
+
continue;
|
|
1282
|
+
const key = line.slice(0, at).trim();
|
|
1283
|
+
const scope = SCOPE_REGISTRY.exec(key)?.[1];
|
|
1284
|
+
const tokenFor = AUTH_TOKEN.exec(key)?.[1];
|
|
1285
|
+
const raw = line.slice(at + 1).trim().replace(QUOTES, "$2");
|
|
1286
|
+
const value = tokenFor === undefined ? literal(raw) : expand2(raw, env);
|
|
1287
|
+
if (value === undefined || value === "")
|
|
1288
|
+
continue;
|
|
1289
|
+
if (scope !== undefined)
|
|
1290
|
+
config.scopes[scope] = value;
|
|
1291
|
+
else if (tokenFor !== undefined)
|
|
1292
|
+
config.tokens[tokenFor] = value;
|
|
1293
|
+
else if (key === "registry")
|
|
1294
|
+
config.registry = value;
|
|
1295
|
+
}
|
|
1296
|
+
return config;
|
|
1297
|
+
}
|
|
1298
|
+
function bunEntry(entry, env) {
|
|
1299
|
+
const url = typeof entry === "string" ? entry : entry.url;
|
|
1300
|
+
const token = typeof entry === "string" || entry.token === undefined ? undefined : expand2(entry.token, env);
|
|
1301
|
+
return { ...url === undefined || literal(url) === undefined ? {} : { url }, ...token === undefined ? {} : { token } };
|
|
1302
|
+
}
|
|
1303
|
+
function parseBunfig(text, env) {
|
|
1304
|
+
const config = { scopes: {}, tokens: {}, scopeTokens: {} };
|
|
1305
|
+
const install = Bun.TOML.parse(text).install;
|
|
1306
|
+
if (install?.registry !== undefined) {
|
|
1307
|
+
const { url, token } = bunEntry(install.registry, env);
|
|
1308
|
+
if (url !== undefined)
|
|
1309
|
+
config.registry = url;
|
|
1310
|
+
if (url !== undefined && token !== undefined)
|
|
1311
|
+
config.tokens[url.replace(PROTOCOL, "")] = token;
|
|
1312
|
+
}
|
|
1313
|
+
for (const [scope, entry] of Object.entries(install?.scopes ?? {})) {
|
|
1314
|
+
const { url, token } = bunEntry(entry, env);
|
|
1315
|
+
if (url !== undefined)
|
|
1316
|
+
config.scopes[scope.startsWith("@") ? scope : `@${scope}`] = url;
|
|
1317
|
+
if (token !== undefined)
|
|
1318
|
+
config.scopeTokens[scope.startsWith("@") ? scope : `@${scope}`] = token;
|
|
1319
|
+
}
|
|
1320
|
+
return config;
|
|
1321
|
+
}
|
|
1322
|
+
function tokenFor(config, url) {
|
|
1323
|
+
const address = `${url.replace(PROTOCOL, "").replace(TRAILING_SLASHES2, "")}/`;
|
|
1324
|
+
const best = Object.keys(config.tokens).filter((key) => address.startsWith(`${key.replace(TRAILING_SLASHES2, "")}/`)).sort((a, b) => b.length - a.length)[0];
|
|
1325
|
+
return best === undefined ? undefined : config.tokens[best];
|
|
1326
|
+
}
|
|
1327
|
+
function mayCarryToken(url) {
|
|
1328
|
+
const { protocol, hostname } = new URL(url);
|
|
1329
|
+
return protocol === "https:" || LOCAL_HOSTS.has(hostname);
|
|
1330
|
+
}
|
|
1331
|
+
function registryFor(name, configs) {
|
|
1332
|
+
const scope = name.startsWith("@") ? name.slice(0, name.indexOf("/")) : undefined;
|
|
1333
|
+
const scoped = scope === undefined ? undefined : configs.find((config) => config.scopes[scope] !== undefined);
|
|
1334
|
+
const url = (scope === undefined ? undefined : scoped?.scopes[scope]) ?? configs.find((config) => config.registry !== undefined)?.registry;
|
|
1335
|
+
if (url === undefined)
|
|
1336
|
+
return { url: PUBLIC_REGISTRY };
|
|
1337
|
+
const token = (scope === undefined ? undefined : scoped?.scopeTokens[scope]) ?? configs.map((other) => tokenFor(other, url)).find((found) => found !== undefined);
|
|
1338
|
+
return { url, token: mayCarryToken(url) ? token : undefined };
|
|
1339
|
+
}
|
|
1340
|
+
function readable(path, parse) {
|
|
1341
|
+
try {
|
|
1342
|
+
return parse();
|
|
1343
|
+
} catch (error) {
|
|
1344
|
+
return unreachable(`${path} cannot be read: ${error instanceof Error ? error.message : String(error)}`);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
async function readIfThere(path) {
|
|
1348
|
+
const file = Bun.file(path);
|
|
1349
|
+
return await file.exists() ? file.text() : undefined;
|
|
1350
|
+
}
|
|
1351
|
+
async function loadConfigs(cwd = process8.cwd(), env = process8.env, home = homedir()) {
|
|
1352
|
+
const directories = [];
|
|
1353
|
+
for (let dir = cwd;!directories.includes(dir); dir = dirname(dir))
|
|
1354
|
+
directories.push(dir);
|
|
1355
|
+
if (!directories.includes(home))
|
|
1356
|
+
directories.push(home);
|
|
1357
|
+
const configs = [];
|
|
1358
|
+
for (const dir of directories) {
|
|
1359
|
+
const bunfig = await readIfThere(join(dir, "bunfig.toml"));
|
|
1360
|
+
const npmrc = await readIfThere(join(dir, ".npmrc"));
|
|
1361
|
+
if (bunfig !== undefined)
|
|
1362
|
+
configs.push(readable(join(dir, "bunfig.toml"), () => parseBunfig(bunfig, env)));
|
|
1363
|
+
if (npmrc !== undefined)
|
|
1364
|
+
configs.push(parseNpmrc(npmrc, env));
|
|
1365
|
+
}
|
|
1366
|
+
return configs;
|
|
1367
|
+
}
|
|
1368
|
+
function isSeverity(value) {
|
|
1369
|
+
return SEVERITIES.includes(value);
|
|
1370
|
+
}
|
|
1371
|
+
function parseSettings(text) {
|
|
1372
|
+
const raw = Bun.JSONC.parse(text);
|
|
1373
|
+
const settings = {};
|
|
1374
|
+
if (Array.isArray(raw?.licenses) && raw.licenses.every((each) => typeof each === "string"))
|
|
1375
|
+
settings.licenses = raw.licenses;
|
|
1376
|
+
if (isSeverity(raw?.blockSeverity))
|
|
1377
|
+
settings.blockSeverity = raw.blockSeverity;
|
|
1378
|
+
return settings;
|
|
1379
|
+
}
|
|
1380
|
+
async function loadSettings(cwd = process8.cwd(), home = homedir()) {
|
|
1381
|
+
const files = [];
|
|
1382
|
+
for (let dir = cwd;!files.includes(join(dir, SETTINGS_FILE)); dir = dirname(dir))
|
|
1383
|
+
files.push(join(dir, SETTINGS_FILE));
|
|
1384
|
+
files.push(join(home, ".config", "pkg", "config.json"));
|
|
1385
|
+
const settings = {};
|
|
1386
|
+
for (const file of files) {
|
|
1387
|
+
const text = await readIfThere(file);
|
|
1388
|
+
if (text === undefined)
|
|
1389
|
+
continue;
|
|
1390
|
+
const found = readable(file, () => parseSettings(text));
|
|
1391
|
+
settings.licenses ??= found.licenses;
|
|
1392
|
+
settings.blockSeverity ??= found.blockSeverity;
|
|
1393
|
+
}
|
|
1394
|
+
return settings;
|
|
1395
|
+
}
|
|
1396
|
+
var ENV_REFERENCE, COMMENT, SCOPE_REGISTRY, AUTH_TOKEN, PROTOCOL, TRAILING_SLASHES2, LOCAL_HOSTS, QUOTES, SEVERITIES, DEFAULT_BLOCK_SEVERITY = "high", SETTINGS_FILE = ".pkgrc.json";
|
|
1397
|
+
var init_config2 = __esm(() => {
|
|
1398
|
+
init_registry();
|
|
1399
|
+
ENV_REFERENCE = /\$\{(\w+)\}|\$(\w+)/g;
|
|
1400
|
+
COMMENT = /^\s*[#;]/;
|
|
1401
|
+
SCOPE_REGISTRY = /^(@[^:]+):registry$/;
|
|
1402
|
+
AUTH_TOKEN = /^(\/\/.+?):_authToken$/;
|
|
1403
|
+
PROTOCOL = /^\w+:/;
|
|
1404
|
+
TRAILING_SLASHES2 = /\/+$/;
|
|
1405
|
+
LOCAL_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
1406
|
+
QUOTES = /^(["'])(.*)\1$/;
|
|
1407
|
+
SEVERITIES = ["low", "moderate", "high", "critical"];
|
|
1408
|
+
});
|
|
1409
|
+
|
|
1410
|
+
// src/semver.ts
|
|
1411
|
+
function isRange(text) {
|
|
1412
|
+
if (text.trim() === "")
|
|
1413
|
+
return true;
|
|
1414
|
+
return text.split(OR).every((alternative) => {
|
|
1415
|
+
const words = alternative.trim().split(WHITESPACE);
|
|
1416
|
+
return words.every((word, index) => word === "-" ? index > 0 && index < words.length - 1 : COMPARATOR.test(word));
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
function compare(version, word) {
|
|
1420
|
+
const bound = BOUND.exec(word);
|
|
1421
|
+
if (bound === null)
|
|
1422
|
+
return;
|
|
1423
|
+
const order = Bun.semver.order(version, bound[2] ?? "");
|
|
1424
|
+
const operator = bound[1] ?? "=";
|
|
1425
|
+
if (operator === "<")
|
|
1426
|
+
return order < 0;
|
|
1427
|
+
if (operator === "<=")
|
|
1428
|
+
return order <= 0;
|
|
1429
|
+
if (operator === ">")
|
|
1430
|
+
return order > 0;
|
|
1431
|
+
return operator === ">=" ? order >= 0 : order === 0;
|
|
1432
|
+
}
|
|
1433
|
+
function inRange(version, range) {
|
|
1434
|
+
if (Bun.semver.satisfies(version, range))
|
|
1435
|
+
return true;
|
|
1436
|
+
if (!PRERELEASE.test(version))
|
|
1437
|
+
return false;
|
|
1438
|
+
return range.split(OR).some((alternative) => alternative.trim().split(WHITESPACE).every((word) => compare(version, word) ?? Bun.semver.satisfies(version, word)));
|
|
1439
|
+
}
|
|
1440
|
+
var OR, WHITESPACE, PRERELEASE, PART, COMPARATOR, BOUND, EXACT_VERSION;
|
|
1441
|
+
var init_semver = __esm(() => {
|
|
1442
|
+
OR = /\s*\|\|\s*/;
|
|
1443
|
+
WHITESPACE = /\s+/;
|
|
1444
|
+
PRERELEASE = /-/;
|
|
1445
|
+
PART = String.raw`(?:\d+|[xX*])`;
|
|
1446
|
+
COMPARATOR = new RegExp(String.raw`^(?:[<>]=?|=|\^|~>?)?v?${PART}(?:\.${PART}){0,2}(?:-[\w.-]+)?(?:\+[\w.-]+)?$`);
|
|
1447
|
+
BOUND = /^(<=|>=|[<>=])?v?(\d+\.\d+\.\d+(?:-[\w.-]+)?)$/;
|
|
1448
|
+
EXACT_VERSION = /^\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?$/;
|
|
1449
|
+
});
|
|
1450
|
+
|
|
1451
|
+
// src/advisories.ts
|
|
1452
|
+
function severityRank(severity) {
|
|
1453
|
+
return SEVERITIES.indexOf(severity);
|
|
1454
|
+
}
|
|
1455
|
+
function fixedVersion(vulnerable, version) {
|
|
1456
|
+
const range = vulnerable.split("||").map((each) => each.trim()).find((each) => inRange(version, each));
|
|
1457
|
+
return range === undefined ? undefined : UPPER_BOUND.exec(range)?.[1];
|
|
1458
|
+
}
|
|
1459
|
+
async function fetchAdvisories(versions, registry, fetcher = fetch) {
|
|
1460
|
+
const url = `${registry.url.replace(TRAILING_SLASHES3, "")}${BULK_PATH}`;
|
|
1461
|
+
const host = new URL(registry.url).host;
|
|
1462
|
+
let response;
|
|
1463
|
+
try {
|
|
1464
|
+
response = await fetcher(url, {
|
|
1465
|
+
method: "POST",
|
|
1466
|
+
headers: { accept: "application/json", "content-type": "application/json", ...registry.token === undefined ? {} : { authorization: `Bearer ${registry.token}` } },
|
|
1467
|
+
body: JSON.stringify(versions),
|
|
1468
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT2)
|
|
1469
|
+
});
|
|
1470
|
+
} catch (error) {
|
|
1471
|
+
return { found: {}, unavailable: `cannot reach ${host} for advisories: ${error instanceof Error ? error.message : String(error)}` };
|
|
1472
|
+
}
|
|
1473
|
+
if (NO_ENDPOINT.has(response.status))
|
|
1474
|
+
return { found: {}, isUnsupported: true, unavailable: `${host} has no advisory endpoint` };
|
|
1475
|
+
if (!response.ok)
|
|
1476
|
+
return { found: {}, unavailable: `${host} answered ${response.status} for advisories` };
|
|
1477
|
+
let body;
|
|
1478
|
+
try {
|
|
1479
|
+
body = await response.json();
|
|
1480
|
+
} catch {
|
|
1481
|
+
return { found: {}, unavailable: `${host} answered advisories with something that is not JSON` };
|
|
1482
|
+
}
|
|
1483
|
+
const found = {};
|
|
1484
|
+
for (const [name, raws] of Object.entries(body)) {
|
|
1485
|
+
if (!Array.isArray(raws))
|
|
1486
|
+
continue;
|
|
1487
|
+
found[name] = raws.filter((raw) => SEVERITIES.includes(raw.severity)).map((raw) => ({
|
|
1488
|
+
id: raw.id,
|
|
1489
|
+
ghsa: GHSA.exec(raw.url)?.[0],
|
|
1490
|
+
url: raw.url,
|
|
1491
|
+
title: raw.title,
|
|
1492
|
+
severity: raw.severity,
|
|
1493
|
+
vulnerable: raw.vulnerable_versions
|
|
1494
|
+
}));
|
|
1495
|
+
}
|
|
1496
|
+
return { found };
|
|
1497
|
+
}
|
|
1498
|
+
function advisoriesFor(advisories, version) {
|
|
1499
|
+
return (advisories ?? []).filter((each) => inRange(version, each.vulnerable)).map((each) => ({ ...each, fixed: fixedVersion(each.vulnerable, version) }));
|
|
1500
|
+
}
|
|
1501
|
+
function filterAdvisories(advisories, level, ignore = []) {
|
|
1502
|
+
return advisories.filter((each) => severityRank(each.severity) >= severityRank(level) && !ignore.includes(each.ghsa ?? "") && !ignore.includes(String(each.id)));
|
|
1503
|
+
}
|
|
1504
|
+
var BULK_PATH = "/-/npm/v1/security/advisories/bulk", TRAILING_SLASHES3, REQUEST_TIMEOUT2 = 1e4, GHSA, UPPER_BOUND, NO_ENDPOINT;
|
|
1505
|
+
var init_advisories = __esm(() => {
|
|
1506
|
+
init_config2();
|
|
1507
|
+
init_semver();
|
|
1508
|
+
TRAILING_SLASHES3 = /\/+$/;
|
|
1509
|
+
GHSA = /GHSA-[\w-]+$/;
|
|
1510
|
+
UPPER_BOUND = /(?:^|\s)<([\w.+-]+)/;
|
|
1511
|
+
NO_ENDPOINT = new Set([404, 405, 501]);
|
|
1512
|
+
});
|
|
1513
|
+
|
|
1514
|
+
// src/licenses.ts
|
|
1515
|
+
function isLicenseAllowed(expression, allowed) {
|
|
1516
|
+
const known = new Set(allowed.map((each) => each.toLowerCase()));
|
|
1517
|
+
return expression.replace(PARENS, " ").trim().split(OR_SPLIT).some((alternative) => alternative.split(AND_SPLIT).every((term) => known.has(term.replace(WITH_EXCEPTION, "").trim().toLowerCase())));
|
|
1518
|
+
}
|
|
1519
|
+
var OR_SPLIT, AND_SPLIT, WITH_EXCEPTION, PARENS;
|
|
1520
|
+
var init_licenses = __esm(() => {
|
|
1521
|
+
OR_SPLIT = /\s+OR\s+/i;
|
|
1522
|
+
AND_SPLIT = /\s+AND\s+/i;
|
|
1523
|
+
WITH_EXCEPTION = /\s+WITH\s+\S+$/i;
|
|
1524
|
+
PARENS = /[()]/g;
|
|
1525
|
+
});
|
|
1526
|
+
|
|
1527
|
+
// src/popular.json
|
|
1528
|
+
var popular_default;
|
|
1529
|
+
var init_popular = __esm(() => {
|
|
1530
|
+
popular_default = [
|
|
1531
|
+
"semver",
|
|
1532
|
+
"minimatch",
|
|
1533
|
+
"debug",
|
|
1534
|
+
"ansi-styles",
|
|
1535
|
+
"brace-expansion",
|
|
1536
|
+
"strip-ansi",
|
|
1537
|
+
"ansi-regex",
|
|
1538
|
+
"ms",
|
|
1539
|
+
"supports-color",
|
|
1540
|
+
"chalk",
|
|
1541
|
+
"commander",
|
|
1542
|
+
"lru-cache",
|
|
1543
|
+
"string-width",
|
|
1544
|
+
"wrap-ansi",
|
|
1545
|
+
"tslib",
|
|
1546
|
+
"picomatch",
|
|
1547
|
+
"emoji-regex",
|
|
1548
|
+
"glob",
|
|
1549
|
+
"type-fest",
|
|
1550
|
+
"color-name",
|
|
1551
|
+
"eslint-visitor-keys",
|
|
1552
|
+
"color-convert",
|
|
1553
|
+
"ajv",
|
|
1554
|
+
"minipass",
|
|
1555
|
+
"source-map",
|
|
1556
|
+
"balanced-match",
|
|
1557
|
+
"readable-stream",
|
|
1558
|
+
"which",
|
|
1559
|
+
"glob-parent",
|
|
1560
|
+
"escape-string-regexp",
|
|
1561
|
+
"has-flag",
|
|
1562
|
+
"find-up",
|
|
1563
|
+
"locate-path",
|
|
1564
|
+
"json-schema-traverse",
|
|
1565
|
+
"p-limit",
|
|
1566
|
+
"yallist",
|
|
1567
|
+
"safe-buffer",
|
|
1568
|
+
"uuid",
|
|
1569
|
+
"p-locate",
|
|
1570
|
+
"undici-types",
|
|
1571
|
+
"ignore",
|
|
1572
|
+
"iconv-lite",
|
|
1573
|
+
"signal-exit",
|
|
1574
|
+
"esbuild",
|
|
1575
|
+
"is-fullwidth-code-point",
|
|
1576
|
+
"js-yaml",
|
|
1577
|
+
"entities",
|
|
1578
|
+
"globals",
|
|
1579
|
+
"postcss",
|
|
1580
|
+
"isexe",
|
|
1581
|
+
"isarray",
|
|
1582
|
+
"path-key",
|
|
1583
|
+
"string_decoder",
|
|
1584
|
+
"argparse",
|
|
1585
|
+
"ws",
|
|
1586
|
+
"mime-db",
|
|
1587
|
+
"resolve",
|
|
1588
|
+
"agent-base",
|
|
1589
|
+
"@esbuild/linux-x64",
|
|
1590
|
+
"yargs-parser",
|
|
1591
|
+
"mime-types",
|
|
1592
|
+
"acorn",
|
|
1593
|
+
"estraverse",
|
|
1594
|
+
"cross-spawn",
|
|
1595
|
+
"react-is",
|
|
1596
|
+
"picocolors",
|
|
1597
|
+
"fs-extra",
|
|
1598
|
+
"hasown",
|
|
1599
|
+
"nanoid",
|
|
1600
|
+
"yargs",
|
|
1601
|
+
"resolve-from",
|
|
1602
|
+
"shebang-command",
|
|
1603
|
+
"pretty-format",
|
|
1604
|
+
"json5",
|
|
1605
|
+
"https-proxy-agent",
|
|
1606
|
+
"path-to-regexp",
|
|
1607
|
+
"path-exists",
|
|
1608
|
+
"punycode",
|
|
1609
|
+
"js-tokens",
|
|
1610
|
+
"cliui",
|
|
1611
|
+
"shebang-regex",
|
|
1612
|
+
"@babel/types",
|
|
1613
|
+
"chokidar",
|
|
1614
|
+
"strip-json-comments",
|
|
1615
|
+
"inherits",
|
|
1616
|
+
"webidl-conversions",
|
|
1617
|
+
"get-stream",
|
|
1618
|
+
"eslint-scope",
|
|
1619
|
+
"cookie",
|
|
1620
|
+
"@babel/parser",
|
|
1621
|
+
"qs",
|
|
1622
|
+
"is-number",
|
|
1623
|
+
"whatwg-url",
|
|
1624
|
+
"@types/estree",
|
|
1625
|
+
"tr46",
|
|
1626
|
+
"convert-source-map",
|
|
1627
|
+
"is-glob",
|
|
1628
|
+
"braces",
|
|
1629
|
+
"fast-deep-equal",
|
|
1630
|
+
"form-data",
|
|
1631
|
+
"lodash",
|
|
1632
|
+
"@babel/helper-validator-identifier",
|
|
1633
|
+
"electron-to-chromium",
|
|
1634
|
+
"fill-range",
|
|
1635
|
+
"function-bind",
|
|
1636
|
+
"readdirp",
|
|
1637
|
+
"escalade",
|
|
1638
|
+
"graceful-fs",
|
|
1639
|
+
"negotiator",
|
|
1640
|
+
"is-stream",
|
|
1641
|
+
"camelcase",
|
|
1642
|
+
"@babel/runtime",
|
|
1643
|
+
"yocto-queue",
|
|
1644
|
+
"to-regex-range",
|
|
1645
|
+
"node-fetch",
|
|
1646
|
+
"micromatch",
|
|
1647
|
+
"node-releases",
|
|
1648
|
+
"get-intrinsic",
|
|
1649
|
+
"universalify",
|
|
1650
|
+
"path-scurry",
|
|
1651
|
+
"jsesc",
|
|
1652
|
+
"browserslist",
|
|
1653
|
+
"es-errors",
|
|
1654
|
+
"statuses",
|
|
1655
|
+
"@radix-ui/react-primitive",
|
|
1656
|
+
"magic-string",
|
|
1657
|
+
"rimraf",
|
|
1658
|
+
"is-extglob",
|
|
1659
|
+
"@jridgewell/trace-mapping",
|
|
1660
|
+
"@jridgewell/resolve-uri",
|
|
1661
|
+
"http-errors",
|
|
1662
|
+
"onetime",
|
|
1663
|
+
"has-symbols",
|
|
1664
|
+
"es-define-property",
|
|
1665
|
+
"gopd",
|
|
1666
|
+
"util-deprecate",
|
|
1667
|
+
"object-assign",
|
|
1668
|
+
"jiti",
|
|
1669
|
+
"yaml",
|
|
1670
|
+
"dotenv",
|
|
1671
|
+
"@babel/generator",
|
|
1672
|
+
"@babel/template",
|
|
1673
|
+
"imurmurhash",
|
|
1674
|
+
"postcss-selector-parser",
|
|
1675
|
+
"fast-glob",
|
|
1676
|
+
"update-browserslist-db",
|
|
1677
|
+
"@types/node",
|
|
1678
|
+
"@babel/compat-data",
|
|
1679
|
+
"eventemitter3",
|
|
1680
|
+
"callsites",
|
|
1681
|
+
"http-proxy-agent",
|
|
1682
|
+
"detect-libc",
|
|
1683
|
+
"espree",
|
|
1684
|
+
"execa",
|
|
1685
|
+
"@babel/core",
|
|
1686
|
+
"@babel/helpers",
|
|
1687
|
+
"concat-map",
|
|
1688
|
+
"source-map-js",
|
|
1689
|
+
"tinyglobby",
|
|
1690
|
+
"call-bind-apply-helpers",
|
|
1691
|
+
"flat-cache",
|
|
1692
|
+
"fdir",
|
|
1693
|
+
"pify",
|
|
1694
|
+
"@jest/types",
|
|
1695
|
+
"normalize-path",
|
|
1696
|
+
"is-core-module",
|
|
1697
|
+
"eslint",
|
|
1698
|
+
"minimist",
|
|
1699
|
+
"estree-walker",
|
|
1700
|
+
"file-entry-cache",
|
|
1701
|
+
"object-inspect",
|
|
1702
|
+
"buffer",
|
|
1703
|
+
"uri-js",
|
|
1704
|
+
"import-fresh",
|
|
1705
|
+
"@babel/helper-module-transforms",
|
|
1706
|
+
"optionator",
|
|
1707
|
+
"flatted",
|
|
1708
|
+
"math-intrinsics",
|
|
1709
|
+
"safer-buffer",
|
|
1710
|
+
"y18n",
|
|
1711
|
+
"@babel/helper-module-imports",
|
|
1712
|
+
"mkdirp",
|
|
1713
|
+
"dunder-proto",
|
|
1714
|
+
"path-parse",
|
|
1715
|
+
"fastq",
|
|
1716
|
+
"levn",
|
|
1717
|
+
"@babel/helper-compilation-targets",
|
|
1718
|
+
"@babel/helper-string-parser",
|
|
1719
|
+
"keyv",
|
|
1720
|
+
"get-proto",
|
|
1721
|
+
"csstype",
|
|
1722
|
+
"npm-run-path",
|
|
1723
|
+
"fast-json-stable-stringify",
|
|
1724
|
+
"reusify",
|
|
1725
|
+
"@babel/helper-plugin-utils",
|
|
1726
|
+
"kind-of",
|
|
1727
|
+
"mime",
|
|
1728
|
+
"caniuse-lite",
|
|
1729
|
+
"lines-and-columns",
|
|
1730
|
+
"fast-levenshtein",
|
|
1731
|
+
"supports-preserve-symlinks-flag",
|
|
1732
|
+
"make-dir",
|
|
1733
|
+
"slash",
|
|
1734
|
+
"prelude-ls",
|
|
1735
|
+
"typescript",
|
|
1736
|
+
"strip-bom",
|
|
1737
|
+
"parent-module",
|
|
1738
|
+
"esutils",
|
|
1739
|
+
"ci-info",
|
|
1740
|
+
"@smithy/util-utf8",
|
|
1741
|
+
"type-check",
|
|
1742
|
+
"mimic-fn",
|
|
1743
|
+
"@babel/helper-validator-option",
|
|
1744
|
+
"@types/json-schema",
|
|
1745
|
+
"@rolldown/pluginutils",
|
|
1746
|
+
"side-channel-list",
|
|
1747
|
+
"json-buffer",
|
|
1748
|
+
"raw-body",
|
|
1749
|
+
"has-tostringtag",
|
|
1750
|
+
"wrappy",
|
|
1751
|
+
"diff",
|
|
1752
|
+
"jackspeak",
|
|
1753
|
+
"baseline-browser-mapping",
|
|
1754
|
+
"deep-is",
|
|
1755
|
+
"foreground-child",
|
|
1756
|
+
"@eslint/js",
|
|
1757
|
+
"anymatch",
|
|
1758
|
+
"natural-compare",
|
|
1759
|
+
"esquery",
|
|
1760
|
+
"@eslint-community/regexpp",
|
|
1761
|
+
"es-set-tostringtag",
|
|
1762
|
+
"acorn-jsx",
|
|
1763
|
+
"parse5",
|
|
1764
|
+
"finalhandler",
|
|
1765
|
+
"parse-json",
|
|
1766
|
+
"depd",
|
|
1767
|
+
"axios",
|
|
1768
|
+
"run-parallel",
|
|
1769
|
+
"source-map-support",
|
|
1770
|
+
"esrecurse",
|
|
1771
|
+
"call-bound",
|
|
1772
|
+
"content-disposition",
|
|
1773
|
+
"human-signals",
|
|
1774
|
+
"ts-api-utils",
|
|
1775
|
+
"ansi-escapes",
|
|
1776
|
+
"jest-util",
|
|
1777
|
+
"send",
|
|
1778
|
+
"@opentelemetry/core",
|
|
1779
|
+
"type-is",
|
|
1780
|
+
"encodeurl",
|
|
1781
|
+
"once",
|
|
1782
|
+
"cosmiconfig",
|
|
1783
|
+
"lodash.merge",
|
|
1784
|
+
"json-stable-stringify-without-jsonify",
|
|
1785
|
+
"open",
|
|
1786
|
+
"prettier",
|
|
1787
|
+
"@eslint/eslintrc",
|
|
1788
|
+
"is-arrayish",
|
|
1789
|
+
"@jridgewell/sourcemap-codec",
|
|
1790
|
+
"gensync",
|
|
1791
|
+
"word-wrap",
|
|
1792
|
+
"express",
|
|
1793
|
+
"arg",
|
|
1794
|
+
"jsonfile",
|
|
1795
|
+
"schema-utils",
|
|
1796
|
+
"@smithy/is-array-buffer",
|
|
1797
|
+
"@typescript-eslint/types",
|
|
1798
|
+
"chownr",
|
|
1799
|
+
"delayed-stream",
|
|
1800
|
+
"@smithy/util-buffer-from",
|
|
1801
|
+
"asynckit",
|
|
1802
|
+
"tapable",
|
|
1803
|
+
"enhanced-resolve",
|
|
1804
|
+
"aria-query",
|
|
1805
|
+
"indent-string",
|
|
1806
|
+
"bytes",
|
|
1807
|
+
"binary-extensions",
|
|
1808
|
+
"ini",
|
|
1809
|
+
"@radix-ui/react-context",
|
|
1810
|
+
"doctrine",
|
|
1811
|
+
"queue-microtask",
|
|
1812
|
+
"accepts",
|
|
1813
|
+
"merge2",
|
|
1814
|
+
"get-caller-file",
|
|
1815
|
+
"@humanwhocodes/retry",
|
|
1816
|
+
"@jridgewell/gen-mapping",
|
|
1817
|
+
"@typescript-eslint/typescript-estree",
|
|
1818
|
+
"jest-worker",
|
|
1819
|
+
"proxy-from-env",
|
|
1820
|
+
"clsx",
|
|
1821
|
+
"side-channel-map",
|
|
1822
|
+
"@typescript-eslint/visitor-keys",
|
|
1823
|
+
"fresh",
|
|
1824
|
+
"restore-cursor",
|
|
1825
|
+
"on-finished",
|
|
1826
|
+
"is-plain-obj",
|
|
1827
|
+
"ipaddr.js",
|
|
1828
|
+
"pathe",
|
|
1829
|
+
"@jest/schemas",
|
|
1830
|
+
"base64-js",
|
|
1831
|
+
"@smithy/types",
|
|
1832
|
+
"require-directory",
|
|
1833
|
+
"tough-cookie",
|
|
1834
|
+
"is-binary-path",
|
|
1835
|
+
"body-parser",
|
|
1836
|
+
"postcss-value-parser",
|
|
1837
|
+
"media-typer",
|
|
1838
|
+
"setprototypeof",
|
|
1839
|
+
"side-channel-weakmap",
|
|
1840
|
+
"@typescript-eslint/tsconfig-utils",
|
|
1841
|
+
"@isaacs/cliui",
|
|
1842
|
+
"@rollup/rollup-linux-x64-gnu",
|
|
1843
|
+
"is-wsl",
|
|
1844
|
+
"retry",
|
|
1845
|
+
"@aws-sdk/types",
|
|
1846
|
+
"@types/react-dom",
|
|
1847
|
+
"combined-stream",
|
|
1848
|
+
"es-object-atoms",
|
|
1849
|
+
"@eslint/core",
|
|
1850
|
+
"whatwg-mimetype",
|
|
1851
|
+
"domutils",
|
|
1852
|
+
"@rollup/rollup-linux-x64-musl",
|
|
1853
|
+
"core-util-is",
|
|
1854
|
+
"@typescript-eslint/scope-manager",
|
|
1855
|
+
"esprima",
|
|
1856
|
+
"loose-envify",
|
|
1857
|
+
"cookie-signature",
|
|
1858
|
+
"follow-redirects",
|
|
1859
|
+
"cli-cursor",
|
|
1860
|
+
"strip-final-newline",
|
|
1861
|
+
"@typescript-eslint/project-service",
|
|
1862
|
+
"eastasianwidth",
|
|
1863
|
+
"json-parse-even-better-errors",
|
|
1864
|
+
"sprintf-js",
|
|
1865
|
+
"path-type",
|
|
1866
|
+
"content-type",
|
|
1867
|
+
"es-module-lexer",
|
|
1868
|
+
"@nodelib/fs.scandir",
|
|
1869
|
+
"write-file-atomic",
|
|
1870
|
+
"@eslint/plugin-kit",
|
|
1871
|
+
"ieee754",
|
|
1872
|
+
"prop-types",
|
|
1873
|
+
"require-from-string",
|
|
1874
|
+
"dom-serializer",
|
|
1875
|
+
"call-bind",
|
|
1876
|
+
"@eslint/config-array",
|
|
1877
|
+
"has-property-descriptors",
|
|
1878
|
+
"@nodelib/fs.stat",
|
|
1879
|
+
"merge-descriptors",
|
|
1880
|
+
"slice-ansi",
|
|
1881
|
+
"rxjs",
|
|
1882
|
+
"p-map",
|
|
1883
|
+
"toidentifier",
|
|
1884
|
+
"globby",
|
|
1885
|
+
"domhandler",
|
|
1886
|
+
"async",
|
|
1887
|
+
"@babel/helper-globals",
|
|
1888
|
+
"pirates",
|
|
1889
|
+
"@opentelemetry/semantic-conventions",
|
|
1890
|
+
"@typescript-eslint/utils",
|
|
1891
|
+
"date-fns",
|
|
1892
|
+
"is-docker",
|
|
1893
|
+
"tar",
|
|
1894
|
+
"which-typed-array",
|
|
1895
|
+
"ajv-formats",
|
|
1896
|
+
"@opentelemetry/api-logs",
|
|
1897
|
+
"@opentelemetry/resources",
|
|
1898
|
+
"side-channel",
|
|
1899
|
+
"cjs-module-lexer",
|
|
1900
|
+
"range-parser",
|
|
1901
|
+
"@humanfs/node",
|
|
1902
|
+
"define-data-property",
|
|
1903
|
+
"node-addon-api",
|
|
1904
|
+
"pako",
|
|
1905
|
+
"lilconfig",
|
|
1906
|
+
"fast-uri",
|
|
1907
|
+
"ip-address",
|
|
1908
|
+
"fs.realpath",
|
|
1909
|
+
"@img/sharp-libvips-linuxmusl-x64",
|
|
1910
|
+
"cssesc",
|
|
1911
|
+
"@opentelemetry/instrumentation",
|
|
1912
|
+
"domelementtype",
|
|
1913
|
+
"hosted-git-info",
|
|
1914
|
+
"@eslint/object-schema",
|
|
1915
|
+
"etag",
|
|
1916
|
+
"@eslint/config-helpers",
|
|
1917
|
+
"package-json-from-dist",
|
|
1918
|
+
"@humanfs/core",
|
|
1919
|
+
"htmlparser2",
|
|
1920
|
+
"jest-message-util",
|
|
1921
|
+
"for-each",
|
|
1922
|
+
"pkg-dir",
|
|
1923
|
+
"unpipe",
|
|
1924
|
+
"buffer-from",
|
|
1925
|
+
"es-abstract",
|
|
1926
|
+
"is-unicode-supported",
|
|
1927
|
+
"@types/yargs",
|
|
1928
|
+
"is-callable",
|
|
1929
|
+
"fast-xml-parser",
|
|
1930
|
+
"istanbul-lib-instrument",
|
|
1931
|
+
"escape-html",
|
|
1932
|
+
"is-regex",
|
|
1933
|
+
"dom-accessibility-api",
|
|
1934
|
+
"css-tree",
|
|
1935
|
+
"error-ex",
|
|
1936
|
+
"ee-first",
|
|
1937
|
+
"@types/unist",
|
|
1938
|
+
"log-symbols",
|
|
1939
|
+
"path-is-absolute",
|
|
1940
|
+
"end-of-stream",
|
|
1941
|
+
"@vitest/utils",
|
|
1942
|
+
"object.assign",
|
|
1943
|
+
"object-keys",
|
|
1944
|
+
"tinyexec",
|
|
1945
|
+
"scheduler",
|
|
1946
|
+
"p-try",
|
|
1947
|
+
"process-nextick-args",
|
|
1948
|
+
"vary",
|
|
1949
|
+
"@babel/traverse",
|
|
1950
|
+
"@pkgjs/parseargs",
|
|
1951
|
+
"@types/babel__generator",
|
|
1952
|
+
"kleur",
|
|
1953
|
+
"zod",
|
|
1954
|
+
"merge-stream",
|
|
1955
|
+
"available-typed-arrays",
|
|
1956
|
+
"mute-stream",
|
|
1957
|
+
"is-typed-array",
|
|
1958
|
+
"safe-regex-test",
|
|
1959
|
+
"tsconfig-paths",
|
|
1960
|
+
"minizlib",
|
|
1961
|
+
"tar-stream",
|
|
1962
|
+
"@floating-ui/core",
|
|
1963
|
+
"jose",
|
|
1964
|
+
"deepmerge",
|
|
1965
|
+
"get-tsconfig",
|
|
1966
|
+
"set-function-length",
|
|
1967
|
+
"@vitest/spy",
|
|
1968
|
+
"css-select",
|
|
1969
|
+
"@types/babel__core",
|
|
1970
|
+
"forwarded",
|
|
1971
|
+
"react",
|
|
1972
|
+
"@typescript-eslint/parser",
|
|
1973
|
+
"ajv-keywords",
|
|
1974
|
+
"define-properties",
|
|
1975
|
+
"is-generator-function",
|
|
1976
|
+
"regexp.prototype.flags",
|
|
1977
|
+
"acorn-walk",
|
|
1978
|
+
"pump",
|
|
1979
|
+
"data-uri-to-buffer",
|
|
1980
|
+
"object-hash",
|
|
1981
|
+
"jsdom",
|
|
1982
|
+
"nopt",
|
|
1983
|
+
"@babel/plugin-syntax-jsx",
|
|
1984
|
+
"@floating-ui/dom",
|
|
1985
|
+
"tiny-invariant",
|
|
1986
|
+
"strip-indent",
|
|
1987
|
+
"d3-array",
|
|
1988
|
+
"chai",
|
|
1989
|
+
"@babel/code-frame",
|
|
1990
|
+
"@typescript-eslint/eslint-plugin",
|
|
1991
|
+
"proxy-addr",
|
|
1992
|
+
"parseurl",
|
|
1993
|
+
"@floating-ui/utils",
|
|
1994
|
+
"ora",
|
|
1995
|
+
"html-encoding-sniffer",
|
|
1996
|
+
"pnpm",
|
|
1997
|
+
"whatwg-encoding",
|
|
1998
|
+
"events",
|
|
1999
|
+
"@typescript-eslint/type-utils",
|
|
2000
|
+
"env-paths",
|
|
2001
|
+
"internal-slot",
|
|
2002
|
+
"string.prototype.trimend",
|
|
2003
|
+
"extend",
|
|
2004
|
+
"resolve-pkg-maps",
|
|
2005
|
+
"istanbul-lib-coverage",
|
|
2006
|
+
"react-dom",
|
|
2007
|
+
"is-number-object",
|
|
2008
|
+
"@radix-ui/primitive",
|
|
2009
|
+
"is-plain-object",
|
|
2010
|
+
"string.prototype.trimstart",
|
|
2011
|
+
"@babel/plugin-syntax-typescript",
|
|
2012
|
+
"jest-diff",
|
|
2013
|
+
"define-lazy-prop",
|
|
2014
|
+
"globalthis",
|
|
2015
|
+
"which-boxed-primitive",
|
|
2016
|
+
"@vitest/expect",
|
|
2017
|
+
"sax",
|
|
2018
|
+
"@floating-ui/react-dom",
|
|
2019
|
+
"@vitest/pretty-format",
|
|
2020
|
+
"internmap",
|
|
2021
|
+
"@radix-ui/react-compose-refs",
|
|
2022
|
+
"is-symbol",
|
|
2023
|
+
"@eslint-community/eslint-utils",
|
|
2024
|
+
"bl",
|
|
2025
|
+
"serve-static",
|
|
2026
|
+
"get-symbol-description",
|
|
2027
|
+
"is-shared-array-buffer",
|
|
2028
|
+
"functions-have-names",
|
|
2029
|
+
"array-buffer-byte-length",
|
|
2030
|
+
"socks-proxy-agent"
|
|
2031
|
+
];
|
|
2032
|
+
});
|
|
2033
|
+
|
|
2034
|
+
// src/nearmiss.ts
|
|
2035
|
+
function baseName(name) {
|
|
2036
|
+
return name.slice(name.indexOf("/") + 1);
|
|
2037
|
+
}
|
|
2038
|
+
function scopeOf2(name) {
|
|
2039
|
+
return name.startsWith("@") ? name.slice(0, name.indexOf("/")) : "";
|
|
2040
|
+
}
|
|
2041
|
+
function squash(name) {
|
|
2042
|
+
return name.toLowerCase().replace(SEPARATORS, "");
|
|
2043
|
+
}
|
|
2044
|
+
function resemblance(name, popular) {
|
|
2045
|
+
if (scopeOf2(name) !== scopeOf2(popular) && baseName(name) === baseName(popular) && baseName(name).length >= MIN_LENGTH)
|
|
2046
|
+
return `${popular} under another scope`;
|
|
2047
|
+
if (squash(name) === squash(popular))
|
|
2048
|
+
return `${popular} spelled with other separators or case`;
|
|
2049
|
+
const shortest = Math.min(name.length, popular.length);
|
|
2050
|
+
const allowed = shortest >= MIN_LENGTH * 2 ? 2 : 1;
|
|
2051
|
+
if (shortest < MIN_LENGTH || Math.abs(name.length - popular.length) > allowed)
|
|
2052
|
+
return;
|
|
2053
|
+
const edits = distance(name, popular);
|
|
2054
|
+
return edits <= allowed ? `${popular}, ${edits} ${edits === 1 ? "edit" : "edits"} away` : undefined;
|
|
2055
|
+
}
|
|
2056
|
+
function nearMisses(name, popular = popular_default) {
|
|
2057
|
+
if (popular.includes(name))
|
|
2058
|
+
return [];
|
|
2059
|
+
const found = [];
|
|
2060
|
+
for (const other of popular) {
|
|
2061
|
+
const text = resemblance(name, other);
|
|
2062
|
+
if (text !== undefined)
|
|
2063
|
+
found.push({ text, edits: distance(name, other) });
|
|
2064
|
+
}
|
|
2065
|
+
return found.sort((a, b) => a.edits - b.edits).slice(0, 3).map((match) => match.text);
|
|
2066
|
+
}
|
|
2067
|
+
var SEPARATORS, MIN_LENGTH = 5;
|
|
2068
|
+
var init_nearmiss = __esm(() => {
|
|
2069
|
+
init_src();
|
|
2070
|
+
init_popular();
|
|
2071
|
+
SEPARATORS = /[-_.]/g;
|
|
2072
|
+
});
|
|
2073
|
+
|
|
2074
|
+
// src/analyze.ts
|
|
2075
|
+
function parseSpec(text) {
|
|
2076
|
+
const at = text.search(VERSION_SEPARATOR);
|
|
2077
|
+
return at === -1 ? { name: text } : { name: text.slice(0, at), request: text.slice(at + 1) };
|
|
2078
|
+
}
|
|
2079
|
+
function isStable(version) {
|
|
2080
|
+
return !version.includes("-");
|
|
2081
|
+
}
|
|
2082
|
+
function resolve(packument, request) {
|
|
2083
|
+
const tags = packument["dist-tags"] ?? {};
|
|
2084
|
+
const versions = Object.keys(packument.versions ?? {});
|
|
2085
|
+
const wanted = request === undefined || request === "" ? "latest" : request;
|
|
2086
|
+
if (tags[wanted] !== undefined)
|
|
2087
|
+
return tags[wanted];
|
|
2088
|
+
if (versions.includes(wanted))
|
|
2089
|
+
return wanted;
|
|
2090
|
+
if (!isRange(wanted))
|
|
2091
|
+
return;
|
|
2092
|
+
return versions.filter((version) => Bun.semver.satisfies(version, wanted)).sort(Bun.semver.order).at(-1);
|
|
2093
|
+
}
|
|
2094
|
+
function licenseOf(license) {
|
|
2095
|
+
return typeof license === "string" ? license : license?.type;
|
|
2096
|
+
}
|
|
2097
|
+
function repositoryOf(packument) {
|
|
2098
|
+
const repository = typeof packument.repository === "string" ? packument.repository : packument.repository?.url;
|
|
2099
|
+
return repository?.replace(GIT_PREFIX, "") ?? packument.homepage;
|
|
2100
|
+
}
|
|
2101
|
+
function ageDays(published, now) {
|
|
2102
|
+
const at = Date.parse(published ?? "");
|
|
2103
|
+
return Number.isNaN(at) ? undefined : (now - at) / DAY;
|
|
2104
|
+
}
|
|
2105
|
+
function daysAgo(age) {
|
|
2106
|
+
return age < 1 ? "less than a day" : `${Math.floor(age)} day${Math.floor(age) === 1 ? "" : "s"}`;
|
|
2107
|
+
}
|
|
2108
|
+
function installScriptsOf(version) {
|
|
2109
|
+
return Object.fromEntries(INSTALL_SCRIPTS.flatMap((name) => version?.scripts?.[name] === undefined ? [] : [[name, version.scripts[name]]]));
|
|
2110
|
+
}
|
|
2111
|
+
function safeRelease(packument, now, minAgeDays) {
|
|
2112
|
+
const old = Object.keys(packument.versions ?? {}).filter((version) => isStable(version) && (ageDays(packument.time?.[version], now) ?? 0) >= minAgeDays && packument.time?.[version] !== undefined);
|
|
2113
|
+
const version = old.sort(Bun.semver.order).at(-1);
|
|
2114
|
+
return version === undefined ? undefined : { version, published: packument.time?.[version] };
|
|
2115
|
+
}
|
|
2116
|
+
function analyze(input) {
|
|
2117
|
+
const { spec, packument, registry, now = Date.now(), minAgeDays = DEFAULT_MIN_AGE_DAYS } = input;
|
|
2118
|
+
const report = { name: spec.name, registry, exists: packument !== undefined, requested: spec.request, installScripts: {}, nearMisses: nearMisses(spec.name), advisories: input.advisories ?? [], fixes: [], warnings: [], blocked: false, downloads: input.downloads };
|
|
2119
|
+
if (report.nearMisses.length > 0)
|
|
2120
|
+
report.warnings.push(`name looks like ${report.nearMisses.join("; ")}, check it is the package meant`);
|
|
2121
|
+
if (packument === undefined) {
|
|
2122
|
+
report.blocked = true;
|
|
2123
|
+
report.warnings.unshift(`${spec.name} is not on ${registry}, the name may be guessed`);
|
|
2124
|
+
return report;
|
|
2125
|
+
}
|
|
2126
|
+
const latest = packument["dist-tags"]?.latest;
|
|
2127
|
+
const version = resolve(packument, spec.request);
|
|
2128
|
+
const entry = version === undefined ? undefined : packument.versions?.[version];
|
|
2129
|
+
report.description = packument.description;
|
|
2130
|
+
report.license = licenseOf(entry?.license) ?? licenseOf(packument.license);
|
|
2131
|
+
report.repository = repositoryOf(packument);
|
|
2132
|
+
report.latest = latest === undefined ? undefined : { version: latest, published: packument.time?.[latest] };
|
|
2133
|
+
report.safe = safeRelease(packument, now, minAgeDays);
|
|
2134
|
+
report.version = version;
|
|
2135
|
+
report.published = version === undefined ? undefined : packument.time?.[version];
|
|
2136
|
+
report.installScripts = installScriptsOf(entry);
|
|
2137
|
+
report.deprecated = entry?.deprecated;
|
|
2138
|
+
if (version === undefined) {
|
|
2139
|
+
report.blocked = true;
|
|
2140
|
+
report.warnings.push(`no version of ${spec.name} matches ${spec.request}`);
|
|
2141
|
+
return report;
|
|
2142
|
+
}
|
|
2143
|
+
const age = ageDays(report.published, now);
|
|
2144
|
+
const kept = new Set(report.advisories.map((each) => each.id));
|
|
2145
|
+
report.fixes = report.safe?.version === version ? [] : (input.safeAdvisories ?? []).filter((each) => !kept.has(each.id));
|
|
2146
|
+
if (age === undefined) {
|
|
2147
|
+
const isBlocking = minAgeDays > 0 && registry === PUBLIC_HOST;
|
|
2148
|
+
report.blocked ||= isBlocking;
|
|
2149
|
+
report.warnings.push(`${registry} gives no publish date for ${version}, its age cannot be checked${isBlocking ? " and it is refused" : ""}`);
|
|
2150
|
+
} else if (age < minAgeDays && report.fixes.length > 0) {
|
|
2151
|
+
report.warnings.push(`${version} was published ${daysAgo(age)} ago, under ${minAgeDays} days, but it fixes ${report.fixes.map((each) => `${each.ghsa ?? each.id} (${each.severity})`).join(", ")} that ${report.safe?.version} has, so its age does not hold it back`);
|
|
2152
|
+
} else if (age < minAgeDays) {
|
|
2153
|
+
report.blocked = true;
|
|
2154
|
+
report.warnings.push(`${version} was published ${daysAgo(age)} ago, under ${minAgeDays} days${report.safe === undefined ? ", and no older stable version exists" : `, use ${spec.name}@${report.safe.version}`}`);
|
|
2155
|
+
}
|
|
2156
|
+
const scripts = Object.keys(report.installScripts);
|
|
2157
|
+
if (scripts.length > 0)
|
|
2158
|
+
report.warnings.push(`${version} runs ${scripts.join(", ")} at install`);
|
|
2159
|
+
if (report.deprecated !== undefined)
|
|
2160
|
+
report.warnings.push(`${version} is deprecated: ${report.deprecated}`);
|
|
2161
|
+
if (input.licenses !== undefined) {
|
|
2162
|
+
const isMissing = report.license === undefined || report.license === "";
|
|
2163
|
+
if (isMissing) {
|
|
2164
|
+
report.blocked = true;
|
|
2165
|
+
report.warnings.push(`${version} declares no licence, and the allowlist needs one`);
|
|
2166
|
+
} else if (!isLicenseAllowed(report.license ?? "", input.licenses)) {
|
|
2167
|
+
report.blocked = true;
|
|
2168
|
+
report.warnings.push(`licence ${report.license} is not in the allowlist (${input.licenses.join(", ")})`);
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
if (input.blockSeverity !== undefined) {
|
|
2172
|
+
const blocking = filterAdvisories(report.advisories, input.blockSeverity);
|
|
2173
|
+
if (blocking.length > 0) {
|
|
2174
|
+
report.blocked = true;
|
|
2175
|
+
report.warnings.push(`${version} has ${blocking.length} advisor${blocking.length === 1 ? "y" : "ies"} at ${input.blockSeverity} or above: ${blocking.map((each) => each.ghsa ?? each.id).join(", ")}`);
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
return report;
|
|
2179
|
+
}
|
|
2180
|
+
var DEFAULT_MIN_AGE_DAYS = 14, DAY = 86400000, PUBLIC_HOST, INSTALL_SCRIPTS, GIT_PREFIX, VERSION_SEPARATOR;
|
|
2181
|
+
var init_analyze = __esm(() => {
|
|
2182
|
+
init_advisories();
|
|
2183
|
+
init_licenses();
|
|
2184
|
+
init_nearmiss();
|
|
2185
|
+
init_registry();
|
|
2186
|
+
init_semver();
|
|
2187
|
+
PUBLIC_HOST = new URL(PUBLIC_REGISTRY).host;
|
|
2188
|
+
INSTALL_SCRIPTS = ["preinstall", "install", "postinstall"];
|
|
2189
|
+
GIT_PREFIX = /^git\+/;
|
|
2190
|
+
VERSION_SEPARATOR = /(?<=.)@/;
|
|
2191
|
+
});
|
|
2192
|
+
|
|
2193
|
+
// src/commands/check.ts
|
|
2194
|
+
var exports_check = {};
|
|
2195
|
+
__export(exports_check, {
|
|
2196
|
+
check: () => check,
|
|
2197
|
+
checkPackage: () => checkPackage
|
|
2198
|
+
});
|
|
2199
|
+
async function checkPackage(text, context) {
|
|
2200
|
+
const spec = parseSpec(text);
|
|
2201
|
+
const registry = registryFor(spec.name, context.configs);
|
|
2202
|
+
const packument = await fetchPackument(spec.name, registry, context.fetcher);
|
|
2203
|
+
const downloads = packument !== undefined && isPublic(registry) ? await fetchDownloads(spec.name, context.fetcher) : undefined;
|
|
2204
|
+
const input = { spec, packument, downloads, registry: new URL(registry.url).host, now: context.now, minAgeDays: context.minAgeDays, licenses: context.settings?.licenses };
|
|
2205
|
+
const report = analyze(input);
|
|
2206
|
+
const blockSeverity = context.settings?.blockSeverity ?? DEFAULT_BLOCK_SEVERITY;
|
|
2207
|
+
if (report.version === undefined)
|
|
2208
|
+
return report;
|
|
2209
|
+
const safe = report.safe?.version;
|
|
2210
|
+
const { found, unavailable, isUnsupported } = await fetchAdvisories({ [spec.name]: safe === undefined || safe === report.version ? [report.version] : [report.version, safe] }, registry, context.fetcher);
|
|
2211
|
+
if (unavailable !== undefined && isUnsupported !== true)
|
|
2212
|
+
return unreachable(unavailable);
|
|
2213
|
+
const checked = analyze({ ...input, blockSeverity, advisories: advisoriesFor(found[spec.name], report.version), safeAdvisories: safe === undefined ? [] : filterAdvisories(advisoriesFor(found[spec.name], safe), blockSeverity) });
|
|
2214
|
+
if (unavailable !== undefined)
|
|
2215
|
+
checked.warnings.push(`${unavailable}, so its known advisories are not checked`);
|
|
2216
|
+
return checked;
|
|
2217
|
+
}
|
|
2218
|
+
function when(release, now) {
|
|
2219
|
+
return release?.published === undefined ? "" : `, published ${formatAge(release.published, now)} (${release.published.slice(0, 10)})`;
|
|
2220
|
+
}
|
|
2221
|
+
function render(report, now = Date.now()) {
|
|
2222
|
+
if (!report.exists)
|
|
2223
|
+
return [report.name, ...report.warnings.map((warning) => ` warning: ${warning}`)].join(`
|
|
2224
|
+
`);
|
|
2225
|
+
const asked = report.requested === undefined ? "" : ` (asked for ${report.requested})`;
|
|
2226
|
+
const rows = [
|
|
2227
|
+
["version", report.version === undefined ? `none${asked}` : `${report.version}${asked}${when(report, now)}`],
|
|
2228
|
+
["latest", report.latest === undefined ? "-" : `${report.latest.version}${when(report.latest, now)}`],
|
|
2229
|
+
["safe", report.safe === undefined ? "-" : `${report.safe.version}${when(report.safe, now)}`],
|
|
2230
|
+
["downloads", report.downloads === undefined ? "-" : `${report.downloads.toLocaleString("en-US")} last week`],
|
|
2231
|
+
["license", report.license ?? "-"],
|
|
2232
|
+
["repository", report.repository ?? "-"],
|
|
2233
|
+
...Object.entries(report.installScripts).map(([name, command]) => [name, command])
|
|
2234
|
+
];
|
|
2235
|
+
return [
|
|
2236
|
+
`${report.name}${report.description === undefined ? "" : `: ${report.description}`}`,
|
|
2237
|
+
table(rows.map(([key, value]) => [` ${key}`, value ?? ""])),
|
|
2238
|
+
...report.warnings.map((warning) => ` warning: ${warning}`)
|
|
2239
|
+
].join(`
|
|
2240
|
+
`);
|
|
2241
|
+
}
|
|
2242
|
+
async function check(args) {
|
|
2243
|
+
const parsed = parse(args, usage, options);
|
|
2244
|
+
const { values, positionals } = parsed;
|
|
2245
|
+
if (positionals.length === 0)
|
|
2246
|
+
fail(`a package name is needed
|
|
2247
|
+
|
|
2248
|
+
${usage}`);
|
|
2249
|
+
const context = { configs: await loadConfigs(), settings: await loadSettings(), minAgeDays: wholeNumber(values["min-age"], "min-age", DEFAULT_MIN_AGE_DAYS, 0) };
|
|
2250
|
+
const reports = await Promise.all(positionals.map(async (text) => checkPackage(text, context)));
|
|
2251
|
+
if (values.json === true)
|
|
2252
|
+
printJson(reports.length === 1 ? reports[0] : reports);
|
|
2253
|
+
else
|
|
2254
|
+
console.log(reports.map((report) => render(report)).join(`
|
|
2255
|
+
|
|
2256
|
+
`));
|
|
2257
|
+
return reports.some((report) => report.blocked) ? 1 : 0;
|
|
2258
|
+
}
|
|
2259
|
+
var usage = `pkg [check] <name>[@version]...
|
|
2260
|
+
|
|
2261
|
+
Checks npm packages before they are added: whether the name exists, the latest and the newest version at least two weeks old, weekly downloads, licence, repository, install scripts and a near miss of a popular name.
|
|
2262
|
+
|
|
2263
|
+
A \`.pkgrc.json\` (or ~/.config/pkg/config.json) with \`licenses\` (SPDX ids) refuses a licence outside the list or a missing one, and \`blockSeverity\` (low, moderate, high, critical; high when unset) refuses a version with an advisory at that level or above.
|
|
2264
|
+
|
|
2265
|
+
Exits 0 when every package passes, 1 when one is blocked (missing, the version asked for is under the minimum age or has no date, its licence is outside the allowlist or an advisory reaches the threshold), 2 when it could not check (the registry unreachable, slow or answering badly, a broken .pkgrc.json, bunfig.toml or .npmrc) or on a usage error.`, options;
|
|
2266
|
+
var init_check = __esm(() => {
|
|
2267
|
+
init_src();
|
|
2268
|
+
init_advisories();
|
|
2269
|
+
init_analyze();
|
|
2270
|
+
init_config2();
|
|
2271
|
+
init_registry();
|
|
2272
|
+
options = {
|
|
2273
|
+
json: jsonOption(),
|
|
2274
|
+
"min-age": { type: "string", description: `days a version must be old (${DEFAULT_MIN_AGE_DAYS})` }
|
|
2275
|
+
};
|
|
2276
|
+
});
|
|
2277
|
+
|
|
2278
|
+
// src/lockfile.ts
|
|
2279
|
+
function split(resolution) {
|
|
2280
|
+
const at = resolution.search(VERSION_SEPARATOR2);
|
|
2281
|
+
if (at === -1)
|
|
2282
|
+
return;
|
|
2283
|
+
const target = resolution.slice(at + 1);
|
|
2284
|
+
if (target.startsWith(NPM_ALIAS))
|
|
2285
|
+
return split(target.slice(NPM_ALIAS.length));
|
|
2286
|
+
return NOT_REGISTRY.test(target) ? undefined : { name: resolution.slice(0, at), version: target };
|
|
2287
|
+
}
|
|
2288
|
+
function parseBunLock(text) {
|
|
2289
|
+
const lock = Bun.JSONC.parse(text);
|
|
2290
|
+
const seen = new Map;
|
|
2291
|
+
for (const entry of Object.values(lock?.packages ?? {})) {
|
|
2292
|
+
const resolution = entry[0];
|
|
2293
|
+
if (typeof resolution !== "string")
|
|
2294
|
+
continue;
|
|
2295
|
+
const locked = split(resolution);
|
|
2296
|
+
if (locked !== undefined)
|
|
2297
|
+
seen.set(`${locked.name}@${locked.version}`, locked);
|
|
2298
|
+
}
|
|
2299
|
+
return [...seen.values()].sort((a, b) => a.name.localeCompare(b.name) || Bun.semver.order(a.version, b.version));
|
|
2300
|
+
}
|
|
2301
|
+
var NOT_REGISTRY, VERSION_SEPARATOR2, NPM_ALIAS = "npm:";
|
|
2302
|
+
var init_lockfile = __esm(() => {
|
|
2303
|
+
NOT_REGISTRY = /^(?:workspace|link|file|github|git|http|https):|^[\w.-]+\/[\w.-]+$/;
|
|
2304
|
+
VERSION_SEPARATOR2 = /(?<=.)@/;
|
|
2305
|
+
});
|
|
2306
|
+
|
|
2307
|
+
// src/commands/audit.ts
|
|
2308
|
+
var exports_audit = {};
|
|
2309
|
+
__export(exports_audit, {
|
|
2310
|
+
audit: () => audit
|
|
2311
|
+
});
|
|
2312
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
2313
|
+
import process9 from "process";
|
|
2314
|
+
function hasFinding(audited) {
|
|
2315
|
+
return audited.blocked || audited.warnings.length > 0 || audited.advisories.length > 0;
|
|
2316
|
+
}
|
|
2317
|
+
async function auditPackages(packages, context) {
|
|
2318
|
+
const packuments = new Map;
|
|
2319
|
+
const lookup = async (name, registry) => {
|
|
2320
|
+
const key = `${registry.url}|${name}`;
|
|
2321
|
+
if (!packuments.has(key))
|
|
2322
|
+
packuments.set(key, fetchPackument(name, registry, context.fetcher));
|
|
2323
|
+
return packuments.get(key);
|
|
2324
|
+
};
|
|
2325
|
+
const looked = [];
|
|
2326
|
+
for (let start = 0;start < packages.length; start += BATCH) {
|
|
2327
|
+
looked.push(...await Promise.all(packages.slice(start, start + BATCH).map(async ({ name, version }) => {
|
|
2328
|
+
const registry = registryFor(name, context.configs);
|
|
2329
|
+
const input = { spec: { name, request: version }, packument: await lookup(name, registry), registry: new URL(registry.url).host, now: context.now, minAgeDays: context.minAgeDays, licenses: context.settings.licenses };
|
|
2330
|
+
return { name, version, registry, input, safe: analyze(input).safe?.version };
|
|
2331
|
+
})));
|
|
2332
|
+
}
|
|
2333
|
+
const registries = new Map;
|
|
2334
|
+
for (const { name, version, registry, safe } of looked) {
|
|
2335
|
+
const group = registries.get(registry.url) ?? { registry, versions: {} };
|
|
2336
|
+
group.versions[name] = [...group.versions[name] ?? [], version, ...safe === undefined || safe === version ? [] : [safe]];
|
|
2337
|
+
registries.set(registry.url, group);
|
|
2338
|
+
}
|
|
2339
|
+
const advisories = {};
|
|
2340
|
+
const unavailable = [];
|
|
2341
|
+
for (const { registry, versions } of registries.values()) {
|
|
2342
|
+
const fetched = await fetchAdvisories(versions, registry, context.fetcher);
|
|
2343
|
+
Object.assign(advisories, fetched.found);
|
|
2344
|
+
if (fetched.unavailable !== undefined)
|
|
2345
|
+
unavailable.push(fetched.unavailable);
|
|
2346
|
+
}
|
|
2347
|
+
const blockSeverity = context.settings.blockSeverity ?? DEFAULT_BLOCK_SEVERITY;
|
|
2348
|
+
const audited = looked.map(({ name, version, input, safe }) => {
|
|
2349
|
+
const found = filterAdvisories(advisoriesFor(advisories[name], version), context.level, context.ignore);
|
|
2350
|
+
const safeAdvisories = safe === undefined ? [] : filterAdvisories(advisoriesFor(advisories[name], safe), blockSeverity, context.ignore);
|
|
2351
|
+
const report = analyze({ ...input, advisories: advisoriesFor(advisories[name], version), safeAdvisories });
|
|
2352
|
+
return { name, version, license: report.license, blocked: report.blocked || found.length > 0, warnings: report.warnings, advisories: found };
|
|
2353
|
+
});
|
|
2354
|
+
return { audited, unavailable };
|
|
2355
|
+
}
|
|
2356
|
+
function renderAudit(findings, total) {
|
|
2357
|
+
const blocks = findings.map(({ name, version, warnings, advisories }) => [
|
|
2358
|
+
`${name}@${version}`,
|
|
2359
|
+
...warnings.map((warning) => ` warning: ${warning}`),
|
|
2360
|
+
...advisories.map((each) => ` ${each.ghsa ?? each.id} ${each.severity}: ${each.title}${each.fixed === undefined ? "" : ` (fixed in ${each.fixed})`}`)
|
|
2361
|
+
].join(`
|
|
2362
|
+
`));
|
|
2363
|
+
return [...blocks, `${findings.length} of ${total} packages with a finding, ${findings.filter((each) => each.blocked).length} blocking`].join(`
|
|
2364
|
+
|
|
2365
|
+
`);
|
|
2366
|
+
}
|
|
2367
|
+
async function audit(args) {
|
|
2368
|
+
const { values, positionals: [asked] } = parse(args, usage2, options2, { positionals: ["[dir]"] });
|
|
2369
|
+
const level = values["audit-level"] ?? "low";
|
|
2370
|
+
if (!isSeverity(level))
|
|
2371
|
+
fail(`--audit-level takes ${SEVERITIES.join(", ")}, not ${level}`);
|
|
2372
|
+
const dir = resolve2(asked ?? process9.cwd());
|
|
2373
|
+
const lock = Bun.file(join2(dir, "bun.lock"));
|
|
2374
|
+
if (!await lock.exists())
|
|
2375
|
+
fail(`no bun.lock in ${dir}`);
|
|
2376
|
+
const packages = parseBunLock(await lock.text());
|
|
2377
|
+
const context = {
|
|
2378
|
+
configs: await loadConfigs(dir),
|
|
2379
|
+
settings: await loadSettings(dir),
|
|
2380
|
+
minAgeDays: wholeNumber(values["min-age"], "min-age", DEFAULT_MIN_AGE_DAYS, 0),
|
|
2381
|
+
level,
|
|
2382
|
+
ignore: values.ignore ?? []
|
|
2383
|
+
};
|
|
2384
|
+
const { audited, unavailable } = await auditPackages(packages, context);
|
|
2385
|
+
const findings = audited.filter(hasFinding);
|
|
2386
|
+
if (values.json === true)
|
|
2387
|
+
printJson(findings);
|
|
2388
|
+
else
|
|
2389
|
+
console.log(renderAudit(findings, packages.length));
|
|
2390
|
+
for (const reason of unavailable)
|
|
2391
|
+
warn(`${reason}, so its advisories are not checked`);
|
|
2392
|
+
if (findings.some((each) => each.blocked))
|
|
2393
|
+
return 1;
|
|
2394
|
+
return unavailable.length > 0 ? 2 : 0;
|
|
2395
|
+
}
|
|
2396
|
+
var usage2 = `pkg audit [dir]
|
|
2397
|
+
|
|
2398
|
+
Reads the bun.lock in the folder (the current one by default) and runs on every registry package it pins the checks \`pkg check\` runs before an add: age, install scripts, a deprecated version, a near miss of a popular name, and the licence allowlist of the pkg config. It also lists the known advisories of each version, with the GHSA, the severity and the fixed version, from the registry's bulk advisory endpoint, the one \`bun audit\` reads.
|
|
2399
|
+
Findings are grouped per package, each registry package looked up once per run.
|
|
2400
|
+
|
|
2401
|
+
Exits 0 when nothing blocks, 1 when a package is missing, too fresh or outside the licence allowlist, or an advisory reaches --audit-level, 2 when the registry could not be reached or answered badly (a warning says which, and nothing is reported as clean), on a usage error or without a bun.lock.`, options2, BATCH = 8;
|
|
2402
|
+
var init_audit = __esm(() => {
|
|
2403
|
+
init_src();
|
|
2404
|
+
init_advisories();
|
|
2405
|
+
init_analyze();
|
|
2406
|
+
init_config2();
|
|
2407
|
+
init_lockfile();
|
|
2408
|
+
init_registry();
|
|
2409
|
+
options2 = {
|
|
2410
|
+
json: jsonOption("[{name, version, license, blocked, warnings, advisories}] for the packages with a finding"),
|
|
2411
|
+
"min-age": { type: "string", description: `days a version must be old (${DEFAULT_MIN_AGE_DAYS})` },
|
|
2412
|
+
"audit-level": { type: "string", description: "lowest advisory severity listed and failing: low, moderate, high, critical (low)" },
|
|
2413
|
+
ignore: { type: "string", multiple: true, description: "an advisory skipped by GHSA or numeric id, repeatable" }
|
|
2414
|
+
};
|
|
2415
|
+
});
|
|
2416
|
+
|
|
2417
|
+
// ../kit/src/shell.ts
|
|
2418
|
+
function wrapper(short = "", long = [], operands = 0) {
|
|
2419
|
+
return { short, long, operands };
|
|
2420
|
+
}
|
|
2421
|
+
var SEPARATORS2, PLAIN_BREAKERS, GLOB_CHARS, COMMENT_PREFIXES, DOUBLE_QUOTED_ESCAPES, KEYWORDS, SHELLS, COMMAND_STRING_PROGRAMS, SHELL_VALUE_OPTIONS, PRINTERS, FIND_EXEC, WRAPPERS;
|
|
2422
|
+
var init_shell = __esm(() => {
|
|
2423
|
+
SEPARATORS2 = new Set([`
|
|
2424
|
+
`, ";", "|"]);
|
|
2425
|
+
PLAIN_BREAKERS = new Set(["<", ">", "(", ")", "&", "|"]);
|
|
2426
|
+
GLOB_CHARS = new Set(["*", "?", "["]);
|
|
2427
|
+
COMMENT_PREFIXES = new Set([";", "&", "|", "(", ")"]);
|
|
2428
|
+
DOUBLE_QUOTED_ESCAPES = new Set(["$", "`", '"', "\\"]);
|
|
2429
|
+
KEYWORDS = new Set(["then", "do", "else", "if", "elif", "while", "until", "!", "{", "}"]);
|
|
2430
|
+
SHELLS = new Set(["sh", "bash", "zsh", "dash", "ash", "ksh"]);
|
|
2431
|
+
COMMAND_STRING_PROGRAMS = new Set([...SHELLS, "su", "runuser"]);
|
|
2432
|
+
SHELL_VALUE_OPTIONS = new Set(["-o", "-O", "--rcfile", "--init-file"]);
|
|
2433
|
+
PRINTERS = new Set(["echo", "printf"]);
|
|
2434
|
+
FIND_EXEC = new Set(["-exec", "-execdir", "-ok", "-okdir"]);
|
|
2435
|
+
WRAPPERS = new Map([
|
|
2436
|
+
["command", wrapper()],
|
|
2437
|
+
["builtin", wrapper()],
|
|
2438
|
+
["nohup", wrapper()],
|
|
2439
|
+
["setsid", wrapper()],
|
|
2440
|
+
["busybox", wrapper()],
|
|
2441
|
+
["exec", wrapper("a")],
|
|
2442
|
+
["time", wrapper("fo", ["--format", "--output"])],
|
|
2443
|
+
["env", wrapper("uCS", ["--unset", "--chdir", "--split-string", "--argv0"])],
|
|
2444
|
+
["sudo", wrapper("ughpCTrtUDR", ["--user", "--group", "--host", "--prompt", "--close-from", "--command-timeout", "--role", "--type", "--other-user", "--chdir", "--chroot"])],
|
|
2445
|
+
["doas", wrapper("uC")],
|
|
2446
|
+
["timeout", wrapper("sk", ["--signal", "--kill-after"], 1)],
|
|
2447
|
+
["nice", wrapper("n", ["--adjustment"])],
|
|
2448
|
+
["ionice", wrapper("cnpPu", ["--class", "--classdata", "--pid", "--pgid", "--uid"])],
|
|
2449
|
+
["stdbuf", wrapper("ioe", ["--input", "--output", "--error"])],
|
|
2450
|
+
["chroot", wrapper("", ["--userspec", "--groups"], 1)],
|
|
2451
|
+
["xargs", wrapper("IndsEaPL", ["--max-args", "--max-procs", "--max-chars", "--delimiter", "--arg-file", "--eof", "--max-lines", "--process-slot-var"])]
|
|
2452
|
+
]);
|
|
2453
|
+
});
|
|
2454
|
+
|
|
2455
|
+
// src/pin.ts
|
|
2456
|
+
function actions(byAction) {
|
|
2457
|
+
return new Map(Object.entries(byAction).flatMap(([action, names]) => names.map((name) => [name, action])));
|
|
2458
|
+
}
|
|
2459
|
+
var LOCKFILES, ACTIONS, OPTION_FLAGS, DIR_FLAGS, VALUE_FLAGS;
|
|
2460
|
+
var init_pin = __esm(() => {
|
|
2461
|
+
init_shell();
|
|
2462
|
+
LOCKFILES = [
|
|
2463
|
+
["bun.lock", "bun"],
|
|
2464
|
+
["bun.lockb", "bun"],
|
|
2465
|
+
["pnpm-lock.yaml", "pnpm"],
|
|
2466
|
+
["yarn.lock", "yarn"],
|
|
2467
|
+
["package-lock.json", "npm"]
|
|
2468
|
+
];
|
|
2469
|
+
ACTIONS = {
|
|
2470
|
+
bun: actions({ install: ["install", "i"], add: ["add", "a"], remove: ["remove", "rm"], update: ["update"] }),
|
|
2471
|
+
pnpm: actions({ install: ["install", "i"], add: ["add"], remove: ["remove", "rm"], update: ["update", "up"] }),
|
|
2472
|
+
yarn: new Map([...actions({ install: ["", "install"], add: ["add"], remove: ["remove"], update: ["upgrade"] }), ["upgrade-interactive", null], ["import", null]]),
|
|
2473
|
+
npm: actions({
|
|
2474
|
+
install: ["install", "i", "in", "ins", "inst", "insta", "instal", "isnt", "isnta", "isntal", "isntall"],
|
|
2475
|
+
add: ["add"],
|
|
2476
|
+
frozen: ["ci", "clean-install", "ic", "install-clean", "isntall-clean"],
|
|
2477
|
+
remove: ["uninstall", "unlink", "remove", "rm", "r", "un"],
|
|
2478
|
+
update: ["update", "u", "up", "upgrade", "udpate"]
|
|
2479
|
+
})
|
|
2480
|
+
};
|
|
2481
|
+
OPTION_FLAGS = new Map([
|
|
2482
|
+
["-D", "dev"],
|
|
2483
|
+
["--save-dev", "dev"],
|
|
2484
|
+
["--dev", "dev"],
|
|
2485
|
+
["-E", "exact"],
|
|
2486
|
+
["--save-exact", "exact"],
|
|
2487
|
+
["--exact", "exact"]
|
|
2488
|
+
]);
|
|
2489
|
+
DIR_FLAGS = new Set(["--cwd", "-C", "--dir", "--prefix"]);
|
|
2490
|
+
VALUE_FLAGS = new Set([...DIR_FLAGS, "--filter", "-F"]);
|
|
2491
|
+
});
|
|
2492
|
+
|
|
2493
|
+
// src/consumers.ts
|
|
2494
|
+
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
2495
|
+
import { dirname as dirname2, join as join3, relative } from "path";
|
|
2496
|
+
function packageFiles(dir, depth, found) {
|
|
2497
|
+
let entries;
|
|
2498
|
+
try {
|
|
2499
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
2500
|
+
} catch {
|
|
2501
|
+
return found;
|
|
2502
|
+
}
|
|
2503
|
+
for (const entry of entries) {
|
|
2504
|
+
if (entry.isFile() && entry.name === "package.json")
|
|
2505
|
+
found.push(join3(dir, entry.name));
|
|
2506
|
+
else if (entry.isDirectory() && depth < MAX_DEPTH && !entry.name.startsWith(".") && !SKIPPED.has(entry.name))
|
|
2507
|
+
packageFiles(join3(dir, entry.name), depth + 1, found);
|
|
2508
|
+
}
|
|
2509
|
+
return found;
|
|
2510
|
+
}
|
|
2511
|
+
function managerFor(dir, root) {
|
|
2512
|
+
for (let at = dir;; at = dirname2(at)) {
|
|
2513
|
+
const lockfile = LOCKFILES.find(([file]) => existsSync(join3(at, file)));
|
|
2514
|
+
if (lockfile !== undefined)
|
|
2515
|
+
return lockfile[1];
|
|
2516
|
+
if (at === root || at === dirname2(at))
|
|
2517
|
+
return "bun";
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
function findConsumers(name, root) {
|
|
2521
|
+
const consumers = [];
|
|
2522
|
+
for (const path of packageFiles(root, 0, []).sort()) {
|
|
2523
|
+
let manifest;
|
|
2524
|
+
try {
|
|
2525
|
+
manifest = JSON.parse(readFileSync(path, "utf8"));
|
|
2526
|
+
} catch {
|
|
2527
|
+
continue;
|
|
2528
|
+
}
|
|
2529
|
+
const kind = KINDS.find((each) => typeof manifest[each]?.[name] === "string");
|
|
2530
|
+
const spec = kind === undefined ? undefined : manifest[kind]?.[name];
|
|
2531
|
+
if (kind !== undefined && spec !== undefined)
|
|
2532
|
+
consumers.push({ dir: relative(root, dirname2(path)) || ".", path, kind, spec, manager: managerFor(dirname2(path), root) });
|
|
2533
|
+
}
|
|
2534
|
+
return consumers;
|
|
2535
|
+
}
|
|
2536
|
+
function isLocal(consumer) {
|
|
2537
|
+
return LOCAL_SPEC.test(consumer.spec);
|
|
2538
|
+
}
|
|
2539
|
+
function addCommand(consumer, name, version) {
|
|
2540
|
+
return ["bun", "add", ...KIND_FLAGS[consumer.kind], "--exact", "--no-cache", `${name}@${version}`];
|
|
2541
|
+
}
|
|
2542
|
+
var KINDS, SKIPPED, MAX_DEPTH = 5, LOCAL_SPEC, KIND_FLAGS;
|
|
2543
|
+
var init_consumers = __esm(() => {
|
|
2544
|
+
init_pin();
|
|
2545
|
+
KINDS = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"];
|
|
2546
|
+
SKIPPED = new Set(["node_modules", "dist", "build", "vendor", "target", "coverage"]);
|
|
2547
|
+
LOCAL_SPEC = /[:/]/;
|
|
2548
|
+
KIND_FLAGS = { dependencies: [], devDependencies: ["--dev"], optionalDependencies: ["--optional"], peerDependencies: ["--peer"] };
|
|
2549
|
+
});
|
|
2550
|
+
|
|
2551
|
+
// src/commands/bump.ts
|
|
2552
|
+
var exports_bump = {};
|
|
2553
|
+
__export(exports_bump, {
|
|
2554
|
+
ROOT_OPTION: () => ROOT_OPTION,
|
|
2555
|
+
bump: () => bump
|
|
2556
|
+
});
|
|
2557
|
+
import { existsSync as existsSync2 } from "fs";
|
|
2558
|
+
import { homedir as homedir2 } from "os";
|
|
2559
|
+
import { dirname as dirname3, join as join4, relative as relative2 } from "path";
|
|
2560
|
+
async function lookup(name, registry, fetcher) {
|
|
2561
|
+
try {
|
|
2562
|
+
return { packument: await fetchPackument(name, registry, fetcher) };
|
|
2563
|
+
} catch (error) {
|
|
2564
|
+
if (error instanceof Exit && error.code === 2)
|
|
2565
|
+
return { error: error.message };
|
|
2566
|
+
throw error;
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
async function servedVersion(name, version, settings) {
|
|
2570
|
+
if (!isValidName(name))
|
|
2571
|
+
fail(`${name} is not a valid npm package name`);
|
|
2572
|
+
if (version !== undefined && !EXACT_VERSION.test(version))
|
|
2573
|
+
fail(`bump takes an exact version, not ${version}: leave it out for the latest`);
|
|
2574
|
+
const registry = registryFor(name, settings.configs);
|
|
2575
|
+
const host = new URL(registry.url).host;
|
|
2576
|
+
const started = Date.now();
|
|
2577
|
+
const region = liveRegion((spinner) => [`${spinner} waiting for ${host} to serve ${name}@${version} ${formatElapsed(Date.now() - started)}`]);
|
|
2578
|
+
let lastError = "";
|
|
2579
|
+
try {
|
|
2580
|
+
for (;; ) {
|
|
2581
|
+
const looked = await lookup(name, registry, settings.fetcher);
|
|
2582
|
+
if ("error" in looked) {
|
|
2583
|
+
lastError = looked.error;
|
|
2584
|
+
} else {
|
|
2585
|
+
const latest = looked.packument?.["dist-tags"]?.latest;
|
|
2586
|
+
if (looked.packument === undefined)
|
|
2587
|
+
fail(`${host} has no ${name}`, 1);
|
|
2588
|
+
if (version === undefined && latest === undefined)
|
|
2589
|
+
fail(`${host} has no ${name}`, 1);
|
|
2590
|
+
if (version === undefined && latest !== undefined)
|
|
2591
|
+
return latest;
|
|
2592
|
+
if (version !== undefined && looked.packument.versions?.[version] !== undefined)
|
|
2593
|
+
return version;
|
|
2594
|
+
}
|
|
2595
|
+
if (Date.now() - started >= settings.timeout)
|
|
2596
|
+
fail(`${host} does not serve ${name}@${version} after ${formatDuration(settings.timeout)}${lastError === "" ? "" : `, last error: ${lastError}`}`);
|
|
2597
|
+
region.redraw();
|
|
2598
|
+
await Bun.sleep(settings.poll ?? POLL);
|
|
2599
|
+
}
|
|
2600
|
+
} finally {
|
|
2601
|
+
region.stop();
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
async function vet(name, version, settings) {
|
|
2605
|
+
if (settings.isForced === true)
|
|
2606
|
+
return true;
|
|
2607
|
+
const report = await checkPackage(`${name}@${version}`, { configs: settings.configs, fetcher: settings.fetcher, minAgeDays: settings.minAgeDays ?? 0, settings: settings.pkgSettings });
|
|
2608
|
+
if (!report.blocked) {
|
|
2609
|
+
for (const warning of report.warnings)
|
|
2610
|
+
warn(`${name}@${version}`, warning);
|
|
2611
|
+
return true;
|
|
2612
|
+
}
|
|
2613
|
+
for (const warning of report.warnings)
|
|
2614
|
+
problem(`${name}@${version} is refused`, warning);
|
|
2615
|
+
problem(`${name}@${version} is refused`, "no consumer was touched, --force bumps it anyway");
|
|
2616
|
+
return false;
|
|
2617
|
+
}
|
|
2618
|
+
function lockfileOf(dir, root) {
|
|
2619
|
+
for (let at = dir;; at = dirname3(at)) {
|
|
2620
|
+
const found = ["bun.lock", "bun.lockb"].find((file) => existsSync2(join4(at, file)));
|
|
2621
|
+
if (found !== undefined)
|
|
2622
|
+
return relative2(dir, join4(at, found));
|
|
2623
|
+
if (at === root || at === dirname3(at))
|
|
2624
|
+
return;
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
async function hasUncommittedChanges(where, root, run) {
|
|
2628
|
+
const lockfile = lockfileOf(where, root);
|
|
2629
|
+
const status = await run(["git", "status", "--porcelain", "--", "package.json", ...lockfile === undefined ? [] : [lockfile]], where);
|
|
2630
|
+
return status.code === 0 && status.text.trim() !== "";
|
|
2631
|
+
}
|
|
2632
|
+
async function checkAndCommit(name, version, where, root, run) {
|
|
2633
|
+
const checked = await run(["check"], where);
|
|
2634
|
+
if (checked.code !== 0)
|
|
2635
|
+
return `check exited ${checked.code}: ${checked.text.trim().split(`
|
|
2636
|
+
`).at(-1) ?? ""}`;
|
|
2637
|
+
const lockfile = lockfileOf(where, root);
|
|
2638
|
+
const committed = await run(["gc", `chore(deps): bump ${name} to ${version}`, "--", "package.json", ...lockfile === undefined ? [] : [lockfile]], where);
|
|
2639
|
+
return committed.code === 0 ? undefined : `gc exited ${committed.code}: ${committed.text.trim().split(`
|
|
2640
|
+
`).at(-1) ?? ""}`;
|
|
2641
|
+
}
|
|
2642
|
+
async function bumpConsumers(name, version, settings) {
|
|
2643
|
+
const found = findConsumers(name, settings.root);
|
|
2644
|
+
const consumers = found.filter((each) => !isLocal(each));
|
|
2645
|
+
const local = found.length - consumers.length;
|
|
2646
|
+
const run = settings.run ?? (async (argv, cwd) => runCommand(argv, { cwd }));
|
|
2647
|
+
const committed = [];
|
|
2648
|
+
const failing = [];
|
|
2649
|
+
const skipped = [];
|
|
2650
|
+
let isClean = true;
|
|
2651
|
+
if (found.length === 0)
|
|
2652
|
+
note(`nothing under ${settings.root} depends on ${name}`);
|
|
2653
|
+
if (local > 0)
|
|
2654
|
+
note(`${local} non-registry dependenc${local === 1 ? "y" : "ies"} (workspace:, file:, git, URL, alias, catalog:)`, "left as they are");
|
|
2655
|
+
for (const consumer of consumers) {
|
|
2656
|
+
const argv = addCommand(consumer, name, version);
|
|
2657
|
+
const where = join4(settings.root, consumer.dir);
|
|
2658
|
+
if (consumer.kind === "peerDependencies") {
|
|
2659
|
+
skipped.push(consumer.dir);
|
|
2660
|
+
note(consumer.dir, `peer range ${consumer.spec}, left as it is`);
|
|
2661
|
+
} else if (consumer.spec === version) {
|
|
2662
|
+
skipped.push(consumer.dir);
|
|
2663
|
+
note(consumer.dir, `already on ${version}`);
|
|
2664
|
+
} else if (consumer.manager !== "bun") {
|
|
2665
|
+
skipped.push(consumer.dir);
|
|
2666
|
+
warn(consumer.dir, `${consumer.spec}, its lockfile pins ${consumer.manager}: put ${version} in by hand`);
|
|
2667
|
+
} else if (settings.isDryRun === true) {
|
|
2668
|
+
note(consumer.dir, `would run ${[argv.join(" "), ...settings.isAll === true ? ["check", `gc 'chore(deps): bump ${name} to ${version}'`] : []].join(", then ")}`);
|
|
2669
|
+
} else if (settings.isAll === true && await hasUncommittedChanges(where, settings.root, run)) {
|
|
2670
|
+
isClean = false;
|
|
2671
|
+
failing.push(consumer.dir);
|
|
2672
|
+
problem(consumer.dir, "package.json or its lockfile has uncommitted changes, left alone so that gc does not commit them");
|
|
2673
|
+
} else {
|
|
2674
|
+
const ran = await run(argv, where);
|
|
2675
|
+
if (ran.code !== 0) {
|
|
2676
|
+
isClean = false;
|
|
2677
|
+
failing.push(consumer.dir);
|
|
2678
|
+
problem(consumer.dir, `${argv.join(" ")} exited ${ran.code}: ${ran.text.trim().split(`
|
|
2679
|
+
`).at(-1) ?? ""}`);
|
|
2680
|
+
} else if (settings.isAll !== true) {
|
|
2681
|
+
ok(consumer.dir, `${consumer.spec} -> ${version}`);
|
|
2682
|
+
} else {
|
|
2683
|
+
const failure = await checkAndCommit(name, version, where, settings.root, run);
|
|
2684
|
+
if (failure === undefined) {
|
|
2685
|
+
committed.push(consumer.dir);
|
|
2686
|
+
ok(consumer.dir, `${consumer.spec} -> ${version}, checked and committed`);
|
|
2687
|
+
} else {
|
|
2688
|
+
isClean = false;
|
|
2689
|
+
failing.push(consumer.dir);
|
|
2690
|
+
problem(consumer.dir, `${consumer.spec} -> ${version}, left uncommitted: ${failure}`);
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
if (settings.isAll === true && settings.isDryRun !== true)
|
|
2696
|
+
note("summary", `${committed.length} bumped and committed, ${failing.length} bumped and failing${failing.length > 0 ? ` (${failing.join(", ")})` : ""}, ${skipped.length + local} skipped`);
|
|
2697
|
+
return isClean;
|
|
2698
|
+
}
|
|
2699
|
+
async function bump(args) {
|
|
2700
|
+
const { values, positionals: [name, asked] } = parse(args, usage3, options3, { positionals: ["<name>", "[version]"] });
|
|
2701
|
+
const settings = {
|
|
2702
|
+
root: values.root ?? join4(homedir2(), "Workspace"),
|
|
2703
|
+
configs: await loadConfigs(),
|
|
2704
|
+
timeout: duration(values.timeout, "timeout", 10 * 60000),
|
|
2705
|
+
isDryRun: values["dry-run"] === true,
|
|
2706
|
+
isAll: values["all-consumers"] === true,
|
|
2707
|
+
isForced: values.force === true,
|
|
2708
|
+
pkgSettings: await loadSettings(),
|
|
2709
|
+
minAgeDays: wholeNumber(values["min-age"], "min-age", 0, 0)
|
|
2710
|
+
};
|
|
2711
|
+
const version = await servedVersion(name, asked, settings);
|
|
2712
|
+
if (!await vet(name, version, settings))
|
|
2713
|
+
return 1;
|
|
2714
|
+
return await bumpConsumers(name, version, settings) ? 0 : 1;
|
|
2715
|
+
}
|
|
2716
|
+
var usage3 = `pkg bump <name> [version]
|
|
2717
|
+
|
|
2718
|
+
Waits until the registry serves the version (the latest when none is given, an exact version otherwise), vets it as \`pkg check\` does (advisories, licence allowlist, and a minimum age only when --min-age asks for one), then runs \`bun add --exact --no-cache\` in each folder under --root whose package.json depends on the package, the kind of dependency kept, a line per folder.
|
|
2719
|
+
A version the vetting blocks is refused before any folder is touched, unless --force is given.
|
|
2720
|
+
A dependency that is not a registry version (workspace:, link:, file:, git, a URL, an npm: alias, catalog:), a peer range, a folder already on the version and one whose lockfile pins another manager are left as they are, each said so.
|
|
2721
|
+
With --all-consumers a folder whose package.json or lockfile already has uncommitted changes is left alone, and each folder whose install went through then runs its own \`check\` (the check bin) and is committed with \`gc 'chore(deps): bump <name> to <version>' -- package.json <lockfile>\` only when that passes; a failing one is left uncommitted and listed in the summary with the skipped ones, and nothing is ever pushed.
|
|
2722
|
+
|
|
2723
|
+
Exits 0 when every install ran or was left as it is (with --all-consumers, and every check passed and every commit landed), 1 when the vetting refuses the version, an install, a check or a commit fails or the registry has no such package, 2 when the version never shows within the timeout (a registry that cannot be reached is retried until then) or on a usage error.`, ROOT_OPTION, options3, POLL = 5000;
|
|
2724
|
+
var init_bump = __esm(() => {
|
|
2725
|
+
init_src();
|
|
2726
|
+
init_progress();
|
|
2727
|
+
init_config2();
|
|
2728
|
+
init_consumers();
|
|
2729
|
+
init_registry();
|
|
2730
|
+
init_semver();
|
|
2731
|
+
init_check();
|
|
2732
|
+
ROOT_OPTION = { type: "string", description: "the folder holding the repositories (~/Workspace)" };
|
|
2733
|
+
options3 = {
|
|
2734
|
+
root: ROOT_OPTION,
|
|
2735
|
+
timeout: { type: "string", short: "t", description: "how long to wait for the registry (10m): 30s, 5m, 1h" },
|
|
2736
|
+
"all-consumers": { type: "boolean", description: "after each install run the folder's check and commit it through gc when it passes" },
|
|
2737
|
+
"dry-run": { type: "boolean", description: "print what would run, changing nothing" },
|
|
2738
|
+
force: { type: "boolean", description: "bump even when the version is blocked by the vetting" },
|
|
2739
|
+
"min-age": { type: "string", description: "days a version must be old (0: a bump adopts a release on purpose, often one just made)" }
|
|
2740
|
+
};
|
|
2741
|
+
});
|
|
2742
|
+
|
|
2743
|
+
// src/commands/consumers.ts
|
|
2744
|
+
var exports_consumers = {};
|
|
2745
|
+
__export(exports_consumers, {
|
|
2746
|
+
consumers: () => consumers
|
|
2747
|
+
});
|
|
2748
|
+
import { homedir as homedir3 } from "os";
|
|
2749
|
+
import { join as join5 } from "path";
|
|
2750
|
+
function consumers(args) {
|
|
2751
|
+
const { values, positionals: [name] } = parse(args, usage4, options4, { positionals: ["<name>"] });
|
|
2752
|
+
const root = values.root ?? join5(homedir3(), "Workspace");
|
|
2753
|
+
const { shown, footer } = capped(findConsumers(name, root), limitOf(values, CONSUMERS_LIMIT));
|
|
2754
|
+
if (values.json === true)
|
|
2755
|
+
printJson(shown);
|
|
2756
|
+
else if (shown.length === 0)
|
|
2757
|
+
console.log(`nothing under ${root} depends on ${name}`);
|
|
2758
|
+
else
|
|
2759
|
+
console.log([table([["FOLDER", "KIND", "VERSION", "MANAGER"], ...shown.map((each) => [each.dir, each.kind, each.spec, each.manager])], { header: true }), ...footer === undefined ? [] : [footer]].join(`
|
|
2760
|
+
`));
|
|
2761
|
+
return 0;
|
|
2762
|
+
}
|
|
2763
|
+
var usage4 = `pkg consumers <name>
|
|
2764
|
+
|
|
2765
|
+
Lists the folders under --root whose package.json depends on the package: the folder, the kind of dependency, the version it asks for and the manager its lockfile pins, 30 at most with the count of the rest after them (--limit <n>, --full for all; --json is never cut unless --limit is given).
|
|
2766
|
+
|
|
2767
|
+
Exits 0 when it listed them, 2 on a usage error.`, CONSUMERS_LIMIT = 30, options4;
|
|
2768
|
+
var init_consumers2 = __esm(() => {
|
|
2769
|
+
init_src();
|
|
2770
|
+
init_consumers();
|
|
2771
|
+
init_bump();
|
|
2772
|
+
options4 = {
|
|
2773
|
+
root: ROOT_OPTION,
|
|
2774
|
+
...limitOptions(CONSUMERS_LIMIT),
|
|
2775
|
+
json: jsonOption("[{dir, path, kind, spec, manager}]")
|
|
2776
|
+
};
|
|
2777
|
+
});
|
|
2778
|
+
|
|
2779
|
+
// src/cli.ts
|
|
2780
|
+
init_src();
|
|
2781
|
+
import process10 from "process";
|
|
2782
|
+
// package.json
|
|
2783
|
+
var version = "0.7.0";
|
|
2784
|
+
|
|
2785
|
+
// src/cli.ts
|
|
2786
|
+
process10.exitCode = await runCli({
|
|
2787
|
+
name: "pkg",
|
|
2788
|
+
version,
|
|
2789
|
+
about: "checks npm packages before they are added, and moves a lib's consumers onto a new release",
|
|
2790
|
+
replaces: "bun add on trust, and a bun info and sleep loop then a bun add per consumer",
|
|
2791
|
+
examples: [["pkg zod", "the name, the newest version two weeks old, its licence and scripts"], ["pkg bump @kaynooo/cli-kit --dry-run", "the consumers a release would move"]],
|
|
2792
|
+
defaultCommand: "check",
|
|
2793
|
+
commands: {
|
|
2794
|
+
check: { summary: "check packages before they are added (`pkg <name>` alone runs it)", run: async (args) => (await Promise.resolve().then(() => (init_check(), exports_check))).check(args) },
|
|
2795
|
+
audit: { summary: "check every package a bun.lock pins, with its known advisories", run: async (args) => (await Promise.resolve().then(() => (init_audit(), exports_audit))).audit(args) },
|
|
2796
|
+
bump: { summary: "wait for a release on the registry, then bun add it in every consumer", run: async (args) => (await Promise.resolve().then(() => (init_bump(), exports_bump))).bump(args) },
|
|
2797
|
+
consumers: { summary: "list the folders depending on a package, with the version each asks for", run: async (args) => (await Promise.resolve().then(() => (init_consumers2(), exports_consumers))).consumers(args) }
|
|
2798
|
+
}
|
|
2799
|
+
});
|