san-cli-utils
Version:
San CLI 中所用到的工具类函数:
168 lines (141 loc) • 4.27 kB
JavaScript
/**
* The MIT License (MIT)
* Copyright (c) 2017-present, Yuxi (Evan) You
*
* This source code is licensed under the MIT license found in the
* LICENSE file at
* https://github.com/vuejs/vue-cli/blob/dev/LICENSE
*
* Reference: https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-shared-utils/lib/ipc.js
*/
const ipc = require('node-ipc');
const DEFAULT_ID = process.env.SAN_CLI_IPC || 'san-cli';
const DEFAULT_IDLE_TIMEOUT = 3000;
const DEFAULT_OPTIONS = {
networkId: DEFAULT_ID,
autoConnect: true,
disconnectOnIdle: false,
idleTimeout: DEFAULT_IDLE_TIMEOUT,
namespaceOnProject: true
};
const PROJECT_ID = process.env.SAN_CLI_PROJECT_ID;
exports.IpcMessenger = class IpcMessenger {
constructor(options = {}) {
options = Object.assign({}, DEFAULT_OPTIONS, options);
ipc.config.id = this.id = options.networkId;
ipc.config.retry = 1500;
ipc.config.silent = true;
this.connected = false;
this.connecting = false;
this.disconnecting = false;
this.queue = null;
this.options = options;
this.listeners = [];
this.disconnectTimeout = 15000;
this.idleTimer = null;
// Prevent forced process exit
// (or else ipc messages may not be sent before kill)
process.exit = code => {
process.exitCode = code;
};
this._reset();
}
checkConnection() {
if (!ipc.of[this.id]) {
this.connected = false;
}
}
send(data, type = 'message') {
this.checkConnection();
if (this.connected) {
if (this.options.namespaceOnProject && PROJECT_ID) {
data = {
// eslint-disable-next-line
_projectId: PROJECT_ID,
// eslint-disable-next-line
_data: data
};
}
ipc.of[this.id].emit(type, data);
clearTimeout(this.idleTimer);
if (this.options.disconnectOnIdle) {
this.idleTimer = setTimeout(() => {
this.disconnect();
}, this.options.idleTimeout);
}
}
else {
this.queue.push(data);
if (this.options.autoConnect && !this.connecting) {
this.connect();
}
}
}
connect() {
this.checkConnection();
if (this.connected || this.connecting) {
return;
}
this.connecting = true;
this.disconnecting = false;
ipc.connectTo(this.id, () => {
this.connected = true;
this.connecting = false;
this.queue && this.queue.forEach(data => this.send(data));
this.queue = null;
ipc.of[this.id].on('message', this._onMessage);
});
}
disconnect() {
this.checkConnection();
if (!this.connected || this.disconnecting) {
return;
}
this.disconnecting = true;
this.connecting = false;
const ipcTimer = setTimeout(() => {
this._disconnect();
}, this.disconnectTimeout);
this.send({
done: true
}, 'ack');
ipc.of[this.id].on('ack', data => {
if (data.ok) {
clearTimeout(ipcTimer);
this._disconnect();
}
});
}
on(listener) {
this.listeners.push(listener);
}
off(listener) {
const index = this.listeners.indexOf(listener);
if (index !== -1) {
this.listeners.splice(index, 1);
}
}
_reset() {
this.queue = [];
this.connected = false;
}
_disconnect() {
this.connected = false;
this.disconnecting = false;
ipc.disconnect(this.id);
this._reset();
}
_onMessage(data) {
this.listeners.forEach(fn => {
if (this.options.namespaceOnProject && data._projectId) {
if (data._projectId === PROJECT_ID) {
data = data._data;
}
else {
return;
}
}
fn(data);
});
}
};