@loopback/rest 5.1.0 → 5.2.1

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.
Files changed (107) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/body-parsers/body-parser.d.ts +1 -1
  3. package/dist/body-parsers/body-parser.js +112 -115
  4. package/dist/body-parsers/body-parser.js.map +1 -1
  5. package/dist/body-parsers/body-parser.json.js +24 -27
  6. package/dist/body-parsers/body-parser.json.js.map +1 -1
  7. package/dist/body-parsers/body-parser.raw.js +19 -22
  8. package/dist/body-parsers/body-parser.raw.js.map +1 -1
  9. package/dist/body-parsers/body-parser.text.js +21 -24
  10. package/dist/body-parsers/body-parser.text.js.map +1 -1
  11. package/dist/body-parsers/body-parser.urlencoded.js +19 -22
  12. package/dist/body-parsers/body-parser.urlencoded.js.map +1 -1
  13. package/dist/coercion/coerce-parameter.d.ts +3 -1
  14. package/dist/coercion/coerce-parameter.js +28 -12
  15. package/dist/coercion/coerce-parameter.js.map +1 -1
  16. package/dist/http-handler.d.ts +1 -1
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.js +2 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/keys.d.ts +1 -1
  21. package/dist/keys.js +33 -34
  22. package/dist/keys.js.map +1 -1
  23. package/dist/parser.js +1 -1
  24. package/dist/parser.js.map +1 -1
  25. package/dist/providers/find-route.provider.d.ts +1 -1
  26. package/dist/providers/find-route.provider.js +21 -24
  27. package/dist/providers/find-route.provider.js.map +1 -1
  28. package/dist/providers/invoke-method.provider.d.ts +1 -1
  29. package/dist/providers/invoke-method.provider.js +16 -19
  30. package/dist/providers/invoke-method.provider.js.map +1 -1
  31. package/dist/providers/log-error.provider.d.ts +1 -1
  32. package/dist/providers/parse-params.provider.d.ts +1 -1
  33. package/dist/providers/parse-params.provider.js +20 -23
  34. package/dist/providers/parse-params.provider.js.map +1 -1
  35. package/dist/providers/reject.provider.d.ts +1 -1
  36. package/dist/providers/reject.provider.js +25 -28
  37. package/dist/providers/reject.provider.js.map +1 -1
  38. package/dist/providers/send.provider.d.ts +1 -1
  39. package/dist/request-context.d.ts +1 -1
  40. package/dist/rest.application.d.ts +1 -2
  41. package/dist/rest.application.js.map +1 -1
  42. package/dist/rest.component.d.ts +1 -1
  43. package/dist/rest.component.js +46 -49
  44. package/dist/rest.component.js.map +1 -1
  45. package/dist/rest.server.d.ts +1 -2
  46. package/dist/rest.server.js +618 -621
  47. package/dist/rest.server.js.map +1 -1
  48. package/dist/router/base-route.d.ts +1 -1
  49. package/dist/router/controller-route.d.ts +1 -1
  50. package/dist/router/controller-route.js +3 -4
  51. package/dist/router/controller-route.js.map +1 -1
  52. package/dist/router/handler-route.d.ts +1 -1
  53. package/dist/router/handler-route.js +2 -2
  54. package/dist/router/handler-route.js.map +1 -1
  55. package/dist/router/redirect-route.js +2 -2
  56. package/dist/router/redirect-route.js.map +1 -1
  57. package/dist/router/regexp-router.js +55 -58
  58. package/dist/router/regexp-router.js.map +1 -1
  59. package/dist/router/route-entry.d.ts +1 -1
  60. package/dist/router/trie-router.js +31 -34
  61. package/dist/router/trie-router.js.map +1 -1
  62. package/dist/sequence.d.ts +1 -1
  63. package/dist/sequence.js +74 -77
  64. package/dist/sequence.js.map +1 -1
  65. package/dist/spec-enhancers/consolidate.spec-enhancer.js +89 -92
  66. package/dist/spec-enhancers/consolidate.spec-enhancer.js.map +1 -1
  67. package/dist/spec-enhancers/info.spec-enhancer.js +63 -67
  68. package/dist/spec-enhancers/info.spec-enhancer.js.map +1 -1
  69. package/dist/types.d.ts +10 -0
  70. package/dist/validation/ajv-factory.provider.js +63 -66
  71. package/dist/validation/ajv-factory.provider.js.map +1 -1
  72. package/dist/validation/request-body.validator.d.ts +10 -2
  73. package/dist/validation/request-body.validator.js +25 -9
  74. package/dist/validation/request-body.validator.js.map +1 -1
  75. package/package.json +29 -27
  76. package/src/body-parsers/body-parser.json.ts +1 -1
  77. package/src/body-parsers/body-parser.raw.ts +1 -1
  78. package/src/body-parsers/body-parser.text.ts +1 -1
  79. package/src/body-parsers/body-parser.ts +1 -1
  80. package/src/body-parsers/body-parser.urlencoded.ts +1 -1
  81. package/src/coercion/coerce-parameter.ts +55 -15
  82. package/src/http-handler.ts +1 -1
  83. package/src/index.ts +6 -0
  84. package/src/keys.ts +1 -2
  85. package/src/parser.ts +1 -1
  86. package/src/providers/find-route.provider.ts +1 -1
  87. package/src/providers/invoke-method.provider.ts +1 -1
  88. package/src/providers/log-error.provider.ts +1 -1
  89. package/src/providers/parse-params.provider.ts +1 -1
  90. package/src/providers/reject.provider.ts +1 -1
  91. package/src/providers/send.provider.ts +1 -1
  92. package/src/request-context.ts +1 -1
  93. package/src/rest.application.ts +4 -2
  94. package/src/rest.component.ts +1 -1
  95. package/src/rest.server.ts +5 -3
  96. package/src/router/base-route.ts +1 -1
  97. package/src/router/controller-route.ts +2 -2
  98. package/src/router/external-express-routes.ts +1 -1
  99. package/src/router/handler-route.ts +1 -1
  100. package/src/router/redirect-route.ts +1 -2
  101. package/src/router/regexp-router.ts +1 -1
  102. package/src/router/route-entry.ts +1 -1
  103. package/src/router/trie-router.ts +1 -1
  104. package/src/sequence.ts +1 -1
  105. package/src/spec-enhancers/info.spec-enhancer.ts +3 -2
  106. package/src/types.ts +11 -0
  107. package/src/validation/request-body.validator.ts +35 -12
