@docker-doctor/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -4
- package/dist/cli.cjs +475 -62
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +427 -15
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +8 -17
- package/dist/index.d.mts +8 -17
- package/dist/index.mjs +1 -1
- package/dist/{src-Bt3AB-Xl.mjs → src-EqtziccA.mjs} +277 -111
- package/dist/src-EqtziccA.mjs.map +1 -0
- package/dist/{src-BUYNqQd8.cjs → src-TEhFWhpk.cjs} +277 -113
- package/dist/src-TEhFWhpk.cjs.map +1 -0
- package/package.json +2 -2
- package/dist/src-BUYNqQd8.cjs.map +0 -1
- package/dist/src-Bt3AB-Xl.mjs.map +0 -1
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_src = require('./src-
|
|
2
|
+
const require_src = require('./src-TEhFWhpk.cjs');
|
|
3
3
|
let node_fs_promises = require("node:fs/promises");
|
|
4
4
|
node_fs_promises = require_src.__toESM(node_fs_promises, 1);
|
|
5
5
|
let node_path = require("node:path");
|
|
@@ -9,10 +9,418 @@ node_os = require_src.__toESM(node_os, 1);
|
|
|
9
9
|
let node_readline = require("node:readline");
|
|
10
10
|
node_readline = require_src.__toESM(node_readline, 1);
|
|
11
11
|
let node_timers_promises = require("node:timers/promises");
|
|
12
|
-
let
|
|
13
|
-
|
|
12
|
+
let node_process = require("node:process");
|
|
13
|
+
node_process = require_src.__toESM(node_process, 1);
|
|
14
|
+
let node_tty = require("node:tty");
|
|
15
|
+
node_tty = require_src.__toESM(node_tty, 1);
|
|
14
16
|
let commander = require("commander");
|
|
15
17
|
|
|
18
|
+
//#region ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
19
|
+
const ANSI_BACKGROUND_OFFSET = 10;
|
|
20
|
+
const wrapAnsi16 = (offset = 0) => (code) => `\u001B[${code + offset}m`;
|
|
21
|
+
const wrapAnsi256 = (offset = 0) => (code) => `\u001B[${38 + offset};5;${code}m`;
|
|
22
|
+
const wrapAnsi16m = (offset = 0) => (red, green, blue) => `\u001B[${38 + offset};2;${red};${green};${blue}m`;
|
|
23
|
+
const styles$1 = {
|
|
24
|
+
modifier: {
|
|
25
|
+
reset: [0, 0],
|
|
26
|
+
bold: [1, 22],
|
|
27
|
+
dim: [2, 22],
|
|
28
|
+
italic: [3, 23],
|
|
29
|
+
underline: [4, 24],
|
|
30
|
+
overline: [53, 55],
|
|
31
|
+
inverse: [7, 27],
|
|
32
|
+
hidden: [8, 28],
|
|
33
|
+
strikethrough: [9, 29]
|
|
34
|
+
},
|
|
35
|
+
color: {
|
|
36
|
+
black: [30, 39],
|
|
37
|
+
red: [31, 39],
|
|
38
|
+
green: [32, 39],
|
|
39
|
+
yellow: [33, 39],
|
|
40
|
+
blue: [34, 39],
|
|
41
|
+
magenta: [35, 39],
|
|
42
|
+
cyan: [36, 39],
|
|
43
|
+
white: [37, 39],
|
|
44
|
+
blackBright: [90, 39],
|
|
45
|
+
gray: [90, 39],
|
|
46
|
+
grey: [90, 39],
|
|
47
|
+
redBright: [91, 39],
|
|
48
|
+
greenBright: [92, 39],
|
|
49
|
+
yellowBright: [93, 39],
|
|
50
|
+
blueBright: [94, 39],
|
|
51
|
+
magentaBright: [95, 39],
|
|
52
|
+
cyanBright: [96, 39],
|
|
53
|
+
whiteBright: [97, 39]
|
|
54
|
+
},
|
|
55
|
+
bgColor: {
|
|
56
|
+
bgBlack: [40, 49],
|
|
57
|
+
bgRed: [41, 49],
|
|
58
|
+
bgGreen: [42, 49],
|
|
59
|
+
bgYellow: [43, 49],
|
|
60
|
+
bgBlue: [44, 49],
|
|
61
|
+
bgMagenta: [45, 49],
|
|
62
|
+
bgCyan: [46, 49],
|
|
63
|
+
bgWhite: [47, 49],
|
|
64
|
+
bgBlackBright: [100, 49],
|
|
65
|
+
bgGray: [100, 49],
|
|
66
|
+
bgGrey: [100, 49],
|
|
67
|
+
bgRedBright: [101, 49],
|
|
68
|
+
bgGreenBright: [102, 49],
|
|
69
|
+
bgYellowBright: [103, 49],
|
|
70
|
+
bgBlueBright: [104, 49],
|
|
71
|
+
bgMagentaBright: [105, 49],
|
|
72
|
+
bgCyanBright: [106, 49],
|
|
73
|
+
bgWhiteBright: [107, 49]
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const modifierNames = Object.keys(styles$1.modifier);
|
|
77
|
+
const foregroundColorNames = Object.keys(styles$1.color);
|
|
78
|
+
const backgroundColorNames = Object.keys(styles$1.bgColor);
|
|
79
|
+
const colorNames = [...foregroundColorNames, ...backgroundColorNames];
|
|
80
|
+
function assembleStyles() {
|
|
81
|
+
const codes = /* @__PURE__ */ new Map();
|
|
82
|
+
for (const [groupName, group] of Object.entries(styles$1)) {
|
|
83
|
+
for (const [styleName, style] of Object.entries(group)) {
|
|
84
|
+
styles$1[styleName] = {
|
|
85
|
+
open: `\u001B[${style[0]}m`,
|
|
86
|
+
close: `\u001B[${style[1]}m`
|
|
87
|
+
};
|
|
88
|
+
group[styleName] = styles$1[styleName];
|
|
89
|
+
codes.set(style[0], style[1]);
|
|
90
|
+
}
|
|
91
|
+
Object.defineProperty(styles$1, groupName, {
|
|
92
|
+
value: group,
|
|
93
|
+
enumerable: false
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
Object.defineProperty(styles$1, "codes", {
|
|
97
|
+
value: codes,
|
|
98
|
+
enumerable: false
|
|
99
|
+
});
|
|
100
|
+
styles$1.color.close = "\x1B[39m";
|
|
101
|
+
styles$1.bgColor.close = "\x1B[49m";
|
|
102
|
+
styles$1.color.ansi = wrapAnsi16();
|
|
103
|
+
styles$1.color.ansi256 = wrapAnsi256();
|
|
104
|
+
styles$1.color.ansi16m = wrapAnsi16m();
|
|
105
|
+
styles$1.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
|
|
106
|
+
styles$1.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
|
107
|
+
styles$1.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
108
|
+
Object.defineProperties(styles$1, {
|
|
109
|
+
rgbToAnsi256: {
|
|
110
|
+
value(red, green, blue) {
|
|
111
|
+
if (red === green && green === blue) {
|
|
112
|
+
if (red < 8) return 16;
|
|
113
|
+
if (red > 248) return 231;
|
|
114
|
+
return Math.round((red - 8) / 247 * 24) + 232;
|
|
115
|
+
}
|
|
116
|
+
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
|
|
117
|
+
},
|
|
118
|
+
enumerable: false
|
|
119
|
+
},
|
|
120
|
+
hexToRgb: {
|
|
121
|
+
value(hex) {
|
|
122
|
+
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
|
123
|
+
if (!matches) return [
|
|
124
|
+
0,
|
|
125
|
+
0,
|
|
126
|
+
0
|
|
127
|
+
];
|
|
128
|
+
let [colorString] = matches;
|
|
129
|
+
if (colorString.length === 3) colorString = [...colorString].map((character) => character + character).join("");
|
|
130
|
+
const integer = Number.parseInt(colorString, 16);
|
|
131
|
+
return [
|
|
132
|
+
integer >> 16 & 255,
|
|
133
|
+
integer >> 8 & 255,
|
|
134
|
+
integer & 255
|
|
135
|
+
];
|
|
136
|
+
},
|
|
137
|
+
enumerable: false
|
|
138
|
+
},
|
|
139
|
+
hexToAnsi256: {
|
|
140
|
+
value: (hex) => styles$1.rgbToAnsi256(...styles$1.hexToRgb(hex)),
|
|
141
|
+
enumerable: false
|
|
142
|
+
},
|
|
143
|
+
ansi256ToAnsi: {
|
|
144
|
+
value(code) {
|
|
145
|
+
if (code < 8) return 30 + code;
|
|
146
|
+
if (code < 16) return 90 + (code - 8);
|
|
147
|
+
let red;
|
|
148
|
+
let green;
|
|
149
|
+
let blue;
|
|
150
|
+
if (code >= 232) {
|
|
151
|
+
red = ((code - 232) * 10 + 8) / 255;
|
|
152
|
+
green = red;
|
|
153
|
+
blue = red;
|
|
154
|
+
} else {
|
|
155
|
+
code -= 16;
|
|
156
|
+
const remainder = code % 36;
|
|
157
|
+
red = Math.floor(code / 36) / 5;
|
|
158
|
+
green = Math.floor(remainder / 6) / 5;
|
|
159
|
+
blue = remainder % 6 / 5;
|
|
160
|
+
}
|
|
161
|
+
const value = Math.max(red, green, blue) * 2;
|
|
162
|
+
if (value === 0) return 30;
|
|
163
|
+
let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
|
|
164
|
+
if (value === 2) result += 60;
|
|
165
|
+
return result;
|
|
166
|
+
},
|
|
167
|
+
enumerable: false
|
|
168
|
+
},
|
|
169
|
+
rgbToAnsi: {
|
|
170
|
+
value: (red, green, blue) => styles$1.ansi256ToAnsi(styles$1.rgbToAnsi256(red, green, blue)),
|
|
171
|
+
enumerable: false
|
|
172
|
+
},
|
|
173
|
+
hexToAnsi: {
|
|
174
|
+
value: (hex) => styles$1.ansi256ToAnsi(styles$1.hexToAnsi256(hex)),
|
|
175
|
+
enumerable: false
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
return styles$1;
|
|
179
|
+
}
|
|
180
|
+
const ansiStyles = assembleStyles();
|
|
181
|
+
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/supports-color/index.js
|
|
184
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : node_process.default.argv) {
|
|
185
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
186
|
+
const position = argv.indexOf(prefix + flag);
|
|
187
|
+
const terminatorPosition = argv.indexOf("--");
|
|
188
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
189
|
+
}
|
|
190
|
+
const { env } = node_process.default;
|
|
191
|
+
let flagForceColor;
|
|
192
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) flagForceColor = 0;
|
|
193
|
+
else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) flagForceColor = 1;
|
|
194
|
+
function envForceColor() {
|
|
195
|
+
if ("FORCE_COLOR" in env) {
|
|
196
|
+
if (env.FORCE_COLOR === "true") return 1;
|
|
197
|
+
if (env.FORCE_COLOR === "false") return 0;
|
|
198
|
+
return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function translateLevel(level) {
|
|
202
|
+
if (level === 0) return false;
|
|
203
|
+
return {
|
|
204
|
+
level,
|
|
205
|
+
hasBasic: true,
|
|
206
|
+
has256: level >= 2,
|
|
207
|
+
has16m: level >= 3
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
211
|
+
const noFlagForceColor = envForceColor();
|
|
212
|
+
if (noFlagForceColor !== void 0) flagForceColor = noFlagForceColor;
|
|
213
|
+
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
214
|
+
if (forceColor === 0) return 0;
|
|
215
|
+
if (sniffFlags) {
|
|
216
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) return 3;
|
|
217
|
+
if (hasFlag("color=256")) return 2;
|
|
218
|
+
}
|
|
219
|
+
if ("TF_BUILD" in env && "AGENT_NAME" in env) return 1;
|
|
220
|
+
if (haveStream && !streamIsTTY && forceColor === void 0) return 0;
|
|
221
|
+
const min = forceColor || 0;
|
|
222
|
+
if (env.TERM === "dumb") return min;
|
|
223
|
+
if (node_process.default.platform === "win32") {
|
|
224
|
+
const osRelease = node_os.default.release().split(".");
|
|
225
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
226
|
+
return 1;
|
|
227
|
+
}
|
|
228
|
+
if ("CI" in env) {
|
|
229
|
+
if ([
|
|
230
|
+
"GITHUB_ACTIONS",
|
|
231
|
+
"GITEA_ACTIONS",
|
|
232
|
+
"CIRCLECI"
|
|
233
|
+
].some((key) => key in env)) return 3;
|
|
234
|
+
if ([
|
|
235
|
+
"TRAVIS",
|
|
236
|
+
"APPVEYOR",
|
|
237
|
+
"GITLAB_CI",
|
|
238
|
+
"BUILDKITE",
|
|
239
|
+
"DRONE"
|
|
240
|
+
].some((sign) => sign in env) || env.CI_NAME === "codeship") return 1;
|
|
241
|
+
return min;
|
|
242
|
+
}
|
|
243
|
+
if ("TEAMCITY_VERSION" in env) return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
244
|
+
if (env.COLORTERM === "truecolor") return 3;
|
|
245
|
+
if (env.TERM === "xterm-kitty") return 3;
|
|
246
|
+
if (env.TERM === "xterm-ghostty") return 3;
|
|
247
|
+
if (env.TERM === "wezterm") return 3;
|
|
248
|
+
if ("TERM_PROGRAM" in env) {
|
|
249
|
+
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
250
|
+
switch (env.TERM_PROGRAM) {
|
|
251
|
+
case "iTerm.app": return version >= 3 ? 3 : 2;
|
|
252
|
+
case "Apple_Terminal": return 2;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (/-256(color)?$/i.test(env.TERM)) return 2;
|
|
256
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) return 1;
|
|
257
|
+
if ("COLORTERM" in env) return 1;
|
|
258
|
+
return min;
|
|
259
|
+
}
|
|
260
|
+
function createSupportsColor(stream, options = {}) {
|
|
261
|
+
return translateLevel(_supportsColor(stream, {
|
|
262
|
+
streamIsTTY: stream && stream.isTTY,
|
|
263
|
+
...options
|
|
264
|
+
}));
|
|
265
|
+
}
|
|
266
|
+
const supportsColor = {
|
|
267
|
+
stdout: createSupportsColor({ isTTY: node_tty.default.isatty(1) }),
|
|
268
|
+
stderr: createSupportsColor({ isTTY: node_tty.default.isatty(2) })
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
//#endregion
|
|
272
|
+
//#region ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/utilities.js
|
|
273
|
+
function stringReplaceAll(string, substring, replacer) {
|
|
274
|
+
let index = string.indexOf(substring);
|
|
275
|
+
if (index === -1) return string;
|
|
276
|
+
const substringLength = substring.length;
|
|
277
|
+
let endIndex = 0;
|
|
278
|
+
let returnValue = "";
|
|
279
|
+
do {
|
|
280
|
+
returnValue += string.slice(endIndex, index) + substring + replacer;
|
|
281
|
+
endIndex = index + substringLength;
|
|
282
|
+
index = string.indexOf(substring, endIndex);
|
|
283
|
+
} while (index !== -1);
|
|
284
|
+
returnValue += string.slice(endIndex);
|
|
285
|
+
return returnValue;
|
|
286
|
+
}
|
|
287
|
+
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
288
|
+
let endIndex = 0;
|
|
289
|
+
let returnValue = "";
|
|
290
|
+
do {
|
|
291
|
+
const gotCR = string[index - 1] === "\r";
|
|
292
|
+
returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
|
|
293
|
+
endIndex = index + 1;
|
|
294
|
+
index = string.indexOf("\n", endIndex);
|
|
295
|
+
} while (index !== -1);
|
|
296
|
+
returnValue += string.slice(endIndex);
|
|
297
|
+
return returnValue;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/index.js
|
|
302
|
+
const { stdout: stdoutColor, stderr: stderrColor } = supportsColor;
|
|
303
|
+
const GENERATOR = Symbol("GENERATOR");
|
|
304
|
+
const STYLER = Symbol("STYLER");
|
|
305
|
+
const IS_EMPTY = Symbol("IS_EMPTY");
|
|
306
|
+
const levelMapping = [
|
|
307
|
+
"ansi",
|
|
308
|
+
"ansi",
|
|
309
|
+
"ansi256",
|
|
310
|
+
"ansi16m"
|
|
311
|
+
];
|
|
312
|
+
const styles = Object.create(null);
|
|
313
|
+
const applyOptions = (object, options = {}) => {
|
|
314
|
+
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) throw new Error("The `level` option should be an integer from 0 to 3");
|
|
315
|
+
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
|
316
|
+
object.level = options.level === void 0 ? colorLevel : options.level;
|
|
317
|
+
};
|
|
318
|
+
const chalkFactory = (options) => {
|
|
319
|
+
const chalk = (...strings) => strings.join(" ");
|
|
320
|
+
applyOptions(chalk, options);
|
|
321
|
+
Object.setPrototypeOf(chalk, createChalk.prototype);
|
|
322
|
+
return chalk;
|
|
323
|
+
};
|
|
324
|
+
function createChalk(options) {
|
|
325
|
+
return chalkFactory(options);
|
|
326
|
+
}
|
|
327
|
+
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
|
|
328
|
+
for (const [styleName, style] of Object.entries(ansiStyles)) styles[styleName] = { get() {
|
|
329
|
+
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
|
|
330
|
+
Object.defineProperty(this, styleName, { value: builder });
|
|
331
|
+
return builder;
|
|
332
|
+
} };
|
|
333
|
+
styles.visible = { get() {
|
|
334
|
+
const builder = createBuilder(this, this[STYLER], true);
|
|
335
|
+
Object.defineProperty(this, "visible", { value: builder });
|
|
336
|
+
return builder;
|
|
337
|
+
} };
|
|
338
|
+
const getModelAnsi = (model, level, type, ...arguments_) => {
|
|
339
|
+
if (model === "rgb") {
|
|
340
|
+
if (level === "ansi16m") return ansiStyles[type].ansi16m(...arguments_);
|
|
341
|
+
if (level === "ansi256") return ansiStyles[type].ansi256(ansiStyles.rgbToAnsi256(...arguments_));
|
|
342
|
+
return ansiStyles[type].ansi(ansiStyles.rgbToAnsi(...arguments_));
|
|
343
|
+
}
|
|
344
|
+
if (model === "hex") return getModelAnsi("rgb", level, type, ...ansiStyles.hexToRgb(...arguments_));
|
|
345
|
+
return ansiStyles[type][model](...arguments_);
|
|
346
|
+
};
|
|
347
|
+
for (const model of [
|
|
348
|
+
"rgb",
|
|
349
|
+
"hex",
|
|
350
|
+
"ansi256"
|
|
351
|
+
]) {
|
|
352
|
+
styles[model] = { get() {
|
|
353
|
+
const { level } = this;
|
|
354
|
+
return function(...arguments_) {
|
|
355
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansiStyles.color.close, this[STYLER]);
|
|
356
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
357
|
+
};
|
|
358
|
+
} };
|
|
359
|
+
const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
|
|
360
|
+
styles[bgModel] = { get() {
|
|
361
|
+
const { level } = this;
|
|
362
|
+
return function(...arguments_) {
|
|
363
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansiStyles.bgColor.close, this[STYLER]);
|
|
364
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
365
|
+
};
|
|
366
|
+
} };
|
|
367
|
+
}
|
|
368
|
+
const proto = Object.defineProperties(() => {}, {
|
|
369
|
+
...styles,
|
|
370
|
+
level: {
|
|
371
|
+
enumerable: true,
|
|
372
|
+
get() {
|
|
373
|
+
return this[GENERATOR].level;
|
|
374
|
+
},
|
|
375
|
+
set(level) {
|
|
376
|
+
this[GENERATOR].level = level;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
const createStyler = (open, close, parent) => {
|
|
381
|
+
let openAll;
|
|
382
|
+
let closeAll;
|
|
383
|
+
if (parent === void 0) {
|
|
384
|
+
openAll = open;
|
|
385
|
+
closeAll = close;
|
|
386
|
+
} else {
|
|
387
|
+
openAll = parent.openAll + open;
|
|
388
|
+
closeAll = close + parent.closeAll;
|
|
389
|
+
}
|
|
390
|
+
return {
|
|
391
|
+
open,
|
|
392
|
+
close,
|
|
393
|
+
openAll,
|
|
394
|
+
closeAll,
|
|
395
|
+
parent
|
|
396
|
+
};
|
|
397
|
+
};
|
|
398
|
+
const createBuilder = (self, _styler, _isEmpty) => {
|
|
399
|
+
const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
|
|
400
|
+
Object.setPrototypeOf(builder, proto);
|
|
401
|
+
builder[GENERATOR] = self;
|
|
402
|
+
builder[STYLER] = _styler;
|
|
403
|
+
builder[IS_EMPTY] = _isEmpty;
|
|
404
|
+
return builder;
|
|
405
|
+
};
|
|
406
|
+
const applyStyle = (self, string) => {
|
|
407
|
+
if (self.level <= 0 || !string) return self[IS_EMPTY] ? "" : string;
|
|
408
|
+
let styler = self[STYLER];
|
|
409
|
+
if (styler === void 0) return string;
|
|
410
|
+
const { openAll, closeAll } = styler;
|
|
411
|
+
if (string.includes("\x1B")) while (styler !== void 0) {
|
|
412
|
+
string = stringReplaceAll(string, styler.close, styler.open);
|
|
413
|
+
styler = styler.parent;
|
|
414
|
+
}
|
|
415
|
+
const lfIndex = string.indexOf("\n");
|
|
416
|
+
if (lfIndex !== -1) string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
|
|
417
|
+
return openAll + string + closeAll;
|
|
418
|
+
};
|
|
419
|
+
Object.defineProperties(createChalk.prototype, styles);
|
|
420
|
+
const chalk = createChalk();
|
|
421
|
+
const chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
422
|
+
|
|
423
|
+
//#endregion
|
|
16
424
|
//#region src/formatters/terminal.ts
|
|
17
425
|
const printCodeFrame = (content, line, severityColor) => {
|
|
18
426
|
if (!content || !line) return;
|
|
@@ -23,23 +431,23 @@ const printCodeFrame = (content, line, severityColor) => {
|
|
|
23
431
|
const rawLine = lines[i - 1];
|
|
24
432
|
const isTarget = i === line;
|
|
25
433
|
const lineNumberStr = String(i).padStart(5, " ");
|
|
26
|
-
if (isTarget) console.log(` ${severityColor(">")} ${chalk.
|
|
27
|
-
else console.log(` ${chalk.
|
|
434
|
+
if (isTarget) console.log(` ${severityColor(">")} ${chalk.bold(lineNumberStr)} │ ${chalk.white(rawLine)}`);
|
|
435
|
+
else console.log(` ${chalk.dim(lineNumberStr)} │ ${chalk.dim(rawLine)}`);
|
|
28
436
|
}
|
|
29
437
|
console.log();
|
|
30
438
|
};
|
|
31
439
|
const printDiscoveredFiles = (project) => {
|
|
32
440
|
console.log(`\nDiscovered Files:`);
|
|
33
|
-
console.log(` Dockerfile(s): ${project.dockerfiles.length ? project.dockerfiles.map((f) => chalk.
|
|
34
|
-
console.log(` Compose file(s): ${project.composeFiles.length ? project.composeFiles.map((f) => chalk.
|
|
441
|
+
console.log(` Dockerfile(s): ${project.dockerfiles.length ? project.dockerfiles.map((f) => chalk.cyan(f)).join(", ") : chalk.dim("None")}`);
|
|
442
|
+
console.log(` Compose file(s): ${project.composeFiles.length ? project.composeFiles.map((f) => chalk.cyan(f)).join(", ") : chalk.dim("None")}`);
|
|
35
443
|
};
|
|
36
444
|
const printDiagnostics = (diagnostics, verbose, fileContents, categoryIssueCounts) => {
|
|
37
445
|
if (diagnostics.length === 0) {
|
|
38
|
-
console.log(`\n${chalk.
|
|
446
|
+
console.log(`\n${chalk.green.bold("✔ No issues found! Your Docker setup looks healthy.")}`);
|
|
39
447
|
return;
|
|
40
448
|
}
|
|
41
449
|
if (!verbose) {
|
|
42
|
-
console.log(`\n All ${chalk.
|
|
450
|
+
console.log(`\n All ${chalk.bold(diagnostics.length)} issues\n`);
|
|
43
451
|
for (const cat of [
|
|
44
452
|
"Security",
|
|
45
453
|
"Performance",
|
|
@@ -49,16 +457,16 @@ const printDiagnostics = (diagnostics, verbose, fileContents, categoryIssueCount
|
|
|
49
457
|
]) {
|
|
50
458
|
const count = categoryIssueCounts[cat];
|
|
51
459
|
const issueLabel = count === 1 ? "1 issue" : `${count} issues`;
|
|
52
|
-
console.log(` ${cat} › ${chalk.
|
|
460
|
+
console.log(` ${cat} › ${chalk.dim(issueLabel)}`);
|
|
53
461
|
}
|
|
54
|
-
console.log(`\n Run ${chalk.
|
|
462
|
+
console.log(`\n Run ${chalk.cyan("docker-doctor --verbose")} to list every error and warning`);
|
|
55
463
|
const ruleCounts = {};
|
|
56
464
|
for (const d of diagnostics) ruleCounts[d.rule] = (ruleCounts[d.rule] || 0) + 1;
|
|
57
465
|
const migrationRules = Object.entries(ruleCounts).filter(([_, count]) => count >= 5);
|
|
58
466
|
if (migrationRules.length > 0) {
|
|
59
467
|
console.log();
|
|
60
|
-
console.log(` ${chalk.
|
|
61
|
-
for (const [rule, count] of migrationRules) console.log(` ${chalk.
|
|
468
|
+
console.log(` ${chalk.yellow("⚠ Migration-scale change: sample before you sweep")}`);
|
|
469
|
+
for (const [rule, count] of migrationRules) console.log(` ${chalk.cyan(rule)} ×${count} across ${count} files`);
|
|
62
470
|
console.log(` Fixing all of them at once is hard to review and prone to`);
|
|
63
471
|
console.log(` subtle mistakes across the whole repo. Fix a representative`);
|
|
64
472
|
console.log(` few first and confirm the recipe holds. Then get the code`);
|
|
@@ -67,30 +475,30 @@ const printDiagnostics = (diagnostics, verbose, fileContents, categoryIssueCount
|
|
|
67
475
|
}
|
|
68
476
|
return;
|
|
69
477
|
}
|
|
70
|
-
console.log(`\nFound ${chalk.
|
|
478
|
+
console.log(`\nFound ${chalk.bold(diagnostics.length)} issue(s):`);
|
|
71
479
|
const filesGrouped = {};
|
|
72
480
|
for (const d of diagnostics) {
|
|
73
481
|
if (!filesGrouped[d.file]) filesGrouped[d.file] = [];
|
|
74
482
|
filesGrouped[d.file].push(d);
|
|
75
483
|
}
|
|
76
484
|
for (const [file, fileDiags] of Object.entries(filesGrouped)) {
|
|
77
|
-
console.log(`\n${chalk.
|
|
485
|
+
console.log(`\n${chalk.underline.bold(file)}`);
|
|
78
486
|
for (const d of fileDiags) {
|
|
79
|
-
let sevColor = chalk.
|
|
487
|
+
let sevColor = chalk.cyan;
|
|
80
488
|
let prefix = "ℹ INFO";
|
|
81
489
|
if (d.severity === "error") {
|
|
82
|
-
sevColor = chalk.
|
|
490
|
+
sevColor = chalk.red.bold;
|
|
83
491
|
prefix = "✖ ERROR";
|
|
84
492
|
} else if (d.severity === "warning") {
|
|
85
|
-
sevColor = chalk.
|
|
493
|
+
sevColor = chalk.yellow;
|
|
86
494
|
prefix = "⚠ WARN";
|
|
87
495
|
}
|
|
88
496
|
const lineInfo = d.line ? `:${d.line}` : "";
|
|
89
|
-
console.log(` ${sevColor(prefix)} [${chalk.
|
|
497
|
+
console.log(` ${sevColor(prefix)} [${chalk.dim(d.rule)}]${lineInfo}`);
|
|
90
498
|
const content = fileContents[file];
|
|
91
499
|
printCodeFrame(content, d.line, sevColor);
|
|
92
|
-
console.log(` ${chalk.
|
|
93
|
-
console.log(` ${chalk.
|
|
500
|
+
console.log(` ${chalk.white(d.message)}`);
|
|
501
|
+
console.log(` ${chalk.dim("Help:")} ${d.help}`);
|
|
94
502
|
console.log();
|
|
95
503
|
}
|
|
96
504
|
}
|
|
@@ -100,10 +508,10 @@ const getWhaleMascot = (score, border) => {
|
|
|
100
508
|
let spout = " ";
|
|
101
509
|
if (score >= 75) {
|
|
102
510
|
eyes = "◠ ◠";
|
|
103
|
-
spout = chalk.
|
|
511
|
+
spout = chalk.cyan(" \":\" ");
|
|
104
512
|
} else if (score >= 50) {
|
|
105
513
|
eyes = "• •";
|
|
106
|
-
spout = chalk.
|
|
514
|
+
spout = chalk.cyan(" . ");
|
|
107
515
|
}
|
|
108
516
|
return [
|
|
109
517
|
spout,
|
|
@@ -113,15 +521,15 @@ const getWhaleMascot = (score, border) => {
|
|
|
113
521
|
];
|
|
114
522
|
};
|
|
115
523
|
const easeOutCubic = (x) => 1 - (1 - x) ** 3;
|
|
116
|
-
const printScoreBox = async (score, label, categoryIssueCounts) => {
|
|
524
|
+
const printScoreBox = async (score, label, categoryIssueCounts, warningsCount, errorsCount) => {
|
|
117
525
|
const { isTTY } = process.stdout;
|
|
118
526
|
const shouldAnimate = isTTY && !process.env.CI && !process.env.NO_ANIMATION && process.env.TERM !== "dumb" && process.env.NODE_ENV !== "test";
|
|
119
|
-
let scoreColor = chalk.
|
|
120
|
-
if (score >= 90) scoreColor = chalk.
|
|
121
|
-
else if (score >= 75) scoreColor = chalk.
|
|
122
|
-
else if (score >= 50) scoreColor = chalk.
|
|
527
|
+
let scoreColor = chalk.red.bold;
|
|
528
|
+
if (score >= 90) scoreColor = chalk.green.bold;
|
|
529
|
+
else if (score >= 75) scoreColor = chalk.yellow.bold;
|
|
530
|
+
else if (score >= 50) scoreColor = chalk.magenta.bold;
|
|
123
531
|
const whaleLines = getWhaleMascot(score, scoreColor);
|
|
124
|
-
const shareUrl = `https://
|
|
532
|
+
const shareUrl = `https://docker-doctor.vercel.app/share?s=${score}&w=${warningsCount}&e=${errorsCount}`;
|
|
125
533
|
if (shouldAnimate) {
|
|
126
534
|
const frameCount = 20;
|
|
127
535
|
const frameDelay = 15;
|
|
@@ -132,10 +540,10 @@ const printScoreBox = async (score, label, categoryIssueCounts) => {
|
|
|
132
540
|
const currentScore = Math.round(score * progress);
|
|
133
541
|
const filledBlocks = Math.round(currentScore / 2);
|
|
134
542
|
const emptyBlocks = 50 - filledBlocks;
|
|
135
|
-
const bar = scoreColor("█".repeat(filledBlocks)) + chalk.
|
|
543
|
+
const bar = scoreColor("█".repeat(filledBlocks)) + chalk.dim("░".repeat(emptyBlocks));
|
|
136
544
|
if (frame > 0) process.stdout.write("\x1B[4A\r");
|
|
137
545
|
else console.log();
|
|
138
|
-
process.stdout.write(` ${whaleLines[0]} ${scoreColor(`${currentScore} / 100`)} ${scoreColor(label)}\n ${whaleLines[1]} ${bar}\n ${whaleLines[2]} ${chalk.
|
|
546
|
+
process.stdout.write(` ${whaleLines[0]} ${scoreColor(`${currentScore} / 100`)} ${scoreColor(label)}\n ${whaleLines[1]} ${bar}\n ${whaleLines[2]} ${chalk.dim("Docker Doctor (https://docker-doctor.vercel.app)")}\n ${whaleLines[3]}\n`);
|
|
139
547
|
if (frame < frameCount) await (0, node_timers_promises.setTimeout)(frameDelay);
|
|
140
548
|
}
|
|
141
549
|
} finally {
|
|
@@ -144,24 +552,24 @@ const printScoreBox = async (score, label, categoryIssueCounts) => {
|
|
|
144
552
|
} else {
|
|
145
553
|
const filledBlocks = Math.round(score / 2);
|
|
146
554
|
const emptyBlocks = 50 - filledBlocks;
|
|
147
|
-
const bar = scoreColor("█".repeat(filledBlocks)) + chalk.
|
|
555
|
+
const bar = scoreColor("█".repeat(filledBlocks)) + chalk.dim("░".repeat(emptyBlocks));
|
|
148
556
|
console.log(`\n ${whaleLines[0]} ${scoreColor(`${score} / 100`)} ${scoreColor(label)}`);
|
|
149
557
|
console.log(` ${whaleLines[1]} ${bar}`);
|
|
150
|
-
console.log(` ${whaleLines[2]} ${chalk.
|
|
558
|
+
console.log(` ${whaleLines[2]} ${chalk.dim("Docker Doctor (https://docker-doctor.vercel.app)")}`);
|
|
151
559
|
console.log(` ${whaleLines[3]}`);
|
|
152
560
|
}
|
|
153
|
-
console.log(`\n ${chalk.
|
|
154
|
-
console.log(` Share: ${chalk.
|
|
561
|
+
console.log(`\n ${chalk.dim("────────────────────────────────────────────────────────────")}\n`);
|
|
562
|
+
console.log(` Share: ${chalk.cyan(shareUrl)}`);
|
|
155
563
|
console.log(` Tell others how you did on socials\n`);
|
|
156
|
-
console.log(` Docs: ${chalk.
|
|
564
|
+
console.log(` Docs: ${chalk.cyan("https://docker-doctor.vercel.app")}`);
|
|
157
565
|
console.log(` Learn more about fixing issues, setting up CI/CD, and`);
|
|
158
566
|
console.log(` configuring rules with a config file\n`);
|
|
159
|
-
console.log(` GitHub: ${chalk.
|
|
567
|
+
console.log(` GitHub: ${chalk.cyan("https://github.com/PunGrumpy/docker-doctor")}`);
|
|
160
568
|
console.log(` Report issues and star the repository!`);
|
|
161
569
|
};
|
|
162
570
|
const formatTerminal = async (diagnostics, score, label, project, verbose = false, fileContents = {}) => {
|
|
163
571
|
if (verbose) {
|
|
164
|
-
console.log(`\n${chalk.
|
|
572
|
+
console.log(`\n${chalk.bold("Docker Doctor Diagnostics")}`);
|
|
165
573
|
console.log(`=================================`);
|
|
166
574
|
printDiscoveredFiles(project);
|
|
167
575
|
}
|
|
@@ -172,12 +580,16 @@ const formatTerminal = async (diagnostics, score, label, project, verbose = fals
|
|
|
172
580
|
Performance: 0,
|
|
173
581
|
Security: 0
|
|
174
582
|
};
|
|
583
|
+
let warningsCount = 0;
|
|
584
|
+
let errorsCount = 0;
|
|
175
585
|
for (const d of diagnostics) {
|
|
176
586
|
const category = require_src.findRule(d.rule)?.category || "Best Practices";
|
|
177
587
|
categoryIssueCounts[category] = (categoryIssueCounts[category] || 0) + 1;
|
|
588
|
+
if (d.severity === "warning") warningsCount += 1;
|
|
589
|
+
else if (d.severity === "error") errorsCount += 1;
|
|
178
590
|
}
|
|
179
591
|
printDiagnostics(diagnostics, verbose, fileContents, categoryIssueCounts);
|
|
180
|
-
await printScoreBox(score, label, categoryIssueCounts);
|
|
592
|
+
await printScoreBox(score, label, categoryIssueCounts, warningsCount, errorsCount);
|
|
181
593
|
};
|
|
182
594
|
|
|
183
595
|
//#endregion
|
|
@@ -192,12 +604,12 @@ const askConfirm = (question, defaultYes = false) => {
|
|
|
192
604
|
process.stdout.write("\x1B[?25l");
|
|
193
605
|
const render = (firstTime = false) => {
|
|
194
606
|
if (!firstTime) process.stdout.write("\x1B[3A\r");
|
|
195
|
-
process.stdout.write(`\r\u001B[K ${chalk.
|
|
196
|
-
const yesPrefix = value ? chalk.
|
|
197
|
-
const yesText = value ? chalk.
|
|
607
|
+
process.stdout.write(`\r\u001B[K ${chalk.green("✔")} ${chalk.bold(question)}\n`);
|
|
608
|
+
const yesPrefix = value ? chalk.cyan("❯ ") : " ";
|
|
609
|
+
const yesText = value ? chalk.cyan.bold("Yes") : chalk.dim("Yes");
|
|
198
610
|
process.stdout.write(`\r\u001B[K${yesPrefix}${yesText}\n`);
|
|
199
|
-
const noPrefix = value ? " " : chalk.
|
|
200
|
-
const noText = value ? chalk.
|
|
611
|
+
const noPrefix = value ? " " : chalk.cyan("❯ ");
|
|
612
|
+
const noText = value ? chalk.dim("No") : chalk.cyan.bold("No");
|
|
201
613
|
process.stdout.write(`\r\u001B[K${noPrefix}${noText}\n`);
|
|
202
614
|
};
|
|
203
615
|
render(true);
|
|
@@ -220,7 +632,7 @@ const askConfirm = (question, defaultYes = false) => {
|
|
|
220
632
|
} else if (key.name === "return" || key.name === "enter" || str === "\r" || str === "\n") {
|
|
221
633
|
cleanup();
|
|
222
634
|
process.stdout.write("\x1B[3A\r\x1B[K");
|
|
223
|
-
process.stdout.write(` ${chalk.
|
|
635
|
+
process.stdout.write(` ${chalk.green("✔")} ${chalk.bold(question)} › ${value ? chalk.cyan("Yes") : chalk.dim("No")}\n`);
|
|
224
636
|
process.stdout.write("\r\x1B[K\n");
|
|
225
637
|
process.stdout.write("\r\x1B[K\n");
|
|
226
638
|
process.stdout.write("\x1B[2A");
|
|
@@ -244,12 +656,12 @@ const askSelect = (question, options, defaultIndex = 0) => {
|
|
|
244
656
|
process.stdout.write("\x1B[?25l");
|
|
245
657
|
const render = (firstTime = false) => {
|
|
246
658
|
if (!firstTime) process.stdout.write(`\u001B[${options.length + 1}A\r`);
|
|
247
|
-
process.stdout.write(`\r\u001B[K ${chalk.
|
|
659
|
+
process.stdout.write(`\r\u001B[K ${chalk.green("✔")} ${chalk.bold(question)}\n`);
|
|
248
660
|
let i = 0;
|
|
249
661
|
for (const option of options) {
|
|
250
662
|
const isSelected = i === index;
|
|
251
|
-
const prefix = isSelected ? chalk.
|
|
252
|
-
const text = isSelected ? chalk.
|
|
663
|
+
const prefix = isSelected ? chalk.cyan("❯ ") : " ";
|
|
664
|
+
const text = isSelected ? chalk.cyan.bold(option) : chalk.dim(option);
|
|
253
665
|
process.stdout.write(`\r\u001B[K${prefix}${text}\n`);
|
|
254
666
|
i += 1;
|
|
255
667
|
}
|
|
@@ -271,7 +683,7 @@ const askSelect = (question, options, defaultIndex = 0) => {
|
|
|
271
683
|
} else if (key.name === "return" || key.name === "enter" || str === "\r" || str === "\n") {
|
|
272
684
|
cleanup();
|
|
273
685
|
process.stdout.write(`\u001B[${options.length + 1}A\r\u001B[K`);
|
|
274
|
-
process.stdout.write(` ${chalk.
|
|
686
|
+
process.stdout.write(` ${chalk.green("✔")} ${chalk.bold(question)} › ${chalk.cyan(options[index])}\n`);
|
|
275
687
|
for (const _ of options) process.stdout.write("\r\x1B[K\n");
|
|
276
688
|
process.stdout.write(`\u001B[${options.length}A`);
|
|
277
689
|
resolve(index);
|
|
@@ -308,12 +720,12 @@ jobs:
|
|
|
308
720
|
- name: Run docker-doctor
|
|
309
721
|
run: bunx docker-doctor .
|
|
310
722
|
`, "utf-8");
|
|
311
|
-
console.log(`\n ${chalk.
|
|
723
|
+
console.log(`\n ${chalk.green("✨")} Created ${chalk.cyan(".github/workflows/docker-doctor.yml")}!`);
|
|
312
724
|
console.log(` Scan every pull request to prevent new Docker issues while you fix the backlog.`);
|
|
313
725
|
}
|
|
314
726
|
if (await askSelect("What would you like to do next?", ["View rules list", "Skip"]) === 0) {
|
|
315
|
-
console.log(`\n ${chalk.
|
|
316
|
-
for (const r of require_src.allRules) console.log(` - ${chalk.
|
|
727
|
+
console.log(`\n ${chalk.bold("Available Rules:")}`);
|
|
728
|
+
for (const r of require_src.allRules) console.log(` - ${chalk.cyan(r.key)}: ${r.message} (${chalk.dim(r.category)})`);
|
|
317
729
|
}
|
|
318
730
|
} catch {}
|
|
319
731
|
};
|
|
@@ -405,9 +817,9 @@ program.argument("[dir]", "directory to scan", ".").option("-v, --verbose", "sho
|
|
|
405
817
|
};
|
|
406
818
|
if (process.stdout.isTTY && !isSilent) {
|
|
407
819
|
process.stdout.write("\x1B[?25l");
|
|
408
|
-
process.stdout.write(`${chalk.
|
|
820
|
+
process.stdout.write(`${chalk.cyan(spinnerFrames[0])} ${statusText}`);
|
|
409
821
|
spinnerInterval = setInterval(() => {
|
|
410
|
-
process.stdout.write(`\r\u001B[K${chalk.
|
|
822
|
+
process.stdout.write(`\r\u001B[K${chalk.cyan(spinnerFrames[frameIndex])} ${statusText}`);
|
|
411
823
|
frameIndex = (frameIndex + 1) % spinnerFrames.length;
|
|
412
824
|
}, 80);
|
|
413
825
|
}
|
|
@@ -433,21 +845,22 @@ program.argument("[dir]", "directory to scan", ".").option("-v, --verbose", "sho
|
|
|
433
845
|
spinnerInterval = null;
|
|
434
846
|
process.stdout.write("\r\x1B[K\x1B[?25h");
|
|
435
847
|
}
|
|
436
|
-
if (process.stdout.isTTY && !isSilent) console.log(`${chalk.
|
|
848
|
+
if (process.stdout.isTTY && !isSilent) console.log(`${chalk.green("✔")} Scanned ${projectFilesList.length} files in ${duration}s [~${concurrency} workers]`);
|
|
437
849
|
if (options.score) {
|
|
438
850
|
console.log(score);
|
|
439
|
-
process.
|
|
851
|
+
process.exitCode = score < 50 ? 1 : 0;
|
|
852
|
+
return;
|
|
440
853
|
} else if (options.json) {
|
|
441
854
|
const report = require_src.toJsonReport(filteredDiagnostics, score, label, project);
|
|
442
855
|
console.log(JSON.stringify(report, null, 2));
|
|
443
856
|
const hasErrors = filteredDiagnostics.some((d) => d.severity === "error");
|
|
444
|
-
process.
|
|
445
|
-
|
|
446
|
-
await formatTerminal(filteredDiagnostics, score, label, project, options.verbose, fileContents);
|
|
447
|
-
const hasErrors = filteredDiagnostics.some((d) => d.severity === "error");
|
|
448
|
-
if (process.stdout.isTTY && process.stdin.isTTY) await runInteractiveWizard();
|
|
449
|
-
process.exit(hasErrors ? 1 : 0);
|
|
857
|
+
process.exitCode = hasErrors ? 1 : 0;
|
|
858
|
+
return;
|
|
450
859
|
}
|
|
860
|
+
await formatTerminal(filteredDiagnostics, score, label, project, options.verbose, fileContents);
|
|
861
|
+
const hasErrors = filteredDiagnostics.some((d) => d.severity === "error");
|
|
862
|
+
if (process.stdout.isTTY && process.stdin.isTTY) await runInteractiveWizard();
|
|
863
|
+
process.exitCode = hasErrors ? 1 : 0;
|
|
451
864
|
} finally {
|
|
452
865
|
if (spinnerInterval !== null) {
|
|
453
866
|
clearInterval(spinnerInterval);
|