Files
overlookmotel fe3b32ee71 feat(linter/plugins): add oxlint-plugin-eslint package (#20009)
Closes #19746.

Add `oxlint-plugin-eslint` plugin which exports all ESLint's built-in rules as a JS plugin which can be used with Oxlint.

The code for rules is lazy-loaded on first use, so just using the plugin doesn't load the code for all the rules, only the ones which the user actually uses. However, the `meta` property of each rule is provided eagerly, so that `registerPlugin` in Oxlint can load the plugin without triggering the getters which lazy-load rule code.

All ESLint's rule code is bundled into this plugin package, so the package has no dependencies. This has a few advantages:

1. We control the version of ESLint which the rules are taken from.
2. Avoids "works on my machine" unreproducible bug reports due to differing ESLint versions.
3. Avoids relying on ESLint's `eslint/use-at-your-own-risk` export, which could change without warning.

At present, the plugin contains *all* ESLint's rules, including ones which are natively implemented in Oxlint.

We might choose to scale it back to include only the rules which Oxlint doesn't natively implement. But then we need to consider what happens when we implement more rules in future: Do they disappear from this package without warning? Would that be considered a breaking change? If it would, how long do we keep them in this package?

I propose that in the interests of getting this useful feature released without having to decide all these issues, we just go with it as is for now. JS plugins are not yet stable, so at present we can still make changes later on if we need to, without breaking any promises.
2026-03-09 17:22:40 +00:00

43 lines
1.5 KiB
TypeScript
Executable File

// oxlint-disable no-console
import { execSync } from "node:child_process";
import { copyFileSync, readdirSync, rmSync } from "node:fs";
import { join } from "node:path";
import generatePluginEslint from "./generate-plugin-eslint.ts";
const oxlintDirPath = join(import.meta.dirname, ".."),
srcDirPath = join(oxlintDirPath, "src-js"),
distDirPath = join(oxlintDirPath, "dist"),
distPkgPluginsDirPath = join(oxlintDirPath, "dist-pkg-plugins"),
distPkgPluginEslintDirPath = join(oxlintDirPath, "dist-pkg-plugin-eslint");
// Delete `dist-pkg-plugins` directory
console.log("Deleting `dist-pkg-plugins` directory...");
rmSync(distPkgPluginsDirPath, { recursive: true, force: true });
// Delete `dist-pkg-plugin-eslint` directory
console.log("Deleting `dist-pkg-plugin-eslint` directory...");
rmSync(distPkgPluginEslintDirPath, { recursive: true, force: true });
// Generate plugin-eslint files
console.log("Generating oxlint-plugin-eslint files...");
generatePluginEslint();
// Build with tsdown
console.log("Building with tsdown...");
execSync("pnpm tsdown", { stdio: "inherit", cwd: oxlintDirPath });
// Delete `cli.d.ts`
console.log("Deleting cli.d.ts...");
rmSync(join(distDirPath, "cli.d.ts"));
// Copy native `.node` files from `src-js`
console.log("Copying `.node` files...");
for (const filename of readdirSync(srcDirPath)) {
if (!filename.endsWith(".node")) continue;
const srcPath = join(srcDirPath, filename);
copyFileSync(srcPath, join(distDirPath, filename));
}
console.log("Build complete!");