@qlover/create-app 0.6.2 → 0.7.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 +53 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/react-app/README.en.md +257 -0
- package/dist/templates/react-app/README.md +29 -231
- package/dist/templates/react-app/__tests__/__mocks__/I18nService.ts +13 -0
- package/dist/templates/react-app/__tests__/__mocks__/MockAppConfit.ts +48 -0
- package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +16 -0
- package/dist/templates/react-app/__tests__/__mocks__/MockLogger.ts +14 -0
- package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +92 -0
- package/dist/templates/react-app/__tests__/setup/index.ts +51 -0
- package/dist/templates/react-app/__tests__/src/App.test.tsx +139 -0
- package/dist/templates/react-app/__tests__/src/base/cases/AppConfig.test.ts +288 -0
- package/dist/templates/react-app/__tests__/src/base/cases/AppError.test.ts +102 -0
- package/dist/templates/react-app/__tests__/src/base/cases/DialogHandler.test.ts +228 -0
- package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +207 -0
- package/dist/templates/react-app/__tests__/src/base/cases/InversifyContainer.test.ts +181 -0
- package/dist/templates/react-app/__tests__/src/base/cases/PublicAssetsPath.test.ts +61 -0
- package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +199 -0
- package/dist/templates/react-app/__tests__/src/base/cases/RequestStatusCatcher.test.ts +192 -0
- package/dist/templates/react-app/__tests__/src/base/cases/RouterLoader.test.ts +235 -0
- package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +224 -0
- package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +257 -0
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +72 -0
- package/dist/templates/react-app/__tests__/src/main.integration.test.tsx +62 -0
- package/dist/templates/react-app/__tests__/src/main.test.tsx +46 -0
- package/dist/templates/react-app/__tests__/src/uikit/components/BaseHeader.test.tsx +88 -0
- package/dist/templates/react-app/config/app.router.ts +155 -0
- package/dist/templates/react-app/config/common.ts +9 -1
- package/dist/templates/react-app/docs/en/bootstrap.md +562 -0
- package/dist/templates/react-app/docs/en/development-guide.md +523 -0
- package/dist/templates/react-app/docs/en/env.md +482 -0
- package/dist/templates/react-app/docs/en/global.md +509 -0
- package/dist/templates/react-app/docs/en/i18n.md +268 -0
- package/dist/templates/react-app/docs/en/index.md +173 -0
- package/dist/templates/react-app/docs/en/ioc.md +424 -0
- package/dist/templates/react-app/docs/en/project-structure.md +434 -0
- package/dist/templates/react-app/docs/en/request.md +425 -0
- package/dist/templates/react-app/docs/en/router.md +404 -0
- package/dist/templates/react-app/docs/en/store.md +321 -0
- package/dist/templates/react-app/docs/en/test-guide.md +782 -0
- package/dist/templates/react-app/docs/en/theme.md +424 -0
- package/dist/templates/react-app/docs/en/typescript-guide.md +473 -0
- package/dist/templates/react-app/docs/zh/bootstrap.md +7 -0
- package/dist/templates/react-app/docs/zh/development-guide.md +523 -0
- package/dist/templates/react-app/docs/zh/env.md +24 -25
- package/dist/templates/react-app/docs/zh/global.md +28 -27
- package/dist/templates/react-app/docs/zh/i18n.md +268 -0
- package/dist/templates/react-app/docs/zh/index.md +173 -0
- package/dist/templates/react-app/docs/zh/ioc.md +44 -32
- package/dist/templates/react-app/docs/zh/project-structure.md +434 -0
- package/dist/templates/react-app/docs/zh/request.md +429 -0
- package/dist/templates/react-app/docs/zh/router.md +408 -0
- package/dist/templates/react-app/docs/zh/store.md +321 -0
- package/dist/templates/react-app/docs/zh/test-guide.md +782 -0
- package/dist/templates/react-app/docs/zh/theme.md +424 -0
- package/dist/templates/react-app/docs/zh/typescript-guide.md +473 -0
- package/dist/templates/react-app/package.json +9 -20
- package/dist/templates/react-app/src/base/cases/AppConfig.ts +16 -9
- package/dist/templates/react-app/src/base/cases/PublicAssetsPath.ts +7 -1
- package/dist/templates/react-app/src/base/services/I18nService.ts +15 -4
- package/dist/templates/react-app/src/base/services/RouteService.ts +43 -7
- package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +31 -10
- package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +1 -1
- package/dist/templates/react-app/src/core/globals.ts +1 -3
- package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +5 -3
- package/dist/templates/react-app/src/main.tsx +6 -1
- package/dist/templates/react-app/src/pages/404.tsx +0 -1
- package/dist/templates/react-app/src/pages/500.tsx +1 -1
- package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +3 -1
- package/dist/templates/react-app/src/styles/css/antd-themes/dark.css +3 -1
- package/dist/templates/react-app/src/styles/css/antd-themes/index.css +1 -1
- package/dist/templates/react-app/src/styles/css/antd-themes/pink.css +6 -1
- package/dist/templates/react-app/src/styles/css/page.css +1 -1
- package/dist/templates/react-app/src/uikit/components/BaseHeader.tsx +9 -2
- package/dist/templates/react-app/src/uikit/components/LocaleLink.tsx +5 -3
- package/dist/templates/react-app/src/uikit/hooks/useI18nGuard.ts +4 -6
- package/dist/templates/react-app/tsconfig.json +2 -1
- package/dist/templates/react-app/tsconfig.test.json +13 -0
- package/dist/templates/react-app/vite.config.ts +3 -2
- package/package.json +1 -1
|
@@ -14,11 +14,20 @@ export type RouterServiceDependencies = {
|
|
|
14
14
|
|
|
15
15
|
export type RouterServiceOptions = {
|
|
16
16
|
routes: RouteConfigValue[];
|
|
17
|
+
/**
|
|
18
|
+
* Whether to use locale routes
|
|
19
|
+
*
|
|
20
|
+
* @default `false`
|
|
21
|
+
*/
|
|
22
|
+
hasLocalRoutes?: boolean;
|
|
17
23
|
logger: LoggerInterface;
|
|
18
24
|
};
|
|
19
25
|
|
|
20
26
|
export class RouterServiceState implements StoreStateInterface {
|
|
21
|
-
constructor(
|
|
27
|
+
constructor(
|
|
28
|
+
public routes: RouteConfigValue[] = [],
|
|
29
|
+
public localeRoutes: boolean = false
|
|
30
|
+
) {}
|
|
22
31
|
}
|
|
23
32
|
|
|
24
33
|
export class RouteService
|
|
@@ -31,7 +40,9 @@ export class RouteService
|
|
|
31
40
|
dependencies?: RouterServiceDependencies;
|
|
32
41
|
|
|
33
42
|
constructor(private options: RouterServiceOptions) {
|
|
34
|
-
super(
|
|
43
|
+
super(
|
|
44
|
+
() => new RouterServiceState(options.routes, !!options.hasLocalRoutes)
|
|
45
|
+
);
|
|
35
46
|
}
|
|
36
47
|
|
|
37
48
|
get logger(): LoggerInterface {
|
|
@@ -51,8 +62,11 @@ export class RouteService
|
|
|
51
62
|
}
|
|
52
63
|
|
|
53
64
|
composePath(path: string): string {
|
|
54
|
-
|
|
55
|
-
|
|
65
|
+
if (this.state.localeRoutes) {
|
|
66
|
+
const targetLang = I18nService.getCurrentLanguage();
|
|
67
|
+
return `/${targetLang}${path}`;
|
|
68
|
+
}
|
|
69
|
+
return path.startsWith('/') ? path : `/${path}`;
|
|
56
70
|
}
|
|
57
71
|
|
|
58
72
|
/**
|
|
@@ -70,13 +84,19 @@ export class RouteService
|
|
|
70
84
|
}
|
|
71
85
|
|
|
72
86
|
changeRoutes(routes: RouteConfigValue[]): void {
|
|
73
|
-
this.emit({ routes });
|
|
87
|
+
this.emit({ routes, localeRoutes: this.state.localeRoutes });
|
|
74
88
|
}
|
|
75
89
|
|
|
76
|
-
goto(
|
|
90
|
+
goto(
|
|
91
|
+
path: string,
|
|
92
|
+
options?: NavigateOptions & {
|
|
93
|
+
navigate?: NavigateFunction;
|
|
94
|
+
}
|
|
95
|
+
): void {
|
|
96
|
+
const { navigate, ...rest } = options || {};
|
|
77
97
|
path = this.composePath(path);
|
|
78
98
|
this.logger.debug('Goto path => ', path);
|
|
79
|
-
this.navigate?.(path,
|
|
99
|
+
(navigate || this.navigate)?.(path, rest);
|
|
80
100
|
}
|
|
81
101
|
|
|
82
102
|
gotoLogin(): void {
|
|
@@ -86,4 +106,20 @@ export class RouteService
|
|
|
86
106
|
replaceToHome(): void {
|
|
87
107
|
this.goto('/', { replace: true });
|
|
88
108
|
}
|
|
109
|
+
|
|
110
|
+
redirectToDefault(navigate: NavigateFunction): void {
|
|
111
|
+
this.goto('/', { replace: true, navigate });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
i18nGuard(lng: string, navigate: NavigateFunction): void {
|
|
115
|
+
if (!this.state.localeRoutes) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!lng) {
|
|
120
|
+
this.goto('/404', { replace: true, navigate });
|
|
121
|
+
} else if (!I18nService.isValidLanguage(lng)) {
|
|
122
|
+
this.goto('/404', { replace: true, navigate });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
89
125
|
}
|
|
@@ -1,34 +1,52 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Bootstrap,
|
|
3
|
+
IOCContainerInterface,
|
|
4
|
+
IOCFunctionInterface
|
|
5
|
+
} from '@qlover/corekit-bridge';
|
|
2
6
|
import { envBlackList, envPrefix, browserGlobalsName } from '@config/common';
|
|
3
|
-
import { IOC } from '../IOC';
|
|
4
7
|
import * as globals from '../globals';
|
|
5
|
-
import { GLOBAL_NO_WINDOW } from '@config/Identifier/common.error';
|
|
6
8
|
import { IocRegisterImpl } from '../registers/IocRegisterImpl';
|
|
7
9
|
import { BootstrapsRegistry } from './BootstrapsRegistry';
|
|
10
|
+
import { isObject } from 'lodash';
|
|
11
|
+
import { IOCIdentifierMap } from '../IOC';
|
|
12
|
+
|
|
13
|
+
export type BootstrapAppArgs = {
|
|
14
|
+
/**
|
|
15
|
+
* 启动的根节点,通常是window
|
|
16
|
+
*/
|
|
17
|
+
root: unknown;
|
|
18
|
+
/**
|
|
19
|
+
* 启动的web地址
|
|
20
|
+
*/
|
|
21
|
+
bootHref: string;
|
|
22
|
+
/**
|
|
23
|
+
* IOC容器
|
|
24
|
+
*/
|
|
25
|
+
IOC: IOCFunctionInterface<IOCIdentifierMap, IOCContainerInterface>;
|
|
26
|
+
};
|
|
8
27
|
|
|
9
28
|
export class BootstrapApp {
|
|
10
|
-
static async main(): Promise<
|
|
11
|
-
const root =
|
|
29
|
+
static async main(args: BootstrapAppArgs): Promise<BootstrapAppArgs> {
|
|
30
|
+
const { root, bootHref, IOC } = args;
|
|
12
31
|
|
|
13
|
-
if (!(
|
|
14
|
-
throw new Error(
|
|
32
|
+
if (!isObject(root)) {
|
|
33
|
+
throw new Error('root is not an object');
|
|
15
34
|
}
|
|
16
35
|
|
|
17
36
|
const { logger, appConfig } = globals;
|
|
18
|
-
const { pathname } = root.location;
|
|
19
37
|
|
|
20
38
|
const bootstrap = new Bootstrap({
|
|
21
39
|
root,
|
|
22
40
|
logger,
|
|
23
41
|
ioc: {
|
|
24
42
|
manager: IOC,
|
|
25
|
-
register: new IocRegisterImpl({ pathname, appConfig })
|
|
43
|
+
register: new IocRegisterImpl({ pathname: bootHref, appConfig })
|
|
26
44
|
},
|
|
27
45
|
envOptions: {
|
|
28
46
|
target: appConfig,
|
|
29
47
|
source: {
|
|
30
48
|
...import.meta.env,
|
|
31
|
-
[envPrefix + 'BOOT_HREF']:
|
|
49
|
+
[envPrefix + 'BOOT_HREF']: bootHref
|
|
32
50
|
},
|
|
33
51
|
prefix: envPrefix,
|
|
34
52
|
blackList: envBlackList
|
|
@@ -49,7 +67,10 @@ export class BootstrapApp {
|
|
|
49
67
|
|
|
50
68
|
await bootstrap.use(bootstrapsRegistry.register()).start();
|
|
51
69
|
} catch (error) {
|
|
70
|
+
console.log(error);
|
|
52
71
|
logger.error(`${appConfig.appName} starup error:`, error);
|
|
53
72
|
}
|
|
73
|
+
|
|
74
|
+
return args;
|
|
54
75
|
}
|
|
55
76
|
}
|
|
@@ -16,8 +16,6 @@ import { DialogHandler } from '@/base/cases/DialogHandler';
|
|
|
16
16
|
import { loggerStyles } from '@config/common';
|
|
17
17
|
import { AppConfig } from '@/base/cases/AppConfig';
|
|
18
18
|
|
|
19
|
-
const isProduction = import.meta.env.VITE_USER_NODE_ENV === 'production';
|
|
20
|
-
|
|
21
19
|
export const appConfig = new AppConfig();
|
|
22
20
|
|
|
23
21
|
export const dialogHandler = new DialogHandler();
|
|
@@ -27,7 +25,7 @@ export const dialogHandler = new DialogHandler();
|
|
|
27
25
|
*/
|
|
28
26
|
export const logger = new Logger({
|
|
29
27
|
handlers: new ConsoleHandler(new ColorFormatter(loggerStyles)),
|
|
30
|
-
silent: isProduction,
|
|
28
|
+
silent: appConfig.isProduction,
|
|
31
29
|
level: 'debug'
|
|
32
30
|
});
|
|
33
31
|
|
|
@@ -16,7 +16,8 @@ import { themeConfig } from '@config/theme';
|
|
|
16
16
|
import { localStorage, logger } from '../globals';
|
|
17
17
|
import { I18nService } from '@/base/services/I18nService';
|
|
18
18
|
import { RouteService } from '@/base/services/RouteService';
|
|
19
|
-
import { baseRoutes } from '@config/app.router';
|
|
19
|
+
import { baseRoutes, baseNoLocaleRoutes } from '@config/app.router';
|
|
20
|
+
import { useLocaleRoutes } from '@config/common';
|
|
20
21
|
import { UserService } from '@/base/services/UserService';
|
|
21
22
|
import { IOCRegister } from '../IOC';
|
|
22
23
|
import { IOCIdentifier } from '@config/IOCIdentifier';
|
|
@@ -62,8 +63,9 @@ export const RegisterCommon: IOCRegister = {
|
|
|
62
63
|
container.bind(
|
|
63
64
|
RouteService,
|
|
64
65
|
new RouteService({
|
|
65
|
-
routes: baseRoutes,
|
|
66
|
-
logger
|
|
66
|
+
routes: useLocaleRoutes ? baseRoutes : baseNoLocaleRoutes,
|
|
67
|
+
logger,
|
|
68
|
+
hasLocalRoutes: useLocaleRoutes
|
|
67
69
|
})
|
|
68
70
|
);
|
|
69
71
|
|
|
@@ -4,8 +4,13 @@ import { StrictMode } from 'react';
|
|
|
4
4
|
import { createRoot } from 'react-dom/client';
|
|
5
5
|
import App from './App.tsx';
|
|
6
6
|
import { BootstrapApp } from './core/bootstraps/BootstrapApp';
|
|
7
|
+
import { IOC } from './core/IOC.ts';
|
|
7
8
|
|
|
8
|
-
BootstrapApp.main(
|
|
9
|
+
BootstrapApp.main({
|
|
10
|
+
root: window,
|
|
11
|
+
bootHref: window.location.href,
|
|
12
|
+
IOC: IOC
|
|
13
|
+
});
|
|
9
14
|
|
|
10
15
|
createRoot(document.getElementById('root')!).render(
|
|
11
16
|
<StrictMode>
|
|
@@ -8,7 +8,6 @@ export default function NotFound({ route }: { route?: string }) {
|
|
|
8
8
|
<div className="flex flex-col justify-center min-h-screen py-6 bg-background sm:py-12">
|
|
9
9
|
<div className="relative py-3 mx-auto sm:max-w-xl">
|
|
10
10
|
<h1 className="text-text text-2xl font-bold text-center">
|
|
11
|
-
404 -
|
|
12
11
|
{route ? `${t(NOT_FOUND_COMPONENT)}: ${route}` : t(PAGE_404_TITLE)}
|
|
13
12
|
</h1>
|
|
14
13
|
</div>
|
|
@@ -7,7 +7,7 @@ export default function NotFound500() {
|
|
|
7
7
|
<div className="flex flex-col justify-center min-h-screen py-6 bg-background sm:py-12">
|
|
8
8
|
<div className="relative py-3 mx-auto sm:max-w-xl">
|
|
9
9
|
<h1 className="text-text text-2xl font-bold text-center">
|
|
10
|
-
|
|
10
|
+
{t(PAGE_500_TITLE)}
|
|
11
11
|
</h1>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { RouteService } from '@/base/services/RouteService';
|
|
2
|
+
import { IOC } from '@/core/IOC';
|
|
1
3
|
import { useEffect } from 'react';
|
|
2
4
|
import { useNavigate } from 'react-router-dom';
|
|
3
5
|
|
|
@@ -6,7 +8,7 @@ const RedirectToDefault = () => {
|
|
|
6
8
|
|
|
7
9
|
useEffect(() => {
|
|
8
10
|
// Redirect to the default language path
|
|
9
|
-
|
|
11
|
+
IOC(RouteService).redirectToDefault(navigate);
|
|
10
12
|
}, [navigate]);
|
|
11
13
|
|
|
12
14
|
return null;
|
|
@@ -37,7 +37,9 @@
|
|
|
37
37
|
/* Antd 基础变量 */
|
|
38
38
|
--fe-color-bg-container: rgb(30 41 59);
|
|
39
39
|
--fe-color-bg-elevated: rgb(51 65 85);
|
|
40
|
-
--fe-color-text-heading: rgb(
|
|
40
|
+
--fe-color-text-heading: rgb(
|
|
41
|
+
241 245 249
|
|
42
|
+
); /* slate-100 用于暗色主题标题文本 */
|
|
41
43
|
--fe-color-text: rgba(255, 255, 255, 0.85);
|
|
42
44
|
--fe-color-text-secondary: rgba(255, 255, 255, 0.45);
|
|
43
45
|
--fe-color-text-tertiary: rgba(255, 255, 255, 0.35);
|
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
--fe-color-primary: #f472b6; /* pink-400 */
|
|
5
5
|
--fe-color-primary-hover: #ec4899; /* pink-500 */
|
|
6
6
|
--fe-color-primary-active: #db2777; /* pink-600 */
|
|
7
|
-
--fe-color-primary-bg: rgba(
|
|
7
|
+
--fe-color-primary-bg: rgba(
|
|
8
|
+
244,
|
|
9
|
+
114,
|
|
10
|
+
182,
|
|
11
|
+
0.1
|
|
12
|
+
); /* pink-400 with 0.1 opacity */
|
|
8
13
|
--fe-color-primary-border: #f472b6; /* pink-400 */
|
|
9
14
|
--fe-color-primary-text: #f472b6; /* pink-400 */
|
|
10
15
|
--fe-color-primary-text-hover: #ec4899; /* pink-500 */
|
|
@@ -11,7 +11,10 @@ export default function BaseHeader({
|
|
|
11
11
|
showLogoutButton?: boolean;
|
|
12
12
|
}) {
|
|
13
13
|
return (
|
|
14
|
-
<header
|
|
14
|
+
<header
|
|
15
|
+
data-testid="base-header"
|
|
16
|
+
className="h-14 bg-secondary border-b border-border sticky top-0 z-50"
|
|
17
|
+
>
|
|
15
18
|
<div className="flex items-center justify-between h-full px-4 mx-auto max-w-7xl">
|
|
16
19
|
<div className="flex items-center">
|
|
17
20
|
<LocaleLink
|
|
@@ -19,11 +22,15 @@ export default function BaseHeader({
|
|
|
19
22
|
className="flex items-center hover:opacity-80 transition-opacity"
|
|
20
23
|
>
|
|
21
24
|
<img
|
|
25
|
+
data-testid="base-header-logo"
|
|
22
26
|
src={IOC(PublicAssetsPath).getPath('/logo.svg')}
|
|
23
27
|
alt="logo"
|
|
24
28
|
className="h-8 w-auto"
|
|
25
29
|
/>
|
|
26
|
-
<span
|
|
30
|
+
<span
|
|
31
|
+
data-testid="base-header-app-name"
|
|
32
|
+
className="ml-2 text-lg font-semibold text-text"
|
|
33
|
+
>
|
|
27
34
|
{IOC('AppConfig').appName}
|
|
28
35
|
</span>
|
|
29
36
|
</LocaleLink>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LinkProps, Link as RouterLink, To, useParams } from 'react-router-dom';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
+
import { useLocaleRoutes } from '@config/common';
|
|
3
4
|
|
|
4
5
|
interface LocaleLinkProps extends Omit<LinkProps, 'href' | 'to'> {
|
|
5
6
|
href: string | To;
|
|
@@ -21,19 +22,20 @@ const LocaleLink: React.FC<LocaleLinkProps> = ({
|
|
|
21
22
|
locale = locale || lng;
|
|
22
23
|
|
|
23
24
|
const isDefaultLocale = locale === defaultLocale;
|
|
25
|
+
const shouldAddLocale = useLocaleRoutes && !isDefaultLocale;
|
|
24
26
|
|
|
25
27
|
let localizedHref: string | To;
|
|
26
28
|
if (typeof href === 'string') {
|
|
27
|
-
localizedHref =
|
|
29
|
+
localizedHref = shouldAddLocale ? `/${locale}${href}` : href;
|
|
28
30
|
} else {
|
|
29
31
|
localizedHref = {
|
|
30
32
|
...href,
|
|
31
|
-
pathname:
|
|
33
|
+
pathname: shouldAddLocale ? `/${locale}${href.pathname}` : href.pathname
|
|
32
34
|
};
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
return (
|
|
36
|
-
<RouterLink {...props} to={localizedHref}>
|
|
38
|
+
<RouterLink data-testid="locale-link" {...props} to={localizedHref}>
|
|
37
39
|
{children}
|
|
38
40
|
</RouterLink>
|
|
39
41
|
);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { I18nServiceLocale } from '@/base/services/I18nService';
|
|
2
|
+
import { RouteService } from '@/base/services/RouteService';
|
|
3
|
+
import { IOC } from '@/core/IOC';
|
|
2
4
|
import { useEffect } from 'react';
|
|
3
5
|
import { useNavigate } from 'react-router-dom';
|
|
4
6
|
import { useParams } from 'react-router-dom';
|
|
@@ -15,10 +17,6 @@ export function useI18nGuard() {
|
|
|
15
17
|
const navigate = useNavigate();
|
|
16
18
|
|
|
17
19
|
useEffect(() => {
|
|
18
|
-
|
|
19
|
-
navigate('/404', { replace: true });
|
|
20
|
-
} else if (!I18nService.isValidLanguage(lng)) {
|
|
21
|
-
navigate('/404', { replace: true });
|
|
22
|
-
}
|
|
20
|
+
IOC(RouteService).i18nGuard(lng as I18nServiceLocale, navigate);
|
|
23
21
|
}, [lng, navigate]);
|
|
24
22
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.app.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"jsx": "react-jsx",
|
|
5
|
+
"types": ["vitest/globals", "vite/client"],
|
|
6
|
+
"paths": {
|
|
7
|
+
"@/*": ["./src/*"],
|
|
8
|
+
"@config/*": ["./config/*"]
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"include": ["__tests__/**/*"],
|
|
12
|
+
"exclude": ["node_modules", "dist"]
|
|
13
|
+
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from './config/common';
|
|
9
9
|
import { name, version } from './package.json';
|
|
10
10
|
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
11
|
-
import envConfig from '@qlover/corekit-bridge/vite-env-config';
|
|
11
|
+
import envConfig from '@qlover/corekit-bridge/build/vite-env-config';
|
|
12
12
|
import ts2Locales from '@brain-toolkit/ts2locales/vite';
|
|
13
13
|
import i18nConfig from './config/i18n';
|
|
14
14
|
import tailwindcss from '@tailwindcss/vite';
|
|
@@ -120,8 +120,9 @@ export default defineConfig({
|
|
|
120
120
|
port: Number(process.env.VITE_SERVER_PORT || 3200)
|
|
121
121
|
},
|
|
122
122
|
test: {
|
|
123
|
+
watch: false,
|
|
123
124
|
environment: 'jsdom',
|
|
124
125
|
globals: true,
|
|
125
|
-
setupFiles: ['./
|
|
126
|
+
setupFiles: ['./__tests__/setup/index.ts']
|
|
126
127
|
}
|
|
127
128
|
});
|