Skip to content

Commit 26f4d2f

Browse files
committed
fix monorepos oxlint not found
1 parent 58b0e47 commit 26f4d2f

6 files changed

Lines changed: 131 additions & 71 deletions

File tree

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,24 @@ export default {
123123
}
124124
```
125125

126+
### Change oxlint path
127+
128+
If you're using this plugin in a monorepo and encountering "command not found: oxlint" errors, you can manually specify the path to the oxlint binary.
129+
130+
If no local oxlint binary is found, the plugin will gracefully fall back to using npx (or the equivalent command for your package manager).
131+
132+
```javascript
133+
import oxlintPlugin from 'vite-plugin-oxlint'
134+
135+
export default {
136+
plugins: [
137+
oxlintPlugin({
138+
oxlintPath: '/path/to/your/monorepo/node_modules/.bin/oxlint'
139+
})
140+
]
141+
}
142+
```
143+
126144
## Integration with ESLint
127145

128146
If your project still needs ESLint, you can use [vite-plugin-eslint](https://github.com/gxmari007/vite-plugin-eslint) and configure ESLint with [eslint-plugin-oxlint](https://github.com/oxc-project/eslint-plugin-oxlint) to turn off rules already supported by oxlint.

dist/index.mjs

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const oxlintPlugin = (options = {}) => {
77
let timeoutId = null;
88
const debounceTime = 300;
99
const executeCommand = async () => {
10-
const { path = '', ignorePattern = '', configFile = 'oxlintrc.json', deny = [], allow = [], warn = [], params = '' } = options;
10+
const { path = '', ignorePattern = '', configFile = 'oxlintrc.json', deny = [], allow = [], warn = [], params = '', oxlintPath = '' } = options;
1111
const args = [];
1212
if (ignorePattern) {
1313
args.push(`--ignore-pattern=${ignorePattern}`);
@@ -27,35 +27,52 @@ const oxlintPlugin = (options = {}) => {
2727
if (!pm)
2828
throw new Error('Could not detect package manager');
2929
return new Promise((resolve, reject) => {
30-
const { command: cmd, args: cmdArgs } = resolveCommand(pm.agent, 'execute-local', ['oxlint', ...args]);
31-
const child = spawn(cmd, cmdArgs, {
32-
cwd,
33-
stdio: 'pipe',
34-
shell: false,
35-
env: {
36-
...process.env,
37-
FORCE_COLOR: '1'
38-
}
39-
});
40-
child.stdout?.pipe(process.stdout);
41-
let stderrOutput = '';
42-
child.stderr?.on('data', data => {
43-
stderrOutput += data.toString();
44-
process.stderr.write(data); // Forward stderr with formatting intact
45-
});
46-
child.on('error', error => {
47-
console.error(`oxlint Error: ${error.message}`);
48-
reject(error);
49-
});
50-
child.on('exit', code => {
51-
if (code === 0) {
52-
console.log('\nOxlint successfully finished.');
53-
}
54-
else {
55-
console.warn(`\n\x1b[33mOxlint finished with exit code: ${code}\x1b[0m`);
56-
}
57-
resolve();
58-
});
30+
let isExecuteLocal = true;
31+
const executeWithFallback = (useExecuteLocal) => {
32+
const { command: cmd, args: cmdArgs } = resolveCommand(pm.agent, useExecuteLocal ? 'execute-local' : 'execute', [useExecuteLocal ? oxlintPath || 'oxlint' : 'oxlint', ...args]);
33+
const child = spawn(cmd, cmdArgs, {
34+
cwd,
35+
stdio: 'pipe',
36+
shell: false,
37+
env: {
38+
...process.env,
39+
FORCE_COLOR: '1'
40+
}
41+
});
42+
// child.stdout?.pipe(process.stdout)
43+
let stderrOutput = '';
44+
child.stdout?.on('data', data => {
45+
const dataString = data.toString();
46+
if (!dataString.includes('undefined') &&
47+
!(dataString.includes('not found') && useExecuteLocal)) {
48+
stderrOutput += dataString;
49+
process.stdout.write(data);
50+
}
51+
});
52+
child.stderr?.on('data', data => {
53+
stderrOutput += data.toString();
54+
process.stderr.write(data);
55+
});
56+
child.on('error', error => {
57+
console.error(`oxlint Error: ${error.message}`);
58+
reject(error);
59+
});
60+
child.on('exit', code => {
61+
if (code === 0) {
62+
console.log('\nOxlint successfully finished.');
63+
resolve();
64+
}
65+
else if (useExecuteLocal && code !== 1) {
66+
isExecuteLocal = false;
67+
executeWithFallback(isExecuteLocal);
68+
}
69+
else {
70+
console.warn(`\n\x1b[33mOxlint finished with exit code: ${code}\x1b[0m`);
71+
resolve();
72+
}
73+
});
74+
};
75+
executeWithFallback(isExecuteLocal);
5976
});
6077
};
6178
const handleCommandExecution = async () => {

dist/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ export interface Options {
66
allow?: string[];
77
warn?: string[];
88
params?: string;
9+
oxlintPath?: string;
910
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vite-plugin-oxlint",
3-
"version": "1.3.4",
3+
"version": "1.4.0",
44
"description": "Oxlint plugin for vite.",
55
"author": "Arnaud Riu",
66
"license": "MIT",

src/index.ts

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ const oxlintPlugin = (options: Options = {}): Plugin => {
1818
deny = [],
1919
allow = [],
2020
warn = [],
21-
params = ''
21+
params = '',
22+
oxlintPath = ''
2223
} = options
2324

2425
const args: string[] = []
@@ -44,45 +45,67 @@ const oxlintPlugin = (options: Options = {}): Plugin => {
4445
if (!pm) throw new Error('Could not detect package manager')
4546

4647
return new Promise<void>((resolve, reject) => {
47-
const { command: cmd, args: cmdArgs } = resolveCommand(
48-
pm.agent,
49-
'execute-local',
50-
['oxlint', ...args]
51-
) as { command: string; args: string[] }
52-
53-
const child = spawn(cmd, cmdArgs, {
54-
cwd,
55-
stdio: 'pipe',
56-
shell: false,
57-
env: {
58-
...process.env,
59-
FORCE_COLOR: '1'
60-
}
61-
})
62-
63-
child.stdout?.pipe(process.stdout)
64-
65-
let stderrOutput = ''
66-
child.stderr?.on('data', data => {
67-
stderrOutput += data.toString()
68-
process.stderr.write(data) // Forward stderr with formatting intact
69-
})
70-
71-
child.on('error', error => {
72-
console.error(`oxlint Error: ${error.message}`)
73-
reject(error)
74-
})
75-
76-
child.on('exit', code => {
77-
if (code === 0) {
78-
console.log('\nOxlint successfully finished.')
79-
} else {
80-
console.warn(
81-
`\n\x1b[33mOxlint finished with exit code: ${code}\x1b[0m`
82-
)
83-
}
84-
resolve()
85-
})
48+
let isExecuteLocal = true
49+
50+
const executeWithFallback = (useExecuteLocal: boolean) => {
51+
const { command: cmd, args: cmdArgs } = resolveCommand(
52+
pm.agent,
53+
useExecuteLocal ? 'execute-local' : 'execute',
54+
[useExecuteLocal ? oxlintPath || 'oxlint' : 'oxlint', ...args]
55+
) as { command: string; args: string[] }
56+
57+
const child = spawn(cmd, cmdArgs, {
58+
cwd,
59+
stdio: 'pipe',
60+
shell: false,
61+
env: {
62+
...process.env,
63+
FORCE_COLOR: '1'
64+
}
65+
})
66+
67+
// child.stdout?.pipe(process.stdout)
68+
69+
let stderrOutput = ''
70+
child.stdout?.on('data', data => {
71+
const dataString = data.toString()
72+
73+
if (
74+
!dataString.includes('undefined') &&
75+
!(dataString.includes('not found') && useExecuteLocal)
76+
) {
77+
stderrOutput += dataString
78+
process.stdout.write(data)
79+
}
80+
})
81+
82+
child.stderr?.on('data', data => {
83+
stderrOutput += data.toString()
84+
process.stderr.write(data)
85+
})
86+
87+
child.on('error', error => {
88+
console.error(`oxlint Error: ${error.message}`)
89+
reject(error)
90+
})
91+
92+
child.on('exit', code => {
93+
if (code === 0) {
94+
console.log('\nOxlint successfully finished.')
95+
resolve()
96+
} else if (useExecuteLocal && code !== 1) {
97+
isExecuteLocal = false
98+
executeWithFallback(isExecuteLocal)
99+
} else {
100+
console.warn(
101+
`\n\x1b[33mOxlint finished with exit code: ${code}\x1b[0m`
102+
)
103+
resolve()
104+
}
105+
})
106+
}
107+
108+
executeWithFallback(isExecuteLocal)
86109
})
87110
}
88111

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ export interface Options {
66
allow?: string[]
77
warn?: string[]
88
params?: string
9+
oxlintPath?: string
910
}

0 commit comments

Comments
 (0)