<repo_name>IDEO-coLAB/nomad-dht-shim<file_sep>/src/index.js
const Hapi = require('hapi')

const { applyError, missingDataError, missingNodeIdError } = require('./error')
const store = require('./store')

const PORT = 8000

const server = new Hapi.Server()

server.connection({
  // host: 'localhost',
  port: PORT
})

server.route({
  method: 'POST',
  path:'/connect',
  handler: function (request, reply) {
    const data = request.payload
    if (!data) {
      return applyError(reply, missingDataError)
    }

    const nodeId = data.id
    if (!nodeId) {
      return applyError(reply, missingNodeIdError)
    }

    // TODO: check for multiaddrs

    return store.set(nodeId, data)
      .then(() => reply(true))
      .catch(err => applyError(reply, err))
  }
})

server.route({
  method: 'DELETE',
  path:'/connect',
  handler: function (request, reply) {
    const data = request.payload
    if (!data) {
      return applyError(reply, missingDataError)
    }

    const nodeId = data.id
    if (!nodeId) {
      return applyError(reply, missingNodeIdError)
    }
    return store.remove(nodeId)
      .then(() => reply(true))
      .catch(err => applyError(reply, err))
  }
})

server.route({
  method: 'GET',
  path:'/connect',
  handler: function (request, reply) {
    const nodeId = request.query.id

    if (!nodeId) {
      return applyError(reply, missingNodeIdError)
    }
    return store.get(nodeId)
      .then((peerInfo) => {
        const result = peerInfo || null
        return reply(JSON.stringify(result))
      })
      .catch(err => applyError(reply, err))
  }
})

// Start the shim server
server.start((err) => {
  if (err) {
    throw err
  }
  console.log('Shim server listening on port:', server.info.uri)
  // console.log(server.info)
})
<file_sep>/README.md
# Nomad signal server
Docker container for running a WebRTCStar signaling server.
See https://github.com/libp2p/js-libp2p-webrtc-star for more details.
<file_sep>/src/error.js
exports = module.exports

exports.missingNodeIdError = new Error('Missing node id')
exports.missingDataError = new Error('Missing data')

exports.applyError = (reply, error) => {
  const code = 400
  return reply({
    message: error.message,
    code: code
  }).code(code)
}
<file_sep>/Dockerfile
#Choose a base image
FROM node:6.9.4

# Create a new folder for our application
RUN mkdir -p /app

# Set the working dir when our container executes
WORKDIR /app

# Copy our package.json file
ADD package.json /app

# Install our packages
RUN npm install

# Copy the rest of our application
COPY . /app

#Expose our application port
EXPOSE 8000

# Set start command
CMD ["npm", "start"]
<file_sep>/src/store.js
const Datastore = require('nedb')

exports = module.exports

const DB_PATH = 'store/peer-id-store'

class Store {
  constructor (path = DB_PATH) {
    this.db = new Datastore({ filename: path, autoload: true })
  }

  get (node) {
    return new Promise((resolve, reject) => {
      this.db.findOne({ node }, (err, object) => {
        if (err) {
          reject(err)
          return
        }
        if (object === null) {
          resolve(null)
          return
        }
        resolve(object.object)
        return
      })
    })
  }

  set (node, object) {
    const errorUpdateNotFound = new Error(`Failed to update ${node}: Not found`)

    return new Promise((resolve, reject) => {
      this.db.findOne({ node }, (err, found) => {
        if (err) {
          reject(err)
          return
        }

        // If no object is found, create one
        if (!found) {
          this.db.insert({ node, object }, (err, newObj) => {
            if (err) {
              reject(err)
              return
            }
            resolve(newObj.object)
          })
          return
        }

        // Otherwise update the existing one
        this.db.update({ node },
          { $set: { object: object } },
          (err, numUpdated) => {
            if (err) {
              reject(err)
              return
            }

            if (numUpdated === 0) {
              reject(errorUpdateNotFound)
              return
            }
            // Return the most recent one
            this.db.findOne({ node }, (err, updatedObj) => {
              if (err) {
                reject(err)
                return
              }
              resolve(updatedObj.object)
            })
          }
        )
      })
    })
  }

  remove (node) {
    return new Promise((resolve, reject) => {
      this.db.remove({ node }, (err, numRemoved) => {
        if (err) {
          reject(err)
          return
        }
        resolve(numRemoved)
        return
      })
    })
  }
}

module.exports = new Store()
