@docker-doctor/cli 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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-DvNFg6Nz.mjs";
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 chalk from "chalk";
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;
@@ -148,7 +555,7 @@ const printScoreBox = async (score, label, categoryIssueCounts, warningsCount, e
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://github.com/PunGrumpy/docker-doctor/docs")}`);
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")}`);
@@ -435,18 +842,19 @@ program.argument("[dir]", "directory to scan", ".").option("-v, --verbose", "sho
435
842
  if (process.stdout.isTTY && !isSilent) console.log(`${chalk.green("✔")} Scanned ${projectFilesList.length} files in ${duration}s [~${concurrency} workers]`);
436
843
  if (options.score) {
437
844
  console.log(score);
438
- process.exit(score < 50 ? 1 : 0);
845
+ process.exitCode = score < 50 ? 1 : 0;
846
+ return;
439
847
  } else if (options.json) {
440
848
  const report = toJsonReport(filteredDiagnostics, score, label, project);
441
849
  console.log(JSON.stringify(report, null, 2));
442
850
  const hasErrors = filteredDiagnostics.some((d) => d.severity === "error");
443
- process.exit(hasErrors ? 1 : 0);
444
- } else {
445
- await formatTerminal(filteredDiagnostics, score, label, project, options.verbose, fileContents);
446
- const hasErrors = filteredDiagnostics.some((d) => d.severity === "error");
447
- if (process.stdout.isTTY && process.stdin.isTTY) await runInteractiveWizard();
448
- process.exit(hasErrors ? 1 : 0);
851
+ process.exitCode = hasErrors ? 1 : 0;
852
+ return;
449
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;
450
858
  } finally {
451
859
  if (spinnerInterval !== null) {
452
860
  clearInterval(spinnerInterval);