@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.
Files changed (68) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/templates/next-app/next.config.ts +4 -3
  5. package/dist/templates/next-app/package.json +14 -11
  6. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +2 -3
  7. package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +6 -4
  8. package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +14 -10
  9. package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +2 -2
  10. package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +1 -4
  11. package/dist/templates/next-app/src/base/services/I18nService.ts +6 -2
  12. package/dist/templates/next-app/src/base/services/adminApi/AdminApiRequester.ts +11 -7
  13. package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +11 -10
  14. package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +16 -12
  15. package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +19 -19
  16. package/dist/templates/next-app/src/base/services/appApi/AppApiRequester.ts +26 -21
  17. package/dist/templates/next-app/src/base/services/appApi/AppUserApi.ts +15 -6
  18. package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +12 -14
  19. package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +34 -17
  20. package/dist/templates/next-app/src/server/NextApiServer.ts +10 -4
  21. package/dist/templates/next-app/src/server/PasswordEncrypt.ts +2 -2
  22. package/dist/templates/next-app/src/server/controllers/UserController.ts +2 -2
  23. package/dist/templates/next-app/src/server/port/ServerInterface.ts +2 -2
  24. package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +6 -7
  25. package/dist/templates/next-app/src/server/services/UserService.ts +2 -2
  26. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +11 -47
  27. package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +3 -2
  28. package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +6 -1
  29. package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +21 -61
  30. package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +29 -51
  31. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +8 -26
  32. package/dist/templates/react-app/__tests__/src/main.test.tsx +2 -2
  33. package/dist/templates/react-app/config/IOCIdentifier.ts +1 -1
  34. package/dist/templates/react-app/docs/en/test-guide.md +5 -5
  35. package/dist/templates/react-app/docs/zh/test-guide.md +5 -5
  36. package/dist/templates/react-app/package.json +2 -1
  37. package/dist/templates/react-app/src/base/apis/AiApi.ts +20 -12
  38. package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +14 -5
  39. package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +26 -13
  40. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +30 -34
  41. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +20 -17
  42. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +11 -5
  43. package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +19 -6
  44. package/dist/templates/react-app/src/base/cases/RequestLogger.ts +11 -11
  45. package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +11 -5
  46. package/dist/templates/react-app/src/base/services/UserBootstrap.ts +6 -7
  47. package/dist/templates/react-app/src/base/services/UserService.ts +1 -5
  48. package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +6 -7
  49. package/dist/templates/react-app/src/main.tsx +1 -1
  50. package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +5 -5
  51. package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +3 -1
  52. package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +6 -2
  53. package/dist/templates/react-app/src/pages/base/MessagePage.tsx +34 -3
  54. package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +13 -7
  55. package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +6 -1
  56. package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +26 -11
  57. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +1 -1
  58. package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +3 -1
  59. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +16 -7
  60. package/dist/templates/react-app/src/vite-env.d.ts +1 -1
  61. package/dist/templates/react-app/tsconfig.e2e.json +5 -2
  62. package/dist/templates/react-app/tsconfig.json +7 -0
  63. package/dist/templates/react-app/tsconfig.node.json +4 -2
  64. package/dist/templates/react-app/tsconfig.test.json +4 -1
  65. package/package.json +3 -3
  66. package/dist/templates/react-app/src/base/cases/AppError.ts +0 -10
  67. package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +0 -20
  68. package/dist/templates/react-app/src/base/services/UserGatewayPlugin.ts +0 -20
@@ -6,8 +6,8 @@ import type {
6
6
  UserApiRegisterTransaction
7
7
  } from '@/base/port/AppUserApiInterface';
8
8
  import { AppApiRequester } from './AppApiRequester';
9
- import type { AppApiConfig } from './AppApiRequester';
10
- import type { RequestTransaction } from '@qlover/fe-corekit';
9
+ import type { AppApiConfig, AppApiRequesterContext } from './AppApiRequester';
10
+ import { RequestExecutor } from '@qlover/fe-corekit';
11
11
 
