├── .editorconfig ├── .gitignore ├── .prettierrc.json ├── README.md ├── docs └── README.md ├── env.d.ts ├── eslint.config.js ├── index.html ├── package-lock.json ├── package.json ├── playwright.config.ts ├── public └── favicon.ico ├── src ├── App.ts ├── App.vue ├── assets │ ├── base.css │ ├── logo.svg │ └── main.css ├── components │ ├── HelloWorld.ts │ ├── HelloWorld.vue │ ├── TheWelcome.vue │ ├── WelcomeItem.vue │ ├── __tests__ │ │ └── HelloWorld.spec.ts │ └── icons │ │ ├── IconCommunity.vue │ │ ├── IconDocumentation.vue │ │ ├── IconEcosystem.vue │ │ ├── IconSupport.vue │ │ └── IconTooling.vue ├── main.ts ├── router │ └── index.ts ├── stores │ └── counter.ts └── views │ ├── AboutView.vue │ └── HomeView.vue ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json ├── tsconfig.vitest.json ├── vite.config.ts └── vitest.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}] 2 | charset = utf-8 3 | indent_size = 2 4 | indent_style = space 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | 30 | *.tsbuildinfo 31 | 32 | test-results/ 33 | playwright-report/ 34 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "$schema": "https://json.schemastore.org/prettierrc", 4 | "semi": false, 5 | "singleQuote": true, 6 | "printWidth": 100 7 | } 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # web-decorator-vue-example 2 | ## 环境版本(推荐使用 node 18) 3 | - node v18.16.0 4 | ## 克隆项目 5 | ... 6 | ## 依赖项目 7 | ``` 8 | npm install 9 | ``` 10 | 11 | ### 运行环境 12 | ``` 13 | npm run serve 14 | ``` 15 | 16 | ### 编译项目 17 | ``` 18 | npm run build 19 | ``` 20 | ### 最新装饰器 21 | [vue 装饰器/注解 文档点这里](https://www.npmjs.com/package/web-decorator-vue). 22 | 23 | ### [如何从 0 开始搭建一个新项目](docs%2FREADME.md) 24 | 25 | ## 联系我们 26 | QQ 729694111 27 | 28 | ### Customize configuration 29 | See [Configuration Reference](https://cli.vuejs.org/config/). 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ### 如何在 vue3 中使用 (TS + 装饰器/注解) 2 | ### 为什么要用装饰器 3 | [请看点这里](https://segmentfault.com/a/1190000023471570) 4 | ## 创建vite项目 5 | ```` 6 | √ 请输入项目名称: ... 7 | √ 是否使用 TypeScript 语法? ... 是 8 | √ 是否启用 JSX 支持? ... 是 9 | √ 是否引入 Vue Router 进行单页面应用开发? ... 是 10 | √ 是否引入 Pinia 用于状态管理? ... 是 11 | √ 是否引入 Vitest 用于单元测试? ... 是 12 | √ 是否要引入一款端到端(End to End)测试工具? » Playwright 13 | √ 是否引入 ESLint 用于代码质量检测? ... 否 14 | 15 | ```` 16 | ### 安装 decorator 库 17 | ```` 18 | npm i web-decorator-vue 19 | ```` 20 | ### 配置装饰器 21 | - tsconfig.json 22 | - tsconfig.app.json 23 | - tsconfig.node.json 24 | - tsconfig.vitest.json 25 | ```` 26 | // 加入如下代码 "experimentalDecorators": true,"emitDecoratorMetadata": true, 27 | // 如下所示 28 | "compilerOptions": { 29 | "experimentalDecorators": true, 30 | "emitDecoratorMetadata": true, 31 | } 32 | ```` 33 | ### 修改代码 34 | ```` 35 | // HelloWorld.vue 36 | 45 | ```` 46 | ### 启动项目 47 | ```` 48 | npm run dev 49 | ```` 50 | --------- 51 | ## 通过 @vue/cli 创建项目 52 | ```` 53 | npm install -g @vue/cli 54 | # OR 55 | yarn global add @vue/cli 56 | ```` 57 | ### 新建项目 58 | ```` 59 | // 输入指令创建 app 60 | vue create my-project 61 | // 选择自定义 62 | - 选择[ Manually select features ] 63 | // 选中 64 | ? Please pick a preset: Manually select features 65 | ? Check the features needed for your project: (Press to select, to toggle all, to invert selection, and 66 | to proceed) 67 | (*) Babel 68 | (*) TypeScript 69 | ( ) Progressive Web App (PWA) Support 70 | (*) Router 71 | (*) Vuex 72 | ( ) CSS Pre-processors 73 | ( ) Linter / Formatter 74 | ( ) Unit Testing 75 | ( ) E2E Testing 76 | ```` 77 | ### 运行指令删除不在维护的 vue-class-component 库 78 | ```` 79 | npm uninstall vue-class-component 80 | ```` 81 | ### 依赖 web-decorator-vue 82 | ```` 83 | npm i web-decorator-vue -S 84 | ```` 85 | ### 更新代码中的注解 HomeView.vue 86 | ````ts 87 | import { Component, VueHook } from "web-decorator-vue"; 88 | import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src 89 | @Component({ 90 | components: { 91 | HelloWorld, 92 | }, 93 | }) 94 | export default class HomeView { 95 | } 96 | ```` 97 | ### HelloWorld.vue 98 | ````ts 99 | import { Component, Prop } from "web-decorator-vue"; 100 | @Component() 101 | export default class HelloWorld { 102 | @Prop({type: String, default: ""}) msg!: string; 103 | } 104 | ```` 105 | ### 运行 106 | ```` 107 | npm run dev 108 | ```` 109 | 110 | ### 注意如果选中 Linter / Formatter 111 | - 开启装饰器 tsconfig.json 112 | ````json 113 | "compilerOptions": { 114 | "experimentalDecorators": true, 115 | "emitDecoratorMetadata": true, 116 | } 117 | ```` 118 | 119 | ### 装饰器文档 120 | [vue 装饰器/注解 文档点这里](https://www.npmjs.com/package/web-decorator-vue). 121 | 122 | - 在 vue.config 中关闭eslint(根据实际情况配置) 123 | ````js 124 | // 此处只做快速关闭,实际根据自身情况来关闭。 125 | lintOnSave:false 126 | ```` 127 | ### [项目demo项目链接](https://github.com/waliu/web-decorator-vue-example) 128 | 129 | ## 联系我们 130 | QQ群 729694111 131 | -------------------------------------------------------------------------------- /env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import pluginVue from 'eslint-plugin-vue' 2 | import vueTsEslintConfig from '@vue/eslint-config-typescript' 3 | import pluginVitest from '@vitest/eslint-plugin' 4 | import pluginPlaywright from 'eslint-plugin-playwright' 5 | import skipFormatting from '@vue/eslint-config-prettier/skip-formatting' 6 | 7 | export default [ 8 | { 9 | name: 'app/files-to-lint', 10 | files: ['**/*.{ts,mts,tsx,vue}'], 11 | }, 12 | 13 | { 14 | name: 'app/files-to-ignore', 15 | ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**'], 16 | }, 17 | 18 | ...pluginVue.configs['flat/essential'], 19 | ...vueTsEslintConfig(), 20 | 21 | { 22 | ...pluginVitest.configs.recommended, 23 | files: ['src/**/__tests__/*'], 24 | }, 25 | 26 | { 27 | ...pluginPlaywright.configs['flat/recommended'], 28 | files: ['e2e/**/*.{test,spec}.{js,ts,jsx,tsx}'], 29 | }, 30 | skipFormatting, 31 | ] 32 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-decorator-vue-example", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "run-p type-check \"build-only {@}\" --", 9 | "preview": "vite preview", 10 | "test:unit": "vitest", 11 | "test:e2e": "playwright test", 12 | "build-only": "vite build", 13 | "type-check": "vue-tsc --build --force", 14 | "lint": "eslint . --fix", 15 | "format": "prettier --write src/" 16 | }, 17 | "dependencies": { 18 | "pinia": "^2.2.6", 19 | "vue": "^3.5.12", 20 | "vue-router": "^4.4.5", 21 | "web-decorator-vue": "^1.1.5" 22 | }, 23 | "devDependencies": { 24 | "@playwright/test": "^1.48.2", 25 | "@tsconfig/node22": "^22.0.0", 26 | "@types/jsdom": "^21.1.7", 27 | "@types/node": "^22.9.0", 28 | "@vitejs/plugin-vue": "^5.1.4", 29 | "@vitejs/plugin-vue-jsx": "^4.0.1", 30 | "@vitest/eslint-plugin": "1.1.7", 31 | "@vue/eslint-config-prettier": "^10.1.0", 32 | "@vue/eslint-config-typescript": "^14.1.3", 33 | "@vue/test-utils": "^2.4.6", 34 | "@vue/tsconfig": "^0.5.1", 35 | "eslint": "^9.14.0", 36 | "eslint-plugin-playwright": "^2.0.0", 37 | "eslint-plugin-vue": "^9.30.0", 38 | "jsdom": "^25.0.1", 39 | "npm-run-all2": "^7.0.1", 40 | "prettier": "^3.3.3", 41 | "typescript": "~5.6.3", 42 | "vite": "^5.4.10", 43 | "vite-plugin-vue-devtools": "^7.5.4", 44 | "vitest": "^2.1.4", 45 | "vue-tsc": "^2.1.10" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /playwright.config.ts: -------------------------------------------------------------------------------- 1 | import process from 'node:process' 2 | import { defineConfig, devices } from '@playwright/test' 3 | 4 | /** 5 | * Read environment variables from file. 6 | * https://github.com/motdotla/dotenv 7 | */ 8 | // require('dotenv').config(); 9 | 10 | /** 11 | * See https://playwright.dev/docs/test-configuration. 12 | */ 13 | export default defineConfig({ 14 | testDir: './e2e', 15 | /* Maximum time one test can run for. */ 16 | timeout: 30 * 1000, 17 | expect: { 18 | /** 19 | * Maximum time expect() should wait for the condition to be met. 20 | * For example in `await expect(locator).toHaveText();` 21 | */ 22 | timeout: 5000, 23 | }, 24 | /* Fail the build on CI if you accidentally left test.only in the source code. */ 25 | forbidOnly: !!process.env.CI, 26 | /* Retry on CI only */ 27 | retries: process.env.CI ? 2 : 0, 28 | /* Opt out of parallel tests on CI. */ 29 | workers: process.env.CI ? 1 : undefined, 30 | /* Reporter to use. See https://playwright.dev/docs/test-reporters */ 31 | reporter: 'html', 32 | /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ 33 | use: { 34 | /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ 35 | actionTimeout: 0, 36 | /* Base URL to use in actions like `await page.goto('/')`. */ 37 | baseURL: process.env.CI ? 'http://localhost:4173' : 'http://localhost:5173', 38 | 39 | /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ 40 | trace: 'on-first-retry', 41 | 42 | /* Only on CI systems run the tests headless */ 43 | headless: !!process.env.CI, 44 | }, 45 | 46 | /* Configure projects for major browsers */ 47 | projects: [ 48 | { 49 | name: 'chromium', 50 | use: { 51 | ...devices['Desktop Chrome'], 52 | }, 53 | }, 54 | { 55 | name: 'firefox', 56 | use: { 57 | ...devices['Desktop Firefox'], 58 | }, 59 | }, 60 | { 61 | name: 'webkit', 62 | use: { 63 | ...devices['Desktop Safari'], 64 | }, 65 | }, 66 | 67 | /* Test against mobile viewports. */ 68 | // { 69 | // name: 'Mobile Chrome', 70 | // use: { 71 | // ...devices['Pixel 5'], 72 | // }, 73 | // }, 74 | // { 75 | // name: 'Mobile Safari', 76 | // use: { 77 | // ...devices['iPhone 12'], 78 | // }, 79 | // }, 80 | 81 | /* Test against branded browsers. */ 82 | // { 83 | // name: 'Microsoft Edge', 84 | // use: { 85 | // channel: 'msedge', 86 | // }, 87 | // }, 88 | // { 89 | // name: 'Google Chrome', 90 | // use: { 91 | // channel: 'chrome', 92 | // }, 93 | // }, 94 | ], 95 | 96 | /* Folder for test artifacts such as screenshots, videos, traces, etc. */ 97 | // outputDir: 'test-results/', 98 | 99 | /* Run your local dev server before starting the tests */ 100 | webServer: { 101 | /** 102 | * Use the dev server by default for faster feedback loop. 103 | * Use the preview server on CI for more realistic testing. 104 | * Playwright will re-use the local server if there is already a dev-server running. 105 | */ 106 | command: process.env.CI ? 'npm run preview' : 'npm run dev', 107 | port: process.env.CI ? 4173 : 5173, 108 | reuseExistingServer: !process.env.CI, 109 | }, 110 | }) 111 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waliu/web-decorator-vue-example/fa37625d153ced9b7449696ec69d400741a79a60/public/favicon.ico -------------------------------------------------------------------------------- /src/App.ts: -------------------------------------------------------------------------------- 1 | import { Component } from 'web-decorator-vue' 2 | import { RouterLink, RouterView } from 'vue-router' 3 | import HelloWorld from './components/HelloWorld.vue' 4 | @Component({ 5 | name: 'app-root', 6 | components: { 7 | HelloWorld, 8 | RouterLink, 9 | RouterView 10 | } 11 | }) 12 | export default class AppRoot {} 13 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 83 | -------------------------------------------------------------------------------- /src/assets/base.css: -------------------------------------------------------------------------------- 1 | /* color palette from */ 2 | :root { 3 | --vt-c-white: #ffffff; 4 | --vt-c-white-soft: #f8f8f8; 5 | --vt-c-white-mute: #f2f2f2; 6 | 7 | --vt-c-black: #181818; 8 | --vt-c-black-soft: #222222; 9 | --vt-c-black-mute: #282828; 10 | 11 | --vt-c-indigo: #2c3e50; 12 | 13 | --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); 14 | --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); 15 | --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); 16 | --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); 17 | 18 | --vt-c-text-light-1: var(--vt-c-indigo); 19 | --vt-c-text-light-2: rgba(60, 60, 60, 0.66); 20 | --vt-c-text-dark-1: var(--vt-c-white); 21 | --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); 22 | } 23 | 24 | /* semantic color variables for this project */ 25 | :root { 26 | --color-background: var(--vt-c-white); 27 | --color-background-soft: var(--vt-c-white-soft); 28 | --color-background-mute: var(--vt-c-white-mute); 29 | 30 | --color-border: var(--vt-c-divider-light-2); 31 | --color-border-hover: var(--vt-c-divider-light-1); 32 | 33 | --color-heading: var(--vt-c-text-light-1); 34 | --color-text: var(--vt-c-text-light-1); 35 | 36 | --section-gap: 160px; 37 | } 38 | 39 | @media (prefers-color-scheme: dark) { 40 | :root { 41 | --color-background: var(--vt-c-black); 42 | --color-background-soft: var(--vt-c-black-soft); 43 | --color-background-mute: var(--vt-c-black-mute); 44 | 45 | --color-border: var(--vt-c-divider-dark-2); 46 | --color-border-hover: var(--vt-c-divider-dark-1); 47 | 48 | --color-heading: var(--vt-c-text-dark-1); 49 | --color-text: var(--vt-c-text-dark-2); 50 | } 51 | } 52 | 53 | *, 54 | *::before, 55 | *::after { 56 | box-sizing: border-box; 57 | margin: 0; 58 | font-weight: normal; 59 | } 60 | 61 | body { 62 | min-height: 100vh; 63 | color: var(--color-text); 64 | background: var(--color-background); 65 | transition: 66 | color 0.5s, 67 | background-color 0.5s; 68 | line-height: 1.6; 69 | font-family: 70 | Inter, 71 | -apple-system, 72 | BlinkMacSystemFont, 73 | 'Segoe UI', 74 | Roboto, 75 | Oxygen, 76 | Ubuntu, 77 | Cantarell, 78 | 'Fira Sans', 79 | 'Droid Sans', 80 | 'Helvetica Neue', 81 | sans-serif; 82 | font-size: 15px; 83 | text-rendering: optimizeLegibility; 84 | -webkit-font-smoothing: antialiased; 85 | -moz-osx-font-smoothing: grayscale; 86 | } 87 | -------------------------------------------------------------------------------- /src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | 3 | #app { 4 | max-width: 1280px; 5 | margin: 0 auto; 6 | padding: 2rem; 7 | font-weight: normal; 8 | } 9 | 10 | a, 11 | .green { 12 | text-decoration: none; 13 | color: hsla(160, 100%, 37%, 1); 14 | transition: 0.4s; 15 | padding: 3px; 16 | } 17 | 18 | @media (hover: hover) { 19 | a:hover { 20 | background-color: hsla(160, 100%, 37%, 0.2); 21 | } 22 | } 23 | 24 | @media (min-width: 1024px) { 25 | body { 26 | display: flex; 27 | place-items: center; 28 | } 29 | 30 | #app { 31 | display: grid; 32 | grid-template-columns: 1fr 1fr; 33 | padding: 0 2rem; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/components/HelloWorld.ts: -------------------------------------------------------------------------------- 1 | import { Component, Prop } from 'web-decorator-vue' 2 | 3 | @Component( 4 | { 5 | name: 'hello-world', 6 | } 7 | ) 8 | export default class HelloWorld { 9 | /** 10 | * Prop meg消息 11 | */ 12 | @Prop() msg!: string; 13 | } 14 | -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 38 | -------------------------------------------------------------------------------- /src/components/TheWelcome.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 91 | -------------------------------------------------------------------------------- /src/components/WelcomeItem.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 88 | -------------------------------------------------------------------------------- /src/components/__tests__/HelloWorld.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest' 2 | 3 | import { mount } from '@vue/test-utils' 4 | import HelloWorld from '../HelloWorld.vue' 5 | 6 | describe('HelloWorld', () => { 7 | it('renders properly', () => { 8 | const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) 9 | expect(wrapper.text()).toContain('Hello Vitest') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /src/components/icons/IconCommunity.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/components/icons/IconDocumentation.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/components/icons/IconEcosystem.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/components/icons/IconSupport.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/components/icons/IconTooling.vue: -------------------------------------------------------------------------------- 1 | 2 | 20 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import './assets/main.css' 2 | 3 | import { createApp } from 'vue' 4 | import { createPinia } from 'pinia' 5 | 6 | import App from './App.vue' 7 | import router from './router' 8 | 9 | const app = createApp(App) 10 | 11 | app.use(createPinia()) 12 | app.use(router) 13 | 14 | app.mount('#app') 15 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | import HomeView from '../views/HomeView.vue' 3 | 4 | const router = createRouter({ 5 | history: createWebHistory(import.meta.env.BASE_URL), 6 | routes: [ 7 | { 8 | path: '/', 9 | name: 'home', 10 | component: HomeView, 11 | }, 12 | { 13 | path: '/about', 14 | name: 'about', 15 | // route level code-splitting 16 | // this generates a separate chunk (About.[hash].js) for this route 17 | // which is lazy-loaded when the route is visited. 18 | component: () => import('../views/AboutView.vue'), 19 | }, 20 | ], 21 | }) 22 | 23 | export default router 24 | -------------------------------------------------------------------------------- /src/stores/counter.ts: -------------------------------------------------------------------------------- 1 | import { ref, computed } from 'vue' 2 | import { defineStore } from 'pinia' 3 | 4 | export const useCounterStore = defineStore('counter', () => { 5 | const count = ref(0) 6 | const doubleCount = computed(() => count.value * 2) 7 | function increment() { 8 | count.value++ 9 | } 10 | 11 | return { count, doubleCount, increment } 12 | }) 13 | -------------------------------------------------------------------------------- /src/views/AboutView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /src/views/HomeView.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 8 | 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["./src/*"] 12 | }, 13 | "experimentalDecorators": true, 14 | "emitDecoratorMetadata": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.node.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | }, 10 | { 11 | "path": "./tsconfig.vitest.json" 12 | } 13 | ], 14 | "compilerOptions": { 15 | "experimentalDecorators": true, 16 | "emitDecoratorMetadata": true, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node22/tsconfig.json", 3 | "include": [ 4 | "vite.config.*", 5 | "vitest.config.*", 6 | "cypress.config.*", 7 | "nightwatch.conf.*", 8 | "playwright.config.*" 9 | ], 10 | "compilerOptions": { 11 | "composite": true, 12 | "noEmit": true, 13 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 14 | 15 | "module": "ESNext", 16 | "moduleResolution": "Bundler", 17 | "types": ["node"], 18 | "experimentalDecorators": true, 19 | "emitDecoratorMetadata": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.vitest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.app.json", 3 | "exclude": [], 4 | "compilerOptions": { 5 | "composite": true, 6 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", 7 | 8 | "lib": [], 9 | "types": ["node", "jsdom"], 10 | "experimentalDecorators": true, 11 | "emitDecoratorMetadata": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | import vueJsx from '@vitejs/plugin-vue-jsx' 6 | import vueDevTools from 'vite-plugin-vue-devtools' 7 | 8 | // https://vite.dev/config/ 9 | export default defineConfig({ 10 | plugins: [ 11 | vue(), 12 | vueJsx(), 13 | vueDevTools(), 14 | ], 15 | resolve: { 16 | alias: { 17 | '@': fileURLToPath(new URL('./src', import.meta.url)) 18 | }, 19 | }, 20 | }) 21 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url' 2 | import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' 3 | import viteConfig from './vite.config' 4 | 5 | export default mergeConfig( 6 | viteConfig, 7 | defineConfig({ 8 | test: { 9 | environment: 'jsdom', 10 | exclude: [...configDefaults.exclude, 'e2e/**'], 11 | root: fileURLToPath(new URL('./', import.meta.url)), 12 | }, 13 | }), 14 | ) 15 | --------------------------------------------------------------------------------