create-bubbles 0.1.22 → 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.
Files changed (281) hide show
  1. package/dist/index.mjs +5 -0
  2. package/index.js +1 -1
  3. package/package.json +25 -24
  4. package/template-taro-react-oxc/.env.development +1 -1
  5. package/template-taro-react-oxc/.env.production +1 -1
  6. package/template-taro-react-oxc/project.config.json +1 -1
  7. package/template-taro-vue-eslint/project.config.json +2 -2
  8. 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
  9. package/template-vp-monorepo-react-hono/.vite-hooks/commit-msg +2 -0
  10. package/template-vp-monorepo-react-hono/.vite-hooks/pre-commit +2 -0
  11. package/template-vp-monorepo-react-hono/.vscode/extensions.json +3 -0
  12. package/template-vp-monorepo-react-hono/.vscode/settings.json +23 -0
  13. package/template-vp-monorepo-react-hono/AGENTS.md +16 -0
  14. package/template-vp-monorepo-react-hono/README.md +54 -0
  15. package/template-vp-monorepo-react-hono/apps/server/.env.example +13 -0
  16. package/template-vp-monorepo-react-hono/apps/server/README.md +75 -0
  17. package/template-vp-monorepo-react-hono/apps/server/drizzle/0000_flaky_madame_masque.sql +18 -0
  18. package/template-vp-monorepo-react-hono/apps/server/drizzle/meta/0000_snapshot.json +153 -0
  19. package/template-vp-monorepo-react-hono/apps/server/drizzle/meta/_journal.json +13 -0
  20. package/template-vp-monorepo-react-hono/apps/server/drizzle.config.ts +19 -0
  21. package/template-vp-monorepo-react-hono/apps/server/package.json +46 -0
  22. package/template-vp-monorepo-react-hono/apps/server/src/app.test.ts +57 -0
  23. package/template-vp-monorepo-react-hono/apps/server/src/app.ts +68 -0
  24. package/template-vp-monorepo-react-hono/apps/server/src/common/errors/app-error.ts +23 -0
  25. package/template-vp-monorepo-react-hono/apps/server/src/common/http/response.ts +21 -0
  26. package/template-vp-monorepo-react-hono/apps/server/src/common/logger.ts +30 -0
  27. package/template-vp-monorepo-react-hono/apps/server/src/config/env.ts +54 -0
  28. package/template-vp-monorepo-react-hono/apps/server/src/index.bun.ts +60 -0
  29. package/template-vp-monorepo-react-hono/apps/server/src/index.ts +73 -0
  30. package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/database/client.ts +46 -0
  31. package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/database/schema/index.ts +1 -0
  32. package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/database/schema/job-runs.ts +42 -0
  33. package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/queue/connection.ts +6 -0
  34. package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/redis/client.ts +39 -0
  35. package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/redis/options.ts +28 -0
  36. package/template-vp-monorepo-react-hono/apps/server/src/modules/health/health.routes.ts +17 -0
  37. package/template-vp-monorepo-react-hono/apps/server/src/modules/health/health.service.ts +59 -0
  38. package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.queue.ts +46 -0
  39. package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.repository.ts +101 -0
  40. package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.routes.ts +46 -0
  41. package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.schemas.ts +9 -0
  42. package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.service.ts +57 -0
  43. package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.types.ts +11 -0
  44. package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.worker.ts +108 -0
  45. package/template-vp-monorepo-react-hono/apps/server/src/runtime/shutdown.ts +38 -0
  46. package/template-vp-monorepo-react-hono/apps/server/src/worker.ts +48 -0
  47. package/template-vp-monorepo-react-hono/apps/server/tsconfig.json +15 -0
  48. package/template-vp-monorepo-react-hono/apps/server/vite.config.ts +15 -0
  49. package/template-vp-monorepo-react-hono/apps/web/.env +2 -0
  50. package/template-vp-monorepo-react-hono/apps/web/.env.dev +1 -0
  51. package/template-vp-monorepo-react-hono/apps/web/.env.prod +1 -0
  52. package/template-vp-monorepo-react-hono/apps/web/index.html +13 -0
  53. package/template-vp-monorepo-react-hono/apps/web/package.json +35 -0
  54. package/template-vp-monorepo-react-hono/apps/web/public/favicon.svg +1 -0
  55. package/template-vp-monorepo-react-hono/apps/web/public/icons.svg +24 -0
  56. package/template-vp-monorepo-react-hono/apps/web/src/App.tsx +25 -0
  57. package/template-vp-monorepo-react-hono/apps/web/src/assets/hero.png +0 -0
  58. package/template-vp-monorepo-react-hono/apps/web/src/assets/react.svg +1 -0
  59. package/template-vp-monorepo-react-hono/apps/web/src/assets/vite.svg +1 -0
  60. package/template-vp-monorepo-react-hono/apps/web/src/components/Loading/PageLoading.tsx +11 -0
  61. package/template-vp-monorepo-react-hono/apps/web/src/locales/en_US.json +4 -0
  62. package/template-vp-monorepo-react-hono/apps/web/src/locales/zh_CN.json +4 -0
  63. package/template-vp-monorepo-react-hono/apps/web/src/main.tsx +5 -0
  64. package/template-vp-monorepo-react-hono/apps/web/src/pages/home/index.tsx +47 -0
  65. package/template-vp-monorepo-react-hono/apps/web/src/router/index.tsx +25 -0
  66. package/template-vp-monorepo-react-hono/apps/web/src/router/modules/.gitkeep +0 -0
  67. package/template-vp-monorepo-react-hono/apps/web/src/styles/index.css +7 -0
  68. package/template-vp-monorepo-react-hono/apps/web/src/types/auto-imports.d.ts +58 -0
  69. package/template-vp-monorepo-react-hono/apps/web/src/utils/env/index.ts +6 -0
  70. package/template-vp-monorepo-react-hono/apps/web/src/utils/request/core/index.ts +420 -0
  71. package/template-vp-monorepo-react-hono/apps/web/src/utils/request/core/utils.ts +39 -0
  72. package/template-vp-monorepo-react-hono/apps/web/src/utils/request/index.ts +61 -0
  73. package/template-vp-monorepo-react-hono/apps/web/tsconfig.json +18 -0
  74. package/template-vp-monorepo-react-hono/apps/web/vite.config.ts +45 -0
  75. package/template-vp-monorepo-react-hono/commitlint.config.js +1 -0
  76. package/template-vp-monorepo-react-hono/docker-compose.yml +41 -0
  77. package/template-vp-monorepo-react-hono/mise.toml +4 -0
  78. package/template-vp-monorepo-react-hono/package.json +37 -0
  79. package/template-vp-monorepo-react-hono/packages/i18n/core/package.json +20 -0
  80. package/template-vp-monorepo-react-hono/packages/i18n/core/src/format.ts +9 -0
  81. package/template-vp-monorepo-react-hono/packages/i18n/core/src/i18n.ts +73 -0
  82. package/template-vp-monorepo-react-hono/packages/i18n/core/src/index.ts +24 -0
  83. package/template-vp-monorepo-react-hono/packages/i18n/core/src/storage.ts +47 -0
  84. package/template-vp-monorepo-react-hono/packages/i18n/core/src/store.ts +48 -0
  85. package/template-vp-monorepo-react-hono/packages/i18n/core/src/types.ts +36 -0
  86. package/template-vp-monorepo-react-hono/packages/i18n/core/tsconfig.json +4 -0
  87. package/template-vp-monorepo-react-hono/packages/i18n/core/vite.config.ts +13 -0
  88. package/template-vp-monorepo-react-hono/packages/i18n/react/package.json +28 -0
  89. package/template-vp-monorepo-react-hono/packages/i18n/react/src/index.tsx +26 -0
  90. package/template-vp-monorepo-react-hono/packages/i18n/react/src/use-store.ts +14 -0
  91. package/template-vp-monorepo-react-hono/packages/i18n/react/tsconfig.json +9 -0
  92. package/template-vp-monorepo-react-hono/packages/i18n/react/vite.config.ts +16 -0
  93. package/template-vp-monorepo-react-hono/packages/i18n/vue/package.json +27 -0
  94. package/template-vp-monorepo-react-hono/packages/i18n/vue/src/index.ts +52 -0
  95. package/template-vp-monorepo-react-hono/packages/i18n/vue/src/use-store.ts +19 -0
  96. package/template-vp-monorepo-react-hono/packages/i18n/vue/tsconfig.json +8 -0
  97. package/template-vp-monorepo-react-hono/packages/i18n/vue/vite.config.ts +16 -0
  98. package/template-vp-monorepo-react-hono/pnpm-workspace.yaml +57 -0
  99. package/template-vp-monorepo-react-hono/scripts/clean.mjs +48 -0
  100. package/template-vp-monorepo-react-hono/tsconfig.base.json +10 -0
  101. package/template-vp-monorepo-react-hono/tsconfig.bundler.json +12 -0
  102. package/template-vp-monorepo-react-hono/tsconfig.json +11 -0
  103. package/template-vp-monorepo-react-hono/tsconfig.lib.json +10 -0
  104. package/template-vp-monorepo-react-hono/vite.config.ts +20 -0
  105. package/template-vp-monorepo-react-nestjs/.spaces/server/todo.md +991 -0
  106. package/template-vp-monorepo-react-nestjs/.vscode/launch.json +16 -0
  107. package/template-vp-monorepo-react-nestjs/.vscode/settings.json +21 -17
  108. package/template-vp-monorepo-react-nestjs/apps/server/.env.development +3 -39
  109. package/template-vp-monorepo-react-nestjs/apps/server/.swcrc +8 -0
  110. package/template-vp-monorepo-react-nestjs/apps/server/drizzle.config.ts +8 -3
  111. package/template-vp-monorepo-react-nestjs/apps/server/nest-cli.json +8 -1
  112. package/template-vp-monorepo-react-nestjs/apps/server/package.json +11 -6
  113. package/template-vp-monorepo-react-nestjs/apps/server/src/app.controller.ts +2 -0
  114. package/template-vp-monorepo-react-nestjs/apps/server/src/app.module.ts +20 -15
  115. package/template-vp-monorepo-react-nestjs/apps/server/src/common/adapters/fastify.adapter.ts +16 -0
  116. package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/auth.ts +2 -0
  117. package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/response.ts +0 -4
  118. package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/session.constants.ts +28 -0
  119. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/current-auth.decorator.ts +16 -0
  120. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/public.decorator.ts +4 -0
  121. package/template-vp-monorepo-react-nestjs/apps/server/src/common/dto/api-failure.dto.ts +25 -0
  122. package/template-vp-monorepo-react-nestjs/apps/server/src/common/error/common.error.ts +40 -0
  123. package/template-vp-monorepo-react-nestjs/apps/server/src/common/exceptions/app.exception.ts +55 -0
  124. package/template-vp-monorepo-react-nestjs/apps/server/src/common/filters/global-exception.filter.ts +384 -0
  125. package/template-vp-monorepo-react-nestjs/apps/server/src/common/openapi/response-headers.ts +9 -0
  126. package/template-vp-monorepo-react-nestjs/apps/server/src/config/index.ts +1 -1
  127. package/template-vp-monorepo-react-nestjs/apps/server/src/config/session.config.ts +36 -0
  128. package/template-vp-monorepo-react-nestjs/apps/server/src/database/schema.ts +7 -8
  129. package/template-vp-monorepo-react-nestjs/apps/server/src/main.ts +29 -8
  130. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.controller.ts +55 -0
  131. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.errors.ts +42 -0
  132. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.module.ts +26 -0
  133. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.repository.ts +40 -0
  134. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.service.ts +129 -0
  135. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/auth-repsponse.dto.ts +31 -0
  136. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/login.dto.ts +11 -0
  137. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/register.dto.ts +17 -0
  138. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/guards/session-auth.guard.ts +50 -0
  139. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password.service.ts +24 -0
  140. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-store.service.ts +198 -0
  141. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-token.service.ts +29 -0
  142. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.script.ts +221 -0
  143. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.types.ts +24 -0
  144. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.controller.ts +1 -1
  145. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/dto/create-user.dto.ts +3 -5
  146. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.service.ts +1 -1
  147. package/template-vp-monorepo-react-nestjs/apps/server/src/utils/env-arr.ts +3 -0
  148. package/template-vp-monorepo-react-nestjs/apps/server/test/error-catalog.spec.ts +30 -0
  149. package/template-vp-monorepo-react-nestjs/apps/server/tsconfig.build.json +11 -1
  150. package/template-vp-monorepo-react-nestjs/apps/server/tsconfig.json +12 -20
  151. package/template-vp-monorepo-react-nestjs/apps/server/vite.config.ts +15 -0
  152. package/template-vp-monorepo-react-nestjs/apps/web/package.json +1 -0
  153. package/template-vp-monorepo-react-nestjs/apps/web/tsconfig.json +5 -15
  154. package/template-vp-monorepo-react-nestjs/apps/web-vue/commitlint.config.js +1 -1
  155. package/template-vp-monorepo-react-nestjs/apps/web-vue/lefthook.yml +1 -1
  156. package/template-vp-monorepo-react-nestjs/apps/web-vue/package.json +1 -3
  157. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/api/index.ts +5 -5
  158. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/components/Icon/svg-icon.vue +3 -3
  159. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/hooks/chart/lib.ts +6 -6
  160. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/hooks/chart/useEcharts.ts +34 -29
  161. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/i18n/instance.ts +2 -0
  162. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/index.vue +17 -32
  163. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/locales/en_US.json +4 -1
  164. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/locales/zh_CN.json +4 -1
  165. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/index.ts +3 -3
  166. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/permissionGuard.ts +7 -7
  167. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/index.ts +7 -7
  168. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/interface.ts +6 -6
  169. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/index.ts +6 -6
  170. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/modules/user.ts +9 -9
  171. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/styles/index.scss +3 -3
  172. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/types/antdv-next.d.ts +1 -0
  173. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/env.ts +1 -1
  174. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/index.ts +63 -45
  175. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/utils.ts +12 -6
  176. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/index.ts +1 -1
  177. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/echart/config.ts +687 -687
  178. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/echart/index.vue +7 -7
  179. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/tree-chart.vue +2 -7
  180. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/home/index.vue +13 -3
  181. package/template-vp-monorepo-react-nestjs/apps/web-vue/tsconfig.json +5 -17
  182. package/template-vp-monorepo-react-nestjs/apps/web-vue/uno.config.ts +5 -5
  183. package/template-vp-monorepo-react-nestjs/i18n.config.ts +22 -0
  184. package/template-vp-monorepo-react-nestjs/package.json +12 -1
  185. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/README.md +113 -0
  186. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/docs/excel-sync-plan.md +618 -0
  187. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/package.json +31 -0
  188. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/cli.ts +5 -0
  189. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/command.ts +512 -0
  190. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/config.ts +15 -0
  191. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/files.ts +67 -0
  192. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/index.ts +19 -0
  193. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/load-config.ts +228 -0
  194. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/report.ts +57 -0
  195. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.test.ts +81 -0
  196. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.ts +290 -0
  197. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/sync.ts +274 -0
  198. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/command.test.ts +209 -0
  199. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/config.test.ts +19 -0
  200. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/load-config.test.ts +194 -0
  201. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/report.test.ts +63 -0
  202. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/sync.test.ts +203 -0
  203. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/temporary-directory.ts +25 -0
  204. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/tsconfig.json +9 -0
  205. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/vite.config.ts +18 -0
  206. package/template-vp-monorepo-react-nestjs/packages/i18n/core/tsconfig.json +1 -12
  207. package/template-vp-monorepo-react-nestjs/packages/i18n/react/tsconfig.json +3 -10
  208. package/template-vp-monorepo-react-nestjs/packages/i18n/vue/tsconfig.json +3 -10
  209. package/template-vp-monorepo-react-nestjs/packages/shared/package.json +40 -0
  210. package/template-vp-monorepo-react-nestjs/packages/shared/src/index.ts +13 -0
  211. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/auth.ts +35 -0
  212. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/common.ts +11 -0
  213. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/index.ts +11 -0
  214. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/account.ts +5 -0
  215. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/index.ts +2 -0
  216. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/session-terminal.ts +11 -0
  217. package/template-vp-monorepo-react-nestjs/packages/shared/tsconfig.json +4 -0
  218. package/template-vp-monorepo-react-nestjs/packages/shared/vite.config.ts +17 -0
  219. package/template-vp-monorepo-react-nestjs/pnpm-workspace.yaml +6 -6
  220. package/template-vp-monorepo-react-nestjs/scripts/clean.mjs +48 -0
  221. package/template-vp-monorepo-react-nestjs/tsconfig.base.json +10 -0
  222. package/template-vp-monorepo-react-nestjs/tsconfig.bundler.json +12 -0
  223. package/template-vp-monorepo-react-nestjs/tsconfig.json +8 -6
  224. package/template-vp-monorepo-react-nestjs/tsconfig.lib.json +10 -0
  225. package/template-vp-monorepo-react-nestjs/vite.config.ts +2 -1
  226. package/template-vp-vue-eslint-vapor/.env +6 -0
  227. package/template-vp-vue-eslint-vapor/.env.development +2 -0
  228. package/template-vp-vue-eslint-vapor/.env.production +2 -0
  229. package/template-vp-vue-eslint-vapor/.vite-hooks/commit-msg +1 -0
  230. package/template-vp-vue-eslint-vapor/.vite-hooks/pre-commit +1 -0
  231. package/template-vp-vue-eslint-vapor/.vscode/extensions.json +3 -0
  232. package/template-vp-vue-eslint-vapor/AGENTS.md +16 -0
  233. package/template-vp-vue-eslint-vapor/README.md +93 -0
  234. package/template-vp-vue-eslint-vapor/commitlint.config.js +1 -0
  235. package/template-vp-vue-eslint-vapor/eslint.config.js +13 -0
  236. package/template-vp-vue-eslint-vapor/index.html +13 -0
  237. package/template-vp-vue-eslint-vapor/package.json +64 -0
  238. package/template-vp-vue-eslint-vapor/pnpm-workspace.yaml +2 -0
  239. package/template-vp-vue-eslint-vapor/public/vite.svg +1 -0
  240. package/template-vp-vue-eslint-vapor/src/App.vue +7 -0
  241. package/template-vp-vue-eslint-vapor/src/api/index.ts +12 -0
  242. package/template-vp-vue-eslint-vapor/src/assets/icon/home.svg +3 -0
  243. package/template-vp-vue-eslint-vapor/src/assets/icon/logo.svg +1 -0
  244. package/template-vp-vue-eslint-vapor/src/assets/image/.gitkeep +0 -0
  245. package/template-vp-vue-eslint-vapor/src/components/Icon/svg-icon.vue +29 -0
  246. package/template-vp-vue-eslint-vapor/src/hooks/chart/lib.ts +57 -0
  247. package/template-vp-vue-eslint-vapor/src/hooks/chart/useEcharts.ts +65 -0
  248. package/template-vp-vue-eslint-vapor/src/layout/default/header/index.vue +57 -0
  249. package/template-vp-vue-eslint-vapor/src/layout/default/index.vue +138 -0
  250. package/template-vp-vue-eslint-vapor/src/main.ts +19 -0
  251. package/template-vp-vue-eslint-vapor/src/router/guard/index.ts +7 -0
  252. package/template-vp-vue-eslint-vapor/src/router/guard/permissionGuard.ts +13 -0
  253. package/template-vp-vue-eslint-vapor/src/router/index.ts +18 -0
  254. package/template-vp-vue-eslint-vapor/src/router/interface.ts +9 -0
  255. package/template-vp-vue-eslint-vapor/src/router/modules/index.ts +33 -0
  256. package/template-vp-vue-eslint-vapor/src/store/index.ts +11 -0
  257. package/template-vp-vue-eslint-vapor/src/store/modules/user.ts +17 -0
  258. package/template-vp-vue-eslint-vapor/src/styles/font.scss +0 -0
  259. package/template-vp-vue-eslint-vapor/src/styles/index.scss +29 -0
  260. package/template-vp-vue-eslint-vapor/src/styles/variables.scss +3 -0
  261. package/template-vp-vue-eslint-vapor/src/types/vite-env.d.ts +15 -0
  262. package/template-vp-vue-eslint-vapor/src/utils/env.ts +11 -0
  263. package/template-vp-vue-eslint-vapor/src/utils/request/core/index.ts +425 -0
  264. package/template-vp-vue-eslint-vapor/src/utils/request/core/utils.ts +39 -0
  265. package/template-vp-vue-eslint-vapor/src/utils/request/index.ts +44 -0
  266. package/template-vp-vue-eslint-vapor/src/views/example/echart/config.ts +1794 -0
  267. package/template-vp-vue-eslint-vapor/src/views/example/echart/index.vue +20 -0
  268. package/template-vp-vue-eslint-vapor/src/views/example/tree-chart.vue +16 -0
  269. package/template-vp-vue-eslint-vapor/src/views/home/index.vue +16 -0
  270. package/template-vp-vue-eslint-vapor/src/views/login/index.vue +9 -0
  271. package/template-vp-vue-eslint-vapor/tsconfig.json +32 -0
  272. package/template-vp-vue-eslint-vapor/tsconfig.tsbuildinfo +1 -0
  273. package/template-vp-vue-eslint-vapor/uno.config.ts +17 -0
  274. package/template-vp-vue-eslint-vapor/vite.config.ts +66 -0
  275. package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/decorator.ts +0 -2
  276. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/bypass.ts +0 -12
  277. package/template-vp-monorepo-react-nestjs/apps/server/src/common/interceptors/transform.ts +0 -34
  278. package/template-vp-monorepo-react-nestjs/apps/server/src/common/model/response.ts +0 -23
  279. package/template-vp-monorepo-react-nestjs/apps/server/src/config/auth.config.ts +0 -64
  280. package/template-vp-monorepo-react-nestjs/apps/web-vue/pnpm-workspace.yaml +0 -16
  281. /package/{template-vp-monorepo-react-nestjs/apps/server/src/config/security.config.ts → template-vp-monorepo-react-hono/.agents/auth.config.ts} +0 -0
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ vp dlx commitlint --edit "$1"
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ # vp staged
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["VoidZero.vite-plus-extension-pack"]
3
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "prettier.enable": false,
3
+ "biome.enabled": false,
4
+
5
+ "editor.defaultFormatter": "oxc.oxc-vscode",
6
+ "editor.formatOnSave": true,
7
+
8
+ "editor.codeActionsOnSave": {
9
+ "source.organizeImports": "explicit",
10
+ "source.fixAll.oxc": "explicit"
11
+ },
12
+
13
+ "oxc.typeAware": false,
14
+ "oxc.lint.run": "onType",
15
+
16
+ "files.watcherExclude": {
17
+ "**/node_modules/**": true,
18
+ "**/.pnpm/**": true,
19
+ "**/dist/**": true,
20
+ "**/coverage/**": true,
21
+ "**/.vite/**": true
22
+ }
23
+ }
@@ -0,0 +1,16 @@
1
+ <!--VITE PLUS START-->
2
+
3
+ # Using Vite+, the Unified Toolchain for the Web
4
+
5
+ This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called `vp`. Vite+ is distinct from Vite, and it invokes Vite through `vp dev` and `vp build`. Run `vp help` to print a list of commands and `vp <command> --help` for information about a specific command.
6
+
7
+ Docs are local at `node_modules/vite-plus/docs` or online at https://viteplus.dev/guide/.
8
+
9
+ ## Review Checklist
10
+
11
+ - [ ] Run `vp install` after pulling remote changes and before getting started.
12
+ - [ ] Run `vp check` and `vp test` to format, lint, type check and test changes.
13
+ - [ ] Check if there are `vite.config.ts` tasks or `package.json` scripts necessary for validation, run via `vp run <script>`.
14
+ - [ ] If setup, runtime, or package-manager behavior looks wrong, run `vp env doctor` and include its output when asking for help.
15
+
16
+ <!--VITE PLUS END-->
@@ -0,0 +1,54 @@
1
+ # Vite+ React + Hono Monorepo
2
+
3
+ 这个模板包含 React 前端、Hono API、Drizzle/PostgreSQL、Redis 与独立 BullMQ Worker。
4
+
5
+ ## 项目结构
6
+
7
+ - `apps/web`: React 前端,开发端口 `9999`
8
+ - `apps/server`: Hono API 与 BullMQ Worker,API 开发端口 `10000`
9
+ - `packages/i18n`: 可复用的国际化包
10
+ - `docker-compose.yml`: PostgreSQL、Redis 与 MinIO 本地基础设施
11
+
12
+ ## 首次启动
13
+
14
+ ```powershell
15
+ vp install
16
+ Copy-Item apps/server/.env.example apps/server/.env
17
+ docker compose up -d postgres redis
18
+ vp run --filter server db:migrate
19
+ ```
20
+
21
+ 分别启动应用与队列 Worker:
22
+
23
+ ```powershell
24
+ # 终端 1:React + Hono API
25
+ vp run dev
26
+
27
+ # 终端 2:BullMQ Worker
28
+ vp run dev:worker
29
+ ```
30
+
31
+ 也可以通过 Vite+ 选择后端运行时:
32
+
33
+ ```powershell
34
+ # Node API / Worker
35
+ vp run dev:server:node
36
+ vp run dev:worker:node
37
+
38
+ # Bun API / Worker
39
+ vp run dev:server:bun
40
+ vp run dev:worker:bun
41
+ ```
42
+
43
+ 前端的 `/api/*` 代理会移除 `/api` 前缀,因此:
44
+
45
+ - 浏览器请求 `/api/health/live`,后端路由为 `/health/live`
46
+ - 浏览器请求 `/api/v1/jobs/demo`,后端路由为 `/v1/jobs/demo`
47
+
48
+ 后端也同时挂载 `/api/health/*` 与 `/api/v1/jobs/*`,因此生产环境即使不配置 rewrite 也可直接使用前端的 `/api` 地址。
49
+
50
+ ## 验证
51
+
52
+ ```powershell
53
+ vp run ready
54
+ ```
@@ -0,0 +1,13 @@
1
+ NODE_ENV=development
2
+ APP_NAME=bubbles-server
3
+ HOST=0.0.0.0
4
+ PORT=10000
5
+ CORS_ORIGINS=http://localhost:9999
6
+ DATABASE_URL=postgresql://postgres:ml@localhost:5432/postgres
7
+ DATABASE_POOL_MAX=10
8
+ REDIS_URL=redis://:ml@localhost:6379/0
9
+ REDIS_CONNECT_TIMEOUT_MS=5000
10
+ JOB_QUEUE_NAME=jobs
11
+ JOB_QUEUE_PREFIX=bubbles
12
+ JOB_WORKER_CONCURRENCY=5
13
+ SHUTDOWN_TIMEOUT_MS=10000
@@ -0,0 +1,75 @@
1
+ # Server
2
+
3
+ Hono 后端采用两个独立进程:HTTP API 负责接收请求与写入队列,BullMQ Worker 负责消费任务。数据库、Redis 和队列连接均按需创建,导入 `app.ts` 不会连接外部服务。
4
+
5
+ ## 分层
6
+
7
+ ```text
8
+ src/
9
+ ├─ app.ts # Hono 应用、middleware、路由与错误处理
10
+ ├─ index.ts # HTTP 进程入口
11
+ ├─ worker.ts # BullMQ Worker 进程入口
12
+ ├─ config/ # Zod 环境变量校验
13
+ ├─ common/ # 错误、响应、日志
14
+ ├─ infrastructure/
15
+ │ ├─ database/ # pg Pool、Drizzle 与 schema
16
+ │ ├─ redis/ # 普通 Redis 客户端与连接参数
17
+ │ └─ queue/ # BullMQ 连接工厂
18
+ ├─ modules/
19
+ │ ├─ health/ # live / ready 健康检查
20
+ │ └─ jobs/ # 示例任务的 route/service/repository/worker
21
+ └─ runtime/ # 优雅关闭工具
22
+ ```
23
+
24
+ ## 常用命令
25
+
26
+ ```powershell
27
+ # Node API / Worker(默认)
28
+ vp run --filter server dev:node
29
+ vp run --filter server dev:worker:node
30
+
31
+ # Bun API / Worker
32
+ vp run --filter server dev:bun
33
+ vp run --filter server dev:worker:bun
34
+
35
+ vp run --filter server build
36
+ vp run --filter server test
37
+ vp run --filter server db:generate
38
+ vp run --filter server db:migrate
39
+ vp run --filter server db:studio
40
+ ```
41
+
42
+ 生产构建同样通过 Vite+ 启动:
43
+
44
+ ```powershell
45
+ vp run --filter server start:node
46
+ vp run --filter server start:bun
47
+ vp run --filter server start:worker:node
48
+ vp run --filter server start:worker:bun
49
+ ```
50
+
51
+ Node API 使用 `@hono/node-server`,Bun API 使用原生 `Bun.serve`,二者共用同一个 `app.ts`。Bun 命令使用 `--no-env-file`,统一交给 `dotenv/config` 加载 `.env`,避免两个运行时读取不同的环境文件。
52
+
53
+ ## 接口
54
+
55
+ - `GET /health/live`: 进程存活检查,不访问外部依赖
56
+ - `GET /health/ready`: 检查 PostgreSQL 与 Redis
57
+ - `POST /v1/jobs/demo`: 写入 `job_runs` 并投递 BullMQ 示例任务
58
+ - `GET /v1/jobs/:id`: 查询任务执行状态
59
+ - 上述路由也同时挂载在 `/api/*`,可兼容没有 rewrite 的生产部署
60
+
61
+ 创建示例任务的请求体:
62
+
63
+ ```json
64
+ {
65
+ "payload": {
66
+ "message": "hello"
67
+ }
68
+ }
69
+ ```
70
+
71
+ Redis 必须使用 `noeviction` 策略,HTTP Queue 与阻塞式 Worker 使用不同连接;Worker 连接的 `maxRetriesPerRequest` 固定为 `null`。
72
+
73
+ BullMQ、ioredis 和 `pg` 主要以 Node 为生产目标,因此 Worker 默认推荐使用 Node。Bun Worker 可以用于开发与兼容性验证,但生产启用前应测试任务重试、延迟任务、锁续期、stalled recovery 和优雅关闭。
74
+
75
+ 示例 jobs 模块通过固定 `jobId` 和失败补偿降低重复与悬挂风险,但 PostgreSQL 写入和 Redis 入队仍不是同一个原子事务。对支付、通知等关键任务,应把创建任务改为 transactional outbox,并让独立 dispatcher 将 outbox 可靠投递到 BullMQ;具体业务处理器也必须保持幂等。
@@ -0,0 +1,18 @@
1
+ CREATE TYPE "public"."job_run_status" AS ENUM('queued', 'processing', 'completed', 'failed');--> statement-breakpoint
2
+ CREATE TABLE "job_runs" (
3
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
4
+ "queue_name" varchar(100) NOT NULL,
5
+ "job_name" varchar(100) NOT NULL,
6
+ "status" "job_run_status" DEFAULT 'queued' NOT NULL,
7
+ "payload" jsonb NOT NULL,
8
+ "result" jsonb,
9
+ "attempts" integer DEFAULT 0 NOT NULL,
10
+ "error" text,
11
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
12
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
13
+ "started_at" timestamp with time zone,
14
+ "finished_at" timestamp with time zone
15
+ );
16
+ --> statement-breakpoint
17
+ CREATE INDEX "job_runs_status_created_at_idx" ON "job_runs" USING btree ("status","created_at");--> statement-breakpoint
18
+ CREATE INDEX "job_runs_queue_name_idx" ON "job_runs" USING btree ("queue_name");
@@ -0,0 +1,153 @@
1
+ {
2
+ "id": "07916fda-3931-48b0-93df-ae9a88ba500c",
3
+ "prevId": "00000000-0000-0000-0000-000000000000",
4
+ "version": "7",
5
+ "dialect": "postgresql",
6
+ "tables": {
7
+ "public.job_runs": {
8
+ "name": "job_runs",
9
+ "schema": "",
10
+ "columns": {
11
+ "id": {
12
+ "name": "id",
13
+ "type": "uuid",
14
+ "primaryKey": true,
15
+ "notNull": true,
16
+ "default": "gen_random_uuid()"
17
+ },
18
+ "queue_name": {
19
+ "name": "queue_name",
20
+ "type": "varchar(100)",
21
+ "primaryKey": false,
22
+ "notNull": true
23
+ },
24
+ "job_name": {
25
+ "name": "job_name",
26
+ "type": "varchar(100)",
27
+ "primaryKey": false,
28
+ "notNull": true
29
+ },
30
+ "status": {
31
+ "name": "status",
32
+ "type": "job_run_status",
33
+ "typeSchema": "public",
34
+ "primaryKey": false,
35
+ "notNull": true,
36
+ "default": "'queued'"
37
+ },
38
+ "payload": {
39
+ "name": "payload",
40
+ "type": "jsonb",
41
+ "primaryKey": false,
42
+ "notNull": true
43
+ },
44
+ "result": {
45
+ "name": "result",
46
+ "type": "jsonb",
47
+ "primaryKey": false,
48
+ "notNull": false
49
+ },
50
+ "attempts": {
51
+ "name": "attempts",
52
+ "type": "integer",
53
+ "primaryKey": false,
54
+ "notNull": true,
55
+ "default": 0
56
+ },
57
+ "error": {
58
+ "name": "error",
59
+ "type": "text",
60
+ "primaryKey": false,
61
+ "notNull": false
62
+ },
63
+ "created_at": {
64
+ "name": "created_at",
65
+ "type": "timestamp with time zone",
66
+ "primaryKey": false,
67
+ "notNull": true,
68
+ "default": "now()"
69
+ },
70
+ "updated_at": {
71
+ "name": "updated_at",
72
+ "type": "timestamp with time zone",
73
+ "primaryKey": false,
74
+ "notNull": true,
75
+ "default": "now()"
76
+ },
77
+ "started_at": {
78
+ "name": "started_at",
79
+ "type": "timestamp with time zone",
80
+ "primaryKey": false,
81
+ "notNull": false
82
+ },
83
+ "finished_at": {
84
+ "name": "finished_at",
85
+ "type": "timestamp with time zone",
86
+ "primaryKey": false,
87
+ "notNull": false
88
+ }
89
+ },
90
+ "indexes": {
91
+ "job_runs_status_created_at_idx": {
92
+ "name": "job_runs_status_created_at_idx",
93
+ "columns": [
94
+ {
95
+ "expression": "status",
96
+ "isExpression": false,
97
+ "asc": true,
98
+ "nulls": "last"
99
+ },
100
+ {
101
+ "expression": "created_at",
102
+ "isExpression": false,
103
+ "asc": true,
104
+ "nulls": "last"
105
+ }
106
+ ],
107
+ "isUnique": false,
108
+ "concurrently": false,
109
+ "method": "btree",
110
+ "with": {}
111
+ },
112
+ "job_runs_queue_name_idx": {
113
+ "name": "job_runs_queue_name_idx",
114
+ "columns": [
115
+ {
116
+ "expression": "queue_name",
117
+ "isExpression": false,
118
+ "asc": true,
119
+ "nulls": "last"
120
+ }
121
+ ],
122
+ "isUnique": false,
123
+ "concurrently": false,
124
+ "method": "btree",
125
+ "with": {}
126
+ }
127
+ },
128
+ "foreignKeys": {},
129
+ "compositePrimaryKeys": {},
130
+ "uniqueConstraints": {},
131
+ "policies": {},
132
+ "checkConstraints": {},
133
+ "isRLSEnabled": false
134
+ }
135
+ },
136
+ "enums": {
137
+ "public.job_run_status": {
138
+ "name": "job_run_status",
139
+ "schema": "public",
140
+ "values": ["queued", "processing", "completed", "failed"]
141
+ }
142
+ },
143
+ "schemas": {},
144
+ "sequences": {},
145
+ "roles": {},
146
+ "policies": {},
147
+ "views": {},
148
+ "_meta": {
149
+ "columns": {},
150
+ "schemas": {},
151
+ "tables": {}
152
+ }
153
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": "7",
3
+ "dialect": "postgresql",
4
+ "entries": [
5
+ {
6
+ "idx": 0,
7
+ "version": "7",
8
+ "when": 1786180920930,
9
+ "tag": "0000_flaky_madame_masque",
10
+ "breakpoints": true
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,19 @@
1
+ import 'dotenv/config'
2
+ import { defineConfig } from 'drizzle-kit'
3
+
4
+ const databaseUrl = process.env.DATABASE_URL
5
+
6
+ if (!databaseUrl) {
7
+ throw new Error('DATABASE_URL is required to run Drizzle commands')
8
+ }
9
+
10
+ export default defineConfig({
11
+ schema: './src/infrastructure/database/schema/index.ts',
12
+ out: './drizzle',
13
+ dialect: 'postgresql',
14
+ dbCredentials: {
15
+ url: databaseUrl,
16
+ },
17
+ strict: true,
18
+ verbose: true,
19
+ })
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "server",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx watch src/index.ts",
8
+ "dev:node": "tsx watch src/index.ts",
9
+ "dev:bun": "bun --no-env-file --watch src/index.bun.ts",
10
+ "dev:worker": "tsx watch src/worker.ts",
11
+ "dev:worker:node": "tsx watch src/worker.ts",
12
+ "dev:worker:bun": "bun --no-env-file --watch src/worker.ts",
13
+ "build": "vp pack",
14
+ "start": "node dist/index.mjs",
15
+ "start:node": "node dist/index.mjs",
16
+ "start:bun": "bun --no-env-file dist/index.bun.mjs",
17
+ "start:worker": "node dist/worker.mjs",
18
+ "start:worker:node": "node dist/worker.mjs",
19
+ "start:worker:bun": "bun --no-env-file dist/worker.mjs",
20
+ "test": "vp test run",
21
+ "db:generate": "drizzle-kit generate",
22
+ "db:migrate": "drizzle-kit migrate",
23
+ "db:push": "drizzle-kit push",
24
+ "db:studio": "drizzle-kit studio"
25
+ },
26
+ "dependencies": {
27
+ "@hono/node-server": "catalog:",
28
+ "bullmq": "catalog:",
29
+ "dotenv": "catalog:",
30
+ "drizzle-orm": "catalog:",
31
+ "hono": "catalog:",
32
+ "ioredis": "catalog:",
33
+ "pg": "catalog:",
34
+ "zod": "catalog:"
35
+ },
36
+ "devDependencies": {
37
+ "@types/bun": "catalog:",
38
+ "@types/node": "catalog:",
39
+ "@types/pg": "catalog:",
40
+ "drizzle-kit": "catalog:",
41
+ "tsx": "catalog:",
42
+ "typescript": "catalog:",
43
+ "vite": "catalog:",
44
+ "vite-plus": "catalog:"
45
+ }
46
+ }
@@ -0,0 +1,57 @@
1
+ import { describe, expect, it } from 'vite-plus/test'
2
+ import { createApp } from './app.js'
3
+
4
+ describe('server app', () => {
5
+ const app = createApp()
6
+
7
+ it('returns liveness without connecting to infrastructure', async () => {
8
+ const response = await app.request('/health/live')
9
+ const body = await response.json()
10
+
11
+ expect(response.status).toBe(200)
12
+ expect(body).toMatchObject({
13
+ code: 200,
14
+ data: {
15
+ status: 'ok',
16
+ },
17
+ msg: '操作成功',
18
+ })
19
+ })
20
+
21
+ it('uses the frontend-compatible response envelope', async () => {
22
+ const response = await app.request('/')
23
+ const body = await response.json()
24
+
25
+ expect(response.status).toBe(200)
26
+ expect(body).toMatchObject({
27
+ code: 200,
28
+ data: {
29
+ health: '/health/live',
30
+ },
31
+ msg: '操作成功',
32
+ })
33
+ })
34
+
35
+ it('supports the production /api prefix without a rewrite proxy', async () => {
36
+ const response = await app.request('/api/health/live')
37
+
38
+ expect(response.status).toBe(200)
39
+ await expect(response.json()).resolves.toMatchObject({
40
+ code: 200,
41
+ data: {
42
+ status: 'ok',
43
+ },
44
+ })
45
+ })
46
+
47
+ it('returns a wrapped 404 response', async () => {
48
+ const response = await app.request('/missing')
49
+
50
+ expect(response.status).toBe(404)
51
+ await expect(response.json()).resolves.toEqual({
52
+ code: 404,
53
+ data: null,
54
+ msg: '接口不存在',
55
+ })
56
+ })
57
+ })
@@ -0,0 +1,68 @@
1
+ import { cors } from 'hono/cors'
2
+ import { Hono } from 'hono'
3
+ import { logger } from 'hono/logger'
4
+ import { requestId } from 'hono/request-id'
5
+ import { secureHeaders } from 'hono/secure-headers'
6
+ import { AppError } from './common/errors/app-error.js'
7
+ import { apiFailure, apiSuccess } from './common/http/response.js'
8
+ import { appLogger } from './common/logger.js'
9
+ import { getEnv } from './config/env.js'
10
+ import { healthRoutes } from './modules/health/health.routes.js'
11
+ import { jobsRoutes } from './modules/jobs/jobs.routes.js'
12
+
13
+ export function createApp() {
14
+ const env = getEnv()
15
+ const app = new Hono()
16
+ const allowEveryOrigin = env.CORS_ORIGINS.includes('*')
17
+
18
+ app.use('*', requestId())
19
+ app.use('*', secureHeaders())
20
+ app.use(
21
+ '*',
22
+ cors({
23
+ origin: (origin) => {
24
+ if (allowEveryOrigin) return '*'
25
+ return env.CORS_ORIGINS.includes(origin) ? origin : ''
26
+ },
27
+ credentials: !allowEveryOrigin,
28
+ }),
29
+ )
30
+
31
+ if (env.NODE_ENV !== 'test') {
32
+ app.use('*', logger())
33
+ }
34
+
35
+ app.get('/', (context) =>
36
+ context.json(
37
+ apiSuccess({
38
+ name: env.APP_NAME,
39
+ environment: env.NODE_ENV,
40
+ health: '/health/live',
41
+ apiHealth: '/api/health/live',
42
+ }),
43
+ ),
44
+ )
45
+ app.route('/health', healthRoutes)
46
+ app.route('/api/health', healthRoutes)
47
+ app.route('/v1/jobs', jobsRoutes)
48
+ app.route('/api/v1/jobs', jobsRoutes)
49
+
50
+ app.notFound((context) => context.json(apiFailure(404, '接口不存在'), 404))
51
+ app.onError((error, context) => {
52
+ if (error instanceof AppError) {
53
+ return context.json(apiFailure(error.code, error.message, error.details), error.status)
54
+ }
55
+
56
+ appLogger.error('Unhandled request error', {
57
+ method: context.req.method,
58
+ path: context.req.path,
59
+ error: error instanceof Error ? error.message : String(error),
60
+ stack: error instanceof Error ? error.stack : undefined,
61
+ })
62
+
63
+ const message = env.NODE_ENV === 'production' ? '服务内部错误' : error.message
64
+ return context.json(apiFailure(500, message), 500)
65
+ })
66
+
67
+ return app
68
+ }
@@ -0,0 +1,23 @@
1
+ export type AppErrorStatus = 400 | 401 | 403 | 404 | 409 | 422 | 429 | 500 | 502 | 503
2
+
3
+ interface AppErrorOptions {
4
+ status: AppErrorStatus
5
+ message: string
6
+ code?: number
7
+ details?: unknown
8
+ cause?: unknown
9
+ }
10
+
11
+ export class AppError extends Error {
12
+ readonly status: AppErrorStatus
13
+ readonly code: number
14
+ readonly details?: unknown
15
+
16
+ constructor(options: AppErrorOptions) {
17
+ super(options.message, { cause: options.cause })
18
+ this.name = 'AppError'
19
+ this.status = options.status
20
+ this.code = options.code ?? options.status
21
+ this.details = options.details
22
+ }
23
+ }
@@ -0,0 +1,21 @@
1
+ export interface ApiResponse<T> {
2
+ code: number
3
+ data: T
4
+ msg: string
5
+ }
6
+
7
+ export function apiSuccess<T>(data: T, msg = '操作成功'): ApiResponse<T> {
8
+ return {
9
+ code: 200,
10
+ data,
11
+ msg,
12
+ }
13
+ }
14
+
15
+ export function apiFailure(code: number, msg: string, data: unknown = null): ApiResponse<unknown> {
16
+ return {
17
+ code,
18
+ data,
19
+ msg,
20
+ }
21
+ }
@@ -0,0 +1,30 @@
1
+ type LogContext = Record<string, unknown>
2
+
3
+ function write(level: 'info' | 'warn' | 'error', message: string, context?: LogContext): void {
4
+ const entry = {
5
+ level,
6
+ time: new Date().toISOString(),
7
+ message,
8
+ ...context,
9
+ }
10
+
11
+ const serialized = JSON.stringify(entry)
12
+
13
+ if (level === 'error') {
14
+ console.error(serialized)
15
+ return
16
+ }
17
+
18
+ if (level === 'warn') {
19
+ console.warn(serialized)
20
+ return
21
+ }
22
+
23
+ console.info(serialized)
24
+ }
25
+
26
+ export const appLogger = {
27
+ info: (message: string, context?: LogContext) => write('info', message, context),
28
+ warn: (message: string, context?: LogContext) => write('warn', message, context),
29
+ error: (message: string, context?: LogContext) => write('error', message, context),
30
+ }