@eslint-react/shared 2.0.0-next.17 → 2.0.0-next.170
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/index.d.ts +196 -1014
- package/dist/index.js +198 -223
- package/package.json +10 -11
package/dist/index.js
CHANGED
|
@@ -1,243 +1,218 @@
|
|
|
1
|
-
import module from
|
|
2
|
-
import path from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
1
|
+
import module from "node:module";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { getOrElseUpdate, identity } from "@eslint-react/eff";
|
|
4
|
+
import { P, match } from "ts-pattern";
|
|
5
|
+
import "@eslint-react/kit";
|
|
6
|
+
import { z } from "zod/v4";
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
//#region src/_id.ts
|
|
9
|
+
let id = 0n;
|
|
10
|
+
/**
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
const getId = () => (id++).toString();
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/_require.ts
|
|
17
|
+
/**
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
const _require = module.createRequire(process.cwd() + path.sep);
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/constants.ts
|
|
24
|
+
/**
|
|
25
|
+
* The NPM scope for this project.
|
|
26
|
+
*/
|
|
27
|
+
const NPM_SCOPE = "@eslint-react";
|
|
28
|
+
/**
|
|
29
|
+
* The GitHub repository for this project.
|
|
30
|
+
*/
|
|
31
|
+
const GITHUB_URL = "https://github.com/Rel1cx/eslint-react";
|
|
32
|
+
/**
|
|
33
|
+
* The URL to the project's website.
|
|
34
|
+
*/
|
|
35
|
+
const WEBSITE_URL = "https://eslint-react.xyz";
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/get-config-adapters.ts
|
|
39
|
+
function getConfigAdapters(pluginName, plugin) {
|
|
40
|
+
function toFlatConfig(config) {
|
|
41
|
+
return {
|
|
42
|
+
...config,
|
|
43
|
+
plugins: { [pluginName]: plugin }
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function toLegacyConfig({ rules }) {
|
|
47
|
+
return {
|
|
48
|
+
plugins: [pluginName],
|
|
49
|
+
rules
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
toFlatConfig,
|
|
54
|
+
toLegacyConfig
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/get-doc-url.ts
|
|
60
|
+
/**
|
|
61
|
+
* Get the URL for the documentation of a rule in a plugin.
|
|
62
|
+
* @internal
|
|
63
|
+
* @param pluginName The name of the plugin.
|
|
64
|
+
* @returns The URL for the documentation of a rule.
|
|
65
|
+
*/
|
|
66
|
+
const getDocsUrl = (pluginName) => (ruleName) => {
|
|
67
|
+
if (pluginName === "x") return `${WEBSITE_URL}/docs/rules/${ruleName}`;
|
|
68
|
+
return `${WEBSITE_URL}/docs/rules/${pluginName}-${ruleName}`;
|
|
24
69
|
};
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/get-react-version.ts
|
|
25
73
|
function getReactVersion(fallback) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
74
|
+
try {
|
|
75
|
+
return match(_require("react")).with({ version: P.select(P.string) }, identity).otherwise(() => fallback);
|
|
76
|
+
} catch {
|
|
77
|
+
return fallback;
|
|
78
|
+
}
|
|
31
79
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
var CustomComponentSchema = z.object({
|
|
60
|
-
/**
|
|
61
|
-
* The name of the user-defined component.
|
|
62
|
-
* @example
|
|
63
|
-
* "Link"
|
|
64
|
-
*/
|
|
65
|
-
name: z.string(),
|
|
66
|
-
/**
|
|
67
|
-
* The name of the host component that the user-defined component represents.
|
|
68
|
-
* @example
|
|
69
|
-
* "a"
|
|
70
|
-
*/
|
|
71
|
-
as: z.optional(z.string()),
|
|
72
|
-
/**
|
|
73
|
-
* Attributes mapping between the user-defined component and the host component.
|
|
74
|
-
* @example
|
|
75
|
-
* `Link` component has a `to` attribute that represents the `href` attribute in the built-in `a` element with a default value of `"/"`.
|
|
76
|
-
*/
|
|
77
|
-
attributes: z.optional(z.array(CustomComponentPropSchema)),
|
|
78
|
-
/**
|
|
79
|
-
* The ESQuery selector to select the component precisely.
|
|
80
|
-
* @internal
|
|
81
|
-
* @example
|
|
82
|
-
* `JSXElement:has(JSXAttribute[name.name='component'][value.value='a'])`
|
|
83
|
-
*/
|
|
84
|
-
selector: z.optional(z.string())
|
|
85
|
-
});
|
|
86
|
-
var CustomHooksSchema = z.object({
|
|
87
|
-
use: z.optional(z.array(z.string())),
|
|
88
|
-
useActionState: z.optional(z.array(z.string())),
|
|
89
|
-
useCallback: z.optional(z.array(z.string())),
|
|
90
|
-
useContext: z.optional(z.array(z.string())),
|
|
91
|
-
useDebugValue: z.optional(z.array(z.string())),
|
|
92
|
-
useDeferredValue: z.optional(z.array(z.string())),
|
|
93
|
-
useEffect: z.optional(z.array(z.string())),
|
|
94
|
-
useFormStatus: z.optional(z.array(z.string())),
|
|
95
|
-
useId: z.optional(z.array(z.string())),
|
|
96
|
-
useImperativeHandle: z.optional(z.array(z.string())),
|
|
97
|
-
useInsertionEffect: z.optional(z.array(z.string())),
|
|
98
|
-
useLayoutEffect: z.optional(z.array(z.string())),
|
|
99
|
-
useMemo: z.optional(z.array(z.string())),
|
|
100
|
-
useOptimistic: z.optional(z.array(z.string())),
|
|
101
|
-
useReducer: z.optional(z.array(z.string())),
|
|
102
|
-
useRef: z.optional(z.array(z.string())),
|
|
103
|
-
useState: z.optional(z.array(z.string())),
|
|
104
|
-
useSyncExternalStore: z.optional(z.array(z.string())),
|
|
105
|
-
useTransition: z.optional(z.array(z.string()))
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/settings.ts
|
|
83
|
+
/**
|
|
84
|
+
* Schema for custom hooks aliases that should be treated as React Hooks
|
|
85
|
+
*/
|
|
86
|
+
const CustomHooksSchema = z.object({
|
|
87
|
+
use: z.optional(z.array(z.string())),
|
|
88
|
+
useActionState: z.optional(z.array(z.string())),
|
|
89
|
+
useCallback: z.optional(z.array(z.string())),
|
|
90
|
+
useContext: z.optional(z.array(z.string())),
|
|
91
|
+
useDebugValue: z.optional(z.array(z.string())),
|
|
92
|
+
useDeferredValue: z.optional(z.array(z.string())),
|
|
93
|
+
useEffect: z.optional(z.array(z.string())),
|
|
94
|
+
useFormStatus: z.optional(z.array(z.string())),
|
|
95
|
+
useId: z.optional(z.array(z.string())),
|
|
96
|
+
useImperativeHandle: z.optional(z.array(z.string())),
|
|
97
|
+
useInsertionEffect: z.optional(z.array(z.string())),
|
|
98
|
+
useLayoutEffect: z.optional(z.array(z.string())),
|
|
99
|
+
useMemo: z.optional(z.array(z.string())),
|
|
100
|
+
useOptimistic: z.optional(z.array(z.string())),
|
|
101
|
+
useReducer: z.optional(z.array(z.string())),
|
|
102
|
+
useRef: z.optional(z.array(z.string())),
|
|
103
|
+
useState: z.optional(z.array(z.string())),
|
|
104
|
+
useSyncExternalStore: z.optional(z.array(z.string())),
|
|
105
|
+
useTransition: z.optional(z.array(z.string()))
|
|
106
106
|
});
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
* @example `"as"`
|
|
119
|
-
*/
|
|
120
|
-
polymorphicPropName: z.optional(z.string()),
|
|
121
|
-
/**
|
|
122
|
-
* @default `true`
|
|
123
|
-
* @internal
|
|
124
|
-
*/
|
|
125
|
-
strict: z.optional(z.boolean()),
|
|
126
|
-
/**
|
|
127
|
-
* Check both the shape and the import to determine if an API is from React.
|
|
128
|
-
* @default `true`
|
|
129
|
-
* @internal
|
|
130
|
-
*/
|
|
131
|
-
skipImportCheck: z.optional(z.boolean()),
|
|
132
|
-
/**
|
|
133
|
-
* React version to use, "detect" means auto detect React version from the project's dependencies.
|
|
134
|
-
* If `importSource` is specified, an equivalent version of React should be provided here.
|
|
135
|
-
* @example `"18.3.1"`
|
|
136
|
-
* @default `"detect"`
|
|
137
|
-
*/
|
|
138
|
-
version: z.optional(z.string()),
|
|
139
|
-
/**
|
|
140
|
-
* A object to define additional hooks that are equivalent to the built-in React Hooks.
|
|
141
|
-
* @description ESLint React will recognize these aliases as equivalent to the built-in hooks in all its rules.
|
|
142
|
-
* @example `{ useEffect: ["useIsomorphicLayoutEffect"] }`
|
|
143
|
-
*/
|
|
144
|
-
additionalHooks: z.optional(CustomHooksSchema),
|
|
145
|
-
/**
|
|
146
|
-
* An array of user-defined components
|
|
147
|
-
* @description This is used to inform the ESLint React plugins how to treat these components during checks.
|
|
148
|
-
* @example `[{ name: "Link", as: "a", attributes: [{ name: "to", as: "href" }, { name: "rel", defaultValue: "noopener noreferrer" }] }]`
|
|
149
|
-
*/
|
|
150
|
-
additionalComponents: z.optional(z.array(CustomComponentSchema))
|
|
107
|
+
/**
|
|
108
|
+
* Schema for ESLint React settings configuration
|
|
109
|
+
* @internal
|
|
110
|
+
*/
|
|
111
|
+
const ESLintReactSettingsSchema = z.object({
|
|
112
|
+
importSource: z.optional(z.string()),
|
|
113
|
+
polymorphicPropName: z.optional(z.string()),
|
|
114
|
+
strict: z.optional(z.boolean()),
|
|
115
|
+
skipImportCheck: z.optional(z.boolean()),
|
|
116
|
+
version: z.optional(z.string()),
|
|
117
|
+
additionalHooks: z.optional(CustomHooksSchema)
|
|
151
118
|
});
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Schema for ESLint settings
|
|
121
|
+
* @internal
|
|
122
|
+
*/
|
|
123
|
+
const ESLintSettingsSchema = z.optional(z.object({ "react-x": z.optional(z.unknown()) }));
|
|
124
|
+
/**
|
|
125
|
+
* Default ESLint React settings
|
|
126
|
+
*/
|
|
127
|
+
const DEFAULT_ESLINT_REACT_SETTINGS = {
|
|
128
|
+
version: "detect",
|
|
129
|
+
importSource: "react",
|
|
130
|
+
strict: true,
|
|
131
|
+
skipImportCheck: true,
|
|
132
|
+
polymorphicPropName: "as",
|
|
133
|
+
additionalHooks: {
|
|
134
|
+
useEffect: ["useIsomorphicLayoutEffect"],
|
|
135
|
+
useLayoutEffect: ["useIsomorphicLayoutEffect"]
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Default ESLint settings with React settings included
|
|
140
|
+
*/
|
|
141
|
+
const DEFAULT_ESLINT_SETTINGS = { "react-x": DEFAULT_ESLINT_REACT_SETTINGS };
|
|
142
|
+
/**
|
|
143
|
+
* Checks if the provided settings conform to ESLintSettings schema
|
|
144
|
+
* @param settings The settings object to validate
|
|
145
|
+
*/
|
|
158
146
|
function isESLintSettings(settings) {
|
|
159
|
-
|
|
147
|
+
return ESLintSettingsSchema.safeParse(settings).success;
|
|
160
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Checks if the provided settings conform to ESLintReactSettings schema
|
|
151
|
+
* @param settings The settings object to validate
|
|
152
|
+
*/
|
|
161
153
|
function isESLintReactSettings(settings) {
|
|
162
|
-
|
|
154
|
+
return ESLintReactSettingsSchema.safeParse(settings).success;
|
|
163
155
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
additionalComponents: [],
|
|
171
|
-
additionalHooks: {
|
|
172
|
-
useEffect: ["useIsomorphicLayoutEffect"],
|
|
173
|
-
useLayoutEffect: ["useIsomorphicLayoutEffect"]
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
var DEFAULT_ESLINT_SETTINGS = {
|
|
177
|
-
"react-x": DEFAULT_ESLINT_REACT_SETTINGS
|
|
178
|
-
};
|
|
179
|
-
var coerceESLintSettings = (settings) => {
|
|
180
|
-
return settings;
|
|
156
|
+
/**
|
|
157
|
+
* Coerces unknown input to ESLintSettings type
|
|
158
|
+
* @param settings The settings object to coerce
|
|
159
|
+
*/
|
|
160
|
+
const coerceESLintSettings = (settings) => {
|
|
161
|
+
return settings;
|
|
181
162
|
};
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Decodes and validates ESLint settings, using defaults if invalid
|
|
165
|
+
* @param settings The settings object to decode
|
|
166
|
+
*/
|
|
167
|
+
const decodeESLintSettings = (settings) => {
|
|
168
|
+
if (isESLintSettings(settings)) return settings;
|
|
169
|
+
return DEFAULT_ESLINT_SETTINGS;
|
|
187
170
|
};
|
|
188
|
-
|
|
189
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Coerces unknown input to ESLintReactSettings type
|
|
173
|
+
* @param settings The settings object to coerce
|
|
174
|
+
*/
|
|
175
|
+
const coerceSettings = (settings) => {
|
|
176
|
+
return settings;
|
|
190
177
|
};
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
178
|
+
/**
|
|
179
|
+
* Decodes and validates ESLint React settings, using defaults if invalid
|
|
180
|
+
* @param settings The settings object to decode
|
|
181
|
+
*/
|
|
182
|
+
const decodeSettings = (settings) => {
|
|
183
|
+
if (isESLintReactSettings(settings)) return settings;
|
|
184
|
+
return DEFAULT_ESLINT_REACT_SETTINGS;
|
|
196
185
|
};
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const re = RegExp.toRegExp(name);
|
|
212
|
-
return {
|
|
213
|
-
...rest2,
|
|
214
|
-
name,
|
|
215
|
-
re,
|
|
216
|
-
as,
|
|
217
|
-
attributes: attributes.map(({ name: name2, as: as2 = name2, ...rest3 }) => ({
|
|
218
|
-
...rest3,
|
|
219
|
-
name: name2,
|
|
220
|
-
as: as2
|
|
221
|
-
}))
|
|
222
|
-
};
|
|
223
|
-
}),
|
|
224
|
-
additionalHooks,
|
|
225
|
-
importSource,
|
|
226
|
-
polymorphicPropName,
|
|
227
|
-
skipImportCheck,
|
|
228
|
-
strict,
|
|
229
|
-
version: match(version).with(P.union(P.nullish, "", "detect"), () => getReactVersion("19.1.0")).otherwise(identity)
|
|
230
|
-
};
|
|
186
|
+
/**
|
|
187
|
+
* Normalizes ESLint React settings to a consistent internal format
|
|
188
|
+
* Transforms component definitions and resolves version information
|
|
189
|
+
*/
|
|
190
|
+
const normalizeSettings = ({ additionalHooks = {}, importSource = "react", polymorphicPropName = "as", skipImportCheck = true, strict = true, version,...rest }) => {
|
|
191
|
+
return {
|
|
192
|
+
...rest,
|
|
193
|
+
additionalHooks,
|
|
194
|
+
importSource,
|
|
195
|
+
polymorphicPropName,
|
|
196
|
+
skipImportCheck,
|
|
197
|
+
strict,
|
|
198
|
+
version: match(version).with(P.union(P.nullish, "", "detect"), () => getReactVersion("19.1.0")).otherwise(identity)
|
|
199
|
+
};
|
|
231
200
|
};
|
|
232
|
-
|
|
201
|
+
const cache = /* @__PURE__ */ new Map();
|
|
202
|
+
/**
|
|
203
|
+
* Retrieves normalized ESLint React settings from the rule context
|
|
204
|
+
* Uses caching for performance optimization
|
|
205
|
+
* @param context The ESLint rule context
|
|
206
|
+
*/
|
|
233
207
|
function getSettingsFromContext(context) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
cache,
|
|
237
|
-
settings["react-x"],
|
|
238
|
-
() => normalizeSettings(decodeSettings(settings["react-x"]))
|
|
239
|
-
);
|
|
208
|
+
const settings = context.settings;
|
|
209
|
+
return getOrElseUpdate(cache, settings["react-x"], () => normalizeSettings(decodeSettings(settings["react-x"])));
|
|
240
210
|
}
|
|
241
|
-
|
|
211
|
+
/**
|
|
212
|
+
* Helper function for defining typed settings for "react-x" in JavaScript files
|
|
213
|
+
* Provides type checking without runtime transformation
|
|
214
|
+
*/
|
|
215
|
+
const defineSettings = identity;
|
|
242
216
|
|
|
243
|
-
|
|
217
|
+
//#endregion
|
|
218
|
+
export { CustomHooksSchema, DEFAULT_ESLINT_REACT_SETTINGS, DEFAULT_ESLINT_SETTINGS, ESLintReactSettingsSchema, ESLintSettingsSchema, GITHUB_URL, NPM_SCOPE, WEBSITE_URL, _require, coerceESLintSettings, coerceSettings, decodeESLintSettings, decodeSettings, defineSettings, getConfigAdapters, getDocsUrl, getId, getReactVersion, getSettingsFromContext, isESLintReactSettings, isESLintSettings, normalizeSettings };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/shared",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.170",
|
|
4
4
|
"description": "ESLint React's Shared constants and functions.",
|
|
5
5
|
"homepage": "https://github.com/Rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -27,25 +27,24 @@
|
|
|
27
27
|
"./package.json"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@typescript-eslint/utils": "^8.
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"@eslint-react/
|
|
34
|
-
"@eslint-react/
|
|
30
|
+
"@typescript-eslint/utils": "^8.42.0",
|
|
31
|
+
"ts-pattern": "^5.8.0",
|
|
32
|
+
"zod": "^4.1.5",
|
|
33
|
+
"@eslint-react/eff": "2.0.0-next.170",
|
|
34
|
+
"@eslint-react/kit": "2.0.0-next.170"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@tsconfig/node22": "^22.0.
|
|
38
|
-
"@types/picomatch": "^4.0.
|
|
39
|
-
"
|
|
37
|
+
"@tsconfig/node22": "^22.0.2",
|
|
38
|
+
"@types/picomatch": "^4.0.2",
|
|
39
|
+
"tsdown": "^0.14.2",
|
|
40
40
|
"type-fest": "^4.41.0",
|
|
41
41
|
"@local/configs": "0.0.0"
|
|
42
42
|
},
|
|
43
43
|
"engines": {
|
|
44
|
-
"bun": ">=1.0.15",
|
|
45
44
|
"node": ">=20.19.0"
|
|
46
45
|
},
|
|
47
46
|
"scripts": {
|
|
48
|
-
"build": "
|
|
47
|
+
"build": "tsdown --dts-resolve",
|
|
49
48
|
"build:docs": "typedoc",
|
|
50
49
|
"lint:publish": "publint",
|
|
51
50
|
"lint:ts": "tsc --noEmit"
|