This repository has been archived by the owner on Feb 6, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 25
/
wrappers.js
108 lines (91 loc) · 3.48 KB
/
wrappers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import makeDebug from 'debug';
import errors from 'feathers-errors';
import { hooks } from 'feathers-commons';
const debug = makeDebug('feathers:rest');
const hookObject = hooks.hookObject;
const statusCodes = {
created: 201,
noContent: 204,
methodNotAllowed: 405
};
const methodMap = {
find: 'GET',
get: 'GET',
create: 'POST',
update: 'PUT',
patch: 'PATCH',
remove: 'DELETE'
};
const allowedMethods = function (service) {
return Object.keys(methodMap)
.filter(method => typeof service[method] === 'function')
.map(method => methodMap[method])
// Filter out duplicates
.filter((value, index, list) => list.indexOf(value) === index);
};
// A function that returns the middleware for a given method and service
// `getArgs` is a function that should return additional leading service arguments
function getHandler (method, getArgs, service) {
return function (req, res, next) {
res.setHeader('Allow', allowedMethods(service).join(','));
// Check if the method exists on the service at all. Send 405 (Method not allowed) if not
if (typeof service[method] !== 'function') {
debug(`Method '${method}' not allowed on '${req.url}'`);
res.status(statusCodes.methodNotAllowed);
return next(new errors.MethodNotAllowed(`Method \`${method}\` is not supported by this endpoint.`));
}
let params = Object.assign({}, req.params || {});
delete params.__feathersId;
// Grab the service parameters. Use req.feathers and set the query to req.query
params = Object.assign({ query: req.query || {} }, params, req.feathers);
// Run the getArgs callback, if available, for additional parameters
const args = getArgs(req, res, next);
// The service success callback which sets res.data or calls next() with the error
const callback = function (error, data) {
const hookArgs = args.concat([ params, callback ]);
if (error) {
debug(`Error in REST handler: \`${error.message || error}\``);
res.hook = hookObject(method, 'error', hookArgs);
return next(error);
}
res.data = data;
res.hook = hookObject(method, 'after', hookArgs);
if (!data) {
debug(`No content returned for '${req.url}'`);
res.status(statusCodes.noContent);
} else if (method === 'create') {
res.status(statusCodes.created);
}
return next();
};
debug(`REST handler calling \`${method}\` from \`${req.url}\``);
service[method].apply(service, args.concat([ params, callback ]));
};
}
// Returns no leading parameters
function reqNone () {
return [];
}
// Returns the leading parameters for a `get` or `remove` request (the id)
function reqId (req) {
return [ req.params.__feathersId || null ];
}
// Returns the leading parameters for an `update` or `patch` request (id, data)
function reqUpdate (req) {
return [ req.params.__feathersId || null, req.body ];
}
// Returns the leading parameters for a `create` request (data)
function reqCreate (req) {
return [ req.body ];
}
// Returns wrapped middleware for a service method.
// Doing some fancy ES 5 .bind argument currying for .getHandler()
// Basically what you are getting for each is a function(service) {}
export default {
find: getHandler.bind(null, 'find', reqNone),
get: getHandler.bind(null, 'get', reqId),
create: getHandler.bind(null, 'create', reqCreate),
update: getHandler.bind(null, 'update', reqUpdate),
patch: getHandler.bind(null, 'patch', reqUpdate),
remove: getHandler.bind(null, 'remove', reqId)
};