@qlover/create-app 0.1.4 → 0.1.6
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 +9 -0
- package/bin/create-app.js +44 -4
- package/{templates/pack-app → configs/_common}/.env.template +8 -1
- package/{templates/pack-app → configs/_common}/.github/workflows/general-check.yml +9 -9
- package/{templates/pack-app → configs/_common}/.github/workflows/release.yml.template +26 -26
- package/configs/_common/.prettierrc.js +7 -0
- package/configs/_common/.release-it.json.template +42 -0
- package/configs/_common/.vscode/extensions.json +9 -0
- package/configs/_common/.vscode/react.code-snippets +19 -0
- package/configs/_common/.vscode/settings.json +11 -0
- package/configs/_common/package.json.template +61 -0
- package/configs/node-lib/eslint.config.js +50 -0
- package/configs/react-app/eslint.config.js +66 -0
- package/dist/cjs/index.d.ts +58 -38
- package/dist/cjs/index.js +1 -1
- package/dist/es/index.d.ts +58 -38
- package/dist/es/index.js +1 -1
- package/package.json +3 -1
- package/templates/node-lib/__tests__/readJson.test.ts +1 -0
- package/templates/node-lib/bin/test.js +30 -0
- package/templates/node-lib/package.json +22 -6
- package/templates/node-lib/rollup.config.js +12 -22
- package/templates/node-lib/src/readJson.ts +9 -3
- package/templates/node-lib/tsconfig.json +19 -1
- package/templates/pack-app/eslint.config.js +81 -61
- package/templates/pack-app/fe-config.json +1 -5
- package/templates/pack-app/package.json +19 -11
- package/templates/pack-app/tsconfig.json +1 -1
- package/templates/pack-app/vite.config.ts +14 -0
- package/templates/react-app/README.md +177 -40
- package/templates/react-app/config/i18n.ts +1 -1
- package/templates/react-app/lib/fe-react-controller/FeController.ts +7 -3
- package/templates/react-app/lib/fe-react-theme/ThemeController.ts +1 -1
- package/templates/react-app/package.json +53 -9
- package/templates/react-app/src/App.tsx +4 -5
- package/templates/react-app/src/{services → base/apis}/feApi/FeApiMockPlugin.ts +1 -1
- package/templates/react-app/src/base/cases/UserToken.ts +47 -0
- package/templates/react-app/src/base/port/IOCInterface.ts +53 -0
- package/templates/react-app/src/base/port/StorageTokenInterface.ts +5 -0
- package/templates/react-app/src/{types → base/port}/UIDependenciesInterface.ts +6 -0
- package/templates/react-app/src/{types → base/types}/global.d.ts +1 -1
- package/templates/react-app/src/components/ThemeSwitcher.tsx +3 -2
- package/templates/react-app/src/core/bootstrap.ts +21 -0
- package/templates/react-app/src/core/feIOC/FeIOC.ts +32 -0
- package/templates/react-app/src/core/feIOC/RegisterApi.ts +41 -0
- package/templates/react-app/src/core/feIOC/RegisterCommon.ts +20 -0
- package/templates/react-app/src/core/feIOC/RegisterControllers.ts +53 -0
- package/templates/react-app/src/core/index.ts +31 -0
- package/templates/react-app/src/main.tsx +8 -10
- package/templates/react-app/src/pages/404.tsx +2 -2
- package/templates/react-app/src/pages/500.tsx +1 -1
- package/templates/react-app/src/pages/auth/Layout.tsx +3 -2
- package/templates/react-app/src/pages/auth/Login.tsx +6 -4
- package/templates/react-app/src/pages/base/About.tsx +1 -1
- package/templates/react-app/src/pages/base/Executor.tsx +8 -4
- package/templates/react-app/src/pages/base/Home.tsx +1 -1
- package/templates/react-app/src/pages/base/JSONStorage.tsx +6 -4
- package/templates/react-app/src/pages/base/Layout.tsx +1 -1
- package/templates/react-app/src/pages/base/RedirectPathname.tsx +1 -1
- package/templates/react-app/src/pages/base/Request.tsx +8 -3
- package/templates/react-app/src/pages/index.tsx +7 -2
- package/templates/react-app/src/services/{pageProcesser/PageProcesser.ts → processer/ProcesserService.ts} +3 -3
- package/templates/react-app/src/{containers/context → uikit/contexts}/BaseRouteContext.ts +4 -4
- package/templates/react-app/src/{services → uikit}/controllers/ExecutorController.ts +5 -5
- package/templates/react-app/src/{services → uikit}/controllers/JSONStorageController.ts +2 -2
- package/templates/react-app/src/{services → uikit}/controllers/RequestController.ts +3 -3
- package/templates/react-app/src/{services → uikit}/controllers/RouterController.ts +2 -2
- package/templates/react-app/src/{services → uikit}/controllers/UserController.ts +25 -51
- package/templates/react-app/src/{containers/context → uikit/providers}/BaseRouteProvider.tsx +2 -2
- package/templates/react-app/src/{components → uikit/providers}/ProcessProvider.tsx +13 -7
- package/templates/react-app/tsconfig.json +27 -5
- package/templates/react-app/tsconfig.node.json +3 -15
- package/templates/react-app/vite.config.ts +15 -12
- package/templates/pack-app/.env +0 -5
- package/templates/pack-app/.gitignore.template +0 -50
- package/templates/pack-app/.prettierrc.js +0 -3
- package/templates/pack-app/CHANGELOG.md +0 -0
- package/templates/pack-app/jest.config.js +0 -31
- package/templates/react-app/eslint.config.js +0 -31
- package/templates/react-app/src/containers/index.ts +0 -71
- package/templates/react-app/src/services/pageProcesser/index.ts +0 -1
- package/templates/react-app/tsconfig.app.json +0 -29
- package/templates/react-vite-lib/.gitignore.template +0 -27
- package/templates/react-vite-lib/README.md +0 -50
- package/templates/react-vite-lib/__tests__/Sum.test.ts +0 -9
- package/templates/react-vite-lib/__tests__/Text.test.tsx +0 -11
- package/templates/react-vite-lib/eslint.config.js +0 -28
- package/templates/react-vite-lib/index.html +0 -13
- package/templates/react-vite-lib/package.json +0 -30
- package/templates/react-vite-lib/public/vite.svg +0 -1
- package/templates/react-vite-lib/src/calc.ts +0 -3
- package/templates/react-vite-lib/src/commponents/Text.tsx +0 -7
- package/templates/react-vite-lib/src/index.ts +0 -2
- package/templates/react-vite-lib/src/vite-env.d.ts +0 -1
- package/templates/react-vite-lib/tsconfig.json +0 -25
- package/templates/react-vite-lib/vite.config.ts +0 -24
- /package/{templates/pack-app → configs/_common}/.editorconfig +0 -0
- /package/{templates/pack-app → configs/_common}/.gitattributes +0 -0
- /package/{templates/react-app → configs/_common}/.gitignore.template +0 -0
- /package/{templates/pack-app → configs/_common}/.prettierignore +0 -0
- /package/templates/react-app/src/{services → base/apis}/feApi/FeApi.ts +0 -0
- /package/templates/react-app/src/{services → base/apis}/feApi/FeApiType.ts +0 -0
- /package/templates/react-app/src/{services → base/apis}/feApi/index.ts +0 -0
- /package/templates/react-app/src/{types → base/types}/Page.ts +0 -0
- /package/templates/react-app/src/{containers → core}/globals.ts +0 -0
- /package/templates/react-app/src/{hooks → uikit/hooks}/useLanguageGuard.ts +0 -0
- /package/templates/react-app/src/{hooks → uikit/hooks}/useStrictEffect.ts +0 -0
- /package/templates/react-app/src/{styles → uikit/styles}/css/index.css +0 -0
- /package/templates/react-app/src/{styles → uikit/styles}/css/page.css +0 -0
- /package/templates/react-app/src/{styles → uikit/styles}/css/tailwind.css +0 -0
- /package/templates/react-app/src/{utils → uikit/utils}/RequestLogger.ts +0 -0
- /package/templates/react-app/src/{utils → uikit/utils}/datetime.ts +0 -0
- /package/templates/react-app/src/{utils → uikit/utils}/thread.ts +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "pack-app",
|
|
3
3
|
"version": "0.0.0",
|
|
4
4
|
"description": "A template for fe-pack-app",
|
|
5
5
|
"type": "module",
|
|
@@ -10,11 +10,10 @@
|
|
|
10
10
|
},
|
|
11
11
|
"homepage": "https://github.com/qlover/fe-base#readme",
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "pnpm run build
|
|
14
|
-
"build:[PKG_NAME]": "pnpm run build --filter=@qlover/${PKG_NAME}",
|
|
13
|
+
"build": "pnpm -r run build",
|
|
15
14
|
"prettier": "prettier --ignore-path .prettierignore **/*.{js,ts,json,cjs,mjs} --write",
|
|
16
15
|
"lint": "eslint . --fix",
|
|
17
|
-
"test": "
|
|
16
|
+
"test": "pnpm run test",
|
|
18
17
|
"clean": "fe-clean",
|
|
19
18
|
"clean:build": "fe-clean -f packages/*/dist -r",
|
|
20
19
|
"check-packages": "fe-check-packages",
|
|
@@ -39,25 +38,34 @@
|
|
|
39
38
|
"@rollup/plugin-node-resolve": "^15.3.0",
|
|
40
39
|
"@rollup/plugin-terser": "^0.4.4",
|
|
41
40
|
"@rollup/plugin-typescript": "^12.1.1",
|
|
42
|
-
"@testing-library/jest-dom": "^6.6.3",
|
|
43
41
|
"@testing-library/react": "^16.1.0",
|
|
44
|
-
"@types/jest": "^29.5.11",
|
|
45
42
|
"eslint": "^9.17.0",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
43
|
+
"eslint-plugin-react": "^7.37.4",
|
|
44
|
+
"eslint-plugin-react-hooks": "^5.0.0",
|
|
45
|
+
"eslint-plugin-react-refresh": "^0.4.14",
|
|
46
|
+
"globals": "^15.12.0",
|
|
47
|
+
"husky": "^9.1.7",
|
|
48
|
+
"jsdom": "^26.0.0",
|
|
49
|
+
"prettier": "^3.5.0",
|
|
48
50
|
"rollup": "^4.24.2",
|
|
49
51
|
"rollup-plugin-delete": "^2.1.0",
|
|
50
52
|
"rollup-plugin-dts": "^6.1.1",
|
|
51
53
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
52
54
|
"ts-node": "^10.9.2",
|
|
53
|
-
"typescript": "~5.4.0"
|
|
55
|
+
"typescript": "~5.4.0",
|
|
56
|
+
"vite": "^5.4.8",
|
|
57
|
+
"vitest": "^3.0.5"
|
|
54
58
|
},
|
|
55
59
|
"workspaces": [
|
|
56
60
|
"packages/*"
|
|
57
61
|
],
|
|
58
62
|
"lint-staged": {
|
|
59
|
-
"
|
|
60
|
-
"eslint --fix"
|
|
63
|
+
"packages/**/*.{js,jsx,ts,tsx}": [
|
|
64
|
+
"eslint --cache --fix --quiet",
|
|
65
|
+
"prettier --write"
|
|
66
|
+
],
|
|
67
|
+
"packages/**/*.{json,css,scss,md}": [
|
|
68
|
+
"prettier --write"
|
|
61
69
|
]
|
|
62
70
|
},
|
|
63
71
|
"packageManager": "pnpm@9.1.0"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
build: {
|
|
5
|
+
outDir: 'dist',
|
|
6
|
+
sourcemap: true
|
|
7
|
+
},
|
|
8
|
+
plugins: [],
|
|
9
|
+
test: {
|
|
10
|
+
environment: 'jsdom',
|
|
11
|
+
globals: true,
|
|
12
|
+
include: ['**/__tests__/**/*.test.{ts,tsx}']
|
|
13
|
+
}
|
|
14
|
+
});
|
|
@@ -1,50 +1,187 @@
|
|
|
1
|
-
# React
|
|
1
|
+
# FE-React Template
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
一个现代化的 React 前端项目模板,集成了多项实用功能和最佳实践。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 特性亮点
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
7
|
+
- 🚀 基于 Vite 的快速开发体验
|
|
8
|
+
- 🎨 集成 Tailwind CSS 的主题系统
|
|
9
|
+
- 🌍 完善的国际化支持
|
|
10
|
+
- 🔄 IOC 容器的依赖注入
|
|
11
|
+
- 📡 统一的 API 请求处理
|
|
12
|
+
- 🎮 控制器模式的状态管理
|
|
9
13
|
|
|
10
|
-
##
|
|
14
|
+
## 环境要求
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
- Node.js >= 16
|
|
17
|
+
- pnpm >= 8.0
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
## 配置说明
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
项目配置文件位于 `config/` 目录:
|
|
22
|
+
|
|
23
|
+
- `app.common.ts`: 应用通用配置,包含 API 配置、默认登录信息等
|
|
24
|
+
- `app.router.json`: 路由配置,定义应用的路由结构
|
|
25
|
+
- `i18n.ts`: 国际化配置,支持中英文切换
|
|
26
|
+
- `theme.json`: 主题配置,定义应用的主题系统
|
|
27
|
+
|
|
28
|
+
## 项目结构
|
|
29
|
+
|
|
30
|
+
├── config/ # 配置文件目录
|
|
31
|
+
│ ├── app.common.ts # 应用通用配置
|
|
32
|
+
│ ├── app.router.json # 路由配置
|
|
33
|
+
│ ├── i18n.ts # 国际化配置
|
|
34
|
+
│ └── theme.json # 主题配置
|
|
35
|
+
├── lib/ # 公共库目录
|
|
36
|
+
│ ├── fe-react-controller/ # React 控制器库
|
|
37
|
+
│ ├── fe-react-theme/ # React 主题库
|
|
38
|
+
│ ├── openAiApi/ # OpenAI API 封装
|
|
39
|
+
│ ├── request-common-plugin/ # 请求公共插件
|
|
40
|
+
│ └── tw-root10px/ # Tailwind 10px 根字体配置
|
|
41
|
+
├── public/ # 静态资源目录
|
|
42
|
+
│ └── locales/ # 国际化资源文件
|
|
43
|
+
├── src/ # 源代码目录
|
|
44
|
+
│ ├── base/ # 基础代码
|
|
45
|
+
│ │ ├── apis/ # API 接口定义
|
|
46
|
+
│ │ ├── cases/ # 业务用例
|
|
47
|
+
│ │ ├── port/ # 接口定义
|
|
48
|
+
│ │ └── types/ # 类型定义
|
|
49
|
+
│ ├── core/ # 核心代码
|
|
50
|
+
│ │ └── feIOC/ # IOC 容器实现
|
|
51
|
+
│ │ └── globals.ts # 全局变量
|
|
52
|
+
│ │ └── bootstrap.ts # 启动器
|
|
53
|
+
│ ├── pages/ # 页面组件
|
|
54
|
+
│ ├── services/ # 服务层
|
|
55
|
+
│ └── uikit/ # UI 组件库
|
|
56
|
+
└── vite.config.ts # Vite 配置文件
|
|
57
|
+
|
|
58
|
+
## 目录结构说明
|
|
59
|
+
|
|
60
|
+
1. `config/`: 集中管理配置文件,便于统一维护和修改
|
|
61
|
+
2. `lib/`: 可复用的独立功能库,方便跨项目使用
|
|
62
|
+
3. `src/base/`: 基础代码层,定义接口和类型
|
|
63
|
+
4. `src/core/`: 核心功能实现,包含 IOC 容器等基础设施
|
|
64
|
+
5. `src/pages/`: 页面组件,按功能模块组织
|
|
65
|
+
6. `src/services/`: 服务层,处理业务逻辑
|
|
66
|
+
7. `src/uikit/`: UI 组件库,提供可复用的界面组件
|
|
67
|
+
|
|
68
|
+
## 核心特性
|
|
69
|
+
|
|
70
|
+
### 1. IOC 容器
|
|
71
|
+
|
|
72
|
+
项目使用依赖注入容器管理依赖,主要包含:
|
|
73
|
+
|
|
74
|
+
- `FeIOC`: IOC 容器的核心实现
|
|
75
|
+
- `RegisterApi`: API 服务注册
|
|
76
|
+
- `RegisterCommon`: 通用服务注册
|
|
77
|
+
- `RegisterControllers`: 控制器注册
|
|
78
|
+
|
|
79
|
+
### 2. 国际化支持
|
|
80
|
+
|
|
81
|
+
- 支持中文和英文
|
|
82
|
+
- 使用 i18next 实现
|
|
83
|
+
- 按模块划分语言文件
|
|
84
|
+
|
|
85
|
+
### 3. 主题系统
|
|
86
|
+
|
|
87
|
+
- 支持主题切换
|
|
88
|
+
- 基于 Tailwind CSS
|
|
89
|
+
- 自定义 10px 根字体配置
|
|
90
|
+
|
|
91
|
+
### 4. API 请求处理
|
|
92
|
+
|
|
93
|
+
- 统一的请求处理机制
|
|
94
|
+
- 支持请求拦截和响应处理
|
|
95
|
+
- Mock 数据支持
|
|
96
|
+
- OpenAI API 集成
|
|
97
|
+
|
|
98
|
+
### 5. 控制器模式
|
|
99
|
+
|
|
100
|
+
采用控制器模式管理业务逻辑:
|
|
101
|
+
|
|
102
|
+
- `JSONStorageController`: JSON 存储控制
|
|
103
|
+
- `RequestController`: 请求控制
|
|
104
|
+
- `RouterController`: 路由控制
|
|
105
|
+
- `UserController`: 用户控制
|
|
106
|
+
- `ThemeController`: 主题控制
|
|
107
|
+
|
|
108
|
+
## 技术栈
|
|
109
|
+
|
|
110
|
+
- React
|
|
111
|
+
- TypeScript
|
|
112
|
+
- Vite
|
|
113
|
+
- Tailwind CSS
|
|
114
|
+
- i18next
|
|
115
|
+
- @qlover/fe-utils
|
|
116
|
+
|
|
117
|
+
## 开发
|
|
118
|
+
|
|
119
|
+
项目使用 pnpm 管理依赖,请先安装 pnpm
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npm install -g pnpm
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 开发指南
|
|
126
|
+
|
|
127
|
+
### API 开发
|
|
128
|
+
|
|
129
|
+
项目使用统一的 API 请求处理机制:
|
|
130
|
+
|
|
131
|
+
- 支持请求拦截和响应处理
|
|
132
|
+
- 内置 Mock 数据支持
|
|
133
|
+
- 集成 OpenAI API
|
|
134
|
+
|
|
135
|
+
### 控制器开发
|
|
136
|
+
|
|
137
|
+
项目采用控制器模式管理业务逻辑:
|
|
138
|
+
|
|
139
|
+
- `JSONStorageController`: 处理 JSON 数据存储
|
|
140
|
+
- `RequestController`: 处理 API 请求
|
|
141
|
+
- `UserController`: 处理用户认证
|
|
142
|
+
- `ThemeController`: 处理主题切换
|
|
143
|
+
|
|
144
|
+
### 国际化开发
|
|
145
|
+
|
|
146
|
+
语言文件位于 `public/locales/` 目录:
|
|
147
|
+
|
|
148
|
+
- `zh/`: 中文语言包
|
|
149
|
+
- `en/`: 英文语言包
|
|
150
|
+
|
|
151
|
+
### 安装依赖
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
pnpm install
|
|
26
155
|
```
|
|
27
156
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
```js
|
|
33
|
-
// eslint.config.js
|
|
34
|
-
import react from 'eslint-plugin-react'
|
|
35
|
-
|
|
36
|
-
export default tseslint.config({
|
|
37
|
-
// Set the react version
|
|
38
|
-
settings: { react: { version: '18.3' } },
|
|
39
|
-
plugins: {
|
|
40
|
-
// Add the react plugin
|
|
41
|
-
react,
|
|
42
|
-
},
|
|
43
|
-
rules: {
|
|
44
|
-
// other rules...
|
|
45
|
-
// Enable its recommended rules
|
|
46
|
-
...react.configs.recommended.rules,
|
|
47
|
-
...react.configs['jsx-runtime'].rules,
|
|
48
|
-
},
|
|
49
|
-
})
|
|
157
|
+
### 开发模式
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
pnpm run dev
|
|
50
161
|
```
|
|
162
|
+
|
|
163
|
+
### 构建
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
pnpm run build
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 测试
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
pnpm run test
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 常见问题
|
|
176
|
+
|
|
177
|
+
### Q: 如何切换主题?
|
|
178
|
+
|
|
179
|
+
A: 项目支持主题切换功能,通过 ThemeController 进行控制。
|
|
180
|
+
|
|
181
|
+
### Q: 如何添加新的语言支持?
|
|
182
|
+
|
|
183
|
+
A: 在 `public/locales/` 目录下添加新的语言文件,并在 `i18n.ts` 中配置。
|
|
184
|
+
|
|
185
|
+
## 许可证
|
|
186
|
+
|
|
187
|
+
ISC
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { SliceStore } from '@qlover/slice-store';
|
|
1
|
+
import { SliceStore } from '@qlover/slice-store-react';
|
|
2
2
|
|
|
3
3
|
export class FeController<T> extends SliceStore<T> {
|
|
4
|
-
constructor(
|
|
5
|
-
super(
|
|
4
|
+
constructor(private stateFactory: () => T) {
|
|
5
|
+
super(stateFactory);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
getState(): T {
|
|
@@ -12,4 +12,8 @@ export class FeController<T> extends SliceStore<T> {
|
|
|
12
12
|
setState(state: Partial<T>): void {
|
|
13
13
|
this.emit({ ...this.state, ...state });
|
|
14
14
|
}
|
|
15
|
+
|
|
16
|
+
reset(): void {
|
|
17
|
+
this.emit(this.stateFactory());
|
|
18
|
+
}
|
|
15
19
|
}
|
|
@@ -4,7 +4,7 @@ import { ThemeStateGetter } from './ThemeStateGetter';
|
|
|
4
4
|
|
|
5
5
|
export class ThemeController extends FeController<ThemeControllerState> {
|
|
6
6
|
constructor(private props: ThemeControllerProps) {
|
|
7
|
-
super(ThemeStateGetter.create(props));
|
|
7
|
+
super(() => ThemeStateGetter.create(props));
|
|
8
8
|
|
|
9
9
|
this.bindToTheme();
|
|
10
10
|
}
|
|
@@ -1,13 +1,54 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
3
|
-
"
|
|
2
|
+
"name": "react-app",
|
|
3
|
+
"description": "A react app template",
|
|
4
4
|
"version": "0.0.0",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"private": true,
|
|
7
|
+
"homepage": "",
|
|
8
|
+
"author": "qlover",
|
|
9
|
+
"license": "ISC",
|
|
10
|
+
"main": "./dist/es/index.js",
|
|
11
|
+
"module": "./dist/es/index.js",
|
|
12
|
+
"types": "./dist/es/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/es/index.d.ts",
|
|
16
|
+
"import": "./dist/es/index.js",
|
|
17
|
+
"require": "./dist/cjs/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./cjs/*": "./dist/cjs/*",
|
|
20
|
+
"./es/*": "./dist/es/*",
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/qlover/fe-base.git",
|
|
26
|
+
"directory": ""
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"bin",
|
|
30
|
+
"dist",
|
|
31
|
+
"package.json",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"keywords": [
|
|
35
|
+
"scripts",
|
|
36
|
+
"release",
|
|
37
|
+
"fe-release"
|
|
38
|
+
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"bin": {
|
|
43
|
+
"fe-release": "./bin/release.js"
|
|
44
|
+
},
|
|
6
45
|
"scripts": {
|
|
7
46
|
"dev": "vite",
|
|
8
|
-
"build": "
|
|
9
|
-
"lint": "eslint
|
|
10
|
-
"
|
|
47
|
+
"build": "vite build",
|
|
48
|
+
"lint": "eslint ./src --fix",
|
|
49
|
+
"prettier": "prettier --write ./src",
|
|
50
|
+
"preview": "vite preview",
|
|
51
|
+
"test": "vitest run"
|
|
11
52
|
},
|
|
12
53
|
"dependencies": {
|
|
13
54
|
"@qlover/fe-utils": "latest",
|
|
@@ -19,12 +60,12 @@
|
|
|
19
60
|
"react": "^18.3.1",
|
|
20
61
|
"react-dom": "^18.3.1",
|
|
21
62
|
"react-i18next": "^15.2.0",
|
|
22
|
-
"react-router-dom": "
|
|
63
|
+
"react-router-dom": "^7.1.5"
|
|
23
64
|
},
|
|
24
65
|
"devDependencies": {
|
|
25
66
|
"@eslint/js": "^9.11.1",
|
|
26
|
-
"@qlover/eslint-plugin-fe-dev": "^0.2.0",
|
|
27
67
|
"@qlover/env-loader": "latest",
|
|
68
|
+
"@qlover/eslint-plugin-fe-dev": "^0.2.0",
|
|
28
69
|
"@qlover/fe-scripts": "latest",
|
|
29
70
|
"@rollup/plugin-alias": "^5.1.1",
|
|
30
71
|
"@types/lodash": "^4.17.13",
|
|
@@ -32,10 +73,12 @@
|
|
|
32
73
|
"@types/react-dom": "^18.3.0",
|
|
33
74
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
34
75
|
"@types/typo-js": "^1.2.2",
|
|
35
|
-
"@vitejs/plugin-react": "^4.3.
|
|
76
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
36
77
|
"@vitejs/plugin-react-swc": "^3.5.0",
|
|
37
78
|
"autoprefixer": "^10.4.20",
|
|
38
79
|
"eslint": "^9.15.0",
|
|
80
|
+
"eslint-plugin-prettier": "^5.2.3",
|
|
81
|
+
"eslint-plugin-react": "^7.37.4",
|
|
39
82
|
"eslint-plugin-react-hooks": "^5.0.0",
|
|
40
83
|
"eslint-plugin-react-refresh": "^0.4.14",
|
|
41
84
|
"globals": "^15.12.0",
|
|
@@ -45,6 +88,7 @@
|
|
|
45
88
|
"typescript": "^5.6.3",
|
|
46
89
|
"typescript-eslint": "^8.15.0",
|
|
47
90
|
"vite": "^5.4.8",
|
|
48
|
-
"vite-plugin-cross-origin-isolation": "^0.1.6"
|
|
91
|
+
"vite-plugin-cross-origin-isolation": "^0.1.6",
|
|
92
|
+
"vitest": "^3.0.5"
|
|
49
93
|
}
|
|
50
94
|
}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import '
|
|
1
|
+
import '@/uikit/styles/css/index.css';
|
|
2
2
|
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
|
|
3
3
|
import { createFeReactRoutes } from './pages';
|
|
4
|
-
import { I18nService } from '@/services/i18n';
|
|
5
4
|
import { useMemo } from 'react';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
I18nService.init();
|
|
5
|
+
import { IOC } from './core';
|
|
6
|
+
import { RouterController } from './uikit/controllers/RouterController';
|
|
9
7
|
|
|
10
8
|
function App() {
|
|
11
9
|
const routerBase = useMemo(() => {
|
|
10
|
+
const routerController = IOC(RouterController);
|
|
12
11
|
const routes = createFeReactRoutes(routerController.getRoutes());
|
|
13
12
|
const router = createBrowserRouter(routes);
|
|
14
13
|
return router;
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
RequestAdapterFetchConfig,
|
|
5
5
|
RequestAdapterResponse
|
|
6
6
|
} from '@qlover/fe-utils';
|
|
7
|
-
import { sleep } from '@/utils/thread';
|
|
7
|
+
import { sleep } from '@/uikit/utils/thread';
|
|
8
8
|
|
|
9
9
|
export class FeApiMockPlugin implements ExecutorPlugin {
|
|
10
10
|
readonly pluginName = 'FeApiMockPlugin';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { StorageTokenInterface } from '@/base/port/StorageTokenInterface';
|
|
2
|
+
import { adjustExpirationTime } from '@/uikit/utils/datetime';
|
|
3
|
+
import { JSONStorage } from '@qlover/fe-utils';
|
|
4
|
+
|
|
5
|
+
export interface UserTokenOptions {
|
|
6
|
+
/**
|
|
7
|
+
* @default `month`
|
|
8
|
+
*/
|
|
9
|
+
expiresIn?: number | 'day' | 'week' | 'month' | 'year';
|
|
10
|
+
storageKey: string;
|
|
11
|
+
storage: JSONStorage;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class UserToken implements StorageTokenInterface {
|
|
15
|
+
private token = '';
|
|
16
|
+
|
|
17
|
+
constructor(private options: UserTokenOptions) {}
|
|
18
|
+
|
|
19
|
+
getToken(): string {
|
|
20
|
+
if (!this.token) {
|
|
21
|
+
const { storageKey, storage } = this.options;
|
|
22
|
+
const token = storage.getItem(storageKey, '');
|
|
23
|
+
|
|
24
|
+
if (token) {
|
|
25
|
+
this.setToken(token);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return this.token;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
setToken(token: string, expireTime?: number): void {
|
|
33
|
+
this.token = token;
|
|
34
|
+
|
|
35
|
+
expireTime =
|
|
36
|
+
expireTime !== undefined
|
|
37
|
+
? expireTime
|
|
38
|
+
: adjustExpirationTime(Date.now(), this.options.expiresIn ?? 'month');
|
|
39
|
+
|
|
40
|
+
this.options.storage.setItem(this.options.storageKey, token, expireTime);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
removeToken(): void {
|
|
44
|
+
this.token = '';
|
|
45
|
+
this.options.storage.removeItem(this.options.storageKey);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface Abstract<T> {
|
|
2
|
+
prototype: T;
|
|
3
|
+
}
|
|
4
|
+
export type Newable<T, Args extends unknown[] = unknown[]> = new (
|
|
5
|
+
...args: Args
|
|
6
|
+
) => T;
|
|
7
|
+
|
|
8
|
+
export type ServiceIdentifier<T = unknown> =
|
|
9
|
+
| string
|
|
10
|
+
| symbol
|
|
11
|
+
| Newable<T>
|
|
12
|
+
| Abstract<T>;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* IOC container
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
export interface IOCInterface {
|
|
19
|
+
/**
|
|
20
|
+
* configure IOC container
|
|
21
|
+
*/
|
|
22
|
+
configure(): void;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* bind instance
|
|
26
|
+
*
|
|
27
|
+
* @param serviceIdentifier
|
|
28
|
+
* @param value
|
|
29
|
+
*/
|
|
30
|
+
bind<T>(serviceIdentifier: ServiceIdentifier<T>, value: T): void;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* get instance
|
|
34
|
+
*
|
|
35
|
+
* @param serviceIdentifier
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
get<T>(serviceIdentifier: ServiceIdentifier<T>): T;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* You can also use the override method to specify a replacement at runtime
|
|
42
|
+
*
|
|
43
|
+
* However, it may have performance issues because it creates an additional instance
|
|
44
|
+
*
|
|
45
|
+
* @param serviceIdentifier
|
|
46
|
+
* @param value
|
|
47
|
+
*/
|
|
48
|
+
override<T>(serviceIdentifier: ServiceIdentifier<T>, value: T): void;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface IOCRegisterInterface {
|
|
52
|
+
register(container: IOCInterface): void;
|
|
53
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IOC } from '@/core';
|
|
2
2
|
import { useController } from '@lib/fe-react-controller';
|
|
3
|
+
import { ThemeController } from '@lib/fe-react-theme/ThemeController';
|
|
3
4
|
import { useTranslation } from 'react-i18next';
|
|
4
5
|
|
|
5
6
|
export default function ThemeSwitcher() {
|
|
6
|
-
const controller = useController(
|
|
7
|
+
const controller = useController(IOC(ThemeController));
|
|
7
8
|
const { theme } = controller.getState();
|
|
8
9
|
const themes = controller.getSupportedThemes();
|
|
9
10
|
const { t } = useTranslation('common');
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as feGlobals from '@/core/globals';
|
|
2
|
+
import { IOC } from '.';
|
|
3
|
+
import { IOCInterface } from '@/base/port/IOCInterface';
|
|
4
|
+
import { I18nService } from '@/services/i18n';
|
|
5
|
+
|
|
6
|
+
export class Bootstrap {
|
|
7
|
+
constructor(private IOCContainer: IOCInterface) {}
|
|
8
|
+
|
|
9
|
+
start(): void {
|
|
10
|
+
// set global feGlobals
|
|
11
|
+
if (typeof window !== 'undefined') {
|
|
12
|
+
window.feGlobals = Object.freeze(Object.assign({}, feGlobals));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// startup IOC
|
|
16
|
+
IOC.implement(this.IOCContainer);
|
|
17
|
+
|
|
18
|
+
// startup i18n
|
|
19
|
+
I18nService.init();
|
|
20
|
+
}
|
|
21
|
+
}
|