@coderwyd/eslint-config
Version:
Donny's ESLint config
228 lines (217 loc) • 7.14 kB
JavaScript
// src/cli/index.ts
import process2 from "node:process";
import c3 from "picocolors";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
// src/cli/constants.ts
import c from "picocolors";
// package.json
var version = "4.2.1";
var devDependencies = {
"@antfu/ni": "^24.3.0",
"@eslint-react/eslint-plugin": "^1.38.0",
"@eslint/config-inspector": "^1.0.2",
"@types/eslint-config-prettier": "^6.11.3",
"@types/node": "^22.13.13",
"@types/prompts": "^2.4.9",
"@types/yargs": "^17.0.33",
"@unocss/eslint-plugin": "^66.1.0-beta.6",
bumpp: "^10.1.0",
eslint: "^9.23.0",
"eslint-plugin-react-compiler": "19.0.0-beta-e552027-20250112",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.19",
"eslint-plugin-svelte": "^3.3.3",
"eslint-plugin-tailwindcss": "^3.18.0",
jiti: "^2.4.2",
"nano-staged": "^0.8.0",
"simple-git-hooks": "^2.12.1",
svelte: "^5.25.3",
"svelte-eslint-parser": "^1.1.0",
tsup: "^8.4.0",
typescript: "^5.8.2"
};
// src/cli/constants.ts
var ARROW = c.cyan("\u2192");
var CHECK = c.green("\u2714");
var CROSS = c.red("\u2718");
var WARN = c.yellow("\u2139");
var eslintVersion = devDependencies.eslint;
var vscodeSettingsString = `
"editor.formatOnSave": true,
// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},
`;
// src/cli/run.ts
import fs from "node:fs";
import fsp from "node:fs/promises";
import path from "node:path";
import process from "node:process";
import parse from "parse-gitignore";
import c2 from "picocolors";
import prompts from "prompts";
// src/cli/utils.ts
import { execSync } from "node:child_process";
function isGitClean() {
try {
execSync("git diff-index --quiet HEAD --");
return true;
} catch {
return false;
}
}
// src/cli/run.ts
async function run(options = {}) {
const SKIP_PROMPT = !!process.env.SKIP_PROMPT || options.yes;
const SKIP_GIT_CHECK = !!process.env.SKIP_GIT_CHECK;
const cwd = process.cwd();
const pathFlatConfig = path.join(cwd, "eslint.config.js");
const pathPackageJSON = path.join(cwd, "package.json");
const pathESLintIngore = path.join(cwd, ".eslintignore");
if (fs.existsSync(pathFlatConfig)) {
console.log(
c2.yellow(
`${WARN} eslint.config.js already exists, migration wizard exited.`
)
);
return process.exit(1);
}
if (!SKIP_GIT_CHECK && !isGitClean()) {
const { confirmed } = await prompts({
initial: false,
message: "There are uncommitted changes in the current repository, are you sure to continue?",
name: "confirmed",
type: "confirm"
});
if (!confirmed) return process.exit(1);
}
console.log(c2.cyan(`${ARROW} bumping @coderwyd/eslint-config to v${version}`));
const pkgContent = await fsp.readFile(pathPackageJSON, "utf-8");
const pkg = JSON.parse(pkgContent);
pkg.devDependencies ??= {};
pkg.devDependencies["@coderwyd/eslint-config"] = `^${version}`;
if (!pkg.devDependencies.eslint) pkg.devDependencies.eslint = eslintVersion;
await fsp.writeFile(pathPackageJSON, JSON.stringify(pkg, null, 2));
console.log(c2.green(`${CHECK} changes wrote to package.json`));
const eslintIgnores = [];
if (fs.existsSync(pathESLintIngore)) {
console.log(c2.cyan(`${ARROW} migrating existing .eslintignore`));
const content = await fsp.readFile(pathESLintIngore, "utf-8");
const parsed = parse(content);
const globs = parsed.globs();
for (const glob of globs) {
if (glob.type === "ignore") {
eslintIgnores.push(...glob.patterns);
} else if (glob.type === "unignore") {
eslintIgnores.push(
...glob.patterns.map((pattern) => `!${pattern}`)
);
}
}
}
let eslintConfigContent = "";
const coderwydConfig = `${eslintIgnores.length > 0 ? `ignores: ${JSON.stringify(eslintIgnores)}` : ""}`;
if (pkg.type === "module") {
eslintConfigContent = `
import { defineConfig } from '@coderwyd/eslint-config'
export default defineConfig({
${coderwydConfig}
})
`.trimStart();
} else {
eslintConfigContent = `
const { defineConfig } = require('@coderwyd/eslint-config')
module.exports = defineConfig({
${coderwydConfig}
})
`.trimStart();
}
await fsp.writeFile(pathFlatConfig, eslintConfigContent);
console.log(c2.green(`${CHECK} created eslint.config.js`));
const files = fs.readdirSync(cwd);
const legacyConfig = [];
files.forEach((file) => {
if (/eslint|prettier/.test(file) && !/eslint.config./.test(file))
legacyConfig.push(file);
});
if (legacyConfig.length > 0) {
console.log(`${WARN} you can now remove those files manually:`);
console.log(` ${c2.dim(legacyConfig.join(", "))}`);
}
let promptResult = {
updateVscodeSettings: true
};
if (!SKIP_PROMPT) {
try {
promptResult = await prompts(
{
initial: true,
message: "Update .vscode/settings.json for better VS Code experience?",
name: "updateVscodeSettings",
type: "confirm"
},
{
onCancel: () => {
throw new Error(`Cancelled`);
}
}
);
} catch (error) {
console.log(error.message);
return;
}
}
if (promptResult?.updateVscodeSettings ?? true) {
const dotVscodePath = path.join(cwd, ".vscode");
const settingsPath = path.join(dotVscodePath, "settings.json");
if (!fs.existsSync(dotVscodePath))
await fsp.mkdir(dotVscodePath, { recursive: true });
if (!fs.existsSync(settingsPath)) {
await fsp.writeFile(settingsPath, `{${vscodeSettingsString}}
`, "utf-8");
console.log(c2.green(`${CHECK} created .vscode/settings.json`));
} else {
let settingsContent = await fsp.readFile(settingsPath, "utf8");
settingsContent = settingsContent.trim().replace(/\s*\}$/, "");
settingsContent += settingsContent.endsWith(",") || settingsContent.endsWith("{") ? "" : ",";
settingsContent += `${vscodeSettingsString}}
`;
await fsp.writeFile(settingsPath, settingsContent, "utf-8");
console.log(c2.green(`${CHECK} updated .vscode/settings.json`));
}
}
console.log(c2.green(`${CHECK} migration completed`));
console.log(
`Now you can update the dependencies and run ${c2.blue("eslint . --fix")}
`
);
}
// src/cli/index.ts
function header() {
console.log(`
${c3.green(`@coderwyd/eslint-config `)}${c3.dim(`v${version}`)}`);
}
var instance = yargs(hideBin(process2.argv)).scriptName("@coderwyd/eslint-config").usage("").command(
"*",
"Run the initialization or migration",
(args) => args.option("yes", {
alias: "y",
description: "Skip prompts and use default values",
type: "boolean"
}).help(),
async (args) => {
header();
console.log();
try {
await run(args);
} catch (error) {
console.error(c3.inverse(c3.red(" Failed to migrate ")));
console.error(c3.red(`${CROSS} ${String(error)}`));
process2.exit(1);
}
}
).showHelpOnFail(false).alias("h", "help").version("version", version).alias("v", "version");
instance.help().argv;