Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
eac9360
Initial working implementation of TS config files
aryaemami59 Feb 20, 2024
3833b5b
Simplify implementation
aryaemami59 Feb 20, 2024
840378c
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Feb 23, 2024
150d567
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Feb 23, 2024
f196b6b
Use typescript's `transpile()` instead of `tsx` to avoid side effects
aryaemami59 Feb 27, 2024
9b630ea
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Feb 28, 2024
ac08d46
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Feb 29, 2024
c5a8862
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 2, 2024
a016dff
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 5, 2024
00af268
Remove unnecessary nullish coalescing
aryaemami59 Mar 6, 2024
5ee0c4c
Use `jiti` instead of TypeScript
aryaemami59 Mar 6, 2024
d58270e
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 7, 2024
c69224c
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 9, 2024
421587c
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 11, 2024
5eae061
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 13, 2024
40c77d4
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 15, 2024
e004292
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 17, 2024
7540572
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 19, 2024
0f8dc8a
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 21, 2024
6eb0f88
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 26, 2024
6ccf10f
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Mar 28, 2024
7b00b03
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Apr 2, 2024
c341646
Add missing section related to `importedConfigFileModificationTime`
aryaemami59 Apr 2, 2024
8614fd3
Enable `esmResolve` for `jiti`
aryaemami59 Apr 2, 2024
8556132
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Apr 3, 2024
5ebf9f9
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Apr 6, 2024
68ab0af
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Apr 9, 2024
1081889
Merge branch 'eslint.config.ts' of https://github.com/aryaemami59/esl…
aryaemami59 Apr 12, 2024
e7eb303
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Apr 17, 2024
424ce93
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Apr 22, 2024
ab5ef8f
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Apr 23, 2024
599c6a5
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Apr 29, 2024
dad7b0e
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Apr 30, 2024
2bfe8b5
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 May 6, 2024
10d147e
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 May 9, 2024
9f09770
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 May 11, 2024
360cf38
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 May 14, 2024
b162744
Make `jiti` an optional peer dependency
aryaemami59 May 14, 2024
8aca3eb
Throw an error if `jiti` is not installed
aryaemami59 May 14, 2024
b532667
Add `jiti` to `ignoreDependencies` in `knip.jsonc`
aryaemami59 May 14, 2024
9248177
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 May 16, 2024
eee920e
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 May 25, 2024
5ac3927
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 May 29, 2024
f339591
Fix broken unit tests caused by stubbed `process.version`
aryaemami59 May 29, 2024
8fa2ddb
Prioritize JavaScript config files over TypeScript config files
aryaemami59 May 29, 2024
822baf7
Add some basic tests for loading TS config files
aryaemami59 May 29, 2024
33f5ee6
Fix minor type issues in JSDocs
aryaemami59 May 29, 2024
90657fa
Partially Inline the `FlatConfig` type from `@types/eslint` to reuse
aryaemami59 May 29, 2024
9da10d4
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 May 29, 2024
4467fb3
Merge branch 'eslint.config.ts' of https://github.com/aryaemami59/esl…
aryaemami59 May 30, 2024
76c3d28
Stringify `mtime`
aryaemami59 May 31, 2024
b0e5f96
Check if ESLint is running in Deno or Bun
aryaemami59 May 31, 2024
209c791
Try a different approach for loading TS config files
aryaemami59 May 31, 2024
ce4b72b
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 May 31, 2024
61abc9b
Add tests for `lintFiles` with TS config files
aryaemami59 May 31, 2024
0b11b0d
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 1, 2024
df7a08d
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 3, 2024
bfa5b0c
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 4, 2024
730e5cb
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 4, 2024
f0edb14
Revert "Try a different approach for loading TS config files"
aryaemami59 Jun 4, 2024
8a988ca
Convert `Severity` type to a `const enum`
aryaemami59 Jun 4, 2024
3d16b62
Add tests for TS config files containing `const enum`s
aryaemami59 Jun 4, 2024
391ff9d
Add `ESLintNameSpace` local `namespace`
aryaemami59 Jun 4, 2024
60a66d4
Add tests for TS config files containing importing a local `namespace`
aryaemami59 Jun 4, 2024
33f77d0
Fix minor type issues in JSDocs
aryaemami59 Jun 4, 2024
0112441
Add tests for passing TS config files to `overrideConfigFile`
aryaemami59 Jun 5, 2024
7df58cd
Bump `jiti` to version 1.21.1
aryaemami59 Jun 5, 2024
de86b20
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 5, 2024
fe914db
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 5, 2024
6ae6261
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 15, 2024
9cf9076
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 17, 2024
226669e
Bump `jiti` to version 1.21.6
aryaemami59 Jun 19, 2024
9b9c6ec
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 19, 2024
328e30f
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 24, 2024
2f9c6fc
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 25, 2024
43c66b7
Add basic docs for loading TypeScript configuration files
aryaemami59 Jun 26, 2024
3b05c55
Fix lint issues
aryaemami59 Jun 26, 2024
3bcc3a4
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jun 29, 2024
e4b439f
Bump `jiti` to version 2.0.0-beta.1
aryaemami59 Jun 29, 2024
5e424b6
Remove `esmResolve` as it has been removed in v2 of `jiti`
aryaemami59 Jun 29, 2024
99dc9e6
Fix types for `createCustomTeardown`
aryaemami59 Jun 29, 2024
88c03bf
Remove `interopDefault: true`
aryaemami59 Jun 29, 2024
90252b3
Fix type of `eslint` in test file
aryaemami59 Jun 29, 2024
f4f36c2
Fix lint issues in test file
aryaemami59 Jun 29, 2024
05e2276
Add more tests
aryaemami59 Jun 29, 2024
5b27883
Defer to v10 in docs
aryaemami59 Jun 29, 2024
3e120f9
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jul 2, 2024
63fa91b
Bump `jiti` to version 2.0.0-beta.3
aryaemami59 Jul 2, 2024
beb9f7a
Fix import of `jiti`
aryaemami59 Jul 2, 2024
5ea22c5
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jul 2, 2024
54abd14
Fix `jiti` link in docs
aryaemami59 Jul 2, 2024
82e35a5
Fix `jiti` link in docs
aryaemami59 Jul 2, 2024
cf360c5
Add `unstable_ts_config` to `activeFlags`
aryaemami59 Jul 2, 2024
f801ddc
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jul 3, 2024
3f772e5
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jul 8, 2024
9de006e
Fix issues in `configuration-files.md`
aryaemami59 Jul 8, 2024
0e6f45e
Fix `LintResults` in `eslint.js`
aryaemami59 Jul 8, 2024
7ca2096
Change `LintResults` to `LintResult` in `eslint.js`
aryaemami59 Jul 8, 2024
b7c6a44
Remove warning regarding top-level `await`
aryaemami59 Jul 8, 2024
8d121d5
Explicitly check for `.ts`, `.mts` or `.cts` extensions
aryaemami59 Jul 9, 2024
9951239
Check if `"unstable_ts_config"` flag is enabled
aryaemami59 Jul 9, 2024
8c2094a
Fix import and export assignment tests
aryaemami59 Jul 9, 2024
0ea096f
Fix remaining issues in `configuration-files.md`
aryaemami59 Jul 11, 2024
f08ec04
Fix test title
aryaemami59 Jul 11, 2024
6e2cff0
De-duplicate test
aryaemami59 Jul 11, 2024
f369145
Revert "Fix broken unit tests caused by stubbed `process.version`"
aryaemami59 Jul 11, 2024
25016fc
Remove unnecessary checks for `"unstable_ts_config"` flag
aryaemami59 Jul 11, 2024
2111cf7
Fix type of `findConfigFile`
aryaemami59 Jul 11, 2024
f2b07cd
Make sure tests fail when the correct config file is not loaded
aryaemami59 Jul 11, 2024
896e08f
Add a test for `"unstable_ts_config"`
aryaemami59 Jul 11, 2024
4d45eff
Remove fallback to `default` when loading `jiti.createJiti`
aryaemami59 Jul 11, 2024
3daca1c
Update `configuration-files.md`
aryaemami59 Jul 12, 2024
9881712
Update description of `"unstable_ts_config"` flag
aryaemami59 Jul 12, 2024
479847a
Add comment explaining purpose of `helper.ts`
aryaemami59 Jul 12, 2024
60f6a22
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jul 16, 2024
df1e6d9
Disable `moduleCache`
aryaemami59 Jul 16, 2024
c16eb7c
Add test to check reloading logic for TS config files
aryaemami59 Jul 16, 2024
0277242
Add comment for disabling `moduleCache`
aryaemami59 Jul 17, 2024
89f3b07
Rework `hasUnstableTSConfigFlag` logic
aryaemami59 Jul 17, 2024
74a6988
Fix unit tests
aryaemami59 Jul 17, 2024
f9a4a89
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jul 20, 2024
79d65e4
Fallback to `default` when loading `jiti`
aryaemami59 Jul 20, 2024
166ca0f
Rework logic for loading TS config files
aryaemami59 Jul 20, 2024
275dbe1
Remove default value for `hasUnstableTSConfigFlag` parameter
aryaemami59 Jul 23, 2024
c560d9e
Remove type assertion
aryaemami59 Jul 23, 2024
9a5b2c7
Remove unnecessary `process?.versions?.bun` check
aryaemami59 Jul 23, 2024
bd9ce95
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jul 24, 2024
e26d690
Remove unnecessary `LintResults` type
aryaemami59 Jul 24, 2024
62a9007
Fix parameter type of `eslintWithPlugins`
aryaemami59 Jul 24, 2024
83a374b
Add tests for loading TypeScript config files that export a promise
aryaemami59 Jul 24, 2024
7c25109
Update `jiti` peer dependency to allow any version
aryaemami59 Jul 24, 2024
cad6f0a
Warn about using an outdated version of `jiti`
aryaemami59 Jul 25, 2024
81e7276
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Jul 30, 2024
c4143e1
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Aug 1, 2024
a54f83c
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Aug 2, 2024
41dc58c
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Aug 5, 2024
e985e83
Fix minor issue in `configuration-files.md`
aryaemami59 Aug 5, 2024
bface3f
Add section about `--flag` in `configuration-files.md`
aryaemami59 Aug 5, 2024
8cc853d
Reapply "Fix broken unit tests caused by stubbed `process.version`"
aryaemami59 Aug 5, 2024
0fd89a0
Switch to `jiti` v1 until `jiti` v2 becomes stable
aryaemami59 Aug 5, 2024
8ece0be
Add commented-out unit tests for `jiti` v2
aryaemami59 Aug 6, 2024
ef4a619
Merge branch 'main' of https://github.com/eslint/eslint into eslint.c…
aryaemami59 Aug 7, 2024
9a80b89
Throw a `TypeError` if `jiti.import` is not a function
aryaemami59 Aug 7, 2024
d5a00f9
Change `TypeError` to `Error`
aryaemami59 Aug 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions docs/src/use/configure/configuration-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ The ESLint configuration file may be named any of the following:
* `eslint.config.js`
* `eslint.config.mjs`
* `eslint.config.cjs`
* `eslint.config.ts` (requires [additional setup](#typescript-configuration-files))
* `eslint.config.mts` (requires [additional setup](#typescript-configuration-files))
* `eslint.config.cts` (requires [additional setup](#typescript-configuration-files))

It should be placed in the root directory of your project and export an array of [configuration objects](#configuration-objects). Here's an example:

Expand Down Expand Up @@ -495,3 +498,84 @@ npx eslint --config some-other-file.js **/*.js
```

In this case, ESLint does not search for `eslint.config.js` and instead uses `some-other-file.js`.

## TypeScript Configuration Files

::: warning
This feature is currently experimental and may change in future versions.
:::

You need to enable this feature through the `unstable_ts_config` feature flag:

```bash
npx eslint --flag unstable_ts_config
```

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):

```bash
npm install -D jiti
# or
yarn add --dev jiti
# or
pnpm add -D jiti
```

You can then create a configuration file with a `.ts`, `.mts`, or `.cts` extension, and export an array of [configuration objects](#configuration-objects). Here's an example in ESM format:

```ts
import js from "@eslint/js";
import type { Linter } from "eslint";

export default [
js.configs.recommended,
{
rules: {
"no-console": [0],
},
},
] satisfies Linter.FlatConfig[];
```

Here's an example in CommonJS format:

```ts
import type { Linter } from "eslint";
const eslint = require("@eslint/js");

const config: Linter.FlatConfig[] = [
eslint.configs.recommended,
{
rules: {
"no-console": [0],
},
},
];

module.exports = config;
```

::: important
ESLint does not perform type checking on your configuration file and does not apply any settings from `tsconfig.json`.
:::

::: warning
As of now, [`jiti`](https://github.com/unjs/jiti) does not support [Top-level `await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await)
:::

### Configuration File Precedence

If you have multiple ESLint configuration files, ESLint prioritizes JavaScript files over TypeScript files. The order of precedence is as follows:

1. `eslint.config.js`
2. `eslint.config.mjs`
3. `eslint.config.cjs`
4. `eslint.config.ts`
5. `eslint.config.mts`
6. `eslint.config.cts`

To override this behavior, use the `--config` or `-c` command line option to specify a different configuration file:

```bash
npx eslint --flag unstable_ts_config --config eslint.config.ts
```
5 changes: 4 additions & 1 deletion knip.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
"rollup-plugin-node-polyfills",

// FIXME: not sure why is eslint-config-eslint reported as unused
"eslint-config-eslint"
"eslint-config-eslint",

// Optional peer dependency used for loading TypeScript configuration files
"jiti"
]
},
"docs": {
Expand Down
7 changes: 4 additions & 3 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,16 +340,17 @@ const cli = {
/**
* Calculates the command string for the --inspect-config operation.
* @param {string} configFile The path to the config file to inspect.
* @param {boolean} hasUnstableTSConfigFlag `true` if the `unstable_ts_config` flag is enabled, `false` if it's not.
* @returns {Promise<string>} The command string to execute.
*/
async calculateInspectConfigFlags(configFile) {
async calculateInspectConfigFlags(configFile, hasUnstableTSConfigFlag) {

// find the config file
const {
configFilePath,
basePath,
error
} = await locateConfigFileToUse({ cwd: process.cwd(), configFile });
} = await locateConfigFileToUse({ cwd: process.cwd(), configFile }, hasUnstableTSConfigFlag);

if (error) {
throw error;
Expand Down Expand Up @@ -454,7 +455,7 @@ const cli = {
try {
const flatOptions = await translateOptions(options, "flat");
const spawn = require("cross-spawn");
const flags = await cli.calculateInspectConfigFlags(flatOptions.overrideConfigFile);
const flags = await cli.calculateInspectConfigFlags(flatOptions.overrideConfigFile, flatOptions.flags ? flatOptions.flags.includes("unstable_ts_config") : false);

spawn.sync("npx", ["@eslint/config-inspector@latest", ...flags], { encoding: "utf8", stdio: "inherit" });
} catch (error) {
Expand Down
110 changes: 93 additions & 17 deletions lib/eslint/eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ const { Retrier } = require("@humanwhocodes/retry");
/** @typedef {import("../shared/types").RuleConf} RuleConf */
/** @typedef {import("../shared/types").Rule} Rule */
/** @typedef {ReturnType<ConfigArray.extractConfig>} ExtractedConfig */
/** @typedef {import('../cli-engine/cli-engine').CLIEngine} CLIEngine */
/** @typedef {import('./legacy-eslint').CLIEngineLintReport} CLIEngineLintReport */

/**
* The options with which to configure the ESLint instance.
Expand All @@ -86,7 +88,7 @@ const { Retrier } = require("@humanwhocodes/retry");
* when a string.
* @property {Record<string,Plugin>} [plugins] An array of plugin implementations.
* @property {boolean} [stats] True enables added statistics on lint results.
* @property {boolean} warnIgnored Show warnings when the file list includes ignored files
* @property {boolean} [warnIgnored] Show warnings when the file list includes ignored files
* @property {boolean} [passOnNoPatterns=false] When set to true, missing patterns cause
* the linting operation to short circuit and not report any failures.
*/
Expand All @@ -100,8 +102,18 @@ const FLAT_CONFIG_FILENAMES = [
"eslint.config.mjs",
"eslint.config.cjs"
];
const FLAT_CONFIG_FILENAMES_WITH_TS = [
...FLAT_CONFIG_FILENAMES,
"eslint.config.ts",
"eslint.config.mts",
"eslint.config.cts"
];
const debug = require("debug")("eslint:eslint");
const privateMembers = new WeakMap();

/**
* @type {Map<string, string>}
*/
const importedConfigFileModificationTime = new Map();
const removedFormatters = new Set([
"checkstyle",
Expand Down Expand Up @@ -262,28 +274,59 @@ function compareResultsByFilePath(a, b) {
* Searches from the current working directory up until finding the
* given flat config filename.
* @param {string} cwd The current working directory to search from.
* @param {boolean} hasUnstableTSConfigFlag `true` if the `unstable_ts_config` flag is enabled, `false` if it's not.
* @returns {Promise<string|undefined>} The filename if found or `undefined` if not.
*/
function findFlatConfigFile(cwd) {
function findFlatConfigFile(cwd, hasUnstableTSConfigFlag) {
const filenames = hasUnstableTSConfigFlag ? FLAT_CONFIG_FILENAMES_WITH_TS : FLAT_CONFIG_FILENAMES;

return findUp(
FLAT_CONFIG_FILENAMES,
filenames,
{ cwd }
);
}

/**
* Check if the file is a TypeScript file.
* @param {string} filePath The file path to check.
* @returns {boolean} `true` if the file is a TypeScript file, `false` if it's not.
*/
function isFileTS(filePath) {
const fileExtension = path.extname(filePath);

return /^\.[mc]?ts$/u.test(fileExtension);
}

/**
* Check if ESLint is running in Bun.
* @returns {boolean} `true` if the ESLint is running Bun, `false` if it's not.
*/
function isRunningInBun() {
return !!globalThis.Bun;
}

/**
* Check if ESLint is running in Deno.
* @returns {boolean} `true` if the ESLint is running in Deno, `false` if it's not.
*/
function isRunningInDeno() {
return !!globalThis.Deno;
}

/**
* Load the config array from the given filename.
* @param {string} filePath The filename to load from.
* @param {boolean} hasUnstableTSConfigFlag `true` if the `unstable_ts_config` flag is enabled, `false` if it's not.
* @returns {Promise<any>} The config loaded from the config file.
*/
async function loadFlatConfigFile(filePath) {
async function loadFlatConfigFile(filePath, hasUnstableTSConfigFlag) {
debug(`Loading config from ${filePath}`);

const fileURL = pathToFileURL(filePath);

debug(`Config file URL is ${fileURL}`);

const mtime = (await fs.stat(filePath)).mtime.getTime();
const mtime = (await fs.stat(filePath)).mtime.getTime().toString();

/*
* Append a query with the config file's modification time (`mtime`) in order
Expand Down Expand Up @@ -314,7 +357,37 @@ async function loadFlatConfigFile(filePath) {
delete require.cache[filePath];
}

const config = (await import(fileURL)).default;
const isTS = isFileTS(filePath) && hasUnstableTSConfigFlag;

const isBun = isRunningInBun();

const isDeno = isRunningInDeno();

if (isTS && !isDeno && !isBun) {

const createJiti = await import("jiti").then(jitiModule => jitiModule.default, () => {
throw new Error("The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it.");
});

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

const jiti = createJiti(__filename, { moduleCache: 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);

return config?.default ?? config;
}

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

importedConfigFileModificationTime.set(filePath, mtime);

Expand All @@ -326,11 +399,12 @@ async function loadFlatConfigFile(filePath) {
* override config file was passed, and if so, using it; otherwise, as long
* as override config file is not explicitly set to `false`, it will search
* upwards from the cwd for a file named `eslint.config.js`.
* @param {import("./eslint").ESLintOptions} options The ESLint instance options.
* @returns {{configFilePath:string|undefined,basePath:string,error:Error|null}} Location information for
* @param {ESLintOptions} options The ESLint instance options.
* @param {boolean} hasUnstableTSConfigFlag `true` if the `unstable_ts_config` flag is enabled, `false` if it's not.
* @returns {Promise<{configFilePath:string|undefined;basePath:string;error:Error|null}>} Location information for
* the config file.
*/
async function locateConfigFileToUse({ configFile, cwd }) {
async function locateConfigFileToUse({ configFile, cwd }, hasUnstableTSConfigFlag) {

// determine where to load config file from
let configFilePath;
Expand All @@ -342,7 +416,7 @@ async function locateConfigFileToUse({ configFile, cwd }) {
configFilePath = path.resolve(cwd, configFile);
} else if (configFile !== false) {
debug("Searching for eslint.config.js");
configFilePath = await findFlatConfigFile(cwd);
configFilePath = await findFlatConfigFile(cwd, hasUnstableTSConfigFlag);

if (configFilePath) {
basePath = path.resolve(path.dirname(configFilePath));
Expand All @@ -364,8 +438,8 @@ async function locateConfigFileToUse({ configFile, cwd }) {
/**
* Calculates the config array for this run based on inputs.
* @param {ESLint} eslint The instance to create the config array for.
* @param {import("./eslint").ESLintOptions} options The ESLint instance options.
* @returns {FlatConfigArray} The config array for `eslint``.
* @param {ESLintOptions} options The ESLint instance options.
* @returns {Promise<typeof FlatConfigArray>} The config array for `eslint``.
*/
async function calculateConfigArray(eslint, {
cwd,
Expand All @@ -383,7 +457,9 @@ async function calculateConfigArray(eslint, {
return slots.configs;
}

const { configFilePath, basePath, error } = await locateConfigFileToUse({ configFile, cwd });
const hasUnstableTSConfigFlag = eslint.hasFlag("unstable_ts_config");

const { configFilePath, basePath, error } = await locateConfigFileToUse({ configFile, cwd }, hasUnstableTSConfigFlag);

// config file is required to calculate config
if (error) {
Expand All @@ -394,7 +470,7 @@ async function calculateConfigArray(eslint, {

// load config file
if (configFilePath) {
const fileConfig = await loadFlatConfigFile(configFilePath);
const fileConfig = await loadFlatConfigFile(configFilePath, hasUnstableTSConfigFlag);

if (Array.isArray(fileConfig)) {
configs.push(...fileConfig);
Expand Down Expand Up @@ -1144,7 +1220,7 @@ class ESLint {

/**
* The main formatter method.
* @param {LintResults[]} results The lint results to format.
* @param {LintResult[]} results The lint results to format.
* @param {ResultsMeta} resultsMeta Warning count and max threshold.
* @returns {string} The formatted lint results.
*/
Expand Down Expand Up @@ -1190,12 +1266,12 @@ class ESLint {
/**
* Finds the config file being used by this instance based on the options
* passed to the constructor.
* @returns {string|undefined} The path to the config file being used or
* @returns {Promise<string|undefined>} The path to the config file being used or
* `undefined` if no config file is being used.
*/
async findConfigFile() {
const options = privateMembers.get(this).options;
const { configFilePath } = await locateConfigFileToUse(options);
const { configFilePath } = await locateConfigFileToUse(options, this.hasFlag("unstable_ts_config"));

return configFilePath;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/shared/flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
* @type {Map<string, string>}
*/
const activeFlags = new Map([
["test_only", "Used only for testing."]
["test_only", "Used only for testing."],
["unstable_ts_config", "Enable TypeScript configuration files."]
]);

/**
Expand Down
9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
"globals": "^15.0.0",
"got": "^11.8.3",
"gray-matter": "^4.0.3",
"jiti": "^1.21.6",
"js-yaml": "^4.1.0",
"knip": "^5.21.0",
"lint-staged": "^11.0.0",
Expand Down Expand Up @@ -165,6 +166,14 @@
"webpack-cli": "^4.5.0",
"yorkie": "^2.0.0"
},
"peerDependencies": {
"jiti": "*"
},
"peerDependenciesMeta": {
"jiti": {
"optional": true
}
},
"keywords": [
"ast",
"lint",
Expand Down
Loading