mock-service-cli 3.3.2 → 3.3.4
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 -17
- package/bin/mock-service-cli +96 -65
- package/lib/manageMockFiles.js +1 -1
- package/lib/mockServer.js +71 -28
- package/lib/staticServer.js +30 -3
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
### 简介
|
|
11
11
|
|
|
12
|
-
内置 **Static Server**、**Mock Server**、**SPA
|
|
12
|
+
内置 **Static Server**、**Mock Server**、**SPA Server**、Http?s request proxy 等功能集。
|
|
13
13
|
|
|
14
14
|
**简易轻量**、**B/S 架构**、**0 秒启动**的本地命令行 Mock 服务套件, 支持热更新,对于开发调试 mock 数据很实用,能提高前端开发者的开发效率。支持 `GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`OPTIONS`,`COPY`,`LINK`,`UNLINK`,`PURGE` 等常用请求类型,无需布署后端,可能是本地最好用的 Mock 工具之一。
|
|
15
15
|
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
|
|
25
25
|
#### Mock Server - 本地 Mock 服务器
|
|
26
26
|
|
|
27
|
+
**支持热更新,即 Mock 文件改动后自动重启服务**
|
|
28
|
+
|
|
27
29
|
> Mock File 仅支持 commonjs 规范的 js、cjs 文件,不支持 ES Module
|
|
28
30
|
|
|
29
31
|
支持以下常见业务场景:
|
|
@@ -74,22 +76,25 @@ This will install `mock-service-cli` globally so that it may be run from the com
|
|
|
74
76
|
|
|
75
77
|
`[path]` defaults to `./mock` .
|
|
76
78
|
|
|
77
|
-
| Command
|
|
78
|
-
|
|
|
79
|
-
| `-h` or `--help`
|
|
80
|
-
| `-p` or `--port`
|
|
81
|
-
| `-d`
|
|
82
|
-
| `-f`
|
|
83
|
-
| `-s` or `--silent`
|
|
84
|
-
| `-v` or `--version`
|
|
85
|
-
| `-S` or `--socket-server`
|
|
86
|
-
| `-a` or `--api-stat`
|
|
87
|
-
| `-
|
|
88
|
-
| `-o` or `--cors-origin`
|
|
89
|
-
| `-O` or `--proxy-options`
|
|
90
|
-
| `-
|
|
91
|
-
| `-
|
|
92
|
-
|
|
79
|
+
| Command | Description | Defaults |
|
|
80
|
+
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
|
|
81
|
+
| `-h` or `--help` | Print this list and exit. | |
|
|
82
|
+
| `-p` or `--port` | Mock server port to use. Use `-p 8090` to look for an open port, starting at 8090. | 8090 |
|
|
83
|
+
| `-d` | Specify mock directory | ./mock |
|
|
84
|
+
| `-f` | Specify mock file | |
|
|
85
|
+
| `-s` or `--silent` | Suppress log messages from output | |
|
|
86
|
+
| `-v` or `--version` | Print the version and exit. | |
|
|
87
|
+
| `-S` or `--socket-server` | Start socket server which used to save api response data for future mock. | false |
|
|
88
|
+
| `-a` or `--api-stat` | Whether print api url and file path info or not, default false. | false |
|
|
89
|
+
| `-t` or `--track` | Whether record operation info by write file, default false. | false |
|
|
90
|
+
| `-o` or `--cors-origin` | Allow origin by cors, list separated by commas, must not be \* when withCredential is true .If specified, cors-headers will be `Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,X-Data-Type,X-Requested-With,X-Data-Type,X-Auth-Token,Token` | \* |
|
|
91
|
+
| `-O` or `--proxy-options` | Optionally provide http request proxy options list, support accept js file、json file、cli arguments string. Examples: `-O '/api/apaas\|http://192.168.0.105:60700,/api/permission\| http://192.168.0.105:60700'`. Must start web server to use proxy for http request test under browser console or api test tools. | - |
|
|
92
|
+
| `-H` or `--cors-headers` | When start Mock Server, optionally provide CORS headers list separated by commas. default \*. | - |
|
|
93
|
+
| `-A` or `--append-headers` | When start Mock/Web/Static Server, optionally add response headers list separated by commas. For example: X-Frame-options=DENY,content-security-policy=frame-ancestors. | - |
|
|
94
|
+
|
|
95
|
+
| `-P` or `--web-port` | Web server port to use. Use `-P 9090` to look for an open port, starting at 9090 | 9090 |
|
|
96
|
+
| `-b` or `--web-baseurl` | Specify public path of the SPA web server, can be base address of SPA route. | - |
|
|
97
|
+
| `-R` or `--static-server` | Specify directory of the Static Web Server. | - |
|
|
93
98
|
|
|
94
99
|
## Example
|
|
95
100
|
|
package/bin/mock-service-cli
CHANGED
|
@@ -9,6 +9,7 @@ const argv = require('minimist')(process.argv.slice(2));
|
|
|
9
9
|
const { logger } = require('../lib/utils');
|
|
10
10
|
const spawn = require('child_process').spawn;
|
|
11
11
|
const node = process.execPath;
|
|
12
|
+
|
|
12
13
|
process.title = 'mock-service-cli';
|
|
13
14
|
|
|
14
15
|
if (argv.h || argv.help) {
|
|
@@ -18,30 +19,33 @@ if (argv.h || argv.help) {
|
|
|
18
19
|
'',
|
|
19
20
|
'PS: Mock File仅支持commonjs规范的js、cjs文件,不支持ES Module',
|
|
20
21
|
'options:',
|
|
21
|
-
' -p --port
|
|
22
|
-
' -d
|
|
23
|
-
'
|
|
24
|
-
' -f --file
|
|
25
|
-
'
|
|
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',
|
|
26
27
|
' -s --silent Suppress log messages from output',
|
|
27
|
-
' -S --socket-server
|
|
28
|
-
' -a --api-stat
|
|
29
|
-
' -
|
|
30
|
-
' -o --cors-origin
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
' -H --cors-headers
|
|
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.',
|
|
34
40
|
'',
|
|
35
|
-
' -
|
|
36
|
-
' -
|
|
37
|
-
' -
|
|
38
|
-
' -D --web-dir Enable web server, specify web directory, default [./dist] directory',
|
|
39
|
-
' -b --web-baseurl Specify website public path when enabled web server.',
|
|
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.',
|
|
40
44
|
'',
|
|
41
|
-
' -R --static-server
|
|
45
|
+
' -R --static-server Specify static resource file directory when enabled static server.',
|
|
42
46
|
'',
|
|
43
|
-
' -h --help
|
|
44
|
-
' -v --version
|
|
47
|
+
' -h --help Print this list and exit.',
|
|
48
|
+
' -v --version Print the version and exit.'
|
|
45
49
|
].join('\n')
|
|
46
50
|
);
|
|
47
51
|
process.exit();
|
|
@@ -113,6 +117,7 @@ if (proxyArg) {
|
|
|
113
117
|
}
|
|
114
118
|
process.env.PROXY_OPTIONS = JSON.stringify(proxyTable);
|
|
115
119
|
}
|
|
120
|
+
// whether to start Web server or not
|
|
116
121
|
if (argv.D || argv['web-dir']) {
|
|
117
122
|
// 解析SPA应用参数:SPA Web目录
|
|
118
123
|
process.env.WEB_ROOT = resolve(process.cwd(), argv.D || argv['web-dir']);
|
|
@@ -122,24 +127,38 @@ if (argv.D || argv['web-dir']) {
|
|
|
122
127
|
}
|
|
123
128
|
// Web Server port
|
|
124
129
|
portfinder.basePort = argv.P || argv['web-port'] || 9090;
|
|
130
|
+
portfinder.getPort(function (err, webPort) {
|
|
131
|
+
if (err) {
|
|
132
|
+
throw err;
|
|
133
|
+
}
|
|
134
|
+
process.env.WEB_PORT = webPort;
|
|
135
|
+
// Mock Server port
|
|
136
|
+
portfinder.basePort = port || 8090;
|
|
137
|
+
portfinder.getPort(function (err, port) {
|
|
138
|
+
if (err) {
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
process.env.PORT = port;
|
|
142
|
+
initServe();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
} else {
|
|
146
|
+
// Mock Server port
|
|
147
|
+
portfinder.basePort = port || 8090;
|
|
125
148
|
portfinder.getPort(function (err, port) {
|
|
126
149
|
if (err) {
|
|
127
150
|
throw err;
|
|
128
151
|
}
|
|
129
|
-
process.env.
|
|
152
|
+
process.env.PORT = port;
|
|
153
|
+
initServe();
|
|
130
154
|
});
|
|
131
155
|
}
|
|
132
156
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
process.env.PORT = port;
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
const watchMockFiles = function (watchDir) {
|
|
157
|
+
/**
|
|
158
|
+
* Watch change of mock files, restart serve
|
|
159
|
+
* @param watchDir
|
|
160
|
+
*/
|
|
161
|
+
function watchMockFiles(watchDir) {
|
|
143
162
|
/**
|
|
144
163
|
* script 重启的脚本
|
|
145
164
|
* ext 检测的文件
|
|
@@ -164,50 +183,62 @@ const watchMockFiles = function (watchDir) {
|
|
|
164
183
|
[colors.green('\nnodemon: mockServer restarted due to: '), files, colors.green(' have changed'), '\n'].join('')
|
|
165
184
|
);
|
|
166
185
|
});
|
|
167
|
-
}
|
|
186
|
+
}
|
|
168
187
|
|
|
169
188
|
// Node子进程启动MockServer
|
|
170
|
-
|
|
189
|
+
function startMockServer() {
|
|
171
190
|
spawn(node, [resolve(__dirname, '../lib/mockServer.js')], {
|
|
172
191
|
stdio: 'inherit'
|
|
173
192
|
});
|
|
174
|
-
}
|
|
193
|
+
}
|
|
175
194
|
|
|
176
195
|
// Node子进程启动StaticServer
|
|
177
|
-
|
|
196
|
+
function startStaticServer() {
|
|
178
197
|
spawn(node, [resolve(__dirname, '../lib/staticServer.js')], {
|
|
179
198
|
stdio: 'inherit'
|
|
180
199
|
});
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
} else
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
} else
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
// log.info('SPECIFIED_DIR::', process.env.SPECIFIED_DIR);
|
|
208
|
-
if (isStartSocketServer) {
|
|
209
|
-
startMockServer();
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* 初始化服务
|
|
203
|
+
*/
|
|
204
|
+
function initServe() {
|
|
205
|
+
if (specifiedFile) {
|
|
206
|
+
// Mock服务器:指定文件
|
|
207
|
+
process.env.SPECIFIED_FILE = resolve(process.cwd(), specifiedFile);
|
|
208
|
+
if (isStartSocketServer) {
|
|
209
|
+
startMockServer();
|
|
210
|
+
} else {
|
|
211
|
+
watchMockFiles(process.env.SPECIFIED_FILE);
|
|
212
|
+
}
|
|
213
|
+
} else if (watchDir) {
|
|
214
|
+
// Mock服务器:指定目录
|
|
215
|
+
process.env.SPECIFIED_DIR = resolve(process.cwd(), watchDir);
|
|
216
|
+
// log.info('SPECIFIED_DIR::', process.env.SPECIFIED_DIR);
|
|
217
|
+
if (isStartSocketServer) {
|
|
218
|
+
startMockServer();
|
|
219
|
+
} else {
|
|
220
|
+
watchMockFiles(process.env.SPECIFIED_DIR);
|
|
221
|
+
}
|
|
222
|
+
} else if (process.env.STATIC_DIRECTORY) {
|
|
223
|
+
// 静态服务器
|
|
224
|
+
process.env.STATIC_DIRECTORY = resolve(process.cwd(), process.env.STATIC_DIRECTORY);
|
|
225
|
+
startStaticServer();
|
|
210
226
|
} else {
|
|
211
|
-
|
|
227
|
+
// Mock服务:使用默认目录
|
|
228
|
+
watchDir = process.env.SPECIFIED_DIR = resolve(process.cwd(), './mock');
|
|
229
|
+
// log.info('SPECIFIED_DIR::', process.env.SPECIFIED_DIR);
|
|
230
|
+
if (isStartSocketServer) {
|
|
231
|
+
startMockServer();
|
|
232
|
+
} else {
|
|
233
|
+
// whether include web serve or not
|
|
234
|
+
const includesWebServe = process.env.STATIC_DIRECTORY || process.env.WEB_ROOT;
|
|
235
|
+
|
|
236
|
+
if (includesWebServe && !existsSync(resolve(process.cwd(), watchDir))) {
|
|
237
|
+
// 若包含web服务,则允许不启动mock服务
|
|
238
|
+
startMockServer();
|
|
239
|
+
} else {
|
|
240
|
+
watchMockFiles(watchDir);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
212
243
|
}
|
|
213
244
|
}
|
package/lib/manageMockFiles.js
CHANGED
|
@@ -67,7 +67,7 @@ const genMockFiles = async function ({ url: apiUrl, method, data: resJsonData, d
|
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
69
|
apiUrl = apiUrl.trim().split('?')[0];
|
|
70
|
-
const LOGGER = logFile(processArgv.
|
|
70
|
+
const LOGGER = logFile(processArgv.t || processArgv.track, mockDir);
|
|
71
71
|
const normalizeApiUrl = filePath2ApiUrl(path.normalize(apiUrl));
|
|
72
72
|
const mockListFilePath = path.resolve(process.cwd(), `${mockDir}/mock-list.json`);
|
|
73
73
|
const mockFilePath = path.resolve(process.cwd(), `${mockDir}/${encodeURIComponent(path.normalize(apiUrl))}.json`);
|
package/lib/mockServer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const express = require('express'), // 引入express
|
|
2
2
|
bodyParser = require('body-parser'),
|
|
3
|
-
|
|
3
|
+
{ readdirSync, existsSync } = require('fs'),
|
|
4
4
|
os = require('os'),
|
|
5
5
|
path = require('path'),
|
|
6
6
|
colors = require('colors/safe'),
|
|
@@ -25,8 +25,6 @@ const app = express();
|
|
|
25
25
|
const log = logger(process.env.SILENT);
|
|
26
26
|
const argv = JSON.parse(process.env.ARGV);
|
|
27
27
|
let socketServer = null; // Socket server instance
|
|
28
|
-
const AsyncTaskQueue = require('./asyncTaskQueue');
|
|
29
|
-
const saveDataAsyncTask = new AsyncTaskQueue();
|
|
30
28
|
let corsOrigin = [],
|
|
31
29
|
corsHeaders = '';
|
|
32
30
|
|
|
@@ -35,6 +33,12 @@ let count = 0,
|
|
|
35
33
|
fileCount = 0, // 记录mock api个数,mock file个数
|
|
36
34
|
mockDirStat = {}, // 缓存mock目录的统计信息
|
|
37
35
|
mockFileStat = {}; // 缓存mock文件的统计信息
|
|
36
|
+
|
|
37
|
+
// whether include web serve or not
|
|
38
|
+
const includesWebServe = process.env.STATIC_DIRECTORY || process.env.WEB_ROOT;
|
|
39
|
+
|
|
40
|
+
const mockFileOrDir = process.env.SPECIFIED_FILE || process.env.SPECIFIED_DIR;
|
|
41
|
+
|
|
38
42
|
if (!process.env.PORT) {
|
|
39
43
|
portfinder.basePort = 8090;
|
|
40
44
|
portfinder.getPort(function (err, port) {
|
|
@@ -68,12 +72,16 @@ function init() {
|
|
|
68
72
|
app.use(crossDomain()); // 允许跨域
|
|
69
73
|
app.use(bodyParser.json()); // 解析body
|
|
70
74
|
|
|
75
|
+
let requireMockServe = true;
|
|
71
76
|
if (process.env.SPECIFIED_FILE) {
|
|
72
77
|
composeRouteFromJsFile(process.env.SPECIFIED_FILE);
|
|
78
|
+
} else if (includesWebServe && !existsSync(path.resolve(process.cwd(), process.env.SPECIFIED_DIR))) {
|
|
79
|
+
// 若包含web服务,则允许不启动mock服务
|
|
80
|
+
requireMockServe = false;
|
|
73
81
|
} else {
|
|
74
82
|
parseMockFiles(process.env.SPECIFIED_DIR);
|
|
75
83
|
}
|
|
76
|
-
argv.a && log.info(colors.yellow(`${fileCount} mock file are parsed in total.`));
|
|
84
|
+
requireMockServe && argv.a && log.info(colors.yellow(`${fileCount} mock file are parsed in total.`));
|
|
77
85
|
|
|
78
86
|
startServer();
|
|
79
87
|
}
|
|
@@ -85,6 +93,20 @@ function init() {
|
|
|
85
93
|
*/
|
|
86
94
|
function crossDomain() {
|
|
87
95
|
return (req, res, next) => {
|
|
96
|
+
if (typeof argv.A === 'string') {
|
|
97
|
+
const resHeaders = {};
|
|
98
|
+
argv.A.split(/\s*,\s*/).forEach(function (h) {
|
|
99
|
+
const [key, value] = h.split('=');
|
|
100
|
+
resHeaders[key] = value;
|
|
101
|
+
}, this);
|
|
102
|
+
// 添加自定义响应头
|
|
103
|
+
for (const key in resHeaders) {
|
|
104
|
+
if (resHeaders.hasOwnProperty(key)) {
|
|
105
|
+
res.header(key, resHeaders[key]);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
88
110
|
// 设置withCredentials: true时,需设置以下两项
|
|
89
111
|
res.header('Access-Control-Allow-Credentials', true);
|
|
90
112
|
// withCredentials, must be specified value instead of *
|
|
@@ -144,7 +166,7 @@ function composeRouteFromJsFile(file) {
|
|
|
144
166
|
* @return {void}
|
|
145
167
|
*/
|
|
146
168
|
function parseMockFiles(specialDir = '../mock') {
|
|
147
|
-
const files =
|
|
169
|
+
const files = readdirSync(path.resolve(process.cwd(), specialDir), { withFileTypes: true });
|
|
148
170
|
const curFilesSize = files.length;
|
|
149
171
|
for (let index = 0; index < curFilesSize; index++) {
|
|
150
172
|
const el = files[index];
|
|
@@ -225,13 +247,30 @@ function startServer() {
|
|
|
225
247
|
console.warn(colors.yellow('\nEnable web proxy Failed:', error));
|
|
226
248
|
}
|
|
227
249
|
}
|
|
250
|
+
// 添加自定义响应头
|
|
251
|
+
if (typeof argv.A === 'string') {
|
|
252
|
+
webApp.use((req, res, next) => {
|
|
253
|
+
const resHeaders = {};
|
|
254
|
+
argv.A.split(/\s*,\s*/).forEach(function (h) {
|
|
255
|
+
const [key, value] = h.split('=');
|
|
256
|
+
resHeaders[key] = value;
|
|
257
|
+
}, this);
|
|
258
|
+
// 添加自定义响应头
|
|
259
|
+
for (const key in resHeaders) {
|
|
260
|
+
if (resHeaders.hasOwnProperty(key)) {
|
|
261
|
+
res.header(key, resHeaders[key]);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
next();
|
|
265
|
+
});
|
|
266
|
+
}
|
|
228
267
|
// console.log(process.env.WEB_PUBLIC_PATH, process.env.WEB_ROOT);
|
|
229
268
|
if (process.env.WEB_PUBLIC_PATH) {
|
|
230
269
|
webPublicPath = process.env.WEB_PUBLIC_PATH;
|
|
231
270
|
}
|
|
232
271
|
webApp.use(webPublicPath, express.static(process.env.WEB_ROOT)); // 将dist目录下所有文件作为静态文件来管理
|
|
233
272
|
const defaultStaticEntry = `${process.env.WEB_ROOT}/index.html`;
|
|
234
|
-
if (
|
|
273
|
+
if (existsSync(defaultStaticEntry)) {
|
|
235
274
|
// Used as static HTTP server for SPA
|
|
236
275
|
webApp.get('*', (req, res) => {
|
|
237
276
|
res.sendFile(defaultStaticEntry);
|
|
@@ -255,6 +294,9 @@ function startServer() {
|
|
|
255
294
|
}
|
|
256
295
|
const http = require('http').createServer(app);
|
|
257
296
|
if (process.env.SOCKET_SERVER) {
|
|
297
|
+
const AsyncTaskQueue = require('./asyncTaskQueue');
|
|
298
|
+
const saveDataAsyncTask = new AsyncTaskQueue();
|
|
299
|
+
|
|
258
300
|
socketServer = new Server(http, { path: '/ws/mock-service' });
|
|
259
301
|
log.info(colors.bgBlue(`Socket server has started. path: /ws/mock-service, `));
|
|
260
302
|
socketServer.of('/mock-data').on('connection', function (socket) {
|
|
@@ -302,34 +344,35 @@ function startServer() {
|
|
|
302
344
|
});
|
|
303
345
|
}
|
|
304
346
|
|
|
305
|
-
|
|
306
|
-
|
|
347
|
+
if (existsSync(mockFileOrDir)) {
|
|
348
|
+
http.listen(Number.parseInt(process.env.PORT, 10), () => {
|
|
349
|
+
console.info(colors.red('\n Mock File仅支持commonjs规范的js、cjs文件,不支持ES Module'));
|
|
307
350
|
|
|
308
|
-
console.info(
|
|
309
|
-
[
|
|
310
|
-
colors.yellow(`\n${process.env.RESTARTED ? 'Restarting' : 'Starting'} up mock-server, serving `),
|
|
311
|
-
colors.cyan(process.env.SPECIFIED_FILE || process.env.SPECIFIED_DIR),
|
|
312
|
-
colors.yellow(` ${dateFormat('YYYY-mm-dd HH:MM:SS', new Date())}`)
|
|
313
|
-
].join('')
|
|
314
|
-
);
|
|
315
|
-
if (!process.env.RESTARTED) {
|
|
316
351
|
console.info(
|
|
317
|
-
[
|
|
352
|
+
[
|
|
353
|
+
colors.yellow(`\n${process.env.RESTARTED ? 'Restarting' : 'Starting'} up mock-server, serving `),
|
|
354
|
+
colors.cyan(process.env.SPECIFIED_FILE || process.env.SPECIFIED_DIR),
|
|
355
|
+
colors.yellow(` ${dateFormat('YYYY-mm-dd HH:MM:SS', new Date())}`)
|
|
356
|
+
].join('')
|
|
318
357
|
);
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
358
|
+
if (!process.env.RESTARTED) {
|
|
359
|
+
console.info(
|
|
360
|
+
[colors.yellow('\n🌍 mock-server version: '), colors.cyan(require('../package.json').version), '\n'].join('')
|
|
361
|
+
);
|
|
362
|
+
console.info(colors.yellow(`\n Mock server available on:\n`));
|
|
363
|
+
console.info(' http://localhost:' + colors.green(process.env.PORT));
|
|
364
|
+
Object.keys(ifaces).forEach(function (dev) {
|
|
365
|
+
ifaces[dev].forEach(function (details) {
|
|
366
|
+
if (details.family === 'IPv4') {
|
|
367
|
+
console.info(' http://' + details.address + ':' + colors.green(process.env.PORT));
|
|
368
|
+
}
|
|
369
|
+
});
|
|
326
370
|
});
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
}
|
|
330
374
|
|
|
331
375
|
if (webApp && !process.env.RESTARTED) {
|
|
332
|
-
console.info(colors.red('\n Mock File仅支持commonjs规范的js、cjs文件,不支持ES Module'));
|
|
333
376
|
webApp.listen(Number.parseInt(process.env.WEB_PORT, 10), () => {
|
|
334
377
|
console.info(colors.yellow(`\n Web server available on:\n`));
|
|
335
378
|
console.info(' http://localhost:' + colors.green(process.env.WEB_PORT) + webPublicPath);
|
package/lib/staticServer.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Static Server
|
|
3
3
|
* @Date: 2023-12-03 18:02:24
|
|
4
4
|
* @LastEditors: chendq
|
|
5
|
-
* @LastEditTime: 2025-
|
|
5
|
+
* @LastEditTime: 2025-07-29 19:20:21
|
|
6
6
|
* @Author : chendq
|
|
7
7
|
*/
|
|
8
8
|
const express = require('express'), // 引入express
|
|
@@ -12,6 +12,9 @@ const express = require('express'), // 引入express
|
|
|
12
12
|
const { dateFormat, logger } = require('./utils');
|
|
13
13
|
const ifaces = os.networkInterfaces();
|
|
14
14
|
const log = logger(process.env.SILENT);
|
|
15
|
+
const argv = JSON.parse(process.env.ARGV);
|
|
16
|
+
|
|
17
|
+
const resHeaders = {};
|
|
15
18
|
|
|
16
19
|
if (!process.env.PORT) {
|
|
17
20
|
portfinder.basePort = 8090;
|
|
@@ -26,12 +29,36 @@ if (!process.env.PORT) {
|
|
|
26
29
|
startServer();
|
|
27
30
|
}
|
|
28
31
|
|
|
32
|
+
/**
|
|
33
|
+
* @description: 添加自定义响应头
|
|
34
|
+
* @param {*}
|
|
35
|
+
* @return {*}
|
|
36
|
+
*/
|
|
37
|
+
function appendResHeaders() {
|
|
38
|
+
return (req, res, next) => {
|
|
39
|
+
for (const key in resHeaders) {
|
|
40
|
+
if (resHeaders.hasOwnProperty(key)) {
|
|
41
|
+
res.header(key, resHeaders[key]);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
next();
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
29
48
|
/**
|
|
30
49
|
* Start server
|
|
31
50
|
*/
|
|
32
51
|
function startServer() {
|
|
33
52
|
const app = express();
|
|
34
53
|
|
|
54
|
+
if (typeof argv.A === 'string') {
|
|
55
|
+
argv.A.split(/\s*,\s*/).forEach(function (h) {
|
|
56
|
+
const [key, value] = h.split('=');
|
|
57
|
+
resHeaders[key] = value;
|
|
58
|
+
}, this);
|
|
59
|
+
app.use(appendResHeaders()); // 添加响应头
|
|
60
|
+
}
|
|
61
|
+
|
|
35
62
|
app.use(express.static(process.env.STATIC_DIRECTORY)); // 将dist目录下所有文件作为静态文件来管理
|
|
36
63
|
|
|
37
64
|
app.listen(Number.parseInt(process.env.PORT, 10), () => {
|
|
@@ -67,11 +94,11 @@ if (process.platform === 'win32') {
|
|
|
67
94
|
}
|
|
68
95
|
|
|
69
96
|
process.on('SIGINT', function () {
|
|
70
|
-
log.info(colors.red('
|
|
97
|
+
log.info(colors.red('static-server process stopped.'));
|
|
71
98
|
process.exit();
|
|
72
99
|
});
|
|
73
100
|
|
|
74
101
|
process.on('SIGTERM', function () {
|
|
75
|
-
log.info(colors.red('
|
|
102
|
+
log.info(colors.red('static-server process stopped.'));
|
|
76
103
|
process.exit();
|
|
77
104
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mock-service-cli",
|
|
3
|
-
"version": "3.3.
|
|
4
|
-
"description": "🦅 Local
|
|
3
|
+
"version": "3.3.4",
|
|
4
|
+
"description": "🦅 Local Mock/Static/SPA server, Http?s request proxy",
|
|
5
5
|
"main": "./lib/mockServer.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mock-service-cli": "bin/mock-service-cli"
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
"node": ">=12"
|
|
29
29
|
},
|
|
30
30
|
"author": "chendq <deqiaochen@gmail.com>",
|
|
31
|
-
"packageManager": "yarn@1.22.19",
|
|
32
31
|
"keywords": [
|
|
32
|
+
"Mock",
|
|
33
33
|
"Static Server",
|
|
34
34
|
"Web Server",
|
|
35
35
|
"Mock Server CLI",
|
|
36
|
-
"
|
|
36
|
+
"SPA Server",
|
|
37
37
|
"mock-service-cli",
|
|
38
38
|
"Socket server"
|
|
39
39
|
],
|