mock-service-cli 3.6.5 → 4.0.0
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 +22 -21
- package/bin/mock-service-cli +1 -266
- package/{lib → dist}/asyncTaskQueue.js +6 -18
- package/dist/cli.js +6608 -0
- package/{lib → dist}/file-explorer.html +40 -4
- package/dist/fileExplorerServer.js +28186 -0
- package/dist/manageMockFiles.js +5020 -0
- package/dist/mockServer.js +53214 -0
- package/dist/packageInfo.js +19 -0
- package/dist/staticServer.js +26688 -0
- package/dist/utils.js +857 -0
- package/package.json +21 -17
- package/lib/fileExplorerServer.js +0 -329
- package/lib/manageMockFiles.js +0 -252
- package/lib/mockServer.js +0 -497
- package/lib/staticServer.js +0 -104
- package/lib/utils.js +0 -297
- /package/{lib → dist}/api-overview.html +0 -0
package/README.md
CHANGED
|
@@ -52,27 +52,28 @@ npx mock-service-cli [options] [path]
|
|
|
52
52
|
|
|
53
53
|
## 🛠️ 命令行选项
|
|
54
54
|
|
|
55
|
-
| 选项 | 描述
|
|
56
|
-
| -------------------------- |
|
|
57
|
-
| `-h` 或 `--help` | 显示帮助信息
|
|
58
|
-
| `-p` 或 `--port` | Mock 服务器端口
|
|
59
|
-
| `-d` | 指定 mock 目录
|
|
60
|
-
| `-f` | 指定单个 mock 文件
|
|
61
|
-
| `-s` 或 `--silent` | 抑制日志输出
|
|
62
|
-
| `-v` 或 `--version` | 显示版本信息
|
|
63
|
-
| `-S` 或 `--socket-server` | 启动 socket 服务器,用于保存 API 响应数据
|
|
64
|
-
| `-a` 或 `--api-stat` | 打印 API URL 和文件路径信息
|
|
65
|
-
| `-t` 或 `--track` | 记录操作信息到文件
|
|
66
|
-
| `-o` 或 `--cors-origin` | 配置 CORS 允许的源,多个源用逗号分隔
|
|
67
|
-
| `-O` 或 `--proxy-options` | 配置 HTTP 请求代理选项,支持 js 文件、json 文件或命令行参数
|
|
68
|
-
| `-
|
|
69
|
-
| `-
|
|
70
|
-
| `-
|
|
71
|
-
| `-
|
|
72
|
-
| `-
|
|
73
|
-
| `-
|
|
74
|
-
| `-
|
|
75
|
-
| `-
|
|
55
|
+
| 选项 | 描述 | 默认值 |
|
|
56
|
+
| -------------------------- | ----------------------------------------------------------------- | ------ |
|
|
57
|
+
| `-h` 或 `--help` | 显示帮助信息 | - |
|
|
58
|
+
| `-p` 或 `--port` | Mock 服务器端口 | 8090 |
|
|
59
|
+
| `-d` | 指定 mock 目录 | ./mock |
|
|
60
|
+
| `-f` | 指定单个 mock 文件 | - |
|
|
61
|
+
| `-s` 或 `--silent` | 抑制日志输出 | - |
|
|
62
|
+
| `-v` 或 `--version` | 显示版本信息 | - |
|
|
63
|
+
| `-S` 或 `--socket-server` | 启动 socket 服务器,用于保存 API 响应数据 | false |
|
|
64
|
+
| `-a` 或 `--api-stat` | 打印 API URL 和文件路径信息 | false |
|
|
65
|
+
| `-t` 或 `--track` | 记录操作信息到文件 | false |
|
|
66
|
+
| `-o` 或 `--cors-origin` | 配置 CORS 允许的源,多个源用逗号分隔 | \* |
|
|
67
|
+
| `-O` 或 `--proxy-options` | 配置 HTTP 请求代理选项,支持 js 文件、json 文件或命令行参数 | - |
|
|
68
|
+
| `-r` 或 `--rewrite` | rewrite http or https request url prefix of proxy, default false. | false |
|
|
69
|
+
| `-H` 或 `--cors-headers` | 配置 CORS 头信息 | \* |
|
|
70
|
+
| `-A` 或 `--append-headers` | 添加响应头信息,多个头用逗号分隔 | - |
|
|
71
|
+
| `-D` 或 `--web-dir` | 启用 Web 服务器,指定 web 目录(SPA 应用) | - |
|
|
72
|
+
| `-P` 或 `--web-port` | Web 服务器端口 | 9090 |
|
|
73
|
+
| `-b` 或 `--web-baseurl` | 指定 SPA Web 服务器的公共路径 | - |
|
|
74
|
+
| `-R` 或 `--static-server` | 启用静态服务器,指定静态资源目录 | - |
|
|
75
|
+
| `-w` 或 `--open` | 自动打开 API 概览页、文件浏览器页 | false |
|
|
76
|
+
| `-e` 或 `--explorer` | 启用文件浏览器服务器,指定要浏览的目录 | ./ |
|
|
76
77
|
|
|
77
78
|
## 📖 使用示例
|
|
78
79
|
|
package/bin/mock-service-cli
CHANGED
|
@@ -1,268 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
portfinder = require('portfinder'),
|
|
5
|
-
{ resolve } = require('path'),
|
|
6
|
-
nodemon = require('nodemon');
|
|
7
|
-
const { existsSync } = require('fs-extra');
|
|
8
|
-
const argv = require('minimist')(process.argv.slice(2));
|
|
9
|
-
const { logger } = require('../lib/utils');
|
|
10
|
-
const spawn = require('child_process').spawn;
|
|
11
|
-
const node = process.execPath;
|
|
12
|
-
|
|
13
|
-
process.title = 'mock-service-cli';
|
|
14
|
-
|
|
15
|
-
if (argv.h || argv.help) {
|
|
16
|
-
console.log(
|
|
17
|
-
[
|
|
18
|
-
'usage: mock-service-cli [options]',
|
|
19
|
-
'',
|
|
20
|
-
'PS: Mock File仅支持commonjs规范的js、cjs文件,不支持ES Module',
|
|
21
|
-
'options:',
|
|
22
|
-
' -p --port Mock server port to use. If 0, look for open port. [8090]',
|
|
23
|
-
' -d Specify mock directory, default [./mock] directory,',
|
|
24
|
-
' Also watch js files changes and support hot reload',
|
|
25
|
-
' -f --file Specify the input data source, support javascript ',
|
|
26
|
-
' The priority is over the directory watches',
|
|
27
|
-
' -s --silent Suppress log messages from output',
|
|
28
|
-
' -S --socket-server Whether start socket server or not, default false.',
|
|
29
|
-
' -a --api-stat Whether print api url and file path or not, default false.',
|
|
30
|
-
' -t --track Whether record operation info by write file, default false.',
|
|
31
|
-
' -o --cors-origin Allow origin by cors, list separated by commas, must not be * when withCredential is true',
|
|
32
|
-
' .If specified, cors-headers will be "Authorization,Content-Type,Accept,Origin,User-Agent,DNT',
|
|
33
|
-
' ,Cache-Control,X-Mx-ReqToken,X-Data-Type,X-Requested-With,X-Data-Type,X-Auth-Token,Token", default *.',
|
|
34
|
-
' -H --cors-headers When start Mock Server, optionally provide CORS headers list separated by commas. default *',
|
|
35
|
-
' -A --append-headers When start Mock/Web/Static Server, optionally add response headers list separated by commas.',
|
|
36
|
-
' For example: X-Frame-options=DENY,content-security-policy=frame-ancestors',
|
|
37
|
-
'',
|
|
38
|
-
' -O --proxy-options Optionally provide proxy options list separated by commas.',
|
|
39
|
-
' -r --rewrite rewrite http or https request url prefix of proxy, default false.',
|
|
40
|
-
'',
|
|
41
|
-
' -D --web-dir Enable web server, specify web directory, default [./dist] directory',
|
|
42
|
-
' -P --web-port Web server port to use. If 0, look for open port. [9090]',
|
|
43
|
-
' -b --web-baseurl Specify website public path when enabled web server.',
|
|
44
|
-
'',
|
|
45
|
-
' -R --static-server Specify static resource file directory when enabled static server.',
|
|
46
|
-
'',
|
|
47
|
-
' -h --help Print this list and exit.',
|
|
48
|
-
' -v --version Print the version and exit.',
|
|
49
|
-
' -w --open Open API overview page automatically, default false.',
|
|
50
|
-
' -e --explorer Enable file explorer server, specify directory to browse, default [./].'
|
|
51
|
-
].join('\n')
|
|
52
|
-
);
|
|
53
|
-
process.exit();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 保留命令行参数
|
|
57
|
-
process.env.ARGV = JSON.stringify(argv);
|
|
58
|
-
|
|
59
|
-
var port = argv.p || argv.port,
|
|
60
|
-
watchDir = argv.d,
|
|
61
|
-
specifiedFile = argv.f || argv.file,
|
|
62
|
-
version = argv.v || argv.version,
|
|
63
|
-
isStartSocketServer = argv.S || false,
|
|
64
|
-
rewrite = argv.r || argv.rewrite || false,
|
|
65
|
-
isOpenApiOverview = argv.w || argv.open || false,
|
|
66
|
-
explorerDir = argv.e || argv.explorer,
|
|
67
|
-
log = null;
|
|
68
|
-
|
|
69
|
-
if (!argv.s && !argv.silent) {
|
|
70
|
-
log = logger(false);
|
|
71
|
-
} else if (colors) {
|
|
72
|
-
process.env.SILENT = true;
|
|
73
|
-
log = logger(true);
|
|
74
|
-
}
|
|
75
|
-
// 注入环境变量
|
|
76
|
-
const injectEnvVariable = (envName, envArgs) => {
|
|
77
|
-
if (envArgs) {
|
|
78
|
-
process.env[envName] = envArgs;
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
if (isStartSocketServer) {
|
|
83
|
-
process.env.SOCKET_SERVER = true;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (isOpenApiOverview) {
|
|
87
|
-
process.env.OPEN_API_OVERVIEW = true;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (version) {
|
|
91
|
-
log.info('v' + require('../package.json').version);
|
|
92
|
-
process.exit();
|
|
93
|
-
}
|
|
94
|
-
injectEnvVariable('PREFIX_REWRITE', rewrite);
|
|
95
|
-
injectEnvVariable('CORS_ORIGIN', argv.o || argv['cors-origin']);
|
|
96
|
-
injectEnvVariable('CORS_HEADERS', argv.H || argv['cors-headers']);
|
|
97
|
-
|
|
98
|
-
injectEnvVariable('WEB_PUBLIC_PATH', argv.b || argv['web-baseurl']);
|
|
99
|
-
injectEnvVariable('STATIC_DIRECTORY', argv.R || argv['static-server']);
|
|
100
|
-
injectEnvVariable('EXPLORER_DIRECTORY', explorerDir);
|
|
101
|
-
// injectEnvVariable('PROXY_OPTIONS', argv.O || argv['proxy-options']);
|
|
102
|
-
// 解析Web代理配置项(来源js|config文件或命令行参数字符串)
|
|
103
|
-
const proxyArg = argv.O || argv['proxy-options'];
|
|
104
|
-
if (proxyArg) {
|
|
105
|
-
const proxyTable = {};
|
|
106
|
-
if (proxyArg.endsWith('.js') || proxyArg.endsWith('.json')) {
|
|
107
|
-
const proxyOptFile = resolve(process.cwd(), proxyArg);
|
|
108
|
-
if (!existsSync(proxyOptFile)) {
|
|
109
|
-
console.error(`proxy-options: 文件 ${proxyOptFile} 不存在`);
|
|
110
|
-
process.exit();
|
|
111
|
-
}
|
|
112
|
-
const proxyObj = require(proxyOptFile);
|
|
113
|
-
Object.keys(proxyObj).forEach(function (h) {
|
|
114
|
-
proxyTable[h] = proxyObj[h];
|
|
115
|
-
}, this);
|
|
116
|
-
} else {
|
|
117
|
-
try {
|
|
118
|
-
proxyArg.split(/\s*,\s*/).forEach(function (h) {
|
|
119
|
-
const [origin, target] = h.split('|');
|
|
120
|
-
proxyTable[origin] = target;
|
|
121
|
-
}, this);
|
|
122
|
-
} catch (error) {
|
|
123
|
-
console.warn(colors.yellow('\nParse web proxy options Failed:', error));
|
|
124
|
-
throw error;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
process.env.PROXY_OPTIONS = JSON.stringify(proxyTable);
|
|
128
|
-
}
|
|
129
|
-
// whether to start Web server or not
|
|
130
|
-
if (argv.D || argv['web-dir']) {
|
|
131
|
-
// 解析SPA应用参数:SPA Web目录
|
|
132
|
-
process.env.WEB_ROOT = resolve(process.cwd(), argv.D || argv['web-dir']);
|
|
133
|
-
if (!existsSync(process.env.WEB_ROOT)) {
|
|
134
|
-
console.error(`web-dir: 目录 ${process.env.WEB_ROOT} 不存在`);
|
|
135
|
-
process.exit();
|
|
136
|
-
}
|
|
137
|
-
// Web Server port
|
|
138
|
-
portfinder.basePort = argv.P || argv['web-port'] || 9090;
|
|
139
|
-
portfinder.getPort(function (err, webPort) {
|
|
140
|
-
if (err) {
|
|
141
|
-
throw err;
|
|
142
|
-
}
|
|
143
|
-
process.env.WEB_PORT = webPort;
|
|
144
|
-
// Mock Server port
|
|
145
|
-
portfinder.basePort = port || 8090;
|
|
146
|
-
portfinder.getPort(function (err, port) {
|
|
147
|
-
if (err) {
|
|
148
|
-
throw err;
|
|
149
|
-
}
|
|
150
|
-
process.env.PORT = port;
|
|
151
|
-
initServe();
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
} else {
|
|
155
|
-
// Mock Server port
|
|
156
|
-
portfinder.basePort = port || 8090;
|
|
157
|
-
portfinder.getPort(function (err, port) {
|
|
158
|
-
if (err) {
|
|
159
|
-
throw err;
|
|
160
|
-
}
|
|
161
|
-
process.env.PORT = port;
|
|
162
|
-
initServe();
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Watch change of mock files, restart serve
|
|
168
|
-
* @param watchDir
|
|
169
|
-
*/
|
|
170
|
-
function watchMockFiles(watchDir) {
|
|
171
|
-
/**
|
|
172
|
-
* script 重启的脚本
|
|
173
|
-
* ext 检测的文件
|
|
174
|
-
*/
|
|
175
|
-
nodemon({
|
|
176
|
-
script: resolve(__dirname, '../lib/mockServer.js'),
|
|
177
|
-
watch: [watchDir],
|
|
178
|
-
ext: 'cjs,js,json'
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
nodemon
|
|
182
|
-
.on('start', function () {
|
|
183
|
-
// log.info('nodemon: mockServer has started');
|
|
184
|
-
})
|
|
185
|
-
.on('quit', function () {
|
|
186
|
-
// log.info('nodemon: mockServer has quit');
|
|
187
|
-
process.exit();
|
|
188
|
-
})
|
|
189
|
-
.on('restart', function (files) {
|
|
190
|
-
process.env.RESTARTED = true;
|
|
191
|
-
log.info(
|
|
192
|
-
[colors.green('\nnodemon: mockServer restarted due to: '), files, colors.green(' have changed'), '\n'].join('')
|
|
193
|
-
);
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Node子进程启动MockServer
|
|
198
|
-
function startMockServer() {
|
|
199
|
-
spawn(node, [resolve(__dirname, '../lib/mockServer.js')], {
|
|
200
|
-
stdio: 'inherit'
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Node子进程启动StaticServer
|
|
205
|
-
function startStaticServer() {
|
|
206
|
-
spawn(node, [resolve(__dirname, '../lib/staticServer.js')], {
|
|
207
|
-
stdio: 'inherit'
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Node子进程启动FileExplorerServer
|
|
212
|
-
function startFileExplorerServer() {
|
|
213
|
-
spawn(node, [resolve(__dirname, '../lib/fileExplorerServer.js')], {
|
|
214
|
-
stdio: 'inherit'
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* 初始化服务
|
|
219
|
-
*/
|
|
220
|
-
function initServe() {
|
|
221
|
-
if (explorerDir) {
|
|
222
|
-
// 文件浏览器:指定目录
|
|
223
|
-
process.env.EXPLORER_DIRECTORY = resolve(process.cwd(), explorerDir);
|
|
224
|
-
if (!existsSync(process.env.EXPLORER_DIRECTORY)) {
|
|
225
|
-
console.error(`explorer: 目录 ${process.env.EXPLORER_DIRECTORY} 不存在`);
|
|
226
|
-
process.exit();
|
|
227
|
-
}
|
|
228
|
-
startFileExplorerServer();
|
|
229
|
-
} else if (specifiedFile) {
|
|
230
|
-
// Mock服务器:指定文件
|
|
231
|
-
process.env.SPECIFIED_FILE = resolve(process.cwd(), specifiedFile);
|
|
232
|
-
if (isStartSocketServer) {
|
|
233
|
-
startMockServer();
|
|
234
|
-
} else {
|
|
235
|
-
watchMockFiles(process.env.SPECIFIED_FILE);
|
|
236
|
-
}
|
|
237
|
-
} else if (watchDir) {
|
|
238
|
-
// Mock服务器:指定目录
|
|
239
|
-
process.env.SPECIFIED_DIR = resolve(process.cwd(), watchDir);
|
|
240
|
-
// log.info('SPECIFIED_DIR::', process.env.SPECIFIED_DIR);
|
|
241
|
-
if (isStartSocketServer) {
|
|
242
|
-
startMockServer();
|
|
243
|
-
} else {
|
|
244
|
-
watchMockFiles(process.env.SPECIFIED_DIR);
|
|
245
|
-
}
|
|
246
|
-
} else if (process.env.STATIC_DIRECTORY) {
|
|
247
|
-
// 静态服务器
|
|
248
|
-
process.env.STATIC_DIRECTORY = resolve(process.cwd(), process.env.STATIC_DIRECTORY);
|
|
249
|
-
startStaticServer();
|
|
250
|
-
} else {
|
|
251
|
-
// Mock服务:使用默认目录
|
|
252
|
-
watchDir = process.env.SPECIFIED_DIR = resolve(process.cwd(), './mock');
|
|
253
|
-
// log.info('SPECIFIED_DIR::', process.env.SPECIFIED_DIR);
|
|
254
|
-
if (isStartSocketServer) {
|
|
255
|
-
startMockServer();
|
|
256
|
-
} else {
|
|
257
|
-
// whether include web serve or not
|
|
258
|
-
const includesWebServe = process.env.STATIC_DIRECTORY || process.env.WEB_ROOT;
|
|
259
|
-
|
|
260
|
-
if (includesWebServe && !existsSync(resolve(process.cwd(), watchDir))) {
|
|
261
|
-
// 若包含web服务,则允许不启动mock服务
|
|
262
|
-
startMockServer();
|
|
263
|
-
} else {
|
|
264
|
-
watchMockFiles(watchDir);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
3
|
+
require('../dist/cli');
|
|
@@ -1,25 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* @Date: 2022-01-04 10:46:20
|
|
4
|
-
* @LastEditors: chendq
|
|
5
|
-
* @LastEditTime: 2026-03-15 17:23:52
|
|
6
|
-
* @Author: chendq
|
|
7
|
-
*/
|
|
8
|
-
// const { getDataType } = require('./utils');
|
|
9
|
-
class AsyncTaskQueue {
|
|
1
|
+
// src/lib/asyncTaskQueue.js
|
|
2
|
+
var AsyncTaskQueue = class {
|
|
10
3
|
constructor(isSaveItem = false) {
|
|
11
4
|
this.list = [];
|
|
12
5
|
this.index = 0;
|
|
13
6
|
this.isStop = false;
|
|
14
7
|
this.isParallel = false;
|
|
15
|
-
this.isSaveItem = isSaveItem;
|
|
8
|
+
this.isSaveItem = isSaveItem;
|
|
16
9
|
}
|
|
17
|
-
|
|
18
10
|
next() {
|
|
19
|
-
// 加限制
|
|
20
11
|
if (this.index >= this.list.length - 1 || this.isStop) return;
|
|
21
12
|
if (!this.isSaveItem) {
|
|
22
|
-
this.list.splice(this.index, 1,
|
|
13
|
+
this.list.splice(this.index, 1, "");
|
|
23
14
|
}
|
|
24
15
|
const cur = this.list[++this.index];
|
|
25
16
|
cur(this.next.bind(this));
|
|
@@ -36,9 +27,8 @@ class AsyncTaskQueue {
|
|
|
36
27
|
*/
|
|
37
28
|
run() {
|
|
38
29
|
const cur = this.list[this.index];
|
|
39
|
-
typeof cur ===
|
|
30
|
+
typeof cur === "function" && cur(this.next.bind(this));
|
|
40
31
|
}
|
|
41
|
-
|
|
42
32
|
/**
|
|
43
33
|
* @description: 并发执行异步任务
|
|
44
34
|
*/
|
|
@@ -48,14 +38,12 @@ class AsyncTaskQueue {
|
|
|
48
38
|
fn(this.next.bind(this));
|
|
49
39
|
}
|
|
50
40
|
}
|
|
51
|
-
|
|
52
41
|
/**
|
|
53
42
|
* @description: 暂停执行异步任务
|
|
54
43
|
*/
|
|
55
44
|
stop() {
|
|
56
45
|
this.isStop = true;
|
|
57
46
|
}
|
|
58
|
-
|
|
59
47
|
/**
|
|
60
48
|
* @description: 重试执行异步任务
|
|
61
49
|
*/
|
|
@@ -70,5 +58,5 @@ class AsyncTaskQueue {
|
|
|
70
58
|
this.isStop = false;
|
|
71
59
|
this.next();
|
|
72
60
|
}
|
|
73
|
-
}
|
|
61
|
+
};
|
|
74
62
|
module.exports = AsyncTaskQueue;
|