From 3c9fd3052f088d04f3e17ece16681319cbd5b1a0 Mon Sep 17 00:00:00 2001 From: Jakob Scheid Date: Sat, 24 Oct 2026 23:05:32 +0200 Subject: [PATCH] chore: add TypeScript support Added TypeScript configuration for Vite and Node (tsconfig.app.json and tsconfig.node.json, referenced in tsconfig.json). Vite configuration was migrated to TypeScript. Added ESLint TypeScript rules and general ESLint TypeScript configuration. Npm scripts for type checking have been added and build script has been updated to run type checking script before building. --- .prettierignore | 1 - eslint.config.js | 95 +++++++++++++++++++++++--------- package.json | 4 +- tsconfig.app.json | 32 +++++++++++ tsconfig.json | 11 ++++ tsconfig.node.json | 31 +++++++++++ vite.config.js => vite.config.ts | 6 +- 7 files changed, 149 insertions(+), 31 deletions(-) create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json rename vite.config.js => vite.config.ts (85%) diff --git a/.prettierignore b/.prettierignore index c7390de..163bed0 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,2 @@ .gitea/ .github/ -eslint.config.js diff --git a/eslint.config.js b/eslint.config.js index 0072245..54b01d0 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,11 +1,40 @@ import js from '@eslint/js'; import { defineConfig } from 'eslint/config'; import pluginVue from 'eslint-plugin-vue'; +import tseslint from 'typescript-eslint'; +import vueParser from 'vue-eslint-parser'; import globals from 'globals'; +const commonRules = { + 'eqeqeq': 'error', // prettier-ignore + + 'prefer-const': 'error', + 'no-var': 'error', + 'no-duplicate-imports': 'error', + 'no-import-assign': 'error', + + 'prefer-arrow-callback': 'error', + 'require-await': 'warn', + 'no-async-promise-executor': 'error', + + 'no-unreachable': 'error', + 'no-constant-condition': 'error', + + 'no-debugger': 'error', + 'no-alert': 'error', + 'no-console': 'warn', + + 'no-new-object': 'error', + 'no-array-constructor': 'error', + 'no-prototype-builtins': 'error', + 'object-shorthand': 'error', + + 'prefer-template': 'error', +}; + export default defineConfig([ { - files: ['**/*.{js,mjs,cjs,vue}'], + files: ['**/*.{js,mjs,cjs,ts,mts,cts,vue}'], plugins: { js }, extends: ['js/recommended'], languageOptions: { @@ -14,37 +43,51 @@ export default defineConfig([ ...globals.node, }, }, - rules: { - 'eqeqeq': 'error', + rules: commonRules, + }, + pluginVue.configs['flat/essential'], + + { + files: ['**/*.{js,mjs,cjs}'], + rules: { 'no-unused-vars': 'error', 'no-undef': 'error', - 'prefer-const': 'error', - 'no-var': 'error', - 'no-duplicate-imports': 'error', - 'no-import-assign': 'error', 'no-empty-function': 'error', 'default-param-last': 'error', - 'prefer-arrow-callback': 'error', - 'require-await': 'warn', - 'no-async-promise-executor': 'error', - - 'no-unreachable': 'error', - - 'no-constant-condition': 'error', - - 'no-debugger': 'error', - 'no-alert': 'error', - 'no-console': 'warn', - - 'no-new-object': 'error', - 'no-array-constructor': 'error', - 'no-prototype-builtins': 'error', - 'object-shorthand': 'error', - - 'prefer-template': 'error', }, }, - pluginVue.configs['flat/essential'], + + { + files: ['**/*.{ts,mts,cts,vue}'], + extends: [tseslint.configs.recommended], + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + }, + }, + rules: { + 'no-undef': 'off', + + '@typescript-eslint/no-unused-vars': 'error', + '@typescript-eslint/no-empty-function': 'error', + '@typescript-eslint/default-param-last': 'error', + + '@typescript-eslint/consistent-type-imports': 'error', + '@typescript-eslint/no-explicit-any': 'warn', + }, + }, + + { + files: ['**/*.vue'], + languageOptions: { + parser: vueParser, + parserOptions: { + parser: tseslint.parser, + extraFileExtensions: ['.vue'], + }, + }, + }, ]); diff --git a/package.json b/package.json index fcf9ac9..237f7ab 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,10 @@ "type": "module", "scripts": { "dev": "vite", - "build": "vite build", + "build": "npm run type-check && vite build", "preview": "vite preview", + "type-check": "vue-tsc --noEmit -p tsconfig.app.json && tsc --noEmit -p tsconfig.node.json", + "type-check:watch": "vue-tsc --noEmit -p tsconfig.app.json --watch", "test": "vitest", "test:run": "vitest run", "lint": "eslint .", diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..187f714 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "esnext", + "moduleResolution": "bundler", + + "strict": true, + "noEmit": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "noImplicitAny": true, + + "allowJs": true, + "checkJs": false, + + "resolveJsonModule": true, + "skipLibCheck": true, + "types": ["vite/client"], + + "paths": { + "@/*": ["./src/*"] + }, + + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "useDefineForClassFields": true, + "jsx": "preserve", + "esModuleInterop": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.vue"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..41ccf0f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..3fb8912 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": ["ES2020"], + + "module": "esnext", + "moduleResolution": "bundler", + + "strict": true, + "noEmit": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "noImplicitAny": true, + + "allowJs": true, + "checkJs": false, + + "skipLibCheck": true, + "types": ["node"], + + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo" + }, + "include": [ + "vite.config.js", + "vite.config.ts", + "vitest.config.js", + "vitest.config.ts", + "eslint.config.js", + "eslint.config.ts" + ] +} diff --git a/vite.config.js b/vite.config.ts similarity index 85% rename from vite.config.js rename to vite.config.ts index 891f26f..e5e5790 100644 --- a/vite.config.js +++ b/vite.config.ts @@ -15,8 +15,8 @@ limitations under the License. */ import vue from '@vitejs/plugin-vue'; -import path from 'path'; -import { defineConfig } from 'vite'; +import { fileURLToPath, URL } from 'node:url'; +import { defineConfig } from 'vitest/config'; import { createHtmlPlugin } from 'vite-plugin-html'; // https://vite.dev/config/ @@ -32,7 +32,7 @@ export default defineConfig({ ], resolve: { alias: { - '@': path.resolve(__dirname, './src'), + '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, test: {