@qlover/create-app 0.1.15 → 0.1.17

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 (115) hide show
  1. package/CHANGELOG.md +39 -27
  2. package/bin/create-app.js +0 -0
  3. package/configs/_common/package.json.template +11 -1
  4. package/configs/react-app/eslint.config.js +70 -42
  5. package/dist/index.cjs +1 -3631
  6. package/dist/index.js +1 -3625
  7. package/package.json +8 -8
  8. package/templates/node-lib/package.json +1 -1
  9. package/templates/pack-app/package.json +1 -1
  10. package/templates/react-app/.env +1 -0
  11. package/templates/react-app/README.md +0 -1
  12. package/templates/react-app/config/ErrorIdentifier.ts +27 -0
  13. package/templates/react-app/config/app.router.json +9 -0
  14. package/templates/react-app/config/common.ts +12 -0
  15. package/templates/react-app/config/feapi.mock.json +15 -2
  16. package/templates/react-app/config/i18n.ts +3 -11
  17. package/templates/react-app/package.json +7 -4
  18. package/templates/react-app/public/locales/en/common.json +6 -2
  19. package/templates/react-app/public/locales/zh/common.json +6 -3
  20. package/templates/react-app/src/App.tsx +8 -8
  21. package/templates/react-app/src/base/apis/AiApi.ts +55 -0
  22. package/templates/react-app/src/base/apis/feApi/FeApi.ts +13 -44
  23. package/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +14 -0
  24. package/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +67 -0
  25. package/templates/react-app/src/base/apis/feApi/FeApiType.ts +2 -35
  26. package/templates/react-app/src/base/apis/userApi/UserApi.ts +64 -0
  27. package/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +14 -0
  28. package/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +75 -0
  29. package/templates/react-app/src/base/apis/userApi/UserApiType.ts +52 -0
  30. package/templates/react-app/src/base/cases/RequestLogger.ts +71 -0
  31. package/templates/react-app/src/base/cases/RequestStatusCatcher.ts +41 -0
  32. package/templates/react-app/src/base/cases/appError/AppError.ts +13 -0
  33. package/templates/react-app/{lib/router-loader/RouterLoader.ts → src/base/cases/router-loader/index.ts} +1 -1
  34. package/templates/react-app/src/base/port/ApiTransactionInterface.ts +7 -0
  35. package/templates/react-app/src/base/port/InversifyIocInterface.ts +1 -1
  36. package/templates/react-app/src/base/port/LoginInterface.ts +4 -0
  37. package/templates/react-app/src/base/port/RequestCatcherInterface.ts +12 -0
  38. package/templates/react-app/src/{services → base/services}/I18nService.ts +7 -2
  39. package/templates/react-app/src/{services/processer → base/services}/ProcesserService.ts +10 -11
  40. package/templates/react-app/src/base/types/Page.ts +1 -13
  41. package/templates/react-app/src/core/AppConfig.ts +14 -5
  42. package/templates/react-app/src/core/IOC.ts +77 -37
  43. package/templates/react-app/src/core/bootstrap.ts +38 -25
  44. package/templates/react-app/src/core/bootstraps/BootstrapApp.ts +7 -0
  45. package/templates/react-app/src/core/bootstraps/index.ts +12 -0
  46. package/templates/react-app/src/core/globals.ts +7 -10
  47. package/templates/react-app/src/core/registers/RegisterApi.ts +1 -52
  48. package/templates/react-app/src/core/registers/RegisterCommon.ts +44 -6
  49. package/templates/react-app/src/core/registers/RegisterControllers.ts +5 -34
  50. package/templates/react-app/src/core/registers/RegisterGlobals.ts +8 -2
  51. package/templates/react-app/src/core/registers/index.ts +2 -1
  52. package/templates/react-app/src/main.tsx +4 -1
  53. package/templates/react-app/src/pages/auth/Layout.tsx +4 -3
  54. package/templates/react-app/src/pages/auth/Login.tsx +5 -3
  55. package/templates/react-app/src/pages/base/ErrorIdentifier.tsx +39 -0
  56. package/templates/react-app/src/pages/base/Executor.tsx +31 -10
  57. package/templates/react-app/src/pages/base/Home.tsx +58 -30
  58. package/templates/react-app/src/pages/base/JSONStorage.tsx +2 -4
  59. package/templates/react-app/src/pages/base/Request.tsx +318 -73
  60. package/templates/react-app/src/pages/base/components/BaseHeader.tsx +2 -2
  61. package/templates/react-app/src/{components → uikit/components}/RouterRenderComponent.tsx +1 -1
  62. package/templates/react-app/src/{components → uikit/components}/ThemeSwitcher.tsx +6 -6
  63. package/templates/react-app/src/uikit/contexts/BaseRouteContext.ts +6 -3
  64. package/templates/react-app/src/uikit/controllers/ExecutorController.ts +52 -22
  65. package/templates/react-app/src/uikit/controllers/JSONStorageController.ts +7 -3
  66. package/templates/react-app/src/uikit/controllers/RequestController.ts +65 -11
  67. package/templates/react-app/src/uikit/controllers/RouterController.ts +8 -7
  68. package/templates/react-app/src/uikit/controllers/UserController.ts +48 -54
  69. package/templates/react-app/src/uikit/hooks/useLanguageGuard.ts +1 -2
  70. package/templates/react-app/src/uikit/providers/ProcessProvider.tsx +4 -4
  71. package/templates/react-app/src/uikit/styles/css/index.css +1 -1
  72. package/templates/react-app/src/uikit/styles/css/page.css +1 -1
  73. package/templates/react-app/tailwind.config.js +2 -2
  74. package/templates/react-app/tsconfig.json +0 -1
  75. package/templates/react-app/tsconfig.node.json +1 -2
  76. package/templates/react-app/vite.config.ts +21 -26
  77. package/templates/react-app/.env.local +0 -24
  78. package/templates/react-app/lib/bootstrap/Bootstrap.ts +0 -36
  79. package/templates/react-app/lib/bootstrap/BootstrapExecutorPlugin.ts +0 -20
  80. package/templates/react-app/lib/bootstrap/IOCContainerInterface.ts +0 -33
  81. package/templates/react-app/lib/bootstrap/IOCManagerInterface.ts +0 -12
  82. package/templates/react-app/lib/bootstrap/index.ts +0 -7
  83. package/templates/react-app/lib/bootstrap/plugins/InjectEnv.ts +0 -61
  84. package/templates/react-app/lib/bootstrap/plugins/InjectGlobal.ts +0 -36
  85. package/templates/react-app/lib/bootstrap/plugins/InjectIOC.ts +0 -24
  86. package/templates/react-app/lib/env-config/injectPkgConfig.ts +0 -11
  87. package/templates/react-app/lib/fe-react-controller/FeController.ts +0 -19
  88. package/templates/react-app/lib/fe-react-controller/index.ts +0 -2
  89. package/templates/react-app/lib/fe-react-controller/useController.ts +0 -71
  90. package/templates/react-app/lib/fe-react-theme/ThemeController.ts +0 -40
  91. package/templates/react-app/lib/fe-react-theme/ThemeStateGetter.ts +0 -53
  92. package/templates/react-app/lib/fe-react-theme/index.ts +0 -3
  93. package/templates/react-app/lib/fe-react-theme/type.ts +0 -21
  94. package/templates/react-app/lib/openAiApi/OpenAIAuthPlugin.ts +0 -29
  95. package/templates/react-app/lib/openAiApi/OpenAIClient.ts +0 -51
  96. package/templates/react-app/lib/openAiApi/StreamProcessor.ts +0 -81
  97. package/templates/react-app/lib/openAiApi/index.ts +0 -3
  98. package/templates/react-app/lib/request-common-plugin/index.ts +0 -169
  99. package/templates/react-app/lib/router-loader/Page.ts +0 -68
  100. package/templates/react-app/lib/tw-root10px/index.css +0 -4
  101. package/templates/react-app/pnpm-lock.yaml +0 -5892
  102. package/templates/react-app/src/base/apis/feApi/FeApiMockPlugin.ts +0 -44
  103. package/templates/react-app/src/base/apis/feApi/index.ts +0 -2
  104. package/templates/react-app/src/base/cases/UserToken.ts +0 -47
  105. package/templates/react-app/src/base/consts/IOCIdentifier.ts +0 -16
  106. package/templates/react-app/src/base/port/IOCFunctionInterface.ts +0 -39
  107. package/templates/react-app/src/base/port/StorageTokenInterface.ts +0 -27
  108. package/templates/react-app/src/core/AppIOCContainer.ts +0 -30
  109. package/templates/react-app/src/uikit/utils/RequestLogger.ts +0 -37
  110. package/templates/react-app/src/uikit/utils/datetime.ts +0 -30
  111. package/templates/react-app/src/uikit/utils/thread.ts +0 -3
  112. /package/templates/react-app/lib/{tw-root10px/index.js → tailwind/root10px.js} +0 -0
  113. /package/templates/react-app/lib/{fe-react-theme/tw-generator.js → tailwind/theme-generator.js} +0 -0
  114. /package/templates/react-app/src/{components → uikit/components}/Loading.tsx +0 -0
  115. /package/templates/react-app/src/{components → uikit/components}/LocaleLink.tsx +0 -0
