create-fullstack-scaffold 0.1.0

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 (530) hide show
  1. package/README.md +154 -0
  2. package/dist/cli/index.d.ts +2 -0
  3. package/dist/cli/index.js +439 -0
  4. package/dist/cli/index.js.map +1 -0
  5. package/package.json +171 -0
  6. package/template/.agents/skills/writing-hookify-rules/SKILL.md +408 -0
  7. package/template/.ai-context.md +368 -0
  8. package/template/.claude/hookify.block-dangerous-commands.local.md +41 -0
  9. package/template/.claude/hookify.check-api-types.local.md +111 -0
  10. package/template/.claude/hookify.check-duplicate-types.local.md +287 -0
  11. package/template/.claude/hookify.check-test-assertions.local.md +93 -0
  12. package/template/.claude/hookify.remind-add-tests.local.md +209 -0
  13. package/template/.claude/hookify.remind-db-migration.local.md +58 -0
  14. package/template/.claude/hookify.remind-run-tests.local.md +52 -0
  15. package/template/.claude/hookify.warn-any-type.local.md +203 -0
  16. package/template/.claude/hookify.warn-console-log.local.md +73 -0
  17. package/template/.claude/rules/00-project-config.md +147 -0
  18. package/template/.claude/rules/01-file-types.md +127 -0
  19. package/template/.claude/rules/02-git-workflow.md +167 -0
  20. package/template/.claude/rules/10-api-type-inference.md +555 -0
  21. package/template/.claude/rules/20-server-api.md +349 -0
  22. package/template/.claude/rules/21-server-entrypoint.md +257 -0
  23. package/template/.claude/rules/30-client-components.md +314 -0
  24. package/template/.claude/rules/31-client-services.md +768 -0
  25. package/template/.claude/rules/32-client-state-zustand.md +324 -0
  26. package/template/.claude/rules/33-client-app-entry.md +276 -0
  27. package/template/.claude/rules/34-client-admin-module.md +445 -0
  28. package/template/.claude/rules/35-cli-module.md +259 -0
  29. package/template/.claude/rules/40-admin-module.md +495 -0
  30. package/template/.claude/rules/40-shared-types.md +450 -0
  31. package/template/.claude/rules/50-websocket.md +245 -0
  32. package/template/.claude/rules/51-sse.md +372 -0
  33. package/template/.claude/rules/52-cloudflare-realtime.md +384 -0
  34. package/template/.claude/rules/60-testing-standards.md +245 -0
  35. package/template/.claude/rules/61-hono-testing.md +200 -0
  36. package/template/.claude/scripts/README.md +187 -0
  37. package/template/.claude/scripts/check-duplicate-types.ts +188 -0
  38. package/template/.claude/scripts/post-edit-check-incremental.sh +61 -0
  39. package/template/.claude/scripts/post-edit-check.sh +22 -0
  40. package/template/.claude/scripts/pre-tool-use-check.sh +86 -0
  41. package/template/.claude/scripts/test-pre-tool-use.sh +73 -0
  42. package/template/.claude/scripts/validate-git-changes.sh +38 -0
  43. package/template/.claude/settings.json +32 -0
  44. package/template/.claude/skills/writing-hookify-rules/SKILL.md +408 -0
  45. package/template/.dev-context-compact.md +54 -0
  46. package/template/.dev-context.md +621 -0
  47. package/template/.dev-guide.md +243 -0
  48. package/template/.env.example +60 -0
  49. package/template/.eslintrc.routes.json +39 -0
  50. package/template/.husky/_/husky.sh +27 -0
  51. package/template/.husky/commit-msg +4 -0
  52. package/template/.husky/post-commit +4 -0
  53. package/template/.husky/pre-commit +19 -0
  54. package/template/.husky/pre-push +12 -0
  55. package/template/.prettierignore +22 -0
  56. package/template/.prettierrc +8 -0
  57. package/template/.sessions/3/2026-03-26T05-41-09-154Z_03bb597f-3898-4a2e-8c08-5746bbe8d95e.jsonl +18 -0
  58. package/template/.sessions/3/2026-03-26T05-48-30-052Z_12de4774-9cb3-494c-9852-bd1e6b0003c3.jsonl +6 -0
  59. package/template/.vscode/extensions.json +8 -0
  60. package/template/.vscode/settings.json +4 -0
  61. package/template/.workspaces/3/hello.py +1 -0
  62. package/template/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/803c2e37182b913f8857edf6d8776515cef4af6d48fcb25913e457f4b14ffa97.sqlite +0 -0
  63. package/template/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/803c2e37182b913f8857edf6d8776515cef4af6d48fcb25913e457f4b14ffa97.sqlite-shm +0 -0
  64. package/template/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/803c2e37182b913f8857edf6d8776515cef4af6d48fcb25913e457f4b14ffa97.sqlite-wal +0 -0
  65. package/template/CLAUDE.md +296 -0
  66. package/template/DESIGN.md +260 -0
  67. package/template/DEV_CONTEXT_GUIDE.md +366 -0
  68. package/template/DEV_TOOLS_README.md +396 -0
  69. package/template/FRAMEWORK_HISTORY.md +34 -0
  70. package/template/PROJECT_SUMMARY.md +325 -0
  71. package/template/QUICKSTART.md +305 -0
  72. package/template/README.md +154 -0
  73. package/template/STRUCTURE.txt +81 -0
  74. package/template/admin.html +13 -0
  75. package/template/auth-inject.html +33 -0
  76. package/template/commitlint.config.js +12 -0
  77. package/template/docs/PERMISSION_ARCHITECTURE.md +279 -0
  78. package/template/docs/PERMISSION_EXAMPLES.md +230 -0
  79. package/template/docs/PERMISSION_SYSTEM.md +301 -0
  80. package/template/docs/SMART_TEST.md +171 -0
  81. package/template/docs/runtime-abstract.md +253 -0
  82. package/template/drizzle/0000_rainy_boomer.sql +101 -0
  83. package/template/drizzle/0001_add_todo_attachments.sql +12 -0
  84. package/template/drizzle/0002_chilly_magneto.sql +89 -0
  85. package/template/drizzle/meta/0000_snapshot.json +652 -0
  86. package/template/drizzle/meta/0001_snapshot.json +735 -0
  87. package/template/drizzle/meta/0002_snapshot.json +1198 -0
  88. package/template/drizzle/meta/_journal.json +27 -0
  89. package/template/drizzle.config.ts +13 -0
  90. package/template/eslint-rules/README-no-middleware-in-routes.md +154 -0
  91. package/template/eslint-rules/__tests__/enforce-valid-method.test.ts +251 -0
  92. package/template/eslint-rules/__tests__/layer-boundary.test.ts +102 -0
  93. package/template/eslint-rules/__tests__/module-boundary.test.ts +77 -0
  94. package/template/eslint-rules/__tests__/no-direct-zod-import-in-file-routes.test.ts +45 -0
  95. package/template/eslint-rules/__tests__/no-new-old-service-naming.test.ts +76 -0
  96. package/template/eslint-rules/e2e-test-location.js +153 -0
  97. package/template/eslint-rules/enforce-valid-method.js +217 -0
  98. package/template/eslint-rules/flat-routes-services.js +69 -0
  99. package/template/eslint-rules/framework-protect.js +186 -0
  100. package/template/eslint-rules/layer-boundary.js +164 -0
  101. package/template/eslint-rules/limit-type-complexity.js +130 -0
  102. package/template/eslint-rules/middleware-location.js +162 -0
  103. package/template/eslint-rules/module-boundary.js +125 -0
  104. package/template/eslint-rules/no-ambiguous-file-paths.js +64 -0
  105. package/template/eslint-rules/no-any-on-apiclient.js +173 -0
  106. package/template/eslint-rules/no-boolean-success.js +43 -0
  107. package/template/eslint-rules/no-deep-relative-imports.js +69 -0
  108. package/template/eslint-rules/no-direct-fetch.js +122 -0
  109. package/template/eslint-rules/no-direct-ws-sse.js +57 -0
  110. package/template/eslint-rules/no-direct-zod-import-in-file-routes.js +54 -0
  111. package/template/eslint-rules/no-disable-direct-fetch.js +57 -0
  112. package/template/eslint-rules/no-disable-type-safe-client.js +58 -0
  113. package/template/eslint-rules/no-inline-schema.js +220 -0
  114. package/template/eslint-rules/no-middleware-in-routes.js +81 -0
  115. package/template/eslint-rules/no-new-old-service-naming.js +123 -0
  116. package/template/eslint-rules/no-type-assertion-in-rpc.js +99 -0
  117. package/template/eslint-rules/no-type-assertion-on-shared-types.js +109 -0
  118. package/template/eslint-rules/no-util-functions-in-service.js +128 -0
  119. package/template/eslint-rules/prefer-shared-types.js +352 -0
  120. package/template/eslint-rules/protect-ws-sse-interface.js +66 -0
  121. package/template/eslint-rules/require-antd-generic-types.js +73 -0
  122. package/template/eslint-rules/require-file-openapi-props.js +114 -0
  123. package/template/eslint-rules/require-hono-chain-syntax.js +129 -0
  124. package/template/eslint-rules/require-nullable-for-optional.js +99 -0
  125. package/template/eslint-rules/require-response-helpers.js +140 -0
  126. package/template/eslint-rules/require-type-safe-test-client.js +106 -0
  127. package/template/eslint-rules/route-location.js +72 -0
  128. package/template/eslint.config.js +231 -0
  129. package/template/index.html +17 -0
  130. package/template/lint-scripts/DIRECTORY_RULES.md +335 -0
  131. package/template/lint-scripts/README.md +299 -0
  132. package/template/lint-scripts/TESTING.md +273 -0
  133. package/template/lint-scripts/ai-context-generator.ts +159 -0
  134. package/template/lint-scripts/check-framework-modify.sh +8 -0
  135. package/template/lint-scripts/check-menu-permissions.js +242 -0
  136. package/template/lint-scripts/check-refs.ts +165 -0
  137. package/template/lint-scripts/check-route-auth-complete.js +260 -0
  138. package/template/lint-scripts/check-route-auth.js +212 -0
  139. package/template/lint-scripts/check-route-permissions.js +210 -0
  140. package/template/lint-scripts/config/project.config.ts +358 -0
  141. package/template/lint-scripts/dev-context-analyzer.ts +707 -0
  142. package/template/lint-scripts/dev-guide-generator.ts +830 -0
  143. package/template/lint-scripts/dev-server.ts +58 -0
  144. package/template/lint-scripts/eslint-route-auth.js +158 -0
  145. package/template/lint-scripts/eslint-routes-permission.js +147 -0
  146. package/template/lint-scripts/fix-route-auth.js +245 -0
  147. package/template/lint-scripts/framework/check-modify.ts +152 -0
  148. package/template/lint-scripts/framework/hash-utils.ts +180 -0
  149. package/template/lint-scripts/framework/init-baseline.ts +84 -0
  150. package/template/lint-scripts/framework/update-baseline.ts +148 -0
  151. package/template/lint-scripts/post-commit-track.ts +66 -0
  152. package/template/lint-scripts/quick-test.sh +27 -0
  153. package/template/lint-scripts/smart-test.ts +268 -0
  154. package/template/lint-scripts/test-history.ts +360 -0
  155. package/template/lint-scripts/test-tracker.ts +350 -0
  156. package/template/lint-scripts/validate-all.ts +250 -0
  157. package/template/lint-scripts/validators/api-coverage.validator.ts +355 -0
  158. package/template/lint-scripts/validators/client-rpc.validator.ts +190 -0
  159. package/template/lint-scripts/validators/client-tests.validator.ts +155 -0
  160. package/template/lint-scripts/validators/console-log.validator.ts +122 -0
  161. package/template/lint-scripts/validators/directory-structure.validator.ts +181 -0
  162. package/template/lint-scripts/validators/imports.validator.ts +180 -0
  163. package/template/lint-scripts/validators/index.ts +271 -0
  164. package/template/lint-scripts/validators/md-refs.validator.ts +165 -0
  165. package/template/lint-scripts/validators/module-tests.validator.ts +112 -0
  166. package/template/lint-scripts/validators/sensitive.validator.ts +185 -0
  167. package/template/lint-scripts/validators/server-rpc.validator.ts +141 -0
  168. package/template/lint-scripts/validators/test-quality.validator.ts +257 -0
  169. package/template/lint-scripts/validators/todos.validator.ts +126 -0
  170. package/template/lint-scripts/watch-validator.ts +131 -0
  171. package/template/modules.config.ts +71 -0
  172. package/template/package-lock.json +14554 -0
  173. package/template/package.json +158 -0
  174. package/template/patches/@hono+zod-openapi+1.2.2.patch +67 -0
  175. package/template/patches/@hono+zod-validator+0.7.6.patch +13 -0
  176. package/template/patches/hono+4.12.16.patch +246 -0
  177. package/template/patches/typescript+5.8.3.patch +26 -0
  178. package/template/playwright.config.ts +60 -0
  179. package/template/pnpm-lock.yaml +7137 -0
  180. package/template/postcss.config.js +6 -0
  181. package/template/scripts/create-template.ts +1724 -0
  182. package/template/src/admin/App.tsx +59 -0
  183. package/template/src/admin/components/AccountSwitcher.tsx +104 -0
  184. package/template/src/admin/components/CaptchaModal.tsx +150 -0
  185. package/template/src/admin/components/NotificationDrawer.tsx +213 -0
  186. package/template/src/admin/components/PageHeader.tsx +45 -0
  187. package/template/src/admin/components/PermissionConfigEditor.tsx +237 -0
  188. package/template/src/admin/components/PermissionGuard.tsx +108 -0
  189. package/template/src/admin/components/PermissionTree.tsx +193 -0
  190. package/template/src/admin/components/ProtectedRoute.tsx +33 -0
  191. package/template/src/admin/components/StatsCard.tsx +44 -0
  192. package/template/src/admin/components/UserFormModal.tsx +67 -0
  193. package/template/src/admin/components/UserTable.tsx +72 -0
  194. package/template/src/admin/components/__tests__/PageHeader.test.tsx +48 -0
  195. package/template/src/admin/components/__tests__/PermissionConfigEditor.test.tsx +147 -0
  196. package/template/src/admin/components/__tests__/PermissionGuard.test.tsx +221 -0
  197. package/template/src/admin/components/__tests__/PermissionTree.test.tsx +187 -0
  198. package/template/src/admin/components/__tests__/ProtectedRoute.test.tsx +129 -0
  199. package/template/src/admin/components/__tests__/StatsCard.test.tsx +44 -0
  200. package/template/src/admin/components/__tests__/UserFormModal.test.tsx +125 -0
  201. package/template/src/admin/components/__tests__/UserTable.test.tsx +89 -0
  202. package/template/src/admin/components/index.ts +7 -0
  203. package/template/src/admin/hooks/__tests__/useAuditLogs.test.ts +109 -0
  204. package/template/src/admin/hooks/__tests__/usePermissions.test.tsx +327 -0
  205. package/template/src/admin/hooks/__tests__/usePermissionsBranches.test.ts +198 -0
  206. package/template/src/admin/hooks/__tests__/useRoles.test.ts +261 -0
  207. package/template/src/admin/hooks/useAdminNotifications.ts +156 -0
  208. package/template/src/admin/hooks/useAuditLogs.ts +44 -0
  209. package/template/src/admin/hooks/useConfig.ts +168 -0
  210. package/template/src/admin/hooks/usePermissions.ts +156 -0
  211. package/template/src/admin/hooks/useRoles.ts +120 -0
  212. package/template/src/admin/layouts/Header.tsx +93 -0
  213. package/template/src/admin/layouts/Layout.tsx +23 -0
  214. package/template/src/admin/layouts/Sidebar.tsx +120 -0
  215. package/template/src/admin/main.tsx +18 -0
  216. package/template/src/admin/pages/ContentPage.tsx +252 -0
  217. package/template/src/admin/pages/DashboardPage.tsx +141 -0
  218. package/template/src/admin/pages/DisputesPage.tsx +261 -0
  219. package/template/src/admin/pages/LoginPage.tsx +121 -0
  220. package/template/src/admin/pages/MediaTestPage.tsx +524 -0
  221. package/template/src/admin/pages/OrdersPage.tsx +302 -0
  222. package/template/src/admin/pages/PermissionsPage.tsx +95 -0
  223. package/template/src/admin/pages/RegisterPage.tsx +103 -0
  224. package/template/src/admin/pages/RolesPage.tsx +330 -0
  225. package/template/src/admin/pages/SettingsPage.tsx +73 -0
  226. package/template/src/admin/pages/SystemLogsPage.tsx +218 -0
  227. package/template/src/admin/pages/TestCaptchaPage.tsx +120 -0
  228. package/template/src/admin/pages/TicketsPage.tsx +292 -0
  229. package/template/src/admin/pages/UsersPage.tsx +282 -0
  230. package/template/src/admin/pages/__tests__/ContentPage.test.tsx +213 -0
  231. package/template/src/admin/pages/__tests__/DashboardPage.test.tsx +153 -0
  232. package/template/src/admin/pages/__tests__/DisputesPage.test.tsx +196 -0
  233. package/template/src/admin/pages/__tests__/LoginPage.test.tsx +112 -0
  234. package/template/src/admin/pages/__tests__/OrdersPage.test.tsx +217 -0
  235. package/template/src/admin/pages/__tests__/PermissionsPage.test.tsx +119 -0
  236. package/template/src/admin/pages/__tests__/RegisterPage.test.tsx +179 -0
  237. package/template/src/admin/pages/__tests__/RolesPage.test.tsx +256 -0
  238. package/template/src/admin/pages/__tests__/SettingsPage.test.tsx +66 -0
  239. package/template/src/admin/pages/__tests__/SystemLogsPage.test.tsx +125 -0
  240. package/template/src/admin/pages/__tests__/TicketsPage.test.tsx +202 -0
  241. package/template/src/admin/pages/__tests__/UsersPage.test.tsx +229 -0
  242. package/template/src/admin/services/README.md +263 -0
  243. package/template/src/admin/services/TESTING.md +323 -0
  244. package/template/src/admin/services/__tests__/skipLoading.test.ts +146 -0
  245. package/template/src/admin/services/apiClient.ts +66 -0
  246. package/template/src/admin/services/requestInterceptor.ts +127 -0
  247. package/template/src/admin/services/types.ts +5 -0
  248. package/template/src/admin/stores/__tests__/adminStore.test.ts +184 -0
  249. package/template/src/admin/stores/__tests__/adminStoreBranches.test.ts +148 -0
  250. package/template/src/admin/stores/__tests__/captchaStore.test.ts +75 -0
  251. package/template/src/admin/stores/__tests__/captchaStoreBranches.test.ts +37 -0
  252. package/template/src/admin/stores/__tests__/loadingStore.test.ts +68 -0
  253. package/template/src/admin/stores/adminStore.ts +88 -0
  254. package/template/src/admin/stores/captchaStore.ts +47 -0
  255. package/template/src/admin/stores/loadingStore.ts +27 -0
  256. package/template/src/cli/index.ts +22 -0
  257. package/template/src/cli/modules/config/index.ts +132 -0
  258. package/template/src/cli/modules/index.ts +12 -0
  259. package/template/src/cli/modules/notification/index.ts +86 -0
  260. package/template/src/cli/modules/todo/index.ts +60 -0
  261. package/template/src/cli/rpc/client.ts +23 -0
  262. package/template/src/cli/rpc/index.ts +1 -0
  263. package/template/src/cli/utils/api.ts +17 -0
  264. package/template/src/cli/utils/auto-command.ts +229 -0
  265. package/template/src/cli/utils/index.ts +8 -0
  266. package/template/src/cli/utils/logger.ts +79 -0
  267. package/template/src/client/App.tsx +24 -0
  268. package/template/src/client/Layout.tsx +27 -0
  269. package/template/src/client/components/AuthButton.tsx +41 -0
  270. package/template/src/client/components/ConnectionStatus.tsx +75 -0
  271. package/template/src/client/components/EmptyState.tsx +26 -0
  272. package/template/src/client/components/Footer.tsx +17 -0
  273. package/template/src/client/components/LoadingSpinner.tsx +26 -0
  274. package/template/src/client/components/MessageCard.tsx +61 -0
  275. package/template/src/client/components/Navigation.tsx +65 -0
  276. package/template/src/client/components/StatusBadge.tsx +50 -0
  277. package/template/src/client/components/__tests__/App.test.tsx +79 -0
  278. package/template/src/client/components/__tests__/AuthButton.test.tsx +119 -0
  279. package/template/src/client/components/__tests__/ConnectionStatus.test.tsx +188 -0
  280. package/template/src/client/components/__tests__/EmptyState.test.tsx +70 -0
  281. package/template/src/client/components/__tests__/Footer.test.tsx +22 -0
  282. package/template/src/client/components/__tests__/LoadingSpinner.test.tsx +75 -0
  283. package/template/src/client/components/__tests__/MessageCard.test.tsx +142 -0
  284. package/template/src/client/components/__tests__/Navigation.test.tsx +40 -0
  285. package/template/src/client/components/__tests__/StatusBadge.test.tsx +107 -0
  286. package/template/src/client/components/index.ts +6 -0
  287. package/template/src/client/index.css +27 -0
  288. package/template/src/client/main.tsx +25 -0
  289. package/template/src/client/pages/ContentDetailPage.tsx +142 -0
  290. package/template/src/client/pages/ContentListPage.tsx +169 -0
  291. package/template/src/client/pages/NotificationPage.tsx +288 -0
  292. package/template/src/client/pages/TodoPage.tsx +389 -0
  293. package/template/src/client/pages/WebSocketPage.tsx +239 -0
  294. package/template/src/client/pages/__tests__/ContentDetailPage.test.tsx +176 -0
  295. package/template/src/client/pages/__tests__/ContentListPage.test.tsx +202 -0
  296. package/template/src/client/pages/__tests__/NotificationPage.test.tsx +246 -0
  297. package/template/src/client/pages/__tests__/TodoPage.test.tsx +433 -0
  298. package/template/src/client/pages/__tests__/WebSocketPage.test.tsx +378 -0
  299. package/template/src/client/services/apiClient.ts +66 -0
  300. package/template/src/client/stores/__tests__/authStore.test.ts +139 -0
  301. package/template/src/client/stores/__tests__/chatWSStore.test.ts +416 -0
  302. package/template/src/client/stores/__tests__/notificationStore.test.ts +453 -0
  303. package/template/src/client/stores/__tests__/todoStore.test.ts +509 -0
  304. package/template/src/client/stores/authStore.ts +51 -0
  305. package/template/src/client/stores/chatWSStore.ts +122 -0
  306. package/template/src/client/stores/notificationStore.ts +199 -0
  307. package/template/src/client/stores/todoStore.ts +207 -0
  308. package/template/src/server/__tests__/integration/todos-api.test.ts +138 -0
  309. package/template/src/server/app.ts +105 -0
  310. package/template/src/server/config.ts +86 -0
  311. package/template/src/server/core/__tests__/realtime-core.test.ts +329 -0
  312. package/template/src/server/core/__tests__/realtime-scanner.test.ts +210 -0
  313. package/template/src/server/core/__tests__/runtime-node.test.ts +330 -0
  314. package/template/src/server/core/__tests__/runtime.test.ts +219 -0
  315. package/template/src/server/core/__tests__/typed-runtime.test.ts +178 -0
  316. package/template/src/server/core/durable-objects/RealtimeDO.ts +206 -0
  317. package/template/src/server/core/index.ts +83 -0
  318. package/template/src/server/core/module-loader.ts +281 -0
  319. package/template/src/server/core/realtime-core.ts +152 -0
  320. package/template/src/server/core/realtime-scanner.ts +99 -0
  321. package/template/src/server/core/runtime-cloudflare.ts +207 -0
  322. package/template/src/server/core/runtime-node.ts +170 -0
  323. package/template/src/server/core/runtime.ts +129 -0
  324. package/template/src/server/core/typed-runtime.ts +80 -0
  325. package/template/src/server/db/__tests__/driver.test.ts +203 -0
  326. package/template/src/server/db/config.ts +1 -0
  327. package/template/src/server/db/driver-cloudflare.ts +50 -0
  328. package/template/src/server/db/driver.ts +116 -0
  329. package/template/src/server/db/index.ts +3 -0
  330. package/template/src/server/db/init.ts +412 -0
  331. package/template/src/server/db/schema/api-endpoints.ts +23 -0
  332. package/template/src/server/db/schema/contents.ts +31 -0
  333. package/template/src/server/db/schema/disputes.ts +39 -0
  334. package/template/src/server/db/schema/index.ts +14 -0
  335. package/template/src/server/db/schema/notifications.ts +16 -0
  336. package/template/src/server/db/schema/orders.ts +30 -0
  337. package/template/src/server/db/schema/permission-audit-logs.ts +17 -0
  338. package/template/src/server/db/schema/permission-route-mappings.ts +22 -0
  339. package/template/src/server/db/schema/permissions.ts +17 -0
  340. package/template/src/server/db/schema/role-permissions.ts +22 -0
  341. package/template/src/server/db/schema/roles.ts +17 -0
  342. package/template/src/server/db/schema/tickets.ts +62 -0
  343. package/template/src/server/db/schema/todo-attachments.ts +22 -0
  344. package/template/src/server/db/schema/todos.ts +21 -0
  345. package/template/src/server/db/schema/user-roles.ts +17 -0
  346. package/template/src/server/db/seeds/index.ts +1 -0
  347. package/template/src/server/db/seeds/permission-data.ts +354 -0
  348. package/template/src/server/db/test-setup.ts +647 -0
  349. package/template/src/server/entries/cloudflare.ts +71 -0
  350. package/template/src/server/entries/node.ts +190 -0
  351. package/template/src/server/index.ts +62 -0
  352. package/template/src/server/middleware/__tests__/auth-simple.test.ts +147 -0
  353. package/template/src/server/middleware/__tests__/auth.test.ts +276 -0
  354. package/template/src/server/middleware/__tests__/captcha.test.ts +258 -0
  355. package/template/src/server/middleware/__tests__/error-handler.test.ts +364 -0
  356. package/template/src/server/middleware/__tests__/error-response-format.test.ts +80 -0
  357. package/template/src/server/middleware/__tests__/permission.test.ts +312 -0
  358. package/template/src/server/middleware/audit-log.ts +101 -0
  359. package/template/src/server/middleware/auth.ts +235 -0
  360. package/template/src/server/middleware/captcha.ts +166 -0
  361. package/template/src/server/middleware/cors.ts +30 -0
  362. package/template/src/server/middleware/error-handler.ts +135 -0
  363. package/template/src/server/middleware/index.ts +24 -0
  364. package/template/src/server/middleware/logger.ts +73 -0
  365. package/template/src/server/middleware/permission.ts +127 -0
  366. package/template/src/server/middleware/rate-limit.ts +69 -0
  367. package/template/src/server/middleware/realtime-env.ts +12 -0
  368. package/template/src/server/module-admin/__tests__/admin-routes.test.ts +360 -0
  369. package/template/src/server/module-admin/__tests__/admin-service.test.ts +222 -0
  370. package/template/src/server/module-admin/__tests__/audit-log-routes.test.ts +261 -0
  371. package/template/src/server/module-admin/__tests__/export-routes.test.ts +160 -0
  372. package/template/src/server/module-admin/__tests__/media-routes.test.ts +122 -0
  373. package/template/src/server/module-admin/module.ts +40 -0
  374. package/template/src/server/module-admin/routes/admin-notification-routes.ts +197 -0
  375. package/template/src/server/module-admin/routes/admin-routes.ts +20 -0
  376. package/template/src/server/module-admin/routes/auth-routes.ts +86 -0
  377. package/template/src/server/module-admin/routes/export-routes.ts +207 -0
  378. package/template/src/server/module-admin/routes/media-routes.ts +78 -0
  379. package/template/src/server/module-admin/routes/system-routes.ts +89 -0
  380. package/template/src/server/module-admin/routes/user-management-routes.ts +143 -0
  381. package/template/src/server/module-admin/services/admin-service.ts +268 -0
  382. package/template/src/server/module-captcha/__tests__/captcha-route.test.ts +35 -0
  383. package/template/src/server/module-captcha/__tests__/captcha-service.test.ts +53 -0
  384. package/template/src/server/module-captcha/module.ts +35 -0
  385. package/template/src/server/module-captcha/routes/captcha-routes.ts +68 -0
  386. package/template/src/server/module-captcha/services/captcha-service.ts +3 -0
  387. package/template/src/server/module-chat/__tests__/chat-routes.test.ts +39 -0
  388. package/template/src/server/module-chat/__tests__/chat-rpc.test.ts +185 -0
  389. package/template/src/server/module-chat/__tests__/chat-service.test.ts +64 -0
  390. package/template/src/server/module-chat/module.ts +27 -0
  391. package/template/src/server/module-chat/routes/chat-routes.ts +46 -0
  392. package/template/src/server/module-chat/services/chat-service.ts +38 -0
  393. package/template/src/server/module-content/__tests__/content-route.test.ts +40 -0
  394. package/template/src/server/module-content/__tests__/content-service.test.ts +107 -0
  395. package/template/src/server/module-content/module.ts +39 -0
  396. package/template/src/server/module-content/routes/content-routes.ts +182 -0
  397. package/template/src/server/module-content/routes/public-content-routes.ts +58 -0
  398. package/template/src/server/module-content/services/content-service.ts +224 -0
  399. package/template/src/server/module-dispute/__tests__/dispute-route.test.ts +43 -0
  400. package/template/src/server/module-dispute/__tests__/dispute-service.test.ts +135 -0
  401. package/template/src/server/module-dispute/module.ts +30 -0
  402. package/template/src/server/module-dispute/routes/dispute-routes.ts +153 -0
  403. package/template/src/server/module-dispute/services/dispute-service.ts +255 -0
  404. package/template/src/server/module-file/__tests__/file-routes.test.ts +284 -0
  405. package/template/src/server/module-file/__tests__/file-storage-service.test.ts +323 -0
  406. package/template/src/server/module-file/module.ts +28 -0
  407. package/template/src/server/module-file/routes/file-routes.ts +288 -0
  408. package/template/src/server/module-notifications/__tests__/notification-route-rpc.test.ts +375 -0
  409. package/template/src/server/module-notifications/__tests__/notification-service.test.ts +241 -0
  410. package/template/src/server/module-notifications/__tests__/sse-rpc.test.ts +289 -0
  411. package/template/src/server/module-notifications/module.ts +32 -0
  412. package/template/src/server/module-notifications/routes/notification-routes.ts +190 -0
  413. package/template/src/server/module-notifications/services/notification-service.ts +104 -0
  414. package/template/src/server/module-order/__tests__/order-route.test.ts +258 -0
  415. package/template/src/server/module-order/__tests__/order-service.test.ts +222 -0
  416. package/template/src/server/module-order/module.ts +30 -0
  417. package/template/src/server/module-order/routes/order-routes.ts +202 -0
  418. package/template/src/server/module-order/services/order-service.ts +268 -0
  419. package/template/src/server/module-permission/__tests__/permission-middleware.test.ts +90 -0
  420. package/template/src/server/module-permission/__tests__/permission-routes.test.ts +330 -0
  421. package/template/src/server/module-permission/__tests__/permission-service-impl.test.ts +388 -0
  422. package/template/src/server/module-permission/__tests__/permission-service.test.ts +190 -0
  423. package/template/src/server/module-permission/__tests__/role-routes.test.ts +215 -0
  424. package/template/src/server/module-permission/module.ts +68 -0
  425. package/template/src/server/module-permission/routes/audit-log-routes.ts +76 -0
  426. package/template/src/server/module-permission/routes/permission-routes.ts +184 -0
  427. package/template/src/server/module-permission/routes/role-routes.ts +263 -0
  428. package/template/src/server/module-permission/services/audit-log-service.ts +108 -0
  429. package/template/src/server/module-permission/services/permission-service-impl.ts +233 -0
  430. package/template/src/server/module-permission/services/permission-service.ts +256 -0
  431. package/template/src/server/module-permission/services/role-service.ts +122 -0
  432. package/template/src/server/module-ticket/__tests__/ticket-route.test.ts +173 -0
  433. package/template/src/server/module-ticket/__tests__/ticket-service.test.ts +201 -0
  434. package/template/src/server/module-ticket/module.ts +30 -0
  435. package/template/src/server/module-ticket/routes/ticket-routes.ts +210 -0
  436. package/template/src/server/module-ticket/services/ticket-service.ts +297 -0
  437. package/template/src/server/module-todos/__tests__/todo-service.test.ts +196 -0
  438. package/template/src/server/module-todos/__tests__/todos-file-upload.test.ts +439 -0
  439. package/template/src/server/module-todos/__tests__/todos-route-rpc.test.ts +575 -0
  440. package/template/src/server/module-todos/module.ts +30 -0
  441. package/template/src/server/module-todos/routes/todos-routes.ts +260 -0
  442. package/template/src/server/module-todos/services/todo-service.ts +202 -0
  443. package/template/src/server/route-registry.ts +47 -0
  444. package/template/src/server/test-utils/test-client.ts +66 -0
  445. package/template/src/server/test-utils/test-server.ts +131 -0
  446. package/template/src/server/types/bindings.ts +10 -0
  447. package/template/src/server/utils/__tests__/app-error.test.ts +374 -0
  448. package/template/src/server/utils/__tests__/auth.test.ts +76 -0
  449. package/template/src/server/utils/__tests__/captcha.test.ts +80 -0
  450. package/template/src/server/utils/__tests__/file-storage.test.ts +472 -0
  451. package/template/src/server/utils/__tests__/logger.test.ts +221 -0
  452. package/template/src/server/utils/__tests__/route-helpers.test.ts +264 -0
  453. package/template/src/server/utils/app-error.ts +355 -0
  454. package/template/src/server/utils/auth.ts +65 -0
  455. package/template/src/server/utils/captcha.ts +119 -0
  456. package/template/src/server/utils/date.ts +50 -0
  457. package/template/src/server/utils/env.ts +4 -0
  458. package/template/src/server/utils/file-storage.ts +462 -0
  459. package/template/src/server/utils/generate.ts +26 -0
  460. package/template/src/server/utils/id-helpers.ts +5 -0
  461. package/template/src/server/utils/logger.ts +139 -0
  462. package/template/src/server/utils/permission-utils.ts +6 -0
  463. package/template/src/server/utils/response.ts +40 -0
  464. package/template/src/server/utils/route-helpers.ts +200 -0
  465. package/template/src/server/utils/uuid.ts +8 -0
  466. package/template/src/server/utils/ws-helper.ts +30 -0
  467. package/template/src/shared/constants/index.ts +1 -0
  468. package/template/src/shared/constants/resource-types.ts +72 -0
  469. package/template/src/shared/core/__tests__/sse-client.test.ts +376 -0
  470. package/template/src/shared/core/__tests__/ws-client.test.ts +468 -0
  471. package/template/src/shared/core/api-request.ts +192 -0
  472. package/template/src/shared/core/api-schemas.ts +41 -0
  473. package/template/src/shared/core/index.ts +37 -0
  474. package/template/src/shared/core/module-manifest.ts +120 -0
  475. package/template/src/shared/core/protocol-types.ts +26 -0
  476. package/template/src/shared/core/sse-client.ts +185 -0
  477. package/template/src/shared/core/ws-client.ts +236 -0
  478. package/template/src/shared/hooks/index.ts +2 -0
  479. package/template/src/shared/hooks/useSSE.ts +57 -0
  480. package/template/src/shared/hooks/useWebSocket.ts +66 -0
  481. package/template/src/shared/index.ts +5 -0
  482. package/template/src/shared/modules/admin/index.ts +1 -0
  483. package/template/src/shared/modules/admin/schemas.ts +100 -0
  484. package/template/src/shared/modules/audit/index.ts +1 -0
  485. package/template/src/shared/modules/audit/schemas.ts +24 -0
  486. package/template/src/shared/modules/captcha/index.ts +1 -0
  487. package/template/src/shared/modules/captcha/schemas.ts +19 -0
  488. package/template/src/shared/modules/chat/index.ts +38 -0
  489. package/template/src/shared/modules/content/index.ts +1 -0
  490. package/template/src/shared/modules/content/schemas.ts +53 -0
  491. package/template/src/shared/modules/dispute/index.ts +1 -0
  492. package/template/src/shared/modules/dispute/schemas.ts +62 -0
  493. package/template/src/shared/modules/files/index.ts +11 -0
  494. package/template/src/shared/modules/files/schemas.ts +44 -0
  495. package/template/src/shared/modules/index.ts +70 -0
  496. package/template/src/shared/modules/notifications/index.ts +26 -0
  497. package/template/src/shared/modules/notifications/schemas.ts +73 -0
  498. package/template/src/shared/modules/order/index.ts +1 -0
  499. package/template/src/shared/modules/order/schemas.ts +63 -0
  500. package/template/src/shared/modules/permission/index.ts +42 -0
  501. package/template/src/shared/modules/permission/permission-dependencies.ts +50 -0
  502. package/template/src/shared/modules/permission/permissions.ts +275 -0
  503. package/template/src/shared/modules/permission/schemas.ts +92 -0
  504. package/template/src/shared/modules/permission/types.ts +23 -0
  505. package/template/src/shared/modules/role/index.ts +1 -0
  506. package/template/src/shared/modules/role/schemas.ts +46 -0
  507. package/template/src/shared/modules/ticket/index.ts +1 -0
  508. package/template/src/shared/modules/ticket/schemas.ts +77 -0
  509. package/template/src/shared/modules/todos/index.ts +20 -0
  510. package/template/src/shared/modules/todos/schemas.ts +65 -0
  511. package/template/src/shared/schemas/index.ts +79 -0
  512. package/template/src/types/global.d.ts +14 -0
  513. package/template/src/vite-env.d.ts +21 -0
  514. package/template/tailwind.config.js +11 -0
  515. package/template/tests/e2e/admin-crud.spec.ts +81 -0
  516. package/template/tests/e2e/case-o1.spec.ts +108 -0
  517. package/template/tests/e2e/global-setup.ts +73 -0
  518. package/template/tests/e2e/global-teardown.ts +28 -0
  519. package/template/tests/e2e/notification.spec.ts +458 -0
  520. package/template/tests/e2e/todo.spec.ts +623 -0
  521. package/template/tests/e2e/websocket.spec.ts +254 -0
  522. package/template/tsconfig.json +35 -0
  523. package/template/tsup.config.ts +95 -0
  524. package/template/vite-plugins.ts +113 -0
  525. package/template/vite.config.ts +96 -0
  526. package/template/vitest.config.ts +53 -0
  527. package/template/vitest.integration.config.ts +24 -0
  528. package/template/vitest.integration.setup.ts +22 -0
  529. package/template/vitest.setup.ts +74 -0
  530. package/template/wrangler.toml +33 -0
