Compare commits

...

1 Commits
main ... inline

Author SHA1 Message Date
Alex
179cf83891 Inline repo 2024-04-19 21:42:48 -04:00
84 changed files with 9571 additions and 115 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
!/packages/eslint-plugin-react-hooks
/react
src/types/rules
dist/**/*.js
dist/**/*.js.map

12
dist/package.json vendored
View File

@ -44,17 +44,17 @@
"tsconfig-paths": "^4.2.0"
},
"overrides": {
"is-core-module": "file:./overrides/is-core-module",
"supports-preserve-symlinks-flag": "file:./overrides/supports-preserve-symlinks-flag"
"supports-preserve-symlinks-flag": "file:./overrides/supports-preserve-symlinks-flag",
"is-core-module": "file:./overrides/is-core-module"
},
"resolutions": {
"**/is-core-module": "file:./overrides/is-core-module",
"**/supports-preserve-symlinks-flag": "file:./overrides/supports-preserve-symlinks-flag"
"**/supports-preserve-symlinks-flag": "file:./overrides/supports-preserve-symlinks-flag",
"**/is-core-module": "file:./overrides/is-core-module"
},
"pnpm": {
"overrides": {
"is-core-module": "file:./overrides/is-core-module",
"supports-preserve-symlinks-flag": "file:./overrides/supports-preserve-symlinks-flag"
"supports-preserve-symlinks-flag": "file:./overrides/supports-preserve-symlinks-flag",
"is-core-module": "file:./overrides/is-core-module"
}
}
}

View File