@@ -0,0 +1,75 @@
1
+ import {
2
+ FetchAbortPlugin,
3
+ RequestAdapterConfig,
4
+ RequestAdapterResponse,
5
+ RequestTransactionInterface
6
+ } from '@qlover/fe-corekit';
7
+ import { IOC, IOCIdentifier } from '@/core/IOC';
8
+ import { RequestLogger } from '@/base/cases/RequestLogger';
9
+ import { FetchURLPlugin } from '@qlover/fe-corekit';
10
+ import {
11
+ type BootstrapContext,
12
+ type BootstrapExecutorPlugin,
13
+ type ApiMockPluginConfig,
14
+ type ApiCatchPluginConfig,
15
+ type ApiCatchPluginResponse
16
+ } from '@qlover/corekit-bridge';
17
+ import { UserApi } from './UserApi';
18
+
19
+ /**
20
+ * UserApiConfig
21
+ *
22
+ * @description
23
+ * UserApiConfig is the config for the UserApi.
24
+ *
25
+ * extends:
26
+ * - ApiMockPluginConfig
27
+ * - ApiCatchPluginConfig
28
+ */
29
+ export interface UserApiConfig<Request = unknown>
30
+ extends RequestAdapterConfig<Request>,
31
+ ApiMockPluginConfig,
32
+ ApiCatchPluginConfig {}
33
+
34
+ /**
35
+ * UserApiResponse
36
+ *
37
+ * @description
38
+ * UserApiResponse is the response for the UserApi.
39
+ *
40
+ * extends:
41
+ * - RequestAdapterResponse<Request, Response>
42
+ */
43
+ export interface UserApiResponse<Request = unknown, Response = unknown>
44
+ extends RequestAdapterResponse<Request, Response>,
45
+ ApiCatchPluginResponse {}
46
+
47
+ /**
48
+ * UserApi common transaction
49
+ *
50
+ * FIXME: maybe we can add data to RequestTransactionInterface
51
+ *
52
+ * add data property
53
+ */
54
+ export interface UserApiTransaction<Request = unknown, Response = unknown>
55
+ extends RequestTransactionInterface<
56
+ UserApiConfig<Request>,
57
+ UserApiResponse<Request, Response>
58
+ > {
59
+ data: UserApiConfig<Request>['data'];
60
+ }
61
+
62
+ export class UserApiBootstarp implements BootstrapExecutorPlugin {
63
+ readonly pluginName = 'UserApiBootstarp';
64
+
65
+ onBefore({ parameters: { ioc } }: BootstrapContext): void {
66
+ ioc
67
+ .get<UserApi>(UserApi)
68
+ .usePlugin(new FetchURLPlugin())
69
+ .usePlugin(IOC.get(IOCIdentifier.FeApiCommonPlugin))
70
+ .usePlugin(IOC.get(IOCIdentifier.ApiMockPlugin))
71
+ .usePlugin(IOC.get(RequestLogger))
72
+ .usePlugin(IOC.get(FetchAbortPlugin))
73
+ .usePlugin(IOC.get(IOCIdentifier.ApiCatchPlugin));
74
+ }
75
+ }
@@ -0,0 +1,52 @@
1
+ import { UserApiTransaction } from './UserApiBootstarp';
2
+
3
+ export type GetIpInfoTransaction = UserApiTransaction<
4
+ undefined,
5
+ {
6
+ status: string;
7
+ country: string;
8
+ countryCode: string;
9
+ region: string;
10
+ regionName: string;
11
+ city: string;
12
+ zip: string;
13
+ lat: number;
14
+ lon: number;
15
+ timezone: string;
16
+ isp: string;
17
+ org: string;
18
+ as: string;
19
+ query: string;
20
+ }
21
+ >;
22
+
23
+ export type UserApiGetRandomUser = UserApiTransaction<
24
+ undefined,
25
+ {
26
+ results: unknown[];
27
+ info: {
28
+ seed: string;
29
+ results: number;
30
+ page: number;
31
+ version: string;
32
+ };
33
+ }
34
+ >;
35
+
36
+ export type UserApiGetUserInfoTransaction = UserApiTransaction<
37
+ string,
38
+ {
39
+ name: string;
40
+ email: string;
41
+ picture: string;
42
+ }
43
+ >;
44
+
45
+ export type UserApiLoginTransaction = UserApiTransaction<
46
+ { username: string; password: string },
47
+ {
48
+ token: string;
49
+ }
50
+ >;
51
+
52
+ export type UserApiTestApiCatchResultTransaction = UserApiGetRandomUser;
@@ -0,0 +1,71 @@
1
+ import { IOCIdentifier } from '@/core/IOC';
2
+ import {
3
+ type ExecutorPlugin,
4
+ type ExecutorContext,
5
+ type RequestAdapterFetchConfig,
6
+ type RequestAdapterResponse,
7
+ Logger
8
+ } from '@qlover/fe-corekit';
9
+ import {
10
+ type ApiCatchPluginConfig,
11
+ type ApiCatchPluginResponse
12
+ } from '@qlover/corekit-bridge';
13
+ import { injectable, inject } from 'inversify';
14
+
15
+ @injectable()
16
+ export class RequestLogger
17
+ implements ExecutorPlugin<RequestAdapterFetchConfig>
18
+ {
19
+ readonly pluginName = 'RequestLogger';
20
+
21
+ constructor(@inject(IOCIdentifier.Logger) public logger: Logger) {}
22
+
23
+ onBefore(context: ExecutorContext<RequestAdapterFetchConfig<unknown>>): void {
24
+ this.logger.log(
25
+ `%c[Request before]%c [${new Date().toLocaleString()}] ${context.parameters.method} ${context.parameters.url}`,
26
+ 'color: #0ff;',
27
+ 'color: inherit;',
28
+ context.parameters
29
+ );
30
+ }
31
+
32
+ async onSuccess({
33
+ parameters,
34
+ returnValue
35
+ }: ExecutorContext<
36
+ RequestAdapterFetchConfig & ApiCatchPluginConfig
37
+ >): Promise<void> {
38
+ const _returnValue = returnValue as RequestAdapterResponse &
39
+ ApiCatchPluginResponse;
40
+
41
+ // If the apiCatchResult is not null, it means that the error has been caught
42
+ // from `ApiCatchPlugin`
43
+ if (_returnValue.apiCatchResult) {
44
+ this.loggerError(parameters, _returnValue.apiCatchResult);
45
+ return;
46
+ }
47
+
48
+ this.logger.log(
49
+ `%c[Request success]%c [${new Date().toLocaleString()}] ${parameters.method} ${parameters.url}`,
50
+ 'color: #0f0;',
51
+ 'color: inherit;',
52
+ _returnValue
53
+ );
54
+ }
55
+
56
+ onError({
57
+ parameters,
58
+ error
59
+ }: ExecutorContext<RequestAdapterFetchConfig>): void {
60
+ this.loggerError(parameters, error);
61
+ }
62
+
63
+ loggerError(config: RequestAdapterFetchConfig, error: unknown): void {
64
+ this.logger.log(
65
+ `%c[Request error]%c [${new Date().toLocaleString()}] ${config.method} ${config.url}`,
66
+ 'color: #f00;',
67
+ 'color: inherit;',
68
+ error
69
+ );
70
+ }
71
+ }
@@ -0,0 +1,41 @@
1
+ import type { RequestCatcherInterface } from '@/base/port/RequestCatcherInterface';
2
+ import { IOCIdentifier } from '@/core/IOC';
3
+ import type { Logger, RequestAdapterResponse } from '@qlover/fe-corekit';
4
+ import { inject, injectable } from 'inversify';
5
+
6
+ @injectable()
7
+ export class RequestStatusCatcher
8
+ implements RequestCatcherInterface<RequestAdapterResponse>
9
+ {
10
+ constructor(
11
+ @inject(IOCIdentifier.Logger)
12
+ private readonly logger: Logger
13
+ ) {}
14
+ /**
15
+ * default handler
16
+ * @override
17
+ */
18
+ default(context: RequestAdapterResponse<unknown, unknown>): void {
19
+ this.logger.warn(`RequestStatusCatcher default handler`, context);
20
+ }
21
+
22
+ /**
23
+ * handler
24
+ * @override
25
+ */
26
+ handler(context: RequestAdapterResponse<unknown, unknown>): void {
27
+ const { status } = context;
28
+
29
+ const _handler = this[`case${status}` as keyof RequestStatusCatcher];
30
+
31
+ if (typeof _handler === 'function') {
32
+ return _handler.call(this, context);
33
+ }
34
+
35
+ return this.default(context);
36
+ }
37
+
38
+ case200(_context: RequestAdapterResponse<unknown, unknown>): void {
39
+ // this.logger.info(`RequestStatusCatcher case200 handler`, context);
40
+ }
41
+ }
@@ -0,0 +1,13 @@
1
+ import { ExecutorError } from '@qlover/fe-corekit';
2
+
3
+ /**
4
+ * 统一当前项目中开发的错误
5
+ */
6
+ export class AppError extends ExecutorError {
7
+ constructor(
8
+ public readonly id: string,
9
+ public readonly source?: string | Error
10
+ ) {
11
+ super(id, source);
12
+ }
13
+ }
@@ -2,7 +2,7 @@ import { RouteObject } from 'react-router-dom';
2
2
  import isString from 'lodash/isString';
