@santi020k/eslint-config-basic 3.2.0 → 3.4.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 +37 -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 +22 -20
- 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 +74 -2
- package/dist/cli-preset.js +253 -6
- 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 +1 -1
- package/dist/cli.js +461 -176
- package/dist/cli.js.map +1 -0
- package/dist/define-config-metadata.js +2 -4
- package/dist/define-config-metadata.js.map +1 -0
- package/dist/frameworks.d.ts +1 -0
- package/dist/frameworks.js +2 -1
- package/dist/frameworks.js.map +1 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.js +83 -22
- package/dist/index.js.map +1 -0
- package/dist/integrations.js +1 -0
- package/dist/integrations.js.map +1 -0
- package/dist/optional-package-errors.js +1 -0
- package/dist/optional-package-errors.js.map +1 -0
- package/dist/recommended.d.ts +6 -3
- package/dist/recommended.js +3 -1
- 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 +25 -25
- package/IMPROVEMENTS.md +0 -270
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-advanced.ts"],"sourcesContent":["/* eslint-disable no-console -- CLI handlers own user-facing terminal output */\n/* eslint-disable complexity -- report builders intentionally cover compatibility and config-source branches */\nimport { existsSync, readdirSync, readFileSync } from 'node:fs'\nimport { createRequire, findPackageJSON } from 'node:module'\nimport { basename, dirname, join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\ninterface SemverApi {\n satisfies: (version: string, range: string) => boolean\n subset: (subRange: string, superRange: string) => boolean\n validRange: (range: string) => null | string\n}\n\ninterface PackageManifest {\n engines?: { node?: string }\n name?: string\n peerDependencies?: Record<string, string>\n version?: string\n}\n\ninterface ResolvedPackageManifest {\n manifest: PackageManifest\n path: string\n}\n\ninterface FlatConfigEntry {\n files?: unknown\n name?: string\n rules?: Record<string, unknown>\n}\n\ninterface ProjectEslint {\n calculateConfigForFile: (filePath: string) => Promise<unknown>\n lintFiles: (patterns: string[]) => Promise<LintResult[]>\n}\n\ninterface LintResult {\n filePath: string\n messages: {\n column?: number\n endColumn?: number\n endLine?: number\n line?: number\n message: string\n ruleId: null | string\n }[]\n}\n\ninterface RuleDiagnostic {\n column: null | number\n endColumn: null | number\n endLine: null | number\n file: string\n line: null | number\n message: string\n}\n\ntype ProjectEslintConstructor = new(options: { cwd: string }) => ProjectEslint\n\nexport interface ExplainRuleOptions {\n file?: string\n json?: boolean\n rule: string\n}\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 BASIC_PACKAGE_NAME = '@santi020k/eslint-config-basic'\nconst FULL_PACKAGE_NAME = '@santi020k/eslint-config-full'\n\nconst RULE_PACKAGE_HINTS: Partial<Record<string, string>> = {\n '@angular-eslint': '@santi020k/eslint-config-angular',\n '@eslint-react': '@santi020k/eslint-config-react',\n '@next/next': '@santi020k/eslint-config-next',\n '@typescript-eslint': '@santi020k/eslint-config-typescript',\n astro: '@santi020k/eslint-config-astro',\n cypress: '@santi020k/eslint-config-testing',\n jest: '@santi020k/eslint-config-testing',\n jsonc: '@santi020k/eslint-config-formats',\n playwright: '@santi020k/eslint-config-testing',\n react: '@santi020k/eslint-config-react',\n 'testing-library': '@santi020k/eslint-config-testing',\n unicorn: '@santi020k/eslint-config-extensions',\n vue: '@santi020k/eslint-config-vue'\n}\n\nconst semver = createRequire(import.meta.url)('semver') as SemverApi\n\nconst readJson = (filePath: string): null | Record<string, unknown> => {\n if (!existsSync(filePath)) return null\n\n try {\n return JSON.parse(readFileSync(filePath, 'utf8')) as Record<string, unknown>\n } catch {\n return null\n }\n}\n\nconst findConfigPath = (cwd: string): null | string => (\n CONFIG_FILENAMES.map(file => join(cwd, file)).find(file => existsSync(file)) ?? null\n)\n\nconst flattenConfig = async (value: unknown): Promise<FlatConfigEntry[]> => {\n const resolved = await value\n\n if (Array.isArray(resolved)) {\n const nested = await Promise.all(resolved.map(entry => flattenConfig(entry)))\n\n return nested.flat()\n }\n\n if (resolved && typeof resolved === 'object') return [resolved]\n\n return []\n}\n\nconst loadConfigEntries = async (configPath: null | string): Promise<FlatConfigEntry[]> => {\n if (!configPath) return []\n\n try {\n const loaded: unknown = await import(`${pathToFileURL(configPath).href}?basic-eslint-explain=${Date.now()}`)\n\n if (!loaded || typeof loaded !== 'object' || !('default' in loaded)) return []\n\n return await flattenConfig((loaded).default)\n } catch {\n return []\n }\n}\n\nconst loadProjectEslint = (cwd: string): 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({ cwd })\n}\n\nconst getRuleSeverity = (ruleValue: unknown): unknown => (\n Array.isArray(ruleValue) ? ruleValue[0] : ruleValue\n)\n\nconst isRuleEnabled = (ruleValue: unknown): boolean => {\n const severity = getRuleSeverity(ruleValue)\n\n return severity !== 0 && severity !== 'off'\n}\n\nconst getPackageHint = (rule: string): null | string => {\n const prefix = rule.includes('/') ? rule.slice(0, rule.indexOf('/')) : rule\n const scopedPrefix = rule.startsWith('@') ? rule.split('/').slice(0, 2).join('/') : prefix\n\n return RULE_PACKAGE_HINTS[scopedPrefix] ?? RULE_PACKAGE_HINTS[prefix] ?? null\n}\n\nconst getRuleDiagnostics = async (\n eslint: ProjectEslint,\n file: string,\n rule: string\n): Promise<RuleDiagnostic[]> => {\n if (rule !== 'complexity') return []\n\n try {\n const results = await eslint.lintFiles([file])\n\n return results.flatMap(result => result.messages\n .filter(message => message.ruleId === rule)\n .map(message => ({\n column: message.column ?? null,\n endColumn: message.endColumn ?? null,\n endLine: message.endLine ?? null,\n file: result.filePath,\n line: message.line ?? null,\n message: message.message\n })))\n } catch {\n return []\n }\n}\n\nexport const handleExplainRule = async (\n cwd: string = process.cwd(),\n options: ExplainRuleOptions\n): Promise<void> => {\n const configPath = findConfigPath(cwd)\n const file = options.file ?? 'eslint.config.js'\n const eslint = loadProjectEslint(cwd)\n const effective = await eslint.calculateConfigForFile(file) as null | { rules?: Record<string, unknown> }\n const effectiveValue = effective?.rules?.[options.rule]\n const entries = await loadConfigEntries(configPath)\n const diagnostics = await getRuleDiagnostics(eslint, file, options.rule)\n\n const sources = entries.flatMap((entry, index) => {\n if (!entry.rules || !Object.hasOwn(entry.rules, options.rule)) return []\n\n return [{\n files: entry.files ?? null,\n index,\n name: entry.name ?? `anonymous config #${index + 1}`,\n value: entry.rules[options.rule]\n }]\n })\n\n const payload = {\n configFile: configPath ? basename(configPath) : null,\n diagnostics,\n effective: effectiveValue ?? null,\n enabled: effectiveValue !== undefined && isRuleEnabled(effectiveValue),\n file,\n packageHint: getPackageHint(options.rule),\n rule: options.rule,\n severity: effectiveValue === undefined ? null : getRuleSeverity(effectiveValue),\n sources\n }\n\n if (options.json) {\n console.log(JSON.stringify(payload, null, 2))\n } else {\n console.log([\n `ESLint rule explanation: ${payload.rule}`,\n `- File: ${payload.file}`,\n `- Config: ${payload.configFile ?? 'none'}`,\n `- Effective value: ${JSON.stringify(payload.effective)}`,\n `- Enabled: ${payload.enabled ? 'yes' : 'no'}`,\n `- Likely package: ${payload.packageHint ?? 'core or custom config'}`,\n `- Defining entries: ${payload.sources.length}`,\n ...(payload.diagnostics.length > 0 ?\n [`- Current findings: ${payload.diagnostics.length}`] :\n [])\n ].join('\\n'))\n\n for (const source of payload.sources) {\n console.log(` - ${source.name}: ${JSON.stringify(source.value)}`)\n }\n\n for (const diagnostic of payload.diagnostics) {\n console.log(\n ` - ${diagnostic.file}:${diagnostic.line ?? '?'}:${diagnostic.column ?? '?'} ` +\n diagnostic.message\n )\n }\n }\n\n if (effectiveValue === undefined) process.exitCode = 1\n}\n\nconst getDependencyVersions = (manifest: null | Record<string, unknown>): Record<string, string> => {\n const fields = ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies']\n const dependencies: Record<string, string> = {}\n\n for (const field of fields) {\n const values = manifest?.[field]\n\n if (!values || typeof values !== 'object' || Array.isArray(values)) continue\n\n for (const [name, version] of Object.entries(values)) {\n if (typeof version === 'string') dependencies[name] = version\n }\n }\n\n return dependencies\n}\n\nconst readResolvedManifest = (\n basePath: string,\n packageName: string\n): null | ResolvedPackageManifest => {\n try {\n const manifestPath = findPackageJSON(packageName, pathToFileURL(basePath))\n\n const manifest = manifestPath ?\n readJson(manifestPath) as null | PackageManifest :\n null\n\n if (manifestPath && manifest?.name === packageName) return { manifest, path: manifestPath }\n } catch {\n // Fall through for runtimes where package-JSON resolution is unavailable.\n }\n\n try {\n let directory = dirname(createRequire(basePath).resolve(packageName))\n\n for (let depth = 0; depth < 6; depth++) {\n const manifestPath = join(directory, 'package.json')\n const manifest = readJson(manifestPath) as null | PackageManifest\n\n if (manifest?.name === packageName) return { manifest, path: manifestPath }\n\n directory = dirname(directory)\n }\n } catch {\n return null\n }\n\n return null\n}\n\nconst readWorkspaceManifest = (cwd: string, packageName: string): null | ResolvedPackageManifest => {\n const packagesPath = join(cwd, 'packages')\n\n if (!existsSync(packagesPath)) return null\n\n for (const entry of readdirSync(packagesPath, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n\n const manifestPath = join(packagesPath, entry.name, 'package.json')\n const manifest = readJson(manifestPath) as null | PackageManifest\n\n if (manifest?.name === packageName) return { manifest, path: manifestPath }\n }\n\n return null\n}\n\nexport const createCompatibilityReport = (cwd: string = process.cwd()) => {\n const rootManifestPath = join(cwd, 'package.json')\n const rootManifest = readJson(rootManifestPath)\n const declared = getDependencyVersions(rootManifest)\n const consumerNodeRange = (rootManifest as null | PackageManifest)?.engines?.node ?? null\n\n const configPackages = Object.keys(declared)\n .filter(name => name.startsWith('@santi020k/eslint-config-'))\n .sort()\n\n const runtimeVersions = {\n consumerNodeRange,\n eslint: readResolvedManifest(rootManifestPath, 'eslint')?.manifest.version ?? null,\n node: process.versions.node,\n typescript: readResolvedManifest(rootManifestPath, 'typescript')?.manifest.version ?? null\n }\n\n const packages = configPackages.map(name => {\n const resolvedPackage = readResolvedManifest(rootManifestPath, name) ?? readWorkspaceManifest(cwd, name)\n const manifest = resolvedPackage?.manifest\n const issues: string[] = []\n\n const aggregatedBasic = name === FULL_PACKAGE_NAME && resolvedPackage ?\n readResolvedManifest(resolvedPackage.path, BASIC_PACKAGE_NAME) :\n null\n\n if (!manifest) {\n issues.push('declared but not installed')\n } else {\n const nodeRange = manifest.engines?.node\n\n if (nodeRange && !semver.satisfies(runtimeVersions.node, nodeRange)) {\n issues.push(`requires Node ${nodeRange}`)\n }\n\n if (nodeRange && consumerNodeRange) {\n if (!semver.validRange(consumerNodeRange)) {\n issues.push(`consumer engines.node ${consumerNodeRange} is not a valid semver range`)\n } else if (!semver.subset(consumerNodeRange, nodeRange)) {\n issues.push(\n `consumer engines.node ${consumerNodeRange} permits unsupported runtimes; requires ${nodeRange}`\n )\n }\n }\n\n for (const peer of ['eslint', 'typescript']) {\n const range = manifest.peerDependencies?.[peer]\n const version = runtimeVersions[peer as 'eslint' | 'typescript']\n\n if (range && version && !semver.satisfies(version, range)) {\n issues.push(`requires ${peer} ${range}, resolved ${version}`)\n }\n }\n }\n\n return {\n aggregatedBasic: name === FULL_PACKAGE_NAME ?\n {\n name: BASIC_PACKAGE_NAME,\n resolved: aggregatedBasic?.manifest.version ?? null,\n resolvedPath: aggregatedBasic?.path ?? null\n } :\n null,\n declared: declared[name],\n issues,\n name,\n resolved: manifest?.version ?? null,\n resolvedPath: resolvedPackage?.path ?? null\n }\n })\n\n return {\n compatible: packages.every(item => item.issues.length === 0),\n packages,\n runtime: runtimeVersions\n }\n}\n\nexport const handleCompatibility = (\n cwd: string = process.cwd(),\n json = false\n): void => {\n const report = createCompatibilityReport(cwd)\n\n if (json) {\n console.log(JSON.stringify(report, null, 2))\n } else {\n console.log([\n `ESLint compatibility: ${report.compatible ? 'compatible' : 'issues found'}`,\n `- Node: ${report.runtime.node}`,\n `- Consumer Node range: ${report.runtime.consumerNodeRange ?? 'not declared'}`,\n `- ESLint: ${report.runtime.eslint ?? 'not installed'}`,\n `- TypeScript: ${report.runtime.typescript ?? 'not installed'}`\n ].join('\\n'))\n\n for (const item of report.packages) {\n console.log(\n `- ${item.name}: ${item.resolved ?? 'not installed'}` +\n (item.resolvedPath ? ` at ${item.resolvedPath}` : '') +\n (item.issues.length > 0 ? ` (${item.issues.join('; ')})` : '')\n )\n\n if (item.aggregatedBasic) {\n console.log(\n ` - Composer ${item.aggregatedBasic.name}: ` +\n (item.aggregatedBasic.resolved ?? 'not resolved') +\n (item.aggregatedBasic.resolvedPath ? ` at ${item.aggregatedBasic.resolvedPath}` : '')\n )\n }\n }\n }\n\n if (!report.compatible) process.exitCode = 1\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli-migration.js
CHANGED
|
@@ -468,24 +468,27 @@ const replaceImportedAlias = (content, from, to, invokeReferences = false) => {
|
|
|
468
468
|
const owner = REMOVED_ALIAS_OWNERS[from];
|
|
469
469
|
const acceptedPackages = /* @__PURE__ */ new Set([BASIC_PACKAGE, FULL_PACKAGE, ...owner ? [owner] : []]);
|
|
470
470
|
const importPattern = /import\s*\{([^}]*)\}\s*from\s*(['"])(@santi020k\/eslint-config-[^'"]+)\2/g;
|
|
471
|
-
let updated = content.replace(
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
const
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
471
|
+
let updated = content.replace(
|
|
472
|
+
importPattern,
|
|
473
|
+
(statement, specifierText, _quote, packageName) => {
|
|
474
|
+
if (!acceptedPackages.has(packageName)) return statement;
|
|
475
|
+
const specifiers = specifierText.split(",");
|
|
476
|
+
const rewritten = specifiers.map((specifier) => {
|
|
477
|
+
const aliasMatch = /^(\s*)([a-zA-Z_$][\w$]*)\s+as\s+([a-zA-Z_$][\w$]*)(\s*)$/.exec(specifier);
|
|
478
|
+
if (aliasMatch?.[2] === from) {
|
|
479
|
+
const localName = aliasMatch[3];
|
|
480
|
+
bindings.push({ from: localName, to: localName });
|
|
481
|
+
return `${aliasMatch[1]}${to} as ${localName}${aliasMatch[4]}`;
|
|
482
|
+
}
|
|
483
|
+
const directMatch = /^(\s*)([a-zA-Z_$][\w$]*)(\s*)$/.exec(specifier);
|
|
484
|
+
if (directMatch?.[2] !== from) return specifier;
|
|
485
|
+
bindings.push({ from, to });
|
|
486
|
+
return `${directMatch[1]}${to}${directMatch[3]}`;
|
|
487
|
+
});
|
|
488
|
+
const rewrittenText = rewritten.join(",");
|
|
489
|
+
return rewrittenText === specifierText ? statement : statement.replace(specifierText, rewrittenText);
|
|
490
|
+
}
|
|
491
|
+
);
|
|
489
492
|
for (const binding of bindings) {
|
|
490
493
|
updated = replaceBindingReferences(updated, binding.from, binding.to, invokeReferences);
|
|
491
494
|
}
|
|
@@ -756,7 +759,6 @@ const getExplicitConfigFeaturePackages = (content) => {
|
|
|
756
759
|
};
|
|
757
760
|
for (const category of Object.keys(FEATURE_PACKAGES)) {
|
|
758
761
|
const categorySelections = searchableContent.matchAll(
|
|
759
|
-
// eslint-disable-next-line security/detect-non-literal-regexp -- category names come from the internal package registry
|
|
760
762
|
new RegExp(`(?:\\b${category}\\b|['"]${category}['"])\\s*:\\s*\\[([\\s\\S]*?)\\]`, "g")
|
|
761
763
|
);
|
|
762
764
|
for (const selection of categorySelections) {
|
|
@@ -801,7 +803,6 @@ const getExplicitConfigFeaturePackages = (content) => {
|
|
|
801
803
|
return [...packages];
|
|
802
804
|
};
|
|
803
805
|
const replacePackageSpecifiers = (content, from, to) => content.replace(
|
|
804
|
-
// eslint-disable-next-line security/detect-unsafe-regex -- bounded module specifiers cannot cross quote characters
|
|
805
806
|
/(\b(?:from|import|export)\s*(?:\(\s*)?|\brequire\s*\(\s*)(['"])([^'"]+)\2/g,
|
|
806
807
|
(statement, prefix, quote, specifier) => specifier === from ? `${prefix}${quote}${to}${quote}` : statement
|
|
807
808
|
);
|
|
@@ -1132,3 +1133,4 @@ export {
|
|
|
1132
1133
|
handleMigrateV3,
|
|
1133
1134
|
migrateConfigToV3
|
|
1134
1135
|
};
|
|
1136
|
+
//# sourceMappingURL=cli-migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-migration.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-dynamic-delete -- migration rewrites validated package.json dependency records */\n/* eslint-disable complexity -- migration planners intentionally cover dry-run, write, lean, full, and compatibility branches */\n/* eslint-disable no-console -- CLI handlers own user-facing terminal output */\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { basename, join } from 'node:path'\n\nexport interface V3MigrationContext {\n declaredConfigPackages?: string[]\n extensions: string[]\n formats: string[]\n frameworks: string[]\n libraries: string[]\n packageManager: string\n testing: string[]\n tools: string[]\n typescript: boolean\n}\n\nexport interface V3MigrationOptions {\n check?: boolean\n full?: boolean\n json?: boolean\n write?: boolean\n}\n\ninterface MigrationChange {\n detail: string\n target: string\n}\n\ninterface MigrationResult {\n changes: MigrationChange[]\n configFile: null | string\n installCommand: string\n mode: 'full' | 'lean'\n packages: string[]\n written: string[]\n}\n\nconst BASIC_PACKAGE = '@santi020k/eslint-config-basic'\nconst FULL_PACKAGE = '@santi020k/eslint-config-full'\nconst INTEGRATIONS_PACKAGE = '@santi020k/eslint-config-integrations'\nconst LITE_PACKAGE = '@santi020k/eslint-config-lite'\nconst REMIX_PACKAGE = '@santi020k/eslint-config-remix'\n\nconst 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<string, 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 FEATURE_EXPORTS: Record<keyof typeof FEATURE_PACKAGES, string[]> = {\n extensions: [\n 'a11y',\n 'astroDoctor',\n 'bestPractices',\n 'biome',\n 'boundaries',\n 'compat',\n 'deMorgan',\n 'depend',\n 'noOnlyTests',\n 'node',\n 'oxlint',\n 'perfectionist',\n 'regexp',\n 'security',\n 'sonarjs',\n 'unicorn'\n ],\n formats: [\n 'css',\n 'graphql',\n 'html',\n 'jsonc',\n 'markdown',\n 'mdx',\n 'packageJson',\n 'toml',\n 'yaml'\n ],\n libraries: [\n 'aiSdk',\n 'autogen',\n 'drizzle',\n 'googleGenAi',\n 'i18next',\n 'langchain',\n 'llamaIndex',\n 'mastra',\n 'mcp',\n 'mikroOrm',\n 'openAiAgents',\n 'prisma',\n 'sequelize',\n 'stencil',\n 'storybook',\n 'tailwind',\n 'tanstackQuery',\n 'tanstackRouter',\n 'typeorm',\n 'turbo',\n 'zod'\n ],\n testing: [\n 'cypress',\n 'jest',\n 'jestDom',\n 'playwright',\n 'testingLibrary',\n 'vitest'\n ],\n tools: [\n 'command',\n 'cspell',\n 'docker',\n 'githubActions',\n 'jsdoc',\n 'nx',\n 'pnpm',\n 'prettier',\n 'swagger'\n ]\n}\n\nconst EXPORT_TO_FEATURE_PACKAGE = new Map(\n Object.entries(FEATURE_EXPORTS).flatMap(([category, exports]) => exports.map(exportName => [\n exportName,\n\n FEATURE_PACKAGES[category as keyof typeof FEATURE_PACKAGES]\n ] as const))\n)\n\nconst toKebabCase = (value: string): string => (\n value.replaceAll(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()\n)\n\nconst FEATURE_NAME_TO_PACKAGE = new Map(\n Object.entries(FEATURE_EXPORTS).flatMap(([category, exports]) => exports.flatMap(exportName => {\n const packageName = FEATURE_PACKAGES[category as keyof typeof FEATURE_PACKAGES]\n\n return [\n [exportName.toLowerCase(), packageName],\n [toKebabCase(exportName), packageName]\n ] as const\n }))\n)\n\nconst PRESET_FEATURE_PACKAGES: Record<string, string[]> = {\n all: Object.values(FEATURE_PACKAGES),\n app: [\n FEATURE_PACKAGES.testing,\n FEATURE_PACKAGES.tools\n ],\n ci: [\n FEATURE_PACKAGES.extensions,\n FEATURE_PACKAGES.tools\n ],\n library: [\n FEATURE_PACKAGES.extensions,\n FEATURE_PACKAGES.tools\n ],\n monorepo: [\n FEATURE_PACKAGES.extensions,\n FEATURE_PACKAGES.tools\n ]\n}\n\nconst REMOVED_ALIAS_REPLACEMENTS: Record<string, string> = {\n angularConfig: 'angular',\n astroConfig: 'createAstroConfig',\n eslintConfig: 'defineConfig',\n expoConfig: 'expo',\n gitignore: 'createGitignoreConfig',\n jsConfig: 'coreConfig',\n nestConfig: 'nest',\n nextConfig: 'next',\n preactConfig: 'preact',\n reactConfig: 'react',\n solidConfig: 'solid',\n svelteConfig: 'svelte',\n tsConfig: 'typescriptConfig',\n vueConfig: 'vue'\n}\n\nconst REMOVED_ALIAS_OWNERS: Record<string, string> = {\n angularConfig: '@santi020k/eslint-config-angular',\n astroConfig: '@santi020k/eslint-config-astro',\n expoConfig: '@santi020k/eslint-config-expo',\n gitignore: '@santi020k/eslint-config-core',\n jsConfig: '@santi020k/eslint-config-core',\n nestConfig: '@santi020k/eslint-config-nest',\n nextConfig: '@santi020k/eslint-config-next',\n preactConfig: '@santi020k/eslint-config-preact',\n reactConfig: '@santi020k/eslint-config-react',\n solidConfig: '@santi020k/eslint-config-solid',\n svelteConfig: '@santi020k/eslint-config-svelte',\n tsConfig: '@santi020k/eslint-config-typescript',\n vueConfig: '@santi020k/eslint-config-vue'\n}\n\nconst FACTORY_ALIAS_REPLACEMENTS = new Set([\n 'astroConfig',\n 'gitignore'\n])\n\nconst PARAMETER_PROPERTY_MODIFIERS = new Set([\n 'override',\n 'private',\n 'protected',\n 'public',\n 'readonly'\n])\n\nconst dependencyFields = [\n 'dependencies',\n 'devDependencies',\n 'optionalDependencies',\n 'peerDependencies'\n] as const\n\ntype DependencyField = typeof dependencyFields[number]\n\nconst readPackageJson = (cwd: string): Record<string, unknown> => {\n const packagePath = join(cwd, 'package.json')\n\n if (!existsSync(packagePath)) throw new Error('package.json is required for a v3 migration.')\n\n try {\n return JSON.parse(readFileSync(packagePath, 'utf8')) as Record<string, unknown>\n } catch {\n throw new Error('package.json is invalid JSON.')\n }\n}\n\nconst getConfigPath = (cwd: string): null | string => {\n const 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\n return filenames.map(filename => join(cwd, filename)).find(path => existsSync(path)) ?? null\n}\n\nconst createBackupPath = (filePath: string, suffix: string): string => {\n const preferred = `${filePath}.${suffix}.bak`\n\n if (!existsSync(preferred)) return preferred\n\n let index = 2\n\n while (existsSync(`${preferred}.${index}`)) index++\n\n return `${preferred}.${index}`\n}\n\nconst getDependencyRecord = (\n packageJson: Record<string, unknown>,\n field: DependencyField\n): Record<string, string> => {\n const value = packageJson[field]\n\n if (!value || typeof value !== 'object' || Array.isArray(value)) return {}\n\n return value as Record<string, string>\n}\n\nconst getPackageDependencyFields = (\n packageJson: Record<string, unknown>,\n packageName: string\n): DependencyField[] => (\n dependencyFields.filter(field => packageName in getDependencyRecord(packageJson, field))\n)\n\nconst getPreferredConfigDependencyFields = (\n packageJson: Record<string, unknown>\n): DependencyField[] => {\n const fields = new Set<DependencyField>()\n\n for (const packageName of [\n BASIC_PACKAGE,\n FULL_PACKAGE,\n INTEGRATIONS_PACKAGE,\n LITE_PACKAGE\n ]) {\n for (const field of getPackageDependencyFields(packageJson, packageName)) fields.add(field)\n }\n\n return fields.size > 0 ? [...fields] : ['devDependencies']\n}\n\nconst getDeclaredConfigPackages = (packageJson: Record<string, unknown>): Set<string> => {\n const names = new Set<string>()\n\n for (const field of dependencyFields) {\n for (const name of Object.keys(getDependencyRecord(packageJson, field))) {\n if (name.startsWith('@santi020k/eslint-config-')) names.add(name)\n }\n }\n\n return names\n}\n\nconst getImportRanges = (content: string): { end: number, start: number }[] => (\n [...content.matchAll(/import\\s*\\{[\\s\\S]*?\\}\\s*from\\s*(['\"])[^'\"]+\\1/g)]\n .map(match => ({\n end: match.index + match[0].length,\n start: match.index\n }))\n)\n\nconst maskNonCode = (content: string, preserveStrings = false): string => {\n const characters = Array<string>(content.length)\n let quote: null | string = null\n let blockComment = false\n let lineComment = false\n\n for (let index = 0; index < content.length; index++) {\n characters[index] = content[index]\n }\n\n for (let index = 0; index < characters.length; index++) {\n const character = characters[index]\n const next = characters[index + 1]\n\n if (lineComment) {\n if (character === '\\n') {\n lineComment = false\n } else {\n characters[index] = ' '\n }\n\n continue\n }\n\n if (blockComment) {\n characters[index] = character === '\\n' ? '\\n' : ' '\n\n if (character === '*' && next === '/') {\n characters[index + 1] = ' '\n\n blockComment = false\n\n index++\n }\n\n continue\n }\n\n if (quote) {\n if (!preserveStrings) characters[index] = character === '\\n' ? '\\n' : ' '\n\n if (character === '\\\\') {\n if (!preserveStrings && index + 1 < characters.length) {\n characters[index + 1] = next === '\\n' ? '\\n' : ' '\n }\n\n index++\n } else if (character === quote) {\n quote = null\n }\n\n continue\n }\n\n if (character === '/' && next === '/') {\n characters[index] = ' '\n\n characters[index + 1] = ' '\n\n lineComment = true\n\n index++\n\n continue\n }\n\n if (character === '/' && next === '*') {\n characters[index] = ' '\n\n characters[index + 1] = ' '\n\n blockComment = true\n\n index++\n\n continue\n }\n\n if (character === '\\'' || character === '\"' || character === '`') {\n if (!preserveStrings) characters[index] = ' '\n\n quote = character\n }\n }\n\n return characters.join('')\n}\n\nconst getEnclosingDelimiter = (content: string, offset: number): null | string => {\n const expectedOpeners: string[] = []\n\n const closingDelimiters: Record<string, string> = {\n ')': '(',\n ']': '[',\n '}': '{'\n }\n\n for (let index = offset - 1; index >= 0; index--) {\n const character = content[index]\n const expectedOpener = closingDelimiters[character]\n\n if (expectedOpener) {\n expectedOpeners.push(expectedOpener)\n\n continue\n }\n\n if (!['(', '[', '{'].includes(character)) continue\n\n if (expectedOpeners.at(-1) === character) {\n expectedOpeners.pop()\n } else if (expectedOpeners.length === 0) {\n return character\n }\n }\n\n return null\n}\n\ninterface SourceRange {\n end: number\n start: number\n}\n\nconst findClosingDelimiter = (\n content: string,\n start: number,\n opener: string,\n closer: string\n): number => {\n let depth = 0\n\n for (let index = start; index < content.length; index++) {\n if (content[index] === opener) depth++\n else if (content[index] === closer && --depth === 0) return index + 1\n }\n\n return content.length\n}\n\nconst getShadowedRanges = (content: string, name: string): SourceRange[] => {\n const masked = maskNonCode(content)\n const importRanges = getImportRanges(content)\n let searchable = masked\n\n for (const range of importRanges.toReversed()) {\n searchable = `${searchable.slice(0, range.start)}${' '.repeat(range.end - range.start)}${searchable.slice(range.end)}`\n }\n\n const getArrowRange = (start: number, arrowIndex: number): SourceRange => {\n const relativeBodyStart = searchable.slice(arrowIndex + 2).search(/\\S/)\n const bodyStart = relativeBodyStart === -1 ? searchable.length : arrowIndex + 2 + relativeBodyStart\n const bodyDelimiter = searchable[bodyStart]\n let bodyCloser: string | undefined\n\n if (bodyDelimiter === '(') bodyCloser = ')'\n else if (bodyDelimiter === '[') bodyCloser = ']'\n\n if (bodyDelimiter === '{') {\n return { end: findClosingDelimiter(searchable, bodyStart, '{', '}'), start }\n }\n\n if (bodyCloser) {\n return { end: findClosingDelimiter(searchable, bodyStart, bodyDelimiter, bodyCloser), start }\n }\n\n const lineEnd = searchable.indexOf('\\n', arrowIndex + 2)\n\n return { end: lineEnd === -1 ? searchable.length : lineEnd, start }\n }\n\n const unparenthesizedArrowPattern = new RegExp(`\\\\b${name}\\\\b\\\\s*=>`, 'gm')\n\n const ranges = [...searchable.matchAll(unparenthesizedArrowPattern)].map(match => (\n getArrowRange(match.index, searchable.indexOf('=>', match.index))\n ))\n\n const splitAtTopLevel = (value: string, separator: string): string[] => {\n const parts: string[] = []\n const closers: Record<string, string> = { '(': ')', '[': ']', '{': '}' }\n const expectedClosers: string[] = []\n let partStart = 0\n\n for (let index = 0; index < value.length; index++) {\n const character = value[index]\n const closer = closers[character]\n\n if (closer) expectedClosers.push(closer)\n else if (character === expectedClosers.at(-1)) expectedClosers.pop()\n else if (character === separator && expectedClosers.length === 0) {\n parts.push(value.slice(partStart, index))\n\n partStart = index + 1\n }\n }\n\n parts.push(value.slice(partStart))\n\n return parts\n }\n\n const hasBindingName = (value: string): boolean => {\n let binding = splitAtTopLevel(value, '=')[0].trim()\n\n if (binding.startsWith('...')) binding = binding.slice(3).trim()\n\n binding = splitAtTopLevel(binding, ':')[0].trim()\n\n const bindingParts = binding.split(/\\s+/)\n\n while (PARAMETER_PROPERTY_MODIFIERS.has(bindingParts[0])) bindingParts.shift()\n\n binding = bindingParts.join(' ')\n\n if (binding.startsWith('{') && binding.endsWith('}')) {\n return splitAtTopLevel(binding.slice(1, -1), ',').some(property => {\n const propertyParts = splitAtTopLevel(property, ':')\n\n return hasBindingName(propertyParts.length > 1 ? propertyParts.slice(1).join(':') : property)\n })\n }\n\n if (binding.startsWith('[') && binding.endsWith(']')) {\n return splitAtTopLevel(binding.slice(1, -1), ',').some(hasBindingName)\n }\n\n return binding.replace(/\\?$/, '') === name\n }\n\n const hasParameterBinding = (parameters: string): boolean => (\n splitAtTopLevel(parameters, ',').some(hasBindingName)\n )\n\n const parameterOwnerPattern = /(?:\\bfunction\\b[^()]*|\\bcatch|\\b(?:constructor|[a-zA-Z_$][\\w$]*))\\s*$/\n\n for (let parameterStart = 0; parameterStart < searchable.length; parameterStart++) {\n if (searchable[parameterStart] !== '(') continue\n\n const parameterEnd = findClosingDelimiter(searchable, parameterStart, '(', ')')\n\n if (searchable[parameterEnd - 1] !== ')') continue\n\n const parameters = searchable.slice(parameterStart + 1, parameterEnd - 1)\n\n if (!hasParameterBinding(parameters)) continue\n\n const relativeBodyStart = searchable.slice(parameterEnd).search(/\\S/)\n const bodyStart = relativeBodyStart === -1 ? searchable.length : parameterEnd + relativeBodyStart\n\n if (searchable.startsWith('=>', bodyStart)) {\n ranges.push(getArrowRange(parameterStart, bodyStart))\n\n continue\n }\n\n if (searchable[bodyStart] !== '{') continue\n\n const ownerMatch = parameterOwnerPattern.exec(searchable.slice(0, parameterStart))\n\n if (!ownerMatch) continue\n\n ranges.push({\n end: findClosingDelimiter(searchable, bodyStart, '{', '}'),\n start: ownerMatch.index\n })\n }\n\n const blockBindingPattern = new RegExp(`\\\\b(?:const|let|var|function|class)\\\\s+${name}\\\\b`, 'g')\n\n for (const match of searchable.matchAll(blockBindingPattern)) {\n const blockStart = searchable.lastIndexOf('{', match.index)\n\n if (blockStart !== -1) {\n ranges.push({\n end: findClosingDelimiter(searchable, blockStart, '{', '}'),\n start: blockStart\n })\n }\n }\n\n return ranges\n}\n\nconst replaceBindingReferences = (\n content: string,\n from: string,\n to: string,\n invokeReferences = false\n): string => {\n const importRanges = getImportRanges(content)\n const masked = maskNonCode(content)\n const identifierPattern = new RegExp(`\\\\b${from}\\\\b`, 'g')\n const matches = [...masked.matchAll(identifierPattern)]\n const shadowedRanges = getShadowedRanges(content, from)\n let updated = content\n\n for (const match of matches.reverse()) {\n const offset = match.index\n const isImportSpecifier = importRanges.some(range => offset >= range.start && offset < range.end)\n const isShadowed = shadowedRanges.some(range => offset >= range.start && offset < range.end)\n\n if (isImportSpecifier || isShadowed) continue\n\n const precedingContent = masked.slice(0, offset).trimEnd()\n const preceding = precedingContent.at(-1)\n const following = masked.slice(offset + from.length)\n const isMemberAccess = preceding === '.' && !precedingContent.endsWith('...')\n const isProperty = isMemberAccess || /^\\s*:/.test(following)\n const isAlreadyInvoked = /^\\s*\\(/.test(following)\n\n const isObjectShorthand = (\n getEnclosingDelimiter(masked, offset) === '{' &&\n (preceding === '{' || preceding === ',') &&\n /^\\s*[,}]/.test(following)\n )\n\n if (isProperty) continue\n\n let replacement = to\n\n if (invokeReferences && isObjectShorthand) {\n replacement = `${from}: ${to}()`\n } else if (invokeReferences && !isAlreadyInvoked) {\n replacement = `${to}()`\n }\n\n updated = `${updated.slice(0, offset)}${replacement}${updated.slice(offset + from.length)}`\n }\n\n return updated\n}\n\nconst replaceImportedAlias = (\n content: string,\n from: string,\n to: string,\n invokeReferences = false\n): string => {\n const bindings: { from: string, to: string }[] = []\n const owner = REMOVED_ALIAS_OWNERS[from]\n const acceptedPackages = new Set([BASIC_PACKAGE, FULL_PACKAGE, ...(owner ? [owner] : [])])\n const importPattern = /import\\s*\\{([^}]*)\\}\\s*from\\s*(['\"])(@santi020k\\/eslint-config-[^'\"]+)\\2/g\n\n let updated = content.replace(\n importPattern,\n (statement, specifierText: string, _quote: string, packageName: string) => {\n if (!acceptedPackages.has(packageName)) return statement\n\n const specifiers = specifierText.split(',')\n\n const rewritten = specifiers.map(specifier => {\n const aliasMatch = /^(\\s*)([a-zA-Z_$][\\w$]*)\\s+as\\s+([a-zA-Z_$][\\w$]*)(\\s*)$/.exec(specifier)\n\n if (aliasMatch?.[2] === from) {\n const localName = aliasMatch[3]\n\n bindings.push({ from: localName, to: localName })\n\n return `${aliasMatch[1]}${to} as ${localName}${aliasMatch[4]}`\n }\n\n const directMatch = /^(\\s*)([a-zA-Z_$][\\w$]*)(\\s*)$/.exec(specifier)\n\n if (directMatch?.[2] !== from) return specifier\n\n bindings.push({ from, to })\n\n return `${directMatch[1]}${to}${directMatch[3]}`\n })\n\n const rewrittenText = rewritten.join(',')\n\n return rewrittenText === specifierText ? statement : statement.replace(specifierText, rewrittenText)\n }\n )\n\n for (const binding of bindings) {\n updated = replaceBindingReferences(updated, binding.from, binding.to, invokeReferences)\n }\n\n return updated\n}\n\nconst splitBasicIntegrationImports = (\n content: string\n): { changed: boolean, content: string, featurePackages: string[], moved: string[] } => {\n const moved = new Set<string>()\n const featurePackages = new Set<string>()\n const importPattern = /import\\s*\\{([^}]+)\\}\\s*from\\s*(['\"])@santi020k\\/eslint-config-(?:basic|lite)\\2/g\n\n const transformed = content.replace(importPattern, (statement, specifierText: string, quote: string) => {\n const specifiers = specifierText.split(',').map(value => value.trim()).filter(Boolean)\n const grouped = new Map<string, string[]>()\n\n const integrations = specifiers.filter(specifier => {\n const imported = specifier.split(/\\s+as\\s+/)[0]?.trim() ?? ''\n const packageName = EXPORT_TO_FEATURE_PACKAGE.get(imported)\n\n if (!packageName) return false\n\n const values = grouped.get(packageName) ?? []\n\n values.push(specifier)\n\n grouped.set(packageName, values)\n\n return true\n })\n\n if (integrations.length === 0) return statement\n\n for (const specifier of integrations) moved.add(specifier)\n\n const basic = specifiers.filter(specifier => !integrations.includes(specifier))\n const lines: string[] = []\n\n if (basic.length > 0) {\n lines.push(`import { ${basic.join(', ')} } from ${quote}${BASIC_PACKAGE}${quote}`)\n }\n\n for (const [packageName, values] of grouped) {\n featurePackages.add(packageName)\n\n lines.push(`import { ${values.join(', ')} } from ${quote}${packageName}${quote}`)\n }\n\n return lines.join('\\n')\n })\n\n return {\n changed: transformed !== content,\n content: transformed,\n featurePackages: [...featurePackages],\n moved: [...moved]\n }\n}\n\nconst hasCodePropertySeparator = (codeContent: string, match: RegExpMatchArray): boolean => {\n const separatorOffset = match[0].indexOf(':')\n const matchIndex = match.index ?? -1\n\n return matchIndex >= 0 && separatorOffset >= 0 && codeContent[matchIndex + separatorOffset] === ':'\n}\n\nconst replaceCodeProperty = (\n content: string,\n property: string,\n replacement: string,\n matches?: RegExpMatchArray[]\n): string => {\n const masked = maskNonCode(content, true)\n const pattern = new RegExp(`\\\\b${property}\\\\b(?=\\\\s*:)`, 'g')\n const propertyMatches = matches ?? [...masked.matchAll(pattern)]\n let updated = content\n\n for (const match of propertyMatches.toReversed()) {\n const { index } = match\n\n if (index === undefined) continue\n\n updated = `${updated.slice(0, index)}${replacement}${updated.slice(index + property.length)}`\n }\n\n return updated\n}\n\nconst toFeatureName = (value: string): null | string => {\n const trimmed = value.trim()\n const enumMatch = /^(?:Extension|Format|Library|Testing|Tool)\\.([a-zA-Z0-9_$]+)$/.exec(trimmed)\n const stringMatch = /^(['\"])([^'\"]+)\\1$/.exec(trimmed)\n const raw = enumMatch?.[1] ?? stringMatch?.[2]\n\n return raw ? toKebabCase(raw) : null\n}\n\nconst getOwningObjectStart = (structure: string, position: number): number | undefined => {\n const objectStarts: number[] = []\n\n for (let index = 0; index < position; index++) {\n if (structure[index] === '{') objectStarts.push(index)\n\n if (structure[index] === '}') objectStarts.pop()\n }\n\n return objectStarts.at(-1)\n}\n\nconst getDefineConfigOptionOwners = (searchable: string): Set<number> => {\n const owners = new Set(\n [...searchable.matchAll(/\\bdefineConfig\\s*\\(\\s*\\{/g)]\n .map(match => match.index + match[0].lastIndexOf('{'))\n )\n\n const optionNames = new Set(\n [...searchable.matchAll(/\\bdefineConfig\\s*\\(\\s*([a-zA-Z_$][\\w$]*)\\b/g)]\n .map(match => match[1])\n )\n\n for (const optionName of optionNames) {\n const bindingPattern = new RegExp(`\\\\b(?:const|let|var)\\\\s+${optionName}\\\\s*=\\\\s*\\\\{`, 'g')\n\n for (const match of searchable.matchAll(bindingPattern)) {\n owners.add(match.index + match[0].lastIndexOf('{'))\n }\n }\n\n return owners\n}\n\nconst getDirectChildObjectStarts = (\n structure: string,\n containerStart: number\n): number[] => {\n const children: number[] = []\n const objectStarts = [containerStart]\n\n for (let index = containerStart + 1; index < structure.length && objectStarts.length > 0; index++) {\n if (structure[index] === '{') {\n if (objectStarts.at(-1) === containerStart) children.push(index)\n\n objectStarts.push(index)\n } else if (structure[index] === '}') {\n objectStarts.pop()\n }\n }\n\n return children\n}\n\nconst getOwnedObjectPropertyStarts = (\n searchable: string,\n structure: string,\n property: string,\n owners: Set<number>\n): number[] => {\n const pattern = new RegExp(`\\\\b${property}\\\\b\\\\s*:\\\\s*\\\\{`, 'g')\n\n return [...searchable.matchAll(pattern)].flatMap(match => {\n const owner = getOwningObjectStart(structure, match.index)\n const objectStart = match.index + match[0].lastIndexOf('{')\n\n return owner !== undefined &&\n owners.has(owner) &&\n hasCodePropertySeparator(structure, match) &&\n structure[objectStart] === '{' ?\n [objectStart] :\n []\n })\n}\n\nconst getBasicOptionOwners = (\n searchable: string,\n structure: string\n): Set<number> => {\n const owners = getDefineConfigOptionOwners(searchable)\n\n for (const projectDefaultsOwner of getOwnedObjectPropertyStarts(\n searchable,\n structure,\n 'projectDefaults',\n owners\n )) {\n owners.add(projectDefaultsOwner)\n }\n\n const visitedProjectContainers = new Set<number>()\n let projectContainers = getOwnedObjectPropertyStarts(searchable, structure, 'projects', owners)\n\n while (projectContainers.length > 0) {\n for (const container of projectContainers) {\n visitedProjectContainers.add(container)\n\n for (const projectOwner of getDirectChildObjectStarts(structure, container)) {\n owners.add(projectOwner)\n }\n }\n\n projectContainers = getOwnedObjectPropertyStarts(searchable, structure, 'projects', owners)\n .filter(container => !visitedProjectContainers.has(container))\n }\n\n return owners\n}\n\nconst getOwnedPropertyMatches = (\n searchable: string,\n structure: string,\n property: string,\n owners: Set<number>\n): RegExpMatchArray[] => {\n const pattern = new RegExp(`\\\\b${property}\\\\b\\\\s*:`, 'g')\n\n return [...searchable.matchAll(pattern)].flatMap(match => {\n const owner = getOwningObjectStart(structure, match.index)\n\n return owner !== undefined && owners.has(owner) && hasCodePropertySeparator(structure, match) ? [match] : []\n })\n}\n\nconst modernizeLiteralFeatureArrays = (\n content: string\n): { changed: boolean, content: string, features: string[] } => {\n const searchable = maskNonCode(content, true)\n const structure = maskNonCode(content)\n const optionOwners = getBasicOptionOwners(searchable, structure)\n\n const selections = [...searchable.matchAll(\n /\\b(?:extensions|formats|libraries|testing|tools)\\b\\s*:\\s*\\[([\\s\\S]*?)\\]\\s*,?/g\n )].flatMap(match => {\n if (/\\/[/*]/.test(content.slice(match.index, match.index + match[0].length))) return []\n\n const features = match[1].split(',').filter(Boolean).map(toFeatureName)\n const owner = getOwningObjectStart(structure, match.index)\n\n if (\n owner === undefined ||\n !optionOwners.has(owner) ||\n !hasCodePropertySeparator(structure, match) ||\n features.length === 0 ||\n features.some(feature => feature === null)\n ) return []\n\n return [{\n end: match.index + match[0].length,\n features: features as string[],\n owner,\n start: match.index\n }]\n })\n\n if (selections.length === 0) return { changed: false, content, features: [] }\n\n const features = [...new Set(selections.flatMap(selection => selection.features))]\n const selectionsByOwner = new Map<number, typeof selections>()\n\n for (const selection of selections) {\n const ownedSelections = selectionsByOwner.get(selection.owner)\n\n if (ownedSelections) ownedSelections.push(selection)\n else selectionsByOwner.set(selection.owner, [selection])\n }\n\n const existingFeaturesByOwner = new Map<number, RegExpMatchArray>()\n\n for (const match of searchable.matchAll(/\\bfeatures\\b\\s*:\\s*\\{/g)) {\n const owner = getOwningObjectStart(structure, match.index)\n\n if (owner !== undefined && !existingFeaturesByOwner.has(owner)) {\n existingFeaturesByOwner.set(owner, match)\n }\n }\n\n const edits: { end: number, replacement: string, start: number }[] = []\n\n for (const [owner, ownedSelections] of selectionsByOwner) {\n const ownedFeatures = [...new Set(ownedSelections.flatMap(selection => selection.features))]\n const first = ownedSelections[0]\n const lineStart = content.lastIndexOf('\\n', first.start) + 1\n const indent = /^\\s*/.exec(content.slice(lineStart, first.start))?.[0] ?? ''\n const existingFeatures = existingFeaturesByOwner.get(owner)\n\n const featureBlock = existingFeatures ?\n `\\n${ownedFeatures.map(feature => `${indent} ${JSON.stringify(feature)}: true,`).join('\\n')}` :\n [\n 'features: {',\n ...ownedFeatures.map(feature => `${indent} ${JSON.stringify(feature)}: true,`),\n `${indent}},`\n ].join('\\n')\n\n for (const selection of ownedSelections) {\n edits.push({\n end: selection.end,\n replacement: !existingFeatures && selection === first ? featureBlock : '',\n start: selection.start\n })\n }\n\n if (existingFeatures) {\n const insertionIndex = (existingFeatures.index ?? 0) + existingFeatures[0].length\n\n edits.push({\n end: insertionIndex,\n replacement: featureBlock,\n start: insertionIndex\n })\n }\n }\n\n let updated = content\n\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n updated = `${updated.slice(0, edit.start)}${edit.replacement}${updated.slice(edit.end)}`\n }\n\n return { changed: updated !== content, content: updated, features }\n}\n\nconst modernizeConfigOptions = (\n content: string\n): { changes: string[], content: string } => {\n const changes: string[] = []\n let updated = content\n const searchable = maskNonCode(updated, true)\n const structure = maskNonCode(updated)\n const basicOptionOwners = getBasicOptionOwners(searchable, structure)\n\n const featureOwners = new Set(\n getOwnedPropertyMatches(searchable, structure, 'features', basicOptionOwners)\n .flatMap(match => {\n if (match.index === undefined) return []\n\n const owner = getOwningObjectStart(structure, match.index)\n\n return owner === undefined ? [] : [owner]\n })\n )\n\n const integrationMatches = getOwnedPropertyMatches(searchable, structure, 'integrations', basicOptionOwners)\n .filter(match => {\n if (match.index === undefined) return false\n\n const owner = getOwningObjectStart(structure, match.index)\n\n return owner !== undefined && !featureOwners.has(owner)\n })\n\n if (integrationMatches.length > 0) {\n updated = replaceCodeProperty(updated, 'integrations', 'features', integrationMatches)\n\n changes.push('Replaced the deprecated integrations map with features.')\n }\n\n const updatedSearchable = maskNonCode(updated, true)\n const updatedStructure = maskNonCode(updated)\n const optionOwners = getDefineConfigOptionOwners(updatedSearchable)\n const rootMatches = getOwnedPropertyMatches(updatedSearchable, updatedStructure, 'root', optionOwners)\n\n const rootAliasMatches = new Map([\n ['detectRootDir', getOwnedPropertyMatches(updatedSearchable, updatedStructure, 'detectRootDir', optionOwners)],\n ['tsconfigRootDir', getOwnedPropertyMatches(updatedSearchable, updatedStructure, 'tsconfigRootDir', optionOwners)]\n ])\n\n const rootAliases = [...rootAliasMatches]\n .filter(([, matches]) => matches.length > 0)\n .map(([alias]) => alias)\n\n if (rootMatches.length === 0 && rootAliases.length === 1) {\n const alias = rootAliases[0]\n\n updated = replaceCodeProperty(updated, alias, 'root', rootAliasMatches.get(alias))\n\n changes.push(`Replaced ${alias} with the v3 root option.`)\n } else if (rootAliases.length > 0) {\n changes.push(\n `Manual action required: consolidate ${rootAliases.join(' and ')} into root after confirming they resolve to the same directory.`\n )\n }\n\n const featureMigration = modernizeLiteralFeatureArrays(updated)\n\n if (featureMigration.changed) {\n updated = featureMigration.content\n\n changes.push(`Replaced literal category arrays with the v3 features map (${featureMigration.features.join(', ')}).`)\n }\n\n if (maskNonCode(updated, true).includes('better-tailwindcss/no-unknown-classes')) {\n changes.push(\n 'Manual action required: replace the raw better-tailwindcss/no-unknown-classes override with ' +\n 'projects[\"<scope>\"].tailwind.noUnknownClasses.'\n )\n }\n\n return { changes, content: updated }\n}\n\nexport const getExplicitConfigFeaturePackages = (content: string): string[] => {\n const packages = new Set<string>()\n const codeContent = maskNonCode(content)\n const searchableContent = maskNonCode(content, true)\n const optionOwners = getBasicOptionOwners(searchableContent, codeContent)\n\n const isBasicOption = (match: RegExpMatchArray): boolean => {\n const owner = getOwningObjectStart(codeContent, match.index ?? -1)\n\n return owner !== undefined && optionOwners.has(owner) && hasCodePropertySeparator(codeContent, match)\n }\n\n for (const category of Object.keys(FEATURE_PACKAGES) as (keyof typeof FEATURE_PACKAGES)[]) {\n const categorySelections = searchableContent.matchAll(\n new RegExp(`(?:\\\\b${category}\\\\b|['\"]${category}['\"])\\\\s*:\\\\s*\\\\[([\\\\s\\\\S]*?)\\\\]`, 'g')\n )\n\n for (const selection of categorySelections) {\n if (\n isBasicOption(selection) &&\n selection[1].trim()\n ) {\n packages.add(FEATURE_PACKAGES[category])\n\n break\n }\n }\n }\n\n const featureSelections = /(?:\\b(?:features|integrations)\\b|['\"](?:features|integrations)['\"])\\s*:\\s*\\{([\\s\\S]*?)\\}/g\n\n for (const selection of searchableContent.matchAll(featureSelections)) {\n if (!isBasicOption(selection)) continue\n\n const enabledFeaturePattern = /(?:['\"]([^'\"]+)['\"]|([a-zA-Z_$][\\w$-]*))\\s*:\\s*true\\b/g\n\n for (const match of selection[1].matchAll(enabledFeaturePattern)) {\n const featureName = (match[1] || match[2]).toLowerCase()\n const packageName = FEATURE_NAME_TO_PACKAGE.get(featureName)\n\n if (packageName) packages.add(packageName)\n }\n }\n\n const enumPresetPattern = /(?:\\bpreset\\b|['\"]preset['\"])\\s*:\\s*Preset\\.(All|App|CI|Library|Monorepo)/g\n\n for (const match of searchableContent.matchAll(enumPresetPattern)) {\n if (!isBasicOption(match)) continue\n\n const presetName = match[1].toLowerCase()\n\n for (const packageName of PRESET_FEATURE_PACKAGES[presetName] ?? []) {\n packages.add(packageName)\n }\n }\n\n const stringPresetPattern = /(?:\\bpreset\\b|['\"]preset['\"])\\s*:\\s*(['\"`])(all|app|ci|library|monorepo)\\1/g\n\n for (const match of searchableContent.matchAll(stringPresetPattern)) {\n if (!isBasicOption(match)) continue\n\n for (const packageName of PRESET_FEATURE_PACKAGES[match[2]] ?? []) {\n packages.add(packageName)\n }\n }\n\n const strictPattern = /(?:\\bstrict\\b|['\"]strict['\"])\\s*:\\s*(['\"`])pedantic\\1/g\n\n for (const match of searchableContent.matchAll(strictPattern)) {\n if (isBasicOption(match)) {\n packages.add(FEATURE_PACKAGES.extensions)\n\n break\n }\n }\n\n return [...packages]\n}\n\nconst replacePackageSpecifiers = (content: string, from: string, to: string): string => content.replace(\n /(\\b(?:from|import|export)\\s*(?:\\(\\s*)?|\\brequire\\s*\\(\\s*)(['\"])([^'\"]+)\\2/g,\n (statement, prefix: string, quote: string, specifier: string) => (\n specifier === from ? `${prefix}${quote}${to}${quote}` : statement\n )\n)\n\nexport const migrateConfigToV3 = (\n content: string,\n mode: 'full' | 'lean'\n): { changes: string[], content: string, featurePackages: string[] } => {\n const changes: string[] = []\n const featurePackages = new Set(getExplicitConfigFeaturePackages(content))\n let migrated = content\n const liteMigrated = replacePackageSpecifiers(migrated, LITE_PACKAGE, BASIC_PACKAGE)\n\n if (liteMigrated !== migrated) {\n migrated = liteMigrated\n\n changes.push('Replaced the Lite compatibility import with Basic.')\n }\n\n if (mode === 'full') {\n const fullMigrated = replacePackageSpecifiers(migrated, BASIC_PACKAGE, FULL_PACKAGE)\n\n if (fullMigrated !== migrated) {\n migrated = fullMigrated\n\n changes.push('Switched the root config import to the full bundle.')\n }\n }\n\n if (mode === 'lean') {\n const split = splitBasicIntegrationImports(migrated)\n\n migrated = split.content\n\n if (split.changed) {\n changes.push(`Moved feature factories to their granular packages: ${split.moved.join(', ')}.`)\n }\n\n for (const packageName of split.featurePackages) featurePackages.add(packageName)\n }\n\n for (const [removed, replacement] of Object.entries(REMOVED_ALIAS_REPLACEMENTS)) {\n const invokeReferences = FACTORY_ALIAS_REPLACEMENTS.has(removed)\n const updated = replaceImportedAlias(migrated, removed, replacement, invokeReferences)\n\n if (updated !== migrated) {\n migrated = updated\n\n changes.push(`Replaced ${removed} with ${replacement}${invokeReferences ? '()' : ''}.`)\n }\n }\n\n const remixMigrated = migrated.replace(\n /(\\bframeworks\\s*:\\s*\\{)([\\s\\S]*?)(\\})/,\n (_match, opening: string, body: string, closing: string) => (\n `${opening}${body.replaceAll(/\\bremix(\\s*:)/g, '\\'react-router\\'$1')}${closing}`\n )\n )\n\n if (remixMigrated !== migrated) {\n migrated = remixMigrated\n\n changes.push('Moved frameworks.remix to frameworks[\"react-router\"].')\n }\n\n const reactRouterMigrated = replacePackageSpecifiers(\n migrated,\n REMIX_PACKAGE,\n FRAMEWORK_PACKAGES['react-router']\n )\n\n if (reactRouterMigrated !== migrated) {\n migrated = reactRouterMigrated\n\n changes.push('Replaced the Remix package import with React Router.')\n }\n\n if (/\\bloadModule\\b/.test(migrated)) {\n changes.push('Manual action required: replace loadModule usage with createModuleLoader(resolver).')\n }\n\n const modernized = modernizeConfigOptions(migrated)\n\n migrated = modernized.content\n\n changes.push(...modernized.changes)\n\n return {\n changes,\n content: migrated,\n featurePackages: [...featurePackages]\n }\n}\n\nconst shouldUseFullBundle = (\n configContent: null | string,\n packageJson: Record<string, unknown>,\n forceFull: boolean\n): boolean => {\n if (forceFull) return true\n\n if (configContent?.includes(FULL_PACKAGE)) return true\n\n if (configContent) {\n const codeContent = maskNonCode(configContent)\n const searchableContent = maskNonCode(configContent, true)\n const optionOwners = getDefineConfigOptionOwners(searchableContent)\n\n const isRootOption = (match: RegExpMatchArray): boolean => {\n const owner = getOwningObjectStart(codeContent, match.index ?? -1)\n\n return owner !== undefined && optionOwners.has(owner) && hasCodePropertySeparator(codeContent, match)\n }\n\n const enumPresetPattern = /(?:\\bpreset\\b|['\"]preset['\"])\\s*:\\s*Preset\\.All/g\n\n for (const match of searchableContent.matchAll(enumPresetPattern)) {\n if (isRootOption(match)) return true\n }\n\n const stringPresetPattern = /(?:\\bpreset\\b|['\"]preset['\"])\\s*:\\s*(['\"`])all\\1/g\n\n for (const match of searchableContent.matchAll(stringPresetPattern)) {\n if (isRootOption(match)) return true\n }\n }\n\n return getDeclaredConfigPackages(packageJson).has(FULL_PACKAGE)\n}\n\nconst createInstallCommand = (\n packageManager: string,\n packages: string[],\n workspaceRoot = false\n): string => {\n const packageList = packages.join(' ')\n\n switch (packageManager) {\n case 'bun':\n return `bun add -d ${packageList}`\n\n case 'pnpm':\n return `pnpm add -D${workspaceRoot ? ' --workspace-root' : ''} ${packageList}`\n\n case 'yarn':\n return `yarn add -D ${packageList}`\n\n default:\n return `npm install -D ${packageList}`\n }\n}\n\nconst createManifestInstallCommand = (packageManager: string): string => {\n switch (packageManager) {\n case 'bun':\n return 'bun install'\n\n case 'pnpm':\n return 'pnpm install'\n\n case 'yarn':\n return 'yarn install'\n\n default:\n return 'npm install'\n }\n}\n\nconst migratePackageJson = (\n packageJson: Record<string, unknown>,\n context: V3MigrationContext,\n mode: 'full' | 'lean',\n configFeaturePackages: string[]\n): {\n changed: boolean\n packageJson: Record<string, unknown>\n packages: string[]\n preservesRuntimeFields: boolean\n} => {\n const next = structuredClone(packageJson)\n const preferredFields = getPreferredConfigDependencyFields(packageJson)\n const originalFields = new Map<string, DependencyField[]>()\n const migratedPackages = new Map<string, Set<DependencyField>>()\n\n const previouslyDeclared = new Set([\n ...getDeclaredConfigPackages(next),\n ...(context.declaredConfigPackages ?? [])\n ])\n\n const migratableConfigPackages = [\n BASIC_PACKAGE,\n FULL_PACKAGE,\n INTEGRATIONS_PACKAGE,\n LITE_PACKAGE,\n REMIX_PACKAGE,\n ...Object.values(FEATURE_PACKAGES),\n ...Object.values(FRAMEWORK_PACKAGES)\n ]\n\n for (const packageName of ['eslint', 'typescript', ...migratableConfigPackages]) {\n originalFields.set(packageName, getPackageDependencyFields(packageJson, packageName))\n }\n\n for (const field of dependencyFields) {\n const dependencies = { ...getDependencyRecord(next, field) }\n\n for (const packageName of [\n BASIC_PACKAGE,\n FULL_PACKAGE,\n INTEGRATIONS_PACKAGE,\n LITE_PACKAGE,\n REMIX_PACKAGE,\n ...Object.values(FEATURE_PACKAGES),\n ...Object.values(FRAMEWORK_PACKAGES)\n ]) {\n delete dependencies[packageName]\n }\n\n if (Object.keys(dependencies).length > 0) next[field] = dependencies\n else delete next[field]\n }\n\n const addPackage = (\n packageName: string,\n version: string,\n fields: DependencyField[] = originalFields.get(packageName) ?? []\n ): void => {\n const targetFields = fields.length > 0 ? fields : preferredFields\n\n for (const field of targetFields) {\n const dependencies = {\n ...getDependencyRecord(next, field),\n [packageName]: version\n }\n\n next[field] = dependencies\n\n const packageFields = migratedPackages.get(packageName) ?? new Set<DependencyField>()\n\n packageFields.add(field)\n\n migratedPackages.set(packageName, packageFields)\n }\n }\n\n addPackage(\n 'eslint',\n '^10.0.0',\n originalFields.get('eslint')?.length ? originalFields.get('eslint') : ['devDependencies']\n )\n\n const mainPackageFields = mode === 'full' ?\n [\n ...new Set(\n migratableConfigPackages.flatMap(packageName => originalFields.get(packageName) ?? [])\n )\n ] :\n [\n ...new Set([\n ...(originalFields.get(BASIC_PACKAGE) ?? []),\n ...(originalFields.get(FULL_PACKAGE) ?? []),\n ...(originalFields.get(LITE_PACKAGE) ?? [])\n ])\n ]\n\n addPackage(\n mode === 'full' ? FULL_PACKAGE : BASIC_PACKAGE,\n '^3.0.0',\n mainPackageFields\n )\n\n if (mode === 'lean') {\n const frameworkNames = new Set(context.frameworks)\n\n if (previouslyDeclared.has(REMIX_PACKAGE)) frameworkNames.add('react-router')\n\n for (const [framework, packageName] of Object.entries(FRAMEWORK_PACKAGES)) {\n if (frameworkNames.has(framework) || previouslyDeclared.has(packageName)) {\n const fields = [\n ...(originalFields.get(packageName) ?? []),\n ...(framework === 'react-router' ? originalFields.get(REMIX_PACKAGE) ?? [] : [])\n ]\n\n addPackage(packageName, '^3.0.0', [...new Set(fields)])\n }\n }\n\n const selectedFeaturePackages = new Set(configFeaturePackages)\n\n for (const category of Object.keys(FEATURE_PACKAGES) as (keyof typeof FEATURE_PACKAGES)[]) {\n const packageName = FEATURE_PACKAGES[category]\n\n if (context[category].length > 0 || previouslyDeclared.has(packageName)) {\n selectedFeaturePackages.add(packageName)\n }\n }\n\n for (const packageName of selectedFeaturePackages) {\n addPackage(packageName, '^3.0.0')\n }\n\n if (previouslyDeclared.has(INTEGRATIONS_PACKAGE)) {\n addPackage(INTEGRATIONS_PACKAGE, '^3.0.0')\n }\n }\n\n if (context.typescript) {\n const typescriptFields = originalFields.get('typescript') ?? []\n\n if (typescriptFields.length === 0) addPackage('typescript', '^5.0.0')\n }\n\n const peerDependenciesMeta = packageJson.peerDependenciesMeta\n\n if (\n peerDependenciesMeta &&\n typeof peerDependenciesMeta === 'object' &&\n !Array.isArray(peerDependenciesMeta)\n ) {\n const nextPeerNames = new Set(Object.keys(getDependencyRecord(next, 'peerDependencies')))\n const nextPeerMeta: Record<string, unknown> = {}\n\n for (const [packageName, metadata] of Object.entries(peerDependenciesMeta)) {\n let targetPackage = packageName\n\n if (!nextPeerNames.has(targetPackage)) {\n if (packageName === REMIX_PACKAGE) {\n targetPackage = FRAMEWORK_PACKAGES['react-router']\n } else if (\n [BASIC_PACKAGE, FULL_PACKAGE, LITE_PACKAGE].includes(packageName)\n ) {\n targetPackage = mode === 'full' ? FULL_PACKAGE : BASIC_PACKAGE\n } else if (mode === 'full' && migratableConfigPackages.includes(packageName)) {\n targetPackage = FULL_PACKAGE\n }\n }\n\n if (nextPeerNames.has(targetPackage)) nextPeerMeta[targetPackage] = metadata\n }\n\n if (Object.keys(nextPeerMeta).length > 0) next.peerDependenciesMeta = nextPeerMeta\n else delete next.peerDependenciesMeta\n }\n\n for (const field of dependencyFields) {\n const dependencies = getDependencyRecord(next, field)\n\n if (Object.keys(dependencies).length > 0) {\n next[field] = Object.fromEntries(\n Object.entries(dependencies).sort(([a], [b]) => a.localeCompare(b))\n )\n }\n }\n\n const packages = [...migratedPackages.keys()]\n .sort((a, b) => a.localeCompare(b))\n .map(name => {\n for (const field of dependencyFields) {\n const version = getDependencyRecord(next, field)[name]\n\n if (version) return `${name}@${version}`\n }\n\n return name\n })\n\n return {\n changed: JSON.stringify(next) !== JSON.stringify(packageJson),\n packageJson: next,\n packages,\n preservesRuntimeFields: [...migratedPackages.values()]\n .some(fields => [...fields].some(field => field !== 'devDependencies'))\n }\n}\n\nconst outputMigration = (result: MigrationResult, json: boolean): void => {\n if (json) {\n console.log(JSON.stringify(result, null, 2))\n\n return\n }\n\n console.log(`v2 to v3 migration plan (${result.mode}):`)\n\n if (result.changes.length === 0) {\n console.log('- No v3 migration changes are required.')\n } else {\n for (const change of result.changes) console.log(`- ${change.target}: ${change.detail}`)\n }\n\n console.log(`- Install command: ${result.installCommand}`)\n\n if (result.written.length > 0) {\n console.log(`- Updated: ${result.written.join(', ')}`)\n } else {\n console.log('- Dry run only; pass --write to apply safe changes.')\n }\n}\n\nexport const handleMigrateV3 = (\n cwd: string,\n context: V3MigrationContext,\n options: V3MigrationOptions = {}\n): void => {\n const packagePath = join(cwd, 'package.json')\n const packageJson = readPackageJson(cwd)\n const configPath = getConfigPath(cwd)\n const configContent = configPath ? readFileSync(configPath, 'utf8') : null\n const mode = shouldUseFullBundle(configContent, packageJson, options.full ?? false) ? 'full' : 'lean'\n const configMigration = configContent ? migrateConfigToV3(configContent, mode) : null\n\n const packageMigration = migratePackageJson(\n packageJson,\n context,\n mode,\n configMigration?.featurePackages ?? []\n )\n\n const changes: MigrationChange[] = []\n const written: string[] = []\n\n for (const detail of configMigration?.changes ?? []) {\n changes.push({ detail, target: configPath ? basename(configPath) : 'eslint.config.*' })\n }\n\n if (packageMigration.changed) {\n changes.push({ detail: 'Updated the ESLint v3 dependency set.', target: 'package.json' })\n }\n\n const configChanged = Boolean(configPath && configMigration && configMigration.content !== configContent)\n\n if (options.write) {\n if (configPath && configMigration && configChanged) {\n const backupPath = createBackupPath(configPath, 'v2')\n\n writeFileSync(backupPath, configContent ?? '')\n\n writeFileSync(configPath, configMigration.content)\n\n written.push(basename(configPath), basename(backupPath))\n }\n\n if (packageMigration.changed) {\n const backupPath = createBackupPath(packagePath, 'v2')\n\n writeFileSync(backupPath, `${JSON.stringify(packageJson, null, 2)}\\n`)\n\n writeFileSync(packagePath, `${JSON.stringify(packageMigration.packageJson, null, 2)}\\n`)\n\n written.push('package.json', basename(backupPath))\n }\n }\n\n const result: MigrationResult = {\n changes,\n configFile: configPath ? basename(configPath) : null,\n installCommand: packageMigration.preservesRuntimeFields ?\n createManifestInstallCommand(context.packageManager) :\n createInstallCommand(\n context.packageManager,\n packageMigration.packages,\n context.packageManager === 'pnpm' && existsSync(join(cwd, 'pnpm-workspace.yaml'))\n ),\n mode,\n packages: packageMigration.packages,\n written\n }\n\n outputMigration(result, options.json ?? false)\n\n if (options.check && changes.length > 0) process.exitCode = 1\n}\n"],"mappings":"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","names":["features"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type CatalogPreference = false | string | true;
|
|
2
|
+
declare const createInstallCommand: (packageManager: string, packages: string[], workspaceRoot?: boolean, catalog?: CatalogPreference) => string;
|
|
3
|
+
declare const createInstallInvocation: (packageManager: string, packages: string[], workspaceRoot?: boolean, catalog?: CatalogPreference) => [string, string[]];
|
|
4
|
+
declare const findPnpmWorkspaceRoot: (cwd: string) => string | undefined;
|
|
5
|
+
declare const detectPackageManager: (cwd: string) => string;
|
|
6
|
+
declare const getCatalogPreference: (packageJson: null | Record<string, unknown>) => CatalogPreference;
|
|
7
|
+
declare const getCompatibleConfigVersion: (packageJson: null | Record<string, unknown>, fallbackVersion: string, workspaceRoot?: string) => string;
|
|
8
|
+
declare const addCompatibleConfigVersions: (packages: string[], version: string) => string[];
|
|
9
|
+
|
|
10
|
+
export { type CatalogPreference, addCompatibleConfigVersions, createInstallCommand, createInstallInvocation, detectPackageManager, findPnpmWorkspaceRoot, getCatalogPreference, getCompatibleConfigVersion };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
const BASIC_PACKAGE_NAME = "@santi020k/eslint-config-basic";
|
|
4
|
+
const INTEGRATIONS_PACKAGE_NAME = "@santi020k/eslint-config-integrations";
|
|
5
|
+
const LITE_PACKAGE_NAME = "@santi020k/eslint-config-lite";
|
|
6
|
+
const createInstallCommand = (packageManager, packages, workspaceRoot = false, catalog = false) => {
|
|
7
|
+
const packageList = packages.join(" ");
|
|
8
|
+
switch (packageManager) {
|
|
9
|
+
case "bun":
|
|
10
|
+
return `bun add -d ${packageList}`;
|
|
11
|
+
case "npm":
|
|
12
|
+
return `npm install -D ${packageList}`;
|
|
13
|
+
case "yarn":
|
|
14
|
+
return `yarn add -D ${packageList}`;
|
|
15
|
+
default:
|
|
16
|
+
return `pnpm add -D${workspaceRoot ? " --workspace-root" : ""}` + (catalog === true ? " --save-catalog" : "") + `${typeof catalog === "string" ? ` --save-catalog-name=${catalog}` : ""} ${packageList}`;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const createInstallInvocation = (packageManager, packages, workspaceRoot = false, catalog = false) => {
|
|
20
|
+
switch (packageManager) {
|
|
21
|
+
case "bun":
|
|
22
|
+
return ["bun", ["add", "-d", ...packages]];
|
|
23
|
+
case "npm":
|
|
24
|
+
return ["npm", ["install", "-D", ...packages]];
|
|
25
|
+
case "yarn":
|
|
26
|
+
return ["yarn", ["add", "-D", ...packages]];
|
|
27
|
+
default:
|
|
28
|
+
return ["pnpm", [
|
|
29
|
+
"add",
|
|
30
|
+
"-D",
|
|
31
|
+
...workspaceRoot ? ["--workspace-root"] : [],
|
|
32
|
+
...catalog === true ? ["--save-catalog"] : [],
|
|
33
|
+
...typeof catalog === "string" ? [`--save-catalog-name=${catalog}`] : [],
|
|
34
|
+
...packages
|
|
35
|
+
]];
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const findPnpmWorkspaceRoot = (cwd) => {
|
|
39
|
+
let current = cwd;
|
|
40
|
+
for (; ; ) {
|
|
41
|
+
if (existsSync(join(current, "pnpm-workspace.yaml"))) return current;
|
|
42
|
+
const parent = dirname(current);
|
|
43
|
+
if (parent === current) return void 0;
|
|
44
|
+
current = parent;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const detectPackageManager = (cwd) => {
|
|
48
|
+
if (findPnpmWorkspaceRoot(cwd) || existsSync(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
49
|
+
if (existsSync(join(cwd, "yarn.lock"))) return "yarn";
|
|
50
|
+
if (existsSync(join(cwd, "bun.lockb")) || existsSync(join(cwd, "bun.lock"))) return "bun";
|
|
51
|
+
return "npm";
|
|
52
|
+
};
|
|
53
|
+
const parseCatalog = (value) => {
|
|
54
|
+
if (typeof value !== "string" || !value.startsWith("catalog:")) return false;
|
|
55
|
+
const name = value.slice("catalog:".length);
|
|
56
|
+
return name && name !== "default" ? name : true;
|
|
57
|
+
};
|
|
58
|
+
const isDependencyRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
59
|
+
const getDependencyRecords = (packageJson) => ["devDependencies", "dependencies"].map((field) => packageJson?.[field]).filter(isDependencyRecord);
|
|
60
|
+
const getCatalogPreference = (packageJson) => {
|
|
61
|
+
const dependencyRecords = getDependencyRecords(packageJson);
|
|
62
|
+
const basicCatalog = dependencyRecords.map((dependencies) => parseCatalog(Reflect.get(dependencies, BASIC_PACKAGE_NAME))).find(Boolean);
|
|
63
|
+
if (basicCatalog) return basicCatalog;
|
|
64
|
+
return dependencyRecords.flatMap((dependencies) => Object.values(dependencies)).map(parseCatalog).find(Boolean) ?? false;
|
|
65
|
+
};
|
|
66
|
+
const parseYamlMappingLine = (line) => {
|
|
67
|
+
const match = /^(\s*)(?:"([^"]+)"|'([^']+)'|([^'"].*?))\s*:\s*(.*?)\s*$/.exec(line);
|
|
68
|
+
if (!match) return void 0;
|
|
69
|
+
const value = match[5].replace(/\s+#.*$/, "").trim();
|
|
70
|
+
const key = match[2] || match[3] || match[4];
|
|
71
|
+
return {
|
|
72
|
+
indent: match[1].length,
|
|
73
|
+
key: key.trim(),
|
|
74
|
+
value: /^(['"]).*\1$/.test(value) ? value.slice(1, -1) : value
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
const findRootMapping = (lines, key) => lines.findIndex((line) => {
|
|
78
|
+
const mapping = parseYamlMappingLine(line);
|
|
79
|
+
return mapping?.indent === 0 && mapping.key === key && mapping.value === "";
|
|
80
|
+
});
|
|
81
|
+
const findNamedCatalogSection = (lines, rootIndex, catalog) => {
|
|
82
|
+
if (rootIndex < 0) return void 0;
|
|
83
|
+
for (let index = rootIndex + 1; index < lines.length; index++) {
|
|
84
|
+
const mapping = parseYamlMappingLine(lines.at(index) ?? "");
|
|
85
|
+
if (!mapping) continue;
|
|
86
|
+
if (mapping.indent === 0) break;
|
|
87
|
+
if (mapping.key === catalog && mapping.value === "") {
|
|
88
|
+
return { index, indent: mapping.indent };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return void 0;
|
|
92
|
+
};
|
|
93
|
+
const findCatalogSection = (lines, catalog) => {
|
|
94
|
+
if (catalog !== true) return findNamedCatalogSection(lines, findRootMapping(lines, "catalogs"), catalog);
|
|
95
|
+
const rootIndex = findRootMapping(lines, "catalog");
|
|
96
|
+
return rootIndex < 0 ? void 0 : { index: rootIndex, indent: 0 };
|
|
97
|
+
};
|
|
98
|
+
const getCatalogVersion = (workspaceRoot, packageName, catalog) => {
|
|
99
|
+
const workspacePath = join(workspaceRoot, "pnpm-workspace.yaml");
|
|
100
|
+
if (!existsSync(workspacePath)) return void 0;
|
|
101
|
+
const lines = readFileSync(workspacePath, "utf8").split(/\r?\n/);
|
|
102
|
+
const section = findCatalogSection(lines, catalog);
|
|
103
|
+
if (!section) return void 0;
|
|
104
|
+
for (let index = section.index + 1; index < lines.length; index++) {
|
|
105
|
+
const mapping = parseYamlMappingLine(lines.at(index) ?? "");
|
|
106
|
+
if (!mapping) continue;
|
|
107
|
+
if (mapping.indent <= section.indent) break;
|
|
108
|
+
if (mapping.key === packageName) return mapping.value || void 0;
|
|
109
|
+
}
|
|
110
|
+
return void 0;
|
|
111
|
+
};
|
|
112
|
+
const getCompatibleConfigVersion = (packageJson, fallbackVersion, workspaceRoot) => {
|
|
113
|
+
const basicSpec = ["devDependencies", "dependencies", "peerDependencies"].map((field) => packageJson?.[field]).filter(isDependencyRecord).map((dependencies) => dependencies[BASIC_PACKAGE_NAME]).find((value) => typeof value === "string");
|
|
114
|
+
const catalogName = basicSpec?.startsWith("catalog:") ? basicSpec.slice("catalog:".length) : void 0;
|
|
115
|
+
let selectedCatalog;
|
|
116
|
+
if (catalogName !== void 0) selectedCatalog = catalogName && catalogName !== "default" ? catalogName : true;
|
|
117
|
+
const resolvedSpec = selectedCatalog && workspaceRoot ? getCatalogVersion(workspaceRoot, BASIC_PACKAGE_NAME, selectedCatalog) : basicSpec;
|
|
118
|
+
const match = /(\d+)\.(\d+)\.(\d+)/.exec(resolvedSpec ?? fallbackVersion);
|
|
119
|
+
return match ? `^${match[1]}.${match[2]}.${match[3]}` : "^3.1.0";
|
|
120
|
+
};
|
|
121
|
+
const addCompatibleConfigVersions = (packages, version) => {
|
|
122
|
+
const major = /\d+/.exec(version)?.[0];
|
|
123
|
+
const companionVersion = major ? `^${major}.0.0` : version;
|
|
124
|
+
return packages.map((packageName) => packageName.startsWith("@santi020k/eslint-config-") && packageName !== LITE_PACKAGE_NAME && packageName !== INTEGRATIONS_PACKAGE_NAME ? `${packageName}@${packageName === BASIC_PACKAGE_NAME ? version : companionVersion}` : packageName);
|
|
125
|
+
};
|
|
126
|
+
export {
|
|
127
|
+
addCompatibleConfigVersions,
|
|
128
|
+
createInstallCommand,
|
|
129
|
+
createInstallInvocation,
|
|
130
|
+
detectPackageManager,
|
|
131
|
+
findPnpmWorkspaceRoot,
|
|
132
|
+
getCatalogPreference,
|
|
133
|
+
getCompatibleConfigVersion
|
|
134
|
+
};
|
|
135
|
+
//# sourceMappingURL=cli-package-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-package-manager.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\nconst BASIC_PACKAGE_NAME = '@santi020k/eslint-config-basic'\nconst INTEGRATIONS_PACKAGE_NAME = '@santi020k/eslint-config-integrations'\nconst LITE_PACKAGE_NAME = '@santi020k/eslint-config-lite'\n\nexport type CatalogPreference = false | string | true\n\nexport const createInstallCommand = (\n packageManager: string,\n packages: string[],\n workspaceRoot = false,\n catalog: CatalogPreference = false\n): string => {\n const packageList = packages.join(' ')\n\n switch (packageManager) {\n case 'bun':\n return `bun add -d ${packageList}`\n\n case 'npm':\n return `npm install -D ${packageList}`\n\n case 'yarn':\n return `yarn add -D ${packageList}`\n\n default:\n return `pnpm add -D${workspaceRoot ? ' --workspace-root' : ''}` +\n (catalog === true ? ' --save-catalog' : '') +\n `${typeof catalog === 'string' ? ` --save-catalog-name=${catalog}` : ''} ${packageList}`\n }\n}\n\nexport const createInstallInvocation = (\n packageManager: string,\n packages: string[],\n workspaceRoot = false,\n catalog: CatalogPreference = false\n): [string, string[]] => {\n switch (packageManager) {\n case 'bun':\n return ['bun', ['add', '-d', ...packages]]\n\n case 'npm':\n return ['npm', ['install', '-D', ...packages]]\n\n case 'yarn':\n return ['yarn', ['add', '-D', ...packages]]\n\n default:\n return ['pnpm', [\n 'add',\n '-D',\n ...(workspaceRoot ? ['--workspace-root'] : []),\n ...(catalog === true ? ['--save-catalog'] : []),\n ...(typeof catalog === 'string' ? [`--save-catalog-name=${catalog}`] : []),\n ...packages\n ]]\n }\n}\n\nexport const findPnpmWorkspaceRoot = (cwd: string): string | undefined => {\n let current = cwd\n\n for (;;) {\n if (existsSync(join(current, 'pnpm-workspace.yaml'))) return current\n\n const parent = dirname(current)\n\n if (parent === current) return undefined\n\n current = parent\n }\n}\n\nexport const detectPackageManager = (cwd: string): string => {\n if (findPnpmWorkspaceRoot(cwd) || existsSync(join(cwd, 'pnpm-lock.yaml'))) return 'pnpm'\n\n if (existsSync(join(cwd, 'yarn.lock'))) return 'yarn'\n\n if (existsSync(join(cwd, 'bun.lockb')) || existsSync(join(cwd, 'bun.lock'))) return 'bun'\n\n return 'npm'\n}\n\nconst parseCatalog = (value: unknown): CatalogPreference => {\n if (typeof value !== 'string' || !value.startsWith('catalog:')) return false\n\n const name = value.slice('catalog:'.length)\n\n return name && name !== 'default' ? name : true\n}\n\nconst isDependencyRecord = (value: unknown): value is Record<string, unknown> => (\n Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n)\n\nconst getDependencyRecords = (\n packageJson: null | Record<string, unknown>\n): Record<string, unknown>[] => ['devDependencies', 'dependencies']\n .map(field => packageJson?.[field])\n .filter(isDependencyRecord)\n\nexport const getCatalogPreference = (\n packageJson: null | Record<string, unknown>\n): CatalogPreference => {\n const dependencyRecords = getDependencyRecords(packageJson)\n\n const basicCatalog = dependencyRecords\n .map(dependencies => parseCatalog(Reflect.get(dependencies, BASIC_PACKAGE_NAME)))\n .find(Boolean)\n\n if (basicCatalog) return basicCatalog\n\n return dependencyRecords\n .flatMap(dependencies => Object.values(dependencies))\n .map(parseCatalog)\n .find(Boolean) ?? false\n}\n\ninterface YamlMappingLine {\n indent: number\n key: string\n value: string\n}\n\nconst parseYamlMappingLine = (line: string): undefined | YamlMappingLine => {\n const match = /^(\\s*)(?:\"([^\"]+)\"|'([^']+)'|([^'\"].*?))\\s*:\\s*(.*?)\\s*$/.exec(line)\n\n if (!match) return undefined\n\n const value = match[5].replace(/\\s+#.*$/, '').trim()\n const key = match[2] || match[3] || match[4]\n\n return {\n indent: match[1].length,\n key: key.trim(),\n value: /^(['\"]).*\\1$/.test(value) ? value.slice(1, -1) : value\n }\n}\n\nconst findRootMapping = (lines: string[], key: string): number => lines.findIndex(line => {\n const mapping = parseYamlMappingLine(line)\n\n return mapping?.indent === 0 && mapping.key === key && mapping.value === ''\n})\n\nconst findNamedCatalogSection = (\n lines: string[],\n rootIndex: number,\n catalog: string\n): { index: number, indent: number } | undefined => {\n if (rootIndex < 0) return undefined\n\n for (let index = rootIndex + 1; index < lines.length; index++) {\n const mapping = parseYamlMappingLine(lines.at(index) ?? '')\n\n if (!mapping) continue\n\n if (mapping.indent === 0) break\n\n if (mapping.key === catalog && mapping.value === '') {\n return { index, indent: mapping.indent }\n }\n }\n\n return undefined\n}\n\nconst findCatalogSection = (\n lines: string[],\n catalog: string | true\n): { index: number, indent: number } | undefined => {\n if (catalog !== true) return findNamedCatalogSection(lines, findRootMapping(lines, 'catalogs'), catalog)\n\n const rootIndex = findRootMapping(lines, 'catalog')\n\n return rootIndex < 0 ? undefined : { index: rootIndex, indent: 0 }\n}\n\nconst getCatalogVersion = (\n workspaceRoot: string,\n packageName: string,\n catalog: string | true\n): string | undefined => {\n const workspacePath = join(workspaceRoot, 'pnpm-workspace.yaml')\n\n if (!existsSync(workspacePath)) return undefined\n\n const lines = readFileSync(workspacePath, 'utf8').split(/\\r?\\n/)\n const section = findCatalogSection(lines, catalog)\n\n if (!section) return undefined\n\n for (let index = section.index + 1; index < lines.length; index++) {\n const mapping = parseYamlMappingLine(lines.at(index) ?? '')\n\n if (!mapping) continue\n\n if (mapping.indent <= section.indent) break\n\n if (mapping.key === packageName) return mapping.value || undefined\n }\n\n return undefined\n}\n\nexport const getCompatibleConfigVersion = (\n packageJson: null | Record<string, unknown>,\n fallbackVersion: string,\n workspaceRoot?: string\n): string => {\n const basicSpec = ['devDependencies', 'dependencies', 'peerDependencies']\n .map(field => packageJson?.[field])\n .filter(isDependencyRecord)\n .map(dependencies => dependencies[BASIC_PACKAGE_NAME])\n .find((value): value is string => typeof value === 'string')\n\n const catalogName = basicSpec?.startsWith('catalog:') ? basicSpec.slice('catalog:'.length) : undefined\n let selectedCatalog: string | true | undefined\n\n if (catalogName !== undefined) selectedCatalog = catalogName && catalogName !== 'default' ? catalogName : true\n\n const resolvedSpec = selectedCatalog && workspaceRoot ?\n getCatalogVersion(workspaceRoot, BASIC_PACKAGE_NAME, selectedCatalog) :\n basicSpec\n\n const match = /(\\d+)\\.(\\d+)\\.(\\d+)/.exec(resolvedSpec ?? fallbackVersion)\n\n return match ? `^${match[1]}.${match[2]}.${match[3]}` : '^3.1.0'\n}\n\nexport const addCompatibleConfigVersions = (\n packages: string[],\n version: string\n): string[] => {\n const major = /\\d+/.exec(version)?.[0]\n const companionVersion = major ? `^${major}.0.0` : version\n\n return packages.map(packageName => packageName.startsWith('@santi020k/eslint-config-') &&\n packageName !== LITE_PACKAGE_NAME &&\n packageName !== INTEGRATIONS_PACKAGE_NAME ?\n `${packageName}@${packageName === BASIC_PACKAGE_NAME ? version : companionVersion}` :\n packageName)\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli-preset.d.ts
CHANGED
|
@@ -1,17 +1,51 @@
|
|
|
1
1
|
import { EslintConfigOptions } from '@santi020k/eslint-config-core';
|
|
2
|
+
import { CommandRunner } from './cli-workflows.js';
|
|
2
3
|
|
|
3
4
|
interface ExplainPresetOptions {
|
|
5
|
+
analyzeSource?: boolean;
|
|
4
6
|
compatibility?: boolean;
|
|
5
7
|
file?: string;
|
|
8
|
+
files?: string[];
|
|
6
9
|
json?: boolean;
|
|
7
10
|
output?: string;
|
|
8
11
|
}
|
|
9
|
-
|
|
12
|
+
interface CreatePresetReportOptions {
|
|
13
|
+
analyzeSource?: boolean;
|
|
14
|
+
sourceFiles?: string[];
|
|
15
|
+
typescriptRunner?: CommandRunner;
|
|
16
|
+
}
|
|
17
|
+
interface FindingSummary {
|
|
18
|
+
errors: number;
|
|
19
|
+
fixable: number;
|
|
20
|
+
total: number;
|
|
21
|
+
warnings: number;
|
|
22
|
+
}
|
|
23
|
+
interface TypeScriptDiagnostic {
|
|
24
|
+
code: string;
|
|
25
|
+
config: string;
|
|
26
|
+
message: string;
|
|
27
|
+
}
|
|
28
|
+
declare const createTypeScriptPreflight: (cwd: string, configuredProjects?: string[], runner?: CommandRunner) => {
|
|
29
|
+
configs: never[];
|
|
30
|
+
diagnosticCount: number;
|
|
31
|
+
rootDiagnostics: TypeScriptDiagnostic[];
|
|
32
|
+
status: "skipped";
|
|
33
|
+
} | {
|
|
34
|
+
configs: {
|
|
35
|
+
config: string;
|
|
36
|
+
status: number;
|
|
37
|
+
}[];
|
|
38
|
+
diagnosticCount: number;
|
|
39
|
+
rootDiagnostics: TypeScriptDiagnostic[];
|
|
40
|
+
status: "failed" | "passed";
|
|
41
|
+
};
|
|
42
|
+
declare const createPresetReport: (cwd: string, presetName: string, file?: string, options?: CreatePresetReportOptions) => Promise<{
|
|
10
43
|
added: Record<string, unknown>;
|
|
11
44
|
changed: Record<string, {
|
|
12
45
|
from: unknown;
|
|
13
46
|
to: unknown;
|
|
14
47
|
}>;
|
|
48
|
+
compatibilityScope: string;
|
|
15
49
|
file: string;
|
|
16
50
|
groups: {
|
|
17
51
|
[k: string]: string[];
|
|
@@ -20,6 +54,44 @@ declare const createPresetReport: (cwd: string, presetName: string, file?: strin
|
|
|
20
54
|
preset: string;
|
|
21
55
|
presetOptions: Partial<EslintConfigOptions>;
|
|
22
56
|
removed: Record<string, unknown>;
|
|
57
|
+
sourceAnalysis: {
|
|
58
|
+
autofixPreview: {
|
|
59
|
+
changedFileCount: number;
|
|
60
|
+
changedFiles: string[];
|
|
61
|
+
estimatedChangedLines: number;
|
|
62
|
+
remainingErrors: number;
|
|
63
|
+
remainingFixableRules: string[];
|
|
64
|
+
remainingWarnings: number;
|
|
65
|
+
};
|
|
66
|
+
byCategory: Record<string, FindingSummary>;
|
|
67
|
+
byFileType: Record<string, FindingSummary>;
|
|
68
|
+
byRule: Record<string, FindingSummary>;
|
|
69
|
+
lintTargets: string[];
|
|
70
|
+
nonFormattingErrors: {
|
|
71
|
+
count: number;
|
|
72
|
+
rules: string[];
|
|
73
|
+
};
|
|
74
|
+
typescriptPreflight: {
|
|
75
|
+
configs: never[];
|
|
76
|
+
diagnosticCount: number;
|
|
77
|
+
rootDiagnostics: TypeScriptDiagnostic[];
|
|
78
|
+
status: "skipped";
|
|
79
|
+
} | {
|
|
80
|
+
configs: {
|
|
81
|
+
config: string;
|
|
82
|
+
status: number;
|
|
83
|
+
}[];
|
|
84
|
+
diagnosticCount: number;
|
|
85
|
+
rootDiagnostics: TypeScriptDiagnostic[];
|
|
86
|
+
status: "failed" | "passed";
|
|
87
|
+
};
|
|
88
|
+
totals: {
|
|
89
|
+
errors: number;
|
|
90
|
+
files: number;
|
|
91
|
+
findings: number;
|
|
92
|
+
warnings: number;
|
|
93
|
+
};
|
|
94
|
+
} | null;
|
|
23
95
|
totals: {
|
|
24
96
|
added: number;
|
|
25
97
|
changed: number;
|
|
@@ -28,4 +100,4 @@ declare const createPresetReport: (cwd: string, presetName: string, file?: strin
|
|
|
28
100
|
}>;
|
|
29
101
|
declare const handleExplainPreset: (cwd: string | undefined, preset: string, options?: ExplainPresetOptions) => Promise<void>;
|
|
30
102
|
|
|
31
|
-
export { type ExplainPresetOptions, createPresetReport, handleExplainPreset };
|
|
103
|
+
export { type ExplainPresetOptions, createPresetReport, createTypeScriptPreflight, handleExplainPreset };
|