@ -1,7 +1,8 @@
{
"name": "@aet/eslint-configs",
"scripts": {
"build": "./scripts/build.ts",
"build": "./scripts/build-all.ts",
"build-types": "cd ./packages/eslint-define-config && ./scripts/index.ts",
"check-import": "./scripts/check-imports.ts"
},
"private": true,
@ -11,7 +12,7 @@
"@babel/preset-env": "^7.24.4",
"@types/babel-plugin-macros": "^3.1.3",
"@types/babel__core": "^7.20.5",
"@types/eslint": "^8.56.9",
"@types/eslint": "^8.56.10",
"@types/esprima": "^4.0.6",
"@types/esquery": "^1.5.3",
"@types/estree": "^1.0.5",
@ -24,13 +25,13 @@
"@typescript-eslint/typescript-estree": "^7.7.0",
"@typescript-eslint/utils": "^7.7.0",
"babel-plugin-macros": "^3.1.0",
"dts-bundle-generator": "^9.4.0",
"dts-bundle-generator": "^9.5.0",
"esbin": "0.0.4",
"esbuild": "0.20.2",
"esbuild-plugin-alias": "^0.2.1",
"eslint": "8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-define-config": "^1.24.1",
"eslint-define-config": "file:./src/types",
"esprima": "^4.0.1",
"esquery": "^1.5.0",
"fast-glob": "^3.3.2",

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-2023 Christopher Quadflieg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,144 @@
<p>
<a href="https://www.npmjs.com/package/eslint-define-config" target="_blank">
<img alt="NPM package" src="https://img.shields.io/npm/v/eslint-define-config.svg">
</a>
<a href="https://www.npmjs.com/package/eslint-define-config" target="_blank">
<img alt="Downloads" src="https://img.shields.io/npm/dt/eslint-define-config.svg">
</a>
<a href="https://github.com/eslint-types/eslint-define-config/actions/workflows/ci.yml">
<img alt="Build Status" src="https://github.com/eslint-types/eslint-define-config/actions/workflows/ci.yml/badge.svg?branch=main">
</a>
<a href="https://github.com/eslint-types/eslint-define-config/blob/main/LICENSE">
<img alt="License: MIT" src="https://img.shields.io/github/license/eslint-types/eslint-define-config.svg">
</a>
<a href="https://prettier.io" target="_blank">
<img alt="Code Style: Prettier" src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg">
</a>
<a href="https://www.paypal.com/donate?hosted_button_id=L7GY729FBKTZY" target="_blank">
<img alt="Donate: PayPal" src="https://img.shields.io/badge/Donate-PayPal-blue.svg">
</a>
</p>
# eslint-define-config
Provide a `defineConfig` function for `.eslintrc.js`, and a `defineFlatConfig` function for `eslint.config.js` files.
> This project is written by a human and only partially automatically generated!
> Some rules are even enhanced by hand!
> Unfortunately, this has the disadvantage that not everything is immediately defined. For example, if a rule is not defined, it falls back to a basic definition.
> However, the advantage is that you get documentation for pretty much everything in the code and usually get a direct link to the respective plugin or eslint rule. The types are also strictly typed.
>
> So if you are missing something like a rule or a plugin that should also be supported or a rule definition is e.g. out of date, feel free to open an issue or PR for it.
# Installation
```bash
# add eslint and eslint-define-config to projects dev dependencies
npm add --save-dev eslint eslint-define-config
# or
yarn add --dev eslint eslint-define-config
# or
pnpm add --save-dev eslint eslint-define-config
```
# Usage
`.eslintrc.js`
```ts
// @ts-check
// To activate auto-suggestions for Rules of specific plugins, you need to add a `/// <reference types="eslint-plugin-PLUGIN_NAME/define-config-support" />` comment.
// ⚠️ This feature is very new and requires the support of the respective plugin owners.
/// <reference types="@typescript-eslint/eslint-plugin/define-config-support" />
const { defineConfig } = require('eslint-define-config');
module.exports = defineConfig({
root: true,
rules: {
// rules...
},
});
```
## Flat Config
`eslint.config.js`
```ts
// @ts-check
const { defineFlatConfig } = require('eslint-define-config');
module.exports = defineFlatConfig([
'eslint:recommended',
{
plugins: {
// plugins...
},
rules: {
// rules...
},
},
]);
```
# Why?
Improve your eslint configuration experience with:
- auto-suggestions
- type checking (Use `// @ts-check` at the first line in your `.eslintrc.js` or `eslint.config.js`)
- documentation
- deprecation warnings
<img src="https://user-images.githubusercontent.com/7195563/112484789-8a416480-8d7a-11eb-9337-d8b5bc16de17.png" alt="Image" width="600px"/>
## Video
_Click on the thumbnail to play the video_
<a href="https://user-images.githubusercontent.com/7195563/112726158-4a19e780-8f1c-11eb-8cc6-4ea6c100137f.mp4" target="_blank">
<img src="https://user-images.githubusercontent.com/7195563/112726343-30c56b00-8f1d-11eb-9b92-260c530caf1b.png" alt="Video" width="600px"/>
</a>
## Want to support your own plugin?
:warning: **This feature is very new and requires the support of the respective plugin owners**
Add a `declare module` to your plugin package like this:
```ts
declare module 'eslint-define-config' {
export interface CustomRuleOptions {
/**
* Require consistently using either `T[]` or `Array<T>` for arrays.
*
* @see [array-type](https://typescript-eslint.io/rules/array-type)
*/
'@typescript-eslint/array-type': [
{
default?: 'array' | 'generic' | 'array-simple';
readonly?: 'array' | 'generic' | 'array-simple';
},
];
// ... more Rules
}
}
```
There are other interfaces that can be extended.
- `CustomExtends`
- `CustomParserOptions`
- `CustomParsers`
- `CustomPlugins`
- `CustomSettings`
# Credits
- [Proposal Idea](https://github.com/eslint/eslint/issues/14249)
- [Vite](https://github.com/vitejs/vite) and [Evan You](https://github.com/yyx990803) for the idea
- [@antfu](https://github.com/antfu) and his [tweet](https://twitter.com/antfu7/status/1365907188338753536)

View File

@ -0,0 +1,120 @@
{
"name": "eslint-define-config",
"version": "1.24.1",
"description": "Provide a defineConfig function for .eslintrc.js files",
"scripts": {
"clean": "rimraf coverage .eslintcache dist pnpm-lock.yaml node_modules",
"format": "prettier --cache --write .",
"lint:run": "eslint --cache --cache-strategy content --report-unused-disable-directives .",
"lint": "run-s build lint:run",
"typecheck": "vitest typecheck",
"ts-check": "tsc",
"test": "vitest",
"coverage": "vitest run --coverage",
"generate:rules": "tsx ./scripts/generate-rule-files/cli.ts",
"prepublishOnly": "pnpm run clean && pnpm install && pnpm run build",
"preflight": "pnpm install && run-s format lint ts-check test typecheck"
},
"type": "module",
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"default": "./dist/index.js"
}
},
"keywords": [
"config",
"configuration",
"define-config",
"eslint-config",
"eslint",
"eslintconfig",
"typed",
"typescript"
],
"author": {
"name": "Christopher Quadflieg",
"email": "chrissi92@hotmail.de",
"url": "https://github.com/Shinigami92"
},
"repository": {
"type": "git",
"url": "https://github.com/eslint-types/eslint-define-config.git"
},
"funding": [
{
"type": "github",
"url": "https://github.com/Shinigami92"
},
{
"type": "paypal",
"url": "https://www.paypal.com/donate/?hosted_button_id=L7GY729FBKTZY"
}
],
"bugs": "https://github.com/eslint-types/eslint-define-config/issues",
"license": "MIT",
"files": [
"dist",
"src",
"tsconfig.json"
],
"devDependencies": {
"@graphql-eslint/eslint-plugin": "~3.20.1",
"@intlify/eslint-plugin-vue-i18n": "~2.0.0",
"@poppinss/cliui": "~6.4.1",
"@types/dedent": "^0.7.2",
"@types/eslint": "~8.44.3",
"@types/json-schema": "~7.0.13",
"@types/node": "~20.8.3",
"@typescript-eslint/eslint-plugin": "~6.7.4",
"@typescript-eslint/parser": "~6.7.4",
"@vitest/coverage-v8": "~0.34.6",
"change-case": "~5.4.4",
"dedent": "^1.5.3",
"eslint-config-prettier": "~9.0.0",
"eslint-gitignore": "~0.1.0",
"eslint-plugin-deprecation": "~2.0.0",
"eslint-plugin-eslint-comments": "~3.2.0",
"eslint-plugin-import": "~2.28.1",
"eslint-plugin-inclusive-language": "~2.2.1",
"eslint-plugin-jsdoc": "~46.8.2",
"eslint-plugin-jsonc": "~2.9.0",
"eslint-plugin-jsx-a11y": "~6.7.1",
"eslint-plugin-mdx": "~3.1.5",
"eslint-plugin-n": "~16.1.0",
"eslint-plugin-node": "~11.1.0",
"eslint-plugin-prettier": "~5.0.0",
"eslint-plugin-promise": "~6.1.1",
"eslint-plugin-react": "~7.33.2",
"eslint-plugin-react-hooks": "~4.6.0",
"eslint-plugin-sonarjs": "~0.21.0",
"eslint-plugin-spellcheck": "~0.0.20",
"eslint-plugin-testing-library": "~6.0.2",
"eslint-plugin-unicorn": "~48.0.1",
"eslint-plugin-vitest": "~0.3.2",
"eslint-plugin-vue": "~9.17.0",
"eslint-plugin-vue-pug": "~0.6.0",
"eslint-plugin-yml": "~1.10.0",
"expect-type": "~0.17.3",
"graphql": "~16.8.1",
"json-schema": "~0.4.0",
"json-schema-to-ts": "~2.9.2",
"json-schema-to-typescript": "~13.1.1",
"npm-run-all": "~4.1.5",
"prettier-plugin-organize-imports": "^3.2.4",
"rimraf": "~5.0.5",
"tsup": "~7.2.0",
"vue-eslint-parser": "~9.3.2"
},
"packageManager": "pnpm@8.8.0",
"engines": {
"node": ">=18.0.0",
"npm": ">=9.0.0",
"pnpm": ">=8.6.0"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
diff --git b/lib/rules/eslint/no-constructor-return.d.ts a/lib/rules/eslint/no-constructor-return.d.ts
index fedeca4..3e1fd03 100644
--- b/lib/rules/eslint/no-constructor-return.d.ts
+++ a/lib/rules/eslint/no-constructor-return.d.ts
@@ -1,16 +1,9 @@
import type { RuleConfig } from '../rule-config';
-/**
- * Option.
- */
-export interface NoConstructorReturnOption {
- [k: string]: any;
-}
-
/**
* Options.
*/
-export type NoConstructorReturnOptions = NoConstructorReturnOption;
+export type NoConstructorReturnOptions = [];
/**
* Disallow returning value from constructor.

View File

@ -0,0 +1,14 @@
diff --git b/lib/rules/graphql-eslint/naming-convention.d.ts a/lib/rules/graphql-eslint/naming-convention.d.ts
index 60b228b..5e01373 100644
--- b/lib/rules/graphql-eslint/naming-convention.d.ts
+++ a/lib/rules/graphql-eslint/naming-convention.d.ts
@@ -78,8 +78,7 @@ export type NamingConventionOption =
VariableDefinition?: AsString | AsObject;
allowLeadingUnderscore?: boolean;
allowTrailingUnderscore?: boolean;
- /**
- */
+ } & {
[k: string]: AsString | AsObject;
},
];

View File

@ -0,0 +1,13 @@
diff --git b/lib/rules/node/file-extension-in-import.d.ts a/lib/rules/node/file-extension-in-import.d.ts
index 652b18d..7261252 100644
--- b/lib/rules/node/file-extension-in-import.d.ts
+++ a/lib/rules/node/file-extension-in-import.d.ts
@@ -5,7 +5,7 @@ import type { RuleConfig } from '../rule-config';
*/
export interface FileExtensionInImportConfig {
tryExtensions?: string[];
- [k: string]: 'always' | 'never';
+ [ext: `.${string}`]: 'always' | 'never';
}
/**

View File

@ -0,0 +1,23 @@
diff --git a/lib/rules/react/jsx-no-constructed-context-values.d.ts b/lib/rules/react/jsx-no-constructed-context-values.d.ts
index 410f060..e356693 100644
--- a/lib/rules/react/jsx-no-constructed-context-values.d.ts
+++ b/lib/rules/react/jsx-no-constructed-context-values.d.ts
@@ -1,17 +1,9 @@
import type { RuleConfig } from '../rule-config';
-/**
- * Option.
- */
-export interface JsxNoConstructedContextValuesOption {
- [k: string]: any;
-}
-
/**
* Options.
*/
-export type JsxNoConstructedContextValuesOptions =
- JsxNoConstructedContextValuesOption;
+export type JsxNoConstructedContextValuesOptions = [];
/**
* Disallows JSX context provider values from taking values that will cause needless rerenders.

View File

@ -0,0 +1,13 @@
diff --git a/lib/rules/react/jsx-props-no-spreading.d.ts b/lib/rules/react/jsx-props-no-spreading.d.ts
index c1e0069..ba1e1bc 100644
--- a/lib/rules/react/jsx-props-no-spreading.d.ts
+++ b/lib/rules/react/jsx-props-no-spreading.d.ts
@@ -8,8 +8,6 @@ export type JsxPropsNoSpreadingOption = {
custom?: 'enforce' | 'ignore';
exceptions?: string[];
[k: string]: any;
-} & {
- [k: string]: any;
};
/**

View File

@ -0,0 +1,21 @@
diff --git a/lib/rules/vitest/valid-title.d.ts b/lib/rules/vitest/valid-title.d.ts
index 160be76..834ac9b 100644
--- a/lib/rules/vitest/valid-title.d.ts
+++ b/lib/rules/vitest/valid-title.d.ts
@@ -7,15 +7,7 @@ export interface ValidTitleOption {
ignoreTypeOfDescribeName?: boolean;
allowArguments?: boolean;
disallowedWords?: string[];
- /**
- */
- [k: string]:
- | string
- | [string]
- | [string, string]
- | {
- [k: string]: string | [string] | [string, string];
- };
+ [k: string]: any;
}
/**

View File

@ -0,0 +1,178 @@
#!/usr/bin/env bun
import { Logger, colors as cliColors } from '@poppinss/cliui';
import { pascalCase } from 'change-case';
import type { Rule } from 'eslint';
import { existsSync, promises as fs } from 'node:fs';
import { join, resolve } from 'node:path';
import { format } from 'prettier';
import { buildJSDoc, prettierConfig, type Plugin } from './utils';
import { PLUGIN_REGISTRY, loadPlugin } from './plugins-map';
import { RuleFile } from './rule-file';
interface FailedRule {
ruleName: string;
err: unknown;
}
const logger = new Logger();
const colors = cliColors.ansi();
const getRuleName = (name: string) =>
name === 'ESLint' ? 'ESLintRule' : `${pascalCase(name)}Rule`;
const index: [string, string][] = [];
/**
* Generate the `index.d.ts` file for the plugin's rules that will re-export all rules.
*/
async function generateRuleIndexFile(
pluginDirectory: string,
{ rules, name, id }: Plugin,
failedRules: FailedRule[],
): Promise<void> {
const generatedRules = Object.keys(rules!).filter(
ruleName => !failedRules.some(failedRule => failedRule.ruleName === ruleName),
);
/**
* Build all the import statements for the rules.
*/
const rulesImports = generatedRules
.map(name => `import type { ${getRuleName(name)} } from './${name}';`)
.join('\n');
/**
* Build the exported type that is an intersection of all the rules.
*/
const rulesFinalIntersection = generatedRules
.map(name => `${getRuleName(name)}`)
.sort()
.join(' & ');
const pluginRulesType = `
${buildJSDoc([`All ${name} rules.`])}
export type ${name}Rules = ${rulesFinalIntersection};
`;
/**
* Write the final `index.d.ts` file.
*/
const fileContent = `
${rulesImports}
${pluginRulesType}
`;
const indexPath = join(pluginDirectory, 'index.d.ts');
await fs.writeFile(indexPath, await format(fileContent, prettierConfig));
index.push([`${name}Rules`, `./${id}/index`]);
}
/**
* Print a report after having generated rules files for a plugin.
*/
function printGenerationReport(
rules: Array<[string, Rule.RuleModule]>,
failedRules: FailedRule[],
): void {
const msg: string = ` ✅ Generated ${rules.length - failedRules.length} rules`;
logger.logUpdate(colors.green(msg));
logger.logUpdatePersist();
if (failedRules.length) {
logger.log(colors.red(` ❌ Failed ${failedRules.length} rules`));
failedRules.forEach(({ ruleName, err }) => {
logger.log(colors.red(` - ${ruleName}: ${String(err)}`));
});
}
logger.log('');
}
/**
* Generate a `.d.ts` file for each rule in the given plugin.
*/
async function generateRulesFiles(
plugin: Plugin,
pluginDirectory: string,
): Promise<{ failedRules: FailedRule[] }> {
const failedRules: FailedRule[] = [];
const pluginRules = plugin.rules;
if (!pluginRules) {
throw new Error(
`Plugin ${plugin.name} doesn't have any rules. Did you forget to load them?`,
);
}
const rules = Object.entries(pluginRules);
for (const [ruleName, rule] of rules) {
logger.logUpdate(colors.yellow(` Generating > ${ruleName}`));
try {
await RuleFile(plugin, pluginDirectory, ruleName, rule);
} catch (err) {
failedRules.push({ ruleName, err });
}
}
printGenerationReport(rules, failedRules);
return { failedRules };
}
const rulesDirectory = resolve(__dirname, '../../../src/types/rules');
/**
* If it doesn't exist, create the directory that will contain the plugin's rule files.
*/
async function createPluginDirectory(pluginName: string): Promise<string> {
const pluginDirectory = join(rulesDirectory, pluginName);
if (existsSync(pluginDirectory)) {
await fs.rm(pluginDirectory, { recursive: true, force: true });
}
await fs.mkdir(pluginDirectory, { mode: 0o755, recursive: true });
return pluginDirectory;
}
export interface RunOptions {
plugins?: string[];
targetDirectory?: string;
}
for (const plugin of PLUGIN_REGISTRY) {
logger.info(`Generating ${plugin.name} rules.`);
logger.logUpdate(colors.yellow(` Loading plugin > ${plugin.name}`));
const loadedPlugin = await loadPlugin(plugin);
const pluginDir = await createPluginDirectory(plugin.id);
const { failedRules } = await generateRulesFiles(loadedPlugin, pluginDir);
await generateRuleIndexFile(pluginDir, loadedPlugin, failedRules);
}
await fs.writeFile(
resolve(rulesDirectory, 'index.d.ts'),
await format(
[
'import type { RuleConfig } from "./rule-config";',
...index.map(([name, path]) => `import { ${name} } from ${JSON.stringify(path)};`),
'',
'/**',
' * Rules.',
' *',
' * @see [Rules](https://eslint.org/docs/user-guide/configuring/rules)',
' */',
'',
'export type Rules = Partial<',
...index.map(([name]) => ` ${name} &`),
' Record<string, RuleConfig>',
'>;',
].join('\n'),
prettierConfig,
),
);

View File

@ -0,0 +1,58 @@
import type { JSONSchema4 } from 'json-schema';
import { compile } from 'json-schema-to-typescript';
/**
* Remove unnecessary comments that are generated by `json-schema-to-typescript`.
*/
function cleanJsDoc(content: string): string {
const patterns = [
/\* This interface was referenced by .+ JSON-Schema definition/,
/\* via the `.+` "/,
];
return content
.split('\n')
.filter(line => !patterns.some(ignoredLine => ignoredLine.test(line)))
.join('\n');
}
/**
* Replace some types that are generated by `json-schema-to-typescript`.
*/
export function patchTypes(content: string): string {
const replacements: [RegExp, string][] = [
[
/\(string & \{\s*\[k: string\]: any\s*\} & \{\s*\[k: string\]: any\s*\}\)\[\]/,
'string[]',
],
];
for (const [pattern, replacement] of replacements) {
content = content.replace(pattern, replacement);
}
return content;
}
/**
* Generate a type from the given JSON schema.
*/
export async function generateTypeFromSchema(
schema: JSONSchema4,
typeName: string,
): Promise<string> {
schema = JSON.parse(
JSON.stringify(schema).replace(/#\/items\/0\/\$defs\//g, '#/$defs/'),
);
const result = await compile(schema, typeName, {
format: false,
bannerComment: '',
style: {
singleQuote: true,
trailingComma: 'all',
},
unknownAny: false,
});
return patchTypes(cleanJsDoc(result));
}

View File

@ -0,0 +1,145 @@
import type { Plugin, PluginRules } from './utils';
/**
* Map of plugins for which the script will generate rule files.
*/
export const PLUGIN_REGISTRY: Plugin[] = [
{
id: 'deprecation',
name: 'Deprecation',
module: () => import('eslint-plugin-deprecation'),
},
{
id: 'eslint',
name: 'ESLint',
module: () => import('eslint'),
},
{
id: 'typescript-eslint',
name: 'TypeScript',
prefix: '@typescript-eslint',
module: () => import('@typescript-eslint/eslint-plugin'),
},
{
id: 'import',
name: 'Import',
module: () => import('eslint-plugin-import'),
},
{
id: 'eslint-comments',
name: 'EslintComments',
module: () => import('eslint-plugin-eslint-comments'),
},
{
id: 'graphql-eslint',
name: 'GraphQL',
prefix: '@graphql-eslint',
module: () => import('@graphql-eslint/eslint-plugin'),
},
{
id: 'jsdoc',
name: 'JSDoc',
prefix: 'jsdoc',
module: () => import('eslint-plugin-jsdoc'),
},
{
id: 'jsonc',
name: 'Jsonc',
module: () => import('eslint-plugin-jsonc'),
},
{
id: 'jsx-a11y',
name: 'JsxA11y',
module: () => import('eslint-plugin-jsx-a11y'),
},
{
id: 'mdx',
name: 'Mdx',
module: () => import('eslint-plugin-mdx'),
},
{
id: 'n',
name: 'N',
module: () => import('eslint-plugin-n'),
},
{
id: 'node',
name: 'Node',
module: () => import('eslint-plugin-node'),
},
{
id: 'promise',
name: 'Promise',
module: () => import('eslint-plugin-promise'),
},
{
id: 'react',
name: 'React',
module: () => import('eslint-plugin-react'),
},
{
id: 'react-hooks',
name: 'ReactHooks',
module: () => import('eslint-plugin-react-hooks'),
},
{
id: 'sonarjs',
name: 'SonarJS',
prefix: 'sonarjs',
module: () => import('eslint-plugin-sonarjs'),
},
{
id: 'spellcheck',
name: 'Spellcheck',
module: () => import('eslint-plugin-spellcheck'),
},
{
id: 'testing-library',
name: 'TestingLibrary',
module: () => import('eslint-plugin-testing-library'),
},
{
id: 'unicorn',
name: 'Unicorn',
module: () => import('eslint-plugin-unicorn'),
},
{
id: 'vitest',
name: 'Vitest',
module: () => import('eslint-plugin-vitest'),
},
{
id: 'vue',
name: 'Vue',
module: () => import('eslint-plugin-vue'),
},
{
id: 'vue-i18n',
name: 'VueI18n',
prefix: '@intlify/vue-i18n',
module: () => import('@intlify/eslint-plugin-vue-i18n'),
},
{
id: 'vue-pug',
name: 'VuePug',
module: () => import('eslint-plugin-vue-pug'),
},
{
id: 'yml',
name: 'Yml',
module: () => import('eslint-plugin-yml'),
},
] as const;
export async function loadPlugin(plugin: Plugin): Promise<Plugin> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const mod: any = await plugin.module();
const rules: PluginRules =
plugin.name === 'ESLint'
? Object.fromEntries(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
new mod.Linter().getRules().entries(),
)
: mod.rules ?? mod.default.rules;
return { ...plugin, rules };
}

View File

@ -0,0 +1,168 @@
import { Logger, colors as cliColors } from '@poppinss/cliui';
import { pascalCase, kebabCase } from 'change-case';
import type { Rule } from 'eslint';
import type { JSONSchema4 } from 'json-schema';
import { execSync } from 'node:child_process';
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { format } from 'prettier';
import { generateTypeFromSchema } from './json-schema-to-ts';
import { buildJSDoc, prettierConfig, type Plugin } from './utils';
const logger = new Logger();
const colors = cliColors.ansi();
/**
* Build the rule description to append to the JSDoc.
*/
function buildDescription(description = ''): string {
description = description.charAt(0).toUpperCase() + description.slice(1);
if (description.length > 0 && !description.endsWith('.')) {
description += '.';
}
return description.replace('*/', '');
}
export async function RuleFile(
plugin: Plugin,
pluginDirectory: string,
ruleName: string,
rule: Rule.RuleModule,
) {
let content = '';
const rulePath = resolve(pluginDirectory, `${ruleName}.d.ts`);
const ruleNamePascalCase = pascalCase(ruleName);
const schema: JSONSchema4 | JSONSchema4[] | undefined = rule.meta?.schema;
const isSchemaArray = Array.isArray(schema);
const mainSchema = isSchemaArray ? schema[0] : schema;
const sideSchema = isSchemaArray && schema.length > 1 ? schema[1] : undefined;
const thirdSchema = isSchemaArray && schema.length > 2 ? schema[2] : undefined;
/**
* Generate a JSDoc with the rule description and `@see` url.
*/
function generateTypeJsDoc(): string {
const { meta } = rule;
const seeDocLink: string = meta?.docs?.url
? `@see [${ruleName}](${meta.docs.url})`
: '';
return buildJSDoc([
buildDescription(rule.meta?.docs?.description),
' ',
rule.meta?.deprecated ? '@deprecated' : '',
rule.meta?.deprecated ? ' ' : '',
seeDocLink,
]);
}
/**
* Generate a type from a JSON schema and append it to the file content.
*/
async function appendJsonSchemaType(
schema: JSONSchema4,
comment: string,
): Promise<void> {
const type = await generateTypeFromSchema(schema, ruleNamePascalCase + comment);
const jsdoc = buildJSDoc([`${comment}.`]);
content += `\n${jsdoc}`;
content += `\n${type}\n`;
}
/**
* Scoped rule name ESLint config uses.
*/
function prefixedRuleName(): string {
const { prefix, name } = plugin;
const rulePrefix = (prefix ?? kebabCase(name)) + '/';
return name === 'ESLint' ? ruleName : `${rulePrefix}${ruleName}`;
}
/**
* Append the `import type { RuleConfig } from '../rule-config'` at the top of the file.
*/
const nestedDepth = ruleName.split('/').length;
content += `import type { RuleConfig } from '${'../'.repeat(nestedDepth)}rule-config'\n\n`;
/**
* Generate and append types for the rule schemas.
*/
if (thirdSchema) {
await appendJsonSchemaType(thirdSchema, 'Setting');
}
if (sideSchema) {
await appendJsonSchemaType(sideSchema, 'Config');
}
if (mainSchema) {
await appendJsonSchemaType(mainSchema, 'Option');
}
if (mainSchema) {
/**
* Append the rule type options to the file content.
*/
let type: string = '';
if (!isSchemaArray) {
type = `${ruleNamePascalCase}Option`;
} else if (thirdSchema) {
type = `[${ruleNamePascalCase}Option?, ${ruleNamePascalCase}Config?, ${ruleNamePascalCase}Setting?]`;
} else if (sideSchema) {
type = `[${ruleNamePascalCase}Option?, ${ruleNamePascalCase}Config?]`;
} else if (mainSchema) {
type = `[${ruleNamePascalCase}Option?]`;
}
content += buildJSDoc(['Options.']) + '\n';
content += `export type ${ruleNamePascalCase}Options = ${type}\n\n`;
}
/**
* Append the rule config type to the file content.
*/
content += generateTypeJsDoc() + '\n';
content += `export type ${ruleNamePascalCase}RuleConfig = RuleConfig<${mainSchema ? `${ruleNamePascalCase}Options` : '[]'}>;\n\n`;
/**
* Append the final rule interface to the file content.
*/
content += generateTypeJsDoc() + '\n';
content += `export interface ${ruleNamePascalCase}Rule {`;
content += `${generateTypeJsDoc()}\n`;
content += `'${prefixedRuleName()}': ${ruleNamePascalCase}RuleConfig;`;
content += '}';
content = await format(content, prettierConfig);
/**
* Create the directory of the rule file if it doesn't exist.
*/
const subPath = dirname(rulePath);
if (!existsSync(subPath)) {
mkdirSync(subPath, { recursive: true });
}
writeFileSync(rulePath, content);
/**
* Apply a patch to the generated content if a diff file exists for it.
*
* Must be called after `generate()`.
*/
const pathParts = rulePath.split('/');
const diffFile = resolve(
__dirname,
'./diffs/rules',
pathParts.at(-2) ?? '',
`${pathParts.at(-1) ?? ''}.diff`,
);
if (existsSync(diffFile)) {
logger.logUpdate(colors.yellow(` 🧹 Adjusting ${prefixedRuleName()}`));
logger.logUpdatePersist();
execSync(`git apply ${diffFile}`);
}
}

View File

@ -0,0 +1,24 @@
import type { Rule } from 'eslint';
import type { Config } from 'prettier';
export function buildJSDoc(content: string[]) {
return ['/**', ...content.filter(Boolean).map(line => ` * ${line}`), ' */'].join('\n');
}
export const prettierConfig: Config = {
plugins: ['prettier-plugin-organize-imports'],
parser: 'typescript',
singleQuote: true,
trailingComma: 'all',
};
export type MaybeArray<T> = T | T[];
export type PluginRules = Record<string, Rule.RuleModule>;
export interface Plugin {
id: string;
name: string;
prefix?: string;
module: () => Promise<any>;
rules?: PluginRules;
}

@ -1 +1 @@
Subproject commit 7b6bfc39474817efda02d186349523bb2bd569cf
Subproject commit 7a02ac08b5aaac8c217f0e87142f97eafcc38fbc

@ -1 +1 @@
Subproject commit 6b95a021938139726b3f862beb37012d6e2afab2
Subproject commit f77ceb679d59ced5d9a633123385470a9eea10d9

@ -1 +1 @@
Subproject commit fffb05b38c8eee926ee758e9ceb9eae4e697fbdd
Subproject commit 0d5321a5457c5f0da0ca216053cc5b4f571b53ae

@ -1 +1 @@
Subproject commit 47cd9a6a0e360d10d50e27a01123169dec00d40b
Subproject commit eb11b5b35a6a797dc7fba6df53b1c4dada3a2a55

@ -1 +1 @@
Subproject commit ecadb92609998520be80d64c0bd6bc5e05934aa9
Subproject commit 4467db503e38b9356517cf6926d11be544ccf4b1

View File

@ -8,20 +8,22 @@
/* eslint-disable no-for-of-loops/no-for-of-loops */
import type { Rule, Scope } from 'eslint';
import type {
FunctionDeclaration,
CallExpression,
Expression,
Super,
Node,
ArrayExpression,
ArrowFunctionExpression,
FunctionExpression,
SpreadElement,
Identifier,
VariableDeclarator,
MemberExpression,
CallExpression,
ChainExpression,
Pattern,
Expression,
FunctionDeclaration,
FunctionExpression,
Identifier,
MemberExpression,
Node,
OptionalMemberExpression,
Pattern,
SpreadElement,
Super,
TSAsExpression,
VariableDeclarator,
} from 'estree';
import type { FromSchema } from 'json-schema-to-ts';
import { __EXPERIMENTAL__ } from './index';
@ -109,7 +111,7 @@ const rule: Rule.RuleModule = {
*/
function visitFunctionWithDependencies(
node: ArrowFunctionExpression | FunctionExpression | FunctionDeclaration,
declaredDependenciesNode: SpreadElement | Expression,
declaredDependenciesNode: SpreadElement | Expression | undefined,
reactiveHook: Super | Expression,
reactiveHookName: string,
isEffect: boolean,
@ -128,7 +130,7 @@ const rule: Rule.RuleModule = {
' }\n' +
' fetchData();\n' +
`}, [someId]); // Or [] if effect doesn't need props or state\n\n` +
'Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching',
'Learn more about data fetching with Hooks: https://react.dev/link/hooks-data-fetching',
});
}
@ -194,7 +196,7 @@ const rule: Rule.RuleModule = {
if (init == null) {
return false;
}
while (init.type === 'TSAsExpression') {
while (init.type === 'TSAsExpression' || init.type === 'AsExpression') {
init = init.expression;
}
// Detect primitive constants
@ -620,7 +622,11 @@ const rule: Rule.RuleModule = {
const declaredDependencies: DeclaredDependency[] = [];
const externalDependencies = new Set<string>();
if (declaredDependenciesNode.type !== 'ArrayExpression') {
const isArrayExpression = declaredDependenciesNode.type === 'ArrayExpression';
const isTSAsArrayExpression =
declaredDependenciesNode.type === 'TSAsExpression' &&
declaredDependenciesNode.expression.type === 'ArrayExpression';
if (!isArrayExpression && !isTSAsArrayExpression) {
// If the declared dependencies are not an array expression then we
// can't verify that the user provided the correct dependencies. Tell
// the user this in an error.
@ -633,7 +639,10 @@ const rule: Rule.RuleModule = {
'dependencies.',
});
} else {
declaredDependenciesNode.elements.forEach(declaredDependencyNode => {
const arrayExpression = isTSAsArrayExpression
? ((declaredDependenciesNode as TSAsExpression).expression as ArrayExpression)
: (declaredDependenciesNode as ArrayExpression);
arrayExpression.elements.forEach(declaredDependencyNode => {
// Skip elided elements.
if (declaredDependencyNode === null) {
return;
@ -1158,7 +1167,11 @@ const rule: Rule.RuleModule = {
const reactiveHook = node.callee as Identifier | MemberExpression;
const reactiveHookName = (getNodeWithoutReactNamespace(reactiveHook) as Identifier)
.name;
const declaredDependenciesNode = node.arguments[callbackIndex + 1];
const maybeNode = node.arguments[callbackIndex + 1];
const declaredDependenciesNode =
maybeNode && !(maybeNode.type === 'Identifier' && maybeNode.name === 'undefined')
? maybeNode
: undefined;
const isEffect = /Effect($|[^a-z])/g.test(reactiveHookName);
// Check whether a callback is supplied. If there is no callback supplied
@ -1203,6 +1216,15 @@ const rule: Rule.RuleModule = {
isEffect,
);
return; // Handled
case 'TSAsExpression':
visitFunctionWithDependencies(
callback.expression,
declaredDependenciesNode,
reactiveHook,
reactiveHookName,
isEffect,
);
return; // Handled
case 'Identifier':
if (!declaredDependenciesNode) {
// No deps, no problems.
@ -1545,7 +1567,7 @@ function getConstructionExpressionType(node: Node) {
}
return null;
case 'TypeCastExpression':
return getConstructionExpressionType(node.expression);
case 'AsExpression':
case 'TSAsExpression':
return getConstructionExpressionType(node.expression);
}
@ -1749,7 +1771,7 @@ function analyzePropertyChain(
}
}
function getNodeWithoutReactNamespace(node: Identifier | MemberExpression) {
function getNodeWithoutReactNamespace(node: Expression | Super) {
if (
node.type === 'MemberExpression' &&
node.object.type === 'Identifier' &&

View File

@ -24,10 +24,7 @@ import { __EXPERIMENTAL__ } from './index';
*/
function isHookName(s: string) {
if (__EXPERIMENTAL__) {
return s === 'use' || /^use[A-Z0-9]/.test(s);
}
return /^use[A-Z0-9]/.test(s);
}
/**
@ -59,7 +56,7 @@ function isComponentName(node: Node) {
return node.type === 'Identifier' && /^[A-Z]/.test(node.name);
}
function isReactFunction(node: Expression | Super, functionName: string) {
function isReactFunction(node: Node, functionName: string) {
return (
(node as Identifier).name === functionName ||
(node.type === 'MemberExpression' &&
@ -115,10 +112,7 @@ function isUseEffectEventIdentifier(node: Node) {
}
function isUseIdentifier(node: Node) {
if (__EXPERIMENTAL__) {
return node.type === 'Identifier' && node.name === 'use';
}
return false;
return isReactFunction(node, 'use');
}
const rule: Rule.RuleModule = {

View File

@ -3,8 +3,8 @@
"version": 1,
"sources": {
"main": {
"repository": "git@github.com:facebook/react.git",
"commit": "899cb95f52cc83ab5ca1eb1e268c909d3f0961e7",
"repository": "https://github.com/facebook/react",
"commit": "0e0b69321a6fcfe8a3eaae3b1016beb110437b38",
"branch": "main"
}
}

30
pnpm-lock.yaml generated
View File

@ -32,8 +32,8 @@ devDependencies:
specifier: ^7.20.5
version: 7.20.5
'@types/eslint':
specifier: ^8.56.9
version: 8.56.9
specifier: ^8.56.10
version: 8.56.10
'@types/esprima':
specifier: ^4.0.6
version: 4.0.6
@ -71,8 +71,8 @@ devDependencies:
specifier: ^3.1.0
version: 3.1.0
dts-bundle-generator:
specifier: ^9.4.0
version: 9.4.0
specifier: ^9.5.0
version: 9.5.0
esbin:
specifier: 0.0.4
version: 0.0.4(esbuild@0.20.2)
@ -89,8 +89,8 @@ devDependencies:
specifier: ^9.1.0
version: 9.1.0(eslint@8.57.0)
eslint-define-config:
specifier: ^1.24.1
version: 1.24.1
specifier: file:./src/types
version: file:src/types
esprima:
specifier: ^4.0.1
version: 4.0.1
@ -1793,8 +1793,8 @@ packages:
'@babel/types': 7.24.0
dev: true
/@types/eslint@8.56.9:
resolution: {integrity: sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg==}
/@types/eslint@8.56.10:
resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==}
dependencies:
'@types/estree': 1.0.5
'@types/json-schema': 7.0.15
@ -2300,8 +2300,8 @@ packages:
esutils: 2.0.3
dev: true
/dts-bundle-generator@9.4.0:
resolution: {integrity: sha512-XncfIDd3QMZLAQcXqHUd1GrNHFzPSSwJBVmsY7cyrSIgY2K+vr46Nrjw5x9jmvxivR7YNFUWrPMLn8OD0OEwAg==}
/dts-bundle-generator@9.5.0:
resolution: {integrity: sha512-i+FofnRXVyn0q46DC2TaXSrmt7/FdDEf1UKnj7DkF90WmTiyF2zPU53tt9SSWb7Y0KegFDTI5l2DlgGK91bpKg==}
engines: {node: '>=14.0.0'}
hasBin: true
dependencies:
@ -2396,11 +2396,6 @@ packages:
eslint: 8.57.0
dev: true
/eslint-define-config@1.24.1:
resolution: {integrity: sha512-o36vBhPSWyIQlHoMqGhhcGmOOm2A2ccBVIdLTG/AWdm9YmjpsLpf+5ntf9LlHR6dduLREgxtGwvwPwSt7vnXJg==}
engines: {node: '>=18.0.0', npm: '>=9.0.0', pnpm: '>= 8.6.0'}
dev: true
/eslint-scope@7.2.2:
resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@ -3503,3 +3498,8 @@ packages:
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
engines: {node: '>=12.20'}
dev: true
file:src/types:
resolution: {directory: src/types, type: directory}
name: types
dev: true

View File

@ -1,4 +1,5 @@
#!/usr/bin/env tsx
#!/usr/bin/env bun
import './build-local-rules';
import { promises as fs } from 'node:fs';
import { resolve, relative } from 'node:path';
import { isBuiltin } from 'node:module';
@ -7,7 +8,6 @@ import type { Plugin } from 'esbuild';
import { memoize } from 'lodash';
import { gray, green } from 'picocolors';
import { dependencies } from '../dist/package.json';
import { buildLocalRules } from '../src/build-local-rules';
import { dts } from './dts';
import { babelPlugin } from './modifier';
@ -124,9 +124,6 @@ function bundleType(source: string, output: string) {
}
async function main() {
console.log('Building local rules...');
await buildLocalRules();
console.log('Building type definitions...');
bundleType('./src/index.ts', './dist/index.d.ts');
bundleType('./src/prettier.ts', './dist/prettier.d.ts');

View File

@ -1,14 +1,12 @@
#!/usr/bin/env tsx
import { promises as fs } from 'node:fs';
import { camelCase } from 'lodash';
export async function buildLocalRules() {
const files = (await fs.readdir('./src/rules'))
const files = (await fs.readdir('./src/rules'))
.filter(file => file.endsWith('.ts'))
.filter(file => file !== 'index.ts')
.map(file => file.slice(0, -3));
const entryFile = /* js */ `
const entryFile = /* js */ `
import type { Rule } from 'eslint';
import type { ESLintUtils } from '@typescript-eslint/utils';
@ -22,9 +20,5 @@ export const rules: Record<
};
`.trim();
await fs.writeFile('./src/rules/index.ts', entryFile + '\n');
}
if (require.main === module) {
buildLocalRules();
}
console.log('Building local rules...');
await fs.writeFile('./src/rules/index.ts', entryFile + '\n');

View File

@ -17,6 +17,9 @@ export function dts({
const entry: EntryPointConfig = {
filePath: source,
failOnClass: false,
libraries: {
importedLibraries: ['eslint-define-config'],
},
output: {
inlineDeclareExternals: false,
inlineDeclareGlobals: false,
@ -29,7 +32,7 @@ export function dts({
const generatedDts = generateDtsBundle([entry], {
preferredConfigPath: project,
followSymlinks: true,
followSymlinks: false,
});
ts.sys.writeFile(dist, generatedDts[0]);

View File

@ -1,24 +1,16 @@
#!/usr/bin/env tsx
import assert from 'node:assert';
import { readFileSync, promises as fs } from 'node:fs';
import { resolve, extname, relative } from 'node:path';
import { isBuiltin } from 'node:module';
import esbuild from 'esbuild';
import { readFileSync } from 'node:fs';
import { resolve, extname } from 'node:path';
import type { Loader, Plugin } from 'esbuild';
import * as babel from '@babel/core';
import { memoize } from 'lodash';
import { gray, green } from 'picocolors';
import type { types as t, types } from '@babel/core';
import { dependencies } from '../dist/package.json';
import { createMacro, type MacroHandler } from 'babel-plugin-macros';
import * as polyfill from '../src/polyfill';
import { buildLocalRules } from '../src/build-local-rules';
import { dts } from './dts';
const polyfills = Object.keys(polyfill);
const ENV = (process.env.NODE_ENV ??= 'production');
const PROD = ENV === 'production';
class HandlerMap {
map = new Map<string, MacroHandler>();

View File

@ -18,10 +18,10 @@
"subject": "[Deps] update `@babel/runtime`, `safe-regex-test`"
},
"eslint-plugin-n": {
"hash": "8d711f5446655c9874aeffb2ef28b3c4d8463fb6",
"date": "2024-04-16T16:08:04+08:00",
"hash": "eb11b5b35a6a797dc7fba6df53b1c4dada3a2a55",
"date": "2024-04-17T17:40:32+08:00",
"committer": "GitHub",
"subject": "chore: update outdated funding (#246)"
"subject": "chore: upgrade globals v15 (#241)"
},
"eslint-plugin-react": {
"hash": "4467db503e38b9356517cf6926d11be544ccf4b1",

View File

@ -4,7 +4,6 @@ import fs from 'node:fs';
import type { Rule } from 'eslint';
import type { ESLintUtils } from '@typescript-eslint/utils';
import type { ESLintConfig, Rules } from 'eslint-define-config';
// import findCacheDirectory from 'find-cache-dir';
import { typescriptRules } from './presets/typescript';
import { unicornRules } from './presets/unicorn';
import { eslintRules } from './presets/eslint';
@ -36,8 +35,8 @@ const ensureArray = <T>(value?: T | T[]): T[] =>
type RuleLevel = 'error' | 'warn' | 'off' | 0 | 1 | 2;
type RuleEntry<Options> = RuleLevel | [RuleLevel, Partial<Options>];
declare module 'eslint-define-config/src/rules/react/no-unknown-property.d.ts' {
export interface NoUnknownPropertyOption {
declare module 'eslint-define-config' {
interface NoUnknownPropertyOption {
extends: ('next' | 'emotion')[];
}
}
@ -167,13 +166,7 @@ export function extendConfig(of: InputConfig = {}): ESLintConfig {
},
overrides: [
{
files: [
'.eslintrc.js',
'*.config.js',
'index.js',
'babel.config.js',
'next.config.js',
],
files: ['.eslintrc.js', '.eslintrc.cjs', '*.config.js', 'index.js'],
extends: ['plugin:@typescript-eslint/disable-type-checked'],
rules: {
'rules/restrict-template-expressions': off,
@ -186,7 +179,7 @@ export function extendConfig(of: InputConfig = {}): ESLintConfig {
},
},
{
files: ['repl.ts'],
files: ['repl.ts', 'scripts/**/*.ts'],
rules: {
'no-console': off,
},

View File

@ -1,7 +1,7 @@
import { error, warn, off } from '../constants';
import { EslintRules } from 'eslint-define-config/src/rules/eslint';
import { ESLintRules } from 'eslint-define-config/rules/eslint';
export const eslintRules: Partial<EslintRules> = {
export const eslintRules: Partial<ESLintRules> = {
'arrow-body-style': [error, 'as-needed'],
'class-methods-use-this': off,
'func-style': [error, 'declaration', { allowArrowFunctions: true }],

View File

@ -1,4 +1,4 @@
import { GraphQLRules } from 'eslint-define-config/src/rules/graphql-eslint';
import { GraphQLRules } from 'eslint-define-config/rules/graphql-eslint';
// https://the-guild.dev/graphql/eslint/rules
export const graphqlRules: Partial<GraphQLRules> = {};

View File

@ -1,5 +1,5 @@
import { error, off } from '../constants';
import { ImportRules } from 'eslint-define-config/src/rules/import';
import { ImportRules } from 'eslint-define-config/rules/import';
export const importRules: Partial<ImportRules> = {
'import/export': off,

View File

@ -1,3 +1,3 @@
import { JSDocRules } from 'eslint-define-config/src/rules/jsdoc';
import { JSDocRules } from 'eslint-define-config/rules/jsdoc';
export const jsDocRules: Partial<JSDocRules> = {};

View File

@ -1,4 +1,4 @@
import type { LocalRuleOptions } from '..';
import type { LocalRuleOptions } from '../index';
import { error } from '../constants';
export const localRules: Partial<LocalRuleOptions> = {

View File

@ -1,5 +1,5 @@
import { error, off } from '../constants';
import { ReactRules } from 'eslint-define-config/src/rules/react';
import { ReactRules } from 'eslint-define-config/rules/react';
export const reactRules: Partial<ReactRules> = {
'react/display-name': off,

View File

@ -1,5 +1,5 @@
import { error, off, warn } from '../constants';
import type { TypeScriptRules } from 'eslint-define-config/src/rules/typescript-eslint';
import type { TypeScriptRules } from 'eslint-define-config/rules/typescript-eslint';
export const typescriptRules: Partial<TypeScriptRules> = {
'@typescript-eslint/ban-ts-comment': [

View File

@ -1,5 +1,5 @@
import { error, warn } from '../constants';
import { UnicornRules } from 'eslint-define-config/src/rules/unicorn';
import { UnicornRules } from 'eslint-define-config/rules/unicorn';
const suggest = (suggest: string) => ({ suggest, fix: false });

View File

@ -1,15 +1,15 @@
import type { Rule } from 'eslint';
import type { ESLintUtils } from '@typescript-eslint/utils';
import noEmptyObjectLiteral from './no-empty-object-literal';
import noImportDot from './no-import-dot';
import noEmptyObjectLiteral from './no-empty-object-literal';
import restrictTemplateExpressions from './restrict-template-expressions';
export const rules: Record<
string,
Rule.RuleModule | ESLintUtils.RuleModule<string, unknown[]>
> = {
'no-empty-object-literal': noEmptyObjectLiteral,
'no-import-dot': noImportDot,
'no-empty-object-literal': noEmptyObjectLiteral,
'restrict-template-expressions': restrictTemplateExpressions,
};

171
src/types/config/env.d.ts vendored Normal file
View File

@ -0,0 +1,171 @@
/**
* An environment provides predefined global variables.
*
* @see [Environments](https://eslint.org/docs/user-guide/configuring/language-options#specifying-environments)
*/
export interface Environments extends Partial<Record<string, boolean>> {
/**
* Browser global variables.
*/
browser?: boolean;
/**
* Node.js global variables and Node.js scoping.
*/
node?: boolean;
/**
* CommonJS global variables and CommonJS scoping (use this for browser-only code that uses Browserify/WebPack).
*/
commonjs?: boolean;
/**
* Globals common to both Node.js and Browser.
*/
'shared-node-browser'?: boolean;
/**
* Enable all ECMAScript 6 features except for modules (this automatically sets the `ecmaVersion` parser option to 6).
*/
es6?: boolean;
/**
* Adds all ECMAScript 2016 globals and automatically sets the `ecmaVersion` parser option to 7.
*/
es2016?: boolean;
/**
* Adds all ECMAScript 2017 globals and automatically sets the `ecmaVersion` parser option to 8.
*/
es2017?: boolean;
/**
* Adds all ECMAScript 2018 globals and automatically sets the `ecmaVersion` parser option to 9.
*/
es2018?: boolean;
/**
* Adds all ECMAScript 2019 globals and automatically sets the `ecmaVersion` parser option to 10.
*/
es2019?: boolean;
/**
* Adds all ECMAScript 2020 globals and automatically sets the `ecmaVersion` parser option to 11.
*/
es2020?: boolean;
/**
* Adds all ECMAScript 2021 globals and automatically sets the `ecmaVersion` parser option to 12.
*/
es2021?: boolean;
/**
* Adds all ECMAScript 2022 globals and automatically sets the `ecmaVersion` parser option to 13.
*/
es2022?: boolean;
/**
* Adds all ECMAScript 2023 globals and automatically sets the `ecmaVersion` parser option to 14.
*/
es2023?: boolean;
/**
* Web workers global variables.
*/
worker?: boolean;
/**
* Defines `require()` and `define()` as global variables as per the amd spec.
*/
amd?: boolean;
/**
* Adds all of the Mocha testing global variables.
*/
mocha?: boolean;
/**
* Adds all of the Jasmine testing global variables for version 1.3 and 2.0.
*/
jasmine?: boolean;
/**
* Jest global variables.
*/
jest?: boolean;
/**
* PhantomJS global variables.
*/
phantomjs?: boolean;
/**
* Protractor global variables.
*/
protractor?: boolean;
/**
* QUnit global variables.
*/
qunit?: boolean;
/**
* jQuery global variables.
*/
jquery?: boolean;
/**
* Prototype.js global variables.
*/
prototypejs?: boolean;
/**
* ShellJS global variables.
*/
shelljs?: boolean;
/**
* Meteor global variables.
*/
meteor?: boolean;
/**
* MongoDB global variables.
*/
mongo?: boolean;
/**
* AppleScript global variables.
*/
applescript?: boolean;
/**
* Java 8 Nashorn global variables.
*/
nashorn?: boolean;
/**
* Service Worker global variables.
*/
serviceworker?: boolean;
/**
* Atom test helper globals.
*/
atomtest?: boolean;
/**
* Ember test helper globals.
*/
embertest?: boolean;
/**
* WebExtensions globals.
*/
webextensions?: boolean;
/**
* GreaseMonkey globals.
*/
greasemonkey?: boolean;
}

View File

@ -0,0 +1,6 @@
/**
* Eslint EslintComments extends.
*
* @see [Eslint EslintComments extends](https://mysticatea.github.io/eslint-plugin-eslint-comments/#%F0%9F%93%96-usage)
*/
export type EslintCommentsExtends = 'plugin:eslint-comments/recommended';

View File

@ -0,0 +1,11 @@
/**
* Eslint GraphQL extends.
*
* @see [Eslint GraphQL extends](https://the-guild.dev/graphql/eslint/docs/configs)
*/
export type GraphqlExtends =
| 'plugin:@graphql-eslint/operations-all'
| 'plugin:@graphql-eslint/operations-recommended'
| 'plugin:@graphql-eslint/relay'
| 'plugin:@graphql-eslint/schema-all'
| 'plugin:@graphql-eslint/schema-recommended';

View File

@ -0,0 +1,9 @@
/**
* Eslint import extends.
*
* @see [Eslint import extends](https://github.com/benmosher/eslint-plugin-import#installation)
*/
export type ImportExtends =
| 'plugin:import/errors'
| 'plugin:import/warnings'
| 'plugin:import/typescript';

View File

@ -0,0 +1,6 @@
/**
* Eslint JSDoc extends.
*
* @see [Eslint JSDoc extends](https://github.com/gajus/eslint-plugin-jsdoc#configuration)
*/
export type JsdocExtends = 'plugin:jsdoc/recommended';

View File

@ -0,0 +1,13 @@
/**
* Eslint Jsonc extends.
*
* @see [Eslint Jsonc extends](https://github.com/ota-meshi/eslint-plugin-jsonc#configuration)
*/
export type JsoncExtends =
| 'plugin:jsdoc/base'
| 'plugin:jsdoc/recommended'
| 'plugin:jsonc/recommended-with-json'
| 'plugin:jsonc/recommended-with-jsonc'
| 'plugin:jsonc/recommended-with-json5'
| 'plugin:jsonc/prettier'
| 'plugin:jsonc/all';

View File

@ -0,0 +1,8 @@
/**
* Eslint JSX A11y extends.
*
* @see [Eslint JSX A11y extends](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y)
*/
export type JsxA11yExtends =
| 'plugin:jsx-a11y/strict'
| 'plugin:jsx-a11y/recommended';

View File

@ -0,0 +1,10 @@
/**
* Eslint MDX extends.
*
* @see [Eslint MDX extends](https://github.com/mdx-js/eslint-mdx/tree/master/packages/eslint-plugin-mdx)
*/
export type MdxExtends =
| 'plugin:mdx/base'
| 'plugin:mdx/code-blocks'
| 'plugin:mdx/overrides'
| 'plugin:mdx/recommended';

View File

@ -0,0 +1,9 @@
/**
* Eslint N (Node) extends.
*
* @see [Eslint N extends](https://github.com/eslint-community/eslint-plugin-n#-configs)
*/
export type NExtends =
| 'plugin:n/recommended'
| 'plugin:n/recommended-module'
| 'plugin:n/recommended-script';

View File

@ -0,0 +1,9 @@
/**
* Eslint Node extends.
*
* @see [Eslint Node extends](https://github.com/mysticatea/eslint-plugin-node#-configs)
*/
export type NodeExtends =
| 'plugin:node/recommended'
| 'plugin:node/recommended-module'
| 'plugin:node/recommended-script';

View File

@ -0,0 +1,6 @@
/**
* Eslint Prettier extends.
*
* @see [Eslint Prettier extends](https://github.com/prettier/eslint-plugin-prettier#recommended-configuration)
*/
export type PrettierExtends = 'plugin:prettier/recommended' | 'prettier';

View File

@ -0,0 +1,6 @@
/**
* Eslint promise extends.
*
* @see [Eslint promise extends](https://github.com/eslint-community/eslint-plugin-promise#usage)
*/
export type PromiseExtends = 'plugin:promise/recommended';

View File

@ -0,0 +1,6 @@
/**
* Eslint ReactHooks extends.
*
* @see [Eslint ReactHooks extends](https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks)
*/
export type ReactHooksExtends = 'plugin:react-hooks/recommended';

View File

@ -0,0 +1,9 @@
/**
* Eslint React extends.
*
* @see [Eslint React extends](https://github.com/jsx-eslint/eslint-plugin-react)
*/
export type ReactExtends =
| 'plugin:react/all'
| 'plugin:react/jsx-runtime'
| 'plugin:react/recommended';

View File

@ -0,0 +1,6 @@
/**
* Eslint Sonarjs extends.
*
* @see [Eslint Sonarjs extends](https://github.com/SonarSource/eslint-plugin-sonarjs#available-configurations)
*/
export type SonarjsExtends = 'plugin:sonarjs/recommended';

View File

@ -0,0 +1,11 @@
/**
* Eslint TestingLibrary extends.
*
* @see [Eslint TestingLibrary extends](https://github.com/testing-library/eslint-plugin-testing-library)
*/
export type TestingLibraryExtends =
| 'plugin:testing-library/angular'
| 'plugin:testing-library/dom'
| 'plugin:testing-library/marko'
| 'plugin:testing-library/react'
| 'plugin:testing-library/vue';

View File

@ -0,0 +1,8 @@
/**
* Eslint Unicorn extends.
*
* @see [Eslint Unicorn extends](https://github.com/sindresorhus/eslint-plugin-unicorn)
*/
export type UnicornExtends =
| 'plugin:unicorn/recommended'
| 'plugin:unicorn/all';

View File

@ -0,0 +1,6 @@
/**
* Eslint Vitest extends.
*
* @see [Eslint Vitest extends](https://eslint.vuejs.org/user-guide/#usage)
*/
export type VitestExtends = 'plugin:vitest/all' | 'plugin:vitest/recommended';

View File

@ -0,0 +1,13 @@
/**
* Eslint Vue Pug extends.
*
* @see [Eslint Vue Pug extends](https://github.com/rashfael/eslint-plugin-vue-pug#usage)
*/
export type VuePugExtends =
| 'plugin:vue-pug/base'
| 'plugin:vue-pug/vue3-essential'
| 'plugin:vue-pug/vue3-strongly-recommended'
| 'plugin:vue-pug/vue3-recommended'
| 'plugin:vue-pug/essential'
| 'plugin:vue-pug/strongly-recommended'
| 'plugin:vue-pug/recommended';

View File

@ -0,0 +1,13 @@
/**
* Eslint Vue extends.
*
* @see [Eslint Vue extends](https://eslint.vuejs.org/user-guide/#usage)
*/
export type VueExtends =
| 'plugin:vue/base'
| 'plugin:vue/vue3-essential'
| 'plugin:vue/vue3-strongly-recommended'
| 'plugin:vue/vue3-recommended'
| 'plugin:vue/essential'
| 'plugin:vue/strongly-recommended'
| 'plugin:vue/recommended';

4
src/types/config/extends/eslint.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
/**
* Eslint extends.
*/
export type EslintExtends = 'eslint:recommended' | 'eslint:all';

82
src/types/config/extends/index.d.ts vendored Normal file
View File

@ -0,0 +1,82 @@
import type { LiteralUnion } from '../../utility-types';
import type { EslintExtends } from './eslint';
import type { EslintCommentsExtends } from './eslint-plugin-eslint-comment';
import type { GraphqlExtends } from './eslint-plugin-graphql';
import type { ImportExtends } from './eslint-plugin-import';
import type { JsdocExtends } from './eslint-plugin-jsdoc';
import type { JsoncExtends } from './eslint-plugin-jsonc';
import type { MdxExtends } from './eslint-plugin-mdx';
import type { NExtends } from './eslint-plugin-n';
import type { NodeExtends } from './eslint-plugin-node';
import type { PrettierExtends } from './eslint-plugin-prettier';
import type { PromiseExtends } from './eslint-plugin-promise';
import type { ReactExtends } from './eslint-plugin-react';
import type { ReactHooksExtends } from './eslint-plugin-react-hooks';
import type { SonarjsExtends } from './eslint-plugin-sonarjs';
import type { TestingLibraryExtends } from './eslint-plugin-testing-library';
import type { UnicornExtends } from './eslint-plugin-unicorn';
import type { VitestExtends } from './eslint-plugin-vitest';
import type { VueExtends } from './eslint-plugin-vue';
import type { VuePugExtends } from './eslint-plugin-vue-pug';
import type { IntlifyVueI18nExtends } from './intlify-vue-i18n';
import type { TypescriptEslintExtends } from './typescript-eslint';
/**
* This is a special exported interface for other packages to declare
* additional extensions that should bail out for eslint extensions. For example
* `'@typescript-eslint/eslint-plugin'` can declare it like so in its `d.ts`:
*
* ```ts
* declare module 'eslint-define-config' {
* export interface CustomExtends {
* 'plugin:@typescript-eslint/all': void;
* 'plugin:@typescript-eslint/base': void;
* 'plugin:@typescript-eslint/disable-type-checked': void;
* 'plugin:@typescript-eslint/eslint-recommended': void;
* 'plugin:@typescript-eslint/recommended-type-checked': void;
* 'plugin:@typescript-eslint/recommended': void;
* 'plugin:@typescript-eslint/strict-type-checked': void;
* 'plugin:@typescript-eslint/strict': void;
* 'plugin:@typescript-eslint/stylistic-type-checked': void;
* 'plugin:@typescript-eslint/stylistic': void;
* }
* }
* ```
*/
export interface CustomExtends {}
/**
* All known extends.
*/
export type KnownExtends = LiteralUnion<
| EslintCommentsExtends
| EslintExtends
| GraphqlExtends
| ImportExtends
| IntlifyVueI18nExtends
| JsdocExtends
| JsoncExtends
| MdxExtends
| NExtends
| NodeExtends
| PrettierExtends
| PromiseExtends
| ReactExtends
| ReactHooksExtends
| SonarjsExtends
| TestingLibraryExtends
| TypescriptEslintExtends
| UnicornExtends
| VitestExtends
| VueExtends
| VuePugExtends
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
| keyof CustomExtends
>;
/**
* Extending Configuration Files.
*
* @see [Extends](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files)
*/
export type Extends = KnownExtends | KnownExtends[];

View File

@ -0,0 +1,6 @@
/**
* Eslint Intlify VueI18n extends.
*
* @see [Eslint Intlify VueI18n extends](https://eslint-plugin-vue-i18n.intlify.dev/started.html)
*/
export type IntlifyVueI18nExtends = 'plugin:@intlify/vue-i18n/recommended';

View File

@ -0,0 +1,17 @@
/**
* Typescript eslint extends.
*
* @see [Typescript eslint extends](https://typescript-eslint.io/linting/configs#recommended-configurations)
*/
export type TypescriptEslintExtends =
| 'plugin:@typescript-eslint/all'
| 'plugin:@typescript-eslint/base'
| 'plugin:@typescript-eslint/disable-type-checked'
| 'plugin:@typescript-eslint/eslint-recommended'
| 'plugin:@typescript-eslint/recommended-requiring-type-checking' // this requiring-type-checking is deprecated and only for @typescript-eslint/eslint-plugin@v5
| 'plugin:@typescript-eslint/recommended-type-checked'
| 'plugin:@typescript-eslint/recommended'
| 'plugin:@typescript-eslint/strict-type-checked'
| 'plugin:@typescript-eslint/strict'
| 'plugin:@typescript-eslint/stylistic-type-checked'
| 'plugin:@typescript-eslint/stylistic';

121
src/types/config/index.d.ts vendored Normal file
View File

@ -0,0 +1,121 @@
import type { Parser, ParserOptions } from '../parser-options';
import type { Rules } from '../rules';
import type { Environments } from './env';
import type { Extends } from './extends';
import type { Overrides } from './overrides';
import type { Plugin } from './plugin';
import type { Settings } from './settings';
/**
* ESLint Configuration.
*
* @see [ESLint Configuration](https://eslint.org/docs/latest/user-guide/configuring/)
*/
export interface ESLintConfig {
/**
* @see [Using Configuration Files](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#using-configuration-files)
*/
root?: boolean;
/**
* Tell ESLint to ignore specific files and directories.
*
* @see [Ignore Patterns](https://eslint.org/docs/latest/user-guide/configuring/ignoring-code)
*/
ignorePatterns?: string[];
/**
* An environment provides predefined global variables.
*
* @see [Environments](https://eslint.org/docs/latest/user-guide/configuring/language-options#specifying-environments)
*/
env?: Environments;
/**
* Extending Configuration Files.
*
* @see [Extends](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#extending-configuration-files)
*/
extends?: Extends;
/**
* Specifying Globals.
*
* @see [Globals](https://eslint.org/docs/latest/user-guide/configuring/language-options#specifying-globals)
*/
globals?: Record<
string,
'readonly' | 'writable' | false | 'readable' | true | 'writeable' | 'off'
>;
/**
* Parser.
*
* @see [Working with Custom Parsers](https://eslint.org/docs/latest/developer-guide/working-with-custom-parsers)
* @see [Specifying Parser](https://eslint.org/docs/latest/user-guide/configuring/plugins#configure-a-parser)
*/
parser?: Parser;
/**
* Parser Options.
*
* @see [Working with Custom Parsers](https://eslint.org/docs/latest/developer-guide/working-with-custom-parsers)
* @see [Specifying Parser Options](https://eslint.org/docs/latest/user-guide/configuring/language-options#specifying-parser-options)
*/
parserOptions?: ParserOptions;
/**
* Which third-party plugins define additional rules, environments, configs, etc. for ESLint to use.
*
* @see [Configuring Plugins](https://eslint.org/docs/latest/user-guide/configuring/plugins#configure-plugins)
*/
plugins?: Plugin[];
/**
* Specifying Processor.
*
* @see [processor](https://eslint.org/docs/latest/user-guide/configuring/plugins#specify-a-processor)
*/
processor?: string;
/**
* Rules.
*
* @see [Rules](https://eslint.org/docs/latest/user-guide/configuring/rules)
*/
rules?: Partial<Rules>;
/**
* Overrides.
*
* @see [How do overrides work](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#how-do-overrides-work)
*/
overrides?: Overrides;
/**
* Settings.
*
* @see [Settings](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#adding-shared-settings)
*/
settings?: Settings;
/**
* Disabling Inline Comments.
*
* @see [Disabling Inline Comments](https://eslint.org/docs/latest/user-guide/configuring/rules#disabling-inline-comments)
*/
noInlineConfig?: boolean;
/**
* Report unused `ESLint-disable` comments.
*
* @see [Report unused `ESLint-disable` comments](https://eslint.org/docs/latest/user-guide/configuring/rules#report-unused-eslint-disable-comments)
*/
reportUnusedDisableDirectives?: boolean;
}
export * from './env';
export * from './extends';
export * from './overrides';
export * from './plugin';
export * from './settings';

96
src/types/config/overrides.d.ts vendored Normal file
View File

@ -0,0 +1,96 @@
import type { Parser, ParserOptions } from '../parser-options';
import type { Rules } from '../rules';
import type { Environments } from './env';
import type { Extends } from './extends';
import type { Plugin } from './plugin';
import type { Settings } from './settings';
/**
* OverrideConfigData.
*/
export interface Override {
/**
* The glob patterns for target files.
*/
// https://github.com/eslint/eslint/blob/762a8727fb3b5619cff900826053b643ca5f1162/lib/shared/types.js#L61
files: string[] | string;
/**
* The glob patterns for excluded files.
*/
// https://github.com/eslint/eslint/blob/762a8727fb3b5619cff900826053b643ca5f1162/lib/shared/types.js#L59
excludedFiles?: string | string[];
/**
* An environment provides predefined global variables.
*
* @see [Environments](https://eslint.org/docs/user-guide/configuring/language-options#specifying-environments)
*/
env?: Environments;
/**
* Extending Configuration Files.
*
* @see [Extends](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files)
*/
extends?: Extends;
/**
* Specifying Globals.
*
* @see [Globals](https://eslint.org/docs/latest/user-guide/configuring/language-options#specifying-globals)
*/
globals?: Record<
string,
'readonly' | 'writable' | false | 'readable' | true | 'writeable' | 'off'
>;
/**
* Parser.
*
* @see [Working with Custom Parsers](https://eslint.org/docs/developer-guide/working-with-custom-parsers)
* @see [Specifying Parser](https://eslint.org/docs/user-guide/configuring/plugins#specifying-parser)
*/
parser?: Parser;
/**
* Parser Options.
*
* @see [Working with Custom Parsers](https://eslint.org/docs/developer-guide/working-with-custom-parsers)
* @see [Specifying Parser Options](https://eslint.org/docs/user-guide/configuring/language-options#specifying-parser-options)
*/
parserOptions?: ParserOptions;
/**
* Which third-party plugins define additional rules, environments, configs, etc. for ESLint to use.
*
* @see [Configuring Plugins](https://eslint.org/docs/user-guide/configuring/plugins#configuring-plugins)
*/
plugins?: Plugin[];
/**
* Specifying Processor.
*
* @see [processor](https://eslint.org/docs/user-guide/configuring/plugins#specifying-processor)
*/
processor?: string;
/**
* Rules.
*
* @see [Rules](https://eslint.org/docs/user-guide/configuring/rules)
*/
rules?: Partial<Rules>;
/**
* Settings.
*
* @see [Settings](https://eslint.org/docs/user-guide/configuring/configuration-files#adding-shared-settings)
*/
settings?: Settings;
}
/**
* Overrides.
*/
export type Overrides = Override[];

40
src/types/config/plugin.d.ts vendored Normal file
View File

@ -0,0 +1,40 @@
import type { LiteralUnion } from '../utility-types';
/**
* This is a special exported interface for other packages to declare
* additional plugins that should bail out for eslint plugins. For example
* `'@typescript-eslint/eslint-plugin'` can declare it like so in its `d.ts`:
*
* ```ts
* declare module 'eslint-define-config' {
* export interface CustomPlugins {
* '@typescript-eslint': void;
* }
* }
* ```
*/
export interface CustomPlugins {}
/** Plugin. */
export type Plugin = LiteralUnion<
| '@graphql-eslint'
| '@typescript-eslint'
| 'deprecation'
| 'import'
| 'inclusive-language'
| 'jsdoc'
| 'jsx-a11y'
| 'mdx'
| 'prettier'
| 'promise'
| 'react-hooks'
| 'react'
| 'sonarjs'
| 'spellcheck'
| 'testing-library'
| 'unicorn'
| 'vitest'
| 'vue'
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
| keyof CustomPlugins
>;

66
src/types/config/settings/import.d.ts vendored Normal file
View File

@ -0,0 +1,66 @@
import type { Parser } from '../../parser-options';
/**
* Import settings.
*/
export interface ImportSettings {
/**
* A list of file extensions that will be parsed as modules and inspected for `export`s.
*
* @see [import/extensions](https://github.com/benmosher/eslint-plugin-import/blob/master/README.md#importextensions)
*/
'import/extensions'?: string[];
/**
* If you require more granular extension definitions.
*
* @see [import/resolver](https://github.com/benmosher/eslint-plugin-import/blob/master/README.md#importresolver)
*/
'import/resolver'?: string | Record<string, unknown>;
/**
* A list of regex strings that, if matched by a path, will not report the matching module if no `exports` are found.
*
* @see [import/ignore](https://github.com/benmosher/eslint-plugin-import/blob/master/README.md#importignore)
*/
'import/ignore'?: string[];
/**
* An array of additional modules to consider as "core" modules--modules that should be considered resolved but have no path on the filesystem.
*
* @see [import/core-modules](https://github.com/benmosher/eslint-plugin-import/blob/master/README.md#importcore-modules)
*/
'import/core-modules'?: string[];
/**
* An array of folders. Resolved modules only from those folders will be considered as "external".
*
* @default ["node_modules"]
*
* @see [import/external-module-folders](https://github.com/benmosher/eslint-plugin-import/blob/master/README.md#importexternal-module-folders)
*/
'import/external-module-folders'?: string[];
/**
* A map from parsers to file extension arrays.
*
* @see [import/parsers](https://github.com/benmosher/eslint-plugin-import/blob/master/README.md#importparsers)
*/
'import/parsers'?: Partial<Record<Parser, string[]>>;
/**
* Settings for cache behavior.
*
* @see [import/cache](https://github.com/benmosher/eslint-plugin-import/blob/master/README.md#importcache)
*/
'import/cache'?: { lifetime?: number } & Record<string, unknown>;
/**
* A regex for packages should be treated as internal.
*
* Useful when you are utilizing a monorepo setup or developing a set of packages that depend on each other.
*
* @see [import/internal-regex](https://github.com/benmosher/eslint-plugin-import/blob/master/README.md#importinternal-regex)
*/
'import/internal-regex'?: string;
}

36
src/types/config/settings/index.d.ts vendored Normal file
View File

@ -0,0 +1,36 @@
import type { ImportSettings } from './import';
import type { JSDocSettings } from './jsdoc';
import type { JsxA11ySettings } from './jsx-a11y';
import type { MdxSettings } from './mdx';
import type { NodeSettings } from './node';
import type { ReactSettings } from './react';
/**
* This is a special exported interface for other packages to declare
* additional settings that should bail out for eslint settings. For example
* `'eslint-plugin-jsx-a11y'` can declare it like so in its `d.ts`:
*
* ```ts
* declare module 'eslint-define-config' {
* export interface CustomSettings {
* 'jsx-a11y': {
* components?: Record<string, string>;
* };
* }
* }
* ```
*/
export interface CustomSettings {}
/**
* Settings.
*/
export interface Settings
extends ImportSettings,
JSDocSettings,
JsxA11ySettings,
MdxSettings,
NodeSettings,
ReactSettings,
Partial<CustomSettings>,
Partial<Record<string, unknown>> {}

59
src/types/config/settings/jsdoc.d.ts vendored Normal file
View File

@ -0,0 +1,59 @@
/**
* JSDoc settings.
*/
export interface JSDocSetting extends Partial<Record<string, unknown>> {
/**
* Disables all rules for the comment block on which a `@private` tag (or `@access private`) occurs.
*
* Defaults to `false`.
*
* Note: This has no effect with the rule `check-access` (whose purpose is to check access modifiers) or `empty-tags` (which checks `@private` itself).
*
* @see [mode](https://github.com/gajus/eslint-plugin-jsdoc#allow-tags-private-or-internal-to-disable-rules-for-that-comment-block)
*/
ignorePrivate?: boolean;
/**
* Disables all rules for the comment block on which a `@internal` tag occurs.
*
* Defaults to `false`.
*
* Note: This has no effect with the rule `empty-tags` (which checks `@internal` itself).
*
* @see [mode](https://github.com/gajus/eslint-plugin-jsdoc#allow-tags-private-or-internal-to-disable-rules-for-that-comment-block)
*/
ignoreInternal?: boolean;
/**
* Set to `typescript`, `closure`, or `jsdoc` (the default unless the `@typescript-eslint` parser is in use in which case `typescript` will be the default).
*
* @see [mode](https://github.com/gajus/eslint-plugin-jsdoc#mode)
*/
mode?: 'typescript' | 'closure' | 'jsdoc';
/**
* Configure a preferred alias name for a JSDoc tag.
*
* @see [Alias Preference](https://github.com/gajus/eslint-plugin-jsdoc#alias-preference)
*/
tagNamePreference?: Record<
string,
string | { message: string; replacement?: string } | false
>;
overrideReplacesDocs?: boolean;
augmentsExtendsReplacesDocs?: boolean;
implementsReplacesDocs?: boolean;
preferredTypes?: unknown;
}
/**
* JSDoc settings.
*/
export interface JSDocSettings {
/**
* JSDoc settings.
*
* @see [JSDoc settings](https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-settings)
*/
jsdoc?: JSDocSetting;
}

10
src/types/config/settings/jsx-a11y.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
/**
* JSX A11y settings.
*
* @see [JSX A11y settings](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y)
*/
export interface JsxA11ySettings extends Partial<Record<string, unknown>> {
'jsx-a11y'?: {
components?: Record<string, string>;
};
}

6
src/types/config/settings/mdx.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
import type { ESLintMdxSettings } from 'eslint-plugin-mdx';
/**
* MDX settings.
*/
export type MdxSettings = ESLintMdxSettings;

18
src/types/config/settings/node.d.ts vendored Normal file
View File

@ -0,0 +1,18 @@
/**
* Node settings.
*/
export interface NodeSetting extends Partial<Record<string, unknown>> {
allowModules?: string[];
resolvePaths?: string[];
tryExtensions?: string[];
}
/**
* Node settings.
*/
export interface NodeSettings {
/**
* Node settings.
*/
node?: NodeSetting;
}

103
src/types/config/settings/react.d.ts vendored Normal file
View File

@ -0,0 +1,103 @@
import type { LiteralUnion } from '../../utility-types';
/**
* React settings.
*
* @see [React settings](https://github.com/jsx-eslint/eslint-plugin-react)
*/
export interface ReactSettings extends Partial<Record<string, unknown>> {
react?: {
/**
* Regex for Component Factory to use.
*
* @default 'createReactClass'
*/
createClass?: LiteralUnion<'createReactClass'>;
/**
* Pragma to use.
*
* @default 'React'
*/
pragma?: LiteralUnion<'React'>;
/**
* Fragment to use (may be a property of <pragma>).
*
* @default 'Fragment'
*/
fragment?: LiteralUnion<'Fragment'>;
/**
* React version. "detect" automatically picks the version you have installed.
*
* You can also use `16.0`, `16.3`, etc, if you want to override the detected value.
*
* It will default to "latest" and warn if missing, and to "detect" in the future.
*
* @default 'latest'
*/
version?: LiteralUnion<'latest' | 'detect'>;
/**
* Flow version.
*/
flowVersion?: string;
};
/**
* The names of any function used to wrap propTypes, e.g. `forbidExtraProps`.
*
* If this isn't set, any propTypes wrapped in a function will be skipped.
*/
propWrapperFunctions?: Array<
| string
| {
property: string;
object?: string;
/**
* For rules that check exact prop wrappers.
*/
exact?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[k: string]: any;
}
>;
/**
* The name of any function used to wrap components, e.g. Mobx `observer` function.
*
* If this isn't set, components wrapped by these functions will be skipped.
*/
componentWrapperFunctions?: Array<
| string
| {
property: string;
object?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[k: string]: any;
}
>;
/**
* Components used as alternatives to <form> for forms, eg. <Form endpoint={ url } />.
*/
formComponents?: Array<
| string
| {
name: string;
formAttribute: string;
}
>;
/**
* Components used as alternatives to <a> for linking, eg. <Link to={ url } />.
*/
linkComponents?: Array<
| string
| {
name: string;
linkAttribute: string;
}
>;
}

View File

@ -0,0 +1,24 @@
import type { LiteralUnion } from '../../utility-types';
/**
* Testing Library settings.
*
* @see [Testing Library settings](https://github.com/testing-library/eslint-plugin-testing-library)
*/
export interface TestingLibrarySettings
extends Partial<Record<string, unknown>> {
/**
* @see [testing-library/custom-queries](https://github.com/testing-library/eslint-plugin-testing-library#testing-librarycustom-queries)
*/
'testing-library/custom-queries'?: 'off' | string[];
/**
* @see [testing-library/custom-renders](https://github.com/testing-library/eslint-plugin-testing-library#testing-librarycustom-renders)
*/
'testing-library/custom-renders'?: 'off' | string[];
/**
* @see [testing-library/utils-module](https://github.com/testing-library/eslint-plugin-testing-library#testing-libraryutils-module)
*/
'testing-library/utils-module'?: LiteralUnion<'off'>;
}

80
src/types/flat-config/index.d.ts vendored Normal file
View File

@ -0,0 +1,80 @@
import type { ESLint, Linter } from 'eslint';
import type { Rules } from '../rules';
import type { LanguageOptions } from './language-options';
import type { LinterOptions } from './linter-options';
/**
* Flat ESLint Configuration.
*
* @see [Configuration Files (New)](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new)
*/
export interface FlatESLintConfigItem {
/**
* An array of glob patterns indicating the files that the configuration object should apply to. If not specified, the configuration object applies to all files.
*
* @see [Ignore Patterns](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#excluding-files-with-ignores)
*/
files?: string[];
/**
* An array of glob patterns indicating the files that the configuration object should not apply to. If not specified, the configuration object applies to all files matched by files.
*
* @see [Ignore Patterns](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#excluding-files-with-ignores)
*/
ignores?: string[];
/**
* An object containing settings related to how JavaScript is configured for linting.
*
* @see [Configuring language options](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuring-language-options)
*/
languageOptions?: LanguageOptions;
/**
* An object containing settings related to the linting process.
*/
linterOptions?: LinterOptions;
/**
* Either an object containing `preprocess()` and `postprocess()` methods or a string indicating the name of a processor inside of a plugin (i.e., `"pluginName/processorName"`).
*
* @see [Using processors](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#using-processors)
*/
processor?: string | Linter.Processor;
/**
* An object containing a name-value mapping of plugin names to plugin objects. When `files` is specified, these plugins are only available to the matching files.
*
* @see [Using plugins in your configuration](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#using-plugins-in-your-configuration)
*/
plugins?: Record<string, ESLint.Plugin>;
/**
* An object containing the configured rules. When `files` or `ignores` are specified, these rule configurations are only available to the matching files.
*
* @see [Configuring rules](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuring-rules)
*/
rules?: Partial<Rules>;
/**
* An object containing name-value pairs of information that should be available to all rules.
*
* @see [Configuring shared settings](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuring-shared-settings)
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
settings?: Record<string, any>;
}
/**
* Predefined configurations.
*
* @see [Using predefined configurations](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#using-predefined-configurations)
*
* @deprecated The predefined string configurations are deprecated and will be replaced by the @eslint/js package.
*/
export type PredefinedConfig = 'eslint:recommended' | 'eslint:all';
export type FlatESLintConfig = FlatESLintConfigItem | PredefinedConfig;
export * from './language-options';
export * from './linter-options';

View File

@ -0,0 +1,64 @@
import type {
EcmaVersion,
Parser,
ParserOptions,
SourceType,
} from '../parser-options';
export type ParserModule =
| {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
parse(text: string, options?: any): any;
}
| {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
parseForESLint(text: string, options?: any): any;
};
/**
* An object containing settings related to how JavaScript is configured for linting
*/
export interface LanguageOptions {
/**
* The version of ECMAScript to support. May be any year (i.e., `2022`) or version (i.e., `5`). Set to `"latest"` for the most recent supported version.
*
* @default "latest"
* @see [Configuring the JavaScript version](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuring-the-javascript-version)
*/
ecmaVersion?: EcmaVersion;
/**
* The type of JavaScript source code. Possible values are `"script"` for traditional script files, `"module"` for ECMAScript modules (ESM), and `"commonjs"` for CommonJS files.
*
* (default: `"module"` for .js and .mjs files; `"commonjs"` for .cjs files)
*
* @see [Configuring the JavaScript source type](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuring-the-javascript-source-type)
*/
sourceType?: SourceType | 'commonjs';
/**
* An object specifying additional objects that should be added to the global scope during linting.
*
* @see [Configuring global variables](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuring-global-variables)
*/
globals?: Record<
string,
'readonly' | 'writable' | false | 'readable' | true | 'writeable' | 'off'
>;
/**
* Either an object containing a `parse()` method or a string indicating the name of a parser inside of a plugin (i.e., `"pluginName/parserName"`).
*
* @default "@/espree"
*
* @see [Configuring a custom parser and its options](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuring-a-custom-parser-and-its-options)
*/
parser?: Parser | ParserModule;
/**
* An object specifying additional options that are passed directly to the `parser()` method on the parser. The available options are parser-dependent.
*
* @see [Configuring a custom parser and its options](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuring-a-custom-parser-and-its-options)
*/
parserOptions?: ParserOptions;
}

View File

@ -0,0 +1,18 @@
/**
* An object containing settings related to the linting process.
*/
export interface LinterOptions {
/**
* A boolean value indicating if inline configuration is allowed.
*
* @see [Disabling inline configuration](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#disabling-inline-configuration)
*/
noInlineConfig?: boolean;
/**
* A boolean value indicating if unused disable directives should be tracked and reported.
*
* @see [Reporting unused disable directives](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#reporting-unused-disable-directives)
*/
reportUnusedDisableDirectives?: boolean;
}

4
src/types/index.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
export type * from './config';
export type * from './flat-config';
export type * from './parser-options';
export type * from './rules';

402
src/types/parser-options.d.ts vendored Normal file
View File

@ -0,0 +1,402 @@
import type { LiteralUnion } from './utility-types';
// Some types copied from `@types/eslint` `Linter.ParserOptions`
/**
* Any valid ECMAScript version number or 'latest':
*
* - A version: es3, es5, es6, es7, es8, es9, es10, es11, es12, es13, es14, ...
* - A year: es2015, es2016, es2017, es2018, es2019, es2020, es2021, es2022, es2023, ...
* - 'latest'
*
* @see https://typescript-eslint.io/architecture/parser/#ecmaversion
*/
export type EcmaVersion =
| 3
| 5
| 6
| 7
| 8
| 9
| 10
| 11
| 12
| 13
| 14
| 2015
| 2016
| 2017
| 2018
| 2019
| 2020
| 2021
| 2022
| 2023
| 'latest';
/**
* Set to "script" (default) or "module" if your code is in ECMAScript modules.
*/
export type SourceType = 'script' | 'module';
/**
* An object indicating which additional language features you'd like to use.
*
* @see https://eslint.org/docs/latest/user-guide/configuring/language-options#specifying-parser-options
* @see https://typescript-eslint.io/architecture/parser#ecmafeatures
*/
export interface EcmaFeatures extends Partial<Record<string, boolean>> {
/**
* Allow `return` statements in the global scope.
*/
globalReturn?: boolean;
/**
* Enable global [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) (if `ecmaVersion` is 5 or greater).
*/
impliedStrict?: boolean;
/**
* Enable [JSX](https://facebook.github.io/jsx).
*/
jsx?: boolean;
}
/** Lib. */
export type Lib = LiteralUnion<
| 'es5'
| 'es6'
| 'es2015'
| 'es7'
| 'es2016'
| 'es2017'
| 'es2018'
| 'es2019'
| 'es2020'
| 'esnext'
| 'dom'
| 'dom.iterable'
| 'webworker'
| 'webworker.importscripts'
| 'webworker.iterable'
| 'scripthost'
| 'es2015.core'
| 'es2015.collection'
| 'es2015.generator'
| 'es2015.iterable'
| 'es2015.promise'
| 'es2015.proxy'
| 'es2015.reflect'
| 'es2015.symbol'
| 'es2015.symbol.wellknown'
| 'es2016.array.include'
| 'es2017.object'
| 'es2017.sharedmemory'
| 'es2017.string'
| 'es2017.intl'
| 'es2017.typedarrays'
| 'es2018.asyncgenerator'
| 'es2018.asynciterable'
| 'es2018.intl'
| 'es2018.promise'
| 'es2018.regexp'
| 'es2019.array'
| 'es2019.object'
| 'es2019.string'
| 'es2019.symbol'
| 'es2020.bigint'
| 'es2020.promise'
| 'es2020.sharedmemory'
| 'es2020.string'
| 'es2020.symbol.wellknown'
| 'es2020.intl'
| 'esnext.array'
| 'esnext.symbol'
| 'esnext.asynciterable'
| 'esnext.intl'
| 'esnext.bigint'
| 'esnext.string'
| 'esnext.promise'
| 'esnext.weakref'
| 'es2016.full'
| 'es2017.full'
| 'es2018.full'
| 'es2019.full'
| 'es2020.full'
| 'esnext.full'
| 'lib'
>;
/** DebugLevel. */
export type DebugLevel =
| boolean
| Array<'eslint' | 'typescript' | 'typescript-eslint'>;
/**
* This is a special exported interface for other packages to declare
* additional parsers that should bail out for eslint parsers. For example
* `'@typescript-eslint/eslint-plugin'` can declare it like so in its `d.ts`:
*
* ```ts
* declare module 'eslint-define-config' {
* export interface CustomParsers {
* '@typescript-eslint/parser': void;
* }
* }
* ```
*/
export interface CustomParsers {}
/** Parser. */
export type Parser = LiteralUnion<
| 'babel-eslint'
| '@typescript-eslint/parser'
| 'jsonc-eslint-parser'
| 'vue-eslint-parser'
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
| keyof CustomParsers
>;
/**
* This is a special exported interface for other packages to declare
* additional parser options that should bail out for eslint parser options. For example
* `@typescript-eslint/eslint-plugin` can declare it like so in its `d.ts`:
*
* ```ts
* declare module 'eslint-define-config' {
* export interface CustomParserOptions {
* /**
* * This option allows you to provide the root directory for relative tsconfig paths specified in the `project` option above.
* *
* * \@see [tsconfigRootDir](https://typescript-eslint.io/architecture/parser/#tsconfigrootdir)
* *\/
* tsconfigRootDir?: string;
*
* useJSXTextNode?: boolean;
*
* /**
* * This option allows you to toggle the warning that the parser will give you if you use a version of TypeScript which is not explicitly supported.
* *
* * \@default true
* *
* * \@see [warnOnUnsupportedTypeScriptVersion](https://typescript-eslint.io/architecture/parser/#warnonunsupportedtypescriptversion)
* *\/
* warnOnUnsupportedTypeScriptVersion?: boolean;
*
* /**
* * This option allow you to tell parser to act as if `emitDecoratorMetadata: true` is set in `tsconfig.json`, but without [type-aware linting](https://typescript-eslint.io/linting/typed-linting).
* * In other words, you don't have to specify `parserOptions.project` in this case, making the linting process faster.
* *
* * \@default undefined
* *
* * \@see [emitDecoratorMetadata](https://typescript-eslint.io/architecture/parser/#emitdecoratormetadata)
* *\/
* emitDecoratorMetadata?: boolean;
* }
* }
* ```
*/
export interface CustomParserOptions {}
/**
* Parser options.
*
* @see [Specifying Parser Options](https://eslint.org/docs/user-guide/configuring/language-options#specifying-parser-options)
*/
export interface ParserOptions
extends Partial<CustomParserOptions>,
Partial<Record<string, unknown>> {
/**
* Accepts any valid ECMAScript version number or `'latest'`:
*
* - A version: es3, es5, es6, es7, es8, es9, es10, es11, es12, es13, es14, ..., or
* - A year: es2015, es2016, es2017, es2018, es2019, es2020, es2021, es2022, es2023, ..., or
* - `'latest'`
*
* When it's a version or a year, the value must be a number - so do not include the `es` prefix.
*
* Specifies the version of ECMAScript syntax you want to use. This is used by the parser to determine how to perform scope analysis, and it affects the default
*
* @default 2018
*
* @see https://typescript-eslint.io/architecture/parser/#ecmaversion
*/
ecmaVersion?: EcmaVersion;
/**
* Set to "script" (default) or "module" if your code is in ECMAScript modules.
*
* @default 'script'
*
* @see https://eslint.org/docs/latest/user-guide/configuring/language-options#specifying-parser-options
*/
sourceType?: SourceType;
/**
* An object indicating which additional language features you'd like to use.
*
* @see https://eslint.org/docs/latest/user-guide/configuring/language-options#specifying-parser-options
* @see https://typescript-eslint.io/architecture/parser#ecmafeatures
*/
ecmaFeatures?: EcmaFeatures;
/**
* The identifier that's used for JSX Elements creation (after transpilation).
* If you're using a library other than React (like `preact`), then you should change this value.
* If you are using the [new JSX transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) you can set this to `null`.
*
* This should not be a member expression - just the root identifier (i.e. use `"React"` instead of `"React.createElement"`).
*
* If you provide `parserOptions.project`, you do not need to set this, as it will automatically detected from the compiler.
*
* @default 'React'
*
* @see [jsxPragma](https://typescript-eslint.io/architecture/parser#jsxpragma)
*/
jsxPragma?: string;
/**
* The identifier that's used for JSX fragment elements (after transpilation).
* If `null`, assumes transpilation will always use a member of the configured `jsxPragma`.
* This should not be a member expression - just the root identifier (i.e. use `"h"` instead of `"h.Fragment"`).
*
* If you provide `parserOptions.project`, you do not need to set this, as it will automatically detected from the compiler.
*
* @default null
*
* @see [jsxFragmentName](https://typescript-eslint.io/architecture/parser#jsxfragmentname)
*/
jsxFragmentName?: string | null;
/**
* For valid options, see the [TypeScript compiler options](https://www.typescriptlang.org/tsconfig#lib).
*
* Specifies the TypeScript `libs` that are available.
* This is used by the scope analyser to ensure there are global variables declared for the types exposed by TypeScript.
*
* If you provide `parserOptions.project`, you do not need to set this, as it will automatically detected from the compiler.
*
* @default ['es2018']
*
* @see [lib](https://typescript-eslint.io/architecture/parser/#lib)
*/
lib?: Lib[];
comment?: boolean;
debugLevel?: DebugLevel;
errorOnTypeScriptSyntacticAndSemanticIssues?: boolean;
errorOnUnknownASTType?: boolean;
/**
* This option allows you to provide one or more additional file extensions which should be considered in the TypeScript Program compilation.
*
* The default extensions are `.ts`, `.tsx`, `.js`, and `.jsx`. Add extensions starting with `.`, followed by the file extension.
* E.g. for a `.vue` file use `"extraFileExtensions: [".vue"]`.
*
* @see [extraFileExtensions](https://typescript-eslint.io/architecture/parser/#extrafileextensions)
*/
extraFileExtensions?: string[];
filePath?: string;
loc?: boolean;
/**
* Parser.
*
* @see [Working with Custom Parsers](https://eslint.org/docs/developer-guide/working-with-custom-parsers)
* @see [Specifying Parser](https://eslint.org/docs/user-guide/configuring/plugins#specifying-parser)
*/
parser?: Parser;
/**
* This option allows you to provide a path to your project's `tsconfig.json`.
* **This setting is required if you want to use rules which require type information.**
* Relative paths are interpreted relative to the current working directory if `tsconfigRootDir` is not set.
* If you intend on running ESLint from directories other than the project root, you should consider using `tsconfigRootDir`.
*
* @default undefined
*
* @see [project](https://typescript-eslint.io/architecture/parser/#project)
*/
project?: string | string[] | true | null;
/**
* This option allows you to ignore folders from being included in your provided list of `project`s.
* This is useful if you have configured glob patterns, but want to make sure you ignore certain folders.
*
* It accepts an array of globs to exclude from the `project` globs.
*
* For example, by default it will ensure that a glob like `./**/tsconfig.json` will not match any `tsconfigs` within your `node_modules` folder (some npm packages do not exclude their source files from their published packages).
*
* @default ['**/node_modules/**']
*
* @see [projectFolderIgnoreList](https://typescript-eslint.io/architecture/parser/#projectfolderignorelist)
*/
projectFolderIgnoreList?: Array<string | RegExp>;
range?: boolean;
tokens?: boolean;
/**
* This option allows you to provide the root directory for relative tsconfig paths specified in the `project` option above.
*
* @see [tsconfigRootDir](https://typescript-eslint.io/architecture/parser/#tsconfigrootdir)
*/
tsconfigRootDir?: string;
useJSXTextNode?: boolean;
/**
* This option allows you to toggle the warning that the parser will give you if you use a version of TypeScript which is not explicitly supported.
*
* @default true
*
* @see [warnOnUnsupportedTypeScriptVersion](https://typescript-eslint.io/architecture/parser/#warnonunsupportedtypescriptversion)
*/
warnOnUnsupportedTypeScriptVersion?: boolean;
/**
* This option allow you to tell parser to act as if `emitDecoratorMetadata: true` is set in `tsconfig.json`, but without [type-aware linting](https://typescript-eslint.io/linting/typed-linting).
* In other words, you don't have to specify `parserOptions.project` in this case, making the linting process faster.
*
* @default undefined
*
* @see [emitDecoratorMetadata](https://typescript-eslint.io/architecture/parser/#emitdecoratormetadata)
*/
emitDecoratorMetadata?: boolean;
/**
* @see [vueFeatures](https://github.com/vuejs/vue-eslint-parser#parseroptionsvuefeatures)
*/
vueFeatures?: {
/**
* You can use `parserOptions.vueFeatures.filter` property to specify whether to parse the Vue2 filter.
*
* If you specify `false`, the parser does not parse `|` as a filter.
*
* @see [filter](https://github.com/vuejs/vue-eslint-parser#parseroptionsvuefeaturesfilter)
*/
filter?: boolean;
/**
* You can use `parserOptions.vueFeatures.interpolationAsNonHTML` property to specify whether to parse the interpolation as HTML.
*
* If you specify `true`, the parser handles the interpolation as non-HTML (However, you can use HTML escaping in the interpolation).
*
* @see [interpolationAsNonHTML](https://github.com/vuejs/vue-eslint-parser#parseroptionsvuefeaturesinterpolationasnonhtml)
*/
interpolationAsNonHTML?: boolean;
};
/**
* @see [templateTokenizer](https://github.com/rashfael/eslint-plugin-vue-pug#usage)
*/
templateTokenizer?: {
pug?: LiteralUnion<'vue-eslint-parser-template-tokenizer-pug'>;
};
}

8
src/types/utility-types.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
/**
* A literal type that supports custom further strings but preserves autocompletion in IDEs.
*
* @see [copied from issue](https://github.com/microsoft/TypeScript/issues/29729#issuecomment-471566609)
*/
export type LiteralUnion<Union extends Base, Base = string> =
| Union
| (Base & { zz_IGNORE_ME?: never });

View File

@ -6,7 +6,7 @@
"esModuleInterop": true,
"experimentalDecorators": true,
"jsx": "react-jsx",
"module": "commonjs",
"module": "esnext",
"moduleResolution": "node",
"noEmit": true,
"noImplicitOverride": true,
@ -15,6 +15,7 @@
"resolveJsonModule": true,
"strict": true,
"stripInternal": true,
"skipLibCheck": true,
"target": "esnext",
"useUnknownInCatchVariables": false
}