@qlover/create-app 0.12.0 → 1.0.1

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 (68) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/templates/next-app/next.config.ts +4 -3
  5. package/dist/templates/next-app/package.json +12 -9
  6. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +2 -3
  7. package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +6 -4
  8. package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +14 -10
  9. package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +2 -2
  10. package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +1 -4
  11. package/dist/templates/next-app/src/base/services/I18nService.ts +6 -2
  12. package/dist/templates/next-app/src/base/services/adminApi/AdminApiRequester.ts +11 -7
  13. package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +11 -10
  14. package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +16 -12
  15. package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +19 -19
  16. package/dist/templates/next-app/src/base/services/appApi/AppApiRequester.ts +26 -21
  17. package/dist/templates/next-app/src/base/services/appApi/AppUserApi.ts +15 -6
  18. package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +12 -14
  19. package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +34 -17
  20. package/dist/templates/next-app/src/server/NextApiServer.ts +10 -4
  21. package/dist/templates/next-app/src/server/PasswordEncrypt.ts +2 -2
  22. package/dist/templates/next-app/src/server/controllers/UserController.ts +2 -2
  23. package/dist/templates/next-app/src/server/port/ServerInterface.ts +2 -2
  24. package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +6 -7
  25. package/dist/templates/next-app/src/server/services/UserService.ts +2 -2
  26. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +11 -47
  27. package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +3 -2
  28. package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +6 -1
  29. package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +21 -61
  30. package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +29 -51
  31. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +8 -26
  32. package/dist/templates/react-app/__tests__/src/main.test.tsx +2 -2
  33. package/dist/templates/react-app/config/IOCIdentifier.ts +1 -1
  34. package/dist/templates/react-app/docs/en/test-guide.md +5 -5
  35. package/dist/templates/react-app/docs/zh/test-guide.md +5 -5
  36. package/dist/templates/react-app/package.json +2 -1
  37. package/dist/templates/react-app/src/base/apis/AiApi.ts +20 -12
  38. package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +14 -5
  39. package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +26 -13
  40. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +30 -34
  41. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +20 -17
  42. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +11 -5
  43. package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +19 -6
  44. package/dist/templates/react-app/src/base/cases/RequestLogger.ts +11 -11
  45. package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +11 -5
  46. package/dist/templates/react-app/src/base/services/UserBootstrap.ts +6 -7
  47. package/dist/templates/react-app/src/base/services/UserService.ts +1 -5
  48. package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +6 -7
  49. package/dist/templates/react-app/src/main.tsx +1 -1
  50. package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +5 -5
  51. package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +3 -1
  52. package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +6 -2
  53. package/dist/templates/react-app/src/pages/base/MessagePage.tsx +34 -3
  54. package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +13 -7
  55. package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +6 -1
  56. package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +26 -11
  57. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +1 -1
  58. package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +3 -1
  59. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +16 -7
  60. package/dist/templates/react-app/src/vite-env.d.ts +1 -1
  61. package/dist/templates/react-app/tsconfig.e2e.json +5 -2
  62. package/dist/templates/react-app/tsconfig.json +7 -0
  63. package/dist/templates/react-app/tsconfig.node.json +4 -2
  64. package/dist/templates/react-app/tsconfig.test.json +4 -1
  65. package/package.json +3 -3
  66. package/dist/templates/react-app/src/base/cases/AppError.ts +0 -10
  67. package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +0 -20
  68. package/dist/templates/react-app/src/base/services/UserGatewayPlugin.ts +0 -20
@@ -10,17 +10,14 @@
10
10
  */
11
11
 
12
12
  import { MockLogger } from '@__mocks__/MockLogger';
13
+ import {
14
+ ExecutorContextImpl,
15
+ type RequestAdapterFetchConfig,
16
+ type RequestAdapterResponse
17
+ } from '@qlover/fe-corekit';
13
18
  import { describe, it, expect, beforeEach, vi } from 'vitest';
14
19
  import { RequestLogger } from '@/base/cases/RequestLogger';
