Skip to content

Commit

Permalink
feat: drop support for jiti v1.21 (#18996)
Browse files Browse the repository at this point in the history
* feat: drop support for jiti v1.21

* fix for CommonJS TS config that exports undefined
  • Loading branch information
fasttime authored Oct 12, 2024
1 parent 7dd402d commit 1def4cd
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 8 deletions.
2 changes: 1 addition & 1 deletion docs/src/use/configure/configuration-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ npx eslint --flag unstable_ts_config

For more information about using feature flags, see [Feature Flags](../../flags/).

For Deno and Bun, TypeScript configuration files are natively supported; for Node.js, you must install the optional dev dependency [`jiti`](https://github.com/unjs/jiti) in your project (this dependency is not automatically installed by ESLint):
For Deno and Bun, TypeScript configuration files are natively supported; for Node.js, you must install the optional dev dependency [`jiti`](https://github.com/unjs/jiti) in version 2.0.0 or later in your project (this dependency is not automatically installed by ESLint):

```bash
npm install -D jiti
Expand Down
23 changes: 16 additions & 7 deletions lib/config/config-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,21 +173,22 @@ async function loadConfigFile(filePath, allowTS) {
*/
if (allowTS && isTS && !isDeno && !isBun) {

const createJiti = await import("jiti").then(jitiModule => (typeof jitiModule?.createJiti === "function" ? jitiModule.createJiti : jitiModule.default), () => {
// eslint-disable-next-line no-use-before-define -- `ConfigLoader.loadJiti` can be overwritten for testing
const { createJiti } = await ConfigLoader.loadJiti().catch(() => {
throw new Error("The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it.");
});

// `createJiti` was added in jiti v2.
if (typeof createJiti !== "function") {
throw new Error("You are using an outdated version of the 'jiti' library. Please update to the latest version of 'jiti' to ensure compatibility and access to the latest features.");
}

/*
* Disabling `moduleCache` allows us to reload a
* config file when the last modified timestamp changes.
*/

const jiti = createJiti(__filename, { moduleCache: false, interopDefault: false });

if (typeof jiti?.import !== "function") {
throw new Error("You are using an outdated version of the 'jiti' library. Please update to the latest version of 'jiti' to ensure compatibility and access to the latest features.");
}

const config = await jiti.import(fileURL.href);

importedConfigFileModificationTime.set(filePath, mtime);
Expand Down Expand Up @@ -294,7 +295,6 @@ async function calculateConfigArray(configFilePath, basePath, options) {
return configs;
}


//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -517,6 +517,15 @@ class ConfigLoader {
return this.#configArrays.get(configFilePath);
}

/**
* Used to import the jiti dependency. This method is exposed internally for testing purposes.
* @returns {Promise<Record<string, unknown>>} A promise that fulfills with a module object
* or rejects with an error if jiti is not found.
*/
static loadJiti() {
return import("jiti");
}

}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export = void 0;
110 changes: 110 additions & 0 deletions tests/lib/eslint/eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -1313,6 +1313,61 @@ describe("ESLint", () => {

});

it("should fail to load a TS config file if jiti is not installed", async () => {

const { ConfigLoader } = require("../../../lib/config/config-loader");

sinon.stub(ConfigLoader, "loadJiti").rejects();

const cwd = getFixturePath("ts-config-files", "ts");

eslint = new ESLint({
cwd,
flags: tsFlags
});

await assert.rejects(
eslint.lintText("foo();"),
{ message: "The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it." }
);
});

it("should fail to load a TS config file if an outdated version of jiti is installed", async () => {

const { ConfigLoader } = require("../../../lib/config/config-loader");

sinon.stub(ConfigLoader, "loadJiti").resolves({});

const cwd = getFixturePath("ts-config-files", "ts");

eslint = new ESLint({
cwd,
flags: tsFlags
});

await assert.rejects(
eslint.lintText("foo();"),
{ message: "You are using an outdated version of the 'jiti' library. Please update to the latest version of 'jiti' to ensure compatibility and access to the latest features." }
);
});

it("should fail to load a CommonJS TS config file that exports undefined with a helpful error message", async () => {

const cwd = getFixturePath("ts-config-files", "ts");

eslint = new ESLint({
cwd,
flags: tsFlags,
overrideConfigFile: "eslint.undefined.config.ts"
});

await assert.rejects(
eslint.lintText("foo"),
{ message: "Config (unnamed): Unexpected undefined config at user-defined index 0." }
);

});

});

it("should pass BOM through processors", async () => {
Expand Down Expand Up @@ -5753,6 +5808,61 @@ describe("ESLint", () => {

});

it("should fail to load a TS config file if jiti is not installed", async () => {

const { ConfigLoader } = require("../../../lib/config/config-loader");

sinon.stub(ConfigLoader, "loadJiti").rejects();

const cwd = getFixturePath("ts-config-files", "ts");

eslint = new ESLint({
cwd,
flags: newFlags
});

await assert.rejects(
eslint.lintFiles("foo.js"),
{ message: "The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it." }
);
});

it("should fail to load a TS config file if an outdated version of jiti is installed", async () => {

const { ConfigLoader } = require("../../../lib/config/config-loader");

sinon.stub(ConfigLoader, "loadJiti").resolves({});

const cwd = getFixturePath("ts-config-files", "ts");

eslint = new ESLint({
cwd,
flags: newFlags
});

await assert.rejects(
eslint.lintFiles("foo.js"),
{ message: "You are using an outdated version of the 'jiti' library. Please update to the latest version of 'jiti' to ensure compatibility and access to the latest features." }
);
});

it("should fail to load a CommonJS TS config file that exports undefined with a helpful error message", async () => {

const cwd = getFixturePath("ts-config-files", "ts");

eslint = new ESLint({
cwd,
flags: newFlags,
overrideConfigFile: "eslint.undefined.config.ts"
});

await assert.rejects(
eslint.lintFiles("foo.js"),
{ message: "Config (unnamed): Unexpected undefined config at user-defined index 0." }
);

});

});

it("should stop linting files if a rule crashes", async () => {
Expand Down

0 comments on commit 1def4cd

Please sign in to comment.