@karry.sun/yapi-gen 0.2.0 → 0.2.2
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 +95 -51
- package/bin/yapi-gen.js +3 -2
- package/dist/config/schema.d.ts +4 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/gen-api-cli.d.ts +32 -0
- package/dist/gen-api-cli.d.ts.map +1 -0
- package/dist/gen-api-cli.js +245 -0
- package/dist/run.d.ts +1 -0
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +72 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# yapi-gen
|
|
2
2
|
|
|
3
|
-
基于 [yapi-to-typescript](https://github.com/fjc0k/yapi-to-typescript) 的 YApi
|
|
3
|
+
基于 [yapi-to-typescript](https://github.com/fjc0k/yapi-to-typescript) 的 YApi 接口代码生成 CLI,支持可配置的请求适配器、目录映射与按需生成。适用于 Vite、Nuxt、Vue 等不同请求封装。
|
|
4
|
+
|
|
5
|
+
---
|
|
4
6
|
|
|
5
7
|
## 安装
|
|
6
8
|
|
|
@@ -10,70 +12,112 @@ pnpm add -D @karry.sun/yapi-gen
|
|
|
10
12
|
|
|
11
13
|
本包已内置 yapi-to-typescript,无需单独安装。
|
|
12
14
|
|
|
15
|
+
---
|
|
16
|
+
|
|
13
17
|
## 快速开始
|
|
14
18
|
|
|
15
|
-
1.
|
|
16
|
-
```bash
|
|
17
|
-
pnpm add -D @karry.sun/yapi-gen
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
2. **生成配置文件**(若还没有 `yapi-gen.config.ts`)
|
|
21
|
-
```bash
|
|
22
|
-
pnpm yapi-gen init
|
|
23
|
-
```
|
|
24
|
-
会生成 `yapi-gen.config.ts`,用编辑器打开,按需修改:
|
|
25
|
-
- `serverUrl`:YApi 服务器地址
|
|
26
|
-
- `projects[0].token`:YApi 项目 token(建议用 `process.env.YAPI_TOKEN`)
|
|
27
|
-
- `requestAdapter`:`'axios'`(Vue/defHttp)或 `'nuxt-bbm'`(Nuxt),或 `'custom'` 并填写 `requestFunctionFilePath`
|
|
28
|
-
- `outputFilePath`:生成文件的目录规则(默认按分类生成到 `src/yapi/cat_xxx/index.ts`)
|
|
29
|
-
|
|
30
|
-
3. **生成接口代码**
|
|
31
|
-
```bash
|
|
32
|
-
pnpm yapi-gen
|
|
33
|
-
```
|
|
34
|
-
或在 `package.json` 的 `scripts` 里加 `"gen:api": "yapi-gen"`,然后执行:
|
|
35
|
-
```bash
|
|
36
|
-
pnpm gen:api
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
4. **在业务代码中引用**
|
|
40
|
-
生成的文件在 `outputFilePath` 配置的路径下,按分类或单文件导出请求函数与类型,直接从对应路径 import 使用即可。
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
5. 选择请求适配方式
|
|
44
|
-
|
|
45
|
-
- **内置预设(推荐)**:在配置中设置 `requestAdapter: 'axios'` 或 `requestAdapter: 'nuxt-bbm'`,无需在各仓库维护 `request.ts`,运行 `yapi-gen` 时会自动生成并写入 `src/yapi/request.ts`(路径可配)。
|
|
46
|
-
- **axios**:适用于封装了 axios 的项目(如 defHttp)。可选 `requestAdapter: { type: 'axios', axiosInstancePath: '/@/utils/http/axios' }` 指定实例路径,默认 `'/@/utils/http/axios'`(defHttp 常见路径)。
|
|
47
|
-
- **nuxt-bbm**:适用于 Nuxt 项目,使用 Layer 的 `#imports` 或 `@bitunix/bbm` 的 request。可选 `requestAdapter: { type: 'nuxt-bbm', requestImportPath: '#imports' }`,默认 `'#imports'`。
|
|
48
|
-
- **自定义**:设置 `requestAdapter: 'custom'` 并配置 `requestFunctionFilePath`,在对应文件中自行实现适配逻辑;或参考包内 `templates/request-*.ts` 复制后修改。
|
|
19
|
+
### 1. 初始化
|
|
49
20
|
|
|
50
|
-
|
|
21
|
+
```bash
|
|
22
|
+
pnpm yapi-gen init
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
会生成:
|
|
26
|
+
|
|
27
|
+
- `yapi-gen.config.ts`:主配置(serverUrl、token、requestAdapter 等)
|
|
28
|
+
- `src/yapi/gen-api-mapping.json`:分类→目录名映射(可手动维护)
|
|
29
|
+
|
|
30
|
+
### 2. 修改配置
|
|
31
|
+
|
|
32
|
+
编辑 `yapi-gen.config.ts`,至少修改:
|
|
33
|
+
|
|
34
|
+
- `serverUrl`:YApi 服务器地址
|
|
35
|
+
- `projects[0].token`:项目 token(建议用 `process.env.YAPI_TOKEN`)
|
|
36
|
+
|
|
37
|
+
### 3. 生成接口
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pnpm yapi-gen
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
或在 `package.json` 中配置 `"gen:api": "yapi-gen"`,然后执行 `pnpm gen:api`。
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 请求适配方式
|
|
48
|
+
|
|
49
|
+
| 方式 | 说明 |
|
|
50
|
+
|------|------|
|
|
51
|
+
| `'axios'` | 封装 axios/defHttp 的项目,自动生成 `src/yapi/request.ts` |
|
|
52
|
+
| `'nuxt-bbm'` | Nuxt 项目,使用 `#imports` 或 `@bitunix/bbm` |
|
|
53
|
+
| `'custom'` | 自定义,需配置 `requestFunctionFilePath` 指向项目内 request 文件 |
|
|
51
54
|
|
|
52
|
-
|
|
55
|
+
**axios 示例**:`requestAdapter: { type: 'axios', axiosInstancePath: '/@/utils/http/axios' }`
|
|
56
|
+
|
|
57
|
+
**nuxt-bbm 示例**:`requestAdapter: { type: 'nuxt-bbm', requestImportPath: '#imports' }`
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 目录映射与按需生成
|
|
62
|
+
|
|
63
|
+
### 命令用法
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# 全量生成
|
|
67
|
+
pnpm yapi-gen
|
|
68
|
+
|
|
69
|
+
# 按分类生成
|
|
70
|
+
pnpm yapi-gen cat_401
|
|
71
|
+
pnpm yapi-gen cat_401=financialReconciliation # 指定目录名并写入映射
|
|
72
|
+
|
|
73
|
+
# 批量映射
|
|
74
|
+
pnpm yapi-gen --map cat_401=financialReconciliation,cat_413=specialAccount
|
|
75
|
+
|
|
76
|
+
# 按接口生成(合并模式)
|
|
77
|
+
pnpm yapi-gen 2116
|
|
78
|
+
pnpm yapi-gen 2116 --map cat_413=specialAccount
|
|
79
|
+
|
|
80
|
+
# 自定义路径
|
|
81
|
+
pnpm yapi-gen --output-dir src/yapi --mapping-file src/yapi/gen-api-mapping.json
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 映射文件
|
|
85
|
+
|
|
86
|
+
- **路径**:`src/yapi/gen-api-mapping.json`(默认)
|
|
87
|
+
- **格式**:`{ "cat_401": "financialReconciliation", "cat_413": "specialAccount" }`
|
|
88
|
+
- **优先级**:命令行 > 配置文件 > 默认 `cat_xxx`
|
|
89
|
+
- **映射变更时**:旧目录会自动重命名为新目录名
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
// src/yapi/gen-api-mapping.json(由业务维护)
|
|
93
|
+
{
|
|
94
|
+
"cat_401": "publicCategory",
|
|
95
|
+
"cat_413": "specialAccountAsset"
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 配置说明
|
|
53
102
|
|
|
54
103
|
| 字段 | 说明 | 必填 |
|
|
55
104
|
|------|------|------|
|
|
56
105
|
| `serverUrl` | YApi 服务器地址 | 是 |
|
|
57
|
-
| `serverType` | `'yapi'` \| `'swagger'` |
|
|
58
|
-
| `requestAdapter` |
|
|
59
|
-
| `requestFunctionFilePath` |
|
|
60
|
-
| `outputFilePath` | 生成文件路径或函数
|
|
61
|
-
| `projects` |
|
|
62
|
-
| `dataKey` | 业务数据字段,如 `'result'
|
|
63
|
-
| `prodEnvName` / `devEnvName` | 生产/测试环境名称(用于域名) | 否 |
|
|
64
|
-
| `typesOnly` | 是否只生成类型 | 否,默认 `false` |
|
|
65
|
-
| `target` | `'typescript'` \| `'javascript'` | 否,默认 `'typescript'` |
|
|
66
|
-
| `reactHooks` | React Hooks 生成配置 | 否 |
|
|
106
|
+
| `serverType` | `'yapi'` \| `'swagger'` | 否 |
|
|
107
|
+
| `requestAdapter` | `'axios'` / `'nuxt-bbm'` / `'custom'` | 否 |
|
|
108
|
+
| `requestFunctionFilePath` | 自定义 request 文件路径 | custom 时必填 |
|
|
109
|
+
| `outputFilePath` | 生成文件路径或函数 | 是 |
|
|
110
|
+
| `projects` | 项目列表(token、categories) | 是 |
|
|
111
|
+
| `dataKey` | 业务数据字段,如 `'result'` | 否 |
|
|
67
112
|
| `preproccessInterface` | 预处理/过滤接口 | 否 |
|
|
68
|
-
| `getRequestFunctionName` | 请求函数命名 | 否 |
|
|
69
113
|
|
|
70
|
-
|
|
114
|
+
---
|
|
71
115
|
|
|
72
116
|
## 配置文件查找顺序
|
|
73
117
|
|
|
74
|
-
|
|
118
|
+
`yapi-gen.config.ts`、`yapi-gen.config.mts`、`yapi-gen.config.cts`、`yapi-gen.config.js`、`yapi-gen.config.mjs`、`yapi-gen.config.cjs`、`.yapi-genrc.ts`、`.yapi-genrc.mts`、`.yapi-genrc.js`、`.yapi-genrc.mjs`
|
|
75
119
|
|
|
76
|
-
|
|
120
|
+
---
|
|
77
121
|
|
|
78
122
|
## License
|
|
79
123
|
|
package/bin/yapi-gen.js
CHANGED
|
@@ -9,6 +9,7 @@ const runPath = join(__dirname, '..', 'dist', 'run.js');
|
|
|
9
9
|
const runUrl = pathToFileURL(runPath).href;
|
|
10
10
|
|
|
11
11
|
const { run } = await import(runUrl);
|
|
12
|
-
const
|
|
13
|
-
const
|
|
12
|
+
const argv = process.argv.slice(2);
|
|
13
|
+
const init = argv.includes('init');
|
|
14
|
+
const code = run({ cwd: process.cwd(), init, argv });
|
|
14
15
|
process.exit(code);
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -50,6 +50,10 @@ export interface YapiGenUserConfig {
|
|
|
50
50
|
devEnvName?: string;
|
|
51
51
|
/** 业务数据字段,如 'result' / 'data',请求函数需据此解包 */
|
|
52
52
|
dataKey?: string | string[];
|
|
53
|
+
/** 生成文件输出根目录,用于目录映射与合并模式,默认 'src/yapi' */
|
|
54
|
+
outputDir?: string;
|
|
55
|
+
/** 分类->目录名映射文件路径,默认 '{outputDir}/gen-api-mapping.json',可被业务维护 */
|
|
56
|
+
categoryMappingPath?: string;
|
|
53
57
|
/**
|
|
54
58
|
* 请求适配方式(与 requestFunctionFilePath 二选一):
|
|
55
59
|
* - 'axios':封装 axios/defHttp,可选 axiosInstancePath
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gen-api CLI 参数解析与目录映射逻辑
|
|
3
|
+
* 对应 web-finance-admin scripts/gen-api.mjs 的能力
|
|
4
|
+
*/
|
|
5
|
+
export interface GenApiArgs {
|
|
6
|
+
interfaceIds: string[];
|
|
7
|
+
categoryIds: string[];
|
|
8
|
+
manualMapping: Record<string, string>;
|
|
9
|
+
outputDir: string;
|
|
10
|
+
mappingFilePath: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 解析命令行参数
|
|
14
|
+
* 用法:
|
|
15
|
+
* yapi-gen # 全量
|
|
16
|
+
* yapi-gen 2116 # 仅接口 2116(合并模式)
|
|
17
|
+
* yapi-gen cat_401 # 仅分类 401
|
|
18
|
+
* yapi-gen cat_401=financialReconciliation
|
|
19
|
+
* yapi-gen --map cat_401=financialReconciliation,cat_413=specialAccount
|
|
20
|
+
* yapi-gen --output-dir src/yapi --mapping-file src/yapi/gen-api-mapping.json
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseArgs(argv: string[] | undefined, cwd: string): GenApiArgs;
|
|
23
|
+
export declare function loadMapping(mappingPath: string): Record<string, string>;
|
|
24
|
+
export declare function saveMapping(mappingPath: string, mapping: Record<string, string>): void;
|
|
25
|
+
export declare function getDirName(catId: string, fileMapping: Record<string, string>, manualMapping: Record<string, string>): string;
|
|
26
|
+
/** 映射变更时重命名目录 */
|
|
27
|
+
export declare function renameDirsOnMappingChange(yapiDir: string, fileMapping: Record<string, string>, mergedMapping: Record<string, string>): void;
|
|
28
|
+
/** 转为 ytt 需要的格式:数字 key */
|
|
29
|
+
export declare function mappingForYtt(m: Record<string, string>): Record<string, string>;
|
|
30
|
+
/** 接口模式:将 .temp 下的单接口文件合并到分类文件中 */
|
|
31
|
+
export declare function mergeTempToTarget(yapiDir: string, tempDir: string, interfaceIds: string[], fileMapping: Record<string, string>, manualMapping: Record<string, string>, tempFilePattern?: RegExp): void;
|
|
32
|
+
//# sourceMappingURL=gen-api-cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gen-api-cli.d.ts","sourceRoot":"","sources":["../src/gen-api-cli.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAKD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,YAAwB,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CA2CzF;AAED,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAevE;AAED,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAItF;AAMD,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,MAAM,CAKR;AAED,iBAAiB;AACjB,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,IAAI,CAoBN;AAED,0BAA0B;AAC1B,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO/E;AA4ED,mCAAmC;AACnC,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EAAE,EACtB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,eAAe,GAAE,MAA0B,GAC1C,IAAI,CAuDN"}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gen-api CLI 参数解析与目录映射逻辑
|
|
3
|
+
* 对应 web-finance-admin scripts/gen-api.mjs 的能力
|
|
4
|
+
*/
|
|
5
|
+
import { readdirSync, readFileSync, writeFileSync, rmSync, existsSync, mkdirSync, renameSync, } from 'fs';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
const DEFAULT_OUTPUT_DIR = 'src/yapi';
|
|
8
|
+
const DEFAULT_MAPPING_FILENAME = 'gen-api-mapping.json';
|
|
9
|
+
/**
|
|
10
|
+
* 解析命令行参数
|
|
11
|
+
* 用法:
|
|
12
|
+
* yapi-gen # 全量
|
|
13
|
+
* yapi-gen 2116 # 仅接口 2116(合并模式)
|
|
14
|
+
* yapi-gen cat_401 # 仅分类 401
|
|
15
|
+
* yapi-gen cat_401=financialReconciliation
|
|
16
|
+
* yapi-gen --map cat_401=financialReconciliation,cat_413=specialAccount
|
|
17
|
+
* yapi-gen --output-dir src/yapi --mapping-file src/yapi/gen-api-mapping.json
|
|
18
|
+
*/
|
|
19
|
+
export function parseArgs(argv = process.argv.slice(2), cwd) {
|
|
20
|
+
const interfaceIds = [];
|
|
21
|
+
const categoryIds = [];
|
|
22
|
+
const manualMapping = {};
|
|
23
|
+
let outputDir = DEFAULT_OUTPUT_DIR;
|
|
24
|
+
let mappingFilePath = '';
|
|
25
|
+
for (let i = 0; i < argv.length; i++) {
|
|
26
|
+
const arg = argv[i];
|
|
27
|
+
if (arg === '--ids' && argv[i + 1]) {
|
|
28
|
+
interfaceIds.push(...argv[i + 1].split(',').map((s) => s.trim()));
|
|
29
|
+
i++;
|
|
30
|
+
}
|
|
31
|
+
else if (arg === '--map' && argv[i + 1]) {
|
|
32
|
+
for (const pair of argv[i + 1].split(',')) {
|
|
33
|
+
const [key, val] = pair.split('=').map((s) => s.trim());
|
|
34
|
+
if (key && val) {
|
|
35
|
+
const catKey = /^\d+$/.test(key) ? `cat_${key}` : key;
|
|
36
|
+
manualMapping[catKey] = val;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
i++;
|
|
40
|
+
}
|
|
41
|
+
else if (arg === '--output-dir' && argv[i + 1]) {
|
|
42
|
+
outputDir = argv[i + 1].trim();
|
|
43
|
+
i++;
|
|
44
|
+
}
|
|
45
|
+
else if (arg === '--mapping-file' && argv[i + 1]) {
|
|
46
|
+
mappingFilePath = argv[i + 1].trim();
|
|
47
|
+
i++;
|
|
48
|
+
}
|
|
49
|
+
else if (arg?.startsWith('cat_')) {
|
|
50
|
+
const parts = arg.split('=');
|
|
51
|
+
const catPart = parts[0].replace(/^cat_/, '');
|
|
52
|
+
categoryIds.push(catPart);
|
|
53
|
+
if (parts[1])
|
|
54
|
+
manualMapping[parts[0].trim()] = parts[1].trim();
|
|
55
|
+
}
|
|
56
|
+
else if (/^\d+$/.test(arg)) {
|
|
57
|
+
interfaceIds.push(arg);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!mappingFilePath) {
|
|
61
|
+
mappingFilePath = join(outputDir, DEFAULT_MAPPING_FILENAME);
|
|
62
|
+
}
|
|
63
|
+
mappingFilePath = join(cwd, mappingFilePath);
|
|
64
|
+
return { interfaceIds, categoryIds, manualMapping, outputDir, mappingFilePath };
|
|
65
|
+
}
|
|
66
|
+
export function loadMapping(mappingPath) {
|
|
67
|
+
try {
|
|
68
|
+
const content = readFileSync(mappingPath, 'utf-8');
|
|
69
|
+
const raw = JSON.parse(content);
|
|
70
|
+
const normalized = {};
|
|
71
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
72
|
+
if (k && v) {
|
|
73
|
+
const key = /^\d+$/.test(k) ? `cat_${k}` : k;
|
|
74
|
+
normalized[key] = String(v);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return normalized;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return {};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function saveMapping(mappingPath, mapping) {
|
|
84
|
+
const dir = join(mappingPath, '..');
|
|
85
|
+
mkdirSync(dir, { recursive: true });
|
|
86
|
+
writeFileSync(mappingPath, JSON.stringify(mapping, null, 2) + '\n', 'utf-8');
|
|
87
|
+
}
|
|
88
|
+
function toCatKey(catId) {
|
|
89
|
+
return catId.startsWith('cat_') ? catId : `cat_${catId}`;
|
|
90
|
+
}
|
|
91
|
+
export function getDirName(catId, fileMapping, manualMapping) {
|
|
92
|
+
const key = toCatKey(catId);
|
|
93
|
+
if (manualMapping[key])
|
|
94
|
+
return manualMapping[key];
|
|
95
|
+
if (fileMapping[key])
|
|
96
|
+
return fileMapping[key];
|
|
97
|
+
return `cat_${catId}`;
|
|
98
|
+
}
|
|
99
|
+
/** 映射变更时重命名目录 */
|
|
100
|
+
export function renameDirsOnMappingChange(yapiDir, fileMapping, mergedMapping) {
|
|
101
|
+
for (const catKey of Object.keys(mergedMapping)) {
|
|
102
|
+
const oldDirName = fileMapping[catKey];
|
|
103
|
+
const newDirName = mergedMapping[catKey];
|
|
104
|
+
if (!oldDirName || !newDirName || oldDirName === newDirName)
|
|
105
|
+
continue;
|
|
106
|
+
const oldPath = join(yapiDir, oldDirName);
|
|
107
|
+
const newPath = join(yapiDir, newDirName);
|
|
108
|
+
if (!existsSync(oldPath))
|
|
109
|
+
continue;
|
|
110
|
+
try {
|
|
111
|
+
if (existsSync(newPath)) {
|
|
112
|
+
rmSync(newPath, { recursive: true });
|
|
113
|
+
}
|
|
114
|
+
renameSync(oldPath, newPath);
|
|
115
|
+
console.log(`[yapi-gen] 已重命名目录: ${oldDirName} -> ${newDirName}`);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
console.warn(`[yapi-gen] 重命名 ${oldDirName} -> ${newDirName} 失败:`, err?.message);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** 转为 ytt 需要的格式:数字 key */
|
|
123
|
+
export function mappingForYtt(m) {
|
|
124
|
+
const out = {};
|
|
125
|
+
for (const [k, v] of Object.entries(m)) {
|
|
126
|
+
const num = k.replace(/^cat_/, '');
|
|
127
|
+
if (/^\d+$/.test(num))
|
|
128
|
+
out[num] = v;
|
|
129
|
+
}
|
|
130
|
+
return out;
|
|
131
|
+
}
|
|
132
|
+
function extractCatId(content) {
|
|
133
|
+
const m = content.match(/interface\/api\/cat_(\d+)/);
|
|
134
|
+
return m ? m[1] : null;
|
|
135
|
+
}
|
|
136
|
+
function extractInterfaceBlock(content, interfaceId) {
|
|
137
|
+
const idStr = String(interfaceId);
|
|
138
|
+
const idRegex = new RegExp(`interface/api/${idStr}\\b`);
|
|
139
|
+
const nextInterfaceRegex = new RegExp(`interface/api/(?!${idStr}\\b)\\d+`);
|
|
140
|
+
const lines = content.split('\n');
|
|
141
|
+
let startIdx = -1;
|
|
142
|
+
let endIdx = -1;
|
|
143
|
+
for (let i = 0; i < lines.length; i++) {
|
|
144
|
+
if (idRegex.test(lines[i]) && startIdx === -1)
|
|
145
|
+
startIdx = i;
|
|
146
|
+
if (startIdx >= 0 && endIdx === -1 && i > startIdx && nextInterfaceRegex.test(lines[i])) {
|
|
147
|
+
endIdx = i;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (startIdx === -1)
|
|
152
|
+
return null;
|
|
153
|
+
if (endIdx === -1)
|
|
154
|
+
endIdx = lines.length;
|
|
155
|
+
return lines.slice(startIdx, endIdx).join('\n').trim();
|
|
156
|
+
}
|
|
157
|
+
function replaceInterfaceBlock(targetContent, interfaceId, newBlock) {
|
|
158
|
+
const idStr = String(interfaceId);
|
|
159
|
+
const idRegex = new RegExp(`interface/api/${idStr}\\b`);
|
|
160
|
+
const nextInterfaceRegex = new RegExp(`interface/api/(?!${idStr}\\b)\\d+`);
|
|
161
|
+
const lines = targetContent.split('\n');
|
|
162
|
+
let startIdx = -1;
|
|
163
|
+
let endIdx = -1;
|
|
164
|
+
for (let i = 0; i < lines.length; i++) {
|
|
165
|
+
if (idRegex.test(lines[i]) && startIdx === -1)
|
|
166
|
+
startIdx = i;
|
|
167
|
+
if (startIdx >= 0 && endIdx === -1 && i > startIdx && nextInterfaceRegex.test(lines[i])) {
|
|
168
|
+
endIdx = i;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (startIdx === -1)
|
|
173
|
+
return null;
|
|
174
|
+
if (endIdx === -1)
|
|
175
|
+
endIdx = lines.length;
|
|
176
|
+
const before = lines.slice(0, startIdx).join('\n');
|
|
177
|
+
const after = lines.slice(endIdx).join('\n');
|
|
178
|
+
return before + '\n\n' + newBlock + '\n\n' + after;
|
|
179
|
+
}
|
|
180
|
+
function replaceConstantRefs(block, targetContent) {
|
|
181
|
+
const targetMatch = targetContent && targetContent.match(/(mockUrl|devUrl|prodUrl|dataKey)_([a-zA-Z0-9_]+)/);
|
|
182
|
+
if (!targetMatch)
|
|
183
|
+
return block;
|
|
184
|
+
const targetSuffix = targetMatch[2];
|
|
185
|
+
return block.replace(/(mockUrl|devUrl|prodUrl|dataKey)_[a-zA-Z0-9_]+/g, (m) => m.replace(/_[a-zA-Z0-9_]+$/, '_' + targetSuffix));
|
|
186
|
+
}
|
|
187
|
+
function appendInterfaceBlock(targetContent, newBlock) {
|
|
188
|
+
const insertMarker = '/* prettier-ignore-end */';
|
|
189
|
+
const idx = targetContent.lastIndexOf(insertMarker);
|
|
190
|
+
if (idx >= 0) {
|
|
191
|
+
return (targetContent.slice(0, idx).trimEnd() + '\n\n' + newBlock + '\n\n' + targetContent.slice(idx));
|
|
192
|
+
}
|
|
193
|
+
return targetContent.trimEnd() + '\n\n' + newBlock + '\n';
|
|
194
|
+
}
|
|
195
|
+
/** 接口模式:将 .temp 下的单接口文件合并到分类文件中 */
|
|
196
|
+
export function mergeTempToTarget(yapiDir, tempDir, interfaceIds, fileMapping, manualMapping, tempFilePattern = /^api_(\d+)\.ts$/) {
|
|
197
|
+
if (!existsSync(tempDir))
|
|
198
|
+
return;
|
|
199
|
+
const tempFiles = readdirSync(tempDir).filter((f) => tempFilePattern.test(f));
|
|
200
|
+
for (const file of tempFiles) {
|
|
201
|
+
const match = file.match(tempFilePattern);
|
|
202
|
+
if (!match || !interfaceIds.includes(match[1]))
|
|
203
|
+
continue;
|
|
204
|
+
const interfaceId = match[1];
|
|
205
|
+
const tempPath = join(tempDir, file);
|
|
206
|
+
const tempContent = readFileSync(tempPath, 'utf-8');
|
|
207
|
+
const catId = extractCatId(tempContent);
|
|
208
|
+
if (!catId) {
|
|
209
|
+
console.warn(`[yapi-gen] 无法从 ${file} 提取分类 ID,跳过`);
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
const dirName = getDirName(catId, fileMapping, manualMapping);
|
|
213
|
+
const targetDir = join(yapiDir, dirName);
|
|
214
|
+
const targetPath = join(targetDir, 'index.ts');
|
|
215
|
+
let targetContent = existsSync(targetPath) ? readFileSync(targetPath, 'utf-8') : '';
|
|
216
|
+
let newContent;
|
|
217
|
+
if (!targetContent || targetContent.trim() === '') {
|
|
218
|
+
mkdirSync(targetDir, { recursive: true });
|
|
219
|
+
newContent = tempContent;
|
|
220
|
+
console.log(`[yapi-gen] 已新增接口 ${interfaceId} -> ${dirName}/index.ts(新建分类)`);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
let newBlock = extractInterfaceBlock(tempContent, interfaceId);
|
|
224
|
+
if (!newBlock) {
|
|
225
|
+
console.warn(`[yapi-gen] 无法从 ${file} 提取接口块,跳过`);
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
newBlock = replaceConstantRefs(newBlock, targetContent);
|
|
229
|
+
const replaced = replaceInterfaceBlock(targetContent, interfaceId, newBlock);
|
|
230
|
+
if (!replaced) {
|
|
231
|
+
newContent = appendInterfaceBlock(targetContent, newBlock);
|
|
232
|
+
console.log(`[yapi-gen] 已新增接口 ${interfaceId} -> ${dirName}/index.ts`);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
newContent = replaced;
|
|
236
|
+
console.log(`[yapi-gen] 已更新接口 ${interfaceId} -> ${dirName}/index.ts`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
writeFileSync(targetPath, newContent, 'utf-8');
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
rmSync(tempDir, { recursive: true });
|
|
243
|
+
}
|
|
244
|
+
catch (_) { }
|
|
245
|
+
}
|
package/dist/run.d.ts
CHANGED
package/dist/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAqKA,wBAAgB,GAAG,CAAC,OAAO,GAAE;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACZ,GAAG,MAAM,CAqFd"}
|
package/dist/run.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLI 执行逻辑:解析用户配置、生成 ytt 包装配置并执行 ytt
|
|
3
3
|
* 从本包依赖的 yapi-to-typescript 调用 ytt,无需使用方单独安装
|
|
4
|
+
* 支持目录映射、按接口/分类生成、合并模式(对应 web-finance-admin gen-api.mjs)
|
|
4
5
|
*/
|
|
5
6
|
import { spawnSync } from 'child_process';
|
|
6
7
|
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
@@ -8,6 +9,7 @@ import { resolve, dirname, basename, relative, join } from 'path';
|
|
|
8
9
|
import { fileURLToPath } from 'url';
|
|
9
10
|
import { createRequire } from 'module';
|
|
10
11
|
import { readFileSync } from 'fs';
|
|
12
|
+
import { parseArgs, loadMapping, saveMapping, renameDirsOnMappingChange, mappingForYtt, mergeTempToTarget, } from './gen-api-cli.js';
|
|
11
13
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
14
|
const require = createRequire(import.meta.url);
|
|
13
15
|
function getPackageName() {
|
|
@@ -68,6 +70,9 @@ export default defineConfig(resolvedList);
|
|
|
68
70
|
}
|
|
69
71
|
function runInit(cwd) {
|
|
70
72
|
const configPath = resolve(cwd, 'yapi-gen.config.ts');
|
|
73
|
+
const outputDir = 'src/yapi';
|
|
74
|
+
const mappingPath = resolve(cwd, outputDir, 'gen-api-mapping.json');
|
|
75
|
+
let createdConfig = false;
|
|
71
76
|
if (existsSync(configPath)) {
|
|
72
77
|
console.log('[yapi-gen] 已存在 yapi-gen.config.ts,跳过创建');
|
|
73
78
|
}
|
|
@@ -80,15 +85,25 @@ function runInit(cwd) {
|
|
|
80
85
|
import { defineYapiGenConfig } from '${packageName}';
|
|
81
86
|
|
|
82
87
|
export default defineYapiGenConfig({
|
|
88
|
+
// 替换为 Yapi 服务器地址
|
|
83
89
|
serverUrl: 'https://yapi.example.com',
|
|
84
90
|
serverType: 'yapi',
|
|
85
91
|
// 请求适配:'axios' | 'nuxt-bbm' | 'custom'
|
|
86
|
-
requestAdapter: 'axios',
|
|
87
92
|
// axios 时可选指定实例路径,默认 '/@/utils/http/axios'
|
|
88
93
|
// requestAdapter: { type: 'axios', axiosInstancePath: '/@/utils/http/axios' },
|
|
94
|
+
requestAdapter: 'axios',
|
|
89
95
|
outputFilePath: (interfaceInfo, changeCase) => {
|
|
96
|
+
const ids = process.env.YTT_INTERFACE_IDS;
|
|
97
|
+
if (ids) return \`src/yapi/.temp/api_\${interfaceInfo._id}.ts\`;
|
|
90
98
|
const catId = interfaceInfo.catid ?? 0;
|
|
91
|
-
|
|
99
|
+
let dirName = \`cat_\${catId}\`;
|
|
100
|
+
try {
|
|
101
|
+
const mapping = process.env.YTT_CAT_MAPPING
|
|
102
|
+
? (JSON.parse(process.env.YTT_CAT_MAPPING) as Record<string, string>)
|
|
103
|
+
: {};
|
|
104
|
+
if (mapping[String(catId)]) dirName = mapping[String(catId)];
|
|
105
|
+
} catch (_) {}
|
|
106
|
+
return \`src/yapi/\${dirName}/index.ts\`;
|
|
92
107
|
},
|
|
93
108
|
dataKey: 'result',
|
|
94
109
|
preproccessInterface(interfaceInfo) {
|
|
@@ -120,13 +135,23 @@ export default defineYapiGenConfig({
|
|
|
120
135
|
});
|
|
121
136
|
`;
|
|
122
137
|
writeFileSync(configPath, tpl, 'utf-8');
|
|
123
|
-
console.log('[yapi-gen] 已创建 yapi-gen.config.ts
|
|
138
|
+
console.log('[yapi-gen] 已创建 yapi-gen.config.ts');
|
|
139
|
+
createdConfig = true;
|
|
140
|
+
}
|
|
141
|
+
if (!existsSync(mappingPath)) {
|
|
142
|
+
mkdirSync(resolve(cwd, outputDir), { recursive: true });
|
|
143
|
+
writeFileSync(mappingPath, JSON.stringify({}, null, 2) + '\n', 'utf-8');
|
|
144
|
+
console.log('[yapi-gen] 已创建 src/yapi/gen-api-mapping.json(分类→目录名映射,可手动维护)');
|
|
145
|
+
}
|
|
146
|
+
if (createdConfig) {
|
|
147
|
+
console.log('[yapi-gen] 请修改 serverUrl、token 后执行 pnpm yapi-gen 生成接口');
|
|
124
148
|
}
|
|
125
149
|
return 0;
|
|
126
150
|
}
|
|
127
151
|
export function run(options = {}) {
|
|
128
152
|
const cwd = options.cwd ?? process.cwd();
|
|
129
|
-
|
|
153
|
+
const argv = options.argv ?? process.argv.slice(2);
|
|
154
|
+
if (options.init || argv.includes('init')) {
|
|
130
155
|
return runInit(cwd);
|
|
131
156
|
}
|
|
132
157
|
const configPath = options.configPath ?? findConfig(cwd);
|
|
@@ -135,6 +160,36 @@ export function run(options = {}) {
|
|
|
135
160
|
console.error('[yapi-gen] 或使用 init 子命令:pnpm yapi-gen init');
|
|
136
161
|
return 1;
|
|
137
162
|
}
|
|
163
|
+
// 解析 gen-api CLI 参数(目录映射、按接口/分类生成)
|
|
164
|
+
const args = parseArgs(argv, cwd);
|
|
165
|
+
const { interfaceIds, categoryIds, manualMapping, outputDir, mappingFilePath } = args;
|
|
166
|
+
const isInterfaceMode = interfaceIds.length > 0;
|
|
167
|
+
const isCategoryMode = categoryIds.length > 0;
|
|
168
|
+
if (isInterfaceMode && isCategoryMode) {
|
|
169
|
+
console.error('[yapi-gen] 接口模式与分类模式不能同时使用');
|
|
170
|
+
return 1;
|
|
171
|
+
}
|
|
172
|
+
const yapiDir = resolve(cwd, outputDir);
|
|
173
|
+
const tempDir = join(yapiDir, '.temp');
|
|
174
|
+
const fileMapping = loadMapping(mappingFilePath);
|
|
175
|
+
const mergedMapping = { ...fileMapping, ...manualMapping };
|
|
176
|
+
if (Object.keys(manualMapping).length > 0) {
|
|
177
|
+
renameDirsOnMappingChange(yapiDir, fileMapping, mergedMapping);
|
|
178
|
+
saveMapping(mappingFilePath, mergedMapping);
|
|
179
|
+
console.log('[yapi-gen] 已更新映射配置:', Object.keys(manualMapping).join(', '));
|
|
180
|
+
}
|
|
181
|
+
process.env.YTT_CAT_MAPPING = JSON.stringify(mappingForYtt(mergedMapping));
|
|
182
|
+
if (isInterfaceMode) {
|
|
183
|
+
process.env.YTT_INTERFACE_IDS = interfaceIds.join(',');
|
|
184
|
+
console.log(`[yapi-gen] 仅更新接口: ${interfaceIds.join(', ')}(合并模式,同分类其他接口保持不变)`);
|
|
185
|
+
}
|
|
186
|
+
else if (isCategoryMode) {
|
|
187
|
+
process.env.YTT_CATEGORY_IDS = categoryIds.join(',');
|
|
188
|
+
console.log(`[yapi-gen] 仅生成分类: cat_${categoryIds.join(', cat_')}`);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
console.log('[yapi-gen] 全量生成');
|
|
192
|
+
}
|
|
138
193
|
const wrapperDir = resolve(cwd, WRAPPER_DIR);
|
|
139
194
|
if (!existsSync(wrapperDir)) {
|
|
140
195
|
mkdirSync(wrapperDir, { recursive: true });
|
|
@@ -142,11 +197,22 @@ export function run(options = {}) {
|
|
|
142
197
|
const wrapperPath = resolve(wrapperDir, WRAPPER_FILENAME);
|
|
143
198
|
const content = getWrapperContent(cwd, configPath);
|
|
144
199
|
writeFileSync(wrapperPath, content, 'utf-8');
|
|
145
|
-
// 使用本包依赖的 yapi-to-typescript 的 CLI,不依赖使用方安装
|
|
146
200
|
const yttCliPath = require.resolve('yapi-to-typescript/lib/cjs/cli.js');
|
|
147
201
|
const result = spawnSync(process.execPath, [yttCliPath, '-c', wrapperPath], {
|
|
148
202
|
cwd,
|
|
149
203
|
stdio: 'inherit',
|
|
204
|
+
env: {
|
|
205
|
+
...process.env,
|
|
206
|
+
YTT_INTERFACE_IDS: process.env.YTT_INTERFACE_IDS,
|
|
207
|
+
YTT_CATEGORY_IDS: process.env.YTT_CATEGORY_IDS,
|
|
208
|
+
YTT_CAT_MAPPING: process.env.YTT_CAT_MAPPING,
|
|
209
|
+
},
|
|
150
210
|
});
|
|
151
|
-
|
|
211
|
+
if (result.status !== 0) {
|
|
212
|
+
return result.status ?? 1;
|
|
213
|
+
}
|
|
214
|
+
if (isInterfaceMode) {
|
|
215
|
+
mergeTempToTarget(yapiDir, tempDir, interfaceIds, fileMapping, manualMapping);
|
|
216
|
+
}
|
|
217
|
+
return 0;
|
|
152
218
|
}
|