@qlover/create-app 0.7.14 → 0.8.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 (361) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/configs/_common/.gitignore.template +6 -0
  3. package/dist/configs/_common/.prettierignore +17 -5
  4. package/dist/configs/_common/.vscode/settings.json +6 -1
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/templates/next-app/.env.template +1 -1
  8. package/dist/templates/next-app/README.en.md +130 -0
  9. package/dist/templates/next-app/README.md +114 -20
  10. package/dist/templates/next-app/config/Identifier/api.ts +5 -5
  11. package/dist/templates/next-app/config/Identifier/common/admint.table.ts +69 -0
  12. package/dist/templates/next-app/config/Identifier/common/common.ts +76 -0
  13. package/dist/templates/next-app/config/Identifier/common/index.ts +3 -0
  14. package/dist/templates/next-app/config/Identifier/{validator.ts → common/validators.ts} +5 -5
  15. package/dist/templates/next-app/config/Identifier/index.ts +2 -12
  16. package/dist/templates/next-app/config/Identifier/pages/index.ts +6 -0
  17. package/dist/templates/next-app/config/Identifier/pages/page.admin.home.ts +27 -0
  18. package/dist/templates/next-app/config/Identifier/pages/page.admin.locales.ts +266 -0
  19. package/dist/templates/next-app/config/Identifier/pages/page.admin.user.ts +293 -0
  20. package/dist/templates/{react-app/config/Identifier → next-app/config/Identifier/pages}/page.home.ts +15 -22
  21. package/dist/templates/next-app/config/Identifier/{page.login.ts → pages/page.login.ts} +28 -34
  22. package/dist/templates/next-app/config/Identifier/{page.register.ts → pages/page.register.ts} +30 -29
  23. package/dist/templates/next-app/config/adminNavs.ts +19 -0
  24. package/dist/templates/next-app/config/common.ts +22 -13
  25. package/dist/templates/next-app/config/i18n/HomeI18n.ts +5 -5
  26. package/dist/templates/next-app/config/i18n/admin18n.ts +61 -19
  27. package/dist/templates/next-app/config/i18n/i18nConfig.ts +2 -0
  28. package/dist/templates/next-app/config/i18n/i18nKeyScheam.ts +36 -0
  29. package/dist/templates/next-app/config/i18n/loginI18n.ts +22 -22
  30. package/dist/templates/next-app/config/i18n/register18n.ts +23 -24
  31. package/dist/templates/next-app/docs/en/api.md +387 -0
  32. package/dist/templates/next-app/docs/en/component.md +544 -0
  33. package/dist/templates/next-app/docs/en/database.md +496 -0
  34. package/dist/templates/next-app/docs/en/development-guide.md +727 -0
  35. package/dist/templates/next-app/docs/en/env.md +563 -0
  36. package/dist/templates/next-app/docs/en/i18n.md +287 -0
  37. package/dist/templates/next-app/docs/en/index.md +165 -0
  38. package/dist/templates/next-app/docs/en/page.md +457 -0
  39. package/dist/templates/next-app/docs/en/project-structure.md +176 -0
  40. package/dist/templates/next-app/docs/en/router.md +427 -0
  41. package/dist/templates/next-app/docs/en/theme.md +532 -0
  42. package/dist/templates/next-app/docs/en/validator.md +478 -0
  43. package/dist/templates/next-app/docs/zh/api.md +387 -0
  44. package/dist/templates/next-app/docs/zh/component.md +544 -0
  45. package/dist/templates/next-app/docs/zh/database.md +496 -0
  46. package/dist/templates/next-app/docs/zh/development-guide.md +727 -0
  47. package/dist/templates/next-app/docs/zh/env.md +563 -0
  48. package/dist/templates/next-app/docs/zh/i18n.md +287 -0
  49. package/dist/templates/next-app/docs/zh/index.md +165 -0
  50. package/dist/templates/next-app/docs/zh/page.md +457 -0
  51. package/dist/templates/next-app/docs/zh/project-structure.md +176 -0
  52. package/dist/templates/next-app/docs/zh/router.md +427 -0
  53. package/dist/templates/next-app/docs/zh/theme.md +532 -0
  54. package/dist/templates/next-app/docs/zh/validator.md +476 -0
  55. package/dist/templates/next-app/make/generateLocales.ts +19 -12
  56. package/dist/templates/next-app/migrations/schema/LocalesSchema.ts +15 -0
  57. package/dist/templates/next-app/migrations/sql/1694244000000.sql +11 -0
  58. package/dist/templates/next-app/package.json +7 -3
  59. package/dist/templates/next-app/public/locales/en.json +172 -207
  60. package/dist/templates/next-app/public/locales/zh.json +172 -207
  61. package/dist/templates/next-app/src/app/[locale]/admin/locales/page.tsx +153 -0
  62. package/dist/templates/next-app/src/app/[locale]/admin/users/page.tsx +48 -50
  63. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +2 -2
  64. package/dist/templates/next-app/src/app/api/admin/locales/create/route.ts +34 -0
  65. package/dist/templates/next-app/src/app/api/admin/locales/import/route.ts +40 -0
  66. package/dist/templates/next-app/src/app/api/admin/locales/route.ts +42 -0
  67. package/dist/templates/next-app/src/app/api/admin/locales/update/route.ts +32 -0
  68. package/dist/templates/next-app/src/app/api/locales/json/route.ts +44 -0
  69. package/dist/templates/next-app/src/base/cases/AdminPageManager.ts +1 -13
  70. package/dist/templates/next-app/src/base/cases/Datetime.ts +18 -0
  71. package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +12 -6
  72. package/dist/templates/next-app/src/base/cases/ResourceState.ts +17 -0
  73. package/dist/templates/next-app/src/base/cases/TranslateI18nInterface.ts +25 -0
  74. package/dist/templates/next-app/src/base/cases/ZodColumnBuilder.ts +200 -0
  75. package/dist/templates/next-app/src/base/port/ZodBuilderInterface.ts +8 -0
  76. package/dist/templates/next-app/src/base/services/AdminLocalesService.ts +20 -0
  77. package/dist/templates/next-app/src/base/services/AdminPageEvent.ts +26 -0
  78. package/dist/templates/next-app/src/base/services/AdminPageScheduler.ts +42 -0
  79. package/dist/templates/next-app/src/base/services/ResourceService.ts +122 -0
  80. package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +104 -0
  81. package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +38 -5
  82. package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +1 -1
  83. package/dist/templates/next-app/src/i18n/request.ts +30 -1
  84. package/dist/templates/next-app/src/server/PageParams.ts +2 -10
  85. package/dist/templates/next-app/src/server/port/DBBridgeInterface.ts +5 -0
  86. package/dist/templates/next-app/src/server/port/DBTableInterface.ts +2 -0
  87. package/dist/templates/next-app/src/server/port/LocalesRepositoryInterface.ts +43 -0
  88. package/dist/templates/next-app/src/server/repositorys/LocalesRepository.ts +197 -0
  89. package/dist/templates/next-app/src/server/services/ApiLocaleService.ts +122 -0
  90. package/dist/templates/next-app/src/server/sqlBridges/SupabaseBridge.ts +60 -11
  91. package/dist/templates/next-app/src/server/validators/ExtendedExecutorError.ts +6 -0
  92. package/dist/templates/next-app/src/server/validators/LocalesValidator.ts +131 -0
  93. package/dist/templates/next-app/src/server/validators/LoginValidator.ts +2 -5
  94. package/dist/templates/next-app/src/server/validators/PaginationValidator.ts +32 -16
  95. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/_default.css +2 -1
  96. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/dark.css +28 -29
  97. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/pink.css +2 -1
  98. package/dist/templates/next-app/src/uikit/components/AdminLayout.tsx +17 -3
  99. package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +5 -4
  100. package/dist/templates/next-app/src/uikit/components/BaseLayout.tsx +5 -4
  101. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +3 -2
  102. package/dist/templates/next-app/src/uikit/components/ComboProvider.tsx +1 -1
  103. package/dist/templates/next-app/src/uikit/components/EditableCell.tsx +118 -0
  104. package/dist/templates/next-app/src/uikit/components/LogoutButton.tsx +5 -6
  105. package/dist/templates/next-app/src/uikit/components/ThemeSwitcher.tsx +1 -1
  106. package/dist/templates/next-app/src/uikit/components/With.tsx +2 -2
  107. package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportButton.tsx +62 -0
  108. package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportEvent.ts +28 -0
  109. package/dist/templates/next-app/src/uikit/components/localesImportButton/import.module.css +6 -0
  110. package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +8 -14
  111. package/dist/templates/next-app/src/uikit/hook/useWarnTranslations.ts +25 -0
  112. package/dist/templates/react-app/.prettierignore +17 -0
  113. package/dist/templates/react-app/README.en.md +71 -54
  114. package/dist/templates/react-app/README.md +35 -18
  115. package/dist/templates/react-app/__tests__/__mocks__/BootstrapTest.ts +14 -0
  116. package/dist/templates/react-app/__tests__/__mocks__/MockAppConfit.ts +1 -1
  117. package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +2 -2
  118. package/dist/templates/react-app/__tests__/__mocks__/MockLogger.ts +1 -1
  119. package/dist/templates/react-app/__tests__/__mocks__/components/TestApp.tsx +45 -0
  120. package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +34 -0
  121. package/dist/templates/react-app/__tests__/__mocks__/components/TestRouter.tsx +46 -0
  122. package/dist/templates/react-app/__tests__/__mocks__/components/index.ts +12 -0
  123. package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +1 -2
  124. package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOC.ts +51 -0
  125. package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +69 -0
  126. package/dist/templates/react-app/__tests__/setup/index.ts +1 -51
  127. package/dist/templates/react-app/__tests__/setup/setupGlobal.ts +51 -0
  128. package/dist/templates/react-app/__tests__/src/App.structure.test.tsx +115 -0
  129. package/dist/templates/react-app/__tests__/src/base/cases/AppConfig.test.ts +2 -2
  130. package/dist/templates/react-app/__tests__/src/base/cases/AppError.test.ts +1 -1
  131. package/dist/templates/react-app/__tests__/src/base/cases/DialogHandler.test.ts +3 -5
  132. package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +13 -2
  133. package/dist/templates/react-app/__tests__/src/base/cases/InversifyContainer.test.ts +1 -1
  134. package/dist/templates/react-app/__tests__/src/base/cases/PublicAssetsPath.test.ts +1 -1
  135. package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +5 -5
  136. package/dist/templates/react-app/__tests__/src/base/cases/RequestStatusCatcher.test.ts +1 -2
  137. package/dist/templates/react-app/__tests__/src/base/cases/RouterLoader.test.ts +25 -15
  138. package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +29 -15
  139. package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +19 -9
  140. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +153 -0
  141. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +9 -7
  142. package/dist/templates/react-app/__tests__/src/main.integration.test.tsx +4 -5
  143. package/dist/templates/react-app/__tests__/src/main.test.tsx +4 -4
  144. package/dist/templates/react-app/__tests__/src/uikit/components/BaseHeader.test.tsx +68 -59
  145. package/dist/templates/react-app/config/IOCIdentifier.ts +8 -8
  146. package/dist/templates/react-app/config/Identifier/{common.error.ts → common/common.error.ts} +5 -5
  147. package/dist/templates/react-app/config/Identifier/{common.ts → common/common.ts} +9 -9
  148. package/dist/templates/react-app/config/Identifier/common/index.ts +2 -0
  149. package/dist/templates/react-app/config/Identifier/index.ts +1 -9
  150. package/dist/templates/react-app/config/Identifier/pages/index.ts +8 -0
  151. package/dist/templates/react-app/config/Identifier/{page.about.ts → pages/page.about.ts} +34 -26
  152. package/dist/templates/react-app/config/Identifier/{page.executor.ts → pages/page.executor.ts} +47 -39
  153. package/dist/templates/{next-app/config/Identifier → react-app/config/Identifier/pages}/page.home.ts +24 -23
  154. package/dist/templates/react-app/config/Identifier/pages/page.identifiter.ts +102 -0
  155. package/dist/templates/react-app/config/Identifier/{page.jsonStorage.ts → pages/page.jsonStorage.ts} +18 -11
  156. package/dist/templates/react-app/config/Identifier/{page.login.ts → pages/page.login.ts} +37 -27
  157. package/dist/templates/react-app/config/Identifier/{page.register.ts → pages/page.register.ts} +37 -25
  158. package/dist/templates/react-app/config/Identifier/{page.request.ts → pages/page.request.ts} +34 -44
  159. package/dist/templates/react-app/config/app.router.ts +66 -69
  160. package/dist/templates/react-app/config/i18n/PageI18nInterface.ts +51 -0
  161. package/dist/templates/react-app/config/i18n/aboutI18n.ts +42 -0
  162. package/dist/templates/react-app/config/i18n/executorI18n.ts +51 -0
  163. package/dist/templates/react-app/config/i18n/homeI18n.ts +24 -0
  164. package/dist/templates/react-app/config/i18n/i18nConfig.ts +30 -0
  165. package/dist/templates/react-app/config/i18n/identifiter18n.ts +30 -0
  166. package/dist/templates/react-app/config/i18n/jsonStorage18n.ts +27 -0
  167. package/dist/templates/react-app/config/i18n/login18n.ts +42 -0
  168. package/dist/templates/react-app/config/i18n/notFoundI18n.ts +34 -0
  169. package/dist/templates/react-app/config/i18n/register18n.ts +40 -0
  170. package/dist/templates/react-app/config/i18n/request18n.ts +41 -0
  171. package/dist/templates/react-app/config/theme.ts +14 -4
  172. package/dist/templates/react-app/docs/en/bootstrap.md +1670 -341
  173. package/dist/templates/react-app/docs/en/development-guide.md +1021 -345
  174. package/dist/templates/react-app/docs/en/env.md +1132 -278
  175. package/dist/templates/react-app/docs/en/i18n.md +858 -147
  176. package/dist/templates/react-app/docs/en/index.md +733 -104
  177. package/dist/templates/react-app/docs/en/ioc.md +1228 -287
  178. package/dist/templates/react-app/docs/en/playwright/e2e-tests.md +321 -0
  179. package/dist/templates/react-app/docs/en/playwright/index.md +19 -0
  180. package/dist/templates/react-app/docs/en/playwright/installation-summary.md +332 -0
  181. package/dist/templates/react-app/docs/en/playwright/overview.md +222 -0
  182. package/dist/templates/react-app/docs/en/playwright/quickstart.md +325 -0
  183. package/dist/templates/react-app/docs/en/playwright/reorganization-notes.md +340 -0
  184. package/dist/templates/react-app/docs/en/playwright/setup-complete.md +290 -0
  185. package/dist/templates/react-app/docs/en/playwright/testing-guide.md +565 -0
  186. package/dist/templates/react-app/docs/en/store.md +1194 -184
  187. package/dist/templates/react-app/docs/en/why-no-globals.md +797 -0
  188. package/dist/templates/react-app/docs/zh/bootstrap.md +1670 -341
  189. package/dist/templates/react-app/docs/zh/development-guide.md +1021 -345
  190. package/dist/templates/react-app/docs/zh/env.md +1132 -275
  191. package/dist/templates/react-app/docs/zh/i18n.md +858 -147
  192. package/dist/templates/react-app/docs/zh/index.md +717 -104
  193. package/dist/templates/react-app/docs/zh/ioc.md +1229 -287
  194. package/dist/templates/react-app/docs/zh/playwright/e2e-tests.md +321 -0
  195. package/dist/templates/react-app/docs/zh/playwright/index.md +19 -0
  196. package/dist/templates/react-app/docs/zh/playwright/installation-summary.md +332 -0
  197. package/dist/templates/react-app/docs/zh/playwright/overview.md +222 -0
  198. package/dist/templates/react-app/docs/zh/playwright/quickstart.md +325 -0
  199. package/dist/templates/react-app/docs/zh/playwright/reorganization-notes.md +340 -0
  200. package/dist/templates/react-app/docs/zh/playwright/setup-complete.md +290 -0
  201. package/dist/templates/react-app/docs/zh/playwright/testing-guide.md +565 -0
  202. package/dist/templates/react-app/docs/zh/store.md +1192 -184
  203. package/dist/templates/react-app/docs/zh/why-no-globals.md +797 -0
  204. package/dist/templates/react-app/e2e/App.spec.ts +319 -0
  205. package/dist/templates/react-app/e2e/fixtures/base.fixture.ts +40 -0
  206. package/dist/templates/react-app/e2e/main.spec.ts +20 -0
  207. package/dist/templates/react-app/e2e/utils/test-helpers.ts +19 -0
  208. package/dist/templates/react-app/eslint.config.mjs +247 -0
  209. package/dist/templates/react-app/makes/eslint-utils.mjs +195 -0
  210. package/dist/templates/react-app/makes/generateTs2LocalesOptions.ts +26 -0
  211. package/dist/templates/react-app/package.json +31 -3
  212. package/dist/templates/react-app/playwright.config.ts +79 -0
  213. package/dist/templates/react-app/public/locales/en/common.json +190 -179
  214. package/dist/templates/react-app/public/locales/zh/common.json +190 -179
  215. package/dist/templates/react-app/src/App.tsx +15 -42
  216. package/dist/templates/react-app/src/base/apis/AiApi.ts +5 -5
  217. package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +1 -1
  218. package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +1 -1
  219. package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +8 -8
  220. package/dist/templates/react-app/src/base/apis/feApi/FeApiType.ts +1 -1
  221. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +6 -6
  222. package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +1 -1
  223. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +12 -14
  224. package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +1 -1
  225. package/dist/templates/react-app/src/base/cases/DialogHandler.ts +5 -2
  226. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +3 -3
  227. package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +3 -3
  228. package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +2 -2
  229. package/dist/templates/react-app/src/base/cases/RequestLogger.ts +4 -4
  230. package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +1 -1
  231. package/dist/templates/react-app/src/base/cases/ResourceState.ts +23 -0
  232. package/dist/templates/react-app/src/base/cases/RouterLoader.ts +4 -4
  233. package/dist/templates/react-app/src/base/cases/TranslateI18nInterface.ts +26 -0
  234. package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +2 -3
  235. package/dist/templates/react-app/src/base/port/I18nServiceInterface.ts +1 -1
  236. package/dist/templates/react-app/src/base/port/IOCInterface.ts +36 -0
  237. package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +2 -1
  238. package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +1 -1
  239. package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +2 -2
  240. package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +9 -5
  241. package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +1 -1
  242. package/dist/templates/react-app/src/base/services/I18nService.ts +29 -29
  243. package/dist/templates/react-app/src/base/services/IdentifierService.ts +143 -0
  244. package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +3 -3
  245. package/dist/templates/react-app/src/base/services/RouteService.ts +27 -8
  246. package/dist/templates/react-app/src/base/services/UserService.ts +8 -8
  247. package/dist/templates/react-app/src/base/types/Page.ts +14 -2
  248. package/dist/templates/react-app/src/base/types/global.d.ts +1 -1
  249. package/dist/templates/react-app/src/core/IOC.ts +5 -46
  250. package/dist/templates/react-app/src/core/bootstraps/{BootstrapApp.ts → BootstrapClient.ts} +44 -17
  251. package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +14 -7
  252. package/dist/templates/react-app/src/core/bootstraps/IocIdentifierTest.ts +1 -1
  253. package/dist/templates/react-app/src/core/bootstraps/PrintBootstrap.ts +1 -1
  254. package/dist/templates/react-app/src/core/clientIoc/ClientIOC.ts +40 -0
  255. package/dist/templates/react-app/src/core/{IocRegisterImpl.ts → clientIoc/ClientIOCRegister.ts} +35 -24
  256. package/dist/templates/react-app/src/core/globals.ts +9 -9
  257. package/dist/templates/react-app/src/main.tsx +4 -4
  258. package/dist/templates/react-app/src/pages/404.tsx +6 -3
  259. package/dist/templates/react-app/src/pages/500.tsx +5 -2
  260. package/dist/templates/react-app/src/pages/NoRouteFound.tsx +5 -0
  261. package/dist/templates/react-app/src/pages/auth/Layout.tsx +9 -6
  262. package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +46 -56
  263. package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +46 -58
  264. package/dist/templates/react-app/src/pages/base/AboutPage.tsx +35 -40
  265. package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +51 -51
  266. package/dist/templates/react-app/src/pages/base/HomePage.tsx +14 -15
  267. package/dist/templates/react-app/src/pages/base/IdentifierPage.tsx +70 -11
  268. package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +24 -25
  269. package/dist/templates/react-app/src/pages/base/Layout.tsx +2 -2
  270. package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +3 -2
  271. package/dist/templates/react-app/src/pages/base/RequestPage.tsx +41 -59
  272. package/dist/templates/react-app/src/styles/css/antd-themes/{_default.css → _common/_default.css} +85 -0
  273. package/dist/templates/react-app/src/styles/css/antd-themes/{dark.css → _common/dark.css} +99 -0
  274. package/dist/templates/react-app/src/styles/css/antd-themes/_common/index.css +3 -0
  275. package/dist/templates/react-app/src/styles/css/antd-themes/{pink.css → _common/pink.css} +86 -0
  276. package/dist/templates/react-app/src/styles/css/antd-themes/index.css +4 -3
  277. package/dist/templates/react-app/src/styles/css/antd-themes/menu/_default.css +108 -0
  278. package/dist/templates/react-app/src/styles/css/antd-themes/menu/dark.css +67 -0
  279. package/dist/templates/react-app/src/styles/css/antd-themes/menu/index.css +3 -0
  280. package/dist/templates/react-app/src/styles/css/antd-themes/menu/pink.css +67 -0
  281. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/_default.css +34 -0
  282. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/dark.css +31 -0
  283. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/index.css +3 -0
  284. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/pink.css +36 -0
  285. package/dist/templates/react-app/src/styles/css/antd-themes/table/_default.css +44 -0
  286. package/dist/templates/react-app/src/styles/css/antd-themes/table/dark.css +43 -0
  287. package/dist/templates/react-app/src/styles/css/antd-themes/table/index.css +3 -0
  288. package/dist/templates/react-app/src/styles/css/antd-themes/table/pink.css +43 -0
  289. package/dist/templates/react-app/src/styles/css/page.css +4 -3
  290. package/dist/templates/react-app/src/styles/css/themes/_default.css +1 -0
  291. package/dist/templates/react-app/src/styles/css/themes/dark.css +1 -0
  292. package/dist/templates/react-app/src/styles/css/themes/pink.css +1 -0
  293. package/dist/templates/react-app/src/styles/css/zIndex.css +1 -1
  294. package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +3 -3
  295. package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +2 -2
  296. package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +1 -1
  297. package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +3 -3
  298. package/dist/templates/react-app/src/uikit/components/AppRouterProvider.tsx +35 -0
  299. package/dist/templates/react-app/src/uikit/components/BaseHeader.tsx +15 -11
  300. package/dist/templates/react-app/src/uikit/components/BaseRouteProvider.tsx +14 -11
  301. package/dist/templates/react-app/src/uikit/components/BaseRouteSeo.tsx +18 -0
  302. package/dist/templates/react-app/src/uikit/components/BootstrapsProvider.tsx +13 -0
  303. package/dist/templates/react-app/src/uikit/components/ClientSeo.tsx +62 -0
  304. package/dist/templates/react-app/src/uikit/components/ComboProvider.tsx +38 -0
  305. package/dist/templates/react-app/src/uikit/components/LanguageSwitcher.tsx +48 -27
  306. package/dist/templates/react-app/src/uikit/components/Loading.tsx +4 -2
  307. package/dist/templates/react-app/src/uikit/components/LocaleLink.tsx +4 -5
  308. package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +34 -11
  309. package/dist/templates/react-app/src/uikit/components/ProcessExecutorProvider.tsx +9 -5
  310. package/dist/templates/react-app/src/uikit/components/RouterRenderComponent.tsx +6 -3
  311. package/dist/templates/react-app/src/uikit/components/ThemeSwitcher.tsx +97 -40
  312. package/dist/templates/react-app/src/uikit/components/UserAuthProvider.tsx +5 -5
  313. package/dist/templates/react-app/src/uikit/components/With.tsx +17 -0
  314. package/dist/templates/react-app/src/uikit/contexts/BaseRouteContext.ts +17 -11
  315. package/dist/templates/react-app/src/uikit/contexts/IOCContext.ts +13 -0
  316. package/dist/templates/react-app/src/uikit/hooks/useAppTranslation.ts +26 -0
  317. package/dist/templates/react-app/src/uikit/hooks/useI18nGuard.ts +8 -11
  318. package/dist/templates/react-app/src/uikit/hooks/useI18nInterface.ts +25 -0
  319. package/dist/templates/react-app/src/uikit/hooks/useIOC.ts +35 -0
  320. package/dist/templates/react-app/src/uikit/hooks/useNavigateBridge.ts +3 -3
  321. package/dist/templates/react-app/src/uikit/hooks/useStrictEffect.ts +0 -1
  322. package/dist/templates/react-app/tsconfig.e2e.json +21 -0
  323. package/dist/templates/react-app/tsconfig.json +8 -1
  324. package/dist/templates/react-app/tsconfig.node.json +1 -1
  325. package/dist/templates/react-app/tsconfig.test.json +3 -1
  326. package/dist/templates/react-app/vite.config.ts +50 -34
  327. package/package.json +2 -1
  328. package/dist/configs/react-app/eslint.config.js +0 -94
  329. package/dist/templates/next-app/config/Identifier/common.error.ts +0 -41
  330. package/dist/templates/next-app/config/Identifier/common.ts +0 -69
  331. package/dist/templates/next-app/config/Identifier/page.about.ts +0 -181
  332. package/dist/templates/next-app/config/Identifier/page.admin.ts +0 -48
  333. package/dist/templates/next-app/config/Identifier/page.executor.ts +0 -272
  334. package/dist/templates/next-app/config/Identifier/page.identifiter.ts +0 -39
  335. package/dist/templates/next-app/config/Identifier/page.jsonStorage.ts +0 -72
  336. package/dist/templates/next-app/config/Identifier/page.request.ts +0 -182
  337. package/dist/templates/next-app/docs/env.md +0 -94
  338. package/dist/templates/next-app/src/base/cases/ChatAction.ts +0 -21
  339. package/dist/templates/next-app/src/base/cases/FocusBarAction.ts +0 -36
  340. package/dist/templates/next-app/src/base/cases/RequestState.ts +0 -20
  341. package/dist/templates/next-app/src/base/port/AdminPageInterface.ts +0 -85
  342. package/dist/templates/next-app/src/base/port/AsyncStateInterface.ts +0 -7
  343. package/dist/templates/next-app/src/base/services/AdminUserService.ts +0 -45
  344. package/dist/templates/next-app/src/uikit/components/ChatRoot.tsx +0 -17
  345. package/dist/templates/next-app/src/uikit/components/chat/ChatActionInterface.ts +0 -30
  346. package/dist/templates/next-app/src/uikit/components/chat/ChatFocusBar.tsx +0 -65
  347. package/dist/templates/next-app/src/uikit/components/chat/ChatMessages.tsx +0 -59
  348. package/dist/templates/next-app/src/uikit/components/chat/ChatWrap.tsx +0 -28
  349. package/dist/templates/next-app/src/uikit/components/chat/FocusBarActionInterface.ts +0 -19
  350. package/dist/templates/next-app/src/uikit/hook/useMountedClient.ts +0 -17
  351. package/dist/templates/next-app/src/uikit/hook/useStore.ts +0 -15
  352. package/dist/templates/react-app/__tests__/__mocks__/I18nService.ts +0 -13
  353. package/dist/templates/react-app/__tests__/src/App.test.tsx +0 -139
  354. package/dist/templates/react-app/config/Identifier/page.identifiter.ts +0 -39
  355. package/dist/templates/react-app/config/i18n.ts +0 -15
  356. package/dist/templates/react-app/docs/en/project-structure.md +0 -434
  357. package/dist/templates/react-app/docs/zh/project-structure.md +0 -434
  358. package/dist/templates/react-app/src/base/cases/RequestState.ts +0 -20
  359. package/dist/templates/react-app/src/base/port/AsyncStateInterface.ts +0 -7
  360. package/dist/templates/react-app/src/uikit/hooks/useDocumentTitle.ts +0 -15
  361. package/dist/templates/react-app/src/uikit/hooks/useStore.ts +0 -15