@@ -3,7 +3,7 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {Provider, BoundValue} from '@loopback/context';
6
+ import {Provider, BoundValue} from '@loopback/core';
7
7
  import {writeResultToResponse} from '../writer';
8
8
  /**
9
9
  * Provides the function that populates the response object with
@@ -3,7 +3,7 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {Context} from '@loopback/context';
6
+ import {Context} from '@loopback/core';
7
7
  import {
8
8
  HandlerContext,
9
9
  MiddlewareContext,
@@ -4,13 +4,15 @@
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
6
  import {
7
+ Application,
8
+ ApplicationConfig,
7
9
  Binding,
8
10
  BindingAddress,
9
11
  Constructor,
10
12
  Context,
11
13
  Provider,
12
- } from '@loopback/context';
13
- import {Application, ApplicationConfig, Server} from '@loopback/core';
14
+ Server,
15
+ } from '@loopback/core';
14
16
  import {
15
17
  ExpressMiddlewareFactory,
16
18
  ExpressRequestHandler,
@@ -8,7 +8,7 @@ import {
8
8
  Constructor,
9
9
  createBindingFromClass,
10
10
  inject,
11
- } from '@loopback/context';
11
+ } from '@loopback/core';
12
12
  import {
13
13
  Application,
14
14
  Component,
@@ -4,18 +4,20 @@
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
6
  import {
7
+ Application,
7
8
  Binding,
8
9
  BindingAddress,
9
10
  BindingScope,
10
11
  Constructor,
11
12
  ContextObserver,
13
+ CoreBindings,
12
14
  createBindingFromClass,
13
15
  filterByKey,
14
16
  filterByTag,
15
17
  inject,
18
+ Server,
16
19
  Subscription,
17
- } from '@loopback/context';
18
- import {Application, CoreBindings, Server} from '@loopback/core';
20
+ } from '@loopback/core';
19
21
  import {BaseMiddlewareRegistry, ExpressRequestHandler} from '@loopback/express';
20
22
  import {HttpServer, HttpServerOptions} from '@loopback/http-server';
21
23
  import {
@@ -178,7 +180,7 @@ export class RestServer extends BaseMiddlewareRegistry
178
180
  * will be 'http://localhost:3000' regardless of the `basePath`.
179
181
  */
