@qlover/create-app 0.7.5 → 0.7.7

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 (166) hide show
  1. package/CHANGELOG.md +257 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/templates/next-app/.env.template +22 -0
  5. package/dist/templates/next-app/.prettierignore +58 -0
  6. package/dist/templates/next-app/README.md +36 -0
  7. package/dist/templates/next-app/build/generateLocales.ts +25 -0
  8. package/dist/templates/next-app/config/IOCIdentifier.ts +45 -0
  9. package/dist/templates/next-app/config/Identifier/common.error.ts +34 -0
  10. package/dist/templates/next-app/config/Identifier/common.ts +62 -0
  11. package/dist/templates/next-app/config/Identifier/index.ts +10 -0
  12. package/dist/templates/next-app/config/Identifier/page.about.ts +181 -0
  13. package/dist/templates/next-app/config/Identifier/page.executor.ts +272 -0
  14. package/dist/templates/next-app/config/Identifier/page.home.ts +63 -0
  15. package/dist/templates/next-app/config/Identifier/page.identifiter.ts +39 -0
  16. package/dist/templates/next-app/config/Identifier/page.jsonStorage.ts +72 -0
  17. package/dist/templates/next-app/config/Identifier/page.login.ts +165 -0
  18. package/dist/templates/next-app/config/Identifier/page.register.ts +147 -0
  19. package/dist/templates/next-app/config/Identifier/page.request.ts +182 -0
  20. package/dist/templates/next-app/config/common.ts +34 -0
  21. package/dist/templates/next-app/config/i18n/PageI18nInterface.ts +51 -0
  22. package/dist/templates/next-app/config/i18n/i18nConfig.ts +12 -0
  23. package/dist/templates/next-app/config/i18n/index.ts +3 -0
  24. package/dist/templates/next-app/config/i18n/loginI18n.ts +42 -0
  25. package/dist/templates/next-app/config/theme.ts +23 -0
  26. package/dist/templates/next-app/docs/env.md +94 -0
  27. package/dist/templates/next-app/eslint.config.mjs +181 -0
  28. package/dist/templates/next-app/next.config.ts +21 -0
  29. package/dist/templates/next-app/package.json +58 -0
  30. package/dist/templates/next-app/plugins/eslint-plugin-testid.mjs +94 -0
  31. package/dist/templates/next-app/plugins/generateLocalesPlugin.ts +33 -0
  32. package/dist/templates/next-app/postcss.config.mjs +5 -0
  33. package/dist/templates/next-app/public/file.svg +1 -0
  34. package/dist/templates/next-app/public/globe.svg +1 -0
  35. package/dist/templates/next-app/public/locales/en/common.json +183 -0
  36. package/dist/templates/next-app/public/locales/zh/common.json +183 -0
  37. package/dist/templates/next-app/public/next.svg +1 -0
  38. package/dist/templates/next-app/public/vercel.svg +1 -0
  39. package/dist/templates/next-app/public/window.svg +1 -0
  40. package/dist/templates/next-app/src/app/[locale]/favicon.ico +0 -0
  41. package/dist/templates/next-app/src/app/[locale]/layout.tsx +44 -0
  42. package/dist/templates/next-app/src/app/[locale]/login/FeatureItem.tsx +13 -0
  43. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +115 -0
  44. package/dist/templates/next-app/src/app/[locale]/login/page.tsx +73 -0
  45. package/dist/templates/next-app/src/app/[locale]/not-found.tsx +24 -0
  46. package/dist/templates/next-app/src/app/[locale]/page.tsx +106 -0
  47. package/dist/templates/next-app/src/base/cases/AppConfig.ts +15 -0
  48. package/dist/templates/next-app/src/base/cases/InversifyContainer.ts +33 -0
  49. package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +25 -0
  50. package/dist/templates/next-app/src/base/port/UserServiceInterface.ts +11 -0
  51. package/dist/templates/next-app/src/base/services/I18nService.ts +115 -0
  52. package/dist/templates/next-app/src/base/services/UserService.ts +23 -0
  53. package/dist/templates/next-app/src/core/IOC.ts +58 -0
  54. package/dist/templates/next-app/src/core/IocRegisterImpl.ts +100 -0
  55. package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +98 -0
  56. package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +47 -0
  57. package/dist/templates/next-app/src/core/bootstraps/IocIdentifierTest.ts +26 -0
  58. package/dist/templates/next-app/src/core/bootstraps/PrintBootstrap.ts +18 -0
  59. package/dist/templates/next-app/src/core/globals.ts +21 -0
  60. package/dist/templates/next-app/src/i18n/request.ts +22 -0
  61. package/dist/templates/next-app/src/i18n/routing.ts +30 -0
  62. package/dist/templates/next-app/src/middleware.ts +22 -0
  63. package/dist/templates/next-app/src/server/getServerI18n.ts +26 -0
  64. package/dist/templates/next-app/src/styles/css/antd-themes/_default.css +239 -0
  65. package/dist/templates/next-app/src/styles/css/antd-themes/dark.css +178 -0
  66. package/dist/templates/next-app/src/styles/css/antd-themes/index.css +3 -0
  67. package/dist/templates/next-app/src/styles/css/antd-themes/no-context.css +34 -0
  68. package/dist/templates/next-app/src/styles/css/antd-themes/pink.css +204 -0
  69. package/dist/templates/next-app/src/styles/css/index.css +6 -0
  70. package/dist/templates/next-app/src/styles/css/page.css +19 -0
  71. package/dist/templates/next-app/src/styles/css/tailwind.css +5 -0
  72. package/dist/templates/next-app/src/styles/css/themes/_default.css +29 -0
  73. package/dist/templates/next-app/src/styles/css/themes/dark.css +29 -0
  74. package/dist/templates/next-app/src/styles/css/themes/index.css +3 -0
  75. package/dist/templates/next-app/src/styles/css/themes/pink.css +29 -0
  76. package/dist/templates/next-app/src/styles/css/zIndex.css +9 -0
  77. package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +42 -0
  78. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +25 -0
  79. package/dist/templates/next-app/src/uikit/components/ComboProvider.tsx +45 -0
  80. package/dist/templates/next-app/src/uikit/components/LanguageSwitcher.tsx +52 -0
  81. package/dist/templates/next-app/src/uikit/components/LocaleLink.tsx +51 -0
  82. package/dist/templates/next-app/src/uikit/components/NextIntlProvider.tsx +21 -0
  83. package/dist/templates/next-app/src/uikit/components/ThemeSwitcher.tsx +86 -0
  84. package/dist/templates/next-app/src/uikit/context/IOCContext.ts +6 -0
  85. package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +28 -0
  86. package/dist/templates/next-app/src/uikit/hook/useIOC.ts +37 -0
  87. package/dist/templates/next-app/src/uikit/hook/useMountedClient.ts +11 -0
  88. package/dist/templates/next-app/src/uikit/hook/useStore.ts +15 -0
  89. package/dist/templates/next-app/tailwind.config.ts +8 -0
  90. package/dist/templates/next-app/tsconfig.json +36 -0
  91. package/dist/templates/react-app/.env.template +0 -2
  92. package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +1 -1
  93. package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +6 -31
  94. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +1 -1
  95. package/dist/templates/react-app/config/IOCIdentifier.ts +77 -5
  96. package/dist/templates/react-app/config/app.router.ts +2 -2
  97. package/dist/templates/react-app/package.json +4 -7
  98. package/dist/templates/react-app/public/locales/en/common.json +1 -1
  99. package/dist/templates/react-app/public/locales/zh/common.json +1 -1
  100. package/dist/templates/react-app/src/App.tsx +9 -4
  101. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +1 -1
  102. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +4 -0
  103. package/dist/templates/react-app/src/base/cases/DialogHandler.ts +16 -13
  104. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +4 -3
  105. package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +2 -2
  106. package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +39 -0
  107. package/dist/templates/react-app/src/base/cases/RequestState.ts +20 -0
  108. package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +2 -2
  109. package/dist/templates/react-app/src/base/cases/RouterLoader.ts +8 -2
  110. package/dist/templates/react-app/src/base/port/AsyncStateInterface.ts +7 -0
  111. package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +24 -0
  112. package/dist/templates/react-app/src/base/port/I18nServiceInterface.ts +10 -0
  113. package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +20 -0
  114. package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +20 -0
  115. package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +23 -0
  116. package/dist/templates/react-app/src/base/port/RequestStatusInterface.ts +5 -0
  117. package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +27 -0
  118. package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +12 -0
  119. package/dist/templates/react-app/src/base/services/I18nService.ts +10 -6
  120. package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +23 -5
  121. package/dist/templates/react-app/src/base/services/RouteService.ts +25 -54
  122. package/dist/templates/react-app/src/base/services/UserService.ts +10 -20
  123. package/dist/templates/react-app/src/core/IOC.ts +1 -26
  124. package/dist/templates/react-app/src/core/IocRegisterImpl.ts +125 -0
  125. package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +4 -6
  126. package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +8 -6
  127. package/dist/templates/react-app/src/core/bootstraps/IocIdentifierTest.ts +26 -0
  128. package/dist/templates/react-app/src/pages/auth/Layout.tsx +2 -2
  129. package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +5 -6
  130. package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +8 -7
  131. package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +8 -19
  132. package/dist/templates/react-app/src/pages/base/{ErrorIdentifierPage.tsx → IdentifierPage.tsx} +1 -1
  133. package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +11 -15
  134. package/dist/templates/react-app/src/pages/base/Layout.tsx +1 -1
  135. package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +2 -2
  136. package/dist/templates/react-app/src/pages/base/RequestPage.tsx +34 -46
  137. package/dist/templates/react-app/src/styles/css/antd-themes/_default.css +2 -2
  138. package/dist/templates/react-app/src/styles/css/antd-themes/dark.css +2 -2
  139. package/dist/templates/react-app/src/styles/css/antd-themes/pink.css +2 -2
  140. package/dist/templates/react-app/src/styles/css/index.css +1 -0
  141. package/dist/templates/react-app/src/styles/css/page.css +8 -0
  142. package/dist/templates/react-app/src/styles/css/zIndex.css +9 -0
  143. package/dist/templates/react-app/src/uikit/{controllers/ExecutorController.ts → bridges/ExecutorPageBridge.ts} +13 -36
  144. package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +41 -0
  145. package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +16 -0
  146. package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +136 -0
  147. package/dist/templates/react-app/src/uikit/components/LanguageSwitcher.tsx +3 -2
  148. package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +2 -2
  149. package/dist/templates/react-app/src/uikit/{providers → components}/ProcessExecutorProvider.tsx +4 -4
  150. package/dist/templates/react-app/src/uikit/components/RouterRenderComponent.tsx +1 -1
  151. package/dist/templates/react-app/src/uikit/components/ThemeSwitcher.tsx +3 -5
  152. package/dist/templates/react-app/src/uikit/{providers → components}/UserAuthProvider.tsx +3 -3
  153. package/dist/templates/react-app/src/uikit/hooks/useI18nGuard.ts +5 -2
  154. package/dist/templates/react-app/src/uikit/hooks/{userRouterService.ts → useNavigateBridge.ts} +3 -3
  155. package/dist/templates/react-app/src/uikit/hooks/useStore.ts +5 -2
  156. package/dist/templates/react-app/tsconfig.json +1 -4
  157. package/package.json +1 -1
  158. package/dist/templates/react-app/src/base/port/InteractionHubInterface.ts +0 -94
  159. package/dist/templates/react-app/src/base/port/UIDependenciesInterface.ts +0 -37
  160. package/dist/templates/react-app/src/core/registers/IocRegisterImpl.ts +0 -25
  161. package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +0 -74
  162. package/dist/templates/react-app/src/core/registers/RegisterControllers.ts +0 -26
  163. package/dist/templates/react-app/src/core/registers/RegisterGlobals.ts +0 -30
  164. package/dist/templates/react-app/src/uikit/controllers/JSONStorageController.ts +0 -49
  165. package/dist/templates/react-app/src/uikit/controllers/RequestController.ts +0 -158
  166. /package/dist/templates/react-app/src/uikit/{providers → components}/BaseRouteProvider.tsx +0 -0
