1 |
|
2 | const moment = require('moment');
|
3 |
|
4 | const statusCodeHelper = (res) => (code) => (body = {}) => {
|
5 |
|
6 | res.status(code).json(body);
|
7 | };
|
8 |
|
9 | const removeEmpty = (obj = {}) =>
|
10 | Object.entries(obj).reduce((a, [key, value]) => {
|
11 | const copy = { ...a };
|
12 | if (value !== null && value !== undefined)
|
13 | copy[key] = value;
|
14 | return copy;
|
15 | }, {});
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | const stripMongoDBProps = (i) => {
|
29 | try {
|
30 | if (typeof i !== 'object') return i;
|
31 |
|
32 | const json = JSON.parse(JSON.stringify(i));
|
33 | const cleaned = removeEmpty(json);
|
34 |
|
35 | delete cleaned._id;
|
36 | delete cleaned.__v;
|
37 | delete cleaned.password;
|
38 | delete cleaned.secret;
|
39 |
|
40 | return Object.entries(cleaned).reduce(
|
41 | (a, [k, v]) =>
|
42 | Object.assign(a, {
|
43 | [k]: Array.isArray(v)
|
44 | ? v.map(stripMongoDBProps)
|
45 | : stripMongoDBProps(v),
|
46 | }),
|
47 | cleaned,
|
48 | );
|
49 | } catch (e) {
|
50 | return JSON.parse(JSON.stringify(i));
|
51 | }
|
52 | };
|
53 |
|
54 | const decorateResponse = (req, res, next) => {
|
55 | const dispatch = statusCodeHelper(res);
|
56 |
|
57 | req.marshal = (o) => {
|
58 | if (Array.isArray(o)) {
|
59 |
|
60 | return o.map(stripMongoDBProps);
|
61 | }
|
62 |
|
63 |
|
64 | return stripMongoDBProps(o);
|
65 | };
|
66 |
|
67 | req.isFresh = (d) => {
|
68 | const unmod =
|
69 | req.headers['If-Unmodified-Since'] ||
|
70 | req.headers['if-unmodified-since'];
|
71 |
|
72 | return moment(unmod, moment.ISO_8601, true).isValid() &&
|
73 | moment(d, moment.ISO_8601, true).isValid() &&
|
74 | moment(d).isAfter(new Date(unmod).toISOString())
|
75 | ? res.status(412).send()
|
76 | : true;
|
77 | };
|
78 |
|
79 | res.acknowledge = dispatch(204);
|
80 | res.ok = dispatch(200);
|
81 | res.update = dispatch(200);
|
82 | res.create = dispatch(201);
|
83 | next();
|
84 | };
|
85 |
|
86 | module.exports = decorateResponse;
|