mock-service-cli 3.3.1 → 3.3.2
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/lib/manageMockFiles.js +3 -3
- package/lib/mockServer.js +185 -172
- package/lib/staticServer.js +27 -26
- package/package.json +5 -9
package/lib/manageMockFiles.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* @description: 生成Mock文件、获取mock数据统计
|
|
3
3
|
* @Date: 2021-12-22 16:57:08
|
|
4
4
|
* @LastEditors: chendq
|
|
5
|
-
* @LastEditTime:
|
|
5
|
+
* @LastEditTime: 2025-06-15 22:25:45
|
|
6
6
|
* @Author: chendq
|
|
7
7
|
*/
|
|
8
8
|
const fsa = require('fs-extra'),
|
|
9
9
|
fs = require('fs'),
|
|
10
10
|
path = require('path'),
|
|
11
|
-
|
|
11
|
+
isEqual = require('lodash/isEqual'),
|
|
12
12
|
colors = require('colors/safe');
|
|
13
13
|
const {
|
|
14
14
|
getFileLatestContent,
|
|
@@ -96,7 +96,7 @@ const genMockFiles = async function ({ url: apiUrl, method, data: resJsonData, d
|
|
|
96
96
|
if (fsa.pathExistsSync(mockFilePath)) {
|
|
97
97
|
const mockFileContent = getFileLatestContent(mockFilePath);
|
|
98
98
|
// 内容一样不作修改
|
|
99
|
-
if (mockFileContent.hasOwnProperty(method) &&
|
|
99
|
+
if (mockFileContent.hasOwnProperty(method) && isEqual(mockFileContent[method], resJsonData)) {
|
|
100
100
|
// log.assert(
|
|
101
101
|
// !_.isEqual(mockFileContent[method], resJsonData),
|
|
102
102
|
// colors.bgYellow(`${method} ${apiUrl}, Mock data is same`)
|
package/lib/mockServer.js
CHANGED
|
@@ -27,13 +27,14 @@ const argv = JSON.parse(process.env.ARGV);
|
|
|
27
27
|
let socketServer = null; // Socket server instance
|
|
28
28
|
const AsyncTaskQueue = require('./asyncTaskQueue');
|
|
29
29
|
const saveDataAsyncTask = new AsyncTaskQueue();
|
|
30
|
+
let corsOrigin = [],
|
|
31
|
+
corsHeaders = '';
|
|
30
32
|
|
|
31
33
|
const httpsRE = /^https:\/\//;
|
|
32
34
|
let count = 0,
|
|
33
35
|
fileCount = 0, // 记录mock api个数,mock file个数
|
|
34
36
|
mockDirStat = {}, // 缓存mock目录的统计信息
|
|
35
37
|
mockFileStat = {}; // 缓存mock文件的统计信息
|
|
36
|
-
let done = false;
|
|
37
38
|
if (!process.env.PORT) {
|
|
38
39
|
portfinder.basePort = 8090;
|
|
39
40
|
portfinder.getPort(function (err, port) {
|
|
@@ -41,53 +42,68 @@ if (!process.env.PORT) {
|
|
|
41
42
|
throw err;
|
|
42
43
|
}
|
|
43
44
|
process.env.PORT = port;
|
|
44
|
-
|
|
45
|
+
init();
|
|
45
46
|
});
|
|
46
47
|
} else {
|
|
47
|
-
|
|
48
|
+
init();
|
|
48
49
|
}
|
|
49
|
-
// 将异步函数转换为同步代码代码执行
|
|
50
|
-
require('deasync').loopWhile(function () {
|
|
51
|
-
return !done;
|
|
52
|
-
});
|
|
53
|
-
let corsOrigin = [],
|
|
54
|
-
corsHeaders = '';
|
|
55
|
-
if (process.env.CORS_ORIGIN) {
|
|
56
|
-
process.env.CORS_ORIGIN.split(/\s*,\s*/).forEach(function (h) {
|
|
57
|
-
corsOrigin.push(h);
|
|
58
|
-
}, this);
|
|
59
50
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Init mock server
|
|
53
|
+
*/
|
|
54
|
+
function init() {
|
|
55
|
+
if (process.env.CORS_ORIGIN) {
|
|
56
|
+
process.env.CORS_ORIGIN.split(/\s*,\s*/).forEach(function (h) {
|
|
57
|
+
corsOrigin.push(h);
|
|
58
|
+
}, this);
|
|
59
|
+
|
|
60
|
+
corsHeaders = DefaultHeaders;
|
|
61
|
+
}
|
|
62
|
+
if (process.env.CORS_HEADERS) {
|
|
63
|
+
process.env.CORS_HEADERS.split(/\s*,\s*/).forEach(function (h) {
|
|
64
|
+
corsHeaders += corsHeaders ? ', ' + h : h;
|
|
65
|
+
}, this);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
app.use(crossDomain()); // 允许跨域
|
|
69
|
+
app.use(bodyParser.json()); // 解析body
|
|
70
|
+
|
|
71
|
+
if (process.env.SPECIFIED_FILE) {
|
|
72
|
+
composeRouteFromJsFile(process.env.SPECIFIED_FILE);
|
|
73
|
+
} else {
|
|
74
|
+
parseMockFiles(process.env.SPECIFIED_DIR);
|
|
75
|
+
}
|
|
76
|
+
argv.a && log.info(colors.yellow(`${fileCount} mock file are parsed in total.`));
|
|
77
|
+
|
|
78
|
+
startServer();
|
|
66
79
|
}
|
|
80
|
+
|
|
67
81
|
/**
|
|
68
82
|
* @description: 跨域设置
|
|
69
83
|
* @param {*}
|
|
70
84
|
* @return {*}
|
|
71
85
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
function crossDomain() {
|
|
87
|
+
return (req, res, next) => {
|
|
88
|
+
// 设置withCredentials: true时,需设置以下两项
|
|
89
|
+
res.header('Access-Control-Allow-Credentials', true);
|
|
90
|
+
// withCredentials, must be specified value instead of *
|
|
91
|
+
res.header('Access-Control-Allow-Origin', corsOrigin.includes(req.headers.origin) ? req.headers.origin : '*');
|
|
92
|
+
// res.header('Access-Control-Allow-Origin', '*');
|
|
93
|
+
res.header('Access-Control-Allow-Methods', SupportMethods.join(','));
|
|
94
|
+
res.header('Access-Control-Allow-Headers', corsHeaders ? corsHeaders : '*');
|
|
95
|
+
// res.header('Access-Control-Allow-Headers', '*');
|
|
96
|
+
if (req.method === 'OPTIONS') res.status(200); // 让OPTIONS快速返回
|
|
97
|
+
next();
|
|
98
|
+
};
|
|
99
|
+
}
|
|
84
100
|
|
|
85
101
|
/**
|
|
86
102
|
* @description: 构建本地服务的路由请求
|
|
87
103
|
* @param {*} file
|
|
88
104
|
* @returns {*}
|
|
89
105
|
*/
|
|
90
|
-
|
|
106
|
+
function composeRouteFromJsFile(file) {
|
|
91
107
|
// 先删除require之前导入的缓存文件,否则获取到的文件内容还是旧内容
|
|
92
108
|
const fileObject = getFileLatestContent(file);
|
|
93
109
|
|
|
@@ -121,13 +137,13 @@ const composeRouteFromJsFile = function (file) {
|
|
|
121
137
|
});
|
|
122
138
|
}
|
|
123
139
|
});
|
|
124
|
-
}
|
|
140
|
+
}
|
|
125
141
|
/**
|
|
126
142
|
* @description: 解析mock目录下的js文件,为构建路由请求做准备
|
|
127
143
|
* @param {string} specialDir 目录路径
|
|
128
144
|
* @return {void}
|
|
129
145
|
*/
|
|
130
|
-
|
|
146
|
+
function parseMockFiles(specialDir = '../mock') {
|
|
131
147
|
const files = fs.readdirSync(path.resolve(process.cwd(), specialDir), { withFileTypes: true });
|
|
132
148
|
const curFilesSize = files.length;
|
|
133
149
|
for (let index = 0; index < curFilesSize; index++) {
|
|
@@ -171,66 +187,60 @@ const parseMockFiles = function (specialDir = '../mock') {
|
|
|
171
187
|
}
|
|
172
188
|
composeRouteFromJsFile(filePath);
|
|
173
189
|
}
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
app.use(crossDomain()); // 允许跨域
|
|
177
|
-
app.use(bodyParser.json()); // 解析body
|
|
178
|
-
|
|
179
|
-
if (process.env.SPECIFIED_FILE) {
|
|
180
|
-
composeRouteFromJsFile(process.env.SPECIFIED_FILE);
|
|
181
|
-
} else {
|
|
182
|
-
parseMockFiles(process.env.SPECIFIED_DIR);
|
|
183
190
|
}
|
|
184
|
-
argv.a && log.info(colors.yellow(`${fileCount} mock file are parsed in total.`));
|
|
185
191
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Start web server、socket server
|
|
194
|
+
*/
|
|
195
|
+
function startServer() {
|
|
196
|
+
let webApp = null,
|
|
197
|
+
webPublicPath = '/',
|
|
198
|
+
proxyTable = {};
|
|
199
|
+
// Enable Web Server
|
|
200
|
+
if (process.env.WEB_ROOT) {
|
|
201
|
+
webApp = express();
|
|
202
|
+
// Enable web proxy
|
|
203
|
+
if (process.env.PROXY_OPTIONS) {
|
|
204
|
+
try {
|
|
205
|
+
const options = JSON.parse(process.env.PROXY_OPTIONS);
|
|
206
|
+
Object.keys(options).forEach(function (prefix) {
|
|
207
|
+
proxyTable[prefix] = options[prefix];
|
|
208
|
+
const opts = {
|
|
209
|
+
target: options[prefix],
|
|
210
|
+
changeOrigin: true,
|
|
211
|
+
ws: true
|
|
212
|
+
};
|
|
213
|
+
if (httpsRE.test(options[prefix])) {
|
|
214
|
+
// https is require secure=false
|
|
215
|
+
opts.secure = false;
|
|
216
|
+
}
|
|
217
|
+
if (process.env.PREFIX_REWRITE) {
|
|
218
|
+
opts.pathRewrite = path => path.replace(new RegExp(`^${prefix}`), '');
|
|
219
|
+
}
|
|
220
|
+
// 接口代理
|
|
221
|
+
// https://github.com/http-party/node-http-proxy#options
|
|
222
|
+
webApp.use(prefix, createProxyMiddleware(opts));
|
|
223
|
+
}, this);
|
|
224
|
+
} catch (error) {
|
|
225
|
+
console.warn(colors.yellow('\nEnable web proxy Failed:', error));
|
|
226
|
+
}
|
|
216
227
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
.send(`Hi, welcome to web server entrance ui, you can test http proxy on browser console or api request tools. Examples as follows:<br />
|
|
228
|
+
// console.log(process.env.WEB_PUBLIC_PATH, process.env.WEB_ROOT);
|
|
229
|
+
if (process.env.WEB_PUBLIC_PATH) {
|
|
230
|
+
webPublicPath = process.env.WEB_PUBLIC_PATH;
|
|
231
|
+
}
|
|
232
|
+
webApp.use(webPublicPath, express.static(process.env.WEB_ROOT)); // 将dist目录下所有文件作为静态文件来管理
|
|
233
|
+
const defaultStaticEntry = `${process.env.WEB_ROOT}/index.html`;
|
|
234
|
+
if (fs.existsSync(defaultStaticEntry)) {
|
|
235
|
+
// Used as static HTTP server for SPA
|
|
236
|
+
webApp.get('*', (req, res) => {
|
|
237
|
+
res.sendFile(defaultStaticEntry);
|
|
238
|
+
});
|
|
239
|
+
} else {
|
|
240
|
+
// Used as api server for test on browser console or api request tools
|
|
241
|
+
webApp.use(webPublicPath, (req, res) => {
|
|
242
|
+
res.status(200)
|
|
243
|
+
.send(`Hi, welcome to web server entrance ui, you can test http proxy on browser console or api request tools. Examples as follows:<br />
|
|
234
244
|
fetch("http://localhost:${process.env.WEB_PORT}/api/permission/auth/login", {
|
|
235
245
|
method: 'post',
|
|
236
246
|
headers: {
|
|
@@ -240,101 +250,104 @@ if (process.env.WEB_ROOT) {
|
|
|
240
250
|
body:JSON.stringify({"loginName":"admin","password":"admin"})
|
|
241
251
|
})
|
|
242
252
|
`);
|
|
243
|
-
|
|
253
|
+
});
|
|
254
|
+
}
|
|
244
255
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
socket.on('mock-dir-stat', function (dir) {
|
|
257
|
-
socket.emit('mock-dir-stat', isEmptyObj(mockDirStat) ? (mockDirStat = getMockStatFromDir(dir)) : mockDirStat);
|
|
258
|
-
});
|
|
259
|
-
socket.on('mock-file-stat', function (filePath) {
|
|
260
|
-
socket.emit(
|
|
261
|
-
'mock-file-stat',
|
|
262
|
-
isEmptyObj(mockFileStat) ? (mockFileStat = getMockStatFromFile(filePath)) : mockFileStat
|
|
256
|
+
const http = require('http').createServer(app);
|
|
257
|
+
if (process.env.SOCKET_SERVER) {
|
|
258
|
+
socketServer = new Server(http, { path: '/ws/mock-service' });
|
|
259
|
+
log.info(colors.bgBlue(`Socket server has started. path: /ws/mock-service, `));
|
|
260
|
+
socketServer.of('/mock-data').on('connection', function (socket) {
|
|
261
|
+
const { headers, address } = socket.handshake;
|
|
262
|
+
const clientIp = headers.hasOwnProperty('x-forwarded-for') ? headers['x-forwarded-for'] : address;
|
|
263
|
+
log.info(
|
|
264
|
+
colors.green(
|
|
265
|
+
`Socket client ${clientIp} has connected. --- ${dateFormat('YYYY-mm-dd HH:MM:SS', new Date())}`
|
|
266
|
+
)
|
|
263
267
|
);
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
268
|
+
socket.on('mock-dir-stat', function (dir) {
|
|
269
|
+
socket.emit('mock-dir-stat', isEmptyObj(mockDirStat) ? (mockDirStat = getMockStatFromDir(dir)) : mockDirStat);
|
|
270
|
+
});
|
|
271
|
+
socket.on('mock-file-stat', function (filePath) {
|
|
272
|
+
socket.emit(
|
|
273
|
+
'mock-file-stat',
|
|
274
|
+
isEmptyObj(mockFileStat) ? (mockFileStat = getMockStatFromFile(filePath)) : mockFileStat
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
const async = args => {
|
|
278
|
+
return async next => {
|
|
279
|
+
await genMockFiles(args);
|
|
280
|
+
next();
|
|
281
|
+
};
|
|
269
282
|
};
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
saveDataAsyncTask.add(async(data));
|
|
283
|
+
socket.on('save-data', function (data) {
|
|
284
|
+
// console.log('lis save-data:', data);
|
|
285
|
+
saveDataAsyncTask.add(async(data));
|
|
274
286
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
287
|
+
if (saveDataAsyncTask.list.length === 1) {
|
|
288
|
+
saveDataAsyncTask.run();
|
|
289
|
+
} else {
|
|
290
|
+
saveDataAsyncTask.next();
|
|
291
|
+
}
|
|
292
|
+
// await genMockFiles(data);
|
|
293
|
+
});
|
|
282
294
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
295
|
+
socket.on('disconnect', function () {
|
|
296
|
+
log.info(
|
|
297
|
+
colors.gray(
|
|
298
|
+
`Socket client ${clientIp} has disconnected. --- ${dateFormat('YYYY-mm-dd HH:MM:SS', new Date())}`
|
|
299
|
+
)
|
|
300
|
+
);
|
|
301
|
+
});
|
|
289
302
|
});
|
|
290
|
-
}
|
|
291
|
-
}
|
|
303
|
+
}
|
|
292
304
|
|
|
293
|
-
http.listen(Number.parseInt(process.env.PORT, 10), () => {
|
|
294
|
-
|
|
305
|
+
http.listen(Number.parseInt(process.env.PORT, 10), () => {
|
|
306
|
+
console.info(colors.red('\n Mock File仅支持commonjs规范的js、cjs文件,不支持ES Module'));
|
|
295
307
|
|
|
296
|
-
console.info(
|
|
297
|
-
[
|
|
298
|
-
colors.yellow(`\n${process.env.RESTARTED ? 'Restarting' : 'Starting'} up mock-server, serving `),
|
|
299
|
-
colors.cyan(process.env.SPECIFIED_FILE || process.env.SPECIFIED_DIR),
|
|
300
|
-
colors.yellow(` ${dateFormat('YYYY-mm-dd HH:MM:SS', new Date())}`)
|
|
301
|
-
].join('')
|
|
302
|
-
);
|
|
303
|
-
if (!process.env.RESTARTED) {
|
|
304
308
|
console.info(
|
|
305
|
-
[
|
|
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('')
|
|
306
314
|
);
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
315
|
+
if (!process.env.RESTARTED) {
|
|
316
|
+
console.info(
|
|
317
|
+
[colors.yellow('\n🌍 mock-server version: '), colors.cyan(require('../package.json').version), '\n'].join('')
|
|
318
|
+
);
|
|
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
|
+
}
|
|
326
|
+
});
|
|
314
327
|
});
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
});
|
|
328
|
+
}
|
|
329
|
+
});
|
|
318
330
|
|
|
319
|
-
if (webApp && !process.env.RESTARTED) {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
331
|
+
if (webApp && !process.env.RESTARTED) {
|
|
332
|
+
console.info(colors.red('\n Mock File仅支持commonjs规范的js、cjs文件,不支持ES Module'));
|
|
333
|
+
webApp.listen(Number.parseInt(process.env.WEB_PORT, 10), () => {
|
|
334
|
+
console.info(colors.yellow(`\n Web server available on:\n`));
|
|
335
|
+
console.info(' http://localhost:' + colors.green(process.env.WEB_PORT) + webPublicPath);
|
|
336
|
+
Object.keys(ifaces).forEach(function (dev) {
|
|
337
|
+
ifaces[dev].forEach(function (details) {
|
|
338
|
+
if (details.family === 'IPv4') {
|
|
339
|
+
console.info(' http://' + details.address + ':' + colors.green(process.env.WEB_PORT) + webPublicPath);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
329
342
|
});
|
|
343
|
+
if (!isEmptyObj(proxyTable)) {
|
|
344
|
+
console.info(colors.yellow(`\n Enable proxy at web server on:`));
|
|
345
|
+
Object.keys(proxyTable).forEach(prefix => {
|
|
346
|
+
console.info(` ${prefix} -> ${proxyTable[prefix]}`);
|
|
347
|
+
});
|
|
348
|
+
}
|
|
330
349
|
});
|
|
331
|
-
|
|
332
|
-
console.info(colors.yellow(`\n Enable proxy at web server on:`));
|
|
333
|
-
Object.keys(proxyTable).forEach(prefix => {
|
|
334
|
-
console.info(` ${prefix} -> ${proxyTable[prefix]}`);
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
});
|
|
350
|
+
}
|
|
338
351
|
}
|
|
339
352
|
|
|
340
353
|
if (process.platform === 'win32') {
|
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:
|
|
5
|
+
* @LastEditTime: 2025-06-15 22:16:36
|
|
6
6
|
* @Author : chendq
|
|
7
7
|
*/
|
|
8
8
|
const express = require('express'), // 引入express
|
|
@@ -13,7 +13,6 @@ const { dateFormat, logger } = require('./utils');
|
|
|
13
13
|
const ifaces = os.networkInterfaces();
|
|
14
14
|
const log = logger(process.env.SILENT);
|
|
15
15
|
|
|
16
|
-
let done = false;
|
|
17
16
|
if (!process.env.PORT) {
|
|
18
17
|
portfinder.basePort = 8090;
|
|
19
18
|
portfinder.getPort(function (err, port) {
|
|
@@ -21,38 +20,40 @@ if (!process.env.PORT) {
|
|
|
21
20
|
throw err;
|
|
22
21
|
}
|
|
23
22
|
process.env.PORT = port;
|
|
24
|
-
|
|
23
|
+
startServer();
|
|
25
24
|
});
|
|
26
25
|
} else {
|
|
27
|
-
|
|
26
|
+
startServer();
|
|
28
27
|
}
|
|
29
|
-
// 将异步函数转换为同步代码代码执行
|
|
30
|
-
require('deasync').loopWhile(function () {
|
|
31
|
-
return !done;
|
|
32
|
-
});
|
|
33
|
-
const app = express();
|
|
34
28
|
|
|
35
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Start server
|
|
31
|
+
*/
|
|
32
|
+
function startServer() {
|
|
33
|
+
const app = express();
|
|
34
|
+
|
|
35
|
+
app.use(express.static(process.env.STATIC_DIRECTORY)); // 将dist目录下所有文件作为静态文件来管理
|
|
36
36
|
|
|
37
|
-
app.listen(Number.parseInt(process.env.PORT, 10), () => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
app.listen(Number.parseInt(process.env.PORT, 10), () => {
|
|
38
|
+
console.info(
|
|
39
|
+
[
|
|
40
|
+
colors.yellow(`\nStarting up Static Server, serving `),
|
|
41
|
+
colors.cyan(process.env.STATIC_DIRECTORY),
|
|
42
|
+
colors.yellow(` ${dateFormat('YYYY-mm-dd HH:MM:SS', new Date())}`)
|
|
43
|
+
].join('')
|
|
44
|
+
);
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
console.info(colors.yellow(`\n Static Server available on:\n`));
|
|
47
|
+
console.info(' http://localhost:' + colors.green(process.env.PORT));
|
|
48
|
+
Object.keys(ifaces).forEach(function (dev) {
|
|
49
|
+
ifaces[dev].forEach(function (details) {
|
|
50
|
+
if (details.family === 'IPv4') {
|
|
51
|
+
console.info(' http://' + details.address + ':' + colors.green(process.env.PORT));
|
|
52
|
+
}
|
|
53
|
+
});
|
|
53
54
|
});
|
|
54
55
|
});
|
|
55
|
-
}
|
|
56
|
+
}
|
|
56
57
|
|
|
57
58
|
if (process.platform === 'win32') {
|
|
58
59
|
require('readline')
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mock-service-cli",
|
|
3
|
-
"version": "3.3.
|
|
4
|
-
"description": "🦅 Local mock server",
|
|
3
|
+
"version": "3.3.2",
|
|
4
|
+
"description": "🦅 Local mock server, Static server, SPA server, Http?s request proxy",
|
|
5
5
|
"main": "./lib/mockServer.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mock-service-cli": "bin/mock-service-cli"
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
"start": "node ./bin/mock-service-cli",
|
|
11
11
|
"test:unit": "tap --reporter=spec test/*.test.js",
|
|
12
12
|
"test": "tap --cov --coverage-report=lcov --reporter=spec test/*.test.js ",
|
|
13
|
-
"coverage": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls -v",
|
|
14
13
|
"test-watch": "tap --reporter=spec --watch test/*.test.js",
|
|
15
14
|
"fix": "eslint --ext .js,.vue,.css --fix",
|
|
16
15
|
"prettier": "prettier -c --write \"**/*.{ts,js,jsx,css,less,scss,json}\"",
|
|
@@ -31,14 +30,12 @@
|
|
|
31
30
|
"author": "chendq <deqiaochen@gmail.com>",
|
|
32
31
|
"packageManager": "yarn@1.22.19",
|
|
33
32
|
"keywords": [
|
|
34
|
-
"MIT-licensed",
|
|
35
33
|
"Static Server",
|
|
36
|
-
"
|
|
34
|
+
"Web Server",
|
|
35
|
+
"Mock Server CLI",
|
|
37
36
|
"MockServer",
|
|
38
37
|
"mock-service-cli",
|
|
39
|
-
"
|
|
40
|
-
"Socket server",
|
|
41
|
-
"socket.io"
|
|
38
|
+
"Socket server"
|
|
42
39
|
],
|
|
43
40
|
"repository": {
|
|
44
41
|
"type": "git",
|
|
@@ -49,7 +46,6 @@
|
|
|
49
46
|
"dependencies": {
|
|
50
47
|
"body-parser": "^1.20.2",
|
|
51
48
|
"colors": "^1.4.0",
|
|
52
|
-
"deasync": "^0.1.23",
|
|
53
49
|
"express": "^4.17.1",
|
|
54
50
|
"fs-extra": "^10.0.0",
|
|
55
51
|
"http-proxy-middleware": "^2.0.6",
|