create-aiko 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 (317) hide show
  1. package/README.md +46 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +7 -0
  4. package/dist/create.d.ts +1 -0
  5. package/dist/create.js +174 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +2 -0
  8. package/dist/scaffold.d.ts +7 -0
  9. package/dist/scaffold.js +310 -0
  10. package/package.json +37 -0
  11. package/template/README.md +63 -0
  12. package/template/docs/better-sqlite3-design.md +101 -0
  13. package/template/docs/shared-vs-shared-auth.md +54 -0
  14. package/template/package.json +23 -0
  15. package/template/packages/admin/.env.dev +1 -0
  16. package/template/packages/admin/.env.prod +4 -0
  17. package/template/packages/admin/.env.stage +4 -0
  18. package/template/packages/admin/Dockerfile +37 -0
  19. package/template/packages/admin/README.MD +27 -0
  20. package/template/packages/admin/components.json +21 -0
  21. package/template/packages/admin/eslint.config.js +28 -0
  22. package/template/packages/admin/index.html +50 -0
  23. package/template/packages/admin/package.json +100 -0
  24. package/template/packages/admin/public/vite.svg +1 -0
  25. package/template/packages/admin/src/App.css +82 -0
  26. package/template/packages/admin/src/App.tsx +128 -0
  27. package/template/packages/admin/src/app.config.ts +3 -0
  28. package/template/packages/admin/src/components/admin-ui/approval-flow.tsx +205 -0
  29. package/template/packages/admin/src/components/admin-ui/data-table/data-table-pagination.tsx +148 -0
  30. package/template/packages/admin/src/components/admin-ui/data-table/data-table-sorter.tsx +50 -0
  31. package/template/packages/admin/src/components/admin-ui/data-table/index.tsx +296 -0
  32. package/template/packages/admin/src/components/admin-ui/editable-table.tsx +292 -0
  33. package/template/packages/admin/src/components/admin-ui/form/input-password.tsx +38 -0
  34. package/template/packages/admin/src/components/admin-ui/form/sign-in-form.tsx +104 -0
  35. package/template/packages/admin/src/components/admin-ui/layout/error-component.tsx +71 -0
  36. package/template/packages/admin/src/components/admin-ui/layout/header.tsx +148 -0
  37. package/template/packages/admin/src/components/admin-ui/layout/language-switcher.tsx +47 -0
  38. package/template/packages/admin/src/components/admin-ui/layout/layout.tsx +42 -0
  39. package/template/packages/admin/src/components/admin-ui/layout/loading-overlay.tsx +36 -0
  40. package/template/packages/admin/src/components/admin-ui/layout/shell-bar.tsx +232 -0
  41. package/template/packages/admin/src/components/admin-ui/layout/sidebar.tsx +193 -0
  42. package/template/packages/admin/src/components/admin-ui/layout/user-avatar.tsx +31 -0
  43. package/template/packages/admin/src/components/admin-ui/list-report.tsx +313 -0
  44. package/template/packages/admin/src/components/admin-ui/master-detail.tsx +382 -0
  45. package/template/packages/admin/src/components/admin-ui/notification/toaster.tsx +23 -0
  46. package/template/packages/admin/src/components/admin-ui/notification/undoable-notification.tsx +84 -0
  47. package/template/packages/admin/src/components/admin-ui/object-page.tsx +539 -0
  48. package/template/packages/admin/src/components/admin-ui/process-stepper.tsx +204 -0
  49. package/template/packages/admin/src/components/admin-ui/theme/theme-provider.tsx +160 -0
  50. package/template/packages/admin/src/components/admin-ui/theme/theme-select.tsx +129 -0
  51. package/template/packages/admin/src/components/admin-ui/theme/theme-toggle.tsx +90 -0
  52. package/template/packages/admin/src/components/admin-ui/timeline.tsx +137 -0
  53. package/template/packages/admin/src/components/admin-ui/tree-navigator.tsx +243 -0
  54. package/template/packages/admin/src/components/ui/accordion.tsx +64 -0
  55. package/template/packages/admin/src/components/ui/alert-dialog.tsx +157 -0
  56. package/template/packages/admin/src/components/ui/alert.tsx +66 -0
  57. package/template/packages/admin/src/components/ui/aspect-ratio.tsx +9 -0
  58. package/template/packages/admin/src/components/ui/avatar.tsx +53 -0
  59. package/template/packages/admin/src/components/ui/badge.tsx +47 -0
  60. package/template/packages/admin/src/components/ui/breadcrumb.tsx +111 -0
  61. package/template/packages/admin/src/components/ui/button.tsx +59 -0
  62. package/template/packages/admin/src/components/ui/calendar.tsx +74 -0
  63. package/template/packages/admin/src/components/ui/card.tsx +92 -0
  64. package/template/packages/admin/src/components/ui/carousel.tsx +237 -0
  65. package/template/packages/admin/src/components/ui/chart.tsx +351 -0
  66. package/template/packages/admin/src/components/ui/checkbox.tsx +32 -0
  67. package/template/packages/admin/src/components/ui/collapsible.tsx +33 -0
  68. package/template/packages/admin/src/components/ui/command.tsx +182 -0
  69. package/template/packages/admin/src/components/ui/context-menu.tsx +252 -0
  70. package/template/packages/admin/src/components/ui/dialog.tsx +141 -0
  71. package/template/packages/admin/src/components/ui/drawer.tsx +130 -0
  72. package/template/packages/admin/src/components/ui/dropdown-menu.tsx +255 -0
  73. package/template/packages/admin/src/components/ui/form.tsx +166 -0
  74. package/template/packages/admin/src/components/ui/hover-card.tsx +42 -0
  75. package/template/packages/admin/src/components/ui/input-otp.tsx +77 -0
  76. package/template/packages/admin/src/components/ui/input.tsx +21 -0
  77. package/template/packages/admin/src/components/ui/label.tsx +22 -0
  78. package/template/packages/admin/src/components/ui/menubar.tsx +274 -0
  79. package/template/packages/admin/src/components/ui/navigation-menu.tsx +168 -0
  80. package/template/packages/admin/src/components/ui/pagination.tsx +127 -0
  81. package/template/packages/admin/src/components/ui/popover.tsx +48 -0
  82. package/template/packages/admin/src/components/ui/progress.tsx +29 -0
  83. package/template/packages/admin/src/components/ui/radio-group.tsx +45 -0
  84. package/template/packages/admin/src/components/ui/resizable.tsx +54 -0
  85. package/template/packages/admin/src/components/ui/scroll-area.tsx +58 -0
  86. package/template/packages/admin/src/components/ui/select.tsx +183 -0
  87. package/template/packages/admin/src/components/ui/separator.tsx +26 -0
  88. package/template/packages/admin/src/components/ui/sheet.tsx +139 -0
  89. package/template/packages/admin/src/components/ui/sidebar.tsx +740 -0
  90. package/template/packages/admin/src/components/ui/skeleton.tsx +13 -0
  91. package/template/packages/admin/src/components/ui/slider.tsx +63 -0
  92. package/template/packages/admin/src/components/ui/sonner.tsx +23 -0
  93. package/template/packages/admin/src/components/ui/switch.tsx +31 -0
  94. package/template/packages/admin/src/components/ui/table.tsx +114 -0
  95. package/template/packages/admin/src/components/ui/tabs.tsx +66 -0
  96. package/template/packages/admin/src/components/ui/textarea.tsx +18 -0
  97. package/template/packages/admin/src/components/ui/toggle-group.tsx +73 -0
  98. package/template/packages/admin/src/components/ui/toggle.tsx +45 -0
  99. package/template/packages/admin/src/components/ui/tooltip.tsx +59 -0
  100. package/template/packages/admin/src/hooks/use-mobile.ts +21 -0
  101. package/template/packages/admin/src/i18n.ts +20 -0
  102. package/template/packages/admin/src/index.tsx +18 -0
  103. package/template/packages/admin/src/layouts/menu-layout.tsx +211 -0
  104. package/template/packages/admin/src/layouts/tile-layout.tsx +355 -0
  105. package/template/packages/admin/src/lib/utils.ts +6 -0
  106. package/template/packages/admin/src/locales/en.json +68 -0
  107. package/template/packages/admin/src/locales/zh.json +68 -0
  108. package/template/packages/admin/src/pages/dashboard.tsx +12 -0
  109. package/template/packages/admin/src/pages/goods-receipt/CreatePage.tsx +302 -0
  110. package/template/packages/admin/src/pages/goods-receipt/EditPage.tsx +221 -0
  111. package/template/packages/admin/src/pages/goods-receipt/ListPage.tsx +283 -0
  112. package/template/packages/admin/src/pages/goods-receipt/ViewPage.tsx +280 -0
  113. package/template/packages/admin/src/pages/goods-receipt/index.ts +4 -0
  114. package/template/packages/admin/src/pages/home-page.tsx +244 -0
  115. package/template/packages/admin/src/pages/login-page.tsx +91 -0
  116. package/template/packages/admin/src/pages/master-data/cost-centers/index.tsx +461 -0
  117. package/template/packages/admin/src/pages/master-data/currencies/index.tsx +255 -0
  118. package/template/packages/admin/src/pages/master-data/materials/ListPage.tsx +271 -0
  119. package/template/packages/admin/src/pages/master-data/materials/ViewPage.tsx +240 -0
  120. package/template/packages/admin/src/pages/master-data/materials/index.ts +2 -0
  121. package/template/packages/admin/src/pages/master-data/plants/ListPage.tsx +279 -0
  122. package/template/packages/admin/src/pages/master-data/plants/ViewPage.tsx +380 -0
  123. package/template/packages/admin/src/pages/master-data/plants/index.ts +2 -0
  124. package/template/packages/admin/src/pages/master-data/purchase-organizations/index.tsx +341 -0
  125. package/template/packages/admin/src/pages/master-data/units-of-measure/index.tsx +295 -0
  126. package/template/packages/admin/src/pages/master-data/vendors/ListPage.tsx +266 -0
  127. package/template/packages/admin/src/pages/master-data/vendors/ViewPage.tsx +274 -0
  128. package/template/packages/admin/src/pages/master-data/vendors/index.ts +2 -0
  129. package/template/packages/admin/src/pages/placeholder-page.tsx +13 -0
  130. package/template/packages/admin/src/pages/purchase-orders/ListPage.tsx +289 -0
  131. package/template/packages/admin/src/pages/purchase-orders/ViewPage.tsx +343 -0
  132. package/template/packages/admin/src/pages/purchase-orders/index.ts +2 -0
  133. package/template/packages/admin/src/pages/purchase-requisitions/CreatePage.tsx +398 -0
  134. package/template/packages/admin/src/pages/purchase-requisitions/EditPage.tsx +473 -0
  135. package/template/packages/admin/src/pages/purchase-requisitions/ListPage.tsx +307 -0
  136. package/template/packages/admin/src/pages/purchase-requisitions/ViewPage.tsx +304 -0
  137. package/template/packages/admin/src/pages/purchase-requisitions/constants.ts +51 -0
  138. package/template/packages/admin/src/pages/purchase-requisitions/index.ts +4 -0
  139. package/template/packages/admin/src/pages/reports/PurchaseOrderReport.tsx +312 -0
  140. package/template/packages/admin/src/pages/reports/PurchaseRequisitionReport.tsx +303 -0
  141. package/template/packages/admin/src/pages/reports/index.ts +2 -0
  142. package/template/packages/admin/src/pages/settings-page.tsx +335 -0
  143. package/template/packages/admin/src/providers/app-config.tsx +50 -0
  144. package/template/packages/admin/src/routes/auth.ts +6 -0
  145. package/template/packages/admin/src/routes/index.ts +85 -0
  146. package/template/packages/admin/src/routes/menu.ts +176 -0
  147. package/template/packages/admin/src/routes/modules/goods-receipt.ts +31 -0
  148. package/template/packages/admin/src/routes/modules/master-data.ts +41 -0
  149. package/template/packages/admin/src/routes/modules/purchase-orders.ts +27 -0
  150. package/template/packages/admin/src/routes/modules/purchase-requisitions.ts +39 -0
  151. package/template/packages/admin/src/routes/modules/reports.ts +33 -0
  152. package/template/packages/admin/src/routes/modules/settings.ts +19 -0
  153. package/template/packages/admin/src/routes/withSuspense.tsx +21 -0
  154. package/template/packages/admin/src/theme/amber.css +27 -0
  155. package/template/packages/admin/src/theme/blue.css +27 -0
  156. package/template/packages/admin/src/theme/default.css +75 -0
  157. package/template/packages/admin/src/theme/fiori.css +180 -0
  158. package/template/packages/admin/src/theme/green.css +27 -0
  159. package/template/packages/admin/src/theme/index.css +12 -0
  160. package/template/packages/admin/src/theme/rose.css +27 -0
  161. package/template/packages/admin/src/theme/violet.css +27 -0
  162. package/template/packages/admin/src/vite-env.d.ts +1 -0
  163. package/template/packages/admin/tsconfig.json +28 -0
  164. package/template/packages/admin/tsconfig.node.json +21 -0
  165. package/template/packages/admin/vite.config.ts +26 -0
  166. package/template/packages/api/.eslintrc.json +6 -0
  167. package/template/packages/api/.swcrc +17 -0
  168. package/template/packages/api/app.config.ts +160 -0
  169. package/template/packages/api/docs/api-document.md +497 -0
  170. package/template/packages/api/examples/security/README.md +664 -0
  171. package/template/packages/api/examples/security/complete/.env.example +26 -0
  172. package/template/packages/api/examples/security/complete/PROJECT_STRUCTURE.md +220 -0
  173. package/template/packages/api/examples/security/complete/README.md +847 -0
  174. package/template/packages/api/examples/security/complete/app.config.ts +69 -0
  175. package/template/packages/api/examples/security/complete/app.ts +63 -0
  176. package/template/packages/api/examples/security/complete/controller/auth.controller.ts +131 -0
  177. package/template/packages/api/examples/security/complete/controller/index.ts +4 -0
  178. package/template/packages/api/examples/security/complete/controller/permission.controller.ts +41 -0
  179. package/template/packages/api/examples/security/complete/controller/role.controller.ts +53 -0
  180. package/template/packages/api/examples/security/complete/controller/user.controller.ts +53 -0
  181. package/template/packages/api/examples/security/complete/dto/change-password.dto.ts +10 -0
  182. package/template/packages/api/examples/security/complete/dto/create-permission.dto.ts +14 -0
  183. package/template/packages/api/examples/security/complete/dto/create-role.dto.ts +11 -0
  184. package/template/packages/api/examples/security/complete/dto/create-user.dto.ts +15 -0
  185. package/template/packages/api/examples/security/complete/dto/index.ts +7 -0
  186. package/template/packages/api/examples/security/complete/dto/login.dto.ts +10 -0
  187. package/template/packages/api/examples/security/complete/dto/oauth-profile.dto.ts +7 -0
  188. package/template/packages/api/examples/security/complete/dto/register.dto.ts +17 -0
  189. package/template/packages/api/examples/security/complete/entity/index.ts +6 -0
  190. package/template/packages/api/examples/security/complete/entity/oauth-account.entity.ts +39 -0
  191. package/template/packages/api/examples/security/complete/entity/permission.entity.ts +31 -0
  192. package/template/packages/api/examples/security/complete/entity/role-permission.entity.ts +19 -0
  193. package/template/packages/api/examples/security/complete/entity/role.entity.ts +25 -0
  194. package/template/packages/api/examples/security/complete/entity/user-role.entity.ts +19 -0
  195. package/template/packages/api/examples/security/complete/entity/user.entity.ts +46 -0
  196. package/template/packages/api/examples/security/complete/init.sql +81 -0
  197. package/template/packages/api/examples/security/complete/middleware/auth.interceptor.ts +39 -0
  198. package/template/packages/api/examples/security/complete/middleware/index.ts +2 -0
  199. package/template/packages/api/examples/security/complete/middleware/permission.interceptor.ts +61 -0
  200. package/template/packages/api/examples/security/complete/package.json +54 -0
  201. package/template/packages/api/examples/security/complete/seed.sql +42 -0
  202. package/template/packages/api/examples/security/complete/service/auth.service.ts +41 -0
  203. package/template/packages/api/examples/security/complete/service/index.ts +5 -0
  204. package/template/packages/api/examples/security/complete/service/oauth.service.ts +82 -0
  205. package/template/packages/api/examples/security/complete/service/permission.service.ts +113 -0
  206. package/template/packages/api/examples/security/complete/service/role.service.ts +85 -0
  207. package/template/packages/api/examples/security/complete/service/user.service.ts +132 -0
  208. package/template/packages/api/examples/security/complete/tests/TEST_REPORT.md +318 -0
  209. package/template/packages/api/examples/security/complete/tests/generate-report.js +335 -0
  210. package/template/packages/api/examples/security/complete/tests/helpers/api-helpers.ts +116 -0
  211. package/template/packages/api/examples/security/complete/tests/helpers/index.ts +2 -0
  212. package/template/packages/api/examples/security/complete/tests/helpers/test-helpers.ts +129 -0
  213. package/template/packages/api/examples/security/complete/tests/integration/auth.api.test.ts +429 -0
  214. package/template/packages/api/examples/security/complete/tests/integration/role.api.test.ts +400 -0
  215. package/template/packages/api/examples/security/complete/tests/integration/user.api.test.ts +459 -0
  216. package/template/packages/api/examples/security/complete/tests/jest.config.js +40 -0
  217. package/template/packages/api/examples/security/complete/tests/run-all-tests.js +135 -0
  218. package/template/packages/api/examples/security/complete/tests/run-tests.js +109 -0
  219. package/template/packages/api/examples/security/complete/tests/setup.ts +19 -0
  220. package/template/packages/api/examples/security/complete/tests/unit/auth.service.test.ts +199 -0
  221. package/template/packages/api/examples/security/complete/tests/unit/permission.service.test.ts +377 -0
  222. package/template/packages/api/examples/security/complete/tests/unit/user.service.test.ts +288 -0
  223. package/template/packages/api/examples/security/complete/tsconfig.json +35 -0
  224. package/template/packages/api/examples/security/jwt/README.md +424 -0
  225. package/template/packages/api/examples/security/local/README.md +499 -0
  226. package/template/packages/api/examples/security/oauth2/README.md +637 -0
  227. package/template/packages/api/examples/security/permission/README.md +943 -0
  228. package/template/packages/api/examples/security/session/README.md +753 -0
  229. package/template/packages/api/package.json +56 -0
  230. package/template/packages/api/src/controller/auth.controller.ts +127 -0
  231. package/template/packages/api/src/controller/cache.controller.ts +106 -0
  232. package/template/packages/api/src/controller/menu.controller.ts +46 -0
  233. package/template/packages/api/src/controller/mq.controller.ts +35 -0
  234. package/template/packages/api/src/controller/role.controller.ts +51 -0
  235. package/template/packages/api/src/controller/upload.controller.ts +85 -0
  236. package/template/packages/api/src/controller/user.controller.ts +57 -0
  237. package/template/packages/api/src/dto/auth.dto.ts +30 -0
  238. package/template/packages/api/src/dto/cache.dto.ts +24 -0
  239. package/template/packages/api/src/dto/menu.dto.ts +37 -0
  240. package/template/packages/api/src/dto/mq.dto.ts +16 -0
  241. package/template/packages/api/src/dto/role.dto.ts +16 -0
  242. package/template/packages/api/src/dto/user.dto.ts +35 -0
  243. package/template/packages/api/src/entity/menu.entity.ts +34 -0
  244. package/template/packages/api/src/entity/role-menu.entity.ts +13 -0
  245. package/template/packages/api/src/entity/role.entity.ts +22 -0
  246. package/template/packages/api/src/entity/user-role.entity.ts +13 -0
  247. package/template/packages/api/src/entity/user.entity.ts +31 -0
  248. package/template/packages/api/src/mapper/menu.mapper.ts +6 -0
  249. package/template/packages/api/src/mapper/role-menu.mapper.ts +6 -0
  250. package/template/packages/api/src/mapper/role.mapper.ts +6 -0
  251. package/template/packages/api/src/mapper/user-role.mapper.ts +6 -0
  252. package/template/packages/api/src/mapper/user.mapper.ts +11 -0
  253. package/template/packages/api/src/scripts/init-db.ts +185 -0
  254. package/template/packages/api/src/server.ts +76 -0
  255. package/template/packages/api/src/service/auth.service.ts +106 -0
  256. package/template/packages/api/src/service/cache.service.ts +80 -0
  257. package/template/packages/api/src/service/log.request.service.ts +158 -0
  258. package/template/packages/api/src/service/log.service.ts +123 -0
  259. package/template/packages/api/src/service/menu.service.ts +94 -0
  260. package/template/packages/api/src/service/mq.consumer.service.ts +26 -0
  261. package/template/packages/api/src/service/role.service.ts +88 -0
  262. package/template/packages/api/src/service/user.service.ts +170 -0
  263. package/template/packages/api/src/types/sqljs.d.ts +18 -0
  264. package/template/packages/api/src/utils/auth.utils.js +0 -0
  265. package/template/packages/api/src/utils/jwt.util.ts +29 -0
  266. package/template/packages/api/tsconfig.json +17 -0
  267. package/template/packages/api/tsup.config.ts +9 -0
  268. package/template/packages/api/uploads/.gitkeep +0 -0
  269. package/template/packages/core/package.json +31 -0
  270. package/template/packages/core/src/auth/auth-client-middleware.ts +22 -0
  271. package/template/packages/core/src/auth/auth-service.ts +65 -0
  272. package/template/packages/core/src/auth/default-auth-provider.ts +37 -0
  273. package/template/packages/core/src/auth/index.ts +10 -0
  274. package/template/packages/core/src/auth/types.ts +38 -0
  275. package/template/packages/core/src/authorization/authorization-client-middleware.ts +38 -0
  276. package/template/packages/core/src/authorization/authorization-config.ts +13 -0
  277. package/template/packages/core/src/authorization/authorization-provider.tsx +116 -0
  278. package/template/packages/core/src/authorization/default-authorization-provider.ts +26 -0
  279. package/template/packages/core/src/authorization/index.ts +15 -0
  280. package/template/packages/core/src/authorization/types.ts +42 -0
  281. package/template/packages/core/src/index.ts +3 -0
  282. package/template/packages/core/src/utils/promise-result-cache.ts +18 -0
  283. package/template/packages/core/tsconfig.json +19 -0
  284. package/template/packages/mobile/README.md +55 -0
  285. package/template/packages/mobile/index.html +13 -0
  286. package/template/packages/mobile/package.json +30 -0
  287. package/template/packages/mobile/postcss.config.mjs +7 -0
  288. package/template/packages/mobile/src/App.tsx +5 -0
  289. package/template/packages/mobile/src/app/globals.css +1 -0
  290. package/template/packages/mobile/src/components/LoginForm.tsx +76 -0
  291. package/template/packages/mobile/src/hooks/index.ts +5 -0
  292. package/template/packages/mobile/src/lib/utils.ts +7 -0
  293. package/template/packages/mobile/src/main.tsx +13 -0
  294. package/template/packages/mobile/src/pages/HomePage.tsx +35 -0
  295. package/template/packages/mobile/src/pages/LoginPage.tsx +35 -0
  296. package/template/packages/mobile/src/pages/index.ts +2 -0
  297. package/template/packages/mobile/src/routes/ProtectedRoute.tsx +29 -0
  298. package/template/packages/mobile/src/routes/index.tsx +24 -0
  299. package/template/packages/mobile/src/routes/routes.ts +11 -0
  300. package/template/packages/mobile/src/types/index.ts +5 -0
  301. package/template/packages/mobile/src/vite-env.d.ts +1 -0
  302. package/template/packages/mobile/tsconfig.json +23 -0
  303. package/template/packages/mobile/tsconfig.node.json +11 -0
  304. package/template/packages/mobile/vite.config.ts +19 -0
  305. package/template/packages/shared/package.json +20 -0
  306. package/template/packages/shared/src/constants.ts +8 -0
  307. package/template/packages/shared/src/index.ts +5 -0
  308. package/template/packages/shared/tsconfig.json +13 -0
  309. package/template/packages/shared-auth/package.json +29 -0
  310. package/template/packages/shared-auth/src/AuthContext.tsx +177 -0
  311. package/template/packages/shared-auth/src/AuthProviderWrapper.tsx +29 -0
  312. package/template/packages/shared-auth/src/index.ts +10 -0
  313. package/template/packages/shared-auth/tsconfig.json +14 -0
  314. package/template/pnpm-lock.yaml +16349 -0
  315. package/template/pnpm-workspace.yaml +3 -0
  316. package/template/scripts/postinstall.cjs +42 -0
  317. package/template/scripts/rebuild-sqlite.cjs +23 -0
