@santi020k/eslint-config-basic 3.1.0 → 3.3.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 +54 -0
- package/dist/agent-skill-generator.d.ts +7 -18
- package/dist/agent-skill-generator.js +54 -18
- package/dist/agent-skill-generator.js.map +1 -0
- package/dist/cli-advanced.d.ts +7 -0
- package/dist/cli-advanced.js +74 -15
- package/dist/cli-advanced.js.map +1 -0
- package/dist/cli-migration.js +388 -34
- package/dist/cli-migration.js.map +1 -0
- package/dist/cli-package-manager.d.ts +10 -0
- package/dist/cli-package-manager.js +135 -0
- package/dist/cli-package-manager.js.map +1 -0
- package/dist/cli-preset.d.ts +103 -0
- package/dist/cli-preset.js +562 -0
- package/dist/cli-preset.js.map +1 -0
- package/dist/cli-workflows.js +1 -0
- package/dist/cli-workflows.js.map +1 -0
- package/dist/cli.d.ts +14 -2
- package/dist/cli.js +689 -94
- package/dist/cli.js.map +1 -0
- package/dist/define-config-metadata.d.ts +10 -0
- package/dist/define-config-metadata.js +16 -0
- package/dist/define-config-metadata.js.map +1 -0
- package/dist/frameworks.d.ts +1 -0
- package/dist/frameworks.js +6 -2
- package/dist/frameworks.js.map +1 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +145 -27
- package/dist/index.js.map +1 -0
- package/dist/integrations.js +4 -1
- package/dist/integrations.js.map +1 -0
- package/dist/optional-package-errors.d.ts +3 -0
- package/dist/optional-package-errors.js +15 -0
- package/dist/optional-package-errors.js.map +1 -0
- package/dist/recommended.js +1 -0
- package/dist/recommended.js.map +1 -0
- package/dist/resolvers.js +1 -0
- package/dist/resolvers.js.map +1 -0
- package/dist/tailwind.d.ts +3 -1
- package/dist/tailwind.js +115 -13
- package/dist/tailwind.js.map +1 -0
- package/package.json +20 -19
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { createRequire, findPackageJSON } from "node:module";
|
|
3
|
+
import { dirname, extname, join, relative } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import {
|
|
6
|
+
detectProjectOptions,
|
|
7
|
+
Preset
|
|
8
|
+
} from "@santi020k/eslint-config-core";
|
|
9
|
+
import { defaultCommandRunner } from "./cli-workflows.js";
|
|
10
|
+
import { getDefineConfigMetadata } from "./define-config-metadata.js";
|
|
11
|
+
import { defineConfig } from "./index.js";
|
|
12
|
+
import { isMissingRequestedPackage } from "./optional-package-errors.js";
|
|
13
|
+
import { resolvePreset } from "./resolvers.js";
|
|
14
|
+
const PRESETS = new Set(Object.values(Preset));
|
|
15
|
+
const CONFIG_FILENAMES = [
|
|
16
|
+
"eslint.config.js",
|
|
17
|
+
"eslint.config.mjs",
|
|
18
|
+
"eslint.config.cjs",
|
|
19
|
+
"eslint.config.ts",
|
|
20
|
+
"eslint.config.mts",
|
|
21
|
+
"eslint.config.cts"
|
|
22
|
+
];
|
|
23
|
+
const loadDefineConfigMetadata = async (cwd) => {
|
|
24
|
+
const configPath = CONFIG_FILENAMES.map((name) => join(cwd, name)).find((path) => existsSync(path));
|
|
25
|
+
if (!configPath) return void 0;
|
|
26
|
+
try {
|
|
27
|
+
const loaded = await import(`${pathToFileURL(configPath).href}?basic-eslint-preset=${Date.now()}`);
|
|
28
|
+
return getDefineConfigMetadata(await loaded.default);
|
|
29
|
+
} catch {
|
|
30
|
+
return void 0;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const PRESET_FEATURE_PACKAGES = {
|
|
34
|
+
extensions: "@santi020k/eslint-config-extensions",
|
|
35
|
+
formats: "@santi020k/eslint-config-formats",
|
|
36
|
+
libraries: "@santi020k/eslint-config-libraries",
|
|
37
|
+
testing: "@santi020k/eslint-config-testing",
|
|
38
|
+
tools: "@santi020k/eslint-config-tools"
|
|
39
|
+
};
|
|
40
|
+
const FRAMEWORK_PACKAGES = {
|
|
41
|
+
angular: "@santi020k/eslint-config-angular",
|
|
42
|
+
astro: "@santi020k/eslint-config-astro",
|
|
43
|
+
expo: "@santi020k/eslint-config-expo",
|
|
44
|
+
hono: "@santi020k/eslint-config-hono",
|
|
45
|
+
lit: "@santi020k/eslint-config-lit",
|
|
46
|
+
nest: "@santi020k/eslint-config-nest",
|
|
47
|
+
next: "@santi020k/eslint-config-next",
|
|
48
|
+
nuxt: "@santi020k/eslint-config-nuxt",
|
|
49
|
+
preact: "@santi020k/eslint-config-preact",
|
|
50
|
+
qwik: "@santi020k/eslint-config-qwik",
|
|
51
|
+
react: "@santi020k/eslint-config-react",
|
|
52
|
+
"react-router": "@santi020k/eslint-config-react-router",
|
|
53
|
+
slidev: "@santi020k/eslint-config-slidev",
|
|
54
|
+
solid: "@santi020k/eslint-config-solid",
|
|
55
|
+
svelte: "@santi020k/eslint-config-svelte",
|
|
56
|
+
"tanstack-start": "@santi020k/eslint-config-tanstack-start",
|
|
57
|
+
vite: "@santi020k/eslint-config-vite",
|
|
58
|
+
vue: "@santi020k/eslint-config-vue"
|
|
59
|
+
};
|
|
60
|
+
const FRAMEWORK_PREFIXES = /* @__PURE__ */ new Set([
|
|
61
|
+
"@angular-eslint",
|
|
62
|
+
"@eslint-react",
|
|
63
|
+
"@next/next",
|
|
64
|
+
"astro",
|
|
65
|
+
"lit",
|
|
66
|
+
"qwik",
|
|
67
|
+
"react",
|
|
68
|
+
"react-hooks",
|
|
69
|
+
"react-refresh",
|
|
70
|
+
"solid",
|
|
71
|
+
"svelte",
|
|
72
|
+
"vue"
|
|
73
|
+
]);
|
|
74
|
+
const DOMAIN_PREFIXES = /* @__PURE__ */ new Set([
|
|
75
|
+
"better-tailwindcss",
|
|
76
|
+
"drizzle",
|
|
77
|
+
"graphql-eslint",
|
|
78
|
+
"i18next",
|
|
79
|
+
"prisma",
|
|
80
|
+
"storybook",
|
|
81
|
+
"tailwindcss",
|
|
82
|
+
"tanstack-query",
|
|
83
|
+
"turbo",
|
|
84
|
+
"zod"
|
|
85
|
+
]);
|
|
86
|
+
const FORMAT_PREFIXES = /* @__PURE__ */ new Set([
|
|
87
|
+
"@stylistic",
|
|
88
|
+
"css",
|
|
89
|
+
"html",
|
|
90
|
+
"jsonc",
|
|
91
|
+
"markdown",
|
|
92
|
+
"mdx",
|
|
93
|
+
"prettier",
|
|
94
|
+
"toml",
|
|
95
|
+
"yaml"
|
|
96
|
+
]);
|
|
97
|
+
const MULTI_SEGMENT_RULE_PREFIXES = /* @__PURE__ */ new Set(["@next/next"]);
|
|
98
|
+
const getRulePrefix = (rule) => {
|
|
99
|
+
const segments = rule.split("/");
|
|
100
|
+
if (!rule.startsWith("@")) return segments[0];
|
|
101
|
+
const multiSegmentPrefix = segments.slice(0, 2).join("/");
|
|
102
|
+
return MULTI_SEGMENT_RULE_PREFIXES.has(multiSegmentPrefix) ? multiSegmentPrefix : segments[0];
|
|
103
|
+
};
|
|
104
|
+
const getRuleGroup = (rule) => {
|
|
105
|
+
const prefix = getRulePrefix(rule);
|
|
106
|
+
if (prefix === "security" || prefix === "no-secrets" || rule.includes("security") || rule.includes("no-unsanitized")) return "security";
|
|
107
|
+
if (FRAMEWORK_PREFIXES.has(prefix)) return "framework";
|
|
108
|
+
if (DOMAIN_PREFIXES.has(prefix)) return "domain";
|
|
109
|
+
if (FORMAT_PREFIXES.has(prefix) || rule.includes("format") || rule.includes("spacing")) return "formatting";
|
|
110
|
+
return "correctness";
|
|
111
|
+
};
|
|
112
|
+
const getSeverity = (value) => Array.isArray(value) ? value[0] : value;
|
|
113
|
+
const isEnabled = (value) => {
|
|
114
|
+
const severity = getSeverity(value);
|
|
115
|
+
return severity !== 0 && severity !== "off" && severity !== void 0;
|
|
116
|
+
};
|
|
117
|
+
const normalizeRule = (value) => JSON.stringify(value);
|
|
118
|
+
const loadProjectEslint = (cwd, overrideConfig, fix = false) => {
|
|
119
|
+
const projectRequire = createRequire(join(cwd, "package.json"));
|
|
120
|
+
const eslintModule = projectRequire("eslint");
|
|
121
|
+
if (!eslintModule.ESLint) throw new Error("The installed eslint package does not expose the ESLint API.");
|
|
122
|
+
return new eslintModule.ESLint({
|
|
123
|
+
cwd,
|
|
124
|
+
...fix ? { fix: true } : {},
|
|
125
|
+
...overrideConfig ? { overrideConfig, overrideConfigFile: true } : {}
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
const getResolvablePresetOptions = (cwd, presetOptions) => {
|
|
129
|
+
const projectPackageUrl = pathToFileURL(join(cwd, "package.json"));
|
|
130
|
+
const options = { ...presetOptions };
|
|
131
|
+
const detectedOptions = detectProjectOptions(cwd);
|
|
132
|
+
const missingPackages = /* @__PURE__ */ new Set();
|
|
133
|
+
const detection = options.detection;
|
|
134
|
+
const detectionControls = typeof detection === "object" ? detection : {};
|
|
135
|
+
const detectionEnabled = (category) => detection !== false && detectionControls[category] !== false;
|
|
136
|
+
for (const [category, specifier] of Object.entries(PRESET_FEATURE_PACKAGES)) {
|
|
137
|
+
const categoryKey = category;
|
|
138
|
+
const explicit = options[categoryKey];
|
|
139
|
+
const detected = detectionEnabled(categoryKey) ? detectedOptions[categoryKey] : [];
|
|
140
|
+
const selected = [.../* @__PURE__ */ new Set([
|
|
141
|
+
...Array.isArray(explicit) ? explicit : [],
|
|
142
|
+
...Array.isArray(detected) ? detected : []
|
|
143
|
+
])];
|
|
144
|
+
if (selected.length === 0) continue;
|
|
145
|
+
try {
|
|
146
|
+
findPackageJSON(specifier, projectPackageUrl);
|
|
147
|
+
} catch (error) {
|
|
148
|
+
if (!isMissingRequestedPackage(error, specifier)) throw error;
|
|
149
|
+
Object.assign(options, {
|
|
150
|
+
[category]: [],
|
|
151
|
+
detection: {
|
|
152
|
+
...typeof options.detection === "object" ? options.detection : detectionControls,
|
|
153
|
+
[category]: false
|
|
154
|
+
},
|
|
155
|
+
features: {
|
|
156
|
+
...options.features,
|
|
157
|
+
...Object.fromEntries(selected.map((feature) => [feature, false]))
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
missingPackages.add(specifier);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const frameworkDetectionEnabled = detection !== false && detectionControls.frameworks !== false;
|
|
164
|
+
const detectedFrameworks = frameworkDetectionEnabled ? detectedOptions.detectedFrameworks ?? [] : [];
|
|
165
|
+
const configuredFrameworks = Object.entries(options.frameworks ?? {}).filter((entry) => entry[1] === true).map(([framework]) => framework);
|
|
166
|
+
const selectedFrameworks = [.../* @__PURE__ */ new Set([...detectedFrameworks, ...configuredFrameworks])];
|
|
167
|
+
const resolvableFrameworks = {
|
|
168
|
+
...options.frameworks
|
|
169
|
+
};
|
|
170
|
+
for (const framework of selectedFrameworks) {
|
|
171
|
+
const specifier = FRAMEWORK_PACKAGES[framework];
|
|
172
|
+
try {
|
|
173
|
+
findPackageJSON(specifier, projectPackageUrl);
|
|
174
|
+
resolvableFrameworks[framework] = true;
|
|
175
|
+
} catch (error) {
|
|
176
|
+
if (!isMissingRequestedPackage(error, specifier)) throw error;
|
|
177
|
+
Reflect.deleteProperty(resolvableFrameworks, framework);
|
|
178
|
+
missingPackages.add(specifier);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (!resolvableFrameworks.react) {
|
|
182
|
+
delete resolvableFrameworks.expo;
|
|
183
|
+
delete resolvableFrameworks.next;
|
|
184
|
+
delete resolvableFrameworks["react-router"];
|
|
185
|
+
if (!resolvableFrameworks.solid) delete resolvableFrameworks["tanstack-start"];
|
|
186
|
+
}
|
|
187
|
+
if (!resolvableFrameworks.vue) {
|
|
188
|
+
delete resolvableFrameworks.nuxt;
|
|
189
|
+
delete resolvableFrameworks.slidev;
|
|
190
|
+
}
|
|
191
|
+
if (selectedFrameworks.length > 0) {
|
|
192
|
+
options.autoFrameworks = false;
|
|
193
|
+
options.frameworks = resolvableFrameworks;
|
|
194
|
+
}
|
|
195
|
+
return { missingPackages: [...missingPackages], options };
|
|
196
|
+
};
|
|
197
|
+
const createCompatibilityConfig = (preset, addedRules, changedRules) => [
|
|
198
|
+
`// Temporary compatibility override generated for Preset.${preset.charAt(0).toUpperCase()}${preset.slice(1)}.`,
|
|
199
|
+
"// Remove entries as the project adopts the preset findings.",
|
|
200
|
+
"export default {",
|
|
201
|
+
` name: 'eslint-config-basic/preset-${preset}-compatibility',`,
|
|
202
|
+
" rules: {",
|
|
203
|
+
...Object.keys(addedRules).sort().map((rule) => ` ${JSON.stringify(rule)}: 'off',`),
|
|
204
|
+
...Object.keys(changedRules).sort().map((rule) => ` ${JSON.stringify(rule)}: ${JSON.stringify(changedRules[rule].from)},`),
|
|
205
|
+
" },",
|
|
206
|
+
"}",
|
|
207
|
+
""
|
|
208
|
+
].join("\n");
|
|
209
|
+
const createFindingSummary = () => ({
|
|
210
|
+
errors: 0,
|
|
211
|
+
fixable: 0,
|
|
212
|
+
total: 0,
|
|
213
|
+
warnings: 0
|
|
214
|
+
});
|
|
215
|
+
const addFinding = (summaries, key, message) => {
|
|
216
|
+
const summary = summaries[key] ?? createFindingSummary();
|
|
217
|
+
summary.total++;
|
|
218
|
+
if (message.severity === 2) summary.errors++;
|
|
219
|
+
else summary.warnings++;
|
|
220
|
+
if (message.fix !== void 0) summary.fixable++;
|
|
221
|
+
summaries[key] = summary;
|
|
222
|
+
};
|
|
223
|
+
const estimateChangedLines = (before, after) => {
|
|
224
|
+
const beforeLines = before.split("\n");
|
|
225
|
+
const afterLines = after.split("\n");
|
|
226
|
+
const comparableLines = Math.min(beforeLines.length, afterLines.length);
|
|
227
|
+
let changed = Math.abs(beforeLines.length - afterLines.length);
|
|
228
|
+
for (let index = 0; index < comparableLines; index++) {
|
|
229
|
+
if (beforeLines[index] !== afterLines[index]) changed++;
|
|
230
|
+
}
|
|
231
|
+
return changed;
|
|
232
|
+
};
|
|
233
|
+
const readOriginalSource = (filePath) => {
|
|
234
|
+
try {
|
|
235
|
+
return readFileSync(filePath, "utf8");
|
|
236
|
+
} catch {
|
|
237
|
+
return void 0;
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
const TYPESCRIPT_CONFIG_FILENAMES = [
|
|
241
|
+
"tsconfig.json",
|
|
242
|
+
"tsconfig.base.json",
|
|
243
|
+
"tsconfig.app.json",
|
|
244
|
+
"tsconfig.node.json",
|
|
245
|
+
"tsconfig.eslint.json"
|
|
246
|
+
];
|
|
247
|
+
const TYPESCRIPT_ROOT_DIAGNOSTIC_CODES = /* @__PURE__ */ new Set([
|
|
248
|
+
"TS2307",
|
|
249
|
+
"TS2688",
|
|
250
|
+
"TS2792",
|
|
251
|
+
"TS6053"
|
|
252
|
+
]);
|
|
253
|
+
const resolveTypeScriptCli = (cwd) => {
|
|
254
|
+
try {
|
|
255
|
+
const projectRequire = createRequire(join(cwd, "package.json"));
|
|
256
|
+
const packagePath = projectRequire.resolve("typescript/package.json");
|
|
257
|
+
const manifest = JSON.parse(readFileSync(packagePath, "utf8"));
|
|
258
|
+
const bin = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.tsc;
|
|
259
|
+
return bin ? join(dirname(packagePath), bin) : null;
|
|
260
|
+
} catch {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
const getTypeScriptConfigs = (cwd, configuredProjects) => {
|
|
265
|
+
const detectedProjects = Object.keys(detectProjectOptions(cwd).projects ?? {});
|
|
266
|
+
const projectRoots = [.../* @__PURE__ */ new Set([...detectedProjects, ...configuredProjects])];
|
|
267
|
+
const roots = [
|
|
268
|
+
cwd,
|
|
269
|
+
...projectRoots.map((project) => join(cwd, project))
|
|
270
|
+
];
|
|
271
|
+
return [...new Set(roots.flatMap((root) => {
|
|
272
|
+
const config = TYPESCRIPT_CONFIG_FILENAMES.find((file) => existsSync(join(root, file)));
|
|
273
|
+
return config ? [join(root, config)] : [];
|
|
274
|
+
}))];
|
|
275
|
+
};
|
|
276
|
+
const parseTypeScriptDiagnostics = (cwd, config, output) => output.split(/\r?\n/).flatMap((line) => {
|
|
277
|
+
const match = /\berror (TS\d+):\s*(.+)$/.exec(line);
|
|
278
|
+
if (!match) return [];
|
|
279
|
+
return [{
|
|
280
|
+
code: match[1],
|
|
281
|
+
config: relative(cwd, config),
|
|
282
|
+
message: match[2]
|
|
283
|
+
}];
|
|
284
|
+
});
|
|
285
|
+
const createTypeScriptPreflight = (cwd, configuredProjects = [], runner = defaultCommandRunner) => {
|
|
286
|
+
const executable = resolveTypeScriptCli(cwd);
|
|
287
|
+
const configs = getTypeScriptConfigs(cwd, configuredProjects);
|
|
288
|
+
if (!executable || configs.length === 0) {
|
|
289
|
+
return {
|
|
290
|
+
configs: [],
|
|
291
|
+
diagnosticCount: 0,
|
|
292
|
+
rootDiagnostics: [],
|
|
293
|
+
status: "skipped"
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
const diagnostics = [];
|
|
297
|
+
const results = configs.map((config) => {
|
|
298
|
+
const result = runner(process.execPath, [
|
|
299
|
+
executable,
|
|
300
|
+
"--noEmit",
|
|
301
|
+
"--pretty",
|
|
302
|
+
"false",
|
|
303
|
+
"--project",
|
|
304
|
+
config
|
|
305
|
+
], cwd);
|
|
306
|
+
diagnostics.push(...parseTypeScriptDiagnostics(
|
|
307
|
+
cwd,
|
|
308
|
+
config,
|
|
309
|
+
`${result.stdout}
|
|
310
|
+
${result.stderr}`
|
|
311
|
+
));
|
|
312
|
+
return {
|
|
313
|
+
config: relative(cwd, config),
|
|
314
|
+
status: result.status
|
|
315
|
+
};
|
|
316
|
+
});
|
|
317
|
+
const rootDiagnostics = diagnostics.filter(
|
|
318
|
+
(diagnostic) => TYPESCRIPT_ROOT_DIAGNOSTIC_CODES.has(diagnostic.code)
|
|
319
|
+
);
|
|
320
|
+
return {
|
|
321
|
+
configs: results,
|
|
322
|
+
diagnosticCount: diagnostics.length,
|
|
323
|
+
rootDiagnostics: (rootDiagnostics.length > 0 ? rootDiagnostics : diagnostics).slice(0, 20),
|
|
324
|
+
status: results.some((result) => result.status !== 0) ? "failed" : "passed"
|
|
325
|
+
};
|
|
326
|
+
};
|
|
327
|
+
const analyzePresetSource = async (cwd, selectedConfig, sourceFiles, configuredProjects, typescriptRunner) => {
|
|
328
|
+
const lintTargets = sourceFiles.length > 0 ? sourceFiles : ["."];
|
|
329
|
+
const lintResults = await loadProjectEslint(cwd, selectedConfig).lintFiles(lintTargets);
|
|
330
|
+
const previewResults = await loadProjectEslint(cwd, selectedConfig, true).lintFiles(lintTargets);
|
|
331
|
+
const byCategory = {};
|
|
332
|
+
const byFileType = {};
|
|
333
|
+
const byRule = {};
|
|
334
|
+
const nonFormattingErrorRules = /* @__PURE__ */ new Set();
|
|
335
|
+
let nonFormattingErrors = 0;
|
|
336
|
+
for (const result of lintResults) {
|
|
337
|
+
const fileType = extname(result.filePath) || "[no extension]";
|
|
338
|
+
for (const message of result.messages) {
|
|
339
|
+
const rule = message.ruleId ?? (message.fatal ? "[fatal]" : "[unknown]");
|
|
340
|
+
const category = message.ruleId ? getRuleGroup(message.ruleId) : "correctness";
|
|
341
|
+
addFinding(byCategory, category, message);
|
|
342
|
+
addFinding(byFileType, fileType, message);
|
|
343
|
+
addFinding(byRule, rule, message);
|
|
344
|
+
if (message.severity === 2 && category !== "formatting") {
|
|
345
|
+
nonFormattingErrors++;
|
|
346
|
+
nonFormattingErrorRules.add(rule);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const changedFiles = [];
|
|
351
|
+
const remainingFixableRules = /* @__PURE__ */ new Set();
|
|
352
|
+
let estimatedChangedLines = 0;
|
|
353
|
+
let remainingErrors = 0;
|
|
354
|
+
let remainingWarnings = 0;
|
|
355
|
+
for (const result of previewResults) {
|
|
356
|
+
remainingErrors += result.errorCount;
|
|
357
|
+
remainingWarnings += result.warningCount;
|
|
358
|
+
for (const message of result.messages) {
|
|
359
|
+
if (message.fix !== void 0) remainingFixableRules.add(message.ruleId ?? "[fatal]");
|
|
360
|
+
}
|
|
361
|
+
if (result.output === void 0) continue;
|
|
362
|
+
changedFiles.push(relative(cwd, result.filePath));
|
|
363
|
+
const original = readOriginalSource(result.filePath);
|
|
364
|
+
if (original !== void 0) estimatedChangedLines += estimateChangedLines(original, result.output);
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
autofixPreview: {
|
|
368
|
+
changedFileCount: changedFiles.length,
|
|
369
|
+
changedFiles: changedFiles.sort(),
|
|
370
|
+
estimatedChangedLines,
|
|
371
|
+
remainingErrors,
|
|
372
|
+
remainingFixableRules: [...remainingFixableRules].sort(),
|
|
373
|
+
remainingWarnings
|
|
374
|
+
},
|
|
375
|
+
byCategory,
|
|
376
|
+
byFileType,
|
|
377
|
+
byRule,
|
|
378
|
+
lintTargets,
|
|
379
|
+
nonFormattingErrors: {
|
|
380
|
+
count: nonFormattingErrors,
|
|
381
|
+
rules: [...nonFormattingErrorRules].sort()
|
|
382
|
+
},
|
|
383
|
+
typescriptPreflight: createTypeScriptPreflight(cwd, configuredProjects, typescriptRunner),
|
|
384
|
+
totals: {
|
|
385
|
+
errors: lintResults.reduce((total, result) => total + result.errorCount, 0),
|
|
386
|
+
files: lintResults.length,
|
|
387
|
+
findings: lintResults.reduce(
|
|
388
|
+
(total, result) => total + result.errorCount + result.warningCount,
|
|
389
|
+
0
|
|
390
|
+
),
|
|
391
|
+
warnings: lintResults.reduce((total, result) => total + result.warningCount, 0)
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
};
|
|
395
|
+
const formatSourceAnalysis = (analysis) => {
|
|
396
|
+
if (!analysis) {
|
|
397
|
+
return [
|
|
398
|
+
"",
|
|
399
|
+
"Pass --analyze-source to lint with the selected preset and preview autofix without writing files."
|
|
400
|
+
];
|
|
401
|
+
}
|
|
402
|
+
const nonFormattingRuleSuffix = analysis.nonFormattingErrors.rules.length > 0 ? ` (${analysis.nonFormattingErrors.rules.join(", ")})` : "";
|
|
403
|
+
const remainingFixableRules = analysis.autofixPreview.remainingFixableRules.length > 0 ? analysis.autofixPreview.remainingFixableRules.join(", ") : "none";
|
|
404
|
+
const typescriptLines = analysis.typescriptPreflight.status === "failed" ? [
|
|
405
|
+
`- TypeScript preflight: failed with ${analysis.typescriptPreflight.diagnosticCount} diagnostics`,
|
|
406
|
+
...analysis.typescriptPreflight.rootDiagnostics.map((diagnostic) => ` - ${diagnostic.config} ${diagnostic.code}: ${diagnostic.message}`),
|
|
407
|
+
"- Fix TypeScript compiler errors before reviewing cascading type-aware unsafe-rule findings."
|
|
408
|
+
] : [
|
|
409
|
+
`- TypeScript preflight: ${analysis.typescriptPreflight.status}` + (analysis.typescriptPreflight.status === "passed" ? ` (${analysis.typescriptPreflight.configs.length} configs)` : " (TypeScript or a supported tsconfig was not found)")
|
|
410
|
+
];
|
|
411
|
+
return [
|
|
412
|
+
"",
|
|
413
|
+
"Source analysis (selected preset, no files written):",
|
|
414
|
+
`- Lint targets: ${analysis.lintTargets.join(", ")}`,
|
|
415
|
+
`- Files analyzed: ${analysis.totals.files}`,
|
|
416
|
+
`- Findings: ${analysis.totals.findings} (${analysis.totals.errors} errors, ${analysis.totals.warnings} warnings)`,
|
|
417
|
+
`- Non-formatting errors to resolve first: ${analysis.nonFormattingErrors.count}${nonFormattingRuleSuffix}`,
|
|
418
|
+
`- Autofix preview: ${analysis.autofixPreview.changedFileCount} files, about ${analysis.autofixPreview.estimatedChangedLines} changed lines`,
|
|
419
|
+
`- Findings remaining after preview: ${analysis.autofixPreview.remainingErrors} errors, ${analysis.autofixPreview.remainingWarnings} warnings`,
|
|
420
|
+
`- Fixable rules still remaining: ${remainingFixableRules}`,
|
|
421
|
+
...typescriptLines
|
|
422
|
+
];
|
|
423
|
+
};
|
|
424
|
+
const formatCompatibilityGuidance = (compatibilityFile) => {
|
|
425
|
+
if (compatibilityFile) {
|
|
426
|
+
return [
|
|
427
|
+
"",
|
|
428
|
+
`Compatibility override written to ${compatibilityFile}. Import it after the preset config.`,
|
|
429
|
+
"It preserves the current effective configuration, not existing source violations."
|
|
430
|
+
];
|
|
431
|
+
}
|
|
432
|
+
return [
|
|
433
|
+
"",
|
|
434
|
+
"Pass --compatibility to write a temporary override that disables newly enabled rules.",
|
|
435
|
+
"Compatibility output preserves effective configuration, not current source behavior."
|
|
436
|
+
];
|
|
437
|
+
};
|
|
438
|
+
const createPresetReport = async (cwd, presetName, file = "eslint.config.js", options = {}) => {
|
|
439
|
+
const normalizedPreset = presetName.toLowerCase();
|
|
440
|
+
if (!PRESETS.has(normalizedPreset)) {
|
|
441
|
+
throw new Error(
|
|
442
|
+
`Unknown preset "${presetName}". Use one of: ${[...PRESETS].sort().join(", ")}.`
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
const preset = normalizedPreset;
|
|
446
|
+
const presetOptions = resolvePreset(preset);
|
|
447
|
+
const current = await loadProjectEslint(cwd).calculateConfigForFile(file);
|
|
448
|
+
const currentMetadata = await loadDefineConfigMetadata(cwd);
|
|
449
|
+
const currentOptions = currentMetadata?.options ?? {};
|
|
450
|
+
const targetOptions = {
|
|
451
|
+
...presetOptions,
|
|
452
|
+
...currentOptions,
|
|
453
|
+
features: {
|
|
454
|
+
...presetOptions.features,
|
|
455
|
+
...currentOptions.features
|
|
456
|
+
},
|
|
457
|
+
frameworks: {
|
|
458
|
+
...presetOptions.frameworks,
|
|
459
|
+
...currentOptions.frameworks
|
|
460
|
+
},
|
|
461
|
+
preset,
|
|
462
|
+
root: currentOptions.root ?? cwd
|
|
463
|
+
};
|
|
464
|
+
const { missingPackages, options: resolvablePresetOptions } = getResolvablePresetOptions(cwd, targetOptions);
|
|
465
|
+
if (!current) {
|
|
466
|
+
throw new Error(`ESLint did not calculate a current configuration for ${file}. Check that the file is not ignored.`);
|
|
467
|
+
}
|
|
468
|
+
const selectedConfig = await defineConfig(
|
|
469
|
+
resolvablePresetOptions,
|
|
470
|
+
...currentMetadata?.extraConfigs ?? []
|
|
471
|
+
);
|
|
472
|
+
const selected = await loadProjectEslint(cwd, selectedConfig).calculateConfigForFile(file);
|
|
473
|
+
if (!selected) {
|
|
474
|
+
throw new Error(`The ${normalizedPreset} preset did not produce a configuration for ${file}.`);
|
|
475
|
+
}
|
|
476
|
+
const currentRules = current.rules ?? {};
|
|
477
|
+
const selectedRules = selected.rules ?? {};
|
|
478
|
+
const added = {};
|
|
479
|
+
const changed = {};
|
|
480
|
+
const removed = {};
|
|
481
|
+
for (const [rule, value] of Object.entries(selectedRules)) {
|
|
482
|
+
const currentValue = currentRules[rule];
|
|
483
|
+
if (isEnabled(value) && !isEnabled(currentValue)) {
|
|
484
|
+
added[rule] = value;
|
|
485
|
+
} else if (isEnabled(value) && isEnabled(currentValue) && normalizeRule(value) !== normalizeRule(currentValue)) {
|
|
486
|
+
changed[rule] = { from: currentValue, to: value };
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
for (const [rule, value] of Object.entries(currentRules)) {
|
|
490
|
+
if (isEnabled(value) && !isEnabled(selectedRules[rule])) removed[rule] = value;
|
|
491
|
+
}
|
|
492
|
+
const groups = Object.fromEntries(
|
|
493
|
+
["formatting", "correctness", "security", "framework", "domain"].map((group) => [
|
|
494
|
+
group,
|
|
495
|
+
Object.keys(added).filter((rule) => getRuleGroup(rule) === group).sort()
|
|
496
|
+
])
|
|
497
|
+
);
|
|
498
|
+
const sourceAnalysis = options.analyzeSource ? await analyzePresetSource(
|
|
499
|
+
cwd,
|
|
500
|
+
selectedConfig,
|
|
501
|
+
options.sourceFiles ?? [],
|
|
502
|
+
Object.keys(resolvablePresetOptions.projects ?? {}),
|
|
503
|
+
options.typescriptRunner ?? defaultCommandRunner
|
|
504
|
+
) : null;
|
|
505
|
+
return {
|
|
506
|
+
added,
|
|
507
|
+
changed,
|
|
508
|
+
compatibilityScope: "effective-config",
|
|
509
|
+
file,
|
|
510
|
+
groups,
|
|
511
|
+
missingPackages,
|
|
512
|
+
preset: normalizedPreset,
|
|
513
|
+
presetOptions,
|
|
514
|
+
removed,
|
|
515
|
+
sourceAnalysis,
|
|
516
|
+
totals: {
|
|
517
|
+
added: Object.keys(added).length,
|
|
518
|
+
changed: Object.keys(changed).length,
|
|
519
|
+
removed: Object.keys(removed).length
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
};
|
|
523
|
+
const handleExplainPreset = async (cwd = process.cwd(), preset, options = {}) => {
|
|
524
|
+
const report = await createPresetReport(cwd, preset, options.file, {
|
|
525
|
+
analyzeSource: options.analyzeSource,
|
|
526
|
+
sourceFiles: options.files
|
|
527
|
+
});
|
|
528
|
+
let compatibilityFile = null;
|
|
529
|
+
if (options.compatibility) {
|
|
530
|
+
const output = options.output ?? `.eslint-preset-${report.preset}-compat.mjs`;
|
|
531
|
+
const outputPath = join(cwd, output);
|
|
532
|
+
if (existsSync(outputPath)) {
|
|
533
|
+
throw new Error(`${output} already exists; remove it or choose another path with --output.`);
|
|
534
|
+
}
|
|
535
|
+
writeFileSync(outputPath, createCompatibilityConfig(report.preset, report.added, report.changed));
|
|
536
|
+
compatibilityFile = relative(cwd, outputPath);
|
|
537
|
+
}
|
|
538
|
+
const payload = { ...report, compatibilityFile };
|
|
539
|
+
if (options.json) {
|
|
540
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
console.log([
|
|
544
|
+
`Preset adoption report: ${report.preset}`,
|
|
545
|
+
`- Representative file: ${report.file}`,
|
|
546
|
+
"- Config comparison: effective rules and options",
|
|
547
|
+
`- Newly enabled rules: ${report.totals.added}`,
|
|
548
|
+
`- Changed rule options: ${report.totals.changed}`,
|
|
549
|
+
`- Rules no longer enabled: ${report.totals.removed}`,
|
|
550
|
+
`- Optional packs not installed (excluded from comparison): ${report.missingPackages.length > 0 ? report.missingPackages.join(", ") : "none"}`,
|
|
551
|
+
"",
|
|
552
|
+
...Object.entries(report.groups).map(([group, rules]) => `- ${group}: ${rules.length}${rules.length > 0 ? ` (${rules.join(", ")})` : ""}`),
|
|
553
|
+
...formatSourceAnalysis(report.sourceAnalysis),
|
|
554
|
+
...formatCompatibilityGuidance(compatibilityFile)
|
|
555
|
+
].join("\n"));
|
|
556
|
+
};
|
|
557
|
+
export {
|
|
558
|
+
createPresetReport,
|
|
559
|
+
createTypeScriptPreflight,
|
|
560
|
+
handleExplainPreset
|
|
561
|
+
};
|
|
562
|
+
//# sourceMappingURL=cli-preset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-preset.ts"],"sourcesContent":["/* eslint-disable no-console -- CLI handlers own user-facing terminal output */\n/* eslint-disable complexity -- report comparison and formatting intentionally cover multiple result branches */\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { createRequire, findPackageJSON } from 'node:module'\nimport { dirname, extname, join, relative } from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nimport {\n type DetectedFrameworkName,\n detectProjectOptions,\n type EslintConfigOptions,\n Preset\n} from '@santi020k/eslint-config-core'\n\nimport { type CommandRunner, defaultCommandRunner } from './cli-workflows.js'\nimport { type DefineConfigMetadata, getDefineConfigMetadata } from './define-config-metadata.js'\nimport { defineConfig } from './index.js'\nimport { isMissingRequestedPackage } from './optional-package-errors.js'\nimport { resolvePreset } from './resolvers.js'\n\ninterface EffectiveConfig {\n rules?: Partial<Record<string, unknown>>\n}\n\ninterface ProjectLintMessage {\n fatal?: boolean\n fix?: unknown\n ruleId: null | string\n severity: number\n}\n\ninterface ProjectLintResult {\n errorCount: number\n filePath: string\n messages: ProjectLintMessage[]\n output?: string\n warningCount: number\n}\n\ninterface ProjectEslint {\n calculateConfigForFile: (filePath: string) => Promise<EffectiveConfig | null>\n lintFiles: (patterns: string[]) => Promise<ProjectLintResult[]>\n}\n\ntype ProjectEslintConstructor = new(options: {\n cwd: string\n fix?: boolean\n overrideConfig?: unknown\n overrideConfigFile?: boolean\n}) => ProjectEslint\n\nexport interface ExplainPresetOptions {\n analyzeSource?: boolean\n compatibility?: boolean\n file?: string\n files?: string[]\n json?: boolean\n output?: string\n}\n\ninterface CreatePresetReportOptions {\n analyzeSource?: boolean\n sourceFiles?: string[]\n typescriptRunner?: CommandRunner\n}\n\nconst PRESETS = new Set<string>(Object.values(Preset))\n\nconst CONFIG_FILENAMES = [\n 'eslint.config.js',\n 'eslint.config.mjs',\n 'eslint.config.cjs',\n 'eslint.config.ts',\n 'eslint.config.mts',\n 'eslint.config.cts'\n]\n\nconst loadDefineConfigMetadata = async (cwd: string): Promise<DefineConfigMetadata | undefined> => {\n const configPath = CONFIG_FILENAMES.map(name => join(cwd, name)).find(path => existsSync(path))\n\n if (!configPath) return undefined\n\n try {\n const loaded = await import(`${pathToFileURL(configPath).href}?basic-eslint-preset=${Date.now()}`) as {\n default?: unknown\n }\n\n return getDefineConfigMetadata(await loaded.default)\n } catch {\n return undefined\n }\n}\n\nconst PRESET_FEATURE_PACKAGES = {\n extensions: '@santi020k/eslint-config-extensions',\n formats: '@santi020k/eslint-config-formats',\n libraries: '@santi020k/eslint-config-libraries',\n testing: '@santi020k/eslint-config-testing',\n tools: '@santi020k/eslint-config-tools'\n} as const\n\nconst FRAMEWORK_PACKAGES: Record<DetectedFrameworkName, string> = {\n angular: '@santi020k/eslint-config-angular',\n astro: '@santi020k/eslint-config-astro',\n expo: '@santi020k/eslint-config-expo',\n hono: '@santi020k/eslint-config-hono',\n lit: '@santi020k/eslint-config-lit',\n nest: '@santi020k/eslint-config-nest',\n next: '@santi020k/eslint-config-next',\n nuxt: '@santi020k/eslint-config-nuxt',\n preact: '@santi020k/eslint-config-preact',\n qwik: '@santi020k/eslint-config-qwik',\n react: '@santi020k/eslint-config-react',\n 'react-router': '@santi020k/eslint-config-react-router',\n slidev: '@santi020k/eslint-config-slidev',\n solid: '@santi020k/eslint-config-solid',\n svelte: '@santi020k/eslint-config-svelte',\n 'tanstack-start': '@santi020k/eslint-config-tanstack-start',\n vite: '@santi020k/eslint-config-vite',\n vue: '@santi020k/eslint-config-vue'\n}\n\nconst FRAMEWORK_PREFIXES = new Set([\n '@angular-eslint',\n '@eslint-react',\n '@next/next',\n 'astro',\n 'lit',\n 'qwik',\n 'react',\n 'react-hooks',\n 'react-refresh',\n 'solid',\n 'svelte',\n 'vue'\n])\n\nconst DOMAIN_PREFIXES = new Set([\n 'better-tailwindcss',\n 'drizzle',\n 'graphql-eslint',\n 'i18next',\n 'prisma',\n 'storybook',\n 'tailwindcss',\n 'tanstack-query',\n 'turbo',\n 'zod'\n])\n\nconst FORMAT_PREFIXES = new Set([\n '@stylistic',\n 'css',\n 'html',\n 'jsonc',\n 'markdown',\n 'mdx',\n 'prettier',\n 'toml',\n 'yaml'\n])\n\nconst MULTI_SEGMENT_RULE_PREFIXES = new Set(['@next/next'])\n\nconst getRulePrefix = (rule: string): string => {\n const segments = rule.split('/')\n\n if (!rule.startsWith('@')) return segments[0]\n\n const multiSegmentPrefix = segments.slice(0, 2).join('/')\n\n return MULTI_SEGMENT_RULE_PREFIXES.has(multiSegmentPrefix) ? multiSegmentPrefix : segments[0]\n}\n\nconst getRuleGroup = (rule: string): 'correctness' | 'domain' | 'formatting' | 'framework' | 'security' => {\n const prefix = getRulePrefix(rule)\n\n if (\n prefix === 'security' ||\n prefix === 'no-secrets' ||\n rule.includes('security') ||\n rule.includes('no-unsanitized')\n ) return 'security'\n\n if (FRAMEWORK_PREFIXES.has(prefix)) return 'framework'\n\n if (DOMAIN_PREFIXES.has(prefix)) return 'domain'\n\n if (FORMAT_PREFIXES.has(prefix) || rule.includes('format') || rule.includes('spacing')) return 'formatting'\n\n return 'correctness'\n}\n\nconst getSeverity = (value: unknown): unknown => Array.isArray(value) ? value[0] : value\n\nconst isEnabled = (value: unknown): boolean => {\n const severity = getSeverity(value)\n\n return severity !== 0 && severity !== 'off' && severity !== undefined\n}\n\nconst normalizeRule = (value: unknown): string => JSON.stringify(value)\n\nconst loadProjectEslint = (\n cwd: string,\n overrideConfig?: unknown,\n fix = false\n): ProjectEslint => {\n const projectRequire = createRequire(join(cwd, 'package.json'))\n const eslintModule = projectRequire('eslint') as { ESLint?: ProjectEslintConstructor }\n\n if (!eslintModule.ESLint) throw new Error('The installed eslint package does not expose the ESLint API.')\n\n return new eslintModule.ESLint({\n cwd,\n ...(fix ? { fix: true } : {}),\n ...(overrideConfig ? { overrideConfig, overrideConfigFile: true } : {})\n })\n}\n\nconst getResolvablePresetOptions = (\n cwd: string,\n presetOptions: Partial<EslintConfigOptions>\n): { missingPackages: string[], options: Partial<EslintConfigOptions> } => {\n const projectPackageUrl = pathToFileURL(join(cwd, 'package.json'))\n const options = { ...presetOptions }\n const detectedOptions = detectProjectOptions(cwd)\n const missingPackages = new Set<string>()\n const detection = options.detection\n const detectionControls = typeof detection === 'object' ? detection : {}\n\n const detectionEnabled = (category: keyof typeof PRESET_FEATURE_PACKAGES): boolean => (\n detection !== false && detectionControls[category] !== false\n )\n\n for (const [category, specifier] of Object.entries(PRESET_FEATURE_PACKAGES)) {\n const categoryKey = category as keyof typeof PRESET_FEATURE_PACKAGES\n const explicit = options[categoryKey]\n const detected = detectionEnabled(categoryKey) ? detectedOptions[categoryKey] : []\n\n const selected = [...new Set([\n ...(Array.isArray(explicit) ? explicit : []),\n ...(Array.isArray(detected) ? detected : [])\n ])]\n\n if (selected.length === 0) continue\n\n try {\n findPackageJSON(specifier, projectPackageUrl)\n } catch (error) {\n if (!isMissingRequestedPackage(error, specifier)) throw error\n\n Object.assign(options, {\n [category]: [],\n detection: {\n ...(typeof options.detection === 'object' ? options.detection : detectionControls),\n [category]: false\n },\n features: {\n ...options.features,\n ...Object.fromEntries(selected.map(feature => [feature, false]))\n }\n })\n\n missingPackages.add(specifier)\n }\n }\n\n const frameworkDetectionEnabled = detection !== false && detectionControls.frameworks !== false\n const detectedFrameworks = frameworkDetectionEnabled ? detectedOptions.detectedFrameworks ?? [] : []\n\n const configuredFrameworks = Object.entries(options.frameworks ?? {})\n .filter((entry): entry is [DetectedFrameworkName, true] => entry[1] === true)\n .map(([framework]) => framework)\n\n const selectedFrameworks = [...new Set([...detectedFrameworks, ...configuredFrameworks])]\n\n const resolvableFrameworks: NonNullable<EslintConfigOptions['frameworks']> = {\n ...options.frameworks\n }\n\n for (const framework of selectedFrameworks) {\n const specifier = FRAMEWORK_PACKAGES[framework]\n\n try {\n findPackageJSON(specifier, projectPackageUrl)\n\n resolvableFrameworks[framework] = true\n } catch (error) {\n if (!isMissingRequestedPackage(error, specifier)) throw error\n\n Reflect.deleteProperty(resolvableFrameworks, framework)\n\n missingPackages.add(specifier)\n }\n }\n\n if (!resolvableFrameworks.react) {\n delete resolvableFrameworks.expo\n\n delete resolvableFrameworks.next\n\n delete resolvableFrameworks['react-router']\n\n if (!resolvableFrameworks.solid) delete resolvableFrameworks['tanstack-start']\n }\n\n if (!resolvableFrameworks.vue) {\n delete resolvableFrameworks.nuxt\n\n delete resolvableFrameworks.slidev\n }\n\n if (selectedFrameworks.length > 0) {\n options.autoFrameworks = false\n\n options.frameworks = resolvableFrameworks\n }\n\n return { missingPackages: [...missingPackages], options }\n}\n\nconst createCompatibilityConfig = (\n preset: string,\n addedRules: Record<string, unknown>,\n changedRules: Record<string, { from: unknown, to: unknown }>\n): string => [\n `// Temporary compatibility override generated for Preset.${preset.charAt(0).toUpperCase()}${preset.slice(1)}.`,\n '// Remove entries as the project adopts the preset findings.',\n 'export default {',\n ` name: 'eslint-config-basic/preset-${preset}-compatibility',`,\n ' rules: {',\n ...Object.keys(addedRules).sort().map(rule => ` ${JSON.stringify(rule)}: 'off',`),\n ...Object.keys(changedRules).sort().map(rule => (\n ` ${JSON.stringify(rule)}: ${JSON.stringify(changedRules[rule].from)},`\n )),\n ' },',\n '}',\n ''\n].join('\\n')\n\ninterface FindingSummary {\n errors: number\n fixable: number\n total: number\n warnings: number\n}\n\nconst createFindingSummary = (): FindingSummary => ({\n errors: 0,\n fixable: 0,\n total: 0,\n warnings: 0\n})\n\nconst addFinding = (\n summaries: Record<string, FindingSummary>,\n key: string,\n message: ProjectLintMessage\n): void => {\n const summary = summaries[key] ?? createFindingSummary()\n\n summary.total++\n\n if (message.severity === 2) summary.errors++\n else summary.warnings++\n\n if (message.fix !== undefined) summary.fixable++\n\n summaries[key] = summary\n}\n\nconst estimateChangedLines = (before: string, after: string): number => {\n const beforeLines = before.split('\\n')\n const afterLines = after.split('\\n')\n const comparableLines = Math.min(beforeLines.length, afterLines.length)\n let changed = Math.abs(beforeLines.length - afterLines.length)\n\n for (let index = 0; index < comparableLines; index++) {\n if (beforeLines[index] !== afterLines[index]) changed++\n }\n\n return changed\n}\n\nconst readOriginalSource = (filePath: string): string | undefined => {\n try {\n return readFileSync(filePath, 'utf8')\n } catch {\n return undefined\n }\n}\n\nconst TYPESCRIPT_CONFIG_FILENAMES = [\n 'tsconfig.json',\n 'tsconfig.base.json',\n 'tsconfig.app.json',\n 'tsconfig.node.json',\n 'tsconfig.eslint.json'\n]\n\nconst TYPESCRIPT_ROOT_DIAGNOSTIC_CODES = new Set([\n 'TS2307',\n 'TS2688',\n 'TS2792',\n 'TS6053'\n])\n\nconst resolveTypeScriptCli = (cwd: string): null | string => {\n try {\n const projectRequire = createRequire(join(cwd, 'package.json'))\n const packagePath = projectRequire.resolve('typescript/package.json')\n\n const manifest = JSON.parse(readFileSync(packagePath, 'utf8')) as {\n bin?: Record<string, string> | string\n }\n\n const bin = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin?.tsc\n\n return bin ? join(dirname(packagePath), bin) : null\n } catch {\n return null\n }\n}\n\nconst getTypeScriptConfigs = (\n cwd: string,\n configuredProjects: string[]\n): string[] => {\n const detectedProjects = Object.keys(detectProjectOptions(cwd).projects ?? {})\n const projectRoots = [...new Set([...detectedProjects, ...configuredProjects])]\n\n const roots = [\n cwd,\n ...projectRoots.map(project => join(cwd, project))\n ]\n\n return [...new Set(roots.flatMap(root => {\n const config = TYPESCRIPT_CONFIG_FILENAMES.find(file => existsSync(join(root, file)))\n\n return config ? [join(root, config)] : []\n }))]\n}\n\ninterface TypeScriptDiagnostic {\n code: string\n config: string\n message: string\n}\n\nconst parseTypeScriptDiagnostics = (\n cwd: string,\n config: string,\n output: string\n): TypeScriptDiagnostic[] => output\n .split(/\\r?\\n/)\n .flatMap(line => {\n const match = /\\berror (TS\\d+):\\s*(.+)$/.exec(line)\n\n if (!match) return []\n\n return [{\n code: match[1],\n config: relative(cwd, config),\n message: match[2]\n }]\n })\n\nexport const createTypeScriptPreflight = (\n cwd: string,\n configuredProjects: string[] = [],\n runner: CommandRunner = defaultCommandRunner\n) => {\n const executable = resolveTypeScriptCli(cwd)\n const configs = getTypeScriptConfigs(cwd, configuredProjects)\n\n if (!executable || configs.length === 0) {\n return {\n configs: [],\n diagnosticCount: 0,\n rootDiagnostics: [] as TypeScriptDiagnostic[],\n status: 'skipped' as const\n }\n }\n\n const diagnostics: TypeScriptDiagnostic[] = []\n\n const results = configs.map(config => {\n const result = runner(process.execPath, [\n executable,\n '--noEmit',\n '--pretty',\n 'false',\n '--project',\n config\n ], cwd)\n\n diagnostics.push(...parseTypeScriptDiagnostics(\n cwd,\n config,\n `${result.stdout}\\n${result.stderr}`\n ))\n\n return {\n config: relative(cwd, config),\n status: result.status\n }\n })\n\n const rootDiagnostics = diagnostics.filter(\n diagnostic => TYPESCRIPT_ROOT_DIAGNOSTIC_CODES.has(diagnostic.code)\n )\n\n return {\n configs: results,\n diagnosticCount: diagnostics.length,\n rootDiagnostics: (rootDiagnostics.length > 0 ? rootDiagnostics : diagnostics).slice(0, 20),\n status: results.some(result => result.status !== 0) ? 'failed' as const : 'passed' as const\n }\n}\n\nconst analyzePresetSource = async (\n cwd: string,\n selectedConfig: unknown,\n sourceFiles: string[],\n configuredProjects: string[],\n typescriptRunner: CommandRunner\n) => {\n const lintTargets = sourceFiles.length > 0 ? sourceFiles : ['.']\n const lintResults = await loadProjectEslint(cwd, selectedConfig).lintFiles(lintTargets)\n const previewResults = await loadProjectEslint(cwd, selectedConfig, true).lintFiles(lintTargets)\n const byCategory: Record<string, FindingSummary> = {}\n const byFileType: Record<string, FindingSummary> = {}\n const byRule: Record<string, FindingSummary> = {}\n const nonFormattingErrorRules = new Set<string>()\n let nonFormattingErrors = 0\n\n for (const result of lintResults) {\n const fileType = extname(result.filePath) || '[no extension]'\n\n for (const message of result.messages) {\n const rule = message.ruleId ?? (message.fatal ? '[fatal]' : '[unknown]')\n const category = message.ruleId ? getRuleGroup(message.ruleId) : 'correctness'\n\n addFinding(byCategory, category, message)\n\n addFinding(byFileType, fileType, message)\n\n addFinding(byRule, rule, message)\n\n if (message.severity === 2 && category !== 'formatting') {\n nonFormattingErrors++\n\n nonFormattingErrorRules.add(rule)\n }\n }\n }\n\n const changedFiles: string[] = []\n const remainingFixableRules = new Set<string>()\n let estimatedChangedLines = 0\n let remainingErrors = 0\n let remainingWarnings = 0\n\n for (const result of previewResults) {\n remainingErrors += result.errorCount\n\n remainingWarnings += result.warningCount\n\n for (const message of result.messages) {\n if (message.fix !== undefined) remainingFixableRules.add(message.ruleId ?? '[fatal]')\n }\n\n if (result.output === undefined) continue\n\n changedFiles.push(relative(cwd, result.filePath))\n\n const original = readOriginalSource(result.filePath)\n\n if (original !== undefined) estimatedChangedLines += estimateChangedLines(original, result.output)\n }\n\n return {\n autofixPreview: {\n changedFileCount: changedFiles.length,\n changedFiles: changedFiles.sort(),\n estimatedChangedLines,\n remainingErrors,\n remainingFixableRules: [...remainingFixableRules].sort(),\n remainingWarnings\n },\n byCategory,\n byFileType,\n byRule,\n lintTargets,\n nonFormattingErrors: {\n count: nonFormattingErrors,\n rules: [...nonFormattingErrorRules].sort()\n },\n typescriptPreflight: createTypeScriptPreflight(cwd, configuredProjects, typescriptRunner),\n totals: {\n errors: lintResults.reduce((total, result) => total + result.errorCount, 0),\n files: lintResults.length,\n findings: lintResults.reduce(\n (total, result) => total + result.errorCount + result.warningCount,\n 0\n ),\n warnings: lintResults.reduce((total, result) => total + result.warningCount, 0)\n }\n }\n}\n\ntype PresetSourceAnalysis = Awaited<ReturnType<typeof analyzePresetSource>>\n\nconst formatSourceAnalysis = (\n analysis: null | PresetSourceAnalysis\n): string[] => {\n if (!analysis) {\n return [\n '',\n 'Pass --analyze-source to lint with the selected preset and preview autofix without writing files.'\n ]\n }\n\n const nonFormattingRuleSuffix = analysis.nonFormattingErrors.rules.length > 0 ?\n ` (${analysis.nonFormattingErrors.rules.join(', ')})` :\n ''\n\n const remainingFixableRules = analysis.autofixPreview.remainingFixableRules.length > 0 ?\n analysis.autofixPreview.remainingFixableRules.join(', ') :\n 'none'\n\n const typescriptLines = analysis.typescriptPreflight.status === 'failed' ?\n [\n `- TypeScript preflight: failed with ${analysis.typescriptPreflight.diagnosticCount} diagnostics`,\n ...analysis.typescriptPreflight.rootDiagnostics.map(diagnostic => (\n ` - ${diagnostic.config} ${diagnostic.code}: ${diagnostic.message}`\n )),\n '- Fix TypeScript compiler errors before reviewing cascading type-aware unsafe-rule findings.'\n ] :\n [\n `- TypeScript preflight: ${analysis.typescriptPreflight.status}` +\n (analysis.typescriptPreflight.status === 'passed' ?\n ` (${analysis.typescriptPreflight.configs.length} configs)` :\n ' (TypeScript or a supported tsconfig was not found)')\n ]\n\n return [\n '',\n 'Source analysis (selected preset, no files written):',\n `- Lint targets: ${analysis.lintTargets.join(', ')}`,\n `- Files analyzed: ${analysis.totals.files}`,\n `- Findings: ${analysis.totals.findings} ` +\n `(${analysis.totals.errors} errors, ${analysis.totals.warnings} warnings)`,\n `- Non-formatting errors to resolve first: ${analysis.nonFormattingErrors.count}${nonFormattingRuleSuffix}`,\n `- Autofix preview: ${analysis.autofixPreview.changedFileCount} files, ` +\n `about ${analysis.autofixPreview.estimatedChangedLines} changed lines`,\n `- Findings remaining after preview: ${analysis.autofixPreview.remainingErrors} errors, ` +\n `${analysis.autofixPreview.remainingWarnings} warnings`,\n `- Fixable rules still remaining: ${remainingFixableRules}`,\n ...typescriptLines\n ]\n}\n\nconst formatCompatibilityGuidance = (\n compatibilityFile: null | string\n): string[] => {\n if (compatibilityFile) {\n return [\n '',\n `Compatibility override written to ${compatibilityFile}. Import it after the preset config.`,\n 'It preserves the current effective configuration, not existing source violations.'\n ]\n }\n\n return [\n '',\n 'Pass --compatibility to write a temporary override that disables newly enabled rules.',\n 'Compatibility output preserves effective configuration, not current source behavior.'\n ]\n}\n\nexport const createPresetReport = async (\n cwd: string,\n presetName: string,\n file = 'eslint.config.js',\n options: CreatePresetReportOptions = {}\n) => {\n const normalizedPreset = presetName.toLowerCase()\n\n if (!PRESETS.has(normalizedPreset)) {\n throw new Error(\n `Unknown preset \"${presetName}\". Use one of: ${[...PRESETS].sort().join(', ')}.`\n )\n }\n\n const preset = normalizedPreset as Preset\n const presetOptions = resolvePreset(preset)\n const current = await loadProjectEslint(cwd).calculateConfigForFile(file)\n const currentMetadata = await loadDefineConfigMetadata(cwd)\n const currentOptions = currentMetadata?.options ?? {}\n\n const targetOptions = {\n ...presetOptions,\n ...currentOptions,\n features: {\n ...presetOptions.features,\n ...currentOptions.features\n },\n frameworks: {\n ...presetOptions.frameworks,\n ...currentOptions.frameworks\n },\n preset,\n root: currentOptions.root ?? cwd\n }\n\n const { missingPackages, options: resolvablePresetOptions } = getResolvablePresetOptions(cwd, targetOptions)\n\n if (!current) {\n throw new Error(`ESLint did not calculate a current configuration for ${file}. Check that the file is not ignored.`)\n }\n\n const selectedConfig = await defineConfig(\n resolvablePresetOptions,\n ...(currentMetadata?.extraConfigs ?? [])\n )\n\n const selected = await loadProjectEslint(cwd, selectedConfig).calculateConfigForFile(file)\n\n if (!selected) {\n throw new Error(`The ${normalizedPreset} preset did not produce a configuration for ${file}.`)\n }\n\n const currentRules = current.rules ?? {}\n const selectedRules = selected.rules ?? {}\n const added: Record<string, unknown> = {}\n const changed: Record<string, { from: unknown, to: unknown }> = {}\n const removed: Record<string, unknown> = {}\n\n for (const [rule, value] of Object.entries(selectedRules)) {\n const currentValue = currentRules[rule]\n\n if (isEnabled(value) && !isEnabled(currentValue)) {\n added[rule] = value\n } else if (\n isEnabled(value) &&\n isEnabled(currentValue) &&\n normalizeRule(value) !== normalizeRule(currentValue)\n ) {\n changed[rule] = { from: currentValue, to: value }\n }\n }\n\n for (const [rule, value] of Object.entries(currentRules)) {\n if (isEnabled(value) && !isEnabled(selectedRules[rule])) removed[rule] = value\n }\n\n const groups = Object.fromEntries(\n ['formatting', 'correctness', 'security', 'framework', 'domain'].map(group => [\n group,\n Object.keys(added).filter(rule => getRuleGroup(rule) === group).sort()\n ])\n )\n\n const sourceAnalysis = options.analyzeSource ?\n await analyzePresetSource(\n cwd,\n selectedConfig,\n options.sourceFiles ?? [],\n Object.keys(resolvablePresetOptions.projects ?? {}),\n options.typescriptRunner ?? defaultCommandRunner\n ) :\n null\n\n return {\n added,\n changed,\n compatibilityScope: 'effective-config',\n file,\n groups,\n missingPackages,\n preset: normalizedPreset,\n presetOptions,\n removed,\n sourceAnalysis,\n totals: {\n added: Object.keys(added).length,\n changed: Object.keys(changed).length,\n removed: Object.keys(removed).length\n }\n }\n}\n\nexport const handleExplainPreset = async (\n cwd: string = process.cwd(),\n preset: string,\n options: ExplainPresetOptions = {}\n): Promise<void> => {\n const report = await createPresetReport(cwd, preset, options.file, {\n analyzeSource: options.analyzeSource,\n sourceFiles: options.files\n })\n\n let compatibilityFile: null | string = null\n\n if (options.compatibility) {\n const output = options.output ?? `.eslint-preset-${report.preset}-compat.mjs`\n const outputPath = join(cwd, output)\n\n if (existsSync(outputPath)) {\n throw new Error(`${output} already exists; remove it or choose another path with --output.`)\n }\n\n writeFileSync(outputPath, createCompatibilityConfig(report.preset, report.added, report.changed))\n\n compatibilityFile = relative(cwd, outputPath)\n }\n\n const payload = { ...report, compatibilityFile }\n\n if (options.json) {\n console.log(JSON.stringify(payload, null, 2))\n\n return\n }\n\n console.log([\n `Preset adoption report: ${report.preset}`,\n `- Representative file: ${report.file}`,\n '- Config comparison: effective rules and options',\n `- Newly enabled rules: ${report.totals.added}`,\n `- Changed rule options: ${report.totals.changed}`,\n `- Rules no longer enabled: ${report.totals.removed}`,\n `- Optional packs not installed (excluded from comparison): ${report.missingPackages.length > 0 ? report.missingPackages.join(', ') : 'none'}`,\n '',\n ...Object.entries(report.groups).map(([group, rules]) => (\n `- ${group}: ${rules.length}${rules.length > 0 ? ` (${rules.join(', ')})` : ''}`\n )),\n ...formatSourceAnalysis(report.sourceAnalysis),\n ...formatCompatibilityGuidance(compatibilityFile)\n ].join('\\n'))\n}\n"],"mappings":"AAEA,SAAS,YAAY,cAAc,qBAAqB;AACxD,SAAS,eAAe,uBAAuB;AAC/C,SAAS,SAAS,SAAS,MAAM,gBAAgB;AACjD,SAAS,qBAAqB;AAE9B;AAAA,EAEE;AAAA,EAEA;AAAA,OACK;AAEP,SAA6B,4BAA4B;AACzD,SAAoC,+BAA+B;AACnE,SAAS,oBAAoB;AAC7B,SAAS,iCAAiC;AAC1C,SAAS,qBAAqB;AAgD9B,MAAM,UAAU,IAAI,IAAY,OAAO,OAAO,MAAM,CAAC;AAErD,MAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,2BAA2B,OAAO,QAA2D;AACjG,QAAM,aAAa,iBAAiB,IAAI,UAAQ,KAAK,KAAK,IAAI,CAAC,EAAE,KAAK,UAAQ,WAAW,IAAI,CAAC;AAE9F,MAAI,CAAC,WAAY,QAAO;AAExB,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,GAAG,cAAc,UAAU,EAAE,IAAI,wBAAwB,KAAK,IAAI,CAAC;AAI/F,WAAO,wBAAwB,MAAM,OAAO,OAAO;AAAA,EACrD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,MAAM,0BAA0B;AAAA,EAC9B,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,WAAW;AAAA,EACX,SAAS;AAAA,EACT,OAAO;AACT;AAEA,MAAM,qBAA4D;AAAA,EAChE,SAAS;AAAA,EACT,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,MAAM;AAAA,EACN,KAAK;AACP;AAEA,MAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,MAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,MAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,MAAM,8BAA8B,oBAAI,IAAI,CAAC,YAAY,CAAC;AAE1D,MAAM,gBAAgB,CAAC,SAAyB;AAC9C,QAAM,WAAW,KAAK,MAAM,GAAG;AAE/B,MAAI,CAAC,KAAK,WAAW,GAAG,EAAG,QAAO,SAAS,CAAC;AAE5C,QAAM,qBAAqB,SAAS,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG;AAExD,SAAO,4BAA4B,IAAI,kBAAkB,IAAI,qBAAqB,SAAS,CAAC;AAC9F;AAEA,MAAM,eAAe,CAAC,SAAqF;AACzG,QAAM,SAAS,cAAc,IAAI;AAEjC,MACE,WAAW,cACX,WAAW,gBACX,KAAK,SAAS,UAAU,KACxB,KAAK,SAAS,gBAAgB,EAC9B,QAAO;AAET,MAAI,mBAAmB,IAAI,MAAM,EAAG,QAAO;AAE3C,MAAI,gBAAgB,IAAI,MAAM,EAAG,QAAO;AAExC,MAAI,gBAAgB,IAAI,MAAM,KAAK,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,SAAS,EAAG,QAAO;AAE/F,SAAO;AACT;AAEA,MAAM,cAAc,CAAC,UAA4B,MAAM,QAAQ,KAAK,IAAI,MAAM,CAAC,IAAI;AAEnF,MAAM,YAAY,CAAC,UAA4B;AAC7C,QAAM,WAAW,YAAY,KAAK;AAElC,SAAO,aAAa,KAAK,aAAa,SAAS,aAAa;AAC9D;AAEA,MAAM,gBAAgB,CAAC,UAA2B,KAAK,UAAU,KAAK;AAEtE,MAAM,oBAAoB,CACxB,KACA,gBACA,MAAM,UACY;AAClB,QAAM,iBAAiB,cAAc,KAAK,KAAK,cAAc,CAAC;AAC9D,QAAM,eAAe,eAAe,QAAQ;AAE5C,MAAI,CAAC,aAAa,OAAQ,OAAM,IAAI,MAAM,8DAA8D;AAExG,SAAO,IAAI,aAAa,OAAO;AAAA,IAC7B;AAAA,IACA,GAAI,MAAM,EAAE,KAAK,KAAK,IAAI,CAAC;AAAA,IAC3B,GAAI,iBAAiB,EAAE,gBAAgB,oBAAoB,KAAK,IAAI,CAAC;AAAA,EACvE,CAAC;AACH;AAEA,MAAM,6BAA6B,CACjC,KACA,kBACyE;AACzE,QAAM,oBAAoB,cAAc,KAAK,KAAK,cAAc,CAAC;AACjE,QAAM,UAAU,EAAE,GAAG,cAAc;AACnC,QAAM,kBAAkB,qBAAqB,GAAG;AAChD,QAAM,kBAAkB,oBAAI,IAAY;AACxC,QAAM,YAAY,QAAQ;AAC1B,QAAM,oBAAoB,OAAO,cAAc,WAAW,YAAY,CAAC;AAEvE,QAAM,mBAAmB,CAAC,aACxB,cAAc,SAAS,kBAAkB,QAAQ,MAAM;AAGzD,aAAW,CAAC,UAAU,SAAS,KAAK,OAAO,QAAQ,uBAAuB,GAAG;AAC3E,UAAM,cAAc;AACpB,UAAM,WAAW,QAAQ,WAAW;AACpC,UAAM,WAAW,iBAAiB,WAAW,IAAI,gBAAgB,WAAW,IAAI,CAAC;AAEjF,UAAM,WAAW,CAAC,GAAG,oBAAI,IAAI;AAAA,MAC3B,GAAI,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC;AAAA,MAC1C,GAAI,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC;AAAA,IAC5C,CAAC,CAAC;AAEF,QAAI,SAAS,WAAW,EAAG;AAE3B,QAAI;AACF,sBAAgB,WAAW,iBAAiB;AAAA,IAC9C,SAAS,OAAO;AACd,UAAI,CAAC,0BAA0B,OAAO,SAAS,EAAG,OAAM;AAExD,aAAO,OAAO,SAAS;AAAA,QACrB,CAAC,QAAQ,GAAG,CAAC;AAAA,QACb,WAAW;AAAA,UACT,GAAI,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY;AAAA,UAChE,CAAC,QAAQ,GAAG;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,GAAG,QAAQ;AAAA,UACX,GAAG,OAAO,YAAY,SAAS,IAAI,aAAW,CAAC,SAAS,KAAK,CAAC,CAAC;AAAA,QACjE;AAAA,MACF,CAAC;AAED,sBAAgB,IAAI,SAAS;AAAA,IAC/B;AAAA,EACF;AAEA,QAAM,4BAA4B,cAAc,SAAS,kBAAkB,eAAe;AAC1F,QAAM,qBAAqB,4BAA4B,gBAAgB,sBAAsB,CAAC,IAAI,CAAC;AAEnG,QAAM,uBAAuB,OAAO,QAAQ,QAAQ,cAAc,CAAC,CAAC,EACjE,OAAO,CAAC,UAAkD,MAAM,CAAC,MAAM,IAAI,EAC3E,IAAI,CAAC,CAAC,SAAS,MAAM,SAAS;AAEjC,QAAM,qBAAqB,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,oBAAoB,GAAG,oBAAoB,CAAC,CAAC;AAExF,QAAM,uBAAuE;AAAA,IAC3E,GAAG,QAAQ;AAAA,EACb;AAEA,aAAW,aAAa,oBAAoB;AAC1C,UAAM,YAAY,mBAAmB,SAAS;AAE9C,QAAI;AACF,sBAAgB,WAAW,iBAAiB;AAE5C,2BAAqB,SAAS,IAAI;AAAA,IACpC,SAAS,OAAO;AACd,UAAI,CAAC,0BAA0B,OAAO,SAAS,EAAG,OAAM;AAExD,cAAQ,eAAe,sBAAsB,SAAS;AAEtD,sBAAgB,IAAI,SAAS;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,CAAC,qBAAqB,OAAO;AAC/B,WAAO,qBAAqB;AAE5B,WAAO,qBAAqB;AAE5B,WAAO,qBAAqB,cAAc;AAE1C,QAAI,CAAC,qBAAqB,MAAO,QAAO,qBAAqB,gBAAgB;AAAA,EAC/E;AAEA,MAAI,CAAC,qBAAqB,KAAK;AAC7B,WAAO,qBAAqB;AAE5B,WAAO,qBAAqB;AAAA,EAC9B;AAEA,MAAI,mBAAmB,SAAS,GAAG;AACjC,YAAQ,iBAAiB;AAEzB,YAAQ,aAAa;AAAA,EACvB;AAEA,SAAO,EAAE,iBAAiB,CAAC,GAAG,eAAe,GAAG,QAAQ;AAC1D;AAEA,MAAM,4BAA4B,CAChC,QACA,YACA,iBACW;AAAA,EACX,4DAA4D,OAAO,OAAO,CAAC,EAAE,YAAY,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC;AAAA,EAC5G;AAAA,EACA;AAAA,EACA,uCAAuC,MAAM;AAAA,EAC7C;AAAA,EACA,GAAG,OAAO,KAAK,UAAU,EAAE,KAAK,EAAE,IAAI,UAAQ,OAAO,KAAK,UAAU,IAAI,CAAC,UAAU;AAAA,EACnF,GAAG,OAAO,KAAK,YAAY,EAAE,KAAK,EAAE,IAAI,UACtC,OAAO,KAAK,UAAU,IAAI,CAAC,KAAK,KAAK,UAAU,aAAa,IAAI,EAAE,IAAI,CAAC,GACxE;AAAA,EACD;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AASX,MAAM,uBAAuB,OAAuB;AAAA,EAClD,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,OAAO;AAAA,EACP,UAAU;AACZ;AAEA,MAAM,aAAa,CACjB,WACA,KACA,YACS;AACT,QAAM,UAAU,UAAU,GAAG,KAAK,qBAAqB;AAEvD,UAAQ;AAER,MAAI,QAAQ,aAAa,EAAG,SAAQ;AAAA,MAC/B,SAAQ;AAEb,MAAI,QAAQ,QAAQ,OAAW,SAAQ;AAEvC,YAAU,GAAG,IAAI;AACnB;AAEA,MAAM,uBAAuB,CAAC,QAAgB,UAA0B;AACtE,QAAM,cAAc,OAAO,MAAM,IAAI;AACrC,QAAM,aAAa,MAAM,MAAM,IAAI;AACnC,QAAM,kBAAkB,KAAK,IAAI,YAAY,QAAQ,WAAW,MAAM;AACtE,MAAI,UAAU,KAAK,IAAI,YAAY,SAAS,WAAW,MAAM;AAE7D,WAAS,QAAQ,GAAG,QAAQ,iBAAiB,SAAS;AACpD,QAAI,YAAY,KAAK,MAAM,WAAW,KAAK,EAAG;AAAA,EAChD;AAEA,SAAO;AACT;AAEA,MAAM,qBAAqB,CAAC,aAAyC;AACnE,MAAI;AACF,WAAO,aAAa,UAAU,MAAM;AAAA,EACtC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,MAAM,8BAA8B;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,mCAAmC,oBAAI,IAAI;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,MAAM,uBAAuB,CAAC,QAA+B;AAC3D,MAAI;AACF,UAAM,iBAAiB,cAAc,KAAK,KAAK,cAAc,CAAC;AAC9D,UAAM,cAAc,eAAe,QAAQ,yBAAyB;AAEpE,UAAM,WAAW,KAAK,MAAM,aAAa,aAAa,MAAM,CAAC;AAI7D,UAAM,MAAM,OAAO,SAAS,QAAQ,WAAW,SAAS,MAAM,SAAS,KAAK;AAE5E,WAAO,MAAM,KAAK,QAAQ,WAAW,GAAG,GAAG,IAAI;AAAA,EACjD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,MAAM,uBAAuB,CAC3B,KACA,uBACa;AACb,QAAM,mBAAmB,OAAO,KAAK,qBAAqB,GAAG,EAAE,YAAY,CAAC,CAAC;AAC7E,QAAM,eAAe,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,kBAAkB,GAAG,kBAAkB,CAAC,CAAC;AAE9E,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,GAAG,aAAa,IAAI,aAAW,KAAK,KAAK,OAAO,CAAC;AAAA,EACnD;AAEA,SAAO,CAAC,GAAG,IAAI,IAAI,MAAM,QAAQ,UAAQ;AACvC,UAAM,SAAS,4BAA4B,KAAK,UAAQ,WAAW,KAAK,MAAM,IAAI,CAAC,CAAC;AAEpF,WAAO,SAAS,CAAC,KAAK,MAAM,MAAM,CAAC,IAAI,CAAC;AAAA,EAC1C,CAAC,CAAC,CAAC;AACL;AAQA,MAAM,6BAA6B,CACjC,KACA,QACA,WAC2B,OAC1B,MAAM,OAAO,EACb,QAAQ,UAAQ;AACf,QAAM,QAAQ,2BAA2B,KAAK,IAAI;AAElD,MAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,SAAO,CAAC;AAAA,IACN,MAAM,MAAM,CAAC;AAAA,IACb,QAAQ,SAAS,KAAK,MAAM;AAAA,IAC5B,SAAS,MAAM,CAAC;AAAA,EAClB,CAAC;AACH,CAAC;AAEI,MAAM,4BAA4B,CACvC,KACA,qBAA+B,CAAC,GAChC,SAAwB,yBACrB;AACH,QAAM,aAAa,qBAAqB,GAAG;AAC3C,QAAM,UAAU,qBAAqB,KAAK,kBAAkB;AAE5D,MAAI,CAAC,cAAc,QAAQ,WAAW,GAAG;AACvC,WAAO;AAAA,MACL,SAAS,CAAC;AAAA,MACV,iBAAiB;AAAA,MACjB,iBAAiB,CAAC;AAAA,MAClB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,cAAsC,CAAC;AAE7C,QAAM,UAAU,QAAQ,IAAI,YAAU;AACpC,UAAM,SAAS,OAAO,QAAQ,UAAU;AAAA,MACtC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,GAAG,GAAG;AAEN,gBAAY,KAAK,GAAG;AAAA,MAClB;AAAA,MACA;AAAA,MACA,GAAG,OAAO,MAAM;AAAA,EAAK,OAAO,MAAM;AAAA,IACpC,CAAC;AAED,WAAO;AAAA,MACL,QAAQ,SAAS,KAAK,MAAM;AAAA,MAC5B,QAAQ,OAAO;AAAA,IACjB;AAAA,EACF,CAAC;AAED,QAAM,kBAAkB,YAAY;AAAA,IAClC,gBAAc,iCAAiC,IAAI,WAAW,IAAI;AAAA,EACpE;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,iBAAiB,YAAY;AAAA,IAC7B,kBAAkB,gBAAgB,SAAS,IAAI,kBAAkB,aAAa,MAAM,GAAG,EAAE;AAAA,IACzF,QAAQ,QAAQ,KAAK,YAAU,OAAO,WAAW,CAAC,IAAI,WAAoB;AAAA,EAC5E;AACF;AAEA,MAAM,sBAAsB,OAC1B,KACA,gBACA,aACA,oBACA,qBACG;AACH,QAAM,cAAc,YAAY,SAAS,IAAI,cAAc,CAAC,GAAG;AAC/D,QAAM,cAAc,MAAM,kBAAkB,KAAK,cAAc,EAAE,UAAU,WAAW;AACtF,QAAM,iBAAiB,MAAM,kBAAkB,KAAK,gBAAgB,IAAI,EAAE,UAAU,WAAW;AAC/F,QAAM,aAA6C,CAAC;AACpD,QAAM,aAA6C,CAAC;AACpD,QAAM,SAAyC,CAAC;AAChD,QAAM,0BAA0B,oBAAI,IAAY;AAChD,MAAI,sBAAsB;AAE1B,aAAW,UAAU,aAAa;AAChC,UAAM,WAAW,QAAQ,OAAO,QAAQ,KAAK;AAE7C,eAAW,WAAW,OAAO,UAAU;AACrC,YAAM,OAAO,QAAQ,WAAW,QAAQ,QAAQ,YAAY;AAC5D,YAAM,WAAW,QAAQ,SAAS,aAAa,QAAQ,MAAM,IAAI;AAEjE,iBAAW,YAAY,UAAU,OAAO;AAExC,iBAAW,YAAY,UAAU,OAAO;AAExC,iBAAW,QAAQ,MAAM,OAAO;AAEhC,UAAI,QAAQ,aAAa,KAAK,aAAa,cAAc;AACvD;AAEA,gCAAwB,IAAI,IAAI;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAyB,CAAC;AAChC,QAAM,wBAAwB,oBAAI,IAAY;AAC9C,MAAI,wBAAwB;AAC5B,MAAI,kBAAkB;AACtB,MAAI,oBAAoB;AAExB,aAAW,UAAU,gBAAgB;AACnC,uBAAmB,OAAO;AAE1B,yBAAqB,OAAO;AAE5B,eAAW,WAAW,OAAO,UAAU;AACrC,UAAI,QAAQ,QAAQ,OAAW,uBAAsB,IAAI,QAAQ,UAAU,SAAS;AAAA,IACtF;AAEA,QAAI,OAAO,WAAW,OAAW;AAEjC,iBAAa,KAAK,SAAS,KAAK,OAAO,QAAQ,CAAC;AAEhD,UAAM,WAAW,mBAAmB,OAAO,QAAQ;AAEnD,QAAI,aAAa,OAAW,0BAAyB,qBAAqB,UAAU,OAAO,MAAM;AAAA,EACnG;AAEA,SAAO;AAAA,IACL,gBAAgB;AAAA,MACd,kBAAkB,aAAa;AAAA,MAC/B,cAAc,aAAa,KAAK;AAAA,MAChC;AAAA,MACA;AAAA,MACA,uBAAuB,CAAC,GAAG,qBAAqB,EAAE,KAAK;AAAA,MACvD;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB;AAAA,MACnB,OAAO;AAAA,MACP,OAAO,CAAC,GAAG,uBAAuB,EAAE,KAAK;AAAA,IAC3C;AAAA,IACA,qBAAqB,0BAA0B,KAAK,oBAAoB,gBAAgB;AAAA,IACxF,QAAQ;AAAA,MACN,QAAQ,YAAY,OAAO,CAAC,OAAO,WAAW,QAAQ,OAAO,YAAY,CAAC;AAAA,MAC1E,OAAO,YAAY;AAAA,MACnB,UAAU,YAAY;AAAA,QACpB,CAAC,OAAO,WAAW,QAAQ,OAAO,aAAa,OAAO;AAAA,QACtD;AAAA,MACF;AAAA,MACA,UAAU,YAAY,OAAO,CAAC,OAAO,WAAW,QAAQ,OAAO,cAAc,CAAC;AAAA,IAChF;AAAA,EACF;AACF;AAIA,MAAM,uBAAuB,CAC3B,aACa;AACb,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,0BAA0B,SAAS,oBAAoB,MAAM,SAAS,IAC1E,KAAK,SAAS,oBAAoB,MAAM,KAAK,IAAI,CAAC,MAClD;AAEF,QAAM,wBAAwB,SAAS,eAAe,sBAAsB,SAAS,IACnF,SAAS,eAAe,sBAAsB,KAAK,IAAI,IACvD;AAEF,QAAM,kBAAkB,SAAS,oBAAoB,WAAW,WAC9D;AAAA,IACE,uCAAuC,SAAS,oBAAoB,eAAe;AAAA,IACnF,GAAG,SAAS,oBAAoB,gBAAgB,IAAI,gBAClD,OAAO,WAAW,MAAM,IAAI,WAAW,IAAI,KAAK,WAAW,OAAO,EACnE;AAAA,IACD;AAAA,EACF,IACA;AAAA,IACE,2BAA2B,SAAS,oBAAoB,MAAM,MAC7D,SAAS,oBAAoB,WAAW,WACvC,KAAK,SAAS,oBAAoB,QAAQ,MAAM,cAChD;AAAA,EACJ;AAEF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,mBAAmB,SAAS,YAAY,KAAK,IAAI,CAAC;AAAA,IAClD,qBAAqB,SAAS,OAAO,KAAK;AAAA,IAC1C,eAAe,SAAS,OAAO,QAAQ,KACnC,SAAS,OAAO,MAAM,YAAY,SAAS,OAAO,QAAQ;AAAA,IAC9D,6CAA6C,SAAS,oBAAoB,KAAK,GAAG,uBAAuB;AAAA,IACzG,sBAAsB,SAAS,eAAe,gBAAgB,iBACrD,SAAS,eAAe,qBAAqB;AAAA,IACtD,uCAAuC,SAAS,eAAe,eAAe,YAC3E,SAAS,eAAe,iBAAiB;AAAA,IAC5C,oCAAoC,qBAAqB;AAAA,IACzD,GAAG;AAAA,EACL;AACF;AAEA,MAAM,8BAA8B,CAClC,sBACa;AACb,MAAI,mBAAmB;AACrB,WAAO;AAAA,MACL;AAAA,MACA,qCAAqC,iBAAiB;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,qBAAqB,OAChC,KACA,YACA,OAAO,oBACP,UAAqC,CAAC,MACnC;AACH,QAAM,mBAAmB,WAAW,YAAY;AAEhD,MAAI,CAAC,QAAQ,IAAI,gBAAgB,GAAG;AAClC,UAAM,IAAI;AAAA,MACR,mBAAmB,UAAU,kBAAkB,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;AAAA,IAC/E;AAAA,EACF;AAEA,QAAM,SAAS;AACf,QAAM,gBAAgB,cAAc,MAAM;AAC1C,QAAM,UAAU,MAAM,kBAAkB,GAAG,EAAE,uBAAuB,IAAI;AACxE,QAAM,kBAAkB,MAAM,yBAAyB,GAAG;AAC1D,QAAM,iBAAiB,iBAAiB,WAAW,CAAC;AAEpD,QAAM,gBAAgB;AAAA,IACpB,GAAG;AAAA,IACH,GAAG;AAAA,IACH,UAAU;AAAA,MACR,GAAG,cAAc;AAAA,MACjB,GAAG,eAAe;AAAA,IACpB;AAAA,IACA,YAAY;AAAA,MACV,GAAG,cAAc;AAAA,MACjB,GAAG,eAAe;AAAA,IACpB;AAAA,IACA;AAAA,IACA,MAAM,eAAe,QAAQ;AAAA,EAC/B;AAEA,QAAM,EAAE,iBAAiB,SAAS,wBAAwB,IAAI,2BAA2B,KAAK,aAAa;AAE3G,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,wDAAwD,IAAI,uCAAuC;AAAA,EACrH;AAEA,QAAM,iBAAiB,MAAM;AAAA,IAC3B;AAAA,IACA,GAAI,iBAAiB,gBAAgB,CAAC;AAAA,EACxC;AAEA,QAAM,WAAW,MAAM,kBAAkB,KAAK,cAAc,EAAE,uBAAuB,IAAI;AAEzF,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,OAAO,gBAAgB,+CAA+C,IAAI,GAAG;AAAA,EAC/F;AAEA,QAAM,eAAe,QAAQ,SAAS,CAAC;AACvC,QAAM,gBAAgB,SAAS,SAAS,CAAC;AACzC,QAAM,QAAiC,CAAC;AACxC,QAAM,UAA0D,CAAC;AACjE,QAAM,UAAmC,CAAC;AAE1C,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,aAAa,GAAG;AACzD,UAAM,eAAe,aAAa,IAAI;AAEtC,QAAI,UAAU,KAAK,KAAK,CAAC,UAAU,YAAY,GAAG;AAChD,YAAM,IAAI,IAAI;AAAA,IAChB,WACE,UAAU,KAAK,KACf,UAAU,YAAY,KACtB,cAAc,KAAK,MAAM,cAAc,YAAY,GACnD;AACA,cAAQ,IAAI,IAAI,EAAE,MAAM,cAAc,IAAI,MAAM;AAAA,IAClD;AAAA,EACF;AAEA,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACxD,QAAI,UAAU,KAAK,KAAK,CAAC,UAAU,cAAc,IAAI,CAAC,EAAG,SAAQ,IAAI,IAAI;AAAA,EAC3E;AAEA,QAAM,SAAS,OAAO;AAAA,IACpB,CAAC,cAAc,eAAe,YAAY,aAAa,QAAQ,EAAE,IAAI,WAAS;AAAA,MAC5E;AAAA,MACA,OAAO,KAAK,KAAK,EAAE,OAAO,UAAQ,aAAa,IAAI,MAAM,KAAK,EAAE,KAAK;AAAA,IACvE,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB,QAAQ,gBAC7B,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,QAAQ,eAAe,CAAC;AAAA,IACxB,OAAO,KAAK,wBAAwB,YAAY,CAAC,CAAC;AAAA,IAClD,QAAQ,oBAAoB;AAAA,EAC9B,IACA;AAEF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,MACN,OAAO,OAAO,KAAK,KAAK,EAAE;AAAA,MAC1B,SAAS,OAAO,KAAK,OAAO,EAAE;AAAA,MAC9B,SAAS,OAAO,KAAK,OAAO,EAAE;AAAA,IAChC;AAAA,EACF;AACF;AAEO,MAAM,sBAAsB,OACjC,MAAc,QAAQ,IAAI,GAC1B,QACA,UAAgC,CAAC,MACf;AAClB,QAAM,SAAS,MAAM,mBAAmB,KAAK,QAAQ,QAAQ,MAAM;AAAA,IACjE,eAAe,QAAQ;AAAA,IACvB,aAAa,QAAQ;AAAA,EACvB,CAAC;AAED,MAAI,oBAAmC;AAEvC,MAAI,QAAQ,eAAe;AACzB,UAAM,SAAS,QAAQ,UAAU,kBAAkB,OAAO,MAAM;AAChE,UAAM,aAAa,KAAK,KAAK,MAAM;AAEnC,QAAI,WAAW,UAAU,GAAG;AAC1B,YAAM,IAAI,MAAM,GAAG,MAAM,kEAAkE;AAAA,IAC7F;AAEA,kBAAc,YAAY,0BAA0B,OAAO,QAAQ,OAAO,OAAO,OAAO,OAAO,CAAC;AAEhG,wBAAoB,SAAS,KAAK,UAAU;AAAA,EAC9C;AAEA,QAAM,UAAU,EAAE,GAAG,QAAQ,kBAAkB;AAE/C,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAE5C;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,IACV,2BAA2B,OAAO,MAAM;AAAA,IACxC,0BAA0B,OAAO,IAAI;AAAA,IACrC;AAAA,IACA,0BAA0B,OAAO,OAAO,KAAK;AAAA,IAC7C,2BAA2B,OAAO,OAAO,OAAO;AAAA,IAChD,8BAA8B,OAAO,OAAO,OAAO;AAAA,IACnD,8DAA8D,OAAO,gBAAgB,SAAS,IAAI,OAAO,gBAAgB,KAAK,IAAI,IAAI,MAAM;AAAA,IAC5I;AAAA,IACA,GAAG,OAAO,QAAQ,OAAO,MAAM,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,MACjD,KAAK,KAAK,KAAK,MAAM,MAAM,GAAG,MAAM,SAAS,IAAI,KAAK,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,EAC/E;AAAA,IACD,GAAG,qBAAqB,OAAO,cAAc;AAAA,IAC7C,GAAG,4BAA4B,iBAAiB;AAAA,EAClD,EAAE,KAAK,IAAI,CAAC;AACd;","names":[]}
|
package/dist/cli-workflows.js
CHANGED