@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 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
  <!-- [![Quality](https://img.shields.io/codacy/grade/940768d54f7545f7b42f89b26c23c751?logo=codacy)](https://www.codacy.com/gh/mountain-pass/waycharter/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=mountain-pass/waycharter&amp;utm_campaign=Badge_Grade) [![Coverage](https://img.shields.io/codacy/coverage/940768d54f7545f7b42f89b26c23c751?logo=codacy)](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
- [![source code vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/mountain-pass/waycharter?label=source%20code%20vulnerabilities&logo=snyk)](https://snyk.io/test/github/mountain-pass/waycharter) [![npm package vulnerabilities](https://img.shields.io/snyk/vulnerabilities/npm/@mountainpass/waycharter@1.0.75?label=npm%20package%20vulnerabilties&logo=snyk)](https://snyk.io/test/npm/@mountainpass/waycharter/1.0.75)
16
+ [![source code vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/mountain-pass/waycharter?label=source%20code%20vulnerabilities&logo=snyk)](https://snyk.io/test/github/mountain-pass/waycharter) [![npm package vulnerabilities](https://img.shields.io/snyk/vulnerabilities/npm/@mountainpass/waycharter@1.0.76?label=npm%20package%20vulnerabilties&logo=snyk)](https://snyk.io/test/npm/@mountainpass/waycharter/1.0.76)
17
17
 
18
18
 
19
19
  [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](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"}
@@ -25,14 +25,9 @@ var _builtItemLinks = require("./collections/built-item-links");
25
25
 
26
26
  var _methodIsCacheable = require("./method-is-cacheable");
27
27
 
28
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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: collectionPath
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 = { ...request.params
227
- };
225
+ const filteredParameters = {};
228
226
 
229
227
  for (const filter of filters) {
230
228
  for (const parameter of filter.parameters) {
231
- if (otherParameters[parameter] !== undefined) {
232
- filteredParameters[parameter] = otherParameters[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, collectionPath, otherParameters), ...(0, _buildPreviousLink.buildPreviousLink)(pageInt, collectionPath, otherParameters), ...(0, _buildFirstLink.buildFirstLink)(hasMore, pageInt, collectionPath, otherParameters)],
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
@@ -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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mountainpass/waycharter",
3
- "version": "1.0.75",
3
+ "version": "1.0.76",
4
4
  "description": "Express middleware creating for HATEOAS level 3 RESTful APIs that provide hypermedia controls",
5
5
  "repository": {
6
6
  "type": "git",