@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qlover/create-app",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/index.cjs",
@@ -26,11 +26,6 @@
26
26
  "bin": {
27
27
  "create-app": "bin/create-app.js"
28
28
  },
29
- "scripts": {
30
- "build": "rollup -c",
31
- "create:app:build": "npm run build && npm run create:app",
32
- "create:app": "node ./bin/create-app.js"
33
- },
34
29
  "repository": {
35
30
  "type": "git",
36
31
  "url": "git+https://github.com/qlover/fe-base.git",
@@ -52,11 +47,16 @@
52
47
  },
53
48
  "dependencies": {
54
49
  "@qlover/fe-corekit": "^1.2.2",
55
- "@qlover/scripts-context": "^0.0.8",
50
+ "@qlover/scripts-context": "^0.0.11",
56
51
  "commander": "^13.1.0",
57
52
  "ignore": "^7.0.3",
58
53
  "inquirer": "^12.3.2",
59
54
  "ora": "^8.1.1",
60
55
  "lodash": "^4.17.21"
56
+ },
57
+ "scripts": {
58
+ "build": "rollup -c",
59
+ "create:app:build": "npm run build && npm run create:app",
60
+ "create:app": "node ./bin/create-app.js"
61
61
  }
62
- }
62
+ }
@@ -61,6 +61,6 @@
61
61
  "rollup-plugin-typescript2": "^0.36.0"
62
62
  },
63
63
  "dependencies": {
64
- "@qlover/fe-utils": "latest"
64
+ "@qlover/fe-corekit": "latest"
65
65
  }
66
66
  }
@@ -32,7 +32,7 @@
32
32
  "devDependencies": {
33
33
  "@qlover/fe-scripts": "latest",
34
34
  "@qlover/fe-standard": "workspace:*",
35
- "@qlover/fe-utils": "latest",
35
+ "@qlover/fe-corekit": "latest",
36
36
  "@qlover/fe-release": "latest",
37
37
  "@rollup/plugin-commonjs": "^28.0.1",
38
38
  "@rollup/plugin-json": "^6.1.0",
@@ -22,3 +22,4 @@ VITE_OPEN_AI_TOKEN_PREFIX=Bearer
22
22
  VITE_OPEN_AI_REQUIRE_TOKEN=true
23
23
  VITE_LOGIN_USER=admin
24
24
  VITE_LOGIN_PASSWORD=123456
25
+ VITE_FE_API_BASE_URL=https://feapi.example.com/
@@ -112,7 +112,6 @@
112
112
  - Vite
113
113
  - Tailwind CSS
114
114
  - i18next
115
- - @qlover/fe-utils
116
115
 
117
116
  ## 开发
118
117
 
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @description IOC 未实现
3
+ * @localZh IOC 未实现
4
+ * @localEn IOC not implemented
5
+ */
6
+ export const APP_IOC_NOT_IMPLEMENTED = 'err.ioc.not.implemented';
7
+
8
+ /**
9
+ * @description 本地未找到 user token
10
+ * @localZh 本地未找到 user token
11
+ * @localEn Local no user token
12
+ */
13
+ export const LOCAL_NO_USER_TOKEN = 'err.local.no.user.token';
14
+
15
+ /**
16
+ * @description 全局未找到 window
17
+ * @localZh 全局未找到 window
18
+ * @localEn Global no window
19
+ */
20
+ export const GLOBAL_NO_WINDOW = 'err.global.no.window';
21
+
22
+ /**
23
+ * @description 必须在 PageProvider 中使用
24
+ * @localZh 必须在 PageProvider 中使用
25
+ * @localEn Must be used in PageProvider
26
+ */
27
+ export const WITHIN_PAGE_PROVIDER = 'err.within.page.provider';
@@ -60,6 +60,15 @@
60
60
  "localNamespace": "executor"
61
61
  }
62
62
  },
