├── .DS_Store ├── .dockerignore ├── .editorconfig ├── .gitignore ├── README.md ├── backend ├── .gitignore ├── README.md ├── eslint.config.js ├── nest-cli.json ├── package.json ├── src │ ├── app.controller.ts │ ├── app.module.ts │ ├── app.service.ts │ └── main.ts ├── test │ ├── app.e2e-spec.ts │ └── jest-e2e.json ├── tsconfig.build.json └── tsconfig.json ├── eslint.config.js ├── frontend ├── .dockerignore ├── .editorconfig ├── .github │ └── workflows │ │ └── ci.yml ├── .vscode │ ├── extensions.json │ └── settings.json ├── Dockerfile ├── LICENSE ├── README.md ├── README.zh-CN.md ├── cypress.config.ts ├── cypress │ ├── e2e │ │ └── basic.spec.ts │ └── tsconfig.json ├── eslint.config.js ├── index.html ├── locales │ ├── README.md │ ├── ar.yml │ ├── de.yml │ ├── en.yml │ ├── es.yml │ ├── fr.yml │ ├── id.yml │ ├── it.yml │ ├── ja.yml │ ├── ka.yml │ ├── ko.yml │ ├── pl.yml │ ├── pt-BR.yml │ ├── ru.yml │ ├── tr.yml │ ├── uk.yml │ ├── uz.yml │ ├── vi.yml │ └── zh-CN.yml ├── netlify.toml ├── package.json ├── public │ ├── _headers │ ├── favicon-dark.svg │ ├── favicon.svg │ ├── pwa-192x192.png │ ├── pwa-512x512.png │ └── safari-pinned-tab.svg ├── src │ ├── App.vue │ ├── auto-imports.d.ts │ ├── components.d.ts │ ├── components │ │ ├── README.md │ │ ├── TheCounter.vue │ │ ├── TheFooter.vue │ │ └── TheInput.vue │ ├── composables │ │ └── dark.ts │ ├── layouts │ │ ├── 404.vue │ │ ├── README.md │ │ ├── default.vue │ │ └── home.vue │ ├── main.ts │ ├── modules │ │ ├── README.md │ │ ├── i18n.ts │ │ ├── nprogress.ts │ │ ├── pinia.ts │ │ └── pwa.ts │ ├── pages │ │ ├── README.md │ │ ├── [...all].vue │ │ ├── about.md │ │ ├── hi │ │ │ └── [name].vue │ │ └── index.vue │ ├── shims.d.ts │ ├── stores │ │ └── user.ts │ ├── styles │ │ ├── main.css │ │ └── markdown.css │ ├── typed-router.d.ts │ └── types.ts ├── test │ ├── __snapshots__ │ │ └── component.test.ts.snap │ ├── basic.test.ts │ └── component.test.ts ├── tsconfig.json ├── uno.config.ts └── vite.config.ts ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── vitest.workspace.ts /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Groupguanfang/bt/5ffd4bf25b8f9640d55397fce182bf43671e98ed/.DS_Store -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | dist 3 | node_modules 4 | build 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | pnpm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | lerna-debug.log* 14 | 15 | # OS 16 | .DS_Store 17 | 18 | # Tests 19 | coverage 20 | .nyc_output 21 | 22 | # IDEs and editors 23 | .idea 24 | .project 25 | .classpath 26 | .c9/ 27 | *.launch 28 | .settings/ 29 | *.sublime-workspace 30 | 31 | # IDE - VSCode 32 | .vscode/* 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json 36 | 37 | # dotenv environment variable files 38 | .env 39 | .env.development.local 40 | .env.test.local 41 | .env.production.local 42 | .env.local 43 | 44 | # temp directory 45 | .temp 46 | .tmp 47 | 48 | # Runtime data 49 | pids 50 | *.pid 51 | *.seed 52 | *.pid.lock 53 | 54 | # Diagnostic reports (https://nodejs.org/api/report.html) 55 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Monorepo 2 | 3 | > There are no descriptions for this repository. 4 | -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Groupguanfang/bt/5ffd4bf25b8f9640d55397fce182bf43671e98ed/backend/.gitignore -------------------------------------------------------------------------------- /backend/README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 6 | [circleci-url]: https://circleci.com/gh/nestjs/nest 7 | 8 |

A progressive Node.js framework for building efficient and scalable server-side applications.

9 |

10 | NPM Version 11 | Package License 12 | NPM Downloads 13 | CircleCI 14 | Coverage 15 | Discord 16 | Backers on Open Collective 17 | Sponsors on Open Collective 18 | Donate us 19 | Support us 20 | Follow us on Twitter 21 |

22 | 24 | 25 | ## Description 26 | 27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. 28 | 29 | ## Project setup 30 | 31 | ```bash 32 | $ pnpm install 33 | ``` 34 | 35 | ## Compile and run the project 36 | 37 | ```bash 38 | # development 39 | $ pnpm run start 40 | 41 | # watch mode 42 | $ pnpm run start:dev 43 | 44 | # production mode 45 | $ pnpm run start:prod 46 | ``` 47 | 48 | ## Run tests 49 | 50 | ```bash 51 | # unit tests 52 | $ pnpm run test 53 | 54 | # e2e tests 55 | $ pnpm run test:e2e 56 | 57 | # test coverage 58 | $ pnpm run test:cov 59 | ``` 60 | 61 | ## Deployment 62 | 63 | When you're ready to deploy your NestJS application to production, there are some key steps you can take to ensure it runs as efficiently as possible. Check out the [deployment documentation](https://docs.nestjs.com/deployment) for more information. 64 | 65 | If you are looking for a cloud-based platform to deploy your NestJS application, check out [Mau](https://mau.nestjs.com), our official platform for deploying NestJS applications on AWS. Mau makes deployment straightforward and fast, requiring just a few simple steps: 66 | 67 | ```bash 68 | $ pnpm install -g mau 69 | $ mau deploy 70 | ``` 71 | 72 | With Mau, you can deploy your application in just a few clicks, allowing you to focus on building features rather than managing infrastructure. 73 | 74 | ## Resources 75 | 76 | Check out a few resources that may come in handy when working with NestJS: 77 | 78 | - Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework. 79 | - For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy). 80 | - To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/). 81 | - Deploy your application to AWS with the help of [NestJS Mau](https://mau.nestjs.com) in just a few clicks. 82 | - Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com). 83 | - Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com). 84 | - To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs). 85 | - Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com). 86 | 87 | ## Support 88 | 89 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). 90 | 91 | ## Stay in touch 92 | 93 | - Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec) 94 | - Website - [https://nestjs.com](https://nestjs.com/) 95 | - Twitter - [@nestframework](https://twitter.com/nestframework) 96 | 97 | ## License 98 | 99 | Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE). 100 | -------------------------------------------------------------------------------- /backend/eslint.config.js: -------------------------------------------------------------------------------- 1 | import antfu from '@antfu/eslint-config' 2 | 3 | export default antfu({ 4 | rules: { 5 | 'ts/consistent-type-imports': 'off', 6 | }, 7 | }) 8 | -------------------------------------------------------------------------------- /backend/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src", 5 | "compilerOptions": { 6 | "deleteOutDir": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "private": true, 6 | "description": "", 7 | "author": "Naily Zero ", 8 | "scripts": { 9 | "build": "nest build", 10 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", 11 | "start": "nest start", 12 | "start:dev": "nest start --watch", 13 | "start:debug": "nest start --debug --watch", 14 | "start:prod": "node dist/main", 15 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", 16 | "test": "jest", 17 | "test:watch": "jest --watch", 18 | "test:cov": "jest --coverage", 19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", 20 | "test:e2e": "jest --config ./test/jest-e2e.json" 21 | }, 22 | "dependencies": { 23 | "@nestjs/common": "^10.0.0", 24 | "@nestjs/core": "10.3.6", 25 | "@nestjs/platform-express": "^10.0.0", 26 | "nestjs-trpc": "^1.5.1", 27 | "reflect-metadata": "^0.2.0", 28 | "rxjs": "^7.8.1" 29 | }, 30 | "devDependencies": { 31 | "@nestjs/cli": "^10.0.0", 32 | "@nestjs/schematics": "^10.0.0", 33 | "@nestjs/testing": "^10.0.0", 34 | "@types/express": "^5.0.0", 35 | "@types/jest": "^29.5.2", 36 | "@types/node": "^20.3.1", 37 | "@types/supertest": "^6.0.0", 38 | "@typescript-eslint/eslint-plugin": "^8.0.0", 39 | "@typescript-eslint/parser": "^8.0.0", 40 | "eslint": "^9.0.0", 41 | "eslint-config-prettier": "^9.0.0", 42 | "eslint-plugin-prettier": "^5.0.0", 43 | "jest": "^29.5.0", 44 | "prettier": "^3.0.0", 45 | "source-map-support": "^0.5.21", 46 | "supertest": "^7.0.0", 47 | "ts-jest": "^29.1.0", 48 | "ts-loader": "^9.4.3", 49 | "ts-node": "^10.9.1", 50 | "tsconfig-paths": "^4.2.0", 51 | "typescript": "^5.1.3" 52 | }, 53 | "jest": { 54 | "moduleFileExtensions": [ 55 | "js", 56 | "json", 57 | "ts" 58 | ], 59 | "rootDir": "src", 60 | "testRegex": ".*\\.spec\\.ts$", 61 | "transform": { 62 | "^.+\\.(t|j)s$": "ts-jest" 63 | }, 64 | "collectCoverageFrom": [ 65 | "**/*.(t|j)s" 66 | ], 67 | "coverageDirectory": "../coverage", 68 | "testEnvironment": "node" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /backend/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import type { AppService } from './app.service' 2 | import { Controller, Get } from '@nestjs/common' 3 | 4 | @Controller() 5 | export class AppController { 6 | constructor(private readonly appService: AppService) {} 7 | 8 | @Get() 9 | getHello(): string { 10 | return this.appService.getHello() 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common' 2 | import { TRPCModule } from 'nestjs-trpc' 3 | import { AppController } from './app.controller' 4 | import { AppService } from './app.service' 5 | 6 | @Module({ 7 | imports: [ 8 | TRPCModule.forRoot({ 9 | autoSchemaFile: './src/@generated', 10 | }), 11 | ], 12 | controllers: [AppController], 13 | providers: [AppService], 14 | }) 15 | export class AppModule {} 16 | -------------------------------------------------------------------------------- /backend/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common' 2 | 3 | @Injectable() 4 | export class AppService { 5 | getHello(): string { 6 | return 'Hello World!' 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/src/main.ts: -------------------------------------------------------------------------------- 1 | import { env } from 'node:process' 2 | import { NestFactory } from '@nestjs/core' 3 | import { AppModule } from './app.module' 4 | 5 | async function bootstrap() { 6 | const app = await NestFactory.create(AppModule) 7 | await app.listen(env.PORT ?? 3000) 8 | } 9 | bootstrap() 10 | -------------------------------------------------------------------------------- /backend/test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import type { INestApplication } from '@nestjs/common' 2 | import type { TestingModule } from '@nestjs/testing' 3 | import { Test } from '@nestjs/testing' 4 | import * as request from 'supertest' 5 | import { AppModule } from './../src/app.module' 6 | 7 | describe('AppController (e2e)', () => { 8 | let app: INestApplication 9 | 10 | beforeEach(async () => { 11 | const moduleFixture: TestingModule = await Test.createTestingModule({ 12 | imports: [AppModule], 13 | }).compile() 14 | 15 | app = moduleFixture.createNestApplication() 16 | await app.init() 17 | }) 18 | 19 | it('/ (GET)', () => { 20 | return request(app.getHttpServer()) 21 | .get('/') 22 | .expect(200) 23 | .expect('Hello World!') 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /backend/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "incremental": true, 4 | "target": "ES2021", 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "baseUrl": "./", 8 | "module": "commonjs", 9 | "strictBindCallApply": false, 10 | "strictNullChecks": false, 11 | "noFallthroughCasesInSwitch": false, 12 | "noImplicitAny": false, 13 | "declaration": true, 14 | "outDir": "./dist", 15 | "removeComments": true, 16 | "sourceMap": true, 17 | "allowSyntheticDefaultImports": true, 18 | "forceConsistentCasingInFileNames": false, 19 | "skipLibCheck": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import antfu from '@antfu/eslint-config' 2 | 3 | export default antfu({ 4 | rules: {}, 5 | }) 6 | -------------------------------------------------------------------------------- /frontend/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /frontend/.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | lint: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: pnpm/action-setup@v3 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: lts/* 21 | cache: pnpm 22 | 23 | - name: Install 24 | run: pnpm install 25 | 26 | - name: Lint 27 | run: pnpm run lint 28 | 29 | typecheck: 30 | runs-on: ubuntu-latest 31 | steps: 32 | - uses: actions/checkout@v4 33 | - uses: pnpm/action-setup@v3 34 | - uses: actions/setup-node@v4 35 | with: 36 | node-version: lts/* 37 | cache: pnpm 38 | 39 | - name: Install 40 | run: pnpm install 41 | 42 | - name: Typecheck 43 | run: pnpm run typecheck 44 | 45 | test: 46 | runs-on: ${{ matrix.os }} 47 | 48 | strategy: 49 | matrix: 50 | node-version: [18.x, 20.x] 51 | os: [ubuntu-latest] 52 | fail-fast: false 53 | 54 | steps: 55 | - uses: actions/checkout@v4 56 | - uses: pnpm/action-setup@v3 57 | - name: Use Node.js ${{ matrix.node-version }} 58 | uses: actions/setup-node@v4 59 | with: 60 | node-version: ${{ matrix.node-version }} 61 | registry-url: https://registry.npmjs.org/ 62 | cache: pnpm 63 | 64 | - run: pnpm install 65 | - run: pnpm run test:unit 66 | 67 | test-e2e: 68 | runs-on: ubuntu-latest 69 | steps: 70 | - uses: actions/checkout@v4 71 | - uses: actions/cache@v4 72 | with: 73 | path: | 74 | ~/.cache 75 | key: cypress-cache-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} 76 | 77 | - uses: pnpm/action-setup@v3 78 | 79 | - name: Use Node.js 80 | uses: actions/setup-node@v4 81 | with: 82 | node-version: lts/* 83 | registry-url: https://registry.npmjs.org/ 84 | cache: pnpm 85 | 86 | - run: pnpm install 87 | 88 | - name: Cypress PNPM Patch 89 | run: cp pnpm-lock.yaml package-lock.json 90 | 91 | - name: Cypress 92 | uses: cypress-io/github-action@v6 93 | with: 94 | install-command: echo 95 | build: pnpm run build 96 | start: npx vite preview --port 3333 97 | -------------------------------------------------------------------------------- /frontend/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "antfu.iconify", 4 | "antfu.unocss", 5 | "antfu.vite", 6 | "antfu.goto-alias", 7 | "csstools.postcss", 8 | "dbaeumer.vscode-eslint", 9 | "vue.volar", 10 | "lokalise.i18n-ally", 11 | "streetsidesoftware.code-spell-checker" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /frontend/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "antfu", 4 | "demi", 5 | "iconify", 6 | "intlify", 7 | "nprogress", 8 | "pinia", 9 | "pnpm", 10 | "shiki", 11 | "shikijs", 12 | "sizecheck", 13 | "taze", 14 | "typecheck", 15 | "unhead", 16 | "unocss", 17 | "unplugin", 18 | "Vite", 19 | "vitejs", 20 | "Vitesse", 21 | "vitest", 22 | "vueuse", 23 | "webfont" 24 | ], 25 | "i18n-ally.sourceLanguage": "en", 26 | "i18n-ally.keystyle": "nested", 27 | "i18n-ally.localesPaths": "locales", 28 | "i18n-ally.sortKeys": true, 29 | 30 | // Disable the default formatter 31 | "prettier.enable": false, 32 | "editor.formatOnSave": false, 33 | 34 | // Auto fix 35 | "editor.codeActionsOnSave": { 36 | "source.fixAll.eslint": "explicit", 37 | "source.organizeImports": "never" 38 | }, 39 | 40 | // Silent the stylistic rules in you IDE, but still auto fix them 41 | "eslint.rules.customizations": [ 42 | { "rule": "style/*", "severity": "off" }, 43 | { "rule": "format/*", "severity": "off" }, 44 | { "rule": "*-indent", "severity": "off" }, 45 | { "rule": "*-spacing", "severity": "off" }, 46 | { "rule": "*-spaces", "severity": "off" }, 47 | { "rule": "*-order", "severity": "off" }, 48 | { "rule": "*-dangle", "severity": "off" }, 49 | { "rule": "*-newline", "severity": "off" }, 50 | { "rule": "*quotes", "severity": "off" }, 51 | { "rule": "*semi", "severity": "off" } 52 | ], 53 | 54 | // The following is optional. 55 | // It's better to put under project setting `.vscode/settings.json` 56 | // to avoid conflicts with working with different eslint configs 57 | // that does not support all formats. 58 | "eslint.validate": [ 59 | "javascript", 60 | "javascriptreact", 61 | "typescript", 62 | "typescriptreact", 63 | "vue", 64 | "html", 65 | "markdown", 66 | "json", 67 | "jsonc", 68 | "yaml" 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-alpine as build-stage 2 | 3 | WORKDIR /app 4 | RUN corepack enable 5 | 6 | COPY .npmrc package.json pnpm-lock.yaml ./ 7 | RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store \ 8 | pnpm install --frozen-lockfile 9 | 10 | COPY . . 11 | RUN pnpm build 12 | 13 | FROM nginx:stable-alpine as production-stage 14 | 15 | COPY --from=build-stage /app/dist /usr/share/nginx/html 16 | EXPOSE 80 17 | 18 | CMD ["nginx", "-g", "daemon off;"] 19 | -------------------------------------------------------------------------------- /frontend/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-PRESENT Anthony Fu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 |

