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