@rslint/core 0.6.2 → 0.6.4

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.
@@ -0,0 +1,167 @@
1
+ import { spawn } from "child_process";
2
+ import { Socket } from "node:net";
3
+ import { createRequire } from "node:module";
4
+ import { RSLintService } from "./service.js";
5
+ const node_require = createRequire(import.meta.url);
6
+ function resolveRslintBinary() {
7
+ const arch = process.arch;
8
+ const tuples = 'linux' === process.platform ? [
9
+ `linux-${arch}-gnu`,
10
+ `linux-${arch}-musl`
11
+ ] : 'win32' === process.platform ? [
12
+ `win32-${arch}-msvc`
13
+ ] : [
14
+ `${process.platform}-${arch}`
15
+ ];
16
+ for (const tuple of tuples)try {
17
+ return node_require.resolve(`@rslint/native-${tuple}/bin`);
18
+ } catch {}
19
+ throw new Error(`rslint: no native binary for ${process.platform}-${arch} (looked for @rslint/native-{${tuples.join(',')}})`);
20
+ }
21
+ class NodeRslintService {
22
+ nextMessageId;
23
+ pendingMessages;
24
+ rslintPath;
25
+ process;
26
+ chunks;
27
+ chunkSize;
28
+ expectedSize;
29
+ dead;
30
+ closing;
31
+ constructor(options = {}){
32
+ this.nextMessageId = 1;
33
+ this.pendingMessages = new Map();
34
+ this.rslintPath = options.rslintPath || resolveRslintBinary();
35
+ this.dead = false;
36
+ this.closing = false;
37
+ this.process = spawn(this.rslintPath, [
38
+ '--api'
39
+ ], {
40
+ stdio: [
41
+ 'pipe',
42
+ 'pipe',
43
+ 'inherit'
44
+ ],
45
+ cwd: options.workingDirectory || process.cwd(),
46
+ env: {
47
+ ...process.env
48
+ }
49
+ });
50
+ this.setLoopActive(false);
51
+ this.process.stdout.on('data', (data)=>{
52
+ this.handleChunk(data);
53
+ });
54
+ this.process.on('error', (err)=>{
55
+ this.dead = true;
56
+ this.rejectAllPending(new Error(`rslint process error: ${err.message}`));
57
+ });
58
+ this.process.on('exit', (code, signal)=>{
59
+ this.dead = true;
60
+ if (this.closing) this.resolveAllPending();
61
+ else this.rejectAllPending(new Error(`rslint process exited unexpectedly (code=${code}, signal=${signal})`));
62
+ });
63
+ this.process.stdin.on('error', ()=>{});
64
+ this.chunks = [];
65
+ this.chunkSize = 0;
66
+ this.expectedSize = null;
67
+ }
68
+ setLoopActive(active) {
69
+ if (active) this.process.ref();
70
+ else this.process.unref();
71
+ for (const stream of [
72
+ this.process.stdin,
73
+ this.process.stdout
74
+ ])if (stream instanceof Socket) if (active) stream.ref();
75
+ else stream.unref();
76
+ }
77
+ async sendMessage(kind, data) {
78
+ return new Promise((resolve, reject)=>{
79
+ if (this.dead) return void reject(new Error('rslint service is no longer running'));
80
+ if ('exit' === kind) this.closing = true;
81
+ const id = this.nextMessageId++;
82
+ const message = {
83
+ id,
84
+ kind,
85
+ data
86
+ };
87
+ this.pendingMessages.set(id, {
88
+ resolve,
89
+ reject
90
+ });
91
+ if (1 === this.pendingMessages.size) this.setLoopActive(true);
92
+ const json = JSON.stringify(message);
93
+ const jsonBuffer = Buffer.from(json, 'utf8');
94
+ const length = Buffer.alloc(4);
95
+ length.writeUInt32LE(jsonBuffer.length, 0);
96
+ this.process.stdin.write(Buffer.concat([
97
+ length,
98
+ jsonBuffer
99
+ ]));
100
+ });
101
+ }
102
+ handleChunk(chunk) {
103
+ this.chunks.push(chunk);
104
+ this.chunkSize += chunk.length;
105
+ while(true){
106
+ if (null === this.expectedSize) {
107
+ if (this.chunkSize < 4) return;
108
+ const combined = Buffer.concat(this.chunks);
109
+ this.expectedSize = combined.readUInt32LE(0);
110
+ this.chunks = [
111
+ combined.subarray(4)
112
+ ];
113
+ this.chunkSize -= 4;
114
+ }
115
+ if (this.chunkSize < this.expectedSize) return;
116
+ const combined = Buffer.concat(this.chunks);
117
+ const message = combined.subarray(0, this.expectedSize).toString('utf8');
118
+ try {
119
+ const parsed = JSON.parse(message);
120
+ this.handleMessage(parsed);
121
+ } catch (err) {
122
+ console.error('Error parsing message:', err);
123
+ }
124
+ this.chunks = [
125
+ combined.subarray(this.expectedSize)
126
+ ];
127
+ this.chunkSize = this.chunks[0].length;
128
+ this.expectedSize = null;
129
+ }
130
+ }
131
+ handleMessage(message) {
132
+ const { id, kind, data } = message;
133
+ const pending = this.pendingMessages.get(id);
134
+ if (!pending) return;
135
+ this.pendingMessages.delete(id);
136
+ if ('error' === kind) pending.reject(new Error(data.message));
137
+ else pending.resolve(data);
138
+ if (0 === this.pendingMessages.size) this.setLoopActive(false);
139
+ }
140
+ rejectAllPending(err) {
141
+ if (0 === this.pendingMessages.size) return;
142
+ for (const [, pending] of this.pendingMessages)pending.reject(err);
143
+ this.pendingMessages.clear();
144
+ }
145
+ resolveAllPending() {
146
+ if (0 === this.pendingMessages.size) return;
147
+ for (const [, pending] of this.pendingMessages)pending.resolve(null);
148
+ this.pendingMessages.clear();
149
+ }
150
+ terminate() {
151
+ this.dead = true;
152
+ if (this.process && !this.process.killed) {
153
+ this.process.stdin.end();
154
+ this.process.kill();
155
+ }
156
+ this.rejectAllPending(new Error('rslint service terminated'));
157
+ }
158
+ }
159
+ async function lint(options) {
160
+ const service = new RSLintService(new NodeRslintService({
161
+ workingDirectory: options.workingDirectory
162
+ }));
163
+ const result = await service.lint(options);
164
+ await service.close();
165
+ return result;
166
+ }
167
+ export { NodeRslintService, lint };
package/dist/service.d.ts CHANGED
@@ -1,15 +1,3 @@
1
- export declare interface ApplyFixesRequest {
2
- fileContent: string;
3
- diagnostics: Diagnostic[];
4
- }
5
-
6
- export declare interface ApplyFixesResponse {
7
- fixedContent: string[];
8
- wasFixed: boolean;
9
- appliedCount: number;
10
- unappliedCount: number;
11
- }
12
-
13
1
  export declare interface Diagnostic {
14
2
  ruleName: string;
15
3
  message: string;
@@ -17,7 +5,14 @@ export declare interface Diagnostic {
17
5
  filePath: string;
18
6
  range: Range;
19
7
  severity?: string;
20
- suggestions: any[];
8
+ fixes?: Fix[];
9
+ suggestions?: Suggestion[];
10
+ }
11
+
12
+ declare interface Fix {
13
+ text: string;
14
+ startPos: number;
15
+ endPos: number;
21
16
  }
22
17
 
23
18
  /**
@@ -96,26 +91,32 @@ export declare interface IndexInfo {
96
91
  isReadonly: boolean;
97
92
  }
98
93
 
99
- export declare interface LanguageOptions {
100
- parserOptions?: ParserOptions;
94
+ export declare interface IpcMessage {
95
+ id: number;
96
+ kind: string;
97
+ data: any;
101
98
  }
102
99
 
103
100
  export declare interface LintOptions {
104
101
  files?: string[];
105
- config?: string;
102
+ config?: Record<string, unknown>[];
103
+ configDirectory?: string;
106
104
  workingDirectory?: string;
107
- ruleOptions?: Record<string, string>;
108
105
  fileContents?: Record<string, string>;
109
- languageOptions?: LanguageOptions;
110
106
  includeEncodedSourceFiles?: boolean;
107
+ fix?: boolean;
111
108
  }
112
109
 
113
110
  export declare interface LintResponse {
114
111
  diagnostics: Diagnostic[];
115
112
  errorCount: number;
113
+ warningCount: number;
114
+ fixableErrorCount: number;
115
+ fixableWarningCount: number;
116
116
  fileCount: number;
117
117
  ruleCount: number;
118
- duration: string;
118
+ lintedFiles?: string[];
119
+ output?: Record<string, string>;
119
120
  encodedSourceFiles?: Record<string, string>;
120
121
  }
121
122
 
@@ -218,9 +219,9 @@ export declare interface ParameterInfo {
218
219
  rest: boolean;
219
220
  }
220
221
 
221
- export declare interface ParserOptions {
222
- projectService?: boolean;
223
- project?: string[] | string;
222
+ export declare interface PendingMessage {
223
+ resolve: (data: any) => void;
224
+ reject: (error: Error) => void;
224
225
  }
225
226
 
226
227
  /**
@@ -242,7 +243,9 @@ export declare interface RSlintOptions {
242
243
  }
243
244
 
244
245
  /**
245
- * Main RslintService class that automatically uses the appropriate implementation
246
+ * Environment-agnostic RslintService facade: drives the handshake +
247
+ * lint / getAstInfo / close protocol over a backend (NodeRslintService or
248
+ * BrowserRslintService) supplied by the caller.
246
249
  */
247
250
  export declare class RSLintService {
248
251
  private readonly service;
@@ -251,10 +254,6 @@ export declare class RSLintService {
251
254
  * Run the linter on specified files
252
255
  */
253
256
  lint(options?: LintOptions): Promise<LintResponse>;
254
- /**
255
- * Apply fixes to a file based on diagnostics
256
- */
257
- applyFixes(options: ApplyFixesRequest): Promise<ApplyFixesResponse>;
258
257
  /**
259
258
  * Get detailed AST information at a specific position
260
259
  * Returns Node, Type, Symbol, Signature, and Flow information
@@ -288,6 +287,13 @@ export declare interface SignatureInfo {
288
287
  declaration?: NodeInfo;
289
288
  }
290
289
 
290
+ declare interface Suggestion {
291
+ messageId: string;
292
+ message: string;
293
+ data?: Record<string, string>;
294
+ fixes?: Fix[];
295
+ }
296
+
291
297
  /**
292
298
  * Detailed information about a TypeScript symbol
293
299
  */
package/dist/service.js CHANGED
@@ -4,29 +4,18 @@ class RSLintService {
4
4
  this.service = service;
5
5
  }
6
6
  async lint(options = {}) {
7
- const { files, config, workingDirectory, ruleOptions, fileContents, languageOptions, includeEncodedSourceFiles } = options;
7
+ const { files, config, configDirectory, workingDirectory, fileContents, includeEncodedSourceFiles, fix } = options;
8
8
  await this.service.sendMessage('handshake', {
9
9
  version: '1.0.0'
10
10
  });
11
11
  return this.service.sendMessage('lint', {
12
12
  files,
13
13
  config,
14
+ configDirectory,
14
15
  workingDirectory,
15
- ruleOptions,
16
16
  fileContents,
17
- languageOptions,
18
17
  includeEncodedSourceFiles,
19
- format: 'jsonline'
20
- });
21
- }
22
- async applyFixes(options) {
23
- const { fileContent, diagnostics } = options;
24
- await this.service.sendMessage('handshake', {
25
- version: '1.0.0'
26
- });
27
- return this.service.sendMessage('applyFixes', {
28
- fileContent,
29
- diagnostics
18
+ fix
30
19
  });
31
20
  }
32
21
  async getAstInfo(options) {
@@ -45,12 +34,10 @@ class RSLintService {
45
34
  });
46
35
  }
47
36
  async close() {
48
- return new Promise((resolve)=>{
49
- this.service.sendMessage('exit', {}).finally(()=>{
50
- this.service.terminate();
51
- resolve();
52
- });
53
- });
37
+ try {
38
+ await this.service.sendMessage('exit', {});
39
+ } catch {}
40
+ this.service.terminate();
54
41
  }
55
42
  }
56
43
  export { RSLintService };
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@rslint/core",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "exports": {
5
5
  ".": {
6
6
  "@typescript/source": "./src/index.ts",
7
7
  "default": "./dist/index.js"
8
8
  },
9
- "./browser": {
10
- "@typescript/source": "./src/browser.ts",
11
- "default": "./dist/browser.js"
12
- },
13
9
  "./service": {
14
- "@typescript/source": "./src/service.ts",
10
+ "@typescript/source": "./src/service/service.ts",
15
11
  "default": "./dist/service.js"
16
12
  },
13
+ "./internal": {
14
+ "@typescript/source": "./src/internal/node.ts",
15
+ "default": "./dist/internal.js"
16
+ },
17
17
  "./config-loader": {
18
- "@typescript/source": "./src/config-loader.ts",
18
+ "@typescript/source": "./src/config/config-loader.ts",
19
19
  "default": "./dist/config-loader.js"
20
20
  },
21
21
  "./eslint-plugin": {
@@ -47,13 +47,11 @@
47
47
  "rslint",
48
48
  "linter",
49
49
  "typescript",
50
- "go",
51
- "browser",
52
- "webworker"
50
+ "go"
53
51
  ],
54
52
  "devDependencies": {
55
- "@eslint/plugin-kit": "0.3.5",
56
- "@rslib/core": "0.22.0",
53
+ "@eslint/plugin-kit": "0.7.2",
54
+ "@rslib/core": "0.23.0",
57
55
  "@types/node": "24.0.14",
58
56
  "@types/picomatch": "4.0.2",
59
57
  "@typescript-eslint/scope-manager": "8.59.4",
@@ -66,7 +64,7 @@
66
64
  "globals": "17.6.0",
67
65
  "tinyglobby": "0.2.15",
68
66
  "typescript": "5.9.3",
69
- "@rslint/api": "0.6.2"
67
+ "@rslint/api": "0.6.4"
70
68
  },
71
69
  "peerDependencies": {
72
70
  "jiti": "^2.0.0"
@@ -77,14 +75,14 @@
77
75
  }
78
76
  },
