-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
executable file
·122 lines (106 loc) · 3.9 KB
/
server.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
#!/usr/bin/env node
'use strict';
const handleStatic = require('./util/static-server');
const app = require('http').createServer(handleStatic);
const io = require('socket.io')(app, {serveClient: false});
const chalk = require('chalk');
const pty = require('node-pty');
const {args, requiredArgErrors} = require('./util/arguments');
const stringArgv = require('string-argv');
const {line, helpScreen} = require('./util/output-helpers');
const {port, cmd, multi, help, historyLines, clientArgs} = args;
let {interactive} = args;
if (help || requiredArgErrors.length) {
if (requiredArgErrors.length && !help) {
process.stdout.write(`\n${requiredArgErrors.join('\n')}\n`);
process.exitCode = 1;
}
process.stdout.write(helpScreen());
process.exit();
}
const cmdSplit = cmd.split(' ');
const cmdBin = cmdSplit.shift();
const cmdParams = stringArgv(cmdSplit.join(' '));
const singleSessionHistoryLines = parseInt(historyLines, 10);
const status = require('./util/status');
const [defCols, defRows] = [parseInt(args.cols, 10), parseInt(args.rows, 10)];
const [cwd, env] = [process.cwd(), process.env];
const makeSession = (params = {path: cmdParams, query: []}) => {
const sessionParams = [...params.path, ...params.query];
const sessionInst = pty.spawn(cmdBin, sessionParams, {cols: defCols, rows: defRows, cwd, env});
status.addSession(sessionInst);
sessionInst.on('exit', code => status.removeSession(sessionInst, code && 'fail' || 'succeed'));
return sessionInst;
};
const exitMsg = (cols, code) => line(cols, 'end', chalk[code === 0 ? 'yellow' : 'red']);
let singleSession = null;
let singleSessionBuffer = '';
if (!multi) {
// start up single session
singleSession = makeSession();
singleSession.on('data', d => {
singleSessionBuffer += d;
if (singleSessionBuffer.split('\n').length > singleSessionHistoryLines) {
singleSessionBuffer = singleSessionBuffer
.split('\n')
.slice(singleSessionHistoryLines * -1)
.join('\n');
}
});
singleSession.on('exit', code => {
interactive = 'off';
singleSessionBuffer += exitMsg(defCols, code);
});
}
io.on('connection', function (socket) {
status.addClient(socket);
socket.on('disconnect', () => status.removeClient(socket));
let [cols, rows] = [defCols, defRows];
let sessionInteractive = false;
const clientAddress = socket.conn.remoteAddress.replace(/^.*?([\d\.]+).*?$/, '$1');
const localAddrs = ['127.0.0.1', '1'];
const isLocal = localAddrs.includes(clientAddress);
if (interactive === 'local' && isLocal) { sessionInteractive = true; }
if (interactive === 'all') { sessionInteractive = true; }
const cmd = cmdParams.reduce((acc, v) => {
const isSwitch = v.startsWith('-') || v.startsWith('/');
if (acc.query.length === 0 && !isSwitch) {
acc.path.push(v);
} else {
acc.query.push(v);
}
return acc;
}, {path:[], query:[], bin: cmdBin});
const handleSessionData = d => socket.emit('output', d);
if (!multi) { socket.emit('output', singleSessionBuffer); }
socket.on('client-config', (cfg) => {
if (clientArgs && multi) {
const hasPathParams = cfg.cmd.path && cfg.cmd.path.length;
const hasQueryParams = cfg.cmd.query && cfg.cmd.query.length;
if (hasPathParams || hasQueryParams || cfg.cmd.bin) {
cmd.path = cfg.cmd.path;
cmd.query = cfg.cmd.query;
}
}
const session = (multi ? makeSession(cmd) : singleSession);
if (multi) {
({cols, rows} = cfg);
session.resize(cols, rows);
}
socket.emit('server-config', {
interactive: sessionInteractive,
multi, cmd, cols, rows
});
session.on('data', handleSessionData);
session.on('exit', code => socket.emit('output', exitMsg(cols, code)));
if (sessionInteractive) { socket.on('input', d => session.write(d)); }
socket.on('disconnect', () => {
socket.removeAllListeners();
session.removeListener('data', handleSessionData);
if (multi) { session.destroy(); }
});
});
});
app.listen(port, (err) => {
if (err) { return console.log('something bad happened', err); }
});