143 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
const ipc = require('@achrinza/node-ipc')
 | 
						|
 | 
						|
const DEFAULT_ID = process.env.VUE_CLI_IPC || 'vue-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.VUE_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 = {
 | 
						|
          _projectId: PROJECT_ID,
 | 
						|
          _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)
 | 
						|
    })
 | 
						|
  }
 | 
						|
}
 |