79
77
  "optionalDependencies": {
80
- "@rslint/native-darwin-arm64": "0.6.2",
81
- "@rslint/native-darwin-x64": "0.6.2",
82
- "@rslint/native-linux-arm64-gnu": "0.6.2",
83
- "@rslint/native-linux-x64-gnu": "0.6.2",
84
- "@rslint/native-linux-x64-musl": "0.6.2",
85
- "@rslint/native-linux-arm64-musl": "0.6.2",
86
- "@rslint/native-win32-arm64-msvc": "0.6.2",
87
- "@rslint/native-win32-x64-msvc": "0.6.2"
78
+ "@rslint/native-darwin-arm64": "0.6.4",
79
+ "@rslint/native-linux-arm64-gnu": "0.6.4",
80
+ "@rslint/native-linux-x64-gnu": "0.6.4",
81
+ "@rslint/native-darwin-x64": "0.6.4",
82
+ "@rslint/native-linux-arm64-musl": "0.6.4",
83
+ "@rslint/native-win32-arm64-msvc": "0.6.4",
84
+ "@rslint/native-linux-x64-musl": "0.6.4",
85
+ "@rslint/native-win32-x64-msvc": "0.6.4"
88
86
  },
89
87
  "dependencies": {
90
88
  "picomatch": "4.0.4"
package/dist/34.js DELETED
@@ -1,33 +0,0 @@
1
- const NATIVE_PLUGINS = [
2
- "@typescript-eslint",
3
- 'import',
4
- 'jest',
5
- 'jsx-a11y',
6
- 'promise',
7
- 'react',
8
- 'react-hooks',
9
- 'unicorn'
10
- ];
11
- const NATIVE_PLUGIN_DECL_ALIASES = [
12
- 'eslint-plugin-import',
13
- 'eslint-plugin-jest',
14
- 'eslint-plugin-jsx-a11y',
15
- 'eslint-plugin-promise',
16
- 'eslint-plugin-react-hooks',
17
- 'eslint-plugin-unicorn'
18
- ];
19
- const NATIVE_PLUGIN_RESERVED_NAMES = new Set([
20
- ...NATIVE_PLUGINS,
21
- ...NATIVE_PLUGIN_DECL_ALIASES
22
- ]);
23
- function defineConfig(config) {
24
- return config;
25
- }
26
- function globalIgnores(ignorePatterns) {
27
- if (!Array.isArray(ignorePatterns)) throw new TypeError('ignorePatterns must be an array');
28
- if (0 === ignorePatterns.length) throw new TypeError('ignorePatterns must contain at least one pattern');
29
- return {
30
- ignores: ignorePatterns
31
- };
32
- }
33
- export { NATIVE_PLUGIN_RESERVED_NAMES, defineConfig, globalIgnores };
package/dist/browser.d.ts DELETED
@@ -1,52 +0,0 @@
1
- /**
2
- * Browser implementation of RslintService using web workers
3
- */
4
- export declare class BrowserRslintService implements RslintServiceInterface {
5
- private nextMessageId;
6
- private readonly pendingMessages;
7
- private worker;
8
- private readonly workerUrl;
9
- private chunks;
10
- private chunkSize;
11
- private expectedSize;
12
- constructor(options: RSlintOptions & {
13
- workerUrl: string;
14
- wasmUrl: string;
15
- });
16
- /**
17
- * Initialize the web worker
18
- */
19
- private ensureWorker;
20
- /**
21
- * Handle incoming binary data chunks
22
- */
23
- private handlePacket;
24
- /**
25
- * Combine multiple Uint8Array chunks into a single Uint8Array
26
- */
27
- private combineChunks;
28
- /**
29
- * Send a message to the worker
30
- */
31
- sendMessage(kind: string, data: any): Promise<any>;
32
- /**
33
- * Handle messages from the worker
34
- */
35
- private handleResponse;
36
- /**
37
- * Terminate the worker
38
- */
39
- terminate(): void;
40
- }
41
-
42
- declare interface RSlintOptions {
43
- rslintPath?: string;
44
- workingDirectory?: string;
45
- }
46
-
47
- declare interface RslintServiceInterface {
48
- sendMessage(kind: string, data: any): Promise<any>;
49
- terminate(): void;
50
- }
51
-
52
- export { }
package/dist/browser.js DELETED
@@ -1,115 +0,0 @@
1
- class BrowserRslintService {
2
- nextMessageId;
3
- pendingMessages;
4
- worker;
5
- workerUrl;
6
- chunks;
7
- chunkSize;
8
- expectedSize;
9
- constructor(options){
10
- this.nextMessageId = 1;
11
- this.pendingMessages = new Map();
12
- this.chunks = [];
13
- this.chunkSize = 0;
14
- this.expectedSize = null;
15
- this.workerUrl = options.workerUrl;
16
- this.ensureWorker(options.wasmUrl);
17
- }
18
- async ensureWorker(wasmUrl) {
19
- if (!this.worker) {
20
- this.worker = new Worker(this.workerUrl, {
21
- name: 'rslint-worker.js'
22
- });
23
- this.worker.onmessage = (event)=>{
24
- this.handlePacket(event.data);
25
- };
26
- this.worker.onerror = (error)=>{
27
- console.error('Worker error:', error);
28
- for (const [, pending] of this.pendingMessages)pending.reject(new Error(`Worker error: ${error.message}`));
29
- this.pendingMessages.clear();
30
- };
31
- this.worker.postMessage({
32
- kind: 'init',
33
- data: {
34
- version: '1.0.0',
35
- wasmURL: wasmUrl
36
- }
37
- });
38
- }
39
- return this.worker;
40
- }
41
- handlePacket(chunk) {
42
- this.chunks.push(chunk);
43
- this.chunkSize += chunk.length;
44
- while(true){
45
- if (null === this.expectedSize) {
46
- if (this.chunkSize < 4) return;
47
- const combined = this.combineChunks();
48
- const dataView = new DataView(combined.buffer, combined.byteOffset, combined.byteLength);
49
- this.expectedSize = dataView.getUint32(0, true);
50
- this.chunks = [
51
- combined.slice(4)
52
- ];
53
- this.chunkSize -= 4;
54
- }
55
- if (this.chunkSize < this.expectedSize) return;
56
- const combined = this.combineChunks();
57
- const messageBytes = combined.slice(0, this.expectedSize);
58
- const message = new TextDecoder().decode(messageBytes);
59
- try {
60
- const parsed = JSON.parse(message);
61
- this.handleResponse(parsed);
62
- } catch (err) {
63
- console.error('Error parsing message:', err);
64
- }
65
- this.chunks = [
66
- combined.slice(this.expectedSize)
67
- ];
68
- this.chunkSize = this.chunks[0].length;
69
- this.expectedSize = null;
70
- }
71
- }
72
- combineChunks() {
73
- if (1 === this.chunks.length) return this.chunks[0];
74
- const totalLength = this.chunks.reduce((sum, chunk)=>sum + chunk.length, 0);
75
- const combined = new Uint8Array(totalLength);
76
- let offset = 0;
77
- for (const chunk of this.chunks){
78
- combined.set(chunk, offset);
79
- offset += chunk.length;
80
- }
81
- return combined;
82
- }
83
- async sendMessage(kind, data) {
84
- return new Promise((resolve, reject)=>{
85
- const id = this.nextMessageId++;
86
- const message = {
87
- id,
88
- kind,
89
- data
90
- };
91
- this.pendingMessages.set(id, {
92
- resolve,
93
- reject
94
- });
95
- this.worker.postMessage(message);
96
- });
97
- }
98
- handleResponse(message) {
99
- const { id, kind, data } = message;
100
- const pending = this.pendingMessages.get(id);
101
- if (!pending) return;
102
- this.pendingMessages.delete(id);
103
- if ('error' === kind) pending.reject(new Error(data.message));
104
- else pending.resolve(data);
105
- }
106
- terminate() {
107
- if (this.worker) {
108
- for (const [, pending] of this.pendingMessages)pending.reject(new Error('Service terminated'));
109
- this.pendingMessages.clear();
110
- this.worker.terminate();
111
- this.worker = null;
112
- }
113
- }
114
- }
115
- export { BrowserRslintService };