@santi020k/eslint-config-basic 1.6.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 +133 -1
- package/README.md +4 -22
- package/dist/agent-skill-generator.d.ts +42 -20
- package/dist/agent-skill-generator.js +375 -198
- package/dist/cli.d.ts +22 -0
- package/dist/cli.js +603 -38
- 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 +11 -6
- package/dist/index.js +703 -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,57 +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";
|
|
14
23
|
import {
|
|
15
24
|
AGENT_TARGETS,
|
|
16
25
|
generateAgentSkills,
|
|
17
26
|
generateSkillContent
|
|
18
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";
|
|
19
58
|
import {
|
|
20
59
|
coreConfig as coreConfig2,
|
|
21
60
|
createCoreConfig as createCoreConfig2,
|
|
61
|
+
createImportGroups,
|
|
22
62
|
detectProjectOptions as detectProjectOptions2,
|
|
23
|
-
Extension,
|
|
24
|
-
Format,
|
|
63
|
+
Extension as Extension2,
|
|
64
|
+
Format as Format2,
|
|
25
65
|
getGlobalsForRuntime,
|
|
26
66
|
gitignore as gitignore2,
|
|
67
|
+
groups,
|
|
27
68
|
hasReactConfig,
|
|
28
69
|
jsConfig,
|
|
29
|
-
Library,
|
|
70
|
+
Library as Library2,
|
|
30
71
|
NextMode as NextMode2,
|
|
31
|
-
Preset,
|
|
72
|
+
Preset as Preset2,
|
|
32
73
|
ReactConfigKeys,
|
|
33
74
|
Runtime as Runtime2,
|
|
34
75
|
Setting as Setting2,
|
|
35
|
-
Testing,
|
|
36
|
-
Tool
|
|
76
|
+
Testing as Testing2,
|
|
77
|
+
Tool as Tool2
|
|
37
78
|
} from "@santi020k/eslint-config-core";
|
|
38
|
-
import { tsConfig, typescriptConfig } from "@santi020k/eslint-config-typescript";
|
|
39
79
|
import {
|
|
80
|
+
a11y,
|
|
81
|
+
aiSdk,
|
|
82
|
+
autogen,
|
|
40
83
|
bestPractices,
|
|
84
|
+
biome,
|
|
85
|
+
command,
|
|
86
|
+
compat,
|
|
41
87
|
cspell,
|
|
88
|
+
css,
|
|
42
89
|
cypress,
|
|
90
|
+
deMorgan,
|
|
91
|
+
depend,
|
|
92
|
+
docker,
|
|
93
|
+
drizzle,
|
|
94
|
+
githubActions,
|
|
95
|
+
googleGenAi,
|
|
43
96
|
graphql,
|
|
97
|
+
html,
|
|
44
98
|
i18next,
|
|
45
99
|
jest,
|
|
100
|
+
jestDom,
|
|
46
101
|
jsdoc,
|
|
47
102
|
jsonc,
|
|
103
|
+
langchain,
|
|
104
|
+
llamaIndex,
|
|
48
105
|
markdown,
|
|
106
|
+
mastra,
|
|
107
|
+
mcp,
|
|
49
108
|
mdx,
|
|
109
|
+
mikroOrm,
|
|
110
|
+
node,
|
|
111
|
+
noOnlyTests,
|
|
112
|
+
nx,
|
|
113
|
+
openAiAgents,
|
|
114
|
+
oxlint,
|
|
115
|
+
packageJson,
|
|
50
116
|
perfectionist,
|
|
51
117
|
playwright,
|
|
118
|
+
pnpm,
|
|
52
119
|
prettier,
|
|
120
|
+
prisma,
|
|
53
121
|
regexp,
|
|
54
122
|
security,
|
|
123
|
+
sequelize,
|
|
55
124
|
sonarjs,
|
|
56
125
|
stencil,
|
|
57
126
|
storybook,
|
|
@@ -61,77 +130,379 @@ import {
|
|
|
61
130
|
tanstackRouter,
|
|
62
131
|
testingLibrary,
|
|
63
132
|
toml,
|
|
133
|
+
turbo,
|
|
134
|
+
typeorm,
|
|
64
135
|
unicorn,
|
|
65
136
|
vitest,
|
|
66
|
-
yaml
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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])
|
|
95
264
|
);
|
|
96
265
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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,
|
|
124
487
|
...tsconfigRootDir ? [{
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
parserOptions: {
|
|
128
|
-
tsconfigRootDir
|
|
129
|
-
}
|
|
130
|
-
}
|
|
488
|
+
languageOptions: { parserOptions: { tsconfigRootDir } },
|
|
489
|
+
name: "eslint-config-basic/tsconfig-root-dir"
|
|
131
490
|
}] : [],
|
|
132
|
-
|
|
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
|
+
},
|
|
133
505
|
...runtimeCoreConfig,
|
|
134
|
-
// React config (included if any React-based framework is used/passed)
|
|
135
506
|
...hasReact ? reactParam : [],
|
|
136
507
|
...nextParam,
|
|
137
508
|
...expoParam,
|
|
@@ -143,82 +514,310 @@ const eslintConfig = (options) => {
|
|
|
143
514
|
...angularParam,
|
|
144
515
|
...qwikParam,
|
|
145
516
|
...remixParam,
|
|
146
|
-
...
|
|
147
|
-
|
|
148
|
-
|
|
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
|
+
}) : [],
|
|
149
528
|
...astroParam,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
|
157
541
|
}
|
|
158
542
|
}
|
|
159
|
-
] : [],
|
|
160
|
-
|
|
161
|
-
...getOptionalConfigs(
|
|
162
|
-
uniqueLibraries,
|
|
163
|
-
uniqueTools,
|
|
164
|
-
uniqueTesting,
|
|
165
|
-
uniqueFormats,
|
|
166
|
-
uniqueExtensions
|
|
167
|
-
),
|
|
168
|
-
// Prettier always last
|
|
169
|
-
...getPrettierConfig(uniqueTools)
|
|
543
|
+
}] : [],
|
|
544
|
+
...await getPrettierConfig(uniqueTools)
|
|
170
545
|
];
|
|
171
|
-
return applyStrictMode(configs, strict);
|
|
172
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;
|
|
173
709
|
export {
|
|
174
710
|
AGENT_TARGETS,
|
|
175
|
-
Extension,
|
|
176
|
-
Format,
|
|
177
|
-
Library,
|
|
711
|
+
Extension2 as Extension,
|
|
712
|
+
Format2 as Format,
|
|
713
|
+
Library2 as Library,
|
|
178
714
|
NextMode2 as NextMode,
|
|
179
|
-
Preset,
|
|
715
|
+
Preset2 as Preset,
|
|
180
716
|
ReactConfigKeys,
|
|
181
717
|
Runtime2 as Runtime,
|
|
182
718
|
Setting2 as Setting,
|
|
183
|
-
Testing,
|
|
184
|
-
Tool,
|
|
719
|
+
Testing2 as Testing,
|
|
720
|
+
Tool2 as Tool,
|
|
721
|
+
a11y,
|
|
722
|
+
aiSdk,
|
|
723
|
+
angular,
|
|
724
|
+
angularConfig,
|
|
725
|
+
astro,
|
|
726
|
+
autogen,
|
|
185
727
|
bestPractices,
|
|
728
|
+
biome,
|
|
729
|
+
command,
|
|
730
|
+
compat,
|
|
186
731
|
coreConfig2 as coreConfig,
|
|
187
732
|
createCoreConfig2 as createCoreConfig,
|
|
733
|
+
createImportGroups,
|
|
188
734
|
cspell,
|
|
735
|
+
css,
|
|
189
736
|
cypress,
|
|
737
|
+
deMorgan,
|
|
738
|
+
defineConfig,
|
|
739
|
+
depend,
|
|
190
740
|
detectProjectOptions2 as detectProjectOptions,
|
|
741
|
+
docker,
|
|
742
|
+
drizzle,
|
|
191
743
|
eslintConfig,
|
|
744
|
+
expo,
|
|
745
|
+
expoConfig,
|
|
192
746
|
generateAgentSkills,
|
|
193
747
|
generateSkillContent,
|
|
194
748
|
getGlobalsForRuntime,
|
|
749
|
+
githubActions,
|
|
195
750
|
gitignore2 as gitignore,
|
|
751
|
+
googleGenAi,
|
|
196
752
|
graphql,
|
|
753
|
+
groups,
|
|
197
754
|
hasReactConfig,
|
|
755
|
+
hono,
|
|
756
|
+
html,
|
|
198
757
|
i18next,
|
|
199
758
|
jest,
|
|
759
|
+
jestDom,
|
|
200
760
|
jsConfig,
|
|
201
761
|
jsdoc,
|
|
202
762
|
jsonc,
|
|
763
|
+
langchain,
|
|
764
|
+
lit,
|
|
765
|
+
llamaIndex,
|
|
203
766
|
markdown,
|
|
767
|
+
mastra,
|
|
768
|
+
mcp,
|
|
204
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,
|
|
205
782
|
perfectionist,
|
|
206
783
|
playwright,
|
|
784
|
+
pnpm,
|
|
785
|
+
preact,
|
|
786
|
+
preactConfig,
|
|
207
787
|
prettier,
|
|
788
|
+
prisma,
|
|
789
|
+
qwik,
|
|
790
|
+
react,
|
|
791
|
+
reactConfig,
|
|
792
|
+
reactRouter,
|
|
208
793
|
regexp,
|
|
794
|
+
remix,
|
|
209
795
|
security,
|
|
796
|
+
sequelize,
|
|
797
|
+
slidev,
|
|
798
|
+
solid,
|
|
799
|
+
solidConfig,
|
|
210
800
|
sonarjs,
|
|
211
801
|
stencil,
|
|
212
802
|
storybook,
|
|
803
|
+
svelte,
|
|
804
|
+
svelteConfig,
|
|
213
805
|
swagger,
|
|
214
806
|
tailwind,
|
|
215
807
|
tanstackQuery,
|
|
216
808
|
tanstackRouter,
|
|
809
|
+
tanstackStart,
|
|
217
810
|
testingLibrary,
|
|
218
811
|
toml,
|
|
219
812
|
tsConfig,
|
|
813
|
+
turbo,
|
|
814
|
+
typeorm,
|
|
220
815
|
typescriptConfig,
|
|
221
816
|
unicorn,
|
|
817
|
+
vite,
|
|
222
818
|
vitest,
|
|
223
|
-
|
|
819
|
+
vue,
|
|
820
|
+
vueConfig,
|
|
821
|
+
yaml,
|
|
822
|
+
zod
|
|
224
823
|
};
|