@@ -1,68 +1,66 @@
1
1
  'use client';
2
2
 
3
- import { Table } from 'antd';
4
- import { useEffect, useRef } from 'react';
5
- import { AdminUserService } from '@/base/services/AdminUserService';
3
+ import { ResourceTable } from '@brain-toolkit/antd-blocks/resourceTable/ResourceTable';
4
+ import { ResourceTableHeader } from '@brain-toolkit/antd-blocks/resourceTable/ResourceTableHeader';
5
+ import { useFactory, useLifecycle } from '@brain-toolkit/react-kit';
6
+ import { ResourceStore } from '@qlover/corekit-bridge';
7
+ import { useMemo } from 'react';
8
+ import { ResourceState } from '@/base/cases/ResourceState';
9
+ import { ZodColumnBuilder } from '@/base/cases/ZodColumnBuilder';
10
+ import { AdminUserApi } from '@/base/services/adminApi/AdminUserApi';
11
+ import { AdminPageEvent } from '@/base/services/AdminPageEvent';
12
+ import { ResourceService } from '@/base/services/ResourceService';
6
13
  import { ClientSeo } from '@/uikit/components/ClientSeo';
7
14
  import { useI18nInterface } from '@/uikit/hook/useI18nInterface';
8
15
  import { useIOC } from '@/uikit/hook/useIOC';
