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 CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  ### 简介
11
11
 
12
- 内置 **Static Server**、**Mock Server**、**SPA Web Server**、Http?s request proxy 等功能集。
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 | Description | Defaults |
78
- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
79
- | `-h` or `--help` | Print this list and exit. | |
80
- | `-p` or `--port` | Mock server port to use. Use `-p 8090` to look for an open port, starting at 8090. | 8090 |
81
- | `-d` | Specify mock directory | ./mock |
82
- | `-f` | Specify mock file | |
83
- | `-s` or `--silent` | Suppress log messages from output | |
84
- | `-v` or `--version` | Print the version and exit. | |
85
- | `-S` or `--socket-server` | Start socket server which used to save api response data for future mock. | false |
86
- | `-a` or `--api-stat` | Whether print api url and file path info or not, default false. | false |
87
- | `-l` or `--log` | Whether record operation info by write file, default false. | false |
88
- | `-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` | \* |
89
- | `-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. | - |
90
- | `-P` or `--web-port` | Web server port to use. Use `-P 9090` to look for an open port, starting at 9090 | 9090 |
91
- | `-b` or `--web-baseurl` | Specify public path of the SPA web server, can be base address of SPA route. | - |
92
- | `-R` or `--static-server` | Specify directory of the Static Web Server. | - |
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
 
@@ -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 Mock server port to use. If 0, look for open port. [8090]',
22
- ' -d Specify mock directory, default [./mock] directory,',
23
- ' Also watch js files changes and support hot reload',
24
- ' -f --file Specify the input data source, support javascript ',
25
- ' The priority is over the directory watches',
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 Whether start socket server or not, default false.',
28
- ' -a --api-stat Whether print api url and file path or not, default false.',
29
- ' -l --log Whether record operation info by write file, default false.',
30
- ' -o --cors-origin Allow origin by cors, list separated by commas, must not be * when withCredential is true',
31
- ' .If specified, cors-headers will be "Authorization,Content-Type,Accept,Origin,User-Agent,DNT',
32
- ' ,Cache-Control,X-Mx-ReqToken,X-Data-Type,X-Requested-With,X-Data-Type,X-Auth-Token,Token", default *.',
33
- ' -H --cors-headers Optionally provide CORS headers list separated by commas. default *',
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
- ' -O --proxy-options Optionally provide proxy options list separated by commas.',
36
- ' -r --rewrite rewrite http or https request url prefix of proxy, default false.',
37
- ' -P --web-port Web server port to use. If 0, look for open port. [9090]',
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 Specify static resource file directory when enabled static server.',
45
+ ' -R --static-server Specify static resource file directory when enabled static server.',
42
46
  '',
43
- ' -h --help Print this list and exit.',
44
- ' -v --version Print the version and exit.'
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.WEB_PORT = port;
152
+ process.env.PORT = port;
153
+ initServe();
130
154
  });
131
155
  }
132
156
 
133
- // Mock Server port
134
- portfinder.basePort = port || 8090;
135
- portfinder.getPort(function (err, port) {
136
- if (err) {
137
- throw err;
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
- const startMockServer = function () {
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
- const startStaticServer = function () {
196
+ function startStaticServer() {
178
197
  spawn(node, [resolve(__dirname, '../lib/staticServer.js')], {
179
198
  stdio: 'inherit'
180
199
  });
181
- };
182
-
183
- if (specifiedFile) {
184
- // Mock服务器:指定文件
185
- process.env.SPECIFIED_FILE = resolve(process.cwd(), specifiedFile);
186
- if (isStartSocketServer) {
187
- startMockServer();
188
- } else {
189
- watchMockFiles(process.env.SPECIFIED_FILE);
190
- }
191
- } else if (watchDir) {
192
- // Mock服务器:指定目录
193
- process.env.SPECIFIED_DIR = resolve(process.cwd(), watchDir);
194
- // log.info('SPECIFIED_DIR::', process.env.SPECIFIED_DIR);
195
- if (isStartSocketServer) {
196
- startMockServer();
197
- } else {
198
- watchMockFiles(process.env.SPECIFIED_DIR);
199
- }
200
- } else if (process.env.STATIC_DIRECTORY) {
201
- // 静态服务器
202
- process.env.STATIC_DIRECTORY = resolve(process.cwd(), process.env.STATIC_DIRECTORY);
203
- startStaticServer();
204
- } else {
205
- // Mock服务:使用默认目录
206
- watchDir = process.env.SPECIFIED_DIR = resolve(process.cwd(), './mock');
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
- watchMockFiles(watchDir);
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
  }
@@ -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.l || processArgv.log, mockDir);
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
- fs = require('fs'),
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 = fs.readdirSync(path.resolve(process.cwd(), specialDir), { withFileTypes: true });
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 (fs.existsSync(defaultStaticEntry)) {
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
- http.listen(Number.parseInt(process.env.PORT, 10), () => {
306
- console.info(colors.red('\n Mock File仅支持commonjs规范的js、cjs文件,不支持ES Module'));
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
- [colors.yellow('\n🌍 mock-server version: '), colors.cyan(require('../package.json').version), '\n'].join('')
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
- console.info(colors.yellow(`\n Mock server available on:\n`));
320
- console.info(' http://localhost:' + colors.green(process.env.PORT));
321
- Object.keys(ifaces).forEach(function (dev) {
322
- ifaces[dev].forEach(function (details) {
323
- if (details.family === 'IPv4') {
324
- console.info(' http://' + details.address + ':' + colors.green(process.env.PORT));
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);
@@ -2,7 +2,7 @@
2
2
  * Static Server
3
3
  * @Date: 2023-12-03 18:02:24
4
4
  * @LastEditors: chendq
5
- * @LastEditTime: 2025-06-15 22:16:36
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('mock-server process stopped.'));
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('mock-server process stopped.'));
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.2",
4
- "description": "🦅 Local mock server, Static server, SPA server, Http?s request proxy",
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
- "MockServer",
36
+ "SPA Server",
37
37
  "mock-service-cli",
38
38
  "Socket server"
39
39
  ],