@qlover/create-app 0.12.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.
- package/CHANGELOG.md +4 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/next-app/next.config.ts +4 -3
- package/dist/templates/next-app/package.json +14 -11
- package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +2 -3
- package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +6 -4
- package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +14 -10
- package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +2 -2
- package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +1 -4
- package/dist/templates/next-app/src/base/services/I18nService.ts +6 -2
- package/dist/templates/next-app/src/base/services/adminApi/AdminApiRequester.ts +11 -7
- package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +11 -10
- package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +16 -12
- package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +19 -19
- package/dist/templates/next-app/src/base/services/appApi/AppApiRequester.ts +26 -21
- package/dist/templates/next-app/src/base/services/appApi/AppUserApi.ts +15 -6
- package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +12 -14
- package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +34 -17
- package/dist/templates/next-app/src/server/NextApiServer.ts +10 -4
- package/dist/templates/next-app/src/server/PasswordEncrypt.ts +2 -2
- package/dist/templates/next-app/src/server/controllers/UserController.ts +2 -2
- package/dist/templates/next-app/src/server/port/ServerInterface.ts +2 -2
- package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +6 -7
- package/dist/templates/next-app/src/server/services/UserService.ts +2 -2
- package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +11 -47
- package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +3 -2
- package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +6 -1
- package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +21 -61
- package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +29 -51
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +8 -26
- package/dist/templates/react-app/__tests__/src/main.test.tsx +2 -2
- package/dist/templates/react-app/config/IOCIdentifier.ts +1 -1
- package/dist/templates/react-app/docs/en/test-guide.md +5 -5
- package/dist/templates/react-app/docs/zh/test-guide.md +5 -5
- package/dist/templates/react-app/package.json +2 -1
- package/dist/templates/react-app/src/base/apis/AiApi.ts +20 -12
- package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +14 -5
- package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +26 -13
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +30 -34
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +20 -17
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +11 -5
- package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +19 -6
- package/dist/templates/react-app/src/base/cases/RequestLogger.ts +11 -11
- package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +11 -5
- package/dist/templates/react-app/src/base/services/UserBootstrap.ts +6 -7
- package/dist/templates/react-app/src/base/services/UserService.ts +1 -5
- package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +6 -7
- package/dist/templates/react-app/src/main.tsx +1 -1
- package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +5 -5
- package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +3 -1
- package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +6 -2
- package/dist/templates/react-app/src/pages/base/MessagePage.tsx +34 -3
- package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +13 -7
- package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +6 -1
- package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +26 -11
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +1 -1
- package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +3 -1
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +16 -7
- package/dist/templates/react-app/src/vite-env.d.ts +1 -1
- package/dist/templates/react-app/tsconfig.e2e.json +5 -2
- package/dist/templates/react-app/tsconfig.json +7 -0
- package/dist/templates/react-app/tsconfig.node.json +4 -2
- package/dist/templates/react-app/tsconfig.test.json +4 -1
- package/package.json +3 -3
- package/dist/templates/react-app/src/base/cases/AppError.ts +0 -10
- package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +0 -20
- 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
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
110
|
+
_ioc: IOCFunctionInterface<IOCIdentifierMap, IOCContainerInterface>
|
|
111
111
|
) => {
|
|
112
|
-
return [
|
|
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
|
-
|
|
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]:
|
|
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
|
-
|
|
4
|
-
RequestCommonPlugin
|
|
5
|
-
} from '@qlover/corekit-bridge';
|
|
6
|
-
import {
|
|
7
|
-
FetchURLPlugin,
|
|
4
|
+
LifecycleExecutor,
|
|
8
5
|
RequestAdapterFetch,
|
|
9
|
-
|
|
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
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
new RequestCommonPlugin({
|
|
40
|
+
apiApi.use(
|
|
41
|
+
new RequestPlugin({
|
|
35
42
|
tokenPrefix: appConfig.aiApiTokenPrefix,
|
|
36
43
|
token: appConfig.aiApiToken
|
|
37
44
|
})
|
|
38
45
|
);
|
|
39
|
-
|
|
40
|
-
|
|
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 {
|
|
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
|
|
13
|
+
export class FeApi extends RequestExecutor<
|
|
14
|
+
FeApiConfig,
|
|
15
|
+
ExecutorContextInterface<FeApiConfig>
|
|
16
|
+
> {
|
|
9
17
|
constructor(@inject(FeApiAdapter) adapter: RequestAdapterFetch) {
|
|
10
|
-
super(
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
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
|
|
26
|
-
|
|
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
|
-
.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
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(
|
|
41
|
-
@inject(UserApiAdapter) adapter:
|
|
42
|
+
@inject(Aborter) protected abortPlugin: AborterInterface<AborterConfig>,
|
|
43
|
+
@inject(UserApiAdapter) adapter: RequestAdapterInterface<UserApiConfig>
|
|
42
44
|
) {
|
|
43
|
-
super(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
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
|
|
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<
|
|
89
|
-
'
|
|
90
|
-
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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 {
|
|
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
|
-
.
|
|
74
|
-
.
|
|
75
|
-
.
|
|
76
|
-
|
|
77
|
-
)
|
|
78
|
-
.
|
|
79
|
-
.
|
|
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
|
}
|