create-bubbles 0.1.23 → 0.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +1 -1
- package/package.json +25 -24
- package/template-taro-react-oxc/.env.development +1 -1
- package/template-taro-react-oxc/.env.production +1 -1
- package/template-taro-react-oxc/project.config.json +1 -1
- package/template-taro-vue-eslint/project.config.json +2 -2
- package/{template-vp-monorepo-react-nestjs → template-vp-monorepo-react-hono}/.spaces/server//347/231/273/345/275/225/JWT/344/270/216RefreshToken/350/275/256/346/215/242/351/211/264/346/235/203/346/236/266/346/236/204/345/256/236/347/216/260/346/214/207/345/215/227.md +588 -1133
- package/template-vp-monorepo-react-hono/.vite-hooks/commit-msg +2 -0
- package/template-vp-monorepo-react-hono/.vite-hooks/pre-commit +2 -0
- package/template-vp-monorepo-react-hono/.vscode/extensions.json +3 -0
- package/template-vp-monorepo-react-hono/.vscode/settings.json +23 -0
- package/template-vp-monorepo-react-hono/AGENTS.md +16 -0
- package/template-vp-monorepo-react-hono/README.md +54 -0
- package/template-vp-monorepo-react-hono/apps/server/.env.example +13 -0
- package/template-vp-monorepo-react-hono/apps/server/README.md +75 -0
- package/template-vp-monorepo-react-hono/apps/server/drizzle/0000_flaky_madame_masque.sql +18 -0
- package/template-vp-monorepo-react-hono/apps/server/drizzle/meta/0000_snapshot.json +153 -0
- package/template-vp-monorepo-react-hono/apps/server/drizzle/meta/_journal.json +13 -0
- package/template-vp-monorepo-react-hono/apps/server/drizzle.config.ts +19 -0
- package/template-vp-monorepo-react-hono/apps/server/package.json +46 -0
- package/template-vp-monorepo-react-hono/apps/server/src/app.test.ts +57 -0
- package/template-vp-monorepo-react-hono/apps/server/src/app.ts +68 -0
- package/template-vp-monorepo-react-hono/apps/server/src/common/errors/app-error.ts +23 -0
- package/template-vp-monorepo-react-hono/apps/server/src/common/http/response.ts +21 -0
- package/template-vp-monorepo-react-hono/apps/server/src/common/logger.ts +30 -0
- package/template-vp-monorepo-react-hono/apps/server/src/config/env.ts +54 -0
- package/template-vp-monorepo-react-hono/apps/server/src/index.bun.ts +60 -0
- package/template-vp-monorepo-react-hono/apps/server/src/index.ts +73 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/database/client.ts +46 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/database/schema/index.ts +1 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/database/schema/job-runs.ts +42 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/queue/connection.ts +6 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/redis/client.ts +39 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/redis/options.ts +28 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/health/health.routes.ts +17 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/health/health.service.ts +59 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.queue.ts +46 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.repository.ts +101 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.routes.ts +46 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.schemas.ts +9 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.service.ts +57 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.types.ts +11 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.worker.ts +108 -0
- package/template-vp-monorepo-react-hono/apps/server/src/runtime/shutdown.ts +38 -0
- package/template-vp-monorepo-react-hono/apps/server/src/worker.ts +48 -0
- package/template-vp-monorepo-react-hono/apps/server/tsconfig.json +15 -0
- package/template-vp-monorepo-react-hono/apps/server/vite.config.ts +15 -0
- package/template-vp-monorepo-react-hono/apps/web/.env +2 -0
- package/template-vp-monorepo-react-hono/apps/web/.env.dev +1 -0
- package/template-vp-monorepo-react-hono/apps/web/.env.prod +1 -0
- package/template-vp-monorepo-react-hono/apps/web/index.html +13 -0
- package/template-vp-monorepo-react-hono/apps/web/package.json +35 -0
- package/template-vp-monorepo-react-hono/apps/web/public/favicon.svg +1 -0
- package/template-vp-monorepo-react-hono/apps/web/public/icons.svg +24 -0
- package/template-vp-monorepo-react-hono/apps/web/src/App.tsx +25 -0
- package/template-vp-monorepo-react-hono/apps/web/src/assets/hero.png +0 -0
- package/template-vp-monorepo-react-hono/apps/web/src/assets/react.svg +1 -0
- package/template-vp-monorepo-react-hono/apps/web/src/assets/vite.svg +1 -0
- package/template-vp-monorepo-react-hono/apps/web/src/components/Loading/PageLoading.tsx +11 -0
- package/template-vp-monorepo-react-hono/apps/web/src/locales/en_US.json +4 -0
- package/template-vp-monorepo-react-hono/apps/web/src/locales/zh_CN.json +4 -0
- package/template-vp-monorepo-react-hono/apps/web/src/main.tsx +5 -0
- package/template-vp-monorepo-react-hono/apps/web/src/pages/home/index.tsx +47 -0
- package/template-vp-monorepo-react-hono/apps/web/src/router/index.tsx +25 -0
- package/template-vp-monorepo-react-hono/apps/web/src/router/modules/.gitkeep +0 -0
- package/template-vp-monorepo-react-hono/apps/web/src/styles/index.css +7 -0
- package/template-vp-monorepo-react-hono/apps/web/src/types/auto-imports.d.ts +58 -0
- package/template-vp-monorepo-react-hono/apps/web/src/utils/env/index.ts +6 -0
- package/template-vp-monorepo-react-hono/apps/web/src/utils/request/core/index.ts +420 -0
- package/template-vp-monorepo-react-hono/apps/web/src/utils/request/core/utils.ts +39 -0
- package/template-vp-monorepo-react-hono/apps/web/src/utils/request/index.ts +61 -0
- package/template-vp-monorepo-react-hono/apps/web/tsconfig.json +18 -0
- package/template-vp-monorepo-react-hono/apps/web/vite.config.ts +45 -0
- package/template-vp-monorepo-react-hono/commitlint.config.js +1 -0
- package/template-vp-monorepo-react-hono/docker-compose.yml +41 -0
- package/template-vp-monorepo-react-hono/mise.toml +4 -0
- package/template-vp-monorepo-react-hono/package.json +37 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/package.json +20 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/format.ts +9 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/i18n.ts +73 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/index.ts +24 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/storage.ts +47 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/store.ts +48 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/types.ts +36 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/tsconfig.json +4 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/vite.config.ts +13 -0
- package/template-vp-monorepo-react-hono/packages/i18n/react/package.json +28 -0
- package/template-vp-monorepo-react-hono/packages/i18n/react/src/index.tsx +26 -0
- package/template-vp-monorepo-react-hono/packages/i18n/react/src/use-store.ts +14 -0
- package/template-vp-monorepo-react-hono/packages/i18n/react/tsconfig.json +9 -0
- package/template-vp-monorepo-react-hono/packages/i18n/react/vite.config.ts +16 -0
- package/template-vp-monorepo-react-hono/packages/i18n/vue/package.json +27 -0
- package/template-vp-monorepo-react-hono/packages/i18n/vue/src/index.ts +52 -0
- package/template-vp-monorepo-react-hono/packages/i18n/vue/src/use-store.ts +19 -0
- package/template-vp-monorepo-react-hono/packages/i18n/vue/tsconfig.json +8 -0
- package/template-vp-monorepo-react-hono/packages/i18n/vue/vite.config.ts +16 -0
- package/template-vp-monorepo-react-hono/pnpm-workspace.yaml +57 -0
- package/template-vp-monorepo-react-hono/scripts/clean.mjs +48 -0
- package/template-vp-monorepo-react-hono/tsconfig.base.json +10 -0
- package/template-vp-monorepo-react-hono/tsconfig.bundler.json +12 -0
- package/template-vp-monorepo-react-hono/tsconfig.json +11 -0
- package/template-vp-monorepo-react-hono/tsconfig.lib.json +10 -0
- package/template-vp-monorepo-react-hono/vite.config.ts +20 -0
- package/template-vp-monorepo-react-nestjs/.spaces/server/todo.md +991 -0
- package/template-vp-monorepo-react-nestjs/.vscode/launch.json +16 -0
- package/template-vp-monorepo-react-nestjs/.vscode/settings.json +21 -18
- package/template-vp-monorepo-react-nestjs/apps/server/.env.development +3 -39
- package/template-vp-monorepo-react-nestjs/apps/server/.swcrc +8 -0
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle.config.ts +8 -3
- package/template-vp-monorepo-react-nestjs/apps/server/nest-cli.json +8 -1
- package/template-vp-monorepo-react-nestjs/apps/server/package.json +11 -6
- package/template-vp-monorepo-react-nestjs/apps/server/src/app.controller.ts +2 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/app.module.ts +20 -15
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/adapters/fastify.adapter.ts +16 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/auth.ts +2 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/response.ts +0 -4
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/session.constants.ts +28 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/current-auth.decorator.ts +16 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/public.decorator.ts +4 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/dto/api-failure.dto.ts +25 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/error/common.error.ts +40 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/exceptions/app.exception.ts +55 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/filters/global-exception.filter.ts +384 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/openapi/response-headers.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/index.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/session.config.ts +36 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/database/schema.ts +4 -64
- package/template-vp-monorepo-react-nestjs/apps/server/src/main.ts +29 -8
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.controller.ts +55 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.errors.ts +42 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.module.ts +26 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.repository.ts +40 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.service.ts +129 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/auth-repsponse.dto.ts +31 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/login.dto.ts +11 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/register.dto.ts +17 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/guards/session-auth.guard.ts +50 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password.service.ts +24 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-store.service.ts +198 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-token.service.ts +29 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.script.ts +221 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.types.ts +24 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.controller.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/dto/create-user.dto.ts +3 -5
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.service.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/server/src/utils/env-arr.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/test/error-catalog.spec.ts +30 -0
- package/template-vp-monorepo-react-nestjs/apps/server/tsconfig.build.json +11 -1
- package/template-vp-monorepo-react-nestjs/apps/server/tsconfig.json +12 -20
- package/template-vp-monorepo-react-nestjs/apps/server/vite.config.ts +15 -0
- package/template-vp-monorepo-react-nestjs/apps/web/package.json +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web/tsconfig.json +5 -15
- package/template-vp-monorepo-react-nestjs/apps/web-vue/commitlint.config.js +1 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/lefthook.yml +1 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/package.json +1 -3
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/api/index.ts +5 -5
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/components/Icon/svg-icon.vue +3 -3
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/hooks/chart/lib.ts +6 -6
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/hooks/chart/useEcharts.ts +34 -29
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/i18n/instance.ts +2 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/index.vue +17 -32
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/locales/en_US.json +4 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/locales/zh_CN.json +4 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/index.ts +3 -3
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/permissionGuard.ts +7 -7
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/index.ts +7 -7
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/interface.ts +6 -6
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/index.ts +6 -6
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/modules/user.ts +9 -9
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/styles/index.scss +3 -3
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/types/antdv-next.d.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/env.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/index.ts +63 -45
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/utils.ts +12 -6
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/index.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/echart/config.ts +687 -687
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/echart/index.vue +7 -7
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/tree-chart.vue +2 -7
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/home/index.vue +13 -3
- package/template-vp-monorepo-react-nestjs/apps/web-vue/tsconfig.json +5 -17
- package/template-vp-monorepo-react-nestjs/apps/web-vue/uno.config.ts +5 -5
- package/template-vp-monorepo-react-nestjs/i18n.config.ts +22 -0
- package/template-vp-monorepo-react-nestjs/package.json +12 -1
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/README.md +113 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/docs/excel-sync-plan.md +618 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/package.json +31 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/cli.ts +5 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/command.ts +512 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/config.ts +15 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/files.ts +67 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/index.ts +19 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/load-config.ts +228 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/report.ts +57 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.test.ts +81 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.ts +290 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/sync.ts +274 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/command.test.ts +209 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/config.test.ts +19 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/load-config.test.ts +194 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/report.test.ts +63 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/sync.test.ts +203 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/temporary-directory.ts +25 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/tsconfig.json +9 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/vite.config.ts +18 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/core/tsconfig.json +1 -12
- package/template-vp-monorepo-react-nestjs/packages/i18n/react/tsconfig.json +3 -10
- package/template-vp-monorepo-react-nestjs/packages/i18n/vue/tsconfig.json +3 -10
- package/template-vp-monorepo-react-nestjs/packages/shared/package.json +40 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/index.ts +13 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/auth.ts +35 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/common.ts +11 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/index.ts +11 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/account.ts +5 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/index.ts +2 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/session-terminal.ts +11 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/tsconfig.json +4 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/vite.config.ts +17 -0
- package/template-vp-monorepo-react-nestjs/pnpm-workspace.yaml +6 -6
- package/template-vp-monorepo-react-nestjs/scripts/clean.mjs +48 -0
- package/template-vp-monorepo-react-nestjs/tsconfig.base.json +10 -0
- package/template-vp-monorepo-react-nestjs/tsconfig.bundler.json +12 -0
- package/template-vp-monorepo-react-nestjs/tsconfig.json +8 -6
- package/template-vp-monorepo-react-nestjs/tsconfig.lib.json +10 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/decorator.ts +0 -2
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/bypass.ts +0 -12
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/interceptors/transform.ts +0 -34
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/model/response.ts +0 -23
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/auth.config.ts +0 -64
- package/template-vp-monorepo-react-nestjs/apps/web-vue/pnpm-workspace.yaml +0 -16
- /package/{template-vp-monorepo-react-nestjs/apps/server/src/config/security.config.ts → template-vp-monorepo-react-hono/.agents/auth.config.ts} +0 -0
package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.script.ts
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
export const CREATE_OR_REPLACE_SESSION_SCRIPT = String.raw`
|
|
2
|
+
local function isValidTerminal(value)
|
|
3
|
+
return value == 'web' or value == 'desktop' or value == 'mobile'
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
local function isValidDigest(value)
|
|
7
|
+
return value
|
|
8
|
+
and string.len(value) == 64
|
|
9
|
+
and string.match(value, '^[0-9a-f]+$') ~= nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
local function isValidUserId(value)
|
|
13
|
+
return string.len(value) > 0
|
|
14
|
+
and string.len(value) <= 100
|
|
15
|
+
and string.match(value, '^[%w_-]+$') ~= nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
local newDigest = ARGV[1]
|
|
19
|
+
local userId = ARGV[2]
|
|
20
|
+
local terminal = ARGV[3]
|
|
21
|
+
local idleTtlMs = tonumber(ARGV[4])
|
|
22
|
+
local absoluteTtlMs = tonumber(ARGV[5])
|
|
23
|
+
local loginIp = ARGV[6]
|
|
24
|
+
local userAgent = ARGV[7]
|
|
25
|
+
local sessionKeyPrefix = ARGV[8]
|
|
26
|
+
|
|
27
|
+
if not isValidDigest(newDigest)
|
|
28
|
+
or not isValidUserId(userId)
|
|
29
|
+
or not isValidTerminal(terminal)
|
|
30
|
+
or not sessionKeyPrefix
|
|
31
|
+
or sessionKeyPrefix == ''
|
|
32
|
+
then
|
|
33
|
+
return { 0, 'INVALID_ARGUMENT' }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if not idleTtlMs or not absoluteTtlMs or idleTtlMs <= 0 or absoluteTtlMs <= idleTtlMs then
|
|
38
|
+
return { 0, 'INVALID_TTL' }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
local redisTime = redis.call('TIME')
|
|
42
|
+
local nowMs = tonumber(redisTime[1]) * 1000 + math.floor(tonumber(redisTime[2]) / 1000)
|
|
43
|
+
local absoluteExpiresAtMs = nowMs + absoluteTtlMs
|
|
44
|
+
local initialExpiresAtMs = math.min(nowMs + idleTtlMs, absoluteExpiresAtMs)
|
|
45
|
+
local oldDigest = redis.call('GET', KEYS[1])
|
|
46
|
+
local oldSessionKey = nil
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if oldDigest then
|
|
50
|
+
if not isValidDigest(oldDigest) then
|
|
51
|
+
return { 0, 'INVALID_SLOT_DATA' }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
oldSessionKey = sessionKeyPrefix .. oldDigest
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
redis.call(
|
|
59
|
+
'HSET',
|
|
60
|
+
KEYS[2],
|
|
61
|
+
'userId', userId,
|
|
62
|
+
'terminal', terminal,
|
|
63
|
+
'createdAtMs', tostring(nowMs),
|
|
64
|
+
'lastSeenAtMs', tostring(nowMs),
|
|
65
|
+
'absoluteExpiresAtMs', tostring(absoluteExpiresAtMs),
|
|
66
|
+
'loginIp', loginIp,
|
|
67
|
+
'userAgent', userAgent
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
redis.call('PEXPIREAT', KEYS[2], initialExpiresAtMs)
|
|
71
|
+
redis.call('SET', KEYS[1], newDigest)
|
|
72
|
+
redis.call('PEXPIREAT', KEYS[1], initialExpiresAtMs)
|
|
73
|
+
|
|
74
|
+
if oldSessionKey and oldDigest ~= newDigest then
|
|
75
|
+
redis.call('DEL', oldSessionKey)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
1,
|
|
82
|
+
oldDigest or '',
|
|
83
|
+
tostring(initialExpiresAtMs),
|
|
84
|
+
tostring(absoluteExpiresAtMs)
|
|
85
|
+
}
|
|
86
|
+
`
|
|
87
|
+
|
|
88
|
+
export const VALIDATE_AND_TOUCH_SESSION_SCRIPT = String.raw`
|
|
89
|
+
local function isValidTerminal(value)
|
|
90
|
+
return value == 'web' or value == 'desktop' or value == 'mobile'
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
local function isValidUserId(value)
|
|
95
|
+
return string.len(value) > 0
|
|
96
|
+
and string.len(value) <= 100
|
|
97
|
+
and string.match(value, '^[%w_-]+$') ~= nil
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
local currentDigest = ARGV[1]
|
|
101
|
+
local slotKeyPrefix = ARGV[2]
|
|
102
|
+
local idleTtlMs = tonumber(ARGV[3])
|
|
103
|
+
|
|
104
|
+
if not isValidDigest(currentDigest) or not idleTtlMs or idleTtlMs <= 0 then
|
|
105
|
+
return { 0, 'INVALID_ARGUMENT' }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
local sessionValues = redis.call(
|
|
109
|
+
'HMGET',
|
|
110
|
+
KEYS[1],
|
|
111
|
+
'userId',
|
|
112
|
+
'terminal',
|
|
113
|
+
'absoluteExpiresAtMs'
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
local userId = sessionValues[1]
|
|
117
|
+
local terminal = sessionValues[2]
|
|
118
|
+
local absoluteExpiresAtMs = tonumber(sessionValues[3])
|
|
119
|
+
|
|
120
|
+
if not userId or not terminal or not absoluteExpiresAtMs then
|
|
121
|
+
return { 0, 'NOT_FOUND' }
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
if not isValidUserId(userId) or not isValidTerminal(terminal) then
|
|
125
|
+
return { 0, 'INVALID_SESSION_DATA' }
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
local slotKey = slotKeyPrefix .. userId .. ':' .. terminal
|
|
129
|
+
local slotDigest = redis.call('GET', slotKey)
|
|
130
|
+
|
|
131
|
+
if slotDigest ~= currentDigest then
|
|
132
|
+
redis.call('DEL', KEYS[1])
|
|
133
|
+
return { 0, 'REPLACED' }
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
local redisTime = redis.call('TIME')
|
|
137
|
+
local nowMs = tonumber(redisTime[1]) * 1000 + math.floor(tonumber(redisTime[2]) / 1000)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
if nowMs >= absoluteExpiresAtMs then
|
|
141
|
+
redis.call('DEL', KEYS[1])
|
|
142
|
+
redis.call('DEL', slotKey)
|
|
143
|
+
return { 0, 'ABSOLUTE_EXPIRED' }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
local expiresAtMs = math.min(nowMs + idleTtlMs, absoluteExpiresAtMs)
|
|
147
|
+
redis.call('HSET', KEYS[1], 'lastSeenAtMs', tostring(nowMs))
|
|
148
|
+
redis.call('PEXPIREAT', KEYS[1], expiresAtMs)
|
|
149
|
+
redis.call('PEXPIREAT', slotKey, expiresAtMs)
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
1,
|
|
153
|
+
userId,
|
|
154
|
+
terminal,
|
|
155
|
+
tostring(expiresAtMs)
|
|
156
|
+
}
|
|
157
|
+
`
|
|
158
|
+
|
|
159
|
+
export const LOGOUT_SESSION_SCRIPT = String.raw`
|
|
160
|
+
local function isValidTerminal(value)
|
|
161
|
+
return value == 'web' or value == 'desktop' or value == 'mobile'
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
local function isValidUserId(value)
|
|
165
|
+
return string.len(value) > 0
|
|
166
|
+
and string.len(value) <= 100
|
|
167
|
+
and string.match(value, '^[%w_-]+$') ~= nil
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
local currentDigest = ARGV[1]
|
|
171
|
+
local slotKeyPrefix = ARGV[2]
|
|
172
|
+
|
|
173
|
+
local sessionValues = redis.call(
|
|
174
|
+
'HMGET',
|
|
175
|
+
KEYS[1],
|
|
176
|
+
'userId',
|
|
177
|
+
'terminal'
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
local userId = sessionValues[1]
|
|
181
|
+
local terminal = sessionValues[2]
|
|
182
|
+
|
|
183
|
+
if not userId or not terminal then
|
|
184
|
+
return { 1, 'ALREADY_GONE' }
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
if not isValidUserId(userId) or not isValidTerminal(terminal) then
|
|
188
|
+
return { 0, 'INVALID_SESSION_DATA' }
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
local slotKey = slotKeyPrefix .. userId .. ':' .. terminal
|
|
192
|
+
local slotDigest = redis.call('GET', slotKey)
|
|
193
|
+
|
|
194
|
+
if slotDigest == currentDigest then
|
|
195
|
+
redis.call('DEL', slotKey)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
redis.call('DEL', KEYS[1])
|
|
199
|
+
|
|
200
|
+
return { 1, 'LOGGED_OUT' }
|
|
201
|
+
`
|
|
202
|
+
|
|
203
|
+
export const REVOKE_USER_SESSIONS_SCRIPT = String.raw`
|
|
204
|
+
local sessionKeyPrefix = ARGV[1]
|
|
205
|
+
local revokedCount = 0
|
|
206
|
+
|
|
207
|
+
for index = 1, #KEYS DO
|
|
208
|
+
local digest = redis.call('GET', KEYS[index])
|
|
209
|
+
|
|
210
|
+
if digest
|
|
211
|
+
and string.len(digest) == 64
|
|
212
|
+
and string.match(digest, '^[0-9a-f]+$') ~= nil then
|
|
213
|
+
redis.call('DEL', sessionKeyPrefix .. digest)
|
|
214
|
+
revokedCount = revokedCount + 1
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
redis.call('DEL', KEYS[index])
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
return { 1, tostring(revokedCount) }
|
|
221
|
+
`
|
package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.types.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FastifyRequest } from 'fastify'
|
|
2
|
+
import { SessionTerminalType } from 'shared/types'
|
|
3
|
+
|
|
4
|
+
export interface CurrentAuthType {
|
|
5
|
+
userId: string
|
|
6
|
+
terminal: SessionTerminalType
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type AuthenticatedRequest = FastifyRequest & {
|
|
10
|
+
auth?: CurrentAuthType
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface CreateSessionInput {
|
|
14
|
+
tokenDigest: string
|
|
15
|
+
userId: string
|
|
16
|
+
terminal: SessionTerminalType
|
|
17
|
+
loginIp: string
|
|
18
|
+
userAgent: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CreatedSession {
|
|
22
|
+
initialExpiresAtMs: number
|
|
23
|
+
absoluteExpiresAtMs: number
|
|
24
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Body, Controller, Get, Post } from '@nestjs/common'
|
|
2
|
+
import { ApiOperation, ApiTags } from '@nestjs/swagger'
|
|
2
3
|
import { DbService } from './db.service'
|
|
3
|
-
import { ApiBody, ApiOperation, ApiTags } from '@nestjs/swagger'
|
|
4
4
|
import { CreateUserDto } from './dto/create-user.dto'
|
|
5
5
|
|
|
6
6
|
@ApiTags('DB 测试')
|
package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/dto/create-user.dto.ts
CHANGED
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
import { users } from '@/database/schema'
|
|
2
2
|
import { createInsertSchema } from 'drizzle-zod'
|
|
3
3
|
import { createZodDto } from 'nestjs-zod'
|
|
4
|
-
import { z } from 'zod'
|
|
5
4
|
/**
|
|
6
5
|
* 1. 基于数据库表生成zod schema
|
|
7
6
|
* drizzle-zod 会自动把 varchar({ length: 100 }) 翻成 .max(100)
|
|
8
7
|
* 把notNull 翻成 必填字段
|
|
9
8
|
*/
|
|
10
9
|
|
|
11
|
-
const baseSchema = createInsertSchema(users
|
|
12
|
-
// 数据库不知道邮箱格式, 这里用zod增强
|
|
13
|
-
email: z.email(),
|
|
14
|
-
})
|
|
10
|
+
const baseSchema = createInsertSchema(users)
|
|
15
11
|
|
|
16
12
|
/**
|
|
17
13
|
* 2. 创建用户的入参不应该包括 id 和 createdAt(这两数据库自动生成)
|
|
18
14
|
*/
|
|
19
15
|
export const createUserSchema = baseSchema.omit({
|
|
20
16
|
id: true,
|
|
17
|
+
status: true,
|
|
21
18
|
createdAt: true,
|
|
19
|
+
updatedAt: true,
|
|
22
20
|
})
|
|
23
21
|
|
|
24
22
|
/**
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { COMMON_ERRORS } from '@/common/error/common.error'
|
|
2
|
+
import { AUTH_ERRORS } from '@/modules/auth/auth.errors'
|
|
3
|
+
import { describe, expect, it } from 'vite-plus/test'
|
|
4
|
+
|
|
5
|
+
const definitions = [...Object.values(COMMON_ERRORS), ...Object.values(AUTH_ERRORS)]
|
|
6
|
+
|
|
7
|
+
describe('error catalog', () => {
|
|
8
|
+
it('uses valid and globally unique error codes', () => {
|
|
9
|
+
const codes = definitions.map((definition) => definition.code)
|
|
10
|
+
|
|
11
|
+
expect(new Set(codes).size).toBe(codes.length)
|
|
12
|
+
|
|
13
|
+
for (const definition of definitions) {
|
|
14
|
+
expect(definition.code).toMatch(/^[A-Z][A-Z0-9_]*(?:\.[A-Z][A-Z0-9_]*)+$/)
|
|
15
|
+
expect(definition.code.length).toBeLessThanOrEqual(80)
|
|
16
|
+
expect(definition.status).toBeGreaterThanOrEqual(400)
|
|
17
|
+
expect(definition.status).toBeLessThanOrEqual(599)
|
|
18
|
+
expect(definition.publicMessage.trim()).not.toBe('')
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('keeps bearerChallenge and HTTP 401 in sync', () => {
|
|
23
|
+
for (const definition of definitions) {
|
|
24
|
+
const hasBearerChallenge =
|
|
25
|
+
'bearerChallenge' in definition && definition.bearerChallenge === true
|
|
26
|
+
|
|
27
|
+
expect(hasBearerChallenge).toBe(definition.status === 401)
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "./tsconfig.json",
|
|
3
|
-
"
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"noEmit": false,
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"sourceMap": true,
|
|
8
|
+
"removeComments": true,
|
|
9
|
+
"incremental": false,
|
|
10
|
+
"declaration": false
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*.ts"],
|
|
13
|
+
"exclude": ["node_modules", "test", "dist", "**/*.spec.ts"]
|
|
4
14
|
}
|
|
@@ -1,28 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
2
3
|
"compilerOptions": {
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
4
|
+
"target": "ES2023",
|
|
5
|
+
"module": "NodeNext",
|
|
6
|
+
"moduleResolution": "NodeNext",
|
|
7
|
+
"types": ["node"],
|
|
7
8
|
"isolatedModules": true,
|
|
8
|
-
"declaration": true,
|
|
9
|
-
"removeComments": true,
|
|
10
|
-
"emitDecoratorMetadata": true,
|
|
11
9
|
"experimentalDecorators": true,
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"rootDir": "./",
|
|
17
|
-
"incremental": true,
|
|
18
|
-
"skipLibCheck": true,
|
|
19
|
-
"strictNullChecks": true,
|
|
20
|
-
"forceConsistentCasingInFileNames": true,
|
|
21
|
-
"noImplicitAny": false,
|
|
22
|
-
"strictBindCallApply": false,
|
|
23
|
-
"noFallthroughCasesInSwitch": false,
|
|
10
|
+
"emitDecoratorMetadata": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"noUncheckedIndexedAccess": true,
|
|
24
14
|
"paths": {
|
|
25
15
|
"@/*": ["./src/*"]
|
|
26
16
|
}
|
|
27
|
-
}
|
|
17
|
+
},
|
|
18
|
+
"include": ["src/**/*.ts", "test/**/*.ts", "*.config.ts"],
|
|
19
|
+
"exclude": ["node_modules", "dist"]
|
|
28
20
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { resolve } from 'path'
|
|
2
|
+
import { defineConfig } from 'vite-plus'
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
resolve: {
|
|
6
|
+
alias: {
|
|
7
|
+
'@': resolve(__dirname, 'src'),
|
|
8
|
+
},
|
|
9
|
+
},
|
|
10
|
+
test: {
|
|
11
|
+
environment: 'node',
|
|
12
|
+
include: ['test/**/*.spec.ts'],
|
|
13
|
+
restoreMocks: true,
|
|
14
|
+
},
|
|
15
|
+
})
|
|
@@ -1,28 +1,18 @@
|
|
|
1
1
|
{
|
|
2
|
-
"extends": "../../tsconfig.json",
|
|
2
|
+
"extends": "../../tsconfig.bundler.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
|
-
"target": "
|
|
5
|
-
"
|
|
4
|
+
"target": "ES2023",
|
|
5
|
+
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
|
6
6
|
"jsx": "react-jsx",
|
|
7
|
-
"lib": ["ES2023", "DOM"],
|
|
8
7
|
"types": ["vite-plus/client"],
|
|
9
8
|
"paths": {
|
|
10
9
|
"@/*": ["./src/*"]
|
|
11
10
|
},
|
|
12
|
-
"skipLibCheck": true,
|
|
13
|
-
|
|
14
|
-
/* Bundler mode */
|
|
15
|
-
"moduleResolution": "bundler",
|
|
16
11
|
"allowImportingTsExtensions": true,
|
|
17
|
-
"
|
|
18
|
-
"moduleDetection": "force",
|
|
19
|
-
"noEmit": true,
|
|
20
|
-
|
|
21
|
-
/* Linting */
|
|
12
|
+
"erasableSyntaxOnly": true,
|
|
22
13
|
"noUnusedLocals": true,
|
|
23
14
|
"noUnusedParameters": true,
|
|
24
|
-
"
|
|
25
|
-
"noFallthroughCasesInSwitch": true
|
|
15
|
+
"noUncheckedIndexedAccess": true
|
|
26
16
|
},
|
|
27
17
|
"include": ["src"]
|
|
28
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default { extends: [
|
|
1
|
+
export default { extends: ['@commitlint/config-conventional'] }
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@alova/adapter-axios": "catalog:",
|
|
15
15
|
"@antdv-next/icons": "catalog:",
|
|
16
|
-
"@bubblesjs/i18n-vue": "workspace:*",
|
|
17
16
|
"alova": "catalog:",
|
|
18
17
|
"antdv-next": "catalog:",
|
|
19
18
|
"axios": "catalog:",
|
|
@@ -34,7 +33,6 @@
|
|
|
34
33
|
"@commitlint/config-conventional": "catalog:",
|
|
35
34
|
"@types/node": "catalog:",
|
|
36
35
|
"@types/nprogress": "catalog:",
|
|
37
|
-
"@typescript/native": "catalog:",
|
|
38
36
|
"@unocss/eslint-plugin": "catalog:",
|
|
39
37
|
"@unocss/preset-attributify": "catalog:",
|
|
40
38
|
"@unocss/preset-wind4": "catalog:",
|
|
@@ -47,7 +45,7 @@
|
|
|
47
45
|
"lefthook": "catalog:",
|
|
48
46
|
"oxlint": "catalog:",
|
|
49
47
|
"sass": "catalog:",
|
|
50
|
-
"typescript": "catalog:
|
|
48
|
+
"typescript": "catalog:",
|
|
51
49
|
"unocss": "catalog:",
|
|
52
50
|
"unplugin-auto-import": "catalog:",
|
|
53
51
|
"unplugin-vue-components": "catalog:",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import request from
|
|
1
|
+
import request from '@/utils/request'
|
|
2
2
|
|
|
3
|
-
export const EXPIRE_TIME = 60 * 10 * 1000
|
|
3
|
+
export const EXPIRE_TIME = 60 * 10 * 1000
|
|
4
4
|
|
|
5
5
|
export function getTree() {
|
|
6
|
-
return request.Get(
|
|
6
|
+
return request.Get('/xxx/xx', {
|
|
7
7
|
cacheFor: {
|
|
8
|
-
mode:
|
|
8
|
+
mode: 'restore',
|
|
9
9
|
expire: EXPIRE_TIME,
|
|
10
10
|
},
|
|
11
|
-
})
|
|
11
|
+
})
|
|
12
12
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
PictorialBarChart,
|
|
7
7
|
PieChart,
|
|
8
8
|
RadarChart,
|
|
9
|
-
} from
|
|
9
|
+
} from 'echarts/charts'
|
|
10
10
|
import {
|
|
11
11
|
AriaComponent,
|
|
12
12
|
CalendarComponent,
|
|
@@ -22,11 +22,11 @@ import {
|
|
|
22
22
|
ToolboxComponent,
|
|
23
23
|
TooltipComponent,
|
|
24
24
|
VisualMapComponent,
|
|
25
|
-
} from
|
|
26
|
-
import * as echarts from
|
|
25
|
+
} from 'echarts/components'
|
|
26
|
+
import * as echarts from 'echarts/core'
|
|
27
27
|
// TODO 如果想换成SVG渲染,就导出SVGRenderer,
|
|
28
28
|
// 并且放到 echarts.use 里,注释掉 CanvasRenderer
|
|
29
|
-
import { /* SVGRenderer */ CanvasRenderer } from
|
|
29
|
+
import { /* SVGRenderer */ CanvasRenderer } from 'echarts/renderers'
|
|
30
30
|
|
|
31
31
|
echarts.use([
|
|
32
32
|
LegendComponent,
|
|
@@ -52,6 +52,6 @@ echarts.use([
|
|
|
52
52
|
TimelineComponent,
|
|
53
53
|
CalendarComponent,
|
|
54
54
|
GraphicComponent,
|
|
55
|
-
])
|
|
55
|
+
])
|
|
56
56
|
|
|
57
|
-
export default echarts
|
|
57
|
+
export default echarts
|
|
@@ -1,27 +1,29 @@
|
|
|
1
|
-
import type { EChartsOption } from
|
|
1
|
+
import type { EChartsOption } from 'echarts'
|
|
2
2
|
|
|
3
|
-
import type { ShallowRef } from
|
|
3
|
+
import type { ShallowRef } from 'vue'
|
|
4
4
|
|
|
5
|
-
import { debounce } from
|
|
5
|
+
import { debounce } from 'radashi'
|
|
6
6
|
|
|
7
|
-
import echarts from
|
|
7
|
+
import echarts from './lib'
|
|
8
8
|
|
|
9
|
-
type setOptionsType = (options: EChartsOption, clear?: boolean) => void
|
|
9
|
+
type setOptionsType = (options: EChartsOption, clear?: boolean) => void
|
|
10
10
|
|
|
11
11
|
export function useECharts(
|
|
12
12
|
elRef: Ref<HTMLDivElement> | Readonly<ShallowRef<HTMLDivElement | null>>,
|
|
13
13
|
) {
|
|
14
|
-
let chartInstance: echarts.ECharts | null = null
|
|
15
|
-
let resizeObserver: ResizeObserver | undefined
|
|
14
|
+
let chartInstance: echarts.ECharts | null = null
|
|
15
|
+
let resizeObserver: ResizeObserver | undefined
|
|
16
16
|
|
|
17
17
|
const resize = () => {
|
|
18
|
-
chartInstance?.resize()
|
|
19
|
-
}
|
|
18
|
+
chartInstance?.resize()
|
|
19
|
+
}
|
|
20
20
|
|
|
21
21
|
const initCharts = () => {
|
|
22
|
-
if (!elRef)
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
if (!elRef)
|
|
23
|
+
return
|
|
24
|
+
const el = unref(elRef)
|
|
25
|
+
if (!el)
|
|
26
|
+
return
|
|
25
27
|
|
|
26
28
|
resizeObserver = new ResizeObserver(
|
|
27
29
|
debounce(
|
|
@@ -30,36 +32,39 @@ export function useECharts(
|
|
|
30
32
|
},
|
|
31
33
|
resize,
|
|
32
34
|
),
|
|
33
|
-
)
|
|
34
|
-
resizeObserver.observe(el)
|
|
35
|
+
)
|
|
36
|
+
resizeObserver.observe(el)
|
|
35
37
|
|
|
36
|
-
chartInstance = echarts.init(el)
|
|
37
|
-
}
|
|
38
|
+
chartInstance = echarts.init(el)
|
|
39
|
+
}
|
|
38
40
|
|
|
39
41
|
const setOptions: setOptionsType = (options, clear = true) => {
|
|
40
42
|
if (!chartInstance) {
|
|
41
|
-
initCharts()
|
|
42
|
-
if (!chartInstance)
|
|
43
|
+
initCharts()
|
|
44
|
+
if (!chartInstance)
|
|
45
|
+
return
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
if (clear)
|
|
48
|
+
chartInstance.clear()
|
|
49
|
+
chartInstance?.setOption(options)
|
|
50
|
+
}
|
|
47
51
|
|
|
48
52
|
const getInstance: () => echarts.ECharts | null = () => {
|
|
49
|
-
if (!chartInstance)
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
if (!chartInstance)
|
|
54
|
+
initCharts()
|
|
55
|
+
return chartInstance
|
|
56
|
+
}
|
|
52
57
|
|
|
53
58
|
onUnmounted(() => {
|
|
54
|
-
chartInstance?.dispose()
|
|
55
|
-
resizeObserver?.disconnect()
|
|
56
|
-
resizeObserver = undefined
|
|
57
|
-
})
|
|
59
|
+
chartInstance?.dispose()
|
|
60
|
+
resizeObserver?.disconnect()
|
|
61
|
+
resizeObserver = undefined
|
|
62
|
+
})
|
|
58
63
|
|
|
59
64
|
return {
|
|
60
65
|
setOptions,
|
|
61
66
|
resize,
|
|
62
67
|
echarts,
|
|
63
68
|
getInstance,
|
|
64
|
-
}
|
|
69
|
+
}
|
|
65
70
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createJsonStorage, i18n } from '@bubblesjs/i18n-core'
|
|
2
2
|
|
|
3
|
+
// Initialization must finish before App renders so the first locale is available synchronously.
|
|
4
|
+
// eslint-disable-next-line antfu/no-top-level-await
|
|
3
5
|
export const leftStore = await i18n.init({
|
|
4
6
|
locale: 'zh_CN',
|
|
5
7
|
loaderMessage: async (locale?: string) => (await import(`@/locales/${locale}.json`))?.default,
|