Content-Length: 179410 | pFad | http://github.com/typescript-eslint/typescript-eslint/pull/11207.patch
thub.com
From 5378779bb67c9c193c48137ecbc509bdc305bc0b Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Sat, 10 May 2025 21:52:52 -0400
Subject: [PATCH 1/3] Package split: parser-services
---
.vscode/settings.json | 2 +
packages/parser-services/LICENSE | 21 ++++
packages/parser-services/README.md | 3 +
packages/parser-services/package.json | 65 ++++++++++
packages/parser-services/project.json | 16 +++
.../src/clear-caches.ts | 3 -
.../WatchCompilerHostOfConfigFile.ts | 0
.../create-program/createIsolatedProgram.ts | 2 +-
.../create-program/createProjectProgram.ts | 5 +-
.../createProjectProgramError.ts | 3 +-
.../create-program/createProjectService.ts | 3 +-
.../src/create-program/createSourceFile.ts | 4 +-
.../src/create-program/describeFilePath.ts | 0
.../src/create-program/getParsedConfigFile.ts | 0
.../src/create-program/getScriptKind.ts | 0
.../getWatchProgramsForProjects.ts | 2 +-
.../src/create-program/shared.ts | 3 +-
.../src/create-program/useProvidedPrograms.ts | 2 +-
.../src/create-program/utils.ts | 22 ++++
.../validateDefaultProjectForFilesGlob.ts | 0
.../src/createParserServices.ts | 5 +-
packages/parser-services/src/index.ts | 6 +
.../src/parseSettings/ExpiringCache.ts | 0
.../src/parseSettings/createParseSettings.ts | 8 +-
.../parseSettings/getProjectConfigFiles.ts | 2 +-
.../src/parseSettings/index.ts | 6 +-
.../src/parseSettings/inferSingleRun.ts | 3 +-
.../src/parseSettings/resolveProjectList.ts | 9 +-
.../src/parseSettings/warnAboutTSVersion.ts | 4 +-
.../src/parser.ts | 31 +++--
.../src/semantic-or-syntactic-errors.ts | 119 ++++++++++++++++++
.../src/source-files.ts | 0
packages/parser-services/src/types.ts | 29 +++++
.../src/use-at-your-own-risk.ts | 6 +
.../src/useProgramFromProjectService.ts | 0
packages/parser-services/src/version.ts | 3 +
.../src/withoutProjectParserOptions.ts | 0
packages/parser-services/tsconfig.build.json | 17 +++
packages/parser-services/tsconfig.json | 16 +++
packages/parser-services/tsconfig.spec.json | 18 +++
.../parser-services/typings/typescript.d.ts | 57 +++++++++
packages/parser-services/vitest.config.mts | 22 ++++
packages/parser/package.json | 1 +
packages/parser/src/index.ts | 6 +-
packages/parser/src/parser.ts | 12 +-
packages/parser/tsconfig.build.json | 3 +
packages/parser/tsconfig.json | 3 +
.../src/getConstrainedTypeAtLocation.ts | 6 +-
packages/type-utils/src/getDeclaration.ts | 6 +-
.../typeDeclaredInFile.ts | 2 +-
packages/typescript-estree/package.json | 2 -
.../typescript-estree/src/ast-converter.ts | 37 ++++--
packages/typescript-estree/src/convert.ts | 26 +---
packages/typescript-estree/src/errors.ts | 72 +++++++++++
packages/typescript-estree/src/index.ts | 25 ++--
packages/typescript-estree/src/node-maps.ts | 27 ++++
packages/typescript-estree/src/node-utils.ts | 55 --------
.../typescript-estree/src/parser-options.ts | 43 -------
.../src/semantic-or-syntactic-errors.ts | 116 +----------------
.../src/use-at-your-own-risk.ts | 5 -
packages/utils/package.json | 1 +
.../src/eslint-utils/getParserServices.ts | 2 +-
packages/utils/src/ts-estree.ts | 2 +-
packages/utils/tsconfig.build.json | 3 +
packages/utils/tsconfig.json | 3 +
tsconfig.json | 1 +
yarn.lock | 21 +++-
67 files changed, 653 insertions(+), 344 deletions(-)
create mode 100644 packages/parser-services/LICENSE
create mode 100644 packages/parser-services/README.md
create mode 100644 packages/parser-services/package.json
create mode 100644 packages/parser-services/project.json
rename packages/{typescript-estree => parser-services}/src/clear-caches.ts (91%)
rename packages/{typescript-estree => parser-services}/src/create-program/WatchCompilerHostOfConfigFile.ts (100%)
rename packages/{typescript-estree => parser-services}/src/create-program/createIsolatedProgram.ts (96%)
rename packages/{typescript-estree => parser-services}/src/create-program/createProjectProgram.ts (89%)
rename packages/{typescript-estree => parser-services}/src/create-program/createProjectProgramError.ts (98%)
rename packages/{typescript-estree => parser-services}/src/create-program/createProjectService.ts (98%)
rename packages/{typescript-estree => parser-services}/src/create-program/createSourceFile.ts (95%)
rename packages/{typescript-estree => parser-services}/src/create-program/describeFilePath.ts (100%)
rename packages/{typescript-estree => parser-services}/src/create-program/getParsedConfigFile.ts (100%)
rename packages/{typescript-estree => parser-services}/src/create-program/getScriptKind.ts (100%)
rename packages/{typescript-estree => parser-services}/src/create-program/getWatchProgramsForProjects.ts (99%)
rename packages/{typescript-estree => parser-services}/src/create-program/shared.ts (98%)
rename packages/{typescript-estree => parser-services}/src/create-program/useProvidedPrograms.ts (97%)
create mode 100644 packages/parser-services/src/create-program/utils.ts
rename packages/{typescript-estree => parser-services}/src/create-program/validateDefaultProjectForFilesGlob.ts (100%)
rename packages/{typescript-estree => parser-services}/src/createParserServices.ts (91%)
create mode 100644 packages/parser-services/src/index.ts
rename packages/{typescript-estree => parser-services}/src/parseSettings/ExpiringCache.ts (100%)
rename packages/{typescript-estree => parser-services}/src/parseSettings/createParseSettings.ts (95%)
rename packages/{typescript-estree => parser-services}/src/parseSettings/getProjectConfigFiles.ts (96%)
rename packages/{typescript-estree => parser-services}/src/parseSettings/index.ts (93%)
rename packages/{typescript-estree => parser-services}/src/parseSettings/inferSingleRun.ts (97%)
rename packages/{typescript-estree => parser-services}/src/parseSettings/resolveProjectList.ts (93%)
rename packages/{typescript-estree => parser-services}/src/parseSettings/warnAboutTSVersion.ts (92%)
rename packages/{typescript-estree => parser-services}/src/parser.ts (94%)
create mode 100644 packages/parser-services/src/semantic-or-syntactic-errors.ts
rename packages/{typescript-estree => parser-services}/src/source-files.ts (100%)
create mode 100644 packages/parser-services/src/types.ts
create mode 100644 packages/parser-services/src/use-at-your-own-risk.ts
rename packages/{typescript-estree => parser-services}/src/useProgramFromProjectService.ts (100%)
create mode 100644 packages/parser-services/src/version.ts
rename packages/{typescript-estree => parser-services}/src/withoutProjectParserOptions.ts (100%)
create mode 100644 packages/parser-services/tsconfig.build.json
create mode 100644 packages/parser-services/tsconfig.json
create mode 100644 packages/parser-services/tsconfig.spec.json
create mode 100644 packages/parser-services/typings/typescript.d.ts
create mode 100644 packages/parser-services/vitest.config.mts
create mode 100644 packages/typescript-estree/src/errors.ts
create mode 100644 packages/typescript-estree/src/node-maps.ts
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 896fbaebbb3a..f48612982bca 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,6 @@
{
+ "eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }],
+
// This matches the value configured on the autoformatter
"editor.rulers": [80],
diff --git a/packages/parser-services/LICENSE b/packages/parser-services/LICENSE
new file mode 100644
index 000000000000..310a18f8a6cb
--- /dev/null
+++ b/packages/parser-services/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 typescript-eslint and other contributors
+
+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.
diff --git a/packages/parser-services/README.md b/packages/parser-services/README.md
new file mode 100644
index 000000000000..e4797e146dac
--- /dev/null
+++ b/packages/parser-services/README.md
@@ -0,0 +1,3 @@
+# `@typescript-eslint/parser-services`
+
+TODO
diff --git a/packages/parser-services/package.json b/packages/parser-services/package.json
new file mode 100644
index 000000000000..3c0a42e07fe5
--- /dev/null
+++ b/packages/parser-services/package.json
@@ -0,0 +1,65 @@
+{
+ "name": "@typescript-eslint/parser-services",
+ "version": "8.32.0",
+ "description": "TODO",
+ "files": [
+ "dist",
+ "!*.tsbuildinfo",
+ "package.json",
+ "README.md",
+ "LICENSE"
+ ],
+ "type": "commonjs",
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "types": "./dist/index.d.ts",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/typescript-eslint/typescript-eslint.git",
+ "directory": "packages/parser-services"
+ },
+ "bugs": {
+ "url": "https://github.com/typescript-eslint/typescript-eslint/issues"
+ },
+ "homepage": "https://typescript-eslint.io",
+ "license": "MIT",
+ "keywords": [
+ "eslint",
+ "typescript",
+ "estree"
+ ],
+ "scripts": {
+ "build": "tsc -b tsconfig.build.json",
+ "clean": "tsc -b tsconfig.build.json --clean",
+ "postclean": "rimraf dist/ coverage/",
+ "format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
+ "lint": "npx nx lint",
+ "test": "vitest --run --config=$INIT_CWD/vitest.config.mts",
+ "check-types": "npx nx typecheck"
+ },
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "^8.32.0",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.3.2",
+ "is-glob": "^4.0.3"
+ },
+ "devDependencies": {
+ "@vitest/coverage-v8": "^3.1.2",
+ "prettier": "^3.2.5",
+ "rimraf": "*",
+ "typescript": "*",
+ "vitest": "^3.1.2"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+}
diff --git a/packages/parser-services/project.json b/packages/parser-services/project.json
new file mode 100644
index 000000000000..efa611dad79d
--- /dev/null
+++ b/packages/parser-services/project.json
@@ -0,0 +1,16 @@
+{
+ "name": "parser-services",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "projectType": "library",
+ "root": "packages/parser-services",
+ "sourceRoot": "packages/parser-services/src",
+ "targets": {
+ "lint": {
+ "executor": "@nx/eslint:lint",
+ "outputs": ["{options.outputFile}"]
+ },
+ "test": {
+ "executor": "@nx/vite:test"
+ }
+ }
+}
diff --git a/packages/typescript-estree/src/clear-caches.ts b/packages/parser-services/src/clear-caches.ts
similarity index 91%
rename from packages/typescript-estree/src/clear-caches.ts
rename to packages/parser-services/src/clear-caches.ts
index 5e9867d3beab..81a69c559db4 100644
--- a/packages/typescript-estree/src/clear-caches.ts
+++ b/packages/parser-services/src/clear-caches.ts
@@ -24,6 +24,3 @@ export function clearCaches(): void {
clearTSServerProjectService();
clearGlobCache();
}
-
-// TODO - delete this in next major
-export const clearProgramCache = clearCaches;
diff --git a/packages/typescript-estree/src/create-program/WatchCompilerHostOfConfigFile.ts b/packages/parser-services/src/create-program/WatchCompilerHostOfConfigFile.ts
similarity index 100%
rename from packages/typescript-estree/src/create-program/WatchCompilerHostOfConfigFile.ts
rename to packages/parser-services/src/create-program/WatchCompilerHostOfConfigFile.ts
diff --git a/packages/typescript-estree/src/create-program/createIsolatedProgram.ts b/packages/parser-services/src/create-program/createIsolatedProgram.ts
similarity index 96%
rename from packages/typescript-estree/src/create-program/createIsolatedProgram.ts
rename to packages/parser-services/src/create-program/createIsolatedProgram.ts
index e952931155aa..83fa93ec57dc 100644
--- a/packages/typescript-estree/src/create-program/createIsolatedProgram.ts
+++ b/packages/parser-services/src/create-program/createIsolatedProgram.ts
@@ -8,7 +8,7 @@ import { getScriptKind } from './getScriptKind';
import { createDefaultCompilerOptionsFromExtra } from './shared';
const log = debug(
- 'typescript-eslint:typescript-estree:create-program:createIsolatedProgram',
+ 'typescript-eslint:parser-services:create-program:createIsolatedProgram',
);
/**
diff --git a/packages/typescript-estree/src/create-program/createProjectProgram.ts b/packages/parser-services/src/create-program/createProjectProgram.ts
similarity index 89%
rename from packages/typescript-estree/src/create-program/createProjectProgram.ts
rename to packages/parser-services/src/create-program/createProjectProgram.ts
index 00c8ae67c9bc..b30e38991d09 100644
--- a/packages/typescript-estree/src/create-program/createProjectProgram.ts
+++ b/packages/parser-services/src/create-program/createProjectProgram.ts
@@ -2,12 +2,12 @@ import type * as ts from 'typescript';
import debug from 'debug';
-import type { ParseSettings } from '../parseSettings';
import type { ASTAndDefiniteProgram } from './shared';
-import { firstDefined } from '../node-utils';
import { createProjectProgramError } from './createProjectProgramError';
import { getAstFromProgram } from './shared';
+import { ParseSettings } from '../parseSettings';
+import { firstDefined } from './utils';
const log = debug(
'typescript-eslint:typescript-estree:create-program:createProjectProgram',
@@ -23,6 +23,7 @@ export function createProjectProgram(
): ASTAndDefiniteProgram {
log('Creating project program for: %s', parseSettings.filePath);
+ // TODO: switch to .find()?
const astAndProgram = firstDefined(programsForProjects, currentProgram =>
getAstFromProgram(currentProgram, parseSettings.filePath),
);
diff --git a/packages/typescript-estree/src/create-program/createProjectProgramError.ts b/packages/parser-services/src/create-program/createProjectProgramError.ts
similarity index 98%
rename from packages/typescript-estree/src/create-program/createProjectProgramError.ts
rename to packages/parser-services/src/create-program/createProjectProgramError.ts
index f1474d344bf6..124035febc49 100644
--- a/packages/typescript-estree/src/create-program/createProjectProgramError.ts
+++ b/packages/parser-services/src/create-program/createProjectProgramError.ts
@@ -2,10 +2,9 @@ import type * as ts from 'typescript';
import path from 'node:path';
-import type { ParseSettings } from '../parseSettings';
-
import { describeFilePath } from './describeFilePath';
import { DEFAULT_EXTRA_FILE_EXTENSIONS } from './shared';
+import { ParseSettings } from '../parseSettings';
export function createProjectProgramError(
parseSettings: ParseSettings,
diff --git a/packages/typescript-estree/src/create-program/createProjectService.ts b/packages/parser-services/src/create-program/createProjectService.ts
similarity index 98%
rename from packages/typescript-estree/src/create-program/createProjectService.ts
rename to packages/parser-services/src/create-program/createProjectService.ts
index 26b2c5421612..00f6db76e7f1 100644
--- a/packages/typescript-estree/src/create-program/createProjectService.ts
+++ b/packages/parser-services/src/create-program/createProjectService.ts
@@ -3,10 +3,9 @@ import type * as ts from 'typescript/lib/tsserverlibrary';
import debug from 'debug';
-import type { ProjectServiceOptions } from '../parser-options';
-
import { getParsedConfigFile } from './getParsedConfigFile';
import { validateDefaultProjectForFilesGlob } from './validateDefaultProjectForFilesGlob';
+import { ProjectServiceOptions } from '@typescript-eslint/types';
const DEFAULT_PROJECT_MATCHED_FILES_THRESHOLD = 8;
diff --git a/packages/typescript-estree/src/create-program/createSourceFile.ts b/packages/parser-services/src/create-program/createSourceFile.ts
similarity index 95%
rename from packages/typescript-estree/src/create-program/createSourceFile.ts
rename to packages/parser-services/src/create-program/createSourceFile.ts
index bfe947fd1ef6..0f30ace060bf 100644
--- a/packages/typescript-estree/src/create-program/createSourceFile.ts
+++ b/packages/parser-services/src/create-program/createSourceFile.ts
@@ -1,11 +1,11 @@
import debug from 'debug';
import * as ts from 'typescript';
-import type { ParseSettings } from '../parseSettings';
import type { ASTAndNoProgram } from './shared';
-import { isSourceFile } from '../source-files';
import { getScriptKind } from './getScriptKind';
+import { ParseSettings } from '../parseSettings';
+import { isSourceFile } from '../source-files';
const log = debug(
'typescript-eslint:typescript-estree:create-program:createSourceFile',
diff --git a/packages/typescript-estree/src/create-program/describeFilePath.ts b/packages/parser-services/src/create-program/describeFilePath.ts
similarity index 100%
rename from packages/typescript-estree/src/create-program/describeFilePath.ts
rename to packages/parser-services/src/create-program/describeFilePath.ts
diff --git a/packages/typescript-estree/src/create-program/getParsedConfigFile.ts b/packages/parser-services/src/create-program/getParsedConfigFile.ts
similarity index 100%
rename from packages/typescript-estree/src/create-program/getParsedConfigFile.ts
rename to packages/parser-services/src/create-program/getParsedConfigFile.ts
diff --git a/packages/typescript-estree/src/create-program/getScriptKind.ts b/packages/parser-services/src/create-program/getScriptKind.ts
similarity index 100%
rename from packages/typescript-estree/src/create-program/getScriptKind.ts
rename to packages/parser-services/src/create-program/getScriptKind.ts
diff --git a/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts b/packages/parser-services/src/create-program/getWatchProgramsForProjects.ts
similarity index 99%
rename from packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts
rename to packages/parser-services/src/create-program/getWatchProgramsForProjects.ts
index b745af116bb4..4d13c9f9828b 100644
--- a/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts
+++ b/packages/parser-services/src/create-program/getWatchProgramsForProjects.ts
@@ -2,7 +2,6 @@ import debug from 'debug';
import fs from 'node:fs';
import * as ts from 'typescript';
-import type { ParseSettings } from '../parseSettings';
import type { CanonicalPath } from './shared';
import type { WatchCompilerHostOfConfigFile } from './WatchCompilerHostOfConfigFile';
@@ -13,6 +12,7 @@ import {
createHash,
getCanonicalFileName,
} from './shared';
+import { ParseSettings } from '../parseSettings';
const log = debug(
'typescript-eslint:typescript-estree:create-program:getWatchProgramsForProjects',
diff --git a/packages/typescript-estree/src/create-program/shared.ts b/packages/parser-services/src/create-program/shared.ts
similarity index 98%
rename from packages/typescript-estree/src/create-program/shared.ts
rename to packages/parser-services/src/create-program/shared.ts
index 07a67cbb9b38..0f1e63f4130f 100644
--- a/packages/typescript-estree/src/create-program/shared.ts
+++ b/packages/parser-services/src/create-program/shared.ts
@@ -2,8 +2,7 @@ import type { Program } from 'typescript';
import path from 'node:path';
import * as ts from 'typescript';
-
-import type { ParseSettings } from '../parseSettings';
+import { ParseSettings } from '../parseSettings';
export interface ASTAndNoProgram {
ast: ts.SourceFile;
diff --git a/packages/typescript-estree/src/create-program/useProvidedPrograms.ts b/packages/parser-services/src/create-program/useProvidedPrograms.ts
similarity index 97%
rename from packages/typescript-estree/src/create-program/useProvidedPrograms.ts
rename to packages/parser-services/src/create-program/useProvidedPrograms.ts
index f84767ea19c7..6b3ff2a11848 100644
--- a/packages/typescript-estree/src/create-program/useProvidedPrograms.ts
+++ b/packages/parser-services/src/create-program/useProvidedPrograms.ts
@@ -2,11 +2,11 @@ import debug from 'debug';
import * as path from 'node:path';
import * as ts from 'typescript';
-import type { ParseSettings } from '../parseSettings';
import type { ASTAndDefiniteProgram } from './shared';
import { getParsedConfigFile } from './getParsedConfigFile';
import { getAstFromProgram } from './shared';
+import { ParseSettings } from '../parseSettings';
const log = debug(
'typescript-eslint:typescript-estree:create-program:useProvidedPrograms',
diff --git a/packages/parser-services/src/create-program/utils.ts b/packages/parser-services/src/create-program/utils.ts
new file mode 100644
index 000000000000..87333d022f4f
--- /dev/null
+++ b/packages/parser-services/src/create-program/utils.ts
@@ -0,0 +1,22 @@
+/**
+ * Like `forEach`, but suitable for use with numbers and strings (which may be falsy).
+ * @todo Switch to .find()?
+ */
+export function firstDefined(
+ array: readonly T[] | undefined,
+ callback: (element: T, index: number) => U | undefined,
+): U | undefined {
+ // eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish
+ if (array === undefined) {
+ return undefined;
+ }
+
+ for (let i = 0; i < array.length; i++) {
+ const result = callback(array[i], i);
+ // eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish
+ if (result !== undefined) {
+ return result;
+ }
+ }
+ return undefined;
+}
diff --git a/packages/typescript-estree/src/create-program/validateDefaultProjectForFilesGlob.ts b/packages/parser-services/src/create-program/validateDefaultProjectForFilesGlob.ts
similarity index 100%
rename from packages/typescript-estree/src/create-program/validateDefaultProjectForFilesGlob.ts
rename to packages/parser-services/src/create-program/validateDefaultProjectForFilesGlob.ts
diff --git a/packages/typescript-estree/src/createParserServices.ts b/packages/parser-services/src/createParserServices.ts
similarity index 91%
rename from packages/typescript-estree/src/createParserServices.ts
rename to packages/parser-services/src/createParserServices.ts
index ee6f18915d9c..0974be6b1ed7 100644
--- a/packages/typescript-estree/src/createParserServices.ts
+++ b/packages/parser-services/src/createParserServices.ts
@@ -1,7 +1,6 @@
+import { ASTMaps } from '@typescript-eslint/typescript-estree';
import type * as ts from 'typescript';
-
-import type { ASTMaps } from './convert';
-import type { ParserServices } from './parser-options';
+import { ParserServices } from './types';
export function createParserServices(
astMaps: ASTMaps,
diff --git a/packages/parser-services/src/index.ts b/packages/parser-services/src/index.ts
new file mode 100644
index 000000000000..8b2d2b7f2a37
--- /dev/null
+++ b/packages/parser-services/src/index.ts
@@ -0,0 +1,6 @@
+export * from './clear-caches';
+export { getCanonicalFileName } from './create-program/shared';
+export type * from './types';
+export { createProgramFromConfigFile as createProgram } from './create-program/useProvidedPrograms';
+export * from './withoutProjectParserOptions';
+export * from './parser';
diff --git a/packages/typescript-estree/src/parseSettings/ExpiringCache.ts b/packages/parser-services/src/parseSettings/ExpiringCache.ts
similarity index 100%
rename from packages/typescript-estree/src/parseSettings/ExpiringCache.ts
rename to packages/parser-services/src/parseSettings/ExpiringCache.ts
diff --git a/packages/typescript-estree/src/parseSettings/createParseSettings.ts b/packages/parser-services/src/parseSettings/createParseSettings.ts
similarity index 95%
rename from packages/typescript-estree/src/parseSettings/createParseSettings.ts
rename to packages/parser-services/src/parseSettings/createParseSettings.ts
index 6a1c42008c6b..29592ceffbd2 100644
--- a/packages/typescript-estree/src/parseSettings/createParseSettings.ts
+++ b/packages/parser-services/src/parseSettings/createParseSettings.ts
@@ -2,12 +2,11 @@ import debug from 'debug';
import path from 'node:path';
import * as ts from 'typescript';
-import type { ProjectServiceSettings } from '../create-program/createProjectService';
-import type { TSESTreeOptions } from '../parser-options';
+import type { ProjectServiceSettings } from '../../../parser-services/src/create-program/createProjectService';
import type { MutableParseSettings } from './index';
-import { createProjectService } from '../create-program/createProjectService';
-import { ensureAbsolutePath } from '../create-program/shared';
+import { createProjectService } from '../../../parser-services/src/create-program/createProjectService';
+import { ensureAbsolutePath } from '../../../parser-services/src/create-program/shared';
import { isSourceFile } from '../source-files';
import {
DEFAULT_TSCONFIG_CACHE_DURATION_SECONDS,
@@ -17,6 +16,7 @@ import { getProjectConfigFiles } from './getProjectConfigFiles';
import { inferSingleRun } from './inferSingleRun';
import { resolveProjectList } from './resolveProjectList';
import { warnAboutTSVersion } from './warnAboutTSVersion';
+import { TSESTreeOptions } from '@typescript-eslint/typescript-estree';
const log = debug(
'typescript-eslint:typescript-estree:parseSettings:createParseSettings',
diff --git a/packages/typescript-estree/src/parseSettings/getProjectConfigFiles.ts b/packages/parser-services/src/parseSettings/getProjectConfigFiles.ts
similarity index 96%
rename from packages/typescript-estree/src/parseSettings/getProjectConfigFiles.ts
rename to packages/parser-services/src/parseSettings/getProjectConfigFiles.ts
index f7f3dc8851b8..f6bfd0cb325d 100644
--- a/packages/typescript-estree/src/parseSettings/getProjectConfigFiles.ts
+++ b/packages/parser-services/src/parseSettings/getProjectConfigFiles.ts
@@ -2,8 +2,8 @@ import debug from 'debug';
import * as fs from 'node:fs';
import * as path from 'node:path';
-import type { TSESTreeOptions } from '../parser-options';
import type { ParseSettings } from './index';
+import { TSESTreeOptions } from '@typescript-eslint/typescript-estree';
const log = debug(
'typescript-eslint:typescript-estree:parseSettings:getProjectConfigFiles',
diff --git a/packages/typescript-estree/src/parseSettings/index.ts b/packages/parser-services/src/parseSettings/index.ts
similarity index 93%
rename from packages/typescript-estree/src/parseSettings/index.ts
rename to packages/parser-services/src/parseSettings/index.ts
index 1ea208210e0a..5d188bc263e3 100644
--- a/packages/typescript-estree/src/parseSettings/index.ts
+++ b/packages/parser-services/src/parseSettings/index.ts
@@ -1,8 +1,8 @@
+import type { TSESTree } from '@typescript-eslint/typescript-estree';
import type * as ts from 'typescript';
-import type { ProjectServiceSettings } from '../create-program/createProjectService';
-import type { CanonicalPath } from '../create-program/shared';
-import type { TSESTree } from '../ts-estree';
+import type { ProjectServiceSettings } from '../../../parser-services/src/create-program/createProjectService';
+import type { CanonicalPath } from '../../../parser-services/src/create-program/shared';
import type { CacheLike } from './ExpiringCache';
type DebugModule = 'eslint' | 'typescript' | 'typescript-eslint';
diff --git a/packages/typescript-estree/src/parseSettings/inferSingleRun.ts b/packages/parser-services/src/parseSettings/inferSingleRun.ts
similarity index 97%
rename from packages/typescript-estree/src/parseSettings/inferSingleRun.ts
rename to packages/parser-services/src/parseSettings/inferSingleRun.ts
index 8007e6ccd66a..7fd8c81902e6 100644
--- a/packages/typescript-estree/src/parseSettings/inferSingleRun.ts
+++ b/packages/parser-services/src/parseSettings/inferSingleRun.ts
@@ -1,7 +1,6 @@
+import { TSESTreeOptions } from '@typescript-eslint/typescript-estree';
import path from 'node:path';
-import type { TSESTreeOptions } from '../parser-options';
-
/**
* ESLint (and therefore typescript-eslint) is used in both "single run"/one-time contexts,
* such as an ESLint CLI invocation, and long-running sessions (such as continuous feedback
diff --git a/packages/typescript-estree/src/parseSettings/resolveProjectList.ts b/packages/parser-services/src/parseSettings/resolveProjectList.ts
similarity index 93%
rename from packages/typescript-estree/src/parseSettings/resolveProjectList.ts
rename to packages/parser-services/src/parseSettings/resolveProjectList.ts
index f29bf0026469..4404a1a4cdce 100644
--- a/packages/typescript-estree/src/parseSettings/resolveProjectList.ts
+++ b/packages/parser-services/src/parseSettings/resolveProjectList.ts
@@ -1,22 +1,23 @@
+import type { TSESTreeOptions } from '@typescript-eslint/typescript-estree';
+
import debug from 'debug';
import { sync as globSync } from 'fast-glob';
import isGlob from 'is-glob';
-import type { CanonicalPath } from '../create-program/shared';
-import type { TSESTreeOptions } from '../parser-options';
+import type { CanonicalPath } from '../../../parser-services/src/create-program/shared';
import {
createHash,
ensureAbsolutePath,
getCanonicalFileName,
-} from '../create-program/shared';
+} from '../../../parser-services/src/create-program/shared';
import {
DEFAULT_TSCONFIG_CACHE_DURATION_SECONDS,
ExpiringCache,
} from './ExpiringCache';
const log = debug(
- 'typescript-eslint:typescript-estree:parseSettings:resolveProjectList',
+ 'typescript-eslint:parser-services:parseSettings:resolveProjectList',
);
let RESOLUTION_CACHE: ExpiringCache<
diff --git a/packages/typescript-estree/src/parseSettings/warnAboutTSVersion.ts b/packages/parser-services/src/parseSettings/warnAboutTSVersion.ts
similarity index 92%
rename from packages/typescript-estree/src/parseSettings/warnAboutTSVersion.ts
rename to packages/parser-services/src/parseSettings/warnAboutTSVersion.ts
index 8ac2801476bd..4dd06a275d46 100644
--- a/packages/typescript-estree/src/parseSettings/warnAboutTSVersion.ts
+++ b/packages/parser-services/src/parseSettings/warnAboutTSVersion.ts
@@ -3,7 +3,7 @@ import * as ts from 'typescript';
import type { ParseSettings } from './index';
-import { version as TYPESCRIPT_ESTREE_VERSION } from '../version';
+import { version as PARSER_SERVICES_VERSION } from '../version';
/**
* This needs to be kept in sync with package.json in the typescript-eslint monorepo
@@ -43,7 +43,7 @@ export function warnAboutTSVersion(
'\n',
'WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.',
'\n',
- `* @typescript-eslint/typescript-estree version: ${TYPESCRIPT_ESTREE_VERSION}`,
+ `* @typescript-eslint/parser-services version: ${PARSER_SERVICES_VERSION}`,
`* Supported TypeScript versions: ${SUPPORTED_TYPESCRIPT_VERSIONS}`,
`* Your TypeScript version: ${ACTIVE_TYPESCRIPT_VERSION}`,
'\n',
diff --git a/packages/typescript-estree/src/parser.ts b/packages/parser-services/src/parser.ts
similarity index 94%
rename from packages/typescript-estree/src/parser.ts
rename to packages/parser-services/src/parser.ts
index 1c0c6e42aa83..626921fdfb91 100644
--- a/packages/typescript-estree/src/parser.ts
+++ b/packages/parser-services/src/parser.ts
@@ -1,18 +1,14 @@
import type * as ts from 'typescript';
+import {
+ astConverter,
+ convertTSErrorToTSESTreeError,
+} from '@typescript-eslint/typescript-estree';
import debug from 'debug';
import type { ASTAndProgram, CanonicalPath } from './create-program/shared';
-import type {
- ParserServices,
- ParserServicesNodeMaps,
- TSESTreeOptions,
-} from './parser-options';
import type { ParseSettings } from './parseSettings';
-import type { TSESTree } from './ts-estree';
-import { astConverter } from './ast-converter';
-import { convertError } from './convert';
import { createIsolatedProgram } from './create-program/createIsolatedProgram';
import { createProjectProgram } from './create-program/createProjectProgram';
import {
@@ -26,10 +22,16 @@ import {
} from './create-program/useProvidedPrograms';
import { createParserServices } from './createParserServices';
import { createParseSettings } from './parseSettings/createParseSettings';
-import { getFirstSemanticOrSyntacticError } from './semantic-or-syntactic-errors';
import { useProgramFromProjectService } from './useProgramFromProjectService';
+import type {
+ ParserServicesNodeMaps,
+ TSESTree,
+ TSESTreeOptions,
+} from '@typescript-eslint/typescript-estree';
+import { ParserServices } from './types';
+import { getFirstSemanticOrSyntacticError } from './semantic-or-syntactic-errors';
-const log = debug('typescript-eslint:typescript-estree:parser');
+const log = debug('typescript-eslint:parser-services:parser');
/**
* Cache existing programs for the single run use-case.
@@ -101,6 +103,7 @@ export interface ParseAndGenerateServicesResult {
ast: AST;
services: ParserServices;
}
+
interface ParseWithNodeMapsResult
extends ParserServicesNodeMaps {
ast: AST;
@@ -148,7 +151,8 @@ function parseWithNodeMapsInternal(
);
return {
- ast: estree as AST,
+ // @ts-expect-error -- TODO: I don't know why this is no longer working...
+ ast: estree,
esTreeNodeToTSNodeMap: astMaps.esTreeNodeToTSNodeMap,
tsNodeToESTreeNodeMap: astMaps.tsNodeToESTreeNodeMap,
};
@@ -265,7 +269,7 @@ export function parseAndGenerateServices<
if (program && parseSettings.errorOnTypeScriptSyntacticAndSemanticIssues) {
const error = getFirstSemanticOrSyntacticError(program, ast);
if (error) {
- throw convertError(error);
+ throw convertTSErrorToTSESTreeError(error);
}
}
@@ -273,7 +277,8 @@ export function parseAndGenerateServices<
* Return the converted AST and additional parser services
*/
return {
- ast: estree as AST,
+ // @ts-expect-error -- TODO: I don't know why this is no longer working...
+ ast: estree,
services: createParserServices(astMaps, program),
};
}
diff --git a/packages/parser-services/src/semantic-or-syntactic-errors.ts b/packages/parser-services/src/semantic-or-syntactic-errors.ts
new file mode 100644
index 000000000000..a88a3615d9f8
--- /dev/null
+++ b/packages/parser-services/src/semantic-or-syntactic-errors.ts
@@ -0,0 +1,119 @@
+import type {
+ Diagnostic,
+ DiagnosticWithLocation,
+ Program,
+ SourceFile,
+} from 'typescript';
+
+import { flattenDiagnosticMessageText, sys } from 'typescript';
+
+export interface SemanticOrSyntacticError extends Diagnostic {
+ message: string;
+}
+
+/**
+ * By default, diagnostics from the TypeScript compiler contain all errors - regardless of whether
+ * they are related to generic ECMAScript standards, or TypeScript-specific constructs.
+ *
+ * Therefore, we filter out all diagnostics, except for the ones we explicitly want to consider when
+ * the user opts in to throwing errors on semantic issues.
+ */
+export function getFirstSemanticOrSyntacticError(
+ program: Program,
+ ast: SourceFile,
+): SemanticOrSyntacticError | undefined {
+ try {
+ const supportedSyntacticDiagnostics = allowlistSupportedDiagnostics(
+ program.getSyntacticDiagnostics(ast),
+ );
+ if (supportedSyntacticDiagnostics.length > 0) {
+ return convertDiagnosticToSemanticOrSyntacticError(
+ supportedSyntacticDiagnostics[0],
+ );
+ }
+ const supportedSemanticDiagnostics = allowlistSupportedDiagnostics(
+ program.getSemanticDiagnostics(ast),
+ );
+ if (supportedSemanticDiagnostics.length > 0) {
+ return convertDiagnosticToSemanticOrSyntacticError(
+ supportedSemanticDiagnostics[0],
+ );
+ }
+ return undefined;
+ } catch (e) {
+ /**
+ * TypeScript compiler has certain Debug.fail() statements in, which will cause the diagnostics
+ * retrieval above to throw.
+ *
+ * E.g. from ast-alignment-tests
+ * "Debug Failure. Shouldn't ever directly check a JsxOpeningElement"
+ *
+ * For our current use-cases this is undesired behavior, so we just suppress it
+ * and log a warning.
+ */
+ /* istanbul ignore next */
+ console.warn(`Warning From TSC: "${(e as Error).message}`); // eslint-disable-line no-console
+ /* istanbul ignore next */
+ return undefined;
+ }
+}
+
+function allowlistSupportedDiagnostics(
+ diagnostics: readonly (Diagnostic | DiagnosticWithLocation)[],
+): readonly (Diagnostic | DiagnosticWithLocation)[] {
+ return diagnostics.filter(diagnostic => {
+ switch (diagnostic.code) {
+ case 1013: // "A rest parameter or binding pattern may not have a trailing comma."
+ case 1014: // "A rest parameter must be last in a parameter list."
+ case 1044: // "'{0}' modifier cannot appear on a module or namespace element."
+ case 1045: // "A '{0}' modifier cannot be used with an interface declaration."
+ case 1048: // "A rest parameter cannot have an initializer."
+ case 1049: // "A 'set' accessor must have exactly one parameter."
+ case 1070: // "'{0}' modifier cannot appear on a type member."
+ case 1071: // "'{0}' modifier cannot appear on an index signature."
+ case 1085: // "Octal literals are not available when targeting ECMAScript 5 and higher. Use the syntax '{0}'."
+ case 1090: // "'{0}' modifier cannot appear on a parameter."
+ case 1096: // "An index signature must have exactly one parameter."
+ case 1097: // "'{0}' list cannot be empty."
+ case 1098: // "Type parameter list cannot be empty."
+ case 1099: // "Type argument list cannot be empty."
+ case 1117: // "An object literal cannot have multiple properties with the same name in strict mode."
+ case 1121: // "Octal literals are not allowed in strict mode."
+ case 1123: // "Variable declaration list cannot be empty."
+ case 1141: // "String literal expected."
+ case 1162: // "An object member cannot be declared optional."
+ case 1164: // "Computed property names are not allowed in enums."
+ case 1172: // "'extends' clause already seen."
+ case 1173: // "'extends' clause must precede 'implements' clause."
+ case 1175: // "'implements' clause already seen."
+ case 1176: // "Interface declaration cannot have 'implements' clause."
+ case 1190: // "The variable declaration of a 'for...of' statement cannot have an initializer."
+ case 1196: // "Catch clause variable type annotation must be 'any' or 'unknown' if specified."
+ case 1200: // "Line terminator not permitted before arrow."
+ case 1206: // "Decorators are not valid here."
+ case 1211: // "A class declaration without the 'default' modifier must have a name."
+ case 1242: // "'abstract' modifier can only appear on a class, method, or property declaration."
+ case 1246: // "An interface property cannot have an initializer."
+ case 1255: // "A definite assignment assertion '!' is not permitted in this context."
+ case 1308: // "'await' expression is only allowed within an async function."
+ case 2364: // "The left-hand side of an assignment expression must be a variable or a property access."
+ case 2369: // "A parameter property is only allowed in a constructor implementation."
+ case 2452: // "An enum member cannot have a numeric name."
+ case 2462: // "A rest element must be last in a destructuring pattern."
+ case 8017: // "Octal literal types must use ES2015 syntax. Use the syntax '{0}'."
+ case 17012: // "'{0}' is not a valid meta-property for keyword '{1}'. Did you mean '{2}'?"
+ case 17013: // "Meta-property '{0}' is only allowed in the body of a function declaration, function expression, or constructor."
+ return true;
+ }
+ return false;
+ });
+}
+
+function convertDiagnosticToSemanticOrSyntacticError(
+ diagnostic: Diagnostic,
+): SemanticOrSyntacticError {
+ return {
+ ...diagnostic,
+ message: flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine),
+ };
+}
diff --git a/packages/typescript-estree/src/source-files.ts b/packages/parser-services/src/source-files.ts
similarity index 100%
rename from packages/typescript-estree/src/source-files.ts
rename to packages/parser-services/src/source-files.ts
diff --git a/packages/parser-services/src/types.ts b/packages/parser-services/src/types.ts
new file mode 100644
index 000000000000..7c31e060fb10
--- /dev/null
+++ b/packages/parser-services/src/types.ts
@@ -0,0 +1,29 @@
+import {
+ ParserServicesNodeMaps,
+ TSESTree,
+} from '@typescript-eslint/typescript-estree';
+import ts from 'typescript';
+
+export interface ParserServicesBase {
+ emitDecoratorMetadata: boolean | undefined;
+ experimentalDecorators: boolean | undefined;
+ isolatedDeclarations: boolean | undefined;
+}
+
+export interface ParserServicesWithTypeInformation
+ extends ParserServicesNodeMaps,
+ ParserServicesBase {
+ getSymbolAtLocation: (node: TSESTree.Node) => ts.Symbol | undefined;
+ getTypeAtLocation: (node: TSESTree.Node) => ts.Type;
+ program: ts.Program;
+}
+
+export interface ParserServicesWithoutTypeInformation
+ extends ParserServicesNodeMaps,
+ ParserServicesBase {
+ program: null;
+}
+
+export type ParserServices =
+ | ParserServicesWithoutTypeInformation
+ | ParserServicesWithTypeInformation;
diff --git a/packages/parser-services/src/use-at-your-own-risk.ts b/packages/parser-services/src/use-at-your-own-risk.ts
new file mode 100644
index 000000000000..a144380b68f3
--- /dev/null
+++ b/packages/parser-services/src/use-at-your-own-risk.ts
@@ -0,0 +1,6 @@
+// required by website
+export * from './create-program/getScriptKind';
+export type { ParseSettings } from './parseSettings';
+
+// required by packages/type-utils
+export { getCanonicalFileName } from './create-program/shared';
diff --git a/packages/typescript-estree/src/useProgramFromProjectService.ts b/packages/parser-services/src/useProgramFromProjectService.ts
similarity index 100%
rename from packages/typescript-estree/src/useProgramFromProjectService.ts
rename to packages/parser-services/src/useProgramFromProjectService.ts
diff --git a/packages/parser-services/src/version.ts b/packages/parser-services/src/version.ts
new file mode 100644
index 000000000000..1a7b810e764a
--- /dev/null
+++ b/packages/parser-services/src/version.ts
@@ -0,0 +1,3 @@
+// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder
+// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
+export const version: string = require('../package.json').version;
diff --git a/packages/typescript-estree/src/withoutProjectParserOptions.ts b/packages/parser-services/src/withoutProjectParserOptions.ts
similarity index 100%
rename from packages/typescript-estree/src/withoutProjectParserOptions.ts
rename to packages/parser-services/src/withoutProjectParserOptions.ts
diff --git a/packages/parser-services/tsconfig.build.json b/packages/parser-services/tsconfig.build.json
new file mode 100644
index 000000000000..241b39d618e6
--- /dev/null
+++ b/packages/parser-services/tsconfig.build.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "rootDir": "src",
+ "outDir": "dist",
+ "tsBuildInfoFile": "dist/tsconfig.build.tsbuildinfo",
+ "emitDeclarationOnly": false,
+ "types": ["node"]
+ },
+ "include": ["src/**/*.ts", "typings"],
+ "references": [
+ {
+ "path": "../typescript-estree/tsconfig.build.json"
+ }
+ ]
+}
diff --git a/packages/parser-services/tsconfig.json b/packages/parser-services/tsconfig.json
new file mode 100644
index 000000000000..4733311e9be9
--- /dev/null
+++ b/packages/parser-services/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "../typescript-estree"
+ },
+ {
+ "path": "./tsconfig.build.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ]
+}
diff --git a/packages/parser-services/tsconfig.spec.json b/packages/parser-services/tsconfig.spec.json
new file mode 100644
index 000000000000..872d3c655b27
--- /dev/null
+++ b/packages/parser-services/tsconfig.spec.json
@@ -0,0 +1,18 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc/packages/types/vitest",
+ "resolveJsonModule": true,
+ "types": ["vitest/globals", "vitest/importMeta"]
+ },
+ "include": ["vitest.config.mts", "package.json", "tests"],
+ "exclude": ["**/fixtures/**"],
+ "references": [
+ {
+ "path": "./tsconfig.build.json"
+ },
+ {
+ "path": "../../tsconfig.spec.json"
+ }
+ ]
+}
diff --git a/packages/parser-services/typings/typescript.d.ts b/packages/parser-services/typings/typescript.d.ts
new file mode 100644
index 000000000000..7a665b57abbe
--- /dev/null
+++ b/packages/parser-services/typings/typescript.d.ts
@@ -0,0 +1,57 @@
+import 'typescript';
+
+// these additions are marked as internal to typescript
+declare module 'typescript' {
+ interface SourceFile {
+ externalModuleIndicator?: Node | true;
+ parseDiagnostics: DiagnosticWithLocation[];
+ }
+
+ interface JSDocContainer {
+ jsDoc?: JSDoc[];
+ }
+
+ // add back the deprecated properties that were removed in newer TS versions
+ // make sure these properties are marked as @ deprecated so they're flagged
+ // by the `@typescript-eslint/no-deprecated` lint rule
+
+ interface PropertySignature {
+ /** @deprecated removed in 5.0 but we want to keep it for backwards compatibility checks! */
+ readonly initializer?: Expression | undefined;
+ }
+ interface PropertyAssignment {
+ /** @deprecated removed in 5.0 but we want to keep it for backwards compatibility checks! */
+ readonly exclamationToken?: ExclamationToken | undefined;
+ /** @deprecated removed in 5.0 but we want to keep it for backwards compatibility checks! */
+ readonly questionToken?: QuestionToken | undefined;
+ }
+ interface ShorthandPropertyAssignment {
+ /** @deprecated removed in 5.0 but we want to keep it for backwards compatibility checks! */
+ readonly exclamationToken?: ExclamationToken | undefined;
+ /** @deprecated removed in 5.0 but we want to keep it for backwards compatibility checks! */
+ readonly modifiers?: NodeArray | undefined;
+ /** @deprecated removed in 5.0 but we want to keep it for backwards compatibility checks! */
+ readonly questionToken?: QuestionToken | undefined;
+ }
+ interface FunctionTypeNode {
+ /** @deprecated removed in 5.0 but we want to keep it for backwards compatibility checks! */
+ readonly modifiers?: NodeArray | undefined;
+ }
+
+ /**
+ * @deprecated don't use this directly as it does not exist pre-4.8; instead use getDecorators from `src/getModifiers.ts`.
+ */
+ function getDecorators(node: HasDecorators): readonly Decorator[] | undefined;
+ /**
+ * @deprecated don't use this directly as it does not exist pre-4.8; instead use getModifiers from `src/getModifiers.ts`.
+ */
+ function getModifiers(node: HasModifiers): readonly Modifier[] | undefined;
+ /**
+ * @deprecated don't use this directly as it does not exist pre-4.8; instead use getModifiers from `src/getModifiers.ts`.
+ */
+ function canHaveModifiers(node: Node): node is HasModifiers;
+ /**
+ * @deprecated don't use this directly as it does not exist pre-4.8; instead use getDecorators from `src/getModifiers.ts`.
+ */
+ function canHaveDecorators(node: Node): node is HasDecorators;
+}
diff --git a/packages/parser-services/vitest.config.mts b/packages/parser-services/vitest.config.mts
new file mode 100644
index 000000000000..136e4f77b392
--- /dev/null
+++ b/packages/parser-services/vitest.config.mts
@@ -0,0 +1,22 @@
+import * as path from 'node:path';
+import { defineConfig, mergeConfig } from 'vitest/config';
+
+import { vitestBaseConfig } from '../../vitest.config.base.mjs';
+import packageJson from './package.json' with { type: 'json' };
+
+const vitestConfig = mergeConfig(
+ vitestBaseConfig,
+
+ defineConfig({
+ root: import.meta.dirname,
+
+ test: {
+ dir: path.join(import.meta.dirname, 'tests'),
+ name: packageJson.name.replace('@typescript-eslint/', ''),
+ passWithNoTests: true,
+ root: import.meta.dirname,
+ },
+ }),
+);
+
+export default vitestConfig;
diff --git a/packages/parser/package.json b/packages/parser/package.json
index 659172ce81e9..0afd53b02300 100644
--- a/packages/parser/package.json
+++ b/packages/parser/package.json
@@ -52,6 +52,7 @@
"typescript": ">=4.8.4 <5.9.0"
},
"dependencies": {
+ "@typescript-eslint/parser-services": "8.32.0",
"@typescript-eslint/scope-manager": "8.32.0",
"@typescript-eslint/types": "8.32.0",
"@typescript-eslint/typescript-estree": "8.32.0",
diff --git a/packages/parser/src/index.ts b/packages/parser/src/index.ts
index a1af2c02cd4b..db293b5b4762 100644
--- a/packages/parser/src/index.ts
+++ b/packages/parser/src/index.ts
@@ -1,12 +1,12 @@
export { parse, parseForESLint, type ParserOptions } from './parser';
export {
- clearCaches,
- createProgram,
type ParserServices,
type ParserServicesWithoutTypeInformation,
type ParserServicesWithTypeInformation,
+ clearCaches,
+ createProgram,
withoutProjectParserOptions,
-} from '@typescript-eslint/typescript-estree';
+} from '@typescript-eslint/parser-services';
// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
diff --git a/packages/parser/src/parser.ts b/packages/parser/src/parser.ts
index f4a50c81a505..85cea7348102 100644
--- a/packages/parser/src/parser.ts
+++ b/packages/parser/src/parser.ts
@@ -1,18 +1,18 @@
+import {
+ AST,
+ parseAndGenerateServices,
+ type ParserServices,
+} from '@typescript-eslint/parser-services';
import type {
AnalyzeOptions,
ScopeManager,
} from '@typescript-eslint/scope-manager';
import type { Lib, ParserOptions, TSESTree } from '@typescript-eslint/types';
-import type {
- AST,
- ParserServices,
- TSESTreeOptions,
-} from '@typescript-eslint/typescript-estree';
+import type { TSESTreeOptions } from '@typescript-eslint/typescript-estree';
import type { VisitorKeys } from '@typescript-eslint/visitor-keys';
import type * as ts from 'typescript';
import { analyze } from '@typescript-eslint/scope-manager';
-import { parseAndGenerateServices } from '@typescript-eslint/typescript-estree';
import { visitorKeys } from '@typescript-eslint/visitor-keys';
import debug from 'debug';
import { ScriptTarget } from 'typescript';
diff --git a/packages/parser/tsconfig.build.json b/packages/parser/tsconfig.build.json
index ca2c74a7ac78..bee92c2f0195 100644
--- a/packages/parser/tsconfig.build.json
+++ b/packages/parser/tsconfig.build.json
@@ -2,6 +2,9 @@
"extends": "../../tsconfig.build.json",
"compilerOptions": {},
"references": [
+ {
+ "path": "../parser-services/tsconfig.build.json"
+ },
{
"path": "../visitor-keys/tsconfig.build.json"
},
diff --git a/packages/parser/tsconfig.json b/packages/parser/tsconfig.json
index 8122a5aaab8a..fd04f00b8cc1 100644
--- a/packages/parser/tsconfig.json
+++ b/packages/parser/tsconfig.json
@@ -3,6 +3,9 @@
"files": [],
"include": [],
"references": [
+ {
+ "path": "../parser-services"
+ },
{
"path": "../visitor-keys"
},
diff --git a/packages/type-utils/src/getConstrainedTypeAtLocation.ts b/packages/type-utils/src/getConstrainedTypeAtLocation.ts
index d31df29ab5b1..f79c75633e4d 100644
--- a/packages/type-utils/src/getConstrainedTypeAtLocation.ts
+++ b/packages/type-utils/src/getConstrainedTypeAtLocation.ts
@@ -1,7 +1,5 @@
-import type {
- ParserServicesWithTypeInformation,
- TSESTree,
-} from '@typescript-eslint/typescript-estree';
+import { ParserServicesWithTypeInformation } from '@typescript-eslint/utils';
+import type { TSESTree } from '@typescript-eslint/typescript-estree';
import type * as ts from 'typescript';
/**
diff --git a/packages/type-utils/src/getDeclaration.ts b/packages/type-utils/src/getDeclaration.ts
index 9e8d8b770248..9c9cd40f057c 100644
--- a/packages/type-utils/src/getDeclaration.ts
+++ b/packages/type-utils/src/getDeclaration.ts
@@ -1,7 +1,5 @@
-import type {
- ParserServicesWithTypeInformation,
- TSESTree,
-} from '@typescript-eslint/typescript-estree';
+import type { TSESTree } from '@typescript-eslint/typescript-estree';
+import { ParserServicesWithTypeInformation } from '@typescript-eslint/utils';
import type * as ts from 'typescript';
/**
diff --git a/packages/type-utils/src/typeOrValueSpecifiers/typeDeclaredInFile.ts b/packages/type-utils/src/typeOrValueSpecifiers/typeDeclaredInFile.ts
index 548767a5a703..1ea7580a5808 100644
--- a/packages/type-utils/src/typeOrValueSpecifiers/typeDeclaredInFile.ts
+++ b/packages/type-utils/src/typeOrValueSpecifiers/typeDeclaredInFile.ts
@@ -1,7 +1,7 @@
import type * as ts from 'typescript';
-import { getCanonicalFileName } from '@typescript-eslint/typescript-estree';
import path from 'node:path';
+import { getCanonicalFileName } from '@typescript-eslint/parser-services';
export function typeDeclaredInFile(
relativePath: string | undefined,
diff --git a/packages/typescript-estree/package.json b/packages/typescript-estree/package.json
index 56f0f128a669..04792485d313 100644
--- a/packages/typescript-estree/package.json
+++ b/packages/typescript-estree/package.json
@@ -55,8 +55,6 @@
"@typescript-eslint/types": "8.32.0",
"@typescript-eslint/visitor-keys": "8.32.0",
"debug": "^4.3.4",
- "fast-glob": "^3.3.2",
- "is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
"ts-api-utils": "^2.1.0"
diff --git a/packages/typescript-estree/src/ast-converter.ts b/packages/typescript-estree/src/ast-converter.ts
index 65b993cbefa9..8250a4b6089d 100644
--- a/packages/typescript-estree/src/ast-converter.ts
+++ b/packages/typescript-estree/src/ast-converter.ts
@@ -1,17 +1,28 @@
import type { SourceFile } from 'typescript';
import type { ASTMaps } from './convert';
-import type { ParseSettings } from './parseSettings';
import type { TSESTree } from './ts-estree';
-import { Converter, convertError } from './convert';
+import { Converter } from './convert';
import { convertComments } from './convert-comments';
import { convertTokens } from './node-utils';
import { simpleTraverse } from './simple-traverse';
+import { convertTSErrorToTSESTreeError } from './errors';
+
+export interface AstConverterSettings {
+ allowInvalidAST?: boolean | undefined;
+ codeFullText: string;
+ comment?: boolean;
+ errorOnUnknownASTType?: boolean | undefined;
+ loc?: boolean;
+ range?: boolean;
+ suppressDeprecatedPropertyWarnings?: boolean | undefined;
+ tokens?: TSESTree.Token[] | null;
+}
export function astConverter(
ast: SourceFile,
- parseSettings: ParseSettings,
+ settings: AstConverterSettings,
shouldPreserveNodeMaps: boolean,
): { astMaps: ASTMaps; estree: TSESTree.Program } {
/**
@@ -20,18 +31,18 @@ export function astConverter(
*/
const { parseDiagnostics } = ast;
if (parseDiagnostics.length) {
- throw convertError(parseDiagnostics[0]);
+ throw convertTSErrorToTSESTreeError(parseDiagnostics[0]);
}
/**
* Recursively convert the TypeScript AST into an ESTree-compatible AST
*/
const instance = new Converter(ast, {
- allowInvalidAST: parseSettings.allowInvalidAST,
- errorOnUnknownASTType: parseSettings.errorOnUnknownASTType,
+ allowInvalidAST: settings.allowInvalidAST,
+ errorOnUnknownASTType: settings.errorOnUnknownASTType,
shouldPreserveNodeMaps,
suppressDeprecatedPropertyWarnings:
- parseSettings.suppressDeprecatedPropertyWarnings,
+ settings.suppressDeprecatedPropertyWarnings,
});
const estree = instance.convertProgram();
@@ -39,15 +50,15 @@ export function astConverter(
/**
* Optionally remove range and loc if specified
*/
- if (!parseSettings.range || !parseSettings.loc) {
+ if (!settings.range || !settings.loc) {
simpleTraverse(estree, {
enter: node => {
- if (!parseSettings.range) {
+ if (!settings.range) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- TS 4.0 made this an error because the types aren't optional
// @ts-expect-error
delete node.range;
}
- if (!parseSettings.loc) {
+ if (!settings.loc) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- TS 4.0 made this an error because the types aren't optional
// @ts-expect-error
delete node.loc;
@@ -59,15 +70,15 @@ export function astConverter(
/**
* Optionally convert and include all tokens in the AST
*/
- if (parseSettings.tokens) {
+ if (settings.tokens) {
estree.tokens = convertTokens(ast);
}
/**
* Optionally convert and include all comments in the AST
*/
- if (parseSettings.comment) {
- estree.comments = convertComments(ast, parseSettings.codeFullText);
+ if (settings.comment) {
+ estree.comments = convertComments(ast, settings.codeFullText);
}
const astMaps = instance.getASTMaps();
diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts
index 22c0257505a2..ffdf1d3af3d0 100644
--- a/packages/typescript-estree/src/convert.ts
+++ b/packages/typescript-estree/src/convert.ts
@@ -2,18 +2,12 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-condition, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access */
import * as ts from 'typescript';
-import type { TSError } from './node-utils';
-import type {
- ParserWeakMap,
- ParserWeakMapESTreeToTSNode,
-} from './parser-options';
-import type { SemanticOrSyntacticError } from './semantic-or-syntactic-errors';
+import type { ParserWeakMap, ParserWeakMapESTreeToTSNode } from './node-maps';
import type { TSESTree, TSESTreeToTSNode, TSNode } from './ts-estree';
import { getDecorators, getModifiers } from './getModifiers';
import {
canContainDirective,
- createError,
findNextToken,
getBinaryExpressionType,
getContainingFunction,
@@ -40,6 +34,7 @@ import {
unescapeStringLiteralText,
} from './node-utils';
import { AST_NODE_TYPES } from './ts-estree';
+import { createTSESTreeError } from './errors';
const SyntaxKind = ts.SyntaxKind;
@@ -50,21 +45,6 @@ export interface ConverterOptions {
suppressDeprecatedPropertyWarnings?: boolean;
}
-/**
- * Extends and formats a given error object
- * @param error the error object
- * @returns converted error object
- */
-export function convertError(
- error: SemanticOrSyntacticError | ts.DiagnosticWithLocation,
-): TSError {
- return createError(
- ('message' in error && error.message) || (error.messageText as string),
- error.file!,
- error.start!,
- );
-}
-
export interface ASTMaps {
esTreeNodeToTSNodeMap: ParserWeakMapESTreeToTSNode;
tsNodeToESTreeNodeMap: ParserWeakMap;
@@ -392,7 +372,7 @@ export class Converter {
end = node.getEnd();
}
- throw createError(message, this.ast, start, end);
+ throw createTSESTreeError(message, this.ast, start, end);
}
#throwUnlessAllowInvalidAST(
diff --git a/packages/typescript-estree/src/errors.ts b/packages/typescript-estree/src/errors.ts
new file mode 100644
index 000000000000..0e1bd6194a15
--- /dev/null
+++ b/packages/typescript-estree/src/errors.ts
@@ -0,0 +1,72 @@
+import * as ts from 'typescript';
+import { SemanticOrSyntacticError } from './semantic-or-syntactic-errors';
+
+/**
+ * Extends and formats a given error object
+ * @param error the error object
+ * @returns converted error object
+ */
+export function convertTSErrorToTSESTreeError(
+ error: SemanticOrSyntacticError | ts.DiagnosticWithLocation,
+): TSESTreeError {
+ return createTSESTreeError(
+ ('message' in error && error.message) || (error.messageText as string),
+ error.file!,
+ error.start!,
+ );
+}
+
+export function createTSESTreeError(
+ message: string,
+ ast: ts.SourceFile,
+ startIndex: number,
+ endIndex: number = startIndex,
+): TSESTreeError {
+ const [start, end] = [startIndex, endIndex].map(offset => {
+ const { character: column, line } =
+ ast.getLineAndCharacterOfPosition(offset);
+ return { column, line: line + 1, offset };
+ });
+ return new TSESTreeError(message, ast.fileName, { end, start });
+}
+
+export class TSESTreeError extends Error {
+ constructor(
+ message: string,
+ public readonly fileName: string,
+ public readonly location: {
+ end: {
+ column: number;
+ line: number;
+ offset: number;
+ };
+ start: {
+ column: number;
+ line: number;
+ offset: number;
+ };
+ },
+ ) {
+ super(message);
+ Object.defineProperty(this, 'name', {
+ configurable: true,
+ enumerable: false,
+ value: new.target.name,
+ });
+ }
+
+ // For old version of ESLint https://github.com/typescript-eslint/typescript-eslint/pull/6556#discussion_r1123237311
+ get index(): number {
+ return this.location.start.offset;
+ }
+
+ // https://github.com/eslint/eslint/blob/b09a512107249a4eb19ef5a37b0bd672266eafdb/lib/linter/linter.js#L853
+ get lineNumber(): number {
+ return this.location.start.line;
+ }
+
+ // https://github.com/eslint/eslint/blob/b09a512107249a4eb19ef5a37b0bd672266eafdb/lib/linter/linter.js#L854
+ get column(): number {
+ return this.location.start.column;
+ }
+}
diff --git a/packages/typescript-estree/src/index.ts b/packages/typescript-estree/src/index.ts
index 39e921e8762a..bd18dc68e8b9 100644
--- a/packages/typescript-estree/src/index.ts
+++ b/packages/typescript-estree/src/index.ts
@@ -1,23 +1,14 @@
-export * from './clear-caches';
-export * from './create-program/getScriptKind';
-export { getCanonicalFileName } from './create-program/shared';
-export { createProgramFromConfigFile as createProgram } from './create-program/useProvidedPrograms';
+export * from './ast-converter';
+export * from './errors';
export * from './getModifiers';
-export { TSError } from './node-utils';
-export {
- type AST,
- parse,
- parseAndGenerateServices,
- type ParseAndGenerateServicesResult,
-} from './parser';
export type {
- ParserServices,
- ParserServicesWithoutTypeInformation,
- ParserServicesWithTypeInformation,
- TSESTreeOptions,
-} from './parser-options';
+ ASTMaps,
+ ParserServicesNodeMaps,
+ ParserWeakMap,
+ ParserWeakMapESTreeToTSNode,
+} from './node-maps';
+export type { TSESTreeOptions } from './parser-options';
export { simpleTraverse } from './simple-traverse';
export * from './ts-estree';
export { typescriptVersionIsAtLeast } from './version-check';
export { version } from './version';
-export { withoutProjectParserOptions } from './withoutProjectParserOptions';
diff --git a/packages/typescript-estree/src/node-maps.ts b/packages/typescript-estree/src/node-maps.ts
new file mode 100644
index 000000000000..ce882838def1
--- /dev/null
+++ b/packages/typescript-estree/src/node-maps.ts
@@ -0,0 +1,27 @@
+import type { TSESTree, TSESTreeToTSNode, TSNode, TSToken } from './ts-estree';
+
+// This lets us use generics to type the return value, and removes the need to
+// handle the undefined type in the get method
+export interface ParserWeakMap {
+ // This is unsafe internally, so it should only be exposed via safe wrappers.
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
+ get(key: Key): Value;
+ has(key: unknown): boolean;
+}
+
+export interface ParserWeakMapESTreeToTSNode<
+ Key extends TSESTree.Node = TSESTree.Node,
+> {
+ get(key: KeyBase): TSESTreeToTSNode;
+ has(key: unknown): boolean;
+}
+
+export interface ASTMaps {
+ esTreeNodeToTSNodeMap: ParserWeakMapESTreeToTSNode;
+ tsNodeToESTreeNodeMap: ParserWeakMap;
+}
+
+export interface ParserServicesNodeMaps {
+ esTreeNodeToTSNodeMap: ParserWeakMapESTreeToTSNode;
+ tsNodeToESTreeNodeMap: ParserWeakMap;
+}
diff --git a/packages/typescript-estree/src/node-utils.ts b/packages/typescript-estree/src/node-utils.ts
index f2f60c777bd1..d3e8a55314ae 100644
--- a/packages/typescript-estree/src/node-utils.ts
+++ b/packages/typescript-estree/src/node-utils.ts
@@ -653,61 +653,6 @@ export function convertTokens(ast: ts.SourceFile): TSESTree.Token[] {
return result;
}
-export class TSError extends Error {
- constructor(
- message: string,
- public readonly fileName: string,
- public readonly location: {
- end: {
- column: number;
- line: number;
- offset: number;
- };
- start: {
- column: number;
- line: number;
- offset: number;
- };
- },
- ) {
- super(message);
- Object.defineProperty(this, 'name', {
- configurable: true,
- enumerable: false,
- value: new.target.name,
- });
- }
-
- // For old version of ESLint https://github.com/typescript-eslint/typescript-eslint/pull/6556#discussion_r1123237311
- get index(): number {
- return this.location.start.offset;
- }
-
- // https://github.com/eslint/eslint/blob/b09a512107249a4eb19ef5a37b0bd672266eafdb/lib/linter/linter.js#L853
- get lineNumber(): number {
- return this.location.start.line;
- }
-
- // https://github.com/eslint/eslint/blob/b09a512107249a4eb19ef5a37b0bd672266eafdb/lib/linter/linter.js#L854
- get column(): number {
- return this.location.start.column;
- }
-}
-
-export function createError(
- message: string,
- ast: ts.SourceFile,
- startIndex: number,
- endIndex: number = startIndex,
-): TSError {
- const [start, end] = [startIndex, endIndex].map(offset => {
- const { character: column, line } =
- ast.getLineAndCharacterOfPosition(offset);
- return { column, line: line + 1, offset };
- });
- return new TSError(message, ast.fileName, { end, start });
-}
-
export function nodeHasIllegalDecorators(
node: ts.Node,
): node is { illegalDecorators: ts.Node[] } & ts.Node {
diff --git a/packages/typescript-estree/src/parser-options.ts b/packages/typescript-estree/src/parser-options.ts
index d3f8c8649fc5..f0de6791aaa6 100644
--- a/packages/typescript-estree/src/parser-options.ts
+++ b/packages/typescript-estree/src/parser-options.ts
@@ -7,8 +7,6 @@ import type {
} from '@typescript-eslint/types';
import type * as ts from 'typescript';
-import type { TSESTree, TSESTreeToTSNode, TSNode, TSToken } from './ts-estree';
-
export type { ProjectServiceOptions } from '@typescript-eslint/types';
//github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com///github.com//
@@ -220,44 +218,3 @@ interface ParseAndGenerateServicesOptions extends ParseOptions {
}
export type TSESTreeOptions = ParseAndGenerateServicesOptions;
-
-// This lets us use generics to type the return value, and removes the need to
-// handle the undefined type in the get method
-export interface ParserWeakMap {
- // This is unsafe internally, so it should only be exposed via safe wrappers.
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
- get(key: Key): Value;
- has(key: unknown): boolean;
-}
-
-export interface ParserWeakMapESTreeToTSNode<
- Key extends TSESTree.Node = TSESTree.Node,
-> {
- get(key: KeyBase): TSESTreeToTSNode;
- has(key: unknown): boolean;
-}
-
-export interface ParserServicesBase {
- emitDecoratorMetadata: boolean | undefined;
- experimentalDecorators: boolean | undefined;
- isolatedDeclarations: boolean | undefined;
-}
-export interface ParserServicesNodeMaps {
- esTreeNodeToTSNodeMap: ParserWeakMapESTreeToTSNode;
- tsNodeToESTreeNodeMap: ParserWeakMap;
-}
-export interface ParserServicesWithTypeInformation
- extends ParserServicesNodeMaps,
- ParserServicesBase {
- getSymbolAtLocation: (node: TSESTree.Node) => ts.Symbol | undefined;
- getTypeAtLocation: (node: TSESTree.Node) => ts.Type;
- program: ts.Program;
-}
-export interface ParserServicesWithoutTypeInformation
- extends ParserServicesNodeMaps,
- ParserServicesBase {
- program: null;
-}
-export type ParserServices =
- | ParserServicesWithoutTypeInformation
- | ParserServicesWithTypeInformation;
diff --git a/packages/typescript-estree/src/semantic-or-syntactic-errors.ts b/packages/typescript-estree/src/semantic-or-syntactic-errors.ts
index a88a3615d9f8..e24f16c74540 100644
--- a/packages/typescript-estree/src/semantic-or-syntactic-errors.ts
+++ b/packages/typescript-estree/src/semantic-or-syntactic-errors.ts
@@ -1,119 +1,5 @@
-import type {
- Diagnostic,
- DiagnosticWithLocation,
- Program,
- SourceFile,
-} from 'typescript';
-
-import { flattenDiagnosticMessageText, sys } from 'typescript';
+import type { Diagnostic } from 'typescript';
export interface SemanticOrSyntacticError extends Diagnostic {
message: string;
}
-
-/**
- * By default, diagnostics from the TypeScript compiler contain all errors - regardless of whether
- * they are related to generic ECMAScript standards, or TypeScript-specific constructs.
- *
- * Therefore, we filter out all diagnostics, except for the ones we explicitly want to consider when
- * the user opts in to throwing errors on semantic issues.
- */
-export function getFirstSemanticOrSyntacticError(
- program: Program,
- ast: SourceFile,
-): SemanticOrSyntacticError | undefined {
- try {
- const supportedSyntacticDiagnostics = allowlistSupportedDiagnostics(
- program.getSyntacticDiagnostics(ast),
- );
- if (supportedSyntacticDiagnostics.length > 0) {
- return convertDiagnosticToSemanticOrSyntacticError(
- supportedSyntacticDiagnostics[0],
- );
- }
- const supportedSemanticDiagnostics = allowlistSupportedDiagnostics(
- program.getSemanticDiagnostics(ast),
- );
- if (supportedSemanticDiagnostics.length > 0) {
- return convertDiagnosticToSemanticOrSyntacticError(
- supportedSemanticDiagnostics[0],
- );
- }
- return undefined;
- } catch (e) {
- /**
- * TypeScript compiler has certain Debug.fail() statements in, which will cause the diagnostics
- * retrieval above to throw.
- *
- * E.g. from ast-alignment-tests
- * "Debug Failure. Shouldn't ever directly check a JsxOpeningElement"
- *
- * For our current use-cases this is undesired behavior, so we just suppress it
- * and log a warning.
- */
- /* istanbul ignore next */
- console.warn(`Warning From TSC: "${(e as Error).message}`); // eslint-disable-line no-console
- /* istanbul ignore next */
- return undefined;
- }
-}
-
-function allowlistSupportedDiagnostics(
- diagnostics: readonly (Diagnostic | DiagnosticWithLocation)[],
-): readonly (Diagnostic | DiagnosticWithLocation)[] {
- return diagnostics.filter(diagnostic => {
- switch (diagnostic.code) {
- case 1013: // "A rest parameter or binding pattern may not have a trailing comma."
- case 1014: // "A rest parameter must be last in a parameter list."
- case 1044: // "'{0}' modifier cannot appear on a module or namespace element."
- case 1045: // "A '{0}' modifier cannot be used with an interface declaration."
- case 1048: // "A rest parameter cannot have an initializer."
- case 1049: // "A 'set' accessor must have exactly one parameter."
- case 1070: // "'{0}' modifier cannot appear on a type member."
- case 1071: // "'{0}' modifier cannot appear on an index signature."
- case 1085: // "Octal literals are not available when targeting ECMAScript 5 and higher. Use the syntax '{0}'."
- case 1090: // "'{0}' modifier cannot appear on a parameter."
- case 1096: // "An index signature must have exactly one parameter."
- case 1097: // "'{0}' list cannot be empty."
- case 1098: // "Type parameter list cannot be empty."
- case 1099: // "Type argument list cannot be empty."
- case 1117: // "An object literal cannot have multiple properties with the same name in strict mode."
- case 1121: // "Octal literals are not allowed in strict mode."
- case 1123: // "Variable declaration list cannot be empty."
- case 1141: // "String literal expected."
- case 1162: // "An object member cannot be declared optional."
- case 1164: // "Computed property names are not allowed in enums."
- case 1172: // "'extends' clause already seen."
- case 1173: // "'extends' clause must precede 'implements' clause."
- case 1175: // "'implements' clause already seen."
- case 1176: // "Interface declaration cannot have 'implements' clause."
- case 1190: // "The variable declaration of a 'for...of' statement cannot have an initializer."
- case 1196: // "Catch clause variable type annotation must be 'any' or 'unknown' if specified."
- case 1200: // "Line terminator not permitted before arrow."
- case 1206: // "Decorators are not valid here."
- case 1211: // "A class declaration without the 'default' modifier must have a name."
- case 1242: // "'abstract' modifier can only appear on a class, method, or property declaration."
- case 1246: // "An interface property cannot have an initializer."
- case 1255: // "A definite assignment assertion '!' is not permitted in this context."
- case 1308: // "'await' expression is only allowed within an async function."
- case 2364: // "The left-hand side of an assignment expression must be a variable or a property access."
- case 2369: // "A parameter property is only allowed in a constructor implementation."
- case 2452: // "An enum member cannot have a numeric name."
- case 2462: // "A rest element must be last in a destructuring pattern."
- case 8017: // "Octal literal types must use ES2015 syntax. Use the syntax '{0}'."
- case 17012: // "'{0}' is not a valid meta-property for keyword '{1}'. Did you mean '{2}'?"
- case 17013: // "Meta-property '{0}' is only allowed in the body of a function declaration, function expression, or constructor."
- return true;
- }
- return false;
- });
-}
-
-function convertDiagnosticToSemanticOrSyntacticError(
- diagnostic: Diagnostic,
-): SemanticOrSyntacticError {
- return {
- ...diagnostic,
- message: flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine),
- };
-}
diff --git a/packages/typescript-estree/src/use-at-your-own-risk.ts b/packages/typescript-estree/src/use-at-your-own-risk.ts
index 06cc89e1a5ac..89b4e4136e7e 100644
--- a/packages/typescript-estree/src/use-at-your-own-risk.ts
+++ b/packages/typescript-estree/src/use-at-your-own-risk.ts
@@ -1,11 +1,6 @@
// required by website
export * from './ast-converter';
-export * from './create-program/getScriptKind';
-export type { ParseSettings } from './parseSettings';
// required by packages/utils/src/ts-estree.ts
export * from './getModifiers';
export { typescriptVersionIsAtLeast } from './version-check';
-
-// required by packages/type-utils
-export { getCanonicalFileName } from './create-program/shared';
diff --git a/packages/utils/package.json b/packages/utils/package.json
index 9c0a1e6ec872..12d5b7518c4e 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -63,6 +63,7 @@
},
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
+ "@typescript-eslint/parser-services": "8.32.0",
"@typescript-eslint/scope-manager": "8.32.0",
"@typescript-eslint/types": "8.32.0",
"@typescript-eslint/typescript-estree": "8.32.0"
diff --git a/packages/utils/src/eslint-utils/getParserServices.ts b/packages/utils/src/eslint-utils/getParserServices.ts
index 1581638f58d8..51f55a0f9137 100644
--- a/packages/utils/src/eslint-utils/getParserServices.ts
+++ b/packages/utils/src/eslint-utils/getParserServices.ts
@@ -2,7 +2,7 @@ import type * as TSESLint from '../ts-eslint';
import type {
ParserServices,
ParserServicesWithTypeInformation,
-} from '../ts-estree';
+} from '@typescript-eslint/parser-services';
import { parserSeemsToBeTSESLint } from './parserSeemsToBeTSESLint';
diff --git a/packages/utils/src/ts-estree.ts b/packages/utils/src/ts-estree.ts
index 6c61253a1f05..8aca30ad7dbd 100644
--- a/packages/utils/src/ts-estree.ts
+++ b/packages/utils/src/ts-estree.ts
@@ -11,4 +11,4 @@ export type {
ParserServices,
ParserServicesWithoutTypeInformation,
ParserServicesWithTypeInformation,
-} from '@typescript-eslint/typescript-estree';
+} from '@typescript-eslint/parser-services';
diff --git a/packages/utils/tsconfig.build.json b/packages/utils/tsconfig.build.json
index f99a3f7e1b40..726fd5919df0 100644
--- a/packages/utils/tsconfig.build.json
+++ b/packages/utils/tsconfig.build.json
@@ -2,6 +2,9 @@
"extends": "../../tsconfig.build.json",
"compilerOptions": {},
"references": [
+ {
+ "path": "../parser-services/tsconfig.build.json"
+ },
{
"path": "../typescript-estree/tsconfig.build.json"
},
diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json
index bda7a07530ab..bda3cfd7f502 100644
--- a/packages/utils/tsconfig.json
+++ b/packages/utils/tsconfig.json
@@ -3,6 +3,9 @@
"files": [],
"include": [],
"references": [
+ {
+ "path": "../parser-services"
+ },
{
"path": "../typescript-estree"
},
diff --git a/tsconfig.json b/tsconfig.json
index 5a3d4d28b9e8..39cbb87e663c 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -11,6 +11,7 @@
{ "path": "./packages/eslint-plugin-internal" },
{ "path": "./packages/integration-tests" },
{ "path": "./packages/parser" },
+ { "path": "./packages/parser-services" },
{ "path": "./packages/rule-schema-to-typescript-types" },
{ "path": "./packages/rule-tester" },
{ "path": "./packages/scope-manager" },
diff --git a/yarn.lock b/yarn.lock
index 0b52f47c9fe5..86050389977f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5573,10 +5573,27 @@ __metadata:
languageName: unknown
linkType: soft
+"@typescript-eslint/parser-services@8.32.0, @typescript-eslint/parser-services@workspace:packages/parser-services":
+ version: 0.0.0-use.local
+ resolution: "@typescript-eslint/parser-services@workspace:packages/parser-services"
+ dependencies:
+ "@typescript-eslint/typescript-estree": ^8.32.0
+ "@vitest/coverage-v8": ^3.1.2
+ debug: ^4.3.4
+ fast-glob: ^3.3.2
+ is-glob: ^4.0.3
+ prettier: ^3.2.5
+ rimraf: "*"
+ typescript: "*"
+ vitest: ^3.1.2
+ languageName: unknown
+ linkType: soft
+
"@typescript-eslint/parser@8.32.0, @typescript-eslint/parser@workspace:*, @typescript-eslint/parser@workspace:packages/parser":
version: 0.0.0-use.local
resolution: "@typescript-eslint/parser@workspace:packages/parser"
dependencies:
+ "@typescript-eslint/parser-services": 8.32.0
"@typescript-eslint/scope-manager": 8.32.0
"@typescript-eslint/types": 8.32.0
"@typescript-eslint/typescript-estree": 8.32.0
@@ -5752,7 +5769,7 @@ __metadata:
languageName: unknown
linkType: soft
-"@typescript-eslint/typescript-estree@8.32.0, @typescript-eslint/typescript-estree@workspace:*, @typescript-eslint/typescript-estree@workspace:^, @typescript-eslint/typescript-estree@workspace:packages/typescript-estree":
+"@typescript-eslint/typescript-estree@8.32.0, @typescript-eslint/typescript-estree@^8.32.0, @typescript-eslint/typescript-estree@workspace:*, @typescript-eslint/typescript-estree@workspace:^, @typescript-eslint/typescript-estree@workspace:packages/typescript-estree":
version: 0.0.0-use.local
resolution: "@typescript-eslint/typescript-estree@workspace:packages/typescript-estree"
dependencies:
@@ -5761,9 +5778,7 @@ __metadata:
"@typescript-eslint/visitor-keys": 8.32.0
"@vitest/coverage-v8": ^3.1.3
debug: ^4.3.4
- fast-glob: ^3.3.2
glob: "*"
- is-glob: ^4.0.3
minimatch: ^9.0.4
prettier: ^3.2.5
rimraf: "*"
From e44bcfc37f44ff3ffc81e43ec06dcfd222742fb7 Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Sat, 10 May 2025 22:22:58 -0400
Subject: [PATCH 2/3] Package split: types-eslint
---
.../src/rules/member-ordering.ts | 9 +-
.../rules/naming-convention-utils/schema.ts | 18 +-
packages/parser-services/package.json | 1 +
.../src/createParserServices.ts | 2 +-
packages/parser-services/src/index.ts | 1 -
packages/parser-services/src/parser.ts | 2 +-
packages/parser-services/tsconfig.build.json | 3 +
packages/parser-services/tsconfig.json | 3 +
packages/parser/src/index.ts | 8 +-
packages/parser/src/parser.ts | 3 +-
.../src/utils/getRuleOptionsSchema.ts | 2 +-
.../type-utils/src/TypeOrValueSpecifier.ts | 2 +-
packages/type-utils/src/isTypeReadonly.ts | 2 +-
packages/types-eslint/LICENSE | 21 +
packages/types-eslint/README.md | 3 +
packages/types-eslint/package.json | 67 +++
packages/types-eslint/project.json | 16 +
.../src/ts-eslint => types-eslint/src}/AST.ts | 5 +-
.../ts-eslint => types-eslint/src}/Config.ts | 0
.../ts-eslint => types-eslint/src}/ESLint.ts | 0
packages/types-eslint/src/JSONSchema4.ts | 499 +++++++++++++++++
.../ts-eslint => types-eslint/src}/Linter.ts | 1 +
.../ts-eslint => types-eslint/src}/Parser.ts | 3 +-
.../src}/ParserOptions.ts | 0
.../src/ParserServices.ts} | 4 +
.../src}/Processor.ts | 0
.../ts-eslint => types-eslint/src}/Rule.ts | 5 +-
.../src}/RuleTester.ts | 6 +-
.../ts-eslint => types-eslint/src}/Scope.ts | 0
.../src}/SourceCode.ts | 4 +-
.../src}/eslint/ESLintShared.ts | 0
.../src}/eslint/FlatESLint.ts | 1 +
.../src}/eslint/LegacyESLint.ts | 1 +
.../ts-eslint => types-eslint/src}/index.ts | 2 +
packages/types-eslint/tsconfig.build.json | 18 +
packages/types-eslint/tsconfig.json | 19 +
packages/types-eslint/tsconfig.spec.json | 26 +
packages/types-eslint/vitest.config.mts | 26 +
packages/utils/package.json | 1 +
.../eslint-utils/ReferenceTracker.ts | 2 +-
.../ast-utils/eslint-utils/astUtilities.ts | 2 +-
.../ast-utils/eslint-utils/scopeAnalysis.ts | 3 +-
.../src/eslint-utils/InferTypesFromRule.ts | 5 +-
.../utils/src/eslint-utils/RuleCreator.ts | 7 +-
.../src/eslint-utils/getParserServices.ts | 4 +-
packages/utils/src/index.ts | 5 +-
packages/utils/src/json-schema.ts | 520 +-----------------
packages/utils/src/ts-estree.ts | 2 +-
packages/utils/tsconfig.build.json | 3 +
packages/utils/tsconfig.json | 3 +
tsconfig.json | 1 +
yarn.lock | 48 ++
52 files changed, 852 insertions(+), 537 deletions(-)
create mode 100644 packages/types-eslint/LICENSE
create mode 100644 packages/types-eslint/README.md
create mode 100644 packages/types-eslint/package.json
create mode 100644 packages/types-eslint/project.json
rename packages/{utils/src/ts-eslint => types-eslint/src}/AST.ts (76%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/Config.ts (100%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/ESLint.ts (100%)
create mode 100644 packages/types-eslint/src/JSONSchema4.ts
rename packages/{utils/src/ts-eslint => types-eslint/src}/Linter.ts (99%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/Parser.ts (96%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/ParserOptions.ts (100%)
rename packages/{parser-services/src/types.ts => types-eslint/src/ParserServices.ts} (77%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/Processor.ts (100%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/Rule.ts (99%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/RuleTester.ts (97%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/Scope.ts (100%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/SourceCode.ts (98%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/eslint/ESLintShared.ts (100%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/eslint/FlatESLint.ts (98%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/eslint/LegacyESLint.ts (98%)
rename packages/{utils/src/ts-eslint => types-eslint/src}/index.ts (82%)
create mode 100644 packages/types-eslint/tsconfig.build.json
create mode 100644 packages/types-eslint/tsconfig.json
create mode 100644 packages/types-eslint/tsconfig.spec.json
create mode 100644 packages/types-eslint/vitest.config.mts
diff --git a/packages/eslint-plugin/src/rules/member-ordering.ts b/packages/eslint-plugin/src/rules/member-ordering.ts
index 7ae9ec7627cf..5a8e436f4548 100644
--- a/packages/eslint-plugin/src/rules/member-ordering.ts
+++ b/packages/eslint-plugin/src/rules/member-ordering.ts
@@ -1,7 +1,7 @@
// This rule was feature-frozen before we enabled no-property-in-node.
/* eslint-disable eslint-plugin/no-property-in-node */
-import type { JSONSchema, TSESLint, TSESTree } from '@typescript-eslint/utils';
+import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
import naturalCompare from 'natural-compare';
@@ -12,6 +12,7 @@ import {
getNameFromMember,
MemberNameType,
} from '../util';
+import { JSONSchema4 } from '@typescript-eslint/utils/json-schema';
export type MessageIds =
| 'incorrectGroupOrder'
@@ -91,12 +92,12 @@ export type Options = [
},
];
-const neverConfig: JSONSchema.JSONSchema4 = {
+const neverConfig: JSONSchema4 = {
type: 'string',
enum: ['never'],
};
-const arrayConfig = (memberTypes: string): JSONSchema.JSONSchema4 => ({
+const arrayConfig = (memberTypes: string): JSONSchema4 => ({
type: 'array',
items: {
oneOf: [
@@ -113,7 +114,7 @@ const arrayConfig = (memberTypes: string): JSONSchema.JSONSchema4 => ({
},
});
-const objectConfig = (memberTypes: string): JSONSchema.JSONSchema4 => ({
+const objectConfig = (memberTypes: string): JSONSchema4 => ({
type: 'object',
additionalProperties: false,
properties: {
diff --git a/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts b/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts
index 4bd08bb91cd3..dcc0e56a11a6 100644
--- a/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts
+++ b/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts
@@ -1,4 +1,4 @@
-import type { JSONSchema } from '@typescript-eslint/utils';
+import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema';
import type {
IndividualAndMetaSelectorsString,
@@ -15,7 +15,7 @@ import {
UnderscoreOptions,
} from './enums';
-const $DEFS: Record = {
+const $DEFS: Record = {
// enums
predefinedFormats: {
enum: getEnumNames(PredefinedFormats),
@@ -64,16 +64,16 @@ const $DEFS: Record = {
},
};
-const UNDERSCORE_SCHEMA: JSONSchema.JSONSchema4 = {
+const UNDERSCORE_SCHEMA: JSONSchema4 = {
$ref: '#/$defs/underscoreOptions',
};
-const PREFIX_SUFFIX_SCHEMA: JSONSchema.JSONSchema4 = {
+const PREFIX_SUFFIX_SCHEMA: JSONSchema4 = {
$ref: '#/$defs/prefixSuffixConfig',
};
-const MATCH_REGEX_SCHEMA: JSONSchema.JSONSchema4 = {
+const MATCH_REGEX_SCHEMA: JSONSchema4 = {
$ref: '#/$defs/matchRegexConfig',
};
-type JSONSchemaProperties = Record;
+type JSONSchemaProperties = Record;
const FORMAT_OPTIONS_PROPERTIES: JSONSchemaProperties = {
custom: MATCH_REGEX_SCHEMA,
failureMessage: {
@@ -91,7 +91,7 @@ function selectorSchema(
selectorString: IndividualAndMetaSelectorsString,
allowType: boolean,
modifiers?: ModifiersString[],
-): JSONSchema.JSONSchema4[] {
+): JSONSchema4[] {
const selector: JSONSchemaProperties = {
filter: {
oneOf: [
@@ -141,7 +141,7 @@ function selectorSchema(
];
}
-function selectorsSchema(): JSONSchema.JSONSchema4 {
+function selectorsSchema(): JSONSchema4 {
return {
additionalProperties: false,
description: 'Multiple selectors in one config',
@@ -185,7 +185,7 @@ function selectorsSchema(): JSONSchema.JSONSchema4 {
};
}
-export const SCHEMA: JSONSchema.JSONSchema4 = {
+export const SCHEMA: JSONSchema4 = {
$defs: $DEFS,
additionalItems: false,
items: {
diff --git a/packages/parser-services/package.json b/packages/parser-services/package.json
index 3c0a42e07fe5..825b494abf6c 100644
--- a/packages/parser-services/package.json
+++ b/packages/parser-services/package.json
@@ -46,6 +46,7 @@
"check-types": "npx nx typecheck"
},
"dependencies": {
+ "@typescript-eslint/types-eslint": "^8.32.0",
"@typescript-eslint/typescript-estree": "^8.32.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
diff --git a/packages/parser-services/src/createParserServices.ts b/packages/parser-services/src/createParserServices.ts
index 0974be6b1ed7..d6da57c32edb 100644
--- a/packages/parser-services/src/createParserServices.ts
+++ b/packages/parser-services/src/createParserServices.ts
@@ -1,6 +1,6 @@
+import { ParserServices } from '@typescript-eslint/types-eslint';
import { ASTMaps } from '@typescript-eslint/typescript-estree';
import type * as ts from 'typescript';
-import { ParserServices } from './types';
export function createParserServices(
astMaps: ASTMaps,
diff --git a/packages/parser-services/src/index.ts b/packages/parser-services/src/index.ts
index 8b2d2b7f2a37..1a2306afa7a5 100644
--- a/packages/parser-services/src/index.ts
+++ b/packages/parser-services/src/index.ts
@@ -1,6 +1,5 @@
export * from './clear-caches';
export { getCanonicalFileName } from './create-program/shared';
-export type * from './types';
export { createProgramFromConfigFile as createProgram } from './create-program/useProvidedPrograms';
export * from './withoutProjectParserOptions';
export * from './parser';
diff --git a/packages/parser-services/src/parser.ts b/packages/parser-services/src/parser.ts
index 626921fdfb91..6b79c3376501 100644
--- a/packages/parser-services/src/parser.ts
+++ b/packages/parser-services/src/parser.ts
@@ -28,7 +28,7 @@ import type {
TSESTree,
TSESTreeOptions,
} from '@typescript-eslint/typescript-estree';
-import { ParserServices } from './types';
+import { ParserServices } from '@typescript-eslint/types-eslint';
import { getFirstSemanticOrSyntacticError } from './semantic-or-syntactic-errors';
const log = debug('typescript-eslint:parser-services:parser');
diff --git a/packages/parser-services/tsconfig.build.json b/packages/parser-services/tsconfig.build.json
index 241b39d618e6..4c747629e66f 100644
--- a/packages/parser-services/tsconfig.build.json
+++ b/packages/parser-services/tsconfig.build.json
@@ -10,6 +10,9 @@
},
"include": ["src/**/*.ts", "typings"],
"references": [
+ {
+ "path": "../types-eslint/tsconfig.build.json"
+ },
{
"path": "../typescript-estree/tsconfig.build.json"
}
diff --git a/packages/parser-services/tsconfig.json b/packages/parser-services/tsconfig.json
index 4733311e9be9..e5d40828187b 100644
--- a/packages/parser-services/tsconfig.json
+++ b/packages/parser-services/tsconfig.json
@@ -3,6 +3,9 @@
"files": [],
"include": [],
"references": [
+ {
+ "path": "../types-eslint"
+ },
{
"path": "../typescript-estree"
},
diff --git a/packages/parser/src/index.ts b/packages/parser/src/index.ts
index db293b5b4762..9bb87e85c34d 100644
--- a/packages/parser/src/index.ts
+++ b/packages/parser/src/index.ts
@@ -1,8 +1,10 @@
+export type {
+ ParserServices,
+ ParserServicesWithoutTypeInformation,
+ ParserServicesWithTypeInformation,
+} from '@typescript-eslint/types-eslint';
export { parse, parseForESLint, type ParserOptions } from './parser';
export {
- type ParserServices,
- type ParserServicesWithoutTypeInformation,
- type ParserServicesWithTypeInformation,
clearCaches,
createProgram,
withoutProjectParserOptions,
diff --git a/packages/parser/src/parser.ts b/packages/parser/src/parser.ts
index 85cea7348102..d8a9dd3a2a6a 100644
--- a/packages/parser/src/parser.ts
+++ b/packages/parser/src/parser.ts
@@ -1,7 +1,8 @@
+import type { ParserServices } from '@typescript-eslint/types-eslint';
+
import {
AST,
parseAndGenerateServices,
- type ParserServices,
} from '@typescript-eslint/parser-services';
import type {
AnalyzeOptions,
diff --git a/packages/rule-tester/src/utils/getRuleOptionsSchema.ts b/packages/rule-tester/src/utils/getRuleOptionsSchema.ts
index f5977c95c8c8..c461983f3b7e 100644
--- a/packages/rule-tester/src/utils/getRuleOptionsSchema.ts
+++ b/packages/rule-tester/src/utils/getRuleOptionsSchema.ts
@@ -1,6 +1,6 @@
// Forked from https://github.com/eslint/eslint/blob/ad9dd6a933fd098a0d99c6a9aa059850535c23ee/lib/shared/config-validator.js#LL50-L82C2
-import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema';
+import type { JSONSchema4 } from '@typescript-eslint/types-eslint';
import type { AnyRuleModule } from '@typescript-eslint/utils/ts-eslint';
import { isReadonlyArray } from './isReadonlyArray';
diff --git a/packages/type-utils/src/TypeOrValueSpecifier.ts b/packages/type-utils/src/TypeOrValueSpecifier.ts
index 4c8f1211a8be..fd2ea56fdbaa 100644
--- a/packages/type-utils/src/TypeOrValueSpecifier.ts
+++ b/packages/type-utils/src/TypeOrValueSpecifier.ts
@@ -1,4 +1,4 @@
-import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema';
+import type { JSONSchema4 } from '@typescript-eslint/types-eslint';
import type * as ts from 'typescript';
import * as tsutils from 'ts-api-utils';
diff --git a/packages/type-utils/src/isTypeReadonly.ts b/packages/type-utils/src/isTypeReadonly.ts
index c874a60f164a..c27d57024cc3 100644
--- a/packages/type-utils/src/isTypeReadonly.ts
+++ b/packages/type-utils/src/isTypeReadonly.ts
@@ -1,4 +1,4 @@
-import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema';
+import type { JSONSchema4 } from '@typescript-eslint/types-eslint';
import { ESLintUtils } from '@typescript-eslint/utils';
import * as tsutils from 'ts-api-utils';
diff --git a/packages/types-eslint/LICENSE b/packages/types-eslint/LICENSE
new file mode 100644
index 000000000000..310a18f8a6cb
--- /dev/null
+++ b/packages/types-eslint/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 typescript-eslint and other contributors
+
+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.
diff --git a/packages/types-eslint/README.md b/packages/types-eslint/README.md
new file mode 100644
index 000000000000..663b7917077b
--- /dev/null
+++ b/packages/types-eslint/README.md
@@ -0,0 +1,3 @@
+# `@typescript-eslint/types-eslint`
+
+TODO
diff --git a/packages/types-eslint/package.json b/packages/types-eslint/package.json
new file mode 100644
index 000000000000..12c765cae708
--- /dev/null
+++ b/packages/types-eslint/package.json
@@ -0,0 +1,67 @@
+{
+ "name": "@typescript-eslint/types-eslint",
+ "version": "8.32.0",
+ "description": "TODO",
+ "files": [
+ "dist",
+ "!*.tsbuildinfo",
+ "package.json",
+ "README.md",
+ "LICENSE"
+ ],
+ "type": "commonjs",
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "types": "./dist/index.d.ts",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/typescript-eslint/typescript-eslint.git",
+ "directory": "packages/types-eslint"
+ },
+ "bugs": {
+ "url": "https://github.com/typescript-eslint/typescript-eslint/issues"
+ },
+ "homepage": "https://typescript-eslint.io/packages/types-eslint",
+ "license": "MIT",
+ "keywords": [
+ "eslint",
+ "typescript",
+ "estree"
+ ],
+ "scripts": {
+ "build": "tsc -b tsconfig.build.json",
+ "clean": "rimraf dist/ coverage/",
+ "clean-fixtures": "rimraf -g \"./src/**/fixtures/**/snapshots\"",
+ "format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
+ "generate-lib": "npx nx generate-lib repo",
+ "lint": "npx nx lint",
+ "test": "vitest --run --config=$INIT_CWD/vitest.config.mts",
+ "check-types": "npx nx typecheck"
+ },
+ "dependencies": {
+ "@typescript-eslint/types": "8.32.0",
+ "@typescript-eslint/visitor-keys": "8.32.0"
+ },
+ "devDependencies": {
+ "@typescript-eslint/typescript-estree": "8.32.0",
+ "@vitest/coverage-v8": "^3.1.2",
+ "@vitest/pretty-format": "^3.1.2",
+ "glob": "*",
+ "prettier": "^3.2.5",
+ "rimraf": "*",
+ "typescript": "*",
+ "vitest": "^3.1.2"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+}
diff --git a/packages/types-eslint/project.json b/packages/types-eslint/project.json
new file mode 100644
index 000000000000..8dda0be79656
--- /dev/null
+++ b/packages/types-eslint/project.json
@@ -0,0 +1,16 @@
+{
+ "name": "types-eslint",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "root": "packages/types-eslint",
+ "sourceRoot": "packages/types-eslint/src",
+ "projectType": "library",
+ "targets": {
+ "lint": {
+ "executor": "@nx/eslint:lint",
+ "outputs": ["{options.outputFile}"]
+ },
+ "test": {
+ "executor": "@nx/vite:test"
+ }
+ }
+}
diff --git a/packages/utils/src/ts-eslint/AST.ts b/packages/types-eslint/src/AST.ts
similarity index 76%
rename from packages/utils/src/ts-eslint/AST.ts
rename to packages/types-eslint/src/AST.ts
index cc4a74f4f038..ad6d0752ea59 100644
--- a/packages/utils/src/ts-eslint/AST.ts
+++ b/packages/types-eslint/src/AST.ts
@@ -1,6 +1,9 @@
/* eslint-disable @typescript-eslint/no-namespace, no-restricted-syntax */
-import type { AST_TOKEN_TYPES, TSESTree } from '../ts-estree';
+import type {
+ AST_TOKEN_TYPES,
+ TSESTree,
+} from '@typescript-eslint/typescript-estree';
namespace AST {
export type TokenType = AST_TOKEN_TYPES;
diff --git a/packages/utils/src/ts-eslint/Config.ts b/packages/types-eslint/src/Config.ts
similarity index 100%
rename from packages/utils/src/ts-eslint/Config.ts
rename to packages/types-eslint/src/Config.ts
diff --git a/packages/utils/src/ts-eslint/ESLint.ts b/packages/types-eslint/src/ESLint.ts
similarity index 100%
rename from packages/utils/src/ts-eslint/ESLint.ts
rename to packages/types-eslint/src/ESLint.ts
diff --git a/packages/types-eslint/src/JSONSchema4.ts b/packages/types-eslint/src/JSONSchema4.ts
new file mode 100644
index 000000000000..b188a25a372e
--- /dev/null
+++ b/packages/types-eslint/src/JSONSchema4.ts
@@ -0,0 +1,499 @@
+// TODO: Maybe put these in a separate package too, while we're at it?
+
+/**
+ * This is a fork of https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13f63c2eb8d7479caf01ab8d72f9e3683368a8f5/types/json-schema/index.d.ts
+ * We intentionally fork this because:
+ * - ESLint ***ONLY*** supports JSONSchema v4
+ * - We want to provide stricter types
+ */
+
+//==================================================================================================
+// JSON Schema Draft 04
+//==================================================================================================
+
+/**
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1
+ */
+export type JSONSchema4TypeName =
+ | 'any'
+ | 'array'
+ | 'boolean'
+ | 'integer'
+ | 'null'
+ | 'number'
+ | 'object'
+ | 'string';
+
+/**
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-04#section-3.5
+ */
+export type JSONSchema4Type = boolean | number | string | null;
+
+export type JSONSchema4TypeExtended =
+ | JSONSchema4Array
+ | JSONSchema4Object
+ | JSONSchema4Type;
+
+export interface JSONSchema4Object {
+ [key: string]: JSONSchema4TypeExtended;
+}
+
+// Workaround for infinite type recursion
+// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540
+// eslint-disable-next-line @typescript-eslint/no-empty-object-type
+export interface JSONSchema4Array extends Array {}
+
+/**
+ * Meta schema
+ *
+ * Recommended values:
+ * - 'http://json-schema.org/schema#'
+ * - 'http://json-schema.org/hyper-schema#'
+ * - 'http://json-schema.org/draft-04/schema#'
+ * - 'http://json-schema.org/draft-04/hyper-schema#'
+ * - 'http://json-schema.org/draft-03/schema#'
+ * - 'http://json-schema.org/draft-03/hyper-schema#'
+ *
+ * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-5
+ */
+export type JSONSchema4Version = string;
+
+/**
+ * JSON Schema V4
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-04
+ */
+export type JSONSchema4 =
+ | JSONSchema4AllOfSchema
+ | JSONSchema4AnyOfSchema
+ | JSONSchema4AnySchema
+ | JSONSchema4ArraySchema
+ | JSONSchema4BooleanSchema
+ | JSONSchema4MultiSchema
+ | JSONSchema4NullSchema
+ | JSONSchema4NumberSchema
+ | JSONSchema4ObjectSchema
+ | JSONSchema4OneOfSchema
+ | JSONSchema4RefSchema
+ | JSONSchema4StringSchema;
+
+interface JSONSchema4Base {
+ /**
+ * Reusable definitions that can be referenced via `$ref`
+ */
+ $defs?: Record | undefined;
+
+ /**
+ * Path to a schema defined in `definitions`/`$defs` that will form the base
+ * for this schema.
+ *
+ * If you are defining an "array" schema (`schema: [ ... ]`) for your rule
+ * then you should prefix this with `items/0` so that the validator can find
+ * your definitions.
+ *
+ * eg: `'#/items/0/definitions/myDef'`
+ *
+ * Otherwise if you are defining an "object" schema (`schema: { ... }`) for
+ * your rule you can directly reference your definitions
+ *
+ * eg: `'#/definitions/myDef'`
+ */
+ $ref?: string | undefined;
+
+ $schema?: JSONSchema4Version | undefined;
+
+ /**
+ * (AND) Must be valid against all of the sub-schemas
+ */
+ allOf?: JSONSchema4[] | undefined;
+
+ /**
+ * (OR) Must be valid against any of the sub-schemas
+ */
+ anyOf?: JSONSchema4[] | undefined;
+
+ /**
+ * The default value for the item if not present
+ */
+ default?: JSONSchema4TypeExtended | undefined;
+
+ /**
+ * Reusable definitions that can be referenced via `$ref`
+ */
+ definitions?: Record | undefined;
+
+ /**
+ * This attribute is a string that provides a full description of the of
+ * purpose the instance property.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.22
+ */
+ description?: string | undefined;
+
+ /**
+ * The value of this property MUST be another schema which will provide
+ * a base schema which the current schema will inherit from. The
+ * inheritance rules are such that any instance that is valid according
+ * to the current schema MUST be valid according to the referenced
+ * schema. This MAY also be an array, in which case, the instance MUST
+ * be valid for all the schemas in the array. A schema that extends
+ * another schema MAY define additional attributes, constrain existing
+ * attributes, or add other constraints.
+ *
+ * Conceptually, the behavior of extends can be seen as validating an
+ * instance against all constraints in the extending schema as well as
+ * the extended schema(s).
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.26
+ */
+ extends?: string | string[] | undefined;
+
+ id?: string | undefined;
+
+ /**
+ * (NOT) Must not be valid against the given schema
+ */
+ not?: JSONSchema4 | undefined;
+
+ /**
+ * (XOR) Must be valid against exactly one of the sub-schemas
+ */
+ oneOf?: JSONSchema4[] | undefined;
+
+ /**
+ * This attribute indicates if the instance must have a value, and not
+ * be undefined. This is false by default, making the instance
+ * optional.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.7
+ */
+ required?: boolean | string[] | undefined;
+
+ /**
+ * This attribute is a string that provides a short description of the
+ * instance property.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.21
+ */
+ title?: string | undefined;
+
+ /**
+ * A single type, or a union of simple types
+ */
+ type?: JSONSchema4TypeName | JSONSchema4TypeName[] | undefined;
+}
+
+export interface JSONSchema4RefSchema extends JSONSchema4Base {
+ $ref: string;
+ type?: undefined;
+}
+
+export interface JSONSchema4AllOfSchema extends JSONSchema4Base {
+ allOf: JSONSchema4[];
+ type?: undefined;
+}
+
+export interface JSONSchema4AnyOfSchema extends JSONSchema4Base {
+ anyOf: JSONSchema4[];
+ type?: undefined;
+}
+
+export interface JSONSchema4OneOfSchema extends JSONSchema4Base {
+ oneOf: JSONSchema4[];
+ type?: undefined;
+}
+
+export interface JSONSchema4MultiSchema
+ extends Omit,
+ Omit,
+ Omit,
+ Omit,
+ Omit,
+ Omit,
+ Omit {
+ /**
+ * This provides an enumeration of all possible values that are valid
+ * for the instance property. This MUST be an array, and each item in
+ * the array represents a possible value for the instance value. If
+ * this attribute is defined, the instance value MUST be one of the
+ * values in the array in order for the schema to be valid.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
+ */
+ enum?: JSONSchema4Type[];
+ type: JSONSchema4TypeName[];
+}
+
+/**
+ * @see https://json-schema.org/understanding-json-schema/reference/object.html
+ */
+export interface JSONSchema4ObjectSchema extends JSONSchema4Base {
+ /**
+ * This attribute defines a schema for all properties that are not
+ * explicitly defined in an object type definition. If specified, the
+ * value MUST be a schema or a boolean. If false is provided, no
+ * additional properties are allowed beyond the properties defined in
+ * the schema. The default value is an empty schema which allows any
+ * value for additional properties.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.4
+ */
+ additionalProperties?: boolean | JSONSchema4 | undefined;
+
+ /**
+ * The `dependencies` keyword conditionally applies a sub-schema when a given
+ * property is present. This schema is applied in the same way `allOf` applies
+ * schemas. Nothing is merged or extended. Both schemas apply independently.
+ */
+ dependencies?: Record | undefined;
+
+ /**
+ * The maximum number of properties allowed for record-style schemas
+ */
+ maxProperties?: number | undefined;
+
+ /**
+ * The minimum number of properties required for record-style schemas
+ */
+ minProperties?: number | undefined;
+
+ /**
+ * This attribute is an object that defines the schema for a set of
+ * property names of an object instance. The name of each property of
+ * this attribute's object is a regular expression pattern in the ECMA
+ * 262/Perl 5 format, while the value is a schema. If the pattern
+ * matches the name of a property on the instance object, the value of
+ * the instance's property MUST be valid against the pattern name's
+ * schema value.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.3
+ */
+ patternProperties?: Record | undefined;
+
+ /**
+ * This attribute is an object with property definitions that define the
+ * valid values of instance object property values. When the instance
+ * value is an object, the property values of the instance object MUST
+ * conform to the property definitions in this object. In this object,
+ * each property definition's value MUST be a schema, and the property's
+ * name MUST be the name of the instance property that it defines. The
+ * instance property value MUST be valid according to the schema from
+ * the property definition. Properties are considered unordered, the
+ * order of the instance properties MAY be in any order.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.2
+ */
+ properties?: Record | undefined;
+
+ type: 'object';
+}
+
+/**
+ * @see https://json-schema.org/understanding-json-schema/reference/array.html
+ */
+export interface JSONSchema4ArraySchema extends JSONSchema4Base {
+ /**
+ * May only be defined when "items" is defined, and is a tuple of JSONSchemas.
+ *
+ * This provides a definition for additional items in an array instance
+ * when tuple definitions of the items is provided. This can be false
+ * to indicate additional items in the array are not allowed, or it can
+ * be a schema that defines the schema of the additional items.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.6
+ */
+ additionalItems?: boolean | JSONSchema4 | undefined;
+
+ /**
+ * This attribute defines the allowed items in an instance array, and
+ * MUST be a schema or an array of schemas. The default value is an
+ * empty schema which allows any value for items in the instance array.
+ *
+ * When this attribute value is a schema and the instance value is an
+ * array, then all the items in the array MUST be valid according to the
+ * schema.
+ *
+ * When this attribute value is an array of schemas and the instance
+ * value is an array, each position in the instance array MUST conform
+ * to the schema in the corresponding position for this array. This
+ * called tuple typing. When tuple typing is used, additional items are
+ * allowed, disallowed, or constrained by the "additionalItems"
+ * (Section 5.6) attribute using the same rules as
+ * "additionalProperties" (Section 5.4) for objects.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.5
+ */
+ items?: JSONSchema4 | JSONSchema4[] | undefined;
+
+ /**
+ * Defines the maximum length of an array
+ */
+ maxItems?: number | undefined;
+
+ /**
+ * Defines the minimum length of an array
+ */
+ minItems?: number | undefined;
+
+ type: 'array';
+
+ /**
+ * Enforces that all items in the array are unique
+ */
+ uniqueItems?: boolean | undefined;
+}
+
+/**
+ * @see https://json-schema.org/understanding-json-schema/reference/string.html
+ */
+export interface JSONSchema4StringSchema extends JSONSchema4Base {
+ enum?: string[] | undefined;
+
+ /**
+ * The `format` keyword allows for basic semantic identification of certain
+ * kinds of string values that are commonly used.
+ *
+ * For example, because JSON doesn’t have a “DateTime” type, dates need to be
+ * encoded as strings. `format` allows the schema author to indicate that the
+ * string value should be interpreted as a date.
+ *
+ * ajv v6 provides a few built-in formats - all other strings will cause AJV
+ * to throw during schema compilation
+ */
+ format?:
+ | 'date'
+ | 'date-time'
+ | 'email'
+ | 'hostname'
+ | 'ipv4'
+ | 'ipv6'
+ | 'json-pointer'
+ | 'json-pointer-uri-fragment'
+ | 'regex'
+ | 'relative-json-pointer'
+ | 'time'
+ | 'uri'
+ | 'uri-reference'
+ | 'uri-template'
+ | 'url'
+ | 'uuid'
+ | undefined;
+
+ /**
+ * The maximum allowed length for the string
+ */
+ maxLength?: number | undefined;
+
+ /**
+ * The minimum allowed length for the string
+ */
+ minLength?: number | undefined;
+
+ /**
+ * The `pattern` keyword is used to restrict a string to a particular regular
+ * expression. The regular expression syntax is the one defined in JavaScript
+ * (ECMA 262 specifically) with Unicode support.
+ *
+ * When defining the regular expressions, it’s important to note that the
+ * string is considered valid if the expression matches anywhere within the
+ * string. For example, the regular expression "p" will match any string with
+ * a p in it, such as "apple" not just a string that is simply "p". Therefore,
+ * it is usually less confusing, as a matter of course, to surround the
+ * regular expression in ^...$, for example, "^p$", unless there is a good
+ * reason not to do so.
+ */
+ pattern?: string | undefined;
+
+ type: 'string';
+}
+
+/**
+ * @see https://json-schema.org/understanding-json-schema/reference/numeric.html
+ */
+export interface JSONSchema4NumberSchema extends JSONSchema4Base {
+ /**
+ * This provides an enumeration of all possible values that are valid
+ * for the instance property. This MUST be an array, and each item in
+ * the array represents a possible value for the instance value. If
+ * this attribute is defined, the instance value MUST be one of the
+ * values in the array in order for the schema to be valid.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
+ */
+ enum?: number[] | undefined;
+
+ /**
+ * The exclusive minimum allowed value for the number
+ * - `true` = `x < maximum`
+ * - `false` = `x <= maximum`
+ *
+ * Default is `false`
+ */
+ exclusiveMaximum?: boolean | undefined;
+
+ /**
+ * Indicates whether or not `minimum` is the inclusive or exclusive minimum
+ * - `true` = `x > minimum`
+ * - `false` = `x ≥ minimum`
+ *
+ * Default is `false`
+ */
+ exclusiveMinimum?: boolean | undefined;
+
+ /**
+ * The maximum allowed value for the number
+ */
+ maximum?: number | undefined;
+
+ /**
+ * The minimum allowed value for the number
+ */
+ minimum?: number | undefined;
+
+ /**
+ * Numbers can be restricted to a multiple of a given number, using the
+ * `multipleOf` keyword. It may be set to any positive number.
+ */
+ multipleOf?: number | undefined;
+
+ type: 'integer' | 'number';
+}
+
+/**
+ * @see https://json-schema.org/understanding-json-schema/reference/boolean.html
+ */
+export interface JSONSchema4BooleanSchema extends JSONSchema4Base {
+ /**
+ * This provides an enumeration of all possible values that are valid
+ * for the instance property. This MUST be an array, and each item in
+ * the array represents a possible value for the instance value. If
+ * this attribute is defined, the instance value MUST be one of the
+ * values in the array in order for the schema to be valid.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
+ */
+ enum?: boolean[] | undefined;
+
+ type: 'boolean';
+}
+
+/**
+ * @see https://json-schema.org/understanding-json-schema/reference/null.html
+ */
+export interface JSONSchema4NullSchema extends JSONSchema4Base {
+ /**
+ * This provides an enumeration of all possible values that are valid
+ * for the instance property. This MUST be an array, and each item in
+ * the array represents a possible value for the instance value. If
+ * this attribute is defined, the instance value MUST be one of the
+ * values in the array in order for the schema to be valid.
+ *
+ * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
+ */
+ enum?: null[] | undefined;
+
+ type: 'null';
+}
+
+export interface JSONSchema4AnySchema extends JSONSchema4Base {
+ type: 'any';
+}
diff --git a/packages/utils/src/ts-eslint/Linter.ts b/packages/types-eslint/src/Linter.ts
similarity index 99%
rename from packages/utils/src/ts-eslint/Linter.ts
rename to packages/types-eslint/src/Linter.ts
index 499213d95f3b..02203816a771 100644
--- a/packages/utils/src/ts-eslint/Linter.ts
+++ b/packages/types-eslint/src/Linter.ts
@@ -316,6 +316,7 @@ namespace Linter {
* simply parses and reports on the code. In particular, the Linter object does not process configuration objects
* or files.
*/
+// @ts-expect-error -- TODO: I don't know why this is now needed...
class Linter extends (ESLintLinter as typeof LinterBase) {}
export { Linter };
diff --git a/packages/utils/src/ts-eslint/Parser.ts b/packages/types-eslint/src/Parser.ts
similarity index 96%
rename from packages/utils/src/ts-eslint/Parser.ts
rename to packages/types-eslint/src/Parser.ts
index ad9f5763054f..193966ac9b29 100644
--- a/packages/utils/src/ts-eslint/Parser.ts
+++ b/packages/types-eslint/src/Parser.ts
@@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-namespace */
-import type { ParserServices, TSESTree } from '../ts-estree';
+import type { TSESTree } from '@typescript-eslint/typescript-estree';
import type { ParserOptions } from './ParserOptions';
import type { Scope } from './Scope';
+import { ParserServices } from './ParserServices';
export namespace Parser {
export interface ParserMeta {
diff --git a/packages/utils/src/ts-eslint/ParserOptions.ts b/packages/types-eslint/src/ParserOptions.ts
similarity index 100%
rename from packages/utils/src/ts-eslint/ParserOptions.ts
rename to packages/types-eslint/src/ParserOptions.ts
diff --git a/packages/parser-services/src/types.ts b/packages/types-eslint/src/ParserServices.ts
similarity index 77%
rename from packages/parser-services/src/types.ts
rename to packages/types-eslint/src/ParserServices.ts
index 7c31e060fb10..8facb6cdb0a8 100644
--- a/packages/parser-services/src/types.ts
+++ b/packages/types-eslint/src/ParserServices.ts
@@ -4,6 +4,10 @@ import {
} from '@typescript-eslint/typescript-estree';
import ts from 'typescript';
+// NOTE: These types are intentionally in types-eslint, not parser-services,
+// so that packages such as rule-creator can refer to them without taking a full
+// dependency on all the runtime logic & dependencies of parser-services.
+
export interface ParserServicesBase {
emitDecoratorMetadata: boolean | undefined;
experimentalDecorators: boolean | undefined;
diff --git a/packages/utils/src/ts-eslint/Processor.ts b/packages/types-eslint/src/Processor.ts
similarity index 100%
rename from packages/utils/src/ts-eslint/Processor.ts
rename to packages/types-eslint/src/Processor.ts
diff --git a/packages/utils/src/ts-eslint/Rule.ts b/packages/types-eslint/src/Rule.ts
similarity index 99%
rename from packages/utils/src/ts-eslint/Rule.ts
rename to packages/types-eslint/src/Rule.ts
index 35cd1c7f7a0c..5ab1df864ebc 100644
--- a/packages/utils/src/ts-eslint/Rule.ts
+++ b/packages/types-eslint/src/Rule.ts
@@ -1,10 +1,11 @@
-import type { JSONSchema4 } from '../json-schema';
-import type { ParserServices, TSESTree } from '../ts-estree';
+import type { TSESTree } from '@typescript-eslint/typescript-estree';
import type { AST } from './AST';
import type { FlatConfig } from './Config';
import type { Linter } from './Linter';
import type { Scope } from './Scope';
import type { SourceCode } from './SourceCode';
+import { JSONSchema4 } from './JSONSchema4';
+import { ParserServices } from './ParserServices';
export type RuleRecommendation = 'recommended' | 'strict' | 'stylistic';
diff --git a/packages/utils/src/ts-eslint/RuleTester.ts b/packages/types-eslint/src/RuleTester.ts
similarity index 97%
rename from packages/utils/src/ts-eslint/RuleTester.ts
rename to packages/types-eslint/src/RuleTester.ts
index 409baf2a08a4..a0a60d535c79 100644
--- a/packages/utils/src/ts-eslint/RuleTester.ts
+++ b/packages/types-eslint/src/RuleTester.ts
@@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/no-deprecated */
import { RuleTester as ESLintRuleTester } from 'eslint';
-import type { AST_NODE_TYPES, AST_TOKEN_TYPES } from '../ts-estree';
import type { ClassicConfig } from './Config';
import type { Linter } from './Linter';
import type { ParserOptions } from './ParserOptions';
@@ -11,6 +10,10 @@ import type {
RuleModule,
SharedConfigurationSettings,
} from './Rule';
+import {
+ AST_NODE_TYPES,
+ AST_TOKEN_TYPES,
+} from '@typescript-eslint/typescript-estree';
/**
* @deprecated Use `@typescript-eslint/rule-tester` instead.
@@ -226,4 +229,5 @@ declare class RuleTesterBase {
/**
* @deprecated Use `@typescript-eslint/rule-tester` instead.
*/
+// @ts-expect-error -- TODO: I don't know why this is now needed...
export class RuleTester extends (ESLintRuleTester as typeof RuleTesterBase) {}
diff --git a/packages/utils/src/ts-eslint/Scope.ts b/packages/types-eslint/src/Scope.ts
similarity index 100%
rename from packages/utils/src/ts-eslint/Scope.ts
rename to packages/types-eslint/src/Scope.ts
diff --git a/packages/utils/src/ts-eslint/SourceCode.ts b/packages/types-eslint/src/SourceCode.ts
similarity index 98%
rename from packages/utils/src/ts-eslint/SourceCode.ts
rename to packages/types-eslint/src/SourceCode.ts
index f4afb79f2dad..64c4a27180c2 100644
--- a/packages/utils/src/ts-eslint/SourceCode.ts
+++ b/packages/types-eslint/src/SourceCode.ts
@@ -2,9 +2,10 @@
import { SourceCode as ESLintSourceCode } from 'eslint';
-import type { ParserServices, TSESTree } from '../ts-estree';
+import type { TSESTree } from '@typescript-eslint/typescript-estree';
import type { Parser } from './Parser';
import type { Scope } from './Scope';
+import { ParserServices } from './ParserServices';
declare class TokenStore {
/**
@@ -451,6 +452,7 @@ namespace SourceCode {
| FilterPredicate;
}
+// @ts-expect-error -- TODO: I don't know why this is now needed...
class SourceCode extends (ESLintSourceCode as typeof SourceCodeBase) {}
export { SourceCode };
diff --git a/packages/utils/src/ts-eslint/eslint/ESLintShared.ts b/packages/types-eslint/src/eslint/ESLintShared.ts
similarity index 100%
rename from packages/utils/src/ts-eslint/eslint/ESLintShared.ts
rename to packages/types-eslint/src/eslint/ESLintShared.ts
diff --git a/packages/utils/src/ts-eslint/eslint/FlatESLint.ts b/packages/types-eslint/src/eslint/FlatESLint.ts
similarity index 98%
rename from packages/utils/src/ts-eslint/eslint/FlatESLint.ts
rename to packages/types-eslint/src/eslint/FlatESLint.ts
index 085a9e0fdfa9..a57d429f01a6 100644
--- a/packages/utils/src/ts-eslint/eslint/FlatESLint.ts
+++ b/packages/types-eslint/src/eslint/FlatESLint.ts
@@ -34,6 +34,7 @@ declare class FlatESLintBase extends Shared.ESLintBase<
*
* If you want to lint code on browsers, use the Linter class instead.
*/
+// @ts-expect-error -- TODO: I don't know why this is now needed...
export class FlatESLint extends (ESLintFlatESLint as typeof FlatESLintBase) {}
export namespace FlatESLint {
export interface ESLintOptions
diff --git a/packages/utils/src/ts-eslint/eslint/LegacyESLint.ts b/packages/types-eslint/src/eslint/LegacyESLint.ts
similarity index 98%
rename from packages/utils/src/ts-eslint/eslint/LegacyESLint.ts
rename to packages/types-eslint/src/eslint/LegacyESLint.ts
index 6dc316991688..6943d9a8f6f4 100644
--- a/packages/utils/src/ts-eslint/eslint/LegacyESLint.ts
+++ b/packages/types-eslint/src/eslint/LegacyESLint.ts
@@ -20,6 +20,7 @@ declare class LegacyESLintBase extends Shared.ESLintBase<
*
* If you want to lint code on browsers, use the Linter class instead.
*/
+// @ts-expect-error -- TODO: I don't know why this is now needed...
export class LegacyESLint extends (ESLintLegacyESLint as typeof LegacyESLintBase) {}
export namespace LegacyESLint {
export interface ESLintOptions
diff --git a/packages/utils/src/ts-eslint/index.ts b/packages/types-eslint/src/index.ts
similarity index 82%
rename from packages/utils/src/ts-eslint/index.ts
rename to packages/types-eslint/src/index.ts
index 217b46dcbf7d..2908a50fb5e0 100644
--- a/packages/utils/src/ts-eslint/index.ts
+++ b/packages/types-eslint/src/index.ts
@@ -1,9 +1,11 @@
export * from './AST';
+export * from './JSONSchema4';
export * from './Config';
export * from './ESLint';
export * from './Linter';
export * from './Parser';
export * from './ParserOptions';
+export * from './ParserServices';
export * from './Processor';
export * from './Rule';
export * from './RuleTester';
diff --git a/packages/types-eslint/tsconfig.build.json b/packages/types-eslint/tsconfig.build.json
new file mode 100644
index 000000000000..6ad59da4bb89
--- /dev/null
+++ b/packages/types-eslint/tsconfig.build.json
@@ -0,0 +1,18 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "rootDir": "src",
+ "outDir": "dist",
+ "tsBuildInfoFile": "dist/tsconfig.build.tsbuildinfo",
+ "emitDeclarationOnly": false,
+ "types": ["node"]
+ },
+ "include": ["src/**/*.ts"],
+ "exclude": ["vitest.config.mts", "src/**/*.spec.ts", "src/**/*.test.ts"],
+ "references": [
+ {
+ "path": "../typescript-estree/tsconfig.build.json"
+ }
+ ]
+}
diff --git a/packages/types-eslint/tsconfig.json b/packages/types-eslint/tsconfig.json
new file mode 100644
index 000000000000..e5d40828187b
--- /dev/null
+++ b/packages/types-eslint/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "../types-eslint"
+ },
+ {
+ "path": "../typescript-estree"
+ },
+ {
+ "path": "./tsconfig.build.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ]
+}
diff --git a/packages/types-eslint/tsconfig.spec.json b/packages/types-eslint/tsconfig.spec.json
new file mode 100644
index 000000000000..cc2ef165b048
--- /dev/null
+++ b/packages/types-eslint/tsconfig.spec.json
@@ -0,0 +1,26 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc/packages/types-eslint",
+ "module": "NodeNext",
+ "resolveJsonModule": true,
+ "types": ["node", "vitest/globals", "vitest/importMeta"]
+ },
+ "include": [
+ "vitest.config.mts",
+ "package.json",
+ "src/**/*.test.ts",
+ "src/**/*.spec.ts",
+ "src/**/*.d.ts",
+ "tests"
+ ],
+ "exclude": ["**/fixtures/**"],
+ "references": [
+ {
+ "path": "./tsconfig.build.json"
+ },
+ {
+ "path": "../../tsconfig.spec.json"
+ }
+ ]
+}
diff --git a/packages/types-eslint/vitest.config.mts b/packages/types-eslint/vitest.config.mts
new file mode 100644
index 000000000000..b3cf1f898a70
--- /dev/null
+++ b/packages/types-eslint/vitest.config.mts
@@ -0,0 +1,26 @@
+import * as path from 'node:path';
+import { defineProject, mergeConfig } from 'vitest/config';
+
+import { vitestBaseConfig } from '../../vitest.config.base.mjs';
+import packageJson from './package.json' with { type: 'json' };
+
+const vitestConfig = mergeConfig(
+ vitestBaseConfig,
+
+ defineProject({
+ root: import.meta.dirname,
+
+ test: {
+ dir: path.join(import.meta.dirname, 'tests'),
+ name: packageJson.name.replace('@typescript-eslint/', ''),
+ root: import.meta.dirname,
+
+ setupFiles: [
+ './tests/test-utils/serializers/index.ts',
+ './tests/test-utils/custom-matchers/custom-matchers.ts',
+ ],
+ },
+ }),
+);
+
+export default vitestConfig;
diff --git a/packages/utils/package.json b/packages/utils/package.json
index 12d5b7518c4e..d3f9852f2515 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -66,6 +66,7 @@
"@typescript-eslint/parser-services": "8.32.0",
"@typescript-eslint/scope-manager": "8.32.0",
"@typescript-eslint/types": "8.32.0",
+ "@typescript-eslint/types-eslint": "8.32.0",
"@typescript-eslint/typescript-estree": "8.32.0"
},
"peerDependencies": {
diff --git a/packages/utils/src/ast-utils/eslint-utils/ReferenceTracker.ts b/packages/utils/src/ast-utils/eslint-utils/ReferenceTracker.ts
index 5fca306bddf7..fe995439539b 100644
--- a/packages/utils/src/ast-utils/eslint-utils/ReferenceTracker.ts
+++ b/packages/utils/src/ast-utils/eslint-utils/ReferenceTracker.ts
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-namespace */
import * as eslintUtils from '@eslint-community/eslint-utils';
-import type * as TSESLint from '../../ts-eslint';
+import type * as TSESLint from '@typescript-eslint/types-eslint';
import type { TSESTree } from '../../ts-estree';
const ReferenceTrackerREAD: unique symbol = eslintUtils.ReferenceTracker.READ;
diff --git a/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts b/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts
index 8113319b68de..299b02a0652b 100644
--- a/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts
+++ b/packages/utils/src/ast-utils/eslint-utils/astUtilities.ts
@@ -1,6 +1,6 @@
import * as eslintUtils from '@eslint-community/eslint-utils';
-import type * as TSESLint from '../../ts-eslint';
+import type * as TSESLint from '@typescript-eslint/types-eslint';
import type { TSESTree } from '../../ts-estree';
/**
diff --git a/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts b/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts
index 1f7af13dd3cb..2988ef90138a 100644
--- a/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts
+++ b/packages/utils/src/ast-utils/eslint-utils/scopeAnalysis.ts
@@ -1,6 +1,7 @@
+import type * as TSESLint from '@typescript-eslint/types-eslint';
+
import * as eslintUtils from '@eslint-community/eslint-utils';
-import type * as TSESLint from '../../ts-eslint';
import type { TSESTree } from '../../ts-estree';
/**
diff --git a/packages/utils/src/eslint-utils/InferTypesFromRule.ts b/packages/utils/src/eslint-utils/InferTypesFromRule.ts
index 2e8dc3f232a1..92e9c4d31ff5 100644
--- a/packages/utils/src/eslint-utils/InferTypesFromRule.ts
+++ b/packages/utils/src/eslint-utils/InferTypesFromRule.ts
@@ -1,4 +1,7 @@
-import type { RuleCreateFunction, RuleModule } from '../ts-eslint';
+import type {
+ RuleCreateFunction,
+ RuleModule,
+} from '@typescript-eslint/types-eslint';
/**
* Uses type inference to fetch the Options type from the given RuleModule
diff --git a/packages/utils/src/eslint-utils/RuleCreator.ts b/packages/utils/src/eslint-utils/RuleCreator.ts
index cd06aee6231f..7ea670cc7c56 100644
--- a/packages/utils/src/eslint-utils/RuleCreator.ts
+++ b/packages/utils/src/eslint-utils/RuleCreator.ts
@@ -4,7 +4,7 @@ import type {
RuleMetaData,
RuleMetaDataDocs,
RuleModule,
-} from '../ts-eslint/Rule';
+} from '@typescript-eslint/types-eslint';
import { applyDefault } from './applyDefault';
@@ -119,4 +119,7 @@ RuleCreator.withoutDocs = function withoutDocs<
return createRule(args);
};
-export { type RuleListener, type RuleModule } from '../ts-eslint/Rule';
+export {
+ type RuleListener,
+ type RuleModule,
+} from '@typescript-eslint/types-eslint';
diff --git a/packages/utils/src/eslint-utils/getParserServices.ts b/packages/utils/src/eslint-utils/getParserServices.ts
index 51f55a0f9137..174397496573 100644
--- a/packages/utils/src/eslint-utils/getParserServices.ts
+++ b/packages/utils/src/eslint-utils/getParserServices.ts
@@ -1,8 +1,8 @@
-import type * as TSESLint from '../ts-eslint';
+import type * as TSESLint from '@typescript-eslint/types-eslint';
import type {
ParserServices,
ParserServicesWithTypeInformation,
-} from '@typescript-eslint/parser-services';
+} from '@typescript-eslint/types-eslint';
import { parserSeemsToBeTSESLint } from './parserSeemsToBeTSESLint';
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index d6d907cd0ef4..34f8832542ee 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -1,7 +1,8 @@
+// TODO: Should this be deprecated? Probably not, since it's convenient, right?
+export * as TSESLint from '@typescript-eslint/types-eslint';
+
export * as ASTUtils from './ast-utils';
export * as ESLintUtils from './eslint-utils';
-export * as JSONSchema from './json-schema';
-export * as TSESLint from './ts-eslint';
export * from './ts-estree';
export * as TSUtils from './ts-utils';
diff --git a/packages/utils/src/json-schema.ts b/packages/utils/src/json-schema.ts
index bfa890aac372..1442a421e4dd 100644
--- a/packages/utils/src/json-schema.ts
+++ b/packages/utils/src/json-schema.ts
@@ -1,497 +1,23 @@
-/**
- * This is a fork of https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13f63c2eb8d7479caf01ab8d72f9e3683368a8f5/types/json-schema/index.d.ts
- * We intentionally fork this because:
- * - ESLint ***ONLY*** supports JSONSchema v4
- * - We want to provide stricter types
- */
-
-//==================================================================================================
-// JSON Schema Draft 04
-//==================================================================================================
-
-/**
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1
- */
-export type JSONSchema4TypeName =
- | 'any'
- | 'array'
- | 'boolean'
- | 'integer'
- | 'null'
- | 'number'
- | 'object'
- | 'string';
-
-/**
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-04#section-3.5
- */
-export type JSONSchema4Type = boolean | number | string | null;
-
-export type JSONSchema4TypeExtended =
- | JSONSchema4Array
- | JSONSchema4Object
- | JSONSchema4Type;
-
-export interface JSONSchema4Object {
- [key: string]: JSONSchema4TypeExtended;
-}
-
-// Workaround for infinite type recursion
-// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540
-// eslint-disable-next-line @typescript-eslint/no-empty-object-type
-export interface JSONSchema4Array extends Array {}
-
-/**
- * Meta schema
- *
- * Recommended values:
- * - 'http://json-schema.org/schema#'
- * - 'http://json-schema.org/hyper-schema#'
- * - 'http://json-schema.org/draft-04/schema#'
- * - 'http://json-schema.org/draft-04/hyper-schema#'
- * - 'http://json-schema.org/draft-03/schema#'
- * - 'http://json-schema.org/draft-03/hyper-schema#'
- *
- * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-5
- */
-export type JSONSchema4Version = string;
-
-/**
- * JSON Schema V4
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-04
- */
-export type JSONSchema4 =
- | JSONSchema4AllOfSchema
- | JSONSchema4AnyOfSchema
- | JSONSchema4AnySchema
- | JSONSchema4ArraySchema
- | JSONSchema4BooleanSchema
- | JSONSchema4MultiSchema
- | JSONSchema4NullSchema
- | JSONSchema4NumberSchema
- | JSONSchema4ObjectSchema
- | JSONSchema4OneOfSchema
- | JSONSchema4RefSchema
- | JSONSchema4StringSchema;
-
-interface JSONSchema4Base {
- /**
- * Reusable definitions that can be referenced via `$ref`
- */
- $defs?: Record | undefined;
-
- /**
- * Path to a schema defined in `definitions`/`$defs` that will form the base
- * for this schema.
- *
- * If you are defining an "array" schema (`schema: [ ... ]`) for your rule
- * then you should prefix this with `items/0` so that the validator can find
- * your definitions.
- *
- * eg: `'#/items/0/definitions/myDef'`
- *
- * Otherwise if you are defining an "object" schema (`schema: { ... }`) for
- * your rule you can directly reference your definitions
- *
- * eg: `'#/definitions/myDef'`
- */
- $ref?: string | undefined;
-
- $schema?: JSONSchema4Version | undefined;
-
- /**
- * (AND) Must be valid against all of the sub-schemas
- */
- allOf?: JSONSchema4[] | undefined;
-
- /**
- * (OR) Must be valid against any of the sub-schemas
- */
- anyOf?: JSONSchema4[] | undefined;
-
- /**
- * The default value for the item if not present
- */
- default?: JSONSchema4TypeExtended | undefined;
-
- /**
- * Reusable definitions that can be referenced via `$ref`
- */
- definitions?: Record | undefined;
-
- /**
- * This attribute is a string that provides a full description of the of
- * purpose the instance property.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.22
- */
- description?: string | undefined;
-
- /**
- * The value of this property MUST be another schema which will provide
- * a base schema which the current schema will inherit from. The
- * inheritance rules are such that any instance that is valid according
- * to the current schema MUST be valid according to the referenced
- * schema. This MAY also be an array, in which case, the instance MUST
- * be valid for all the schemas in the array. A schema that extends
- * another schema MAY define additional attributes, constrain existing
- * attributes, or add other constraints.
- *
- * Conceptually, the behavior of extends can be seen as validating an
- * instance against all constraints in the extending schema as well as
- * the extended schema(s).
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.26
- */
- extends?: string | string[] | undefined;
-
- id?: string | undefined;
-
- /**
- * (NOT) Must not be valid against the given schema
- */
- not?: JSONSchema4 | undefined;
-
- /**
- * (XOR) Must be valid against exactly one of the sub-schemas
- */
- oneOf?: JSONSchema4[] | undefined;
-
- /**
- * This attribute indicates if the instance must have a value, and not
- * be undefined. This is false by default, making the instance
- * optional.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.7
- */
- required?: boolean | string[] | undefined;
-
- /**
- * This attribute is a string that provides a short description of the
- * instance property.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.21
- */
- title?: string | undefined;
-
- /**
- * A single type, or a union of simple types
- */
- type?: JSONSchema4TypeName | JSONSchema4TypeName[] | undefined;
-}
-
-export interface JSONSchema4RefSchema extends JSONSchema4Base {
- $ref: string;
- type?: undefined;
-}
-
-export interface JSONSchema4AllOfSchema extends JSONSchema4Base {
- allOf: JSONSchema4[];
- type?: undefined;
-}
-
-export interface JSONSchema4AnyOfSchema extends JSONSchema4Base {
- anyOf: JSONSchema4[];
- type?: undefined;
-}
-
-export interface JSONSchema4OneOfSchema extends JSONSchema4Base {
- oneOf: JSONSchema4[];
- type?: undefined;
-}
-
-export interface JSONSchema4MultiSchema
- extends Omit,
- Omit,
- Omit,
- Omit,
- Omit,
- Omit,
- Omit {
- /**
- * This provides an enumeration of all possible values that are valid
- * for the instance property. This MUST be an array, and each item in
- * the array represents a possible value for the instance value. If
- * this attribute is defined, the instance value MUST be one of the
- * values in the array in order for the schema to be valid.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
- */
- enum?: JSONSchema4Type[];
- type: JSONSchema4TypeName[];
-}
-
-/**
- * @see https://json-schema.org/understanding-json-schema/reference/object.html
- */
-export interface JSONSchema4ObjectSchema extends JSONSchema4Base {
- /**
- * This attribute defines a schema for all properties that are not
- * explicitly defined in an object type definition. If specified, the
- * value MUST be a schema or a boolean. If false is provided, no
- * additional properties are allowed beyond the properties defined in
- * the schema. The default value is an empty schema which allows any
- * value for additional properties.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.4
- */
- additionalProperties?: boolean | JSONSchema4 | undefined;
-
- /**
- * The `dependencies` keyword conditionally applies a sub-schema when a given
- * property is present. This schema is applied in the same way `allOf` applies
- * schemas. Nothing is merged or extended. Both schemas apply independently.
- */
- dependencies?: Record | undefined;
-
- /**
- * The maximum number of properties allowed for record-style schemas
- */
- maxProperties?: number | undefined;
-
- /**
- * The minimum number of properties required for record-style schemas
- */
- minProperties?: number | undefined;
-
- /**
- * This attribute is an object that defines the schema for a set of
- * property names of an object instance. The name of each property of
- * this attribute's object is a regular expression pattern in the ECMA
- * 262/Perl 5 format, while the value is a schema. If the pattern
- * matches the name of a property on the instance object, the value of
- * the instance's property MUST be valid against the pattern name's
- * schema value.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.3
- */
- patternProperties?: Record | undefined;
-
- /**
- * This attribute is an object with property definitions that define the
- * valid values of instance object property values. When the instance
- * value is an object, the property values of the instance object MUST
- * conform to the property definitions in this object. In this object,
- * each property definition's value MUST be a schema, and the property's
- * name MUST be the name of the instance property that it defines. The
- * instance property value MUST be valid according to the schema from
- * the property definition. Properties are considered unordered, the
- * order of the instance properties MAY be in any order.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.2
- */
- properties?: Record | undefined;
-
- type: 'object';
-}
-
-/**
- * @see https://json-schema.org/understanding-json-schema/reference/array.html
- */
-export interface JSONSchema4ArraySchema extends JSONSchema4Base {
- /**
- * May only be defined when "items" is defined, and is a tuple of JSONSchemas.
- *
- * This provides a definition for additional items in an array instance
- * when tuple definitions of the items is provided. This can be false
- * to indicate additional items in the array are not allowed, or it can
- * be a schema that defines the schema of the additional items.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.6
- */
- additionalItems?: boolean | JSONSchema4 | undefined;
-
- /**
- * This attribute defines the allowed items in an instance array, and
- * MUST be a schema or an array of schemas. The default value is an
- * empty schema which allows any value for items in the instance array.
- *
- * When this attribute value is a schema and the instance value is an
- * array, then all the items in the array MUST be valid according to the
- * schema.
- *
- * When this attribute value is an array of schemas and the instance
- * value is an array, each position in the instance array MUST conform
- * to the schema in the corresponding position for this array. This
- * called tuple typing. When tuple typing is used, additional items are
- * allowed, disallowed, or constrained by the "additionalItems"
- * (Section 5.6) attribute using the same rules as
- * "additionalProperties" (Section 5.4) for objects.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.5
- */
- items?: JSONSchema4 | JSONSchema4[] | undefined;
-
- /**
- * Defines the maximum length of an array
- */
- maxItems?: number | undefined;
-
- /**
- * Defines the minimum length of an array
- */
- minItems?: number | undefined;
-
- type: 'array';
-
- /**
- * Enforces that all items in the array are unique
- */
- uniqueItems?: boolean | undefined;
-}
-
-/**
- * @see https://json-schema.org/understanding-json-schema/reference/string.html
- */
-export interface JSONSchema4StringSchema extends JSONSchema4Base {
- enum?: string[] | undefined;
-
- /**
- * The `format` keyword allows for basic semantic identification of certain
- * kinds of string values that are commonly used.
- *
- * For example, because JSON doesn’t have a “DateTime” type, dates need to be
- * encoded as strings. `format` allows the schema author to indicate that the
- * string value should be interpreted as a date.
- *
- * ajv v6 provides a few built-in formats - all other strings will cause AJV
- * to throw during schema compilation
- */
- format?:
- | 'date'
- | 'date-time'
- | 'email'
- | 'hostname'
- | 'ipv4'
- | 'ipv6'
- | 'json-pointer'
- | 'json-pointer-uri-fragment'
- | 'regex'
- | 'relative-json-pointer'
- | 'time'
- | 'uri'
- | 'uri-reference'
- | 'uri-template'
- | 'url'
- | 'uuid'
- | undefined;
-
- /**
- * The maximum allowed length for the string
- */
- maxLength?: number | undefined;
-
- /**
- * The minimum allowed length for the string
- */
- minLength?: number | undefined;
-
- /**
- * The `pattern` keyword is used to restrict a string to a particular regular
- * expression. The regular expression syntax is the one defined in JavaScript
- * (ECMA 262 specifically) with Unicode support.
- *
- * When defining the regular expressions, it’s important to note that the
- * string is considered valid if the expression matches anywhere within the
- * string. For example, the regular expression "p" will match any string with
- * a p in it, such as "apple" not just a string that is simply "p". Therefore,
- * it is usually less confusing, as a matter of course, to surround the
- * regular expression in ^...$, for example, "^p$", unless there is a good
- * reason not to do so.
- */
- pattern?: string | undefined;
-
- type: 'string';
-}
-
-/**
- * @see https://json-schema.org/understanding-json-schema/reference/numeric.html
- */
-export interface JSONSchema4NumberSchema extends JSONSchema4Base {
- /**
- * This provides an enumeration of all possible values that are valid
- * for the instance property. This MUST be an array, and each item in
- * the array represents a possible value for the instance value. If
- * this attribute is defined, the instance value MUST be one of the
- * values in the array in order for the schema to be valid.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
- */
- enum?: number[] | undefined;
-
- /**
- * The exclusive minimum allowed value for the number
- * - `true` = `x < maximum`
- * - `false` = `x <= maximum`
- *
- * Default is `false`
- */
- exclusiveMaximum?: boolean | undefined;
-
- /**
- * Indicates whether or not `minimum` is the inclusive or exclusive minimum
- * - `true` = `x > minimum`
- * - `false` = `x ≥ minimum`
- *
- * Default is `false`
- */
- exclusiveMinimum?: boolean | undefined;
-
- /**
- * The maximum allowed value for the number
- */
- maximum?: number | undefined;
-
- /**
- * The minimum allowed value for the number
- */
- minimum?: number | undefined;
-
- /**
- * Numbers can be restricted to a multiple of a given number, using the
- * `multipleOf` keyword. It may be set to any positive number.
- */
- multipleOf?: number | undefined;
-
- type: 'integer' | 'number';
-}
-
-/**
- * @see https://json-schema.org/understanding-json-schema/reference/boolean.html
- */
-export interface JSONSchema4BooleanSchema extends JSONSchema4Base {
- /**
- * This provides an enumeration of all possible values that are valid
- * for the instance property. This MUST be an array, and each item in
- * the array represents a possible value for the instance value. If
- * this attribute is defined, the instance value MUST be one of the
- * values in the array in order for the schema to be valid.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
- */
- enum?: boolean[] | undefined;
-
- type: 'boolean';
-}
-
-/**
- * @see https://json-schema.org/understanding-json-schema/reference/null.html
- */
-export interface JSONSchema4NullSchema extends JSONSchema4Base {
- /**
- * This provides an enumeration of all possible values that are valid
- * for the instance property. This MUST be an array, and each item in
- * the array represents a possible value for the instance value. If
- * this attribute is defined, the instance value MUST be one of the
- * values in the array in order for the schema to be valid.
- *
- * @see https://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.19
- */
- enum?: null[] | undefined;
-
- type: 'null';
-}
-
-export interface JSONSchema4AnySchema extends JSONSchema4Base {
- type: 'any';
-}
+// TODO: Maybe put these in a separate package too, while we're at it?
+
+export type {
+ JSONSchema4,
+ JSONSchema4AllOfSchema,
+ JSONSchema4AnyOfSchema,
+ JSONSchema4AnySchema,
+ JSONSchema4Array,
+ JSONSchema4ArraySchema,
+ JSONSchema4BooleanSchema,
+ JSONSchema4MultiSchema,
+ JSONSchema4NullSchema,
+ JSONSchema4NumberSchema,
+ JSONSchema4Object,
+ JSONSchema4ObjectSchema,
+ JSONSchema4OneOfSchema,
+ JSONSchema4RefSchema,
+ JSONSchema4StringSchema,
+ JSONSchema4Type,
+ JSONSchema4TypeExtended,
+ JSONSchema4TypeName,
+ JSONSchema4Version,
+} from '@typescript-eslint/types-eslint';
diff --git a/packages/utils/src/ts-estree.ts b/packages/utils/src/ts-estree.ts
index 8aca30ad7dbd..794cef380154 100644
--- a/packages/utils/src/ts-estree.ts
+++ b/packages/utils/src/ts-estree.ts
@@ -11,4 +11,4 @@ export type {
ParserServices,
ParserServicesWithoutTypeInformation,
ParserServicesWithTypeInformation,
-} from '@typescript-eslint/parser-services';
+} from '@typescript-eslint/types-eslint';
diff --git a/packages/utils/tsconfig.build.json b/packages/utils/tsconfig.build.json
index 726fd5919df0..1a2f825ae168 100644
--- a/packages/utils/tsconfig.build.json
+++ b/packages/utils/tsconfig.build.json
@@ -11,6 +11,9 @@
{
"path": "../types/tsconfig.build.json"
},
+ {
+ "path": "../types-eslint/tsconfig.build.json"
+ },
{
"path": "../scope-manager/tsconfig.build.json"
}
diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json
index bda3cfd7f502..6af493771d15 100644
--- a/packages/utils/tsconfig.json
+++ b/packages/utils/tsconfig.json
@@ -12,6 +12,9 @@
{
"path": "../types"
},
+ {
+ "path": "../types-eslint"
+ },
{
"path": "../scope-manager"
},
diff --git a/tsconfig.json b/tsconfig.json
index 39cbb87e663c..0cef6c88aeac 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -18,6 +18,7 @@
{ "path": "./packages/types" },
{ "path": "./packages/typescript-eslint" },
{ "path": "./packages/typescript-estree" },
+ { "path": "./packages/types-eslint" },
{ "path": "./packages/type-utils" },
{ "path": "./packages/utils" },
{ "path": "./packages/visitor-keys" },
diff --git a/yarn.lock b/yarn.lock
index 86050389977f..6eaa98aeb0ec 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5577,6 +5577,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@typescript-eslint/parser-services@workspace:packages/parser-services"
dependencies:
+ "@typescript-eslint/types-eslint": ^8.32.0
"@typescript-eslint/typescript-estree": ^8.32.0
"@vitest/coverage-v8": ^3.1.2
debug: ^4.3.4
@@ -5611,6 +5612,35 @@ __metadata:
languageName: unknown
linkType: soft
+"@typescript-eslint/rule-creator@workspace:packages/rule-creator":
+ version: 0.0.0-use.local
+ resolution: "@typescript-eslint/rule-creator@workspace:packages/rule-creator"
+ dependencies:
+ "@types/json-stable-stringify-without-jsonify": ^1.0.2
+ "@types/lodash.merge": 4.6.9
+ "@typescript-eslint/parser": 8.32.0
+ "@typescript-eslint/types-eslint": 8.32.0
+ "@typescript-eslint/typescript-estree": 8.32.0
+ "@typescript-eslint/utils": 8.32.0
+ "@vitest/coverage-v8": ^3.1.2
+ ajv: ^6.12.6
+ chai: ^5.2.0
+ eslint-visitor-keys: ^4.2.0
+ espree: ^10.3.0
+ esprima: ^4.0.1
+ json-stable-stringify-without-jsonify: ^1.0.1
+ lodash.merge: 4.6.2
+ mocha: ^11.0.0
+ semver: ^7.6.0
+ sinon: ^20.0.0
+ source-map-support: ^0.5.21
+ typescript: "*"
+ vitest: ^3.1.2
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ languageName: unknown
+ linkType: soft
+
"@typescript-eslint/rule-schema-to-typescript-types@8.32.0, @typescript-eslint/rule-schema-to-typescript-types@workspace:*, @typescript-eslint/rule-schema-to-typescript-types@workspace:packages/rule-schema-to-typescript-types":
version: 0.0.0-use.local
resolution: "@typescript-eslint/rule-schema-to-typescript-types@workspace:packages/rule-schema-to-typescript-types"
@@ -5692,6 +5722,23 @@ __metadata:
languageName: unknown
linkType: soft
+"@typescript-eslint/types-eslint@8.32.0, @typescript-eslint/types-eslint@^8.32.0, @typescript-eslint/types-eslint@workspace:packages/types-eslint":
+ version: 0.0.0-use.local
+ resolution: "@typescript-eslint/types-eslint@workspace:packages/types-eslint"
+ dependencies:
+ "@typescript-eslint/types": 8.32.0
+ "@typescript-eslint/typescript-estree": 8.32.0
+ "@typescript-eslint/visitor-keys": 8.32.0
+ "@vitest/coverage-v8": ^3.1.2
+ "@vitest/pretty-format": ^3.1.2
+ glob: "*"
+ prettier: ^3.2.5
+ rimraf: "*"
+ typescript: "*"
+ vitest: ^3.1.2
+ languageName: unknown
+ linkType: soft
+
"@typescript-eslint/types@8.32.0, @typescript-eslint/types@^8.9.0, @typescript-eslint/types@workspace:*, @typescript-eslint/types@workspace:^, @typescript-eslint/types@workspace:packages/types":
version: 0.0.0-use.local
resolution: "@typescript-eslint/types@workspace:packages/types"
@@ -5796,6 +5843,7 @@ __metadata:
resolution: "@typescript-eslint/utils@workspace:packages/utils"
dependencies:
"@eslint-community/eslint-utils": ^4.7.0
+ "@typescript-eslint/parser-services": 8.32.0
"@typescript-eslint/scope-manager": 8.32.0
"@typescript-eslint/types": 8.32.0
"@typescript-eslint/typescript-estree": 8.32.0
From 90c32b3a50b436e27ea5b91450eb350bbda33dfd Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Sat, 10 May 2025 22:35:58 -0400
Subject: [PATCH 3/3] Package split: rule-creator
---
packages/eslint-plugin-internal/package.json | 1 +
.../src/util/createRule.ts | 4 +-
.../tsconfig.build.json | 3 +
packages/eslint-plugin-internal/tsconfig.json | 3 +
packages/eslint-plugin/package.json | 1 +
packages/eslint-plugin/src/util/createRule.ts | 4 +-
packages/eslint-plugin/src/util/index.ts | 1 -
packages/eslint-plugin/tsconfig.build.json | 3 +
packages/eslint-plugin/tsconfig.json | 3 +
packages/rule-creator/LICENSE | 21 ++++++
packages/rule-creator/README.md | 3 +
packages/rule-creator/package.json | 67 +++++++++++++++++++
packages/rule-creator/project.json | 16 +++++
.../src}/RuleCreator.ts | 0
.../src}/applyDefault.ts | 0
packages/rule-creator/src/deepMerge.ts | 51 ++++++++++++++
packages/rule-creator/src/index.ts | 1 +
packages/rule-creator/tsconfig.build.json | 18 +++++
packages/rule-creator/tsconfig.json | 16 +++++
packages/rule-creator/tsconfig.spec.json | 26 +++++++
packages/rule-creator/vitest.config.mts | 21 ++++++
packages/utils/package.json | 1 +
packages/utils/src/eslint-utils/index.ts | 5 +-
packages/utils/tsconfig.build.json | 3 +
packages/utils/tsconfig.json | 3 +
yarn.lock | 30 +++------
26 files changed, 279 insertions(+), 26 deletions(-)
create mode 100644 packages/rule-creator/LICENSE
create mode 100644 packages/rule-creator/README.md
create mode 100644 packages/rule-creator/package.json
create mode 100644 packages/rule-creator/project.json
rename packages/{utils/src/eslint-utils => rule-creator/src}/RuleCreator.ts (100%)
rename packages/{utils/src/eslint-utils => rule-creator/src}/applyDefault.ts (100%)
create mode 100644 packages/rule-creator/src/deepMerge.ts
create mode 100644 packages/rule-creator/src/index.ts
create mode 100644 packages/rule-creator/tsconfig.build.json
create mode 100644 packages/rule-creator/tsconfig.json
create mode 100644 packages/rule-creator/tsconfig.spec.json
create mode 100644 packages/rule-creator/vitest.config.mts
diff --git a/packages/eslint-plugin-internal/package.json b/packages/eslint-plugin-internal/package.json
index 458bee57df6a..e19086fef231 100644
--- a/packages/eslint-plugin-internal/package.json
+++ b/packages/eslint-plugin-internal/package.json
@@ -24,6 +24,7 @@
},
"dependencies": {
"@prettier/sync": "^0.5.1",
+ "@typescript-eslint/rule-creator": "workspace:*",
"@typescript-eslint/rule-tester": "workspace:*",
"@typescript-eslint/scope-manager": "workspace:*",
"@typescript-eslint/type-utils": "workspace:*",
diff --git a/packages/eslint-plugin-internal/src/util/createRule.ts b/packages/eslint-plugin-internal/src/util/createRule.ts
index 628498d08dad..4466eabd61c7 100644
--- a/packages/eslint-plugin-internal/src/util/createRule.ts
+++ b/packages/eslint-plugin-internal/src/util/createRule.ts
@@ -1,4 +1,4 @@
-import { ESLintUtils } from '@typescript-eslint/utils';
+import { RuleCreator } from '@typescript-eslint/rule-creator';
// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
@@ -8,7 +8,7 @@ export interface ESLintPluginInternalDocs {
requiresTypeChecking?: true;
}
-export const createRule = ESLintUtils.RuleCreator(
+export const createRule = RuleCreator(
name =>
`https://github.com/typescript-eslint/typescript-eslint/blob/v${version}/packages/eslint-plugin-internal/src/rules/${name}.ts`,
);
diff --git a/packages/eslint-plugin-internal/tsconfig.build.json b/packages/eslint-plugin-internal/tsconfig.build.json
index f7ebbac5e0c2..2b046c51b476 100644
--- a/packages/eslint-plugin-internal/tsconfig.build.json
+++ b/packages/eslint-plugin-internal/tsconfig.build.json
@@ -5,6 +5,9 @@
{
"path": "../type-utils/tsconfig.build.json"
},
+ {
+ "path": "../rule-creator/tsconfig.build.json"
+ },
{
"path": "../scope-manager/tsconfig.build.json"
},
diff --git a/packages/eslint-plugin-internal/tsconfig.json b/packages/eslint-plugin-internal/tsconfig.json
index 9df0fb2d2e38..c0cdc3260a69 100644
--- a/packages/eslint-plugin-internal/tsconfig.json
+++ b/packages/eslint-plugin-internal/tsconfig.json
@@ -6,6 +6,9 @@
{
"path": "../type-utils"
},
+ {
+ "path": "../rule-creator"
+ },
{
"path": "../scope-manager"
},
diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json
index f336fba2b209..e33a178dde8b 100644
--- a/packages/eslint-plugin/package.json
+++ b/packages/eslint-plugin/package.json
@@ -61,6 +61,7 @@
},
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/rule-creator": "8.32.0",
"@typescript-eslint/scope-manager": "8.32.0",
"@typescript-eslint/type-utils": "8.32.0",
"@typescript-eslint/utils": "8.32.0",
diff --git a/packages/eslint-plugin/src/util/createRule.ts b/packages/eslint-plugin/src/util/createRule.ts
index 80611a8fdb89..e92dc1d23ba1 100644
--- a/packages/eslint-plugin/src/util/createRule.ts
+++ b/packages/eslint-plugin/src/util/createRule.ts
@@ -1,7 +1,7 @@
-import { ESLintUtils } from '@typescript-eslint/utils';
+import { RuleCreator } from '@typescript-eslint/rule-creator';
import type { ESLintPluginDocs } from '../../rules';
-export const createRule = ESLintUtils.RuleCreator(
+export const createRule = RuleCreator(
name => `https://typescript-eslint.io/rules/${name}`,
);
diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts
index 035fca0cec4a..995d97d6a445 100644
--- a/packages/eslint-plugin/src/util/index.ts
+++ b/packages/eslint-plugin/src/util/index.ts
@@ -34,7 +34,6 @@ export * from './truthinessUtils';
export * from '@typescript-eslint/type-utils';
export const {
- applyDefault,
deepMerge,
getParserServices,
isObjectNotArray,
diff --git a/packages/eslint-plugin/tsconfig.build.json b/packages/eslint-plugin/tsconfig.build.json
index 04b59df7bb50..dfa993baa1d8 100644
--- a/packages/eslint-plugin/tsconfig.build.json
+++ b/packages/eslint-plugin/tsconfig.build.json
@@ -5,6 +5,9 @@
{
"path": "../visitor-keys/tsconfig.build.json"
},
+ {
+ "path": "../rule-creator/tsconfig.build.json"
+ },
{
"path": "../type-utils/tsconfig.build.json"
},
diff --git a/packages/eslint-plugin/tsconfig.json b/packages/eslint-plugin/tsconfig.json
index 57673ed7cbf0..fd7ad5b96984 100644
--- a/packages/eslint-plugin/tsconfig.json
+++ b/packages/eslint-plugin/tsconfig.json
@@ -9,6 +9,9 @@
{
"path": "../type-utils"
},
+ {
+ "path": "../rule-creator"
+ },
{
"path": "../scope-manager"
},
diff --git a/packages/rule-creator/LICENSE b/packages/rule-creator/LICENSE
new file mode 100644
index 000000000000..310a18f8a6cb
--- /dev/null
+++ b/packages/rule-creator/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 typescript-eslint and other contributors
+
+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.
diff --git a/packages/rule-creator/README.md b/packages/rule-creator/README.md
new file mode 100644
index 000000000000..fe79fc9c2571
--- /dev/null
+++ b/packages/rule-creator/README.md
@@ -0,0 +1,3 @@
+# `@typescript-eslint/rule-creator`
+
+TODO
diff --git a/packages/rule-creator/package.json b/packages/rule-creator/package.json
new file mode 100644
index 000000000000..417f9d735665
--- /dev/null
+++ b/packages/rule-creator/package.json
@@ -0,0 +1,67 @@
+{
+ "name": "@typescript-eslint/rule-creator",
+ "version": "8.32.0",
+ "description": "TODO",
+ "files": [
+ "dist",
+ "!*.tsbuildinfo",
+ "package.json",
+ "README.md",
+ "LICENSE"
+ ],
+ "type": "commonjs",
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
+ "./package.json": "./package.json"
+ },
+ "types": "./dist/index.d.ts",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/typescript-eslint/typescript-eslint.git",
+ "directory": "packages/rule-creator"
+ },
+ "bugs": {
+ "url": "https://github.com/typescript-eslint/typescript-eslint/issues"
+ },
+ "homepage": "https://typescript-eslint.io/packages/rule-creator",
+ "license": "MIT",
+ "keywords": [
+ "eslint",
+ "typescript",
+ "estree"
+ ],
+ "scripts": {
+ "build": "tsc -b tsconfig.build.json",
+ "clean": "rimraf dist/ coverage/",
+ "clean-fixtures": "rimraf -g \"./src/**/fixtures/**/snapshots\"",
+ "format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
+ "generate-lib": "npx nx generate-lib repo",
+ "lint": "npx nx lint",
+ "test": "vitest --run --config=$INIT_CWD/vitest.config.mts",
+ "check-types": "npx nx typecheck"
+ },
+ "dependencies": {
+ "@typescript-eslint/types": "8.32.0",
+ "@typescript-eslint/visitor-keys": "8.32.0"
+ },
+ "devDependencies": {
+ "@typescript-eslint/typescript-estree": "8.32.0",
+ "@vitest/coverage-v8": "^3.1.2",
+ "@vitest/pretty-format": "^3.1.2",
+ "glob": "*",
+ "prettier": "^3.2.5",
+ "rimraf": "*",
+ "typescript": "*",
+ "vitest": "^3.1.2"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+}
diff --git a/packages/rule-creator/project.json b/packages/rule-creator/project.json
new file mode 100644
index 000000000000..d97cc4854dd9
--- /dev/null
+++ b/packages/rule-creator/project.json
@@ -0,0 +1,16 @@
+{
+ "name": "rule-creator",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "root": "packages/rule-creator",
+ "sourceRoot": "packages/rule-creator/src",
+ "projectType": "library",
+ "targets": {
+ "lint": {
+ "executor": "@nx/eslint:lint",
+ "outputs": ["{options.outputFile}"]
+ },
+ "test": {
+ "executor": "@nx/vite:test"
+ }
+ }
+}
diff --git a/packages/utils/src/eslint-utils/RuleCreator.ts b/packages/rule-creator/src/RuleCreator.ts
similarity index 100%
rename from packages/utils/src/eslint-utils/RuleCreator.ts
rename to packages/rule-creator/src/RuleCreator.ts
diff --git a/packages/utils/src/eslint-utils/applyDefault.ts b/packages/rule-creator/src/applyDefault.ts
similarity index 100%
rename from packages/utils/src/eslint-utils/applyDefault.ts
rename to packages/rule-creator/src/applyDefault.ts
diff --git a/packages/rule-creator/src/deepMerge.ts b/packages/rule-creator/src/deepMerge.ts
new file mode 100644
index 000000000000..4246b875815d
--- /dev/null
+++ b/packages/rule-creator/src/deepMerge.ts
@@ -0,0 +1,51 @@
+// TODO: Dedupe from utils/src/eslint-utils? Separate package?
+
+export type ObjectLike = Record;
+
+/**
+ * Check if the variable contains an object strictly rejecting arrays
+ * @returns `true` if obj is an object
+ */
+export function isObjectNotArray(obj: unknown): obj is ObjectLike {
+ return typeof obj === 'object' && obj != null && !Array.isArray(obj);
+}
+
+/**
+ * Pure function - doesn't mutate either parameter!
+ * Merges two objects together deeply, overwriting the properties in first with the properties in second
+ * @param first The first object
+ * @param second The second object
+ * @returns a new object
+ */
+export function deepMerge(
+ first: ObjectLike = {},
+ second: ObjectLike = {},
+): Record {
+ // get the unique set of keys across both objects
+ const keys = new Set([...Object.keys(first), ...Object.keys(second)]);
+
+ return Object.fromEntries(
+ [...keys].map(key => {
+ const firstHasKey = key in first;
+ const secondHasKey = key in second;
+ const firstValue = first[key];
+ const secondValue = second[key];
+
+ let value;
+ if (firstHasKey && secondHasKey) {
+ if (isObjectNotArray(firstValue) && isObjectNotArray(secondValue)) {
+ // object type
+ value = deepMerge(firstValue, secondValue);
+ } else {
+ // value type
+ value = secondValue;
+ }
+ } else if (firstHasKey) {
+ value = firstValue;
+ } else {
+ value = secondValue;
+ }
+ return [key, value];
+ }),
+ );
+}
diff --git a/packages/rule-creator/src/index.ts b/packages/rule-creator/src/index.ts
new file mode 100644
index 000000000000..ecac75f64d57
--- /dev/null
+++ b/packages/rule-creator/src/index.ts
@@ -0,0 +1 @@
+export * from './RuleCreator';
diff --git a/packages/rule-creator/tsconfig.build.json b/packages/rule-creator/tsconfig.build.json
new file mode 100644
index 000000000000..32c684a7f553
--- /dev/null
+++ b/packages/rule-creator/tsconfig.build.json
@@ -0,0 +1,18 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "rootDir": "src",
+ "outDir": "dist",
+ "tsBuildInfoFile": "dist/tsconfig.build.tsbuildinfo",
+ "emitDeclarationOnly": false,
+ "types": ["node"]
+ },
+ "include": ["src/**/*.ts"],
+ "exclude": ["vitest.config.mts", "src/**/*.spec.ts", "src/**/*.test.ts"],
+ "references": [
+ {
+ "path": "../types-eslint/tsconfig.build.json"
+ }
+ ]
+}
diff --git a/packages/rule-creator/tsconfig.json b/packages/rule-creator/tsconfig.json
new file mode 100644
index 000000000000..7b4c81fb1f51
--- /dev/null
+++ b/packages/rule-creator/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "../types-eslint"
+ },
+ {
+ "path": "./tsconfig.build.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ]
+}
diff --git a/packages/rule-creator/tsconfig.spec.json b/packages/rule-creator/tsconfig.spec.json
new file mode 100644
index 000000000000..484d402ed5cb
--- /dev/null
+++ b/packages/rule-creator/tsconfig.spec.json
@@ -0,0 +1,26 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc/packages/rule-creator",
+ "module": "NodeNext",
+ "resolveJsonModule": true,
+ "types": ["node", "vitest/globals", "vitest/importMeta"]
+ },
+ "include": [
+ "vitest.config.mts",
+ "package.json",
+ "src/**/*.test.ts",
+ "src/**/*.spec.ts",
+ "src/**/*.d.ts",
+ "tests"
+ ],
+ "exclude": ["**/fixtures/**"],
+ "references": [
+ {
+ "path": "./tsconfig.build.json"
+ },
+ {
+ "path": "../../tsconfig.spec.json"
+ }
+ ]
+}
diff --git a/packages/rule-creator/vitest.config.mts b/packages/rule-creator/vitest.config.mts
new file mode 100644
index 000000000000..ddc038f86b56
--- /dev/null
+++ b/packages/rule-creator/vitest.config.mts
@@ -0,0 +1,21 @@
+import * as path from 'node:path';
+import { defineProject, mergeConfig } from 'vitest/config';
+
+import { vitestBaseConfig } from '../../vitest.config.base.mjs';
+import packageJson from './package.json' with { type: 'json' };
+
+const vitestConfig = mergeConfig(
+ vitestBaseConfig,
+
+ defineProject({
+ root: import.meta.dirname,
+
+ test: {
+ dir: path.join(import.meta.dirname, 'tests'),
+ name: packageJson.name.replace('@typescript-eslint/', ''),
+ root: import.meta.dirname,
+ },
+ }),
+);
+
+export default vitestConfig;
diff --git a/packages/utils/package.json b/packages/utils/package.json
index d3f9852f2515..7ea08ae0b968 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -64,6 +64,7 @@
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/parser-services": "8.32.0",
+ "@typescript-eslint/rule-creator": "8.32.0",
"@typescript-eslint/scope-manager": "8.32.0",
"@typescript-eslint/types": "8.32.0",
"@typescript-eslint/types-eslint": "8.32.0",
diff --git a/packages/utils/src/eslint-utils/index.ts b/packages/utils/src/eslint-utils/index.ts
index 632b6e051981..c12b7e7c5344 100644
--- a/packages/utils/src/eslint-utils/index.ts
+++ b/packages/utils/src/eslint-utils/index.ts
@@ -1,6 +1,7 @@
-export * from './applyDefault';
export * from './deepMerge';
export * from './getParserServices';
export * from './InferTypesFromRule';
export * from './nullThrows';
-export * from './RuleCreator';
+
+/** @deprecated - use @typescript-eslint/rule-creator directly */
+export * from '@typescript-eslint/rule-creator';
diff --git a/packages/utils/tsconfig.build.json b/packages/utils/tsconfig.build.json
index 1a2f825ae168..1e00e91c2144 100644
--- a/packages/utils/tsconfig.build.json
+++ b/packages/utils/tsconfig.build.json
@@ -5,6 +5,9 @@
{
"path": "../parser-services/tsconfig.build.json"
},
+ {
+ "path": "../rule-creator/tsconfig.build.json"
+ },
{
"path": "../typescript-estree/tsconfig.build.json"
},
diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json
index 6af493771d15..4e47ed69a720 100644
--- a/packages/utils/tsconfig.json
+++ b/packages/utils/tsconfig.json
@@ -6,6 +6,9 @@
{
"path": "../parser-services"
},
+ {
+ "path": "../rule-creator"
+ },
{
"path": "../typescript-estree"
},
diff --git a/yarn.lock b/yarn.lock
index 6eaa98aeb0ec..42542cafa12b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5512,6 +5512,7 @@ __metadata:
resolution: "@typescript-eslint/eslint-plugin-internal@workspace:packages/eslint-plugin-internal"
dependencies:
"@prettier/sync": ^0.5.1
+ "@typescript-eslint/rule-creator": "workspace:*"
"@typescript-eslint/rule-tester": "workspace:*"
"@typescript-eslint/scope-manager": "workspace:*"
"@typescript-eslint/type-utils": "workspace:*"
@@ -5530,6 +5531,7 @@ __metadata:
"@eslint-community/regexpp": ^4.10.0
"@types/mdast": ^4.0.3
"@types/natural-compare": "*"
+ "@typescript-eslint/rule-creator": 8.32.0
"@typescript-eslint/rule-schema-to-typescript-types": 8.32.0
"@typescript-eslint/rule-tester": 8.32.0
"@typescript-eslint/scope-manager": 8.32.0
@@ -5612,32 +5614,20 @@ __metadata:
languageName: unknown
linkType: soft
-"@typescript-eslint/rule-creator@workspace:packages/rule-creator":
+"@typescript-eslint/rule-creator@8.32.0, @typescript-eslint/rule-creator@workspace:*, @typescript-eslint/rule-creator@workspace:packages/rule-creator":
version: 0.0.0-use.local
resolution: "@typescript-eslint/rule-creator@workspace:packages/rule-creator"
dependencies:
- "@types/json-stable-stringify-without-jsonify": ^1.0.2
- "@types/lodash.merge": 4.6.9
- "@typescript-eslint/parser": 8.32.0
- "@typescript-eslint/types-eslint": 8.32.0
+ "@typescript-eslint/types": 8.32.0
"@typescript-eslint/typescript-estree": 8.32.0
- "@typescript-eslint/utils": 8.32.0
+ "@typescript-eslint/visitor-keys": 8.32.0
"@vitest/coverage-v8": ^3.1.2
- ajv: ^6.12.6
- chai: ^5.2.0
- eslint-visitor-keys: ^4.2.0
- espree: ^10.3.0
- esprima: ^4.0.1
- json-stable-stringify-without-jsonify: ^1.0.1
- lodash.merge: 4.6.2
- mocha: ^11.0.0
- semver: ^7.6.0
- sinon: ^20.0.0
- source-map-support: ^0.5.21
+ "@vitest/pretty-format": ^3.1.2
+ glob: "*"
+ prettier: ^3.2.5
+ rimraf: "*"
typescript: "*"
vitest: ^3.1.2
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
languageName: unknown
linkType: soft
@@ -5844,8 +5834,10 @@ __metadata:
dependencies:
"@eslint-community/eslint-utils": ^4.7.0
"@typescript-eslint/parser-services": 8.32.0
+ "@typescript-eslint/rule-creator": 8.32.0
"@typescript-eslint/scope-manager": 8.32.0
"@typescript-eslint/types": 8.32.0
+ "@typescript-eslint/types-eslint": 8.32.0
"@typescript-eslint/typescript-estree": 8.32.0
"@vitest/coverage-v8": ^3.1.3
prettier: ^3.2.5
--- a PPN by Garber Painting Akron. With Image Size Reduction included!Fetched URL: http://github.com/typescript-eslint/typescript-eslint/pull/11207.patch
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy