Skip to content

Commit

Permalink
feat: use importx
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed May 11, 2024
1 parent 06c029c commit d4f16c7
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 53 deletions.
16 changes: 6 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,21 @@ It should make your `eslint` CLI work for those config files automatically. If i

## TypeScript Loaders

There are multiple solutions to load TypeScript files in Node.js at runtime, and each of them consists of different trade-offs. This patch supports the following loaders:
There are multiple solutions to load TypeScript files in Node.js at runtime, and each of them consists of different trade-offs. This patch supports the following loaders powered by [`importx`](https://github.com/antfu/importx):

- [`tsx`](https://github.com/privatenumber/tsx) (default) - Use Node's native ESM loader to load TypeScript files.
- `default`: [Auto-detect the loader based on the user's environment](https://github.com/antfu/importx#auto).
- [`tsx`](https://github.com/privatenumber/tsx) - Use Node's native ESM loader to load TypeScript files.
- **Pros**: Use Node's native ESM loader, running in ESM. Should have the most correct behavior.
- **Cons**: It requires [Node.js v18.19.0+ or v20.8.0](https://nodejs.org/api/module.html#moduleregisterspecifier-parenturl-options). Refer to the [Compatibility](#compatibility) section.
- [`jiti`](https://github.com/unjs/jiti)- Transpile TypeScript files and ESM to CJS and execute them at runtime.
- **Pros**: Easy to use. No need to install additional dependencies.
- **Cons**: Everything is in CJS mode. It does not support top-level-await. It May have inconsistent behavior during ESM/CJS interop.
- **Cons**: Everything is in CJS mode. It does not support top-level-await. It may have inconsistent behavior during ESM/CJS interop.
- [`bundle-require`](https://github.com/egoist/bundle-require) - Use `esbuild` to bundle the `eslint.config.ts` file, and import the temporary bundle.
- **Pros**: Not hacking into Node's internals. ESM and top-level-await are supported.
- **Cons**: It writes a temporary file to disk.

Learn more about the loaders in the [`importx` documentation](https://github.com/antfu/importx).

To try out different loaders, you can set the `ESLINT_TS_PATCH_LOADER` environment variable to one of the following values:

```sh
Expand All @@ -61,13 +64,6 @@ Or you can use magic comments `@eslint-ts-patch-loader` in your `eslint.config.t
// @eslint-ts-patch-loader tsx
```

`jiti` and `bundle-require` are not included in the dependencies of this package, you need to install them yourself.

```sh
npm i -D eslint-ts-patch jiti
npm i -D eslint-ts-patch bundle-require
```

## Compatibility

Tested with the following tools:
Expand Down
4 changes: 2 additions & 2 deletions bin/eslint.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#!/usr/bin/env node

require('../lib/register.js')

const path = require('node:path')

const packageJson = require.resolve('eslint/package.json')
const eslintRoot = path.dirname(packageJson)

const bin = path.join(eslintRoot, 'bin', 'eslint.js')

require('../lib/register.js')

require(bin)
30 changes: 6 additions & 24 deletions lib/register.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,16 @@ const debug = require('debug')('eslint-ts-patch')

const js = String.raw

const supportedTsLoaders = ['jiti', 'tsx', 'bundle-require']
const supportedTsLoaders = ['auto', 'native', 'jiti', 'tsx', 'bundle-require']
const defaultLoader = process.env.ESLINT_TS_PATCH_LOADER || 'auto'

function snippets(defaultLoader) {
return js`
/** --- patched by eslint-ts-patch --- */
const tsLoaders = {
'jiti': async (fileURL) => {
const JITI = require("jiti")(null, { esmResolve: true, interopDefault: true });
return await JITI(fileURL.pathname);
},
'tsx': async (fileURL) => {
const { tsImport } = await import("tsx/esm/api");
return await tsImport(fileURL.pathname, __filename);
},
'bundle-require': async (fileURL) => {
const { bundleRequire } = await import("bundle-require");
return await bundleRequire({ filepath: fileURL.pathname }).then(m => m.mod);
}
}
let config;
if (/\.[cm]?ts$/.test(filePath)) {
let supportedTsLoaders = ${JSON.stringify(supportedTsLoaders)};
let loader = ${JSON.stringify(defaultLoader)};
const fs = require('fs/promises');
const content = await fs.readFile(fileURL, 'utf-8');
Expand All @@ -54,9 +40,9 @@ if (/\.[cm]?ts$/.test(filePath)) {
loader = loaderMatch[1];
console.log('[eslint-ts-patch] Using loader "' + loader + '" from comment')
}
if (!tsLoaders[loader])
throw new Error('[eslint-ts-patch] Loader "' + loader + '" is not supported. Supported loaders are: ' + ${JSON.stringify(supportedTsLoaders.join(', '))});
config = await tsLoaders[loader](fileURL);
if (!supportedTsLoaders.includes(loader))
throw new Error('[eslint-ts-patch] Loader "' + loader + '" is not supported. Supported loaders are: ' + supportedTsLoaders.join(', '));
config = await import('importx').then(x => x.import(fileURL, { loader, parentURL: __filename }));
} else {
config = await import(fileURL);
}
Expand All @@ -66,8 +52,6 @@ if (config.default) config = await config.default;
`.trim()
}

const defaultLoader = process.env.ESLINT_TS_PATCH_LOADER || 'tsx'

const REPLACERS = [
{
paths: [
Expand Down Expand Up @@ -108,8 +92,6 @@ const REPLACERS = [
},
]

require('tsx/esm/api').register()

const extensions = Module._extensions
const originalRegister = extensions['.js']
extensions['.js'] = function (module, filename) {
Expand Down
16 changes: 2 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,16 @@
"lib"
],
"scripts": {
"lint": "eslint-ts .",
"lint": "ESLINT_TS_PATCH_LOADER=jiti eslint-ts .",
"release": "bumpp && npm publish",
"test": "vitest",
"typecheck": "tsc --noEmit",
"prepare": "simple-git-hooks"
},
"peerDependencies": {
"bundle-require": "^4.1.0",
"jiti": "^1.21.0"
},
"peerDependenciesMeta": {
"bundle-require": {
"optional": true
},
"jiti": {
"optional": true
}
},
"dependencies": {
"debug": "^4.3.4",
"eslint": "^9.2.0",
"tsx": "^4.9.4"
"importx": "^0.1.2"
},
"devDependencies": {
"@antfu/eslint-config": "^2.17.0",
Expand Down
19 changes: 16 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d4f16c7

Please sign in to comment.