@mountainpass/waycharter 1.0.72 → 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,27 @@
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
+
7
+ ## <small>1.0.75 (2021-12-13)</small>
8
+
9
+ * feat(collections): item endpoints can now be used when registering collections ([15fa46d](https://github.com/mountain-pass/waycharter/commit/15fa46d))
10
+
11
+
12
+
13
+ ## <small>1.0.74 (2021-11-17)</small>
14
+
15
+ * Merge pull request #357 from mountain-pass/dependabot/npm_and_yarn/snyk-1.763.0 ([ea63657](https://github.com/mountain-pass/waycharter/commit/ea63657)), closes [#357](https://github.com/mountain-pass/waycharter/issues/357)
16
+
17
+
18
+
19
+ ## <small>1.0.73 (2021-11-16)</small>
20
+
21
+ * Merge pull request #344 from mountain-pass/dependabot/npm_and_yarn/eslint-plugin-jsdoc-37.0.3 ([65a78d0](https://github.com/mountain-pass/waycharter/commit/65a78d0)), closes [#344](https://github.com/mountain-pass/waycharter/issues/344)
22
+
23
+
24
+
1
25
  ## <small>1.0.72 (2021-11-15)</small>
2
26
 
3
27
  * Merge pull request #322 from mountain-pass/dependabot/npm_and_yarn/prettier-2.4.1 ([f202372](https://github.com/mountain-pass/waycharter/commit/f202372)), closes [#322](https://github.com/mountain-pass/waycharter/issues/322)
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.72?label=npm%20package%20vulnerabilties&logo=snyk)](https://snyk.io/test/npm/@mountainpass/waycharter/1.0.72)
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)
@@ -117,8 +117,12 @@ function buildLink({
117
117
  rel,
118
118
  uri,
119
119
  anchor,
120
- method: endpoint.method,
121
- parameters: endpoint.parameters || endpoint.bodyParameters,
120
+ ...(endpoint.method && {
121
+ method: endpoint.method
122
+ }),
123
+ ...((endpoint.parameters || endpoint.bodyParameters) && {
124
+ parameters: endpoint.parameters || endpoint.bodyParameters
125
+ }),
122
126
  ...((0, _methodCanHaveBody.methodCanHaveBody)(endpoint.method) && {
123
127
  accept: ['application/x-www-form-urlencoded', 'application/json', 'multipart/form-data']
124
128
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/collections/built-item-links.js"],"names":["builtItemLinks","array","arrayPointer","itemType","selfUri","itemOperations","itemLinks","canonicalLinks","length","push","rel","uri","path","anchor","relationship","endpoint","buildLink","pathTemplate","template","URI","Template","parameters","match","Object","keys","forEach","key","replace","method","bodyParameters","accept"],"mappings":"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","sourcesContent":["import { URI } from 'uri-template-lite'\nimport { methodCanHaveBody } from '../method-can-have-body'\n\n/**\n * @param array\n * @param arrayPointer\n * @param itemType\n * @param collectionPath\n * @param selfUri\n * @param itemOperations\n */\nexport function builtItemLinks (\n array,\n arrayPointer,\n itemType,\n selfUri,\n itemOperations\n) {\n const itemLinks = []\n const canonicalLinks = []\n if (array.length === 1) {\n itemLinks.push({\n rel: 'item',\n uri: `${selfUri}#${arrayPointer || ''}/0`\n })\n if (itemType) {\n canonicalLinks.push({\n rel: 'canonical',\n uri: itemType.path(array[0]),\n anchor: `#${arrayPointer || ''}/0`\n })\n }\n if (itemOperations) {\n for (const relationship in itemOperations) {\n const endpoint = itemOperations[relationship]\n itemLinks.push(\n buildLink({\n rel: relationship,\n uri: endpoint.path(array[0]),\n anchor: `#${arrayPointer || ''}/0`,\n endpoint,\n array,\n arrayPointer\n })\n )\n }\n }\n } else if (array.length > 0) {\n itemLinks.push({\n rel: 'item',\n uri: `${selfUri}#${arrayPointer || ''}/{[0..${array.length - 1}]}`\n })\n if (itemType) {\n let pathTemplate = itemType.pathTemplate + ''\n const template = new URI.Template(itemType.pathTemplate)\n const parameters = template.match(itemType.pathTemplate)\n Object.keys(parameters).forEach(key => {\n pathTemplate = pathTemplate.replace(parameters[key], `{this.${key}}`)\n })\n canonicalLinks.push({\n rel: 'canonical',\n uri: pathTemplate,\n anchor: `#${arrayPointer || ''}/{[0..${array.length - 1}]}`\n })\n }\n if (itemOperations) {\n for (const relationship in itemOperations) {\n const endpoint = itemOperations[relationship]\n let pathTemplate = endpoint.pathTemplate + ''\n const template = new URI.Template(endpoint.pathTemplate)\n const parameters = template.match(endpoint.pathTemplate)\n Object.keys(parameters).forEach(key => {\n pathTemplate = pathTemplate.replace(parameters[key], `{this.${key}}`)\n })\n itemLinks.push(\n buildLink({\n rel: relationship,\n uri: pathTemplate,\n anchor: `#${arrayPointer || ''}/{[0..${array.length - 1}]}`,\n endpoint,\n array,\n arrayPointer\n })\n )\n }\n }\n }\n return { itemLinks, canonicalLinks }\n}\n/**\n * @param root0\n * @param root0.rel\n * @param root0.uri\n * @param root0.anchor\n * @param root0.endpoint\n * @param root0.array\n * @param root0.arrayPointer\n */\nfunction buildLink ({ rel, uri, anchor, endpoint, array, arrayPointer }) {\n return {\n rel,\n uri,\n anchor,\n method: endpoint.method,\n parameters: endpoint.parameters || endpoint.bodyParameters,\n ...(methodCanHaveBody(endpoint.method) && {\n accept: [\n 'application/x-www-form-urlencoded',\n 'application/json',\n 'multipart/form-data'\n ]\n })\n }\n}\n"],"file":"built-item-links.js"}
1
+ {"version":3,"sources":["../../src/collections/built-item-links.js"],"names":["builtItemLinks","array","arrayPointer","itemType","selfUri","itemOperations","itemLinks","canonicalLinks","length","push","rel","uri","path","anchor","relationship","endpoint","buildLink","pathTemplate","template","URI","Template","parameters","match","Object","keys","forEach","key","replace","method","bodyParameters","accept"],"mappings":"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","sourcesContent":["import { URI } from 'uri-template-lite'\nimport { methodCanHaveBody } from '../method-can-have-body'\n\n/**\n * @param array\n * @param arrayPointer\n * @param itemType\n * @param collectionPath\n * @param selfUri\n * @param itemOperations\n */\nexport function builtItemLinks (\n array,\n arrayPointer,\n itemType,\n selfUri,\n itemOperations\n) {\n const itemLinks = []\n const canonicalLinks = []\n if (array.length === 1) {\n itemLinks.push({\n rel: 'item',\n uri: `${selfUri}#${arrayPointer || ''}/0`\n })\n if (itemType) {\n canonicalLinks.push({\n rel: 'canonical',\n uri: itemType.path(array[0]),\n anchor: `#${arrayPointer || ''}/0`\n })\n }\n if (itemOperations) {\n for (const relationship in itemOperations) {\n const endpoint = itemOperations[relationship]\n itemLinks.push(\n buildLink({\n rel: relationship,\n uri: endpoint.path(array[0]),\n anchor: `#${arrayPointer || ''}/0`,\n endpoint,\n array,\n arrayPointer\n })\n )\n }\n }\n } else if (array.length > 0) {\n itemLinks.push({\n rel: 'item',\n uri: `${selfUri}#${arrayPointer || ''}/{[0..${array.length - 1}]}`\n })\n if (itemType) {\n let pathTemplate = itemType.pathTemplate + ''\n const template = new URI.Template(itemType.pathTemplate)\n const parameters = template.match(itemType.pathTemplate)\n Object.keys(parameters).forEach(key => {\n pathTemplate = pathTemplate.replace(parameters[key], `{this.${key}}`)\n })\n canonicalLinks.push({\n rel: 'canonical',\n uri: pathTemplate,\n anchor: `#${arrayPointer || ''}/{[0..${array.length - 1}]}`\n })\n }\n if (itemOperations) {\n for (const relationship in itemOperations) {\n const endpoint = itemOperations[relationship]\n let pathTemplate = endpoint.pathTemplate + ''\n const template = new URI.Template(endpoint.pathTemplate)\n const parameters = template.match(endpoint.pathTemplate)\n Object.keys(parameters).forEach(key => {\n pathTemplate = pathTemplate.replace(parameters[key], `{this.${key}}`)\n })\n itemLinks.push(\n buildLink({\n rel: relationship,\n uri: pathTemplate,\n anchor: `#${arrayPointer || ''}/{[0..${array.length - 1}]}`,\n endpoint,\n array,\n arrayPointer\n })\n )\n }\n }\n }\n return { itemLinks, canonicalLinks }\n}\n/**\n * @param root0\n * @param root0.rel\n * @param root0.uri\n * @param root0.anchor\n * @param root0.endpoint\n * @param root0.array\n * @param root0.arrayPointer\n */\nfunction buildLink ({ rel, uri, anchor, endpoint, array, arrayPointer }) {\n return {\n rel,\n uri,\n anchor,\n ...(endpoint.method && { method: endpoint.method }),\n ...((endpoint.parameters || endpoint.bodyParameters) && {\n parameters: endpoint.parameters || endpoint.bodyParameters\n }),\n ...(methodCanHaveBody(endpoint.method) && {\n accept: [\n 'application/x-www-form-urlencoded',\n 'application/json',\n 'multipart/form-data'\n ]\n })\n }\n}\n"],"file":"built-item-links.js"}
@@ -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]
@@ -56,7 +51,7 @@ class WayCharter {
56
51
  try {
57
52
  const resource = await loader({ ...request.params,
58
53
  ...request.query
59
- }, filteredHeaders, request.url);
54
+ }, filteredHeaders, request.url, request, response);
60
55
 
61
56
  if (loaderVaries) {
62
57
  response.header('vary', [...lowerCaseLoaderVaries]);
@@ -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 {
@@ -158,6 +153,7 @@ class WayCharter {
158
153
  }
159
154
 
160
155
  registerCollection({
156
+ itemEndpoint,
161
157
  itemPath,
162
158
  itemLoader,
163
159
  collectionPath,
@@ -165,12 +161,14 @@ class WayCharter {
165
161
  filters = []
166
162
  }) {
167
163
  // TODO: error handling for itemPath set, but itemLoader isn't and visa-versa
164
+ // TODO: error handling if itemEndpoint is set, and itemPath or itemLoader is set
168
165
  // TODO: error handling for collectionPath not set
169
166
  // TODO: error handling for collectionLoader not set
167
+ // we need to handle collectionPath being parameterised
170
168
  const itemType = itemPath !== undefined && itemLoader !== undefined ? this.registerResourceType({
171
169
  path: `${collectionPath}${itemPath}`,
172
170
  loader: itemLoader
173
- }) : undefined;
171
+ }) : itemEndpoint;
174
172
  const linkTemplates = [];
175
173
 
176
174
  for (const filter of filters) {
@@ -180,38 +178,56 @@ class WayCharter {
180
178
  });
181
179
  }
182
180
 
181
+ const uriTemplate = (0, _routerToRfc.routerToRfc6570)(collectionPath);
183
182
  const type = this.registerResourceType({
184
183
  path: collectionPath,
185
184
  loader: async ({
186
185
  page,
187
186
  ...otherParameters
188
- }, filteredHeaders, selfUri) => {
189
- // ${collectionPath}?page=0 should redirect to ${collectionPath}
187
+ }, filteredHeaders, selfUri, request, response) => {
188
+ const expandedCollectionPath = _uriTemplateLite.URI.expand(uriTemplate, request.params); // ${collectionPath}?page=0 should redirect to ${collectionPath}
189
+
190
+
190
191
  if (page === '0') {
191
192
  return {
192
193
  status: 308,
193
194
  headers: {
194
- location: collectionPath
195
+ location: expandedCollectionPath
195
196
  }
196
197
  };
197
- } // TODO: page is not a number
198
- // page should be >= 0
198
+ } // page should be >= 0
199
199
 
200
200
 
201
201
  const pageInt = Number.parseInt(page || '0');
202
202
 
203
- if (page < 0) {
203
+ if (Number.isNaN(pageInt)) {
204
204
  return {
205
- status: 400
205
+ status: 400,
206
+ body: {
207
+ error: "I don't understand what page you are trying to retrieve",
208
+ page
209
+ }
206
210
  };
207
211
  }
208
212
 
213
+ if (page < 0) {
214
+ return {
215
+ status: 400,
216
+ body: {
217
+ error: "You've asked for a negative page. I don't know what that means",
218
+ page
219
+ }
220
+ };
221
+ } // we only want to include query params that are part of the filter,
222
+ // but we can include all path params
223
+
224
+
209
225
  const filteredParameters = {};
210
226
 
211
227
  for (const filter of filters) {
212
228
  for (const parameter of filter.parameters) {
213
- if (otherParameters[parameter] !== undefined) {
214
- filteredParameters[parameter] = otherParameters[parameter];
229
+ if (request.query[parameter] !== undefined) {
230
+ filteredParameters[parameter] = request.query[parameter];
215
231
  }
216
232
  }
217
233
  }
@@ -221,11 +237,13 @@ class WayCharter {
221
237
  arrayPointer,
222
238
  hasMore,
223
239
  headers,
224
- itemOperations
240
+ itemOperations,
241
+ status
225
242
  } = await collectionLoader({
226
243
  page: pageInt,
227
- ...filteredParameters
228
- });
244
+ ...filteredParameters,
245
+ ...request.params
246
+ }, filteredHeaders, selfUri, request, response);
229
247
  const array = arrayPointer ? _jsonpointer.default.get(body, arrayPointer) : body;
230
248
  const {
231
249
  itemLinks,
@@ -233,9 +251,10 @@ class WayCharter {
233
251
  } = (0, _builtItemLinks.builtItemLinks)(array, arrayPointer, itemType, selfUri, itemOperations);
234
252
  return {
235
253
  body,
236
- 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)],
237
255
  linkTemplates,
238
- headers
256
+ headers,
257
+ status
239
258
  };
240
259
  }
241
260
  });
@@ -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","itemPath","itemLoader","collectionPath","collectionLoader","filters","itemType","undefined","linkTemplates","filter","push","join","type","page","otherParameters","selfUri","location","pageInt","Number","parseInt","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 )\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 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 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 : undefined\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 ) => {\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 // TODO: page is not a number\n\n // page should be >= 0\n const pageInt = Number.parseInt(page || '0')\n if (page < 0) {\n return {\n status: 400\n }\n }\n const filteredParameters = {}\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 } = await collectionLoader({\n page: pageInt,\n ...filteredParameters\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 }\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.72",
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",
@@ -117,7 +117,7 @@
117
117
  "eslint-plugin-eslint-comments": "^3.2.0",
118
118
  "eslint-plugin-import": "^2.22.1",
119
119
  "eslint-plugin-istanbul": "^0.1.2",
120
- "eslint-plugin-jsdoc": "^35.0.0",
120
+ "eslint-plugin-jsdoc": "^37.0.3",
121
121
  "eslint-plugin-json": "^3.0.0",
122
122
  "eslint-plugin-markdown": "^2.2.0",
123
123
  "eslint-plugin-md": "^1.0.19",