@rslint/core 0.6.5 → 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/dist/0~engine.js +109 -19
- package/dist/519.js +601 -0
- package/dist/cli.js +33 -983
- 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 +61 -27
- package/dist/eslint-plugin/lint-worker.js +61 -27
- package/dist/eslint-plugin/types.d.ts +19 -9
- package/dist/index.d.ts +38 -20
- package/dist/index.js +1328 -91
- package/dist/internal.d.ts +38 -3
- package/dist/internal.js +80 -18
- package/dist/service.d.ts +90 -4
- package/dist/service.js +116 -10
- package/package.json +10 -10
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;
|
|
@@ -23169,9 +23169,11 @@ function scope_factory_analyze(ast, opts) {
|
|
|
23169
23169
|
childVisitorKeys: VISITOR_KEYS
|
|
23170
23170
|
});
|
|
23171
23171
|
}
|
|
23172
|
+
const syntheticGlobals = new WeakSet();
|
|
23172
23173
|
function ensureGlobal(gs, name, mode) {
|
|
23173
23174
|
const existing = gs.set?.get(name);
|
|
23174
23175
|
if (existing) {
|
|
23176
|
+
if (!syntheticGlobals.has(existing)) return existing;
|
|
23175
23177
|
existing.writeable = 'writable' === mode;
|
|
23176
23178
|
existing.eslintImplicitGlobalSetting = mode;
|
|
23177
23179
|
return existing;
|
|
@@ -23185,6 +23187,7 @@ function ensureGlobal(gs, name, mode) {
|
|
|
23185
23187
|
eslintImplicitGlobalSetting: mode,
|
|
23186
23188
|
scope: gs
|
|
23187
23189
|
};
|
|
23190
|
+
syntheticGlobals.add(v);
|
|
23188
23191
|
gs.variables.push(v);
|
|
23189
23192
|
gs.set?.set(name, v);
|
|
23190
23193
|
return v;
|
|
@@ -23222,28 +23225,50 @@ function seedGlobals(scopeManager, globals) {
|
|
|
23222
23225
|
const gs = sm.globalScope;
|
|
23223
23226
|
if (!gs) return;
|
|
23224
23227
|
if (!globals) return void resolveThroughReferences(gs);
|
|
23225
|
-
for (const [name,
|
|
23226
|
-
|
|
23227
|
-
|
|
23228
|
-
|
|
23229
|
-
|
|
23230
|
-
|
|
23231
|
-
|
|
23232
|
-
|
|
23233
|
-
|
|
23228
|
+
for (const [name, access] of Object.entries(globals)){
|
|
23229
|
+
const mode = normalizeGlobalAccess(access);
|
|
23230
|
+
if (null != mode) {
|
|
23231
|
+
if ('off' === mode) {
|
|
23232
|
+
const v = gs.set?.get(name);
|
|
23233
|
+
if (v && syntheticGlobals.has(v)) {
|
|
23234
|
+
if (Array.isArray(v.references) && v.references.length > 0) {
|
|
23235
|
+
const through = gs.through ?? (gs.through = []);
|
|
23236
|
+
for (const ref of v.references){
|
|
23237
|
+
ref.resolved = null;
|
|
23238
|
+
through.push(ref);
|
|
23239
|
+
}
|
|
23240
|
+
v.references = [];
|
|
23234
23241
|
}
|
|
23235
|
-
|
|
23242
|
+
const idx = gs.variables.indexOf(v);
|
|
23243
|
+
if (idx >= 0) gs.variables.splice(idx, 1);
|
|
23244
|
+
gs.set?.delete(name);
|
|
23236
23245
|
}
|
|
23237
|
-
|
|
23238
|
-
if (idx >= 0) gs.variables.splice(idx, 1);
|
|
23239
|
-
gs.set.delete(name);
|
|
23246
|
+
continue;
|
|
23240
23247
|
}
|
|
23241
|
-
|
|
23248
|
+
ensureGlobal(gs, name, mode);
|
|
23242
23249
|
}
|
|
23243
|
-
ensureGlobal(gs, name, mode);
|
|
23244
23250
|
}
|
|
23245
23251
|
resolveThroughReferences(gs);
|
|
23246
23252
|
}
|
|
23253
|
+
function normalizeGlobalAccess(access) {
|
|
23254
|
+
switch(access){
|
|
23255
|
+
case true:
|
|
23256
|
+
case 'true':
|
|
23257
|
+
case 'writable':
|
|
23258
|
+
case 'writeable':
|
|
23259
|
+
return 'writable';
|
|
23260
|
+
case false:
|
|
23261
|
+
case null:
|
|
23262
|
+
case 'false':
|
|
23263
|
+
case 'readonly':
|
|
23264
|
+
case 'readable':
|
|
23265
|
+
return 'readonly';
|
|
23266
|
+
case 'off':
|
|
23267
|
+
return 'off';
|
|
23268
|
+
default:
|
|
23269
|
+
return;
|
|
23270
|
+
}
|
|
23271
|
+
}
|
|
23247
23272
|
function esquery_esm_min_e(e, t) {
|
|
23248
23273
|
(null == t || t > e.length) && (t = e.length);
|
|
23249
23274
|
for(var r = 0, n = Array(t); r < t; r++)n[r] = e[r];
|
|
@@ -26681,7 +26706,6 @@ function unwrapPluginModule(mod) {
|
|
|
26681
26706
|
}
|
|
26682
26707
|
async function importConfigFile(configFilePath) {
|
|
26683
26708
|
const ext = node_path.extname(configFilePath);
|
|
26684
|
-
if ('.js' === ext || '.mjs' === ext || '.cjs' === ext) return import(pathToFileURL(configFilePath).href);
|
|
26685
26709
|
if ('.ts' === ext || '.mts' === ext || '.cts' === ext) {
|
|
26686
26710
|
const useNative = Boolean(process.features.typescript);
|
|
26687
26711
|
if (useNative) return import(pathToFileURL(configFilePath).href);
|
|
@@ -26697,7 +26721,7 @@ async function importConfigFile(configFilePath) {
|
|
|
26697
26721
|
const resolved = await jiti.import(configFilePath);
|
|
26698
26722
|
return resolved;
|
|
26699
26723
|
}
|
|
26700
|
-
|
|
26724
|
+
return import(pathToFileURL(configFilePath).href);
|
|
26701
26725
|
}
|
|
26702
26726
|
const MIN_NODE_MAJOR = 20;
|
|
26703
26727
|
class PluginLoaderError extends Error {
|
|
@@ -26752,25 +26776,35 @@ async function loadPluginsFromConfigs(configs) {
|
|
|
26752
26776
|
for(let i = 0; i < configs.length; i++){
|
|
26753
26777
|
const dir = configs[i].configDirectory;
|
|
26754
26778
|
const existing = out.get(dir);
|
|
26755
|
-
out.set(dir, existing ? mergeLoadedPlugins(existing, loadedList[i], dir) : loadedList[i]);
|
|
26779
|
+
out.set(dir, existing ? mergeLoadedPlugins(existing, loadedList[i], dir, configs[i].configPath) : loadedList[i]);
|
|
26756
26780
|
}
|
|
26757
26781
|
return out;
|
|
26758
26782
|
}
|
|
26759
|
-
function mergeLoadedPlugins(a, b, dir) {
|
|
26783
|
+
function mergeLoadedPlugins(a, b, dir, configPath) {
|
|
26784
|
+
const plugins = [
|
|
26785
|
+
...a.plugins
|
|
26786
|
+
];
|
|
26787
|
+
const pluginsByPrefix = new Map(plugins.map((loaded)=>[
|
|
26788
|
+
loaded.prefix,
|
|
26789
|
+
loaded
|
|
26790
|
+
]));
|
|
26791
|
+
for (const loaded of b.plugins){
|
|
26792
|
+
const existing = pluginsByPrefix.get(loaded.prefix);
|
|
26793
|
+
if (existing) {
|
|
26794
|
+
if (existing.plugin !== loaded.plugin) throw new PluginLoaderError(configPath, `Cannot redefine plugin "${loaded.prefix}" for routing key "${dir}".`);
|
|
26795
|
+
continue;
|
|
26796
|
+
}
|
|
26797
|
+
pluginsByPrefix.set(loaded.prefix, loaded);
|
|
26798
|
+
plugins.push(loaded);
|
|
26799
|
+
}
|
|
26760
26800
|
const rules = new Map(a.rules);
|
|
26761
26801
|
for (const [key, rule] of b.rules){
|
|
26762
26802
|
const existing = rules.get(key);
|
|
26763
|
-
if (void 0 !== existing && existing !== rule) {
|
|
26764
|
-
process.stderr.write(`[rslint] plugin rule "${key}" is defined by more than one config in the same directory (${dir}); keeping the first. Deduplicate the rslint.config.* files for this directory.\n`);
|
|
26765
|
-
continue;
|
|
26766
|
-
}
|
|
26803
|
+
if (void 0 !== existing && existing !== rule) throw new PluginLoaderError(configPath, `[rslint] plugin rule "${key}" is defined by different plugin instances for the same config key (${dir})`);
|
|
26767
26804
|
rules.set(key, rule);
|
|
26768
26805
|
}
|
|
26769
26806
|
return {
|
|
26770
|
-
plugins
|
|
26771
|
-
...a.plugins,
|
|
26772
|
-
...b.plugins
|
|
26773
|
-
],
|
|
26807
|
+
plugins,
|
|
26774
26808
|
rules
|
|
26775
26809
|
};
|
|
26776
26810
|
}
|