@qlover/create-app 0.11.0 → 1.0.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 (72) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +3 -3
  4. package/dist/templates/next-app/eslint.config.mjs +76 -1
  5. package/dist/templates/next-app/next.config.ts +4 -3
  6. package/dist/templates/next-app/package.json +15 -11
  7. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +2 -3
  8. package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +6 -4
  9. package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +14 -10
  10. package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +2 -2
  11. package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +1 -4
  12. package/dist/templates/next-app/src/base/services/I18nService.ts +6 -2
  13. package/dist/templates/next-app/src/base/services/adminApi/AdminApiRequester.ts +11 -7
  14. package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +11 -10
  15. package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +16 -12
  16. package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +19 -19
  17. package/dist/templates/next-app/src/base/services/appApi/AppApiRequester.ts +26 -21
  18. package/dist/templates/next-app/src/base/services/appApi/AppUserApi.ts +15 -6
  19. package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +12 -14
  20. package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +34 -17
  21. package/dist/templates/next-app/src/server/NextApiServer.ts +10 -4
  22. package/dist/templates/next-app/src/server/PasswordEncrypt.ts +2 -2
  23. package/dist/templates/next-app/src/server/controllers/UserController.ts +2 -2
  24. package/dist/templates/next-app/src/server/port/ServerInterface.ts +2 -2
  25. package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +6 -7
  26. package/dist/templates/next-app/src/server/services/UserService.ts +2 -2
  27. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +11 -47
  28. package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +3 -2
  29. package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +6 -1
  30. package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +21 -61
  31. package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +29 -51
  32. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +8 -26
  33. package/dist/templates/react-app/__tests__/src/main.test.tsx +2 -2
  34. package/dist/templates/react-app/config/IOCIdentifier.ts +1 -1
  35. package/dist/templates/react-app/docs/en/test-guide.md +5 -5
  36. package/dist/templates/react-app/docs/zh/test-guide.md +5 -5
  37. package/dist/templates/react-app/eslint.config.mjs +79 -7
  38. package/dist/templates/react-app/package.json +4 -3
  39. package/dist/templates/react-app/src/base/apis/AiApi.ts +20 -12
  40. package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +14 -5
  41. package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +29 -13
  42. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +35 -34
  43. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +23 -17
  44. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +11 -5
  45. package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +19 -6
  46. package/dist/templates/react-app/src/base/cases/RequestLogger.ts +11 -11
  47. package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +11 -5
  48. package/dist/templates/react-app/src/base/services/I18nService.ts +3 -0
  49. package/dist/templates/react-app/src/base/services/IdentifierService.ts +24 -0
  50. package/dist/templates/react-app/src/base/services/UserBootstrap.ts +9 -7
  51. package/dist/templates/react-app/src/base/services/UserService.ts +4 -5
  52. package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +6 -7
  53. package/dist/templates/react-app/src/main.tsx +1 -1
  54. package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +5 -5
  55. package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +3 -1
  56. package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +6 -2
  57. package/dist/templates/react-app/src/pages/base/MessagePage.tsx +34 -3
  58. package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +13 -7
  59. package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +6 -1
  60. package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +26 -11
  61. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +7 -1
  62. package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +3 -1
  63. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +16 -7
  64. package/dist/templates/react-app/src/vite-env.d.ts +1 -1
  65. package/dist/templates/react-app/tsconfig.e2e.json +5 -2
  66. package/dist/templates/react-app/tsconfig.json +7 -0
  67. package/dist/templates/react-app/tsconfig.node.json +4 -2
  68. package/dist/templates/react-app/tsconfig.test.json +4 -1
  69. package/package.json +4 -3
  70. package/dist/templates/react-app/src/base/cases/AppError.ts +0 -10
  71. package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +0 -20
  72. 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>();
@@ -92,17 +92,14 @@ const eslintConfig = [
92
92
  'storybook-static/**'
93
93
  ]
94
94
  },
