@qlover/create-app 0.6.0 → 0.6.2

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 (41) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/templates/react-app/config/IOCIdentifier.ts +13 -0
  5. package/dist/templates/react-app/docs/zh/bootstrap.md +555 -0
  6. package/dist/templates/react-app/docs/zh/env.md +480 -0
  7. package/dist/templates/react-app/docs/zh/global.md +510 -0
  8. package/dist/templates/react-app/docs/zh/ioc.md +410 -0
  9. package/dist/templates/react-app/package.json +1 -1
  10. package/dist/templates/react-app/src/base/apis/AiApi.ts +10 -5
  11. package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +1 -1
  12. package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +1 -1
  13. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +10 -17
  14. package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +1 -1
  15. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +2 -1
  16. package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +7 -5
  17. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +3 -2
  18. package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +33 -0
  19. package/dist/templates/react-app/src/base/cases/RequestLogger.ts +1 -1
  20. package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +2 -2
  21. package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +1 -1
  22. package/dist/templates/react-app/src/base/services/RouteService.ts +5 -2
  23. package/dist/templates/react-app/src/base/services/UserService.ts +8 -10
  24. package/dist/templates/react-app/src/core/IOC.ts +73 -83
  25. package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +52 -4
  26. package/dist/templates/react-app/src/core/bootstraps/{index.ts → BootstrapsRegistry.ts} +2 -3
  27. package/dist/templates/react-app/src/core/registers/IocRegisterImpl.ts +25 -0
  28. package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +11 -17
  29. package/dist/templates/react-app/src/core/registers/RegisterControllers.ts +10 -4
  30. package/dist/templates/react-app/src/core/registers/RegisterGlobals.ts +6 -15
  31. package/dist/templates/react-app/src/main.tsx +2 -5
  32. package/dist/templates/react-app/src/uikit/controllers/JSONStorageController.ts +1 -1
  33. package/dist/templates/react-app/tsconfig.app.json +2 -1
  34. package/dist/templates/react-app/tsconfig.node.json +2 -1
  35. package/dist/templates/react-app/vite.config.ts +1 -1
  36. package/package.json +2 -2
  37. package/dist/templates/react-app/src/base/port/ApiTransactionInterface.ts +0 -7
  38. package/dist/templates/react-app/src/base/port/RequestCatcherInterface.ts +0 -12
  39. package/dist/templates/react-app/src/core/bootstrap.ts +0 -58
  40. package/dist/templates/react-app/src/core/registers/RegisterApi.ts +0 -5
  41. package/dist/templates/react-app/src/core/registers/index.ts +0 -32