9
- import { useStore } from '@/uikit/hook/useStore';
10
- import { userSchema, type UserSchema } from '@migrations/schema/UserSchema';
11
- import { adminUsers18n } from '@config/i18n';
12
- import type { ColumnsType } from 'antd/es/table';
16
+ import { useWarnTranslations } from '@/uikit/hook/useWarnTranslations';
17
+ import { userSchema } from '@migrations/schema/UserSchema';
18
+ import { adminUsers18n, adminTableI18n } from '@config/i18n';
13
19
 
14
- const baseColumns: ColumnsType<UserSchema> = Object.keys(
15
- userSchema.omit({
16
- password: true,
17
- credential_token: true
18
- }).shape
19
- ).map((key) => ({
20
- title: key,
21
- dataIndex: key
22
- }));
20
+ const ns = 'admin_users';
23
21
 
24
- export default function UsersPage() {
25
- const adminUserService = useIOC(AdminUserService);
26
- const tt = useI18nInterface(adminUsers18n);
27
- const listParams = useStore(adminUserService, (state) => state.listParams);
28
- const listState = useStore(adminUserService, (state) => state.listState);
29
- const mouted = useRef(false);
22
+ const localesTT = {
23
+ ...adminUsers18n,
24
+ ...adminTableI18n
25
+ };
30
26
 
31
- useEffect(() => {
32
- if (!mouted.current) {
33
- mouted.current = true;
27
+ export default function UsersPage() {
28
+ const tt = useI18nInterface(localesTT);
29
+ const t = useWarnTranslations();
30
+ const adminUserApi = useIOC(AdminUserApi);
31
+ const resourceStore = useFactory(ResourceStore, () => new ResourceState());
32
+ const service = useFactory(ResourceService, ns, resourceStore, adminUserApi);
33
+ const pageEvent = useFactory(AdminPageEvent, ns, service);
34
34
 
35
- requestAnimationFrame(() => {
36
- adminUserService.initialize();
37
- });
38
- }
39
- }, [adminUserService]);
35
+ const zodColumnBuilder = useFactory(
36
+ ZodColumnBuilder,
37
+ ns,
38
+ userSchema.omit({
39
+ password: true,
40
+ credential_token: true
41
+ })
42
+ );
40
43
 
41
- const dataSource = listState.result?.list as UserSchema[];
44
+ useLifecycle(pageEvent);
42
45
 
43
- const columns: ColumnsType<UserSchema> = baseColumns;
46
+ const options = useMemo(
47
+ () => zodColumnBuilder.translate(t).buildAll(),
48
+ [t, zodColumnBuilder]
49
+ );
44
50
 
45
51
  return (
46
52
  <div data-testid="UsersPage">
47
53
  <ClientSeo i18nInterface={tt} />
48
- <Table
49
- rowKey="id"
50
- columns={columns}
51
- dataSource={dataSource}
52
- loading={listState.loading}
53
- scroll={{ x: true }}
54
- pagination={{
55
- pageSizeOptions: [10, 20, 50],
56
- current: listParams.page,
57
- pageSize: listParams.pageSize,
58
- total: listState.result?.total,
59
- onChange: (page, pageSize) => {
60
- adminUserService.changeListParams({
61
- page,
62
- pageSize
63
- });
64
- }
65
- }}
54
+
55
+ <ResourceTableHeader
56
+ settings={Object.assign({}, tt, { create: false })}
57
+ tableEvent={pageEvent}
58
+ />
59
+
60
+ <ResourceTable
61
+ columns={options}
62
+ tableEvent={pageEvent}
63
+ actionProps={false}
66
64
  />
67
65
  </div>
68
66
  );
@@ -2,11 +2,11 @@
2
2
 
3
3
  import { UserOutlined, LockOutlined, GoogleOutlined } from '@ant-design/icons';
4
4
  import { Form, Input, Button } from 'antd';
5
- import { useTranslations } from 'next-intl';
6
5
  import { useState } from 'react';
7
6
  import { LoginValidator } from '@/server/validators/LoginValidator';
8
7
  import { LocaleLink } from '@/uikit/components/LocaleLink';
9
8
  import { useIOC } from '@/uikit/hook/useIOC';
9
+ import { useWarnTranslations } from '@/uikit/hook/useWarnTranslations';
10
10
  import type { LoginI18nInterface } from '@config/i18n/loginI18n';
11
11
  import { I } from '@config/IOCIdentifier';
12
12
 
@@ -17,7 +17,7 @@ interface LoginFormData {
17
17
 
18
18
  export function LoginForm(props: { tt: LoginI18nInterface }) {
19
19
  const { tt } = props;
20
- const t = useTranslations();
20
+ const t = useWarnTranslations();
21
21
  const userService = useIOC(I.UserServiceInterface);
22
22
  const logger = useIOC(I.Logger);
23
23
  const appConfig = useIOC(I.AppConfig);
@@ -0,0 +1,34 @@
1
+ import { ExecutorError } from '@qlover/fe-corekit';
2
+ import { NextResponse } from 'next/server';
3
+ import { BootstrapServer } from '@/core/bootstraps/BootstrapServer';
4
+ import { AppErrorApi } from '@/server/AppErrorApi';
5
+ import { AppSuccessApi } from '@/server/AppSuccessApi';
6
+ import { AdminAuthPlugin } from '@/server/services/AdminAuthPlugin';
7
+ import { ApiLocaleService } from '@/server/services/ApiLocaleService';
8
+ import { LocalesValidator } from '@/server/validators/LocalesValidator';
9
+ import type { NextRequest } from 'next/server';
10
+
11
+ export async function POST(req: NextRequest) {
12
+ const server = new BootstrapServer();
13
+
14
+ const result = await server
15
+ .use(new AdminAuthPlugin())
16
+ .execNoError(async ({ parameters: { IOC } }) => {
17
+ const requestBody = await req.json();
18
+ const localesParams = IOC(LocalesValidator).getThrow(requestBody);
19
+ const adminLocalesService = IOC(ApiLocaleService);
20
+ await adminLocalesService.create(localesParams);
21
+ return {
22
+ success: true
23
+ };
24
+ });
25
+
26
+ if (result instanceof ExecutorError) {
27
+ console.error(result);
28
+ return NextResponse.json(new AppErrorApi(result.id, result.message), {
29
+ status: 400
30
+ });
31
+ }
32
+
33
+ return NextResponse.json(new AppSuccessApi(result));
34
+ }
@@ -0,0 +1,40 @@
1
+ import { ExecutorError } from '@qlover/fe-corekit';
2
+ import { NextResponse } from 'next/server';
3
+ import { BootstrapServer } from '@/core/bootstraps/BootstrapServer';
4
+ import { AppErrorApi } from '@/server/AppErrorApi';
5
+ import { AppSuccessApi } from '@/server/AppSuccessApi';
6
+ import { AdminAuthPlugin } from '@/server/services/AdminAuthPlugin';
7
+ import { ApiLocaleService } from '@/server/services/ApiLocaleService';
8
+ import { LocalesImportValidator } from '@/server/validators/LocalesValidator';
9
+ import type { NextRequest } from 'next/server';
10
+
11
+ export async function POST(req: NextRequest) {
12
+ const server = new BootstrapServer();
13
+
14
+ const result = await server
15
+ .use(new AdminAuthPlugin())
16
+ .execNoError(async ({ parameters: { IOC } }) => {
17
+ const formData = await req.formData();
18
+
19
+ const localesParams = await IOC(LocalesImportValidator).getThrow({
20
+ values: formData
21
+ });
22
+
23
+ const adminLocalesService = IOC(ApiLocaleService);
24
+
25
+ const result = await adminLocalesService.importLocales(localesParams);
26
+ return {
27
+ success: true,
28
+ data: result
29
+ };
30
+ });
31
+
32
+ if (result instanceof ExecutorError) {
33
+ console.error(result);
34
+ return NextResponse.json(new AppErrorApi(result.id, result.message), {
35
+ status: 400
36
+ });
37
+ }
38
+
39
+ return NextResponse.json(new AppSuccessApi(result));
40
+ }
@@ -0,0 +1,42 @@
1
+ import { ExecutorError } from '@qlover/fe-corekit';
2
+ import { NextResponse } from 'next/server';
3
+ import { BootstrapServer } from '@/core/bootstraps/BootstrapServer';
4
+ import { AppErrorApi } from '@/server/AppErrorApi';
5
+ import { AppSuccessApi } from '@/server/AppSuccessApi';
6
+ import { AdminAuthPlugin } from '@/server/services/AdminAuthPlugin';
7
+ import { ApiLocaleService } from '@/server/services/ApiLocaleService';
8
+ import { PaginationValidator } from '@/server/validators/PaginationValidator';
9
+ import type { NextRequest } from 'next/server';
10
+
11
+ export async function GET(req: NextRequest) {
12
+ const server = new BootstrapServer();
13
+
14
+ const result = await server
15
+ .use(new AdminAuthPlugin())
16
+ .execNoError(async ({ parameters: { IOC } }) => {
17
+ const searchParams = Object.fromEntries(
18
+ req.nextUrl.searchParams.entries()
19
+ );
20
+
21
+ const paginationParams = IOC(PaginationValidator).getThrow(searchParams);
22
+
23
+ const apiUserService = IOC(ApiLocaleService);
24
+
25
+ const result = await apiUserService.getLocales({
26
+ page: paginationParams.page,
27
+ pageSize: paginationParams.pageSize,
28
+ orderBy: paginationParams.orders
29
+ });
30
+
31
+ return result;
32
+ });
33
+
34
+ if (result instanceof ExecutorError) {
35
+ console.error(result);
36
+ return NextResponse.json(new AppErrorApi(result.id, result.message), {
37
+ status: 400
38
+ });
39
+ }
40
+
41
+ return NextResponse.json(new AppSuccessApi(result));
42
+ }
@@ -0,0 +1,32 @@
1
+ import { ExecutorError } from '@qlover/fe-corekit';
2
+ import { NextResponse } from 'next/server';
3
+ import { BootstrapServer } from '@/core/bootstraps/BootstrapServer';
4
+ import { AppErrorApi } from '@/server/AppErrorApi';
5
+ import { AppSuccessApi } from '@/server/AppSuccessApi';
6
+ import { AdminAuthPlugin } from '@/server/services/AdminAuthPlugin';
7
+ import { ApiLocaleService } from '@/server/services/ApiLocaleService';
8
+ import type { NextRequest } from 'next/server';
9
+
10
+ export async function POST(req: NextRequest) {
11
+ const server = new BootstrapServer();
12
+
13
+ const result = await server
14
+ .use(new AdminAuthPlugin())
15
+ .execNoError(async ({ parameters: { IOC } }) => {
16
+ const requestBody = await req.json();
17
+ const adminLocalesService = IOC(ApiLocaleService);
18
+ await adminLocalesService.update(requestBody);
19
+ return {
20
+ success: true
21
+ };
22
+ });
23
+
24
+ if (result instanceof ExecutorError) {
25
+ console.error(result);
26
+ return NextResponse.json(new AppErrorApi(result.id, result.message), {
27
+ status: 400
28
+ });
29
+ }
30
+
31
+ return NextResponse.json(new AppSuccessApi(result));
32
+ }
@@ -0,0 +1,44 @@
1
+ import { ExecutorError } from '@qlover/fe-corekit';
2
+ import { NextResponse, type NextRequest } from 'next/server';
3
+ import { BootstrapServer } from '@/core/bootstraps/BootstrapServer';
4
+ import { ApiLocaleService } from '@/server/services/ApiLocaleService';
5
+ import { i18nConfig } from '@config/i18n';
6
+ import type { LocaleType } from '@config/i18n';
7
+
8
+ export const revalidate = i18nConfig.localeCacheTime;
9
+
10
+ export async function GET(req: NextRequest) {
11
+ const searchParams = Object.fromEntries(req.nextUrl.searchParams.entries());
12
+ const locale = searchParams.locale as LocaleType;
13
+
14
+ if (!locale || !i18nConfig.supportedLngs.includes(locale)) {
15
+ return NextResponse.json({}, { status: 404 });
16
+ }
17
+
18
+ const server = new BootstrapServer();
19
+
20
+ const result = await server.execNoError(async ({ parameters: { IOC } }) => {
21
+ const localesService = IOC(ApiLocaleService);
22
+ const result = await localesService.getLocalesJson(locale);
23
+
24
+ return result;
25
+ });
26
+
27
+ if (result instanceof ExecutorError) {
28
+ console.error(result);
29
+ return NextResponse.json(
30
+ {},
31
+ {
32
+ status: 400
33
+ }
34
+ );
35
+ }
36
+
37
+ const response = NextResponse.json(result);
38
+ response.headers.set(
39
+ 'Cache-Control',
40
+ `s-maxage=${i18nConfig.localeCacheTime}`
41
+ );
42
+ response.headers.set('x-cache-tag', `i18n-${locale}`);
43
+ return response;
44
+ }
@@ -1,23 +1,11 @@
1
1
  import { injectable } from 'inversify';
2
+ import { defaultNavItems } from '@config/adminNavs';
2
3
  import { AdminLayoutInterface } from '../port/AdminLayoutInterface';
3
4
  import type {
4
5
  NavItemInterface,
5
6
  AdminPageState
6
7
  } from '../port/AdminLayoutInterface';
7
8
 
8
- const defaultNavItems: NavItemInterface[] = [
9
- {
10
- key: 'dashboard',
11
- i18nKey: 'Dashboard',
12
- pathname: '/admin'
13
- },
14
- {
15
- key: 'users',
16
- i18nKey: 'User Management',
17
- pathname: '/admin/users'
18
- }
19
- ];
20
-
21
9
  class AdminPageManagerState implements AdminPageState {
22
10
  collapsedSidebar = false;
23
11
 
@@ -0,0 +1,18 @@
1
+ import dayjs from 'dayjs';
2
+ import { injectable } from 'inversify';
3
+
4
+ @injectable()
5
+ export class Datetime {
6
+ timestamp(): number {
7
+ return dayjs().unix();
8
+ }
9
+
10
+ timestampz(): string {
11
+ const now = new Date();
12
+ return now.toISOString().replace('T', ' ').replace('Z', '+00');
13
+ }
14
+
15
+ format(format: string, date?: Date): string {
16
+ return dayjs(date).format(format);
17
+ }
18
+ }
@@ -4,8 +4,11 @@ import {
4
4
  type ExecutorPlugin
5
5
  } from '@qlover/fe-corekit';
6
6
  import { inject, injectable } from 'inversify';
7
+ import { i18nKeySchema } from '@config/i18n/i18nKeyScheam';
8
+ import { API_NOT_AUTHORIZED } from '@config/Identifier';
7
9
  import { I } from '@config/IOCIdentifier';
8
10
  import type { DialogHandlerOptions } from './DialogHandler';
11
+ import type { RouterService } from './RouterService';
9
12
  import type { I18nServiceInterface } from '../port/I18nServiceInterface';
10
13
  import type { UIDialogInterface } from '@qlover/corekit-bridge';
11
14
 
@@ -16,7 +19,9 @@ export class DialogErrorPlugin implements ExecutorPlugin {
16
19
  constructor(
17
20
  @inject(I.DialogHandler)
18
21
  protected dialogHandler: UIDialogInterface<DialogHandlerOptions>,
19
- @inject(I.I18nServiceInterface) protected i18nService: I18nServiceInterface
22
+ @inject(I.I18nServiceInterface) protected i18nService: I18nServiceInterface,
23
+ @inject(I.RouterServiceInterface)
24
+ protected routerService: RouterService
20
25
  ) {}
21
26
 
22
27
  onError(context: ExecutorContext<unknown>): void | Promise<void> {
@@ -28,9 +33,13 @@ export class DialogErrorPlugin implements ExecutorPlugin {
28
33
  const handleError = runtimesError || error;
29
34
 
30
35
  if (handleError instanceof ExecutorError) {
31
- if (this.isI18nMessage(handleError.message)) {
36
+ if (this.isI18nMessage(handleError.id)) {
32
37
  const message = this.i18nService.t(handleError.id);
33
38
  this.dialogHandler.error(message);
39
+
40
+ if (handleError.id === API_NOT_AUTHORIZED) {
41
+ this.routerService.gotoLogin();
42
+ }
34
43
  } else {
35
44
  this.dialogHandler.error(handleError.message);
36
45
  }
@@ -38,9 +47,6 @@ export class DialogErrorPlugin implements ExecutorPlugin {
38
47
  }
39
48
 
40
49
  protected isI18nMessage(message: string): boolean {
41
- // Check if message follows the pattern of underscore-separated format
42
- // e.g., "namespace_key" or "namespace__key"
43
- const pattern = /^[a-zA-Z]+(?:_[a-zA-Z]+)+$|^[a-zA-Z]+(?:__[a-zA-Z]+)+$/;
44
- return pattern.test(message);
50
+ return i18nKeySchema.safeParse(message).success;
45
51
  }
46
52
  }
@@ -0,0 +1,17 @@
1
+ import { RequestState } from '@qlover/corekit-bridge';
2
+ import type { PaginationInterface } from '@/server/port/PaginationInterface';
3
+ import type {
4
+ ResourceQuery,
5
+ ResourceStateInterface
6
+ } from '@qlover/corekit-bridge';
7
+
8
+ export class ResourceState implements ResourceStateInterface {
9
+ searchParams: ResourceQuery = {
10
+ page: 1,
11
+ pageSize: 10,
12
+ orderBy: 'updated_at',
13
+ order: 1
14
+ };
15
+ initState = new RequestState<unknown>();
16
+ listState = new RequestState<PaginationInterface<unknown>>();
17
+ }
@@ -0,0 +1,25 @@
1
+ import type { PageI18nInterface } from '@config/i18n';
2
+ import type { useTranslations } from 'next-intl';
3
+
4
+ /**
5
+ * Translate I18n Interface tools class
6
+ *
7
+ * @param i18nInterface - The i18n interface to translate
8
+ * @param t - The translations function
9
+ * @returns The translated i18n interface
10
+ */
11
+ export class TranslateI18nInterface {
12
+ static translate<T extends PageI18nInterface | Record<string, string>>(
13
+ source: T,
14
+ t: ReturnType<typeof useTranslations>
15
+ ): T {
16
+ return Object.fromEntries(
17
+ Object.entries(source).map(([key, value]) => {
18
+ if (typeof value === 'string') {
19
+ return [key, t(value)];
20
+ }
21
+ return [key, value];
22
+ })
23
+ ) as T;
24
+ }
25
+ }
@@ -0,0 +1,200 @@
1
+ import { ResourceTableFormMap } from '@brain-toolkit/antd-blocks';
2
+ import { merge } from 'lodash';
3
+ import {
4
+ type z,
5
+ ZodFirstPartyTypeKind,
6
+ type ZodObject,
7
+ type ZodRawShape,
8
+ type ZodType
9
+ } from 'zod';
10
+ import { joinI18nKey } from '@config/i18n/i18nKeyScheam';
11
+ import type { ZodBuilderInterface } from '../port/ZodBuilderInterface';
12
+ import type {
13
+ ResourceTableFormType,
14
+ ResourceTableOption
15
+ } from '@brain-toolkit/antd-blocks';
16
+ import type { NamePath } from 'antd/es/form/interface';
17
+ import type { useTranslations } from 'next-intl';
18
+
19
+ type OptionMap<
20
+ Value extends ZodRawShape,
21
+ Input extends ZodObject<Value>
22
+ > = Record<keyof Input['shape'], ResourceTableOption<z.infer<Input>>>;
23
+
24
+ export const ZodType2RenderFormMap = {
25
+ [ZodFirstPartyTypeKind.ZodString]: ResourceTableFormMap.input,
26
+ [ZodFirstPartyTypeKind.ZodNumber]: ResourceTableFormMap.input,
27
+ [ZodFirstPartyTypeKind.ZodBigInt]: ResourceTableFormMap.input,
28
+ [ZodFirstPartyTypeKind.ZodBoolean]: ResourceTableFormMap.select,
29
+ [ZodFirstPartyTypeKind.ZodEnum]: ResourceTableFormMap.select,
30
+ [ZodFirstPartyTypeKind.ZodNativeEnum]: ResourceTableFormMap.select
31
+ } as const;
32
+
33
+ export class ZodColumnBuilder<
34
+ Value extends ZodRawShape,
35
+ Input extends ZodObject<Value>
36
+ > implements ZodBuilderInterface<Input, ResourceTableOption<z.infer<Input>>>
37
+ {
38
+ protected optionMap: OptionMap<Value, Input>;
39
+
40
+ constructor(
41
+ readonly namespace: string,
42
+ readonly input: Input,
43
+ optionMap?: OptionMap<Value, Input>
44
+ ) {
45
+ const baseOptions = this.getBaseOptions(input);
46
+ this.optionMap = optionMap ? merge(baseOptions, optionMap) : baseOptions;
47
+ }
48
+
49
+ static zodType2RenderForm(zod: ZodType): ResourceTableFormType | undefined {
50
+ // @ts-expect-error - zod._def.typeName is not typed
51
+ const typeName = zod._def?.typeName as ZodFirstPartyTypeKind;
52
+
53
+ // Handle wrapper types (Optional, Nullable, Default)
54
+ if (
55
+ typeName === ZodFirstPartyTypeKind.ZodOptional ||
56
+ typeName === ZodFirstPartyTypeKind.ZodNullable ||
57
+ typeName === ZodFirstPartyTypeKind.ZodDefault
58
+ ) {
59
+ // @ts-expect-error - innerType is not typed
60
+ return ZodColumnBuilder.zodType2RenderForm(zod._def.innerType);
61
+ }
62
+
63
+ // Direct mapping lookup
64
+ return ZodType2RenderFormMap[
65
+ typeName as keyof typeof ZodType2RenderFormMap
66
+ ];
67
+ }
68
+
69
+ zod2BaseOption(
70
+ key: string,
71
+ zod: ZodType
72
+ ): ResourceTableOption<z.infer<Input>> {
73
+ return {
74
+ key: key,
75
+ title: key,
76
+ dataIndex: key,
77
+ tt: {
78
+ tableTitle: joinI18nKey(this.namespace, key, 'title'),
79
+ description: joinI18nKey(this.namespace, key, 'description'),
80
+ formItemLabel: joinI18nKey(this.namespace, key, 'label'),
81
+ formItemPlaceholder: joinI18nKey(this.namespace, key, 'placeholder'),
82
+ formItemError: joinI18nKey(this.namespace, key, 'error'),
83
+ formItemRequired: joinI18nKey(this.namespace, key, 'required')
84
+ },
85
+ renderForm: ZodColumnBuilder.zodType2RenderForm(zod),
86
+ formItemWrapProps: {
87
+ name: key as NamePath<z.infer<Input>>,
88
+ label: key,
89
+ rules: []
90
+ },
91
+ formItemProps: {}
92
+ };
93
+ }
94
+
95
+ getBaseOptions(input: Input): OptionMap<Value, Input> {
96
+ return Object.entries(input.shape).reduce(
97
+ (acc, [key, zod]) => {
98
+ acc[key as keyof Input['shape']] = this.zod2BaseOption(
99
+ key,
100
+ zod as ZodType
101
+ );
102
+ return acc;
103
+ },
104
+ {} as OptionMap<Value, Input>
105
+ );
106
+ }
107
+
108
+ bind(
109
+ key: keyof Input['shape'],
110
+ params?: Partial<ResourceTableOption<z.infer<Input>>>
111
+ ): this {
112
+ if (params) {
113
+ const existingOption = this.optionMap[key];
114
+ this.optionMap[key] = merge({}, existingOption, params);
115
+ }
116
+ return this;
117
+ }
118
+
119
+ render<K extends keyof Input['shape']>(
120
+ key: K,
121
+ render: (
122
+ value: unknown,
123
+ record: z.infer<Input>,
124
+ index: number
125
+ ) => React.ReactNode
126
+ ): this {
127
+ this.optionMap[key].render = render;
128
+ return this;
129
+ }
130
+
131
+ /**
132
+ * Translate all i18n keys in options to actual text
133
+ * @param t - Translation function from next-intl
134
+ * @returns this for chaining
135
+ */
136
+ translate(t: ReturnType<typeof useTranslations>): this {
137
+ Object.values(this.optionMap).forEach((option) => {
138
+ const { tt } = option;
139
+ // Translate title if it's a string (i18n key)
140
+ if (typeof option.title === 'string') {
141
+ option.title = t(tt.tableTitle);
142
+ }
143
+
144
+ // Translate formItemWrapProps label if exists
145
+ if (
146
+ option.formItemWrapProps?.label &&
147
+ typeof option.formItemWrapProps.label === 'string'
148
+ ) {
149
+ option.formItemWrapProps = {
150
+ ...option.formItemWrapProps,
151
+ label: t(tt.formItemLabel)
152
+ };
153
+ }
154
+
155
+ // Translate formItemProps placeholder if exists
156
+ if (option.formItemProps && typeof option.formItemProps === 'object') {
157
+ Object.assign(
158
+ option.formItemProps as Record<string, unknown>,
159
+ {
160
+ placeholder: t(tt.formItemPlaceholder)
161
+ } as Record<string, unknown>
162
+ );
163
+ }
164
+ });
165
+
166
+ return this;
167
+ }
168
+
169
+ /**
170
+ * Build a single option by key
171
+ * @param key - The key of the option to build
172
+ * @param params - Optional additional parameters to merge
173
+ * @returns The built option
174
+ */
175
+ build(key: string, params?: unknown): ResourceTableOption<z.infer<Input>> {
176
+ const option = this.optionMap[key as keyof Input['shape']];
177
+ if (!option) {
178
+ throw new Error(`Option with key "${key}" not found`);
179
+ }
180
+
181
+ if (params && typeof params === 'object') {
182
+ return merge(
183
+ {},
184
+ option,
185
+ params as Partial<ResourceTableOption<z.infer<Input>>>
186
+ );
187
+ }
188
+
189
+ return option;
190
+ }
191
+
192
+ /**
193
+ * Build all options
194
+ * @param params - Optional additional parameters (currently unused)
195
+ * @returns Array of all built options
196
+ */
197
+ buildAll(_params?: unknown): ResourceTableOption<z.infer<Input>>[] {
198
+ return Object.values(this.optionMap);
199
+ }
200
+ }
@@ -0,0 +1,8 @@
1
+ export interface ZodBuilderInterface<Input, Ouput> {
2
+ readonly input: Input;
3
+
4
+ bind(key: string, params?: Partial<Ouput>): this;
5
+
6
+ build(key: string, params?: unknown): Ouput;
7
+ buildAll(params?: unknown): Ouput[];
8
+ }