UNPKG

vrem

Version:

An open-source automatic time-tracker

125 lines (124 loc) 4.39 kB
"use strict"; 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;