@vinsonchuong/xo_d 1.1.2 → 1.2.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/cli.test.mjs +4 -2
- package/client.mjs +144 -134
- package/package.json +15 -14
- package/server.mjs +40 -33
package/cli.test.mjs
CHANGED
|
@@ -12,16 +12,18 @@ async function cli(args, {cwd, stdin}) {
|
|
|
12
12
|
child.stdin.end(stdin)
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const [exitCode, stdout] = await Promise.all([
|
|
15
|
+
const [exitCode, stdout, stderr] = await Promise.all([
|
|
16
16
|
new Promise((resolve) => {
|
|
17
17
|
child.on('exit', resolve)
|
|
18
18
|
}),
|
|
19
19
|
getStream(child.stdout),
|
|
20
|
+
getStream(child.stderr),
|
|
20
21
|
])
|
|
21
22
|
|
|
22
23
|
return {
|
|
23
24
|
exitCode,
|
|
24
25
|
stdout,
|
|
26
|
+
stderr,
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -45,7 +47,7 @@ test.serial('fix option', async (t) => {
|
|
|
45
47
|
|
|
46
48
|
test.serial('fix option with stdin', async (t) => {
|
|
47
49
|
const directory = await useTemporaryDirectory(t)
|
|
48
|
-
const {stdout} = await cli(['--fix', '--stdin'], {
|
|
50
|
+
const {stdout} = await cli(['--fix', '--stdin', '--stdin-filename=fix.js'], {
|
|
49
51
|
cwd: directory.path,
|
|
50
52
|
stdin: 'console.log()',
|
|
51
53
|
})
|
package/client.mjs
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
|
+
import fs from 'node:fs/promises'
|
|
2
3
|
import {createRequire} from 'node:module'
|
|
4
|
+
import path from 'node:path'
|
|
3
5
|
import getStdin from 'get-stdin'
|
|
6
|
+
import {pathExists} from 'path-exists'
|
|
7
|
+
import findCacheDirectory from 'find-cache-directory'
|
|
4
8
|
import meow from 'meow'
|
|
5
|
-
|
|
9
|
+
|
|
10
|
+
const cacheDirName = 'xo-linter'
|
|
11
|
+
const tsExtensions = new Set(['ts', 'tsx', 'cts', 'mts'])
|
|
6
12
|
|
|
7
13
|
const require = createRequire(import.meta.url)
|
|
8
14
|
|
|
9
|
-
export default async function () {
|
|
15
|
+
export default async function run() {
|
|
10
16
|
process.env.CORE_D_TITLE = 'xo_d'
|
|
11
17
|
process.env.CORE_D_DOTFILE = '.xo_d'
|
|
12
18
|
process.env.CORE_D_SERVICE = require.resolve('./server.js')
|
|
@@ -21,50 +27,32 @@ export default async function () {
|
|
|
21
27
|
) {
|
|
22
28
|
coreD[xoDCommand]()
|
|
23
29
|
} else {
|
|
24
|
-
const
|
|
25
|
-
input,
|
|
26
|
-
flags: options,
|
|
27
|
-
showVersion,
|
|
28
|
-
} = meow(
|
|
30
|
+
const cli = meow(
|
|
29
31
|
`
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Examples
|
|
55
|
-
$ xo
|
|
56
|
-
$ xo index.js
|
|
57
|
-
$ xo *.js !foo.js
|
|
58
|
-
$ xo --space
|
|
59
|
-
$ xo --env=node --env=mocha
|
|
60
|
-
$ xo --plugin=react
|
|
61
|
-
$ xo --plugin=html --extension=html
|
|
62
|
-
$ echo 'const x=true' | xo --stdin --fix
|
|
63
|
-
$ xo --print-config=index.js
|
|
64
|
-
|
|
65
|
-
Tips
|
|
66
|
-
- Add XO to your project with \`npm init xo\`.
|
|
67
|
-
- Put options in package.json instead of using flags so other tools can read it.
|
|
32
|
+
Usage
|
|
33
|
+
$ xo_d [<file|glob> ...]
|
|
34
|
+
$ xo_d [start|stop|status]
|
|
35
|
+
|
|
36
|
+
Options
|
|
37
|
+
--fix Automagically fix issues
|
|
38
|
+
--reporter Reporter to use
|
|
39
|
+
--space Use space indent instead of tabs [Default: 2]
|
|
40
|
+
--config Path to a XO configuration file
|
|
41
|
+
--semicolon Use semicolons [Default: true]
|
|
42
|
+
--react Include React specific parsing and xo-react linting rules [Default: false]
|
|
43
|
+
--prettier Format with prettier or turn off prettier conflicted rules when set to 'compat' [Default: false]
|
|
44
|
+
--version Print XO version
|
|
45
|
+
--quiet Show only errors and no warnings
|
|
46
|
+
--stdin Validate/fix code from stdin
|
|
47
|
+
--stdin-filename Specify a filename for the --stdin option
|
|
48
|
+
--ignore Ignore pattern globs, can be set multiple times
|
|
49
|
+
--cwd=<dir> Working directory for files [Default: process.cwd()]
|
|
50
|
+
|
|
51
|
+
Examples
|
|
52
|
+
$ xo
|
|
53
|
+
$ xo index.js
|
|
54
|
+
$ xo *.js !foo.js
|
|
55
|
+
$ xo --space
|
|
68
56
|
`,
|
|
69
57
|
{
|
|
70
58
|
importMeta: import.meta,
|
|
@@ -73,24 +61,19 @@ export default async function () {
|
|
|
73
61
|
flags: {
|
|
74
62
|
fix: {
|
|
75
63
|
type: 'boolean',
|
|
64
|
+
default: false,
|
|
76
65
|
},
|
|
77
66
|
reporter: {
|
|
78
67
|
type: 'string',
|
|
79
68
|
},
|
|
80
|
-
|
|
81
|
-
type: 'string',
|
|
82
|
-
isMultiple: true,
|
|
83
|
-
},
|
|
84
|
-
global: {
|
|
69
|
+
space: {
|
|
85
70
|
type: 'string',
|
|
86
|
-
isMultiple: true,
|
|
87
71
|
},
|
|
88
|
-
|
|
72
|
+
config: {
|
|
89
73
|
type: 'string',
|
|
90
|
-
isMultiple: true,
|
|
91
74
|
},
|
|
92
|
-
|
|
93
|
-
type: '
|
|
75
|
+
quiet: {
|
|
76
|
+
type: 'boolean',
|
|
94
77
|
},
|
|
95
78
|
semicolon: {
|
|
96
79
|
type: 'boolean',
|
|
@@ -98,124 +81,151 @@ export default async function () {
|
|
|
98
81
|
prettier: {
|
|
99
82
|
type: 'boolean',
|
|
100
83
|
},
|
|
101
|
-
|
|
102
|
-
type: '
|
|
103
|
-
|
|
104
|
-
plugin: {
|
|
105
|
-
type: 'string',
|
|
106
|
-
isMultiple: true,
|
|
84
|
+
react: {
|
|
85
|
+
type: 'boolean',
|
|
86
|
+
default: false,
|
|
107
87
|
},
|
|
108
|
-
|
|
88
|
+
cwd: {
|
|
109
89
|
type: 'string',
|
|
110
|
-
|
|
90
|
+
default: process.cwd(),
|
|
111
91
|
},
|
|
112
|
-
|
|
92
|
+
version: {
|
|
113
93
|
type: 'boolean',
|
|
114
94
|
},
|
|
115
|
-
|
|
95
|
+
stdin: {
|
|
116
96
|
type: 'boolean',
|
|
117
97
|
},
|
|
118
|
-
|
|
119
|
-
type: 'string',
|
|
120
|
-
isMultiple: true,
|
|
121
|
-
},
|
|
122
|
-
cwd: {
|
|
123
|
-
type: 'string',
|
|
124
|
-
},
|
|
125
|
-
printConfig: {
|
|
98
|
+
stdinFilename: {
|
|
126
99
|
type: 'string',
|
|
100
|
+
default: 'stdin.js',
|
|
127
101
|
},
|
|
128
|
-
|
|
102
|
+
open: {
|
|
129
103
|
type: 'boolean',
|
|
130
104
|
},
|
|
131
|
-
|
|
105
|
+
ignore: {
|
|
132
106
|
type: 'string',
|
|
107
|
+
isMultiple: true,
|
|
108
|
+
aliases: ['ignores'],
|
|
133
109
|
},
|
|
134
110
|
},
|
|
135
111
|
},
|
|
136
112
|
)
|
|
137
113
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
114
|
+
const {input, flags: cliOptions, showVersion} = cli
|
|
115
|
+
|
|
116
|
+
const baseXoConfigOptions = {
|
|
117
|
+
space: cliOptions.space,
|
|
118
|
+
semicolon: cliOptions.semicolon,
|
|
119
|
+
prettier: cliOptions.prettier,
|
|
120
|
+
ignores: cliOptions.ignore,
|
|
121
|
+
react: cliOptions.react,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const linterOptions = {
|
|
125
|
+
fix: cliOptions.fix,
|
|
126
|
+
cwd: (cliOptions.cwd && path.resolve(cliOptions.cwd)) ?? process.cwd(),
|
|
127
|
+
quiet: cliOptions.quiet,
|
|
128
|
+
ts: true,
|
|
142
129
|
}
|
|
143
130
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
131
|
+
// Make data types for `options.space` match those of the API
|
|
132
|
+
if (typeof cliOptions.space === 'string') {
|
|
133
|
+
cliOptions.space = cliOptions.space.trim()
|
|
134
|
+
|
|
135
|
+
if (/^\d+$/u.test(cliOptions.space)) {
|
|
136
|
+
baseXoConfigOptions.space = Number.parseInt(cliOptions.space, 10)
|
|
137
|
+
} else if (cliOptions.space === 'true') {
|
|
138
|
+
baseXoConfigOptions.space = true
|
|
139
|
+
} else if (cliOptions.space === 'false') {
|
|
140
|
+
baseXoConfigOptions.space = false
|
|
151
141
|
} else {
|
|
152
|
-
if (
|
|
153
|
-
|
|
142
|
+
if (cliOptions.space !== '') {
|
|
143
|
+
// Assume `options.space` was set to a filename when run as `xo --space file.js`
|
|
144
|
+
input.push(cliOptions.space)
|
|
154
145
|
}
|
|
155
146
|
|
|
156
|
-
|
|
147
|
+
baseXoConfigOptions.space = true
|
|
157
148
|
}
|
|
158
149
|
}
|
|
159
150
|
|
|
160
|
-
if (
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
input.shift()
|
|
151
|
+
if (
|
|
152
|
+
process.env.GITHUB_ACTIONS &&
|
|
153
|
+
!linterOptions.fix &&
|
|
154
|
+
!cliOptions.reporter
|
|
155
|
+
) {
|
|
156
|
+
linterOptions.quiet = true
|
|
167
157
|
}
|
|
168
158
|
|
|
169
|
-
if (
|
|
159
|
+
if (cliOptions.version) {
|
|
170
160
|
showVersion()
|
|
171
161
|
}
|
|
172
162
|
|
|
173
|
-
if (
|
|
174
|
-
|
|
175
|
-
options.nodeVersion = false
|
|
176
|
-
} else if (!semver.validRange(options.nodeVersion)) {
|
|
177
|
-
console.error(
|
|
178
|
-
'The `--node-engine` flag must be a valid semver range (for example `>=6`)',
|
|
179
|
-
)
|
|
180
|
-
process.exit(1)
|
|
181
|
-
}
|
|
182
|
-
}
|
|
163
|
+
if (cliOptions.stdin) {
|
|
164
|
+
const stdin = await getStdin()
|
|
183
165
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
166
|
+
let shouldRemoveStdInFile = false
|
|
167
|
+
|
|
168
|
+
// For TypeScript, we need a file on the filesystem to lint it or else @typescript-eslint will blow up.
|
|
169
|
+
// 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.
|
|
170
|
+
// We clean up the file after linting.
|
|
171
|
+
if (
|
|
172
|
+
cliOptions.stdinFilename &&
|
|
173
|
+
tsExtensions.has(path.extname(cliOptions.stdinFilename).slice(1))
|
|
174
|
+
) {
|
|
175
|
+
const absoluteFilePath = path.resolve(
|
|
176
|
+
cliOptions.cwd,
|
|
177
|
+
cliOptions.stdinFilename,
|
|
188
178
|
)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
179
|
+
if (!(await pathExists(absoluteFilePath))) {
|
|
180
|
+
const cacheDir =
|
|
181
|
+
findCacheDirectory({name: cacheDirName, cwd: linterOptions.cwd}) ??
|
|
182
|
+
path.join(cliOptions.cwd, 'node_modules', '.cache', cacheDirName)
|
|
183
|
+
cliOptions.stdinFilename = path.join(
|
|
184
|
+
cacheDir,
|
|
185
|
+
path.basename(absoluteFilePath),
|
|
186
|
+
)
|
|
187
|
+
shouldRemoveStdInFile = true
|
|
188
|
+
baseXoConfigOptions.ignores = [
|
|
189
|
+
'!**/node_modules/**',
|
|
190
|
+
'!node_modules/**',
|
|
191
|
+
'!node_modules/',
|
|
192
|
+
`!${path.relative(cliOptions.cwd, cliOptions.stdinFilename)}`,
|
|
193
|
+
]
|
|
194
|
+
if (!(await pathExists(path.dirname(cliOptions.stdinFilename)))) {
|
|
195
|
+
await fs.mkdir(path.dirname(cliOptions.stdinFilename), {
|
|
196
|
+
recursive: true,
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
await fs.writeFile(cliOptions.stdinFilename, stdin)
|
|
201
|
+
}
|
|
195
202
|
}
|
|
196
203
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
204
|
+
if (cliOptions.fix) {
|
|
205
|
+
return coreD.invoke([
|
|
206
|
+
cliOptions,
|
|
207
|
+
linterOptions,
|
|
208
|
+
baseXoConfigOptions,
|
|
209
|
+
input,
|
|
210
|
+
stdin,
|
|
211
|
+
])
|
|
205
212
|
}
|
|
206
213
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
214
|
+
coreD.invoke([
|
|
215
|
+
cliOptions,
|
|
216
|
+
linterOptions,
|
|
217
|
+
baseXoConfigOptions,
|
|
218
|
+
input,
|
|
219
|
+
null,
|
|
220
|
+
])
|
|
210
221
|
|
|
211
|
-
if (
|
|
212
|
-
|
|
213
|
-
process.exit(1)
|
|
222
|
+
if (shouldRemoveStdInFile) {
|
|
223
|
+
await fs.rm(cliOptions.stdinFilename)
|
|
214
224
|
}
|
|
215
225
|
|
|
216
|
-
|
|
217
|
-
} else {
|
|
218
|
-
coreD.invoke([input, options, null])
|
|
226
|
+
return
|
|
219
227
|
}
|
|
228
|
+
|
|
229
|
+
coreD.invoke([cliOptions, linterOptions, baseXoConfigOptions, input, null])
|
|
220
230
|
}
|
|
221
231
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vinsonchuong/xo_d",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Speed up xo in the same way as eslint_d",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/vinsonchuong/xo_d",
|
|
@@ -13,22 +13,22 @@
|
|
|
13
13
|
"release": "semantic-release"
|
|
14
14
|
},
|
|
15
15
|
"type": "commonjs",
|
|
16
|
-
"bin":
|
|
17
|
-
"xo_d": "cli.js"
|
|
18
|
-
},
|
|
16
|
+
"bin": "cli.js",
|
|
19
17
|
"dependencies": {
|
|
20
|
-
"core_d": "^
|
|
21
|
-
"eslint-formatter-pretty": "^
|
|
18
|
+
"core_d": "^6.1.0",
|
|
19
|
+
"eslint-formatter-pretty": "^6.0.1",
|
|
20
|
+
"find-cache-directory": "^6.0.0",
|
|
22
21
|
"get-stdin": "^9.0.0",
|
|
23
|
-
"meow": "^
|
|
24
|
-
"
|
|
25
|
-
"xo": "^
|
|
22
|
+
"meow": "^13.2.0",
|
|
23
|
+
"path-exists": "^5.0.0",
|
|
24
|
+
"xo": "^1.1.0"
|
|
26
25
|
},
|
|
27
26
|
"devDependencies": {
|
|
28
|
-
"ava": "^5.
|
|
29
|
-
"ava-patterns": "^3.2.
|
|
30
|
-
"get-stream": "^
|
|
31
|
-
"semantic-release": "^
|
|
27
|
+
"ava": "^5.3.1",
|
|
28
|
+
"ava-patterns": "^3.2.1",
|
|
29
|
+
"get-stream": "^9.0.1",
|
|
30
|
+
"semantic-release": "^24.2.5",
|
|
31
|
+
"typescript": "^5.8.3"
|
|
32
32
|
},
|
|
33
33
|
"ava": {
|
|
34
34
|
"verbose": true
|
|
@@ -52,5 +52,6 @@
|
|
|
52
52
|
},
|
|
53
53
|
"publishConfig": {
|
|
54
54
|
"access": "public"
|
|
55
|
-
}
|
|
55
|
+
},
|
|
56
|
+
"packageManager": "yarn@4.9.2"
|
|
56
57
|
}
|
package/server.mjs
CHANGED
|
@@ -1,46 +1,53 @@
|
|
|
1
|
-
import
|
|
2
|
-
import xo from 'xo'
|
|
1
|
+
import {Xo} from 'xo'
|
|
3
2
|
import formatterPretty from 'eslint-formatter-pretty'
|
|
4
|
-
import openReport from 'xo/lib/open-report.js'
|
|
5
3
|
|
|
6
|
-
async function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
4
|
+
export default async function run([
|
|
5
|
+
cliOptions,
|
|
6
|
+
linterOptions,
|
|
7
|
+
baseXoConfigOptions,
|
|
8
|
+
input,
|
|
9
|
+
stdin,
|
|
10
|
+
]) {
|
|
11
|
+
const xo = new Xo(linterOptions, baseXoConfigOptions)
|
|
12
|
+
|
|
13
|
+
const log = async (report) => {
|
|
14
|
+
const reporter = cliOptions.reporter
|
|
15
|
+
? await new Xo(linterOptions, baseXoConfigOptions).getFormatter(
|
|
16
|
+
cliOptions.reporter,
|
|
17
|
+
)
|
|
18
|
+
: {format: formatterPretty}
|
|
19
|
+
|
|
20
|
+
const text = reporter.format(report.results, {
|
|
21
|
+
cwd: linterOptions.cwd,
|
|
22
|
+
...report,
|
|
23
|
+
})
|
|
24
|
+
const exitCode = report.errorCount === 0 ? 0 : 1
|
|
25
|
+
|
|
26
|
+
return `${text}\n# exit ${exitCode}`
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
if (
|
|
25
|
-
if (
|
|
29
|
+
if (cliOptions.stdin) {
|
|
30
|
+
if (cliOptions.fix) {
|
|
26
31
|
const {
|
|
27
32
|
results: [result],
|
|
28
|
-
} = await xo.lintText(stdin,
|
|
29
|
-
|
|
33
|
+
} = await xo.lintText(stdin, {
|
|
34
|
+
filePath: cliOptions.stdinFilename,
|
|
35
|
+
})
|
|
36
|
+
return result?.output ?? stdin
|
|
30
37
|
}
|
|
31
38
|
|
|
32
|
-
return log(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
await xo.outputFixes(report)
|
|
39
|
+
return log(
|
|
40
|
+
await xo.lintText(stdin, {
|
|
41
|
+
filePath: cliOptions.stdinFilename,
|
|
42
|
+
warnIgnored: false,
|
|
43
|
+
}),
|
|
44
|
+
)
|
|
39
45
|
}
|
|
40
46
|
|
|
41
|
-
|
|
42
|
-
|
|
47
|
+
const report = await xo.lintFiles(input)
|
|
48
|
+
if (cliOptions.fix) {
|
|
49
|
+
await Xo.outputFixes(report)
|
|
43
50
|
}
|
|
44
51
|
|
|
45
|
-
return log(report
|
|
52
|
+
return log(report)
|
|
46
53
|
}
|