@@ -0,0 +1,5 @@
1
+ import { AppRouter } from '@/routes';
2
+
3
+ export default function App() {
4
+ return <AppRouter />;
5
+ }
@@ -0,0 +1 @@
1
+ @import "tailwindcss";
@@ -0,0 +1,76 @@
1
+ import { useState } from 'react';
2
+ import { useAuth } from '@scaffold/shared-auth';
3
+
4
+ export function LoginForm() {
5
+ const [username, setUsername] = useState('');
6
+ const [password, setPassword] = useState('');
7
+ const { user, login, isLoading, error, setError } = useAuth();
8
+
9
+ const handleSubmit = async (e: React.FormEvent) => {
10
+ e.preventDefault();
11
+ setError(null);
12
+ try {
13
+ await login(username, password);
14
+ } catch (err: unknown) {
15
+ const msg = err instanceof Error ? err.message : '登录失败';
16
+ const isNetwork =
17
+ msg.includes('fetch') ||
18
+ msg.includes('Failed to fetch') ||
19
+ msg.includes('NetworkError') ||
20
+ msg.includes('CONNECTION_REFUSED');
21
+ if (isNetwork) {
22
+ setError('无法连接 API,请先在 scaffold 目录执行:pnpm dev:api');
23
+ }
24
+ }
25
+ };
26
+
27
+ return (
28
+ <div className="w-full max-w-sm rounded-lg bg-white p-6 shadow">
29
+ <h1 className="text-xl font-semibold text-gray-900 mb-4">登录</h1>
30
+ <form onSubmit={handleSubmit} className="space-y-4">
31
+ <div>
32
+ <label htmlFor="username" className="block text-sm font-medium text-gray-700 mb-1">
33
+ 用户名
34
+ </label>
35
+ <input
36
+ id="username"
37
+ type="text"
38
+ value={username}
39
+ onChange={(e) => setUsername(e.target.value)}
40
+ className="w-full rounded border border-gray-300 px-3 py-2 text-gray-900 focus:border-blue-500 focus:outline-none"
41
+ placeholder="admin"
42
+ autoComplete="username"
43
+ />
44
+ </div>
45
+ <div>
46
+ <label htmlFor="password" className="block text-sm font-medium text-gray-700 mb-1">
47
+ 密码
48
+ </label>
49
+ <input
50
+ id="password"
51
+ type="password"
52
+ value={password}
53
+ onChange={(e) => setPassword(e.target.value)}
54
+ className="w-full rounded border border-gray-300 px-3 py-2 text-gray-900 focus:border-blue-500 focus:outline-none"
55
+ placeholder="••••••••"
56
+ autoComplete="current-password"
57
+ />
58
+ </div>
59
+ {error && <p className="text-sm text-red-600">{error}</p>}
60
+ {user && (
61
+ <p className="text-sm text-green-600">
62
+ 登录成功:{user.username}({user.email})
63
+ </p>
64
+ )}
65
+ <button
66
+ type="submit"
67
+ disabled={isLoading}
68
+ className="w-full rounded bg-blue-600 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:opacity-50"
69
+ >
70
+ {isLoading ? '登录中...' : '登录'}
71
+ </button>
72
+ </form>
73
+ <p className="mt-4 text-xs text-gray-500">默认账号:admin / admin123</p>
74
+ </div>
75
+ );
76
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 自定义 Hooks
3
+ */
4
+
5
+ // 预留:如 useDebounce、useLocalStorage 等可在此导出
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 通用工具函数
3
+ */
4
+
5
+ export function cn(...classes: (string | undefined | null | false)[]): string {
6
+ return classes.filter(Boolean).join(' ');
7
+ }
@@ -0,0 +1,13 @@
1
+ import { StrictMode } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { AuthProviderWrapper } from '@scaffold/shared-auth';
4
+ import App from './App';
5
+ import './app/globals.css';
6
+
7
+ createRoot(document.getElementById('root')!).render(
8
+ <StrictMode>
9
+ <AuthProviderWrapper>
10
+ <App />
11
+ </AuthProviderWrapper>
12
+ </StrictMode>
13
+ );
@@ -0,0 +1,35 @@
1
+ import { useAuth } from '@scaffold/shared-auth';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import { ROUTES } from '@/routes/routes';
4
+
5
+ /**
6
+ * 移动端通用主页,展示产品名 AIKO-BOOT
7
+ */
8
+ export function HomePage() {
9
+ const { user, logout } = useAuth();
10
+ const navigate = useNavigate();
11
+
12
+ const handleLogout = () => {
13
+ logout();
14
+ navigate(ROUTES.LOGIN, { replace: true });
15
+ };
16
+
17
+ return (
18
+ <div className="min-h-screen bg-gray-50 flex flex-col">
19
+ <header className="flex items-center justify-between px-4 py-3 bg-white border-b border-gray-200 safe-area-top">
20
+ <span className="text-lg font-medium text-gray-800">AIKO-BOOT</span>
21
+ <button
22
+ type="button"
23
+ onClick={handleLogout}
24
+ className="text-sm text-gray-600 hover:text-gray-900"
25
+ >
26
+ 退出
27
+ </button>
28
+ </header>
29
+ <main className="flex-1 flex flex-col items-center justify-center px-4">
30
+ <h1 className="text-2xl font-semibold text-gray-900 mb-1">AIKO-BOOT</h1>
31
+ <p className="text-gray-500 text-sm">欢迎回来,{user?.username ?? ''}</p>
32
+ </main>
33
+ </div>
34
+ );
35
+ }
@@ -0,0 +1,35 @@
1
+ import { useEffect } from 'react';
2
+ import { useNavigate, useLocation } from 'react-router-dom';
3
+ import { useAuth } from '@scaffold/shared-auth';
4
+ import { LoginForm } from '@/components/LoginForm';
5
+ import { ROUTES } from '@/routes/routes';
6
+
7
+ /**
8
+ * 登录页:已登录则重定向到主页;登录成功后跳转到 from 或主页
9
+ */
10
+ export function LoginPage() {
11
+ const { user } = useAuth();
12
+ const navigate = useNavigate();
13
+ const location = useLocation();
14
+ const from = (location.state as { from?: { pathname: string } } | null)?.from?.pathname;
15
+
16
+ useEffect(() => {
17
+ if (user) {
18
+ navigate(from ?? ROUTES.HOME, { replace: true });
19
+ }
20
+ }, [user, navigate, from]);
21
+
22
+ if (user) {
23
+ return (
24
+ <div className="min-h-screen flex items-center justify-center bg-gray-50">
25
+ <span className="text-gray-500">正在跳转...</span>
26
+ </div>
27
+ );
28
+ }
29
+
30
+ return (
31
+ <main className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
32
+ <LoginForm />
33
+ </main>
34
+ );
35
+ }
@@ -0,0 +1,2 @@
1
+ export { LoginPage } from './LoginPage';
2
+ export { HomePage } from './HomePage';
@@ -0,0 +1,29 @@
1
+ import { Navigate, useLocation } from 'react-router-dom';
2
+ import { useAuth } from '@scaffold/shared-auth';
3
+ import { ROUTES } from './routes';
4
+
5
+ interface ProtectedRouteProps {
6
+ children: React.ReactNode;
7
+ }
8
+
9
+ /**
10
+ * 需登录才能访问的页面包装器,未登录时重定向到登录页并记录来自的路径
11
+ */
12
+ export function ProtectedRoute({ children }: ProtectedRouteProps) {
13
+ const { user, isLoading } = useAuth();
14
+ const location = useLocation();
15
+
16
+ if (isLoading) {
17
+ return (
18
+ <div className="min-h-screen flex items-center justify-center bg-gray-50">
19
+ <span className="text-gray-500">加载中...</span>
20
+ </div>
21
+ );
22
+ }
23
+
24
+ if (!user) {
25
+ return <Navigate to={ROUTES.LOGIN} state={{ from: location }} replace />;
26
+ }
27
+
28
+ return <>{children}</>;
29
+ }
@@ -0,0 +1,24 @@
1
+ import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
2
+ import { ProtectedRoute } from './ProtectedRoute';
3
+ import { LoginPage } from '@/pages/LoginPage';
4
+ import { HomePage } from '@/pages/HomePage';
5
+ import { ROUTES } from './routes';
6
+
7
+ export function AppRouter() {
8
+ return (
9
+ <BrowserRouter>
10
+ <Routes>
11
+ <Route path={ROUTES.LOGIN} element={<LoginPage />} />
12
+ <Route
13
+ path={ROUTES.HOME}
14
+ element={
15
+ <ProtectedRoute>
16
+ <HomePage />
17
+ </ProtectedRoute>
18
+ }
19
+ />
20
+ <Route path="*" element={<Navigate to={ROUTES.HOME} replace />} />
21
+ </Routes>
22
+ </BrowserRouter>
23
+ );
24
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 路由路径常量,统一维护便于引用与重定向
3
+ */
4
+ export const ROUTES = {
5
+ /** 登录页 */
6
+ LOGIN: '/login',
7
+ /** 主页(登录后) */
8
+ HOME: '/',
9
+ } as const;
10
+
11
+ export type RoutePath = (typeof ROUTES)[keyof typeof ROUTES];
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 全局类型定义
3
+ */
4
+
5
+ // 预留:页面或组件需要的公共类型可在此声明
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "resolveJsonModule": true,
11
+ "isolatedModules": true,
12
+ "noEmit": true,
13
+ "jsx": "react-jsx",
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "paths": {
19
+ "@/*": ["./src/*"]
20
+ }
21
+ },
22
+ "include": ["src"]
23
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true,
8
+ "strict": true
9
+ },
10
+ "include": ["vite.config.ts"]
11
+ }
@@ -0,0 +1,19 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+ import path from 'path';
4
+
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ resolve: {
8
+ alias: {
9
+ '@': path.resolve(__dirname, './src'),
10
+ },
11
+ },
12
+ server: {
13
+ port: 3002,
14
+ },
15
+ optimizeDeps: {
16
+ include: ['@scaffold/api/client', '@scaffold/shared'],
17
+ exclude: ['@scaffold/shared-auth'],
18
+ },
19
+ });
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@scaffold/shared",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "types": "./src/index.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./src/index.ts",
11
+ "types": "./src/index.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "lint": "eslint src"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^5.3.0"
19
+ }
20
+ }
@@ -0,0 +1,8 @@
1
+ /** API 基础 URL 环境变量 key(admin: VITE_API_URL, mobile: NEXT_PUBLIC_API_URL) */
2
+ export const API_BASE_URL_KEY = 'API_URL';
3
+
4
+ /** 默认 API 基础 URL */
5
+ export const DEFAULT_API_BASE_URL = 'http://localhost:3001';
6
+
7
+ /** 本地存储用户信息的 key,供 mobile/admin 鉴权模块统一使用 */
8
+ export const AUTH_STORAGE_KEY = 'scaffold_auth';
@@ -0,0 +1,5 @@
1
+ export {
2
+ API_BASE_URL_KEY,
3
+ DEFAULT_API_BASE_URL,
4
+ AUTH_STORAGE_KEY,
5
+ } from './constants';
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "declaration": true,
8
+ "outDir": "./dist",
9
+ "rootDir": "./src"
10
+ },
11
+ "include": ["src/**/*"],
12
+ "exclude": ["node_modules", "dist"]
13
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@scaffold/shared-auth",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "types": "./src/index.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./src/index.ts",
11
+ "types": "./src/index.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "lint": "eslint src"
16
+ },
17
+ "dependencies": {
18
+ "@scaffold/api": "workspace:*",
19
+ "@scaffold/shared": "workspace:*",
20
+ "react": "^19.2.3"
21
+ },
22
+ "devDependencies": {
23
+ "@types/react": "^19",
24
+ "typescript": "^5.3.0"
25
+ },
26
+ "peerDependencies": {
27
+ "react": "^18.0.0 || ^19.0.0"
28
+ }
29
+ }
@@ -0,0 +1,177 @@
1
+ 'use client';
2
+
3
+ import {
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useEffect,
8
+ useMemo,
9
+ useState,
10
+ type ReactNode,
11
+ } from 'react';
12
+ import { AuthApi } from '@scaffold/api/client';
13
+ import type { LoginResultDto } from '@scaffold/api/client';
14
+ import { AUTH_STORAGE_KEY } from '@scaffold/shared';
15
+
16
+ /** 登录接口可能返回的 token 字段(JWT / OAuth2 常见形态),与 LoginResultDto 兼容 */
17
+ export type AuthLoginResult = LoginResultDto & {
18
+ accessToken?: string;
19
+ refreshToken?: string;
20
+ /** 有效时长(秒),前端可据此算 expiresAt */
21
+ expiresIn?: number;
22
+ };
23
+
24
+ /** 持久化结构:user 必选,token 相关可选;无 token 时与仅存 user 的旧格式兼容 */
25
+ export interface StoredAuth {
26
+ user: LoginResultDto;
27
+ accessToken?: string;
28
+ refreshToken?: string;
29
+ /** 毫秒时间戳,accessToken 过期时间 */
30
+ expiresAt?: number;
31
+ }
32
+
33
+ export interface AuthState {
34
+ user: LoginResultDto | null;
35
+ /** 当前 accessToken(有则可用于 getAuthHeaders,兼容 JWT/OAuth2) */
36
+ accessToken: string | null;
37
+ isLoading: boolean;
38
+ error: string | null;
39
+ }
40
+
41
+ export interface AuthContextValue extends AuthState {
42
+ login: (username: string, password: string) => Promise<void>;
43
+ logout: () => void;
44
+ setError: (error: string | null) => void;
45
+ /** 供请求封装注入鉴权头:有 accessToken 时返回 { Authorization: 'Bearer <token>' },否则 {} */
46
+ getAuthHeaders: () => Record<string, string>;
47
+ }
48
+
49
+ const AuthContext = createContext<AuthContextValue | null>(null);
50
+
51
+ function readStoredAuth(): StoredAuth | null {
52
+ if (typeof window === 'undefined') return null;
53
+ try {
54
+ const raw = localStorage.getItem(AUTH_STORAGE_KEY);
55
+ if (!raw) return null;
56
+ const data = JSON.parse(raw) as Partial<StoredAuth>;
57
+ if (!data?.user) return null;
58
+ return {
59
+ user: data.user,
60
+ accessToken: data.accessToken,
61
+ refreshToken: data.refreshToken,
62
+ expiresAt: data.expiresAt,
63
+ };
64
+ } catch {
65
+ return null;
66
+ }
67
+ }
68
+
69
+ function writeStoredAuth(stored: StoredAuth | null): void {
70
+ if (typeof window === 'undefined') return;
71
+ try {
72
+ if (stored?.user) {
73
+ localStorage.setItem(AUTH_STORAGE_KEY, JSON.stringify(stored));
74
+ } else {
75
+ localStorage.removeItem(AUTH_STORAGE_KEY);
76
+ }
77
+ } catch (error) {
78
+ if (process.env.NODE_ENV !== 'production') {
79
+ // eslint-disable-next-line no-console
80
+ console.error('[AuthContext] Failed to write auth to storage', error);
81
+ }
82
+ }
83
+ }
84
+
85
+ export interface AuthProviderProps {
86
+ apiBaseUrl: string;
87
+ children: ReactNode;
88
+ }
89
+
90
+ export function AuthProvider({ apiBaseUrl, children }: AuthProviderProps) {
91
+ const [user, setUser] = useState<LoginResultDto | null>(null);
92
+ const [accessToken, setAccessToken] = useState<string | null>(null);
93
+ const [isLoading, setIsLoading] = useState(false);
94
+ const [error, setError] = useState<string | null>(null);
95
+ const [hydrated, setHydrated] = useState(false);
96
+
97
+ const authApi = useMemo(() => new AuthApi(apiBaseUrl), [apiBaseUrl]);
98
+
99
+ useEffect(() => {
100
+ const stored = readStoredAuth();
101
+ if (stored) {
102
+ setUser(stored.user);
103
+ setAccessToken(stored.accessToken ?? null);
104
+ }
105
+ setHydrated(true);
106
+ }, []);
107
+
108
+ const login = useCallback(
109
+ async (username: string, password: string) => {
110
+ setError(null);
111
+ setIsLoading(true);
112
+ try {
113
+ const data = (await authApi.login({ username, password })) as AuthLoginResult;
114
+ const userInfo: LoginResultDto = {
115
+ id: data.id,
116
+ username: data.username,
117
+ email: data.email,
118
+ };
119
+ const expiresAt = data.expiresIn
120
+ ? Date.now() + data.expiresIn * 1000
121
+ : undefined;
122
+ const stored: StoredAuth = {
123
+ user: userInfo,
124
+ ...(data.accessToken && { accessToken: data.accessToken }),
125
+ ...(data.refreshToken && { refreshToken: data.refreshToken }),
126
+ ...(expiresAt !== undefined && { expiresAt }),
127
+ };
128
+ setUser(userInfo);
129
+ setAccessToken(data.accessToken ?? null);
130
+ writeStoredAuth(stored);
131
+ } catch (err: unknown) {
132
+ const msg = err instanceof Error ? err.message : '登录失败';
133
+ setError(msg);
134
+ throw err;
135
+ } finally {
136
+ setIsLoading(false);
137
+ }
138
+ },
139
+ [authApi]
140
+ );
141
+
142
+ const logout = useCallback(() => {
143
+ setUser(null);
144
+ setAccessToken(null);
145
+ setError(null);
146
+ writeStoredAuth(null);
147
+ }, []);
148
+
149
+ const getAuthHeaders = useCallback((): Record<string, string> => {
150
+ const token = hydrated ? accessToken : null;
151
+ return token ? { Authorization: `Bearer ${token}` } : {};
152
+ }, [accessToken, hydrated]);
153
+
154
+ const value = useMemo<AuthContextValue>(
155
+ () => ({
156
+ user: hydrated ? user : null,
157
+ accessToken: hydrated ? accessToken : null,
158
+ isLoading,
159
+ error,
160
+ login,
161
+ logout,
162
+ setError,
163
+ getAuthHeaders,
164
+ }),
165
+ [user, accessToken, hydrated, isLoading, error, login, logout, getAuthHeaders]
166
+ );
167
+
168
+ return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
169
+ }
170
+
171
+ export function useAuth(): AuthContextValue {
172
+ const ctx = useContext(AuthContext);
173
+ if (ctx == null) {
174
+ throw new Error('useAuth must be used within AuthProvider');
175
+ }
176
+ return ctx;
177
+ }
@@ -0,0 +1,29 @@
1
+ import { AuthProvider } from './AuthContext';
2
+ import { DEFAULT_API_BASE_URL } from '@scaffold/shared';
3
+
4
+ function getApiBaseUrl(): string {
5
+ try {
6
+ if (typeof import.meta === 'undefined') return DEFAULT_API_BASE_URL;
7
+ const meta = import.meta as { env?: { VITE_API_URL?: string } };
8
+ const url = meta.env?.VITE_API_URL;
9
+ if (url) return url;
10
+ } catch {
11
+ // ignore
12
+ }
13
+ return DEFAULT_API_BASE_URL;
14
+ }
15
+
16
+ export interface AuthProviderWrapperProps {
17
+ children: React.ReactNode;
18
+ /** 可选:覆盖从环境变量读取的 API 基础 URL */
19
+ apiBaseUrl?: string;
20
+ }
21
+
22
+ /**
23
+ * 为应用根节点提供鉴权 Context,API 地址从 VITE_API_URL 或 shared 默认值读取。
24
+ * admin / mobile 可直接使用,无需各自维护一份。
25
+ */
26
+ export function AuthProviderWrapper({ children, apiBaseUrl }: AuthProviderWrapperProps) {
27
+ const baseUrl = apiBaseUrl ?? getApiBaseUrl();
28
+ return <AuthProvider apiBaseUrl={baseUrl}>{children}</AuthProvider>;
29
+ }
@@ -0,0 +1,10 @@
1
+ export {
2
+ AuthProvider,
3
+ useAuth,
4
+ type AuthState,
5
+ type AuthContextValue,
6
+ type AuthProviderProps,
7
+ type AuthLoginResult,
8
+ type StoredAuth,
9
+ } from './AuthContext';
10
+ export { AuthProviderWrapper, type AuthProviderWrapperProps } from './AuthProviderWrapper';
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "jsx": "react-jsx",
8
+ "declaration": true,
9
+ "outDir": "./dist",
10
+ "rootDir": "./src"
11
+ },
12
+ "include": ["src/**/*"],
13
+ "exclude": ["node_modules", "dist"]
14
+ }