diff --git a/packages/plugin-typescript/eslint.config.js b/packages/plugin-typescript/eslint.config.js
new file mode 100644
index 000000000..40165321a
--- /dev/null
+++ b/packages/plugin-typescript/eslint.config.js
@@ -0,0 +1,21 @@
+import tseslint from 'typescript-eslint';
+import baseConfig from '../../eslint.config.js';
+
+export default tseslint.config(
+ ...baseConfig,
+ {
+ files: ['**/*.ts'],
+ languageOptions: {
+ parserOptions: {
+ projectService: true,
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+ },
+ {
+ files: ['**/*.json'],
+ rules: {
+ '@nx/dependency-checks': 'error',
+ },
+ },
+);
diff --git a/packages/plugin-typescript/package.json b/packages/plugin-typescript/package.json
new file mode 100644
index 000000000..aaf672e9f
--- /dev/null
+++ b/packages/plugin-typescript/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "@code-pushup/typescript-plugin",
+ "version": "0.57.0",
+ "license": "MIT",
+ "description": "Code PushUp plugin for incrementally adopting strict compilation flags in TypeScript projects",
+ "homepage": "https://github.com/code-pushup/cli/tree/main/packages/plugin-typescript#readme",
+ "bugs": {
+ "url": "https://github.com/code-pushup/cli/issues?q=is%3Aissue%20state%3Aopen%20type%3ABug%20label%3A\"🧩%20typescript-plugin\""
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/code-pushup/cli.git",
+ "directory": "packages/plugin-typescript"
+ },
+ "keywords": [
+ "CLI",
+ "Code PushUp",
+ "plugin",
+ "typescript"
+ ],
+ "publishConfig": {
+ "access": "public"
+ },
+ "type": "module",
+ "dependencies": {},
+ "scripts": {}
+}
diff --git a/packages/plugin-typescript/project.json b/packages/plugin-typescript/project.json
new file mode 100644
index 000000000..a34587731
--- /dev/null
+++ b/packages/plugin-typescript/project.json
@@ -0,0 +1,41 @@
+{
+ "name": "plugin-typescript",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "packages/plugin-typescript/src",
+ "projectType": "library",
+ "targets": {
+ "build": {
+ "executor": "@nx/js:tsc",
+ "outputs": ["{options.outputPath}"],
+ "options": {
+ "outputPath": "dist/packages/plugin-typescript",
+ "main": "packages/plugin-typescript/src/index.ts",
+ "tsConfig": "packages/plugin-typescript/tsconfig.lib.json",
+ "assets": ["packages/plugin-typescript/*.md"]
+ }
+ },
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": [
+ "packages/plugin-typescript/**/*.ts",
+ "packages/plugin-typescript/package.json"
+ ]
+ }
+ },
+ "unit-test": {
+ "executor": "@nx/vite:test",
+ "options": {
+ "configFile": "packages/plugin-typescript/vite.config.unit.ts"
+ }
+ },
+ "integration-test": {
+ "executor": "@nx/vite:test",
+ "options": {
+ "configFile": "packages/plugin-typescript/vite.config.integration.ts"
+ }
+ }
+ },
+ "tags": ["scope:plugin", "type:feature", "publishable"]
+}
diff --git a/packages/plugin-typescript/src/index.ts b/packages/plugin-typescript/src/index.ts
new file mode 100644
index 000000000..26c2b67c0
--- /dev/null
+++ b/packages/plugin-typescript/src/index.ts
@@ -0,0 +1 @@
+export { TYPESCRIPT_PLUGIN_SLUG } from './lib/constants.js';
diff --git a/packages/plugin-typescript/src/lib/constants.ts b/packages/plugin-typescript/src/lib/constants.ts
new file mode 100644
index 000000000..b5675c81c
--- /dev/null
+++ b/packages/plugin-typescript/src/lib/constants.ts
@@ -0,0 +1 @@
+export const TYPESCRIPT_PLUGIN_SLUG = 'typescript';
diff --git a/packages/plugin-typescript/tsconfig.json b/packages/plugin-typescript/tsconfig.json
new file mode 100644
index 000000000..893f9a925
--- /dev/null
+++ b/packages/plugin-typescript/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "module": "ESNext",
+ "forceConsistentCasingInFileNames": true,
+ "strict": true,
+ "noImplicitOverride": true,
+ "noPropertyAccessFromIndexSignature": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
+ "types": ["vitest"]
+ },
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ },
+ {
+ "path": "./tsconfig.test.json"
+ }
+ ]
+}
diff --git a/packages/plugin-typescript/tsconfig.lib.json b/packages/plugin-typescript/tsconfig.lib.json
new file mode 100644
index 000000000..ef2f7e2b3
--- /dev/null
+++ b/packages/plugin-typescript/tsconfig.lib.json
@@ -0,0 +1,16 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "declaration": true,
+ "types": ["node"]
+ },
+ "include": ["src/**/*.ts"],
+ "exclude": [
+ "vite.config.unit.ts",
+ "vite.config.integration.ts",
+ "src/**/*.test.ts",
+ "src/**/*.mock.ts",
+ "mocks/**/*.ts"
+ ]
+}
diff --git a/packages/plugin-typescript/tsconfig.test.json b/packages/plugin-typescript/tsconfig.test.json
new file mode 100644
index 000000000..bb1ab5e0c
--- /dev/null
+++ b/packages/plugin-typescript/tsconfig.test.json
@@ -0,0 +1,17 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"]
+ },
+ "include": [
+ "vite.config.unit.ts",
+ "vite.config.integration.ts",
+ "mocks/**/*.ts",
+ "src/**/*.test.ts",
+ "src/**/*.test.tsx",
+ "src/**/*.test.js",
+ "src/**/*.test.jsx",
+ "src/**/*.d.ts"
+ ]
+}
diff --git a/packages/plugin-typescript/vite.config.integration.ts b/packages/plugin-typescript/vite.config.integration.ts
new file mode 100644
index 000000000..9089de7bf
--- /dev/null
+++ b/packages/plugin-typescript/vite.config.integration.ts
@@ -0,0 +1,30 @@
+///
+import { defineConfig } from 'vite';
+import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js';
+
+export default defineConfig({
+ cacheDir: '../../node_modules/.vite/plugin-typescript',
+ test: {
+ reporters: ['basic'],
+ globals: true,
+ cache: {
+ dir: '../../node_modules/.vitest/plugin-typescript',
+ },
+ alias: tsconfigPathAliases(),
+ pool: 'threads',
+ poolOptions: { threads: { singleThread: true } },
+ coverage: {
+ reporter: ['text', 'lcov'],
+ reportsDirectory: '../../coverage/plugin-typescript/integration-tests',
+ exclude: ['mocks/**', '**/types.ts'],
+ },
+ environment: 'node',
+ include: ['src/**/*.integration.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
+ globalSetup: ['../../global-setup.ts'],
+ setupFiles: [
+ '../../testing/test-setup/src/lib/cliui.mock.ts',
+ '../../testing/test-setup/src/lib/reset.mocks.ts',
+ '../../testing/test-setup/src/lib/chrome-path.setup.ts',
+ ],
+ },
+});
diff --git a/packages/plugin-typescript/vite.config.unit.ts b/packages/plugin-typescript/vite.config.unit.ts
new file mode 100644
index 000000000..e7a8783f0
--- /dev/null
+++ b/packages/plugin-typescript/vite.config.unit.ts
@@ -0,0 +1,31 @@
+///
+import { defineConfig } from 'vite';
+import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js';
+
+export default defineConfig({
+ cacheDir: '../../node_modules/.vite/plugin-typescript',
+ test: {
+ reporters: ['basic'],
+ globals: true,
+ cache: {
+ dir: '../../node_modules/.vitest/plugin-typescript',
+ },
+ alias: tsconfigPathAliases(),
+ pool: 'threads',
+ poolOptions: { threads: { singleThread: true } },
+ coverage: {
+ reporter: ['text', 'lcov'],
+ reportsDirectory: '../../coverage/plugin-typescript/unit-tests',
+ exclude: ['mocks/**', '**/types.ts'],
+ },
+ environment: 'node',
+ include: ['src/**/*.unit.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
+ globalSetup: ['../../global-setup.ts'],
+ setupFiles: [
+ '../../testing/test-setup/src/lib/cliui.mock.ts',
+ '../../testing/test-setup/src/lib/fs.mock.ts',
+ '../../testing/test-setup/src/lib/console.mock.ts',
+ '../../testing/test-setup/src/lib/reset.mocks.ts',
+ ],
+ },
+});
diff --git a/tsconfig.base.json b/tsconfig.base.json
index d088eca5a..098bdf388 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -36,6 +36,9 @@
"@code-pushup/test-nx-utils": ["testing/test-nx-utils/src/index.ts"],
"@code-pushup/test-setup": ["testing/test-setup/src/index.ts"],
"@code-pushup/test-utils": ["testing/test-utils/src/index.ts"],
+ "@code-pushup/typescript-plugin": [
+ "packages/plugin-typescript/src/index.ts"
+ ],
"@code-pushup/utils": ["packages/utils/src/index.ts"]
}
},