uniky 1.0.18 → 1.0.19

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uniky",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "description": "uni-app 开发工具库,包含 hooks、http 请求和 vite 插件",
5
5
  "type": "module",
6
6
  "main": "./src/lib/index.ts",
@@ -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
- for (const [filePath, names] of imports) {
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
- for (const [filePath, info] of imports) {
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
+ }
@@ -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;