har-gen-api 0.1.4 → 0.1.5
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 +5 -5
- package/index.js +104 -104
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# har-gen-api
|
|
2
2
|
|
|
3
|
-
> 浏览器har
|
|
3
|
+
> 浏览器har文件转成自定义的接口文件,通过 **vite** 启动 **mock** 服务,实现接口模拟
|
|
4
4
|
|
|
5
5
|
## 使用
|
|
6
6
|
|
|
@@ -13,19 +13,19 @@ yarn add har-gen-api
|
|
|
13
13
|
|
|
14
14
|
### 导出har文件
|
|
15
15
|
1. 打开浏览器`chrome`
|
|
16
|
-
2.
|
|
16
|
+
2. 打开 **F12** 切换到`Network`
|
|
17
17
|
3. 点击导出按钮,选择保存路径
|
|
18
|
-
4.
|
|
18
|
+
4. 保存 **har** 文件到 `mock/har.local` 文件夹下
|
|
19
19
|
|
|
20
20
|
### 命令行使用
|
|
21
21
|
```bash
|
|
22
22
|
npx har-gen-api --input mock/har.local --output mock/api.local --baseURL /api --overwrite
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
###
|
|
25
|
+
### 参数说明
|
|
26
26
|
* input: 输入路径,默认为 `mock/har.local` (default: "mock/har.local")
|
|
27
27
|
* output: 输出路径,默认为 `mock/api.local` (default: "mock/api.local")
|
|
28
|
-
* baseURL: baseURL
|
|
28
|
+
* baseURL: baseURL路径,注意 **windows** 系统需要前面多加`/`,如`//api` (default: "")
|
|
29
29
|
* overwrite: 是否覆盖已存在的文件 (default: false)
|
|
30
30
|
|
|
31
31
|
### vite配置
|
package/index.js
CHANGED
|
@@ -1,104 +1,104 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import JSON5 from 'json5';
|
|
4
|
-
import { program } from 'commander';
|
|
5
|
-
|
|
6
|
-
// 解析命令行参数
|
|
7
|
-
program
|
|
8
|
-
.option('-i, --input <path>', '输入路径,默认为 mock/har.local', 'mock/har.local')
|
|
9
|
-
.option('-o, --output <path>', '输出路径,默认为 mock/api.local', 'mock/api.local')
|
|
10
|
-
// baseURL路径
|
|
11
|
-
.option('-b, --baseURL <path>', 'baseURL路径', '')
|
|
12
|
-
.option('-w, --overwrite', '是否覆盖已存在的文件', false)
|
|
13
|
-
.parse(process.argv);
|
|
14
|
-
|
|
15
|
-
program.parse();
|
|
16
|
-
|
|
17
|
-
const { input, output, overwrite, baseURL } = program.opts();
|
|
18
|
-
const generate = () => {
|
|
19
|
-
console.log('输入路径:', input);
|
|
20
|
-
console.log('输出路径:', output);
|
|
21
|
-
console.log('baseURL路径:', baseURL);
|
|
22
|
-
console.log('是否覆盖已存在的文件:', overwrite);
|
|
23
|
-
|
|
24
|
-
let count = 0;
|
|
25
|
-
|
|
26
|
-
if (!fs.existsSync(input)) {
|
|
27
|
-
// console.error(`File not found: ${input}`);
|
|
28
|
-
console.error(`文件或目录不存在:${input}`);
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// 判断 input 是文件还是目录
|
|
33
|
-
if (fs.statSync(input).isFile()) {
|
|
34
|
-
// 如果是文件,直接处理该文件
|
|
35
|
-
if (input.endsWith('.har')) {
|
|
36
|
-
count += processHarFile(input);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
fs.readdirSync(input).forEach(file => {
|
|
41
|
-
if (file.endsWith('.har')) {
|
|
42
|
-
const filePath = path.join(input, file);
|
|
43
|
-
count += processHarFile(filePath);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
console.log('生成了', count, '条 mock 数据');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const processHarFile = (filePath) => {
|
|
52
|
-
let count = 0;
|
|
53
|
-
|
|
54
|
-
let data = fs.readFileSync(filePath, 'utf-8');
|
|
55
|
-
|
|
56
|
-
data = JSON.parse(data);
|
|
57
|
-
if (!data.log || !data.log.entries) {
|
|
58
|
-
console.error('Invalid HAR file format');
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
data.log.entries.forEach(item => {
|
|
63
|
-
// 只处理XHR请求和200响应,响应内容类型为application/json的请求
|
|
64
|
-
if (item._resourceType == 'xhr' && item.response.status == 200 && item.response.headers.some(item => item.name.toLowerCase() == 'content-type' && item.value.includes('application/json'))) {
|
|
65
|
-
const urlObj = new URL(item.request.url);
|
|
66
|
-
// console.log(url)
|
|
67
|
-
const url = urlObj.pathname.replace(baseURL, '');
|
|
68
|
-
const method = item.request.method.toLowerCase();
|
|
69
|
-
let resData = {
|
|
70
|
-
[urlObj.search]: item.response.content.text
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const filePath = path.join(output, `${url}.${method}`);
|
|
74
|
-
|
|
75
|
-
if (fs.existsSync(filePath)) {
|
|
76
|
-
let d = fs.readFileSync(filePath, 'utf-8');
|
|
77
|
-
d = JSON5.parse(d);
|
|
78
|
-
|
|
79
|
-
if (Object.keys(d).some(key => !key.startsWith('?') && key !== '')) {
|
|
80
|
-
d = {
|
|
81
|
-
'': JSON.stringify(d)
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (!overwrite && d.hasOwnProperty(url.search)) {
|
|
86
|
-
console.log(`已存在相同的路径: ${url.pathname}${url.search}`);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
resData = Object.assign(d, resData);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
94
|
-
|
|
95
|
-
fs.writeFileSync(filePath, JSON5.stringify(resData, null, 2));
|
|
96
|
-
|
|
97
|
-
count++;
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
return count;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export { generate };
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import JSON5 from 'json5';
|
|
4
|
+
import { program } from 'commander';
|
|
5
|
+
|
|
6
|
+
// 解析命令行参数
|
|
7
|
+
program
|
|
8
|
+
.option('-i, --input <path>', '输入路径,默认为 mock/har.local', 'mock/har.local')
|
|
9
|
+
.option('-o, --output <path>', '输出路径,默认为 mock/api.local', 'mock/api.local')
|
|
10
|
+
// baseURL路径
|
|
11
|
+
.option('-b, --baseURL <path>', 'baseURL路径', '')
|
|
12
|
+
.option('-w, --overwrite', '是否覆盖已存在的文件', false)
|
|
13
|
+
.parse(process.argv);
|
|
14
|
+
|
|
15
|
+
program.parse();
|
|
16
|
+
|
|
17
|
+
const { input, output, overwrite, baseURL } = program.opts();
|
|
18
|
+
const generate = () => {
|
|
19
|
+
console.log('输入路径:', input);
|
|
20
|
+
console.log('输出路径:', output);
|
|
21
|
+
console.log('baseURL路径:', baseURL);
|
|
22
|
+
console.log('是否覆盖已存在的文件:', overwrite);
|
|
23
|
+
|
|
24
|
+
let count = 0;
|
|
25
|
+
|
|
26
|
+
if (!fs.existsSync(input)) {
|
|
27
|
+
// console.error(`File not found: ${input}`);
|
|
28
|
+
console.error(`文件或目录不存在:${input}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 判断 input 是文件还是目录
|
|
33
|
+
if (fs.statSync(input).isFile()) {
|
|
34
|
+
// 如果是文件,直接处理该文件
|
|
35
|
+
if (input.endsWith('.har')) {
|
|
36
|
+
count += processHarFile(input);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
fs.readdirSync(input).forEach(file => {
|
|
41
|
+
if (file.endsWith('.har')) {
|
|
42
|
+
const filePath = path.join(input, file);
|
|
43
|
+
count += processHarFile(filePath);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log('生成了', count, '条 mock 数据');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const processHarFile = (filePath) => {
|
|
52
|
+
let count = 0;
|
|
53
|
+
|
|
54
|
+
let data = fs.readFileSync(filePath, 'utf-8');
|
|
55
|
+
|
|
56
|
+
data = JSON.parse(data);
|
|
57
|
+
if (!data.log || !data.log.entries) {
|
|
58
|
+
console.error('Invalid HAR file format');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
data.log.entries.forEach(item => {
|
|
63
|
+
// 只处理XHR请求和200响应,响应内容类型为application/json的请求
|
|
64
|
+
if (item._resourceType == 'xhr' && item.response.status == 200 && item.response.headers.some(item => item.name.toLowerCase() == 'content-type' && item.value.includes('application/json'))) {
|
|
65
|
+
const urlObj = new URL(item.request.url);
|
|
66
|
+
// console.log(url)
|
|
67
|
+
const url = urlObj.pathname.replace(baseURL, '');
|
|
68
|
+
const method = item.request.method.toLowerCase();
|
|
69
|
+
let resData = {
|
|
70
|
+
[urlObj.search]: item.response.content.text
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const filePath = path.join(output, `${url}.${method}`);
|
|
74
|
+
|
|
75
|
+
if (fs.existsSync(filePath)) {
|
|
76
|
+
let d = fs.readFileSync(filePath, 'utf-8');
|
|
77
|
+
d = JSON5.parse(d);
|
|
78
|
+
|
|
79
|
+
if (Object.keys(d).some(key => !key.startsWith('?') && key !== '')) {
|
|
80
|
+
d = {
|
|
81
|
+
'': JSON.stringify(d)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!overwrite && d.hasOwnProperty(url.search)) {
|
|
86
|
+
console.log(`已存在相同的路径: ${url.pathname}${url.search}`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
resData = Object.assign(d, resData);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
94
|
+
|
|
95
|
+
fs.writeFileSync(filePath, JSON5.stringify(resData, null, 2));
|
|
96
|
+
|
|
97
|
+
count++;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return count;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { generate };
|
package/package.json
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "har-gen-api",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/lemonppai/har-gen-api.git"
|
|
9
9
|
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"har",
|
|
12
|
+
"mock",
|
|
13
|
+
"api",
|
|
14
|
+
"vite"
|
|
15
|
+
],
|
|
10
16
|
"exports": {
|
|
11
17
|
".": {
|
|
12
18
|
"import": "./index.js"
|