@santi020k/eslint-config-lite 2.0.0-beta.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/CHANGELOG.md +47 -0
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/compose.d.ts +10 -0
- package/dist/compose.js +30 -0
- package/dist/frameworks.d.ts +58 -0
- package/dist/frameworks.js +105 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +742 -0
- package/dist/integrations.d.ts +12 -0
- package/dist/integrations.js +41 -0
- package/dist/lazy.d.ts +3 -0
- package/dist/lazy.js +9 -0
- package/dist/resolvers.d.ts +15 -0
- package/dist/resolvers.js +96 -0
- package/package.json +167 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,742 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
coreConfig,
|
|
5
|
+
createCoreConfig,
|
|
6
|
+
detectProjectOptions,
|
|
7
|
+
Extension,
|
|
8
|
+
Format,
|
|
9
|
+
gitignore,
|
|
10
|
+
Library,
|
|
11
|
+
NextMode,
|
|
12
|
+
Preset,
|
|
13
|
+
Runtime,
|
|
14
|
+
Setting,
|
|
15
|
+
Testing,
|
|
16
|
+
Tool
|
|
17
|
+
} from "@santi020k/eslint-config-core";
|
|
18
|
+
import { createTypescriptConfig } from "@santi020k/eslint-config-typescript";
|
|
19
|
+
import { applyStrictMode } from "./compose.js";
|
|
20
|
+
import { createDetectedFrameworkFlags } from "./frameworks.js";
|
|
21
|
+
import { getIntegrationConfigs, getPrettierConfig } from "./integrations.js";
|
|
22
|
+
import { resolveFramework, resolvePreset } from "./resolvers.js";
|
|
23
|
+
import {
|
|
24
|
+
angular,
|
|
25
|
+
angularConfig,
|
|
26
|
+
astro,
|
|
27
|
+
expo,
|
|
28
|
+
expoConfig,
|
|
29
|
+
hono,
|
|
30
|
+
lit,
|
|
31
|
+
nest,
|
|
32
|
+
nestConfig,
|
|
33
|
+
next,
|
|
34
|
+
nextConfig,
|
|
35
|
+
nuxt,
|
|
36
|
+
preact,
|
|
37
|
+
preactConfig,
|
|
38
|
+
qwik,
|
|
39
|
+
react,
|
|
40
|
+
reactConfig,
|
|
41
|
+
reactRouter,
|
|
42
|
+
remix,
|
|
43
|
+
slidev,
|
|
44
|
+
solid,
|
|
45
|
+
solidConfig,
|
|
46
|
+
svelte,
|
|
47
|
+
svelteConfig,
|
|
48
|
+
tanstackStart,
|
|
49
|
+
vite,
|
|
50
|
+
vue,
|
|
51
|
+
vueConfig
|
|
52
|
+
} from "./frameworks.js";
|
|
53
|
+
import {
|
|
54
|
+
coreConfig as coreConfig2,
|
|
55
|
+
createCoreConfig as createCoreConfig2,
|
|
56
|
+
createImportGroups,
|
|
57
|
+
detectProjectOptions as detectProjectOptions2,
|
|
58
|
+
Extension as Extension2,
|
|
59
|
+
Format as Format2,
|
|
60
|
+
getGlobalsForRuntime,
|
|
61
|
+
gitignore as gitignore2,
|
|
62
|
+
hasReactConfig,
|
|
63
|
+
jsConfig,
|
|
64
|
+
Library as Library2,
|
|
65
|
+
NextMode as NextMode2,
|
|
66
|
+
Preset as Preset2,
|
|
67
|
+
ReactConfigKeys,
|
|
68
|
+
Runtime as Runtime2,
|
|
69
|
+
Setting as Setting2,
|
|
70
|
+
Testing as Testing2,
|
|
71
|
+
Tool as Tool2
|
|
72
|
+
} from "@santi020k/eslint-config-core";
|
|
73
|
+
import { tsConfig, typescriptConfig } from "@santi020k/eslint-config-typescript";
|
|
74
|
+
const toUniqueArray = (values) => [...new Set(values)];
|
|
75
|
+
const DEFAULT_IGNORES = [
|
|
76
|
+
"**/dist/**",
|
|
77
|
+
"**/build/**",
|
|
78
|
+
"**/coverage/**",
|
|
79
|
+
"**/.turbo/**",
|
|
80
|
+
"**/.next/**",
|
|
81
|
+
"**/.open-next/**",
|
|
82
|
+
"**/.astro/**",
|
|
83
|
+
"**/.svelte-kit/**",
|
|
84
|
+
"**/.vercel/**",
|
|
85
|
+
"**/.wrangler/**",
|
|
86
|
+
"**/playwright-report/**",
|
|
87
|
+
"**/test-results/**",
|
|
88
|
+
"**/node_modules/**",
|
|
89
|
+
"**/tsconfig.tsbuildinfo",
|
|
90
|
+
// Package manager lock files (machine-generated, slow to lint)
|
|
91
|
+
"**/pnpm-lock.yaml",
|
|
92
|
+
"**/yarn.lock",
|
|
93
|
+
"**/package-lock.json",
|
|
94
|
+
"**/bun.lock",
|
|
95
|
+
"**/bun.lockb",
|
|
96
|
+
// AI coding-assistant artifacts (rule/skill folders managed by tools, not source code)
|
|
97
|
+
"**/.agent/**",
|
|
98
|
+
"**/.agents/**",
|
|
99
|
+
"**/.aider*",
|
|
100
|
+
"**/.aider*/**",
|
|
101
|
+
"**/.claude/**",
|
|
102
|
+
"**/.clinerules/**",
|
|
103
|
+
"**/.codex/**",
|
|
104
|
+
"**/.copilot/**",
|
|
105
|
+
"**/.cursor/**",
|
|
106
|
+
"**/.gemini/**",
|
|
107
|
+
"**/.kiro/**",
|
|
108
|
+
"**/.opencode/**",
|
|
109
|
+
"**/.roo/**",
|
|
110
|
+
"**/.windsurf/**"
|
|
111
|
+
];
|
|
112
|
+
const GENERATED_CODE_IGNORES = [
|
|
113
|
+
"**/__generated__/**",
|
|
114
|
+
"**/generated/**",
|
|
115
|
+
"**/codegen/**",
|
|
116
|
+
"**/*.generated.*",
|
|
117
|
+
"**/*.gen.*",
|
|
118
|
+
"**/graphql.ts",
|
|
119
|
+
"**/graphql.tsx",
|
|
120
|
+
"**/gql/**",
|
|
121
|
+
"**/.prisma/**"
|
|
122
|
+
];
|
|
123
|
+
const TAILWIND_ENTRYPOINT_CANDIDATES = [
|
|
124
|
+
"src/styles/global.css",
|
|
125
|
+
"src/app/globals.css",
|
|
126
|
+
"src/globals.css",
|
|
127
|
+
"src/index.css",
|
|
128
|
+
"app/globals.css",
|
|
129
|
+
"styles/global.css"
|
|
130
|
+
];
|
|
131
|
+
const OPTIONAL_BUCKETS = {
|
|
132
|
+
extensions: Object.values(Extension),
|
|
133
|
+
formats: Object.values(Format),
|
|
134
|
+
libraries: Object.values(Library),
|
|
135
|
+
testing: Object.values(Testing),
|
|
136
|
+
tools: Object.values(Tool)
|
|
137
|
+
};
|
|
138
|
+
const mergeArrayOption = (detectedValues, presetValues, explicitValues, strategy) => {
|
|
139
|
+
if (strategy === "replace") {
|
|
140
|
+
if (explicitValues) return toUniqueArray(explicitValues);
|
|
141
|
+
if (presetValues) return toUniqueArray(presetValues);
|
|
142
|
+
return toUniqueArray(detectedValues);
|
|
143
|
+
}
|
|
144
|
+
return toUniqueArray([
|
|
145
|
+
...detectedValues,
|
|
146
|
+
...presetValues ?? [],
|
|
147
|
+
...explicitValues ?? []
|
|
148
|
+
]);
|
|
149
|
+
};
|
|
150
|
+
const isOptionalBucketValue = (bucket, value) => OPTIONAL_BUCKETS[bucket].includes(value);
|
|
151
|
+
const getFeatureEntries = (options, bucket, enabled) => [
|
|
152
|
+
...Object.entries(options?.features ?? {}),
|
|
153
|
+
...Object.entries(options?.integrations ?? {})
|
|
154
|
+
].filter(([name, value]) => value === enabled && isOptionalBucketValue(bucket, name)).map(([name]) => name);
|
|
155
|
+
const applyFeatureDisables = (values, options, bucket) => {
|
|
156
|
+
const disabled = new Set(getFeatureEntries(options, bucket, false));
|
|
157
|
+
return values.filter((value) => !disabled.has(value));
|
|
158
|
+
};
|
|
159
|
+
const mergeOptionalBucket = (bucket, detectedValues, presetValues, explicitValues, options, strategy) => {
|
|
160
|
+
const featureEntries = getFeatureEntries(options, bucket, true);
|
|
161
|
+
const hasExplicitInput = explicitValues !== void 0 || featureEntries.length > 0;
|
|
162
|
+
const mergedExplicit = hasExplicitInput ? [...explicitValues ?? [], ...featureEntries] : void 0;
|
|
163
|
+
return applyFeatureDisables(
|
|
164
|
+
mergeArrayOption(detectedValues, presetValues, mergedExplicit, strategy),
|
|
165
|
+
options,
|
|
166
|
+
bucket
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
const mergeFrameworkOption = (detectedFrameworks, presetFrameworks, explicitFrameworks, strategy) => {
|
|
170
|
+
if (strategy === "replace") {
|
|
171
|
+
if (explicitFrameworks) return { ...explicitFrameworks };
|
|
172
|
+
if (presetFrameworks) return { ...presetFrameworks };
|
|
173
|
+
return { ...detectedFrameworks };
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
...detectedFrameworks,
|
|
177
|
+
...presetFrameworks ?? {},
|
|
178
|
+
...explicitFrameworks ?? {}
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
const resolveDetectionOptions = (detection, defaults = {}) => {
|
|
182
|
+
const defaultControls = {
|
|
183
|
+
extensions: true,
|
|
184
|
+
formats: true,
|
|
185
|
+
frameworks: true,
|
|
186
|
+
libraries: true,
|
|
187
|
+
nextMode: true,
|
|
188
|
+
projects: false,
|
|
189
|
+
runtime: true,
|
|
190
|
+
testing: true,
|
|
191
|
+
tools: true,
|
|
192
|
+
typescript: true,
|
|
193
|
+
...defaults
|
|
194
|
+
};
|
|
195
|
+
if (detection === false) {
|
|
196
|
+
return Object.fromEntries(
|
|
197
|
+
Object.keys(defaultControls).map((key) => [key, false])
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
if (detection === true || detection === void 0) {
|
|
201
|
+
return defaultControls;
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
...defaultControls,
|
|
205
|
+
...detection
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
const applyArrayDetectionControls = (controls, detected) => ({
|
|
209
|
+
detectedFrameworks: controls.frameworks ? detected.detectedFrameworks : [],
|
|
210
|
+
extensions: controls.extensions ? detected.extensions : [],
|
|
211
|
+
formats: controls.formats ? detected.formats : [],
|
|
212
|
+
libraries: controls.libraries ? detected.libraries : [],
|
|
213
|
+
testing: controls.testing ? detected.testing : [],
|
|
214
|
+
tools: controls.tools ? detected.tools : []
|
|
215
|
+
});
|
|
216
|
+
const applyScalarDetectionControls = (controls, detected) => ({
|
|
217
|
+
nextMode: controls.nextMode ? detected.nextMode : void 0,
|
|
218
|
+
preset: controls.typescript && controls.runtime ? detected.preset : void 0,
|
|
219
|
+
projects: controls.projects ? detected.projects : void 0,
|
|
220
|
+
runtime: controls.runtime ? detected.runtime : void 0,
|
|
221
|
+
typescript: controls.typescript ? detected.typescript : false
|
|
222
|
+
});
|
|
223
|
+
const applyDetectionControls = (detected, detection, defaults) => {
|
|
224
|
+
const controls = resolveDetectionOptions(detection, defaults);
|
|
225
|
+
return {
|
|
226
|
+
...detected,
|
|
227
|
+
...applyArrayDetectionControls(controls, detected),
|
|
228
|
+
...applyScalarDetectionControls(controls, detected)
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
const getStrictMode = (explicitStrict, presetStrict) => explicitStrict ?? presetStrict ?? false;
|
|
232
|
+
const applyStrictProfileDefaults = (extensions, strict) => {
|
|
233
|
+
if (strict !== "pedantic") return extensions;
|
|
234
|
+
return toUniqueArray([...extensions, Extension.BestPractices]);
|
|
235
|
+
};
|
|
236
|
+
const hasTsconfig = (rootDir) => [
|
|
237
|
+
"tsconfig.eslint.json",
|
|
238
|
+
"tsconfig.json",
|
|
239
|
+
"tsconfig.base.json",
|
|
240
|
+
"tsconfig.app.json",
|
|
241
|
+
"tsconfig.node.json"
|
|
242
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- config root is user-selected project context
|
|
243
|
+
].some((fileName) => existsSync(join(rootDir, fileName)));
|
|
244
|
+
const resolveTypescriptOptions = (typescript) => {
|
|
245
|
+
if (!typescript || typescript === "off") return false;
|
|
246
|
+
if (typescript === true) return { mode: "type-aware" };
|
|
247
|
+
if (typeof typescript === "string") return { mode: typescript };
|
|
248
|
+
if (typescript.mode === "off") return false;
|
|
249
|
+
return {
|
|
250
|
+
...typescript,
|
|
251
|
+
mode: typescript.mode ?? "type-aware"
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
const resolveTsconfigRootDir = (rootDir, typescript, explicitRootDir) => {
|
|
255
|
+
if (explicitRootDir) return explicitRootDir;
|
|
256
|
+
return resolveTypescriptOptions(typescript) && hasTsconfig(rootDir) ? rootDir : void 0;
|
|
257
|
+
};
|
|
258
|
+
const findTailwindEntryPoint = (rootDir) => TAILWIND_ENTRYPOINT_CANDIDATES.find(
|
|
259
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- probes known stylesheet candidates under project root
|
|
260
|
+
(candidate) => existsSync(join(rootDir, candidate))
|
|
261
|
+
);
|
|
262
|
+
const scopeFilePattern = (projectPath, pattern) => {
|
|
263
|
+
if (typeof pattern === "string") {
|
|
264
|
+
const isNegated = pattern.startsWith("!");
|
|
265
|
+
const basePattern = (isNegated ? pattern.slice(1) : pattern).replace(/^\.\//, "");
|
|
266
|
+
const scoped = `${projectPath.replace(/\/$/, "")}/${basePattern}`;
|
|
267
|
+
return isNegated ? `!${scoped}` : scoped;
|
|
268
|
+
}
|
|
269
|
+
if (Array.isArray(pattern)) {
|
|
270
|
+
return pattern.map((item) => scopeFilePattern(projectPath, item));
|
|
271
|
+
}
|
|
272
|
+
return pattern;
|
|
273
|
+
};
|
|
274
|
+
const scopeConfigToProject = (config, projectPath) => {
|
|
275
|
+
if ("ignores" in config && !config.files) {
|
|
276
|
+
return {
|
|
277
|
+
...config,
|
|
278
|
+
ignores: config.ignores?.map((pattern) => scopeFilePattern(projectPath, pattern))
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
return {
|
|
282
|
+
...config,
|
|
283
|
+
files: Array.isArray(config.files) ? config.files.map((pattern) => scopeFilePattern(projectPath, pattern)) : [`${projectPath.replace(/\/$/, "")}/**/*`]
|
|
284
|
+
};
|
|
285
|
+
};
|
|
286
|
+
const patchImportGroupsConfig = (config, workspacePatterns) => {
|
|
287
|
+
const rule = config.rules?.["simple-import-sort/imports"];
|
|
288
|
+
if (!Array.isArray(rule) || !rule[1]) return config;
|
|
289
|
+
const ruleOpts = rule[1];
|
|
290
|
+
const existingGroups = ruleOpts.groups ?? [];
|
|
291
|
+
if (existingGroups.length === 0) return config;
|
|
292
|
+
const externalIdx = existingGroups.findIndex((g) => g.some((p) => p.includes("^@?\\w")));
|
|
293
|
+
const insertAt = externalIdx >= 0 ? externalIdx : existingGroups.length;
|
|
294
|
+
return {
|
|
295
|
+
...config,
|
|
296
|
+
rules: {
|
|
297
|
+
...config.rules,
|
|
298
|
+
"simple-import-sort/imports": [
|
|
299
|
+
rule[0],
|
|
300
|
+
{ ...ruleOpts, groups: [...existingGroups.slice(0, insertAt), workspacePatterns, ...existingGroups.slice(insertAt)] }
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
};
|
|
305
|
+
const patchImportGroups = (allConfigs, workspacePrefixes) => {
|
|
306
|
+
const workspacePatterns = workspacePrefixes.map(
|
|
307
|
+
(p) => `^${p.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&")}(/.*|$)`
|
|
308
|
+
);
|
|
309
|
+
return allConfigs.map(
|
|
310
|
+
(item) => Array.isArray(item) ? item : patchImportGroupsConfig(item, workspacePatterns)
|
|
311
|
+
);
|
|
312
|
+
};
|
|
313
|
+
const resolveLiteSetup = (options) => ({
|
|
314
|
+
autoFrameworks: options?.autoFrameworks ?? true,
|
|
315
|
+
detectRootDir: options?.detectRootDir ?? options?.tsconfigRootDir,
|
|
316
|
+
optionMergeStrategy: options?.optionMergeStrategy ?? "merge",
|
|
317
|
+
requestedPreset: options?.preset
|
|
318
|
+
});
|
|
319
|
+
const resolveLitePresetMeta = (requestedPreset, detected, autoFrameworks, optProjects) => {
|
|
320
|
+
const preset = requestedPreset ?? detected.preset;
|
|
321
|
+
const presetDefaults = preset ? resolvePreset(preset) : {};
|
|
322
|
+
const frameworkDefaults = autoFrameworks ? createDetectedFrameworkFlags(detected.detectedFrameworks ?? []) : {};
|
|
323
|
+
const configuredProjects = { ...detected.projects ?? {}, ...optProjects ?? {} };
|
|
324
|
+
return { configuredProjects, frameworkDefaults, preset, presetDefaults };
|
|
325
|
+
};
|
|
326
|
+
const resolveLiteBucketDefaults = (detected) => ({
|
|
327
|
+
detectedExtensions: detected.extensions ?? [],
|
|
328
|
+
detectedFormats: detected.formats ?? [],
|
|
329
|
+
detectedLibraries: detected.libraries ?? [],
|
|
330
|
+
detectedTesting: detected.testing ?? [],
|
|
331
|
+
detectedTools: detected.tools ?? []
|
|
332
|
+
});
|
|
333
|
+
const resolveLiteNextMode = (optNextMode, presetNextMode, detectedNextMode) => optNextMode ?? presetNextMode ?? detectedNextMode ?? NextMode.Pages;
|
|
334
|
+
const resolveLiteRuntime = (optRuntime, presetRuntime, detectedRuntime) => optRuntime ?? presetRuntime ?? detectedRuntime ?? Runtime.Universal;
|
|
335
|
+
const resolveLiteTypescript = (optTypescript, presetTypescript, detectedTypescript) => optTypescript ?? presetTypescript ?? detectedTypescript ?? false;
|
|
336
|
+
const resolveLiteScalars = (opts, presetDefaults, detected) => ({
|
|
337
|
+
nextMode: resolveLiteNextMode(opts.nextMode, presetDefaults.nextMode, detected.nextMode),
|
|
338
|
+
runtime: resolveLiteRuntime(opts.runtime, presetDefaults.runtime, detected.runtime),
|
|
339
|
+
settings: opts.settings ?? detected.settings ?? [],
|
|
340
|
+
strict: getStrictMode(opts.strict, presetDefaults.strict),
|
|
341
|
+
typescript: resolveLiteTypescript(opts.typescript, presetDefaults.typescript, detected.typescript)
|
|
342
|
+
});
|
|
343
|
+
const hasReactImplyingFramework = (result) => Boolean(
|
|
344
|
+
result.next ?? result.expo ?? result.remix ?? result["react-router"] ?? (result["tanstack-start"] && !result.solid)
|
|
345
|
+
);
|
|
346
|
+
const applyLiteFrameworkImpliedDeps = (frameworks) => {
|
|
347
|
+
const result = { ...frameworks };
|
|
348
|
+
if (hasReactImplyingFramework(result) && !result.react) result.react = true;
|
|
349
|
+
if (result.slidev && !result.vue) result.vue = true;
|
|
350
|
+
if (result.nuxt && !result.vue) result.vue = true;
|
|
351
|
+
return result;
|
|
352
|
+
};
|
|
353
|
+
const buildLiteIgnoresConfig = (useDefaultIgnores, useGeneratedCodeIgnores, useGitignore, optIgnores) => ({
|
|
354
|
+
defaultIgnores: useDefaultIgnores ? [{
|
|
355
|
+
ignores: [...DEFAULT_IGNORES, ...useGeneratedCodeIgnores ? GENERATED_CODE_IGNORES : []],
|
|
356
|
+
name: "eslint-config-lite/default-ignores"
|
|
357
|
+
}] : [],
|
|
358
|
+
gitignoreConfig: useGitignore ? gitignore : [],
|
|
359
|
+
userIgnores: optIgnores?.length ? [{
|
|
360
|
+
ignores: optIgnores,
|
|
361
|
+
name: "eslint-config-lite/ignores"
|
|
362
|
+
}] : []
|
|
363
|
+
});
|
|
364
|
+
const logLiteDebug = (autoFrameworks, detectRootDir, nextMode, optionMergeStrategy, preset, resolvedFrameworks, resolvedTypescript, runtime, tsconfigRootDir, uniqueExtensions, uniqueFormats, uniqueLibraries, uniqueTesting, uniqueTools) => {
|
|
365
|
+
if (!process.env.ESLINT_CONFIG_LITE_DEBUG && !process.env.ESLINT_BASIC_DEBUG) return;
|
|
366
|
+
process.stdout.write(`[ESLint Config Lite] Resolved options: ${JSON.stringify({
|
|
367
|
+
autoFrameworks,
|
|
368
|
+
detectRootDir: detectRootDir ?? process.cwd(),
|
|
369
|
+
extensions: uniqueExtensions,
|
|
370
|
+
formats: uniqueFormats,
|
|
371
|
+
frameworks: Object.entries(resolvedFrameworks).filter(([, value]) => Boolean(value)).map(([key]) => key),
|
|
372
|
+
libraries: uniqueLibraries,
|
|
373
|
+
nextMode,
|
|
374
|
+
optionMergeStrategy,
|
|
375
|
+
preset,
|
|
376
|
+
runtime,
|
|
377
|
+
testing: uniqueTesting,
|
|
378
|
+
tools: uniqueTools,
|
|
379
|
+
tsconfigRootDir,
|
|
380
|
+
typescript: resolvedTypescript ? resolvedTypescript.mode : false
|
|
381
|
+
}, null, 2)}
|
|
382
|
+
`);
|
|
383
|
+
};
|
|
384
|
+
const buildLiteEslintConfigs = async (params) => {
|
|
385
|
+
const {
|
|
386
|
+
angularParam,
|
|
387
|
+
astroOptions,
|
|
388
|
+
astroParam,
|
|
389
|
+
defaultIgnores,
|
|
390
|
+
expoParam,
|
|
391
|
+
gitignoreConfig,
|
|
392
|
+
honoParam,
|
|
393
|
+
litParam,
|
|
394
|
+
nestParam,
|
|
395
|
+
nextMode,
|
|
396
|
+
nextParam,
|
|
397
|
+
nuxtParam,
|
|
398
|
+
preactParam,
|
|
399
|
+
qwikParam,
|
|
400
|
+
reactParam,
|
|
401
|
+
reactRouterParam,
|
|
402
|
+
remixParam,
|
|
403
|
+
resolvedFrameworks,
|
|
404
|
+
resolvedTypescript,
|
|
405
|
+
runtimeCoreConfig,
|
|
406
|
+
slidevParam,
|
|
407
|
+
solidParam,
|
|
408
|
+
svelteParam,
|
|
409
|
+
tailwindEntryPoint,
|
|
410
|
+
tanstackStartParam,
|
|
411
|
+
tsconfigRootDir,
|
|
412
|
+
uniqueExtensions,
|
|
413
|
+
uniqueFormats,
|
|
414
|
+
uniqueLibraries,
|
|
415
|
+
uniqueTesting,
|
|
416
|
+
uniqueTools,
|
|
417
|
+
userIgnores,
|
|
418
|
+
viteParam,
|
|
419
|
+
vueParam
|
|
420
|
+
} = params;
|
|
421
|
+
const { hasReact } = astroOptions;
|
|
422
|
+
return [
|
|
423
|
+
...defaultIgnores,
|
|
424
|
+
...userIgnores,
|
|
425
|
+
// Settings
|
|
426
|
+
...gitignoreConfig,
|
|
427
|
+
// Global TSConfig Root Dir fix
|
|
428
|
+
...tsconfigRootDir ? [{
|
|
429
|
+
languageOptions: {
|
|
430
|
+
parserOptions: {
|
|
431
|
+
tsconfigRootDir
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
name: "eslint-config-lite/tsconfig-root-dir"
|
|
435
|
+
}] : [],
|
|
436
|
+
{
|
|
437
|
+
files: ["**/*.cjs", "**/*.cts"],
|
|
438
|
+
languageOptions: {
|
|
439
|
+
globals: {
|
|
440
|
+
__dirname: "readonly",
|
|
441
|
+
__filename: "readonly",
|
|
442
|
+
exports: "readonly",
|
|
443
|
+
module: "readonly",
|
|
444
|
+
require: "readonly"
|
|
445
|
+
},
|
|
446
|
+
sourceType: "commonjs"
|
|
447
|
+
},
|
|
448
|
+
name: "eslint-config-lite/commonjs"
|
|
449
|
+
},
|
|
450
|
+
// Core JS config with runtime-aware globals
|
|
451
|
+
...runtimeCoreConfig,
|
|
452
|
+
// React config (included if any React-based framework is used/passed)
|
|
453
|
+
...hasReact ? reactParam : [],
|
|
454
|
+
...nextParam,
|
|
455
|
+
...expoParam,
|
|
456
|
+
...nestParam,
|
|
457
|
+
...honoParam,
|
|
458
|
+
...vueParam,
|
|
459
|
+
...svelteParam,
|
|
460
|
+
...solidParam,
|
|
461
|
+
...angularParam,
|
|
462
|
+
...qwikParam,
|
|
463
|
+
...remixParam,
|
|
464
|
+
...reactRouterParam,
|
|
465
|
+
...tanstackStartParam,
|
|
466
|
+
...nuxtParam,
|
|
467
|
+
...preactParam,
|
|
468
|
+
...litParam,
|
|
469
|
+
...slidevParam,
|
|
470
|
+
...viteParam,
|
|
471
|
+
...resolvedTypescript ? createTypescriptConfig({
|
|
472
|
+
...resolvedTypescript,
|
|
473
|
+
tsconfigRootDir: resolvedTypescript.tsconfigRootDir ?? tsconfigRootDir
|
|
474
|
+
}) : [],
|
|
475
|
+
// Astro needs to run after generic TypeScript so its parser and false-positive
|
|
476
|
+
// workarounds win for .astro files and embedded expressions.
|
|
477
|
+
...astroParam,
|
|
478
|
+
// Next.js App Router overrides (#12)
|
|
479
|
+
...resolvedFrameworks.next && nextMode === NextMode.AppRouter ? [
|
|
480
|
+
{
|
|
481
|
+
files: ["app/**/*.{ts,tsx}", "src/**/*.{ts,tsx}"],
|
|
482
|
+
name: "eslint-config-next/app-router-overrides",
|
|
483
|
+
rules: {
|
|
484
|
+
"@next/next/no-html-link-for-pages": "off"
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
] : [],
|
|
488
|
+
// Integrations
|
|
489
|
+
...await getIntegrationConfigs(
|
|
490
|
+
uniqueLibraries,
|
|
491
|
+
uniqueTools,
|
|
492
|
+
uniqueTesting,
|
|
493
|
+
uniqueFormats,
|
|
494
|
+
uniqueExtensions
|
|
495
|
+
),
|
|
496
|
+
...tailwindEntryPoint ? [{
|
|
497
|
+
name: "eslint-config-lite/tailwind-settings",
|
|
498
|
+
settings: {
|
|
499
|
+
"better-tailwindcss": {
|
|
500
|
+
detectComponentClasses: true,
|
|
501
|
+
entryPoint: tailwindEntryPoint
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}] : [],
|
|
505
|
+
// Prettier always last
|
|
506
|
+
...await getPrettierConfig(uniqueTools)
|
|
507
|
+
];
|
|
508
|
+
};
|
|
509
|
+
const eslintConfig = async (options) => {
|
|
510
|
+
const {
|
|
511
|
+
detection,
|
|
512
|
+
extensions: optExtensions,
|
|
513
|
+
formats: optFormats,
|
|
514
|
+
frameworks: optFrameworks,
|
|
515
|
+
ignores: optIgnores,
|
|
516
|
+
libraries: optLibraries,
|
|
517
|
+
nextMode: optNextMode,
|
|
518
|
+
projects: optProjects,
|
|
519
|
+
runtime: optRuntime,
|
|
520
|
+
settings: optSettings,
|
|
521
|
+
strict: optStrict,
|
|
522
|
+
testing: optTesting,
|
|
523
|
+
tools: optTools,
|
|
524
|
+
tsconfigRootDir: optTsconfigRootDir,
|
|
525
|
+
typescript: optTypescript,
|
|
526
|
+
workspacePrefixes
|
|
527
|
+
} = options ?? {};
|
|
528
|
+
const { autoFrameworks, detectRootDir, optionMergeStrategy, requestedPreset } = resolveLiteSetup(options);
|
|
529
|
+
const shouldDefaultProjectDetection = requestedPreset === Preset.Monorepo;
|
|
530
|
+
const detected = applyDetectionControls(
|
|
531
|
+
detectProjectOptions(detectRootDir),
|
|
532
|
+
detection,
|
|
533
|
+
{ projects: shouldDefaultProjectDetection }
|
|
534
|
+
);
|
|
535
|
+
const { configuredProjects, frameworkDefaults, preset, presetDefaults } = resolveLitePresetMeta(
|
|
536
|
+
requestedPreset,
|
|
537
|
+
detected,
|
|
538
|
+
autoFrameworks,
|
|
539
|
+
optProjects
|
|
540
|
+
);
|
|
541
|
+
const { detectedExtensions, detectedFormats, detectedLibraries, detectedTesting, detectedTools } = resolveLiteBucketDefaults(detected);
|
|
542
|
+
const { nextMode, runtime, settings, strict, typescript } = resolveLiteScalars(
|
|
543
|
+
{ nextMode: optNextMode, runtime: optRuntime, settings: optSettings, strict: optStrict, typescript: optTypescript },
|
|
544
|
+
presetDefaults,
|
|
545
|
+
detected
|
|
546
|
+
);
|
|
547
|
+
const configuredExtensions = mergeOptionalBucket("extensions", detectedExtensions, presetDefaults.extensions, optExtensions, options, optionMergeStrategy);
|
|
548
|
+
const formats = mergeOptionalBucket("formats", detectedFormats, presetDefaults.formats, optFormats, options, optionMergeStrategy);
|
|
549
|
+
const frameworks = mergeFrameworkOption(frameworkDefaults, presetDefaults.frameworks, optFrameworks, optionMergeStrategy);
|
|
550
|
+
const libraries = mergeOptionalBucket("libraries", detectedLibraries, presetDefaults.libraries, optLibraries, options, optionMergeStrategy);
|
|
551
|
+
const testing = mergeOptionalBucket("testing", detectedTesting, presetDefaults.testing, optTesting, options, optionMergeStrategy);
|
|
552
|
+
const tools = mergeOptionalBucket("tools", detectedTools, presetDefaults.tools, optTools, options, optionMergeStrategy);
|
|
553
|
+
const resolvedTypescript = resolveTypescriptOptions(typescript);
|
|
554
|
+
const rootDir = detectRootDir ?? process.cwd();
|
|
555
|
+
const tsconfigRootDir = resolveTsconfigRootDir(rootDir, typescript, optTsconfigRootDir);
|
|
556
|
+
const extensions = applyStrictProfileDefaults(configuredExtensions, strict);
|
|
557
|
+
const resolvedFrameworks = applyLiteFrameworkImpliedDeps({ ...frameworks });
|
|
558
|
+
const uniqueLibraries = [...new Set(libraries)];
|
|
559
|
+
const uniqueTesting = [...new Set(testing)];
|
|
560
|
+
const uniqueFormats = [...new Set(formats)];
|
|
561
|
+
const uniqueTools = [...new Set(tools)];
|
|
562
|
+
const uniqueExtensions = [...new Set(extensions)];
|
|
563
|
+
const uniqueSettings = [...new Set(settings)];
|
|
564
|
+
const hasReact = !!resolvedFrameworks.react;
|
|
565
|
+
const hasVue = !!resolvedFrameworks.vue;
|
|
566
|
+
const hasSvelte = !!resolvedFrameworks.svelte;
|
|
567
|
+
const hasSolid = !!resolvedFrameworks.solid;
|
|
568
|
+
const useGitignore = !uniqueSettings.includes(Setting.NoGitignore);
|
|
569
|
+
const useDefaultIgnores = !uniqueSettings.includes(Setting.NoDefaultIgnores);
|
|
570
|
+
const useGeneratedCodeIgnores = !uniqueSettings.includes(Setting.NoGeneratedCodeIgnores);
|
|
571
|
+
const tailwindEntryPoint = uniqueLibraries.includes(Library.Tailwind) ? findTailwindEntryPoint(rootDir) : void 0;
|
|
572
|
+
const runtimeCoreConfig = runtime === Runtime.Universal ? coreConfig : createCoreConfig(runtime);
|
|
573
|
+
const { defaultIgnores, gitignoreConfig, userIgnores } = buildLiteIgnoresConfig(
|
|
574
|
+
useDefaultIgnores,
|
|
575
|
+
useGeneratedCodeIgnores,
|
|
576
|
+
useGitignore,
|
|
577
|
+
optIgnores
|
|
578
|
+
);
|
|
579
|
+
const [
|
|
580
|
+
reactParam,
|
|
581
|
+
nextParam,
|
|
582
|
+
astroParam,
|
|
583
|
+
expoParam,
|
|
584
|
+
nestParam,
|
|
585
|
+
honoParam,
|
|
586
|
+
vueParam,
|
|
587
|
+
svelteParam,
|
|
588
|
+
solidParam,
|
|
589
|
+
angularParam,
|
|
590
|
+
qwikParam,
|
|
591
|
+
remixParam,
|
|
592
|
+
reactRouterParam,
|
|
593
|
+
tanstackStartParam,
|
|
594
|
+
nuxtParam,
|
|
595
|
+
preactParam,
|
|
596
|
+
litParam,
|
|
597
|
+
slidevParam,
|
|
598
|
+
viteParam
|
|
599
|
+
] = await Promise.all([
|
|
600
|
+
resolveFramework("react", resolvedFrameworks.react),
|
|
601
|
+
resolveFramework("next", resolvedFrameworks.next),
|
|
602
|
+
resolveFramework("astro", resolvedFrameworks.astro, { hasReact, hasSolid, hasSvelte, hasVue }),
|
|
603
|
+
resolveFramework("expo", resolvedFrameworks.expo),
|
|
604
|
+
resolveFramework("nest", resolvedFrameworks.nest),
|
|
605
|
+
resolveFramework("hono", resolvedFrameworks.hono, { runtime }),
|
|
606
|
+
resolveFramework("vue", resolvedFrameworks.vue),
|
|
607
|
+
resolveFramework("svelte", resolvedFrameworks.svelte),
|
|
608
|
+
resolveFramework("solid", resolvedFrameworks.solid),
|
|
609
|
+
resolveFramework("angular", resolvedFrameworks.angular),
|
|
610
|
+
resolveFramework("qwik", resolvedFrameworks.qwik),
|
|
611
|
+
resolveFramework("remix", resolvedFrameworks.remix),
|
|
612
|
+
resolveFramework("react-router", resolvedFrameworks["react-router"]),
|
|
613
|
+
resolveFramework("tanstack-start", resolvedFrameworks["tanstack-start"]),
|
|
614
|
+
resolveFramework("nuxt", resolvedFrameworks.nuxt),
|
|
615
|
+
resolveFramework("preact", resolvedFrameworks.preact),
|
|
616
|
+
resolveFramework("lit", resolvedFrameworks.lit),
|
|
617
|
+
resolveFramework("slidev", resolvedFrameworks.slidev, { runtime }),
|
|
618
|
+
resolveFramework("vite", resolvedFrameworks.vite, { runtime })
|
|
619
|
+
]);
|
|
620
|
+
const configs = await buildLiteEslintConfigs({
|
|
621
|
+
angularParam,
|
|
622
|
+
astroOptions: { hasReact, hasSolid, hasSvelte, hasVue },
|
|
623
|
+
astroParam,
|
|
624
|
+
defaultIgnores,
|
|
625
|
+
expoParam,
|
|
626
|
+
gitignoreConfig,
|
|
627
|
+
honoParam,
|
|
628
|
+
litParam,
|
|
629
|
+
nestParam,
|
|
630
|
+
nextMode,
|
|
631
|
+
nextParam,
|
|
632
|
+
nuxtParam,
|
|
633
|
+
preactParam,
|
|
634
|
+
qwikParam,
|
|
635
|
+
reactParam,
|
|
636
|
+
reactRouterParam,
|
|
637
|
+
remixParam,
|
|
638
|
+
resolvedFrameworks,
|
|
639
|
+
resolvedTypescript,
|
|
640
|
+
rootDir,
|
|
641
|
+
runtime,
|
|
642
|
+
runtimeCoreConfig,
|
|
643
|
+
slidevParam,
|
|
644
|
+
solidParam,
|
|
645
|
+
svelteParam,
|
|
646
|
+
tailwindEntryPoint,
|
|
647
|
+
tanstackStartParam,
|
|
648
|
+
tsconfigRootDir,
|
|
649
|
+
uniqueExtensions,
|
|
650
|
+
uniqueFormats,
|
|
651
|
+
uniqueLibraries,
|
|
652
|
+
uniqueTesting,
|
|
653
|
+
uniqueTools,
|
|
654
|
+
userIgnores,
|
|
655
|
+
viteParam,
|
|
656
|
+
vueParam
|
|
657
|
+
});
|
|
658
|
+
logLiteDebug(
|
|
659
|
+
autoFrameworks,
|
|
660
|
+
detectRootDir,
|
|
661
|
+
nextMode,
|
|
662
|
+
optionMergeStrategy,
|
|
663
|
+
preset,
|
|
664
|
+
resolvedFrameworks,
|
|
665
|
+
resolvedTypescript,
|
|
666
|
+
runtime,
|
|
667
|
+
tsconfigRootDir,
|
|
668
|
+
uniqueExtensions,
|
|
669
|
+
uniqueFormats,
|
|
670
|
+
uniqueLibraries,
|
|
671
|
+
uniqueTesting,
|
|
672
|
+
uniqueTools
|
|
673
|
+
);
|
|
674
|
+
const projectConfigs = await Promise.all(
|
|
675
|
+
Object.entries(configuredProjects).map(async ([projectPath, projectOptions]) => {
|
|
676
|
+
const projectRoot = join(detectRootDir ?? process.cwd(), projectPath);
|
|
677
|
+
const scopedConfigs = await eslintConfig({
|
|
678
|
+
...projectOptions,
|
|
679
|
+
detectRootDir: projectOptions.detectRootDir ?? projectRoot,
|
|
680
|
+
projects: void 0,
|
|
681
|
+
tsconfigRootDir: projectOptions.tsconfigRootDir ?? projectRoot
|
|
682
|
+
});
|
|
683
|
+
return scopedConfigs.map((config) => scopeConfigToProject(config, projectPath));
|
|
684
|
+
})
|
|
685
|
+
);
|
|
686
|
+
const allConfigs = [...configs, ...projectConfigs.flat()];
|
|
687
|
+
const patchedConfigs = workspacePrefixes?.length ? patchImportGroups(allConfigs, workspacePrefixes) : allConfigs;
|
|
688
|
+
return applyStrictMode(patchedConfigs, strict);
|
|
689
|
+
};
|
|
690
|
+
const defineConfig = eslintConfig;
|
|
691
|
+
export {
|
|
692
|
+
Extension2 as Extension,
|
|
693
|
+
Format2 as Format,
|
|
694
|
+
Library2 as Library,
|
|
695
|
+
NextMode2 as NextMode,
|
|
696
|
+
Preset2 as Preset,
|
|
697
|
+
ReactConfigKeys,
|
|
698
|
+
Runtime2 as Runtime,
|
|
699
|
+
Setting2 as Setting,
|
|
700
|
+
Testing2 as Testing,
|
|
701
|
+
Tool2 as Tool,
|
|
702
|
+
angular,
|
|
703
|
+
angularConfig,
|
|
704
|
+
astro,
|
|
705
|
+
coreConfig2 as coreConfig,
|
|
706
|
+
createCoreConfig2 as createCoreConfig,
|
|
707
|
+
createImportGroups,
|
|
708
|
+
defineConfig,
|
|
709
|
+
detectProjectOptions2 as detectProjectOptions,
|
|
710
|
+
eslintConfig,
|
|
711
|
+
expo,
|
|
712
|
+
expoConfig,
|
|
713
|
+
getGlobalsForRuntime,
|
|
714
|
+
gitignore2 as gitignore,
|
|
715
|
+
hasReactConfig,
|
|
716
|
+
hono,
|
|
717
|
+
jsConfig,
|
|
718
|
+
lit,
|
|
719
|
+
nest,
|
|
720
|
+
nestConfig,
|
|
721
|
+
next,
|
|
722
|
+
nextConfig,
|
|
723
|
+
nuxt,
|
|
724
|
+
preact,
|
|
725
|
+
preactConfig,
|
|
726
|
+
qwik,
|
|
727
|
+
react,
|
|
728
|
+
reactConfig,
|
|
729
|
+
reactRouter,
|
|
730
|
+
remix,
|
|
731
|
+
slidev,
|
|
732
|
+
solid,
|
|
733
|
+
solidConfig,
|
|
734
|
+
svelte,
|
|
735
|
+
svelteConfig,
|
|
736
|
+
tanstackStart,
|
|
737
|
+
tsConfig,
|
|
738
|
+
typescriptConfig,
|
|
739
|
+
vite,
|
|
740
|
+
vue,
|
|
741
|
+
vueConfig
|
|
742
|
+
};
|