@@ -0,0 +1,647 @@
1
+ import { getRawClient } from './index'
2
+ import type { Client } from '@libsql/client'
3
+
4
+ export async function setupTestDatabase(): Promise<void> {
5
+ const client = await getRawClient()
6
+
7
+ if (!client || !('execute' in client)) {
8
+ throw new Error('Test database client not available')
9
+ }
10
+
11
+ const migrationSQL = `
12
+ CREATE TABLE IF NOT EXISTS todos (
13
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
14
+ title TEXT NOT NULL,
15
+ description TEXT,
16
+ status TEXT DEFAULT 'pending' NOT NULL,
17
+ created_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL,
18
+ updated_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL
19
+ );
20
+
21
+ CREATE TABLE IF NOT EXISTS todo_attachments (
22
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
23
+ todo_id INTEGER NOT NULL,
24
+ file_name TEXT NOT NULL,
25
+ original_name TEXT NOT NULL,
26
+ mime_type TEXT NOT NULL,
27
+ size INTEGER NOT NULL,
28
+ path TEXT NOT NULL,
29
+ uploaded_by TEXT,
30
+ created_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL,
31
+ FOREIGN KEY (todo_id) REFERENCES todos(id) ON DELETE CASCADE
32
+ );
33
+
34
+ CREATE TABLE IF NOT EXISTS notifications (
35
+ id TEXT PRIMARY KEY NOT NULL,
36
+ type TEXT NOT NULL,
37
+ title TEXT NOT NULL,
38
+ message TEXT NOT NULL,
39
+ read INTEGER DEFAULT false NOT NULL,
40
+ created_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL
41
+ );
42
+
43
+ CREATE TABLE IF NOT EXISTS permissions (
44
+ id TEXT PRIMARY KEY NOT NULL,
45
+ code TEXT NOT NULL UNIQUE,
46
+ name TEXT NOT NULL,
47
+ label TEXT NOT NULL,
48
+ category TEXT NOT NULL,
49
+ description TEXT,
50
+ sort_order INTEGER DEFAULT 0,
51
+ is_active INTEGER DEFAULT true,
52
+ created_at INTEGER,
53
+ updated_at INTEGER
54
+ );
55
+
56
+ CREATE TABLE IF NOT EXISTS roles (
57
+ id TEXT PRIMARY KEY NOT NULL,
58
+ code TEXT NOT NULL UNIQUE,
59
+ name TEXT NOT NULL,
60
+ label TEXT NOT NULL,
61
+ description TEXT,
62
+ is_system INTEGER DEFAULT false,
63
+ is_active INTEGER DEFAULT true,
64
+ sort_order INTEGER DEFAULT 0,
65
+ created_at INTEGER,
66
+ updated_at INTEGER
67
+ );
68
+
69
+ CREATE TABLE IF NOT EXISTS role_permissions (
70
+ role_id TEXT NOT NULL,
71
+ permission_id TEXT NOT NULL,
72
+ created_at INTEGER,
73
+ PRIMARY KEY(role_id, permission_id),
74
+ FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE,
75
+ FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE
76
+ );
77
+
78
+ CREATE TABLE IF NOT EXISTS user_roles (
79
+ id TEXT PRIMARY KEY NOT NULL,
80
+ user_id TEXT NOT NULL,
81
+ role_id TEXT NOT NULL,
82
+ assigned_by TEXT,
83
+ assigned_at INTEGER,
84
+ expires_at INTEGER,
85
+ is_active INTEGER DEFAULT true,
86
+ FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE
87
+ );
88
+
89
+ CREATE TABLE IF NOT EXISTS routes (
90
+ id TEXT PRIMARY KEY NOT NULL,
91
+ path TEXT NOT NULL,
92
+ method TEXT NOT NULL,
93
+ name TEXT,
94
+ description TEXT,
95
+ module TEXT,
96
+ is_public INTEGER DEFAULT false,
97
+ is_active INTEGER DEFAULT true,
98
+ created_at INTEGER,
99
+ updated_at INTEGER
100
+ );
101
+
102
+ CREATE TABLE IF NOT EXISTS permission_routes (
103
+ permission_id TEXT NOT NULL,
104
+ route_id TEXT NOT NULL,
105
+ created_at INTEGER,
106
+ PRIMARY KEY(permission_id, route_id),
107
+ FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE,
108
+ FOREIGN KEY (route_id) REFERENCES routes(id) ON DELETE CASCADE
109
+ );
110
+
111
+ CREATE TABLE IF NOT EXISTS permission_audit_logs (
112
+ id TEXT PRIMARY KEY NOT NULL,
113
+ user_id TEXT NOT NULL,
114
+ action TEXT NOT NULL,
115
+ resource_type TEXT NOT NULL,
116
+ resource_id TEXT,
117
+ old_value TEXT,
118
+ new_value TEXT,
119
+ ip_address TEXT,
120
+ user_agent TEXT,
121
+ created_at INTEGER
122
+ );
123
+
124
+ CREATE TABLE IF NOT EXISTS orders (
125
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
126
+ order_no TEXT NOT NULL,
127
+ customer_name TEXT NOT NULL,
128
+ customer_email TEXT NOT NULL,
129
+ product_name TEXT NOT NULL,
130
+ amount INTEGER NOT NULL,
131
+ status TEXT DEFAULT 'pending' NOT NULL,
132
+ created_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL,
133
+ updated_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL
134
+ );
135
+
136
+ CREATE TABLE IF NOT EXISTS tickets (
137
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
138
+ ticket_no TEXT NOT NULL,
139
+ customer_name TEXT NOT NULL,
140
+ customer_email TEXT NOT NULL,
141
+ subject TEXT NOT NULL,
142
+ description TEXT NOT NULL,
143
+ status TEXT DEFAULT 'open' NOT NULL,
144
+ priority TEXT DEFAULT 'medium' NOT NULL,
145
+ category TEXT NOT NULL,
146
+ assigned_to TEXT,
147
+ created_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL,
148
+ updated_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL
149
+ );
150
+
151
+ CREATE TABLE IF NOT EXISTS ticket_replies (
152
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
153
+ ticket_id INTEGER NOT NULL,
154
+ content TEXT NOT NULL,
155
+ author TEXT NOT NULL,
156
+ is_customer INTEGER DEFAULT 0 NOT NULL,
157
+ created_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL,
158
+ FOREIGN KEY (ticket_id) REFERENCES tickets(id) ON DELETE CASCADE
159
+ );
160
+
161
+ CREATE TABLE IF NOT EXISTS disputes (
162
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
163
+ dispute_no TEXT NOT NULL,
164
+ order_id TEXT NOT NULL,
165
+ order_no TEXT NOT NULL,
166
+ customer_name TEXT NOT NULL,
167
+ customer_email TEXT NOT NULL,
168
+ type TEXT NOT NULL,
169
+ status TEXT DEFAULT 'pending' NOT NULL,
170
+ description TEXT NOT NULL,
171
+ resolution TEXT,
172
+ amount INTEGER NOT NULL,
173
+ resolved_at INTEGER,
174
+ resolved_by TEXT,
175
+ created_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL,
176
+ updated_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL
177
+ );
178
+
179
+ CREATE TABLE IF NOT EXISTS contents (
180
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
181
+ title TEXT NOT NULL,
182
+ body TEXT NOT NULL,
183
+ excerpt TEXT,
184
+ category TEXT NOT NULL,
185
+ tags TEXT,
186
+ status TEXT DEFAULT 'draft' NOT NULL,
187
+ author TEXT NOT NULL,
188
+ view_count INTEGER DEFAULT 0 NOT NULL,
189
+ like_count INTEGER DEFAULT 0 NOT NULL,
190
+ published_at INTEGER,
191
+ created_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL,
192
+ updated_at INTEGER DEFAULT (unixepoch() * 1000) NOT NULL
193
+ );
194
+ `
195
+
196
+ const statements = migrationSQL.split(';').filter(s => s.trim())
197
+
198
+ for (const statement of statements) {
199
+ if (statement.trim()) {
200
+ try {
201
+ await client.execute(statement)
202
+ } catch {
203
+ // Ignore errors for existing tables/indexes
204
+ }
205
+ }
206
+ }
207
+
208
+ // Insert default roles and permissions
209
+ await seedTestData(client)
210
+ }
211
+
212
+ async function seedTestData(client: Client): Promise<void> {
213
+ // Insert default roles - names must match test expectations
214
+ const roles = [
215
+ {
216
+ id: 'role_super_admin',
217
+ code: 'super_admin',
218
+ name: '超级管理员',
219
+ label: '超级管理员',
220
+ is_system: 1,
221
+ sort_order: 1,
222
+ },
223
+ {
224
+ id: 'role_admin',
225
+ code: 'admin',
226
+ name: '管理员',
227
+ label: '管理员',
228
+ is_system: 1,
229
+ sort_order: 2,
230
+ },
231
+ {
232
+ id: 'role_user',
233
+ code: 'user',
234
+ name: '普通用户',
235
+ label: '普通用户',
236
+ is_system: 0,
237
+ sort_order: 3,
238
+ },
239
+ {
240
+ id: 'role_customer_service',
241
+ code: 'customer_service',
242
+ name: '客服人员',
243
+ label: '客服',
244
+ is_system: 0,
245
+ sort_order: 4,
246
+ },
247
+ ]
248
+
249
+ for (const role of roles) {
250
+ try {
251
+ await client.execute({
252
+ sql: `INSERT OR IGNORE INTO roles (id, code, name, label, is_system, is_active, sort_order, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
253
+ args: [
254
+ role.id,
255
+ role.code,
256
+ role.name,
257
+ role.label,
258
+ role.is_system,
259
+ 1,
260
+ role.sort_order,
261
+ Date.now(),
262
+ Date.now(),
263
+ ],
264
+ })
265
+ } catch {
266
+ // Ignore duplicate errors
267
+ }
268
+ }
269
+
270
+ // Insert default permissions - user category (4 permissions)
271
+ const userPermissions = [
272
+ {
273
+ id: 'perm_user_view',
274
+ code: 'user:view',
275
+ name: '查看用户',
276
+ label: '查看用户',
277
+ category: 'user',
278
+ },
279
+ {
280
+ id: 'perm_user_create',
281
+ code: 'user:create',
282
+ name: '创建用户',
283
+ label: '创建用户',
284
+ category: 'user',
285
+ },
286
+ {
287
+ id: 'perm_user_update',
288
+ code: 'user:update',
289
+ name: '更新用户',
290
+ label: '更新用户',
291
+ category: 'user',
292
+ },
293
+ {
294
+ id: 'perm_user_delete',
295
+ code: 'user:delete',
296
+ name: '删除用户',
297
+ label: '删除用户',
298
+ category: 'user',
299
+ },
300
+ ]
301
+
302
+ // content category (4 permissions)
303
+ const contentPermissions = [
304
+ {
305
+ id: 'perm_content_view',
306
+ code: 'content:view',
307
+ name: '查看内容',
308
+ label: '查看内容',
309
+ category: 'content',
310
+ },
311
+ {
312
+ id: 'perm_content_create',
313
+ code: 'content:create',
314
+ name: '创建内容',
315
+ label: '创建内容',
316
+ category: 'content',
317
+ },
318
+ {
319
+ id: 'perm_content_update',
320
+ code: 'content:update',
321
+ name: '更新内容',
322
+ label: '更新内容',
323
+ category: 'content',
324
+ },
325
+ {
326
+ id: 'perm_content_delete',
327
+ code: 'content:delete',
328
+ name: '删除内容',
329
+ label: '删除内容',
330
+ category: 'content',
331
+ },
332
+ ]
333
+
334
+ // system category (3 permissions)
335
+ const systemPermissions = [
336
+ {
337
+ id: 'perm_system_settings',
338
+ code: 'system:settings',
339
+ name: '系统设置',
340
+ label: '系统设置',
341
+ category: 'system',
342
+ },
343
+ {
344
+ id: 'perm_system_logs',
345
+ code: 'system:logs',
346
+ name: '查看日志',
347
+ label: '查看日志',
348
+ category: 'system',
349
+ },
350
+ {
351
+ id: 'perm_system_backup',
352
+ code: 'system:backup',
353
+ name: '系统备份',
354
+ label: '系统备份',
355
+ category: 'system',
356
+ },
357
+ ]
358
+
359
+ // order category (5 permissions)
360
+ const orderPermissions = [
361
+ {
362
+ id: 'perm_order_view',
363
+ code: 'order:view',
364
+ name: '查看订单',
365
+ label: '查看订单',
366
+ category: 'order',
367
+ },
368
+ {
369
+ id: 'perm_order_create',
370
+ code: 'order:create',
371
+ name: '创建订单',
372
+ label: '创建订单',
373
+ category: 'order',
374
+ },
375
+ {
376
+ id: 'perm_order_edit',
377
+ code: 'order:edit',
378
+ name: '编辑订单',
379
+ label: '编辑订单',
380
+ category: 'order',
381
+ },
382
+ {
383
+ id: 'perm_order_delete',
384
+ code: 'order:delete',
385
+ name: '删除订单',
386
+ label: '删除订单',
387
+ category: 'order',
388
+ },
389
+ {
390
+ id: 'perm_order_process',
391
+ code: 'order:process',
392
+ name: '处理订单',
393
+ label: '处理订单',
394
+ category: 'order',
395
+ },
396
+ ]
397
+
398
+ // ticket category (6 permissions)
399
+ const ticketPermissions = [
400
+ {
401
+ id: 'perm_ticket_view',
402
+ code: 'ticket:view',
403
+ name: '查看工单',
404
+ label: '查看工单',
405
+ category: 'ticket',
406
+ },
407
+ {
408
+ id: 'perm_ticket_create',
409
+ code: 'ticket:create',
410
+ name: '创建工单',
411
+ label: '创建工单',
412
+ category: 'ticket',
413
+ },
414
+ {
415
+ id: 'perm_ticket_edit',
416
+ code: 'ticket:edit',
417
+ name: '编辑工单',
418
+ label: '编辑工单',
419
+ category: 'ticket',
420
+ },
421
+ {
422
+ id: 'perm_ticket_delete',
423
+ code: 'ticket:delete',
424
+ name: '删除工单',
425
+ label: '删除工单',
426
+ category: 'ticket',
427
+ },
428
+ {
429
+ id: 'perm_ticket_reply',
430
+ code: 'ticket:reply',
431
+ name: '回复工单',
432
+ label: '回复工单',
433
+ category: 'ticket',
434
+ },
435
+ {
436
+ id: 'perm_ticket_close',
437
+ code: 'ticket:close',
438
+ name: '关闭工单',
439
+ label: '关闭工单',
440
+ category: 'ticket',
441
+ },
442
+ ]
443
+
444
+ // data category (2 permissions)
445
+ const dataPermissions = [
446
+ {
447
+ id: 'perm_data_export',
448
+ code: 'data:export',
449
+ name: '导出数据',
450
+ label: '导出数据',
451
+ category: 'data',
452
+ },
453
+ {
454
+ id: 'perm_data_import',
455
+ code: 'data:import',
456
+ name: '导入数据',
457
+ label: '导入数据',
458
+ category: 'data',
459
+ },
460
+ ]
461
+
462
+ // dispute category (5 permissions)
463
+ const disputePermissions = [
464
+ {
465
+ id: 'perm_dispute_view',
466
+ code: 'dispute:view',
467
+ name: '查看争议',
468
+ label: '查看争议',
469
+ category: 'dispute',
470
+ },
471
+ {
472
+ id: 'perm_dispute_create',
473
+ code: 'dispute:create',
474
+ name: '创建争议',
475
+ label: '创建争议',
476
+ category: 'dispute',
477
+ },
478
+ {
479
+ id: 'perm_dispute_edit',
480
+ code: 'dispute:edit',
481
+ name: '编辑争议',
482
+ label: '编辑争议',
483
+ category: 'dispute',
484
+ },
485
+ {
486
+ id: 'perm_dispute_delete',
487
+ code: 'dispute:delete',
488
+ name: '删除争议',
489
+ label: '删除争议',
490
+ category: 'dispute',
491
+ },
492
+ {
493
+ id: 'perm_dispute_resolve',
494
+ code: 'dispute:resolve',
495
+ name: '解决争议',
496
+ label: '解决争议',
497
+ category: 'dispute',
498
+ },
499
+ ]
500
+
501
+ // Combine all permissions
502
+ const allPermissions = [
503
+ ...userPermissions,
504
+ ...contentPermissions,
505
+ ...systemPermissions,
506
+ ...orderPermissions,
507
+ ...ticketPermissions,
508
+ ...dataPermissions,
509
+ ...disputePermissions,
510
+ ]
511
+
512
+ for (const perm of allPermissions) {
513
+ try {
514
+ await client.execute({
515
+ sql: `INSERT OR IGNORE INTO permissions (id, code, name, label, category, is_active, sort_order, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
516
+ args: [
517
+ perm.id,
518
+ perm.code,
519
+ perm.name,
520
+ perm.label,
521
+ perm.category,
522
+ 1,
523
+ 0,
524
+ Date.now(),
525
+ Date.now(),
526
+ ],
527
+ })
528
+ } catch {
529
+ // Ignore duplicate errors
530
+ }
531
+ }
532
+
533
+ // Assign permissions to roles
534
+ // Super admin gets all permissions
535
+ for (const perm of allPermissions) {
536
+ try {
537
+ await client.execute({
538
+ sql: `INSERT OR IGNORE INTO role_permissions (role_id, permission_id, created_at) VALUES (?, ?, ?)`,
539
+ args: ['role_super_admin', perm.id, Date.now()],
540
+ })
541
+ } catch {
542
+ // Ignore duplicate errors
543
+ }
544
+ }
545
+
546
+ // Admin gets most permissions except system settings
547
+ for (const perm of allPermissions) {
548
+ if (perm.code !== 'system:settings') {
549
+ try {
550
+ await client.execute({
551
+ sql: `INSERT OR IGNORE INTO role_permissions (role_id, permission_id, created_at) VALUES (?, ?, ?)`,
552
+ args: ['role_admin', perm.id, Date.now()],
553
+ })
554
+ } catch {
555
+ // Ignore duplicate errors
556
+ }
557
+ }
558
+ }
559
+
560
+ // Customer service gets view permissions for user, content, order, ticket + reply and close for ticket
561
+ const customerServicePermissions = [
562
+ 'perm_user_view',
563
+ 'perm_content_view',
564
+ 'perm_order_view',
565
+ 'perm_order_create',
566
+ 'perm_order_edit',
567
+ 'perm_order_delete',
568
+ 'perm_order_process',
569
+ 'perm_ticket_view',
570
+ 'perm_ticket_create',
571
+ 'perm_ticket_edit',
572
+ 'perm_ticket_delete',
573
+ 'perm_ticket_reply',
574
+ 'perm_ticket_close',
575
+ 'perm_dispute_view',
576
+ 'perm_dispute_create',
577
+ 'perm_dispute_edit',
578
+ 'perm_dispute_delete',
579
+ 'perm_dispute_resolve',
580
+ ]
581
+ for (const permId of customerServicePermissions) {
582
+ try {
583
+ await client.execute({
584
+ sql: `INSERT OR IGNORE INTO role_permissions (role_id, permission_id, created_at) VALUES (?, ?, ?)`,
585
+ args: ['role_customer_service', permId, Date.now()],
586
+ })
587
+ } catch {
588
+ // Ignore duplicate errors
589
+ }
590
+ }
591
+
592
+ // Assign test user-role mappings for dev token users
593
+ const testUserRoles = [
594
+ { userId: 'super-admin-1', roleId: 'role_super_admin' },
595
+ { userId: 'customer-service-1', roleId: 'role_customer_service' },
596
+ { userId: 'user-1', roleId: 'role_user' },
597
+ ]
598
+ for (const mapping of testUserRoles) {
599
+ try {
600
+ await client.execute({
601
+ sql: `INSERT OR IGNORE INTO user_roles (id, user_id, role_id, is_active, assigned_at) VALUES (?, ?, ?, ?, ?)`,
602
+ args: [`ur_${mapping.userId}`, mapping.userId, mapping.roleId, 1, Date.now()],
603
+ })
604
+ } catch {
605
+ // Ignore duplicate errors
606
+ }
607
+ }
608
+
609
+ // User gets limited permissions - view content and order
610
+ const userPermissionsList = ['perm_content_view', 'perm_order_view']
611
+ for (const permId of userPermissionsList) {
612
+ try {
613
+ await client.execute({
614
+ sql: `INSERT OR IGNORE INTO role_permissions (role_id, permission_id, created_at) VALUES (?, ?, ?)`,
615
+ args: ['role_user', permId, Date.now()],
616
+ })
617
+ } catch {
618
+ // Ignore duplicate errors
619
+ }
620
+ }
621
+ }
622
+
623
+ export async function cleanupTestDatabase(): Promise<void> {
624
+ const client = await getRawClient()
625
+
626
+ if (client && 'execute' in client) {
627
+ try {
628
+ await client.execute('DELETE FROM todo_attachments')
629
+ } catch {
630
+ // Table may not exist in some test environments
631
+ }
632
+ await client.execute('DELETE FROM todos')
633
+ await client.execute('DELETE FROM notifications')
634
+ await client.execute('DELETE FROM permission_routes')
635
+ await client.execute('DELETE FROM permission_audit_logs')
636
+ await client.execute('DELETE FROM role_permissions')
637
+ await client.execute('DELETE FROM user_roles')
638
+ await client.execute('DELETE FROM permissions')
639
+ await client.execute('DELETE FROM roles')
640
+ await client.execute('DELETE FROM routes')
641
+ await client.execute('DELETE FROM ticket_replies')
642
+ await client.execute('DELETE FROM tickets')
643
+ await client.execute('DELETE FROM orders')
644
+ await client.execute('DELETE FROM disputes')
645
+ await client.execute('DELETE FROM contents')
646
+ }
647
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @framework-baseline e350401421193896
3
+ * @framework-modify
4
+ * @reason 统一错误响应格式为 JSON,确保所有错误都返回结构化数据;移除冗余的 globalThis 设置
5
+ * @impact 影响 Cloudflare Workers 环境的错误响应格式
6
+ *
7
+ * Note: In Cloudflare Workers, each request runs in its own isolate,
8
+ * so globalThis is request-scoped and there's no race condition risk.
9
+ * The middleware sets the DB binding for each request.
10
+ */
11
+
12
+ import { createApp } from '../app'
13
+ import type { AppBindings } from '../types/bindings'
14
+ import { getDb } from '../db/driver-cloudflare'
15
+ import { RealtimeDurableObject } from '@server/core'
16
+ import { setRuntimeAdapter } from '@server/core/runtime'
17
+ import { getCloudflareRuntimeAdapter } from '@server/core/runtime-cloudflare'
18
+
19
+ export interface CloudflareBindings extends AppBindings {
20
+ DB: D1Database
21
+ REALTIME_DO: DurableObjectNamespace
22
+ }
23
+
24
+ const runtimeAdapter = getCloudflareRuntimeAdapter()
25
+ setRuntimeAdapter(runtimeAdapter)
26
+
27
+ const app = createApp<CloudflareBindings>()
28
+
29
+ const wrappedApp = app
30
+ .use('*', async (c, next) => {
31
+ ;(globalThis as unknown as { DB: D1Database }).DB = c.env.DB
32
+ await next()
33
+ })
34
+ .get('/', c =>
35
+ c.json({
36
+ name: 'Biomimic Todo App',
37
+ version: '0.1.0',
38
+ environment: 'cloudflare-workers',
39
+ })
40
+ )
41
+ .onError((err, c) => {
42
+ console.error('Server error:', err)
43
+ c.res.headers.set('Content-Type', 'application/json')
44
+ const statusCode =
45
+ err instanceof Error && 'status' in err ? (err as { status: number }).status : 500
46
+ const message = err.message || 'Internal server error'
47
+ const responseStatus = statusCode || 500
48
+ return c.json({ success: false as const, error: message, status: responseStatus }, responseStatus as 500)
49
+ })
50
+
51
+ export default {
52
+ fetch: async (request: Request, env: CloudflareBindings, ctx: ExecutionContext) => {
53
+ const url = new URL(request.url)
54
+
55
+ if (url.pathname.startsWith('/api/') || url.pathname === '/health') {
56
+ return wrappedApp.fetch(request, env, ctx)
57
+ }
58
+
59
+ if (env.ASSETS) {
60
+ const assetResponse = await env.ASSETS.fetch(request)
61
+ if (assetResponse.status !== 404) {
62
+ return assetResponse
63
+ }
64
+ }
65
+
66
+ return wrappedApp.fetch(request, env, ctx)
67
+ },
68
+ }
69
+
70
+ export { RealtimeDurableObject, getDb }
71
+ export type AppType = typeof wrappedApp