@qlover/create-app 0.4.5 → 0.5.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 +95 -35
- package/dist/index.cjs +11 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +10 -2418
- package/{templates → dist/templates}/node-lib/package.json +2 -2
- package/{templates → dist/templates}/react-app/README.md +6 -6
- package/{templates/react-app/config/Identifier/Error.ts → dist/templates/react-app/config/Identifier/common.error.ts} +8 -8
- package/dist/templates/react-app/config/Identifier/common.ts +62 -0
- package/dist/templates/react-app/config/Identifier/index.ts +10 -0
- package/dist/templates/react-app/config/Identifier/page.about.ts +181 -0
- package/dist/templates/react-app/config/Identifier/page.executor.ts +267 -0
- package/dist/templates/react-app/config/Identifier/page.home.ts +63 -0
- package/dist/templates/react-app/config/Identifier/page.identifiter.ts +39 -0
- package/dist/templates/react-app/config/Identifier/page.jsonStorage.ts +70 -0
- package/dist/templates/react-app/config/Identifier/page.login.ts +152 -0
- package/dist/templates/react-app/config/Identifier/page.register.ts +147 -0
- package/dist/templates/react-app/config/Identifier/page.request.ts +179 -0
- package/dist/templates/react-app/config/app.router.ts +163 -0
- package/{templates → dist/templates}/react-app/config/feapi.mock.json +6 -0
- package/dist/templates/react-app/config/theme.ts +11 -0
- package/{templates → dist/templates}/react-app/package.json +2 -2
- package/{templates → dist/templates}/react-app/public/locales/en/common.json +97 -116
- package/{templates → dist/templates}/react-app/public/locales/zh/common.json +98 -117
- package/{templates → dist/templates}/react-app/src/App.tsx +6 -5
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +142 -0
- package/{templates → dist/templates}/react-app/src/base/apis/userApi/UserApiType.ts +11 -0
- package/{templates → dist/templates}/react-app/src/base/cases/AppConfig.ts +11 -0
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +36 -0
- package/{templates → dist/templates}/react-app/src/base/cases/RouterLoader.ts +2 -1
- package/{templates → dist/templates}/react-app/src/base/services/I18nService.ts +4 -4
- package/{templates/react-app/src/base/services/ProcesserService.ts → dist/templates/react-app/src/base/services/ProcesserExecutor.ts} +15 -5
- package/{templates → dist/templates}/react-app/src/base/services/RouteService.ts +11 -13
- package/dist/templates/react-app/src/base/services/UserService.ts +132 -0
- package/{templates → dist/templates}/react-app/src/base/types/Page.ts +12 -2
- package/{templates → dist/templates}/react-app/src/core/IOC.ts +11 -6
- package/{templates → dist/templates}/react-app/src/core/bootstrap.ts +2 -2
- package/{templates → dist/templates}/react-app/src/core/bootstraps/index.ts +3 -1
- package/{templates → dist/templates}/react-app/src/core/globals.ts +23 -7
- package/{templates → dist/templates}/react-app/src/core/registers/RegisterApi.ts +1 -1
- package/{templates → dist/templates}/react-app/src/core/registers/RegisterCommon.ts +14 -15
- package/{templates → dist/templates}/react-app/src/core/registers/RegisterControllers.ts +9 -4
- package/{templates → dist/templates}/react-app/src/core/registers/RegisterGlobals.ts +12 -4
- package/{templates → dist/templates}/react-app/src/pages/404.tsx +4 -1
- package/{templates → dist/templates}/react-app/src/pages/500.tsx +2 -1
- package/{templates → dist/templates}/react-app/src/pages/auth/Layout.tsx +2 -2
- package/{templates/react-app/src/pages/auth/Login.tsx → dist/templates/react-app/src/pages/auth/LoginPage.tsx} +2 -4
- package/{templates/react-app/src/pages/auth/Register.tsx → dist/templates/react-app/src/pages/auth/RegisterPage.tsx} +3 -6
- package/{templates/react-app/src/pages/base/About.tsx → dist/templates/react-app/src/pages/base/AboutPage.tsx} +4 -4
- package/{templates/react-app/src/pages/base/ErrorIdentifier.tsx → dist/templates/react-app/src/pages/base/ErrorIdentifierPage.tsx} +3 -3
- package/{templates/react-app/src/pages/base/Executor.tsx → dist/templates/react-app/src/pages/base/ExecutorPage.tsx} +3 -3
- package/{templates/react-app/src/pages/base/Home.tsx → dist/templates/react-app/src/pages/base/HomePage.tsx} +15 -45
- package/{templates/react-app/src/pages/base/JSONStorage.tsx → dist/templates/react-app/src/pages/base/JSONStoragePage.tsx} +3 -3
- package/{templates → dist/templates}/react-app/src/pages/base/Layout.tsx +4 -4
- package/{templates/react-app/src/pages/base/Request.tsx → dist/templates/react-app/src/pages/base/RequestPage.tsx} +2 -2
- package/{templates/react-app/src/pages/base → dist/templates/react-app/src/uikit}/components/LogoutButton.tsx +1 -1
- package/{templates → dist/templates}/react-app/src/uikit/components/ThemeSwitcher.tsx +5 -6
- package/{templates → dist/templates}/react-app/src/uikit/contexts/BaseRouteContext.ts +1 -1
- package/{templates → dist/templates}/react-app/src/uikit/controllers/ExecutorController.ts +2 -2
- package/{templates → dist/templates}/react-app/src/uikit/controllers/JSONStorageController.ts +5 -5
- package/{templates → dist/templates}/react-app/src/uikit/controllers/RequestController.ts +1 -1
- package/{templates/react-app/src/uikit/hooks/useLanguageGuard.ts → dist/templates/react-app/src/uikit/hooks/useI18nGuard.ts} +1 -1
- package/{templates → dist/templates}/react-app/src/uikit/hooks/useStore.ts +2 -2
- package/dist/templates/react-app/src/uikit/hooks/userRouterService.ts +12 -0
- package/{templates → dist/templates}/react-app/src/uikit/providers/BaseRouteProvider.tsx +1 -0
- package/dist/templates/react-app/src/uikit/providers/ProcessExecutorProvider.tsx +24 -0
- package/dist/templates/react-app/src/uikit/providers/UserAuthProvider.tsx +16 -0
- package/{templates → dist/templates}/react-app/vite.config.ts +2 -1
- package/package.json +4 -6
- package/templates/react-app/config/Identifier/Auth.ts +0 -13
- package/templates/react-app/config/Identifier/I18n.ts +0 -1366
- package/templates/react-app/config/app.router.json +0 -159
- package/templates/react-app/config/theme.json +0 -9
- package/templates/react-app/src/base/apis/userApi/UserApi.ts +0 -64
- package/templates/react-app/src/base/port/LoginInterface.ts +0 -12
- package/templates/react-app/src/base/port/StoreInterface.ts +0 -58
- package/templates/react-app/src/base/services/UserService.ts +0 -130
- package/templates/react-app/src/uikit/providers/ProcessProvider.tsx +0 -45
- /package/{configs → dist/configs}/_common/.editorconfig +0 -0
- /package/{configs → dist/configs}/_common/.env.template +0 -0
- /package/{configs → dist/configs}/_common/.gitattributes +0 -0
- /package/{configs → dist/configs}/_common/.github/workflows/general-check.yml +0 -0
- /package/{configs → dist/configs}/_common/.github/workflows/release.yml +0 -0
- /package/{configs → dist/configs}/_common/.gitignore.template +0 -0
- /package/{configs → dist/configs}/_common/.husky/commit-msg +0 -0
- /package/{configs → dist/configs}/_common/.husky/pre-commit +0 -0
- /package/{configs → dist/configs}/_common/.prettierignore +0 -0
- /package/{configs → dist/configs}/_common/.prettierrc.js +0 -0
- /package/{configs → dist/configs}/_common/.vscode/extensions.json +0 -0
- /package/{configs → dist/configs}/_common/.vscode/react.code-snippets +0 -0
- /package/{configs → dist/configs}/_common/.vscode/settings.json +0 -0
- /package/{configs → dist/configs}/_common/commitlint.config.js +0 -0
- /package/{configs → dist/configs}/_common/package.json.template +0 -0
- /package/{configs → dist/configs}/node-lib/eslint.config.js +0 -0
- /package/{configs → dist/configs}/react-app/eslint.config.js +0 -0
- /package/{templates → dist/templates}/node-lib/__tests__/readJson.test.ts +0 -0
- /package/{templates → dist/templates}/node-lib/bin/test.js +0 -0
- /package/{templates → dist/templates}/node-lib/rollup.config.js +0 -0
- /package/{templates → dist/templates}/node-lib/src/index.ts +0 -0
- /package/{templates → dist/templates}/node-lib/src/readJson.ts +0 -0
- /package/{templates → dist/templates}/node-lib/tsconfig.json +0 -0
- /package/{templates → dist/templates}/pack-app/README.md +0 -0
- /package/{templates → dist/templates}/pack-app/eslint.config.js +0 -0
- /package/{templates → dist/templates}/pack-app/fe-config.json +0 -0
- /package/{templates → dist/templates}/pack-app/package.json +0 -0
- /package/{templates → dist/templates}/pack-app/pnpm-workspace.yaml +0 -0
- /package/{templates → dist/templates}/pack-app/tsconfig.json +0 -0
- /package/{templates → dist/templates}/pack-app/tsconfig.test.json +0 -0
- /package/{templates → dist/templates}/pack-app/vite.config.ts +0 -0
- /package/{templates → dist/templates}/react-app/.env.template +0 -0
- /package/{templates → dist/templates}/react-app/config/common.ts +0 -0
- /package/{templates → dist/templates}/react-app/config/i18n.ts +0 -0
- /package/{templates → dist/templates}/react-app/index.html +0 -0
- /package/{templates → dist/templates}/react-app/postcss.config.js +0 -0
- /package/{templates → dist/templates}/react-app/public/logo.svg +0 -0
- /package/{templates → dist/templates}/react-app/public/router-root/logo.svg +0 -0
- /package/{templates → dist/templates}/react-app/src/assets/react.svg +0 -0
- /package/{templates → dist/templates}/react-app/src/base/apis/AiApi.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/apis/feApi/FeApi.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/apis/feApi/FeApiAdapter.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/apis/feApi/FeApiBootstarp.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/apis/feApi/FeApiType.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/apis/userApi/UserApiAdapter.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/apis/userApi/UserApiBootstarp.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/cases/AppError.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/cases/DialogHandler.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/cases/PublicAssetsPath.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/cases/RequestLogger.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/cases/RequestStatusCatcher.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/port/ApiTransactionInterface.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/port/InteractionHubInterface.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/port/RequestCatcherInterface.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/port/UIDependenciesInterface.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/types/deprecated-antd.d.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/base/types/global.d.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/core/bootstraps/BootstrapApp.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/core/bootstraps/PrintBootstrap.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/core/registers/index.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/main.tsx +0 -0
- /package/{templates → dist/templates}/react-app/src/pages/base/RedirectPathname.tsx +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/antd-themes/_default.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/antd-themes/dark.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/antd-themes/index.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/antd-themes/no-context.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/antd-themes/pink.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/index.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/page.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/tailwind.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/themes/_default.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/themes/dark.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/themes/index.css +0 -0
- /package/{templates → dist/templates}/react-app/src/styles/css/themes/pink.css +0 -0
- /package/{templates/react-app/src/pages/base → dist/templates/react-app/src/uikit}/components/BaseHeader.tsx +0 -0
- /package/{templates → dist/templates}/react-app/src/uikit/components/LanguageSwitcher.tsx +0 -0
- /package/{templates → dist/templates}/react-app/src/uikit/components/Loading.tsx +0 -0
- /package/{templates → dist/templates}/react-app/src/uikit/components/LocaleLink.tsx +0 -0
- /package/{templates → dist/templates}/react-app/src/uikit/components/RouterRenderComponent.tsx +0 -0
- /package/{templates → dist/templates}/react-app/src/uikit/hooks/useDocumentTitle.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/uikit/hooks/useStrictEffect.ts +0 -0
- /package/{templates → dist/templates}/react-app/src/vite-env.d.ts +0 -0
- /package/{templates → dist/templates}/react-app/tailwind.config.js +0 -0
- /package/{templates → dist/templates}/react-app/tsconfig.app.json +0 -0
- /package/{templates → dist/templates}/react-app/tsconfig.json +0 -0
- /package/{templates → dist/templates}/react-app/tsconfig.node.json +0 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FetchAbortPlugin,
|
|
3
|
+
RequestAdapterFetch,
|
|
4
|
+
RequestTransaction
|
|
5
|
+
} from '@qlover/fe-corekit';
|
|
6
|
+
import {
|
|
7
|
+
GetIpInfoTransaction,
|
|
8
|
+
UserApiGetUserInfoTransaction,
|
|
9
|
+
UserApiLoginTransaction,
|
|
10
|
+
UserApiTestApiCatchResultTransaction
|
|
11
|
+
} from './UserApiType';
|
|
12
|
+
import { inject, injectable } from 'inversify';
|
|
13
|
+
import { UserApiAdapter } from './UserApiAdapter';
|
|
14
|
+
import { UserApiConfig } from './UserApiBootstarp';
|
|
15
|
+
import {
|
|
16
|
+
LoginResponseData,
|
|
17
|
+
UserAuthApiInterface,
|
|
18
|
+
UserAuthStoreInterface
|
|
19
|
+
} from '@qlover/corekit-bridge';
|
|
20
|
+
import {
|
|
21
|
+
RegisterFormData,
|
|
22
|
+
UserServiceUserInfo
|
|
23
|
+
} from '@/base/services/UserService';
|
|
24
|
+
import { RES_NO_TOKEN } from '@config/Identifier';
|
|
25
|
+
import { AppError } from '@/base/cases/AppError';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* UserApi
|
|
29
|
+
*
|
|
30
|
+
* @description
|
|
31
|
+
* UserApi is a client for the user API.
|
|
32
|
+
*
|
|
33
|
+
*/
|
|
34
|
+
@injectable()
|
|
35
|
+
export class UserApi
|
|
36
|
+
extends RequestTransaction<UserApiConfig>
|
|
37
|
+
implements UserAuthApiInterface<UserServiceUserInfo>
|
|
38
|
+
{
|
|
39
|
+
protected store: UserAuthStoreInterface<UserServiceUserInfo> | null = null;
|
|
40
|
+
|
|
41
|
+
constructor(
|
|
42
|
+
@inject(FetchAbortPlugin) private abortPlugin: FetchAbortPlugin,
|
|
43
|
+
@inject(UserApiAdapter) adapter: RequestAdapterFetch
|
|
44
|
+
) {
|
|
45
|
+
super(adapter);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
getStore(): UserAuthStoreInterface<UserServiceUserInfo> | null {
|
|
49
|
+
return this.store;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @override
|
|
54
|
+
* @param store
|
|
55
|
+
*/
|
|
56
|
+
setStore(store: UserAuthStoreInterface<UserServiceUserInfo>): void {
|
|
57
|
+
this.store = store;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
stop(request: UserApiConfig): Promise<void> | void {
|
|
61
|
+
this.abortPlugin.abort(request);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async getRandomUser(): Promise<GetIpInfoTransaction['response']> {
|
|
65
|
+
return this.request<GetIpInfoTransaction>({
|
|
66
|
+
url: 'https://randomuser.me/api/',
|
|
67
|
+
method: 'GET',
|
|
68
|
+
disabledMock: true
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async testApiCatchResult(): Promise<
|
|
73
|
+
UserApiTestApiCatchResultTransaction['response']
|
|
74
|
+
> {
|
|
75
|
+
return this.request<UserApiTestApiCatchResultTransaction>({
|
|
76
|
+
url: 'https://randomuser.me/api/?_name=ApiCatchResult',
|
|
77
|
+
method: 'GET',
|
|
78
|
+
disabledMock: true,
|
|
79
|
+
openApiCatch: true
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @override
|
|
85
|
+
* @param params
|
|
86
|
+
* @returns
|
|
87
|
+
*/
|
|
88
|
+
async login(
|
|
89
|
+
params: UserApiLoginTransaction['data']
|
|
90
|
+
): Promise<LoginResponseData> {
|
|
91
|
+
const response = await this.post<UserApiLoginTransaction>(
|
|
92
|
+
'/api/login',
|
|
93
|
+
params
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
if (response.apiCatchResult) {
|
|
97
|
+
throw response.apiCatchResult;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!response.data.token) {
|
|
101
|
+
throw new AppError(RES_NO_TOKEN);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return response.data;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @override
|
|
109
|
+
* @param params
|
|
110
|
+
* @returns
|
|
111
|
+
*/
|
|
112
|
+
register(
|
|
113
|
+
params: RegisterFormData
|
|
114
|
+
): Promise<UserApiLoginTransaction['response']> {
|
|
115
|
+
return this.post<UserApiLoginTransaction>('/api/register', params);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @override
|
|
120
|
+
* @returns
|
|
121
|
+
*/
|
|
122
|
+
logout(): Promise<void> {
|
|
123
|
+
return Promise.resolve();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @override
|
|
128
|
+
* @returns
|
|
129
|
+
*/
|
|
130
|
+
async getUserInfo(): Promise<
|
|
131
|
+
UserApiGetUserInfoTransaction['response']['data']
|
|
132
|
+
> {
|
|
133
|
+
const response =
|
|
134
|
+
await this.get<UserApiGetUserInfoTransaction>('/api/userinfo');
|
|
135
|
+
|
|
136
|
+
if (response.apiCatchResult) {
|
|
137
|
+
throw response.apiCatchResult;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return response.data;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -50,3 +50,14 @@ export type UserApiLoginTransaction = UserApiTransaction<
|
|
|
50
50
|
>;
|
|
51
51
|
|
|
52
52
|
export type UserApiTestApiCatchResultTransaction = UserApiGetRandomUser;
|
|
53
|
+
|
|
54
|
+
export type UserApiRegisterTransaction = UserApiTransaction<
|
|
55
|
+
{
|
|
56
|
+
username: string;
|
|
57
|
+
email: string;
|
|
58
|
+
password: string;
|
|
59
|
+
confirmPassword: string;
|
|
60
|
+
agreeToTerms: boolean;
|
|
61
|
+
},
|
|
62
|
+
UserApiTransaction['response']['data']
|
|
63
|
+
>;
|
|
@@ -55,6 +55,12 @@ export class AppConfig implements EnvConfigInterface {
|
|
|
55
55
|
*/
|
|
56
56
|
readonly userTokenStorageKey = '__fe_user_token__';
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Storage key for user information
|
|
60
|
+
* @description Injected from VITE_USER_INFO_STORAGE_KEY environment variable
|
|
61
|
+
*/
|
|
62
|
+
readonly userInfoStorageKey = '__fe_user_info__';
|
|
63
|
+
|
|
58
64
|
/**
|
|
59
65
|
* Available OpenAI model configurations
|
|
60
66
|
* @description List of supported OpenAI models for the application
|
|
@@ -102,4 +108,9 @@ export class AppConfig implements EnvConfigInterface {
|
|
|
102
108
|
|
|
103
109
|
/** Flag indicating if AI service token is required */
|
|
104
110
|
readonly aiApiRequireToken = true;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Project startup href, usually from window.location.href
|
|
114
|
+
*/
|
|
115
|
+
readonly bootHref = '';
|
|
105
116
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ExecutorContext, ExecutorPlugin } from '@qlover/fe-corekit';
|
|
2
|
+
import type { LoggerInterface } from '@qlover/logger';
|
|
3
|
+
import { inject } from 'inversify';
|
|
4
|
+
import { I18nService } from '../services/I18nService';
|
|
5
|
+
import { IOCIdentifier } from '@/core/IOC';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* When throw error, it will be converted to i18n key
|
|
9
|
+
*
|
|
10
|
+
* If the error thrown is an i18n key, it will be converted to the corresponding text
|
|
11
|
+
*/
|
|
12
|
+
export class I18nKeyErrorPlugin implements ExecutorPlugin {
|
|
13
|
+
readonly pluginName = 'I18nKeyErrorPlugin';
|
|
14
|
+
|
|
15
|
+
constructor(
|
|
16
|
+
@inject(IOCIdentifier.Logger) private logger: LoggerInterface,
|
|
17
|
+
@inject(I18nService) private i18nService: I18nService
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
onError(context: ExecutorContext<unknown>): Error | void {
|
|
21
|
+
const { error } = context;
|
|
22
|
+
|
|
23
|
+
if (error instanceof Error) {
|
|
24
|
+
const i18nKey = error.message;
|
|
25
|
+
|
|
26
|
+
if (i18nKey && typeof i18nKey === 'string') {
|
|
27
|
+
const i18nText = this.i18nService.t(i18nKey);
|
|
28
|
+
|
|
29
|
+
if (i18nText && i18nText !== i18nKey) {
|
|
30
|
+
this.logger.debug('I18nKeyErrorPlugin Error:', i18nText);
|
|
31
|
+
return new Error(i18nText);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ComponentType, LazyExoticComponent, ReactNode } from 'react';
|
|
2
2
|
import { RouteObject } from 'react-router-dom';
|
|
3
3
|
import isString from 'lodash/isString';
|
|
4
|
+
import { RouteMeta } from '../types/Page';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Component mapping type for lazy-loaded components
|
|
@@ -38,7 +39,7 @@ export type RouteConfigValue = Omit<RouteObject, 'element' | 'children'> & {
|
|
|
38
39
|
* Additional metadata for the route
|
|
39
40
|
* @description Can store any route-specific data like permissions, titles, etc.
|
|
40
41
|
*/
|
|
41
|
-
meta?:
|
|
42
|
+
meta?: RouteMeta;
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
/**
|
|
@@ -4,11 +4,11 @@ import LanguageDetector from 'i18next-browser-languagedetector';
|
|
|
4
4
|
import HttpApi from 'i18next-http-backend';
|
|
5
5
|
import merge from 'lodash/merge';
|
|
6
6
|
import i18nConfig from '@config/i18n';
|
|
7
|
-
import type { BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
|
|
8
7
|
import {
|
|
9
|
-
|
|
10
|
-
StoreStateInterface
|
|
11
|
-
|
|
8
|
+
type BootstrapExecutorPlugin,
|
|
9
|
+
type StoreStateInterface,
|
|
10
|
+
StoreInterface
|
|
11
|
+
} from '@qlover/corekit-bridge';
|
|
12
12
|
const { supportedLngs, fallbackLng } = i18nConfig;
|
|
13
13
|
|
|
14
14
|
export type I18nServiceLocale = (typeof supportedLngs)[number];
|
|
@@ -2,12 +2,15 @@ import { AsyncExecutor, ExecutorPlugin } from '@qlover/fe-corekit';
|
|
|
2
2
|
import { IOCIdentifier } from '@/core/IOC';
|
|
3
3
|
import { injectable, inject } from 'inversify';
|
|
4
4
|
import type { LoggerInterface } from '@qlover/logger';
|
|
5
|
+
import { RouteService } from './RouteService';
|
|
5
6
|
|
|
6
7
|
@injectable()
|
|
7
|
-
export class
|
|
8
|
+
export class ProcesserExecutor {
|
|
9
|
+
protected executor: AsyncExecutor = new AsyncExecutor();
|
|
10
|
+
|
|
8
11
|
constructor(
|
|
9
12
|
@inject(IOCIdentifier.Logger) private logger: LoggerInterface,
|
|
10
|
-
@inject(
|
|
13
|
+
@inject(RouteService) private routeService: RouteService
|
|
11
14
|
) {}
|
|
12
15
|
|
|
13
16
|
use(plugin: ExecutorPlugin): this {
|
|
@@ -21,9 +24,16 @@ export class ProcesserService {
|
|
|
21
24
|
});
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
async starup(): Promise<unknown> {
|
|
28
|
+
this.logger.info('PageProcesser startup');
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const result = await this.executor.exec(this.handler);
|
|
32
|
+
return result;
|
|
33
|
+
} catch (err) {
|
|
26
34
|
this.logger.error('PageProcesser init failed', err);
|
|
27
|
-
|
|
35
|
+
|
|
36
|
+
this.routeService.gotoLogin();
|
|
37
|
+
}
|
|
28
38
|
}
|
|
29
39
|
}
|
|
@@ -3,23 +3,23 @@ import type { NavigateFunction, NavigateOptions } from 'react-router-dom';
|
|
|
3
3
|
import type { UIDependenciesInterface } from '@/base/port/UIDependenciesInterface';
|
|
4
4
|
import type { LoggerInterface } from '@qlover/logger';
|
|
5
5
|
import { I18nService } from '@/base/services/I18nService';
|
|
6
|
+
import { StoreInterface, StoreStateInterface } from '@qlover/corekit-bridge';
|
|
6
7
|
|
|
7
8
|
export type RouterServiceDependencies = {
|
|
8
9
|
navigate: NavigateFunction;
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export type RouterServiceOptions = {
|
|
12
|
-
|
|
13
|
-
routes: RouteConfigValue[];
|
|
14
|
-
};
|
|
13
|
+
routes: RouteConfigValue[];
|
|
15
14
|
logger: LoggerInterface;
|
|
16
15
|
};
|
|
17
16
|
|
|
18
|
-
export
|
|
19
|
-
routes: RouteConfigValue[]
|
|
20
|
-
}
|
|
17
|
+
export class RouterServiceState implements StoreStateInterface {
|
|
18
|
+
constructor(public routes: RouteConfigValue[] = []) {}
|
|
19
|
+
}
|
|
21
20
|
|
|
22
21
|
export class RouteService
|
|
22
|
+
extends StoreInterface<RouterServiceState>
|
|
23
23
|
implements UIDependenciesInterface<RouterServiceDependencies>
|
|
24
24
|
{
|
|
25
25
|
/**
|
|
@@ -27,12 +27,8 @@ export class RouteService
|
|
|
27
27
|
*/
|
|
28
28
|
dependencies?: RouterServiceDependencies;
|
|
29
29
|
|
|
30
|
-
state: RouterServiceState;
|
|
31
|
-
|
|
32
30
|
constructor(private options: RouterServiceOptions) {
|
|
33
|
-
|
|
34
|
-
routes: options.config.routes
|
|
35
|
-
};
|
|
31
|
+
super(() => new RouterServiceState(options.routes));
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
get logger(): LoggerInterface {
|
|
@@ -43,7 +39,9 @@ export class RouteService
|
|
|
43
39
|
const navigate = this.dependencies?.navigate;
|
|
44
40
|
|
|
45
41
|
if (!navigate) {
|
|
46
|
-
this.logger.debug(
|
|
42
|
+
this.logger.debug(
|
|
43
|
+
'Please use `RouterServiceProvider` to set dependencies'
|
|
44
|
+
);
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
return navigate;
|
|
@@ -69,7 +67,7 @@ export class RouteService
|
|
|
69
67
|
}
|
|
70
68
|
|
|
71
69
|
changeRoutes(routes: RouteConfigValue[]): void {
|
|
72
|
-
this.
|
|
70
|
+
this.emit({ routes });
|
|
73
71
|
}
|
|
74
72
|
|
|
75
73
|
goto(path: string, options?: NavigateOptions): void {
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { ExecutorPlugin, type SyncStorageInterface } from '@qlover/fe-corekit';
|
|
2
|
+
import type {
|
|
3
|
+
UserApiGetUserInfoTransaction,
|
|
4
|
+
UserApiLoginTransaction
|
|
5
|
+
} from '@/base/apis/userApi/UserApiType';
|
|
6
|
+
import { RouteService } from './RouteService';
|
|
7
|
+
import {
|
|
8
|
+
LoginResponseData,
|
|
9
|
+
type UserAuthApiInterface,
|
|
10
|
+
UserAuthService,
|
|
11
|
+
UserAuthStore
|
|
12
|
+
} from '@qlover/corekit-bridge';
|
|
13
|
+
import { inject, injectable } from 'inversify';
|
|
14
|
+
import { UserApi } from '@/base/apis/userApi/UserApi';
|
|
15
|
+
import { AppError } from '@/base/cases/AppError';
|
|
16
|
+
import * as errKeys from '@config/Identifier/common.error';
|
|
17
|
+
import { IOCIdentifier } from '@/core/IOC';
|
|
18
|
+
import { AppConfig } from '../cases/AppConfig';
|
|
19
|
+
|
|
20
|
+
export type UserServiceUserInfo =
|
|
21
|
+
UserApiGetUserInfoTransaction['response']['data'];
|
|
22
|
+
|
|
23
|
+
export interface RegisterFormData {
|
|
24
|
+
username: string;
|
|
25
|
+
email: string;
|
|
26
|
+
password: string;
|
|
27
|
+
confirmPassword: string;
|
|
28
|
+
agreeToTerms: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@injectable()
|
|
32
|
+
export class UserService
|
|
33
|
+
extends UserAuthService<UserServiceUserInfo>
|
|
34
|
+
implements ExecutorPlugin
|
|
35
|
+
{
|
|
36
|
+
readonly pluginName = 'UserService';
|
|
37
|
+
|
|
38
|
+
constructor(
|
|
39
|
+
@inject(RouteService) protected routerService: RouteService,
|
|
40
|
+
@inject(UserApi) userApi: UserAuthApiInterface<UserServiceUserInfo>,
|
|
41
|
+
@inject(IOCIdentifier.AppConfig) appConfig: AppConfig,
|
|
42
|
+
@inject(IOCIdentifier.LocalStorageEncrypt)
|
|
43
|
+
storage: SyncStorageInterface<string, string>
|
|
44
|
+
) {
|
|
45
|
+
super({
|
|
46
|
+
api: userApi,
|
|
47
|
+
userStorage: {
|
|
48
|
+
key: appConfig.userInfoStorageKey,
|
|
49
|
+
storage: storage
|
|
50
|
+
},
|
|
51
|
+
credentialStorage: {
|
|
52
|
+
key: appConfig.userTokenStorageKey,
|
|
53
|
+
storage: storage
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// FIXME:
|
|
58
|
+
// load credential from storage
|
|
59
|
+
// this.store.setCredential(this.store.getCredentialStorage()?.get() ?? '');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @override
|
|
64
|
+
*/
|
|
65
|
+
override get store(): UserAuthStore<UserServiceUserInfo> {
|
|
66
|
+
return super.store as UserAuthStore<UserServiceUserInfo>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
getToken(): string | null {
|
|
70
|
+
return this.store.getCredential();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @override
|
|
75
|
+
*/
|
|
76
|
+
async onBefore(): Promise<void> {
|
|
77
|
+
if (this.isAuthenticated()) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const userToken = this.getToken();
|
|
82
|
+
|
|
83
|
+
if (!userToken) {
|
|
84
|
+
throw new AppError(errKeys.LOCAL_NO_USER_TOKEN);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (userToken) {
|
|
88
|
+
this.store.authSuccess();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
await this.userInfo();
|
|
92
|
+
this.store.authSuccess();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @override
|
|
97
|
+
*/
|
|
98
|
+
onSuccess(): void {
|
|
99
|
+
// if (this.isAuthenticated()) {
|
|
100
|
+
// this.store.authSuccess();
|
|
101
|
+
// } else {
|
|
102
|
+
// this.logout();
|
|
103
|
+
// }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @override
|
|
108
|
+
*/
|
|
109
|
+
override async logout(): Promise<void> {
|
|
110
|
+
await super.logout();
|
|
111
|
+
|
|
112
|
+
this.routerService.reset();
|
|
113
|
+
this.routerService.gotoLogin();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async register(params: RegisterFormData): Promise<LoginResponseData> {
|
|
117
|
+
const response = (await this.api.register(
|
|
118
|
+
params
|
|
119
|
+
)) as UserApiLoginTransaction['response'];
|
|
120
|
+
|
|
121
|
+
if (response.data?.token) {
|
|
122
|
+
try {
|
|
123
|
+
await this.userInfo({ token: response.data?.token });
|
|
124
|
+
this.store.authSuccess();
|
|
125
|
+
} catch (error) {
|
|
126
|
+
this.store.authFailed(error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
throw new AppError(errKeys.LOCAL_NO_USER_TOKEN);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -10,12 +10,22 @@ export interface BasePageProvider {
|
|
|
10
10
|
type RouteCategory = 'main' | 'auth' | 'common';
|
|
11
11
|
|
|
12
12
|
export interface RouteMeta {
|
|
13
|
-
category?: RouteCategory;
|
|
14
13
|
/**
|
|
15
|
-
*
|
|
14
|
+
* The title of the route
|
|
16
15
|
*/
|
|
17
16
|
title?: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The description of the route
|
|
20
|
+
*/
|
|
21
|
+
description?: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The icon of the route
|
|
25
|
+
*/
|
|
18
26
|
icon?: string;
|
|
27
|
+
|
|
28
|
+
category?: RouteCategory;
|
|
19
29
|
/**
|
|
20
30
|
* from app.router.json
|
|
21
31
|
*
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
import {
|
|
3
3
|
ApiMockPlugin,
|
|
4
4
|
EnvConfigInterface,
|
|
5
|
-
StorageTokenInterface,
|
|
6
5
|
RequestCommonPlugin,
|
|
7
6
|
ApiCatchPlugin,
|
|
8
7
|
IOCContainerInterface,
|
|
9
8
|
createIOCFunction,
|
|
10
|
-
ServiceIdentifier
|
|
9
|
+
ServiceIdentifier,
|
|
10
|
+
TokenStorage,
|
|
11
|
+
CookieStorage
|
|
11
12
|
} from '@qlover/corekit-bridge';
|
|
12
|
-
import type { JSONSerializer,
|
|
13
|
+
import type { JSONSerializer, ObjectStorage } from '@qlover/fe-corekit';
|
|
13
14
|
import type { LoggerInterface } from '@qlover/logger';
|
|
14
15
|
import type { AppConfig } from '@/base/cases/AppConfig';
|
|
15
16
|
import { Container } from 'inversify';
|
|
@@ -69,7 +70,9 @@ export class InversifyContainer implements IOCContainerInterface {
|
|
|
69
70
|
*/
|
|
70
71
|
export const IOCIdentifier = Object.freeze({
|
|
71
72
|
JSON: 'JSON',
|
|
72
|
-
|
|
73
|
+
LocalStorage: 'LocalStorage',
|
|
74
|
+
LocalStorageEncrypt: 'LocalStorageEncrypt',
|
|
75
|
+
CookieStorage: 'CookieStorage',
|
|
73
76
|
Logger: 'Logger',
|
|
74
77
|
FeApiToken: 'FeApiToken',
|
|
75
78
|
FeApiCommonPlugin: 'FeApiCommonPlugin',
|
|
@@ -84,9 +87,11 @@ export const IOCIdentifier = Object.freeze({
|
|
|
84
87
|
*/
|
|
85
88
|
export interface IOCIdentifierMap {
|
|
86
89
|
[IOCIdentifier.JSON]: JSONSerializer;
|
|
87
|
-
[IOCIdentifier.
|
|
90
|
+
[IOCIdentifier.LocalStorage]: ObjectStorage<string, string>;
|
|
91
|
+
[IOCIdentifier.LocalStorageEncrypt]: ObjectStorage<string, string>;
|
|
92
|
+
[IOCIdentifier.CookieStorage]: CookieStorage;
|
|
88
93
|
[IOCIdentifier.Logger]: LoggerInterface;
|
|
89
|
-
[IOCIdentifier.FeApiToken]:
|
|
94
|
+
[IOCIdentifier.FeApiToken]: TokenStorage<string>;
|
|
90
95
|
[IOCIdentifier.FeApiCommonPlugin]: RequestCommonPlugin;
|
|
91
96
|
[IOCIdentifier.AppConfig]: EnvConfigInterface;
|
|
92
97
|
[IOCIdentifier.ApiMockPlugin]: ApiMockPlugin;
|
|
@@ -4,7 +4,7 @@ import { IOC } from './IOC';
|
|
|
4
4
|
import * as globals from '@/core/globals';
|
|
5
5
|
import { IocRegister } from './registers';
|
|
6
6
|
import { BootstrapsRegistry } from './bootstraps';
|
|
7
|
-
import { GLOBAL_NO_WINDOW } from '@config/Identifier/
|
|
7
|
+
import { GLOBAL_NO_WINDOW } from '@config/Identifier/common.error';
|
|
8
8
|
|
|
9
9
|
export default async function startup({
|
|
10
10
|
root,
|
|
@@ -33,7 +33,7 @@ export default async function startup({
|
|
|
33
33
|
},
|
|
34
34
|
envOptions: {
|
|
35
35
|
target: appConfig,
|
|
36
|
-
source: envSource,
|
|
36
|
+
source: { ...envSource, [envPrefix + 'BOOT_HREF']: root.location.href },
|
|
37
37
|
prefix: envPrefix,
|
|
38
38
|
blackList: envBlackList
|
|
39
39
|
},
|
|
@@ -11,6 +11,7 @@ import { AiApiBootstarp } from '@/base/apis/AiApi';
|
|
|
11
11
|
import { printBootstrap } from './PrintBootstrap';
|
|
12
12
|
import { IOCIdentifier, type IOCIdentifierMap } from '../IOC';
|
|
13
13
|
import { I18nService } from '@/base/services/I18nService';
|
|
14
|
+
import { I18nKeyErrorPlugin } from '@/base/cases/I18nKeyErrorPlugin';
|
|
14
15
|
|
|
15
16
|
export class BootstrapsRegistry {
|
|
16
17
|
constructor(
|
|
@@ -29,7 +30,8 @@ export class BootstrapsRegistry {
|
|
|
29
30
|
new UserApiBootstarp(),
|
|
30
31
|
new FeApiBootstarp(),
|
|
31
32
|
AiApiBootstarp,
|
|
32
|
-
new BootstrapApp()
|
|
33
|
+
new BootstrapApp(),
|
|
34
|
+
IOC(I18nKeyErrorPlugin)
|
|
33
35
|
];
|
|
34
36
|
|
|
35
37
|
if (this.appConfig.env !== 'production') {
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
// ! global variables, don't import any dependencies and don't have side effects
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
Base64Serializer,
|
|
4
|
+
JSONSerializer,
|
|
5
|
+
ObjectStorage,
|
|
6
|
+
SyncStorage,
|
|
7
|
+
SyncStorageInterface
|
|
8
|
+
} from '@qlover/fe-corekit';
|
|
9
|
+
import {
|
|
10
|
+
ColorFormatter,
|
|
11
|
+
ConsoleHandler,
|
|
12
|
+
CookieStorage,
|
|
13
|
+
Logger
|
|
14
|
+
} from '@qlover/corekit-bridge';
|
|
4
15
|
import { DialogHandler } from '@/base/cases/DialogHandler';
|
|
5
16
|
import { loggerStyles } from '@config/common';
|
|
6
17
|
import { AppConfig } from '@/base/cases/AppConfig';
|
|
@@ -26,9 +37,14 @@ export const logger = new Logger({
|
|
|
26
37
|
export const JSON = new JSONSerializer();
|
|
27
38
|
|
|
28
39
|
/**
|
|
29
|
-
* Override
|
|
40
|
+
* Override localStorage to use the global local storage
|
|
30
41
|
*/
|
|
31
|
-
export const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
export const localStorage = new SyncStorage(new ObjectStorage(), [
|
|
43
|
+
JSON,
|
|
44
|
+
new Base64Serializer(),
|
|
45
|
+
window.localStorage as unknown as SyncStorageInterface<string>
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
export const localStorageEncrypt = localStorage;
|
|
49
|
+
|
|
50
|
+
export const cookieStorage = new CookieStorage();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InversifyContainer, InversifyRegisterInterface } from '../IOC';
|
|
1
|
+
import type { InversifyContainer, InversifyRegisterInterface } from '../IOC';
|
|
2
2
|
|
|
3
3
|
export class RegisterApi implements InversifyRegisterInterface {
|
|
4
4
|
register(_container: InversifyContainer): void {}
|