12
12
  /**
13
13
  * UserApi
@@ -20,7 +20,7 @@ import type { RequestTransaction } from '@qlover/fe-corekit';
20
20
  export class AppUserApi implements AppUserApiInterface {
21
21
  constructor(
22
22
  @inject(AppApiRequester)
23
- protected client: RequestTransaction<AppApiConfig>
23
+ protected client: RequestExecutor<AppApiConfig, AppApiRequesterContext>
24
24
  ) {}
25
25
 
26
26
  /**
@@ -29,7 +29,10 @@ export class AppUserApi implements AppUserApiInterface {
29
29
  public async login(
30
30
  params: UserApiLoginTransaction['data']
31
31
  ): Promise<UserApiLoginTransaction['response']> {
32
- const response = await this.client.request<UserApiLoginTransaction>({
32
+ const response = await this.client.request<
33
+ UserApiLoginTransaction['response'],
34
+ UserApiLoginTransaction['request']
35
+ >({
33
36
  url: '/user/login',
34
37
  method: 'POST',
35
38
  data: params,
@@ -45,7 +48,10 @@ export class AppUserApi implements AppUserApiInterface {
45
48
  public async register(
46
49
  params: UserApiRegisterTransaction['data']
47
50
  ): Promise<UserApiRegisterTransaction['response']> {
48
- const response = await this.client.request<UserApiRegisterTransaction>({
51
+ const response = await this.client.request<
52
+ UserApiRegisterTransaction['response'],
53
+ UserApiRegisterTransaction['request']
54
+ >({
49
55
  url: '/user/register',
50
56
  method: 'POST',
51
57
  data: params,
@@ -61,7 +67,10 @@ export class AppUserApi implements AppUserApiInterface {
61
67
  public async logout(
62
68
  _params?: unknown
63
69
  ): Promise<UserApiLogoutTransaction['response']> {
64
- return await this.client.request<UserApiLogoutTransaction>({
70
+ return await this.client.request<
71
+ UserApiLogoutTransaction['response'],
72
+ UserApiLogoutTransaction['request']
73
+ >({
65
74
  url: '/user/logout',
66
75
  method: 'POST'
67
76
  });
@@ -1,5 +1,4 @@
1
- import { RequestCommonPlugin } from '@qlover/corekit-bridge';
2
- import { FetchURLPlugin } from '@qlover/fe-corekit';
1
+ import { RequestPlugin, ResponsePlugin } from '@qlover/fe-corekit';
3
2
  import { DialogErrorPlugin } from '@/base/cases/DialogErrorPlugin';
4
3
  import { RequestEncryptPlugin } from '@/base/cases/RequestEncryptPlugin';
5
4
  import { StringEncryptor } from '@/base/cases/StringEncryptor';
@@ -11,7 +10,7 @@ import type {
11
10
  BootstrapContext,
12
11
  BootstrapExecutorPlugin
13
12
  } from '@qlover/corekit-bridge';
14
- import type { ExecutorContext, SerializerIneterface } from '@qlover/fe-corekit';
13
+ import type { SerializerIneterface } from '@qlover/fe-corekit';
15
14
 
16
15
  export class AppUserApiBootstrap implements BootstrapExecutorPlugin {
17
16
  public readonly pluginName = 'AppUserApiBootstrap';
@@ -21,20 +20,19 @@ export class AppUserApiBootstrap implements BootstrapExecutorPlugin {
21
20
  /**
22
21
  * @override
23
22
  */