@@ -0,0 +1,410 @@
1
+ # IOC 容器
2
+
3
+ ## 什么是 IOC?
4
+
5
+ IOC(Inversion of Control,控制反转)是一种设计模式,它将对象的创建和依赖关系的管理交给容器来处理,而不是在代码中直接创建对象。
6
+
7
+ **简单来说**:就像工厂生产产品一样,你不需要知道产品是如何制造的,只需要告诉工厂你需要什么产品,工厂就会给你提供。
8
+
9
+ ## 项目中的 IOC 实现
10
+
11
+ ### 核心技术栈
12
+
13
+ - **InversifyJS**:作为 IOC 容器的实现(你也可以手动实现自己的容器)
14
+ - **TypeScript**:提供类型安全
15
+ - **装饰器模式**:使用 `@injectable()` 和 `@inject()` 装饰器
16
+
17
+ ### 核心文件结构
18
+
19
+ ```
20
+ src/
21
+ ├── core/
22
+ │ ├── IOC.ts # IOC 主入口
23
+ │ ├── registers/ # 注册器目录
24
+ │ │ ├── RegisterGlobals.ts # 全局服务注册
25
+ │ │ ├── RegisterCommon.ts # 通用服务注册
26
+ │ │ └── RegisterControllers.ts # 控制器注册
27
+ │ └── globals.ts # 全局实例
28
+ ├── base/
29
+ │ └── cases/
30
+ │ └── InversifyContainer.ts # Inversify 容器实现
31
+ └── config/
32
+ └── IOCIdentifier.ts # IOC 标识符定义
33
+ ```
34
+
35
+ ## 基本概念
36
+
37
+ ### 1. IOC 标识符
38
+
39
+ ```tsx
40
+ // config/IOCIdentifier.ts
41
+ export const IOCIdentifier = Object.freeze({
42
+ JSON: 'JSON',
43
+ LocalStorage: 'LocalStorage',
44
+ Logger: 'Logger',
45
+ AppConfig: 'AppConfig',
46
+ // ... 更多标识符
47
+ });
48
+ ```
49
+
50
+ ### 2. IOC 标识符映射
51
+
52
+ ```tsx
53
+ // core/IOC.ts
54
+ export interface IOCIdentifierMap {
55
+ [IOCIdentifier.JSON]: import('@qlover/fe-corekit').JSONSerializer;
56
+ [IOCIdentifier.LocalStorage]: import('@qlover/fe-corekit').ObjectStorage<string, string>;
57
+ [IOCIdentifier.Logger]: import('@qlover/logger').LoggerInterface;
58
+ [IOCIdentifier.AppConfig]: import('@qlover/corekit-bridge').EnvConfigInterface;
59
+ // ... 更多映射
60
+ }
61
+ ```
62
+
63
+ ### 3. IOC 函数
64
+
65
+ ```tsx
66
+ // core/IOC.ts
67
+ export const IOC = createIOCFunction<IOCIdentifierMap>(
68
+ new InversifyContainer()
69
+ );
70
+ ```
71
+
72
+ ## 使用方法
73
+
74
+ ### 1. 获取服务实例
75
+
76
+ ```tsx
77
+ // 使用类名获取
78
+ const userService = IOC(UserService);
79
+
80
+ // 使用字符串标识符获取
81
+ const logger = IOC('Logger');
82
+ // 或者
83
+ const logger = IOC(IOCIdentifier.Logger);
84
+
85
+ // 使用 AppConfig
86
+ const appConfig = IOC(IOCIdentifier.AppConfig);
87
+ ```
88
+
89
+ ### 2. 在服务中使用依赖注入
90
+
91
+ ```tsx
92
+ import { inject, injectable } from 'inversify';
93
+ import { UserApi } from '@/base/apis/userApi/UserApi';
94
+ import { RouteService } from './RouteService';
95
+ import { IOCIdentifier } from '@config/IOCIdentifier';
96
+
97
+ @injectable()
98
+ export class UserService extends UserAuthService<UserInfo> {
99
+ constructor(
100
+ @inject(RouteService) protected routerService: RouteService,
101
+ @inject(UserApi) userApi: UserAuthApiInterface<UserInfo>,
102
+ @inject(IOCIdentifier.AppConfig) appConfig: AppConfig,
103
+ @inject(IOCIdentifier.LocalStorageEncrypt) storage: SyncStorageInterface<string, string>
104
+ ) {
105
+ super(userApi, {
106
+ userStorage: {
107
+ key: appConfig.userInfoStorageKey,
108
+ storage: storage
109
+ },
110
+ credentialStorage: {
111
+ key: appConfig.userTokenStorageKey,
112
+ storage: storage
113
+ }
114
+ });
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### 3. 在 Bootstrap 中使用
120
+
121
+ ```tsx
122
+ // 在启动器中注册服务
123
+ bootstrap.use([
124
+ IOC(UserService), // 用户服务
125
+ IOC(I18nService), // 国际化服务
126
+ new UserApiBootstarp() // API 配置
127
+ ]);
128
+ ```
129
+
130
+ ## 服务注册
131
+
132
+ ### 1. 全局服务注册
133
+
134
+ ```tsx
135
+ // core/registers/RegisterGlobals.ts
136
+ export const RegisterGlobals: IOCRegister = {
137
+ register(container, _, options): void {
138
+ // 注册应用配置
139
+ container.bind(IOCIdentifier.AppConfig, options!.appConfig);
140
+
141
+ // 注册日志服务
142
+ container.bind(Logger, logger);
143
+ container.bind(IOCIdentifier.Logger, logger);
144
+
145
+ // 注册存储服务
146
+ container.bind(IOCIdentifier.LocalStorage, localStorage);
147
+ container.bind(IOCIdentifier.LocalStorageEncrypt, localStorageEncrypt);
148
+ container.bind(IOCIdentifier.CookieStorage, cookieStorage);
149
+ }
150
+ };
151
+ ```
152
+
153
+ ### 2. 通用服务注册
154
+
155
+ ```tsx
156
+ // core/registers/RegisterCommon.ts
157
+ export const RegisterCommon: IOCRegister = {
158
+ register(container, _, options): void {
159
+ const AppConfig = container.get(IOCIdentifier.AppConfig);
160
+
161
+ // 注册 API 相关服务
162
+ const feApiToken = new TokenStorage(AppConfig.userTokenStorageKey, {
163
+ storage: container.get(IOCIdentifier.LocalStorageEncrypt)
164
+ });
165
+
166
+ container.bind(IOCIdentifier.FeApiToken, feApiToken);
167
+ container.bind(IOCIdentifier.FeApiCommonPlugin, feApiRequestCommonPlugin);
168
+
169
+ // 注册主题服务
170
+ container.bind(ThemeService, new ThemeService({
171
+ ...themeConfig,
172
+ storage: localStorage
173
+ }));
174
+
175
+ // 注册路由服务
176
+ container.bind(RouteService, new RouteService({
177
+ routes: baseRoutes,
178
+ logger
179
+ }));
180
+
181
+ // 注册国际化服务
182
+ container.bind(I18nService, new I18nService(options!.pathname));
183
+ }
184
+ };
185
+ ```
186
+
187
+ ### 3. 控制器注册
188
+
189
+ ```tsx
190
+ // core/registers/RegisterControllers.ts
191
+ export class RegisterControllers implements IOCRegister {
192
+ register(container: IOCContainer, _: IOCManagerInterface<IOCContainer>): void {
193
+ // 注册控制器
194
+ const jsonStorageController = new JSONStorageController(localStorage);
195
+ container.bind(JSONStorageController, jsonStorageController);
196
+
197
+ // 配置处理器
198
+ container
199
+ .get(ProcesserExecutor)
200
+ .use(container.get(I18nKeyErrorPlugin))
201
+ .use(container.get(UserService));
202
+ }
203
+ }
204
+ ```
205
+
206
+ ## 实际应用场景
207
+
208
+ ### 1. 用户认证服务
209
+
210
+ ```tsx
211
+ @injectable()
212
+ export class UserService extends UserAuthService<UserInfo> {
213
+ constructor(
214
+ @inject(RouteService) protected routerService: RouteService,
215
+ @inject(UserApi) userApi: UserAuthApiInterface<UserInfo>,
216
+ @inject(IOCIdentifier.AppConfig) appConfig: AppConfig,
217
+ @inject(IOCIdentifier.LocalStorageEncrypt) storage: SyncStorageInterface<string, string>
218
+ ) {
219
+ super(userApi, {
220
+ userStorage: {
221
+ key: appConfig.userInfoStorageKey,
222
+ storage: storage
223
+ },
224
+ credentialStorage: {
225
+ key: appConfig.userTokenStorageKey,
226
+ storage: storage
227
+ }
228
+ });
229
+ }
230
+
231
+ async onBefore(): Promise<void> {
232
+ if (this.isAuthenticated()) {
233
+ return;
234
+ }
235
+
236
+ const userToken = this.getToken();
237
+ if (!userToken) {
238
+ throw new AppError('NO_USER_TOKEN');
239
+ }
240
+
241
+ await this.userInfo();
242
+ this.store.authSuccess();
243
+ }
244
+ }
245
+ ```
246
+
247
+ ### 2. API 配置服务
248
+
249
+ ```tsx
250
+ export class UserApiBootstarp implements BootstrapExecutorPlugin {
251
+ readonly pluginName = 'UserApiBootstarp';
252
+
253
+ onBefore({ parameters: { ioc } }: BootstrapContext): void {
254
+ // 通过 IOC 获取 UserApi 实例并配置插件
255
+ ioc
256
+ .get<UserApi>(UserApi)
257
+ .usePlugin(new FetchURLPlugin())
258
+ .usePlugin(IOC.get(IOCIdentifier.ApiMockPlugin))
259
+ .usePlugin(IOC.get(RequestLogger));
260
+ }
261
+ }
262
+ ```
263
+
264
+ ### 3. 在组件中使用
265
+
266
+ ```tsx
267
+ // 在 React 组件中使用 IOC 服务
268
+ function UserProfile() {
269
+ const userService = IOC(UserService);
270
+ const { user } = useStore(userService.store);
271
+
272
+ return (
273
+ <div>
274
+ <h1>欢迎, {user?.name}</h1>
275
+ <button onClick={() => userService.logout()}>退出登录</button>
276
+ </div>
277
+ );
278
+ }
279
+ ```
280
+
281
+ ## 最佳实践
282
+
283
+ ### 1. 服务设计原则
284
+
285
+ ```tsx
286
+ // ✅ 好的设计:单一职责
287
+ @injectable()
288
+ export class UserService {
289
+ constructor(
290
+ @inject(UserApi) private userApi: UserApi,
291
+ @inject(IOCIdentifier.AppConfig) private appConfig: AppConfig
292
+ ) {}
293
+
294
+ async getUserInfo(): Promise<UserInfo> {
295
+ return this.userApi.getUserInfo();
296
+ }
297
+ }
298
+
299
+ // ❌ 不好的设计:职责过多
300
+ @injectable()
301
+ export class BadService {
302
+ constructor(
303
+ @inject(UserApi) private userApi: UserApi,
304
+ @inject(RouteService) private routeService: RouteService,
305
+ @inject(ThemeService) private themeService: ThemeService,
306
+ @inject(I18nService) private i18nService: I18nService
307
+ ) {}
308
+
309
+ // 一个服务做了太多事情
310
+ async handleUserAction(): Promise<void> {
311
+ // 处理用户逻辑
312
+ // 处理路由逻辑
313
+ // 处理主题逻辑
314
+ // 处理国际化逻辑
315
+ }
316
+ }
317
+ ```
318
+
319
+ ### 2. 依赖注入的最佳实践
320
+
321
+ ```tsx
322
+ // ✅ 使用接口而不是具体实现
323
+ @injectable()
324
+ export class UserService {
325
+ constructor(
326
+ @inject('UserApiInterface') private userApi: UserAuthApiInterface<UserInfo>
327
+ ) {}
328
+ }
329
+
330
+ // ✅ 使用标识符而不是类名
331
+ @injectable()
332
+ export class SomeService {
333
+ constructor(
334
+ @inject(IOCIdentifier.Logger) private logger: LoggerInterface,
335
+ @inject(IOCIdentifier.AppConfig) private appConfig: AppConfig
336
+ ) {}
337
+ }
338
+ ```
339
+
340
+ ### 3. 错误处理
341
+
342
+ ```tsx
343
+ @injectable()
344
+ export class SafeService {
345
+ constructor(
346
+ @inject(IOCIdentifier.Logger) private logger: LoggerInterface
347
+ ) {}
348
+
349
+ async doSomething(): Promise<void> {
350
+ try {
351
+ // 业务逻辑
352
+ } catch (error) {
353
+ this.logger.error('操作失败:', error);
354
+ throw error;
355
+ }
356
+ }
357
+ }
358
+ ```
359
+
360
+ ## 调试和测试
361
+
362
+ ### 1. 调试 IOC 容器
363
+
364
+ ```tsx
365
+ // 检查服务是否已注册
366
+ const container = IOC.implemention;
367
+ const isRegistered = container.isBound(UserService);
368
+
369
+ // 获取所有已注册的服务
370
+ const bindings = container.getAll(UserService);
371
+ ```
372
+
373
+ ### 2. 单元测试
374
+
375
+ ```tsx
376
+ import { Container } from 'inversify';
377
+
378
+ describe('UserService', () => {
379
+ let container: Container;
380
+ let userService: UserService;
381
+
382
+ beforeEach(() => {
383
+ container = new Container();
384
+
385
+ // 注册测试依赖
386
+ container.bind('UserApiInterface').toConstantValue(mockUserApi);
387
+ container.bind(IOCIdentifier.AppConfig).toConstantValue(mockAppConfig);
388
+ container.bind(IOCIdentifier.LocalStorageEncrypt).toConstantValue(mockStorage);
389
+
390
+ userService = container.get(UserService);
391
+ });
392
+
393
+ it('should authenticate user successfully', async () => {
394
+ const result = await userService.onBefore();
395
+ expect(result).toBeDefined();
396
+ });
397
+ });
398
+ ```
399
+
400
+ ## 总结
401
+
402
+ IOC 容器在项目中的作用:
403
+
404
+ 1. **依赖管理**:统一管理所有服务的依赖关系
405
+ 2. **类型安全**:通过 TypeScript 提供编译时类型检查
406
+ 3. **可测试性**:便于进行单元测试和模拟
407
+ 4. **可维护性**:清晰的依赖关系,易于理解和修改
408
+ 5. **可扩展性**:轻松添加新的服务和依赖
409
+
410
+ 通过合理使用 IOC 容器,可以让代码更加模块化、可测试和可维护。
@@ -46,7 +46,7 @@
46
46
  "dev": "vite --mode localhost",
47
47
  "dev:staging": "vite --mode staging",
48
48
  "dev:prod": "vite --mode production",
49
- "build": "vite build",
49
+ "build": "npm run lint && vite build",
50
50
  "lint": "tsc -b --noEmit && eslint ./src --fix",
51
51
  "prettier": "prettier --write ./src",
52
52
  "preview": "vite preview",
@@ -8,11 +8,11 @@ import {
8
8
  RequestCommonPlugin
9
9
  } from '@qlover/corekit-bridge';
10
10
  import { RequestLogger } from '../cases/RequestLogger';
11
- import { IOCIdentifier } from '@/core/IOC';
12
- import { appConfig } from '@/core/globals';
11
+ import { IOCIdentifier } from '@config/IOCIdentifier';
12
+ import type { AppConfig } from '../cases/AppConfig';
13
13
 
14
14
  const apiApiAdapter = new RequestAdapterFetch({
15
- baseURL: appConfig.aiApiBaseUrl
15
+ responseType: 'json'
16
16
  });
17
17
 
18
18
  // 使用 RequestScheduler
@@ -24,6 +24,11 @@ const apiApi = new RequestScheduler(apiApiAdapter);
24
24
  export const AiApiBootstarp: BootstrapExecutorPlugin = {
25
25
  pluginName: 'AiApiBootstarp',
26
26
  onBefore({ parameters: { ioc } }) {
27
+ const appConfig = ioc.get<AppConfig>(IOCIdentifier.AppConfig);
28
+
29
+ // dynamic set baseURL
30
+ apiApiAdapter.config.baseURL = appConfig.aiApiBaseUrl;
31
+
27
32
  apiApiAdapter.usePlugin(new FetchURLPlugin());
28
33
  apiApiAdapter.usePlugin(
29
34
  new RequestCommonPlugin({
@@ -40,13 +45,13 @@ export function aiHello(data: {
40
45
  messages: { role: string; content: string }[];
41
46
  }) {
42
47
  return apiApi.request<
43
- typeof data,
44
48
  {
45
49
  id: string;
46
50
  object: string;
47
51
  created: number;
48
52
  choices: { message: { role: string; content: string } }[];
49
- }
53
+ },
54
+ typeof data
50
55
  >({
51
56
  url: '/chat/completions',
52
57
  method: 'POST',
@@ -1,5 +1,5 @@
1
1
  import type { AppConfig } from '@/base/cases/AppConfig';
2
- import { IOCIdentifier } from '@/core/IOC';
2
+ import { IOCIdentifier } from '@config/IOCIdentifier';
3
3
  import { RequestAdapterFetch } from '@qlover/fe-corekit';
4
4
  import { inject, injectable } from 'inversify';
5
5
 
@@ -11,7 +11,7 @@ import {
11
11
  ApiPickDataPlugin
12
12
  } from '@qlover/corekit-bridge';
13
13
  import { FeApi } from './FeApi';
14
- import { IOCIdentifier } from '@/core/IOC';
14
+ import { IOCIdentifier } from '@config/IOCIdentifier';
15
15
  import { RequestLogger } from '@/base/cases/RequestLogger';
16
16
 
17
17
  /**
@@ -7,26 +7,21 @@ import {
7
7
  GetIpInfoTransaction,
8
8
  UserApiGetUserInfoTransaction,
9
9
  UserApiLoginTransaction,
10
- UserApiTestApiCatchResultTransaction
10
+ UserApiTestApiCatchResultTransaction,
11
+ UserInfo
11
12
  } from './UserApiType';
12
13
  import { inject, injectable } from 'inversify';
13
14
  import { UserApiAdapter } from './UserApiAdapter';
14
15
  import { UserApiConfig } from './UserApiBootstarp';
15
- import {
16
+ import type {
16
17
  LoginResponseData,
17
18
  UserAuthApiInterface,
18
- UserAuthStoreInterface,
19
- UserAuthState
19
+ UserAuthStoreInterface
20
20
  } from '@qlover/corekit-bridge';
21
- import {
22
- RegisterFormData,
23
- UserServiceUserInfo
24
- } from '@/base/services/UserService';
21
+ import { RegisterFormData } from '@/base/services/UserService';
25
22
  import { RES_NO_TOKEN } from '@config/Identifier';
26
23
  import { AppError } from '@/base/cases/AppError';
27
24
 
28
- export type UserApiState = UserAuthState<UserServiceUserInfo>;
29
-
30
25
  /**
31
26
  * UserApi
32
27
  *
@@ -37,9 +32,9 @@ export type UserApiState = UserAuthState<UserServiceUserInfo>;
37
32
  @injectable()
38
33
  export class UserApi
39
34
  extends RequestTransaction<UserApiConfig>
40
- implements UserAuthApiInterface<UserApiState>
35
+ implements UserAuthApiInterface<UserInfo>
41
36
  {
42
- protected store: UserAuthStoreInterface<UserApiState> | null = null;
37
+ protected store: UserAuthStoreInterface<UserInfo> | null = null;
43
38
 
44
39
  constructor(
45
40
  @inject(FetchAbortPlugin) private abortPlugin: FetchAbortPlugin,
@@ -48,7 +43,7 @@ export class UserApi
48
43
  super(adapter);
49
44
  }
50
45
 
51
- getStore(): UserAuthStoreInterface<UserApiState> | null {
46
+ getStore(): UserAuthStoreInterface<UserInfo> | null {
52
47
  return this.store;
53
48
  }
54
49
 
@@ -56,7 +51,7 @@ export class UserApi
56
51
  * @override
57
52
  * @param store
58
53
  */
59
- setStore(store: UserAuthStoreInterface<UserApiState>): void {
54
+ setStore(store: UserAuthStoreInterface<UserInfo>): void {
60
55
  this.store = store;
61
56
  }
62
57
 
@@ -130,9 +125,7 @@ export class UserApi
130
125
  * @override
131
126
  * @returns
132
127
  */
133
- async getUserInfo(): Promise<
134
- UserApiGetUserInfoTransaction['response']['data']
135
- > {
128
+ async getUserInfo(): Promise<UserInfo> {
136
129
  const response =
137
130
  await this.get<UserApiGetUserInfoTransaction>('/api/userinfo');
138
131
 
@@ -1,5 +1,5 @@
1
1
  import type { AppConfig } from '@/base/cases/AppConfig';
2
- import { IOCIdentifier } from '@/core/IOC';
2
+ import { IOCIdentifier } from '@config/IOCIdentifier';
3
3
  import { RequestAdapterFetch } from '@qlover/fe-corekit';
4
4
  import { inject, injectable } from 'inversify';
5
5
 
@@ -4,7 +4,8 @@ import {
4
4
  RequestAdapterResponse,
5
5
  RequestTransactionInterface
6
6
  } from '@qlover/fe-corekit';
7
- import { IOC, IOCIdentifier } from '@/core/IOC';
7
+ import { IOC } from '@/core/IOC';
8
+ import { IOCIdentifier } from '@config/IOCIdentifier';
8
9
  import { RequestLogger } from '@/base/cases/RequestLogger';
9
10
  import { FetchURLPlugin } from '@qlover/fe-corekit';
10
11
  import {
@@ -1,5 +1,11 @@
1
1
  import { UserApiTransaction } from './UserApiBootstarp';
2
2
 
3
+ export type UserInfo = {
4
+ name: string;
5
+ email: string;
6
+ picture: string;
7
+ };
8
+
3
9
  export type GetIpInfoTransaction = UserApiTransaction<
4
10
  undefined,
5
11
  {
@@ -35,11 +41,7 @@ export type UserApiGetRandomUser = UserApiTransaction<
35
41
 
36
42
  export type UserApiGetUserInfoTransaction = UserApiTransaction<
37
43
  string,
38
- {
39
- name: string;
40
- email: string;
41
- picture: string;
42
- }
44
+ UserInfo
43
45
  >;
44
46
 
45
47
  export type UserApiLoginTransaction = UserApiTransaction<
@@ -1,14 +1,15 @@
1
1
  import type { ExecutorContext, ExecutorPlugin } from '@qlover/fe-corekit';
2
2
  import type { LoggerInterface } from '@qlover/logger';
3
- import { inject } from 'inversify';
3
+ import { inject, injectable } from 'inversify';
4
4
  import { I18nService } from '../services/I18nService';
5
- import { IOCIdentifier } from '@/core/IOC';
5
+ import { IOCIdentifier } from '@config/IOCIdentifier';
6
6
 
7
7
  /**
8
8
  * When throw error, it will be converted to i18n key
9
9
  *
10
10
  * If the error thrown is an i18n key, it will be converted to the corresponding text
11
11
  */
12
+ @injectable()
12
13
  export class I18nKeyErrorPlugin implements ExecutorPlugin {
13
14
  readonly pluginName = 'I18nKeyErrorPlugin';
14
15
 
@@ -0,0 +1,33 @@
1
+ import { IOCIdentifierMap } from '@/core/IOC';
2
+ import {
3
+ IOCContainerInterface,
4
+ ServiceIdentifier
5
+ } from '@qlover/corekit-bridge';
6
+ import { Container } from 'inversify';
7
+
8
+ export class InversifyContainer implements IOCContainerInterface {
9
+ private container: Container;
10
+
11
+ constructor() {
12
+ this.container = new Container({
13
+ // allow `@injectable` decorator, auto bind injectable classes
14
+ autobind: true,
15
+ // use singleton scope
16
+ defaultScope: 'Singleton'
17
+ });
18
+ }
19
+
20
+ bind<T>(key: ServiceIdentifier<T>, value: T): void {
21
+ this.container.bind<T>(key).toConstantValue(value);
22
+ }
23
+
24
+ get<K extends keyof IOCIdentifierMap>(
25
+ serviceIdentifier: K
26
+ ): IOCIdentifierMap[K];
27
+ get<T>(serviceIdentifier: ServiceIdentifier<T>): T;
28
+ get<T, K extends keyof IOCIdentifierMap>(
29
+ serviceIdentifier: ServiceIdentifier<T> | K
30
+ ): T | IOCIdentifierMap[K] {
31
+ return this.container.get<T>(serviceIdentifier);
32
+ }
33
+ }
@@ -1,4 +1,4 @@
1
- import { IOCIdentifier } from '@/core/IOC';
1
+ import { IOCIdentifier } from '@config/IOCIdentifier';
2
2
  import {
3
3
  type ExecutorPlugin,
4
4
  type ExecutorContext,
@@ -1,5 +1,5 @@
1
- import type { RequestCatcherInterface } from '@/base/port/RequestCatcherInterface';
2
- import { IOCIdentifier } from '@/core/IOC';
1
+ import { IOCIdentifier } from '@config/IOCIdentifier';
2
+ import type { RequestCatcherInterface } from '@qlover/corekit-bridge';
3
3
  import type { RequestAdapterResponse } from '@qlover/fe-corekit';
4
4
  import type { LoggerInterface } from '@qlover/logger';
5
5
  import { inject, injectable } from 'inversify';
@@ -1,5 +1,5 @@
1
1
  import { AsyncExecutor, ExecutorPlugin } from '@qlover/fe-corekit';
2
- import { IOCIdentifier } from '@/core/IOC';
2
+ import { IOCIdentifier } from '@config/IOCIdentifier';
3
3
  import { injectable, inject } from 'inversify';
4
4
  import type { LoggerInterface } from '@qlover/logger';
5
5
  import { RouteService } from './RouteService';
@@ -3,7 +3,10 @@ import type { NavigateFunction, NavigateOptions } from 'react-router-dom';
3
3
  import type { UIDependenciesInterface } from '@/base/port/UIDependenciesInterface';
4
4
  import type { LoggerInterface } from '@qlover/logger';
5
5
  import { I18nService } from '@/base/services/I18nService';
6
- import { StoreInterface, StoreStateInterface } from '@qlover/corekit-bridge';
6
+ import {
7
+ StoreInterface,
8
+ type StoreStateInterface
9
+ } from '@qlover/corekit-bridge';
7
10
 
8
11
  export type RouterServiceDependencies = {
9
12
  navigate: NavigateFunction;
@@ -40,7 +43,7 @@ export class RouteService
40
43
 
41
44
  if (!navigate) {
42
45
  this.logger.debug(
43
- 'Please use `RouterServiceProvider` to set dependencies'
46
+ 'Please use `RouteService.setDependencies` to set dependencies'
44
47
  );
45
48
  }
46
49