95
+
95
96
  {
96
97
  files: ['**/*.{js,jsx,ts,tsx}'],
97
98
  languageOptions: {
98
99
  parser: tseslint.parser,
99
100
  parserOptions: {
100
- project: [
101
- './tsconfig.app.json',
102
- './tsconfig.node.json',
103
- './tsconfig.test.json',
104
- './tsconfig.e2e.json'
105
- ],
101
+ // Note: 'project' is removed here to avoid conflict with projectService in the type-checked config below
102
+ // TypeScript files will get type information from the recommendedTypeChecked config
106
103
  tsconfigRootDir: __dirname
107
104
  }
108
105
  },
@@ -116,7 +113,7 @@ const eslintConfig = [
116
113
  rules: {
117
114
  '@qlover-eslint/ts-class-method-return': 'error',
118
115
  '@qlover-eslint/ts-class-member-accessibility': 'error',
119
- '@qlover-eslint/ts-class-override': 'error',
116
+ '@qlover-eslint/ts-class-override': 'off',
120
117
  '@qlover-eslint/require-root-testid': [
121
118
  'error',
122
119
  {
@@ -202,6 +199,81 @@ const eslintConfig = [
202
199
  'import/no-default-export': 'error'
203
200
  }
204
201
  },
202
+
203
+ // TypeScript files with type checking for ts-class-override rule
204
+ // The ts-class-override rule requires full type information to accurately detect:
205
+ // - Methods that override parent class methods (via extends)
206
+ // - Methods that implement interface methods (via implements)
207
+ // Without type checking, the rule falls back to AST-based heuristics which are less accurate
208
+ // This separate config block enables type checking only for TypeScript files to provide
209
+ // accurate override detection while maintaining good performance
210
+ ...tseslint.configs.recommendedTypeChecked.map((config) => ({
211
+ ...config,
212
+ files: ['src/**/*.{ts,tsx}'],
213
+ ignores: [
214
+ '**/dist/**',
215
+ '**/build/**',
216
+ '**/ts-build/**',
217
+ '**/node_modules/**',
218
+ '**/.nx/**',
219
+ '**/.cache/**',
220
+ '**/coverage/**',
221
+ '**/*.d.ts',
222
+ '**/*.config.ts',
223
+ '**/*.test.ts',
224
+ '**/__mocks__/**',
225
+ '**/__tests__/**',
226
+ '**/*.spec.ts',
227
+ ...(config.ignores || [])
228
+ ],
229
+ languageOptions: {
230
+ ...config.languageOptions,
231
+ parserOptions: {
232
+ ...config.languageOptions?.parserOptions,
233
+ project: './tsconfig.app.json',
234
+ tsconfigRootDir: __dirname
235
+ }
236
+ },
237
+ plugins: {
238
+ ...config.plugins,
239
+ '@qlover-eslint': qloverEslint
240
+ },
241
+ rules: {
242
+ ...config.rules,
243
+ // Enable ts-class-override rule with full type information
244
+ // This rule is disabled in the base config above and only enabled here where
245
+ // type information is available, ensuring accurate detection of override relationships
246
+ '@qlover-eslint/ts-class-override': 'error',
247
+ // Disable other type-checked rules to avoid performance impact
248
+ // We only need type checking for ts-class-override, so we disable other
249
+ // type-aware rules that would slow down linting without providing value
250
+ '@typescript-eslint/ban-ts-comment': 'off',
251
+ '@typescript-eslint/restrict-template-expressions': 'off',
252
+ '@typescript-eslint/no-unsafe-assignment': 'off',
253
+ '@typescript-eslint/no-unnecessary-type-assertion': 'off',
254
+ '@typescript-eslint/no-redundant-type-constituents': 'off',
255
+ '@typescript-eslint/no-unsafe-return': 'off',
256
+ '@typescript-eslint/no-empty-object-type': 'off',
257
+ '@typescript-eslint/no-unsafe-call': 'off',
258
+ '@typescript-eslint/no-unsafe-member-access': 'off',
259
+ '@typescript-eslint/no-unsafe-argument': 'off',
260
+ '@typescript-eslint/no-unsafe-enum-comparison': 'off',
261
+ '@typescript-eslint/no-unsafe-literal-comparison': 'off',
262
+ '@typescript-eslint/no-unsafe-nullish-coalescing': 'off',
263
+ '@typescript-eslint/no-unsafe-optional-chaining': 'off',
264
+ '@typescript-eslint/unbound-method': 'off',
265
+ '@typescript-eslint/await-thenable': 'off',
266
+ '@typescript-eslint/no-floating-promises': 'off',
267
+ '@typescript-eslint/no-misused-promises': 'off',
268
+ '@typescript-eslint/require-await': 'off',
269
+ '@typescript-eslint/no-base-to-string': 'off',
270
+ '@typescript-eslint/prefer-promise-reject-errors': 'off',
271
+ '@typescript-eslint/no-duplicate-type-constituents': 'off',
272
+ // Disable @typescript-eslint/no-unused-vars as we use unused-imports/no-unused-vars instead
273
+ '@typescript-eslint/no-unused-vars': 'off',
274
+ '@typescript-eslint/no-explicit-any': 'off',
275
+ }
276
+ })),
205
277
  {
206
278
  // TODO: antd override theme need use import type
207
279
  files: ['src/base/types/deprecated-antd.d.ts'],
@@ -36,8 +36,8 @@
36
36
  "build:staging": "npm run lint && vite build --mode staging",
37
37
  "build:prod": "npm run lint && vite build --mode production",
38
38
  "build:analyze": "vite build --mode production && start dist/stats.html",
39
- "lint": "eslint ./src ./__tests__ ./config ./makes ./e2e",
40
- "lint:fix": "eslint ./src ./__tests__ ./config ./makes ./e2e --ext .ts,.tsx --fix",
39
+ "lint": "eslint",
40
+ "lint:fix": "eslint --ext .ts,.tsx --fix",
41
41
  "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
42
42
  "format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
43
43
  "fix": "npm run lint:fix && npm run format",
@@ -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
@@ -59,12 +66,21 @@ export interface FeApiTransaction<
59
66
  export class FeApiBootstarp implements BootstrapExecutorPlugin {
60
67
  public readonly pluginName = 'FeApiBootstarp';
61
68
 
69
+ /**
70
+ * @override
71
+ */
62
72
  public onBefore({ parameters: { ioc } }: BootstrapContext): void {
73
+ const appConfig = ioc.get<AppConfig>(I.AppConfig);
63
74
  ioc
64
75
  .get<FeApi>(FeApi)
65
- .usePlugin(new FetchURLPlugin())
66
- .usePlugin(ioc.get(IOCIdentifier.FeApiCommonPlugin))
67
- .usePlugin(ioc.get(RequestLogger))
68
- .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));
69
85
  }
70
86
  }