63
+ {
64
+ "path": "errorIdentifier",
65
+ "element": "base/ErrorIdentifier",
66
+ "meta": {
67
+ "title": "FE-Utils ErrorIdentifier",
68
+ "icon": "info",
69
+ "localNamespace": "common"
70
+ }
71
+ },
63
72
  {
64
73
  "path": "404",
65
74
  "element": "404",
@@ -1,3 +1,15 @@
1
1
  export const envPrefix = 'VITE_';
2
2
 
3
3
  export const browserGlobalsName = 'feGlobals';
4
+
5
+ /**
6
+ * bootstrap ,not inject env
7
+ */
8
+ export const envBlackList = ['env', 'userNodeEnv'];
9
+
10
+ export const loggerStyles = {
11
+ INFO: 'color: blue;',
12
+ WARN: 'color: orange; font-weight: bold;',
13
+ ERROR: 'color: red; font-weight: bold;',
14
+ DEBUG: 'color: #8d7'
15
+ };
@@ -3,12 +3,25 @@
3
3
  "mock": true,
4
4
  "noUrl": true
5
5
  },
6
- "GET https://api.example.com/api/userinfo": {
6
+ "GET https://feapi.example.com/api/userinfo": {
7
7
  "name": "John Doe",
8
8
  "email": "john.doe@example.com",
9
9
  "picture": "https://randomuser.me/api/portraits/men/1.jpg"
10
10
  },
11
- "POST https://api.example.com/api/login": {
11
+ "POST https://feapi.example.com/api/login": {
12
12
  "token": "asdfasdf123123asdfasdf"
13
+ },
14
+ "POST https://api.openai.com/v1/chat/completions": {
15
+ "id": "chatcmpl-1234567890",
16
+ "object": "chat.completion",
17
+ "created": 1721702400,
18
+ "choices": [
19
+ {
20
+ "message": {
21
+ "role": "assistant",
22
+ "content": "Hello, how can I help you today?"
23
+ }
24
+ }
25
+ ]
13
26
  }
14
27
  }
@@ -1,14 +1,8 @@
1
- import { isProduction } from '@/core/globals';
2
-
3
- /** @type {import('i18next').InitOptions} */
4
- export const i18nConfig = {
5
- /**
6
- * default language
7
- */
1
+ export default {
8
2
  fallbackLng: 'en',
9
- debug: !isProduction,
3
+ debug: false,
10
4
  interpolation: {
11
- escapeValue: false // React already does escaping
5
+ escapeValue: false
12
6
  },
13
7
  ns: ['common'],
14
8
  defaultNS: 'common',
@@ -17,5 +11,3 @@ export const i18nConfig = {
17
11
  },
18
12
  supportedLngs: ['en', 'zh']
19
13
  } as const;
20
-
21
- export type I18nServiceLocale = (typeof i18nConfig.supportedLngs)[number];
@@ -51,7 +51,8 @@
51
51
  "test": "vitest run"
52
52
  },
53
53
  "dependencies": {
54
- "@qlover/fe-utils": "latest",
54
+ "@qlover/corekit-bridge": "^0.0.5",
55
+ "@qlover/fe-corekit": "^1.2.5",
55
56
  "@qlover/slice-store-react": "^1.0.8",
56
57
  "i18next": "^24.2.0",
57
58
  "i18next-browser-languagedetector": "^8.0.2",
@@ -65,17 +66,16 @@
65
66
  "reflect-metadata": "^0.2.2"
66
67
  },
67
68
  "devDependencies": {
68
- "@eslint/js": "^9.11.1",
69
69
  "@qlover/env-loader": "latest",
70
70
  "@qlover/eslint-plugin-fe-dev": "^0.2.0",
71
71
  "@qlover/fe-scripts": "latest",
72
- "@rollup/plugin-alias": "^5.1.1",
72
+ "@qlover/fe-standard": "^0.0.4",
73
73
  "@types/lodash": "^4.17.13",
74
74
  "@types/react": "^18.3.11",
75
75
  "@types/react-dom": "^18.3.0",
76
76
  "@types/react-syntax-highlighter": "^15.5.13",
77
77
  "@types/typo-js": "^1.2.2",
78
- "@vitejs/plugin-react": "^4.3.4",
78
+ "@vitejs/plugin-react": "^4.4.1",
79
79
  "@vitejs/plugin-react-swc": "^3.5.0",
80
80
  "autoprefixer": "^10.4.20",
81
81
  "eslint": "^9.15.0",
@@ -83,14 +83,17 @@
83
83
  "eslint-plugin-react": "^7.37.4",
84
84
  "eslint-plugin-react-hooks": "^5.0.0",
85
85
  "eslint-plugin-react-refresh": "^0.4.14",
86
+ "eslint-plugin-vitest": "^0.5.4",
86
87
  "globals": "^15.12.0",
87
88
  "postcss": "^8.4.49",
89
+ "prettier": "^3.5.3",
88
90
  "sass-embedded": "^1.79.4",
89
91
  "tailwindcss": "^3.4.16",
90
92
  "typescript": "^5.6.3",
91
93
  "typescript-eslint": "^8.15.0",
92
94
  "vite": "^5.4.8",
93
95
  "vite-plugin-cross-origin-isolation": "^0.1.6",
96
+ "vite-tsconfig-paths": "^5.1.4",
94
97
  "vitest": "^3.0.5"
95
98
  }
96
99
  }
