har-gen-api 0.1.3 → 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 CHANGED
@@ -1,22 +1,31 @@
1
1
  # har-gen-api
2
- > 浏览器HAR转成接口文件
2
+
3
+ > 浏览器har文件转成自定义的接口文件,通过 **vite** 启动 **mock** 服务,实现接口模拟
3
4
 
4
5
  ## 使用
5
6
 
6
- ### 全局安装
7
+ ### 安装
7
8
  ```bash
8
- npm install -g har-gen-api
9
+ npm install har-gen-api
10
+ # or
11
+ yarn add har-gen-api
9
12
  ```
10
13
 
14
+ ### 导出har文件
15
+ 1. 打开浏览器`chrome`
16
+ 2. 打开 **F12** 切换到`Network`
17
+ 3. 点击导出按钮,选择保存路径
18
+ 4. 保存 **har** 文件到 `mock/har.local` 文件夹下
19
+
11
20
  ### 命令行使用
12
21
  ```bash
13
- har-gen-api --input mock/har.local --output mock/api.local --baseURL /api --overwrite
22
+ npx har-gen-api --input mock/har.local --output mock/api.local --baseURL /api --overwrite
14
23
  ```
15
24
 
16
- ### 参数说明:
17
- * input: 输入路径,默认为 mock/har.local (default: "mock/har.local")
18
- * output: 输出路径,默认为 mock/api.local (default: "mock/api.local")
19
- * baseURL: baseURL路径 (default: "")
25
+ ### 参数说明
26
+ * input: 输入路径,默认为 `mock/har.local` (default: "mock/har.local")
27
+ * output: 输出路径,默认为 `mock/api.local` (default: "mock/api.local")
28
+ * baseURL: baseURL路径,注意 **windows** 系统需要前面多加`/`,如`//api` (default: "")
20
29
  * overwrite: 是否覆盖已存在的文件 (default: false)
21
30
 
22
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,21 +1,24 @@
1
1
  {
2
2
  "name": "har-gen-api",
3
3
  "type": "module",
4
- "version": "0.1.3",
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"
13
19
  },
14
20
  "./vite": {
15
21
  "import": "./mockServer.js"
16
- },
17
- "./vite/esm": {
18
- "import": "./mockServer.mjs"
19
22
  }
20
23
  },
21
24
  "bin": {
package/mockServer.mjs DELETED
@@ -1,78 +0,0 @@
1
- // mock/index.js
2
- const Mock = require('mockjs');
3
- const fs = require('fs');
4
- const _ = require('lodash');
5
- const JSON5 = require('json5');
6
-
7
- const mockServer = ({ mockPath = 'mock', baseURL = '', enabled = false } = {}) => {
8
- return {
9
- name: 'mock-server',
10
- configureServer(server) {
11
- if (localEnabled) {
12
- server.middlewares.use((req, res, next) => {
13
- const url = new URL(req.url, `http://${req.headers.host}`);
14
- let pathname = url.pathname;
15
-
16
- if (pathname.startsWith(baseURL)) {
17
- pathname = pathname.replace(new RegExp(`^${baseURL}`), '');
18
-
19
- // console.log('路径', pathname);
20
-
21
- // console.log(`${mockPath}${pathname}.${req.method.toLowerCase()}`)
22
-
23
- fs.readFile(`${mockPath}${pathname}.${req.method.toLowerCase()}`, (err, data) => {
24
- if (err) {
25
- next();
26
- return;
27
- }
28
-
29
- res.setHeader('X-Powered-By', 'mockjs');
30
- res.setHeader('Content-Type', 'application/json; charset=utf-8');
31
-
32
- try {
33
- data = JSON5.parse(data);
34
- const keys = Object.keys(data).filter(key => key.startsWith('?') || key === '');
35
-
36
- keys.sort((a, b) => {
37
- return a > b ? 1 : -1;
38
- });
39
-
40
- data = data[ url.search ] ?? data[ keys[0] ] ?? data;
41
-
42
- if (_.isString(data)) {
43
- // 模板解析
44
- data = _.template(data)({
45
- headers: req.headers,
46
- query: req.query,
47
- body: req.body,
48
- });
49
-
50
- data = JSON.parse(data || null);
51
- }
52
-
53
- data = Mock.mock(data);
54
-
55
- // res.send(data);
56
- res.end(JSON.stringify(data));
57
- }
58
- catch (e) {
59
- console.error(e);
60
- // res.status(500).send('Mock Error');
61
- // res.send(500, 'Mock Error');
62
- res.statusCode = 500;
63
- res.end('Mock Error');
64
- }
65
- });
66
- }
67
- else {
68
- next();
69
- }
70
- });
71
-
72
- console.log('Mock server is running...');
73
- }
74
- },
75
- };
76
- };
77
-
78
- exports.mockServer = mockServer;