uniky 1.0.21 → 1.0.23
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/README.md +89 -1
- package/docs/INSTALLATION.md +460 -0
- package/package.json +5 -1
- package/scripts/postinstall.js +1 -5
- package/src/lib/http/ky.ts +3 -3
- package/src/plugin/README.md +5 -5
- package/src/plugin/global.defined.ts +14 -14
- package/src/plugin/http.defined.ts +2 -2
- package/src/plugin/index.ts +13 -3
- package/src/plugin/pages.defined.ts +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,70 @@ pnpm add uniky
|
|
|
19
19
|
yarn add uniky
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
## 安装后设置
|
|
23
|
+
|
|
24
|
+
> 📖 **详细文档**: [安装机制完整说明](./docs/INSTALLATION.md)
|
|
25
|
+
|
|
26
|
+
### 自动安装(推荐)
|
|
27
|
+
|
|
28
|
+
安装 `uniky` 后,插件文件会自动安装到项目根目录的 `.uniky` 文件夹。
|
|
29
|
+
|
|
30
|
+
如果自动安装失败或删除了 `.uniky` 文件夹,可以手动触发安装:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# 方式 1: 使用 npx(推荐)
|
|
34
|
+
npx uniky-install
|
|
35
|
+
|
|
36
|
+
# 方式 2: 直接运行脚本
|
|
37
|
+
node node_modules/uniky/scripts/postinstall.js
|
|
38
|
+
|
|
39
|
+
# 方式 3: 重新安装包
|
|
40
|
+
npm install uniky --force
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### bin 命令说明
|
|
44
|
+
|
|
45
|
+
`uniky-install` 是一个可执行命令,通过 `package.json` 中的 `bin` 字段注册:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"bin": {
|
|
50
|
+
"uniky-install": "./scripts/postinstall.js"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**工作原理:**
|
|
56
|
+
|
|
57
|
+
1. 当你在项目中安装 `uniky` 时,npm 会自动在 `node_modules/.bin/` 目录下创建 `uniky-install` 命令的软链接
|
|
58
|
+
2. 这个命令指向 `node_modules/uniky/scripts/postinstall.js` 脚本
|
|
59
|
+
3. 使用 `npx uniky-install` 可以直接执行该脚本,无需记住具体路径
|
|
60
|
+
|
|
61
|
+
**使用场景:**
|
|
62
|
+
|
|
63
|
+
- 删除了 `.uniky` 文件夹后需要重新生成
|
|
64
|
+
- 更新 `uniky` 包后需要更新插件文件
|
|
65
|
+
- CI/CD 环境中确保插件文件存在
|
|
66
|
+
- 调试插件安装问题
|
|
67
|
+
|
|
68
|
+
**执行效果:**
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
$ npx uniky-install
|
|
72
|
+
[uniky] 开始安装插件文件...
|
|
73
|
+
[uniky] 项目根目录: /path/to/your-project
|
|
74
|
+
[uniky] 目标目录: /path/to/your-project/.uniky
|
|
75
|
+
[uniky] 创建目录: /path/to/your-project/.uniky
|
|
76
|
+
[uniky] 源目录: /path/to/your-project/node_modules/uniky/src/plugin
|
|
77
|
+
[uniky] 拷贝了 5 个文件
|
|
78
|
+
[uniky] 创建索引文件: /path/to/your-project/.uniky/index.ts
|
|
79
|
+
[uniky] ✅ 插件文件已成功安装到 /path/to/your-project/.uniky (5 个文件)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 自动检测安装
|
|
83
|
+
|
|
84
|
+
如果 `.uniky` 文件夹缺失,在首次运行 Vite 时,插件会自动检测并安装所需文件。这是最后的保障机制。
|
|
85
|
+
|
|
22
86
|
## 使用
|
|
23
87
|
|
|
24
88
|
### 库功能
|
|
@@ -97,11 +161,35 @@ _To.back();
|
|
|
97
161
|
在 `main.ts` 中安装全局定义:
|
|
98
162
|
|
|
99
163
|
```typescript
|
|
100
|
-
import { installGlobals } from './
|
|
164
|
+
import { installGlobals } from './_unikey/global.install';
|
|
101
165
|
|
|
102
166
|
installGlobals();
|
|
103
167
|
```
|
|
104
168
|
|
|
169
|
+
## 目录结构
|
|
170
|
+
|
|
171
|
+
安装后,项目根目录会生成 `.uniky` 文件夹:
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
your-project/
|
|
175
|
+
├── .uniky/
|
|
176
|
+
│ ├── index.ts
|
|
177
|
+
│ └── plugin/
|
|
178
|
+
│ ├── index.ts
|
|
179
|
+
│ ├── pages.defined.ts
|
|
180
|
+
│ ├── global.defined.ts
|
|
181
|
+
│ ├── http.defined.ts
|
|
182
|
+
│ └── lib.defined.ts
|
|
183
|
+
├── src/
|
|
184
|
+
│ └── _unikey/ # 插件自动生成的文件
|
|
185
|
+
│ ├── global/
|
|
186
|
+
│ │ ├── pages.ts
|
|
187
|
+
│ │ └── ky.ts
|
|
188
|
+
│ ├── global.d.ts
|
|
189
|
+
│ └── global.install.ts
|
|
190
|
+
└── vite.config.ts
|
|
191
|
+
```
|
|
192
|
+
|
|
105
193
|
## 故障排除
|
|
106
194
|
|
|
107
195
|
### ESM 相关错误
|
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
# Uniky 插件安装机制详解
|
|
2
|
+
|
|
3
|
+
本文档详细说明 `uniky` 包的插件文件安装机制,包括自动安装、手动安装和故障排除。
|
|
4
|
+
|
|
5
|
+
## 概述
|
|
6
|
+
|
|
7
|
+
`uniky` 采用三层安装保障机制:
|
|
8
|
+
|
|
9
|
+
1. **npm postinstall 钩子** - 在包安装时自动执行
|
|
10
|
+
2. **bin 命令手动触发** - 提供 `uniky-install` 命令
|
|
11
|
+
3. **Vite 插件自动检测** - 运行时自动安装缺失文件
|
|
12
|
+
|
|
13
|
+
## 安装机制详解
|
|
14
|
+
|
|
15
|
+
### 1. npm postinstall 钩子
|
|
16
|
+
|
|
17
|
+
#### 配置位置
|
|
18
|
+
|
|
19
|
+
`package.json`:
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"scripts": {
|
|
23
|
+
"postinstall": "node scripts/postinstall.js"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
#### 工作原理
|
|
29
|
+
|
|
30
|
+
- 当执行 `npm install uniky` 时,npm 会自动运行 `postinstall` 脚本
|
|
31
|
+
- 脚本会将 `src/plugin` 目录下的所有文件拷贝到项目根目录的 `.uniky/plugin` 文件夹
|
|
32
|
+
- 同时创建 `.uniky/index.ts` 入口文件
|
|
33
|
+
|
|
34
|
+
#### 执行时机
|
|
35
|
+
|
|
36
|
+
- ✅ 首次安装包时:`npm install uniky`
|
|
37
|
+
- ✅ 强制重装时:`npm install uniky --force`
|
|
38
|
+
- ✅ 删除 node_modules 后重新安装:`rm -rf node_modules && npm install`
|
|
39
|
+
- ❌ 普通的 `npm install`(包已存在)
|
|
40
|
+
- ❌ `npm update uniky`
|
|
41
|
+
|
|
42
|
+
#### 脚本逻辑
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
function findProjectRoot() {
|
|
46
|
+
// 1. 检查当前目录是否在 node_modules 中
|
|
47
|
+
if (currentDir.includes('node_modules')) {
|
|
48
|
+
// 找到 node_modules 的父目录(项目根目录)
|
|
49
|
+
const parts = currentDir.split('node_modules');
|
|
50
|
+
return parts[0].replace(/[\/\\]$/, '');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 2. 向上查找包含 package.json 的目录
|
|
54
|
+
// ...
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function copyDirectoryRecursive(source, target) {
|
|
58
|
+
// 递归拷贝整个目录,包括所有子目录和文件
|
|
59
|
+
// ...
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function installPluginFiles() {
|
|
63
|
+
const projectRoot = findProjectRoot();
|
|
64
|
+
const unikyDir = join(projectRoot, '.uniky');
|
|
65
|
+
const pluginDir = join(unikyDir, 'plugin');
|
|
66
|
+
const sourceDir = join(__dirname, '..', 'src', 'plugin');
|
|
67
|
+
|
|
68
|
+
// 拷贝所有插件文件
|
|
69
|
+
copyDirectoryRecursive(sourceDir, pluginDir);
|
|
70
|
+
|
|
71
|
+
// 创建入口文件
|
|
72
|
+
writeFileSync(join(unikyDir, 'index.ts'), `export * from './plugin/index.js';`);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 2. bin 命令手动触发
|
|
77
|
+
|
|
78
|
+
#### 配置位置
|
|
79
|
+
|
|
80
|
+
`package.json`:
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"bin": {
|
|
84
|
+
"uniky-install": "./scripts/postinstall.js"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### 工作原理
|
|
90
|
+
|
|
91
|
+
1. npm 在安装包时,会在 `node_modules/.bin/` 目录下创建可执行文件
|
|
92
|
+
2. 对于 `uniky-install`,会创建一个指向 `node_modules/uniky/scripts/postinstall.js` 的软链接
|
|
93
|
+
3. 使用 `npx uniky-install` 时,会查找并执行这个命令
|
|
94
|
+
|
|
95
|
+
#### 使用方法
|
|
96
|
+
|
|
97
|
+
**方式 1:使用 npx(推荐)**
|
|
98
|
+
```bash
|
|
99
|
+
npx uniky-install
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**方式 2:直接通过 node_modules/.bin 执行**
|
|
103
|
+
```bash
|
|
104
|
+
./node_modules/.bin/uniky-install
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**方式 3:添加到 package.json scripts**
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"scripts": {
|
|
111
|
+
"setup": "uniky-install"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
然后运行:
|
|
116
|
+
```bash
|
|
117
|
+
npm run setup
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### 适用场景
|
|
121
|
+
|
|
122
|
+
- 删除了 `.uniky` 文件夹需要重新生成
|
|
123
|
+
- 更新 `uniky` 版本后需要更新插件文件
|
|
124
|
+
- CI/CD 流程中确保环境正确
|
|
125
|
+
- 多人协作时,其他开发者拉取代码后初始化
|
|
126
|
+
|
|
127
|
+
### 3. Vite 插件自动检测
|
|
128
|
+
|
|
129
|
+
#### 实现位置
|
|
130
|
+
|
|
131
|
+
`src/plugin/index.ts`:
|
|
132
|
+
```typescript
|
|
133
|
+
function ensurePluginInstalled(projectRoot: string): void {
|
|
134
|
+
const unikyDir = join(projectRoot, '.uniky');
|
|
135
|
+
const pluginDir = join(unikyDir, 'plugin');
|
|
136
|
+
|
|
137
|
+
// 检查关键文件是否存在
|
|
138
|
+
const keyFiles = ['index.ts', 'pages.defined.ts', 'global.defined.ts'];
|
|
139
|
+
const needsInstall = !existsSync(pluginDir) ||
|
|
140
|
+
keyFiles.some(file => !existsSync(join(pluginDir, file)));
|
|
141
|
+
|
|
142
|
+
if (!needsInstall) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log('[uniky] 检测到插件文件缺失,正在自动安装...');
|
|
147
|
+
|
|
148
|
+
// 自动安装逻辑...
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function unikyPlugin(options = {}): Plugin[] {
|
|
152
|
+
const setupPlugin: Plugin = {
|
|
153
|
+
name: 'vite-plugin-uniky-setup',
|
|
154
|
+
configResolved(config) {
|
|
155
|
+
ensurePluginInstalled(config.root);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
return [setupPlugin, ...其他插件];
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### 工作原理
|
|
164
|
+
|
|
165
|
+
1. 当 Vite 加载配置时,会调用插件的 `configResolved` 钩子
|
|
166
|
+
2. 在这个钩子中检查 `.uniky/plugin` 目录和关键文件是否存在
|
|
167
|
+
3. 如果缺失,从 `node_modules/uniky/src/plugin` 拷贝文件
|
|
168
|
+
4. 这是最后的保障机制,确保即使前两步失败也能正常工作
|
|
169
|
+
|
|
170
|
+
#### 适用场景
|
|
171
|
+
|
|
172
|
+
- postinstall 脚本执行失败
|
|
173
|
+
- `.gitignore` 忽略了 `.uniky` 文件夹,其他开发者拉取代码后
|
|
174
|
+
- 容器化部署时 node_modules 挂载方式特殊
|
|
175
|
+
- 任何其他导致文件缺失的情况
|
|
176
|
+
|
|
177
|
+
## 文件结构
|
|
178
|
+
|
|
179
|
+
### 安装后的目录结构
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
your-project/
|
|
183
|
+
├── .uniky/ # 安装目标目录
|
|
184
|
+
│ ├── index.ts # 入口文件
|
|
185
|
+
│ └── plugin/ # 插件文件目录
|
|
186
|
+
│ ├── index.ts # 插件总入口
|
|
187
|
+
│ ├── pages.defined.ts # 页面路由生成插件
|
|
188
|
+
│ ├── global.defined.ts # 全局定义生成插件
|
|
189
|
+
│ ├── http.defined.ts # HTTP 配置生成插件
|
|
190
|
+
│ └── lib.defined.ts # 其他辅助插件
|
|
191
|
+
├── node_modules/
|
|
192
|
+
│ ├── .bin/
|
|
193
|
+
│ │ └── uniky-install # bin 命令软链接
|
|
194
|
+
│ └── uniky/
|
|
195
|
+
│ ├── src/
|
|
196
|
+
│ │ └── plugin/ # 源文件(安装源)
|
|
197
|
+
│ │ ├── index.ts
|
|
198
|
+
│ │ ├── pages.defined.ts
|
|
199
|
+
│ │ ├── global.defined.ts
|
|
200
|
+
│ │ ├── http.defined.ts
|
|
201
|
+
│ │ └── lib.defined.ts
|
|
202
|
+
│ └── scripts/
|
|
203
|
+
│ └── postinstall.js # 安装脚本
|
|
204
|
+
└── vite.config.ts
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 生成的文件
|
|
208
|
+
|
|
209
|
+
插件运行时会在 `src/_unikey/` 目录下生成文件:
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
src/
|
|
213
|
+
└── _unikey/ # 插件生成的文件
|
|
214
|
+
├── global/
|
|
215
|
+
│ ├── pages.ts # 页面路由定义
|
|
216
|
+
│ └── ky.ts # HTTP 客户端配置
|
|
217
|
+
├── global.d.ts # 全局类型定义
|
|
218
|
+
└── global.install.ts # 全局变量安装文件
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## 故障排除
|
|
222
|
+
|
|
223
|
+
### 问题 1:postinstall 没有执行
|
|
224
|
+
|
|
225
|
+
**症状:**
|
|
226
|
+
- 安装 `uniky` 后没有生成 `.uniky` 文件夹
|
|
227
|
+
|
|
228
|
+
**原因:**
|
|
229
|
+
- npm 默认只在首次安装时执行 postinstall
|
|
230
|
+
- 如果包已存在,再次 `npm install` 不会触发
|
|
231
|
+
|
|
232
|
+
**解决方案:**
|
|
233
|
+
```bash
|
|
234
|
+
# 方案 1:强制重装
|
|
235
|
+
npm install uniky --force
|
|
236
|
+
|
|
237
|
+
# 方案 2:删除后重装
|
|
238
|
+
rm -rf node_modules/uniky
|
|
239
|
+
npm install
|
|
240
|
+
|
|
241
|
+
# 方案 3:使用 bin 命令
|
|
242
|
+
npx uniky-install
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### 问题 2:找不到 uniky-install 命令
|
|
246
|
+
|
|
247
|
+
**症状:**
|
|
248
|
+
```bash
|
|
249
|
+
$ npx uniky-install
|
|
250
|
+
command not found: uniky-install
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**原因:**
|
|
254
|
+
- `uniky` 包未正确安装
|
|
255
|
+
- `node_modules/.bin` 目录没有正确创建软链接
|
|
256
|
+
|
|
257
|
+
**解决方案:**
|
|
258
|
+
```bash
|
|
259
|
+
# 1. 检查 uniky 是否已安装
|
|
260
|
+
npm list uniky
|
|
261
|
+
|
|
262
|
+
# 2. 重新安装
|
|
263
|
+
npm install uniky
|
|
264
|
+
|
|
265
|
+
# 3. 检查 bin 目录
|
|
266
|
+
ls -la node_modules/.bin/uniky-install
|
|
267
|
+
|
|
268
|
+
# 4. 如果还不行,直接运行脚本
|
|
269
|
+
node node_modules/uniky/scripts/postinstall.js
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### 问题 3:权限问题
|
|
273
|
+
|
|
274
|
+
**症状:**
|
|
275
|
+
```bash
|
|
276
|
+
[uniky] ❌ 插件文件安装失败: Error: EACCES: permission denied
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**原因:**
|
|
280
|
+
- 项目目录没有写入权限
|
|
281
|
+
- 在某些容器或 CI 环境中可能出现
|
|
282
|
+
|
|
283
|
+
**解决方案:**
|
|
284
|
+
```bash
|
|
285
|
+
# 1. 检查目录权限
|
|
286
|
+
ls -la .
|
|
287
|
+
|
|
288
|
+
# 2. 修改权限(如果需要)
|
|
289
|
+
chmod -R u+w .
|
|
290
|
+
|
|
291
|
+
# 3. 使用 sudo(不推荐,仅在必要时)
|
|
292
|
+
sudo npx uniky-install
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### 问题 4:路径问题
|
|
296
|
+
|
|
297
|
+
**症状:**
|
|
298
|
+
```bash
|
|
299
|
+
[uniky] 错误: 源目录不存在 /path/to/node_modules/uniky/src/plugin
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**原因:**
|
|
303
|
+
- 包结构不完整
|
|
304
|
+
- npm 安装时出现问题
|
|
305
|
+
|
|
306
|
+
**解决方案:**
|
|
307
|
+
```bash
|
|
308
|
+
# 1. 检查包是否完整
|
|
309
|
+
ls node_modules/uniky/src/plugin
|
|
310
|
+
|
|
311
|
+
# 2. 清除缓存重装
|
|
312
|
+
npm cache clean --force
|
|
313
|
+
rm -rf node_modules package-lock.json
|
|
314
|
+
npm install
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### 问题 5:.gitignore 导致文件缺失
|
|
318
|
+
|
|
319
|
+
**症状:**
|
|
320
|
+
- 本地开发正常,其他开发者或 CI 环境报错
|
|
321
|
+
- `.uniky` 文件夹不存在
|
|
322
|
+
|
|
323
|
+
**原因:**
|
|
324
|
+
- `.uniky` 被添加到 `.gitignore`
|
|
325
|
+
|
|
326
|
+
**建议:**
|
|
327
|
+
|
|
328
|
+
**方案 1:不要忽略 .uniky 文件夹(推荐)**
|
|
329
|
+
```gitignore
|
|
330
|
+
# .gitignore
|
|
331
|
+
# 不要添加 .uniky
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**方案 2:添加初始化步骤**
|
|
335
|
+
```json
|
|
336
|
+
{
|
|
337
|
+
"scripts": {
|
|
338
|
+
"postinstall": "uniky-install"
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**方案 3:依赖自动检测**
|
|
344
|
+
- 什么都不做,依赖 Vite 插件的自动安装机制
|
|
345
|
+
|
|
346
|
+
## 最佳实践
|
|
347
|
+
|
|
348
|
+
### 1. 版本控制
|
|
349
|
+
|
|
350
|
+
**推荐做法:**
|
|
351
|
+
- ✅ 将 `.uniky` 文件夹提交到 Git
|
|
352
|
+
- ✅ 在 `.gitignore` 中忽略 `src/_unikey`(自动生成的文件)
|
|
353
|
+
|
|
354
|
+
```gitignore
|
|
355
|
+
# .gitignore
|
|
356
|
+
src/_unikey/
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
**原因:**
|
|
360
|
+
- `.uniky` 包含项目配置,应该版本控制
|
|
361
|
+
- `src/_unikey` 是运行时生成的,不需要提交
|
|
362
|
+
|
|
363
|
+
### 2. CI/CD 配置
|
|
364
|
+
|
|
365
|
+
```yaml
|
|
366
|
+
# .github/workflows/build.yml
|
|
367
|
+
- name: Install dependencies
|
|
368
|
+
run: npm install
|
|
369
|
+
|
|
370
|
+
- name: Ensure uniky plugin installed
|
|
371
|
+
run: npx uniky-install
|
|
372
|
+
|
|
373
|
+
- name: Build
|
|
374
|
+
run: npm run build
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### 3. 团队协作
|
|
378
|
+
|
|
379
|
+
在项目 README 中添加说明:
|
|
380
|
+
|
|
381
|
+
```markdown
|
|
382
|
+
## 开发环境设置
|
|
383
|
+
|
|
384
|
+
1. 安装依赖
|
|
385
|
+
```bash
|
|
386
|
+
npm install
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
2. 如果遇到 uniky 插件相关错误,运行:
|
|
390
|
+
```bash
|
|
391
|
+
npx uniky-install
|
|
392
|
+
```
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### 4. Docker 环境
|
|
396
|
+
|
|
397
|
+
```dockerfile
|
|
398
|
+
FROM node:18
|
|
399
|
+
|
|
400
|
+
WORKDIR /app
|
|
401
|
+
|
|
402
|
+
COPY package*.json ./
|
|
403
|
+
RUN npm install
|
|
404
|
+
|
|
405
|
+
# 确保插件文件存在
|
|
406
|
+
RUN npx uniky-install || true
|
|
407
|
+
|
|
408
|
+
COPY . .
|
|
409
|
+
RUN npm run build
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## 技术细节
|
|
413
|
+
|
|
414
|
+
### bin 命令的实现原理
|
|
415
|
+
|
|
416
|
+
1. **package.json 配置**
|
|
417
|
+
```json
|
|
418
|
+
{
|
|
419
|
+
"bin": {
|
|
420
|
+
"uniky-install": "./scripts/postinstall.js"
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
2. **npm 安装时的操作**
|
|
426
|
+
- 读取 `bin` 字段
|
|
427
|
+
- 在 `node_modules/.bin/` 创建可执行文件或软链接
|
|
428
|
+
- Unix/Linux/Mac: 创建符号链接
|
|
429
|
+
- Windows: 创建 `.cmd` 批处理文件
|
|
430
|
+
|
|
431
|
+
3. **npx 的查找顺序**
|
|
432
|
+
```bash
|
|
433
|
+
npx uniky-install
|
|
434
|
+
```
|
|
435
|
+
- 首先查找 `node_modules/.bin/uniky-install`
|
|
436
|
+
- 如果找不到,查找全局安装的包
|
|
437
|
+
- 如果还找不到,临时下载并执行
|
|
438
|
+
|
|
439
|
+
### 脚本权限
|
|
440
|
+
|
|
441
|
+
在 Unix 系统中,脚本需要执行权限:
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
#!/usr/bin/env node
|
|
445
|
+
|
|
446
|
+
# 确保脚本有执行权限
|
|
447
|
+
chmod +x scripts/postinstall.js
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
npm 在创建 bin 链接时会自动处理权限。
|
|
451
|
+
|
|
452
|
+
## 总结
|
|
453
|
+
|
|
454
|
+
`uniky` 的安装机制提供了三层保障:
|
|
455
|
+
|
|
456
|
+
1. **自动安装(postinstall)** - 最佳体验,大多数情况下自动完成
|
|
457
|
+
2. **手动命令(bin)** - 灵活方便,适合各种场景
|
|
458
|
+
3. **运行时检测** - 最后保障,确保始终可用
|
|
459
|
+
|
|
460
|
+
这种设计确保了在各种环境和场景下,插件文件都能正确安装,给用户提供最佳的开发体验。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniky",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"description": "uni-app 开发工具库,包含 hooks、http 请求和 vite 插件",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/lib/index.ts",
|
|
@@ -16,11 +16,15 @@
|
|
|
16
16
|
"import": "./src/plugin/index.ts"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"uniky-install": "./scripts/postinstall.js"
|
|
21
|
+
},
|
|
19
22
|
"sideEffects": false,
|
|
20
23
|
"files": [
|
|
21
24
|
"src/lib",
|
|
22
25
|
"src/plugin",
|
|
23
26
|
"scripts",
|
|
27
|
+
"docs",
|
|
24
28
|
"README.md"
|
|
25
29
|
],
|
|
26
30
|
"scripts": {
|
package/scripts/postinstall.js
CHANGED
package/src/lib/http/ky.ts
CHANGED
|
@@ -209,9 +209,9 @@ class UniKyBase {
|
|
|
209
209
|
originalUrl: string,
|
|
210
210
|
): Promise<UniKyResponse> {
|
|
211
211
|
return new Promise((resolve, reject) => {
|
|
212
|
-
uni.request({
|
|
212
|
+
;(uni.request as any)({
|
|
213
213
|
...options,
|
|
214
|
-
success: (res) => {
|
|
214
|
+
success: (res: any) => {
|
|
215
215
|
const response: UniKyResponse = {
|
|
216
216
|
data: res.data,
|
|
217
217
|
statusCode: res.statusCode,
|
|
@@ -229,7 +229,7 @@ class UniKyBase {
|
|
|
229
229
|
reject(response)
|
|
230
230
|
}
|
|
231
231
|
},
|
|
232
|
-
fail: (err) => {
|
|
232
|
+
fail: (err: any) => {
|
|
233
233
|
reject({
|
|
234
234
|
...err,
|
|
235
235
|
ok: false,
|
package/src/plugin/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
### 1. global.defined.ts - 全局定义插件
|
|
8
8
|
|
|
9
|
-
自动收集 `src/
|
|
9
|
+
自动收集 `src/_uniky/global` 文件夹下的所有导出内容,生成全局类型定义和安装文件。
|
|
10
10
|
|
|
11
11
|
### 2. pages.defined.ts - 页面路由插件
|
|
12
12
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
1. 插件会读取项目中的 OpenAPI 规范文件(支持多个位置)
|
|
24
24
|
2. 解析所有 API 路径和方法
|
|
25
25
|
3. 自动生成对应的请求函数
|
|
26
|
-
4. 生成的代码保存到 `src/
|
|
26
|
+
4. 生成的代码保存到 `src/_uniky/global/ky.ts`
|
|
27
27
|
|
|
28
28
|
### OpenAPI 文件位置
|
|
29
29
|
|
|
@@ -68,12 +68,12 @@ export function apiSysAccountLogin(data?: any, params?: any) {
|
|
|
68
68
|
|
|
69
69
|
```typescript
|
|
70
70
|
// 直接调用
|
|
71
|
-
import { apiSysAccountLogin } from '@/
|
|
71
|
+
import { apiSysAccountLogin } from '@/_uniky/global/ky';
|
|
72
72
|
|
|
73
73
|
await apiSysAccountLogin({ username: 'admin', password: '123456' });
|
|
74
74
|
|
|
75
75
|
// 使用 Hook
|
|
76
|
-
import { useKyData, apiPitfallIndexQuery } from '@/
|
|
76
|
+
import { useKyData, apiPitfallIndexQuery } from '@/_uniky/global/ky';
|
|
77
77
|
|
|
78
78
|
const { data, run } = useKyData(apiPitfallIndexQuery, []);
|
|
79
79
|
```
|
|
@@ -85,7 +85,7 @@ const { data, run } = useKyData(apiPitfallIndexQuery, []);
|
|
|
85
85
|
1. 项目启动时(如果文件不存在)
|
|
86
86
|
2. OpenAPI 规范文件发生变化时
|
|
87
87
|
|
|
88
|
-
如果需要手动触发重新生成,删除 `src/
|
|
88
|
+
如果需要手动触发重新生成,删除 `src/_uniky/global/ky.ts` 文件后重启开发服务器。
|
|
89
89
|
|
|
90
90
|
### 配置选项
|
|
91
91
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// 该插件用于作为 vite.config.ts 中 作为插件;
|
|
2
|
-
// 该插件用于收集 src/
|
|
2
|
+
// 该插件用于收集 src/_uniky/global文件夹下的ts文件 所有export 导出的内容, 并将其合并为一个全局定义文件 src/_uniky/global.d.ts 文件 同时,生成一个 /src/_uniky/global.install.ts 文件.
|
|
3
3
|
// 以便在项目中全局使用这些类型定义,避免了手动维护全局类型定义文件的麻烦。
|
|
4
4
|
|
|
5
5
|
import type { Plugin } from 'vite';
|
|
@@ -14,9 +14,9 @@ interface ExportInfo {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export default function globalDefinedPlugin(): Plugin {
|
|
17
|
-
const globalDir = 'src/
|
|
18
|
-
const globalDtsPath = 'src/
|
|
19
|
-
const installTsPath = 'src/
|
|
17
|
+
const globalDir = 'src/_uniky/global';
|
|
18
|
+
const globalDtsPath = 'src/_uniky/global.d.ts';
|
|
19
|
+
const installTsPath = 'src/_uniky/global.install.ts';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* 递归获取目录下所有 .ts 文件(排除 .d.ts 和 install.ts)
|
|
@@ -158,7 +158,7 @@ export default function globalDefinedPlugin(): Plugin {
|
|
|
158
158
|
|
|
159
159
|
// 按文件分组导出
|
|
160
160
|
for (const exp of allExports) {
|
|
161
|
-
const relativePath = path.relative('src/
|
|
161
|
+
const relativePath = path.relative('src/_uniky', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '');
|
|
162
162
|
if (!imports.has(relativePath)) {
|
|
163
163
|
imports.set(relativePath, new Set());
|
|
164
164
|
}
|
|
@@ -187,11 +187,11 @@ export default function globalDefinedPlugin(): Plugin {
|
|
|
187
187
|
if (globalItems.length > 0) {
|
|
188
188
|
for (const exp of globalItems) {
|
|
189
189
|
if (exp.type === 'function') {
|
|
190
|
-
content += ` const ${exp.name}: typeof import('./${path.relative('src/
|
|
190
|
+
content += ` const ${exp.name}: typeof import('./${path.relative('src/_uniky', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '')}').${exp.name};\n`;
|
|
191
191
|
} else if (exp.type === 'const') {
|
|
192
|
-
content += ` const ${exp.name}: typeof import('./${path.relative('src/
|
|
192
|
+
content += ` const ${exp.name}: typeof import('./${path.relative('src/_uniky', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '')}').${exp.name};\n`;
|
|
193
193
|
} else if (exp.type === 'class') {
|
|
194
|
-
content += ` const ${exp.name}: typeof import('./${path.relative('src/
|
|
194
|
+
content += ` const ${exp.name}: typeof import('./${path.relative('src/_uniky', exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '')}').${exp.name};\n`;
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
}
|
|
@@ -210,7 +210,7 @@ export default function globalDefinedPlugin(): Plugin {
|
|
|
210
210
|
|
|
211
211
|
// 按文件分组导出
|
|
212
212
|
for (const exp of allExports) {
|
|
213
|
-
const relativePath = './global/' + path.relative(path.join('src', '
|
|
213
|
+
const relativePath = './global/' + path.relative(path.join('src', '_uniky', 'global'), exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, '');
|
|
214
214
|
if (!imports.has(relativePath)) {
|
|
215
215
|
imports.set(relativePath, { names: new Set(), hasDefault: false });
|
|
216
216
|
}
|
|
@@ -247,7 +247,7 @@ export default function globalDefinedPlugin(): Plugin {
|
|
|
247
247
|
// 将导出的内容挂载到 globalThis
|
|
248
248
|
const globalItems = allExports.filter(exp => exp.type !== 'interface' && exp.type !== 'type');
|
|
249
249
|
for (const exp of globalItems) {
|
|
250
|
-
const name = exp.isDefault ? (imports.get('./global/' + path.relative(path.join('src', '
|
|
250
|
+
const name = exp.isDefault ? (imports.get('./global/' + path.relative(path.join('src', '_uniky', 'global'), exp.filePath).replace(/\\/g, '/').replace(/\.ts$/, ''))?.defaultName || exp.name) : exp.name;
|
|
251
251
|
content += ` (globalThis as any).${exp.name} = ${name};\n`;
|
|
252
252
|
}
|
|
253
253
|
|
|
@@ -305,25 +305,25 @@ export default function globalDefinedPlugin(): Plugin {
|
|
|
305
305
|
},
|
|
306
306
|
|
|
307
307
|
configureServer(server) {
|
|
308
|
-
// 监听 src/
|
|
308
|
+
// 监听 src/_uniky/global 目录下的文件变化
|
|
309
309
|
server.watcher.add(globalDir);
|
|
310
310
|
|
|
311
311
|
server.watcher.on('change', (file) => {
|
|
312
|
-
if (file.includes('src/
|
|
312
|
+
if (file.includes('src/_uniky/global') && file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.includes('global.install.ts')) {
|
|
313
313
|
console.log(`[globalDefined] 检测到文件变化: ${file}`);
|
|
314
314
|
generate();
|
|
315
315
|
}
|
|
316
316
|
});
|
|
317
317
|
|
|
318
318
|
server.watcher.on('add', (file) => {
|
|
319
|
-
if (file.includes('src/
|
|
319
|
+
if (file.includes('src/_uniky/global') && file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.includes('global.install.ts')) {
|
|
320
320
|
console.log(`[globalDefined] 检测到新文件: ${file}`);
|
|
321
321
|
generate();
|
|
322
322
|
}
|
|
323
323
|
});
|
|
324
324
|
|
|
325
325
|
server.watcher.on('unlink', (file) => {
|
|
326
|
-
if (file.includes('src/
|
|
326
|
+
if (file.includes('src/_uniky/global') && file.endsWith('.ts') && !file.endsWith('.d.ts') && !file.includes('global.install.ts')) {
|
|
327
327
|
console.log(`[globalDefined] 检测到文件删除: ${file}`);
|
|
328
328
|
generate();
|
|
329
329
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// created by zhuxietong on 2026-01-30 23:22
|
|
2
2
|
// 该插件用于生成基础的 HTTP 请求配置
|
|
3
|
-
// 生成的代码将保存到 src/
|
|
3
|
+
// 生成的代码将保存到 src/_uniky/global/ky.ts
|
|
4
4
|
|
|
5
5
|
import type { Plugin } from 'vite';
|
|
6
6
|
import * as fs from 'node:fs';
|
|
7
7
|
import * as path from 'node:path';
|
|
8
8
|
|
|
9
9
|
export default function httpDefinedPlugin(): Plugin {
|
|
10
|
-
const outputPath = 'src/
|
|
10
|
+
const outputPath = 'src/_uniky/global/ky.ts';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* 生成基础请求配置代码
|
package/src/plugin/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// created by zhuxietong on 2026-01-30 16:37
|
|
2
2
|
import type { Plugin } from 'vite';
|
|
3
|
-
import { copyFileSync, mkdirSync, existsSync, readdirSync, statSync } from 'fs';
|
|
3
|
+
import { copyFileSync, mkdirSync, existsSync, readdirSync, statSync, writeFileSync } from 'fs';
|
|
4
4
|
import { join, dirname } from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
|
|
@@ -40,11 +40,16 @@ function ensurePluginInstalled(projectRoot: string): void {
|
|
|
40
40
|
const unikyDir = join(projectRoot, '.uniky');
|
|
41
41
|
const pluginDir = join(unikyDir, 'plugin');
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
// 检查关键文件是否存在
|
|
44
|
+
const keyFiles = ['index.ts', 'pages.defined.ts', 'global.defined.ts'];
|
|
45
|
+
const needsInstall = !existsSync(pluginDir) ||
|
|
46
|
+
keyFiles.some(file => !existsSync(join(pluginDir, file)));
|
|
47
|
+
|
|
48
|
+
if (!needsInstall) {
|
|
44
49
|
return;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
console.log('[uniky]
|
|
52
|
+
console.log('[uniky] 检测到插件文件缺失,正在自动安装...');
|
|
48
53
|
|
|
49
54
|
if (!existsSync(unikyDir)) {
|
|
50
55
|
mkdirSync(unikyDir, { recursive: true });
|
|
@@ -65,6 +70,11 @@ function ensurePluginInstalled(projectRoot: string): void {
|
|
|
65
70
|
|
|
66
71
|
const copiedCount = copyDirectoryRecursive(sourceDir, pluginDir);
|
|
67
72
|
|
|
73
|
+
const indexContent = `// created by zhuxietong on 2026-01-30 16:37
|
|
74
|
+
export * from './plugin/index.js';
|
|
75
|
+
`;
|
|
76
|
+
writeFileSync(join(unikyDir, 'index.ts'), indexContent, 'utf-8');
|
|
77
|
+
|
|
68
78
|
console.log(`[uniky] ✅ 插件文件已自动安装到 ${unikyDir} (${copiedCount} 个文件)`);
|
|
69
79
|
} catch (error) {
|
|
70
80
|
console.warn('[uniky] 插件自动安装失败:', error);
|
|
@@ -248,7 +248,7 @@ export default function pagesDefinedPlugin(): Plugin {
|
|
|
248
248
|
configResolved(config) {
|
|
249
249
|
// 确定 src 目录和输出路径
|
|
250
250
|
srcDir = path.resolve(config.root, 'src');
|
|
251
|
-
outputPath = path.resolve(srcDir, '
|
|
251
|
+
outputPath = path.resolve(srcDir, '_uniky/global/pages.ts');
|
|
252
252
|
},
|
|
253
253
|
|
|
254
254
|
buildStart() {
|