xo 2.0.2 → 3.0.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.d.ts +0 -59
- package/dist/cli.js +139 -88
- package/dist/lib/config.js +2 -407
- package/dist/lib/constants.d.ts +1 -8
- package/dist/lib/constants.js +1 -18
- package/dist/lib/eslint-adapter.d.ts +3 -0
- package/dist/lib/eslint-adapter.js +58 -0
- package/dist/lib/handle-ts-files.d.ts +4 -1
- package/dist/lib/handle-ts-files.js +34 -5
- package/dist/lib/resolve-config.js +8 -7
- package/dist/lib/types.d.ts +10 -5
- package/dist/lib/utils.d.ts +10 -3
- package/dist/lib/utils.js +46 -31
- package/dist/lib/xo-to-eslint.d.ts +2 -6
- package/dist/lib/xo-to-eslint.js +31 -77
- package/dist/lib/xo.d.ts +21 -88
- package/dist/lib/xo.js +383 -261
- package/package.json +25 -64
- package/readme.md +135 -59
- package/dist/lib/rules/no-use-extend-native.d.ts +0 -3
- package/dist/lib/rules/no-use-extend-native.js +0 -386
package/dist/cli.d.ts
CHANGED
|
@@ -1,61 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
declare const cli: import("meow").Result<{
|
|
3
|
-
fix: {
|
|
4
|
-
type: "boolean";
|
|
5
|
-
default: false;
|
|
6
|
-
};
|
|
7
|
-
fixDryRun: {
|
|
8
|
-
type: "boolean";
|
|
9
|
-
default: false;
|
|
10
|
-
};
|
|
11
|
-
reporter: {
|
|
12
|
-
type: "string";
|
|
13
|
-
};
|
|
14
|
-
space: {
|
|
15
|
-
type: "string";
|
|
16
|
-
};
|
|
17
|
-
configPath: {
|
|
18
|
-
type: "string";
|
|
19
|
-
aliases: string[];
|
|
20
|
-
};
|
|
21
|
-
quiet: {
|
|
22
|
-
type: "boolean";
|
|
23
|
-
};
|
|
24
|
-
semicolon: {
|
|
25
|
-
type: "boolean";
|
|
26
|
-
};
|
|
27
|
-
prettier: {
|
|
28
|
-
type: "boolean";
|
|
29
|
-
};
|
|
30
|
-
react: {
|
|
31
|
-
type: "boolean";
|
|
32
|
-
default: false;
|
|
33
|
-
};
|
|
34
|
-
cwd: {
|
|
35
|
-
type: "string";
|
|
36
|
-
default: string;
|
|
37
|
-
};
|
|
38
|
-
printConfig: {
|
|
39
|
-
type: "string";
|
|
40
|
-
};
|
|
41
|
-
version: {
|
|
42
|
-
type: "boolean";
|
|
43
|
-
};
|
|
44
|
-
stdin: {
|
|
45
|
-
type: "boolean";
|
|
46
|
-
};
|
|
47
|
-
stdinFilename: {
|
|
48
|
-
type: "string";
|
|
49
|
-
default: string;
|
|
50
|
-
};
|
|
51
|
-
open: {
|
|
52
|
-
type: "boolean";
|
|
53
|
-
};
|
|
54
|
-
ignore: {
|
|
55
|
-
type: "string";
|
|
56
|
-
isMultiple: true;
|
|
57
|
-
aliases: string[];
|
|
58
|
-
};
|
|
59
|
-
}>;
|
|
60
|
-
export type CliOptions = typeof cli;
|
|
61
2
|
export {};
|
package/dist/cli.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import fs from 'node:fs/promises';
|
|
4
4
|
import process from 'node:process';
|
|
5
|
+
import { ESLint } from 'eslint';
|
|
5
6
|
import formatterPretty from 'eslint-formatter-pretty';
|
|
6
7
|
import getStdin from 'get-stdin';
|
|
7
8
|
import meow from 'meow';
|
|
@@ -10,27 +11,29 @@ import findCacheDirectory from 'find-cache-directory';
|
|
|
10
11
|
import { cacheDirName, tsExtensions } from './lib/constants.js';
|
|
11
12
|
import { Xo } from './lib/xo.js';
|
|
12
13
|
import openReport from './lib/open-report.js';
|
|
14
|
+
const isErrorWithExitCode = (error) => error instanceof Error && 'exitCode' in error && typeof error.exitCode === 'number';
|
|
13
15
|
const cli = meow(`
|
|
14
16
|
Usage
|
|
15
17
|
$ xo [<file|glob> ...]
|
|
16
18
|
|
|
17
19
|
Options
|
|
18
|
-
--fix
|
|
19
|
-
--fix-dry-run
|
|
20
|
-
--reporter
|
|
21
|
-
--space
|
|
22
|
-
--config
|
|
23
|
-
--semicolon
|
|
24
|
-
--
|
|
25
|
-
--
|
|
26
|
-
--
|
|
27
|
-
--
|
|
28
|
-
--
|
|
29
|
-
--
|
|
30
|
-
--stdin
|
|
31
|
-
--stdin-filename
|
|
32
|
-
--ignore
|
|
33
|
-
--
|
|
20
|
+
--fix Automagically fix issues
|
|
21
|
+
--fix-dry-run Automagically fix issues without saving the changes to the file system
|
|
22
|
+
--reporter Reporter to use
|
|
23
|
+
--space Use space indent instead of tabs [Default: 2]
|
|
24
|
+
--config Path to a XO configuration file
|
|
25
|
+
--semicolon Use semicolons [Default: true]
|
|
26
|
+
--prettier Format with prettier or turn off Prettier-conflicted rules when set to 'compat' [Default: false]
|
|
27
|
+
--print-config Print the effective ESLint config for the given file
|
|
28
|
+
--version Print XO version
|
|
29
|
+
--open Open files with issues in your editor
|
|
30
|
+
--quiet Show only errors and no warnings
|
|
31
|
+
--max-warnings Number of warnings to trigger nonzero exit code [Default: -1]
|
|
32
|
+
--stdin Validate/fix code from stdin
|
|
33
|
+
--stdin-filename Specify a filename for the --stdin option
|
|
34
|
+
--ignore Ignore pattern globs, can be set multiple times
|
|
35
|
+
--suppressions-location Path to a custom ESLint suppressions file
|
|
36
|
+
--cwd=<dir> Working directory for files [Default: process.cwd()]
|
|
34
37
|
|
|
35
38
|
Examples
|
|
36
39
|
$ xo
|
|
@@ -70,10 +73,6 @@ const cli = meow(`
|
|
|
70
73
|
prettier: {
|
|
71
74
|
type: 'boolean',
|
|
72
75
|
},
|
|
73
|
-
react: {
|
|
74
|
-
type: 'boolean',
|
|
75
|
-
default: false,
|
|
76
|
-
},
|
|
77
76
|
cwd: {
|
|
78
77
|
type: 'string',
|
|
79
78
|
default: process.cwd(),
|
|
@@ -99,6 +98,13 @@ const cli = meow(`
|
|
|
99
98
|
isMultiple: true,
|
|
100
99
|
aliases: ['ignores'],
|
|
101
100
|
},
|
|
101
|
+
suppressionsLocation: {
|
|
102
|
+
type: 'string',
|
|
103
|
+
},
|
|
104
|
+
maxWarnings: {
|
|
105
|
+
type: 'number',
|
|
106
|
+
default: -1,
|
|
107
|
+
},
|
|
102
108
|
},
|
|
103
109
|
});
|
|
104
110
|
const { input, flags: cliOptions, showVersion } = cli;
|
|
@@ -107,20 +113,20 @@ const baseXoConfigOptions = {
|
|
|
107
113
|
semicolon: cliOptions.semicolon,
|
|
108
114
|
prettier: cliOptions.prettier,
|
|
109
115
|
ignores: cliOptions.ignore,
|
|
110
|
-
react: cliOptions.react,
|
|
111
116
|
};
|
|
112
117
|
const linterOptions = {
|
|
113
118
|
fix: cliOptions.fix || cliOptions.fixDryRun,
|
|
114
|
-
cwd:
|
|
119
|
+
cwd: cliOptions.cwd === '' ? process.cwd() : path.resolve(cliOptions.cwd),
|
|
115
120
|
quiet: cliOptions.quiet,
|
|
116
121
|
ts: true,
|
|
117
122
|
configPath: cliOptions.configPath,
|
|
123
|
+
suppressionsLocation: cliOptions.suppressionsLocation,
|
|
118
124
|
};
|
|
119
125
|
// Make data types for `options.space` match those of the API
|
|
120
126
|
if (typeof cliOptions.space === 'string') {
|
|
121
127
|
cliOptions.space = cliOptions.space.trim();
|
|
122
128
|
if (/^\d+$/v.test(cliOptions.space)) {
|
|
123
|
-
baseXoConfigOptions.space = Number
|
|
129
|
+
baseXoConfigOptions.space = Number(cliOptions.space);
|
|
124
130
|
}
|
|
125
131
|
else if (cliOptions.space === 'true') {
|
|
126
132
|
baseXoConfigOptions.space = true;
|
|
@@ -136,86 +142,131 @@ if (typeof cliOptions.space === 'string') {
|
|
|
136
142
|
baseXoConfigOptions.space = true;
|
|
137
143
|
}
|
|
138
144
|
}
|
|
139
|
-
|
|
145
|
+
const isGitHubActions = Boolean(process.env['GITHUB_ACTIONS']);
|
|
146
|
+
if (isGitHubActions
|
|
140
147
|
&& !linterOptions.fix
|
|
141
|
-
&&
|
|
148
|
+
&& cliOptions.reporter === undefined) {
|
|
142
149
|
linterOptions.quiet = true;
|
|
143
150
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
151
|
+
// --max-warnings needs warning counts, which --quiet filters out
|
|
152
|
+
if (cliOptions.maxWarnings >= 0) {
|
|
153
|
+
linterOptions.quiet = false;
|
|
154
|
+
}
|
|
155
|
+
const log = async (report, xo) => {
|
|
156
|
+
const reporterName = cliOptions.reporter;
|
|
157
|
+
const shouldUsePrettyReporter = reporterName === undefined;
|
|
158
|
+
// Hide warnings when there are errors to reduce noise in the default human-readable output.
|
|
159
|
+
const results = shouldUsePrettyReporter && report.errorCount > 0 && cliOptions.maxWarnings < 0
|
|
160
|
+
? ESLint.getErrorResults(report.results)
|
|
161
|
+
: report.results;
|
|
162
|
+
if (shouldUsePrettyReporter) {
|
|
163
|
+
const counts = {
|
|
164
|
+
errorCount: 0,
|
|
165
|
+
warningCount: 0,
|
|
166
|
+
fixableErrorCount: 0,
|
|
167
|
+
fixableWarningCount: 0,
|
|
168
|
+
};
|
|
169
|
+
for (const result of results) {
|
|
170
|
+
counts.errorCount += result.errorCount;
|
|
171
|
+
counts.warningCount += result.warningCount;
|
|
172
|
+
counts.fixableErrorCount += result.fixableErrorCount;
|
|
173
|
+
counts.fixableWarningCount += result.fixableWarningCount;
|
|
174
|
+
}
|
|
175
|
+
const formatterMetadata = {
|
|
176
|
+
cwd: linterOptions.cwd,
|
|
177
|
+
...report,
|
|
178
|
+
...counts,
|
|
179
|
+
results,
|
|
180
|
+
};
|
|
181
|
+
console.log(formatterPretty(results, formatterMetadata));
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
const reporter = await xo.getFormatter(reporterName);
|
|
185
|
+
console.log(await reporter.format(results));
|
|
186
|
+
}
|
|
150
187
|
process.exitCode = report.errorCount === 0 ? 0 : 1;
|
|
188
|
+
if (cliOptions.maxWarnings >= 0 && report.warningCount > cliOptions.maxWarnings) {
|
|
189
|
+
console.error(`XO found too many warnings (maximum: ${cliOptions.maxWarnings}).`);
|
|
190
|
+
process.exitCode = 1;
|
|
191
|
+
}
|
|
151
192
|
};
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
await
|
|
193
|
+
try {
|
|
194
|
+
if (cliOptions.version) {
|
|
195
|
+
showVersion();
|
|
196
|
+
}
|
|
197
|
+
if (cliOptions.stdin) {
|
|
198
|
+
const stdin = await getStdin();
|
|
199
|
+
let shouldRemoveStdInFile = false;
|
|
200
|
+
// For TypeScript, we need a file on the filesystem to lint it or else @typescript-eslint will blow up.
|
|
201
|
+
// We create a temporary file in the node_modules/.cache/xo-linter directory to avoid conflicts with the user's files and lint that file as if it were the stdin input as a work around.
|
|
202
|
+
// We clean up the file after linting.
|
|
203
|
+
if (cliOptions.stdinFilename !== '' && tsExtensions.includes(path.extname(cliOptions.stdinFilename).slice(1))) {
|
|
204
|
+
const absoluteFilePath = path.resolve(cliOptions.cwd, cliOptions.stdinFilename);
|
|
205
|
+
if (!await pathExists(absoluteFilePath)) {
|
|
206
|
+
const cacheDir = findCacheDirectory({ name: cacheDirName, cwd: linterOptions.cwd }) ?? path.join(cliOptions.cwd, 'node_modules', '.cache', cacheDirName);
|
|
207
|
+
cliOptions.stdinFilename = path.join(cacheDir, path.basename(absoluteFilePath));
|
|
208
|
+
shouldRemoveStdInFile = true;
|
|
209
|
+
baseXoConfigOptions.ignores = [
|
|
210
|
+
'!**/node_modules/**',
|
|
211
|
+
'!node_modules/**',
|
|
212
|
+
'!node_modules/',
|
|
213
|
+
`!${path.relative(cliOptions.cwd, cliOptions.stdinFilename)}`,
|
|
214
|
+
];
|
|
215
|
+
if (!await pathExists(path.dirname(cliOptions.stdinFilename))) {
|
|
216
|
+
await fs.mkdir(path.dirname(cliOptions.stdinFilename), { recursive: true });
|
|
217
|
+
}
|
|
218
|
+
await fs.writeFile(cliOptions.stdinFilename, stdin);
|
|
175
219
|
}
|
|
176
|
-
await fs.writeFile(cliOptions.stdinFilename, stdin);
|
|
177
220
|
}
|
|
178
|
-
|
|
179
|
-
|
|
221
|
+
if (linterOptions.fix) {
|
|
222
|
+
const xo = new Xo(linterOptions, baseXoConfigOptions);
|
|
223
|
+
const { results } = await xo.lintText(stdin, {
|
|
224
|
+
filePath: cliOptions.stdinFilename,
|
|
225
|
+
});
|
|
226
|
+
const [result] = results;
|
|
227
|
+
process.stdout.write((result?.output) ?? stdin);
|
|
228
|
+
process.exit(0);
|
|
229
|
+
}
|
|
230
|
+
if (cliOptions.open) {
|
|
231
|
+
console.error('The `--open` flag is not supported on stdin');
|
|
232
|
+
if (shouldRemoveStdInFile) {
|
|
233
|
+
await fs.rm(cliOptions.stdinFilename);
|
|
234
|
+
}
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
180
237
|
const xo = new Xo(linterOptions, baseXoConfigOptions);
|
|
181
|
-
|
|
182
|
-
filePath: cliOptions.stdinFilename,
|
|
183
|
-
});
|
|
184
|
-
process.stdout.write((result?.output) ?? stdin);
|
|
185
|
-
process.exit(0);
|
|
186
|
-
}
|
|
187
|
-
if (cliOptions.open) {
|
|
188
|
-
console.error('The `--open` flag is not supported on stdin');
|
|
238
|
+
await log(await xo.lintText(stdin, { filePath: cliOptions.stdinFilename, warnIgnored: false }), xo);
|
|
189
239
|
if (shouldRemoveStdInFile) {
|
|
190
240
|
await fs.rm(cliOptions.stdinFilename);
|
|
191
241
|
}
|
|
192
|
-
process.exit(
|
|
242
|
+
process.exit(0);
|
|
193
243
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
244
|
+
if (typeof cliOptions.printConfig === 'string') {
|
|
245
|
+
if (input.length > 0 || cliOptions.printConfig === '') {
|
|
246
|
+
console.error('The `--print-config` flag must be used with exactly one filename');
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
const absoluteFilePath = path.resolve(cliOptions.cwd, cliOptions.printConfig);
|
|
250
|
+
const config = await new Xo(linterOptions, baseXoConfigOptions).calculateConfigForFile(absoluteFilePath);
|
|
251
|
+
console.log(JSON.stringify(config, undefined, '\t'));
|
|
198
252
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
253
|
+
else {
|
|
254
|
+
const xo = new Xo(linterOptions, baseXoConfigOptions);
|
|
255
|
+
const report = await xo.lintFiles(input);
|
|
256
|
+
if (cliOptions.fix) {
|
|
257
|
+
await Xo.outputFixes(report);
|
|
258
|
+
}
|
|
259
|
+
if (cliOptions.open) {
|
|
260
|
+
await openReport(report);
|
|
261
|
+
}
|
|
262
|
+
await log(report, xo);
|
|
205
263
|
}
|
|
206
|
-
const absoluteFilePath = path.resolve(cliOptions.cwd, cliOptions.printConfig);
|
|
207
|
-
const config = await new Xo(linterOptions, baseXoConfigOptions).calculateConfigForFile(absoluteFilePath);
|
|
208
|
-
console.log(JSON.stringify(config, undefined, '\t'));
|
|
209
264
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
await Xo.outputFixes(report);
|
|
215
|
-
}
|
|
216
|
-
if (cliOptions.open) {
|
|
217
|
-
await openReport(report);
|
|
265
|
+
catch (error) {
|
|
266
|
+
if (isErrorWithExitCode(error)) {
|
|
267
|
+
console.error(error.message);
|
|
268
|
+
process.exit(error.exitCode);
|
|
218
269
|
}
|
|
219
|
-
|
|
270
|
+
throw error;
|
|
220
271
|
}
|
|
221
272
|
//# sourceMappingURL=cli.js.map
|