forked from pouchdb/pouchdb-express-router
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4077a8f
Showing
6 changed files
with
510 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
'use strict'; | ||
|
||
var app = require('express')(); | ||
|
||
var routes = { | ||
'db': require('./lib/routes/db.js'), | ||
'document': require('./lib/routes/document.js'), | ||
'attachments': require('./lib/routes/attachments.js') | ||
}; | ||
|
||
module.exports = function(PouchDB) { | ||
|
||
app.use(function (req, res, next) { | ||
for (var prop in req.query) { | ||
try { | ||
req.query[prop] = JSON.parse(req.query[prop]); | ||
} catch (e) {} | ||
} | ||
next(); | ||
}); | ||
|
||
app.get('/', function (req, res) { | ||
res.status(200).send({'pouchdb-express-router': 'Welcome!'}); | ||
}); | ||
|
||
app.get('/_session', function (req, res) { | ||
res.status(200).send({ | ||
'ok': true, | ||
'userCtx':{"name":null,"roles":["_admin"]} | ||
}); | ||
}); | ||
|
||
routes.db(app, PouchDB); | ||
routes.attachments(app, PouchDB); | ||
routes.document(app, PouchDB); | ||
|
||
app.use(function (req, res) { | ||
res.status(404).send( { | ||
error: "not_found", | ||
reason: "missing" | ||
}); | ||
}); | ||
|
||
return app; | ||
}; | ||
|
||
// Used for testing porpoises | ||
var PouchDB = require('pouchdb'); | ||
module.exports(PouchDB); | ||
app.listen(5985); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
'use strict'; | ||
|
||
var rawBody = require('raw-body'); | ||
|
||
var utils = require('../utils.js'); | ||
|
||
function parseRawBody(req, res, next) { | ||
if (req.params.id === '_design' || req.params.id === '_local') { | ||
return next(); | ||
} | ||
rawBody(req, { | ||
length: req.headers['content-length'] | ||
}, function (err, string) { | ||
if (err) { | ||
return next(err) | ||
} | ||
req.rawBody = string | ||
next() | ||
}); | ||
} | ||
|
||
function putAttachment(db, name, req, res) { | ||
var attachment = req.params.attachment | ||
var rev = req.query.rev; | ||
var type = req.get('Content-Type') || 'application/octet-stream'; | ||
var body = new Buffer(req.rawBody || '', 'binary'); | ||
var opts = req.query; | ||
|
||
req.db.putAttachment(name, attachment, rev, body, | ||
type, opts, function (err, response) { | ||
if (err) return utils.sendError(res, err); | ||
utils.sendJSON(res, 201, response); | ||
}); | ||
} | ||
|
||
// Retrieve a document attachment | ||
function getAttachment(name, req, res) { | ||
var attachment = req.params.attachment; | ||
var opts = req.query; | ||
|
||
req.db.get(name, opts, function (err, info) { | ||
if (err) return utils.sendError(res, err); | ||
|
||
if (!info._attachments || !info._attachments[attachment]) { | ||
return utils.sendJSON(res, 404, { | ||
error:'not_found', | ||
reason:'missing' | ||
}); | ||
}; | ||
|
||
var type = info._attachments[attachment].content_type; | ||
var md5 = info._attachments[attachment].digest.slice(4); | ||
|
||
req.db.getAttachment(name, attachment, function (err, response) { | ||
if (err) return utils.sendError(res, err); | ||
res.setHeader('Content-Type', type); | ||
res.status(200).send(response); | ||
}); | ||
}); | ||
} | ||
|
||
// Delete a document attachment | ||
function deleteAttachment(name, req, res) { | ||
var name = req.params.id; | ||
var attachment = req.params.attachment; | ||
var rev = req.query.rev; | ||
var opts = req.query; | ||
|
||
req.db.removeAttachment(name, attachment, rev, function (err, response) { | ||
if (err) return utils.sendError(res, err); | ||
utils.sendJSON(res, 200, response); | ||
}); | ||
} | ||
|
||
|
||
module.exports = function(app, PouchDB) { | ||
|
||
app.put('/:db/_design/:id/:attachment(*)', parseRawBody, function (req, res, next) { | ||
putAttachment(req.params.db, '_design/' + req.params.id, req, res); | ||
}); | ||
|
||
app.put('/:db/:id/:attachment(*)', parseRawBody, function (req, res, next) { | ||
// Be careful not to catch normal design docs or local docs | ||
if (req.params.id === '_design' || req.params.id === '_local') { | ||
return next(); | ||
} | ||
putAttachment(req.params.db, req.params.id, req, res); | ||
}); | ||
|
||
app.get('/:db/_design/:id/:attachment(*)', function (req, res, next) { | ||
getAttachment('_design/' + req.params.id, req, res); | ||
}); | ||
|
||
app.get('/:db/:id/:attachment(*)', function (req, res, next) { | ||
// Be careful not to catch normal design docs or local docs | ||
if (req.params.id === '_design' || req.params.id === '_local') { | ||
return next(); | ||
} | ||
getAttachment(req.params.id, req, res); | ||
}); | ||
|
||
app.delete('/:db/_design/:id/:attachment(*)', function (req, res, next) { | ||
deleteAttachment('_design/' + req.params.id, req, res); | ||
}); | ||
|
||
app.delete('/:db/:id/:attachment(*)', function (req, res, next) { | ||
// Be careful not to catch normal design docs or local docs | ||
if (req.params.id === '_design' || req.params.id === '_local') { | ||
return next(); | ||
} | ||
deleteAttachment(req.params.id, req, res); | ||
}); | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
'use strict'; | ||
|
||
var jsonParser = require('body-parser').json({limit: '1mb'}); | ||
var extend = require('extend'); | ||
|
||
var utils = require('../utils.js'); | ||
|
||
module.exports = function(app, PouchDB) { | ||
|
||
// Create a database | ||
app.put('/:db', jsonParser, function (req, res, next) { | ||
var name = encodeURIComponent(req.params.db); | ||
new PouchDB(name, function (err, db) { | ||
if (err) return res.status(412).send(err); | ||
res.status(201).send({ok: true}); | ||
}); | ||
}); | ||
|
||
// Delete a database | ||
app.delete('/:db', function (req, res, next) { | ||
var name = encodeURIComponent(req.params.db); | ||
PouchDB.destroy(name, function (err, info) { | ||
if (err) return res.status(500).send(err); | ||
res.status(200).send({ok: true }); | ||
}); | ||
}); | ||
|
||
['/:db/*','/:db'].forEach(function (route) { | ||
app.all(route, function (req, res, next) { | ||
var name = encodeURIComponent(req.params.db); | ||
new PouchDB(name, function (err, db) { | ||
if (err) return res.status(412).send(err); | ||
req.db = db; | ||
next(); | ||
}); | ||
}); | ||
}); | ||
|
||
// Get database information | ||
app.get('/:db', function (req, res, next) { | ||
req.db.info(function (err, info) { | ||
if (err) return res.status(500).send(err); | ||
res.status(200).send(info); | ||
}); | ||
}); | ||
|
||
// Bulk docs operations | ||
app.post('/:db/_bulk_docs', jsonParser, function (req, res, next) { | ||
var opts = 'new_edits' in req.body | ||
? { new_edits: req.body.new_edits } : {}; | ||
|
||
if (Array.isArray(req.body)) { | ||
return res.status(400).send({ | ||
error: "bad_request", | ||
reason: "Request body must be a JSON object" | ||
}); | ||
} | ||
|
||
req.db.bulkDocs(req.body, opts, function (err, response) { | ||
if (err) return utils.sendError(res, err); | ||
res.status(201).send(response); | ||
}); | ||
}); | ||
|
||
// All docs operations | ||
app.all('/:db/_all_docs', jsonParser, function (req, res, next) { | ||
if (req.method !== 'GET' && req.method !== 'POST') return next(); | ||
|
||
// Check that the request body, if present, is an object. | ||
if (!!req.body && (typeof req.body !== 'object' || Array.isArray(req.body))) { | ||
return res.status(400).send({ | ||
reason: "Something wrong with the request", | ||
error: 'bad_request' | ||
}); | ||
} | ||
|
||
var opts = extend({}, req.body, req.query); | ||
req.db.allDocs(opts, function (err, response) { | ||
if (err) return res.status(500).send(err); | ||
res.status(200).send(response); | ||
}); | ||
}); | ||
|
||
// Monitor database changes | ||
app.get('/:db/_changes', function (req, res, next) { | ||
req.query.query_params = JSON.parse(JSON.stringify(req.query)); | ||
|
||
if (req.query.feed === 'continuous' || req.query.feed === 'longpoll') { | ||
var heartbeatInterval; | ||
var heartbeat = (typeof req.query.heartbeat === 'number') | ||
? req.query.heartbeat : 6000; | ||
var written = false; | ||
heartbeatInterval = setInterval(function () { | ||
written = true; | ||
res.write('\n'); | ||
}, heartbeat); | ||
|
||
var cleanup = function () { | ||
if (heartbeatInterval) { | ||
clearInterval(heartbeatInterval); | ||
} | ||
}; | ||
|
||
if (req.query.feed === 'continuous') { | ||
req.query.live = req.query.continuous = true; | ||
req.db.changes(req.query).on('change', function (change) { | ||
written = true; | ||
res.write(JSON.stringify(change) + '\n'); | ||
}).on('error', function (err) { | ||
if (!written) { | ||
utils.sendError(res, err); | ||
} else { | ||
res.end(); | ||
} | ||
cleanup(); | ||
}); | ||
} else { // longpoll | ||
// first check if there are >0. if so, return them immediately | ||
req.query.live = req.query.continuous = false; | ||
req.db.changes(req.query).on('complete', function (complete) { | ||
if (!complete.results) { | ||
// canceled, ignore | ||
cleanup(); | ||
} else if (complete.results.length) { | ||
written = true; | ||
res.write(JSON.stringify(complete) + '\n'); | ||
res.end(); | ||
cleanup(); | ||
} else { // do the longpolling | ||
req.query.live = req.query.continuous = true; | ||
var changes = req.db.changes(req.query).on('change', function (change) { | ||
written = true; | ||
res.write(JSON.stringify({ | ||
results: [change], | ||
last_seq: change.seq | ||
}) + '\n'); | ||
res.end(); | ||
changes.cancel(); | ||
cleanup(); | ||
}).on('error', function (err) { | ||
if (!written) { | ||
utils.sendError(res, err); | ||
} | ||
cleanup(); | ||
}); | ||
} | ||
}).on('error', function (err) { | ||
if (!written) { | ||
utils.sendError(res, err); | ||
} | ||
cleanup(); | ||
}); | ||
} | ||
} else { // straight shot, not continuous | ||
req.query.complete = function (err, response) { | ||
if (err) return utils.sendError(res, err); | ||
res.status(200).send(response); | ||
}; | ||
req.db.changes(req.query); | ||
} | ||
}); | ||
|
||
// DB Compaction | ||
app.post('/:db/_compact', jsonParser, function (req, res, next) { | ||
req.db.compact(req.query, function (err, response) { | ||
if (err) return utils.sendError(res, err); | ||
res.status(200).send({ok: true}); | ||
}); | ||
}); | ||
|
||
// Revs Diff | ||
app.post('/:db/_revs_diff', jsonParser, function (req, res, next) { | ||
req.db.revsDiff(req.body || {}, req.query, function (err, diffs) { | ||
if (err) return utils.sendError(res, err); | ||
res.status(200).send(diffs); | ||
}); | ||
}); | ||
|
||
|
||
// Query a document view | ||
app.get('/:db/_design/:id/_view/:view', function (req, res, next) { | ||
var query = req.params.id + '/' + req.params.view; | ||
req.db.query(query, req.query, function (err, response) { | ||
if (err) return res.status(500).send(err); | ||
res.status(200).send(response); | ||
}); | ||
}); | ||
|
||
// Temp Views | ||
app.post('/:db/_temp_view', jsonParser, function (req, res, next) { | ||
if (req.body.map) req.body.map = (new Function('return ' + req.body.map))(); | ||
req.query.conflicts = true; | ||
req.db.query(req.body, req.query, function (err, response) { | ||
if (err) return utils.sendError(res, err); | ||
utils.sendJSON(res, 200, response); | ||
}); | ||
}); | ||
|
||
|
||
}; |
Oops, something went wrong.