180
182
  get rootUrl(): string | undefined {
181
- return this._httpServer && this._httpServer.url;
183
+ return this._httpServer?.url;
182
184
  }
183
185
 
184
186
  /**
@@ -3,7 +3,7 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {Context, InvocationSource} from '@loopback/context';
6
+ import {Context, InvocationSource} from '@loopback/core';
7
7
  import {OperationObject} from '@loopback/openapi-v3';
8
8
  import {OperationArgs, OperationRetval} from '../types';
9
9
  import {RouteEntry} from './route-entry';
@@ -7,11 +7,11 @@ import {
7
7
  BindingScope,
8
8
  Constructor,
9
9
  Context,
10
+ CoreBindings,
10
11
  instantiateClass,
11
12
  invokeMethod,
12
13
  ValueOrPromise,
13
- } from '@loopback/context';
14
- import {CoreBindings} from '@loopback/core';
14
+ } from '@loopback/core';
15
15
  import {ControllerSpec, OperationObject} from '@loopback/openapi-v3';
16
16
  import assert from 'assert';
17
17
  import debugFactory from 'debug';
@@ -3,7 +3,7 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {Context} from '@loopback/context';
6
+ import {Context} from '@loopback/core';
7
7
  import {
8
8
  executeExpressRequestHandler,
9
9
  ExpressRequestHandler,
@@ -3,7 +3,7 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {Context, invokeMethodWithInterceptors} from '@loopback/context';
6
+ import {Context, invokeMethodWithInterceptors} from '@loopback/core';
7
7
  import {OperationObject} from '@loopback/openapi-v3';
8
8
  import {RestBindings} from '../keys';
9
9
  import {OperationArgs, OperationRetval} from '../types';
@@ -54,8 +54,7 @@ export class RedirectRoute implements RouteEntry, ResolvedRoute {
54
54
  const redirectOptions = obj as RedirectRoute;
55
55
  if (
56
56
  redirectOptions?.targetLocation &&
57
- redirectOptions.spec &&
58
- redirectOptions.spec.description === 'LoopBack Redirect route'
57
+ redirectOptions.spec?.description === 'LoopBack Redirect route'
59
58
  ) {
60
59
  return true;
61
60
  }
@@ -3,7 +3,7 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {inject} from '@loopback/context';
6
+ import {inject} from '@loopback/core';
7
7
  import {inspect} from 'util';
8
8
  import {RestBindings} from '../keys';
9
9
  import {PathParameterValues} from '../types';
@@ -3,7 +3,7 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {Context} from '@loopback/context';
6
+ import {Context} from '@loopback/core';
7
7
  import {OperationObject, SchemasObject} from '@loopback/openapi-v3';
8
8
  import {OperationArgs, OperationRetval, PathParameterValues} from '../types';
9
9
 
@@ -3,7 +3,7 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {inject} from '@loopback/context';
6
+ import {inject} from '@loopback/core';
7
7
  import {inspect} from 'util';
8
8
  import {RestBindings} from '../keys';
9
9
  import {RestRouterOptions} from './rest-router';
package/src/sequence.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
6
  const debug = require('debug')('loopback:rest:sequence');
7
- import {inject, ValueOrPromise} from '@loopback/context';
7
+ import {inject, ValueOrPromise} from '@loopback/core';
8
8
  import {InvokeMiddleware} from '@loopback/express';
9
9
  import {RestBindings} from './keys';
10
10
  import {RequestContext} from './request-context';
@@ -4,13 +4,14 @@
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
6
  import {
7
+ ApplicationMetadata,
7
8
  bind,
8
9
  BindingScope,
10
+ CoreBindings,
9
11
  inject,
10
12
  JSONObject,
11
13
  JSONValue,
12
- } from '@loopback/context';
13
- import {ApplicationMetadata, CoreBindings} from '@loopback/core';
14
+ } from '@loopback/core';
14
15
  import {
15
16
  asSpecEnhancer,
16
17
  ContactObject,
package/src/types.ts CHANGED
@@ -108,6 +108,17 @@ export type AjvKeyword = KeywordDefinition & {name: string};
108
108
  */
109
109
  export type AjvFormat = FormatDefinition & {name: string};
110
110
 
