pouchdb / pouchdb-server

CouchDB-compatible server built on PouchDB and Node
Apache License 2.0
955 stars 154 forks source link

Discussion: custom PouchDB Server builds #234

Open gr2m opened 7 years ago

gr2m commented 7 years ago
⚠️ This is just me dreamcodin. The code shown here doesn’t exist, it’s just meant as a base for discussion

I would like to create a custom server which exposes only the CouchDB APIs that I need, similar to PouchDB’s custom builds which only have the features that I need.

const PouchDB = require('PouchDB')
const express = require('express')
const app = express()

app.get('/', function (req, res) {
  res.status(200).send({
      'my-custom-couch': 'Welcome!'
  })
})

app.use(require('@pouchdb-server/express-core')(PouchDB))
app.use(require('@pouchdb-server/express-db')(PouchDB))
app.use(require('@pouchdb-server/express-document')(PouchDB))
app.use(require('@pouchdb-server/express-changes')(PouchDB))
app.use(require('@pouchdb-server/express-attachments')(PouchDB))

app.listen(3000, function () {
  console.log('Listening on port 3000!')
})

A package like pouchdb-express-router could then be implemented like this

const Router = require('express').express.Router

module.exports = function (PouchDB) {
  const router = Router()

  router.use(require('@pouchdb-server/express-core')(PouchDB))
  router.use(require('@pouchdb-server/express-db')(PouchDB))
  router.use(require('@pouchdb-server/express-document')(PouchDB))
  router.use(require('@pouchdb-server/express-changes')(PouchDB))
  router.use(require('@pouchdb-server/express-attachments')(PouchDB))

  return router
}

and be used like this

const PouchDB = require('PouchDB')
const express = require('express')
const app = express()

app.get('/', function (req, res) {
  res.status(200).send({
      'my-custom-couch': 'Welcome!'
  })
})

app.use(require('express-pouchdb-router')(PouchDB))

app.listen(3000, function () {
  console.log('Listening on port 3000!')
})

An "all inclusive" express middleware could be published as @pouchdb-server/express

Dreaming @pouchdb-server/security & @pouchdb-server/express-security

Just as it is today, I would like to separate logic like CouchDB’s security into two packages:

  1. @pouchdb-server/security
    A generic module with APIs needed for security. It uses the passed PouchDB to persist and lookup security settings
  2. @pouchdb-server/express-security
    An express middleware which uses the security module in its route handlers. The logic in the route handlers should be minimal, the bulk of the work should happen in the security module

@pouchdb-server/express-security would look something like this

const Security = require('@pouchdb-server/security')
const Router = require('express').Router

module.exports = function (PouchDB) {
  const router = new Router()
  const security = new Security(PouchDB)

  app.use('/:db(/*)?', function (req, res) {
    security.check(req.params.db, next)
  })

  app.get('/:db/_security', function (req, res) {
    security.get(req.params.db, (error, settings) => {
      // I don’t know express error handling works
      // I’d expect we could define a general error handler
      // in @pouchdb-server/express-core
      if (error) throw error

      res.send(settings)
    })
  })

  app.put('/:db/_security', require('body-parser'), function (req, res) {
    security.update(req.params.db, req.body, (error, settings) => {
      // I don’t know express error handling works
      // I’d expect we could define a general error handler
      // in @pouchdb-server/express-core
      if (error) throw error

      res.send({ok: true})
    })
  })
}

@pouchdb-server/security would keep a local cache of the current database security setting for faster lookup. It could store the security setting internally in a _local/security document.

I’m sure there is lot of things I did not consider. But I think it would be good to get a conversation going of where we want to go with PouchDB Server. And this is my input :)

gr2m commented 7 years ago

ping @nolanlawson @daleharvey @garrensmith

garrensmith commented 7 years ago

@gr2m I like the ideas here. The big thing for me is that the PouchDB core team is really small. So any changes we do to PouchDB-server need to make it easier to maintain. Ideally pouchdb-server needs to be a super thin layer on top of PouchDB.

gr2m commented 7 years ago

I want to help maintaining PouchDB Server and agree :100:

marten-de-vries commented 7 years ago

It's hard to split pouchdb-server up into a bunch of independent routes. I tried, the current 'mode' functionality which allows for enabling/disabling stuff but still keeps everything inside the express-pouchdb module was the best I could do. I don't remember the details, but there is just too much shared state between modules necessary IIRC. The most obvious one being the configuration and a (wrapped) PouchDB object, but there's probably more.

It might actually be easier to do this when building it on top of pouchdb-express-router. But that does mean doing away with some couchdb compatibility, and it hasn't been updated recently so there's probably still a couple of bugs (https://github.com/pouchdb/pouchdb-express-router/issues/5).