@santi020k/eslint-config-basic 2.1.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,12 @@
1
- import { join } from "node:path";
1
+ import { dirname, join } from "node:path";
2
+ import { fileURLToPath } from "node:url";
2
3
  import {
3
4
  applyDetectionControls,
4
5
  applyStrictMode,
5
6
  applyStrictProfileDefaults,
6
7
  coreConfig,
7
8
  createCoreConfig,
9
+ createGitignoreConfig,
8
10
  DEFAULT_IGNORES,
9
11
  detectProjectOptions,
10
12
  Extension,
@@ -12,10 +14,10 @@ import {
12
14
  flattenConfigInputs,
13
15
  GENERATED_CODE_IGNORES,
14
16
  getStrictMode,
15
- gitignore,
16
17
  Library,
17
18
  mergeFrameworkOption,
18
19
  mergeOptionalBucket,
20
+ mergeProjectOptions,
19
21
  NextMode,
20
22
  patchImportGroups,
21
23
  Preset,
@@ -26,58 +28,42 @@ import {
26
28
  Setting,
27
29
  Testing
28
30
  } from "@santi020k/eslint-config-core";
29
- import { tailwind as tailwindIntegration } from "@santi020k/eslint-config-integrations";
30
31
  import { createTypescriptConfig } from "@santi020k/eslint-config-typescript";
31
32
  import { createDetectedFrameworkFlags } from "./frameworks.js";
32
33
  import { getIntegrationConfigs, getPrettierConfig } from "./integrations.js";
33
34
  import { resolveFramework, resolvePreset } from "./resolvers.js";
34
- import {
35
- AGENT_TARGETS,
36
- generateAgentSkills,
37
- generateSkillContent
38
- } from "./agent-skill-generator.js";
35
+ import { buildTailwindSettingsConfig } from "./tailwind.js";
39
36
  import {
40
37
  angular,
41
- angularConfig,
42
38
  astro,
43
39
  expo,
44
- expoConfig,
45
40
  hono,
46
41
  lit,
47
42
  nest,
48
- nestConfig,
49
43
  next,
50
- nextConfig,
51
44
  nuxt,
52
45
  preact,
53
- preactConfig,
54
46
  qwik,
55
47
  react,
56
- reactConfig,
57
48
  reactRouter,
58
- remix,
59
49
  slidev,
60
50
  solid,
61
- solidConfig,
62
51
  svelte,
63
- svelteConfig,
64
52
  tanstackStart,
65
53
  vite,
66
- vue,
67
- vueConfig
54
+ vue
68
55
  } from "./frameworks.js";
69
56
  import {
70
57
  coreConfig as coreConfig2,
71
58
  createCoreConfig as createCoreConfig2,
59
+ createGitignoreConfig as createGitignoreConfig2,
72
60
  createImportGroups,
73
61
  detectProjectOptions as detectProjectOptions2,
74
62
  Extension as Extension2,
75
63
  Format,
76
64
  getGlobalsForRuntime,
77
- gitignore as gitignore2,
78
65
  groups,
79
66
  hasReactConfig,
80
- jsConfig,
81
67
  Library as Library2,
82
68
  NextMode as NextMode2,
83
69
  Preset as Preset2,
@@ -87,109 +73,20 @@ import {
87
73
  Testing as Testing2,
88
74
  Tool
89
75
  } from "@santi020k/eslint-config-core";
90
- import {
91
- a11y,
92
- aiSdk,
93
- autogen,
94
- bestPractices,
95
- biome,
96
- boundaries,
97
- command,
98
- compat,
99
- cspell,
100
- css,
101
- cypress,
102
- deMorgan,
103
- depend,
104
- docker,
105
- drizzle,
106
- githubActions,
107
- googleGenAi,
108
- graphql,
109
- html,
110
- i18next,
111
- jest,
112
- jestDom,
113
- jsdoc,
114
- jsonc,
115
- langchain,
116
- llamaIndex,
117
- markdown,
118
- mastra,
119
- mcp,
120
- mdx,
121
- mikroOrm,
122
- node,
123
- noOnlyTests,
124
- nx,
125
- openAiAgents,
126
- oxlint,
127
- packageJson,
128
- perfectionist,
129
- playwright,
130
- pnpm,
131
- prettier,
132
- prisma,
133
- regexp,
134
- security,
135
- sequelize,
136
- sonarjs,
137
- stencil,
138
- storybook,
139
- swagger,
140
- tailwind,
141
- tanstackQuery,
142
- tanstackRouter,
143
- testingLibrary,
144
- toml,
145
- turbo,
146
- typeorm,
147
- unicorn,
148
- vitest,
149
- yaml,
150
- zod
151
- } from "@santi020k/eslint-config-integrations";
152
- import { tsConfig, typescriptConfig } from "@santi020k/eslint-config-typescript";
153
- const buildTailwindResult = (options, entryPoint) => ({
76
+ import { typescriptConfig } from "@santi020k/eslint-config-typescript";
77
+ const buildTailwindResult = (options, entryPoint, rootDir) => ({
78
+ cwd: options.cwd ?? rootDir,
154
79
  detectComponentClasses: options.detectComponentClasses ?? true,
155
80
  ...entryPoint ? { entryPoint } : {},
156
81
  ...options.ignore?.length ? { ignore: options.ignore } : {},
157
82
  ...options.noUnknownClasses === void 0 ? {} : { noUnknownClasses: options.noUnknownClasses }
158
83
  });
159
- const resolveTailwindOptions = (rootDir, tailwind2) => {
160
- if (tailwind2 === false) return void 0;
161
- const options = tailwind2 ?? {};
84
+ const resolveTailwindOptions = (rootDir, tailwind) => {
85
+ if (tailwind === false) return void 0;
86
+ const options = tailwind ?? {};
162
87
  const entryPoint = options.entryPoint ?? findTailwindEntryPoint(rootDir);
163
- if (!entryPoint && options.detectComponentClasses === void 0 && !options.ignore?.length && options.noUnknownClasses === void 0) return void 0;
164
- return buildTailwindResult(options, entryPoint);
165
- };
166
- const createNoUnknownClassesRule = (tailwindOptions, unknownClassOptions, hasUnknownClassOptions) => {
167
- if (!hasUnknownClassOptions && tailwindOptions.noUnknownClasses === void 0) return void 0;
168
- const severity = tailwindOptions.noUnknownClasses ?? "error";
169
- if (severity === false) return "off";
170
- return hasUnknownClassOptions ? [severity, unknownClassOptions] : severity;
171
- };
172
- const loadTailwindPlugins = async () => {
173
- const tailwindConfigs = await tailwindIntegration();
174
- const pluginConfig = tailwindConfigs.find((config) => config.plugins?.["better-tailwindcss"]);
175
- return pluginConfig?.plugins ?? {};
176
- };
177
- const createTailwindSettingsConfig = async (tailwindOptions) => {
178
- const { noUnknownClasses: _noUnknownClasses, ...settingsOptions } = tailwindOptions;
179
- const unknownClassOptions = {
180
- ...tailwindOptions.entryPoint ? { entryPoint: tailwindOptions.entryPoint } : {},
181
- ...tailwindOptions.ignore?.length ? { ignore: tailwindOptions.ignore } : {}
182
- };
183
- const hasUnknownClassOptions = Object.keys(unknownClassOptions).length > 0;
184
- const noUnknownClassesRule = createNoUnknownClassesRule(tailwindOptions, unknownClassOptions, hasUnknownClassOptions);
185
- return {
186
- name: "eslint-config-basic/tailwind-settings",
187
- plugins: await loadTailwindPlugins(),
188
- ...noUnknownClassesRule === void 0 ? {} : { rules: { "better-tailwindcss/no-unknown-classes": noUnknownClassesRule } },
189
- settings: {
190
- "better-tailwindcss": settingsOptions
191
- }
192
- };
88
+ if (!entryPoint && options.cwd === void 0 && options.detectComponentClasses === void 0 && !options.ignore?.length && options.noUnknownClasses === void 0) return void 0;
89
+ return buildTailwindResult(options, entryPoint, rootDir);
193
90
  };
194
91
  const TESTING_CONFIG_NAMES = {
195
92
  [Testing.Cypress]: ["integrations/cypress"],
@@ -204,9 +101,7 @@ const applyTestingFileOverrides = (configs, testingFiles) => {
204
101
  const entries = Object.entries(testingFiles).filter(([, files]) => files.length > 0);
205
102
  if (entries.length === 0) return configs;
206
103
  return configs.map((config) => {
207
- const match = entries.find(
208
- ([testingName]) => (TESTING_CONFIG_NAMES[testingName] ?? []).includes(config.name ?? "")
209
- );
104
+ const match = entries.find(([testingName]) => (TESTING_CONFIG_NAMES[testingName] ?? []).includes(config.name ?? ""));
210
105
  if (!match) return config;
211
106
  const [, files] = match;
212
107
  return {
@@ -215,16 +110,56 @@ const applyTestingFileOverrides = (configs, testingFiles) => {
215
110
  };
216
111
  });
217
112
  };
218
- const resolveConfigSetup = (options) => ({
219
- autoFrameworks: options?.autoFrameworks ?? true,
220
- detectRootDir: options?.detectRootDir ?? options?.tsconfigRootDir,
221
- optionMergeStrategy: options?.optionMergeStrategy ?? "merge",
222
- requestedPreset: options?.preset
223
- });
224
- const resolveUniqueLibraries = (libraries, tailwind2) => {
113
+ const ESLINT_CONFIG_FILENAMES = [
114
+ "eslint.config.js",
115
+ "eslint.config.cjs",
116
+ "eslint.config.mjs",
117
+ "eslint.config.ts",
118
+ "eslint.config.cts",
119
+ "eslint.config.mts"
120
+ ];
121
+ const findConfigRootFromStack = (stack = new Error().stack) => {
122
+ if (!stack) return void 0;
123
+ for (const line of stack.split("\n")) {
124
+ const configFilename = ESLINT_CONFIG_FILENAMES.find((filename) => line.includes(filename));
125
+ if (!configFilename) continue;
126
+ const filenameStart = line.indexOf(configFilename);
127
+ const fileUrlStart = line.lastIndexOf("file://", filenameStart);
128
+ const windowsPathStart = line.slice(0, filenameStart).search(/[A-Za-z]:[\\/]/);
129
+ const absolutePathStart = line.indexOf("/");
130
+ let configPathStart = absolutePathStart;
131
+ if (windowsPathStart >= 0) configPathStart = windowsPathStart;
132
+ if (fileUrlStart >= 0) configPathStart = fileUrlStart;
133
+ try {
134
+ if (configPathStart < 0) continue;
135
+ const configPath = line.slice(configPathStart, filenameStart + configFilename.length);
136
+ return dirname(configPath.startsWith("file:") ? fileURLToPath(configPath) : configPath);
137
+ } catch {
138
+ }
139
+ }
140
+ return void 0;
141
+ };
142
+ const resolveConfigSetup = (options) => {
143
+ const {
144
+ autoFrameworks = true,
145
+ detectRootDir,
146
+ optionMergeStrategy = "merge",
147
+ preset: requestedPreset,
148
+ root,
149
+ tsconfigRootDir
150
+ } = options ?? {};
151
+ const implicitRootDir = root ?? detectRootDir ?? tsconfigRootDir ?? findConfigRootFromStack();
152
+ return {
153
+ autoFrameworks,
154
+ detectRootDir: implicitRootDir,
155
+ optionMergeStrategy,
156
+ requestedPreset
157
+ };
158
+ };
159
+ const resolveUniqueLibraries = (libraries, tailwind) => {
225
160
  const uniqueLibraries = [...new Set(libraries)];
226
- if (tailwind2 === false) return uniqueLibraries.filter((library) => library !== Library.Tailwind);
227
- if (!tailwind2) return uniqueLibraries;
161
+ if (tailwind === false) return uniqueLibraries.filter((library) => library !== Library.Tailwind);
162
+ if (!tailwind) return uniqueLibraries;
228
163
  return [.../* @__PURE__ */ new Set([...uniqueLibraries, Library.Tailwind])];
229
164
  };
230
165
  const resolvePresetMeta = (requestedPreset, detected, autoFrameworks) => {
@@ -244,12 +179,26 @@ const resolveBucketDefaults = (detected) => ({
244
179
  detectedTesting: detected.testing ?? [],
245
180
  detectedTools: detected.tools ?? []
246
181
  });
182
+ const scopeWorkspaceDetection = (detected, isWorkspace) => isWorkspace ? {
183
+ ...detected,
184
+ detectedFrameworks: [],
185
+ libraries: [],
186
+ nextMode: void 0,
187
+ runtime: Runtime.Universal
188
+ } : detected;
189
+ const resolveDetectedOptions = (detectRootDir, detection, requestedPreset) => {
190
+ const rawDetected = detectProjectOptions(detectRootDir);
191
+ const shouldDetectProjects = requestedPreset === Preset.Monorepo || rawDetected.preset === Preset.Monorepo;
192
+ const detected = applyDetectionControls(rawDetected, detection, { projects: shouldDetectProjects });
193
+ const hasDetectedProjects = Object.keys(detected.projects ?? {}).length > 0;
194
+ return scopeWorkspaceDetection(detected, hasDetectedProjects);
195
+ };
247
196
  const resolveNextModeValue = (options, presetDefaults, detected) => options?.nextMode ?? presetDefaults.nextMode ?? detected.nextMode ?? NextMode.Pages;
248
197
  const resolveRuntimeValue = (options, presetDefaults, detected, usePresetRuntime) => options?.runtime ?? (usePresetRuntime ? presetDefaults.runtime : void 0) ?? detected.runtime ?? Runtime.Universal;
249
198
  const resolveSettingsValue = (options, detected) => options?.settings ?? detected.settings ?? [];
250
199
  const resolveTypescriptValue = (options, presetDefaults, detected) => options?.typescript ?? presetDefaults.typescript ?? detected.typescript ?? false;
251
200
  const needsReactAutoAdd = (frameworks) => Boolean(
252
- frameworks.next ?? frameworks.expo ?? frameworks.remix ?? frameworks["react-router"] ?? (frameworks["tanstack-start"] && !frameworks.solid)
201
+ frameworks.next ?? frameworks.expo ?? frameworks["react-router"] ?? (frameworks["tanstack-start"] && !frameworks.solid)
253
202
  ) && !frameworks.react;
254
203
  const applyFrameworkImpliedDeps = (frameworks) => {
255
204
  const result = { ...frameworks };
@@ -258,31 +207,35 @@ const applyFrameworkImpliedDeps = (frameworks) => {
258
207
  if (result.nuxt && !result.vue) result.vue = true;
259
208
  return result;
260
209
  };
261
- const buildIgnoresConfig = (useDefaultIgnores, useGeneratedCodeIgnores, useGitignore, options) => ({
210
+ const buildIgnoresConfig = (useDefaultIgnores, useGeneratedCodeIgnores, useGitignore, options, rootDir) => ({
262
211
  defaultIgnores: useDefaultIgnores ? [{
263
212
  ignores: [...DEFAULT_IGNORES, ...useGeneratedCodeIgnores ? GENERATED_CODE_IGNORES : []],
264
213
  name: "eslint-config-basic/default-ignores"
265
214
  }] : [],
266
- gitignoreConfig: useGitignore ? gitignore : [],
215
+ gitignoreConfig: useGitignore ? createGitignoreConfig(rootDir) : [],
267
216
  userIgnores: options?.ignores?.length ? [{
268
217
  ignores: options.ignores,
269
218
  name: "eslint-config-basic/ignores"
270
219
  }] : []
271
220
  });
272
221
  const FRAMEWORK_EXTRA_OPTS = {
273
- astro: (ctx) => ({ hasReact: ctx.hasReact, hasSolid: ctx.hasSolid, hasSvelte: ctx.hasSvelte, hasVue: ctx.hasVue }),
222
+ astro: (ctx) => ({
223
+ hasReact: ctx.hasReact,
224
+ hasSolid: ctx.hasSolid,
225
+ hasSvelte: ctx.hasSvelte,
226
+ hasVue: ctx.hasVue,
227
+ tsconfigRootDir: ctx.tsconfigRootDir
228
+ }),
274
229
  hono: (ctx) => ({ runtime: ctx.runtime }),
275
230
  slidev: (ctx) => ({ runtime: ctx.runtime }),
276
231
  vite: (ctx) => ({ runtime: ctx.runtime })
277
232
  };
278
233
  const resolveEnabledFrameworks = async (frameworks, ctx) => {
279
234
  const entries = await Promise.all(
280
- Object.entries(frameworks).filter((entry) => Boolean(entry[1])).map(
281
- ([name, value]) => (
282
- // eslint-disable-next-line security/detect-object-injection
283
- resolveFramework(name, value, FRAMEWORK_EXTRA_OPTS[name]?.(ctx)).then((config) => [name, config])
284
- )
285
- )
235
+ Object.entries(frameworks).filter((entry) => Boolean(entry[1])).map(([name, value]) => (
236
+ // eslint-disable-next-line security/detect-object-injection
237
+ resolveFramework(name, value, FRAMEWORK_EXTRA_OPTS[name]?.(ctx)).then((config) => [name, config])
238
+ ))
286
239
  );
287
240
  return Object.fromEntries(entries);
288
241
  };
@@ -308,7 +261,10 @@ const buildEslintConfigs = async (params) => {
308
261
  userIgnores
309
262
  } = params;
310
263
  const { hasReact, hasSolid, hasSvelte, hasVue } = astroOptions;
311
- const fw = await resolveEnabledFrameworks(resolvedFrameworks, { hasReact, hasSolid, hasSvelte, hasVue, runtime });
264
+ const fw = await resolveEnabledFrameworks(
265
+ resolvedFrameworks,
266
+ { hasReact, hasSolid, hasSvelte, hasVue, runtime, tsconfigRootDir }
267
+ );
312
268
  const get = (name) => fw[name] ?? [];
313
269
  return [
314
270
  ...defaultIgnores,
@@ -343,7 +299,6 @@ const buildEslintConfigs = async (params) => {
343
299
  ...get("solid"),
344
300
  ...get("angular"),
345
301
  ...get("qwik"),
346
- ...get("remix"),
347
302
  ...get("react-router"),
348
303
  ...get("tanstack-start"),
349
304
  ...get("nuxt"),
@@ -373,7 +328,7 @@ const buildEslintConfigs = async (params) => {
373
328
  ...uniqueExtensions.includes(Extension.Security) ? { "security/detect-non-literal-fs-filename": "off" } : {}
374
329
  }
375
330
  },
376
- ...tailwindOptions ? [await createTailwindSettingsConfig(tailwindOptions)] : [],
331
+ ...tailwindOptions ? [buildTailwindSettingsConfig(tailwindOptions)] : [],
377
332
  ...await getPrettierConfig(uniqueTools)
378
333
  ];
379
334
  };
@@ -412,13 +367,53 @@ const logEslintDebug = ({
412
367
  }, null, 2)}
413
368
  `);
414
369
  };
415
- const emitBasicWarnings = (options) => {
416
- if (options?.frameworks && "remix" in options.frameworks) {
417
- process.emitWarning('[eslint-config-basic] Warning: `frameworks.remix` is deprecated and will be removed in the next major. Please use `frameworks["react-router"]` instead.');
418
- }
370
+ const emitAstroDoctorWarning = (extensions, frameworks) => {
371
+ if (!extensions.includes(Extension.AstroDoctor) || frameworks.astro) return;
372
+ process.emitWarning(
373
+ "[eslint-config-basic] Warning: Astro Doctor is enabled without the Astro framework config. Enable `frameworks: { astro: true }` or remove the `astro-doctor` feature."
374
+ );
375
+ };
376
+ const resolveProjectConfigs = async (configuredProjects, projectDefaults, detectRootDir, autoFrameworks) => Promise.all(
377
+ Object.entries(configuredProjects).map(async ([projectPath, projectOptions]) => {
378
+ const projectRoot = join(detectRootDir ?? process.cwd(), projectPath);
379
+ const inheritedOptions = mergeProjectOptions(projectDefaults ?? {}, projectOptions);
380
+ const scopedConfigs = await defineConfig({
381
+ autoFrameworks,
382
+ ...inheritedOptions,
383
+ projectDefaults: void 0,
384
+ projects: void 0,
385
+ root: inheritedOptions.root ?? inheritedOptions.detectRootDir ?? projectRoot
386
+ });
387
+ return scopedConfigs.map((config) => config.name === "eslint-config/gitignore" ? config : scopeConfigToProject(config, projectPath));
388
+ })
389
+ );
390
+ const getConfigsParams = (options, rootDir, runtime, uniqueLibraries, uniqueSettings, resolvedFrameworks) => {
391
+ const hasReact = !!resolvedFrameworks.react;
392
+ const hasVue = !!resolvedFrameworks.vue;
393
+ const hasSvelte = !!resolvedFrameworks.svelte;
394
+ const hasSolid = !!resolvedFrameworks.solid;
395
+ const useGitignore = !uniqueSettings.includes(Setting.NoGitignore);
396
+ const useDefaultIgnores = !uniqueSettings.includes(Setting.NoDefaultIgnores);
397
+ const useGeneratedCodeIgnores = !uniqueSettings.includes(Setting.NoGeneratedCodeIgnores);
398
+ const tailwindOptions = uniqueLibraries.includes(Library.Tailwind) ? resolveTailwindOptions(rootDir, options?.tailwind) : void 0;
399
+ const runtimeCoreConfig = runtime === Runtime.Universal ? coreConfig : createCoreConfig(runtime);
400
+ const { defaultIgnores, gitignoreConfig, userIgnores } = buildIgnoresConfig(
401
+ useDefaultIgnores,
402
+ useGeneratedCodeIgnores,
403
+ useGitignore,
404
+ options,
405
+ rootDir
406
+ );
407
+ return {
408
+ astroOptions: { hasReact, hasSolid, hasSvelte, hasVue },
409
+ defaultIgnores,
410
+ gitignoreConfig,
411
+ runtimeCoreConfig,
412
+ tailwindOptions,
413
+ userIgnores
414
+ };
419
415
  };
420
- const eslintConfig = async (options, ...extraConfigs) => {
421
- emitBasicWarnings(options);
416
+ const defineConfig = async (options, ...extraConfigs) => {
422
417
  const {
423
418
  detection,
424
419
  extensions: optExtensions,
@@ -432,12 +427,7 @@ const eslintConfig = async (options, ...extraConfigs) => {
432
427
  workspacePrefixes
433
428
  } = options ?? {};
434
429
  const { autoFrameworks, detectRootDir, optionMergeStrategy, requestedPreset } = resolveConfigSetup(options);
435
- const shouldDefaultProjectDetection = requestedPreset === Preset.Monorepo;
436
- const detected = applyDetectionControls(
437
- detectProjectOptions(detectRootDir),
438
- detection,
439
- { projects: shouldDefaultProjectDetection }
440
- );
430
+ const detected = resolveDetectedOptions(detectRootDir, detection, requestedPreset);
441
431
  const { frameworkDefaults, preset, presetDefaults } = resolvePresetMeta(requestedPreset, detected, autoFrameworks);
442
432
  const configuredProjects = resolveConfiguredProjects(detected, options);
443
433
  const { detectedExtensions, detectedFormats, detectedLibraries, detectedTesting, detectedTools } = resolveBucketDefaults(detected);
@@ -498,27 +488,19 @@ const eslintConfig = async (options, ...extraConfigs) => {
498
488
  const uniqueTools = [...new Set(tools)];
499
489
  const uniqueExtensions = [...new Set(extensions)];
500
490
  const uniqueSettings = [...new Set(settings)];
501
- const hasReact = !!resolvedFrameworks.react;
502
- const hasVue = !!resolvedFrameworks.vue;
503
- const hasSvelte = !!resolvedFrameworks.svelte;
504
- const hasSolid = !!resolvedFrameworks.solid;
505
- const useGitignore = !uniqueSettings.includes(Setting.NoGitignore);
506
- const useDefaultIgnores = !uniqueSettings.includes(Setting.NoDefaultIgnores);
507
- const useGeneratedCodeIgnores = !uniqueSettings.includes(Setting.NoGeneratedCodeIgnores);
508
- const tailwindOptions = uniqueLibraries.includes(Library.Tailwind) ? resolveTailwindOptions(rootDir, options?.tailwind) : void 0;
509
- const runtimeCoreConfig = runtime === Runtime.Universal ? coreConfig : createCoreConfig(runtime);
510
- const { defaultIgnores, gitignoreConfig, userIgnores } = buildIgnoresConfig(useDefaultIgnores, useGeneratedCodeIgnores, useGitignore, options);
491
+ emitAstroDoctorWarning(uniqueExtensions, resolvedFrameworks);
492
+ const params = getConfigsParams(options, rootDir, runtime, uniqueLibraries, uniqueSettings, resolvedFrameworks);
511
493
  const configs = await buildEslintConfigs({
512
- astroOptions: { hasReact, hasSolid, hasSvelte, hasVue },
513
- defaultIgnores,
514
- gitignoreConfig,
494
+ astroOptions: params.astroOptions,
495
+ defaultIgnores: params.defaultIgnores,
496
+ gitignoreConfig: params.gitignoreConfig,
515
497
  nextMode,
516
498
  resolvedFrameworks,
517
499
  resolvedTypescript,
518
500
  rootDir,
519
501
  runtime,
520
- runtimeCoreConfig,
521
- tailwindOptions,
502
+ runtimeCoreConfig: params.runtimeCoreConfig,
503
+ tailwindOptions: params.tailwindOptions,
522
504
  testingFiles: options?.testingFiles,
523
505
  tsconfigRootDir,
524
506
  uniqueExtensions,
@@ -526,7 +508,7 @@ const eslintConfig = async (options, ...extraConfigs) => {
526
508
  uniqueLibraries,
527
509
  uniqueTesting,
528
510
  uniqueTools,
529
- userIgnores
511
+ userIgnores: params.userIgnores
530
512
  });
531
513
  logEslintDebug({
532
514
  autoFrameworks,
@@ -544,26 +526,17 @@ const eslintConfig = async (options, ...extraConfigs) => {
544
526
  uniqueTesting,
545
527
  uniqueTools
546
528
  });
547
- const projectConfigs = await Promise.all(
548
- Object.entries(configuredProjects).map(async ([projectPath, projectOptions]) => {
549
- const projectRoot = join(detectRootDir ?? process.cwd(), projectPath);
550
- const scopedConfigs = await eslintConfig({
551
- autoFrameworks: options?.autoFrameworks,
552
- ...projectOptions,
553
- detectRootDir: projectOptions.detectRootDir ?? projectRoot,
554
- projects: void 0,
555
- tsconfigRootDir: projectOptions.tsconfigRootDir ?? projectRoot
556
- });
557
- return scopedConfigs.map((config) => scopeConfigToProject(config, projectPath));
558
- })
529
+ const projectConfigs = await resolveProjectConfigs(
530
+ configuredProjects,
531
+ options?.projectDefaults,
532
+ detectRootDir,
533
+ options?.autoFrameworks
559
534
  );
560
535
  const allConfigs = [...configs, ...projectConfigs.flat(), ...flattenConfigInputs(extraConfigs)];
561
536
  const patchedConfigs = workspacePrefixes?.length ? patchImportGroups(allConfigs, workspacePrefixes) : allConfigs;
562
537
  return applyStrictMode(patchedConfigs, strict);
563
538
  };
564
- const defineConfig = eslintConfig;
565
539
  export {
566
- AGENT_TARGETS,
567
540
  Extension2 as Extension,
568
541
  Format,
569
542
  Library2 as Library,
@@ -574,107 +547,32 @@ export {
574
547
  Setting2 as Setting,
575
548
  Testing2 as Testing,
576
549
  Tool,
577
- a11y,
578
- aiSdk,
579
550
  angular,
580
- angularConfig,
581
551
  astro,
582
- autogen,
583
- bestPractices,
584
- biome,
585
- boundaries,
586
- command,
587
- compat,
588
552
  coreConfig2 as coreConfig,
589
553
  createCoreConfig2 as createCoreConfig,
554
+ createGitignoreConfig2 as createGitignoreConfig,
590
555
  createImportGroups,
591
- cspell,
592
- css,
593
- cypress,
594
- deMorgan,
595
556
  defineConfig,
596
- depend,
597
557
  detectProjectOptions2 as detectProjectOptions,
598
- docker,
599
- drizzle,
600
- eslintConfig,
601
558
  expo,
602
- expoConfig,
603
- generateAgentSkills,
604
- generateSkillContent,
605
559
  getGlobalsForRuntime,
606
- githubActions,
607
- gitignore2 as gitignore,
608
- googleGenAi,
609
- graphql,
610
560
  groups,
611
561
  hasReactConfig,
612
562
  hono,
613
- html,
614
- i18next,
615
- jest,
616
- jestDom,
617
- jsConfig,
618
- jsdoc,
619
- jsonc,
620
- langchain,
621
563
  lit,
622
- llamaIndex,
623
- markdown,
624
- mastra,
625
- mcp,
626
- mdx,
627
- mikroOrm,
628
564
  nest,
629
- nestConfig,
630
565
  next,
631
- nextConfig,
632
- noOnlyTests,
633
- node,
634
566
  nuxt,
635
- nx,
636
- openAiAgents,
637
- oxlint,
638
- packageJson,
639
- perfectionist,
640
- playwright,
641
- pnpm,
642
567
  preact,
643
- preactConfig,
644
- prettier,
645
- prisma,
646
568
  qwik,
647
569
  react,
648
- reactConfig,
649
570
  reactRouter,
650
- regexp,
651
- remix,
652
- security,
653
- sequelize,
654
571
  slidev,
655
572
  solid,
656
- solidConfig,
657
- sonarjs,
658
- stencil,
659
- storybook,
660
573
  svelte,
661
- svelteConfig,
662
- swagger,
663
- tailwind,
664
- tanstackQuery,
665
- tanstackRouter,
666
574
  tanstackStart,
667
- testingLibrary,
668
- toml,
669
- tsConfig,
670
- turbo,
671
- typeorm,
672
575
  typescriptConfig,
673
- unicorn,
674
576
  vite,
675
- vitest,
676
- vue,
677
- vueConfig,
678
- yaml,
679
- zod
577
+ vue
680
578
  };
@@ -1 +1,6 @@
1
- export { getIntegrationConfigs, getPrettierConfig } from '@santi020k/eslint-config-integrations';
1
+ import { Library, Tool, Testing, Format, Extension, FlatConfigArray } from '@santi020k/eslint-config-core';
2
+
3
+ declare const getIntegrationConfigs: (libraries: Library[], tools: Tool[], testing: Testing[], formats: Format[], extensions: Extension[]) => Promise<FlatConfigArray>;
4
+ declare const getPrettierConfig: (tools: Tool[]) => Promise<FlatConfigArray>;
5
+
6
+ export { getIntegrationConfigs, getPrettierConfig };
@@ -1,4 +1,47 @@
1
- import { getIntegrationConfigs, getPrettierConfig } from "@santi020k/eslint-config-integrations";
1
+ import {
2
+ createModuleLoader,
3
+ resolveConfigFeatures
4
+ } from "@santi020k/eslint-config-core";
5
+ const loadModule = createModuleLoader((specifier) => import.meta.resolve(specifier, import.meta.url));
6
+ const packCache = /* @__PURE__ */ new Map();
7
+ const loadFeaturePack = async (specifier) => {
8
+ let pending = packCache.get(specifier);
9
+ if (!pending) {
10
+ pending = loadModule(specifier);
11
+ packCache.set(specifier, pending);
12
+ }
13
+ try {
14
+ const module = await pending;
15
+ if (!module.features) {
16
+ throw new Error(`Installed package "${specifier}" does not export a feature registry.`);
17
+ }
18
+ return module.features;
19
+ } catch (error) {
20
+ packCache.delete(specifier);
21
+ throw new Error(
22
+ `Unable to load optional feature pack "${specifier}". Install it for the selected options, or remove those options from defineConfig().`,
23
+ { cause: error }
24
+ );
25
+ }
26
+ };
27
+ const loadSelectedPacks = async (libraries, tools, testing, formats, extensions) => (await Promise.all([
28
+ extensions.length > 0 ? loadFeaturePack("@santi020k/eslint-config-extensions/registry") : [],
29
+ formats.length > 0 ? loadFeaturePack("@santi020k/eslint-config-formats/registry") : [],
30
+ libraries.length > 0 ? loadFeaturePack("@santi020k/eslint-config-libraries/registry") : [],
31
+ testing.length > 0 ? loadFeaturePack("@santi020k/eslint-config-testing/registry") : [],
32
+ tools.length > 0 ? loadFeaturePack("@santi020k/eslint-config-tools/registry") : []
33
+ ])).flat();
34
+ const getIntegrationConfigs = async (libraries, tools, testing, formats, extensions) => {
35
+ const selected = [...libraries, ...tools, ...testing, ...formats, ...extensions];
36
+ if (selected.length === 0) return [];
37
+ const features = await loadSelectedPacks(libraries, tools, testing, formats, extensions);
38
+ return resolveConfigFeatures(features, selected);
39
+ };
40
+ const getPrettierConfig = async (tools) => {
41
+ if (tools.length === 0) return [];
42
+ const features = await loadFeaturePack("@santi020k/eslint-config-tools/registry");
43
+ return resolveConfigFeatures(features, tools, "finalizer");
44
+ };
2
45
  export {
3
46
  getIntegrationConfigs,
4
47
  getPrettierConfig