15
- import type {
16
- ApiCatchPluginConfig,
17
- ApiCatchPluginResponse
18
- } from '@qlover/corekit-bridge';
19
- import type {
20
- ExecutorContext,
21
- RequestAdapterFetchConfig,
22
- RequestAdapterResponse
23
- } from '@qlover/fe-corekit';
20
+ import type { ApiCatchPluginResponse } from '@qlover/corekit-bridge';
24
21
 
25
22
  describe('RequestLogger', () => {
26
23
  let logger: MockLogger;
@@ -46,16 +43,11 @@ describe('RequestLogger', () => {
46
43
 
47
44
  describe('onBefore', () => {
48
45
  it('should log request details before execution', () => {
49
- const context: ExecutorContext<RequestAdapterFetchConfig<unknown>> = {
50
- parameters: {
51
- method: 'GET',
52
- url: 'https://api.example.com/data',
53
- headers: { 'Content-Type': 'application/json' }
54
- },
55
- returnValue: undefined,
56
- hooksRuntimes: {}
57
- };
58
-
46
+ const context = new ExecutorContextImpl({
47
+ method: 'GET',
48
+ url: 'https://api.example.com/data',
49
+ headers: { 'Content-Type': 'application/json' }
50
+ });
59
51
  requestLogger.onBefore(context);
60
52
 
61
53
  expect(logger.log).toHaveBeenCalledWith(
@@ -70,17 +62,12 @@ describe('RequestLogger', () => {
70
62
  describe('onSuccess', () => {
71
63
  it('should log successful response', async () => {
72
64
  const response = { data: { id: 1 }, status: 200 };
73
- const context: ExecutorContext<
74
- RequestAdapterFetchConfig & ApiCatchPluginConfig
75
- > = {
76
- parameters: {
77
- method: 'POST',
78
- url: 'https://api.example.com/create',
79
- headers: { 'Content-Type': 'application/json' }
80
- },
81
- returnValue: response,
82
- hooksRuntimes: {}
83
- };
65
+ const context = new ExecutorContextImpl({
66
+ method: 'POST',
67
+ url: 'https://api.example.com/create',
68
+ headers: { 'Content-Type': 'application/json' }
69
+ });
70
+ context.setReturnValue(response);
84
71
 
85
72
  await requestLogger.onSuccess(context);
86
73
 
@@ -111,17 +98,12 @@ describe('RequestLogger', () => {
111
98
  response: new Response(),
112
99
  apiCatchResult: apiError
113
100
  };
114
- const context: ExecutorContext<
115
- RequestAdapterFetchConfig & ApiCatchPluginConfig
116
- > = {
117
- parameters: {
118
- method: 'GET',
119
- url: 'https://api.example.com/error',
120
- headers: {}
121
- },
122
- returnValue: response,
123
- hooksRuntimes: {}
124
- };
101
+ const context = new ExecutorContextImpl({
102
+ method: 'GET',
103
+ url: 'https://api.example.com/error',
104
+ headers: {}
105
+ });
106
+ context.setReturnValue(response);
125
107
 
126
108
  await requestLogger.onSuccess(context);
127
109
 
@@ -137,16 +119,12 @@ describe('RequestLogger', () => {
137
119
  describe('onError', () => {
138
120
  it('should log request error', () => {
139
121
  const error = new Error('Network error');
140
- const context: ExecutorContext<RequestAdapterFetchConfig> = {
141
- parameters: {
142
- method: 'PUT',
143
- url: 'https://api.example.com/update',
144
- headers: {}
145
- },
146
- error,
147
- returnValue: undefined,
148
- hooksRuntimes: {}
149
- };
122
+ const context = new ExecutorContextImpl({
123
+ method: 'PUT',
124
+ url: 'https://api.example.com/update',
125
+ headers: {}
126
+ });
127
+ context.setError(error);
150
128
 
151
129
  requestLogger.onError(context);
152
130
 
@@ -19,7 +19,6 @@ import type {
19
19
  IOCContainerInterface,
20
20
  IOCFunctionInterface
21
21
  } from '@qlover/corekit-bridge';
22
- import type { ExecutorPlugin } from '@qlover/fe-corekit';
23
22
 
24
23
  describe('BootstrapClient', () => {
25
24
  describe('bootstrap start flow', () => {
@@ -98,18 +97,19 @@ describe('BootstrapClient', () => {
98
97
  });
99
98
 
100
99
  it('should handle bootstrap UserApiBootstarp', async () => {
101
- const mockUserService: ExecutorPlugin = {
102
- pluginName: 'TestUserService',
103
- onBefore: vi.fn().mockResolvedValue(undefined)
100
+ const mockOnExec = vi.fn().mockResolvedValue(undefined);
101
+ const mockUserBootstrap: BootstrapExecutorPlugin = {
102
+ pluginName: 'TestUserBootstrap',
103
+ onExec: mockOnExec
104
104
  };
105
105
  // 将 mock 函数提取出来,以便验证是否被调用
106
106
  const mockRegister = vi
107
107
  .fn()
108
108
  .mockImplementationOnce(
109
109
  (
110
- ioc: IOCFunctionInterface<IOCIdentifierMap, IOCContainerInterface>
110
+ _ioc: IOCFunctionInterface<IOCIdentifierMap, IOCContainerInterface>
111
111
  ) => {
112
- return [ioc.get(I.UserServiceInterface)];
112
+ return [mockUserBootstrap];
113
113
  }
114
114
  );
115
115
 
@@ -121,20 +121,6 @@ describe('BootstrapClient', () => {
121
121
  root: mockRoot,
122
122
  bootHref: mockRoot.location.href,
123
123
  ioc: testIOC,
124
- iocRegister: {
125
- register: vi
126
- .fn()
127
- .mockImplementationOnce(
128
- (
129
- ioc: IOCFunctionInterface<
130
- IOCIdentifierMap,
131
- IOCContainerInterface
132
- >
133
- ) => {
134
- ioc.bind(I.UserServiceInterface, mockUserService as any);
135
- }
136
- )
137
- },
138
124
  RegistryClass: TestBootstrapsRegistry
139
125
  };
140
126
 
@@ -142,12 +128,8 @@ describe('BootstrapClient', () => {
142
128
  const ioc = testIOC.getIoc();
143
129
  expect(ioc).toBeDefined();
144
130
 
145
- const userService = ioc!.get(I.UserServiceInterface);
146
-
147
- expect(userService).toBeDefined();
148
- expect(userService).toEqual(mockUserService);
149
- expect(userService.pluginName).toBe('TestUserService');
150
- expect(userService.onBefore).toBeCalled();
131
+ expect(mockRegister).toBeCalled();
132
+ expect(mockOnExec).toBeCalled();
151
133
  });
152
134
  });
153
135
  });
@@ -1,9 +1,9 @@
1
1
  import { BootstrapClient } from '@/core/bootstraps/BootstrapClient';
2
2
 
3
- // Mock BootstrapApp
3
+ // Mock BootstrapApp - must return a resolved promise to prevent hanging
4
4
  vi.mock('@/core/bootstraps/BootstrapClient', () => ({
5
5
  BootstrapClient: {
6
- main: vi.fn()
6
+ main: vi.fn().mockResolvedValue({})
7
7
  }
8
8
  }));
9
9
 
@@ -81,7 +81,7 @@ export interface IOCIdentifierMap {
81
81
  [IOCIdentifier.RouteServiceInterface]: RouteService;
82
82
  [IOCIdentifier.UserServiceInterface]: UserService;
83
83
  [IOCIdentifier.I18nKeyErrorPlugin]: I18nKeyErrorPlugin;
84
- [IOCIdentifier.FeApiCommonPlugin]: CorekitBridge.RequestCommonPlugin;
84
+ [IOCIdentifier.FeApiCommonPlugin]: FeCorekit.RequestPlugin;
85
85
  [IOCIdentifier.ApiMockPlugin]: CorekitBridge.ApiMockPlugin;
86
86
  [IOCIdentifier.ApiCatchPlugin]: CorekitBridge.ApiCatchPlugin;
87
87
  [IOCIdentifier.ThemeService]: CorekitBridge.ThemeService;
@@ -652,7 +652,7 @@ describe('TypeSafetyTests', () => {
652
652
 
653
653
  it('should infer correct return types', () => {
654
654
  const result = getData();
655
-
655
+
656
656
  // Verify return type
657
657
  expectTypeOf(result).toEqualTypeOf<{ id: number; name: string }>();
658
658
  expectTypeOf(result).not.toEqualTypeOf<{ id: string; name: string }>();
@@ -682,7 +682,7 @@ describe('Generic Type Tests', () => {
682
682
  }
683
683
 
684
684
  const storage = new Storage<User>();
685
-
685
+
686
686
  // Verify generic type
687
687
  expectTypeOf(storage.store).parameter(0).toMatchTypeOf<User>();
688
688
  expectTypeOf(storage.store).returns.toMatchTypeOf<User>();
@@ -755,7 +755,7 @@ describe('Type Narrowing Tests', () => {
755
755
  }
756
756
 
757
757
  const value: unknown = 'test';
758
-
758
+
759
759
  if (isString(value)) {
760
760
  // Within this scope, value should be narrowed to string type
761
761
  expectTypeOf(value).toEqualTypeOf<string>();
@@ -763,7 +763,7 @@ describe('Type Narrowing Tests', () => {
763
763
  });
764
764
 
765
765
  it('should validate discriminated unions', () => {
766
- type Shape =
766
+ type Shape =
767
767
  | { kind: 'circle'; radius: number }
768
768
  | { kind: 'rectangle'; width: number; height: number };
769
769
 
@@ -812,7 +812,7 @@ describe('Combined Runtime and Type Tests', () => {
812
812
  describe('Type Inference Tests', () => {
813
813
  it('should infer types correctly', () => {
814
814
  const data = { id: 1, name: 'John' };
815
-
815
+
816
816
  // Verify inferred type
817
817
  expectTypeOf(data).toEqualTypeOf<{ id: number; name: string }>();
818
818
  expectTypeOf(data.id).toEqualTypeOf<number>();
@@ -652,7 +652,7 @@ describe('TypeSafetyTests', () => {
652
652
 
653
653
  it('should infer correct return types', () => {
654
654
  const result = getData();
655
-
655
+
656
656
  // 验证返回值类型
657
657
  expectTypeOf(result).toEqualTypeOf<{ id: number; name: string }>();
658
658
  expectTypeOf(result).not.toEqualTypeOf<{ id: string; name: string }>();
@@ -682,7 +682,7 @@ describe('Generic Type Tests', () => {
682
682
  }
683
683
 
684
684
  const storage = new Storage<User>();
685
-
685
+
686
686
  // 验证泛型类型
687
687
  expectTypeOf(storage.store).parameter(0).toMatchTypeOf<User>();
688
688
  expectTypeOf(storage.store).returns.toMatchTypeOf<User>();
@@ -755,7 +755,7 @@ describe('Type Narrowing Tests', () => {
755
755
  }
756
756
 
757
757
  const value: unknown = 'test';
758
-
758
+
759
759
  if (isString(value)) {
760
760
  // 在此作用域内,value 应该被窄化为 string 类型
761
761
  expectTypeOf(value).toEqualTypeOf<string>();
@@ -763,7 +763,7 @@ describe('Type Narrowing Tests', () => {
763
763
  });
764
764
 
765
765
  it('should validate discriminated unions', () => {
766
- type Shape =
766
+ type Shape =
767
767
  | { kind: 'circle'; radius: number }
768
768
  | { kind: 'rectangle'; width: number; height: number };
769
769
 
@@ -812,7 +812,7 @@ describe('Combined Runtime and Type Tests', () => {
812
812
  describe('Type Inference Tests', () => {
813
813
  it('should infer types correctly', () => {
814
814
  const data = { id: 1, name: 'John' };
815
-
815
+
816
816
  // 验证推断的类型
817
817
  expectTypeOf(data).toEqualTypeOf<{ id: number; name: string }>();
818
818
  expectTypeOf(data.id).toEqualTypeOf<number>();
@@ -52,7 +52,8 @@
52
52
  "test:e2e:chromium": "playwright test --project=chromium",
53
53
  "test:e2e:firefox": "playwright test --project=firefox",
54
54
  "test:e2e:webkit": "playwright test --project=webkit",
55
- "test:e2e:report": "playwright show-report playwright-report"
55
+ "test:e2e:report": "playwright show-report playwright-report",
56
+ "type-check": "tsc --build"
56
57
  },
57
58
  "dependencies": {
58
59
  "@brain-toolkit/antd-blocks": "^0.0.1",
@@ -1,22 +1,30 @@
1
1
  import { IOCIdentifier } from '@config/IOCIdentifier';
2
+ import { type BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
2
3
  import {
3
- type BootstrapExecutorPlugin,
4
- RequestCommonPlugin
5
- } from '@qlover/corekit-bridge';
6
- import {
7
- FetchURLPlugin,
4
+ LifecycleExecutor,
8
5
  RequestAdapterFetch,
9
- RequestScheduler
6
+ RequestExecutor,
7
+ RequestPlugin,
8
+ ResponsePlugin
10
9
  } from '@qlover/fe-corekit';
11
10
  import { RequestLogger } from '../cases/RequestLogger';
12
11
  import type { AppConfig } from '../cases/AppConfig';
12
+ import type {
13
+ ExecutorContextInterface,
14
+ RequestAdapterFetchConfig
15
+ } from '@qlover/fe-corekit';
13
16
 
14
17
  const apiApiAdapter = new RequestAdapterFetch({
15
18
  responseType: 'json'
16
19
  });
17
20
 
18
21
  // 使用 RequestScheduler
19
- const apiApi = new RequestScheduler(apiApiAdapter);
22
+ const apiApi = new RequestExecutor(
23
+ apiApiAdapter,
24
+ new LifecycleExecutor<
25
+ ExecutorContextInterface<RequestAdapterFetchConfig, unknown>
26
+ >()
27
+ );
20
28
 
21
29
  // 直接使用 adapter
22
30
  // const apiApi = apiApiAdapter;
@@ -29,15 +37,15 @@ export const AiApiBootstarp: BootstrapExecutorPlugin = {
29
37
  // dynamic set baseURL
30
38
  apiApiAdapter.config.baseURL = appConfig.aiApiBaseUrl;
31
39
 
32
- apiApiAdapter.usePlugin(new FetchURLPlugin());
33
- apiApiAdapter.usePlugin(
34
- new RequestCommonPlugin({
40
+ apiApi.use(
41
+ new RequestPlugin({
35
42
  tokenPrefix: appConfig.aiApiTokenPrefix,
36
43
  token: appConfig.aiApiToken
37
44
  })
38
45
  );
39
- apiApiAdapter.usePlugin(ioc.get(IOCIdentifier.ApiMockPlugin));
40
- apiApiAdapter.usePlugin(ioc.get(RequestLogger));
46
+ apiApi.use(ioc.get(ResponsePlugin));
47
+ apiApi.use(ioc.get(IOCIdentifier.ApiMockPlugin));
48
+ apiApi.use(ioc.get(RequestLogger));
41
49
  }
42
50
  };
43
51
 
@@ -1,17 +1,26 @@
1
- import { RequestAdapterFetch, RequestScheduler } from '@qlover/fe-corekit';
1
+ import {
2
+ ExecutorContextInterface,
3
+ LifecycleExecutor,
4
+ RequestAdapterFetch,
5
+ RequestExecutor
6
+ } from '@qlover/fe-corekit';
2
7
  import { inject, injectable } from 'inversify';
3
8
  import { FeApiAdapter } from './FeApiAdapter';
4
9
  import { FeApiConfig } from './FeApiBootstarp';
5
10
  import { FeApiGetIpInfo } from './FeApiType';
6
11
 
7
12
  @injectable()
8
- export class FeApi extends RequestScheduler<FeApiConfig> {
13
+ export class FeApi extends RequestExecutor<
14
+ FeApiConfig,
15
+ ExecutorContextInterface<FeApiConfig>
16
+ > {
9
17
  constructor(@inject(FeApiAdapter) adapter: RequestAdapterFetch) {
10
- super(adapter);
18
+ super(
19
+ adapter,
20
+ new LifecycleExecutor<ExecutorContextInterface<FeApiConfig, unknown>>()
21
+ );
11
22
  }
12
23
 
13
- public stop(_config: FeApiConfig): void {}
14
-
15
24
  public async getIpInfo(): Promise<FeApiGetIpInfo['response']> {
16
25
  return this.get('http://ip-api.com/json/') as unknown as Promise<
17
26
  FeApiGetIpInfo['response']
@@ -1,18 +1,25 @@
1
- import { IOCIdentifier } from '@config/IOCIdentifier';
1
+ import { I } from '@config/IOCIdentifier';
2
2
  import {
3
3
  type BootstrapContext,
4
4
  type BootstrapExecutorPlugin,
5
5
  type ApiMockPluginConfig,
6
6
  ApiPickDataPlugin
7
7
  } from '@qlover/corekit-bridge';
8
- import { FetchURLPlugin } from '@qlover/fe-corekit';
8
+ import {
9
+ RequestPlugin,
10
+ ResponsePlugin,
11
+ type RequestAdapterConfig,
12
+ type RequestAdapterResponse
13
+ } from '@qlover/fe-corekit';
14
+ import type { AppConfig } from '@/base/cases/AppConfig';
9
15
  import { RequestLogger } from '@/base/cases/RequestLogger';
16
+ import type { UserService } from '@/base/services/UserService';
10
17
  import { FeApi } from './FeApi';
11
- import type {
12
- RequestAdapterConfig,
13
- RequestAdapterResponse,
14
- RequestTransactionInterface
15
- } from '@qlover/fe-corekit';
18
+
19
+ export interface RequestTransactionInterface<Request, Response> {
20
+ request: Request;
21
+ response: Response;
22
+ }
16
23
 
17
24
  /**
18
25
  * FeApiConfig
@@ -22,8 +29,8 @@ import type {
22
29
  *
23
30
  * extends:
24
31
  */
25
- export interface FeApiConfig<Request = unknown>
26
- extends RequestAdapterConfig<Request>, ApiMockPluginConfig {}
32
+ export type FeApiConfig<Request = unknown> = RequestAdapterConfig<Request> &
33
+ ApiMockPluginConfig & {};
27
34
 
28
35
  /**
29
36
  * FeApiResponse
@@ -63,11 +70,17 @@ export class FeApiBootstarp implements BootstrapExecutorPlugin {
63
70
  * @override
64
71
  */
65
72
  public onBefore({ parameters: { ioc } }: BootstrapContext): void {
73
+ const appConfig = ioc.get<AppConfig>(I.AppConfig);
66
74
  ioc
67
75
  .get<FeApi>(FeApi)
68
- .usePlugin(new FetchURLPlugin())
69
- .usePlugin(ioc.get(IOCIdentifier.FeApiCommonPlugin))
70
- .usePlugin(ioc.get(RequestLogger))
71
- .usePlugin(ioc.get(ApiPickDataPlugin));
76
+ .use(
77
+ new RequestPlugin({
78
+ tokenPrefix: appConfig.openAiTokenPrefix,
79
+ token: () => ioc.get<UserService>(I.UserServiceInterface).getToken()
80
+ })
81
+ )
82
+ .use(ioc.get(ResponsePlugin))
83
+ .use(ioc.get(RequestLogger))
84
+ .use(ioc.get(ApiPickDataPlugin));
72
85
  }
73
86
  }
@@ -1,11 +1,15 @@
1
1
  import { RES_NO_TOKEN } from '@config/Identifier';
2
2
  import {
3
- FetchAbortPlugin,
4
- RequestAdapterFetch,
5
- RequestTransaction
3
+ Aborter,
4
+ AborterConfig,
5
+ type AborterInterface,
6
+ ExecutorContextInterface,
7
+ ExecutorError,
8
+ LifecycleExecutor,
9
+ type RequestAdapterInterface,
10
+ RequestExecutor
6
11
  } from '@qlover/fe-corekit';
7
12
  import { inject, injectable } from 'inversify';
8
- import { AppError } from '@/base/cases/AppError';
9
13
  import { UserApiAdapter } from './UserApiAdapter';
10
14
  import { UserApiConfig } from './UserApiBootstarp';
11
15
  import {
@@ -17,10 +21,7 @@ import {
17
21
  UserInfo,
18
22
  UserCredential
19
23
  } from './UserApiType';
20
- import type {
21
- UserAuthStoreInterface,
22
- UserServiceGateway
23
- } from '@qlover/corekit-bridge';
24
+ import type { UserServiceGateway } from '@qlover/corekit-bridge';
24
25
 
25
26
  /**
26
27
  * UserApi
@@ -31,27 +32,20 @@ import type {
31
32
  */
32
33
  @injectable()
33
34
  export class UserApi
34
- extends RequestTransaction<UserApiConfig>
35
+ extends RequestExecutor<
36
+ UserApiConfig,
37
+ ExecutorContextInterface<UserApiConfig>
38
+ >
35
39
  implements UserServiceGateway<UserInfo, UserCredential>
36
40
  {
37
- protected store: UserAuthStoreInterface<UserInfo> | null = null;
38
-
39
41
  constructor(
40
- @inject(FetchAbortPlugin) protected abortPlugin: FetchAbortPlugin,
41
- @inject(UserApiAdapter) adapter: RequestAdapterFetch
42
+ @inject(Aborter) protected abortPlugin: AborterInterface<AborterConfig>,
43
+ @inject(UserApiAdapter) adapter: RequestAdapterInterface<UserApiConfig>
42
44
  ) {
43
- super(adapter);
44
- }
45
-
46
- public getStore(): UserAuthStoreInterface<UserInfo> | null {
47
- return this.store;
48
- }
49
-
50
- /**
51
- * @param store
52
- */
53
- public setStore(store: UserAuthStoreInterface<UserInfo>): void {
54
- this.store = store;
45
+ super(
46
+ adapter,
47
+ new LifecycleExecutor<ExecutorContextInterface<UserApiConfig, unknown>>()
48
+ );
55
49
  }
56
50
 
57
51
  public stop(request: UserApiConfig): Promise<void> | void {
@@ -59,7 +53,7 @@ export class UserApi
59
53
  }
60
54
 
61
55
  public async getRandomUser(): Promise<GetIpInfoTransaction['response']> {
62
- return this.request<GetIpInfoTransaction>({
56
+ return this.request({
63
57
  url: 'https://randomuser.me/api/',
64
58
  method: 'GET',
65
59
  disabledMock: true
@@ -69,7 +63,7 @@ export class UserApi
69
63
  public async testApiCatchResult(): Promise<
70
64
  UserApiTestApiCatchResultTransaction['response']
71
65
  > {
72
- return this.request<UserApiTestApiCatchResultTransaction>({
66
+ return this.request({
73
67
  url: 'https://randomuser.me/api/?_name=ApiCatchResult',
74
68
  method: 'GET',
75
69
  disabledMock: true,
@@ -85,17 +79,17 @@ export class UserApi
85
79
  public async login(
86
80
  params: UserApiLoginTransaction['data']
87
81
  ): Promise<UserCredential> {
88
- const response = await this.post<UserApiLoginTransaction>(
89
- '/api/login',
90
- params
91
- );
82
+ const response = await this.post<
83
+ UserApiLoginTransaction['response'],
84
+ UserApiLoginTransaction['data']
85
+ >('/api/login', params);
92
86
 
93
87
  if (response.apiCatchResult) {
94
88
  throw response.apiCatchResult;
95
89
  }
96
90
 
97
91
  if (!response.data.token) {
98
- throw new AppError(RES_NO_TOKEN);
92
+ throw new ExecutorError(RES_NO_TOKEN);
99
93
  }
100
94
 
101
95
  return response.data;
@@ -134,8 +128,10 @@ export class UserApi
134
128
  * @returns
135
129
  */
136
130
  public async getUserInfo(_credential?: UserCredential): Promise<UserInfo> {
137
- const response =
138
- await this.get<UserApiGetUserInfoTransaction>('/api/userinfo');
131
+ const response = await this.get<
132
+ UserApiGetUserInfoTransaction['response'],
133
+ UserApiGetUserInfoTransaction['data']
134
+ >('/api/userinfo');
139
135
 
140
136
  if (response.apiCatchResult) {
141
137
  throw response.apiCatchResult;
@@ -6,15 +6,19 @@ import {
6
6
  type ApiCatchPluginConfig,
7
7
  type ApiCatchPluginResponse
8
8
  } from '@qlover/corekit-bridge';
9
- import { FetchAbortPlugin, FetchURLPlugin } from '@qlover/fe-corekit';
9
+ import {
10
+ Aborter,
11
+ AborterPlugin,
12
+ RequestPlugin,
13
+ ResponsePlugin,
14
+ type AborterConfig,
15
+ type RequestAdapterConfig,
16
+ type RequestAdapterResponse
17
+ } from '@qlover/fe-corekit';
18
+ import { RequestLanguages } from '@/base/cases/RequestLanguages';
10
19
  import { RequestLogger } from '@/base/cases/RequestLogger';
11
20
  import { UserApi } from './UserApi';
12
- import { RequestLanguages } from '../../cases/RequestLanguages';
13
- import type {
14
- RequestAdapterConfig,
15
- RequestAdapterResponse,
16
- RequestTransactionInterface
17
- } from '@qlover/fe-corekit';
21
+ import type { RequestTransactionInterface } from '../feApi/FeApiBootstarp';
18
22
 
19
23
  /**
20
24
  * UserApiConfig
@@ -30,7 +34,8 @@ export interface UserApiConfig<Request = unknown>
30
34
  extends
31
35
  RequestAdapterConfig<Request>,
32
36
  ApiMockPluginOptions,
33
- ApiCatchPluginConfig {}
37
+ ApiCatchPluginConfig,
38
+ AborterConfig {}
34
39
 
35
40
  /**
36
41
  * UserApiResponse
@@ -70,14 +75,12 @@ export class UserApiBootstarp implements BootstrapExecutorPlugin {
70
75
  public onBefore({ parameters: { ioc } }: BootstrapContext): void {
71
76
  ioc
72
77
  .get<UserApi>(UserApi)
73
- .usePlugin(new FetchURLPlugin())
74
- .usePlugin(ioc.get(IOCIdentifier.FeApiCommonPlugin))
75
- .usePlugin(
76
- new RequestLanguages(ioc.get(IOCIdentifier.I18nServiceInterface))
77
- )
78
- .usePlugin(ioc.get(IOCIdentifier.ApiMockPlugin))
79
- .usePlugin(ioc.get(RequestLogger))
80
- .usePlugin(ioc.get(FetchAbortPlugin))
81
- .usePlugin(ioc.get(IOCIdentifier.ApiCatchPlugin));
78
+ .use(new RequestPlugin())
79
+ .use(ioc.get(ResponsePlugin))
80
+ .use(new AborterPlugin(ioc.get(Aborter)))
81
+ .use(new RequestLanguages(ioc.get(IOCIdentifier.I18nServiceInterface)))
82
+ .use(ioc.get(IOCIdentifier.ApiMockPlugin))
83
+ .use(ioc.get(IOCIdentifier.ApiCatchPlugin))
84
+ .use(ioc.get(RequestLogger));
82
85
  }
83
86
  }