@rslint/core 0.6.4 → 0.7.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/bin/rslint.js +23 -0
- package/dist/0~engine.js +109 -19
- package/dist/519.js +601 -0
- package/dist/770.js +18 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +42 -92
- package/dist/config-loader.d.ts +175 -9
- package/dist/config-loader.js +3 -161
- package/dist/eslint-plugin/index.d.ts +25 -13
- package/dist/eslint-plugin/index.js +92 -29
- package/dist/eslint-plugin/lint-worker.js +61 -27
- package/dist/eslint-plugin/types.d.ts +19 -9
- package/dist/index.d.ts +51 -21
- package/dist/index.js +1331 -91
- package/dist/internal.d.ts +38 -3
- package/dist/internal.js +81 -35
- package/dist/service.d.ts +90 -4
- package/dist/service.js +116 -10
- package/package.json +14 -14
- package/bin/rslint.cjs +0 -48
- package/dist/207.js +0 -897
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import node_path from "node:path";
|
|
2
2
|
import node_fs from "node:fs";
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import { resolveRslintBinary } from "./770.js";
|
|
5
|
+
const OUTPUT_FORMATS = [
|
|
6
|
+
'default',
|
|
7
|
+
'jsonline',
|
|
8
|
+
'github',
|
|
9
|
+
'gitlab'
|
|
10
|
+
];
|
|
11
|
+
function isOutputFormat(value) {
|
|
12
|
+
return OUTPUT_FORMATS.includes(value);
|
|
13
|
+
}
|
|
6
14
|
function isJSConfigFile(filePath) {
|
|
7
|
-
return /\.(ts|mts|js|mjs)$/.test(filePath);
|
|
15
|
+
return /\.(ts|mts|cts|js|mjs|cjs)$/.test(filePath);
|
|
8
16
|
}
|
|
9
17
|
function args_parseArgs(argv) {
|
|
10
18
|
const { values, tokens } = parseArgs({
|
|
@@ -13,11 +21,16 @@ function args_parseArgs(argv) {
|
|
|
13
21
|
tokens: true,
|
|
14
22
|
options: {
|
|
15
23
|
config: {
|
|
16
|
-
type: 'string'
|
|
24
|
+
type: 'string',
|
|
25
|
+
short: 'c'
|
|
17
26
|
},
|
|
18
27
|
init: {
|
|
19
28
|
type: 'boolean'
|
|
20
29
|
},
|
|
30
|
+
help: {
|
|
31
|
+
type: 'boolean',
|
|
32
|
+
short: 'h'
|
|
33
|
+
},
|
|
21
34
|
singleThreaded: {
|
|
22
35
|
type: 'boolean'
|
|
23
36
|
},
|
|
@@ -69,89 +82,13 @@ function args_parseArgs(argv) {
|
|
|
69
82
|
return {
|
|
70
83
|
config: values.config ?? null,
|
|
71
84
|
init: values.init ?? false,
|
|
85
|
+
help: values.help ?? false,
|
|
72
86
|
singleThreaded: values.singleThreaded ?? false,
|
|
87
|
+
format: values.format ?? null,
|
|
73
88
|
rest,
|
|
74
89
|
positionals
|
|
75
90
|
};
|
|
76
91
|
}
|
|
77
|
-
function classifyArgs(positionals, cwd) {
|
|
78
|
-
const files = [];
|
|
79
|
-
const dirs = [];
|
|
80
|
-
for (const arg of positionals){
|
|
81
|
-
const resolved = node_path.resolve(cwd, arg);
|
|
82
|
-
try {
|
|
83
|
-
const real = node_fs.realpathSync(resolved);
|
|
84
|
-
if (node_fs.statSync(real).isDirectory()) dirs.push(real);
|
|
85
|
-
else files.push(real);
|
|
86
|
-
} catch {
|
|
87
|
-
files.push(resolved);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
files,
|
|
92
|
-
dirs
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
async function runWithJSConfigs(binPath, configs, goArgs, cwd, singleThreaded) {
|
|
96
|
-
const configEntries = [];
|
|
97
|
-
const dirToPath = new Map();
|
|
98
|
-
const isSingleConfig = 1 === configs.size;
|
|
99
|
-
for (const [configPath, configDir] of configs){
|
|
100
|
-
let rawConfig;
|
|
101
|
-
try {
|
|
102
|
-
rawConfig = await loadConfigFile(configPath);
|
|
103
|
-
} catch (err) {
|
|
104
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
105
|
-
if (isSingleConfig) {
|
|
106
|
-
process.stderr.write(`Error: failed to load config ${configPath}: ${msg}\n`);
|
|
107
|
-
return 1;
|
|
108
|
-
}
|
|
109
|
-
process.stderr.write(`Warning: skipping config ${configPath}: ${msg}\n`);
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
let entries;
|
|
113
|
-
try {
|
|
114
|
-
entries = normalizeConfig(rawConfig);
|
|
115
|
-
} catch (err) {
|
|
116
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
117
|
-
if (isSingleConfig) {
|
|
118
|
-
process.stderr.write(`Error: invalid config in ${configPath}: ${msg}\n`);
|
|
119
|
-
return 1;
|
|
120
|
-
}
|
|
121
|
-
process.stderr.write(`Warning: skipping config ${configPath}: ${msg}\n`);
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
configEntries.push({
|
|
125
|
-
configDirectory: configDir,
|
|
126
|
-
entries
|
|
127
|
-
});
|
|
128
|
-
dirToPath.set(configDir, configPath);
|
|
129
|
-
}
|
|
130
|
-
const { runEngine } = await import("./0~engine.js");
|
|
131
|
-
if (0 === configEntries.length) return runEngine({
|
|
132
|
-
binPath,
|
|
133
|
-
goArgs,
|
|
134
|
-
configs: [],
|
|
135
|
-
cwd
|
|
136
|
-
});
|
|
137
|
-
const filteredEntries = filterConfigsByParentIgnores(configEntries);
|
|
138
|
-
const { eslintPluginEntries, pluginConfigs } = collectPluginMeta(filteredEntries.map((ce)=>({
|
|
139
|
-
configPath: dirToPath.get(ce.configDirectory) ?? '',
|
|
140
|
-
configDirectory: ce.configDirectory,
|
|
141
|
-
entries: ce.entries
|
|
142
|
-
})));
|
|
143
|
-
return runEngine({
|
|
144
|
-
binPath,
|
|
145
|
-
goArgs,
|
|
146
|
-
configs: filteredEntries,
|
|
147
|
-
cwd,
|
|
148
|
-
eslintPluginEntries,
|
|
149
|
-
pluginConfigs,
|
|
150
|
-
runtime: {
|
|
151
|
-
singleThreaded
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
92
|
async function run(binPath, argv, startTime) {
|
|
156
93
|
const cwd = process.cwd();
|
|
157
94
|
const args = args_parseArgs(argv);
|
|
@@ -162,10 +99,13 @@ async function run(binPath, argv, startTime) {
|
|
|
162
99
|
goArgs: [
|
|
163
100
|
'--init'
|
|
164
101
|
],
|
|
165
|
-
configs: [],
|
|
166
102
|
cwd
|
|
167
103
|
});
|
|
168
104
|
}
|
|
105
|
+
if (!args.help && null !== args.format && !isOutputFormat(args.format)) {
|
|
106
|
+
process.stderr.write(`error: invalid output format ${JSON.stringify(args.format)} (expected ${OUTPUT_FORMATS.slice(0, -1).join(', ')}, or ${OUTPUT_FORMATS.at(-1)})\n`);
|
|
107
|
+
return 2;
|
|
108
|
+
}
|
|
169
109
|
if (args.config) {
|
|
170
110
|
const configPath = node_path.resolve(cwd, args.config);
|
|
171
111
|
if (!node_fs.existsSync(configPath)) {
|
|
@@ -177,12 +117,9 @@ async function run(binPath, argv, startTime) {
|
|
|
177
117
|
`--start-time=${startTime}`,
|
|
178
118
|
...args.rest
|
|
179
119
|
];
|
|
180
|
-
const
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
for (const [configPath, configDir] of configs)if (isJSConfigFile(configPath)) jsConfigs.set(configPath, configDir);
|
|
184
|
-
if (jsConfigs.size > 0) return runWithJSConfigs(binPath, jsConfigs, goArgs, cwd, args.singleThreaded);
|
|
185
|
-
const jsonGoArgs = args.config ? [
|
|
120
|
+
const explicitConfigPath = args.config ? node_path.resolve(cwd, args.config) : null;
|
|
121
|
+
const usesExplicitJSConfig = null != explicitConfigPath && isJSConfigFile(explicitConfigPath);
|
|
122
|
+
const jsonGoArgs = args.config && !usesExplicitJSConfig ? [
|
|
186
123
|
'--config',
|
|
187
124
|
args.config,
|
|
188
125
|
...goArgs
|
|
@@ -191,8 +128,21 @@ async function run(binPath, argv, startTime) {
|
|
|
191
128
|
return runEngine({
|
|
192
129
|
binPath,
|
|
193
130
|
goArgs: jsonGoArgs,
|
|
194
|
-
|
|
195
|
-
|
|
131
|
+
cwd,
|
|
132
|
+
runtime: {
|
|
133
|
+
singleThreaded: args.singleThreaded
|
|
134
|
+
},
|
|
135
|
+
extraInit: {
|
|
136
|
+
configDiscovery: {
|
|
137
|
+
mode: usesExplicitJSConfig ? 'explicit' : args.config ? 'disabled' : 'auto',
|
|
138
|
+
explicitConfigPath: usesExplicitJSConfig ? explicitConfigPath : void 0
|
|
139
|
+
}
|
|
140
|
+
}
|
|
196
141
|
});
|
|
197
142
|
}
|
|
198
|
-
|
|
143
|
+
async function runCLI({ argv = process.argv } = {}) {
|
|
144
|
+
const startTime = Date.now();
|
|
145
|
+
const exitCode = await run(resolveRslintBinary(), argv.slice(2), startTime);
|
|
146
|
+
process.exitCode = exitCode;
|
|
147
|
+
}
|
|
148
|
+
export { run, runCLI };
|
package/dist/config-loader.d.ts
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
|
+
/** Go's final effective-ID selection after ignore/ownership resolution. */
|
|
2
|
+
export declare interface ActivateConfigsRequest {
|
|
3
|
+
protocolVersion: typeof CONFIG_DISCOVERY_PROTOCOL_VERSION;
|
|
4
|
+
transactionId: string;
|
|
5
|
+
effectiveConfigIds: string[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Minimal activation payload returned across IPC/JSON-RPC to Go. */
|
|
9
|
+
export declare interface ActivateConfigsResponse {
|
|
10
|
+
transactionId: string;
|
|
11
|
+
eslintPluginEntries: ConfigModuleEslintPluginEntry[];
|
|
12
|
+
}
|
|
13
|
+
|
|
1
14
|
/**
|
|
2
15
|
* Derive, from normalized configs, the ESLint-plugin metadata the Go core
|
|
3
16
|
* needs (`{prefix, ruleNames}` for placeholder rules) and the worker-pool
|
|
4
17
|
* descriptors (only for configs that mount plugins — others stay
|
|
5
|
-
* zero-overhead).
|
|
6
|
-
*
|
|
18
|
+
* zero-overhead). ConfigModuleHost invokes this only after Go selects the
|
|
19
|
+
* transaction's effective IDs, so discarded candidates cannot leak plugin
|
|
20
|
+
* placeholders or worker routes into the activated catalog.
|
|
7
21
|
* ruleNames for a shared prefix are merged (set union) across configs: Go's
|
|
8
22
|
* placeholder registry is a per-prefix superset, while the worker routes the
|
|
9
|
-
* actual rules per
|
|
10
|
-
*
|
|
11
|
-
*
|
|
23
|
+
* actual rules per config. This is not the validation boundary: worker config
|
|
24
|
+
* loading rejects conflicting plugin definitions, including duplicate routing
|
|
25
|
+
* descriptors that mount different instances under the same prefix.
|
|
12
26
|
*/
|
|
13
27
|
export declare function collectPluginMeta(configs: ReadonlyArray<{
|
|
14
28
|
configPath: string;
|
|
@@ -23,13 +37,165 @@ export declare function collectPluginMeta(configs: ReadonlyArray<{
|
|
|
23
37
|
};
|
|
24
38
|
|
|
25
39
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
40
|
+
* Logical protocol shared by the native CLI, programmatic API, and LSP config
|
|
41
|
+
* discovery adapters. The transports differ (framed IPC versus JSON-RPC), but
|
|
42
|
+
* every adapter sends these payloads to the same Node-side module host.
|
|
43
|
+
*
|
|
44
|
+
* Paths in requests identify values selected by Go. Node may native-normalize
|
|
45
|
+
* configPath for local I/O, but configDirectory is an opaque routing identity
|
|
46
|
+
* and must retain its exact spelling. Load responses correlate only by opaque
|
|
47
|
+
* candidate ID. Activation responses contain only the transaction identity and
|
|
48
|
+
* plugin metadata consumed by Go; Node-only preparation data never crosses the
|
|
49
|
+
* transport boundary.
|
|
50
|
+
*/
|
|
51
|
+
export declare const CONFIG_DISCOVERY_PROTOCOL_VERSION: 1;
|
|
52
|
+
|
|
53
|
+
export declare interface ConfigEntry {
|
|
54
|
+
configDirectory: string;
|
|
55
|
+
entries: unknown[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Node-local activation data derived from exactly the effective IDs selected
|
|
60
|
+
* by Go. It is exposed only to the prepare callback and is never serialized
|
|
61
|
+
* as the activation response.
|
|
62
|
+
*/
|
|
63
|
+
export declare interface ConfigModuleActivationPlan {
|
|
64
|
+
transactionId: string;
|
|
65
|
+
configs: EffectiveConfigModule[];
|
|
66
|
+
eslintPluginEntries: ConfigModuleEslintPluginEntry[];
|
|
67
|
+
pluginConfigs: ConfigModulePluginDescriptor[];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export declare interface ConfigModuleCandidate {
|
|
71
|
+
/** Opaque, transaction-local identity allocated by the Go coordinator. */
|
|
72
|
+
id: string;
|
|
73
|
+
/** Absolute path to the JS/TS config module Node must execute. */
|
|
74
|
+
configPath: string;
|
|
75
|
+
/** Go-authoritative directory used for config matching and plugin routing. */
|
|
76
|
+
configDirectory: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export declare interface ConfigModuleEslintPluginEntry {
|
|
80
|
+
prefix: string;
|
|
81
|
+
ruleNames: string[];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Executes config modules on behalf of Go's discovery coordinator.
|
|
86
|
+
*
|
|
87
|
+
* A host may serve multiple concurrent discovery transactions. Operations in
|
|
88
|
+
* one transaction are serialized (frontier batches can safely build on earlier
|
|
89
|
+
* batches), while separate transactions remain independent. Call
|
|
90
|
+
* deleteSession after commit/abort so normalized entries do not remain live.
|
|
91
|
+
*/
|
|
92
|
+
export declare class ConfigModuleHost {
|
|
93
|
+
#private;
|
|
94
|
+
constructor(options?: ConfigModuleHostOptions);
|
|
95
|
+
/** Load and normalize one discovery frontier without fail-fast evaluation. */
|
|
96
|
+
loadConfigs(request: LoadConfigsRequest, signal?: AbortSignal): Promise<LoadConfigsResponse>;
|
|
97
|
+
/**
|
|
98
|
+
* Protocol-facing activation transaction.
|
|
99
|
+
*
|
|
100
|
+
* Plugin workers re-import plugin-bearing config modules. The optional
|
|
101
|
+
* prepare callback therefore runs between two source-fingerprint checks.
|
|
102
|
+
* A caller cannot publish the normalized activation until every effective
|
|
103
|
+
* source still matches the bytes from which that activation was derived.
|
|
104
|
+
*/
|
|
105
|
+
activateConfigs(request: ActivateConfigsRequest, signal?: AbortSignal, prepare?: (plan: ConfigModuleActivationPlan) => Promise<void>): Promise<ActivateConfigsResponse>;
|
|
106
|
+
/** Drop all normalized module state for a committed or aborted transaction. */
|
|
107
|
+
deleteSession(transactionId: string): boolean;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export declare interface ConfigModuleHostOptions {
|
|
111
|
+
/** Test/embedding seam; production defaults to loadConfigFile. */
|
|
112
|
+
loadCached?: ConfigModuleLoader;
|
|
113
|
+
/** Test/embedding seam; production defaults to loadConfigFileFresh. */
|
|
114
|
+
loadFresh?: ConfigModuleLoader;
|
|
115
|
+
/** Test/embedding seam; production defaults to fs.promises.readFile. */
|
|
116
|
+
readSource?: ConfigSourceReader;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
declare type ConfigModuleLoader = (configPath: string) => Promise<unknown>;
|
|
120
|
+
|
|
121
|
+
export declare type ConfigModuleLoadMode = 'cached' | 'fresh';
|
|
122
|
+
|
|
123
|
+
export declare type ConfigModuleLoadResult = LoadedConfigModuleResult | FailedConfigModuleResult;
|
|
124
|
+
|
|
125
|
+
export declare type ConfigModulePluginDescriptor = PluginConfigDescriptor;
|
|
126
|
+
|
|
127
|
+
declare type ConfigSourceReader = (configPath: string) => Promise<Uint8Array>;
|
|
128
|
+
|
|
129
|
+
export declare interface EffectiveConfigModule {
|
|
130
|
+
id: string;
|
|
131
|
+
configPath: string;
|
|
132
|
+
configDirectory: string;
|
|
133
|
+
entries: Record<string, unknown>[];
|
|
134
|
+
sourceFingerprint: string;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export declare interface FailedConfigModuleResult {
|
|
138
|
+
id: string;
|
|
139
|
+
status: 'failed';
|
|
140
|
+
error: {
|
|
141
|
+
message: string;
|
|
142
|
+
code?: string;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Filter loaded nested config candidates whose directory is covered by an
|
|
148
|
+
* ancestor config's global ignores. Candidate discovery and module loading are
|
|
149
|
+
* intentionally independent from this effective-catalog step.
|
|
150
|
+
*
|
|
151
|
+
* `forceIncludeConfigDirectories` is for explicit CLI file targets: ESLint
|
|
152
|
+
* resolves the nearest config for an explicit file even when parent directory
|
|
153
|
+
* traversal would have been blocked.
|
|
154
|
+
*/
|
|
155
|
+
export declare function filterConfigsByParentIgnores<T extends ConfigEntry>(configEntries: T[], forceIncludeConfigDirectories?: Set<string>): T[];
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Load a selected JS/TS config file.
|
|
159
|
+
* TypeScript modules use native import when Node.js supports type stripping
|
|
160
|
+
* and otherwise fall back to jiti. Other module formats use native import.
|
|
30
161
|
*/
|
|
31
162
|
export declare function loadConfigFile(configPath: string): Promise<unknown>;
|
|
32
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Load a config without reusing the config module from a previous reload.
|
|
166
|
+
* TypeScript loading selects native stripping or jiti before evaluation so a
|
|
167
|
+
* runtime exception from the config is propagated without executing it again.
|
|
168
|
+
*/
|
|
169
|
+
export declare function loadConfigFileFresh(configPath: string): Promise<unknown>;
|
|
170
|
+
|
|
171
|
+
export declare interface LoadConfigsRequest {
|
|
172
|
+
protocolVersion: typeof CONFIG_DISCOVERY_PROTOCOL_VERSION;
|
|
173
|
+
/** Isolates batches belonging to one discovery transaction. */
|
|
174
|
+
transactionId: string;
|
|
175
|
+
/**
|
|
176
|
+
* `cached` preserves one-shot CLI module-import semantics. `fresh` is used
|
|
177
|
+
* by long-lived API and editor refreshes; it cache-busts the entry module,
|
|
178
|
+
* while static transitive imports retain Node's normal module cache.
|
|
179
|
+
*/
|
|
180
|
+
loadMode: ConfigModuleLoadMode;
|
|
181
|
+
/** Serialize module evaluation when the CLI requested --singleThreaded. */
|
|
182
|
+
singleThreaded?: boolean;
|
|
183
|
+
candidates: ConfigModuleCandidate[];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export declare interface LoadConfigsResponse {
|
|
187
|
+
transactionId: string;
|
|
188
|
+
/** Results are in exactly the same order as request.candidates. */
|
|
189
|
+
results: ConfigModuleLoadResult[];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export declare interface LoadedConfigModuleResult {
|
|
193
|
+
id: string;
|
|
194
|
+
status: 'loaded';
|
|
195
|
+
/** Serializable normalizeConfig output. Live plugin objects never cross. */
|
|
196
|
+
entries: Record<string, unknown>[];
|
|
197
|
+
}
|
|
198
|
+
|
|
33
199
|
/**
|
|
34
200
|
* Validate and strip non-serializable fields from the config.
|
|
35
201
|
*/
|
package/dist/config-loader.js
CHANGED
|
@@ -1,161 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
"@typescript-eslint",
|
|
5
|
-
'import',
|
|
6
|
-
'jest',
|
|
7
|
-
'jsx-a11y',
|
|
8
|
-
'promise',
|
|
9
|
-
'react',
|
|
10
|
-
'react-hooks',
|
|
11
|
-
'unicorn'
|
|
12
|
-
];
|
|
13
|
-
const NATIVE_PLUGIN_DECL_ALIASES = [
|
|
14
|
-
'eslint-plugin-import',
|
|
15
|
-
'eslint-plugin-jest',
|
|
16
|
-
'eslint-plugin-jsx-a11y',
|
|
17
|
-
'eslint-plugin-promise',
|
|
18
|
-
'eslint-plugin-react-hooks',
|
|
19
|
-
'eslint-plugin-unicorn'
|
|
20
|
-
];
|
|
21
|
-
const NATIVE_PLUGIN_RESERVED_NAMES = new Set([
|
|
22
|
-
...NATIVE_PLUGINS,
|
|
23
|
-
...NATIVE_PLUGIN_DECL_ALIASES
|
|
24
|
-
]);
|
|
25
|
-
function defineConfig(config) {
|
|
26
|
-
return config;
|
|
27
|
-
}
|
|
28
|
-
function globalIgnores(ignorePatterns) {
|
|
29
|
-
if (!Array.isArray(ignorePatterns)) throw new TypeError('ignorePatterns must be an array');
|
|
30
|
-
if (0 === ignorePatterns.length) throw new TypeError('ignorePatterns must contain at least one pattern');
|
|
31
|
-
return {
|
|
32
|
-
ignores: ignorePatterns
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
function selectPluginSource(entry) {
|
|
36
|
-
if (null == entry || 'object' != typeof entry) return null;
|
|
37
|
-
const e = entry;
|
|
38
|
-
if (null != e.plugins && 'object' == typeof e.plugins && !Array.isArray(e.plugins)) return e.plugins;
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
function unwrapPluginModule(mod) {
|
|
42
|
-
if (null == mod || 'object' != typeof mod) return null;
|
|
43
|
-
const m = mod;
|
|
44
|
-
if (null != m.default && 'object' == typeof m.default) return m.default;
|
|
45
|
-
return mod;
|
|
46
|
-
}
|
|
47
|
-
async function loadConfigFile(configPath) {
|
|
48
|
-
const ext = node_path.extname(configPath);
|
|
49
|
-
if ('.js' === ext || '.mjs' === ext) {
|
|
50
|
-
const mod = await import(pathToFileURL(configPath).href);
|
|
51
|
-
return mod.default ?? mod;
|
|
52
|
-
}
|
|
53
|
-
if ('.ts' === ext || '.mts' === ext) {
|
|
54
|
-
const useNative = Boolean(process.features.typescript);
|
|
55
|
-
if (useNative) {
|
|
56
|
-
const mod = await import(pathToFileURL(configPath).href);
|
|
57
|
-
return mod.default ?? mod;
|
|
58
|
-
}
|
|
59
|
-
const jiti = await loadJiti(configPath);
|
|
60
|
-
if (jiti) {
|
|
61
|
-
const resolved = await jiti.import(configPath);
|
|
62
|
-
return extractDefault(resolved);
|
|
63
|
-
}
|
|
64
|
-
throw new Error(`Failed to load TypeScript config file: ${configPath}\nTo load .ts config files, either:\n 1. Use Node.js >= 22.6 (with native TypeScript support)\n 2. Install jiti as a dependency: npm install -D jiti`);
|
|
65
|
-
}
|
|
66
|
-
throw new Error(`Unsupported config file extension: ${ext}`);
|
|
67
|
-
}
|
|
68
|
-
async function loadJiti(configPath) {
|
|
69
|
-
try {
|
|
70
|
-
const { createJiti } = await import("jiti");
|
|
71
|
-
return createJiti(node_path.dirname(configPath), {
|
|
72
|
-
interopDefault: true
|
|
73
|
-
});
|
|
74
|
-
} catch {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
function extractDefault(mod) {
|
|
79
|
-
if ('object' == typeof mod && null !== mod && 'default' in mod) return mod.default;
|
|
80
|
-
return mod;
|
|
81
|
-
}
|
|
82
|
-
function normalizeConfig(config) {
|
|
83
|
-
if (!Array.isArray(config)) throw new Error(`rslint config must export an array (flat config format), got ${typeof config}`);
|
|
84
|
-
return config.filter((entry, index)=>{
|
|
85
|
-
if (null == entry || 'object' != typeof entry) {
|
|
86
|
-
console.warn(`[rslint] Config entry at index ${index} is not an object (got ${null === entry ? 'null' : typeof entry}), skipping.`);
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
return true;
|
|
90
|
-
}).map((entry, index)=>{
|
|
91
|
-
if (null != entry.files && !Array.isArray(entry.files)) throw new Error(`[rslint] Config entry at index ${index}: "files" must be an array, got ${typeof entry.files}`);
|
|
92
|
-
if (null != entry.ignores && !Array.isArray(entry.ignores)) throw new Error(`[rslint] Config entry at index ${index}: "ignores" must be an array, got ${typeof entry.ignores}`);
|
|
93
|
-
const pluginSource = selectPluginSource(entry);
|
|
94
|
-
const eslintPluginMeta = {};
|
|
95
|
-
const pluginPrefixes = [];
|
|
96
|
-
if (null != pluginSource) for (const prefix of Object.keys(pluginSource)){
|
|
97
|
-
if (NATIVE_PLUGIN_RESERVED_NAMES.has(prefix)) throw new Error(`[rslint] Config entry at index ${index}: plugins prefix "${prefix}" collides with the built-in plugin of the same name; choose a different prefix.`);
|
|
98
|
-
const plugin = unwrapPluginModule(pluginSource[prefix]);
|
|
99
|
-
const pluginRules = plugin?.rules;
|
|
100
|
-
if (null == pluginRules || 'object' != typeof pluginRules) throw new Error(`[rslint] Config entry at index ${index}: plugins["${prefix}"] must expose a "rules" object.`);
|
|
101
|
-
eslintPluginMeta[prefix] = {
|
|
102
|
-
ruleNames: Object.keys(pluginRules).sort()
|
|
103
|
-
};
|
|
104
|
-
pluginPrefixes.push(prefix);
|
|
105
|
-
}
|
|
106
|
-
const stringPlugins = Array.isArray(entry.plugins) ? entry.plugins.filter((p)=>'string' == typeof p) : [];
|
|
107
|
-
const plugins = [
|
|
108
|
-
...new Set([
|
|
109
|
-
...stringPlugins,
|
|
110
|
-
...pluginPrefixes
|
|
111
|
-
])
|
|
112
|
-
];
|
|
113
|
-
return {
|
|
114
|
-
files: entry.files,
|
|
115
|
-
ignores: entry.ignores,
|
|
116
|
-
languageOptions: entry.languageOptions,
|
|
117
|
-
rules: entry.rules,
|
|
118
|
-
plugins,
|
|
119
|
-
settings: entry.settings,
|
|
120
|
-
...pluginPrefixes.length > 0 ? {
|
|
121
|
-
eslintPlugins: eslintPluginMeta
|
|
122
|
-
} : {}
|
|
123
|
-
};
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
function collectPluginMeta(configs) {
|
|
127
|
-
const isPluginMetaMap = (v)=>null !== v && 'object' == typeof v;
|
|
128
|
-
const byPrefix = new Map();
|
|
129
|
-
const pluginConfigs = [];
|
|
130
|
-
for (const c of configs){
|
|
131
|
-
let hasPlugins = false;
|
|
132
|
-
for (const entry of c.entries){
|
|
133
|
-
if (null === entry || 'object' != typeof entry || !('eslintPlugins' in entry)) continue;
|
|
134
|
-
const ep = entry.eslintPlugins;
|
|
135
|
-
if (isPluginMetaMap(ep)) for (const [prefix, meta] of Object.entries(ep)){
|
|
136
|
-
hasPlugins = true;
|
|
137
|
-
const existing = byPrefix.get(prefix);
|
|
138
|
-
if (existing) {
|
|
139
|
-
for (const name of meta.ruleNames)if (!existing.includes(name)) existing.push(name);
|
|
140
|
-
} else byPrefix.set(prefix, [
|
|
141
|
-
...meta.ruleNames
|
|
142
|
-
]);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
if (hasPlugins) pluginConfigs.push({
|
|
146
|
-
configPath: c.configPath,
|
|
147
|
-
configDirectory: c.configDirectory
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
const eslintPluginEntries = [
|
|
151
|
-
...byPrefix.entries()
|
|
152
|
-
].map(([prefix, ruleNames])=>({
|
|
153
|
-
prefix,
|
|
154
|
-
ruleNames
|
|
155
|
-
}));
|
|
156
|
-
return {
|
|
157
|
-
eslintPluginEntries,
|
|
158
|
-
pluginConfigs
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
export { collectPluginMeta, defineConfig, globalIgnores, loadConfigFile, normalizeConfig };
|
|
1
|
+
var config_loader_CONFIG_DISCOVERY_PROTOCOL_VERSION = 1;
|
|
2
|
+
export { ConfigModuleHost, collectPluginMeta, filterConfigsByParentIgnores, loadConfigFile, loadConfigFileFresh, normalizeConfig } from "./519.js";
|
|
3
|
+
export { config_loader_CONFIG_DISCOVERY_PROTOCOL_VERSION as CONFIG_DISCOVERY_PROTOCOL_VERSION };
|
|
@@ -40,12 +40,6 @@ declare interface Comment {
|
|
|
40
40
|
loc: SourceLocation;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
/**
|
|
44
|
-
* Types shared between the eslint-plugin host and its lint workers.
|
|
45
|
-
*
|
|
46
|
-
* Wire-format / IPC frame types (the Go↔Node frame contract) live in
|
|
47
|
-
* `src/ipc/protocol.ts` — the single source the CLI host consumes.
|
|
48
|
-
*/
|
|
49
43
|
/**
|
|
50
44
|
* Per-config descriptor handed to the worker pool. Each worker imports
|
|
51
45
|
* every descriptor's `configPath` once at init, then routes per-file
|
|
@@ -55,10 +49,11 @@ declare interface Comment {
|
|
|
55
49
|
* it as a Map key for per-file dispatch.
|
|
56
50
|
*/
|
|
57
51
|
export declare interface ConfigDescriptor {
|
|
58
|
-
/** Absolute filesystem path of the
|
|
52
|
+
/** Absolute filesystem path of the selected JS/TS config file. */
|
|
59
53
|
configPath: string;
|
|
60
|
-
/**
|
|
61
|
-
*
|
|
54
|
+
/** Go-authoritative absolute matching/routing directory. In explicit mode
|
|
55
|
+
* this can differ from the config file's parent and MUST byte-match the
|
|
56
|
+
* `ConfigKey` Go emits during plugin-lint dispatch. */
|
|
62
57
|
configDirectory: string;
|
|
63
58
|
}
|
|
64
59
|
|
|
@@ -101,6 +96,8 @@ export declare interface Diagnostic {
|
|
|
101
96
|
* doesn't need to re-validate Go's serialization.
|
|
102
97
|
*/
|
|
103
98
|
export declare interface EslintPluginLintRequest {
|
|
99
|
+
/** LSP config/worker generation. Omitted by the CLI's single-host path. */
|
|
100
|
+
generation?: string;
|
|
104
101
|
files: ReadonlyArray<{
|
|
105
102
|
path: string;
|
|
106
103
|
/**
|
|
@@ -119,8 +116,8 @@ export declare interface EslintPluginLintRequest {
|
|
|
119
116
|
languageOptions?: unknown;
|
|
120
117
|
settings?: Record<string, unknown>;
|
|
121
118
|
/**
|
|
122
|
-
* The owning config's directory in the
|
|
123
|
-
* its `ConfigDescriptor.configDirectory
|
|
119
|
+
* The owning config's absolute filesystem directory in the same form the
|
|
120
|
+
* host used as its `ConfigDescriptor.configDirectory`.
|
|
124
121
|
* The worker uses it to pick the right `LoadedPlugins`. Empty when
|
|
125
122
|
* no JS config governs the file.
|
|
126
123
|
*/
|
|
@@ -192,6 +189,21 @@ declare interface Fix {
|
|
|
192
189
|
text: string;
|
|
193
190
|
}
|
|
194
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Types shared between the eslint-plugin host and its lint workers.
|
|
194
|
+
*
|
|
195
|
+
* Wire-format / IPC frame types (the Go↔Node frame contract) live in
|
|
196
|
+
* `src/ipc/protocol.ts` — the single source the CLI host consumes.
|
|
197
|
+
*/
|
|
198
|
+
/**
|
|
199
|
+
* ESLint-compatible access values carried to the plugin worker. This mirrors
|
|
200
|
+
* the public config authoring type without coupling the worker build project to
|
|
201
|
+
* the config-loader build project.
|
|
202
|
+
*/
|
|
203
|
+
declare type GlobalAccess = boolean | null | 'true' | 'false' | 'readonly' | 'readable' | 'writable' | 'writeable' | 'off';
|
|
204
|
+
|
|
205
|
+
declare type GlobalsConfig = Record<string, GlobalAccess>;
|
|
206
|
+
|
|
195
207
|
/** Minimal node shape — the fixer only needs `range`. */
|
|
196
208
|
declare interface HasRange {
|
|
197
209
|
range: [number, number];
|
|
@@ -223,7 +235,7 @@ declare interface LanguageOptions {
|
|
|
223
235
|
ecmaVersion?: number | 'latest';
|
|
224
236
|
/** Module / script / commonjs — top-level in ESLint v10. Same rationale as `ecmaVersion`. */
|
|
225
237
|
sourceType?: 'module' | 'script' | 'commonjs';
|
|
226
|
-
globals?:
|
|
238
|
+
globals?: GlobalsConfig;
|
|
227
239
|
/**
|
|
228
240
|
* Parser-specific extras. Only `ecmaFeatures` lives here in v10
|
|
229
241
|
* (rules that gate on `jsx` / `globalReturn` / `impliedStrict` read
|
|
@@ -283,7 +295,7 @@ export declare interface LintFileRequest {
|
|
|
283
295
|
languageOptions?: {
|
|
284
296
|
ecmaVersion?: number | 'latest';
|
|
285
297
|
sourceType?: 'module' | 'script' | 'commonjs';
|
|
286
|
-
globals?:
|
|
298
|
+
globals?: GlobalsConfig;
|
|
287
299
|
parserOptions?: {
|
|
288
300
|
ecmaFeatures?: {
|
|
289
301
|
jsx?: boolean;
|