uniky 1.0.18 → 1.0.20
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/package.json +1 -1
- package/scripts/postinstall.js +26 -22
- package/src/plugin/README.md +113 -0
- package/src/plugin/global.defined.ts +4 -4
- package/src/plugin/http.defined.ts +106 -0
- package/src/plugin/index.ts +8 -3
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { copyFileSync, mkdirSync, existsSync, writeFileSync } from 'fs';
|
|
2
|
+
import { copyFileSync, mkdirSync, existsSync, writeFileSync, readdirSync, statSync } from 'fs';
|
|
3
3
|
import { join, dirname } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
|
|
@@ -28,6 +28,30 @@ function findProjectRoot() {
|
|
|
28
28
|
return process.cwd();
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
function copyDirectoryRecursive(source, target) {
|
|
32
|
+
if (!existsSync(target)) {
|
|
33
|
+
mkdirSync(target, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const files = readdirSync(source);
|
|
37
|
+
let count = 0;
|
|
38
|
+
|
|
39
|
+
files.forEach(file => {
|
|
40
|
+
const sourcePath = join(source, file);
|
|
41
|
+
const targetPath = join(target, file);
|
|
42
|
+
const stat = statSync(sourcePath);
|
|
43
|
+
|
|
44
|
+
if (stat.isDirectory()) {
|
|
45
|
+
count += copyDirectoryRecursive(sourcePath, targetPath);
|
|
46
|
+
} else {
|
|
47
|
+
copyFileSync(sourcePath, targetPath);
|
|
48
|
+
count++;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return count;
|
|
53
|
+
}
|
|
54
|
+
|
|
31
55
|
function installPluginFiles() {
|
|
32
56
|
try {
|
|
33
57
|
const projectRoot = findProjectRoot();
|
|
@@ -38,28 +62,8 @@ function installPluginFiles() {
|
|
|
38
62
|
mkdirSync(unikyDir, { recursive: true });
|
|
39
63
|
}
|
|
40
64
|
|
|
41
|
-
if (!existsSync(pluginDir)) {
|
|
42
|
-
mkdirSync(pluginDir, { recursive: true });
|
|
43
|
-
}
|
|
44
|
-
|
|
45
65
|
const sourceDir = join(__dirname, '..', 'src', 'plugin');
|
|
46
|
-
const
|
|
47
|
-
'pages.defined.ts',
|
|
48
|
-
'global.defined.ts',
|
|
49
|
-
'lib.defined.ts',
|
|
50
|
-
'index.ts'
|
|
51
|
-
];
|
|
52
|
-
|
|
53
|
-
let copiedCount = 0;
|
|
54
|
-
filesToCopy.forEach(file => {
|
|
55
|
-
const sourcePath = join(sourceDir, file);
|
|
56
|
-
const targetPath = join(pluginDir, file);
|
|
57
|
-
|
|
58
|
-
if (existsSync(sourcePath)) {
|
|
59
|
-
copyFileSync(sourcePath, targetPath);
|
|
60
|
-
copiedCount++;
|
|
61
|
-
}
|
|
62
|
-
});
|
|
66
|
+
const copiedCount = copyDirectoryRecursive(sourceDir, pluginDir);
|
|
63
67
|
|
|
64
68
|
const indexContent = `// created by zhuxietong on 2026-01-30 16:37
|
|
65
69
|
export * from './plugin/index.js';
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# UniKy 插件系统
|
|
2
|
+
|
|
3
|
+
该目录包含 UniKy 框架的自动代码生成插件。
|
|
4
|
+
|
|
5
|
+
## 插件列表
|
|
6
|
+
|
|
7
|
+
### 1. global.defined.ts - 全局定义插件
|
|
8
|
+
|
|
9
|
+
自动收集 `src/_unikey/global` 文件夹下的所有导出内容,生成全局类型定义和安装文件。
|
|
10
|
+
|
|
11
|
+
### 2. pages.defined.ts - 页面路由插件
|
|
12
|
+
|
|
13
|
+
自动处理页面路由相关的代码生成。
|
|
14
|
+
|
|
15
|
+
### 3. http.defined.ts - HTTP 请求代码生成插件
|
|
16
|
+
|
|
17
|
+
基于 OpenAPI 规范自动生成类型安全的 HTTP 请求函数。
|
|
18
|
+
|
|
19
|
+
## HTTP 插件使用说明
|
|
20
|
+
|
|
21
|
+
### 工作原理
|
|
22
|
+
|
|
23
|
+
1. 插件会读取项目中的 OpenAPI 规范文件(支持多个位置)
|
|
24
|
+
2. 解析所有 API 路径和方法
|
|
25
|
+
3. 自动生成对应的请求函数
|
|
26
|
+
4. 生成的代码保存到 `src/_unikey/global/ky.ts`
|
|
27
|
+
|
|
28
|
+
### OpenAPI 文件位置
|
|
29
|
+
|
|
30
|
+
插件会按以下顺序查找 OpenAPI 规范文件:
|
|
31
|
+
|
|
32
|
+
1. `.uniky/oas/openapi.json`(推荐)
|
|
33
|
+
2. `openapi.json`
|
|
34
|
+
3. `swagger.json`
|
|
35
|
+
4. `api-docs.json`
|
|
36
|
+
|
|
37
|
+
### 生成规则
|
|
38
|
+
|
|
39
|
+
**路径命名转换:**
|
|
40
|
+
- `/api/sys.account/login` → `apiSysAccountLogin()`
|
|
41
|
+
- `/api/util.tool/upload` → `apiUtilToolUpload()`
|
|
42
|
+
|
|
43
|
+
**请求方法:**
|
|
44
|
+
- GET/DELETE 请求:`functionName(params?: any)`
|
|
45
|
+
- POST/PUT/PATCH 请求:`functionName(data?: any, params?: any)`
|
|
46
|
+
|
|
47
|
+
### 生成的代码结构
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// 1. uniKy 实例配置
|
|
51
|
+
export const _ky = uniKy.create({
|
|
52
|
+
prefixUrl: baseUrl,
|
|
53
|
+
hooks: { ... },
|
|
54
|
+
timeout: 30000
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 2. useKyData Hook
|
|
58
|
+
export function useKyData<T, O extends object = {}>(...)
|
|
59
|
+
|
|
60
|
+
// 3. API 请求函数
|
|
61
|
+
export function apiSysAccountLogin(data?: any, params?: any) {
|
|
62
|
+
return _ky.post('/api/sys.account/login', { data, params })
|
|
63
|
+
.then(res => res.data);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 使用示例
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// 直接调用
|
|
71
|
+
import { apiSysAccountLogin } from '@/_unikey/global/ky';
|
|
72
|
+
|
|
73
|
+
await apiSysAccountLogin({ username: 'admin', password: '123456' });
|
|
74
|
+
|
|
75
|
+
// 使用 Hook
|
|
76
|
+
import { useKyData, apiPitfallIndexQuery } from '@/_unikey/global/ky';
|
|
77
|
+
|
|
78
|
+
const { data, run } = useKyData(apiPitfallIndexQuery, []);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 重新生成代码
|
|
82
|
+
|
|
83
|
+
插件会在以下情况自动重新生成代码:
|
|
84
|
+
|
|
85
|
+
1. 项目启动时(如果文件不存在)
|
|
86
|
+
2. OpenAPI 规范文件发生变化时
|
|
87
|
+
|
|
88
|
+
如果需要手动触发重新生成,删除 `src/_unikey/global/ky.ts` 文件后重启开发服务器。
|
|
89
|
+
|
|
90
|
+
### 配置选项
|
|
91
|
+
|
|
92
|
+
在 `vite.config.ts` 中配置插件:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { unikyPlugin } from './.uniky/index';
|
|
96
|
+
|
|
97
|
+
export default defineConfig({
|
|
98
|
+
plugins: [
|
|
99
|
+
uni(),
|
|
100
|
+
unikyPlugin({
|
|
101
|
+
enablePages: true, // 启用页面插件
|
|
102
|
+
enableGlobal: true, // 启用全局定义插件
|
|
103
|
+
enableHttp: true // 启用 HTTP 插件(默认启用)
|
|
104
|
+
})
|
|
105
|
+
]
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 注意事项
|
|
110
|
+
|
|
111
|
+
1. **文件保护**:如果 `ky.ts` 文件已存在,插件不会覆盖,需手动删除后才会重新生成
|
|
112
|
+
2. **路径格式**:OpenAPI 中的路径需要符合 RESTful 规范
|
|
113
|
+
3. **自动导入**:生成的函数可以通过全局定义系统自动导入使用
|
|
@@ -171,11 +171,11 @@ export default function globalDefinedPlugin(): Plugin {
|
|
|
171
171
|
content += '// 请勿手动修改\n\n';
|
|
172
172
|
|
|
173
173
|
// 生成 import 语句
|
|
174
|
-
|
|
174
|
+
Array.from(imports.entries()).forEach(([filePath, names]) => {
|
|
175
175
|
if (names.size > 0) {
|
|
176
176
|
content += `import type { ${Array.from(names).join(', ')} } from './${filePath}';\n`;
|
|
177
177
|
}
|
|
178
|
-
}
|
|
178
|
+
});
|
|
179
179
|
|
|
180
180
|
content += '\n';
|
|
181
181
|
|
|
@@ -227,7 +227,7 @@ export default function globalDefinedPlugin(): Plugin {
|
|
|
227
227
|
content += '// 请勿手动修改\n\n';
|
|
228
228
|
|
|
229
229
|
// 生成 import 语句
|
|
230
|
-
|
|
230
|
+
Array.from(imports.entries()).forEach(([filePath, info]) => {
|
|
231
231
|
if (info.hasDefault && info.names.size > 0) {
|
|
232
232
|
content += `import ${info.defaultName}, { ${Array.from(info.names).join(', ')} } from '${filePath}';\n`;
|
|
233
233
|
} else if (info.hasDefault) {
|
|
@@ -235,7 +235,7 @@ export default function globalDefinedPlugin(): Plugin {
|
|
|
235
235
|
} else if (info.names.size > 0) {
|
|
236
236
|
content += `import { ${Array.from(info.names).join(', ')} } from '${filePath}';\n`;
|
|
237
237
|
}
|
|
238
|
-
}
|
|
238
|
+
});
|
|
239
239
|
|
|
240
240
|
content += '\n';
|
|
241
241
|
content += '/**\n';
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// created by zhuxietong on 2026-01-30 23:22
|
|
2
|
+
// 该插件用于生成基础的 HTTP 请求配置
|
|
3
|
+
// 生成的代码将保存到 src/_unikey/global/ky.ts
|
|
4
|
+
|
|
5
|
+
import type { Plugin } from 'vite';
|
|
6
|
+
import * as fs from 'node:fs';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
|
|
9
|
+
export default function httpDefinedPlugin(): Plugin {
|
|
10
|
+
const outputPath = 'src/_unikey/global/ky.ts';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 生成基础请求配置代码
|
|
14
|
+
*/
|
|
15
|
+
function generateCode(): string {
|
|
16
|
+
let code = `// created by zhuxietong on 2026-01-30 23:22\n`;
|
|
17
|
+
code += `import { uniKy, useMountedLoad } from "uniky";\n`;
|
|
18
|
+
code += `import { ref } from "vue";\n\n`;
|
|
19
|
+
|
|
20
|
+
code += `const baseUrl = import.meta.env.VITE_API_BASE_URL;\n\n`;
|
|
21
|
+
|
|
22
|
+
code += `export const _ky = uniKy.create({\n`;
|
|
23
|
+
code += ` prefixUrl: baseUrl,\n`;
|
|
24
|
+
code += ` hooks: {\n`;
|
|
25
|
+
code += ` beforeRequest: [\n`;
|
|
26
|
+
code += ` (request, options) => {\n`;
|
|
27
|
+
code += ` const headers = options.headers || {};\n`;
|
|
28
|
+
code += ` try {\n`;
|
|
29
|
+
code += ` const user = uni.getStorageSync('user') || '{}';\n`;
|
|
30
|
+
code += ` const { token } = JSON.parse(user);\n`;
|
|
31
|
+
code += ` if (token) {\n`;
|
|
32
|
+
code += ` headers['Authorization'] = 'Bearer ' + token;\n`;
|
|
33
|
+
code += ` }\n`;
|
|
34
|
+
code += ` options.headers = headers;\n`;
|
|
35
|
+
code += ` } catch (e) {}\n`;
|
|
36
|
+
code += ` },\n`;
|
|
37
|
+
code += ` ],\n`;
|
|
38
|
+
code += ` afterResponse: [\n`;
|
|
39
|
+
code += ` (resp: any, request, options) => {},\n`;
|
|
40
|
+
code += ` ],\n`;
|
|
41
|
+
code += ` },\n`;
|
|
42
|
+
code += ` timeout: 30000,\n`;
|
|
43
|
+
code += `});\n\n`;
|
|
44
|
+
|
|
45
|
+
code += `export function useKyData<T, O extends object = {}>(req: (option: O) => Promise<T>, defaultValue?: T) {\n`;
|
|
46
|
+
code += ` const data = ref<T | undefined>(defaultValue);\n`;
|
|
47
|
+
code += ` const option = ref<any>({});\n`;
|
|
48
|
+
code += ` const run = () => {\n`;
|
|
49
|
+
code += ` return new Promise((resolve, reject) => {\n`;
|
|
50
|
+
code += ` req(option.value)\n`;
|
|
51
|
+
code += ` .then((res: any) => {\n`;
|
|
52
|
+
code += ` data.value = res;\n`;
|
|
53
|
+
code += ` resolve(res);\n`;
|
|
54
|
+
code += ` })\n`;
|
|
55
|
+
code += ` .catch((err) => {\n`;
|
|
56
|
+
code += ` reject(err);\n`;
|
|
57
|
+
code += ` });\n`;
|
|
58
|
+
code += ` });\n`;
|
|
59
|
+
code += ` };\n\n`;
|
|
60
|
+
code += ` useMountedLoad(({ option:o, query, json }) => {\n`;
|
|
61
|
+
code += ` option.value = option;\n`;
|
|
62
|
+
code += ` run()\n`;
|
|
63
|
+
code += ` .then(() => {})\n`;
|
|
64
|
+
code += ` .catch(() => {});\n`;
|
|
65
|
+
code += ` });\n\n`;
|
|
66
|
+
code += ` return {\n`;
|
|
67
|
+
code += ` data,\n`;
|
|
68
|
+
code += ` run,\n`;
|
|
69
|
+
code += ` };\n`;
|
|
70
|
+
code += `}\n`;
|
|
71
|
+
|
|
72
|
+
return code;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 生成文件
|
|
77
|
+
*/
|
|
78
|
+
function generate() {
|
|
79
|
+
try {
|
|
80
|
+
if (fs.existsSync(outputPath)) {
|
|
81
|
+
console.log(`[httpDefined] 文件已存在,跳过生成: ${outputPath}`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const code = generateCode();
|
|
86
|
+
|
|
87
|
+
const dir = path.dirname(outputPath);
|
|
88
|
+
if (!fs.existsSync(dir)) {
|
|
89
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fs.writeFileSync(outputPath, code, 'utf-8');
|
|
93
|
+
console.log(`[httpDefined] 已生成 ${outputPath}`);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('[httpDefined] 生成失败:', error);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
name: 'vite-plugin-http-defined',
|
|
101
|
+
|
|
102
|
+
buildStart() {
|
|
103
|
+
generate();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
package/src/plugin/index.ts
CHANGED
|
@@ -3,30 +3,35 @@ import type { Plugin } from 'vite';
|
|
|
3
3
|
|
|
4
4
|
import pagesDefinedPlugin from './pages.defined';
|
|
5
5
|
import globalDefinedPlugin from './global.defined';
|
|
6
|
+
import httpDefinedPlugin from './http.defined';
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
export interface UnikyPluginOptions {
|
|
10
11
|
enablePages?: boolean;
|
|
11
12
|
enableGlobal?: boolean;
|
|
13
|
+
enableHttp?: boolean;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export function unikyPlugin(options: UnikyPluginOptions = {}): Plugin[] {
|
|
15
|
-
const { enablePages = true, enableGlobal = true } = options;
|
|
17
|
+
const { enablePages = true, enableGlobal = true, enableHttp = true } = options;
|
|
16
18
|
|
|
17
19
|
const plugins: Plugin[] = [];
|
|
18
20
|
|
|
19
21
|
if (enablePages) {
|
|
20
22
|
plugins.push(pagesDefinedPlugin());
|
|
21
23
|
}
|
|
22
|
-
|
|
24
|
+
if (enableHttp) {
|
|
25
|
+
plugins.push(httpDefinedPlugin());
|
|
26
|
+
}
|
|
23
27
|
if (enableGlobal) {
|
|
24
28
|
plugins.push(globalDefinedPlugin());
|
|
25
29
|
}
|
|
26
30
|
|
|
31
|
+
|
|
27
32
|
return plugins;
|
|
28
33
|
}
|
|
29
34
|
|
|
30
|
-
export { pagesDefinedPlugin, globalDefinedPlugin };
|
|
35
|
+
export { pagesDefinedPlugin, globalDefinedPlugin, httpDefinedPlugin };
|
|
31
36
|
|
|
32
37
|
export default unikyPlugin;
|