@modernpoacher/halacious 6.2.8 → 6.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/representation.js +214 -210
- package/package.json +3 -4
- /package/{types → lib}/index.d.ts +0 -0
package/lib/representation.js
CHANGED
|
@@ -15,228 +15,230 @@ const templatedRE = /{*}/
|
|
|
15
15
|
* @param root
|
|
16
16
|
* @constructor
|
|
17
17
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
18
|
+
class Representation {
|
|
19
|
+
constructor (factory, self, entity, root) {
|
|
20
|
+
this._halacious = factory._halacious
|
|
21
|
+
this.factory = factory
|
|
22
|
+
this.request = factory._request
|
|
23
|
+
this._root = root || this
|
|
24
|
+
this.self = self.href
|
|
25
|
+
this._links = { self }
|
|
26
|
+
this._embedded = {}
|
|
27
|
+
this._namespaces = {}
|
|
28
|
+
this._props = {}
|
|
29
|
+
this._ignore = {}
|
|
30
|
+
this.entity = entity
|
|
31
|
+
}
|
|
31
32
|
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Adds a namespace to the 'curie' link collection. all curies in a response, top level or nested, should be declared
|
|
35
|
+
* in the top level _links collection. a reference '_root' is kept to the top level representation for this purpose
|
|
36
|
+
* @param namespace
|
|
37
|
+
*/
|
|
38
|
+
curie (namespace) {
|
|
39
|
+
if (namespace && !this._root._namespaces[namespace.prefix]) {
|
|
40
|
+
this._root._namespaces[namespace.prefix] = namespace
|
|
41
|
+
this._root._links.curies = this._root._links.curies || []
|
|
42
|
+
this._root._links.curies.push({
|
|
43
|
+
name: namespace.prefix,
|
|
44
|
+
href: `${this._halacious.namespaceUrl(this.request, namespace)}/{rel}`,
|
|
45
|
+
templated: true
|
|
46
|
+
})
|
|
47
|
+
}
|
|
46
48
|
}
|
|
47
|
-
}
|
|
48
49
|
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
50
|
+
/**
|
|
51
|
+
* Adds a custom property to the HAL payload
|
|
52
|
+
* @param {String} name the property name
|
|
53
|
+
* @param {*} value the property value
|
|
54
|
+
* @return {Representation}
|
|
55
|
+
*/
|
|
56
|
+
prop (name, value) {
|
|
57
|
+
this._props[name] = value
|
|
58
|
+
return this
|
|
59
|
+
}
|
|
59
60
|
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
61
|
+
/**
|
|
62
|
+
* Merges an object's properties into the custom properties collection.
|
|
63
|
+
* @param prop
|
|
64
|
+
*/
|
|
65
|
+
merge (prop) {
|
|
66
|
+
hoek.merge(this._props, prop)
|
|
67
|
+
}
|
|
67
68
|
|
|
68
|
-
/**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
69
|
+
/**
|
|
70
|
+
* @param {...String || String[]} args properties to ignore
|
|
71
|
+
* @return {Representation}
|
|
72
|
+
*/
|
|
73
|
+
ignore (...args) {
|
|
74
|
+
const props = _.isArray(args[0]) ? args[0] : args
|
|
75
|
+
props.forEach(function (prop) {
|
|
76
|
+
this._ignore[prop] = true
|
|
77
|
+
}, this)
|
|
78
|
+
return this
|
|
79
|
+
}
|
|
79
80
|
|
|
80
|
-
/**
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// copy all target properties in the entity using JSON.stringify(). if the entity has a .toJSON() implementation,
|
|
90
|
-
// it will be called. properties on the ignore list will not be copied
|
|
91
|
-
const { entity } = this
|
|
92
|
-
JSON.stringify(entity, (key, value) => {
|
|
93
|
-
if (!key) {
|
|
94
|
-
return value
|
|
95
|
-
}
|
|
96
|
-
if (!self._ignore[key]) {
|
|
97
|
-
payload[key] = value
|
|
98
|
-
}
|
|
99
|
-
})
|
|
81
|
+
/**
|
|
82
|
+
* Prepares the representation for JSON serialization.
|
|
83
|
+
* @return {{}}
|
|
84
|
+
*/
|
|
85
|
+
toJSON () {
|
|
86
|
+
// initialize the json entity
|
|
87
|
+
const payload = { _links: this._links }
|
|
88
|
+
const self = this
|
|
100
89
|
|
|
101
|
-
|
|
102
|
-
|
|
90
|
+
// copy all target properties in the entity using JSON.stringify(). if the entity has a .toJSON() implementation,
|
|
91
|
+
// it will be called. properties on the ignore list will not be copied
|
|
92
|
+
const { entity } = this
|
|
93
|
+
JSON.stringify(entity, (key, value) => {
|
|
94
|
+
if (!key) {
|
|
95
|
+
return value
|
|
96
|
+
}
|
|
97
|
+
if (!self._ignore[key]) {
|
|
98
|
+
payload[key] = value
|
|
99
|
+
}
|
|
100
|
+
})
|
|
103
101
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
payload._embedded = {}
|
|
102
|
+
// merge in any extra properties
|
|
103
|
+
_.assign(payload, this._props)
|
|
107
104
|
|
|
108
|
-
const
|
|
109
|
-
embeddedKeys.
|
|
110
|
-
|
|
111
|
-
payload._embedded[embedKey] = {}
|
|
112
|
-
} else if (self._embedded[embedKey] instanceof Array) {
|
|
113
|
-
payload._embedded[embedKey] = []
|
|
114
|
-
}
|
|
105
|
+
const embeddedKeys = _.keys(this._embedded)
|
|
106
|
+
if (embeddedKeys.length > 0) {
|
|
107
|
+
payload._embedded = {}
|
|
115
108
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
109
|
+
const self = this
|
|
110
|
+
embeddedKeys.forEach((embedKey) => {
|
|
111
|
+
if (self._embedded[embedKey] instanceof Representation) {
|
|
112
|
+
payload._embedded[embedKey] = {}
|
|
113
|
+
} else if (self._embedded[embedKey] instanceof Array) {
|
|
114
|
+
payload._embedded[embedKey] = []
|
|
119
115
|
}
|
|
120
116
|
|
|
121
|
-
|
|
117
|
+
JSON.stringify(self._embedded[embedKey], (key, value) => {
|
|
118
|
+
if (!key) {
|
|
119
|
+
return value
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
payload._embedded[embedKey][key] = value
|
|
123
|
+
})
|
|
122
124
|
})
|
|
123
|
-
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return payload
|
|
124
128
|
}
|
|
125
129
|
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
/**
|
|
131
|
+
* Creates a new link and adds it to the _links collection
|
|
132
|
+
* @param rel
|
|
133
|
+
* @param link
|
|
134
|
+
* @return {{} || []} the new link
|
|
135
|
+
*/
|
|
136
|
+
link (originalRel, link) {
|
|
137
|
+
const rel = this._halacious.rel(originalRel)
|
|
138
|
+
const qname = rel.qname()
|
|
139
|
+
|
|
140
|
+
if (_.isArray(link)) {
|
|
141
|
+
const that = this
|
|
142
|
+
this._links[qname] = []
|
|
143
|
+
return link.map((l) => that.link(originalRel, l), this)
|
|
144
|
+
}
|
|
128
145
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
// adds the namespace to the top level curie list
|
|
147
|
+
this.curie(rel.namespace)
|
|
148
|
+
|
|
149
|
+
link = this._halacious.link(link, this._links.self.href)
|
|
150
|
+
link.templated = templatedRE.test(link.href) ? true : undefined
|
|
151
|
+
// e.g. 'mco:rel'
|
|
152
|
+
if (!this._links[qname]) {
|
|
153
|
+
this._links[qname] = link
|
|
154
|
+
} else if (_.isArray(this._links[qname])) {
|
|
155
|
+
this._links[qname].push(link)
|
|
156
|
+
} else {
|
|
157
|
+
this._links[qname] = [this._links[qname], link]
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return link
|
|
143
161
|
}
|
|
144
162
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
this._links[qname].push(link)
|
|
155
|
-
} else {
|
|
156
|
-
this._links[qname] = [this._links[qname], link]
|
|
163
|
+
/**
|
|
164
|
+
* Resolves a relative path against the representation's self href
|
|
165
|
+
* @param relativePath
|
|
166
|
+
* @return {*}
|
|
167
|
+
*/
|
|
168
|
+
resolve (relativePath) {
|
|
169
|
+
return new URI(relativePath)
|
|
170
|
+
.absoluteTo(`${this._links.self.href}/`)
|
|
171
|
+
.toString()
|
|
157
172
|
}
|
|
158
173
|
|
|
159
|
-
|
|
160
|
-
|
|
174
|
+
/**
|
|
175
|
+
* Returns the path to a named route (specified by the plugins.hal.name configuration parameter), expanding any supplied
|
|
176
|
+
* path parameters.
|
|
177
|
+
* @param {String} routeName the route's name
|
|
178
|
+
* @param {{}=} params for expanding templated urls
|
|
179
|
+
* @return {*}
|
|
180
|
+
*/
|
|
181
|
+
route (routeName, params) {
|
|
182
|
+
return this._halacious.route(routeName, params)
|
|
183
|
+
}
|
|
161
184
|
|
|
162
|
-
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
.
|
|
171
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Wraps an entity into a HAL representation and adds it to the _embedded collection
|
|
187
|
+
* @param {String} rel the rel name
|
|
188
|
+
* @param {String || {}} self an href or link object for the entity
|
|
189
|
+
* @param {{} || []} entity an object to wrap
|
|
190
|
+
* @return {entity || []}
|
|
191
|
+
*/
|
|
192
|
+
embed (originalRel, self, entity) {
|
|
193
|
+
const rel = this._halacious.rel(originalRel)
|
|
194
|
+
const qname = rel.qname()
|
|
195
|
+
|
|
196
|
+
this.curie(rel.namespace)
|
|
197
|
+
|
|
198
|
+
if (_.isArray(entity)) {
|
|
199
|
+
const that = this
|
|
200
|
+
this._embedded[qname] = []
|
|
201
|
+
return entity.map((e) => that.embed(originalRel, self, e), this)
|
|
202
|
+
}
|
|
172
203
|
|
|
173
|
-
|
|
174
|
-
* Returns the path to a named route (specified by the plugins.hal.name configuration parameter), expanding any supplied
|
|
175
|
-
* path parameters.
|
|
176
|
-
* @param {String} routeName the route's name
|
|
177
|
-
* @param {{}=} params for expanding templated urls
|
|
178
|
-
* @return {*}
|
|
179
|
-
*/
|
|
180
|
-
Representation.prototype.route = function (routeName, params) {
|
|
181
|
-
return this._halacious.route(routeName, params)
|
|
182
|
-
}
|
|
204
|
+
self = this._halacious.link(self, this._links.self.href)
|
|
183
205
|
|
|
184
|
-
|
|
185
|
-
* Wraps an entity into a HAL representation and adds it to the _embedded collection
|
|
186
|
-
* @param {String} rel the rel name
|
|
187
|
-
* @param {String || {}} self an href or link object for the entity
|
|
188
|
-
* @param {{} || []} entity an object to wrap
|
|
189
|
-
* @return {entity || []}
|
|
190
|
-
*/
|
|
191
|
-
Representation.prototype.embed = function (originalRel, self, entity) {
|
|
192
|
-
const rel = this._halacious.rel(originalRel)
|
|
193
|
-
const qname = rel.qname()
|
|
206
|
+
const embedded = this.factory.create(entity, self, this._root)
|
|
194
207
|
|
|
195
|
-
|
|
208
|
+
if (!this._embedded[qname]) {
|
|
209
|
+
this._embedded[qname] = embedded
|
|
210
|
+
} else if (_.isArray(this._embedded[qname])) {
|
|
211
|
+
this._embedded[qname].push(embedded)
|
|
212
|
+
} else {
|
|
213
|
+
this._embedded[qname] = [this._embedded[qname], embedded]
|
|
214
|
+
}
|
|
196
215
|
|
|
197
|
-
|
|
198
|
-
const that = this
|
|
199
|
-
this._embedded[qname] = []
|
|
200
|
-
return entity.map((e) => that.embed(originalRel, self, e), this)
|
|
216
|
+
return embedded
|
|
201
217
|
}
|
|
202
218
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
219
|
+
/**
|
|
220
|
+
* Convenience method for embedding an array of entities
|
|
221
|
+
* @param rel
|
|
222
|
+
* @param self
|
|
223
|
+
* @param entities
|
|
224
|
+
* @return {Representation}
|
|
225
|
+
*/
|
|
226
|
+
embedCollection (rel, self, entities) {
|
|
227
|
+
entities = _.isArray(entities) ? entities : [entities]
|
|
228
|
+
entities.forEach(function (entity) {
|
|
229
|
+
this.embed(rel, hoek.clone(self), entity)
|
|
230
|
+
}, this)
|
|
231
|
+
return this
|
|
213
232
|
}
|
|
214
233
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
* @return {Representation}
|
|
224
|
-
*/
|
|
225
|
-
Representation.prototype.embedCollection = function (rel, self, entities) {
|
|
226
|
-
entities = _.isArray(entities) ? entities : [entities]
|
|
227
|
-
entities.forEach(function (entity) {
|
|
228
|
-
this.embed(rel, hoek.clone(self), entity)
|
|
229
|
-
}, this)
|
|
230
|
-
return this
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Configures a representation using a configuration object such as those found in route definitions
|
|
235
|
-
* @param config
|
|
236
|
-
* @param callback
|
|
237
|
-
*/
|
|
238
|
-
Representation.prototype.configure = function (config, callback) {
|
|
239
|
-
this._halacious.configureRepresentation(this, config, callback)
|
|
234
|
+
/**
|
|
235
|
+
* Configures a representation using a configuration object such as those found in route definitions
|
|
236
|
+
* @param config
|
|
237
|
+
* @param callback
|
|
238
|
+
*/
|
|
239
|
+
configure (config, callback) {
|
|
240
|
+
this._halacious.configureRepresentation(this, config, callback)
|
|
241
|
+
}
|
|
240
242
|
}
|
|
241
243
|
|
|
242
244
|
/**
|
|
@@ -245,24 +247,26 @@ Representation.prototype.configure = function (config, callback) {
|
|
|
245
247
|
* @param request a hapi request object
|
|
246
248
|
* @constructor
|
|
247
249
|
*/
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
250
|
+
class RepresentationFactory {
|
|
251
|
+
constructor (halacious, request) {
|
|
252
|
+
this._halacious = halacious
|
|
253
|
+
this._request = request
|
|
254
|
+
}
|
|
252
255
|
|
|
253
|
-
/**
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
256
|
+
/**
|
|
257
|
+
* Creates a new hal representation out of a javascript object
|
|
258
|
+
* @param {{}=} entity the entity to wrap with a representation. an empty object is created by default
|
|
259
|
+
* @param {String || {}=} self the self href or link object. The request's path is used by default
|
|
260
|
+
* @param {Representation} root a pointer to the top level representation for adding curied links
|
|
261
|
+
* should be expanded into absolute urls
|
|
262
|
+
* @return {Representation}
|
|
263
|
+
*/
|
|
264
|
+
create (entity, self, root) {
|
|
265
|
+
entity = entity || {}
|
|
266
|
+
self = self || (this._request && this._request.path)
|
|
267
|
+
self = this._halacious.link(self)
|
|
268
|
+
return new Representation(this, self, entity, root)
|
|
269
|
+
}
|
|
266
270
|
}
|
|
267
271
|
|
|
268
272
|
module.exports.RepresentationFactory = RepresentationFactory
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modernpoacher/halacious",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.9",
|
|
4
4
|
"description": "A HAL processor for Hapi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"HAL",
|
|
@@ -9,10 +9,9 @@
|
|
|
9
9
|
"HATEOAS"
|
|
10
10
|
],
|
|
11
11
|
"main": "./index.js",
|
|
12
|
-
"
|
|
13
|
-
"author": "Brad Leupen",
|
|
12
|
+
"author": "Jonathan Perry <modernpoacher@modernpoacher.com> (Modern Poacher Limited)",
|
|
14
13
|
"contributors": [
|
|
15
|
-
"
|
|
14
|
+
"Brad Leupen"
|
|
16
15
|
],
|
|
17
16
|
"license": "MIT",
|
|
18
17
|
"engines": {
|
|
File without changes
|