@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.
- package/CHANGELOG.md +18 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +3 -3
- package/dist/templates/next-app/eslint.config.mjs +76 -1
- package/dist/templates/next-app/next.config.ts +4 -3
- package/dist/templates/next-app/package.json +15 -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/eslint.config.mjs +79 -7
- package/dist/templates/react-app/package.json +4 -3
- 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 +29 -13
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +35 -34
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +23 -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/I18nService.ts +3 -0
- package/dist/templates/react-app/src/base/services/IdentifierService.ts +24 -0
- package/dist/templates/react-app/src/base/services/UserBootstrap.ts +9 -7
- package/dist/templates/react-app/src/base/services/UserService.ts +4 -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 +7 -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 +4 -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
|
@@ -5,6 +5,7 @@ import importPlugin from 'eslint-plugin-import';
|
|
|
5
5
|
import prettierPlugin from 'eslint-plugin-prettier';
|
|
6
6
|
import unusedImports from 'eslint-plugin-unused-imports';
|
|
7
7
|
import qloverEslint from '@qlover/eslint-plugin';
|
|
8
|
+
import tseslint from 'typescript-eslint';
|
|
8
9
|
|
|
9
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
11
|
const __dirname = dirname(__filename);
|
|
@@ -106,7 +107,7 @@ const eslintConfig = [
|
|
|
106
107
|
rules: {
|
|
107
108
|
'@qlover-eslint/ts-class-method-return': 'error',
|
|
108
109
|
'@qlover-eslint/ts-class-member-accessibility': 'error',
|
|
109
|
-
'@qlover-eslint/ts-class-override': '
|
|
110
|
+
'@qlover-eslint/ts-class-override': 'off',
|
|
110
111
|
'@qlover-eslint/require-root-testid': ['error', {
|
|
111
112
|
exclude: ['/Provider$/']
|
|
112
113
|
}],
|
|
@@ -188,6 +189,80 @@ const eslintConfig = [
|
|
|
188
189
|
'import/no-default-export': 'error',
|
|
189
190
|
}
|
|
190
191
|
},
|
|
192
|
+
// TypeScript files with type checking for ts-class-override rule
|
|
193
|
+
// The ts-class-override rule requires full type information to accurately detect:
|
|
194
|
+
// - Methods that override parent class methods (via extends)
|
|
195
|
+
// - Methods that implement interface methods (via implements)
|
|
196
|
+
// Without type checking, the rule falls back to AST-based heuristics which are less accurate
|
|
197
|
+
// This separate config block enables type checking only for TypeScript files to provide
|
|
198
|
+
// accurate override detection while maintaining good performance
|
|
199
|
+
...tseslint.configs.recommendedTypeChecked.map((config) => ({
|
|
200
|
+
...config,
|
|
201
|
+
files: ['src/**/*.{ts,tsx}'],
|
|
202
|
+
ignores: [
|
|
203
|
+
'**/dist/**',
|
|
204
|
+
'**/build/**',
|
|
205
|
+
'**/ts-build/**',
|
|
206
|
+
'**/node_modules/**',
|
|
207
|
+
'**/.nx/**',
|
|
208
|
+
'**/.cache/**',
|
|
209
|
+
'**/coverage/**',
|
|
210
|
+
'**/*.d.ts',
|
|
211
|
+
'**/*.config.ts',
|
|
212
|
+
'**/*.test.ts',
|
|
213
|
+
'**/__mocks__/**',
|
|
214
|
+
'**/__tests__/**',
|
|
215
|
+
'**/*.spec.ts',
|
|
216
|
+
...(config.ignores || [])
|
|
217
|
+
],
|
|
218
|
+
languageOptions: {
|
|
219
|
+
...config.languageOptions,
|
|
220
|
+
parserOptions: {
|
|
221
|
+
...config.languageOptions?.parserOptions,
|
|
222
|
+
project: './tsconfig.json',
|
|
223
|
+
tsconfigRootDir: __dirname
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
plugins: {
|
|
227
|
+
...config.plugins,
|
|
228
|
+
'@qlover-eslint': qloverEslint
|
|
229
|
+
},
|
|
230
|
+
rules: {
|
|
231
|
+
...config.rules,
|
|
232
|
+
// Enable ts-class-override rule with full type information
|
|
233
|
+
// This rule is disabled in the base config above and only enabled here where
|
|
234
|
+
// type information is available, ensuring accurate detection of override relationships
|
|
235
|
+
'@qlover-eslint/ts-class-override': 'error',
|
|
236
|
+
// Disable other type-checked rules to avoid performance impact
|
|
237
|
+
// We only need type checking for ts-class-override, so we disable other
|
|
238
|
+
// type-aware rules that would slow down linting without providing value
|
|
239
|
+
'@typescript-eslint/ban-ts-comment': 'off',
|
|
240
|
+
'@typescript-eslint/restrict-template-expressions': 'off',
|
|
241
|
+
'@typescript-eslint/no-unsafe-assignment': 'off',
|
|
242
|
+
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
|
|
243
|
+
'@typescript-eslint/no-redundant-type-constituents': 'off',
|
|
244
|
+
'@typescript-eslint/no-unsafe-return': 'off',
|
|
245
|
+
'@typescript-eslint/no-empty-object-type': 'off',
|
|
246
|
+
'@typescript-eslint/no-unsafe-call': 'off',
|
|
247
|
+
'@typescript-eslint/no-unsafe-member-access': 'off',
|
|
248
|
+
'@typescript-eslint/no-unsafe-argument': 'off',
|
|
249
|
+
'@typescript-eslint/no-unsafe-enum-comparison': 'off',
|
|
250
|
+
'@typescript-eslint/no-unsafe-literal-comparison': 'off',
|
|
251
|
+
'@typescript-eslint/no-unsafe-nullish-coalescing': 'off',
|
|
252
|
+
'@typescript-eslint/no-unsafe-optional-chaining': 'off',
|
|
253
|
+
'@typescript-eslint/unbound-method': 'off',
|
|
254
|
+
'@typescript-eslint/await-thenable': 'off',
|
|
255
|
+
'@typescript-eslint/no-floating-promises': 'off',
|
|
256
|
+
'@typescript-eslint/no-misused-promises': 'off',
|
|
257
|
+
'@typescript-eslint/require-await': 'off',
|
|
258
|
+
'@typescript-eslint/no-base-to-string': 'off',
|
|
259
|
+
'@typescript-eslint/prefer-promise-reject-errors': 'off',
|
|
260
|
+
'@typescript-eslint/no-duplicate-type-constituents': 'off',
|
|
261
|
+
// Disable @typescript-eslint/no-unused-vars as we use unused-imports/no-unused-vars instead
|
|
262
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
263
|
+
'@typescript-eslint/only-throw-error': 'off'
|
|
264
|
+
}
|
|
265
|
+
})),
|
|
191
266
|
// 为特定文件允许 default export
|
|
192
267
|
{
|
|
193
268
|
files: [
|
|
@@ -11,9 +11,10 @@ generateLocales().catch((error) => {
|
|
|
11
11
|
|
|
12
12
|
const nextConfig: NextConfig = {
|
|
13
13
|
// reactStrictMode: false,
|
|
14
|
-
turbopack:
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
// turbopack 在接下本地 file: 依赖时支持还不够好
|
|
15
|
+
// turbopack: {
|
|
16
|
+
// root: __dirname // 明确指定根目录
|
|
17
|
+
// },
|
|
17
18
|
transpilePackages: ['@qlover/corekit-bridge', '@qlover/fe-corekit'],
|
|
18
19
|
env: {
|
|
19
20
|
APP_ENV: process.env.APP_ENV
|
|
@@ -3,18 +3,20 @@
|
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
|
-
"dev": "cross-env APP_ENV=localhost next dev --
|
|
7
|
-
"dev:staging": "cross-env APP_ENV=staging next dev --
|
|
8
|
-
"dev:prod": "cross-env APP_ENV=production next dev --
|
|
9
|
-
"
|
|
10
|
-
"build
|
|
11
|
-
"build:
|
|
6
|
+
"dev": "cross-env APP_ENV=localhost next dev --port 3100",
|
|
7
|
+
"dev:staging": "cross-env APP_ENV=staging next dev --port 3100",
|
|
8
|
+
"dev:prod": "cross-env APP_ENV=production next dev --port 3100",
|
|
9
|
+
"dev:turbo": "cross-env APP_ENV=localhost next dev --turbopack --port 3100",
|
|
10
|
+
"build": "cross-env APP_ENV=localhost next build",
|
|
11
|
+
"build:staging": "cross-env APP_ENV=staging next build",
|
|
12
|
+
"build:prod": "cross-env APP_ENV=production next build",
|
|
12
13
|
"start": "next start --port 3101",
|
|
13
|
-
"lint": "
|
|
14
|
-
"lint:fix": "
|
|
14
|
+
"lint": "npm run type-check && eslint ./src ./config ./make ./migrations",
|
|
15
|
+
"lint:fix": "npm run type-check && eslint ./src ./config ./make ./migrations --ext .ts,.tsx --fix",
|
|
15
16
|
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
|
|
16
17
|
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
|
|
17
|
-
"fix": "npm run lint:fix && npm run format"
|
|
18
|
+
"fix": "npm run lint:fix && npm run format",
|
|
19
|
+
"type-check": "tsc --build --force"
|
|
18
20
|
},
|
|
19
21
|
"dependencies": {
|
|
20
22
|
"@ant-design/icons": "^6.0.0",
|
|
@@ -24,8 +26,9 @@
|
|
|
24
26
|
"@brain-toolkit/antd-theme-override": "^0.0.3",
|
|
25
27
|
"@brain-toolkit/bridge": "^0.0.1",
|
|
26
28
|
"@brain-toolkit/react-kit": "^0.1.0",
|
|
27
|
-
"@qlover/corekit-bridge": "
|
|
28
|
-
"@qlover/fe-corekit": "
|
|
29
|
+
"@qlover/corekit-bridge": "../../../corekit-bridge",
|
|
30
|
+
"@qlover/fe-corekit": "../../../fe-corekit",
|
|
31
|
+
"@qlover/logger": "../../../logger",
|
|
29
32
|
"@qlover/slice-store-react": "^1.4.1",
|
|
30
33
|
"@supabase/postgrest-js": "^2.87.1",
|
|
31
34
|
"@supabase/ssr": "^0.7.0",
|
|
@@ -69,6 +72,7 @@
|
|
|
69
72
|
"eslint-plugin-prettier": "^5.5.4",
|
|
70
73
|
"eslint-plugin-unused-imports": "^4.2.0",
|
|
71
74
|
"prettier": "^3.6.2",
|
|
75
|
+
"typescript-eslint": "^8.15.0",
|
|
72
76
|
"tailwindcss": "^4",
|
|
73
77
|
"typescript": "^5"
|
|
74
78
|
},
|
|
@@ -19,7 +19,6 @@ export function LoginForm(props: { tt: LoginI18nInterface }) {
|
|
|
19
19
|
const { tt } = props;
|
|
20
20
|
const t = useWarnTranslations();
|
|
21
21
|
const userService = useIOC(I.UserServiceInterface);
|
|
22
|
-
const logger = useIOC(I.Logger);
|
|
23
22
|
const appConfig = useIOC(I.AppConfig);
|
|
24
23
|
const routerService = useIOC(I.RouterServiceInterface);
|
|
25
24
|
const [loading, setLoading] = useState(false);
|
|
@@ -29,8 +28,8 @@ export function LoginForm(props: { tt: LoginI18nInterface }) {
|
|
|
29
28
|
setLoading(true);
|
|
30
29
|
await userService.login(values);
|
|
31
30
|
routerService.replaceHome();
|
|
32
|
-
} catch
|
|
33
|
-
|
|
31
|
+
} catch {
|
|
32
|
+
// do nothing
|
|
34
33
|
} finally {
|
|
35
34
|
setLoading(false);
|
|
36
35
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ExecutorContextInterface,
|
|
2
3
|
ExecutorError,
|
|
3
|
-
|
|
4
|
-
type ExecutorPlugin
|
|
4
|
+
LifecyclePluginInterface
|
|
5
5
|
} from '@qlover/fe-corekit';
|
|
6
6
|
import { inject, injectable } from 'inversify';
|
|
7
7
|
import { i18nKeySchema } from '@config/i18n/i18nKeyScheam';
|
|
@@ -13,7 +13,9 @@ import type { I18nServiceInterface } from '../port/I18nServiceInterface';
|
|
|
13
13
|
import type { UIDialogInterface } from '@qlover/corekit-bridge';
|
|
14
14
|
|
|
15
15
|
@injectable()
|
|
16
|
-
export class DialogErrorPlugin
|
|
16
|
+
export class DialogErrorPlugin
|
|
17
|
+
implements LifecyclePluginInterface<ExecutorContextInterface<unknown>>
|
|
18
|
+
{
|
|
17
19
|
public readonly pluginName = 'DialogErrorPlugin';
|
|
18
20
|
|
|
19
21
|
constructor(
|
|
@@ -27,7 +29,7 @@ export class DialogErrorPlugin implements ExecutorPlugin {
|
|
|
27
29
|
/**
|
|
28
30
|
* @override
|
|
29
31
|
*/
|
|
30
|
-
public onError(context:
|
|
32
|
+
public onError(context: ExecutorContextInterface<unknown>): void {
|
|
31
33
|
const { error, hooksRuntimes } = context;
|
|
32
34
|
const runtimesError = hooksRuntimes.returnValue;
|
|
33
35
|
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { clone, isObject } from 'lodash';
|
|
2
2
|
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
ExecutorContextInterface,
|
|
4
|
+
LifecyclePluginInterface,
|
|
5
|
+
RequestAdapterConfig,
|
|
6
|
+
EncryptorInterface
|
|
7
7
|
} from '@qlover/fe-corekit';
|
|
8
8
|
|
|
9
|
-
export interface RequestEncryptPluginProps<
|
|
10
|
-
Request
|
|
11
|
-
> extends RequestAdapterConfig<Request> {
|
|
9
|
+
export interface RequestEncryptPluginProps<Request = unknown>
|
|
10
|
+
extends RequestAdapterConfig<Request> {
|
|
12
11
|
/**
|
|
13
12
|
* 加密密码在 HTTP 请求中
|
|
14
13
|
*
|
|
@@ -19,16 +18,21 @@ export interface RequestEncryptPluginProps<
|
|
|
19
18
|
encryptProps?: string[] | string;
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
export class RequestEncryptPlugin
|
|
21
|
+
export class RequestEncryptPlugin
|
|
22
|
+
implements
|
|
23
|
+
LifecyclePluginInterface<
|
|
24
|
+
ExecutorContextInterface<RequestEncryptPluginProps>
|
|
25
|
+
>
|
|
26
|
+
{
|
|
23
27
|
public readonly pluginName = 'RequestEncryptPlugin';
|
|
24
28
|
|
|
25
|
-
constructor(protected encryptor:
|
|
29
|
+
constructor(protected encryptor: EncryptorInterface<string, string>) {}
|
|
26
30
|
|
|
27
31
|
/**
|
|
28
32
|
* @override
|
|
29
33
|
*/
|
|
30
34
|
public onBefore(
|
|
31
|
-
context:
|
|
35
|
+
context: ExecutorContextInterface<RequestEncryptPluginProps>
|
|
32
36
|
): void | Promise<void> {
|
|
33
37
|
const { responseType, encryptProps } = context.parameters;
|
|
34
38
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Base64Serializer, type
|
|
1
|
+
import { Base64Serializer, type EncryptorInterface } from '@qlover/fe-corekit';
|
|
2
2
|
import { inject, injectable } from 'inversify';
|
|
3
3
|
import { I } from '@config/IOCIdentifier';
|
|
4
4
|
import type { AppConfig } from './AppConfig';
|
|
5
5
|
|
|
6
6
|
@injectable()
|
|
7
|
-
export class StringEncryptor implements
|
|
7
|
+
export class StringEncryptor implements EncryptorInterface<string, string> {
|
|
8
8
|
private readonly key;
|
|
9
9
|
|
|
10
10
|
constructor(
|
|
@@ -13,10 +13,7 @@ export class I18nServiceState implements StoreStateInterface {
|
|
|
13
13
|
public loading: boolean = false;
|
|
14
14
|
constructor(public language: I18nServiceLocale) {}
|
|
15
15
|
}
|
|
16
|
-
export abstract class I18nServiceInterface
|
|
17
|
-
extends StoreInterface<I18nServiceState>
|
|
18
|
-
implements I18nServiceInterface
|
|
19
|
-
{
|
|
16
|
+
export abstract class I18nServiceInterface extends StoreInterface<I18nServiceState> {
|
|
20
17
|
/**
|
|
21
18
|
* @override
|
|
22
19
|
*/
|
|
@@ -5,10 +5,14 @@ import {
|
|
|
5
5
|
} from '../port/I18nServiceInterface';
|
|
6
6
|
import type { I18nServiceLocale } from '../port/I18nServiceInterface';
|
|
7
7
|
import type { useTranslations } from 'next-intl';
|
|
8
|
+
import { BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
|
|
8
9
|
|
|
9
10
|
type TranslationFunction = ReturnType<typeof useTranslations>;
|
|
10
11
|
|
|
11
|
-
export class I18nService
|
|
12
|
+
export class I18nService
|
|
13
|
+
extends I18nServiceInterface
|
|
14
|
+
implements BootstrapExecutorPlugin
|
|
15
|
+
{
|
|
12
16
|
public readonly pluginName = 'I18nService';
|
|
13
17
|
protected pathname: string = '';
|
|
14
18
|
protected translator: TranslationFunction | null = null;
|
|
@@ -34,7 +38,7 @@ export class I18nService extends I18nServiceInterface {
|
|
|
34
38
|
/**
|
|
35
39
|
* @override
|
|
36
40
|
*/
|
|
37
|
-
public
|
|
41
|
+
public onBefore(): void {}
|
|
38
42
|
|
|
39
43
|
public override async changeLanguage(
|
|
40
44
|
language: I18nServiceLocale
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
ExecutorContextInterface,
|
|
3
3
|
RequestAdapterFetch,
|
|
4
|
-
|
|
4
|
+
RequestExecutor
|
|
5
5
|
} from '@qlover/fe-corekit';
|
|
6
|
-
import {
|
|
6
|
+
import { injectable } from 'inversify';
|
|
7
7
|
import type { AppApiConfig } from '../appApi/AppApiRequester';
|
|
8
8
|
|
|
9
|
+
export interface AdminApiRequesterContext
|
|
10
|
+
extends ExecutorContextInterface<AppApiConfig> {}
|
|
11
|
+
|
|
9
12
|
@injectable()
|
|
10
|
-
export class AdminApiRequester extends
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
export class AdminApiRequester extends RequestExecutor<
|
|
14
|
+
AppApiConfig,
|
|
15
|
+
AdminApiRequesterContext
|
|
16
|
+
> {
|
|
17
|
+
constructor() {
|
|
14
18
|
super(
|
|
15
19
|
new RequestAdapterFetch({
|
|
16
20
|
baseURL: '/api/admin',
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
type AppApiTransaction
|
|
9
9
|
} from '../appApi/AppApiRequester';
|
|
10
10
|
import type { ResourceInterface, ResourceQuery } from '@qlover/corekit-bridge';
|
|
11
|
-
import
|
|
11
|
+
import { RequestExecutor } from '@qlover/fe-corekit';
|
|
12
|
+
import { AdminApiRequesterContext } from './AdminApiRequester';
|
|
12
13
|
|
|
13
14
|
export type AdminLocalesListTransaction = AppApiTransaction<
|
|
14
15
|
ResourceQuery,
|
|
@@ -24,17 +25,17 @@ export type AdminLocalesUpdateTransaction = AppApiTransaction<
|
|
|
24
25
|
export class AdminLocalesApi implements ResourceInterface<LocalesSchema> {
|
|
25
26
|
constructor(
|
|
26
27
|
@inject(AppApiRequester)
|
|
27
|
-
protected client:
|
|
28
|
+
protected client: RequestExecutor<AppApiConfig, AdminApiRequesterContext>
|
|
28
29
|
) {}
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* @override
|
|
32
33
|
*/
|
|
33
34
|
public create(data: LocalesSchema): Promise<unknown> {
|
|
34
|
-
return this.client.request
|
|
35
|
+
return this.client.request({
|
|
35
36
|
url: '/admin/locales/create',
|
|
36
37
|
method: 'POST',
|
|
37
|
-
data: data
|
|
38
|
+
data: data
|
|
38
39
|
});
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -42,10 +43,10 @@ export class AdminLocalesApi implements ResourceInterface<LocalesSchema> {
|
|
|
42
43
|
* @override
|
|
43
44
|
*/
|
|
44
45
|
public remove(data: Partial<LocalesSchema>): Promise<unknown> {
|
|
45
|
-
return this.client.request
|
|
46
|
+
return this.client.request({
|
|
46
47
|
url: '/admin/locales',
|
|
47
48
|
method: 'DELETE',
|
|
48
|
-
data
|
|
49
|
+
data
|
|
49
50
|
});
|
|
50
51
|
}
|
|
51
52
|
|
|
@@ -55,7 +56,7 @@ export class AdminLocalesApi implements ResourceInterface<LocalesSchema> {
|
|
|
55
56
|
public search(
|
|
56
57
|
params: ResourceQuery
|
|
57
58
|
): Promise<AdminLocalesListTransaction['response']> {
|
|
58
|
-
return this.client.request
|
|
59
|
+
return this.client.request({
|
|
59
60
|
url: '/admin/locales',
|
|
60
61
|
method: 'GET',
|
|
61
62
|
params: params as unknown as Record<string, unknown>
|
|
@@ -66,10 +67,10 @@ export class AdminLocalesApi implements ResourceInterface<LocalesSchema> {
|
|
|
66
67
|
* @override
|
|
67
68
|
*/
|
|
68
69
|
public export(data: LocalesSchema): Promise<unknown> {
|
|
69
|
-
return this.client.request
|
|
70
|
+
return this.client.request({
|
|
70
71
|
url: '/admin/locales',
|
|
71
72
|
method: 'GET',
|
|
72
|
-
data
|
|
73
|
+
data
|
|
73
74
|
});
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -79,7 +80,7 @@ export class AdminLocalesApi implements ResourceInterface<LocalesSchema> {
|
|
|
79
80
|
public update(
|
|
80
81
|
data: Partial<LocalesSchema>
|
|
81
82
|
): Promise<AdminLocalesUpdateTransaction['response']> {
|
|
82
|
-
return this.client.request
|
|
83
|
+
return this.client.request({
|
|
83
84
|
url: `/admin/locales/update`,
|
|
84
85
|
method: 'POST',
|
|
85
86
|
data
|
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
type AppApiTransaction
|
|
8
8
|
} from '../appApi/AppApiRequester';
|
|
9
9
|
import type { ResourceInterface, ResourceQuery } from '@qlover/corekit-bridge';
|
|
10
|
-
import
|
|
10
|
+
import { RequestExecutor } from '@qlover/fe-corekit';
|
|
11
|
+
import { AdminApiRequesterContext } from './AdminApiRequester';
|
|
11
12
|
|
|
12
13
|
export type AdminUserListTransaction = AppApiTransaction<
|
|
13
14
|
ResourceQuery,
|
|
@@ -18,7 +19,7 @@ export type AdminUserListTransaction = AppApiTransaction<
|
|
|
18
19
|
export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
19
20
|
constructor(
|
|
20
21
|
@inject(AppApiRequester)
|
|
21
|
-
protected client:
|
|
22
|
+
protected client: RequestExecutor<AppApiConfig, AdminApiRequesterContext>
|
|
22
23
|
) {}
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -27,10 +28,13 @@ export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
|
27
28
|
public async search(
|
|
28
29
|
params: AdminUserListTransaction['request']
|
|
29
30
|
): Promise<AdminUserListTransaction['response']> {
|
|
30
|
-
const response = await this.client.request<
|
|
31
|
+
const response = await this.client.request<
|
|
32
|
+
AdminUserListTransaction['response'],
|
|
33
|
+
AdminUserListTransaction['request']
|
|
34
|
+
>({
|
|
31
35
|
url: '/admin/users',
|
|
32
36
|
method: 'GET',
|
|
33
|
-
params
|
|
37
|
+
params
|
|
34
38
|
});
|
|
35
39
|
|
|
36
40
|
return response;
|
|
@@ -40,10 +44,10 @@ export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
|
40
44
|
* @override
|
|
41
45
|
*/
|
|
42
46
|
public create(data: UserSchema): Promise<unknown> {
|
|
43
|
-
return this.client.request
|
|
47
|
+
return this.client.request({
|
|
44
48
|
url: '/admin/users',
|
|
45
49
|
method: 'POST',
|
|
46
|
-
data
|
|
50
|
+
data
|
|
47
51
|
});
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -51,10 +55,10 @@ export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
|
51
55
|
* @override
|
|
52
56
|
*/
|
|
53
57
|
public remove(data: UserSchema): Promise<unknown> {
|
|
54
|
-
return this.client.request
|
|
58
|
+
return this.client.request({
|
|
55
59
|
url: '/admin/users',
|
|
56
60
|
method: 'DELETE',
|
|
57
|
-
data
|
|
61
|
+
data
|
|
58
62
|
});
|
|
59
63
|
}
|
|
60
64
|
|
|
@@ -62,10 +66,10 @@ export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
|
62
66
|
* @override
|
|
63
67
|
*/
|
|
64
68
|
public update(data: UserSchema): Promise<unknown> {
|
|
65
|
-
return this.client.request
|
|
69
|
+
return this.client.request({
|
|
66
70
|
url: '/admin/users',
|
|
67
71
|
method: 'PUT',
|
|
68
|
-
data
|
|
72
|
+
data
|
|
69
73
|
});
|
|
70
74
|
}
|
|
71
75
|
|
|
@@ -73,10 +77,10 @@ export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
|
73
77
|
* @override
|
|
74
78
|
*/
|
|
75
79
|
public export(data: UserSchema): Promise<unknown> {
|
|
76
|
-
return this.client.request
|
|
80
|
+
return this.client.request({
|
|
77
81
|
url: '/admin/users',
|
|
78
82
|
method: 'GET',
|
|
79
|
-
data
|
|
83
|
+
data
|
|
80
84
|
});
|
|
81
85
|
}
|
|
82
86
|
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ExecutorContextInterface,
|
|
2
3
|
ExecutorError,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type ExecutorPlugin
|
|
4
|
+
isRequestAdapterResponse,
|
|
5
|
+
LifecyclePluginInterface
|
|
6
6
|
} from '@qlover/fe-corekit';
|
|
7
7
|
import type { AppApiErrorInterface } from '@/base/port/AppApiInterface';
|
|
8
8
|
import type { AppApiConfig } from './AppApiRequester';
|
|
9
9
|
import type { LoggerInterface } from '@qlover/logger';
|
|
10
10
|
|
|
11
|
-
export class AppApiPlugin implements
|
|
11
|
+
export class AppApiPlugin implements LifecyclePluginInterface<
|
|
12
|
+
ExecutorContextInterface<AppApiConfig>
|
|
13
|
+
> {
|
|
12
14
|
public readonly pluginName = 'AppApiPlugin';
|
|
13
15
|
|
|
14
16
|
constructor(protected logger: LoggerInterface) {}
|
|
@@ -30,48 +32,46 @@ export class AppApiPlugin implements ExecutorPlugin {
|
|
|
30
32
|
/**
|
|
31
33
|
* @override
|
|
32
34
|
*/
|
|
33
|
-
public onSuccess(
|
|
34
|
-
context: ExecutorContext<AppApiConfig>
|
|
35
|
-
): void | Promise<void> {
|
|
35
|
+
public onSuccess(context: ExecutorContextInterface<AppApiConfig>): void {
|
|
36
36
|
const response = context.returnValue;
|
|
37
37
|
const { parameters } = context;
|
|
38
38
|
|
|
39
|
+
// Important: 当响应数据失败则抛出错误
|
|
40
|
+
if (isRequestAdapterResponse(response)) {
|
|
41
|
+
if (this.isAppApiErrorInterface(response.data)) {
|
|
42
|
+
throw new ExecutorError(response.data.message || response.data.id, response);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
39
46
|
this.logger.info(
|
|
40
47
|
`%c[AppApi ${parameters.method} ${parameters.url}]%c - ${new Date().toLocaleString()}`,
|
|
41
48
|
'color: #0f0;',
|
|
42
49
|
'color: inherit;',
|
|
43
50
|
response
|
|
44
51
|
);
|
|
45
|
-
|
|
46
|
-
if (this.isAppApiErrorInterface(response)) {
|
|
47
|
-
throw new Error(response.message || response.id);
|
|
48
|
-
}
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
/**
|
|
52
55
|
* @override
|
|
53
56
|
*/
|
|
54
57
|
public async onError(
|
|
55
|
-
context:
|
|
58
|
+
context: ExecutorContextInterface<AppApiConfig>
|
|
56
59
|
): Promise<ExecutorError | void> {
|
|
57
60
|
const { error, parameters } = context;
|
|
58
61
|
|
|
59
62
|
this.loggerError(parameters, error);
|
|
60
63
|
|
|
61
|
-
if (error instanceof
|
|
62
|
-
|
|
63
|
-
let response = error?.response;
|
|
64
|
+
if (error instanceof Error && parameters.responseType === 'json') {
|
|
65
|
+
let response = error?.cause;
|
|
64
66
|
|
|
65
67
|
if (response instanceof Response) {
|
|
66
68
|
// clone the response to avoid mutating the original response
|
|
67
69
|
response = response.clone();
|
|
68
70
|
|
|
69
|
-
const json = await this.getResponseJson(response);
|
|
71
|
+
const json = await this.getResponseJson(response as Response);
|
|
70
72
|
|
|
71
73
|
if (this.isAppApiErrorInterface(json)) {
|
|
72
|
-
|
|
73
|
-
// context.error = newError;
|
|
74
|
-
return newError;
|
|
74
|
+
return new ExecutorError(json.id, json);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
}
|
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
RequestAdapterFetch,
|
|
4
|
-
RequestTransaction
|
|
5
|
-
} from '@qlover/fe-corekit';
|
|
6
|
-
import { inject, injectable } from 'inversify';
|
|
1
|
+
import { LifecycleExecutor, RequestAdapterFetch, RequestExecutor } from '@qlover/fe-corekit';
|
|
2
|
+
import { injectable } from 'inversify';
|
|
7
3
|
import type { RequestEncryptPluginProps } from '@/base/cases/RequestEncryptPlugin';
|
|
8
4
|
import type { AppApiResult } from '@/base/port/AppApiInterface';
|
|
9
5
|
import type {
|
|
6
|
+
ExecutorContextInterface,
|
|
10
7
|
RequestAdapterConfig,
|
|
11
|
-
RequestAdapterResponse
|
|
12
|
-
RequestTransactionInterface
|
|
8
|
+
RequestAdapterResponse
|
|
13
9
|
} from '@qlover/fe-corekit';
|
|
14
10
|
|
|
11
|
+
export interface RequestTransactionInterface<Request, Response> {
|
|
12
|
+
request: Request;
|
|
13
|
+
response: Response;
|
|
14
|
+
}
|
|
15
|
+
|
|
15
16
|
export interface AppApiConfig<Request = unknown>
|
|
16
|
-
extends RequestAdapterConfig<Request>,
|
|
17
|
+
extends RequestAdapterConfig<Request>,
|
|
18
|
+
RequestEncryptPluginProps<Request> {}
|
|
19
|
+
|
|
20
|
+
export interface AppApiRequesterContext
|
|
21
|
+
extends ExecutorContextInterface<AppApiConfig> {}
|
|
17
22
|
|
|
18
23
|
/**
|
|
19
24
|
* UserApiResponse
|
|
@@ -32,26 +37,26 @@ export type AppApiResponse<
|
|
|
32
37
|
/**
|
|
33
38
|
* UserApi common transaction
|
|
34
39
|
*/
|
|
35
|
-
export interface AppApiTransaction<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
>
|
|
39
|
-
|
|
40
|
-
AppApiResponse<Request, Response>
|
|
41
|
-
> {
|
|
40
|
+
export interface AppApiTransaction<Request = unknown, Response = unknown>
|
|
41
|
+
extends RequestTransactionInterface<
|
|
42
|
+
AppApiConfig<Request>,
|
|
43
|
+
AppApiResponse<Request, Response>
|
|
44
|
+
> {
|
|
42
45
|
data: AppApiConfig<Request>['data'];
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
@injectable()
|
|
46
|
-
export class AppApiRequester extends
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
export class AppApiRequester extends RequestExecutor<
|
|
50
|
+
AppApiConfig,
|
|
51
|
+
AppApiRequesterContext
|
|
52
|
+
> {
|
|
53
|
+
constructor() {
|
|
50
54
|
super(
|
|
51
55
|
new RequestAdapterFetch({
|
|
52
56
|
baseURL: '/api',
|
|
53
57
|
responseType: 'json'
|
|
54
|
-
})
|
|
58
|
+
}),
|
|
59
|
+
new LifecycleExecutor()
|
|
55
60
|
);
|
|
56
61
|
}
|
|
57
62
|
}
|