0
# Node.js API
1
2
Oxlint provides experimental JavaScript bindings through NAPI (Node.js API) for advanced integrations and custom linting workflows. This API allows developers to build JavaScript plugins and integrate oxlint directly into Node.js applications.
3
4
## Package Information
5
6
- **Package Name**: oxlint
7
- **Node.js Requirement**: >=20.0.0
8
- **Platform Support**: 64-bit little-endian platforms only
9
- **Binary Distribution**: Native binaries for supported platforms
10
11
## Supported Platforms
12
13
The npm package includes pre-built native binaries for:
14
15
### Windows
16
- `win32-x64` - Windows x64
17
- `win32-arm64` - Windows ARM64
18
19
### macOS
20
- `darwin-x64` - macOS Intel
21
- `darwin-arm64` - macOS Apple Silicon
22
23
### Linux
24
- `linux-x64-gnu` - Linux x64 (GNU libc)
25
- `linux-arm64-gnu` - Linux ARM64 (GNU libc)
26
- `linux-x64-musl` - Linux x64 (musl libc)
27
- `linux-arm64-musl` - Linux ARM64 (musl libc)
28
29
## JavaScript Plugin Interface
30
31
### Main Lint Function
32
33
The primary API for JavaScript plugin integration.
34
35
```typescript { .api }
36
/**
37
* Main lint function for JavaScript plugins (experimental)
38
* Only available on 64-bit little-endian platforms
39
*
40
* @param loadPlugin - Callback to load plugin from path
41
* @param lintFile - Callback to process lint results
42
* @returns Promise resolving to success status
43
*/
44
function lint(
45
loadPlugin: (path: string) => Promise<string>,
46
lintFile: (filePath: string, bufferId: number, buffer: Uint8Array | null, ruleIds: number[]) => string
47
): Promise<boolean>;
48
```
49
50
### Callback Types
51
52
```typescript { .api }
53
/**
54
* Plugin loading callback
55
* @param path - Path to the plugin file
56
* @returns Promise resolving to plugin content
57
*/
58
type LoadPluginCallback = (path: string) => Promise<string>;
59
60
/**
61
* File linting callback
62
* @param filePath - Path to file being linted
63
* @param bufferId - Internal buffer identifier
64
* @param buffer - File content buffer (null for deleted files)
65
* @param ruleIds - Array of rule IDs to apply
66
* @returns Serialized lint results
67
*/
68
type LintFileCallback = (
69
filePath: string,
70
bufferId: number,
71
buffer: Uint8Array | null,
72
ruleIds: number[]
73
) => string;
74
```
75
76
## Usage Example
77
78
### Basic JavaScript Plugin Integration
79
80
```typescript
81
import { lint } from "oxlint";
82
83
async function customLintWorkflow() {
84
// Plugin loader - loads JavaScript plugins from filesystem
85
const loadPlugin = async (pluginPath: string): Promise<string> => {
86
const fs = await import('fs/promises');
87
return await fs.readFile(pluginPath, 'utf-8');
88
};
89
90
// File processor - handles lint results for each file
91
const lintFile = (
92
filePath: string,
93
bufferId: number,
94
buffer: Uint8Array | null,
95
ruleIds: number[]
96
): string => {
97
if (!buffer) {
98
return JSON.stringify({ deleted: true, filePath });
99
}
100
101
// Process file content and return results
102
const content = new TextDecoder().decode(buffer);
103
const results = {
104
filePath,
105
bufferId,
106
contentLength: content.length,
107
appliedRules: ruleIds,
108
processed: true
109
};
110
111
return JSON.stringify(results);
112
};
113
114
try {
115
const success = await lint(loadPlugin, lintFile);
116
console.log(`Linting ${success ? 'succeeded' : 'failed'}`);
117
} catch (error) {
118
console.error('Linting error:', error);
119
}
120
}
121
```
122
123
### Plugin Development
124
125
```typescript
126
// Custom plugin structure
127
interface CustomPlugin {
128
name: string;
129
version: string;
130
rules: Record<string, any>;
131
}
132
133
const loadPlugin = async (pluginPath: string): Promise<string> => {
134
// Load plugin configuration
135
const pluginModule = await import(pluginPath);
136
const plugin: CustomPlugin = {
137
name: pluginModule.default.name || 'custom-plugin',
138
version: pluginModule.default.version || '1.0.0',
139
rules: pluginModule.default.rules || {}
140
};
141
142
return JSON.stringify(plugin);
143
};
144
```
145
146
## Platform Detection
147
148
### Runtime Platform Check
149
150
```typescript
151
import { platform, arch } from 'os';
152
153
function isJsPluginSupported(): boolean {
154
// JS plugins only work on 64-bit little-endian platforms
155
const supportedPlatforms = [
156
'win32-x64', 'win32-arm64',
157
'linux-x64', 'linux-arm64',
158
'darwin-x64', 'darwin-arm64'
159
];
160
161
const currentPlatform = `${platform()}-${arch()}`;
162
return supportedPlatforms.includes(currentPlatform) &&
163
process.arch === 'x64' || process.arch === 'arm64';
164
}
165
166
// Check before using JS plugins
167
if (isJsPluginSupported()) {
168
// Use lint() function
169
} else {
170
console.warn('JavaScript plugins not supported on this platform');
171
}
172
```
173
174
## Error Handling
175
176
### Common Error Scenarios
177
178
```typescript
179
import { lint } from "oxlint";
180
181
const loadPlugin = async (path: string): Promise<string> => {
182
try {
183
// Plugin loading logic
184
return await loadPluginContent(path);
185
} catch (error) {
186
throw new Error(`Failed to load plugin from ${path}: ${error.message}`);
187
}
188
};
189
190
const lintFile = (filePath: string, bufferId: number, buffer: Uint8Array | null, ruleIds: number[]): string => {
191
try {
192
if (!buffer) {
193
return JSON.stringify({
194
error: 'File not found or deleted',
195
filePath
196
});
197
}
198
199
// File processing logic
200
return JSON.stringify({ success: true, filePath });
201
} catch (error) {
202
return JSON.stringify({
203
error: error.message,
204
filePath,
205
bufferId
206
});
207
}
208
};
209
210
// Main error handling
211
try {
212
const result = await lint(loadPlugin, lintFile);
213
if (!result) {
214
console.error('Linting completed with errors');
215
}
216
} catch (error) {
217
if (error.message?.includes('not supported')) {
218
console.error('JS plugins not supported on this platform');
219
} else {
220
console.error('Unexpected linting error:', error);
221
}
222
}
223
```
224
225
## Limitations
226
227
### Current Restrictions
228
229
- **Platform Limitation**: Only 64-bit little-endian platforms supported
230
- **Experimental Status**: API may change in future versions
231
- **Performance**: JavaScript plugins may be slower than native rules
232
- **Memory Usage**: Plugin loading increases memory footprint
233
- **Error Handling**: Limited error recovery for plugin failures
234
235
### Node.js Version Compatibility
236
237
- **Minimum**: Node.js 20.0.0
238
- **Recommended**: Node.js 20.x LTS or later
239
- **NAPI Version**: Requires NAPI v8 or higher
240
241
## Binary Distribution
242
243
### Installation
244
245
```bash
246
# Install via npm (includes platform-specific binaries)
247
npm install oxlint
248
249
# Verify installation
250
npx oxlint --version
251
```
252
253
### Manual Binary Usage
254
255
The npm package also provides direct binary access:
256
257
```bash
258
# Access binary directly
259
./node_modules/.bin/oxlint [options]
260
261
# Or through npm scripts
262
{
263
"scripts": {
264
"lint": "oxlint src/",
265
"lint:fix": "oxlint --fix src/"
266
}
267
}
268
```
269
270
## Integration Examples
271
272
### Custom CI/CD Integration
273
274
```typescript
275
import { lint } from "oxlint";
276
import { execSync } from "child_process";
277
278
async function ciLintProcess() {
279
// Custom plugin for CI-specific rules
280
const loadPlugin = async (path: string) => {
281
return JSON.stringify({
282
name: "ci-plugin",
283
rules: {
284
"no-console-in-production": "error",
285
"require-file-headers": "warn"
286
}
287
});
288
};
289
290
const lintFile = (filePath: string, bufferId: number, buffer: Uint8Array | null, ruleIds: number[]) => {
291
// CI-specific file processing
292
const result = {
293
file: filePath,
294
ciCheck: true,
295
timestamp: new Date().toISOString()
296
};
297
return JSON.stringify(result);
298
};
299
300
const success = await lint(loadPlugin, lintFile);
301
302
// Set CI exit code
303
process.exit(success ? 0 : 1);
304
}
305
```
306
307
This experimental API provides powerful integration capabilities for advanced use cases while maintaining the performance benefits of the core Rust implementation.