3
3
  import type { ComponentType, LazyExoticComponent, ReactNode } from 'react';
4
4
 
5
- type ComponentValue = Record<string, () => unknown>;
5
+ export type ComponentValue = Record<string, () => unknown>;
6
6
 
7
7
  type RouteComponentType<T = unknown> =
8
8
  | ComponentType<T>
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Use for describe the unified format of Api request
3
+ */
4
+ export interface ApiTransactionInterface<Request, Response> {
5
+ request: Request;
6
+ response: Response;
7
+ }
@@ -1,4 +1,4 @@
1
- import type { IOCRegisterInterface } from '@lib/bootstrap';
1
+ import type { IOCRegisterInterface } from '@qlover/corekit-bridge';
2
2
  import type { Container } from 'inversify';
3
3
 
4
4
  export type InversifyRegisterContainer = Container;
@@ -0,0 +1,4 @@
1
+ export interface LoginInterface {
2
+ login(params: { username: string; password: string }): Promise<unknown>;
3
+ logout(): void;
4
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * RequestCatcherInterface
3
+ *
4
+ * @description
5
+ * RequestCatcherInterface is a interface that catches the request error
6
+ *
7
+ */
8
+ export interface RequestCatcherInterface<Context> {
9
+ handler(context: Context): void;
10
+
11
+ default(context: Context): void;
12
+ }
@@ -3,23 +3,28 @@ import { initReactI18next } from 'react-i18next';
3
3
  import LanguageDetector from 'i18next-browser-languagedetector';
4
4
  import HttpApi from 'i18next-http-backend';
5
5
  import merge from 'lodash/merge';
6
- import { i18nConfig, I18nServiceLocale } from '@config/i18n';
7
- import type { BootstrapExecutorPlugin } from '@lib/bootstrap';
6
+ import i18nConfig from '@config/i18n';
7
+ import type { BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
8
8
 
9
9
  const { supportedLngs, fallbackLng } = i18nConfig;
10
10
 
11
+ export type I18nServiceLocale = (typeof supportedLngs)[number];
12
+
11
13
  export class I18nService implements BootstrapExecutorPlugin {
12
14
  readonly pluginName = 'I18nService';
13
15
 
14
16
  constructor(private pathname: string) {}
15
17
 
16
18
  onBefore(): void {
19
+ const debug = false;
20
+
17
21
  i18n
18
22
  .use(HttpApi)
19
23
  .use(LanguageDetector)
20
24
  .use(initReactI18next)
21
25
  .init(
22
26
  merge({}, i18nConfig, {
27
+ debug,
23
28
  detection: {
24
29
  order: ['pathLanguageDetector', 'navigator'], // use custom detector
25
30
  caches: []
@@ -1,16 +1,15 @@
1
- import { AsyncExecutor, ExecutorPlugin, Logger } from '@qlover/fe-utils';
2
-
3
- export interface ProcesserServiceOptions {
4
- logger: Logger;
5
- }
1
+ import { AsyncExecutor, ExecutorPlugin, Logger } from '@qlover/fe-corekit';
2
+ import { IOCIdentifier } from '@/core/IOC';
3
+ import { injectable, inject } from 'inversify';
6
4
 
5
+ @injectable()
7
6
  export class ProcesserService {
8
- private executor: AsyncExecutor;
9
- constructor(private options: ProcesserServiceOptions) {
10
- this.executor = new AsyncExecutor();
11
- }
7
+ constructor(
8
+ @inject(IOCIdentifier.Logger) private logger: Logger,
9
+ @inject(AsyncExecutor) private executor: AsyncExecutor
10
+ ) {}
12
11
 
13
- usePlugin(plugin: ExecutorPlugin): this {
12
+ use(plugin: ExecutorPlugin): this {
14
13
  this.executor.use(plugin);
15
14
  return this;
16
15
  }
@@ -23,7 +22,7 @@ export class ProcesserService {
23
22
 
24
23
  init(): Promise<unknown> {
25
24
  return this.executor.exec(this.handler).catch((err) => {
26
- this.options.logger.error('PageProcesser init failed', err);
25
+ this.logger.error('PageProcesser init failed', err);
27
26
  });
28
27
  }
29
28
  }
@@ -1,7 +1,5 @@
1
- import type { LazyExoticComponent, PropsWithChildren } from 'react';
2
1
  import type { TFunction } from 'i18next';
3
2
  import type { UseTranslationResponse } from 'react-i18next';
4
- import type { RouteConfigValue } from '@lib/router-loader/RouterLoader';
5
3
 
6
4
  export interface BasePageProvider {
7
5
  meta: RouteMeta;
@@ -9,7 +7,7 @@ export interface BasePageProvider {
9
7
  t: TFunction<string, string>;
10
8
  }
11
9
 
12
- export type RouteCategory = 'main' | 'auth' | 'common';
10
+ type RouteCategory = 'main' | 'auth' | 'common';
13
11
 
14
12
  export interface RouteMeta {
15
13
  category?: RouteCategory;
@@ -25,13 +23,3 @@ export interface RouteMeta {
25
23
  */
26
24
  localNamespace?: string;
27
25
  }
28
-
29
- export type RouteConfig = {
30
- routes: RouteConfigValue[];
31
- };
32
-
33
- export type PagesMaps = Record<
34
- string,
35
- | (() => LazyExoticComponent<React.ComponentType<unknown>>)
36
- | (() => React.ComponentType<unknown>)
37
- >;
@@ -1,14 +1,15 @@
1
- import type { EnvConfigInterface } from '@lib/bootstrap';
1
+ import type { EnvConfigInterface } from '@qlover/corekit-bridge';
2
2
 
3
- class AppConfig implements EnvConfigInterface {
3
+ export class AppConfigImpl implements EnvConfigInterface {
4
4
  readonly appName = '';
5
5
  readonly appVersion = '';
6
6
  /**
7
7
  * vite mode
8
+ *
8
9
  */
9
- readonly env = import.meta.env.VITE_USER_NODE_ENV;
10
+ readonly env: string = '';
10
11
 
11
- readonly userTokenStorageKey = 'fe_user_token';
12
+ readonly userTokenStorageKey = '';
12
13
  readonly openAiModels = [
13
14
  'gpt-4o-mini',
14
15
  'gpt-3.5-turbo',
@@ -22,6 +23,14 @@ class AppConfig implements EnvConfigInterface {
22
23
  readonly openAiRequireToken = true;
23
24
  readonly loginUser = '';
24
25
  readonly loginPassword = '';
26
+
27
+ readonly feApiBaseUrl = '';
28
+ readonly userApiBaseUrl = '';
29
+
30
+ readonly aiApiBaseUrl = 'https://api.openai.com/v1';
31
+ readonly aiApiToken = '';
32
+ readonly aiApiTokenPrefix = 'Bearer';
33
+ readonly aiApiRequireToken = true;
25
34
  }
26
35
 
27
- export default new AppConfig();
36
+ export default new AppConfigImpl();
@@ -1,48 +1,88 @@
1
1
  // ! dont't import tsx, only ts file
2
- import type { IOCContainerInterface } from '@lib/bootstrap';
3
- import type {
4
- IOCIdentifierMap,
5
- IOCFunctionInterface
6
- } from '@/base/port/IOCFunctionInterface';
7
- import type { ServiceIdentifier } from 'inversify';
8
-
9
- let implemention: IOCContainerInterface | null;
10
-
11
- function ioc<T>(serviceIdentifier: ServiceIdentifier<T>): T;
12
- function ioc<K extends keyof IOCIdentifierMap>(
13
- serviceIdentifier: K
14
- ): IOCIdentifierMap[K];
15
- function ioc<T, K extends keyof IOCIdentifierMap>(
16
- serviceIdentifier: ServiceIdentifier<T> | K
17
- ): T | IOCIdentifierMap[K] {
18
- if (!implemention) {
19
- throw new Error('IOC is not implemented');
2
+ import {
3
+ ApiMockPlugin,
4
+ EnvConfigInterface,
5
+ StorageTokenInterface,
6
+ RequestCommonPlugin,
7
+ ApiCatchPlugin,
8
+ IOCContainerInterface,
9
+ createIOCFunction,
10
+ ServiceIdentifier
11
+ } from '@qlover/corekit-bridge';
12
+ import type { JSONSerializer, JSONStorage, Logger } from '@qlover/fe-corekit';
13
+ import { Container } from 'inversify';
14
+ import { InversifyRegisterInterface } from '@/base/port/InversifyIocInterface';
15
+
16
+ export class InversifyContainer implements IOCContainerInterface {
17
+ private container: Container;
18
+
19
+ constructor() {
20
+ this.container = new Container({
21
+ // allow `@injectable` decorator, auto bind injectable classes
22
+ autobind: true,
23
+ // use singleton scope
24
+ defaultScope: 'Singleton'
25
+ });
26
+ }
27
+
28
+ configure(registers?: InversifyRegisterInterface[]): void {
29
+ if (registers) {
30
+ registers.forEach((register) => register.register(this.container, this));
31
+ }
32
+ }
33
+
34
+ bind<T>(key: ServiceIdentifier<T>, value: T): void {
35
+ this.container.bind<T>(key).toConstantValue(value);
36
+ }
37
+
38
+ get<K extends keyof IOCIdentifierMap>(
39
+ serviceIdentifier: K
40
+ ): IOCIdentifierMap[K];
41
+ get<T>(serviceIdentifier: ServiceIdentifier<T>): T;
42
+ get<T, K extends keyof IOCIdentifierMap>(
43
+ serviceIdentifier: ServiceIdentifier<T> | K
44
+ ): T | IOCIdentifierMap[K] {
45
+ return this.container.get<T>(serviceIdentifier);
20
46
  }
21
- return implemention.get(serviceIdentifier);
22
47
  }
23
48
 
24
49
  /**
25
- * IOC manager function.
50
+ * IOC identifier
26
51
  *
27
- * eg.
28
- * ```ts
29
- * class A {}
30
- * const a = IOC(A);
31
- * ```
52
+ * @description
53
+ * IOC identifier is used to identify the service in the IOC container.
32
54
  *
33
- * or
55
+ * @example
34
56
  * ```ts
35
- * const a = IOC<A>();
57
+ * const a = IOC(IOCIdentifier.JSON);
58
+ * const b = IOC('JSON');
36
59
  * ```
37
- *
38
- * or use get(),
39
60
  */
40
- export const IOC: IOCFunctionInterface = Object.assign(ioc, {
41
- get implemention() {
42
- return implemention;
43
- },
44
- implement: (container: IOCContainerInterface) => {
45
- implemention = container;
46
- },
47
- get: ioc
61
+ export const IOCIdentifier = Object.freeze({
62
+ JSON: 'JSON',
63
+ JSONStorage: 'JSONStorage',
64
+ Logger: 'Logger',
65
+ FeApiToken: 'FeApiToken',
66
+ FeApiCommonPlugin: 'FeApiCommonPlugin',
67
+ AppConfig: 'AppConfig',
68
+ ApiMockPlugin: 'ApiMockPlugin',
69
+ ApiCatchPlugin: 'ApiCatchPlugin'
48
70
  });
71
+
72
+ /**
73
+ * IOC identifier map
74
+ */
75
+ export interface IOCIdentifierMap {
76
+ [IOCIdentifier.JSON]: JSONSerializer;
77
+ [IOCIdentifier.JSONStorage]: JSONStorage;
78
+ [IOCIdentifier.Logger]: Logger;
79
+ [IOCIdentifier.FeApiToken]: StorageTokenInterface<string>;
80
+ [IOCIdentifier.FeApiCommonPlugin]: RequestCommonPlugin;
81
+ [IOCIdentifier.AppConfig]: EnvConfigInterface;
82
+ [IOCIdentifier.ApiMockPlugin]: ApiMockPlugin;
83
+ [IOCIdentifier.ApiCatchPlugin]: ApiCatchPlugin;
84
+ }
85
+
86
+ export const IOC = createIOCFunction<IOCIdentifierMap>(
87
+ new InversifyContainer()
88
+ );
@@ -1,17 +1,30 @@
1
1
  import {
2
2
  Bootstrap,
3
- BootstrapExecutorPlugin,
3
+ type BootstrapExecutorPlugin,
4
4
  InjectEnv,
5
5
  InjectIOC,
6
6
  InjectGlobal
7
- } from '@lib/bootstrap';
8
- import { AppIOCContainer } from '@/core/AppIOCContainer';
7
+ } from '@qlover/corekit-bridge';
9
8
  import AppConfig from '@/core/AppConfig';
10
- import { envPrefix, browserGlobalsName } from '@config/common';
9
+ import { envPrefix, browserGlobalsName, envBlackList } from '@config/common';
11
10
  import { IOC } from './IOC';
12
11
  import * as globals from '@/core/globals';
13
- import { I18nService } from '@/services/I18nService';
12
+ import { I18nService } from '@/base/services/I18nService';
14
13
  import { registerList } from './registers';
14
+ import { appBootstrapList } from './bootstraps';
15
+ import { GLOBAL_NO_WINDOW } from '@config/ErrorIdentifier';
16
+
17
+ const printBootstrap: BootstrapExecutorPlugin = {
18
+ pluginName: 'PrintBootstrap',
19
+ onSuccess({ parameters: { logger } }) {
20
+ logger.info(
21
+ 'bootstrap success!\n\n' +
22
+ `You can use \`%cwindow.${browserGlobalsName}%c\` to access the globals`,
23
+ 'color: #0ff; font-weight: bold;',
24
+ 'all: unset;'
25
+ );
26
+ }
27
+ };
15
28
 
16
29
  /**
17
30
  * Bootstrap
@@ -21,15 +34,20 @@ import { registerList } from './registers';
21
34
  * 3. inject globals to window
22
35
  *
23
36
  */
24
- export default function startup(root: typeof globalThis) {
25
- const window =
26
- typeof root !== 'undefined' && root instanceof Window ? root : undefined;
27
-
28
- if (!window) {
29
- throw new Error('Not Found Window');
37
+ export default function startup({
38
+ window,
39
+ envSource
40
+ }: {
41
+ window: unknown;
42
+ envSource: Record<string, unknown>;
43
+ }) {
44
+ if (!(typeof window !== 'undefined' && window instanceof Window)) {
45
+ throw new Error(GLOBAL_NO_WINDOW);
30
46
  }
31
47
 
32
- const bootstrap = new Bootstrap(new AppIOCContainer());
48
+ const { logger } = globals;
49
+
50
+ const bootstrap = new Bootstrap(window, IOC.implemention!, logger);
33
51
 
34
52
  /**
35
53
  * bootstrap start list
@@ -40,27 +58,22 @@ export default function startup(root: typeof globalThis) {
40
58
  * - inject i18n service to Application
41
59
  */
42
60
  const bootstrapList: BootstrapExecutorPlugin[] = [
43
- new InjectEnv(AppConfig, import.meta.env, envPrefix),
61
+ new InjectEnv(AppConfig, envSource, envPrefix, envBlackList),
44
62
  new InjectIOC(IOC, registerList),
45
63
  new InjectGlobal(globals, browserGlobalsName),
46
- new I18nService(window.location.pathname)
64
+ new I18nService(window.location.pathname),
65
+ ...appBootstrapList
47
66
  ];
48
67
 
49
68
  if (AppConfig.env !== 'production') {
50
- bootstrapList.push({
51
- pluginName: 'InjectDevTools',
52
- onBefore() {
53
- console.log(AppConfig);
54
- },
55
- onError({ error }) {
56
- console.error(`${AppConfig.appName} starup error:`, error);
57
- }
58
- });
69
+ bootstrapList.push(printBootstrap);
59
70
  }
60
71
 
61
72
  try {
62
- bootstrap.use(bootstrapList).start(root);
73
+ logger.info('bootstrap start...');
74
+
75
+ bootstrap.use(bootstrapList).start();
63
76
  } catch (error) {
64
- console.error(`${AppConfig.appName} starup error:`, error);
77
+ logger.error(`${AppConfig.appName} starup error:`, error);
65
78
  }
66
79
  }
@@ -0,0 +1,7 @@
1
+ import type { BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
2
+
3
+ export class BootstrapApp implements BootstrapExecutorPlugin {
4
+ readonly pluginName = 'BootstrapApp';
5
+
6
+ onBefore(): void {}
7
+ }