vrem
Version:
An open-source automatic time-tracker
125 lines (124 loc) • 4.39 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.IpcServer = exports.ipcRequest = exports.PersistentConnection = exports.createSequentialSocket = void 0;
const net = require('net');
const { version } = require('../package.json');
function createSequentialSocket(socket) {
const sendRejects = new Set();
let previousPromise = null;
socket.on('error', (e) => {
sendRejects.forEach(reject => reject(e));
sendRejects.clear();
});
return Object.assign(socket, {
send(payload = null) {
const promiseToWait = previousPromise;
previousPromise = new Promise(async (resolve, reject) => {
try {
await promiseToWait;
}
catch (e) { }
sendRejects.add(reject);
socket.write(JSON.stringify(payload), () => {
sendRejects.delete(reject);
resolve();
});
});
return previousPromise;
},
});
}
exports.createSequentialSocket = createSequentialSocket;
class PersistentConnection {
constructor(socketPath, reconnectTimeout = 3000) {
this.reconnectTimeout = reconnectTimeout;
const socket = this.socket = createSequentialSocket(net.createConnection(socketPath));
socket.setEncoding('utf8');
// socket.on('connect', () => {
// console.log('connected');
// })
socket.on('close', (had_error) => {
//console.log('close', had_error);
setTimeout(() => this.socket.connect(socketPath), reconnectTimeout);
});
}
onConnect(callback) {
this.socket.on('connect', callback);
}
onClose(callback) {
this.socket.on('close', callback);
}
onData(callback) {
this.socket.on('data', (data) => {
callback(JSON.parse(data));
});
}
send(...args) {
return this.socket.send(...args);
}
;
}
exports.PersistentConnection = PersistentConnection;
function ipcRequest(socketPath, command, payload = null) {
return new Promise(((resolve, reject) => {
try {
const socket = net.createConnection(socketPath, () => {
socket.setEncoding('utf8');
socket.on('data', data => {
socket.destroy();
resolve(JSON.parse(data));
});
socket.write(JSON.stringify({ command, payload }));
});
socket.once('error', e => {
reject(e);
});
socket.once('close', had_error => {
had_error ? reject('Some socket error') : resolve('');
});
}
catch (e) {
reject(e);
}
}));
}
exports.ipcRequest = ipcRequest;
class IpcServer {
constructor() {
this.handlers = {
ping: () => ({
version: version,
name: "vrem",
}),
exit: (payload, socket) => socket.write('true', () => process.exit()),
};
this.server = net.createServer(socket => {
socket.setEncoding('utf8');
socket.on('data', async (json) => {
const { command, payload } = JSON.parse(json);
if (this.handlers[command]) {
const result = await this.handlers[command](payload, socket);
if (result !== undefined) {
socket.write(JSON.stringify(result));
}
else if (this.handlers[command].length < 2) {
throw new Error('IPC command handler should either return some value or write it manually');
}
}
else {
socket.write(JSON.stringify(`No handler for the command ${command}`));
}
});
});
this.server.on('error', (err) => {
throw err;
});
}
command(command, handler) {
this.handlers[command] = handler;
}
listen(socketPath, callback) {
this.server.listen(socketPath, callback);
}
}
exports.IpcServer = IpcServer;