OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-booking / node_modules / bare-inspector / lib / server.js

120 lines · javascript ref:
const EventEmitter = require('bare-events')
const url = require('bare-url')
const ws = require('bare-ws')
const http = require('bare-http1')
const Session = require('./session')

module.exports = class InspectorServer extends EventEmitter {
  constructor(port, host, opts = {}) {
    if (typeof port === 'object' && port !== null) {
      opts = port
      port = 0
      host = 'localhost'
    } else if (typeof host === 'object' && host !== null) {
      opts = host
      host = 'localhost'
    }

    const { path = require.main.path } = opts

    super()

    this._path = typeof path === 'string' ? url.pathToFileURL(path) : path
    this._sessions = new Map()

    this._server = new ws.Server(
      {
        server: new http.Server(this._onrequest.bind(this)).listen(
          { port, host },
          this._onlistening.bind(this)
        )
      },
      this._onconnection.bind(this)
    )
  }

  get listening() {
    return this._server.listening
  }

  address() {
    return this._server.address()
  }

  close(cb) {
    for (const socket of this._sessions.keys()) socket.destroy()

    return this._server.close(cb)
  }

  ref() {
    this._server.ref()
  }

  unref() {
    this._server.unref()
  }

  _onlistening() {
    this.emit('listening')
  }

  _onrequest(req, res) {
    if (req.url === '/json/list') return this._onlist(req, res)

    res.writeHead(404)
    res.end()
  }

  _onconnection(socket) {
    const sessions = this._sessions

    const session = new Session()

    sessions.set(socket, session)

    session.on('inspectorNotification', onnotification).connect()

    socket.on('close', onclose).on('data', ondata)

    function onnotification(message) {
      socket.write(JSON.stringify(message))
    }

    function onclose() {
      session.destroy()
      sessions.delete(socket)
    }

    function ondata(data) {
      const { id, method, params } = JSON.parse(data)

      session.post(method, params, (err, result) => {
        const response = err ? { id, error: err } : { id, result }

        socket.write(JSON.stringify(response))
      })
    }
  }

  _onlist(req, res) {
    res.writeHead(200, { 'Content-Type': 'application/json' })

    const { address, port } = this.address()

    res.end(
      JSON.stringify([
        {
          title: `bare[${Bare.pid}]`,
          id: `${Bare.pid}`,
          type: 'node',
          url: this._path,
          devtoolsFrontendUrl: `devtools://devtools/bundled/js_app.html?ws=${address}:${port}`,
          webSocketDebuggerUrl: `ws://${address}:${port}`,
          faviconUrl: 'https://holepunch.to/favicon.ico'
        }
      ])
    )
  }
}