-
Notifications
You must be signed in to change notification settings - Fork 114
/
MemoryHandler.js
152 lines (130 loc) · 4.64 KB
/
MemoryHandler.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
'use strict'
const _ = {
assign: require('lodash.assign')
}
const MemoryStore = module.exports = function MemoryStore () {
}
// resources represents out in-memory data store
const resources = { }
/**
Handlers readiness status. This should be set to `true` once all handlers are ready to process requests.
*/
MemoryStore.prototype.ready = false
/**
initialise gets invoked once for each resource that uses this hander.
In this instance, we're allocating an array in our in-memory data store.
*/
MemoryStore.prototype.initialise = function (resourceConfig) {
resources[resourceConfig.resource] = resourceConfig.examples || [ ]
this.ready = true
}
/**
Search for a list of resources, given a resource type.
*/
MemoryStore.prototype.search = function (request, callback) {
const self = this
let results = [].concat(resources[request.params.type])
self._sortList(request, results)
const resultCount = results.length
if (request.params.page) {
results = results.slice(request.params.page.offset, request.params.page.offset + request.params.page.limit)
}
return callback(null, MemoryStore._clone(results), resultCount)
}
/**
Find a specific resource, given a resource type and and id.
*/
MemoryStore.prototype.find = (request, callback) => {
// Pull the requested resource from the in-memory store
const theResource = resources[request.params.type].filter(anyResource => anyResource.id === request.params.id).pop()
// If the resource doesn't exist, error
if (!theResource) {
return callback({ // eslint-disable-line standard/no-callback-literal
status: '404',
code: 'ENOTFOUND',
title: 'Requested resource does not exist',
detail: `There is no ${request.params.type} with id ${request.params.id}`
})
}
// Return the requested resource
return callback(null, MemoryStore._clone(theResource))
}
/**
Create (store) a new resource given a resource type and an object.
*/
MemoryStore.prototype.create = (request, newResource, callback) => {
// Check to see if the ID already exists
const index = MemoryStore._indexOf(resources[request.params.type], newResource)
if (index !== -1) {
return callback({ // eslint-disable-line standard/no-callback-literal
status: '403',
code: 'EFORBIDDEN',
title: 'Requested resource already exists',
detail: `The requested resource already exists of type ${request.params.type} with id ${request.params.id}`
})
}
// Push the newResource into our in-memory store.
resources[request.params.type].push(newResource)
// Return the newly created resource
return callback(null, MemoryStore._clone(newResource))
}
/**
Delete a resource, given a resource type and and id.
*/
MemoryStore.prototype.delete = function (request, callback) {
// Find the requested resource
this.find(request, (err, theResource) => {
if (err) return callback(err)
// Remove the resource from the in-memory store.
const index = MemoryStore._indexOf(resources[request.params.type], theResource)
resources[request.params.type].splice(index, 1)
// Return with no error
return callback()
})
}
/**
Update a resource, given a resource type and id, along with a partialResource.
partialResource contains a subset of changes that need to be merged over the original.
*/
MemoryStore.prototype.update = function (request, partialResource, callback) {
// Find the requested resource
this.find(request, (err, theResource) => {
if (err) return callback(err)
// Merge the partialResource over the original
theResource = _.assign(theResource, partialResource)
// Push the newly updated resource back into the in-memory store
const index = MemoryStore._indexOf(resources[request.params.type], theResource)
resources[request.params.type][index] = theResource
// Return the newly updated resource
return callback(null, MemoryStore._clone(theResource))
})
}
/**
Internal helper function to sort data
*/
MemoryStore.prototype._sortList = (request, list) => {
let attribute = request.params.sort
if (!attribute) return
let ascending = 1
attribute = (`${attribute}`)
if (attribute[0] === '-') {
ascending = -1
attribute = attribute.substring(1, attribute.length)
}
list.sort((a, b) => {
if (typeof a[attribute] === 'string') {
return a[attribute].localeCompare(b[attribute]) * ascending
} else if (typeof a[attribute] === 'number') {
return (a[attribute] - b[attribute]) * ascending
} else {
return 0
}
})
}
MemoryStore._clone = obj => JSON.parse(JSON.stringify(obj))
MemoryStore._indexOf = (list, obj) => {
for (const i in list) {
if (list[i].id === obj.id) return i
}
return -1
}