Skip to content

Commit b3d2487

Browse files
committed
Resource methods to single handler, before hooks
1 parent 119b484 commit b3d2487

2 files changed

Lines changed: 33 additions & 43 deletions

File tree

index.js

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ const jsonwebtoken = require('jsonwebtoken')
77
const tinyParams = require('tiny-params')
88
const port = process.env.PORT || process.env.port || 8091
99
const handlers = {
10-
search: resourceSearch,
11-
create: resourceCreate,
12-
read: resourceRead,
13-
update: resourceUpdate,
14-
delete: resourceDelete
10+
search: (name, req) => findAll(name, req.params),
11+
create: (name, req) => create(name, req.params),
12+
read: (name, req) => find(name, req.id, req.params),
13+
update: (name, req) => save(name, req.id, req.params),
14+
delete: (name, req) => destroy(name, req.id, req.params)
1515
}
1616
const scrud = {
1717
GET: 'search',
@@ -147,21 +147,22 @@ function handleRequest (req, res) {
147147
let modifier = matches[2]
148148
let action = scrud[`${req.method}${modifier}`]
149149
if (!resource || !action) return fourOhFour(res)
150+
let name = resource.name
150151
res.setHeader('Content-Type', 'application/json')
151-
res.setHeader('SCRUD', `${resource.name}:${action}`)
152+
res.setHeader('SCRUD', `${name}:${action}`)
152153
req.id = parseId(url)
153154
req.params = tinyParams(url)
154155
let headers = req.headers || {}
155156
let connection = req.connection || {}
156157
req.params.ip = headers['x-forwarded-for'] || connection.remoteAddress
157158
req.once('error', (err) => sendErr(res, err))
158-
let handler = (resource[action] || handlers[action])
159+
let handler = resource[action] || actionHandler
159160
let jwt = (headers.authorization || '').replace(/^Bearer\s/, '')
160161
let callHandler = () => {
161-
if (!hasBody[action]) return handler(req, res, resource.name)
162+
if (!hasBody[action]) return handler(req, res, name, action)
162163
bodyParse(req).then((body) => {
163164
req.params = Object.assign(body, req.params)
164-
return handler(req, res, resource.name)
165+
return handler(req, res, name, action)
165166
})
166167
}
167168
if (resource.skipAuth && resource.skipAuth[action]) return callHandler()
@@ -172,14 +173,20 @@ function handleRequest (req, res) {
172173
}
173174

174175
function sendData (res, data = null) {
175-
return res.end(JSON.stringify({data, error: null}))
176+
return new Promise((resolve, reject) => {
177+
res.end(JSON.stringify({data, error: null}))
178+
return resolve()
179+
})
176180
}
177181

178182
function sendErr (res, err = new Error(), code = 500) {
179-
res.statusCode = code
180-
logIt(err, 'fatal')
181-
err = err instanceof Error ? (err.message || err.name) : err.toString()
182-
return res.end(JSON.stringify({data: null, error: err}))
183+
return new Promise((resolve, reject) => {
184+
res.statusCode = code
185+
logIt(err, 'fatal')
186+
err = err instanceof Error ? (err.message || err.name) : err.toString()
187+
res.end(JSON.stringify({data: null, error: err}))
188+
return resolve()
189+
})
183190
}
184191

185192
function fourOhOne (res, err = new Error(`unable to auhenticate request`)) {
@@ -251,32 +258,15 @@ function destroy (resource, id, params) {
251258
return callPgFunc(`${pgPrefix}${resource}_delete`, params)
252259
}
253260

254-
// wrap resource methods for fun and profit
255-
function actionWrapper (p, name, res, data) {
256-
return p.then((d) => sendData(res, data || d)).catch((e) => sendErr(res, e))
257-
}
258-
259-
// resource method: search
260-
function resourceSearch (req, res, name) {
261-
return actionWrapper(findAll(name, req.params), name, res)
262-
}
263-
264-
// resource method: create
265-
function resourceCreate (req, res, name) {
266-
return actionWrapper(create(name, req.params), name, res)
267-
}
268-
269-
// resource method: read
270-
function resourceRead (req, res, name) {
271-
return actionWrapper(find(name, req.id, req.params), name, res)
272-
}
273-
274-
// resource method: update
275-
function resourceUpdate (req, res, name) {
276-
return actionWrapper(save(name, req.id, req.params), name, res)
277-
}
278-
279-
// resource method: delete
280-
function resourceDelete (req, res, name) {
281-
return actionWrapper(destroy(name, req.id, req.params), name, res, 'success')
261+
// default handler for all resource methods
262+
function actionHandler (req, res, name, action) {
263+
let bq = resources[name].beforeQuery || {} // (req, res)
264+
if (typeof bq !== 'function') bq = bq[action]
265+
let bs = resources[name].beforeSend || {} // (req, res, data)
266+
if (typeof bs !== 'function') bs = bs[action]
267+
let act = () => handlers[action](name, req)
268+
let send = (d) => sendData(res, d)
269+
let finish = (d) => bs ? bs(req, res, d).then((d) => send(d)) : send(d)
270+
let run = () => bq ? bq(req, res).then(act).then(finish) : act().then(finish)
271+
return run().catch((e) => sendErr(res, e))
282272
}

test/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ test('scrud actions are handled as expected', async (assert) => {
4545
// delete
4646
let d = await axios({method: 'DELETE', url: `${base}/${id}`})
4747
assert.is(d.headers.scrud, 'member:delete')
48-
assert.is(d.data.data, 'success')
48+
assert.falsy(d.data.error)
4949
})
5050

5151
test('register returns resource object', async (assert) => {

0 commit comments

Comments
 (0)