2 | Vitesse - Opinionated Vite Starter Template 3 |

4 | 5 |

6 | Mocking up web app with Vitesse(speed)
7 |

8 | 9 |
10 | 11 |

12 | Live Demo 13 |

14 | 15 |
16 | 17 | > **Note**: This template is created during the early transition of Vue 3 and Vite. At this moment, if you are seeking for better Vue developer experience and more consistent maintenance, we recommend using [Nuxt 3](https://nuxt.com) instead (it also works perfectly with SPA or SSG as needed). This template still serves as a reference, but expect slower updates. 18 | 19 |
20 | 21 |

22 | English | 简体中文 23 | 24 |

25 | 26 |
27 | 28 | ## Features 29 | 30 | - ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [esbuild](https://github.com/evanw/esbuild) - born with fastness 31 | 32 | - 🗂 [File based routing](./src/pages) 33 | 34 | - 📦 [Components auto importing](./src/components) 35 | 36 | - 🍍 [State Management via Pinia](https://pinia.vuejs.org/) 37 | 38 | - 📑 [Layout system](./src/layouts) 39 | 40 | - 📲 [PWA](https://github.com/antfu/vite-plugin-pwa) 41 | 42 | - 🎨 [UnoCSS](https://github.com/antfu/unocss) - the instant on-demand atomic CSS engine 43 | 44 | - 😃 [Use icons from any icon sets with classes](https://github.com/antfu/unocss/tree/main/packages/preset-icons) 45 | 46 | - 🌍 [I18n ready](./locales) 47 | 48 | - 🔎 [Component Preview](https://github.com/johnsoncodehk/vite-plugin-vue-component-preview) 49 | 50 | - 🗒 [Markdown Support](https://github.com/unplugin/unplugin-vue-markdown) 51 | 52 | - 🔥 Use the [new ` 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /frontend/locales/README.md: -------------------------------------------------------------------------------- 1 | ## i18n 2 | 3 | This directory is to serve your locale translation files. YAML under this folder would be loaded automatically and register with their filenames as locale code. 4 | 5 | Check out [`vue-i18n`](https://github.com/intlify/vue-i18n-next) for more details. 6 | 7 | If you are using VS Code, [`i18n Ally`](https://github.com/lokalise/i18n-ally) is recommended to make the i18n experience better. 8 | -------------------------------------------------------------------------------- /frontend/locales/ar.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: حول 3 | back: رجوع 4 | go: تجربة 5 | home: الرئيسية 6 | toggle_dark: التغيير إلى الوضع المظلم 7 | toggle_langs: تغيير اللغة 8 | intro: 9 | desc: vite مثال لتطبيق 10 | dynamic-route: عرض لتوجيهات ديناميكية 11 | hi: مرحبا {name} 12 | aka: معروف أيضا تحت مسمى 13 | whats-your-name: ما إسمك؟ 14 | not-found: صفحة غير موجودة 15 | -------------------------------------------------------------------------------- /frontend/locales/de.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: Über 3 | back: Zurück 4 | go: Los 5 | home: Startseite 6 | toggle_dark: Dunkelmodus umschalten 7 | toggle_langs: Sprachen ändern 8 | intro: 9 | desc: Vite Startvorlage mit Vorlieben 10 | dynamic-route: Demo einer dynamischen Route 11 | hi: Hi, {name}! 12 | aka: Auch bekannt als 13 | whats-your-name: Wie heißt du? 14 | not-found: Nicht gefunden 15 | -------------------------------------------------------------------------------- /frontend/locales/en.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: About 3 | back: Back 4 | go: GO 5 | home: Home 6 | toggle_dark: Toggle dark mode 7 | toggle_langs: Change languages 8 | intro: 9 | desc: Opinionated Vite Starter Template 10 | dynamic-route: Demo of dynamic route 11 | hi: Hi, {name}! 12 | aka: Also known as 13 | whats-your-name: What's your name? 14 | not-found: Not found 15 | -------------------------------------------------------------------------------- /frontend/locales/es.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: Acerca de 3 | back: Atrás 4 | go: Ir 5 | home: Inicio 6 | toggle_dark: Alternar modo oscuro 7 | toggle_langs: Cambiar idiomas 8 | intro: 9 | desc: Plantilla de Inicio de Vite Dogmática 10 | dynamic-route: Demo de ruta dinámica 11 | hi: ¡Hola, {name}! 12 | aka: También conocido como 13 | whats-your-name: ¿Cómo te llamas? 14 | not-found: No se ha encontrado 15 | -------------------------------------------------------------------------------- /frontend/locales/fr.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: À propos 3 | back: Retour 4 | go: Essayer 5 | home: Accueil 6 | toggle_dark: Basculer en mode sombre 7 | toggle_langs: Changer de langue 8 | intro: 9 | desc: Exemple d'application Vite 10 | dynamic-route: Démo de route dynamique 11 | hi: Salut, {name}! 12 | aka: Aussi connu sous le nom de 13 | whats-your-name: Comment t'appelles-tu ? 14 | not-found: Page non trouvée 15 | -------------------------------------------------------------------------------- /frontend/locales/id.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: Tentang 3 | back: Kembali 4 | go: Pergi 5 | home: Beranda 6 | toggle_dark: Ubah ke mode gelap 7 | toggle_langs: Ubah bahasa 8 | intro: 9 | desc: Template awal vite 10 | dynamic-route: Contoh rute dinamik 11 | hi: Halo, {name}! 12 | aka: Juga diketahui sebagai 13 | whats-your-name: Siapa nama anda? 14 | not-found: Tidak ditemukan 15 | -------------------------------------------------------------------------------- /frontend/locales/it.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: Su di me 3 | back: Indietro 4 | go: Vai 5 | home: Home 6 | toggle_dark: Attiva/disattiva modalità scura 7 | toggle_langs: Cambia lingua 8 | intro: 9 | desc: Modello per una Applicazione Vite 10 | dynamic-route: Demo di rotta dinamica 11 | hi: Ciao, {name}! 12 | whats-your-name: Come ti chiami? 13 | not-found: Non trovato 14 | -------------------------------------------------------------------------------- /frontend/locales/ja.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: これは? 3 | back: 戻る 4 | go: 進む 5 | home: ホーム 6 | toggle_dark: ダークモード切り替え 7 | toggle_langs: 言語切り替え 8 | intro: 9 | desc: 固執された Vite スターターテンプレート 10 | dynamic-route: 動的ルートのデモ 11 | hi: こんにちは、{name}! 12 | whats-your-name: 君の名は。 13 | not-found: 見つかりませんでした 14 | -------------------------------------------------------------------------------- /frontend/locales/ka.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: შესახებ 3 | back: უკან 4 | go: დაწყება 5 | home: მთავარი 6 | toggle_dark: გადართე მუქი რეჟიმი 7 | toggle_langs: ენის შეცვლა 8 | intro: 9 | desc: Opinionated Vite Starter Template 10 | dynamic-route: დინამიური როუტინგის დემო 11 | hi: გამარჯობა, {name}! 12 | aka: ასევე ცნობილი როგორც 13 | whats-your-name: რა გქვია? 14 | not-found: ვერ მოიძებნა 15 | -------------------------------------------------------------------------------- /frontend/locales/ko.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: 소개 3 | back: 뒤로가기 4 | go: 이동 5 | home: 홈 6 | toggle_dark: 다크모드 토글 7 | toggle_langs: 언어 변경 8 | intro: 9 | desc: Vite 애플리케이션 템플릿 10 | dynamic-route: 다이나믹 라우트 데모 11 | hi: 안녕, {name}! 12 | whats-your-name: 이름이 뭐예요? 13 | not-found: 찾을 수 없습니다 14 | -------------------------------------------------------------------------------- /frontend/locales/pl.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: O nas 3 | back: Wróć 4 | go: WEJDŹ 5 | home: Strona główna 6 | toggle_dark: Ustaw tryb nocny 7 | toggle_langs: Zmień język 8 | intro: 9 | desc: Opiniowany szablon startowy Vite 10 | dynamic-route: Demonstracja dynamicznego route 11 | hi: Cześć, {name}! 12 | aka: Znany też jako 13 | whats-your-name: Jak masz na imię? 14 | not-found: Nie znaleziono 15 | -------------------------------------------------------------------------------- /frontend/locales/pt-BR.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: Sobre 3 | back: Voltar 4 | go: Ir 5 | home: Início 6 | toggle_dark: Alternar modo escuro 7 | toggle_langs: Mudar de idioma 8 | intro: 9 | desc: Modelo Opinativo de Partida de Vite 10 | dynamic-route: Demonstração de rota dinâmica 11 | hi: Olá, {name}! 12 | aka: Também conhecido como 13 | whats-your-name: Qual é o seu nome? 14 | not-found: Não encontrado 15 | -------------------------------------------------------------------------------- /frontend/locales/ru.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: О шаблоне 3 | back: Назад 4 | go: Перейти 5 | home: Главная 6 | toggle_dark: Включить темный режим 7 | toggle_langs: Сменить язык 8 | intro: 9 | desc: Самостоятельный начальный шаблон Vite 10 | dynamic-route: Демо динамического маршрута 11 | hi: Привет, {name}! 12 | whats-your-name: Как тебя зовут? 13 | not-found: Не найден 14 | -------------------------------------------------------------------------------- /frontend/locales/tr.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: Hakkımda 3 | back: Geri 4 | go: İLERİ 5 | home: Anasayfa 6 | toggle_dark: Karanlık modu değiştir 7 | toggle_langs: Dilleri değiştir 8 | intro: 9 | desc: Görüşlü Vite Başlangıç Şablonu 10 | dynamic-route: Dinamik rota demosu 11 | hi: Merhaba, {name}! 12 | aka: Ayrıca şöyle bilinir 13 | whats-your-name: Adınız nedir? 14 | not-found: Bulunamadı 15 | -------------------------------------------------------------------------------- /frontend/locales/uk.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: Про шаблон 3 | back: Назад 4 | go: Перейти 5 | home: Головна 6 | toggle_dark: Переключити темний режим 7 | toggle_langs: Змінити мову 8 | intro: 9 | desc: Самостійний початковий шаблон Vite 10 | dynamic-route: Демо динамічного маршруту 11 | hi: Привіт, {name}! 12 | whats-your-name: Як тебе звати? 13 | not-found: Не знайдено 14 | -------------------------------------------------------------------------------- /frontend/locales/uz.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: Haqida 3 | back: Orqaga 4 | go: Kettik 5 | home: Bosh sahifa 6 | toggle_dark: Qorong‘i rejimga o‘tish 7 | toggle_langs: Tilni o‘zgartirish 8 | intro: 9 | desc: O‘ylangan boshlang‘ich Vite shabloni 10 | dynamic-route: Dynamic route demo'si 11 | hi: Assalomu alaykum, {name}! 12 | aka: shuningdek 13 | whats-your-name: Ismingiz nima? 14 | not-found: Topilmadi 15 | -------------------------------------------------------------------------------- /frontend/locales/vi.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: Về 3 | back: Quay lại 4 | go: Đi 5 | home: Khởi đầu 6 | toggle_dark: Chuyển đổi chế độ tối 7 | toggle_langs: Thay đổi ngôn ngữ 8 | intro: 9 | desc: Ý kiến cá nhân Vite Template để bắt đầu 10 | dynamic-route: Bản giới thiệu về dynamic route 11 | hi: Hi, {name}! 12 | whats-your-name: Tên bạn là gì? 13 | not-found: Không tìm thấy 14 | -------------------------------------------------------------------------------- /frontend/locales/zh-CN.yml: -------------------------------------------------------------------------------- 1 | button: 2 | about: 关于 3 | back: 返回 4 | go: 确定 5 | home: 首页 6 | toggle_dark: 切换深色模式 7 | toggle_langs: 切换语言 8 | intro: 9 | desc: 固执己见的 Vite 项目模板 10 | dynamic-route: 动态路由演示 11 | hi: 你好,{name} 12 | aka: 也叫 13 | whats-your-name: 输入你的名字 14 | not-found: 未找到页面 15 | -------------------------------------------------------------------------------- /frontend/netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | publish = "dist" 3 | command = "pnpm run build" 4 | 5 | [build.environment] 6 | NODE_VERSION = "20" 7 | 8 | [[redirects]] 9 | from = "/*" 10 | to = "/index.html" 11 | status = 200 12 | 13 | [[headers]] 14 | for = "/manifest.webmanifest" 15 | 16 | [headers.values] 17 | Content-Type = "application/manifest+json" 18 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@es-project-template/unplugin-vitesse", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "description": "Vitesse template", 6 | "keywords": [ 7 | "es-project-template" 8 | ], 9 | "publishConfig": { 10 | "access": "public" 11 | }, 12 | "scripts": { 13 | "build": "vite-ssg build", 14 | "dev": "vite --port 3333 --open", 15 | "lint": "eslint .", 16 | "preview": "vite preview", 17 | "preview-https": "serve dist", 18 | "test": "vitest", 19 | "test:e2e": "cypress open", 20 | "test:unit": "vitest", 21 | "typecheck": "vue-tsc --noEmit", 22 | "up": "taze major -I", 23 | "postinstall": "npx simple-git-hooks", 24 | "sizecheck": "npx vite-bundle-visualizer" 25 | }, 26 | "dependencies": { 27 | "@unhead/vue": "^1.10.0", 28 | "@unocss/reset": "^0.62.2", 29 | "@vueuse/core": "^11.0.1", 30 | "@vueuse/head": "^2.0.0", 31 | "nprogress": "^0.2.0", 32 | "pinia": "^2.2.2", 33 | "vue": "^3.4.38", 34 | "vue-demi": "^0.14.10", 35 | "vue-i18n": "^9.14.0", 36 | "vue-router": "^4.4.3" 37 | }, 38 | "devDependencies": { 39 | "@antfu/eslint-config": "^2.27.1", 40 | "@iconify-json/carbon": "^1.1.37", 41 | "@intlify/unplugin-vue-i18n": "^4.0.0", 42 | "@shikijs/markdown-it": "^1.14.1", 43 | "@types/markdown-it-link-attributes": "^3.0.5", 44 | "@types/nprogress": "^0.2.3", 45 | "@unocss/eslint-config": "^0.62.2", 46 | "@vitejs/plugin-vue": "^5.1.2", 47 | "@vue-macros/volar": "^0.27.4", 48 | "@vue/test-utils": "^2.4.6", 49 | "critters": "^0.0.24", 50 | "cross-env": "^7.0.3", 51 | "cypress": "^13.13.3", 52 | "cypress-vite": "^1.5.0", 53 | "eslint": "^9.9.1", 54 | "eslint-plugin-cypress": "^3.5.0", 55 | "eslint-plugin-format": "^0.1.2", 56 | "https-localhost": "^4.7.1", 57 | "lint-staged": "^15.2.9", 58 | "markdown-it-link-attributes": "^4.0.1", 59 | "pnpm": "^9.8.0", 60 | "rollup": "^4.21.0", 61 | "shiki": "^1.14.1", 62 | "simple-git-hooks": "^2.11.1", 63 | "taze": "^0.16.6", 64 | "typescript": "^5.5.4", 65 | "unocss": "^0.62.2", 66 | "unplugin-auto-import": "^0.18.2", 67 | "unplugin-vue-components": "^0.27.4", 68 | "unplugin-vue-macros": "^2.11.6", 69 | "unplugin-vue-markdown": "^0.26.2", 70 | "unplugin-vue-router": "^0.10.7", 71 | "vite": "^5.4.2", 72 | "vite-bundle-visualizer": "^1.2.1", 73 | "vite-plugin-inspect": "^0.8.7", 74 | "vite-plugin-pwa": "^0.20.1", 75 | "vite-plugin-vue-devtools": "^7.3.8", 76 | "vite-plugin-vue-layouts": "^0.11.0", 77 | "vite-plugin-webfont-dl": "^3.9.5", 78 | "vite-ssg": "^0.23.8", 79 | "vite-ssg-sitemap": "^0.8.1", 80 | "vitest": "^2.0.5", 81 | "vue-tsc": "^2.0.29" 82 | }, 83 | "resolutions": { 84 | "@typescript-eslint/utils": "^8.2.0" 85 | }, 86 | "simple-git-hooks": { 87 | "pre-commit": "pnpm lint-staged" 88 | }, 89 | "lint-staged": { 90 | "*": "eslint --fix" 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /frontend/public/_headers: -------------------------------------------------------------------------------- 1 | /assets/* 2 | cache-control: max-age=31536000 3 | cache-control: immutable 4 | -------------------------------------------------------------------------------- /frontend/public/favicon-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/public/pwa-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Groupguanfang/bt/5ffd4bf25b8f9640d55397fce182bf43671e98ed/frontend/public/pwa-192x192.png -------------------------------------------------------------------------------- /frontend/public/pwa-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Groupguanfang/bt/5ffd4bf25b8f9640d55397fce182bf43671e98ed/frontend/public/pwa-512x512.png -------------------------------------------------------------------------------- /frontend/public/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /frontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 30 | -------------------------------------------------------------------------------- /frontend/src/auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // noinspection JSUnusedGlobalSymbols 5 | // Generated by unplugin-auto-import 6 | export {} 7 | declare global { 8 | const EffectScope: typeof import('vue')['EffectScope'] 9 | const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] 10 | const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] 11 | const computed: typeof import('vue')['computed'] 12 | const computedAsync: typeof import('@vueuse/core')['computedAsync'] 13 | const computedEager: typeof import('@vueuse/core')['computedEager'] 14 | const computedInject: typeof import('@vueuse/core')['computedInject'] 15 | const computedWithControl: typeof import('@vueuse/core')['computedWithControl'] 16 | const controlledComputed: typeof import('@vueuse/core')['controlledComputed'] 17 | const controlledRef: typeof import('@vueuse/core')['controlledRef'] 18 | const createApp: typeof import('vue')['createApp'] 19 | const createEventHook: typeof import('@vueuse/core')['createEventHook'] 20 | const createGlobalState: typeof import('@vueuse/core')['createGlobalState'] 21 | const createInjectionState: typeof import('@vueuse/core')['createInjectionState'] 22 | const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn'] 23 | const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate'] 24 | const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable'] 25 | const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise'] 26 | const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn'] 27 | const customRef: typeof import('vue')['customRef'] 28 | const debouncedRef: typeof import('@vueuse/core')['debouncedRef'] 29 | const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch'] 30 | const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] 31 | const defineComponent: typeof import('vue')['defineComponent'] 32 | const defineLoader: typeof import('vue-router/auto')['defineLoader'] 33 | const definePage: typeof import('unplugin-vue-router/runtime')['definePage'] 34 | const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] 35 | const effectScope: typeof import('vue')['effectScope'] 36 | const extendRef: typeof import('@vueuse/core')['extendRef'] 37 | const getCurrentInstance: typeof import('vue')['getCurrentInstance'] 38 | const getCurrentScope: typeof import('vue')['getCurrentScope'] 39 | const h: typeof import('vue')['h'] 40 | const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] 41 | const inject: typeof import('vue')['inject'] 42 | const injectLocal: typeof import('@vueuse/core')['injectLocal'] 43 | const isDark: typeof import('./composables/dark')['isDark'] 44 | const isDefined: typeof import('@vueuse/core')['isDefined'] 45 | const isProxy: typeof import('vue')['isProxy'] 46 | const isReactive: typeof import('vue')['isReactive'] 47 | const isReadonly: typeof import('vue')['isReadonly'] 48 | const isRef: typeof import('vue')['isRef'] 49 | const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] 50 | const markRaw: typeof import('vue')['markRaw'] 51 | const nextTick: typeof import('vue')['nextTick'] 52 | const onActivated: typeof import('vue')['onActivated'] 53 | const onBeforeMount: typeof import('vue')['onBeforeMount'] 54 | const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] 55 | const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] 56 | const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] 57 | const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] 58 | const onClickOutside: typeof import('@vueuse/core')['onClickOutside'] 59 | const onDeactivated: typeof import('vue')['onDeactivated'] 60 | const onErrorCaptured: typeof import('vue')['onErrorCaptured'] 61 | const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke'] 62 | const onLongPress: typeof import('@vueuse/core')['onLongPress'] 63 | const onMounted: typeof import('vue')['onMounted'] 64 | const onRenderTracked: typeof import('vue')['onRenderTracked'] 65 | const onRenderTriggered: typeof import('vue')['onRenderTriggered'] 66 | const onScopeDispose: typeof import('vue')['onScopeDispose'] 67 | const onServerPrefetch: typeof import('vue')['onServerPrefetch'] 68 | const onStartTyping: typeof import('@vueuse/core')['onStartTyping'] 69 | const onUnmounted: typeof import('vue')['onUnmounted'] 70 | const onUpdated: typeof import('vue')['onUpdated'] 71 | const pausableWatch: typeof import('@vueuse/core')['pausableWatch'] 72 | const preferredDark: typeof import('./composables/dark')['preferredDark'] 73 | const provide: typeof import('vue')['provide'] 74 | const provideLocal: typeof import('@vueuse/core')['provideLocal'] 75 | const reactify: typeof import('@vueuse/core')['reactify'] 76 | const reactifyObject: typeof import('@vueuse/core')['reactifyObject'] 77 | const reactive: typeof import('vue')['reactive'] 78 | const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed'] 79 | const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit'] 80 | const reactivePick: typeof import('@vueuse/core')['reactivePick'] 81 | const readonly: typeof import('vue')['readonly'] 82 | const ref: typeof import('vue')['ref'] 83 | const refAutoReset: typeof import('@vueuse/core')['refAutoReset'] 84 | const refDebounced: typeof import('@vueuse/core')['refDebounced'] 85 | const refDefault: typeof import('@vueuse/core')['refDefault'] 86 | const refThrottled: typeof import('@vueuse/core')['refThrottled'] 87 | const refWithControl: typeof import('@vueuse/core')['refWithControl'] 88 | const resolveComponent: typeof import('vue')['resolveComponent'] 89 | const resolveRef: typeof import('@vueuse/core')['resolveRef'] 90 | const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] 91 | const shallowReactive: typeof import('vue')['shallowReactive'] 92 | const shallowReadonly: typeof import('vue')['shallowReadonly'] 93 | const shallowRef: typeof import('vue')['shallowRef'] 94 | const syncRef: typeof import('@vueuse/core')['syncRef'] 95 | const syncRefs: typeof import('@vueuse/core')['syncRefs'] 96 | const templateRef: typeof import('@vueuse/core')['templateRef'] 97 | const throttledRef: typeof import('@vueuse/core')['throttledRef'] 98 | const throttledWatch: typeof import('@vueuse/core')['throttledWatch'] 99 | const toRaw: typeof import('vue')['toRaw'] 100 | const toReactive: typeof import('@vueuse/core')['toReactive'] 101 | const toRef: typeof import('vue')['toRef'] 102 | const toRefs: typeof import('vue')['toRefs'] 103 | const toValue: typeof import('vue')['toValue'] 104 | const toggleDark: typeof import('./composables/dark')['toggleDark'] 105 | const triggerRef: typeof import('vue')['triggerRef'] 106 | const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount'] 107 | const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount'] 108 | const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted'] 109 | const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose'] 110 | const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted'] 111 | const unref: typeof import('vue')['unref'] 112 | const unrefElement: typeof import('@vueuse/core')['unrefElement'] 113 | const until: typeof import('@vueuse/core')['until'] 114 | const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] 115 | const useAnimate: typeof import('@vueuse/core')['useAnimate'] 116 | const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference'] 117 | const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery'] 118 | const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter'] 119 | const useArrayFind: typeof import('@vueuse/core')['useArrayFind'] 120 | const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex'] 121 | const useArrayFindLast: typeof import('@vueuse/core')['useArrayFindLast'] 122 | const useArrayIncludes: typeof import('@vueuse/core')['useArrayIncludes'] 123 | const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin'] 124 | const useArrayMap: typeof import('@vueuse/core')['useArrayMap'] 125 | const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce'] 126 | const useArraySome: typeof import('@vueuse/core')['useArraySome'] 127 | const useArrayUnique: typeof import('@vueuse/core')['useArrayUnique'] 128 | const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] 129 | const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] 130 | const useAttrs: typeof import('vue')['useAttrs'] 131 | const useBase64: typeof import('@vueuse/core')['useBase64'] 132 | const useBattery: typeof import('@vueuse/core')['useBattery'] 133 | const useBluetooth: typeof import('@vueuse/core')['useBluetooth'] 134 | const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints'] 135 | const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel'] 136 | const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation'] 137 | const useCached: typeof import('@vueuse/core')['useCached'] 138 | const useClipboard: typeof import('@vueuse/core')['useClipboard'] 139 | const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems'] 140 | const useCloned: typeof import('@vueuse/core')['useCloned'] 141 | const useColorMode: typeof import('@vueuse/core')['useColorMode'] 142 | const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog'] 143 | const useCounter: typeof import('@vueuse/core')['useCounter'] 144 | const useCssModule: typeof import('vue')['useCssModule'] 145 | const useCssVar: typeof import('@vueuse/core')['useCssVar'] 146 | const useCssVars: typeof import('vue')['useCssVars'] 147 | const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement'] 148 | const useCycleList: typeof import('@vueuse/core')['useCycleList'] 149 | const useDark: typeof import('@vueuse/core')['useDark'] 150 | const useDateFormat: typeof import('@vueuse/core')['useDateFormat'] 151 | const useDebounce: typeof import('@vueuse/core')['useDebounce'] 152 | const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn'] 153 | const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] 154 | const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion'] 155 | const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] 156 | const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] 157 | const useDevicesList: typeof import('@vueuse/core')['useDevicesList'] 158 | const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] 159 | const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] 160 | const useDraggable: typeof import('@vueuse/core')['useDraggable'] 161 | const useDropZone: typeof import('@vueuse/core')['useDropZone'] 162 | const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] 163 | const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint'] 164 | const useElementHover: typeof import('@vueuse/core')['useElementHover'] 165 | const useElementSize: typeof import('@vueuse/core')['useElementSize'] 166 | const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility'] 167 | const useEventBus: typeof import('@vueuse/core')['useEventBus'] 168 | const useEventListener: typeof import('@vueuse/core')['useEventListener'] 169 | const useEventSource: typeof import('@vueuse/core')['useEventSource'] 170 | const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper'] 171 | const useFavicon: typeof import('@vueuse/core')['useFavicon'] 172 | const useFetch: typeof import('@vueuse/core')['useFetch'] 173 | const useFileDialog: typeof import('@vueuse/core')['useFileDialog'] 174 | const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess'] 175 | const useFocus: typeof import('@vueuse/core')['useFocus'] 176 | const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin'] 177 | const useFps: typeof import('@vueuse/core')['useFps'] 178 | const useFullscreen: typeof import('@vueuse/core')['useFullscreen'] 179 | const useGamepad: typeof import('@vueuse/core')['useGamepad'] 180 | const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] 181 | const useHead: typeof import('@vueuse/head')['useHead'] 182 | const useI18n: typeof import('vue-i18n')['useI18n'] 183 | const useIdle: typeof import('@vueuse/core')['useIdle'] 184 | const useImage: typeof import('@vueuse/core')['useImage'] 185 | const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll'] 186 | const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver'] 187 | const useInterval: typeof import('@vueuse/core')['useInterval'] 188 | const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn'] 189 | const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier'] 190 | const useLastChanged: typeof import('@vueuse/core')['useLastChanged'] 191 | const useLink: typeof import('vue-router/auto')['useLink'] 192 | const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage'] 193 | const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys'] 194 | const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory'] 195 | const useMediaControls: typeof import('@vueuse/core')['useMediaControls'] 196 | const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery'] 197 | const useMemoize: typeof import('@vueuse/core')['useMemoize'] 198 | const useMemory: typeof import('@vueuse/core')['useMemory'] 199 | const useMounted: typeof import('@vueuse/core')['useMounted'] 200 | const useMouse: typeof import('@vueuse/core')['useMouse'] 201 | const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement'] 202 | const useMousePressed: typeof import('@vueuse/core')['useMousePressed'] 203 | const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver'] 204 | const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage'] 205 | const useNetwork: typeof import('@vueuse/core')['useNetwork'] 206 | const useNow: typeof import('@vueuse/core')['useNow'] 207 | const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl'] 208 | const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination'] 209 | const useOnline: typeof import('@vueuse/core')['useOnline'] 210 | const usePageLeave: typeof import('@vueuse/core')['usePageLeave'] 211 | const useParallax: typeof import('@vueuse/core')['useParallax'] 212 | const useParentElement: typeof import('@vueuse/core')['useParentElement'] 213 | const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver'] 214 | const usePermission: typeof import('@vueuse/core')['usePermission'] 215 | const usePointer: typeof import('@vueuse/core')['usePointer'] 216 | const usePointerLock: typeof import('@vueuse/core')['usePointerLock'] 217 | const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] 218 | const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] 219 | const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast'] 220 | const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] 221 | const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] 222 | const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion'] 223 | const usePrevious: typeof import('@vueuse/core')['usePrevious'] 224 | const useRafFn: typeof import('@vueuse/core')['useRafFn'] 225 | const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] 226 | const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] 227 | const useRoute: typeof import('vue-router')['useRoute'] 228 | const useRouter: typeof import('vue-router')['useRouter'] 229 | const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation'] 230 | const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea'] 231 | const useScriptTag: typeof import('@vueuse/core')['useScriptTag'] 232 | const useScroll: typeof import('@vueuse/core')['useScroll'] 233 | const useScrollLock: typeof import('@vueuse/core')['useScrollLock'] 234 | const useSeoMeta: typeof import('@vueuse/head')['useSeoMeta'] 235 | const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage'] 236 | const useShare: typeof import('@vueuse/core')['useShare'] 237 | const useSlots: typeof import('vue')['useSlots'] 238 | const useSorted: typeof import('@vueuse/core')['useSorted'] 239 | const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition'] 240 | const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis'] 241 | const useStepper: typeof import('@vueuse/core')['useStepper'] 242 | const useStorage: typeof import('@vueuse/core')['useStorage'] 243 | const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync'] 244 | const useStyleTag: typeof import('@vueuse/core')['useStyleTag'] 245 | const useSupported: typeof import('@vueuse/core')['useSupported'] 246 | const useSwipe: typeof import('@vueuse/core')['useSwipe'] 247 | const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList'] 248 | const useTextDirection: typeof import('@vueuse/core')['useTextDirection'] 249 | const useTextSelection: typeof import('@vueuse/core')['useTextSelection'] 250 | const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize'] 251 | const useThrottle: typeof import('@vueuse/core')['useThrottle'] 252 | const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn'] 253 | const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] 254 | const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo'] 255 | const useTimeout: typeof import('@vueuse/core')['useTimeout'] 256 | const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn'] 257 | const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll'] 258 | const useTimestamp: typeof import('@vueuse/core')['useTimestamp'] 259 | const useTitle: typeof import('@vueuse/core')['useTitle'] 260 | const useToNumber: typeof import('@vueuse/core')['useToNumber'] 261 | const useToString: typeof import('@vueuse/core')['useToString'] 262 | const useToggle: typeof import('@vueuse/core')['useToggle'] 263 | const useTransition: typeof import('@vueuse/core')['useTransition'] 264 | const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams'] 265 | const useUserMedia: typeof import('@vueuse/core')['useUserMedia'] 266 | const useUserStore: typeof import('./stores/user')['useUserStore'] 267 | const useVModel: typeof import('@vueuse/core')['useVModel'] 268 | const useVModels: typeof import('@vueuse/core')['useVModels'] 269 | const useVibrate: typeof import('@vueuse/core')['useVibrate'] 270 | const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] 271 | const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] 272 | const useWebNotification: typeof import('@vueuse/core')['useWebNotification'] 273 | const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] 274 | const useWebWorker: typeof import('@vueuse/core')['useWebWorker'] 275 | const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn'] 276 | const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus'] 277 | const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] 278 | const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] 279 | const watch: typeof import('vue')['watch'] 280 | const watchArray: typeof import('@vueuse/core')['watchArray'] 281 | const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] 282 | const watchDebounced: typeof import('@vueuse/core')['watchDebounced'] 283 | const watchDeep: typeof import('@vueuse/core')['watchDeep'] 284 | const watchEffect: typeof import('vue')['watchEffect'] 285 | const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable'] 286 | const watchImmediate: typeof import('@vueuse/core')['watchImmediate'] 287 | const watchOnce: typeof import('@vueuse/core')['watchOnce'] 288 | const watchPausable: typeof import('@vueuse/core')['watchPausable'] 289 | const watchPostEffect: typeof import('vue')['watchPostEffect'] 290 | const watchSyncEffect: typeof import('vue')['watchSyncEffect'] 291 | const watchThrottled: typeof import('@vueuse/core')['watchThrottled'] 292 | const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable'] 293 | const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] 294 | const whenever: typeof import('@vueuse/core')['whenever'] 295 | } 296 | // for type re-export 297 | declare global { 298 | // @ts-ignore 299 | export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' 300 | import('vue') 301 | } 302 | // for vue template auto import 303 | import { UnwrapRef } from 'vue' 304 | declare module 'vue' { 305 | interface GlobalComponents {} 306 | interface ComponentCustomProperties { 307 | readonly EffectScope: UnwrapRef 308 | readonly asyncComputed: UnwrapRef 309 | readonly autoResetRef: UnwrapRef 310 | readonly computed: UnwrapRef 311 | readonly computedAsync: UnwrapRef 312 | readonly computedEager: UnwrapRef 313 | readonly computedInject: UnwrapRef 314 | readonly computedWithControl: UnwrapRef 315 | readonly controlledComputed: UnwrapRef 316 | readonly controlledRef: UnwrapRef 317 | readonly createApp: UnwrapRef 318 | readonly createEventHook: UnwrapRef 319 | readonly createGlobalState: UnwrapRef 320 | readonly createInjectionState: UnwrapRef 321 | readonly createReactiveFn: UnwrapRef 322 | readonly createReusableTemplate: UnwrapRef 323 | readonly createSharedComposable: UnwrapRef 324 | readonly createTemplatePromise: UnwrapRef 325 | readonly createUnrefFn: UnwrapRef 326 | readonly customRef: UnwrapRef 327 | readonly debouncedRef: UnwrapRef 328 | readonly debouncedWatch: UnwrapRef 329 | readonly defineAsyncComponent: UnwrapRef 330 | readonly defineComponent: UnwrapRef 331 | readonly eagerComputed: UnwrapRef 332 | readonly effectScope: UnwrapRef 333 | readonly extendRef: UnwrapRef 334 | readonly getCurrentInstance: UnwrapRef 335 | readonly getCurrentScope: UnwrapRef 336 | readonly h: UnwrapRef 337 | readonly ignorableWatch: UnwrapRef 338 | readonly inject: UnwrapRef 339 | readonly injectLocal: UnwrapRef 340 | readonly isDark: UnwrapRef 341 | readonly isDefined: UnwrapRef 342 | readonly isProxy: UnwrapRef 343 | readonly isReactive: UnwrapRef 344 | readonly isReadonly: UnwrapRef 345 | readonly isRef: UnwrapRef 346 | readonly makeDestructurable: UnwrapRef 347 | readonly markRaw: UnwrapRef 348 | readonly nextTick: UnwrapRef 349 | readonly onActivated: UnwrapRef 350 | readonly onBeforeMount: UnwrapRef 351 | readonly onBeforeRouteLeave: UnwrapRef 352 | readonly onBeforeRouteUpdate: UnwrapRef 353 | readonly onBeforeUnmount: UnwrapRef 354 | readonly onBeforeUpdate: UnwrapRef 355 | readonly onClickOutside: UnwrapRef 356 | readonly onDeactivated: UnwrapRef 357 | readonly onErrorCaptured: UnwrapRef 358 | readonly onKeyStroke: UnwrapRef 359 | readonly onLongPress: UnwrapRef 360 | readonly onMounted: UnwrapRef 361 | readonly onRenderTracked: UnwrapRef 362 | readonly onRenderTriggered: UnwrapRef 363 | readonly onScopeDispose: UnwrapRef 364 | readonly onServerPrefetch: UnwrapRef 365 | readonly onStartTyping: UnwrapRef 366 | readonly onUnmounted: UnwrapRef 367 | readonly onUpdated: UnwrapRef 368 | readonly pausableWatch: UnwrapRef 369 | readonly preferredDark: UnwrapRef 370 | readonly provide: UnwrapRef 371 | readonly provideLocal: UnwrapRef 372 | readonly reactify: UnwrapRef 373 | readonly reactifyObject: UnwrapRef 374 | readonly reactive: UnwrapRef 375 | readonly reactiveComputed: UnwrapRef 376 | readonly reactiveOmit: UnwrapRef 377 | readonly reactivePick: UnwrapRef 378 | readonly readonly: UnwrapRef 379 | readonly ref: UnwrapRef 380 | readonly refAutoReset: UnwrapRef 381 | readonly refDebounced: UnwrapRef 382 | readonly refDefault: UnwrapRef 383 | readonly refThrottled: UnwrapRef 384 | readonly refWithControl: UnwrapRef 385 | readonly resolveComponent: UnwrapRef 386 | readonly resolveRef: UnwrapRef 387 | readonly resolveUnref: UnwrapRef 388 | readonly shallowReactive: UnwrapRef 389 | readonly shallowReadonly: UnwrapRef 390 | readonly shallowRef: UnwrapRef 391 | readonly syncRef: UnwrapRef 392 | readonly syncRefs: UnwrapRef 393 | readonly templateRef: UnwrapRef 394 | readonly throttledRef: UnwrapRef 395 | readonly throttledWatch: UnwrapRef 396 | readonly toRaw: UnwrapRef 397 | readonly toReactive: UnwrapRef 398 | readonly toRef: UnwrapRef 399 | readonly toRefs: UnwrapRef 400 | readonly toValue: UnwrapRef 401 | readonly toggleDark: UnwrapRef 402 | readonly triggerRef: UnwrapRef 403 | readonly tryOnBeforeMount: UnwrapRef 404 | readonly tryOnBeforeUnmount: UnwrapRef 405 | readonly tryOnMounted: UnwrapRef 406 | readonly tryOnScopeDispose: UnwrapRef 407 | readonly tryOnUnmounted: UnwrapRef 408 | readonly unref: UnwrapRef 409 | readonly unrefElement: UnwrapRef 410 | readonly until: UnwrapRef 411 | readonly useActiveElement: UnwrapRef 412 | readonly useAnimate: UnwrapRef 413 | readonly useArrayDifference: UnwrapRef 414 | readonly useArrayEvery: UnwrapRef 415 | readonly useArrayFilter: UnwrapRef 416 | readonly useArrayFind: UnwrapRef 417 | readonly useArrayFindIndex: UnwrapRef 418 | readonly useArrayFindLast: UnwrapRef 419 | readonly useArrayIncludes: UnwrapRef 420 | readonly useArrayJoin: UnwrapRef 421 | readonly useArrayMap: UnwrapRef 422 | readonly useArrayReduce: UnwrapRef 423 | readonly useArraySome: UnwrapRef 424 | readonly useArrayUnique: UnwrapRef 425 | readonly useAsyncQueue: UnwrapRef 426 | readonly useAsyncState: UnwrapRef 427 | readonly useAttrs: UnwrapRef 428 | readonly useBase64: UnwrapRef 429 | readonly useBattery: UnwrapRef 430 | readonly useBluetooth: UnwrapRef 431 | readonly useBreakpoints: UnwrapRef 432 | readonly useBroadcastChannel: UnwrapRef 433 | readonly useBrowserLocation: UnwrapRef 434 | readonly useCached: UnwrapRef 435 | readonly useClipboard: UnwrapRef 436 | readonly useClipboardItems: UnwrapRef 437 | readonly useCloned: UnwrapRef 438 | readonly useColorMode: UnwrapRef 439 | readonly useConfirmDialog: UnwrapRef 440 | readonly useCounter: UnwrapRef 441 | readonly useCssModule: UnwrapRef 442 | readonly useCssVar: UnwrapRef 443 | readonly useCssVars: UnwrapRef 444 | readonly useCurrentElement: UnwrapRef 445 | readonly useCycleList: UnwrapRef 446 | readonly useDark: UnwrapRef 447 | readonly useDateFormat: UnwrapRef 448 | readonly useDebounce: UnwrapRef 449 | readonly useDebounceFn: UnwrapRef 450 | readonly useDebouncedRefHistory: UnwrapRef 451 | readonly useDeviceMotion: UnwrapRef 452 | readonly useDeviceOrientation: UnwrapRef 453 | readonly useDevicePixelRatio: UnwrapRef 454 | readonly useDevicesList: UnwrapRef 455 | readonly useDisplayMedia: UnwrapRef 456 | readonly useDocumentVisibility: UnwrapRef 457 | readonly useDraggable: UnwrapRef 458 | readonly useDropZone: UnwrapRef 459 | readonly useElementBounding: UnwrapRef 460 | readonly useElementByPoint: UnwrapRef 461 | readonly useElementHover: UnwrapRef 462 | readonly useElementSize: UnwrapRef 463 | readonly useElementVisibility: UnwrapRef 464 | readonly useEventBus: UnwrapRef 465 | readonly useEventListener: UnwrapRef 466 | readonly useEventSource: UnwrapRef 467 | readonly useEyeDropper: UnwrapRef 468 | readonly useFavicon: UnwrapRef 469 | readonly useFetch: UnwrapRef 470 | readonly useFileDialog: UnwrapRef 471 | readonly useFileSystemAccess: UnwrapRef 472 | readonly useFocus: UnwrapRef 473 | readonly useFocusWithin: UnwrapRef 474 | readonly useFps: UnwrapRef 475 | readonly useFullscreen: UnwrapRef 476 | readonly useGamepad: UnwrapRef 477 | readonly useGeolocation: UnwrapRef 478 | readonly useHead: UnwrapRef 479 | readonly useI18n: UnwrapRef 480 | readonly useIdle: UnwrapRef 481 | readonly useImage: UnwrapRef 482 | readonly useInfiniteScroll: UnwrapRef 483 | readonly useIntersectionObserver: UnwrapRef 484 | readonly useInterval: UnwrapRef 485 | readonly useIntervalFn: UnwrapRef 486 | readonly useKeyModifier: UnwrapRef 487 | readonly useLastChanged: UnwrapRef 488 | readonly useLink: UnwrapRef 489 | readonly useLocalStorage: UnwrapRef 490 | readonly useMagicKeys: UnwrapRef 491 | readonly useManualRefHistory: UnwrapRef 492 | readonly useMediaControls: UnwrapRef 493 | readonly useMediaQuery: UnwrapRef 494 | readonly useMemoize: UnwrapRef 495 | readonly useMemory: UnwrapRef 496 | readonly useMounted: UnwrapRef 497 | readonly useMouse: UnwrapRef 498 | readonly useMouseInElement: UnwrapRef 499 | readonly useMousePressed: UnwrapRef 500 | readonly useMutationObserver: UnwrapRef 501 | readonly useNavigatorLanguage: UnwrapRef 502 | readonly useNetwork: UnwrapRef 503 | readonly useNow: UnwrapRef 504 | readonly useObjectUrl: UnwrapRef 505 | readonly useOffsetPagination: UnwrapRef 506 | readonly useOnline: UnwrapRef 507 | readonly usePageLeave: UnwrapRef 508 | readonly useParallax: UnwrapRef 509 | readonly useParentElement: UnwrapRef 510 | readonly usePerformanceObserver: UnwrapRef 511 | readonly usePermission: UnwrapRef 512 | readonly usePointer: UnwrapRef 513 | readonly usePointerLock: UnwrapRef 514 | readonly usePointerSwipe: UnwrapRef 515 | readonly usePreferredColorScheme: UnwrapRef 516 | readonly usePreferredContrast: UnwrapRef 517 | readonly usePreferredDark: UnwrapRef 518 | readonly usePreferredLanguages: UnwrapRef 519 | readonly usePreferredReducedMotion: UnwrapRef 520 | readonly usePrevious: UnwrapRef 521 | readonly useRafFn: UnwrapRef 522 | readonly useRefHistory: UnwrapRef 523 | readonly useResizeObserver: UnwrapRef 524 | readonly useRoute: UnwrapRef 525 | readonly useRouter: UnwrapRef 526 | readonly useScreenOrientation: UnwrapRef 527 | readonly useScreenSafeArea: UnwrapRef 528 | readonly useScriptTag: UnwrapRef 529 | readonly useScroll: UnwrapRef 530 | readonly useScrollLock: UnwrapRef 531 | readonly useSeoMeta: UnwrapRef 532 | readonly useSessionStorage: UnwrapRef 533 | readonly useShare: UnwrapRef 534 | readonly useSlots: UnwrapRef 535 | readonly useSorted: UnwrapRef 536 | readonly useSpeechRecognition: UnwrapRef 537 | readonly useSpeechSynthesis: UnwrapRef 538 | readonly useStepper: UnwrapRef 539 | readonly useStorage: UnwrapRef 540 | readonly useStorageAsync: UnwrapRef 541 | readonly useStyleTag: UnwrapRef 542 | readonly useSupported: UnwrapRef 543 | readonly useSwipe: UnwrapRef 544 | readonly useTemplateRefsList: UnwrapRef 545 | readonly useTextDirection: UnwrapRef 546 | readonly useTextSelection: UnwrapRef 547 | readonly useTextareaAutosize: UnwrapRef 548 | readonly useThrottle: UnwrapRef 549 | readonly useThrottleFn: UnwrapRef 550 | readonly useThrottledRefHistory: UnwrapRef 551 | readonly useTimeAgo: UnwrapRef 552 | readonly useTimeout: UnwrapRef 553 | readonly useTimeoutFn: UnwrapRef 554 | readonly useTimeoutPoll: UnwrapRef 555 | readonly useTimestamp: UnwrapRef 556 | readonly useTitle: UnwrapRef 557 | readonly useToNumber: UnwrapRef 558 | readonly useToString: UnwrapRef 559 | readonly useToggle: UnwrapRef 560 | readonly useTransition: UnwrapRef 561 | readonly useUrlSearchParams: UnwrapRef 562 | readonly useUserMedia: UnwrapRef 563 | readonly useUserStore: UnwrapRef 564 | readonly useVModel: UnwrapRef 565 | readonly useVModels: UnwrapRef 566 | readonly useVibrate: UnwrapRef 567 | readonly useVirtualList: UnwrapRef 568 | readonly useWakeLock: UnwrapRef 569 | readonly useWebNotification: UnwrapRef 570 | readonly useWebSocket: UnwrapRef 571 | readonly useWebWorker: UnwrapRef 572 | readonly useWebWorkerFn: UnwrapRef 573 | readonly useWindowFocus: UnwrapRef 574 | readonly useWindowScroll: UnwrapRef 575 | readonly useWindowSize: UnwrapRef 576 | readonly watch: UnwrapRef 577 | readonly watchArray: UnwrapRef 578 | readonly watchAtMost: UnwrapRef 579 | readonly watchDebounced: UnwrapRef 580 | readonly watchDeep: UnwrapRef 581 | readonly watchEffect: UnwrapRef 582 | readonly watchIgnorable: UnwrapRef 583 | readonly watchImmediate: UnwrapRef 584 | readonly watchOnce: UnwrapRef 585 | readonly watchPausable: UnwrapRef 586 | readonly watchPostEffect: UnwrapRef 587 | readonly watchSyncEffect: UnwrapRef 588 | readonly watchThrottled: UnwrapRef 589 | readonly watchTriggerable: UnwrapRef 590 | readonly watchWithFilter: UnwrapRef 591 | readonly whenever: UnwrapRef 592 | } 593 | } 594 | declare module '@vue/runtime-core' { 595 | interface GlobalComponents {} 596 | interface ComponentCustomProperties { 597 | readonly EffectScope: UnwrapRef 598 | readonly asyncComputed: UnwrapRef 599 | readonly autoResetRef: UnwrapRef 600 | readonly computed: UnwrapRef 601 | readonly computedAsync: UnwrapRef 602 | readonly computedEager: UnwrapRef 603 | readonly computedInject: UnwrapRef 604 | readonly computedWithControl: UnwrapRef 605 | readonly controlledComputed: UnwrapRef 606 | readonly controlledRef: UnwrapRef 607 | readonly createApp: UnwrapRef 608 | readonly createEventHook: UnwrapRef 609 | readonly createGlobalState: UnwrapRef 610 | readonly createInjectionState: UnwrapRef 611 | readonly createReactiveFn: UnwrapRef 612 | readonly createReusableTemplate: UnwrapRef 613 | readonly createSharedComposable: UnwrapRef 614 | readonly createTemplatePromise: UnwrapRef 615 | readonly createUnrefFn: UnwrapRef 616 | readonly customRef: UnwrapRef 617 | readonly debouncedRef: UnwrapRef 618 | readonly debouncedWatch: UnwrapRef 619 | readonly defineAsyncComponent: UnwrapRef 620 | readonly defineComponent: UnwrapRef 621 | readonly eagerComputed: UnwrapRef 622 | readonly effectScope: UnwrapRef 623 | readonly extendRef: UnwrapRef 624 | readonly getCurrentInstance: UnwrapRef 625 | readonly getCurrentScope: UnwrapRef 626 | readonly h: UnwrapRef 627 | readonly ignorableWatch: UnwrapRef 628 | readonly inject: UnwrapRef 629 | readonly injectLocal: UnwrapRef 630 | readonly isDark: UnwrapRef 631 | readonly isDefined: UnwrapRef 632 | readonly isProxy: UnwrapRef 633 | readonly isReactive: UnwrapRef 634 | readonly isReadonly: UnwrapRef 635 | readonly isRef: UnwrapRef 636 | readonly makeDestructurable: UnwrapRef 637 | readonly markRaw: UnwrapRef 638 | readonly nextTick: UnwrapRef 639 | readonly onActivated: UnwrapRef 640 | readonly onBeforeMount: UnwrapRef 641 | readonly onBeforeRouteLeave: UnwrapRef 642 | readonly onBeforeRouteUpdate: UnwrapRef 643 | readonly onBeforeUnmount: UnwrapRef 644 | readonly onBeforeUpdate: UnwrapRef 645 | readonly onClickOutside: UnwrapRef 646 | readonly onDeactivated: UnwrapRef 647 | readonly onErrorCaptured: UnwrapRef 648 | readonly onKeyStroke: UnwrapRef 649 | readonly onLongPress: UnwrapRef 650 | readonly onMounted: UnwrapRef 651 | readonly onRenderTracked: UnwrapRef 652 | readonly onRenderTriggered: UnwrapRef 653 | readonly onScopeDispose: UnwrapRef 654 | readonly onServerPrefetch: UnwrapRef 655 | readonly onStartTyping: UnwrapRef 656 | readonly onUnmounted: UnwrapRef 657 | readonly onUpdated: UnwrapRef 658 | readonly pausableWatch: UnwrapRef 659 | readonly preferredDark: UnwrapRef 660 | readonly provide: UnwrapRef 661 | readonly provideLocal: UnwrapRef 662 | readonly reactify: UnwrapRef 663 | readonly reactifyObject: UnwrapRef 664 | readonly reactive: UnwrapRef 665 | readonly reactiveComputed: UnwrapRef 666 | readonly reactiveOmit: UnwrapRef 667 | readonly reactivePick: UnwrapRef 668 | readonly readonly: UnwrapRef 669 | readonly ref: UnwrapRef 670 | readonly refAutoReset: UnwrapRef 671 | readonly refDebounced: UnwrapRef 672 | readonly refDefault: UnwrapRef 673 | readonly refThrottled: UnwrapRef 674 | readonly refWithControl: UnwrapRef 675 | readonly resolveComponent: UnwrapRef 676 | readonly resolveRef: UnwrapRef 677 | readonly resolveUnref: UnwrapRef 678 | readonly shallowReactive: UnwrapRef 679 | readonly shallowReadonly: UnwrapRef 680 | readonly shallowRef: UnwrapRef 681 | readonly syncRef: UnwrapRef 682 | readonly syncRefs: UnwrapRef 683 | readonly templateRef: UnwrapRef 684 | readonly throttledRef: UnwrapRef 685 | readonly throttledWatch: UnwrapRef 686 | readonly toRaw: UnwrapRef 687 | readonly toReactive: UnwrapRef 688 | readonly toRef: UnwrapRef 689 | readonly toRefs: UnwrapRef 690 | readonly toValue: UnwrapRef 691 | readonly toggleDark: UnwrapRef 692 | readonly triggerRef: UnwrapRef 693 | readonly tryOnBeforeMount: UnwrapRef 694 | readonly tryOnBeforeUnmount: UnwrapRef 695 | readonly tryOnMounted: UnwrapRef 696 | readonly tryOnScopeDispose: UnwrapRef 697 | readonly tryOnUnmounted: UnwrapRef 698 | readonly unref: UnwrapRef 699 | readonly unrefElement: UnwrapRef 700 | readonly until: UnwrapRef 701 | readonly useActiveElement: UnwrapRef 702 | readonly useAnimate: UnwrapRef 703 | readonly useArrayDifference: UnwrapRef 704 | readonly useArrayEvery: UnwrapRef 705 | readonly useArrayFilter: UnwrapRef 706 | readonly useArrayFind: UnwrapRef 707 | readonly useArrayFindIndex: UnwrapRef 708 | readonly useArrayFindLast: UnwrapRef 709 | readonly useArrayIncludes: UnwrapRef 710 | readonly useArrayJoin: UnwrapRef 711 | readonly useArrayMap: UnwrapRef 712 | readonly useArrayReduce: UnwrapRef 713 | readonly useArraySome: UnwrapRef 714 | readonly useArrayUnique: UnwrapRef 715 | readonly useAsyncQueue: UnwrapRef 716 | readonly useAsyncState: UnwrapRef 717 | readonly useAttrs: UnwrapRef 718 | readonly useBase64: UnwrapRef 719 | readonly useBattery: UnwrapRef 720 | readonly useBluetooth: UnwrapRef 721 | readonly useBreakpoints: UnwrapRef 722 | readonly useBroadcastChannel: UnwrapRef 723 | readonly useBrowserLocation: UnwrapRef 724 | readonly useCached: UnwrapRef 725 | readonly useClipboard: UnwrapRef 726 | readonly useClipboardItems: UnwrapRef 727 | readonly useCloned: UnwrapRef 728 | readonly useColorMode: UnwrapRef 729 | readonly useConfirmDialog: UnwrapRef 730 | readonly useCounter: UnwrapRef 731 | readonly useCssModule: UnwrapRef 732 | readonly useCssVar: UnwrapRef 733 | readonly useCssVars: UnwrapRef 734 | readonly useCurrentElement: UnwrapRef 735 | readonly useCycleList: UnwrapRef 736 | readonly useDark: UnwrapRef 737 | readonly useDateFormat: UnwrapRef 738 | readonly useDebounce: UnwrapRef 739 | readonly useDebounceFn: UnwrapRef 740 | readonly useDebouncedRefHistory: UnwrapRef 741 | readonly useDeviceMotion: UnwrapRef 742 | readonly useDeviceOrientation: UnwrapRef 743 | readonly useDevicePixelRatio: UnwrapRef 744 | readonly useDevicesList: UnwrapRef 745 | readonly useDisplayMedia: UnwrapRef 746 | readonly useDocumentVisibility: UnwrapRef 747 | readonly useDraggable: UnwrapRef 748 | readonly useDropZone: UnwrapRef 749 | readonly useElementBounding: UnwrapRef 750 | readonly useElementByPoint: UnwrapRef 751 | readonly useElementHover: UnwrapRef 752 | readonly useElementSize: UnwrapRef 753 | readonly useElementVisibility: UnwrapRef 754 | readonly useEventBus: UnwrapRef 755 | readonly useEventListener: UnwrapRef 756 | readonly useEventSource: UnwrapRef 757 | readonly useEyeDropper: UnwrapRef 758 | readonly useFavicon: UnwrapRef 759 | readonly useFetch: UnwrapRef 760 | readonly useFileDialog: UnwrapRef 761 | readonly useFileSystemAccess: UnwrapRef 762 | readonly useFocus: UnwrapRef 763 | readonly useFocusWithin: UnwrapRef 764 | readonly useFps: UnwrapRef 765 | readonly useFullscreen: UnwrapRef 766 | readonly useGamepad: UnwrapRef 767 | readonly useGeolocation: UnwrapRef 768 | readonly useHead: UnwrapRef 769 | readonly useI18n: UnwrapRef 770 | readonly useIdle: UnwrapRef 771 | readonly useImage: UnwrapRef 772 | readonly useInfiniteScroll: UnwrapRef 773 | readonly useIntersectionObserver: UnwrapRef 774 | readonly useInterval: UnwrapRef 775 | readonly useIntervalFn: UnwrapRef 776 | readonly useKeyModifier: UnwrapRef 777 | readonly useLastChanged: UnwrapRef 778 | readonly useLink: UnwrapRef 779 | readonly useLocalStorage: UnwrapRef 780 | readonly useMagicKeys: UnwrapRef 781 | readonly useManualRefHistory: UnwrapRef 782 | readonly useMediaControls: UnwrapRef 783 | readonly useMediaQuery: UnwrapRef 784 | readonly useMemoize: UnwrapRef 785 | readonly useMemory: UnwrapRef 786 | readonly useMounted: UnwrapRef 787 | readonly useMouse: UnwrapRef 788 | readonly useMouseInElement: UnwrapRef 789 | readonly useMousePressed: UnwrapRef 790 | readonly useMutationObserver: UnwrapRef 791 | readonly useNavigatorLanguage: UnwrapRef 792 | readonly useNetwork: UnwrapRef 793 | readonly useNow: UnwrapRef 794 | readonly useObjectUrl: UnwrapRef 795 | readonly useOffsetPagination: UnwrapRef 796 | readonly useOnline: UnwrapRef 797 | readonly usePageLeave: UnwrapRef 798 | readonly useParallax: UnwrapRef 799 | readonly useParentElement: UnwrapRef 800 | readonly usePerformanceObserver: UnwrapRef 801 | readonly usePermission: UnwrapRef 802 | readonly usePointer: UnwrapRef 803 | readonly usePointerLock: UnwrapRef 804 | readonly usePointerSwipe: UnwrapRef 805 | readonly usePreferredColorScheme: UnwrapRef 806 | readonly usePreferredContrast: UnwrapRef 807 | readonly usePreferredDark: UnwrapRef 808 | readonly usePreferredLanguages: UnwrapRef 809 | readonly usePreferredReducedMotion: UnwrapRef 810 | readonly usePrevious: UnwrapRef 811 | readonly useRafFn: UnwrapRef 812 | readonly useRefHistory: UnwrapRef 813 | readonly useResizeObserver: UnwrapRef 814 | readonly useRoute: UnwrapRef 815 | readonly useRouter: UnwrapRef 816 | readonly useScreenOrientation: UnwrapRef 817 | readonly useScreenSafeArea: UnwrapRef 818 | readonly useScriptTag: UnwrapRef 819 | readonly useScroll: UnwrapRef 820 | readonly useScrollLock: UnwrapRef 821 | readonly useSeoMeta: UnwrapRef 822 | readonly useSessionStorage: UnwrapRef 823 | readonly useShare: UnwrapRef 824 | readonly useSlots: UnwrapRef 825 | readonly useSorted: UnwrapRef 826 | readonly useSpeechRecognition: UnwrapRef 827 | readonly useSpeechSynthesis: UnwrapRef 828 | readonly useStepper: UnwrapRef 829 | readonly useStorage: UnwrapRef 830 | readonly useStorageAsync: UnwrapRef 831 | readonly useStyleTag: UnwrapRef 832 | readonly useSupported: UnwrapRef 833 | readonly useSwipe: UnwrapRef 834 | readonly useTemplateRefsList: UnwrapRef 835 | readonly useTextDirection: UnwrapRef 836 | readonly useTextSelection: UnwrapRef 837 | readonly useTextareaAutosize: UnwrapRef 838 | readonly useThrottle: UnwrapRef 839 | readonly useThrottleFn: UnwrapRef 840 | readonly useThrottledRefHistory: UnwrapRef 841 | readonly useTimeAgo: UnwrapRef 842 | readonly useTimeout: UnwrapRef 843 | readonly useTimeoutFn: UnwrapRef 844 | readonly useTimeoutPoll: UnwrapRef 845 | readonly useTimestamp: UnwrapRef 846 | readonly useTitle: UnwrapRef 847 | readonly useToNumber: UnwrapRef 848 | readonly useToString: UnwrapRef 849 | readonly useToggle: UnwrapRef 850 | readonly useTransition: UnwrapRef 851 | readonly useUrlSearchParams: UnwrapRef 852 | readonly useUserMedia: UnwrapRef 853 | readonly useUserStore: UnwrapRef 854 | readonly useVModel: UnwrapRef 855 | readonly useVModels: UnwrapRef 856 | readonly useVibrate: UnwrapRef 857 | readonly useVirtualList: UnwrapRef 858 | readonly useWakeLock: UnwrapRef 859 | readonly useWebNotification: UnwrapRef 860 | readonly useWebSocket: UnwrapRef 861 | readonly useWebWorker: UnwrapRef 862 | readonly useWebWorkerFn: UnwrapRef 863 | readonly useWindowFocus: UnwrapRef 864 | readonly useWindowScroll: UnwrapRef 865 | readonly useWindowSize: UnwrapRef 866 | readonly watch: UnwrapRef 867 | readonly watchArray: UnwrapRef 868 | readonly watchAtMost: UnwrapRef 869 | readonly watchDebounced: UnwrapRef 870 | readonly watchDeep: UnwrapRef 871 | readonly watchEffect: UnwrapRef 872 | readonly watchIgnorable: UnwrapRef 873 | readonly watchImmediate: UnwrapRef 874 | readonly watchOnce: UnwrapRef 875 | readonly watchPausable: UnwrapRef 876 | readonly watchPostEffect: UnwrapRef 877 | readonly watchSyncEffect: UnwrapRef 878 | readonly watchThrottled: UnwrapRef 879 | readonly watchTriggerable: UnwrapRef 880 | readonly watchWithFilter: UnwrapRef 881 | readonly whenever: UnwrapRef 882 | } 883 | } 884 | -------------------------------------------------------------------------------- /frontend/src/components.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // @ts-nocheck 3 | // Generated by unplugin-vue-components 4 | // Read more: https://github.com/vuejs/core/pull/3399 5 | export {} 6 | 7 | /* prettier-ignore */ 8 | declare module 'vue' { 9 | export interface GlobalComponents { 10 | README: typeof import('./components/README.md')['default'] 11 | RouterLink: typeof import('vue-router')['RouterLink'] 12 | RouterView: typeof import('vue-router')['RouterView'] 13 | TheCounter: typeof import('./components/TheCounter.vue')['default'] 14 | TheFooter: typeof import('./components/TheFooter.vue')['default'] 15 | TheInput: typeof import('./components/TheInput.vue')['default'] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /frontend/src/components/README.md: -------------------------------------------------------------------------------- 1 | ## Components 2 | 3 | Components in this dir will be auto-registered and on-demand, powered by [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components). 4 | 5 | ### Icons 6 | 7 | You can use icons from almost any icon sets by the power of [Iconify](https://iconify.design/). 8 | 9 | It will only bundle the icons you use. Check out [`unplugin-icons`](https://github.com/antfu/unplugin-icons) for more details. 10 | -------------------------------------------------------------------------------- /frontend/src/components/TheCounter.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | -------------------------------------------------------------------------------- /frontend/src/components/TheFooter.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 38 | -------------------------------------------------------------------------------- /frontend/src/components/TheInput.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | -------------------------------------------------------------------------------- /frontend/src/composables/dark.ts: -------------------------------------------------------------------------------- 1 | // these APIs are auto-imported from @vueuse/core 2 | export const isDark = useDark() 3 | export const toggleDark = useToggle(isDark) 4 | export const preferredDark = usePreferredDark() 5 | -------------------------------------------------------------------------------- /frontend/src/layouts/404.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 19 | -------------------------------------------------------------------------------- /frontend/src/layouts/README.md: -------------------------------------------------------------------------------- 1 | ## Layouts 2 | 3 | Vue components in this dir are used as layouts. 4 | 5 | By default, `default.vue` will be used unless an alternative is specified in the route meta. 6 | 7 | With [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router) and [`vite-plugin-vue-layouts`](https://github.com/JohnCampionJr/vite-plugin-vue-layouts), you can specify the layout in the page's SFCs like this: 8 | 9 | ```vue 10 | 11 | meta: 12 | layout: home 13 | 14 | ``` 15 | -------------------------------------------------------------------------------- /frontend/src/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /frontend/src/layouts/home.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /frontend/src/main.ts: -------------------------------------------------------------------------------- 1 | import { setupLayouts } from 'virtual:generated-layouts' 2 | 3 | import { ViteSSG } from 'vite-ssg' 4 | import { routes } from 'vue-router/auto-routes' 5 | import type { UserModule } from './types' 6 | import App from './App.vue' 7 | 8 | import '@unocss/reset/tailwind.css' 9 | import './styles/main.css' 10 | import 'uno.css' 11 | 12 | // https://github.com/antfu/vite-ssg 13 | export const createApp = ViteSSG( 14 | App, 15 | { 16 | routes: setupLayouts(routes), 17 | base: import.meta.env.BASE_URL, 18 | }, 19 | (ctx) => { 20 | // install all modules under `modules/` 21 | Object.values(import.meta.glob<{ install: UserModule }>('./modules/*.ts', { eager: true })) 22 | .forEach(i => i.install?.(ctx)) 23 | // ctx.app.use(Previewer) 24 | }, 25 | ) 26 | -------------------------------------------------------------------------------- /frontend/src/modules/README.md: -------------------------------------------------------------------------------- 1 | ## Modules 2 | 3 | A custom user module system. Place a `.ts` file with the following template, it will be installed automatically. 4 | 5 | ```ts 6 | import type { UserModule } from '~/types' 7 | 8 | export const install: UserModule = ({ app, router, isClient }) => { 9 | // do something 10 | } 11 | ``` 12 | -------------------------------------------------------------------------------- /frontend/src/modules/i18n.ts: -------------------------------------------------------------------------------- 1 | import type { Locale } from 'vue-i18n' 2 | import { createI18n } from 'vue-i18n' 3 | import type { UserModule } from '~/types' 4 | 5 | // Import i18n resources 6 | // https://vitejs.dev/guide/features.html#glob-import 7 | // 8 | // Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite 9 | const i18n = createI18n({ 10 | legacy: false, 11 | locale: '', 12 | messages: {}, 13 | }) 14 | 15 | const localesMap = Object.fromEntries( 16 | Object.entries(import.meta.glob('../../locales/*.yml')) 17 | .map(([path, loadLocale]) => [path.match(/([\w-]*)\.yml$/)?.[1], loadLocale]), 18 | ) as Record Promise<{ default: Record }>> 19 | 20 | export const availableLocales = Object.keys(localesMap) 21 | 22 | const loadedLanguages: string[] = [] 23 | 24 | function setI18nLanguage(lang: Locale) { 25 | i18n.global.locale.value = lang as any 26 | if (typeof document !== 'undefined') 27 | document.querySelector('html')?.setAttribute('lang', lang) 28 | return lang 29 | } 30 | 31 | export async function loadLanguageAsync(lang: string): Promise { 32 | // If the same language 33 | if (i18n.global.locale.value === lang) 34 | return setI18nLanguage(lang) 35 | 36 | // If the language was already loaded 37 | if (loadedLanguages.includes(lang)) 38 | return setI18nLanguage(lang) 39 | 40 | // If the language hasn't been loaded yet 41 | const messages = await localesMap[lang]() 42 | i18n.global.setLocaleMessage(lang, messages.default) 43 | loadedLanguages.push(lang) 44 | return setI18nLanguage(lang) 45 | } 46 | 47 | export const install: UserModule = ({ app }) => { 48 | app.use(i18n) 49 | loadLanguageAsync('en') 50 | } 51 | -------------------------------------------------------------------------------- /frontend/src/modules/nprogress.ts: -------------------------------------------------------------------------------- 1 | import NProgress from 'nprogress' 2 | import type { UserModule } from '~/types' 3 | 4 | export const install: UserModule = ({ isClient, router }) => { 5 | if (isClient) { 6 | router.beforeEach((to, from) => { 7 | if (to.path !== from.path) 8 | NProgress.start() 9 | }) 10 | router.afterEach(() => { 11 | NProgress.done() 12 | }) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/modules/pinia.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia' 2 | import type { UserModule } from '~/types' 3 | 4 | // Setup Pinia 5 | // https://pinia.vuejs.org/ 6 | export const install: UserModule = ({ isClient, initialState, app }) => { 7 | const pinia = createPinia() 8 | app.use(pinia) 9 | // Refer to 10 | // https://github.com/antfu/vite-ssg/blob/main/README.md#state-serialization 11 | // for other serialization strategies. 12 | if (isClient) 13 | pinia.state.value = (initialState.pinia) || {} 14 | 15 | else 16 | initialState.pinia = pinia.state.value 17 | } 18 | -------------------------------------------------------------------------------- /frontend/src/modules/pwa.ts: -------------------------------------------------------------------------------- 1 | import type { UserModule } from '~/types' 2 | 3 | // https://github.com/antfu/vite-plugin-pwa#automatic-reload-when-new-content-available 4 | export const install: UserModule = ({ isClient, router }) => { 5 | if (!isClient) 6 | return 7 | 8 | router.isReady() 9 | .then(async () => { 10 | const { registerSW } = await import('virtual:pwa-register') 11 | registerSW({ immediate: true }) 12 | }) 13 | .catch(() => {}) 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/pages/README.md: -------------------------------------------------------------------------------- 1 | ## File-based Routing 2 | 3 | Routes will be auto-generated for Vue files in this dir with the same file structure. 4 | Check out [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router) for more details. 5 | 6 | ### Path Aliasing 7 | 8 | `~/` is aliased to `./src/` folder. 9 | 10 | For example, instead of having 11 | 12 | ```ts 13 | import { isDark } from '../../../../composables' 14 | ``` 15 | 16 | now, you can use 17 | 18 | ```ts 19 | import { isDark } from '~/composables' 20 | ``` 21 | -------------------------------------------------------------------------------- /frontend/src/pages/[...all].vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 12 | meta: 13 | layout: 404 14 | 15 | -------------------------------------------------------------------------------- /frontend/src/pages/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About 3 | --- 4 | 5 |
6 | 7 |
8 |

About

9 |
10 | 11 | [Vitesse](https://github.com/antfu/vitesse) is an opinionated [Vite](https://github.com/vitejs/vite) starter template made by [@antfu](https://github.com/antfu) for mocking apps swiftly. With **file-based routing**, **components auto importing**, **markdown support**, I18n, PWA and uses **UnoCSS** for styling and icons. 12 | 13 | ```js 14 | // syntax highlighting example 15 | function vitesse() { 16 | const foo = 'bar' 17 | console.log(foo) 18 | } 19 | ``` 20 | 21 | Check out the [GitHub repo](https://github.com/antfu/vitesse) for more details. 22 | -------------------------------------------------------------------------------- /frontend/src/pages/hi/[name].vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 48 | -------------------------------------------------------------------------------- /frontend/src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 52 | 53 | 54 | meta: 55 | layout: home 56 | 57 | -------------------------------------------------------------------------------- /frontend/src/shims.d.ts: -------------------------------------------------------------------------------- 1 | declare interface Window { 2 | // extend the window 3 | } 4 | 5 | // with unplugin-vue-markdown, markdown files can be treated as Vue components 6 | declare module '*.md' { 7 | import type { DefineComponent } from 'vue' 8 | 9 | const component: DefineComponent 10 | export default component 11 | } 12 | 13 | declare module '*.vue' { 14 | import type { DefineComponent } from 'vue' 15 | 16 | const component: DefineComponent 17 | export default component 18 | } 19 | -------------------------------------------------------------------------------- /frontend/src/stores/user.ts: -------------------------------------------------------------------------------- 1 | import { acceptHMRUpdate, defineStore } from 'pinia' 2 | 3 | export const useUserStore = defineStore('user', () => { 4 | /** 5 | * Current name of the user. 6 | */ 7 | const savedName = ref('') 8 | const previousNames = ref(new Set()) 9 | 10 | const usedNames = computed(() => Array.from(previousNames.value)) 11 | const otherNames = computed(() => usedNames.value.filter(name => name !== savedName.value)) 12 | 13 | /** 14 | * Changes the current name of the user and saves the one that was used 15 | * before. 16 | * 17 | * @param name - new name to set 18 | */ 19 | function setNewName(name: string) { 20 | if (savedName.value) 21 | previousNames.value.add(savedName.value) 22 | 23 | savedName.value = name 24 | } 25 | 26 | return { 27 | setNewName, 28 | otherNames, 29 | savedName, 30 | } 31 | }) 32 | 33 | if (import.meta.hot) 34 | import.meta.hot.accept(acceptHMRUpdate(useUserStore as any, import.meta.hot)) 35 | -------------------------------------------------------------------------------- /frontend/src/styles/main.css: -------------------------------------------------------------------------------- 1 | @import './markdown.css'; 2 | 3 | html, 4 | body, 5 | #app { 6 | height: 100%; 7 | margin: 0; 8 | padding: 0; 9 | } 10 | 11 | html.dark { 12 | background: #121212; 13 | color-scheme: dark; 14 | } 15 | 16 | #nprogress { 17 | pointer-events: none; 18 | } 19 | 20 | #nprogress .bar { 21 | background: rgb(13, 148, 136); 22 | opacity: 0.75; 23 | position: fixed; 24 | z-index: 1031; 25 | top: 0; 26 | left: 0; 27 | width: 100%; 28 | height: 2px; 29 | } 30 | -------------------------------------------------------------------------------- /frontend/src/styles/markdown.css: -------------------------------------------------------------------------------- 1 | .prose pre:not(.shiki) { 2 | padding: 0; 3 | } 4 | 5 | .prose .shiki { 6 | font-family: 'DM Mono', monospace; 7 | font-size: 1.2em; 8 | line-height: 1.4; 9 | } 10 | 11 | .prose img { 12 | width: 100%; 13 | } 14 | 15 | .shiki, 16 | .shiki span { 17 | color: var(--shiki-light); 18 | background: var(--shiki-light-bg); 19 | } 20 | 21 | html.dark .shiki, 22 | html.dark .shiki span { 23 | color: var(--shiki-dark); 24 | background: var(--shiki-dark-bg); 25 | } 26 | -------------------------------------------------------------------------------- /frontend/src/typed-router.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️ 5 | // It's recommended to commit this file. 6 | // Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry. 7 | 8 | declare module 'vue-router/auto-routes' { 9 | import type { 10 | RouteRecordInfo, 11 | ParamValue, 12 | ParamValueOneOrMore, 13 | ParamValueZeroOrMore, 14 | ParamValueZeroOrOne, 15 | } from 'vue-router' 16 | 17 | /** 18 | * Route name map generated by unplugin-vue-router 19 | */ 20 | export interface RouteNamedMap { 21 | '/': RouteRecordInfo<'/', '/', Record, Record>, 22 | '/[...all]': RouteRecordInfo<'/[...all]', '/:all(.*)', { all: ParamValue }, { all: ParamValue }>, 23 | '/about': RouteRecordInfo<'/about', '/about', Record, Record>, 24 | '/hi/[name]': RouteRecordInfo<'/hi/[name]', '/hi/:name', { name: ParamValue }, { name: ParamValue }>, 25 | '/README': RouteRecordInfo<'/README', '/README', Record, Record>, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /frontend/src/types.ts: -------------------------------------------------------------------------------- 1 | import type { ViteSSGContext } from 'vite-ssg' 2 | 3 | export type UserModule = (ctx: ViteSSGContext) => void 4 | -------------------------------------------------------------------------------- /frontend/test/__snapshots__/component.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`component TheCounter.vue > should render 1`] = `"
10
"`; 4 | -------------------------------------------------------------------------------- /frontend/test/basic.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | describe('tests', () => { 4 | it('should works', () => { 5 | expect(1 + 1).toEqual(2) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /frontend/test/component.test.ts: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils' 2 | import { describe, expect, it } from 'vitest' 3 | import TheCounter from '../src/components/TheCounter.vue' 4 | 5 | describe('component TheCounter.vue', () => { 6 | it('should render', () => { 7 | const wrapper = mount(TheCounter, { props: { initial: 10 } }) 8 | expect(wrapper.text()).toContain('10') 9 | expect(wrapper.html()).toMatchSnapshot() 10 | }) 11 | 12 | it('should be interactive', async () => { 13 | const wrapper = mount(TheCounter, { props: { initial: 0 } }) 14 | expect(wrapper.text()).toContain('0') 15 | 16 | expect(wrapper.find('.inc').exists()).toBe(true) 17 | 18 | expect(wrapper.find('.dec').exists()).toBe(true) 19 | 20 | await wrapper.get('.inc').trigger('click') 21 | 22 | expect(wrapper.text()).toContain('1') 23 | 24 | await wrapper.get('.dec').trigger('click') 25 | 26 | expect(wrapper.text()).toContain('0') 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "jsx": "preserve", 5 | "lib": ["DOM", "ESNext"], 6 | "baseUrl": ".", 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "paths": { 10 | "~/*": ["src/*"] 11 | }, 12 | "resolveJsonModule": true, 13 | "types": [ 14 | "vitest", 15 | "vite/client", 16 | "vite-plugin-vue-layouts/client", 17 | "vite-plugin-pwa/client", 18 | "unplugin-vue-macros/macros-global", 19 | "unplugin-vue-router/client" 20 | ], 21 | "allowJs": true, 22 | "strict": true, 23 | "strictNullChecks": true, 24 | "noUnusedLocals": true, 25 | "noEmit": true, 26 | "esModuleInterop": true, 27 | "forceConsistentCasingInFileNames": true, 28 | "isolatedModules": true, 29 | "skipLibCheck": true 30 | }, 31 | "vueCompilerOptions": { 32 | "plugins": [ 33 | "@vue-macros/volar/define-models", 34 | "@vue-macros/volar/define-slots" 35 | ] 36 | }, 37 | "exclude": ["dist", "node_modules", "cypress"] 38 | } 39 | -------------------------------------------------------------------------------- /frontend/uno.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | presetAttributify, 4 | presetIcons, 5 | presetTypography, 6 | presetUno, 7 | presetWebFonts, 8 | transformerDirectives, 9 | transformerVariantGroup, 10 | } from 'unocss' 11 | 12 | export default defineConfig({ 13 | shortcuts: [ 14 | ['btn', 'px-4 py-1 rounded inline-block bg-teal-700 text-white cursor-pointer !outline-none hover:bg-teal-800 disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50'], 15 | ['icon-btn', 'inline-block cursor-pointer select-none opacity-75 transition duration-200 ease-in-out hover:opacity-100 hover:text-teal-600'], 16 | ], 17 | presets: [ 18 | presetUno(), 19 | presetAttributify(), 20 | presetIcons({ 21 | scale: 1.2, 22 | }), 23 | presetTypography(), 24 | presetWebFonts({ 25 | fonts: { 26 | sans: 'DM Sans', 27 | serif: 'DM Serif Display', 28 | mono: 'DM Mono', 29 | }, 30 | }), 31 | ], 32 | transformers: [ 33 | transformerDirectives(), 34 | transformerVariantGroup(), 35 | ], 36 | safelist: 'prose prose-sm m-auto text-left'.split(' '), 37 | }) 38 | -------------------------------------------------------------------------------- /frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import VueI18n from '@intlify/unplugin-vue-i18n/vite' 3 | import Shiki from '@shikijs/markdown-it' 4 | import Vue from '@vitejs/plugin-vue' 5 | import LinkAttributes from 'markdown-it-link-attributes' 6 | import Unocss from 'unocss/vite' 7 | import AutoImport from 'unplugin-auto-import/vite' 8 | import Components from 'unplugin-vue-components/vite' 9 | import VueMacros from 'unplugin-vue-macros/vite' 10 | import Markdown from 'unplugin-vue-markdown/vite' 11 | import { VueRouterAutoImports } from 'unplugin-vue-router' 12 | import VueRouter from 'unplugin-vue-router/vite' 13 | import { defineConfig } from 'vite' 14 | import { VitePWA } from 'vite-plugin-pwa' 15 | import VueDevTools from 'vite-plugin-vue-devtools' 16 | import Layouts from 'vite-plugin-vue-layouts' 17 | import WebfontDownload from 'vite-plugin-webfont-dl' 18 | import generateSitemap from 'vite-ssg-sitemap' 19 | 20 | export default defineConfig({ 21 | resolve: { 22 | alias: { 23 | '~/': `${path.resolve(__dirname, 'src')}/`, 24 | }, 25 | }, 26 | 27 | plugins: [ 28 | VueMacros({ 29 | plugins: { 30 | vue: Vue({ 31 | include: [/\.vue$/, /\.md$/], 32 | }), 33 | }, 34 | }), 35 | 36 | // https://github.com/posva/unplugin-vue-router 37 | VueRouter({ 38 | extensions: ['.vue', '.md'], 39 | dts: 'src/typed-router.d.ts', 40 | }), 41 | 42 | // https://github.com/JohnCampionJr/vite-plugin-vue-layouts 43 | Layouts(), 44 | 45 | // https://github.com/antfu/unplugin-auto-import 46 | AutoImport({ 47 | imports: [ 48 | 'vue', 49 | 'vue-i18n', 50 | '@vueuse/head', 51 | '@vueuse/core', 52 | VueRouterAutoImports, 53 | { 54 | // add any other imports you were relying on 55 | 'vue-router/auto': ['useLink'], 56 | }, 57 | ], 58 | dts: 'src/auto-imports.d.ts', 59 | dirs: [ 60 | 'src/composables', 61 | 'src/stores', 62 | ], 63 | vueTemplate: true, 64 | }), 65 | 66 | // https://github.com/antfu/unplugin-vue-components 67 | Components({ 68 | // allow auto load markdown components under `./src/components/` 69 | extensions: ['vue', 'md'], 70 | // allow auto import and register components used in markdown 71 | include: [/\.vue$/, /\.vue\?vue/, /\.md$/], 72 | dts: 'src/components.d.ts', 73 | }), 74 | 75 | // https://github.com/antfu/unocss 76 | // see uno.config.ts for config 77 | Unocss(), 78 | 79 | // https://github.com/unplugin/unplugin-vue-markdown 80 | // Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite 81 | Markdown({ 82 | wrapperClasses: 'prose prose-sm m-auto text-left', 83 | headEnabled: true, 84 | async markdownItSetup(md) { 85 | md.use(LinkAttributes, { 86 | matcher: (link: string) => /^https?:\/\//.test(link), 87 | attrs: { 88 | target: '_blank', 89 | rel: 'noopener', 90 | }, 91 | }) 92 | md.use(await Shiki({ 93 | defaultColor: false, 94 | themes: { 95 | light: 'vitesse-light', 96 | dark: 'vitesse-dark', 97 | }, 98 | })) 99 | }, 100 | }), 101 | 102 | // https://github.com/antfu/vite-plugin-pwa 103 | VitePWA({ 104 | registerType: 'autoUpdate', 105 | includeAssets: ['favicon.svg', 'safari-pinned-tab.svg'], 106 | manifest: { 107 | name: 'Vitesse', 108 | short_name: 'Vitesse', 109 | theme_color: '#ffffff', 110 | icons: [ 111 | { 112 | src: '/pwa-192x192.png', 113 | sizes: '192x192', 114 | type: 'image/png', 115 | }, 116 | { 117 | src: '/pwa-512x512.png', 118 | sizes: '512x512', 119 | type: 'image/png', 120 | }, 121 | { 122 | src: '/pwa-512x512.png', 123 | sizes: '512x512', 124 | type: 'image/png', 125 | purpose: 'any maskable', 126 | }, 127 | ], 128 | }, 129 | }), 130 | 131 | // https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n 132 | VueI18n({ 133 | runtimeOnly: true, 134 | compositionOnly: true, 135 | fullInstall: true, 136 | include: [path.resolve(__dirname, 'locales/**')], 137 | }), 138 | 139 | // https://github.com/feat-agency/vite-plugin-webfont-dl 140 | WebfontDownload(), 141 | 142 | // https://github.com/webfansplz/vite-plugin-vue-devtools 143 | VueDevTools(), 144 | ], 145 | 146 | // https://github.com/vitest-dev/vitest 147 | test: { 148 | include: ['test/**/*.test.ts'], 149 | environment: 'jsdom', 150 | }, 151 | 152 | // https://github.com/antfu/vite-ssg 153 | ssgOptions: { 154 | script: 'async', 155 | formatting: 'minify', 156 | crittersOptions: { 157 | reduceInlineStyles: false, 158 | }, 159 | onFinished() { 160 | generateSitemap() 161 | }, 162 | }, 163 | 164 | ssr: { 165 | // TODO: workaround until they support native ESM 166 | noExternal: ['workbox-window', /vue-i18n/], 167 | }, 168 | }) 169 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bt-node", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "description": "Node.js server panel.", 6 | "author": "Naily Zero (https://naily.cc)", 7 | "keywords": [ 8 | "es-project-template" 9 | ], 10 | "publishConfig": { 11 | "access": "public" 12 | }, 13 | "scripts": { 14 | "lint": "eslint .", 15 | "postinstall": "npx simple-git-hooks", 16 | "test": "vitest" 17 | }, 18 | "devDependencies": { 19 | "@antfu/eslint-config": "^3.7.3", 20 | "@types/js-yaml": "^4.0.9", 21 | "@types/node": "^22.7.5", 22 | "bumpp": "^9.7.1", 23 | "eslint": "^9.12.0", 24 | "js-yaml": "^4.1.0", 25 | "lint-staged": "^15.2.10", 26 | "simple-git-hooks": "^2.11.1", 27 | "tsup": "^8.3.0", 28 | "tsx": "^4.19.1", 29 | "typescript": "^5.6.3", 30 | "vitest": "^2.1.2" 31 | }, 32 | "simple-git-hooks": { 33 | "pre-commit": "pnpm lint-staged" 34 | }, 35 | "lint-staged": { 36 | "*": "eslint --fix" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - backend 3 | - frontend 4 | -------------------------------------------------------------------------------- /vitest.workspace.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs' 2 | import path from 'node:path' 3 | import { load } from 'js-yaml' 4 | import { defineWorkspace } from 'vitest/config' 5 | 6 | function loadWorkspace(): string[] { 7 | if (!fs.existsSync(path.join('pnpm-workspace.yaml'))) 8 | return [] 9 | const workspaceFile = fs.readFileSync('pnpm-workspace.yaml', 'utf-8') 10 | const parsedFile = (load(workspaceFile) as { packages: string[] }) || { packages: [] } 11 | return (parsedFile || { packages: [] as string[] }).packages || [] 12 | } 13 | 14 | export default defineWorkspace(loadWorkspace()) 15 | --------------------------------------------------------------------------------