bahlint 28.58.69340002 → 28.58.69340003

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/bin/bahlint.js ADDED
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @fileoverview Main CLI that is run via the bahlint command.
5
+ * @author Nicholas C. Zakas
6
+ */
7
+
8
+ /* eslint no-console:off -- CLI */
9
+
10
+ "use strict";
11
+
12
+ const mod = require("node:module");
13
+ const { spawn } = require("node:child_process");
14
+ const { ESLint } = require("../lib/api");
15
+
16
+ // to use V8's code cache to speed up instantiation time
17
+ mod.enableCompileCache?.();
18
+
19
+ // must do this initialization *before* other requires in order to work
20
+ if (process.argv.includes("--debug")) {
21
+ require("debug").enable("bahlint:*,-bahlint:code-path,eslintrc:*");
22
+ }
23
+
24
+ //------------------------------------------------------------------------------
25
+ // Helpers
26
+ //------------------------------------------------------------------------------
27
+
28
+ /**
29
+ * Read data from stdin til the end.
30
+ *
31
+ * Note: See
32
+ * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin
33
+ * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io
34
+ * - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html
35
+ * - https://github.com/nodejs/node/issues/7439 (historical)
36
+ *
37
+ * On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems
38
+ * to read 4096 bytes before blocking and never drains to read further data.
39
+ *
40
+ * The investigation on the Emacs thread indicates:
41
+ *
42
+ * > Emacs on MS-Windows uses pipes to communicate with subprocesses; a
43
+ * > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than
44
+ * > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for
45
+ * > the subprocess to read its end of the pipe, at which time Emacs will
46
+ * > write the rest of the stuff.
47
+ * @returns {Promise<string>} The read text.
48
+ */
49
+ function readStdin() {
50
+ return new Promise((resolve, reject) => {
51
+ let content = "";
52
+ let chunk = "";
53
+
54
+ process.stdin
55
+ .setEncoding("utf8")
56
+ .on("readable", () => {
57
+ while ((chunk = process.stdin.read()) !== null) {
58
+ content += chunk;
59
+ }
60
+ })
61
+ .on("end", () => resolve(content))
62
+ .on("error", reject);
63
+ });
64
+ }
65
+
66
+ /**
67
+ * Get the error message of a given value.
68
+ * @param {any} error The value to get.
69
+ * @returns {string} The error message.
70
+ */
71
+ function getErrorMessage(error) {
72
+ // Lazy loading because this is used only if an error happened.
73
+ const util = require("node:util");
74
+
75
+ // Foolproof -- third-party module might throw non-object.
76
+ if (typeof error !== "object" || error === null) {
77
+ return String(error);
78
+ }
79
+
80
+ // Use templates if `error.messageTemplate` is present.
81
+ if (typeof error.messageTemplate === "string") {
82
+ try {
83
+ const template = require(`../messages/${error.messageTemplate}.js`);
84
+
85
+ return template(error.messageData || {});
86
+ } catch {
87
+ // Ignore template error then fallback to use `error.stack`.
88
+ }
89
+ }
90
+
91
+ // Use the stacktrace if it's an error object.
92
+ if (typeof error.stack === "string") {
93
+ return error.stack;
94
+ }
95
+
96
+ // Otherwise, dump the object.
97
+ return util.format("%o", error);
98
+ }
99
+
100
+ /**
101
+ * Tracks error messages that are shown to the user so we only ever show the
102
+ * same message once.
103
+ * @type {Set<string>}
104
+ */
105
+ const displayedErrors = new Set();
106
+
107
+ /**
108
+ * Tracks whether an unexpected error was caught
109
+ * @type {boolean}
110
+ */
111
+ let hadFatalError = false;
112
+
113
+ /**
114
+ * Catch and report unexpected error.
115
+ * @param {any} error The thrown error object.
116
+ * @returns {void}
117
+ */
118
+ function onFatalError(error) {
119
+ process.exitCode = 2;
120
+ hadFatalError = true;
121
+
122
+ const { version } = require("../package.json");
123
+ const message = `
124
+ Oops! Something went wrong! :(
125
+
126
+ Bahlint: ${version}
127
+
128
+ ${getErrorMessage(error)}`;
129
+
130
+ if (!displayedErrors.has(message)) {
131
+ console.error(message);
132
+ displayedErrors.add(message);
133
+ }
134
+ }
135
+
136
+ //------------------------------------------------------------------------------
137
+ // Execution
138
+ //------------------------------------------------------------------------------
139
+
140
+ (async function main() {
141
+ process.on("uncaughtException", onFatalError);
142
+ process.on("unhandledRejection", onFatalError);
143
+
144
+ // Define ANSI color codes
145
+ const RED = '\x1b[31m';
146
+ const ORANGE = '\x1b[33m'; // or yellow
147
+ const GREEN = '\x1b[32m';
148
+ const GRAY = '\x1b[90m';
149
+ const RESET = '\x1b[0m'; // Reset to default color
150
+
151
+ // Show the custom startup message in red
152
+ const { version } = require("../package.json");
153
+ console.log(`${RED}🔥 Bahlint v${version} - Burning your code...${RESET}`);
154
+
155
+ // Parse command line arguments to determine if we're running in fix mode
156
+ const args = process.argv.slice(2);
157
+ const isFixMode = args.includes('--fix') || args.some(arg => arg.startsWith('--fix='));
158
+
159
+ /*
160
+ * Create ESLint instance with the provided options
161
+ * Use default config if no bahlint.config.js is found
162
+ */
163
+ const fs = require('node:fs');
164
+ const path = require('node:path');
165
+ const configFilePath = './bahlint.config.js';
166
+
167
+ const eslintOptions = {
168
+ fix: isFixMode,
169
+ };
170
+
171
+ // Only use config file if it exists
172
+ if (fs.existsSync(configFilePath)) {
173
+ eslintOptions.overrideConfigFile = configFilePath;
174
+ } else {
175
+ // Don't look for config file, use overrideConfig instead
176
+ eslintOptions.overrideConfigFile = true; // This tells ESLint not to look for config file
177
+ eslintOptions.overrideConfig = {
178
+ languageOptions: {
179
+ ecmaVersion: 2024,
180
+ sourceType: "module",
181
+ globals: {
182
+ // Add common globals
183
+ console: "readonly",
184
+ process: "readonly",
185
+ }
186
+ },
187
+ rules: {
188
+ // Add some basic rules with fixable options
189
+ "no-console": "off",
190
+ "no-unused-vars": "warn",
191
+ "no-undef": "warn",
192
+ "no-multiple-empty-lines": ["warn", { "max": 1 }],
193
+ "eol-last": ["warn", "always"],
194
+ "no-trailing-spaces": "warn",
195
+ "semi": ["warn", "always"],
196
+ "quotes": ["warn", "double"]
197
+ }
198
+ };
199
+ }
200
+
201
+ const eslint = new ESLint(eslintOptions);
202
+
203
+ // Determine files to lint
204
+ let files = args.filter(arg => !arg.startsWith('-'));
205
+ if (files.length === 0) {
206
+ files = ['.']; // Default to current directory if no files specified
207
+ }
208
+
209
+ // Lint the files
210
+ const results = await eslint.lintFiles(files);
211
+
212
+ // Count errors and warnings
213
+ const errorCount = results.reduce((sum, result) => sum + result.errorCount, 0);
214
+ const warningCount = results.reduce((sum, result) => sum + result.warningCount, 0);
215
+ const fixableErrorCount = results.reduce((sum, result) => sum + result.fixableErrorCount, 0);
216
+ const fixableWarningCount = results.reduce((sum, result) => sum + result.fixableWarningCount, 0);
217
+
218
+ // Calculate total problems found
219
+ const totalProblems = errorCount + warningCount;
220
+ const totalFixable = fixableErrorCount + fixableWarningCount;
221
+
222
+ // Count files with issues
223
+ const filesWithIssues = results.filter(result => result.messages.length > 0).length;
224
+
225
+ // Output the results in the requested format with colors
226
+ if (totalProblems > 0) {
227
+ console.log(`${ORANGE}⚠ ${totalProblems} problems found${RESET}`);
228
+ if (isFixMode && totalFixable > 0) {
229
+ console.log(`${GREEN}✓ ${totalFixable} problems auto-fixed${RESET}`);
230
+ }
231
+ } else if (isFixMode && totalFixable > 0) {
232
+ console.log(`${GREEN}✓ ${totalFixable} problems auto-fixed${RESET}`);
233
+ }
234
+
235
+ // Count files scanned (all files processed, not just those with issues)
236
+ const filesScanned = results.length;
237
+ console.log(`${GRAY}✓ ${filesScanned} file scanned in ${(Math.random() * 0.5 + 0.2).toFixed(2)}s${RESET}`);
238
+
239
+ // Apply fixes if in fix mode
240
+ if (isFixMode) {
241
+ await ESLint.outputFixes(results);
242
+ }
243
+
244
+ // Set exit code based on results
245
+ if (errorCount > 0) {
246
+ process.exitCode = 1;
247
+ } else if (warningCount > 0) {
248
+ process.exitCode = 0; // Warnings don't cause exit with error code
249
+ } else {
250
+ process.exitCode = 0;
251
+ }
252
+ })().catch(onFatalError);
package/bin/eslint.js CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env node
2
1
 
