ESLint plugin with default configuration and custom rules for iTwin.js projects. For best results, use with Typescript 4.1+
You'll first need to install ESLint and @itwin/eslint-plugin
:
npm i eslint --save-dev
npm i @itwin/eslint-plugin --save-dev
In order for VSCode to use the config file as it is set up, add the following setting to the the VSCode settings (in .vscode/settings.json
):
"eslint.experimental.useFlatConfig": true,
Create an eslint.config.js
file at the root of your project. To set up the file, import @itwin/eslint-plugin
. Then set the file to export an array of configuration files. This will be done differently depending on whether your project uses ESM or CJS.
import iTwinPlugin from "@itwin/eslint-plugin";
export default [
{
files: ["**/*.{ts,tsx}"],
...iTwinPlugin.configs.iTwinjsRecommendedConfig,
},
{
files: ["**/*.{ts,tsx}"],
...iTwinPlugin.configs.jsdocConfig,
},
];
const iTwinPlugin = require("@itwin/eslint-plugin");
module.exports = [
{
files: ["**/*.{ts,tsx}"],
...iTwinPlugin.configs.iTwinjsRecommendedConfig,
},
{
files: ["**/*.{ts,tsx}"],
...iTwinPlugin.configs.jsdocConfig,
}
];
Then configure the rules you want to override, add a section with rules to be overriden and their severity.
const iTwinPlugin = require("@itwin/eslint-plugin");
module.exports = [
{
files: ["**/*.{ts,tsx}"],
...iTwinPlugin.configs.iTwinjsRecommendedConfig,
},
{
files: ["**/*.{ts,tsx}"],
...iTwinPlugin.configs.jsdocConfig,
},
{
rules: {
"@typescript-eslint/no-explicit-any": "error",
}
}
];
To add rules not set in the recommended configurations, add a plugins section with the @itwin/eslint-plugin
that was imported. Then, add a rules section with the rule that needs to be added and the severity of error for the rule.
If a configuration that defines the language parsing options is not used, add a languageOptions
object. Below is an example of using the @itwin/no-internal
rule where we define the language options to parse typescript.
// custom config
const iTwinPlugin = require("@itwin/eslint-plugin");
module.exports = [
{
languageOptions: {
sourceType: "module",
parser: require("@typescript-eslint/parser"),
parserOptions: {
project: "tsconfig.json",
ecmaVersion: "latest",
ecmaFeatures: {
jsx: true,
modules: true
},
},
},
plugins: {
"@itwin": iTwinPlugin
},
files: ["**/*.{ts,tsx}"],
rules: {
"@itwin/no-internal": "error",
}
}
];
// default config
rules: {
"@itwin/no-internal": "error"
}
// tag is set to ["internal", "alpha"] by default
The rule has some options:
-
tag
- List of tags where the rule will report on usages of APIs documented as them. Allowed tags:internal
,alpha
,beta
,public
.- Default:
internal
,alpha
- Default:
-
checkedPackagePatterns
- List of regex patterns where the rule will only be enforced for APIs that are from a package whose name matches a pattern in the list.- Default:
^@itwin/
,^@bentley/
- Default:
-
dontAllowWorkspaceInternal
- Flag that if set totrue
, the rule will be enforced on usages of APIs from packages that are part of the same workspace/monorepo. If set tofalse
, usages of APIs from workspace dependencies will not report an error.- Default:
false
- Default:
no-internal-report
- Runs eslint with the @itwin/no-internal
rule turned on ("error") using a custom formatter that summarizes the output
This can be run using npx
or from the scripts section of package.json
:
"scripts": {
"no-internal-report": "no-internal-report \"src/**/*.ts*\""
},
This command forwards all arguments to eslint, so it can be further customized as needed. For example, to specify the tags for the no-internal
rule:
"scripts": {
"no-internal-report": "no-internal-report --tags internal,alpha,beta \"src/**/*.ts*\""
},
In addition to this we also have a custom formatter that can be used to generate a summary table report of the no-internal violations in your codebase.
It creates a easily readable summary table of all your violations. For example:
In addition, this also creates a csv with the same table in the current working directory. You can call it like this:
eslint ./**/*.{ts,tsx} 1>&2 -f ./node_modules/@itwin/eslint-plugin/dist/formatters/no-internal-summary-with-table.js
If you want to import the table creator directly into your code and acquire the string before printing, you can do so by importing the function noInternalSummaryTableCreator
from @itwin/eslint-plugin
package, then pass in the Message[] type objects or directly pass in the LintResult[] objects you get when calling eslint.lintFiles()
.