@mountainpass/waycharter 1.0.75 → 1.0.76
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/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/util/router-to-rfc6570.js +14 -0
- package/dist/util/router-to-rfc6570.js.map +1 -0
- package/dist/waycharter.js +16 -17
- package/dist/waycharter.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## <small>1.0.76 (2021-12-16)</small>
|
|
2
|
+
|
|
3
|
+
* fix(collections): fixed first, next, prev links for templated collections ([3ed681a](https://github.com/mountain-pass/waycharter/commit/3ed681a))
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
1
7
|
## <small>1.0.75 (2021-12-13)</small>
|
|
2
8
|
|
|
3
9
|
* feat(collections): item endpoints can now be used when registering collections ([15fa46d](https://github.com/mountain-pass/waycharter/commit/15fa46d))
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ This library is compatible with Node.js 10.x, 12.x and 14.x
|
|
|
13
13
|
|
|
14
14
|
<!-- [](https://www.codacy.com/gh/mountain-pass/waycharter/dashboard?utm_source=github.com&utm_medium=referral&utm_content=mountain-pass/waycharter&utm_campaign=Badge_Grade) [](https://www.codacy.com/gh/mountain-pass/waycharter/dashboard?utm_source=github.com&utm_medium=referral&utm_content=mountain-pass/waycharter&utm_campaign=Badge_Coverage) -->
|
|
15
15
|
|
|
16
|
-
[](https://snyk.io/test/github/mountain-pass/waycharter) [](https://snyk.io/test/github/mountain-pass/waycharter) [](https://snyk.io/test/npm/@mountainpass/waycharter/1.0.76)
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
[](https://conventionalcommits.org) [](https://github.com/prettier/prettier)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.routerToRfc6570 = routerToRfc6570;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param url
|
|
10
|
+
*/
|
|
11
|
+
function routerToRfc6570(url) {
|
|
12
|
+
return url.replace(/:(\w*)/g, '{+$1}');
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=router-to-rfc6570.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/util/router-to-rfc6570.js"],"names":["routerToRfc6570","url","replace"],"mappings":";;;;;;;AAAA;AACA;AACA;AACO,SAASA,eAAT,CAA0BC,GAA1B,EAA+B;AACpC,SAAOA,GAAG,CAACC,OAAJ,CAAY,SAAZ,EAAuB,OAAvB,CAAP;AACD","sourcesContent":["/**\n * @param url\n */\nexport function routerToRfc6570 (url) {\n return url.replace(/:(\\w*)/g, '{+$1}')\n}\n"],"file":"router-to-rfc6570.js"}
|
package/dist/waycharter.js
CHANGED
|
@@ -25,14 +25,9 @@ var _builtItemLinks = require("./collections/built-item-links");
|
|
|
25
25
|
|
|
26
26
|
var _methodIsCacheable = require("./method-is-cacheable");
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
var _routerToRfc = require("./util/router-to-rfc6570");
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
* @param url
|
|
32
|
-
*/
|
|
33
|
-
function routerToRfc6570(url) {
|
|
34
|
-
return url.replace(/:(\w*)/g, '{+$1}');
|
|
35
|
-
}
|
|
30
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
36
31
|
|
|
37
32
|
class WayCharter {
|
|
38
33
|
constructor() {
|
|
@@ -47,7 +42,7 @@ class WayCharter {
|
|
|
47
42
|
// TODO: error handling for path not set
|
|
48
43
|
// TODO: error handling for loader not set
|
|
49
44
|
const lowerCaseLoaderVaries = new Set(loaderVaries ? loaderVaries.map(header => header.toLowerCase()) : []);
|
|
50
|
-
const uriTemplate = routerToRfc6570(path);
|
|
45
|
+
const uriTemplate = (0, _routerToRfc.routerToRfc6570)(path);
|
|
51
46
|
this.router.get(path, async function (request, response, next) {
|
|
52
47
|
const filteredHeaders = Object.keys(request.headers).reduce((filtered, key) => lowerCaseLoaderVaries.has(key) ? { ...filtered,
|
|
53
48
|
[key]: request.headers[key]
|
|
@@ -122,7 +117,7 @@ class WayCharter {
|
|
|
122
117
|
response.json({});
|
|
123
118
|
}
|
|
124
119
|
});
|
|
125
|
-
const uriTemplate = routerToRfc6570(path);
|
|
120
|
+
const uriTemplate = (0, _routerToRfc.routerToRfc6570)(path);
|
|
126
121
|
const template = new _uriTemplateLite.URI.Template(uriTemplate);
|
|
127
122
|
const pathParameters = template.match(uriTemplate);
|
|
128
123
|
return {
|
|
@@ -169,6 +164,7 @@ class WayCharter {
|
|
|
169
164
|
// TODO: error handling if itemEndpoint is set, and itemPath or itemLoader is set
|
|
170
165
|
// TODO: error handling for collectionPath not set
|
|
171
166
|
// TODO: error handling for collectionLoader not set
|
|
167
|
+
// we need to handle collectionPath being parameterised
|
|
172
168
|
const itemType = itemPath !== undefined && itemLoader !== undefined ? this.registerResourceType({
|
|
173
169
|
path: `${collectionPath}${itemPath}`,
|
|
174
170
|
loader: itemLoader
|
|
@@ -182,18 +178,21 @@ class WayCharter {
|
|
|
182
178
|
});
|
|
183
179
|
}
|
|
184
180
|
|
|
181
|
+
const uriTemplate = (0, _routerToRfc.routerToRfc6570)(collectionPath);
|
|
185
182
|
const type = this.registerResourceType({
|
|
186
183
|
path: collectionPath,
|
|
187
184
|
loader: async ({
|
|
188
185
|
page,
|
|
189
186
|
...otherParameters
|
|
190
187
|
}, filteredHeaders, selfUri, request, response) => {
|
|
191
|
-
// ${collectionPath}?page=0 should redirect to ${collectionPath}
|
|
188
|
+
const expandedCollectionPath = _uriTemplateLite.URI.expand(uriTemplate, request.params); // ${collectionPath}?page=0 should redirect to ${collectionPath}
|
|
189
|
+
|
|
190
|
+
|
|
192
191
|
if (page === '0') {
|
|
193
192
|
return {
|
|
194
193
|
status: 308,
|
|
195
194
|
headers: {
|
|
196
|
-
location:
|
|
195
|
+
location: expandedCollectionPath
|
|
197
196
|
}
|
|
198
197
|
};
|
|
199
198
|
} // page should be >= 0
|
|
@@ -223,13 +222,12 @@ class WayCharter {
|
|
|
223
222
|
// but we can include all path params
|
|
224
223
|
|
|
225
224
|
|
|
226
|
-
const filteredParameters = {
|
|
227
|
-
};
|
|
225
|
+
const filteredParameters = {};
|
|
228
226
|
|
|
229
227
|
for (const filter of filters) {
|
|
230
228
|
for (const parameter of filter.parameters) {
|
|
231
|
-
if (
|
|
232
|
-
filteredParameters[parameter] =
|
|
229
|
+
if (request.query[parameter] !== undefined) {
|
|
230
|
+
filteredParameters[parameter] = request.query[parameter];
|
|
233
231
|
}
|
|
234
232
|
}
|
|
235
233
|
}
|
|
@@ -243,7 +241,8 @@ class WayCharter {
|
|
|
243
241
|
status
|
|
244
242
|
} = await collectionLoader({
|
|
245
243
|
page: pageInt,
|
|
246
|
-
...filteredParameters
|
|
244
|
+
...filteredParameters,
|
|
245
|
+
...request.params
|
|
247
246
|
}, filteredHeaders, selfUri, request, response);
|
|
248
247
|
const array = arrayPointer ? _jsonpointer.default.get(body, arrayPointer) : body;
|
|
249
248
|
const {
|
|
@@ -252,7 +251,7 @@ class WayCharter {
|
|
|
252
251
|
} = (0, _builtItemLinks.builtItemLinks)(array, arrayPointer, itemType, selfUri, itemOperations);
|
|
253
252
|
return {
|
|
254
253
|
body,
|
|
255
|
-
links: [...itemLinks, ...canonicalLinks, ...(0, _buildNextLink.buildNextLink)(hasMore, pageInt,
|
|
254
|
+
links: [...itemLinks, ...canonicalLinks, ...(0, _buildNextLink.buildNextLink)(hasMore, pageInt, expandedCollectionPath, filteredParameters), ...(0, _buildPreviousLink.buildPreviousLink)(pageInt, expandedCollectionPath, filteredParameters), ...(0, _buildFirstLink.buildFirstLink)(hasMore, pageInt, expandedCollectionPath, filteredParameters)],
|
|
256
255
|
linkTemplates,
|
|
257
256
|
headers,
|
|
258
257
|
status
|
package/dist/waycharter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/waycharter.js"],"names":["routerToRfc6570","url","replace","WayCharter","constructor","router","registerResourceType","path","loader","loaderVaries","lowerCaseLoaderVaries","Set","map","header","toLowerCase","uriTemplate","get","request","response","next","filteredHeaders","Object","keys","headers","reduce","filtered","key","has","resource","params","query","sendResponse","rel","uri","error","console","status","json","pathTemplate","parameters","URI","expand","registerOperation","method","operation","bodyParameters","headerParameters","upperCaseMethod","toUpperCase","lowerCaseMethod","lowerCaseHeaderParameters","headerName","body","requestHeaders","requestUrl","template","Template","pathParameters","match","registerStaticResource","links","registerCollection","itemEndpoint","itemPath","itemLoader","collectionPath","collectionLoader","filters","itemType","undefined","linkTemplates","filter","push","join","type","page","otherParameters","selfUri","location","pageInt","Number","parseInt","isNaN","filteredParameters","parameter","arrayPointer","hasMore","itemOperations","array","pointer","itemLinks","canonicalLinks","additionalPaths","registerStaticCollection","collection","pageSize","items","slice","length","additionalLinks","toString","end"],"mappings":"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","sourcesContent":["import { Router } from 'express'\nimport { URI } from 'uri-template-lite'\nimport pointer from 'jsonpointer'\nimport { methodCanHaveBody } from './method-can-have-body'\nimport { covertResourceLinks } from './convert-resource-links'\nimport { buildFirstLink } from './collections/build-first-link'\nimport { buildPreviousLink } from './collections/build-previous-link'\nimport { buildNextLink } from './collections/build-next-link'\nimport { builtItemLinks } from './collections/built-item-links'\nimport { methodIsCacheable } from './method-is-cacheable'\n\n/**\n * @param url\n */\nfunction routerToRfc6570 (url) {\n return url.replace(/:(\\w*)/g, '{+$1}')\n}\nexport class WayCharter {\n constructor () {\n this.router = Router()\n }\n\n registerResourceType ({ path, loader, loaderVaries }) {\n // TODO: error handling for path not set\n // TODO: error handling for loader not set\n const lowerCaseLoaderVaries = new Set(\n loaderVaries ? loaderVaries.map(header => header.toLowerCase()) : []\n )\n const uriTemplate = routerToRfc6570(path)\n this.router.get(path, async function (request, response, next) {\n const filteredHeaders = Object.keys(request.headers).reduce(\n (filtered, key) =>\n lowerCaseLoaderVaries.has(key)\n ? { ...filtered, [key]: request.headers[key] }\n : filtered,\n {}\n )\n try {\n const resource = await loader(\n { ...request.params, ...request.query },\n filteredHeaders,\n request.url,\n request,\n response\n )\n\n if (loaderVaries) {\n response.header('vary', [...lowerCaseLoaderVaries])\n }\n sendResponse(resource, response, request.url, [\n {\n rel: 'self',\n uri: request.url\n }\n ])\n } catch (error) {\n // next(error)\n console.error(error)\n response.status(500)\n response.json({})\n }\n })\n return {\n pathTemplate: uriTemplate,\n path: parameters => URI.expand(uriTemplate, parameters)\n }\n }\n\n registerOperation ({\n method,\n path,\n operation,\n bodyParameters,\n headerParameters\n }) {\n const upperCaseMethod = method.toUpperCase()\n const lowerCaseMethod = method.toLowerCase()\n const lowerCaseHeaderParameters =\n headerParameters &&\n new Set(headerParameters.map(header => header.toLowerCase()))\n this.router[lowerCaseMethod](path, async (request, response, next) => {\n try {\n let filteredHeaders = request.headers\n if (methodIsCacheable(upperCaseMethod) && headerParameters) {\n response.header('vary', [...lowerCaseHeaderParameters])\n filteredHeaders = {}\n for (const headerName in request.headers) {\n if (lowerCaseHeaderParameters.has(headerName)) {\n filteredHeaders[headerName] = request.headers[headerName]\n }\n }\n }\n\n const resource = await operation({\n parameters: {\n ...request.params,\n ...request.query,\n ...(methodCanHaveBody(upperCaseMethod) && request.body)\n },\n requestHeaders: filteredHeaders,\n requestUrl: request.url,\n request,\n response\n })\n sendResponse(resource, response, request.url)\n } catch (error) {\n // next(error)\n console.error(error)\n response.status(500)\n response.json({})\n }\n })\n const uriTemplate = routerToRfc6570(path)\n const template = new URI.Template(uriTemplate)\n const pathParameters = template.match(uriTemplate)\n return {\n method: upperCaseMethod,\n ...(methodCanHaveBody(upperCaseMethod) && { bodyParameters }),\n pathParameters,\n ...(methodIsCacheable(upperCaseMethod) && {\n headerParameters: lowerCaseHeaderParameters\n }),\n pathTemplate: uriTemplate,\n path: parameters => URI.expand(uriTemplate, parameters)\n }\n }\n\n registerStaticResource ({ path, body, links }) {\n // TODO: error handling for path not set\n // TODO: error handling for body not set\n\n return this.registerResourceType({\n path,\n loader: async () => {\n return {\n body,\n links\n }\n }\n })\n }\n\n registerCollection ({\n itemEndpoint,\n itemPath,\n itemLoader,\n collectionPath,\n collectionLoader,\n filters = []\n }) {\n // TODO: error handling for itemPath set, but itemLoader isn't and visa-versa\n // TODO: error handling if itemEndpoint is set, and itemPath or itemLoader is set\n // TODO: error handling for collectionPath not set\n // TODO: error handling for collectionLoader not set\n const itemType =\n itemPath !== undefined && itemLoader !== undefined\n ? this.registerResourceType({\n path: `${collectionPath}${itemPath}`,\n loader: itemLoader\n })\n : itemEndpoint\n\n const linkTemplates = []\n for (const filter of filters) {\n linkTemplates.push({\n rel: filter.rel,\n uri: `${collectionPath}{?${filter.parameters.join(',')}}`\n })\n }\n const type = this.registerResourceType({\n path: collectionPath,\n loader: async (\n { page, ...otherParameters },\n filteredHeaders,\n selfUri,\n request,\n response\n ) => {\n // ${collectionPath}?page=0 should redirect to ${collectionPath}\n if (page === '0') {\n return {\n status: 308,\n headers: {\n location: collectionPath\n }\n }\n }\n\n // page should be >= 0\n const pageInt = Number.parseInt(page || '0')\n\n if (Number.isNaN(pageInt)) {\n return {\n status: 400,\n body: {\n error: \"I don't understand what page you are trying to retrieve\",\n page\n }\n }\n }\n if (page < 0) {\n return {\n status: 400,\n body: {\n error:\n \"You've asked for a negative page. I don't know what that means\",\n page\n }\n }\n }\n // we only want to include query params that are part of the filter,\n // but we can include all path params\n const filteredParameters = { ...request.params }\n for (const filter of filters) {\n for (const parameter of filter.parameters) {\n if (otherParameters[parameter] !== undefined) {\n filteredParameters[parameter] = otherParameters[parameter]\n }\n }\n }\n\n const {\n body,\n arrayPointer,\n hasMore,\n headers,\n itemOperations,\n status\n } = await collectionLoader(\n {\n page: pageInt,\n ...filteredParameters\n },\n filteredHeaders,\n selfUri,\n request,\n response\n )\n const array = arrayPointer ? pointer.get(body, arrayPointer) : body\n const { itemLinks, canonicalLinks } = builtItemLinks(\n array,\n arrayPointer,\n itemType,\n selfUri,\n itemOperations\n )\n return {\n body,\n links: [\n ...itemLinks,\n ...canonicalLinks,\n ...buildNextLink(hasMore, pageInt, collectionPath, otherParameters),\n ...buildPreviousLink(pageInt, collectionPath, otherParameters),\n ...buildFirstLink(hasMore, pageInt, collectionPath, otherParameters)\n ],\n linkTemplates,\n headers,\n status\n }\n }\n })\n return { ...type, additionalPaths: linkTemplates }\n }\n\n registerStaticCollection ({\n collectionPath,\n collection,\n pageSize,\n arrayPointer,\n headers\n }) {\n return this.registerCollection({\n collectionPath,\n collectionLoader: async ({ page }) => {\n const items = pageSize\n ? collection.slice(page * pageSize, (page + 1) * pageSize)\n : collection\n return {\n body: items,\n hasMore: pageSize && page < collection.length / pageSize - 1,\n arrayPointer,\n headers\n }\n }\n })\n }\n}\n/**\n * @param resource\n * @param response\n * @param requestUrl\n * @param additionalLinks\n */\nfunction sendResponse (resource, response, requestUrl, additionalLinks = []) {\n if (resource.links || additionalLinks.length > 0) {\n const links = covertResourceLinks([\n ...additionalLinks,\n ...(resource.links || [])\n ])\n response.header('link', links.toString())\n }\n if (resource.linkTemplates) {\n const linkTemplates = covertResourceLinks(resource.linkTemplates)\n response.header('link-template', linkTemplates.toString())\n }\n if (resource.status) {\n response.status(resource.status)\n }\n if (resource.headers) {\n for (const header in resource.headers) {\n response.header(header, resource.headers[header])\n }\n }\n if (resource.body) {\n response.json(resource.body)\n } else {\n response.end()\n }\n}\n"],"file":"waycharter.js"}
|
|
1
|
+
{"version":3,"sources":["../src/waycharter.js"],"names":["WayCharter","constructor","router","registerResourceType","path","loader","loaderVaries","lowerCaseLoaderVaries","Set","map","header","toLowerCase","uriTemplate","get","request","response","next","filteredHeaders","Object","keys","headers","reduce","filtered","key","has","resource","params","query","url","sendResponse","rel","uri","error","console","status","json","pathTemplate","parameters","URI","expand","registerOperation","method","operation","bodyParameters","headerParameters","upperCaseMethod","toUpperCase","lowerCaseMethod","lowerCaseHeaderParameters","headerName","body","requestHeaders","requestUrl","template","Template","pathParameters","match","registerStaticResource","links","registerCollection","itemEndpoint","itemPath","itemLoader","collectionPath","collectionLoader","filters","itemType","undefined","linkTemplates","filter","push","join","type","page","otherParameters","selfUri","expandedCollectionPath","location","pageInt","Number","parseInt","isNaN","filteredParameters","parameter","arrayPointer","hasMore","itemOperations","array","pointer","itemLinks","canonicalLinks","additionalPaths","registerStaticCollection","collection","pageSize","items","slice","length","additionalLinks","toString","end"],"mappings":"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","sourcesContent":["import { Router } from 'express'\nimport { URI } from 'uri-template-lite'\nimport pointer from 'jsonpointer'\nimport { methodCanHaveBody } from './method-can-have-body'\nimport { covertResourceLinks } from './convert-resource-links'\nimport { buildFirstLink } from './collections/build-first-link'\nimport { buildPreviousLink } from './collections/build-previous-link'\nimport { buildNextLink } from './collections/build-next-link'\nimport { builtItemLinks } from './collections/built-item-links'\nimport { methodIsCacheable } from './method-is-cacheable'\nimport { routerToRfc6570 } from './util/router-to-rfc6570'\n\nexport class WayCharter {\n constructor () {\n this.router = Router()\n }\n\n registerResourceType ({ path, loader, loaderVaries }) {\n // TODO: error handling for path not set\n // TODO: error handling for loader not set\n const lowerCaseLoaderVaries = new Set(\n loaderVaries ? loaderVaries.map(header => header.toLowerCase()) : []\n )\n const uriTemplate = routerToRfc6570(path)\n this.router.get(path, async function (request, response, next) {\n const filteredHeaders = Object.keys(request.headers).reduce(\n (filtered, key) =>\n lowerCaseLoaderVaries.has(key)\n ? { ...filtered, [key]: request.headers[key] }\n : filtered,\n {}\n )\n try {\n const resource = await loader(\n { ...request.params, ...request.query },\n filteredHeaders,\n request.url,\n request,\n response\n )\n\n if (loaderVaries) {\n response.header('vary', [...lowerCaseLoaderVaries])\n }\n sendResponse(resource, response, request.url, [\n {\n rel: 'self',\n uri: request.url\n }\n ])\n } catch (error) {\n // next(error)\n console.error(error)\n response.status(500)\n response.json({})\n }\n })\n return {\n pathTemplate: uriTemplate,\n path: parameters => URI.expand(uriTemplate, parameters)\n }\n }\n\n registerOperation ({\n method,\n path,\n operation,\n bodyParameters,\n headerParameters\n }) {\n const upperCaseMethod = method.toUpperCase()\n const lowerCaseMethod = method.toLowerCase()\n const lowerCaseHeaderParameters =\n headerParameters &&\n new Set(headerParameters.map(header => header.toLowerCase()))\n this.router[lowerCaseMethod](path, async (request, response, next) => {\n try {\n let filteredHeaders = request.headers\n if (methodIsCacheable(upperCaseMethod) && headerParameters) {\n response.header('vary', [...lowerCaseHeaderParameters])\n filteredHeaders = {}\n for (const headerName in request.headers) {\n if (lowerCaseHeaderParameters.has(headerName)) {\n filteredHeaders[headerName] = request.headers[headerName]\n }\n }\n }\n\n const resource = await operation({\n parameters: {\n ...request.params,\n ...request.query,\n ...(methodCanHaveBody(upperCaseMethod) && request.body)\n },\n requestHeaders: filteredHeaders,\n requestUrl: request.url,\n request,\n response\n })\n sendResponse(resource, response, request.url)\n } catch (error) {\n // next(error)\n console.error(error)\n response.status(500)\n response.json({})\n }\n })\n const uriTemplate = routerToRfc6570(path)\n const template = new URI.Template(uriTemplate)\n const pathParameters = template.match(uriTemplate)\n return {\n method: upperCaseMethod,\n ...(methodCanHaveBody(upperCaseMethod) && { bodyParameters }),\n pathParameters,\n ...(methodIsCacheable(upperCaseMethod) && {\n headerParameters: lowerCaseHeaderParameters\n }),\n pathTemplate: uriTemplate,\n path: parameters => URI.expand(uriTemplate, parameters)\n }\n }\n\n registerStaticResource ({ path, body, links }) {\n // TODO: error handling for path not set\n // TODO: error handling for body not set\n\n return this.registerResourceType({\n path,\n loader: async () => {\n return {\n body,\n links\n }\n }\n })\n }\n\n registerCollection ({\n itemEndpoint,\n itemPath,\n itemLoader,\n collectionPath,\n collectionLoader,\n filters = []\n }) {\n // TODO: error handling for itemPath set, but itemLoader isn't and visa-versa\n // TODO: error handling if itemEndpoint is set, and itemPath or itemLoader is set\n // TODO: error handling for collectionPath not set\n // TODO: error handling for collectionLoader not set\n\n // we need to handle collectionPath being parameterised\n\n const itemType =\n itemPath !== undefined && itemLoader !== undefined\n ? this.registerResourceType({\n path: `${collectionPath}${itemPath}`,\n loader: itemLoader\n })\n : itemEndpoint\n\n const linkTemplates = []\n for (const filter of filters) {\n linkTemplates.push({\n rel: filter.rel,\n uri: `${collectionPath}{?${filter.parameters.join(',')}}`\n })\n }\n const uriTemplate = routerToRfc6570(collectionPath)\n const type = this.registerResourceType({\n path: collectionPath,\n loader: async (\n { page, ...otherParameters },\n filteredHeaders,\n selfUri,\n request,\n response\n ) => {\n const expandedCollectionPath = URI.expand(uriTemplate, request.params)\n // ${collectionPath}?page=0 should redirect to ${collectionPath}\n if (page === '0') {\n return {\n status: 308,\n headers: {\n location: expandedCollectionPath\n }\n }\n }\n\n // page should be >= 0\n const pageInt = Number.parseInt(page || '0')\n\n if (Number.isNaN(pageInt)) {\n return {\n status: 400,\n body: {\n error: \"I don't understand what page you are trying to retrieve\",\n page\n }\n }\n }\n if (page < 0) {\n return {\n status: 400,\n body: {\n error:\n \"You've asked for a negative page. I don't know what that means\",\n page\n }\n }\n }\n // we only want to include query params that are part of the filter,\n // but we can include all path params\n const filteredParameters = {}\n for (const filter of filters) {\n for (const parameter of filter.parameters) {\n if (request.query[parameter] !== undefined) {\n filteredParameters[parameter] = request.query[parameter]\n }\n }\n }\n\n const {\n body,\n arrayPointer,\n hasMore,\n headers,\n itemOperations,\n status\n } = await collectionLoader(\n {\n page: pageInt,\n ...filteredParameters,\n ...request.params\n },\n filteredHeaders,\n selfUri,\n request,\n response\n )\n const array = arrayPointer ? pointer.get(body, arrayPointer) : body\n const { itemLinks, canonicalLinks } = builtItemLinks(\n array,\n arrayPointer,\n itemType,\n selfUri,\n itemOperations\n )\n return {\n body,\n links: [\n ...itemLinks,\n ...canonicalLinks,\n ...buildNextLink(\n hasMore,\n pageInt,\n expandedCollectionPath,\n filteredParameters\n ),\n ...buildPreviousLink(\n pageInt,\n expandedCollectionPath,\n filteredParameters\n ),\n ...buildFirstLink(\n hasMore,\n pageInt,\n expandedCollectionPath,\n filteredParameters\n )\n ],\n linkTemplates,\n headers,\n status\n }\n }\n })\n return { ...type, additionalPaths: linkTemplates }\n }\n\n registerStaticCollection ({\n collectionPath,\n collection,\n pageSize,\n arrayPointer,\n headers\n }) {\n return this.registerCollection({\n collectionPath,\n collectionLoader: async ({ page }) => {\n const items = pageSize\n ? collection.slice(page * pageSize, (page + 1) * pageSize)\n : collection\n return {\n body: items,\n hasMore: pageSize && page < collection.length / pageSize - 1,\n arrayPointer,\n headers\n }\n }\n })\n }\n}\n/**\n * @param resource\n * @param response\n * @param requestUrl\n * @param additionalLinks\n */\nfunction sendResponse (resource, response, requestUrl, additionalLinks = []) {\n if (resource.links || additionalLinks.length > 0) {\n const links = covertResourceLinks([\n ...additionalLinks,\n ...(resource.links || [])\n ])\n response.header('link', links.toString())\n }\n if (resource.linkTemplates) {\n const linkTemplates = covertResourceLinks(resource.linkTemplates)\n response.header('link-template', linkTemplates.toString())\n }\n if (resource.status) {\n response.status(resource.status)\n }\n if (resource.headers) {\n for (const header in resource.headers) {\n response.header(header, resource.headers[header])\n }\n }\n if (resource.body) {\n response.json(resource.body)\n } else {\n response.end()\n }\n}\n"],"file":"waycharter.js"}
|