@santi020k/eslint-config-basic 3.0.0 → 3.2.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 +93 -0
- package/IMPROVEMENTS.md +270 -0
- package/README.md +6 -14
- package/dist/agent-skill-generator.d.ts +11 -2
- package/dist/agent-skill-generator.js +56 -8
- package/dist/cli-advanced.d.ts +23 -0
- package/dist/cli-advanced.js +217 -0
- package/dist/cli-migration.d.ts +26 -0
- package/dist/cli-migration.js +1134 -0
- package/dist/cli-preset.d.ts +31 -0
- package/dist/cli-preset.js +315 -0
- package/dist/cli-workflows.d.ts +63 -0
- package/dist/cli-workflows.js +444 -0
- package/dist/cli.d.ts +17 -4
- package/dist/cli.js +762 -55
- package/dist/define-config-metadata.d.ts +10 -0
- package/dist/define-config-metadata.js +18 -0
- package/dist/frameworks.d.ts +1 -25
- package/dist/frameworks.js +5 -23
- package/dist/index.d.ts +11 -10
- package/dist/index.js +146 -74
- package/dist/integrations.js +31 -23
- package/dist/optional-package-errors.d.ts +3 -0
- package/dist/optional-package-errors.js +14 -0
- package/package.json +72 -52
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ConfigInput, EslintConfigOptions, FlatConfigArray } from '@santi020k/eslint-config-core';
|
|
2
|
+
|
|
3
|
+
interface DefineConfigMetadata {
|
|
4
|
+
extraConfigs: ConfigInput[];
|
|
5
|
+
options?: EslintConfigOptions;
|
|
6
|
+
}
|
|
7
|
+
declare const attachDefineConfigMetadata: (config: FlatConfigArray, metadata: DefineConfigMetadata) => FlatConfigArray;
|
|
8
|
+
declare const getDefineConfigMetadata: (config: unknown) => DefineConfigMetadata | undefined;
|
|
9
|
+
|
|
10
|
+
export { type DefineConfigMetadata, attachDefineConfigMetadata, getDefineConfigMetadata };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const DEFINE_CONFIG_METADATA = /* @__PURE__ */ Symbol.for("@santi020k/eslint-config-basic/define-config-metadata");
|
|
2
|
+
const attachDefineConfigMetadata = (config, metadata) => {
|
|
3
|
+
Object.defineProperty(config, DEFINE_CONFIG_METADATA, {
|
|
4
|
+
configurable: false,
|
|
5
|
+
enumerable: false,
|
|
6
|
+
value: metadata,
|
|
7
|
+
writable: false
|
|
8
|
+
});
|
|
9
|
+
return config;
|
|
10
|
+
};
|
|
11
|
+
const getDefineConfigMetadata = (config) => (
|
|
12
|
+
// eslint-disable-next-line security/detect-object-injection -- shared symbol is an internal fixed metadata key
|
|
13
|
+
Array.isArray(config) ? config[DEFINE_CONFIG_METADATA] : void 0
|
|
14
|
+
);
|
|
15
|
+
export {
|
|
16
|
+
attachDefineConfigMetadata,
|
|
17
|
+
getDefineConfigMetadata
|
|
18
|
+
};
|
package/dist/frameworks.d.ts
CHANGED
|
@@ -30,29 +30,5 @@ declare const svelte: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
|
30
30
|
declare const tanstackStart: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
31
31
|
declare const vite: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
32
32
|
declare const vue: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
33
|
-
/**
|
|
34
|
-
* @deprecated Remix merged into React Router v7. Use `reactRouter` (the
|
|
35
|
-
* `react-router` framework key) instead. This alias loads the legacy Remix
|
|
36
|
-
* config and will be removed in the next major version.
|
|
37
|
-
*/
|
|
38
|
-
declare const remix: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
39
|
-
/** @deprecated Use `angular` instead. */
|
|
40
|
-
declare const angularConfig: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
41
|
-
/** @deprecated Use `expo` instead. */
|
|
42
|
-
declare const expoConfig: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
43
|
-
/** @deprecated Use `nest` instead. */
|
|
44
|
-
declare const nestConfig: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
45
|
-
/** @deprecated Use `next` instead. */
|
|
46
|
-
declare const nextConfig: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
47
|
-
/** @deprecated Use `preact` instead. */
|
|
48
|
-
declare const preactConfig: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
49
|
-
/** @deprecated Use `react` instead. */
|
|
50
|
-
declare const reactConfig: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
51
|
-
/** @deprecated Use `solid` instead. */
|
|
52
|
-
declare const solidConfig: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
53
|
-
/** @deprecated Use `svelte` instead. */
|
|
54
|
-
declare const svelteConfig: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
55
|
-
/** @deprecated Use `vue` instead. */
|
|
56
|
-
declare const vueConfig: (options?: FrameworkOptions) => Promise<FlatConfigArray>;
|
|
57
33
|
|
|
58
|
-
export { type FrameworkFlags, type FrameworkName, type FrameworkOptions, angular,
|
|
34
|
+
export { type FrameworkFlags, type FrameworkName, type FrameworkOptions, angular, astro, createDetectedFrameworkFlags, expo, getBundledFrameworkConfig, hono, lit, nest, next, nuxt, preact, qwik, react, reactRouter, slidev, solid, svelte, tanstackStart, vite, vue };
|
package/dist/frameworks.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createModuleLoader
|
|
3
3
|
} from "@santi020k/eslint-config-core";
|
|
4
|
+
import { isMissingRequestedPackage } from "./optional-package-errors.js";
|
|
4
5
|
const loadModule = createModuleLoader((specifier) => import.meta.resolve(specifier, import.meta.url));
|
|
5
6
|
const createDetectedFrameworkFlags = (detectedFrameworks = []) => Object.fromEntries(
|
|
6
7
|
detectedFrameworks.map((framework) => [framework, true])
|
|
@@ -18,7 +19,6 @@ const frameworkLoaders = /* @__PURE__ */ new Map([
|
|
|
18
19
|
["qwik", async () => (await loadModule("@santi020k/eslint-config-qwik")).qwik],
|
|
19
20
|
["react", async () => (await loadModule("@santi020k/eslint-config-react")).reactConfig],
|
|
20
21
|
["react-router", async () => (await loadModule("@santi020k/eslint-config-react-router")).reactRouter],
|
|
21
|
-
["remix", async () => (await loadModule("@santi020k/eslint-config-remix")).default],
|
|
22
22
|
["slidev", async () => (await loadModule("@santi020k/eslint-config-slidev")).slidev],
|
|
23
23
|
["solid", async () => (await loadModule("@santi020k/eslint-config-solid")).solidConfig],
|
|
24
24
|
["svelte", async () => (await loadModule("@santi020k/eslint-config-svelte")).svelteConfig],
|
|
@@ -34,8 +34,10 @@ const loadFrameworkConfigInput = (frameworkName) => {
|
|
|
34
34
|
if (!loader) return Promise.resolve([]);
|
|
35
35
|
const pending = loader().catch((error) => {
|
|
36
36
|
frameworkConfigCache.delete(frameworkName);
|
|
37
|
+
const specifier = `@santi020k/eslint-config-${frameworkName}`;
|
|
38
|
+
const remediation = isMissingRequestedPackage(error, specifier) ? `Install "${specifier}" or remove that framework from your defineConfig options.` : `The installed package "${specifier}" failed while evaluating. Inspect this error's cause for the original dependency or runtime failure.`;
|
|
37
39
|
throw new Error(
|
|
38
|
-
`Unable to load optional framework config "${frameworkName}".
|
|
40
|
+
`Unable to load optional framework config "${frameworkName}". ` + remediation,
|
|
39
41
|
{ cause: error }
|
|
40
42
|
);
|
|
41
43
|
});
|
|
@@ -65,45 +67,25 @@ const svelte = createBundledFramework("svelte");
|
|
|
65
67
|
const tanstackStart = createBundledFramework("tanstack-start");
|
|
66
68
|
const vite = createBundledFramework("vite");
|
|
67
69
|
const vue = createBundledFramework("vue");
|
|
68
|
-
const remix = createBundledFramework("remix");
|
|
69
|
-
const angularConfig = angular;
|
|
70
|
-
const expoConfig = expo;
|
|
71
|
-
const nestConfig = nest;
|
|
72
|
-
const nextConfig = next;
|
|
73
|
-
const preactConfig = preact;
|
|
74
|
-
const reactConfig = react;
|
|
75
|
-
const solidConfig = solid;
|
|
76
|
-
const svelteConfig = svelte;
|
|
77
|
-
const vueConfig = vue;
|
|
78
70
|
export {
|
|
79
71
|
angular,
|
|
80
|
-
angularConfig,
|
|
81
72
|
astro,
|
|
82
73
|
createDetectedFrameworkFlags,
|
|
83
74
|
expo,
|
|
84
|
-
expoConfig,
|
|
85
75
|
getBundledFrameworkConfig,
|
|
86
76
|
hono,
|
|
87
77
|
lit,
|
|
88
78
|
nest,
|
|
89
|
-
nestConfig,
|
|
90
79
|
next,
|
|
91
|
-
nextConfig,
|
|
92
80
|
nuxt,
|
|
93
81
|
preact,
|
|
94
|
-
preactConfig,
|
|
95
82
|
qwik,
|
|
96
83
|
react,
|
|
97
|
-
reactConfig,
|
|
98
84
|
reactRouter,
|
|
99
|
-
remix,
|
|
100
85
|
slidev,
|
|
101
86
|
solid,
|
|
102
|
-
solidConfig,
|
|
103
87
|
svelte,
|
|
104
|
-
svelteConfig,
|
|
105
88
|
tanstackStart,
|
|
106
89
|
vite,
|
|
107
|
-
vue
|
|
108
|
-
vueConfig
|
|
90
|
+
vue
|
|
109
91
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { EslintConfigOptions, ConfigInput
|
|
2
|
-
export { DetectedFrameworkName, DetectionOptions, EslintConfigOptions, Extension, ExtensionName, ExtensionOption, FlatConfigArray, Format, FormatName, FormatOption, ImportGroupOptions, ImportedFramework, Library, LibraryName, LibraryOption, NextMode, NextModeName, NextModeOption, OptionalConfigMap, OptionalConfigName, Preset, PresetName, PresetOption, ProjectConfigOptions, ReactConfigKeys, Runtime, RuntimeName, RuntimeOption, Setting, SettingName, SettingOption, StrictMode, Testing, TestingName, TestingOption, Tool, ToolName, ToolOption, TypeScriptMode, TypeScriptOptions, coreConfig, createCoreConfig, createImportGroups, detectProjectOptions, getGlobalsForRuntime,
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export { tsConfig, typescriptConfig } from '@santi020k/eslint-config-typescript';
|
|
1
|
+
import { FlatConfigArray, EslintConfigOptions, ConfigInput } from '@santi020k/eslint-config-core';
|
|
2
|
+
export { DetectedFrameworkName, DetectionOptions, EslintConfigOptions, Extension, ExtensionName, ExtensionOption, FlatConfigArray, Format, FormatName, FormatOption, ImportGroupOptions, ImportedFramework, Library, LibraryName, LibraryOption, NextMode, NextModeName, NextModeOption, OptionalConfigMap, OptionalConfigName, Preset, PresetName, PresetOption, ProjectConfigOptions, ReactConfigKeys, Runtime, RuntimeName, RuntimeOption, Setting, SettingName, SettingOption, StrictMode, Testing, TestingName, TestingOption, Tool, ToolName, ToolOption, TypeScriptMode, TypeScriptOptions, coreConfig, createCoreConfig, createGitignoreConfig, createImportGroups, detectProjectOptions, getGlobalsForRuntime, groups, hasReactConfig } from '@santi020k/eslint-config-core';
|
|
3
|
+
export { angular, astro, expo, hono, lit, nest, next, nuxt, preact, qwik, react, reactRouter, slidev, solid, svelte, tanstackStart, vite, vue } from './frameworks.js';
|
|
4
|
+
export { typescriptConfig } from '@santi020k/eslint-config-typescript';
|
|
6
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Copies already-loaded plugin objects onto rule blocks that reference them.
|
|
8
|
+
* ESLint 10 validates plugin availability per effective config object, while
|
|
9
|
+
* feature packs often keep plugin setup and consumer overrides separate.
|
|
10
|
+
*/
|
|
11
|
+
declare const attachReferencedPlugins: (configs: FlatConfigArray) => FlatConfigArray;
|
|
7
12
|
/**
|
|
8
13
|
* Generates the ESLint configuration array, applying configurations
|
|
9
14
|
* and integration settings based on the input configuration.
|
|
@@ -12,10 +17,6 @@ export { tsConfig, typescriptConfig } from '@santi020k/eslint-config-typescript'
|
|
|
12
17
|
* @param {ConfigInput[]} extraConfigs - Local flat-config overrides appended after generated config
|
|
13
18
|
* @returns {FlatConfigArray} The final ESLint configuration array
|
|
14
19
|
*/
|
|
15
|
-
declare const eslintConfig: (options?: EslintConfigOptions, ...extraConfigs: ConfigInput[]) => Promise<FlatConfigArray>;
|
|
16
|
-
/**
|
|
17
|
-
* Alias for `eslintConfig()` that reads naturally in `eslint.config.*` files.
|
|
18
|
-
*/
|
|
19
20
|
declare const defineConfig: (options?: EslintConfigOptions, ...extraConfigs: ConfigInput[]) => Promise<FlatConfigArray>;
|
|
20
21
|
|
|
21
|
-
export {
|
|
22
|
+
export { attachReferencedPlugins, defineConfig };
|
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,7 +14,6 @@ import {
|
|
|
12
14
|
flattenConfigInputs,
|
|
13
15
|
GENERATED_CODE_IGNORES,
|
|
14
16
|
getStrictMode,
|
|
15
|
-
gitignore,
|
|
16
17
|
Library,
|
|
17
18
|
mergeFrameworkOption,
|
|
18
19
|
mergeOptionalBucket,
|
|
@@ -28,57 +29,42 @@ import {
|
|
|
28
29
|
Testing
|
|
29
30
|
} from "@santi020k/eslint-config-core";
|
|
30
31
|
import { createTypescriptConfig } from "@santi020k/eslint-config-typescript";
|
|
32
|
+
import { attachDefineConfigMetadata } from "./define-config-metadata.js";
|
|
31
33
|
import { createDetectedFrameworkFlags } from "./frameworks.js";
|
|
32
34
|
import { getIntegrationConfigs, getPrettierConfig } from "./integrations.js";
|
|
33
35
|
import { resolveFramework, resolvePreset } from "./resolvers.js";
|
|
34
36
|
import { buildTailwindSettingsConfig } from "./tailwind.js";
|
|
35
|
-
import {
|
|
36
|
-
AGENT_TARGETS,
|
|
37
|
-
generateAgentSkills,
|
|
38
|
-
generateSkillContent
|
|
39
|
-
} from "./agent-skill-generator.js";
|
|
40
37
|
import {
|
|
41
38
|
angular,
|
|
42
|
-
angularConfig,
|
|
43
39
|
astro,
|
|
44
40
|
expo,
|
|
45
|
-
expoConfig,
|
|
46
41
|
hono,
|
|
47
42
|
lit,
|
|
48
43
|
nest,
|
|
49
|
-
nestConfig,
|
|
50
44
|
next,
|
|
51
|
-
nextConfig,
|
|
52
45
|
nuxt,
|
|
53
46
|
preact,
|
|
54
|
-
preactConfig,
|
|
55
47
|
qwik,
|
|
56
48
|
react,
|
|
57
|
-
reactConfig,
|
|
58
49
|
reactRouter,
|
|
59
|
-
remix,
|
|
60
50
|
slidev,
|
|
61
51
|
solid,
|
|
62
|
-
solidConfig,
|
|
63
52
|
svelte,
|
|
64
|
-
svelteConfig,
|
|
65
53
|
tanstackStart,
|
|
66
54
|
vite,
|
|
67
|
-
vue
|
|
68
|
-
vueConfig
|
|
55
|
+
vue
|
|
69
56
|
} from "./frameworks.js";
|
|
70
57
|
import {
|
|
71
58
|
coreConfig as coreConfig2,
|
|
72
59
|
createCoreConfig as createCoreConfig2,
|
|
60
|
+
createGitignoreConfig as createGitignoreConfig2,
|
|
73
61
|
createImportGroups,
|
|
74
62
|
detectProjectOptions as detectProjectOptions2,
|
|
75
63
|
Extension as Extension2,
|
|
76
64
|
Format,
|
|
77
65
|
getGlobalsForRuntime,
|
|
78
|
-
gitignore as gitignore2,
|
|
79
66
|
groups,
|
|
80
67
|
hasReactConfig,
|
|
81
|
-
jsConfig,
|
|
82
68
|
Library as Library2,
|
|
83
69
|
NextMode as NextMode2,
|
|
84
70
|
Preset as Preset2,
|
|
@@ -88,7 +74,7 @@ import {
|
|
|
88
74
|
Testing as Testing2,
|
|
89
75
|
Tool
|
|
90
76
|
} from "@santi020k/eslint-config-core";
|
|
91
|
-
import {
|
|
77
|
+
import { typescriptConfig } from "@santi020k/eslint-config-typescript";
|
|
92
78
|
const buildTailwindResult = (options, entryPoint, rootDir) => ({
|
|
93
79
|
cwd: options.cwd ?? rootDir,
|
|
94
80
|
detectComponentClasses: options.detectComponentClasses ?? true,
|
|
@@ -125,12 +111,52 @@ const applyTestingFileOverrides = (configs, testingFiles) => {
|
|
|
125
111
|
};
|
|
126
112
|
});
|
|
127
113
|
};
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
114
|
+
const ESLINT_CONFIG_FILENAMES = [
|
|
115
|
+
"eslint.config.js",
|
|
116
|
+
"eslint.config.cjs",
|
|
117
|
+
"eslint.config.mjs",
|
|
118
|
+
"eslint.config.ts",
|
|
119
|
+
"eslint.config.cts",
|
|
120
|
+
"eslint.config.mts"
|
|
121
|
+
];
|
|
122
|
+
const findConfigRootFromStack = (stack = new Error().stack) => {
|
|
123
|
+
if (!stack) return void 0;
|
|
124
|
+
for (const line of stack.split("\n")) {
|
|
125
|
+
const configFilename = ESLINT_CONFIG_FILENAMES.find((filename) => line.includes(filename));
|
|
126
|
+
if (!configFilename) continue;
|
|
127
|
+
const filenameStart = line.indexOf(configFilename);
|
|
128
|
+
const fileUrlStart = line.lastIndexOf("file://", filenameStart);
|
|
129
|
+
const windowsPathStart = line.slice(0, filenameStart).search(/[A-Za-z]:[\\/]/);
|
|
130
|
+
const absolutePathStart = line.indexOf("/");
|
|
131
|
+
let configPathStart = absolutePathStart;
|
|
132
|
+
if (windowsPathStart >= 0) configPathStart = windowsPathStart;
|
|
133
|
+
if (fileUrlStart >= 0) configPathStart = fileUrlStart;
|
|
134
|
+
try {
|
|
135
|
+
if (configPathStart < 0) continue;
|
|
136
|
+
const configPath = line.slice(configPathStart, filenameStart + configFilename.length);
|
|
137
|
+
return dirname(configPath.startsWith("file:") ? fileURLToPath(configPath) : configPath);
|
|
138
|
+
} catch {
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return void 0;
|
|
142
|
+
};
|
|
143
|
+
const resolveConfigSetup = (options) => {
|
|
144
|
+
const {
|
|
145
|
+
autoFrameworks = true,
|
|
146
|
+
detectRootDir,
|
|
147
|
+
optionMergeStrategy = "merge",
|
|
148
|
+
preset: requestedPreset,
|
|
149
|
+
root,
|
|
150
|
+
tsconfigRootDir
|
|
151
|
+
} = options ?? {};
|
|
152
|
+
const implicitRootDir = root ?? detectRootDir ?? tsconfigRootDir ?? findConfigRootFromStack();
|
|
153
|
+
return {
|
|
154
|
+
autoFrameworks,
|
|
155
|
+
detectRootDir: implicitRootDir,
|
|
156
|
+
optionMergeStrategy,
|
|
157
|
+
requestedPreset
|
|
158
|
+
};
|
|
159
|
+
};
|
|
134
160
|
const resolveUniqueLibraries = (libraries, tailwind) => {
|
|
135
161
|
const uniqueLibraries = [...new Set(libraries)];
|
|
136
162
|
if (tailwind === false) return uniqueLibraries.filter((library) => library !== Library.Tailwind);
|
|
@@ -154,12 +180,26 @@ const resolveBucketDefaults = (detected) => ({
|
|
|
154
180
|
detectedTesting: detected.testing ?? [],
|
|
155
181
|
detectedTools: detected.tools ?? []
|
|
156
182
|
});
|
|
183
|
+
const scopeWorkspaceDetection = (detected, isWorkspace) => isWorkspace ? {
|
|
184
|
+
...detected,
|
|
185
|
+
detectedFrameworks: [],
|
|
186
|
+
libraries: [],
|
|
187
|
+
nextMode: void 0,
|
|
188
|
+
runtime: Runtime.Universal
|
|
189
|
+
} : detected;
|
|
190
|
+
const resolveDetectedOptions = (detectRootDir, detection, requestedPreset) => {
|
|
191
|
+
const rawDetected = detectProjectOptions(detectRootDir);
|
|
192
|
+
const shouldDetectProjects = requestedPreset === Preset.Monorepo || rawDetected.preset === Preset.Monorepo;
|
|
193
|
+
const detected = applyDetectionControls(rawDetected, detection, { projects: shouldDetectProjects });
|
|
194
|
+
const hasDetectedProjects = Object.keys(detected.projects ?? {}).length > 0;
|
|
195
|
+
return scopeWorkspaceDetection(detected, hasDetectedProjects);
|
|
196
|
+
};
|
|
157
197
|
const resolveNextModeValue = (options, presetDefaults, detected) => options?.nextMode ?? presetDefaults.nextMode ?? detected.nextMode ?? NextMode.Pages;
|
|
158
198
|
const resolveRuntimeValue = (options, presetDefaults, detected, usePresetRuntime) => options?.runtime ?? (usePresetRuntime ? presetDefaults.runtime : void 0) ?? detected.runtime ?? Runtime.Universal;
|
|
159
199
|
const resolveSettingsValue = (options, detected) => options?.settings ?? detected.settings ?? [];
|
|
160
200
|
const resolveTypescriptValue = (options, presetDefaults, detected) => options?.typescript ?? presetDefaults.typescript ?? detected.typescript ?? false;
|
|
161
201
|
const needsReactAutoAdd = (frameworks) => Boolean(
|
|
162
|
-
frameworks.next ?? frameworks.expo ?? frameworks
|
|
202
|
+
frameworks.next ?? frameworks.expo ?? frameworks["react-router"] ?? (frameworks["tanstack-start"] && !frameworks.solid)
|
|
163
203
|
) && !frameworks.react;
|
|
164
204
|
const applyFrameworkImpliedDeps = (frameworks) => {
|
|
165
205
|
const result = { ...frameworks };
|
|
@@ -168,12 +208,12 @@ const applyFrameworkImpliedDeps = (frameworks) => {
|
|
|
168
208
|
if (result.nuxt && !result.vue) result.vue = true;
|
|
169
209
|
return result;
|
|
170
210
|
};
|
|
171
|
-
const buildIgnoresConfig = (useDefaultIgnores, useGeneratedCodeIgnores, useGitignore, options) => ({
|
|
211
|
+
const buildIgnoresConfig = (useDefaultIgnores, useGeneratedCodeIgnores, useGitignore, options, rootDir) => ({
|
|
172
212
|
defaultIgnores: useDefaultIgnores ? [{
|
|
173
213
|
ignores: [...DEFAULT_IGNORES, ...useGeneratedCodeIgnores ? GENERATED_CODE_IGNORES : []],
|
|
174
214
|
name: "eslint-config-basic/default-ignores"
|
|
175
215
|
}] : [],
|
|
176
|
-
gitignoreConfig: useGitignore ?
|
|
216
|
+
gitignoreConfig: useGitignore ? createGitignoreConfig(rootDir) : [],
|
|
177
217
|
userIgnores: options?.ignores?.length ? [{
|
|
178
218
|
ignores: options.ignores,
|
|
179
219
|
name: "eslint-config-basic/ignores"
|
|
@@ -227,6 +267,16 @@ const buildEslintConfigs = async (params) => {
|
|
|
227
267
|
{ hasReact, hasSolid, hasSvelte, hasVue, runtime, tsconfigRootDir }
|
|
228
268
|
);
|
|
229
269
|
const get = (name) => fw[name] ?? [];
|
|
270
|
+
const typescriptConfigs = resolvedTypescript ? createTypescriptConfig({
|
|
271
|
+
...resolvedTypescript,
|
|
272
|
+
tsconfigRootDir: resolvedTypescript.tsconfigRootDir ?? tsconfigRootDir
|
|
273
|
+
}) : [];
|
|
274
|
+
const untypedTypescriptConfigs = typescriptConfigs.filter(
|
|
275
|
+
(config) => config.name === "eslint-config-typescript/untyped-files"
|
|
276
|
+
);
|
|
277
|
+
const typedTypescriptConfigs = typescriptConfigs.filter(
|
|
278
|
+
(config) => config.name !== "eslint-config-typescript/untyped-files"
|
|
279
|
+
);
|
|
230
280
|
return [
|
|
231
281
|
...defaultIgnores,
|
|
232
282
|
...userIgnores,
|
|
@@ -260,7 +310,6 @@ const buildEslintConfigs = async (params) => {
|
|
|
260
310
|
...get("solid"),
|
|
261
311
|
...get("angular"),
|
|
262
312
|
...get("qwik"),
|
|
263
|
-
...get("remix"),
|
|
264
313
|
...get("react-router"),
|
|
265
314
|
...get("tanstack-start"),
|
|
266
315
|
...get("nuxt"),
|
|
@@ -268,10 +317,7 @@ const buildEslintConfigs = async (params) => {
|
|
|
268
317
|
...get("lit"),
|
|
269
318
|
...get("slidev"),
|
|
270
319
|
...get("vite"),
|
|
271
|
-
...
|
|
272
|
-
...resolvedTypescript,
|
|
273
|
-
tsconfigRootDir: resolvedTypescript.tsconfigRootDir ?? tsconfigRootDir
|
|
274
|
-
}) : [],
|
|
320
|
+
...typedTypescriptConfigs,
|
|
275
321
|
...get("astro"),
|
|
276
322
|
...resolvedFrameworks.next && nextMode === NextMode.AppRouter ? [{
|
|
277
323
|
files: ["app/**/*.{ts,tsx}", "src/**/*.{ts,tsx}"],
|
|
@@ -291,6 +337,7 @@ const buildEslintConfigs = async (params) => {
|
|
|
291
337
|
}
|
|
292
338
|
},
|
|
293
339
|
...tailwindOptions ? [buildTailwindSettingsConfig(tailwindOptions)] : [],
|
|
340
|
+
...untypedTypescriptConfigs,
|
|
294
341
|
...await getPrettierConfig(uniqueTools)
|
|
295
342
|
];
|
|
296
343
|
};
|
|
@@ -329,11 +376,6 @@ const logEslintDebug = ({
|
|
|
329
376
|
}, null, 2)}
|
|
330
377
|
`);
|
|
331
378
|
};
|
|
332
|
-
const emitBasicWarnings = (options) => {
|
|
333
|
-
if (options?.frameworks && "remix" in options.frameworks) {
|
|
334
|
-
process.emitWarning('[eslint-config-basic] Warning: `frameworks.remix` is deprecated and will be removed in the next major. Please use `frameworks["react-router"]` instead.');
|
|
335
|
-
}
|
|
336
|
-
};
|
|
337
379
|
const emitAstroDoctorWarning = (extensions, frameworks) => {
|
|
338
380
|
if (!extensions.includes(Extension.AstroDoctor) || frameworks.astro) return;
|
|
339
381
|
process.emitWarning(
|
|
@@ -344,17 +386,62 @@ const resolveProjectConfigs = async (configuredProjects, projectDefaults, detect
|
|
|
344
386
|
Object.entries(configuredProjects).map(async ([projectPath, projectOptions]) => {
|
|
345
387
|
const projectRoot = join(detectRootDir ?? process.cwd(), projectPath);
|
|
346
388
|
const inheritedOptions = mergeProjectOptions(projectDefaults ?? {}, projectOptions);
|
|
347
|
-
const scopedConfigs = await
|
|
389
|
+
const scopedConfigs = await defineConfig({
|
|
348
390
|
autoFrameworks,
|
|
349
391
|
...inheritedOptions,
|
|
350
|
-
detectRootDir: inheritedOptions.detectRootDir ?? projectRoot,
|
|
351
392
|
projectDefaults: void 0,
|
|
352
393
|
projects: void 0,
|
|
353
|
-
|
|
394
|
+
root: inheritedOptions.root ?? inheritedOptions.detectRootDir ?? projectRoot
|
|
354
395
|
});
|
|
355
|
-
return scopedConfigs.map((config) => scopeConfigToProject(config, projectPath));
|
|
396
|
+
return scopedConfigs.map((config) => config.name === "eslint-config/gitignore" ? config : scopeConfigToProject(config, projectPath));
|
|
356
397
|
})
|
|
357
398
|
);
|
|
399
|
+
const resolveInheritedProjectDefaults = (options) => mergeProjectOptions(
|
|
400
|
+
{
|
|
401
|
+
...options?.detection === void 0 ? {} : { detection: options.detection },
|
|
402
|
+
...options?.tailwind === void 0 ? {} : { tailwind: options.tailwind }
|
|
403
|
+
},
|
|
404
|
+
options?.projectDefaults ?? {}
|
|
405
|
+
);
|
|
406
|
+
const getPluginNameFromRule = (ruleName, availablePluginNames) => {
|
|
407
|
+
const segments = ruleName.split("/");
|
|
408
|
+
if (segments.length < 2) return void 0;
|
|
409
|
+
const registeredPrefix = [...availablePluginNames].filter((pluginName) => ruleName.startsWith(`${pluginName}/`)).sort((left, right) => right.length - left.length)[0];
|
|
410
|
+
if (registeredPrefix) return registeredPrefix;
|
|
411
|
+
return ruleName.startsWith("@") && segments.length > 2 ? segments.slice(0, 2).join("/") : segments[0];
|
|
412
|
+
};
|
|
413
|
+
const attachReferencedPlugins = (configs) => {
|
|
414
|
+
const availablePlugins = /* @__PURE__ */ new Map();
|
|
415
|
+
const ambiguousPluginNames = /* @__PURE__ */ new Set();
|
|
416
|
+
for (const config of configs) {
|
|
417
|
+
for (const [pluginName, plugin] of Object.entries(config.plugins ?? {})) {
|
|
418
|
+
const existingPlugin = availablePlugins.get(pluginName);
|
|
419
|
+
if (existingPlugin && existingPlugin !== plugin) {
|
|
420
|
+
availablePlugins.delete(pluginName);
|
|
421
|
+
ambiguousPluginNames.add(pluginName);
|
|
422
|
+
} else if (!ambiguousPluginNames.has(pluginName)) {
|
|
423
|
+
availablePlugins.set(pluginName, plugin);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return configs.map((config) => {
|
|
428
|
+
const requiredPlugins = new Set(
|
|
429
|
+
Object.keys(config.rules ?? {}).map((ruleName) => getPluginNameFromRule(ruleName, availablePlugins.keys())).filter((pluginName) => pluginName !== void 0)
|
|
430
|
+
);
|
|
431
|
+
const missingPluginEntries = [...requiredPlugins].flatMap((pluginName) => {
|
|
432
|
+
const plugin = availablePlugins.get(pluginName);
|
|
433
|
+
return !Object.hasOwn(config.plugins ?? {}, pluginName) && plugin ? [[pluginName, plugin]] : [];
|
|
434
|
+
});
|
|
435
|
+
if (missingPluginEntries.length === 0) return config;
|
|
436
|
+
return {
|
|
437
|
+
...config,
|
|
438
|
+
plugins: {
|
|
439
|
+
...config.plugins,
|
|
440
|
+
...Object.fromEntries(missingPluginEntries)
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
});
|
|
444
|
+
};
|
|
358
445
|
const getConfigsParams = (options, rootDir, runtime, uniqueLibraries, uniqueSettings, resolvedFrameworks) => {
|
|
359
446
|
const hasReact = !!resolvedFrameworks.react;
|
|
360
447
|
const hasVue = !!resolvedFrameworks.vue;
|
|
@@ -365,7 +452,13 @@ const getConfigsParams = (options, rootDir, runtime, uniqueLibraries, uniqueSett
|
|
|
365
452
|
const useGeneratedCodeIgnores = !uniqueSettings.includes(Setting.NoGeneratedCodeIgnores);
|
|
366
453
|
const tailwindOptions = uniqueLibraries.includes(Library.Tailwind) ? resolveTailwindOptions(rootDir, options?.tailwind) : void 0;
|
|
367
454
|
const runtimeCoreConfig = runtime === Runtime.Universal ? coreConfig : createCoreConfig(runtime);
|
|
368
|
-
const { defaultIgnores, gitignoreConfig, userIgnores } = buildIgnoresConfig(
|
|
455
|
+
const { defaultIgnores, gitignoreConfig, userIgnores } = buildIgnoresConfig(
|
|
456
|
+
useDefaultIgnores,
|
|
457
|
+
useGeneratedCodeIgnores,
|
|
458
|
+
useGitignore,
|
|
459
|
+
options,
|
|
460
|
+
rootDir
|
|
461
|
+
);
|
|
369
462
|
return {
|
|
370
463
|
astroOptions: { hasReact, hasSolid, hasSvelte, hasVue },
|
|
371
464
|
defaultIgnores,
|
|
@@ -375,8 +468,7 @@ const getConfigsParams = (options, rootDir, runtime, uniqueLibraries, uniqueSett
|
|
|
375
468
|
userIgnores
|
|
376
469
|
};
|
|
377
470
|
};
|
|
378
|
-
const
|
|
379
|
-
emitBasicWarnings(options);
|
|
471
|
+
const defineConfig = async (options, ...extraConfigs) => {
|
|
380
472
|
const {
|
|
381
473
|
detection,
|
|
382
474
|
extensions: optExtensions,
|
|
@@ -390,12 +482,7 @@ const eslintConfig = async (options, ...extraConfigs) => {
|
|
|
390
482
|
workspacePrefixes
|
|
391
483
|
} = options ?? {};
|
|
392
484
|
const { autoFrameworks, detectRootDir, optionMergeStrategy, requestedPreset } = resolveConfigSetup(options);
|
|
393
|
-
const
|
|
394
|
-
const detected = applyDetectionControls(
|
|
395
|
-
detectProjectOptions(detectRootDir),
|
|
396
|
-
detection,
|
|
397
|
-
{ projects: shouldDefaultProjectDetection }
|
|
398
|
-
);
|
|
485
|
+
const detected = resolveDetectedOptions(detectRootDir, detection, requestedPreset);
|
|
399
486
|
const { frameworkDefaults, preset, presetDefaults } = resolvePresetMeta(requestedPreset, detected, autoFrameworks);
|
|
400
487
|
const configuredProjects = resolveConfiguredProjects(detected, options);
|
|
401
488
|
const { detectedExtensions, detectedFormats, detectedLibraries, detectedTesting, detectedTools } = resolveBucketDefaults(detected);
|
|
@@ -496,17 +583,16 @@ const eslintConfig = async (options, ...extraConfigs) => {
|
|
|
496
583
|
});
|
|
497
584
|
const projectConfigs = await resolveProjectConfigs(
|
|
498
585
|
configuredProjects,
|
|
499
|
-
options
|
|
586
|
+
resolveInheritedProjectDefaults(options),
|
|
500
587
|
detectRootDir,
|
|
501
588
|
options?.autoFrameworks
|
|
502
589
|
);
|
|
503
590
|
const allConfigs = [...configs, ...projectConfigs.flat(), ...flattenConfigInputs(extraConfigs)];
|
|
504
591
|
const patchedConfigs = workspacePrefixes?.length ? patchImportGroups(allConfigs, workspacePrefixes) : allConfigs;
|
|
505
|
-
|
|
592
|
+
const finalConfig = attachReferencedPlugins(applyStrictMode(patchedConfigs, strict));
|
|
593
|
+
return attachDefineConfigMetadata(finalConfig, { extraConfigs, options });
|
|
506
594
|
};
|
|
507
|
-
const defineConfig = eslintConfig;
|
|
508
595
|
export {
|
|
509
|
-
AGENT_TARGETS,
|
|
510
596
|
Extension2 as Extension,
|
|
511
597
|
Format,
|
|
512
598
|
Library2 as Library,
|
|
@@ -518,46 +604,32 @@ export {
|
|
|
518
604
|
Testing2 as Testing,
|
|
519
605
|
Tool,
|
|
520
606
|
angular,
|
|
521
|
-
angularConfig,
|
|
522
607
|
astro,
|
|
608
|
+
attachReferencedPlugins,
|
|
523
609
|
coreConfig2 as coreConfig,
|
|
524
610
|
createCoreConfig2 as createCoreConfig,
|
|
611
|
+
createGitignoreConfig2 as createGitignoreConfig,
|
|
525
612
|
createImportGroups,
|
|
526
613
|
defineConfig,
|
|
527
614
|
detectProjectOptions2 as detectProjectOptions,
|
|
528
|
-
eslintConfig,
|
|
529
615
|
expo,
|
|
530
|
-
expoConfig,
|
|
531
|
-
generateAgentSkills,
|
|
532
|
-
generateSkillContent,
|
|
533
616
|
getGlobalsForRuntime,
|
|
534
|
-
gitignore2 as gitignore,
|
|
535
617
|
groups,
|
|
536
618
|
hasReactConfig,
|
|
537
619
|
hono,
|
|
538
|
-
jsConfig,
|
|
539
620
|
lit,
|
|
540
621
|
nest,
|
|
541
|
-
nestConfig,
|
|
542
622
|
next,
|
|
543
|
-
nextConfig,
|
|
544
623
|
nuxt,
|
|
545
624
|
preact,
|
|
546
|
-
preactConfig,
|
|
547
625
|
qwik,
|
|
548
626
|
react,
|
|
549
|
-
reactConfig,
|
|
550
627
|
reactRouter,
|
|
551
|
-
remix,
|
|
552
628
|
slidev,
|
|
553
629
|
solid,
|
|
554
|
-
solidConfig,
|
|
555
630
|
svelte,
|
|
556
|
-
svelteConfig,
|
|
557
631
|
tanstackStart,
|
|
558
|
-
tsConfig,
|
|
559
632
|
typescriptConfig,
|
|
560
633
|
vite,
|
|
561
|
-
vue
|
|
562
|
-
vueConfig
|
|
634
|
+
vue
|
|
563
635
|
};
|
package/dist/integrations.js
CHANGED
|
@@ -1,40 +1,48 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createModuleLoader,
|
|
3
|
-
|
|
3
|
+
resolveConfigFeatures
|
|
4
4
|
} from "@santi020k/eslint-config-core";
|
|
5
|
+
import { isMissingRequestedPackage } from "./optional-package-errors.js";
|
|
5
6
|
const loadModule = createModuleLoader((specifier) => import.meta.resolve(specifier, import.meta.url));
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const packCache = /* @__PURE__ */ new Map();
|
|
8
|
+
const loadFeaturePack = async (specifier) => {
|
|
9
|
+
let pending = packCache.get(specifier);
|
|
10
|
+
if (!pending) {
|
|
11
|
+
pending = loadModule(specifier);
|
|
12
|
+
packCache.set(specifier, pending);
|
|
13
|
+
}
|
|
9
14
|
try {
|
|
10
|
-
|
|
15
|
+
const module = await pending;
|
|
16
|
+
if (!module.features) {
|
|
17
|
+
throw new Error(`Installed package "${specifier}" does not export a feature registry.`);
|
|
18
|
+
}
|
|
19
|
+
return module.features;
|
|
11
20
|
} catch (error) {
|
|
12
|
-
|
|
21
|
+
packCache.delete(specifier);
|
|
22
|
+
const remediation = isMissingRequestedPackage(error, specifier) ? "Install it for the selected options, or remove those options from defineConfig()." : "The installed feature pack failed while evaluating. Inspect this error's cause for the original dependency or runtime failure.";
|
|
13
23
|
throw new Error(
|
|
14
|
-
|
|
24
|
+
`Unable to load optional feature pack "${specifier}". ` + remediation,
|
|
15
25
|
{ cause: error }
|
|
16
26
|
);
|
|
17
27
|
}
|
|
18
28
|
};
|
|
29
|
+
const loadSelectedPacks = async (libraries, tools, testing, formats, extensions) => (await Promise.all([
|
|
30
|
+
extensions.length > 0 ? loadFeaturePack("@santi020k/eslint-config-extensions/registry") : [],
|
|
31
|
+
formats.length > 0 ? loadFeaturePack("@santi020k/eslint-config-formats/registry") : [],
|
|
32
|
+
libraries.length > 0 ? loadFeaturePack("@santi020k/eslint-config-libraries/registry") : [],
|
|
33
|
+
testing.length > 0 ? loadFeaturePack("@santi020k/eslint-config-testing/registry") : [],
|
|
34
|
+
tools.length > 0 ? loadFeaturePack("@santi020k/eslint-config-tools/registry") : []
|
|
35
|
+
])).flat();
|
|
19
36
|
const getIntegrationConfigs = async (libraries, tools, testing, formats, extensions) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
'Installed "@santi020k/eslint-config-integrations" is incompatible. Update it to v3 or newer.'
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
return module.getIntegrationConfigs(libraries, tools, testing, formats, extensions);
|
|
37
|
+
const selected = [...libraries, ...tools, ...testing, ...formats, ...extensions];
|
|
38
|
+
if (selected.length === 0) return [];
|
|
39
|
+
const features = await loadSelectedPacks(libraries, tools, testing, formats, extensions);
|
|
40
|
+
return resolveConfigFeatures(features, selected);
|
|
28
41
|
};
|
|
29
42
|
const getPrettierConfig = async (tools) => {
|
|
30
|
-
if (
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
throw new Error(
|
|
34
|
-
'Installed "@santi020k/eslint-config-integrations" is incompatible. Update it to v3 or newer.'
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
return module.getPrettierConfig(tools);
|
|
43
|
+
if (tools.length === 0) return [];
|
|
44
|
+
const features = await loadFeaturePack("@santi020k/eslint-config-tools/registry");
|
|
45
|
+
return resolveConfigFeatures(features, tools, "finalizer");
|
|
38
46
|
};
|
|
39
47
|
export {
|
|
40
48
|
getIntegrationConfigs,
|