@@ -2,5 +2,9 @@
2
2
  "404.notComponent": "Component not found",
3
3
  "404.notPage": "Page not found",
4
4
  "500.title": "Server Error",
5
- "header.theme.label": "Switch Theme"
6
- }
5
+ "header.theme.label": "Switch Theme",
6
+ "err.ioc.not.implemented": "IOC not implemented",
7
+ "err.local.no.user.token": "Local no user token",
8
+ "err.global.no.window": "Global no window",
9
+ "err.within.page.provider": "Must be used in PageProvider"
10
+ }
@@ -2,6 +2,9 @@
2
2
  "404.notComponent": "组件不存在",
3
3
  "404.notPage": "页面不存在",
4
4
  "500.title": "服务器错误",
5
- "header.theme.label": "切换主题"
6
- }
7
-
5
+ "header.theme.label": "切换主题",
6
+ "err.ioc.not.implemented": "IOC 未实现",
7
+ "err.local.no.user.token": "本地未找到 user token",
8
+ "err.global.no.window": "全局未找到 window",
9
+ "err.within.page.provider": "必须在 PageProvider 中使用"
10
+ }
@@ -1,10 +1,10 @@
1
1
  import '@/uikit/styles/css/index.css';
2
2
  import { createBrowserRouter, RouterProvider } from 'react-router-dom';
3
3
  import { lazy, useMemo } from 'react';
4
- import { RouterLoader } from '@lib/router-loader/RouterLoader';
5
- import appConfig from '@config/app.router.json';
6
- import { RouterRenderComponent } from './components/RouterRenderComponent';
7
- import { PagesMaps } from './base/types/Page';
4
+ import { RouterRenderComponent } from './uikit/components/RouterRenderComponent';
5
+ import { IOC } from './core/IOC';
6
+ import { RouterController } from './uikit/controllers/RouterController';
7
+ import { RouterLoader, type ComponentValue } from '@/base/cases/router-loader';
8
8
 
9
9
  function getAllPages() {
10
10
  const modules = import.meta.glob('./pages/**/*.tsx');
@@ -17,7 +17,7 @@ function getAllPages() {
17
17
  }>
18
18
  );
19
19
  return acc;
20
- }, {} as PagesMaps);
20
+ }, {} as ComponentValue);
21
21
  }
22
22
 
