forked from bbyars/mountebank
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmb.js
executable file
·150 lines (126 loc) · 3.81 KB
/
mb.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
'use strict';
const fs = require('fs'),
path = require('path'),
spawn = require('child_process').spawn,
exec = require('child_process').exec,
isWindows = require('os').platform().indexOf('win') === 0,
mbPath = process.env.MB_EXECUTABLE || path.join(process.cwd(), 'bin/mb'),
port = process.env.MB_PORT || 2525,
pidfile = 'mb.pid';
function delay (duration) {
return new Promise(resolve => {
setTimeout(() => resolve(), duration);
});
}
async function whenFullyInitialized (operation, callback) {
let count = 0,
pidfileMustExist = operation === 'start',
spinWait = async () => {
count += 1;
if (count > 20) {
console.log(`ERROR: mb ${operation} not initialized after 2 seconds`);
callback({});
}
else if (fs.existsSync(pidfile) === pidfileMustExist) {
callback({});
}
else {
await delay(100);
await spinWait();
}
};
await spinWait();
}
function shellCommand (args) {
let command = mbPath;
if (isWindows) {
args.unshift(mbPath);
command = 'node';
}
return command;
}
function spawnMb (args) {
const command = shellCommand(args),
mb = spawn(command, args, { detached: true, stdio: 'ignore' });
console.log(`${command} ${args.join(' ')}`);
mb.unref();
return mb;
}
async function start (args) {
const mbArgs = ['restart', '--port', port, '--pidfile', pidfile].concat(args || []);
if (process.env.MB_PERSISTENT === 'true') {
mbArgs.push('--datadir');
mbArgs.push('.mbdb');
}
return new Promise((resolve, reject) => {
whenFullyInitialized('start', resolve);
const mb = spawnMb(mbArgs);
mb.on('error', reject);
});
}
async function stop () {
let command = `${mbPath} stop --pidfile ${pidfile}`;
if (isWindows) {
command = `node ${command}`;
}
return new Promise(resolve => {
console.log(command);
exec(command, (error, stdout, stderr) => {
if (error) { throw error; }
if (stdout) { console.log(stdout); }
if (stderr) { console.error(stderr); }
whenFullyInitialized('stop', resolve);
});
});
}
// Can't simply call mb restart
// The start function relies on whenFullyInitialized to wait for the pidfile to already exist
// If it already does exist, and you're expecting mb restart to kill it, the function will
// return before you're ready for it
async function restart (args) {
await stop(args);
await start(args);
}
async function execCommand (command, args) {
let mbArgs = [command, '--port', port].concat(args || []);
return new Promise((resolve, reject) => {
const mb = spawnMb(mbArgs);
mb.on('error', reject);
mb.on('exit', resolve);
});
}
async function save (args) {
return execCommand('save', args);
}
async function replay (args) {
return execCommand('replay', args);
}
async function execute (command, args) {
switch (command) {
case 'start':
await start(args);
break;
case 'restart':
await restart(args);
break;
case 'stop':
await stop(args);
break;
case 'save':
await save(args);
break;
case 'replay':
await replay(args);
break;
default:
throw new Error(`invalid command: ${command}`);
}
}
const command = process.argv[2],
args = process.argv.slice(3);
execute(command, args)
.then(() => process.exit(0)) // eslint-disable-line no-process-exit
.catch(err => {
console.error(err);
process.exit(1); // eslint-disable-line no-process-exit
});