I also recently built a custom eslint plugin ( as part of monorepo ) in typescript and faced a similar issue while integrating into the apps within monorepo and vscode. To solve this I used ts-node register function, which takes care of running the typescript without compiling it.
// rules/customRule.ts
import { ESLintUtils } from '@typescript-eslint/utils';
const rule = ESLintUtils.RuleCreator.withoutDocs({
create(context) {
// ...
},
meta: {
// ...
},
});
export default rule;
// index.ts
import customRule from './rules/customRule';
const rules = {
"custom-rule": customRule,
};
export default rules;
// index.js
/**
* This takes care of running the ts file with commonjs without running a
* compilation process first.
*/
require('ts-node').register()
const pkg = require('./package.json')
const rules = require('./index.ts').default
const pluginName = pkg.name.replace('eslint-plugin-', '')
module.exports = {
rules: rules,
configs: {
recommended: {
plugins: [pluginName],
rules: {
....
}
}
}
}
This way, you can now use this plugin within your application by adding this package to the application and eslintrc file. Couple of things you need to take care which are as follows:
- In the tsconfig.json file of application, you need to ensure that ts-node is running in commonjs. And also if you are using node APIs in the custom eslint plugin, add @types/node to the dev dependencies of the custom plugin package.json.
// tsconfig.json
{
"extends": "tsconfig/base.json",
"compilerOptions": {
"baseUrl": "./src",
"outDir": "./build",
"module": "esnext",
"noEmit": true,
.....
},
// Added this for typescript file used in custom eslint plugin
"ts-node": {
"compilerOptions": {
"module": "commonjs",
"types": ["node"]
},
"swc": true,
},
"include": ["src/**/*", "cypress/**/*", "./global.d.ts"]
}
- If in case you are using pnpm as your package manager and hoisting all your eslint packages to root using public-hoist pattern in npmrc; then you need to add your custom eslint plugin package to root package.json of monorepo for it to work otherwise eslint won't be able to find the custom plugin. More details here
{
"devDependencies": {
"eslint-plugin-custom": "link:packages/eslint-plugin-custom"
}
}