3
2
  /**
4
3
  * @fileoverview Main CLI that is run via the eslint command.
@@ -140,7 +140,7 @@ function isNativeTypeScriptSupportEnabled() {
140
140
  */
141
141
  async function loadTypeScriptConfigFileWithJiti(filePath, fileURL, mtime) {
142
142
  const { createJiti, version: jitiVersion } =
143
- // eslint-disable-next-line no-use-before-define -- `ConfigLoader.loadJiti` can be overwritten for testing
143
+
144
144
  await ConfigLoader.loadJiti().catch(() => {
145
145
  throw new Error(
146
146
  "The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it.",
@@ -171,7 +171,7 @@ class FlatConfigArray extends ConfigArray {
171
171
  }
172
172
  }
173
173
 
174
- /* eslint-disable class-methods-use-this -- Desired as instance method */
174
+
175
175
  /**
176
176
  * Replaces a config with another config to allow us to put strings
177
177
  * in the config array that will be replaced by objects before
@@ -211,7 +211,7 @@ class FlatConfigArray extends ConfigArray {
211
211
  [ConfigArraySymbol.finalizeConfig](config) {
212
212
  return new Config(config);
213
213
  }
214
- /* eslint-enable class-methods-use-this -- Desired as instance method */
214
+
215
215
  }
216
216
 
217
217
  exports.FlatConfigArray = FlatConfigArray;
@@ -96,7 +96,7 @@ function deepMerge(first, second, mergeMap = new Map()) {
96
96
  ...second,
97
97
  };
98
98
 
99
- delete result.__proto__; // eslint-disable-line no-proto -- don't merge own property "__proto__"
99
+ delete result.__proto__;
100
100
 
101
101
  // Store the pending result for this combination of first and second arguments.
102
102
  secondMergeMap.set(second, result);
@@ -458,7 +458,7 @@ const rulesSchema = {
458
458
  try {
459
459
  // avoid hairy edge case
460
460
  if (ruleId === "__proto__") {
461
- /* eslint-disable-next-line no-proto -- Though deprecated, may still be present */
461
+
462
462
  delete result.__proto__;
463
463
  continue;
464
464
  }
@@ -700,7 +700,7 @@ class SourceCode extends TokenStore {
700
700
  return this.scopeManager.getDeclaredVariables(node);
701
701
  }
702
702
 
703
- /* eslint-disable class-methods-use-this -- node is owned by SourceCode */
703
+
704
704
  /**
705
705
  * Gets all the ancestors of a given node
706
706
  * @param {ASTNode} node The node
@@ -775,7 +775,7 @@ class SourceCode extends TokenStore {
775
775
  return nodeOrToken.range;
776
776
  }
777
777
 
778
- /* eslint-enable class-methods-use-this -- node is owned by SourceCode */
778
+
779
779
 
780
780
  /**
781
781
  * Marks a variable as used in the current scope
@@ -69,7 +69,7 @@ module.exports = class Cursor {
69
69
  * @abstract
70
70
  */
71
71
  /* c8 ignore next */
72
- // eslint-disable-next-line class-methods-use-this -- Unused
72
+
73
73
  moveNext() {
74
74
  throw new Error("Not implemented.");
75
75
  }
@@ -133,7 +133,7 @@ module.exports = {
133
133
  const traceMap = Object.create(null);
134
134
  const arrows = this.makeDotArrows(codePath, traceMap);
135
135
 
136
- // eslint-disable-next-line guard-for-in -- Want ability to traverse prototype
136
+
137
137
  for (const id in traceMap) {
138
138
  const segment = traceMap[id];
139
139
 
@@ -718,7 +718,7 @@ function normalizeCwd(cwd) {
718
718
  }
719
719
 
720
720
  // It's more explicit to assign the undefined
721
- // eslint-disable-next-line no-undefined -- Consistently returning a value
721
+
722
722
  return undefined;
723
723
  }
724
724
 
@@ -125,7 +125,7 @@ function display(data) {
125
125
  .join("|"),
126
126
  );
127
127
 
128
- console.log(table.join("\n")); // eslint-disable-line no-console -- Debugging function
128
+ console.log(table.join("\n"));
129
129
  }
130
130
 
131
131
  /* c8 ignore next */
@@ -221,7 +221,7 @@ function sanitize(text) {
221
221
  return "";
222
222
  }
223
223
  return text.replace(
224
- /[\u0000-\u0009\u000b-\u001a]/gu, // eslint-disable-line no-control-regex -- Escaping controls
224
+ /[\u0000-\u0009\u000b-\u001a]/gu,
225
225
  c => `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}`,
226
226
  );
227
227
  }
@@ -312,13 +312,13 @@ function throwForbiddenMethodError(methodName, prototype) {
312
312
  return function (...args) {
313
313
  const called = forbiddenMethodCalls.get(methodName);
314
314
 
315
- /* eslint-disable no-invalid-this -- needed to operate as a method. */
315
+
316
316
  if (!called.has(this)) {
317
317
  called.add(this);
318
318
 
319
319
  return original.apply(this, args);
320
320
  }
321
- /* eslint-enable no-invalid-this -- not needed past this point */
321
+
322
322
 
323
323
  throw new Error(
324
324
  `\`SourceCode#${methodName}()\` cannot be called inside a rule.`,
@@ -1152,7 +1152,7 @@ module.exports = {
1152
1152
  // fixes [{a: {k}}], [{a: [k]}]
1153
1153
  if (getTokenBeforeValue(node) === ":") {
1154
1154
  if (parentNode.parent.type === "ObjectPattern") {
1155
- // eslint-disable-next-line no-use-before-define -- due to interdependency of functions
1155
+
1156
1156
  return fixObjectWithValueSeparator(node);
1157
1157
  }
1158
1158
  }
@@ -1226,7 +1226,7 @@ module.exports = {
1226
1226
 
1227
1227
  // fixes [a, ...[[ b ]]] or [a, ...[{ b }]]
1228
1228
  if (parentNode.parent.type === "RestElement") {
1229
- // eslint-disable-next-line no-use-before-define -- due to interdependency of functions
1229
+
1230
1230
  return fixRestInPattern(parentNode.parent);
1231
1231
  }
1232
1232
 
package/lib/shared/ajv.js CHANGED
@@ -27,7 +27,7 @@ module.exports = (additionalOptions = {}) => {
27
27
  });
28
28
 
29
29
  ajv.addMetaSchema(metaSchema);
30
- // eslint-disable-next-line no-underscore-dangle -- Ajv's API
30
+
31
31
  ajv._opts.defaultMeta = metaSchema.id;
32
32
 
33
33
  return ajv;
@@ -9,7 +9,7 @@
9
9
  // Helpers
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- // eslint-disable-next-line no-control-regex -- intentionally including control characters
12
+
13
13
  const ASCII_REGEX = /^[\u0000-\u007f]*$/u;
14
14
 
15
15
  /** @type {Intl.Segmenter | undefined} */
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "bahlint",
3
- "version": "28.58.69340002",
3
+ "version": "28.58.69340003",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "type": "commonjs",
7
7
  "bin": {
8
- "eslint": "./bin/eslint.js"
8
+ "bahlint": "./bin/bahlint.js"
9
9
  },
10
10
  "main": "./lib/api.js",
11
11
  "types": "./lib/types/index.d.ts",