24
- public onBefore({
25
- parameters: { ioc }
26
- }: BootstrapContext): void | Promise<void> {
23
+ public onBefore({ parameters: { ioc } }: BootstrapContext): void {
27
24
  const appUserApi = ioc.get<AppApiRequester>(AppApiRequester);
28
25
 
29
- appUserApi.usePlugin(new FetchURLPlugin());
30
- appUserApi.usePlugin(new RequestEncryptPlugin(ioc.get(StringEncryptor)));
31
- appUserApi.usePlugin(
32
- new RequestCommonPlugin({
26
+ // 数据加密优先于 RequestPlugin(会序列化数据)
27
+ appUserApi.use(new RequestEncryptPlugin(ioc.get(StringEncryptor)));
28
+ appUserApi.use(
29
+ new RequestPlugin({
33
30
  requestDataSerializer: this.requestDataSerializer.bind(this)
34
31
  })
35
32
  );
36
- appUserApi.usePlugin(new AppApiPlugin(ioc.get(I.Logger)));
37
- appUserApi.usePlugin(ioc.get(DialogErrorPlugin));
33
+ appUserApi.use(new ResponsePlugin());
34
+ appUserApi.use(new AppApiPlugin(ioc.get(I.Logger)));
35
+ appUserApi.use(ioc.get(DialogErrorPlugin));
38
36
  }
39
37
 
40
38
  /**
@@ -42,13 +40,13 @@ export class AppUserApiBootstrap implements BootstrapExecutorPlugin {
42
40
  */
43
41
  protected requestDataSerializer(
44
42
  data: unknown,
45
- context: ExecutorContext<AppApiConfig>
43
+ config: AppApiConfig
46
44
  ): unknown {
47
45
  if (data instanceof FormData) {
48
46
  return data;
49
47
  }
50
48
 
51
- if (context.parameters?.responseType === 'json') {
49
+ if (config.responseType === 'json') {
52
50
  return this.serializer.serialize(data);
53
51
  }
54
52
 
@@ -1,28 +1,37 @@
1
1
  import 'reflect-metadata';
2
2
  import {
3
3
  type ServiceIdentifier,
4
- type BootstrapContextValue,
5
- type BootstrapExecutorPlugin,
6
4
  type IOCContainerInterface,
7
- type IOCFunctionInterface
5
+ type IOCFunctionInterface,
6
+ BootstrapPluginOptions
8
7
  } from '@qlover/corekit-bridge';
9
8
  import {
10
- AsyncExecutor,
11
- type ExecutorError,
12
- type PromiseTask,
13
- type ExecutorPlugin
9
+ ExecutorAsyncTask,
10
+ ExecutorContextInterface,
11
+ LifecycleExecutor,
12
+ LifecyclePluginInterface,
13
+ type ExecutorError
14
14
  } from '@qlover/fe-corekit';
15
15
  import type { ServerInterface } from '@/server/port/ServerInterface';
16
16
  import { I, type IOCIdentifierMapServer } from '@config/IOCIdentifier';
17
17
  import { ServerIOC } from '../serverIoc/ServerIOC';
18
18
  import type { LoggerInterface } from '@qlover/logger';
19
19
 
20
- export interface BootstrapServerContextValue extends BootstrapContextValue {
20
+ export interface BootstrapServerContextOptions extends BootstrapPluginOptions {
21
21
  IOC: IOCFunctionInterface<IOCIdentifierMapServer, IOCContainerInterface>;
22
22
  }
23
23
 
24
+ export interface BootstrapServerPlugin
25
+ extends LifecyclePluginInterface<BootstrapServerContext> {}
26
+
27
+ export interface BootstrapServerContext
28
+ extends ExecutorContextInterface<BootstrapServerContextOptions> {}
29
+
24
30
  export class BootstrapServer implements ServerInterface {
25
- protected executor: AsyncExecutor;
31
+ protected executor: LifecycleExecutor<
32
+ BootstrapServerContext,
33
+ BootstrapServerPlugin
34
+ >;
26
35
  protected root: Record<string, unknown> = {};
27
36
  protected IOC: IOCFunctionInterface<
28
37
  IOCIdentifierMapServer,
@@ -35,7 +44,7 @@ export class BootstrapServer implements ServerInterface {
35
44
  const ioc = serverIOC.create();
36
45
  const logger = ioc(I.Logger);
37
46
 
38
- this.executor = new AsyncExecutor();
47
+ this.executor = new LifecycleExecutor();
39
48
  this.IOC = ioc;
40
49
  this.logger = logger;
41
50
  }
@@ -76,20 +85,25 @@ export class BootstrapServer implements ServerInterface {
76
85
  */
77
86
  public use(
78
87
  plugin:
79
- | BootstrapExecutorPlugin
80
- | BootstrapExecutorPlugin[]
88
+ | BootstrapServerPlugin
89
+ | BootstrapServerPlugin[]
81
90
  | ((
82
91
  ioc: IOCFunctionInterface<
83
92
  IOCIdentifierMapServer,
84
93
  IOCContainerInterface
85
94
  >
86
- ) => BootstrapExecutorPlugin)
95
+ ) => BootstrapServerPlugin)
87
96
  ): this {
88
97
  if (typeof plugin === 'function') {
89
98
  plugin = plugin(this.IOC);
90
99
  }
91
100
 
92
- this.executor.use(plugin as ExecutorPlugin<unknown>);
101
+ if (Array.isArray(plugin)) {
102
+ plugin.forEach((p) => this.executor.use(p));
103
+ return this;
104
+ }
105
+
106
+ this.executor.use(plugin);
93
107
  return this;
94
108
  }
95
109
 
@@ -97,15 +111,18 @@ export class BootstrapServer implements ServerInterface {
97
111
  * @override
98
112
  */
99
113
  public execNoError<Result>(
100
- task?: PromiseTask<Result, BootstrapServerContextValue>
114
+ task?: ExecutorAsyncTask<Result, BootstrapServerContextOptions>
101
115
  ): Promise<Result | ExecutorError> {
102
- const context = {
116
+ const options = {
103
117
  logger: this.logger,
104
118
  root: this.root,
105
119
  ioc: this.IOC.implemention!,
106
120
  IOC: this.IOC
107
121
  };
108
122
 
109
- return this.executor.execNoError(context, task);
123
+ return this.executor.execNoError(
124
+ options,
125
+ task ?? (() => Promise.resolve(undefined as Result))
126
+ );
110
127
  }
111
128
  }
@@ -5,11 +5,11 @@ import {
5
5
  isAppApiSuccessInterface,
6
6
  type AppApiResult
7
7
  } from '@/base/port/AppApiInterface';
8
- import type { BootstrapServerContextValue } from '@/core/bootstraps/BootstrapServer';
8
+ import type { BootstrapServerContextOptions } from '@/core/bootstraps/BootstrapServer';
9
9
  import { BootstrapServer } from '@/core/bootstraps/BootstrapServer';
10
10
  import { AppErrorApi } from './AppErrorApi';
11
11
  import { AppSuccessApi } from './AppSuccessApi';
12
- import type { PromiseTask } from '@qlover/fe-corekit';
12
+ import type { ExecutorAsyncTask } from '@qlover/fe-corekit';
13
13
 
14
14
  export class NextApiServer extends BootstrapServer {
15
15
  /**
@@ -23,7 +23,10 @@ export class NextApiServer extends BootstrapServer {
23
23
  * @override
24
24
  */
25
25
  public async run<Result>(
26
- task?: PromiseTask<Result | AppApiResult, BootstrapServerContextValue>
26
+ task?: ExecutorAsyncTask<
27
+ Result | AppApiResult,
28
+ BootstrapServerContextOptions
29
+ >
27
30
  ): Promise<AppApiResult> {
28
31
  const result = await this.execNoError(task);
29
32
 
@@ -49,7 +52,10 @@ export class NextApiServer extends BootstrapServer {
49
52
  * @override
50
53
  */
51
54
  public async runWithJson<Result>(
52
- task?: PromiseTask<Result | AppApiResult, BootstrapServerContextValue>
55
+ task?: ExecutorAsyncTask<
56
+ Result | AppApiResult,
57
+ BootstrapServerContextOptions
58
+ >
53
59
  ): Promise<NextResponse> {
54
60
  const result = await this.run(task);
55
61
 
@@ -1,7 +1,7 @@
1
1
  import crypto from 'crypto';
2
- import type { Encryptor } from '@qlover/fe-corekit';
2
+ import type { EncryptorInterface } from '@qlover/fe-corekit';
3
3
 
4
- export class PasswordEncrypt implements Encryptor<string, string> {
4
+ export class PasswordEncrypt implements EncryptorInterface<string, string> {
5
5
  /**
6
6
  * @override
7
7
  */
@@ -12,14 +12,14 @@ import type { ServerAuthInterface } from '../port/ServerAuthInterface';
12
12
  import type { UserControllerInerface } from '../port/UserControllerInerface';
13
13
  import type { UserServiceInterface } from '../port/UserServiceInterface';
14
14
  import type { ValidatorInterface } from '../port/ValidatorInterface';
15
- import type { Encryptor } from '@qlover/fe-corekit';
15
+ import type { EncryptorInterface } from '@qlover/fe-corekit';
16
16
 
17
17
  @injectable()
18
18
  export class UserController implements UserControllerInerface {
19
19
  constructor(
20
20
  @inject(ServerAuth) protected serverAuth: ServerAuthInterface,
21
21
  @inject(StringEncryptor)
22
- protected stringEncryptor: Encryptor<string, string>,
22
+ protected stringEncryptor: EncryptorInterface<string, string>,
23
23
  @inject(LoginValidator)
24
24
  protected loginValidator: ValidatorInterface<LoginValidatorData>,
25
25
  @inject(UserService) protected userService: UserServiceInterface
@@ -1,4 +1,4 @@
1
- import { type ExecutorError, type PromiseTask } from '@qlover/fe-corekit';
1
+ import { ExecutorAsyncTask, type ExecutorError } from '@qlover/fe-corekit';
2
2
  import { type IOCIdentifierMapServer } from '@config/IOCIdentifier';
3
3
  import type {
4
4
  ServiceIdentifier,
@@ -17,6 +17,6 @@ export interface ServerInterface {
17
17
  getIOC<T>(serviceIdentifier: ServiceIdentifier<T>): T;
18
18
 
19
19
  execNoError<Result>(
20
- task?: PromiseTask<Result, unknown>
20
+ task?: ExecutorAsyncTask<Result, unknown>
21
21
  ): Promise<Result | ExecutorError>;
22
22
  }
@@ -1,18 +1,17 @@
1
- import type { BootstrapServerContextValue } from '@/core/bootstraps/BootstrapServer';
1
+ import type {
2
+ BootstrapServerContext,
3
+ BootstrapServerPlugin
4
+ } from '@/core/bootstraps/BootstrapServer';
2
5
  import { ServerAuth } from '../ServerAuth';
3
6
  import type { ServerAuthInterface } from '../port/ServerAuthInterface';
4
- import type { BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
5
- import type { ExecutorContext } from '@qlover/fe-corekit';
6
7
 
7
- export class AdminAuthPlugin implements BootstrapExecutorPlugin {
8
+ export class AdminAuthPlugin implements BootstrapServerPlugin {
8
9
  public pluginName = 'AdminAuthPlugin';
9
10
 
10
11
  /**
11
12
  * @override
12
13
  */
13
- public async onBefore(
14
- context: ExecutorContext<BootstrapServerContextValue>
15
- ): Promise<void> {
14
+ public async onBefore(context: BootstrapServerContext): Promise<void> {
16
15
  const { IOC } = context.parameters;
17
16
 
18
17
  const serverAuth: ServerAuthInterface = IOC(ServerAuth);
@@ -16,7 +16,7 @@ import type { CrentialTokenInterface } from '../port/CrentialTokenInterface';
16
16
  import type { ServerAuthInterface } from '../port/ServerAuthInterface';
17
17
  import type { UserRepositoryInterface } from '../port/UserRepositoryInterface';
18
18
  import type { UserServiceInterface } from '../port/UserServiceInterface';
19
- import type { Encryptor } from '@qlover/fe-corekit';
19
+ import type { EncryptorInterface } from '@qlover/fe-corekit';
20
20
 
21
21
  @injectable()
22
22
  export class UserService implements UserServiceInterface {
@@ -26,7 +26,7 @@ export class UserService implements UserServiceInterface {
26
26
  @inject(ServerAuth)
27
27
  protected userAuth: ServerAuthInterface,
28
28
  @inject(PasswordEncrypt)
29
- protected encryptor: Encryptor<string, string>,
29
+ protected encryptor: EncryptorInterface<string, string>,
30
30
  @inject(UserCredentialToken)
31
31
  protected credentialToken: CrentialTokenInterface<UserCredentialTokenValue>
32
32
  ) {}
@@ -1,13 +1,19 @@
1
1
  'use client';
2
2
  import '@ant-design/v5-patch-for-react-19';
3
3
 
4
- import { useState } from 'react';
4
+ import { useEffect, useState } from 'react';
5
+ import { useLocale } from 'next-intl';
5
6
  import { BootstrapClient } from '@/core/bootstraps/BootstrapClient';
6
7
  import { useIOC } from '../hook/useIOC';
7
8
  import { useStrictEffect } from '../hook/useStrictEffect';
9
+ import { useWarnTranslations } from '../hook/useWarnTranslations';
10
+ import { I } from '@config/IOCIdentifier';
11
+ import type { I18nServiceLocale } from '@/base/port/I18nServiceInterface';
8
12
 
9
13
  export function BootstrapsProvider(props: { children: React.ReactNode }) {
10
14
  const IOC = useIOC();
15
+ const locale = useLocale();
16
+ const t = useWarnTranslations();
11
17
 
12
18
  const [, setIocMounted] = useState(false);
13
19
 
@@ -24,52 +30,10 @@ export function BootstrapsProvider(props: { children: React.ReactNode }) {
24
30
  });
25
31
  }, []);
26
32
 
27
- // useEffect(() => {
28
- // const register = new ClientIOCRegister({
29
- // appConfig: appConfig
30
- // });
31
-
32
- // // 启动前注册所有依赖
33
- // // clientIOC.register(register);
34
-
35
- // BootstrapClient.main({
36
- // root: window,
37
- // pathname: window.location.pathname,
38
- // IOC: IOC,
39
- // register: register
40
- // }).then(() => {
41
- // setIocMounted(true);
42
- // });
43
- // }, []);
44
-
45
- // if (!register) {
46
- // return <div data-testid="BootstrapsProviderLoading">Loading...</div>;
47
- // }
48
-
49
- // const IOC = clientIOC.create();
50
- // const locale = useLocale();
51
- // const router = useRouter();
52
- // const t = useWarnTranslations();
53
-
54
- // useEffect(() => {
55
- // IOC(I.RouterServiceInterface).setLocale(locale);
56
- // IOC(NavigateBridge).setUIBridge(router);
57
- // }, [locale, router, IOC]);
58
-
59
- // useEffect(() => {
60
- // IOC(I.I18nServiceInterface).changeLanguage(locale as I18nServiceLocale);
61
- // IOC(I.I18nServiceInterface).setTranslator(t);
62
- // }, [t, IOC, locale]);
63
-
64
- // useEffect(() => {
65
- // if (typeof window !== 'undefined') {
66
- // BootstrapClient.main({
67
- // root: window,
68
- // pathname: window.location.pathname,
69
- // IOC: IOC
70
- // });
71
- // }
72
- // }, [IOC]);
33
+ useEffect(() => {
34
+ IOC(I.I18nServiceInterface).changeLanguage(locale as I18nServiceLocale);
35
+ IOC(I.I18nServiceInterface).setTranslator(t);
36
+ }, [t, IOC, locale]);
73
37
 
74
38
  return props.children;
75
39
  }
@@ -1,9 +1,10 @@
1
1
  import { vi } from 'vitest';
2
- import type { InteractionHubInterface } from '@/base/port/InteractionHubInterface';
2
+ import type { DialogHandlerOptions } from '@/base/cases/DialogHandler';
3
3
  import type { AntdStaticApiInterface } from '@brain-toolkit/antd-theme-override/react';
4
+ import type { UIDialogInterface } from '@qlover/corekit-bridge';
4
5
 
5
6
  export class MockDialogHandler
6
- implements InteractionHubInterface, AntdStaticApiInterface
7
+ implements UIDialogInterface<DialogHandlerOptions>, AntdStaticApiInterface
7
8
  {
8
9
  public setMessage = vi.fn();
9
10
  public setModal = vi.fn();
@@ -79,6 +79,9 @@ export function createMockGlobals() {
79
79
  size: vi.fn(() => Object.keys(mockCookieStorageData).length)
80
80
  };
81
81
 
82
+ // Add length property to prevent lodash.omit from treating this as array-like
83
+ // This is needed because BootstrapClient uses omit(globals, ...) and lodash
84
+ // checks for length property to determine if object is array-like
82
85
  return {
83
86
  logger: mockLogger,
84
87
  appConfig: mockAppConfig,
@@ -86,6 +89,8 @@ export function createMockGlobals() {
86
89
  JSON: mockJSON,
87
90
  localStorage: mockLocalStorage,
88
91
  localStorageEncrypt: mockLocalStorageEncrypt,
89
- cookieStorage: mockCookieStorage
92
+ cookieStorage: mockCookieStorage,
93
+ // Explicitly define length as undefined to satisfy lodash's isArrayLike check
94
+ length: undefined
90
95
  };
91
96
  }
@@ -9,10 +9,10 @@
9
9
  */
10
10
 
11
11
  import { MockLogger } from '@__mocks__/MockLogger';
12
+ import { ExecutorContextImpl } from '@qlover/fe-corekit';
12
13
  import { describe, it, expect, beforeEach } from 'vitest';
13
14
  import { I18nKeyErrorPlugin } from '@/base/cases/I18nKeyErrorPlugin';
14
15
  import { I18nService } from '@/base/services/I18nService';
15
- import type { ExecutorContext } from '@qlover/fe-corekit';
16
16
 
17
17
  class MockI18nService extends I18nService {
18
18
  constructor() {
@@ -44,12 +44,8 @@ describe('I18nKeyErrorPlugin', () => {
44
44
 
45
45
  describe('onError handling', () => {
46
46
  it('should handle non-Error objects', () => {
47
- const context: ExecutorContext<unknown> = {
48
- error: new Error('not an error'),
49
- parameters: {},
50
- returnValue: undefined,
51
- hooksRuntimes: {}
52
- };
47
+ const context = new ExecutorContextImpl({});
48
+ context.setError(new Error('not an error'));
53
49
  const result = plugin.onError(context);
54
50
  expect(result).toBeUndefined();
55
51
  expect(mockLogger.debug).not.toHaveBeenCalled();
@@ -58,12 +54,8 @@ describe('I18nKeyErrorPlugin', () => {
58
54
 
59
55
  it('should handle Error objects without i18n key', () => {
60
56
  const error = new Error('regular error');
61
- const context: ExecutorContext<unknown> = {
62
- error,
63
- parameters: {},
64
- returnValue: undefined,
65
- hooksRuntimes: {}
66
- };
57
+ const context = new ExecutorContextImpl({});
58
+ context.setError(error);
67
59
  const result = plugin.onError(context);
68
60
  expect(result).toBeUndefined();
69
61
  expect(mockLogger.debug).not.toHaveBeenCalled();
@@ -74,12 +66,8 @@ describe('I18nKeyErrorPlugin', () => {
74
66
  const error = new Error('error.key');
75
67
  mockI18nService.t.mockReturnValueOnce('Translated error message');
76
68
 
77
- const context: ExecutorContext<unknown> = {
78
- error,
79
- parameters: {},
80
- returnValue: undefined,
81
- hooksRuntimes: {}
82
- };
69
+ const context = new ExecutorContextImpl({});
70
+ context.setError(error);
83
71
 
84
72
  const result = plugin.onError(context);
85
73
 
@@ -96,12 +84,8 @@ describe('I18nKeyErrorPlugin', () => {
96
84
  const error = new Error('error.key');
97
85
  mockI18nService.t.mockReturnValueOnce('error.key');
98
86
 
99
- const context: ExecutorContext<unknown> = {
100
- error,
101
- parameters: {},
102
- returnValue: undefined,
103
- hooksRuntimes: {}
104
- };
87
+ const context = new ExecutorContextImpl({});
88
+ context.setError(error);
105
89
 
106
90
  const result = plugin.onError(context);
107
91
 
@@ -118,12 +102,8 @@ describe('I18nKeyErrorPlugin', () => {
118
102
  'Error with param1: {0} and param2: {1}'
119
103
  );
120
104
 
121
- const context: ExecutorContext<unknown> = {
122
- error,
123
- parameters: { param1: 'value1', param2: 'value2' },
124
- returnValue: undefined,
125
- hooksRuntimes: {}
126
- };
105
+ const context = new ExecutorContextImpl({});
106
+ context.setError(error);
127
107
 
128
108
  const result = plugin.onError(context);
129
109
 
@@ -142,12 +122,8 @@ describe('I18nKeyErrorPlugin', () => {
142
122
  .mockReturnValueOnce('Wrapped Error')
143
123
  .mockReturnValueOnce('Original Error');
144
124
 
145
- const context: ExecutorContext<unknown> = {
146
- error: wrappedError,
147
- parameters: {},
148
- returnValue: undefined,
149
- hooksRuntimes: {}
150
- };
125
+ const context = new ExecutorContextImpl({});
126
+ context.setError(wrappedError);
151
127
 
152
128
  const result = plugin.onError(context);
153
129
 
@@ -160,12 +136,8 @@ describe('I18nKeyErrorPlugin', () => {
160
136
  describe('edge cases', () => {
161
137
  it('should handle empty error message', () => {
162
138
  const error = new Error('');
163
- const context: ExecutorContext<unknown> = {
164
- error,
165
- parameters: {},
166
- returnValue: undefined,
167
- hooksRuntimes: {}
168
- };
139
+ const context = new ExecutorContextImpl({});
140
+ context.setError(error);
169
141
  const result = plugin.onError(context);
170
142
  expect(result).toBeUndefined();
171
143
  expect(mockLogger.debug).not.toHaveBeenCalled();
@@ -176,12 +148,8 @@ describe('I18nKeyErrorPlugin', () => {
176
148
  it('should handle null error message', () => {
177
149
  const error = new Error();
178
150
  error.message = ''; // Force empty message
179
- const context: ExecutorContext<unknown> = {
180
- error,
181
- parameters: {},
182
- returnValue: undefined,
183
- hooksRuntimes: {}
184
- };
151
+ const context = new ExecutorContextImpl({});
152
+ context.setError(error);
185
153
  const result = plugin.onError(context);
186
154
  expect(result).toBeUndefined();
187
155
  expect(mockLogger.debug).not.toHaveBeenCalled();
@@ -190,12 +158,8 @@ describe('I18nKeyErrorPlugin', () => {
190
158
  });
191
159
 
192
160
  it('should handle undefined context error', () => {
193
- const context: ExecutorContext<unknown> = {
194
- error: undefined,
195
- parameters: {},
196
- returnValue: undefined,
197
- hooksRuntimes: {}
198
- };
161
+ const context = new ExecutorContextImpl({});
162
+ context.setError(undefined);
199
163
  const result = plugin.onError(context);
200
164
  expect(result).toBeUndefined();
201
165
  expect(mockLogger.debug).not.toHaveBeenCalled();
@@ -203,12 +167,8 @@ describe('I18nKeyErrorPlugin', () => {
203
167
  });
204
168
 
205
169
  it('should handle null context error', () => {
206
- const context: ExecutorContext<unknown> = {
207
- error: undefined,
208
- parameters: {},
209
- returnValue: undefined,
210
- hooksRuntimes: {}
211
- };
170
+ const context = new ExecutorContextImpl({});
171
+ context.setError(null);
212
172
  const result = plugin.onError(context);
213
173
  expect(result).toBeUndefined();
214
174
  expect(mockLogger.debug).not.toHaveBeenCalled();