111
+ /**
112
+ * Options for any value validation using AJV
113
+ */
114
+ export interface ValueValidationOptions extends RequestBodyValidationOptions {
115
+ /**
116
+ * Where the data comes from. It can be 'body', 'path', 'header',
117
+ * 'query', 'cookie', etc...
118
+ */
119
+ source?: string;
120
+ }
121
+
111
122
  /**
112
123
  * Options for request body validation using AJV
113
124
  */
@@ -15,7 +15,11 @@ import debugModule from 'debug';
15
15
  import _ from 'lodash';
16
16
  import util from 'util';
17
17
  import {HttpErrors, RequestBody, RestHttpErrors} from '..';
18
- import {RequestBodyValidationOptions, SchemaValidatorCache} from '../types';
18
+ import {
19
+ RequestBodyValidationOptions,
20
+ SchemaValidatorCache,
21
+ ValueValidationOptions,
22
+ } from '../types';
19
23
  import {AjvFactoryProvider} from './ajv-factory.provider';
20
24
 
21
25
  const toJsonSchema = require('@openapi-contrib/openapi-schema-to-json-schema');
@@ -66,7 +70,10 @@ export async function validateRequestBody(
66
70
  if (!schema) return;
67
71
 
68
72
  options = {coerceTypes: !!body.coercionRequired, ...options};
69
- await validateValueAgainstSchema(body.value, schema, globalSchemas, options);
73
+ await validateValueAgainstSchema(body.value, schema, globalSchemas, {
74
+ ...options,
75
+ source: 'body',
76
+ });
70
77
  }
71
78
 
72
79
  /**
@@ -115,12 +122,12 @@ function getKeyForOptions(options: RequestBodyValidationOptions) {
115
122
  * @param globalSchemas - Schema references.
116
123
  * @param options - Request body validation options.
117
124
  */
118
- async function validateValueAgainstSchema(
125
+ export async function validateValueAgainstSchema(
119
126
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
120
- body: any,
127
+ value: any,
121
128
  schema: SchemaObject | ReferenceObject,
122
129
  globalSchemas: SchemasObject = {},
123
- options: RequestBodyValidationOptions = {},
130
+ options: ValueValidationOptions = {},
124
131
  ) {
125
132
  let validate: ajv.ValidateFunction | undefined;
126
133
 
@@ -145,10 +152,10 @@ async function validateValueAgainstSchema(
145
152
 
146
153
  let validationErrors: ajv.ErrorObject[] = [];
147
154
  try {
148
- const validationResult = await validate(body);
149
- // When body is optional & values is empty / null, ajv returns null
155
+ const validationResult = await validate(value);
156
+ // When value is optional & values is empty / null, ajv returns null
150
157
  if (validationResult || validationResult === null) {
151
- debug('Request body passed AJV validation.');
158
+ debug(`Value from ${options.source} passed AJV validation.`);
152
159
  return;
153
160
  }
154
161
  } catch (error) {
@@ -158,8 +165,8 @@ async function validateValueAgainstSchema(
158
165
  /* istanbul ignore if */
159
166
  if (debug.enabled) {
160
167
  debug(
161
- 'Invalid request body: %s. Errors: %s',
162
- util.inspect(body, {depth: null}),
168
+ 'Invalid value: %s. Errors: %s',
169
+ util.inspect(value, {depth: null}),
163
170
  util.inspect(validationErrors),
164
171
  );
165
172
  }
@@ -168,7 +175,24 @@ async function validateValueAgainstSchema(
168
175
  validationErrors = options.ajvErrorTransformer(validationErrors);
169
176
  }
170
177
 
171
- const error = RestHttpErrors.invalidRequestBody();
178
+ // Throw invalid request body error
179
+ if (options.source === 'body') {
180
+ const error = RestHttpErrors.invalidRequestBody();
181
+ addErrorDetails(error, validationErrors);
182
+ throw error;
183
+ }
184
+
185
+ // Throw invalid value error
186
+ const error = new HttpErrors.BadRequest('Invalid value.');
187
+ addErrorDetails(error, validationErrors);
188
+ throw error;
189
+ }
190
+
191
+ function addErrorDetails(
192
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
193
+ error: any,
194
+ validationErrors: ajv.ErrorObject[],
195
+ ) {
172
196
  error.details = _.map(validationErrors, e => {
173
197
  return {
174
198
  path: e.dataPath,
@@ -177,7 +201,6 @@ async function validateValueAgainstSchema(
177
201
  info: e.params,
178
202
  };
179
203
  });
180
- throw error;
181
204
  }
182
205
 
183
206
  /**