@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.mjs
CHANGED
|
@@ -1,13 +1,420 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as runDockerfileRules, c as parseCompose, d as package_default, i as runComposeRules, l as parseDockerfile, n as calculateScore, o as allRules, r as loadConfig, s as findRule, t as toJsonReport, u as discoverProject } from "./src-
|
|
2
|
+
import { a as runDockerfileRules, c as parseCompose, d as package_default, i as runComposeRules, l as parseDockerfile, n as calculateScore, o as allRules, r as loadConfig, s as findRule, t as toJsonReport, u as discoverProject } from "./src-EqtziccA.mjs";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import readline from "node:readline";
|
|
7
7
|
import { setTimeout } from "node:timers/promises";
|
|
8
|
-
import
|
|
8
|
+
import process$1 from "node:process";
|
|
9
|
+
import tty from "node:tty";
|
|
9
10
|
import { Command } from "commander";
|
|
10
11
|
|
|
12
|
+
//#region ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
13
|
+
const ANSI_BACKGROUND_OFFSET = 10;
|
|
14
|
+
const wrapAnsi16 = (offset = 0) => (code) => `\u001B[${code + offset}m`;
|
|
15
|
+
const wrapAnsi256 = (offset = 0) => (code) => `\u001B[${38 + offset};5;${code}m`;
|
|
16
|
+
const wrapAnsi16m = (offset = 0) => (red, green, blue) => `\u001B[${38 + offset};2;${red};${green};${blue}m`;
|
|
17
|
+
const styles$1 = {
|
|
18
|
+
modifier: {
|
|
19
|
+
reset: [0, 0],
|
|
20
|
+
bold: [1, 22],
|
|
21
|
+
dim: [2, 22],
|
|
22
|
+
italic: [3, 23],
|
|
23
|
+
underline: [4, 24],
|
|
24
|
+
overline: [53, 55],
|
|
25
|
+
inverse: [7, 27],
|
|
26
|
+
hidden: [8, 28],
|
|
27
|
+
strikethrough: [9, 29]
|
|
28
|
+
},
|
|
29
|
+
color: {
|
|
30
|
+
black: [30, 39],
|
|
31
|
+
red: [31, 39],
|
|
32
|
+
green: [32, 39],
|
|
33
|
+
yellow: [33, 39],
|
|
34
|
+
blue: [34, 39],
|
|
35
|
+
magenta: [35, 39],
|
|
36
|
+
cyan: [36, 39],
|
|
37
|
+
white: [37, 39],
|
|
38
|
+
blackBright: [90, 39],
|
|
39
|
+
gray: [90, 39],
|
|
40
|
+
grey: [90, 39],
|
|
41
|
+
redBright: [91, 39],
|
|
42
|
+
greenBright: [92, 39],
|
|
43
|
+
yellowBright: [93, 39],
|
|
44
|
+
blueBright: [94, 39],
|
|
45
|
+
magentaBright: [95, 39],
|
|
46
|
+
cyanBright: [96, 39],
|
|
47
|
+
whiteBright: [97, 39]
|
|
48
|
+
},
|
|
49
|
+
bgColor: {
|
|
50
|
+
bgBlack: [40, 49],
|
|
51
|
+
bgRed: [41, 49],
|
|
52
|
+
bgGreen: [42, 49],
|
|
53
|
+
bgYellow: [43, 49],
|
|
54
|
+
bgBlue: [44, 49],
|
|
55
|
+
bgMagenta: [45, 49],
|
|
56
|
+
bgCyan: [46, 49],
|
|
57
|
+
bgWhite: [47, 49],
|
|
58
|
+
bgBlackBright: [100, 49],
|
|
59
|
+
bgGray: [100, 49],
|
|
60
|
+
bgGrey: [100, 49],
|
|
61
|
+
bgRedBright: [101, 49],
|
|
62
|
+
bgGreenBright: [102, 49],
|
|
63
|
+
bgYellowBright: [103, 49],
|
|
64
|
+
bgBlueBright: [104, 49],
|
|
65
|
+
bgMagentaBright: [105, 49],
|
|
66
|
+
bgCyanBright: [106, 49],
|
|
67
|
+
bgWhiteBright: [107, 49]
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const modifierNames = Object.keys(styles$1.modifier);
|
|
71
|
+
const foregroundColorNames = Object.keys(styles$1.color);
|
|
72
|
+
const backgroundColorNames = Object.keys(styles$1.bgColor);
|
|
73
|
+
const colorNames = [...foregroundColorNames, ...backgroundColorNames];
|
|
74
|
+
function assembleStyles() {
|
|
75
|
+
const codes = /* @__PURE__ */ new Map();
|
|
76
|
+
for (const [groupName, group] of Object.entries(styles$1)) {
|
|
77
|
+
for (const [styleName, style] of Object.entries(group)) {
|
|
78
|
+
styles$1[styleName] = {
|
|
79
|
+
open: `\u001B[${style[0]}m`,
|
|
80
|
+
close: `\u001B[${style[1]}m`
|
|
81
|
+
};
|
|
82
|
+
group[styleName] = styles$1[styleName];
|
|
83
|
+
codes.set(style[0], style[1]);
|
|
84
|
+
}
|
|
85
|
+
Object.defineProperty(styles$1, groupName, {
|
|
86
|
+
value: group,
|
|
87
|
+
enumerable: false
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
Object.defineProperty(styles$1, "codes", {
|
|
91
|
+
value: codes,
|
|
92
|
+
enumerable: false
|
|
93
|
+
});
|
|
94
|
+
styles$1.color.close = "\x1B[39m";
|
|
95
|
+
styles$1.bgColor.close = "\x1B[49m";
|
|
96
|
+
styles$1.color.ansi = wrapAnsi16();
|
|
97
|
+
styles$1.color.ansi256 = wrapAnsi256();
|
|
98
|
+
styles$1.color.ansi16m = wrapAnsi16m();
|
|
99
|
+
styles$1.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
|
|
100
|
+
styles$1.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
|
101
|
+
styles$1.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
102
|
+
Object.defineProperties(styles$1, {
|
|
103
|
+
rgbToAnsi256: {
|
|
104
|
+
value(red, green, blue) {
|
|
105
|
+
if (red === green && green === blue) {
|
|
106
|
+
if (red < 8) return 16;
|
|
107
|
+
if (red > 248) return 231;
|
|
108
|
+
return Math.round((red - 8) / 247 * 24) + 232;
|
|
109
|
+
}
|
|
110
|
+
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
|
|
111
|
+
},
|
|
112
|
+
enumerable: false
|
|
113
|
+
},
|
|
114
|
+
hexToRgb: {
|
|
115
|
+
value(hex) {
|
|
116
|
+
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
|
117
|
+
if (!matches) return [
|
|
118
|
+
0,
|
|
119
|
+
0,
|
|
120
|
+
0
|
|
121
|
+
];
|
|
122
|
+
let [colorString] = matches;
|
|
123
|
+
if (colorString.length === 3) colorString = [...colorString].map((character) => character + character).join("");
|
|
124
|
+
const integer = Number.parseInt(colorString, 16);
|
|
125
|
+
return [
|
|
126
|
+
integer >> 16 & 255,
|
|
127
|
+
integer >> 8 & 255,
|
|
128
|
+
integer & 255
|
|
129
|
+
];
|
|
130
|
+
},
|
|
131
|
+
enumerable: false
|
|
132
|
+
},
|
|
133
|
+
hexToAnsi256: {
|
|
134
|
+
value: (hex) => styles$1.rgbToAnsi256(...styles$1.hexToRgb(hex)),
|
|
135
|
+
enumerable: false
|
|
136
|
+
},
|
|
137
|
+
ansi256ToAnsi: {
|
|
138
|
+
value(code) {
|
|
139
|
+
if (code < 8) return 30 + code;
|
|
140
|
+
if (code < 16) return 90 + (code - 8);
|
|
141
|
+
let red;
|
|
142
|
+
let green;
|
|
143
|
+
let blue;
|
|
144
|
+
if (code >= 232) {
|
|
145
|
+
red = ((code - 232) * 10 + 8) / 255;
|
|
146
|
+
green = red;
|
|
147
|
+
blue = red;
|
|
148
|
+
} else {
|
|
149
|
+
code -= 16;
|
|
150
|
+
const remainder = code % 36;
|
|
151
|
+
red = Math.floor(code / 36) / 5;
|
|
152
|
+
green = Math.floor(remainder / 6) / 5;
|
|
153
|
+
blue = remainder % 6 / 5;
|
|
154
|
+
}
|
|
155
|
+
const value = Math.max(red, green, blue) * 2;
|
|
156
|
+
if (value === 0) return 30;
|
|
157
|
+
let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
|
|
158
|
+
if (value === 2) result += 60;
|
|
159
|
+
return result;
|
|
160
|
+
},
|
|
161
|
+
enumerable: false
|
|
162
|
+
},
|
|
163
|
+
rgbToAnsi: {
|
|
164
|
+
value: (red, green, blue) => styles$1.ansi256ToAnsi(styles$1.rgbToAnsi256(red, green, blue)),
|
|
165
|
+
enumerable: false
|
|
166
|
+
},
|
|
167
|
+
hexToAnsi: {
|
|
168
|
+
value: (hex) => styles$1.ansi256ToAnsi(styles$1.hexToAnsi256(hex)),
|
|
169
|
+
enumerable: false
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
return styles$1;
|
|
173
|
+
}
|
|
174
|
+
const ansiStyles = assembleStyles();
|
|
175
|
+
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/supports-color/index.js
|
|
178
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process$1.argv) {
|
|
179
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
180
|
+
const position = argv.indexOf(prefix + flag);
|
|
181
|
+
const terminatorPosition = argv.indexOf("--");
|
|
182
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
183
|
+
}
|
|
184
|
+
const { env } = process$1;
|
|
185
|
+
let flagForceColor;
|
|
186
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) flagForceColor = 0;
|
|
187
|
+
else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) flagForceColor = 1;
|
|
188
|
+
function envForceColor() {
|
|
189
|
+
if ("FORCE_COLOR" in env) {
|
|
190
|
+
if (env.FORCE_COLOR === "true") return 1;
|
|
191
|
+
if (env.FORCE_COLOR === "false") return 0;
|
|
192
|
+
return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function translateLevel(level) {
|
|
196
|
+
if (level === 0) return false;
|
|
197
|
+
return {
|
|
198
|
+
level,
|
|
199
|
+
hasBasic: true,
|
|
200
|
+
has256: level >= 2,
|
|
201
|
+
has16m: level >= 3
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
205
|
+
const noFlagForceColor = envForceColor();
|
|
206
|
+
if (noFlagForceColor !== void 0) flagForceColor = noFlagForceColor;
|
|
207
|
+
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
208
|
+
if (forceColor === 0) return 0;
|
|
209
|
+
if (sniffFlags) {
|
|
210
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) return 3;
|
|
211
|
+
if (hasFlag("color=256")) return 2;
|
|
212
|
+
}
|
|
213
|
+
if ("TF_BUILD" in env && "AGENT_NAME" in env) return 1;
|
|
214
|
+
if (haveStream && !streamIsTTY && forceColor === void 0) return 0;
|
|
215
|
+
const min = forceColor || 0;
|
|
216
|
+
if (env.TERM === "dumb") return min;
|
|
217
|
+
if (process$1.platform === "win32") {
|
|
218
|
+
const osRelease = os.release().split(".");
|
|
219
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
220
|
+
return 1;
|
|
221
|
+
}
|
|
222
|
+
if ("CI" in env) {
|
|
223
|
+
if ([
|
|
224
|
+
"GITHUB_ACTIONS",
|
|
225
|
+
"GITEA_ACTIONS",
|
|
226
|
+
"CIRCLECI"
|
|
227
|
+
].some((key) => key in env)) return 3;
|
|
228
|
+
if ([
|
|
229
|
+
"TRAVIS",
|
|
230
|
+
"APPVEYOR",
|
|
231
|
+
"GITLAB_CI",
|
|
232
|
+
"BUILDKITE",
|
|
233
|
+
"DRONE"
|
|
234
|
+
].some((sign) => sign in env) || env.CI_NAME === "codeship") return 1;
|
|
235
|
+
return min;
|
|
236
|
+
}
|
|
237
|
+
if ("TEAMCITY_VERSION" in env) return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
238
|
+
if (env.COLORTERM === "truecolor") return 3;
|
|
239
|
+
if (env.TERM === "xterm-kitty") return 3;
|
|
240
|
+
if (env.TERM === "xterm-ghostty") return 3;
|
|
241
|
+
if (env.TERM === "wezterm") return 3;
|
|
242
|
+
if ("TERM_PROGRAM" in env) {
|
|
243
|
+
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
244
|
+
switch (env.TERM_PROGRAM) {
|
|
245
|
+
case "iTerm.app": return version >= 3 ? 3 : 2;
|
|
246
|
+
case "Apple_Terminal": return 2;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (/-256(color)?$/i.test(env.TERM)) return 2;
|
|
250
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) return 1;
|
|
251
|
+
if ("COLORTERM" in env) return 1;
|
|
252
|
+
return min;
|
|
253
|
+
}
|
|
254
|
+
function createSupportsColor(stream, options = {}) {
|
|
255
|
+
return translateLevel(_supportsColor(stream, {
|
|
256
|
+
streamIsTTY: stream && stream.isTTY,
|
|
257
|
+
...options
|
|
258
|
+
}));
|
|
259
|
+
}
|
|
260
|
+
const supportsColor = {
|
|
261
|
+
stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
|
|
262
|
+
stderr: createSupportsColor({ isTTY: tty.isatty(2) })
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
//#endregion
|
|
266
|
+
//#region ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/utilities.js
|
|
267
|
+
function stringReplaceAll(string, substring, replacer) {
|
|
268
|
+
let index = string.indexOf(substring);
|
|
269
|
+
if (index === -1) return string;
|
|
270
|
+
const substringLength = substring.length;
|
|
271
|
+
let endIndex = 0;
|
|
272
|
+
let returnValue = "";
|
|
273
|
+
do {
|
|
274
|
+
returnValue += string.slice(endIndex, index) + substring + replacer;
|
|
275
|
+
endIndex = index + substringLength;
|
|
276
|
+
index = string.indexOf(substring, endIndex);
|
|
277
|
+
} while (index !== -1);
|
|
278
|
+
returnValue += string.slice(endIndex);
|
|
279
|
+
return returnValue;
|
|
280
|
+
}
|
|
281
|
+
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
282
|
+
let endIndex = 0;
|
|
283
|
+
let returnValue = "";
|
|
284
|
+
do {
|
|
285
|
+
const gotCR = string[index - 1] === "\r";
|
|
286
|
+
returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
|
|
287
|
+
endIndex = index + 1;
|
|
288
|
+
index = string.indexOf("\n", endIndex);
|
|
289
|
+
} while (index !== -1);
|
|
290
|
+
returnValue += string.slice(endIndex);
|
|
291
|
+
return returnValue;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
//#endregion
|
|
295
|
+
//#region ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/index.js
|
|
296
|
+
const { stdout: stdoutColor, stderr: stderrColor } = supportsColor;
|
|
297
|
+
const GENERATOR = Symbol("GENERATOR");
|
|
298
|
+
const STYLER = Symbol("STYLER");
|
|
299
|
+
const IS_EMPTY = Symbol("IS_EMPTY");
|
|
300
|
+
const levelMapping = [
|
|
301
|
+
"ansi",
|
|
302
|
+
"ansi",
|
|
303
|
+
"ansi256",
|
|
304
|
+
"ansi16m"
|
|
305
|
+
];
|
|
306
|
+
const styles = Object.create(null);
|
|
307
|
+
const applyOptions = (object, options = {}) => {
|
|
308
|
+
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");
|
|
309
|
+
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
|
310
|
+
object.level = options.level === void 0 ? colorLevel : options.level;
|
|
311
|
+
};
|
|
312
|
+
const chalkFactory = (options) => {
|
|
313
|
+
const chalk = (...strings) => strings.join(" ");
|
|
314
|
+
applyOptions(chalk, options);
|
|
315
|
+
Object.setPrototypeOf(chalk, createChalk.prototype);
|
|
316
|
+
return chalk;
|
|
317
|
+
};
|
|
318
|
+
function createChalk(options) {
|
|
319
|
+
return chalkFactory(options);
|
|
320
|
+
}
|
|
321
|
+
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
|
|
322
|
+
for (const [styleName, style] of Object.entries(ansiStyles)) styles[styleName] = { get() {
|
|
323
|
+
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
|
|
324
|
+
Object.defineProperty(this, styleName, { value: builder });
|
|
325
|
+
return builder;
|
|
326
|
+
} };
|
|
327
|
+
styles.visible = { get() {
|
|
328
|
+
const builder = createBuilder(this, this[STYLER], true);
|
|
329
|
+
Object.defineProperty(this, "visible", { value: builder });
|
|
330
|
+
return builder;
|
|
331
|
+
} };
|
|
332
|
+
const getModelAnsi = (model, level, type, ...arguments_) => {
|
|
333
|
+
if (model === "rgb") {
|
|
334
|
+
if (level === "ansi16m") return ansiStyles[type].ansi16m(...arguments_);
|
|
335
|
+
if (level === "ansi256") return ansiStyles[type].ansi256(ansiStyles.rgbToAnsi256(...arguments_));
|
|
336
|
+
return ansiStyles[type].ansi(ansiStyles.rgbToAnsi(...arguments_));
|
|
337
|
+
}
|
|
338
|
+
if (model === "hex") return getModelAnsi("rgb", level, type, ...ansiStyles.hexToRgb(...arguments_));
|
|
339
|
+
return ansiStyles[type][model](...arguments_);
|
|
340
|
+
};
|
|
341
|
+
for (const model of [
|
|
342
|
+
"rgb",
|
|
343
|
+
"hex",
|
|
344
|
+
"ansi256"
|
|
345
|
+
]) {
|
|
346
|
+
styles[model] = { get() {
|
|
347
|
+
const { level } = this;
|
|
348
|
+
return function(...arguments_) {
|
|
349
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansiStyles.color.close, this[STYLER]);
|
|
350
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
351
|
+
};
|
|
352
|
+
} };
|
|
353
|
+
const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
|
|
354
|
+
styles[bgModel] = { get() {
|
|
355
|
+
const { level } = this;
|
|
356
|
+
return function(...arguments_) {
|
|
357
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansiStyles.bgColor.close, this[STYLER]);
|
|
358
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
359
|
+
};
|
|
360
|
+
} };
|
|
361
|
+
}
|
|
362
|
+
const proto = Object.defineProperties(() => {}, {
|
|
363
|
+
...styles,
|
|
364
|
+
level: {
|
|
365
|
+
enumerable: true,
|
|
366
|
+
get() {
|
|
367
|
+
return this[GENERATOR].level;
|
|
368
|
+
},
|
|
369
|
+
set(level) {
|
|
370
|
+
this[GENERATOR].level = level;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
const createStyler = (open, close, parent) => {
|
|
375
|
+
let openAll;
|
|
376
|
+
let closeAll;
|
|
377
|
+
if (parent === void 0) {
|
|
378
|
+
openAll = open;
|
|
379
|
+
closeAll = close;
|
|
380
|
+
} else {
|
|
381
|
+
openAll = parent.openAll + open;
|
|
382
|
+
closeAll = close + parent.closeAll;
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
open,
|
|
386
|
+
close,
|
|
387
|
+
openAll,
|
|
388
|
+
closeAll,
|
|
389
|
+
parent
|
|
390
|
+
};
|
|
391
|
+
};
|
|
392
|
+
const createBuilder = (self, _styler, _isEmpty) => {
|
|
393
|
+
const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
|
|
394
|
+
Object.setPrototypeOf(builder, proto);
|
|
395
|
+
builder[GENERATOR] = self;
|
|
396
|
+
builder[STYLER] = _styler;
|
|
397
|
+
builder[IS_EMPTY] = _isEmpty;
|
|
398
|
+
return builder;
|
|
399
|
+
};
|
|
400
|
+
const applyStyle = (self, string) => {
|
|
401
|
+
if (self.level <= 0 || !string) return self[IS_EMPTY] ? "" : string;
|
|
402
|
+
let styler = self[STYLER];
|
|
403
|
+
if (styler === void 0) return string;
|
|
404
|
+
const { openAll, closeAll } = styler;
|
|
405
|
+
if (string.includes("\x1B")) while (styler !== void 0) {
|
|
406
|
+
string = stringReplaceAll(string, styler.close, styler.open);
|
|
407
|
+
styler = styler.parent;
|
|
408
|
+
}
|
|
409
|
+
const lfIndex = string.indexOf("\n");
|
|
410
|
+
if (lfIndex !== -1) string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
|
|
411
|
+
return openAll + string + closeAll;
|
|
412
|
+
};
|
|
413
|
+
Object.defineProperties(createChalk.prototype, styles);
|
|
414
|
+
const chalk = createChalk();
|
|
415
|
+
const chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
416
|
+
|
|
417
|
+
//#endregion
|
|
11
418
|
//#region src/formatters/terminal.ts
|
|
12
419
|
const printCodeFrame = (content, line, severityColor) => {
|
|
13
420
|
if (!content || !line) return;
|
|
@@ -108,7 +515,7 @@ const getWhaleMascot = (score, border) => {
|
|
|
108
515
|
];
|
|
109
516
|
};
|
|
110
517
|
const easeOutCubic = (x) => 1 - (1 - x) ** 3;
|
|
111
|
-
const printScoreBox = async (score, label, categoryIssueCounts) => {
|
|
518
|
+
const printScoreBox = async (score, label, categoryIssueCounts, warningsCount, errorsCount) => {
|
|
112
519
|
const { isTTY } = process.stdout;
|
|
113
520
|
const shouldAnimate = isTTY && !process.env.CI && !process.env.NO_ANIMATION && process.env.TERM !== "dumb" && process.env.NODE_ENV !== "test";
|
|
114
521
|
let scoreColor = chalk.red.bold;
|
|
@@ -116,7 +523,7 @@ const printScoreBox = async (score, label, categoryIssueCounts) => {
|
|
|
116
523
|
else if (score >= 75) scoreColor = chalk.yellow.bold;
|
|
117
524
|
else if (score >= 50) scoreColor = chalk.magenta.bold;
|
|
118
525
|
const whaleLines = getWhaleMascot(score, scoreColor);
|
|
119
|
-
const shareUrl = `https://
|
|
526
|
+
const shareUrl = `https://docker-doctor.vercel.app/share?s=${score}&w=${warningsCount}&e=${errorsCount}`;
|
|
120
527
|
if (shouldAnimate) {
|
|
121
528
|
const frameCount = 20;
|
|
122
529
|
const frameDelay = 15;
|
|
@@ -130,7 +537,7 @@ const printScoreBox = async (score, label, categoryIssueCounts) => {
|
|
|
130
537
|
const bar = scoreColor("█".repeat(filledBlocks)) + chalk.dim("░".repeat(emptyBlocks));
|
|
131
538
|
if (frame > 0) process.stdout.write("\x1B[4A\r");
|
|
132
539
|
else console.log();
|
|
133
|
-
process.stdout.write(` ${whaleLines[0]} ${scoreColor(`${currentScore} / 100`)} ${scoreColor(label)}\n ${whaleLines[1]} ${bar}\n ${whaleLines[2]} ${chalk.dim("Docker Doctor (https://
|
|
540
|
+
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`);
|
|
134
541
|
if (frame < frameCount) await setTimeout(frameDelay);
|
|
135
542
|
}
|
|
136
543
|
} finally {
|
|
@@ -142,13 +549,13 @@ const printScoreBox = async (score, label, categoryIssueCounts) => {
|
|
|
142
549
|
const bar = scoreColor("█".repeat(filledBlocks)) + chalk.dim("░".repeat(emptyBlocks));
|
|
143
550
|
console.log(`\n ${whaleLines[0]} ${scoreColor(`${score} / 100`)} ${scoreColor(label)}`);
|
|
144
551
|
console.log(` ${whaleLines[1]} ${bar}`);
|
|
145
|
-
console.log(` ${whaleLines[2]} ${chalk.dim("Docker Doctor (https://
|
|
552
|
+
console.log(` ${whaleLines[2]} ${chalk.dim("Docker Doctor (https://docker-doctor.vercel.app)")}`);
|
|
146
553
|
console.log(` ${whaleLines[3]}`);
|
|
147
554
|
}
|
|
148
555
|
console.log(`\n ${chalk.dim("────────────────────────────────────────────────────────────")}\n`);
|
|
149
556
|
console.log(` Share: ${chalk.cyan(shareUrl)}`);
|
|
150
557
|
console.log(` Tell others how you did on socials\n`);
|
|
151
|
-
console.log(` Docs: ${chalk.cyan("https://
|
|
558
|
+
console.log(` Docs: ${chalk.cyan("https://docker-doctor.vercel.app")}`);
|
|
152
559
|
console.log(` Learn more about fixing issues, setting up CI/CD, and`);
|
|
153
560
|
console.log(` configuring rules with a config file\n`);
|
|
154
561
|
console.log(` GitHub: ${chalk.cyan("https://github.com/PunGrumpy/docker-doctor")}`);
|
|
@@ -167,12 +574,16 @@ const formatTerminal = async (diagnostics, score, label, project, verbose = fals
|
|
|
167
574
|
Performance: 0,
|
|
168
575
|
Security: 0
|
|
169
576
|
};
|
|
577
|
+
let warningsCount = 0;
|
|
578
|
+
let errorsCount = 0;
|
|
170
579
|
for (const d of diagnostics) {
|
|
171
580
|
const category = findRule(d.rule)?.category || "Best Practices";
|
|
172
581
|
categoryIssueCounts[category] = (categoryIssueCounts[category] || 0) + 1;
|
|
582
|
+
if (d.severity === "warning") warningsCount += 1;
|
|
583
|
+
else if (d.severity === "error") errorsCount += 1;
|
|
173
584
|
}
|
|
174
585
|
printDiagnostics(diagnostics, verbose, fileContents, categoryIssueCounts);
|
|
175
|
-
await printScoreBox(score, label, categoryIssueCounts);
|
|
586
|
+
await printScoreBox(score, label, categoryIssueCounts, warningsCount, errorsCount);
|
|
176
587
|
};
|
|
177
588
|
|
|
178
589
|
//#endregion
|
|
@@ -431,18 +842,19 @@ program.argument("[dir]", "directory to scan", ".").option("-v, --verbose", "sho
|
|
|
431
842
|
if (process.stdout.isTTY && !isSilent) console.log(`${chalk.green("✔")} Scanned ${projectFilesList.length} files in ${duration}s [~${concurrency} workers]`);
|
|
432
843
|
if (options.score) {
|
|
433
844
|
console.log(score);
|
|
434
|
-
process.
|
|
845
|
+
process.exitCode = score < 50 ? 1 : 0;
|
|
846
|
+
return;
|
|
435
847
|
} else if (options.json) {
|
|
436
848
|
const report = toJsonReport(filteredDiagnostics, score, label, project);
|
|
437
849
|
console.log(JSON.stringify(report, null, 2));
|
|
438
850
|
const hasErrors = filteredDiagnostics.some((d) => d.severity === "error");
|
|
439
|
-
process.
|
|
440
|
-
|
|
441
|
-
await formatTerminal(filteredDiagnostics, score, label, project, options.verbose, fileContents);
|
|
442
|
-
const hasErrors = filteredDiagnostics.some((d) => d.severity === "error");
|
|
443
|
-
if (process.stdout.isTTY && process.stdin.isTTY) await runInteractiveWizard();
|
|
444
|
-
process.exit(hasErrors ? 1 : 0);
|
|
851
|
+
process.exitCode = hasErrors ? 1 : 0;
|
|
852
|
+
return;
|
|
445
853
|
}
|
|
854
|
+
await formatTerminal(filteredDiagnostics, score, label, project, options.verbose, fileContents);
|
|
855
|
+
const hasErrors = filteredDiagnostics.some((d) => d.severity === "error");
|
|
856
|
+
if (process.stdout.isTTY && process.stdin.isTTY) await runInteractiveWizard();
|
|
857
|
+
process.exitCode = hasErrors ? 1 : 0;
|
|
446
858
|
} finally {
|
|
447
859
|
if (spinnerInterval !== null) {
|
|
448
860
|
clearInterval(spinnerInterval);
|