23
23
  const routerLoader = new RouterLoader({
@@ -27,9 +27,9 @@ const routerLoader = new RouterLoader({
27
27
 
28
28
  function App() {
29
29
  const routerBase = useMemo(() => {
30
- const routes = appConfig.base.routes.map((route) =>
31
- routerLoader.toRoute(route)
32
- );
30
+ const routes = IOC(RouterController)
31
+ .getRoutes()
32
+ .map((route) => routerLoader.toRoute(route));
33
33
  const router = createBrowserRouter(routes);
34
34
  return router;
35
35
  }, []);
@@ -0,0 +1,55 @@
1
+ import AppConfig from '@/core/AppConfig';
2
+ import {
3
+ FetchURLPlugin,
4
+ RequestAdapterFetch,
5
+ RequestScheduler
6
+ } from '@qlover/fe-corekit';
7
+ import {
8
+ type BootstrapExecutorPlugin,
9
+ RequestCommonPlugin
10
+ } from '@qlover/corekit-bridge';
11
+ import { RequestLogger } from '../cases/RequestLogger';
12
+ import { IOCIdentifier } from '@/core/IOC';
13
+
14
+ const apiApiAdapter = new RequestAdapterFetch({
15
+ baseURL: AppConfig.aiApiBaseUrl
16
+ });
17
+
18
+ // 使用 RequestScheduler
19
+ const apiApi = new RequestScheduler(apiApiAdapter);
20
+
21
+ // 直接使用 adapter
22
+ // const apiApi = apiApiAdapter;
23
+
24
+ export const AiApiBootstarp: BootstrapExecutorPlugin = {
25
+ pluginName: 'AiApiBootstarp',
26
+ onBefore({ parameters: { ioc } }) {
27
+ apiApiAdapter.usePlugin(new FetchURLPlugin());
28
+ apiApiAdapter.usePlugin(
29
+ new RequestCommonPlugin({
30
+ tokenPrefix: AppConfig.aiApiTokenPrefix,
31
+ token: AppConfig.aiApiToken
32
+ })
33
+ );
34
+ apiApiAdapter.usePlugin(ioc.get(IOCIdentifier.ApiMockPlugin));
35
+ apiApiAdapter.usePlugin(ioc.get(RequestLogger));
36
+ }
37
+ };
38
+
39
+ export function aiHello(data: {
40
+ messages: { role: string; content: string }[];
41
+ }) {
42
+ return apiApi.request<
43
+ typeof data,
44
+ {
45
+ id: string;
46
+ object: string;
47
+ created: number;
48
+ choices: { message: { role: string; content: string } }[];
49
+ }
50
+ >({
51
+ url: '/chat/completions',
52
+ method: 'POST',
53
+ data
54
+ });
55
+ }
@@ -1,51 +1,20 @@
1
- import {
2
- RequestAdapterFetch,
3
- RequestAdapterConfig,
4
- RequestScheduler,
5
- FetchAbortPlugin,
6
- RequestAdapterFetchConfig
7
- } from '@qlover/fe-utils';
8
- import {
9
- FeApiGetIpInfo,
10
- FeApiGetRandomUser,
11
- FeApiGetUserInfo,
12
- FeApiLogin
13
- } from './FeApiType';
1
+ import { RequestAdapterFetch, RequestScheduler } from '@qlover/fe-corekit';
2
+ import { FeApiGetIpInfo } from './FeApiType';
3
+ import { inject, injectable } from 'inversify';
4
+ import { FeApiAdapter } from './FeApiAdapter';
5
+ import { FeApiConfig } from './FeApiBootstarp';
14
6
 
15
- export class FeApi extends RequestScheduler<RequestAdapterConfig> {
16
- private abortPlugin: FetchAbortPlugin;
17
-
18
- constructor({
19
- abortPlugin,
20
- config
21
- }: {
22
- abortPlugin: FetchAbortPlugin;
23
- config?: Partial<RequestAdapterFetchConfig>;
24
- }) {
25
- super(new RequestAdapterFetch(config));
26
- this.abortPlugin = abortPlugin;
7
+ @injectable()
8
+ export class FeApi extends RequestScheduler<FeApiConfig> {
9
+ constructor(@inject(FeApiAdapter) adapter: RequestAdapterFetch) {
10
+ super(adapter);
27
11
  }
28
12
 
29
- stop(config: RequestAdapterConfig): void {
30
- this.abortPlugin.abort(config);
31
- }
13
+ stop(_config: FeApiConfig): void {}
32
14
 
33
15
  async getIpInfo(): Promise<FeApiGetIpInfo['response']> {
34
- return this.get('http://ip-api.com/json/');
35
- }
36
-
37
- async getRandomUser(): Promise<FeApiGetRandomUser['response']> {
38
- return this.get('https://randomuser.me/api/');
39
- }
40
-
41
- async getUserInfo(): Promise<FeApiGetUserInfo['response']> {
42
- return this.get('/api/userinfo');
43
- }
44
-
45
- async login(params: FeApiLogin['request']): Promise<FeApiLogin['response']> {
46
- return this.post('/api/login', {
47
- // FIXME: RequestAdapterResponse response type error
48
- data: params as unknown as FeApiLogin['response']['data']
49
- });
16
+ return this.get('http://ip-api.com/json/') as unknown as Promise<
17
+ FeApiGetIpInfo['response']
18
+ >;
50
19
  }
51
20
  }
@@ -0,0 +1,14 @@
1
+ import { IOCIdentifier } from '@/core/IOC';
2
+ import { RequestAdapterFetch } from '@qlover/fe-corekit';
3
+ import { inject, injectable } from 'inversify';
4
+ import { AppConfigImpl } from '@/core/AppConfig';
5
+
6
+ @injectable()
7
+ export class FeApiAdapter extends RequestAdapterFetch {
8
+ constructor(@inject(IOCIdentifier.AppConfig) appConfig: AppConfigImpl) {
9
+ super({
10
+ responseType: 'json',
11
+ baseURL: appConfig.feApiBaseUrl
12
+ });
13
+ }
14
+ }
@@ -0,0 +1,67 @@
1
+ import type {
2
+ RequestAdapterConfig,
3
+ RequestAdapterResponse,
4
+ RequestTransactionInterface
5
+ } from '@qlover/fe-corekit';
6
+ import { FetchURLPlugin } from '@qlover/fe-corekit';
7
+ import {
8
+ type BootstrapContext,
9
+ type BootstrapExecutorPlugin,
10
+ type ApiMockPluginConfig,
11
+ ApiPickDataPlugin
12
+ } from '@qlover/corekit-bridge';
13
+ import { FeApi } from './FeApi';
14
+ import { IOCIdentifier } from '@/core/IOC';
15
+ import { RequestLogger } from '@/base/cases/RequestLogger';
16
+
17
+ /**
18
+ * FeApiConfig
19
+ *
20
+ * @description
21
+ * FeApiConfig is the config for the FeApi.
22
+ *
23
+ * extends:
24
+ */
25
+ export interface FeApiConfig<Request = unknown>
26
+ extends RequestAdapterConfig<Request>,
27
+ ApiMockPluginConfig {}
28
+
29
+ /**
30
+ * FeApiResponse
31
+ *
32
+ * @description
33
+ * FeApiResponse is the response for the FeApi.
34
+ *
35
+ * extends:
36
+ * - RequestAdapterResponse<Request, Response>
37
+ */
38
+ export interface FeApiResponse<Request = unknown, Response = unknown>
39
+ extends RequestAdapterResponse<Request, Response> {}
40
+
41
+ /**
42
+ * FeApi common transaction
43
+ *
44
+ * FIXME: maybe we can add data to RequestTransactionInterface
45
+ *
46
+ * add data property
47
+ */
48
+ export interface FeApiTransaction<Request = unknown, Response = unknown>
49
+ extends RequestTransactionInterface<
50
+ FeApiConfig<Request>,
51
+ FeApiResponse<Request, Response>['data']
52
+ > {
53
+ data: FeApiConfig<Request>['data'];
54
+ }
55
+
56
+ export class FeApiBootstarp implements BootstrapExecutorPlugin {
57
+ readonly pluginName = 'FeApiBootstarp';
58
+
59
+ onBefore({ parameters: { ioc } }: BootstrapContext): void {
60
+ ioc
61
+ .get<FeApi>(FeApi)
62
+ .usePlugin(new FetchURLPlugin())
63
+ .usePlugin(ioc.get(IOCIdentifier.FeApiCommonPlugin))
64
+ .usePlugin(ioc.get(RequestLogger))
65
+ .usePlugin(ioc.get(ApiPickDataPlugin));
66
+ }
67
+ }
@@ -1,10 +1,6 @@
1
- import { RequestAdapterResponse } from '@qlover/fe-utils';
1
+ import { FeApiTransaction } from './FeApiBootstarp';
2
2
 
3
- export type FeApiType<Request, Response> = {
4
- request: Request;
5
- response: RequestAdapterResponse<Request, Response>;
6
- };
7
- export type FeApiGetIpInfo = FeApiType<
3
+ export type FeApiGetIpInfo = FeApiTransaction<
8
4
  undefined,
9
5
  {
10
6
  status: string;
@@ -23,32 +19,3 @@ export type FeApiGetIpInfo = FeApiType<
23
19
  query: string;
24
20
  }
25
21
  >;
26
-
27
- export type FeApiGetRandomUser = FeApiType<
28
- undefined,
29
- {
30
- results: unknown[];
31
- info: {
32
- seed: string;
33
- results: number;
34
- page: number;
35
- version: string;
36
- };
37
- }
38
- >;
39
-
40
- export type FeApiGetUserInfo = FeApiType<
41
- string,
42
- {
43
- name: string;
44
- email: string;
45
- picture: string;
46
- }
47
- >;
48
-
49
- export type FeApiLogin = FeApiType<
50
- { username: string; password: string },
51
- {
52
- token: string;
53
- }
54
- >;
@@ -0,0 +1,64 @@
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
+
16
+ /**
17
+ * UserApi
18
+ *
19
+ * @description
20
+ * UserApi is a client for the user API.
21
+ *
22
+ */
23
+ @injectable()
24
+ export class UserApi extends RequestTransaction<UserApiConfig> {
25
+ constructor(
26
+ @inject(FetchAbortPlugin) private abortPlugin: FetchAbortPlugin,
27
+ @inject(UserApiAdapter) adapter: RequestAdapterFetch
28
+ ) {
29
+ super(adapter);
30
+ }
31
+
32
+ stop(request: UserApiConfig): Promise<void> | void {
33
+ this.abortPlugin.abort(request);
34
+ }
35
+
36
+ async getRandomUser(): Promise<GetIpInfoTransaction['response']> {
37
+ return this.request<GetIpInfoTransaction>({
38
+ url: 'https://randomuser.me/api/',
39
+ method: 'GET',
40
+ disabledMock: true
41
+ });
42
+ }
43
+
44
+ async testApiCatchResult(): Promise<
45
+ UserApiTestApiCatchResultTransaction['response']
46
+ > {
47
+ return this.request<UserApiTestApiCatchResultTransaction>({
48
+ url: 'https://randomuser.me/api/?_name=ApiCatchResult',
49
+ method: 'GET',
50
+ disabledMock: true,
51
+ openApiCatch: true
52
+ });
53
+ }
54
+
55
+ async getUserInfo(): Promise<UserApiGetUserInfoTransaction['response']> {
56
+ return this.get<UserApiGetUserInfoTransaction>('/api/userinfo');
57
+ }
58
+
59
+ async login(
60
+ params: UserApiLoginTransaction['data']
61
+ ): Promise<UserApiLoginTransaction['response']> {
62
+ return this.post<UserApiLoginTransaction>('/api/login', params);
63
+ }
64
+ }
@@ -0,0 +1,14 @@
1
+ import { IOCIdentifier } from '@/core/IOC';
2
+ import { RequestAdapterFetch } from '@qlover/fe-corekit';
3
+ import { inject, injectable } from 'inversify';
4
+ import { AppConfigImpl } from '@/core/AppConfig';
5
+
6
+ @injectable()
7
+ export class UserApiAdapter extends RequestAdapterFetch {
8
+ constructor(@inject(IOCIdentifier.AppConfig) appConfig: AppConfigImpl) {
9
+ super({
10
+ responseType: 'json',
11
+ baseURL: appConfig.feApiBaseUrl
12
+ });
13
+ }
14
+ }