@@ -2,6 +2,7 @@ import type { ComponentType, LazyExoticComponent, ReactNode } from 'react';
2
2
  import { RouteObject } from 'react-router-dom';
3
3
  import isString from 'lodash/isString';
4
4
  import { RouteMeta } from '../types/Page';
5
+ import { LoggerInterface } from '@qlover/logger';
5
6
 
6
7
  /**
7
8
  * Component mapping type for lazy-loaded components
@@ -79,6 +80,11 @@ export type RouterLoaderOptions = {
79
80
  * @required
80
81
  */
81
82
  render: RouterLoaderRender;
83
+
84
+ /**
85
+ * Logger
86
+ */
87
+ logger?: LoggerInterface;
82
88
  };
83
89
 
84
90
  /**
@@ -107,7 +113,7 @@ export type RouterLoaderOptions = {
107
113
  * });
108
114
  */
109
115
  export class RouterLoader {
110
- constructor(private readonly options: RouterLoaderOptions) {
116
+ constructor(protected options: RouterLoaderOptions) {
111
117
  if (!options.render) {
112
118
  throw new Error('RouterLoader render is required');
113
119
  }
@@ -149,7 +155,7 @@ export class RouterLoader {
149
155
  const { element, children, ...rest } = route;
150
156
 
151
157
  if (!element || !isString(element)) {
152
- console.warn(
158
+ this.options.logger?.warn(
153
159
  `Invalid route, path is: ${route.path}, element is: ${element}`
154
160
  );
155
161
  }
@@ -0,0 +1,7 @@
1
+ export interface AsyncStateInterface<T> {
2
+ loading: boolean;
3
+ result: T | null;
4
+ error: unknown | null;
5
+ startTime: number;
6
+ endTime: number;
7
+ }
@@ -0,0 +1,24 @@
1
+ import { StoreInterface, StoreStateInterface } from '@qlover/corekit-bridge';
2
+ import { RequestState } from '../cases/RequestState';
3
+
4
+ export interface ExecutorPageStateInterface extends StoreStateInterface {
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ helloState: RequestState<any>;
7
+ }
8
+
9
+ /**
10
+ * Executor Page Bridge Interface
11
+ *
12
+ * This interface provides a bridge for the ExecutorPage component to interact with the ExecutorController.
13
+ * It allows the ExecutorPage component to subscribe to the ExecutorController's state and trigger actions.
14
+ *
15
+ * @example
16
+ * const executorPageBridge = new ExecutorPageBridge();
17
+ */
18
+ export abstract class ExecutorPageBridgeInterface extends StoreInterface<ExecutorPageStateInterface> {
19
+ selector = {
20
+ helloState: (state: ExecutorPageStateInterface) => state.helloState
21
+ };
22
+
23
+ abstract onTestPlugins: () => Promise<void>;
24
+ }
@@ -0,0 +1,10 @@
1
+ import { BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
2
+
3
+ export interface I18nServiceInterface extends BootstrapExecutorPlugin {
4
+ t(key: string, params?: Record<string, unknown>): string;
5
+ changeLanguage(language: string): void;
6
+ changeLoading(loading: boolean): void;
7
+ getCurrentLanguage(): string;
8
+ isValidLanguage(language: string): boolean;
9
+ getSupportedLanguages(): string[];
10
+ }
@@ -0,0 +1,20 @@
1
+ import { StoreInterface, StoreStateInterface } from '@qlover/corekit-bridge';
2
+
3
+ export interface JSONStoragePageStateInterface extends StoreStateInterface {
4
+ testKey1?: number;
5
+ testKey2?: number;
6
+ expireTime: number;
7
+ requestTimeout: number;
8
+ }
9
+
10
+ export abstract class JSONStoragePageBridgeInterface extends StoreInterface<JSONStoragePageStateInterface> {
11
+ selector = {
12
+ requestTimeout: (state: JSONStoragePageStateInterface) =>
13
+ state.requestTimeout
14
+ };
15
+
16
+ abstract changeRandomTestKey1: () => void;
17
+ abstract onChangeRandomTestKey2: () => void;
18
+ abstract changeExpireTime: (expireTime: number) => void;
19
+ abstract changeRequestTimeout: (requestTimeout: number) => void;
20
+ }
@@ -0,0 +1,20 @@
1
+ import { ExecutorPlugin } from '@qlover/fe-corekit';
2
+
3
+ export interface ProcesserExecutorInterface extends ExecutorPlugin {
4
+ /**
5
+ * 使用插件
6
+ *
7
+ * @param plugin - 插件
8
+ */
9
+ use(plugin: ExecutorPlugin): this;
10
+
11
+ /**
12
+ * 处理函数
13
+ */
14
+ handler(): Promise<{ success: boolean }>;
15
+
16
+ /**
17
+ * 启动
18
+ */
19
+ starup(): Promise<unknown>;
20
+ }
@@ -0,0 +1,23 @@
1
+ import { StoreInterface, StoreStateInterface } from '@qlover/corekit-bridge';
2
+ import { RequestState } from '../cases/RequestState';
3
+
4
+ export interface RequestPageStateInterface extends StoreStateInterface {
5
+ helloState: RequestState<unknown>;
6
+ ipInfoState: RequestState<unknown>;
7
+ randomUserState: RequestState<unknown>;
8
+ abortState: RequestState<unknown>;
9
+ apiCatchResultState: RequestState<unknown>;
10
+ }
11
+
12
+ export abstract class RequestPageBridgeInterface extends StoreInterface<RequestPageStateInterface> {
13
+ abstract onHello: () => void;
14
+ abstract onIpInfo: () => void;
15
+ abstract onRandomUser: () => void;
16
+ abstract onTriggerApiCatchResult: () => void;
17
+ abstract onTriggerAbortRequest: () => void;
18
+ abstract stopAbortRequest: () => void;
19
+
20
+ emitState(state: Partial<RequestPageStateInterface>): void {
21
+ this.emit(this.cloneState(state));
22
+ }
23
+ }
@@ -0,0 +1,5 @@
1
+ export interface RequestStatusInterface {
2
+ loading: boolean;
3
+ result: unknown | null;
4
+ error: unknown | null;
5
+ }
@@ -0,0 +1,27 @@
1
+ import {
2
+ LoggerInterface,
3
+ StoreInterface,
4
+ StoreStateInterface
5
+ } from '@qlover/corekit-bridge';
6
+ import { RouteConfigValue } from '../cases/RouterLoader';
7
+ import { NavigateFunction, NavigateOptions } from 'react-router-dom';
8
+
9
+ export interface RouteServiceStateInterface extends StoreStateInterface {
10
+ routes: RouteConfigValue[];
11
+ localeRoutes: boolean;
12
+ }
13
+
14
+ export abstract class RouteServiceInterface extends StoreInterface<RouteServiceStateInterface> {
15
+ abstract get logger(): LoggerInterface;
16
+
17
+ abstract getRoutes(): RouteConfigValue[];
18
+ abstract changeRoutes(routes: RouteConfigValue[]): void;
19
+ abstract goto(
20
+ path: string,
21
+ options?: NavigateOptions & { navigate?: NavigateFunction }
22
+ ): void;
23
+ abstract gotoLogin(): void;
24
+ abstract replaceToHome(): void;
25
+ abstract redirectToDefault(navigate: NavigateFunction): void;
26
+ abstract i18nGuard(lng: string, navigate: NavigateFunction): void;
27
+ }
@@ -0,0 +1,12 @@
1
+ import { UserAuthService } from '@qlover/corekit-bridge';
2
+ import { ExecutorPlugin } from '@qlover/fe-corekit';
3
+ import type { UserInfo } from '@/base/apis/userApi/UserApiType';
4
+
5
+ export abstract class UserServiceInterface
6
+ extends UserAuthService<UserInfo>
7
+ implements ExecutorPlugin
8
+ {
9
+ readonly pluginName = 'UserService';
10
+
11
+ abstract getToken(): string | null;
12
+ }
@@ -5,11 +5,11 @@ import HttpApi from 'i18next-http-backend';
5
5
  import merge from 'lodash/merge';
6
6
  import i18nConfig from '@config/i18n';
7
7
  import {
8
- type BootstrapExecutorPlugin,
9
8
  type StoreStateInterface,
10
9
  StoreInterface
11
10
  } from '@qlover/corekit-bridge';
12
11
  import { useLocaleRoutes } from '@config/common';
12
+ import { I18nServiceInterface } from '../port/I18nServiceInterface';
13
13
 
14
14
  const { supportedLngs, fallbackLng } = i18nConfig;
15
15
 
@@ -22,7 +22,7 @@ export class I18nServiceState implements StoreStateInterface {
22
22
 
23
23
  export class I18nService
24
24
  extends StoreInterface<I18nServiceState>
25
- implements BootstrapExecutorPlugin
25
+ implements I18nServiceInterface
26
26
  {
27
27
  readonly pluginName = 'I18nService';
28
28
 
@@ -30,7 +30,7 @@ export class I18nService
30
30
  loading: (state: I18nServiceState) => state.loading
31
31
  };
32
32
 
33
- constructor(private pathname: string) {
33
+ constructor(protected pathname: string) {
34
34
  super(() => new I18nServiceState(i18n.language as I18nServiceLocale));
35
35
  }
36
36
 
@@ -64,7 +64,7 @@ export class I18nService
64
64
  const paths = this.pathname.split('/');
65
65
 
66
66
  for (const path of paths) {
67
- if (I18nService.isValidLanguage(path)) {
67
+ if (this.isValidLanguage(path)) {
68
68
  return path;
69
69
  }
70
70
  }
@@ -93,7 +93,7 @@ export class I18nService
93
93
  this.emit({ ...this.state, loading });
94
94
  }
95
95
 
96
- static getCurrentLanguage(): I18nServiceLocale {
96
+ getCurrentLanguage(): I18nServiceLocale {
97
97
  return i18n.language as I18nServiceLocale;
98
98
  }
99
99
 
@@ -102,10 +102,14 @@ export class I18nService
102
102
  * @param language - language to check
103
103
  * @returns true if the language is supported, false otherwise
104
104
  */
105
- static isValidLanguage(language: string): language is I18nServiceLocale {
105
+ isValidLanguage(language: string): language is I18nServiceLocale {
106
106
  return supportedLngs.includes(language as I18nServiceLocale);
107
107
  }
108
108
 
109
+ getSupportedLanguages(): I18nServiceLocale[] {
110
+ return [...supportedLngs];
111
+ }
112
+
109
113
  /**
110
114
  * translate the key
111
115
  * @param key - key to translate
@@ -1,18 +1,36 @@
1
- import { AsyncExecutor, ExecutorPlugin } from '@qlover/fe-corekit';
1
+ import {
2
+ AsyncExecutor,
3
+ ExecutorContext,
4
+ ExecutorPlugin
5
+ } from '@qlover/fe-corekit';
2
6
  import { IOCIdentifier } from '@config/IOCIdentifier';
3
7
  import { injectable, inject } from 'inversify';
4
8
  import type { LoggerInterface } from '@qlover/logger';
5
- import { RouteService } from './RouteService';
9
+ import type { ProcesserExecutorInterface } from '../port/ProcesserExecutorInterface';
10
+ import type { BootstrapContextValue } from '@qlover/corekit-bridge';
11
+ import type { RouteServiceInterface } from '../port/RouteServiceInterface';
6
12
 
7
13
  @injectable()
8
- export class ProcesserExecutor {
14
+ export class ProcesserExecutor implements ProcesserExecutorInterface {
15
+ pluginName = 'ProcesserExecutor';
9
16
  protected executor: AsyncExecutor = new AsyncExecutor();
10
17
 
11
18
  constructor(
12
- @inject(IOCIdentifier.Logger) private logger: LoggerInterface,
13
- @inject(RouteService) private routeService: RouteService
19
+ @inject(IOCIdentifier.Logger) protected logger: LoggerInterface,
20
+ @inject(IOCIdentifier.RouteServiceInterface)
21
+ protected routeService: RouteServiceInterface
14
22
  ) {}
15
23
 
24
+ /**
25
+ * @override
26
+ */
27
+ onBefore({
28
+ parameters: { ioc }
29
+ }: ExecutorContext<BootstrapContextValue>): void | Promise<void> {
30
+ this.use(ioc.get(IOCIdentifier.I18nKeyErrorPlugin));
31
+ this.use(ioc.get(IOCIdentifier.UserServiceInterface));
32
+ }
33
+
16
34
  use(plugin: ExecutorPlugin): this {
17
35
  this.executor.use(plugin);
18
36
  return this;
@@ -1,16 +1,12 @@
1
1
  import type { RouteConfigValue } from '@/base/cases/RouterLoader';
2
2
  import type { NavigateFunction, NavigateOptions } from 'react-router-dom';
3
- import type { UIDependenciesInterface } from '@/base/port/UIDependenciesInterface';
4
3
  import type { LoggerInterface } from '@qlover/logger';
5
- import { I18nService } from '@/base/services/I18nService';
6
- import {
7
- StoreInterface,
8
- type StoreStateInterface
4
+ import { RouteServiceInterface } from '../port/RouteServiceInterface';
5
+ import type {
6
+ UIBridgeInterface,
7
+ StoreStateInterface
9
8
  } from '@qlover/corekit-bridge';
10
-
11
- export type RouterServiceDependencies = {
12
- navigate: NavigateFunction;
13
- };
9
+ import { I18nServiceInterface } from '../port/I18nServiceInterface';
14
10
 
15
11
  export type RouterServiceOptions = {
16
12
  routes: RouteConfigValue[];
@@ -30,64 +26,38 @@ export class RouterServiceState implements StoreStateInterface {
30
26
  ) {}
31
27
  }
32
28
 
33
- export class RouteService
34
- extends StoreInterface<RouterServiceState>
35
- implements UIDependenciesInterface<RouterServiceDependencies>
36
- {
37
- /**
38
- * @override
39
- */
40
- dependencies?: RouterServiceDependencies;
41
-
42
- constructor(private options: RouterServiceOptions) {
29
+ export class RouteService extends RouteServiceInterface {
30
+ constructor(
31
+ protected uiBridge: UIBridgeInterface<NavigateFunction>,
32
+ protected i18nService: I18nServiceInterface,
33
+ protected options: RouterServiceOptions
34
+ ) {
43
35
  super(
44
36
  () => new RouterServiceState(options.routes, !!options.hasLocalRoutes)
45
37
  );
46
38
  }
47
39
 
48
- get logger(): LoggerInterface {
40
+ override get logger(): LoggerInterface {
49
41
  return this.options.logger;
50
42
  }
51
43
 
52
- get navigate(): NavigateFunction | undefined {
53
- const navigate = this.dependencies?.navigate;
54
-
55
- if (!navigate) {
56
- this.logger.debug(
57
- 'Please use `RouteService.setDependencies` to set dependencies'
58
- );
59
- }
60
-
61
- return navigate;
62
- }
63
-
64
- composePath(path: string): string {
44
+ protected composePath(path: string): string {
65
45
  if (this.state.localeRoutes) {
66
- const targetLang = I18nService.getCurrentLanguage();
46
+ const targetLang = this.i18nService.getCurrentLanguage();
67
47
  return `/${targetLang}${path}`;
68
48
  }
69
49
  return path.startsWith('/') ? path : `/${path}`;
70
50
  }
71
51
 
72
- /**
73
- * @override
74
- */
75
- setDependencies(dependencies: Partial<RouterServiceDependencies>): void {
76
- this.dependencies = Object.assign(
77
- this.dependencies || {},
78
- dependencies
79
- ) as RouterServiceDependencies;
80
- }
81
-
82
- getRoutes(): RouteConfigValue[] {
52
+ override getRoutes(): RouteConfigValue[] {
83
53
  return this.state.routes;
84
54
  }
85
55
 
86
- changeRoutes(routes: RouteConfigValue[]): void {
87
- this.emit({ routes, localeRoutes: this.state.localeRoutes });
56
+ override changeRoutes(routes: RouteConfigValue[]): void {
57
+ this.emit(this.cloneState({ routes }));
88
58
  }
89
59
 
90
- goto(
60
+ override goto(
91
61
  path: string,
92
62
  options?: NavigateOptions & {
93
63
  navigate?: NavigateFunction;
@@ -96,29 +66,30 @@ export class RouteService
96
66
  const { navigate, ...rest } = options || {};
97
67
  path = this.composePath(path);
98
68
  this.logger.debug('Goto path => ', path);
99
- (navigate || this.navigate)?.(path, rest);
69
+
70
+ (navigate || this.uiBridge.getUIBridge())?.(path, rest);
100
71
  }
101
72
 
102
- gotoLogin(): void {
73
+ override gotoLogin(): void {
103
74
  this.goto('/login', { replace: true });
104
75
  }
105
76
 
106
- replaceToHome(): void {
77
+ override replaceToHome(): void {
107
78
  this.goto('/', { replace: true });
108
79
  }
109
80
 
110
- redirectToDefault(navigate: NavigateFunction): void {
81
+ override redirectToDefault(navigate?: NavigateFunction): void {
111
82
  this.goto('/', { replace: true, navigate });
112
83
  }
113
84
 
114
- i18nGuard(lng: string, navigate: NavigateFunction): void {
85
+ override i18nGuard(lng: string, navigate?: NavigateFunction): void {
115
86
  if (!this.state.localeRoutes) {
116
87
  return;
117
88
  }
118
89
 
119
90
  if (!lng) {
120
91
  this.goto('/404', { replace: true, navigate });
121
- } else if (!I18nService.isValidLanguage(lng)) {
92
+ } else if (!this.i18nService.isValidLanguage(lng)) {
122
93
  this.goto('/404', { replace: true, navigate });
123
94
  }
124
95
  }
@@ -1,14 +1,12 @@
1
- import { ExecutorPlugin, type SyncStorageInterface } from '@qlover/fe-corekit';
1
+ import { type SyncStorageInterface } from '@qlover/fe-corekit';
2
2
  import type {
3
3
  UserApiLoginTransaction,
4
4
  UserInfo
5
5
  } from '@/base/apis/userApi/UserApiType';
6
- import { RouteService } from './RouteService';
7
6
  import {
8
7
  type UserAuthApiInterface,
9
8
  type UserAuthState,
10
9
  LoginResponseData,
11
- UserAuthService,
12
10
  UserAuthStore
13
11
  } from '@qlover/corekit-bridge';
14
12
  import { inject, injectable } from 'inversify';
@@ -17,6 +15,8 @@ import { AppError } from '@/base/cases/AppError';
17
15
  import * as errKeys from '@config/Identifier/common.error';
18
16
  import { IOCIdentifier } from '@config/IOCIdentifier';
19
17
  import { AppConfig } from '../cases/AppConfig';
18
+ import { UserServiceInterface } from '../port/UserServiceInterface';
19
+ import { RouteServiceInterface } from '../port/RouteServiceInterface';
20
20
 
21
21
  export interface UserApiState extends UserAuthState<UserInfo> {}
22
22
 
@@ -29,14 +29,10 @@ export interface RegisterFormData {
29
29
  }
30
30
 
31
31
  @injectable()
32
- export class UserService
33
- extends UserAuthService<UserInfo>
34
- implements ExecutorPlugin
35
- {
36
- readonly pluginName = 'UserService';
37
-
32
+ export class UserService extends UserServiceInterface {
38
33
  constructor(
39
- @inject(RouteService) protected routerService: RouteService,
34
+ @inject(IOCIdentifier.RouteServiceInterface)
35
+ protected routerService: RouteServiceInterface,
40
36
  @inject(UserApi)
41
37
  userApi: UserAuthApiInterface<UserInfo>,
42
38
  @inject(IOCIdentifier.AppConfig) appConfig: AppConfig,
@@ -62,7 +58,7 @@ export class UserService
62
58
  return super.store as UserAuthStore<UserApiState>;
63
59
  }
64
60
 
65
- getToken(): string | null {
61
+ override getToken(): string | null {
66
62
  return this.store.getCredential();
67
63
  }
68
64
 
@@ -88,14 +84,6 @@ export class UserService
88
84
  this.store.authSuccess();
89
85
  }
90
86
 
91
- /**
92
- * @override
93
- */
94
- onSuccess(): void {}
95
-
96
- /**
97
- * @override
98
- */
99
87
  override async logout(): Promise<void> {
100
88
  await super.logout();
101
89
 
@@ -103,7 +91,9 @@ export class UserService
103
91
  this.routerService.gotoLogin();
104
92
  }
105
93
 
106
- async register(params: RegisterFormData): Promise<LoginResponseData> {
94
+ override async register(
95
+ params: RegisterFormData
96
+ ): Promise<LoginResponseData> {
107
97
  const response = (await this.api.register(
108
98
  params
109
99
  )) as UserApiLoginTransaction['response'];
@@ -3,32 +3,7 @@ import type { AppConfig } from '@/base/cases/AppConfig';
3
3
  import type { IOCRegisterInterface } from '@qlover/corekit-bridge';
4
4
  import { createIOCFunction } from '@qlover/corekit-bridge';
5
5
  import { InversifyContainer } from '@/base/cases/InversifyContainer';
6
- import { IOCIdentifier } from '@config/IOCIdentifier';
7
-
8
- /**
9
- * IOC identifier map
10
- *
11
- * Define the implementation class corresponding to the string identifier
12
- */
13
- export interface IOCIdentifierMap {
14
- [IOCIdentifier.JSON]: import('@qlover/fe-corekit').JSONSerializer;
15
- [IOCIdentifier.LocalStorage]: import('@qlover/fe-corekit').ObjectStorage<
16
- string,
17
- string
18
- >;
19
- [IOCIdentifier.LocalStorageEncrypt]: import('@qlover/fe-corekit').ObjectStorage<
20
- string,
21
- string
22
- >;
23
- [IOCIdentifier.CookieStorage]: import('@qlover/corekit-bridge').CookieStorage;
24
- [IOCIdentifier.Logger]: import('@qlover/logger').LoggerInterface;
25
- [IOCIdentifier.FeApiToken]: import('@qlover/corekit-bridge').TokenStorage<string>;
26
- [IOCIdentifier.FeApiCommonPlugin]: import('@qlover/corekit-bridge').RequestCommonPlugin;
27
- [IOCIdentifier.AppConfig]: import('@qlover/corekit-bridge').EnvConfigInterface;
28
- [IOCIdentifier.ApiMockPlugin]: import('@qlover/corekit-bridge').ApiMockPlugin;
29
- [IOCIdentifier.ApiCatchPlugin]: import('@qlover/corekit-bridge').ApiCatchPlugin;
30
- [IOCIdentifier.DialogHandler]: import('@/base/cases/DialogHandler').DialogHandler;
31
- }
6
+ import { IOCIdentifierMap } from '@config/IOCIdentifier';
32
7
 
33
8
  /**
34
9
  * IOC register options
@@ -0,0 +1,125 @@
1
+ import type { IOCContainer, IOCRegister, IocRegisterOptions } from './IOC';
2
+ import {
3
+ ApiCatchPlugin,
4
+ ApiMockPlugin,
5
+ RequestCommonPlugin,
6
+ ThemeService,
7
+ type IOCManagerInterface
8
+ } from '@qlover/corekit-bridge';
9
+ import * as globals from './globals';
10
+ import { IOCIdentifier as I } from '@config/IOCIdentifier';
11
+ import mockDataJson from '@config/feapi.mock.json';
12
+ import { I18nService } from '@/base/services/I18nService';
13
+ import { themeConfig } from '@config/theme';
14
+ import { useLocaleRoutes } from '@config/common';
15
+ import { baseNoLocaleRoutes, baseRoutes } from '@config/app.router';
16
+ import { SyncStorageInterface } from '@qlover/fe-corekit';
17
+ import { RouteService } from '@/base/services/RouteService';
18
+ import { RequestStatusCatcher } from '@/base/cases/RequestStatusCatcher';
19
+ import { UserService } from '@/base/services/UserService';
20
+ import { I18nKeyErrorPlugin } from '@/base/cases/I18nKeyErrorPlugin';
21
+ import { ProcesserExecutor } from '@/base/services/ProcesserExecutor';
22
+ import { NavigateBridge } from '@/uikit/bridges/NavigateBridge';
23
+ import { ExecutorPageBridge } from '@/uikit/bridges/ExecutorPageBridge';
24
+ import { JSONStoragePageBridge } from '@/uikit/bridges/JSONStoragePageBridge';
25
+ import { RequestPageBridge } from '@/uikit/bridges/RequestPageBridge';
26
+
27
+ export class IocRegisterImpl implements IOCRegister {
28
+ constructor(protected options: IocRegisterOptions) {}
29
+
30
+ /**
31
+ * Register globals
32
+ *
33
+ * 一般用于注册全局
34
+ *
35
+ * @param ioc - IOC container
36
+ */
37
+ protected registerGlobals(ioc: IOCContainer): void {
38
+ const { appConfig } = this.options;
39
+ const { dialogHandler, localStorageEncrypt, JSON, logger } = globals;
40
+
41
+ ioc.bind(I.JSONSerializer, JSON);
42
+ ioc.bind(I.Logger, logger);
43
+ ioc.bind(I.AppConfig, appConfig);
44
+ ioc.bind(I.EnvConfigInterface, appConfig);
45
+ ioc.bind(I.DialogHandler, dialogHandler);
46
+ ioc.bind(I.UIDialogInterface, dialogHandler);
47
+ ioc.bind(I.AntdStaticApiInterface, dialogHandler);
48
+ ioc.bind(I.LocalStorage, globals.localStorage);
49
+ ioc.bind(I.LocalStorageEncrypt, localStorageEncrypt);
50
+ ioc.bind(I.CookieStorage, globals.cookieStorage);
51
+ }
52
+
53
+ /**
54
+ * 一般用于注册没有其他复杂依赖的项目实现类
55
+ *
56
+ * 比如:
57
+ * - 路由服务
58
+ * - 国际化服务
59
+ * - 主题服务
60
+ *
61
+ * @param ioc
62
+ */
63
+ protected registerImplement(ioc: IOCContainer): void {
64
+ ioc.bind(I.I18nServiceInterface, new I18nService(this.options.pathname));
65
+ ioc.bind(
66
+ I.RouteServiceInterface,
67
+ new RouteService(
68
+ ioc.get(NavigateBridge),
69
+ ioc.get(I.I18nServiceInterface),
70
+ {
71
+ routes: useLocaleRoutes ? baseRoutes : baseNoLocaleRoutes,
72
+ logger: ioc.get(I.Logger),
73
+ hasLocalRoutes: useLocaleRoutes
74
+ }
75
+ )
76
+ );
77
+ ioc.bind(
78
+ I.ThemeService,
79
+ new ThemeService({
80
+ ...themeConfig,
81
+ storage: ioc.get<SyncStorageInterface<string, string>>(I.LocalStorage)
82
+ })
83
+ );
84
+
85
+ ioc.bind(I.I18nKeyErrorPlugin, ioc.get(I18nKeyErrorPlugin));
86
+ ioc.bind(I.ProcesserExecutorInterface, ioc.get(ProcesserExecutor));
87
+ ioc.bind(I.UserServiceInterface, ioc.get(UserService));
88
+ ioc.bind(I.RequestCatcherInterface, ioc.get(RequestStatusCatcher));
89
+ ioc.bind(I.ExecutorPageBridgeInterface, ioc.get(ExecutorPageBridge));
90
+ ioc.bind(I.JSONStoragePageInterface, ioc.get(JSONStoragePageBridge));
91
+ ioc.bind(I.RequestPageBridgeInterface, ioc.get(RequestPageBridge));
92
+ }
93
+
94
+ protected registerCommon(ioc: IOCContainer): void {
95
+ const { appConfig } = this.options;
96
+ const logger = ioc.get(I.Logger);
97
+
98
+ const feApiRequestCommonPlugin = new RequestCommonPlugin({
99
+ tokenPrefix: appConfig.openAiTokenPrefix,
100
+ requiredToken: true,
101
+ token: () => ioc.get(UserService).getToken()
102
+ });
103
+ const apiMockPlugin = new ApiMockPlugin(mockDataJson, logger);
104
+ const apiCatchPlugin = new ApiCatchPlugin(
105
+ logger,
106
+ ioc.get(RequestStatusCatcher)
107
+ );
108
+
109
+ ioc.bind(I.FeApiCommonPlugin, feApiRequestCommonPlugin);
110
+ ioc.bind(I.ApiMockPlugin, apiMockPlugin);
111
+ ioc.bind(I.ApiCatchPlugin, apiCatchPlugin);
112
+ }
113
+
114
+ /**
115
+ * @override
116
+ */
117
+ register(
118
+ ioc: IOCContainer,
119
+ _manager: IOCManagerInterface<IOCContainer>
120
+ ): void {
121
+ this.registerGlobals(ioc);
122
+ this.registerCommon(ioc);
123
+ this.registerImplement(ioc);
124
+ }
125
+ }