@loopback/rest 9.3.1 → 11.0.0
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/README.md +4 -4
- package/dist/body-parsers/body-parser.helpers.js +2 -2
- package/dist/body-parsers/body-parser.helpers.js.map +1 -1
- package/dist/body-parsers/body-parser.js +12 -12
- package/dist/body-parsers/body-parser.js.map +1 -1
- package/dist/body-parsers/body-parser.json.js +8 -8
- package/dist/body-parsers/body-parser.json.js.map +1 -1
- package/dist/body-parsers/body-parser.raw.js +7 -7
- package/dist/body-parsers/body-parser.raw.js.map +1 -1
- package/dist/body-parsers/body-parser.text.js +7 -7
- package/dist/body-parsers/body-parser.text.js.map +1 -1
- package/dist/body-parsers/body-parser.urlencoded.js +7 -7
- package/dist/body-parsers/body-parser.urlencoded.js.map +1 -1
- package/dist/body-parsers/index.js +8 -8
- package/dist/body-parsers/index.js.map +1 -1
- package/dist/coercion/coerce-parameter.js +14 -14
- package/dist/coercion/coerce-parameter.js.map +1 -1
- package/dist/coercion/utils.js +2 -2
- package/dist/coercion/utils.js.map +1 -1
- package/dist/index.js +19 -19
- package/dist/index.js.map +1 -1
- package/dist/keys.d.ts +1 -1
- package/dist/keys.js +1 -1
- package/dist/parser.js +8 -8
- package/dist/parser.js.map +1 -1
- package/dist/providers/find-route.provider.js +10 -10
- package/dist/providers/find-route.provider.js.map +1 -1
- package/dist/providers/index.js +6 -6
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/invoke-method.provider.js +9 -9
- package/dist/providers/invoke-method.provider.js.map +1 -1
- package/dist/providers/log-error.provider.js +2 -2
- package/dist/providers/log-error.provider.js.map +1 -1
- package/dist/providers/parse-params.provider.js +13 -13
- package/dist/providers/parse-params.provider.js.map +1 -1
- package/dist/providers/reject.provider.js +9 -9
- package/dist/providers/reject.provider.js.map +1 -1
- package/dist/providers/send.provider.js +4 -4
- package/dist/providers/send.provider.js.map +1 -1
- package/dist/rest-http-error.js +1 -1
- package/dist/rest-http-error.js.map +1 -1
- package/dist/rest.application.js +1 -1
- package/dist/rest.application.js.map +1 -1
- package/dist/rest.component.js +16 -16
- package/dist/rest.component.js.map +1 -1
- package/dist/rest.server.d.ts +1 -1
- package/dist/rest.server.js +33 -33
- package/dist/rest.server.js.map +1 -1
- package/dist/router/controller-route.js +8 -8
- package/dist/router/controller-route.js.map +1 -1
- package/dist/router/external-express-routes.js +5 -5
- package/dist/router/external-express-routes.js.map +1 -1
- package/dist/router/handler-route.js +1 -1
- package/dist/router/handler-route.js.map +1 -1
- package/dist/router/index.js +14 -14
- package/dist/router/index.js.map +1 -1
- package/dist/router/openapi-path.js +1 -1
- package/dist/router/openapi-path.js.map +1 -1
- package/dist/router/regexp-router.js +7 -7
- package/dist/router/regexp-router.js.map +1 -1
- package/dist/router/route-entry.d.ts +1 -1
- package/dist/router/route-sort.js +1 -1
- package/dist/router/route-sort.js.map +1 -1
- package/dist/router/router-base.js +2 -2
- package/dist/router/router-base.js.map +1 -1
- package/dist/router/routing-table.js +6 -6
- package/dist/router/routing-table.js.map +1 -1
- package/dist/router/trie-router.js +5 -5
- package/dist/router/trie-router.js.map +1 -1
- package/dist/router/trie.js +2 -2
- package/dist/router/trie.js.map +1 -1
- package/dist/sequence.js +18 -18
- package/dist/sequence.js.map +1 -1
- package/dist/spec-enhancers/consolidate.spec-enhancer.js +10 -10
- package/dist/spec-enhancers/consolidate.spec-enhancer.js.map +1 -1
- package/dist/spec-enhancers/info.spec-enhancer.js +7 -7
- package/dist/spec-enhancers/info.spec-enhancer.js.map +1 -1
- package/dist/types.d.ts +12 -17
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validation/ajv-factory.provider.js +27 -36
- package/dist/validation/ajv-factory.provider.js.map +1 -1
- package/dist/validation/openapi-formats.d.ts +5 -5
- package/dist/validation/openapi-formats.js.map +1 -1
- package/dist/validation/request-body.validator.js +9 -9
- package/dist/validation/request-body.validator.js.map +1 -1
- package/dist/writer.js +1 -1
- package/dist/writer.js.map +1 -1
- package/package.json +34 -33
- package/src/keys.ts +1 -1
- package/src/parser.ts +2 -2
- package/src/rest.server.ts +2 -2
- package/src/router/route-entry.ts +1 -1
- package/src/router/routing-table.ts +1 -1
- package/src/types.ts +19 -15
- package/src/validation/ajv-factory.provider.ts +14 -21
- package/src/validation/openapi-formats.ts +5 -5
- package/src/validation/request-body.validator.ts +14 -13
- package/src/writer.ts +2 -2
|
@@ -7,12 +7,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
exports.validateValueAgainstSchema = exports.validateRequestBody = void 0;
|
|
8
8
|
const tslib_1 = require("tslib");
|
|
9
9
|
const openapi_v3_1 = require("@loopback/openapi-v3");
|
|
10
|
-
const debug_1 = tslib_1.__importDefault(require("debug"));
|
|
11
|
-
const util_1 = tslib_1.__importDefault(require("util"));
|
|
10
|
+
const debug_1 = (0, tslib_1.__importDefault)(require("debug"));
|
|
11
|
+
const util_1 = (0, tslib_1.__importDefault)(require("util"));
|
|
12
12
|
const __1 = require("..");
|
|
13
13
|
const ajv_factory_provider_1 = require("./ajv-factory.provider");
|
|
14
14
|
const toJsonSchema = require('@openapi-contrib/openapi-schema-to-json-schema');
|
|
15
|
-
const debug = debug_1.default('loopback:rest:validation');
|
|
15
|
+
const debug = (0, debug_1.default)('loopback:rest:validation');
|
|
16
16
|
/**
|
|
17
17
|
* Check whether the request body is valid according to the provided OpenAPI schema.
|
|
18
18
|
* The JSON schema is generated from the OpenAPI schema which is typically defined
|
|
@@ -37,7 +37,7 @@ async function validateRequestBody(body, requestBodySpec, globalSchemas = {}, op
|
|
|
37
37
|
if (debug.enabled) {
|
|
38
38
|
debug('Request body schema:', util_1.default.inspect(schema, { depth: null }));
|
|
39
39
|
if (schema &&
|
|
40
|
-
openapi_v3_1.isReferenceObject(schema) &&
|
|
40
|
+
(0, openapi_v3_1.isReferenceObject)(schema) &&
|
|
41
41
|
schema.$ref.startsWith('#/components/schemas/')) {
|
|
42
42
|
const ref = schema.$ref.slice('#/components/schemas/'.length);
|
|
43
43
|
debug(' referencing:', util_1.default.inspect(globalSchemas[ref], { depth: null }));
|
|
@@ -113,9 +113,9 @@ value, schema, globalSchemas = {}, options = {}) {
|
|
|
113
113
|
}
|
|
114
114
|
let validationErrors = [];
|
|
115
115
|
try {
|
|
116
|
-
const validationResult =
|
|
116
|
+
const validationResult = validate(value);
|
|
117
117
|
debug(`Value from ${options.source} passed AJV validation.`, validationResult);
|
|
118
|
-
return validationResult;
|
|
118
|
+
return await validationResult;
|
|
119
119
|
}
|
|
120
120
|
catch (error) {
|
|
121
121
|
validationErrors = error.errors;
|
|
@@ -143,7 +143,7 @@ function buildErrorDetails(validationErrors) {
|
|
|
143
143
|
return validationErrors.map((e) => {
|
|
144
144
|
var _a;
|
|
145
145
|
return {
|
|
146
|
-
path: e.
|
|
146
|
+
path: e.instancePath,
|
|
147
147
|
code: e.keyword,
|
|
148
148
|
message: (_a = e.message) !== null && _a !== void 0 ? _a : `must pass validation rule ${e.keyword}`,
|
|
149
149
|
info: e.params,
|
|
@@ -161,11 +161,11 @@ function createValidator(schema, globalSchemas = {}, ajvInst) {
|
|
|
161
161
|
// Clone global schemas to set `$async: true` flag
|
|
162
162
|
const schemas = {};
|
|
163
163
|
for (const name in globalSchemas) {
|
|
164
|
-
// See https://github.com/
|
|
164
|
+
// See https://github.com/loopbackio/loopback-next/issues/4939
|
|
165
165
|
schemas[name] = { ...globalSchemas[name], $async: true };
|
|
166
166
|
}
|
|
167
167
|
const schemaWithRef = { components: { schemas }, ...jsonSchema };
|
|
168
|
-
// See https://
|
|
168
|
+
// See https://js.org/#asynchronous-validation for async validation
|
|
169
169
|
schemaWithRef.$async = true;
|
|
170
170
|
return ajvInst.compile(schemaWithRef);
|
|
171
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-body.validator.js","sourceRoot":"","sources":["../../src/validation/request-body.validator.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;;AAEhE,qDAM8B;
|
|
1
|
+
{"version":3,"file":"request-body.validator.js","sourceRoot":"","sources":["../../src/validation/request-body.validator.ts"],"names":[],"mappings":"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"}
|
package/dist/writer.js
CHANGED
|
@@ -45,7 +45,7 @@ result) {
|
|
|
45
45
|
}
|
|
46
46
|
else {
|
|
47
47
|
// TODO(ritch) remove this, should be configurable
|
|
48
|
-
// See https://github.com/
|
|
48
|
+
// See https://github.com/loopbackio/loopback-next/issues/436
|
|
49
49
|
response.setHeader('Content-Type', 'application/json');
|
|
50
50
|
// TODO(bajtos) handle errors - JSON.stringify can throw
|
|
51
51
|
result = JSON.stringify(result);
|
package/dist/writer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../src/writer.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../src/writer.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;AAEhE,mCAAgC;AAGhC;;;;;;GAMG;AACH,SAAgB,qBAAqB;AACnC,+DAA+D;AAC/D,QAAkB;AAClB,uDAAuD;AACvD,MAAuB;IAEvB,6EAA6E;IAC7E,yCAAyC;IACzC,IAAI,MAAM,KAAK,QAAQ,IAAI,QAAQ,CAAC,WAAW,EAAE;QAC/C,OAAO;KACR;IACD,IAAI,MAAM,KAAK,SAAS,EAAE;QACxB,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAC;QAC1B,QAAQ,CAAC,GAAG,EAAE,CAAC;QACf,OAAO;KACR;IAED,MAAM,QAAQ,GACZ,MAAM,YAAY,iBAAQ,IAAI,OAAO,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,CAAA,KAAK,UAAU,CAAC;IAEnE,IAAI,QAAQ,EAAE;QACZ,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;QAC/D,SAAS;QACT,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO;KACR;IACD,QAAQ,OAAO,MAAM,EAAE;QACrB,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS,CAAC;QACf,KAAK,QAAQ;YACX,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBAC3B,yBAAyB;gBACzB,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;aAChE;iBAAM;gBACL,kDAAkD;gBAClD,6DAA6D;gBAC7D,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;gBACvD,wDAAwD;gBACxD,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;aACjC;YACD,MAAM;QACR;YACE,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;YACjD,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC3B,MAAM;KACT;IACD,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACvB,CAAC;AA/CD,sDA+CC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loopback/rest",
|
|
3
3
|
"description": "Expose controllers as REST endpoints and route REST API requests to controller methods",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "11.0.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"copyright.owner": "IBM Corp.",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
|
-
"url": "https://github.com/
|
|
12
|
+
"url": "https://github.com/loopbackio/loopback-next.git",
|
|
13
13
|
"directory": "packages/rest"
|
|
14
14
|
},
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": "
|
|
16
|
+
"node": "12 || 14 || 16 || 17"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"acceptance": "lb-mocha \"dist/__tests__/acceptance/**/*.js\"",
|
|
@@ -35,27 +35,28 @@
|
|
|
35
35
|
"!*/__tests__"
|
|
36
36
|
],
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@loopback/core": "^
|
|
38
|
+
"@loopback/core": "^3.0.0"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@loopback/express": "^
|
|
42
|
-
"@loopback/http-server": "^
|
|
43
|
-
"@loopback/openapi-v3": "^
|
|
44
|
-
"@openapi-contrib/openapi-schema-to-json-schema": "^3.1.
|
|
45
|
-
"@types/body-parser": "^1.19.
|
|
46
|
-
"@types/cors": "^2.8.
|
|
47
|
-
"@types/express": "^4.17.
|
|
48
|
-
"@types/express-serve-static-core": "^4.17.
|
|
49
|
-
"@types/http-errors": "^1.8.
|
|
41
|
+
"@loopback/express": "^4.0.0",
|
|
42
|
+
"@loopback/http-server": "^3.0.0",
|
|
43
|
+
"@loopback/openapi-v3": "^7.0.0",
|
|
44
|
+
"@openapi-contrib/openapi-schema-to-json-schema": "^3.1.1",
|
|
45
|
+
"@types/body-parser": "^1.19.1",
|
|
46
|
+
"@types/cors": "^2.8.12",
|
|
47
|
+
"@types/express": "^4.17.13",
|
|
48
|
+
"@types/express-serve-static-core": "^4.17.24",
|
|
49
|
+
"@types/http-errors": "^1.8.1",
|
|
50
50
|
"@types/on-finished": "^2.3.1",
|
|
51
|
-
"@types/serve-static": "1.13.
|
|
51
|
+
"@types/serve-static": "1.13.10",
|
|
52
52
|
"@types/type-is": "^1.6.3",
|
|
53
|
-
"ajv": "^6.
|
|
54
|
-
"ajv-errors": "^
|
|
55
|
-
"ajv-
|
|
53
|
+
"ajv": "^8.6.3",
|
|
54
|
+
"ajv-errors": "^3.0.0",
|
|
55
|
+
"ajv-formats": "^2.1.1",
|
|
56
|
+
"ajv-keywords": "^5.0.0",
|
|
56
57
|
"body-parser": "^1.19.0",
|
|
57
58
|
"cors": "^2.8.5",
|
|
58
|
-
"debug": "^4.3.
|
|
59
|
+
"debug": "^4.3.2",
|
|
59
60
|
"express": "^4.17.1",
|
|
60
61
|
"http-errors": "^1.8.0",
|
|
61
62
|
"js-yaml": "^4.1.0",
|
|
@@ -65,26 +66,26 @@
|
|
|
65
66
|
"path-to-regexp": "^6.2.0",
|
|
66
67
|
"qs": "^6.10.1",
|
|
67
68
|
"strong-error-handler": "^4.0.0",
|
|
68
|
-
"tslib": "^2.
|
|
69
|
+
"tslib": "^2.3.1",
|
|
69
70
|
"type-is": "^1.6.18",
|
|
70
71
|
"validator": "^13.6.0"
|
|
71
72
|
},
|
|
72
73
|
"devDependencies": {
|
|
73
|
-
"@loopback/build": "^
|
|
74
|
-
"@loopback/core": "^
|
|
75
|
-
"@loopback/eslint-config": "^
|
|
76
|
-
"@loopback/openapi-spec-builder": "^
|
|
77
|
-
"@loopback/repository": "^
|
|
78
|
-
"@loopback/testlab": "^
|
|
79
|
-
"@types/debug": "^4.1.
|
|
80
|
-
"@types/js-yaml": "^4.0.
|
|
81
|
-
"@types/json-schema-compare": "^0.2.
|
|
82
|
-
"@types/lodash": "^4.14.
|
|
83
|
-
"@types/multer": "^1.4.
|
|
74
|
+
"@loopback/build": "^8.0.0",
|
|
75
|
+
"@loopback/core": "^3.0.0",
|
|
76
|
+
"@loopback/eslint-config": "^12.0.0",
|
|
77
|
+
"@loopback/openapi-spec-builder": "^4.0.0",
|
|
78
|
+
"@loopback/repository": "^4.0.0",
|
|
79
|
+
"@loopback/testlab": "^4.0.0",
|
|
80
|
+
"@types/debug": "^4.1.7",
|
|
81
|
+
"@types/js-yaml": "^4.0.4",
|
|
82
|
+
"@types/json-schema-compare": "^0.2.1",
|
|
83
|
+
"@types/lodash": "^4.14.176",
|
|
84
|
+
"@types/multer": "^1.4.7",
|
|
84
85
|
"@types/node": "^10.17.60",
|
|
85
86
|
"@types/on-finished": "^2.3.1",
|
|
86
|
-
"@types/qs": "^6.9.
|
|
87
|
-
"multer": "^1.4.
|
|
87
|
+
"@types/qs": "^6.9.7",
|
|
88
|
+
"multer": "^1.4.3"
|
|
88
89
|
},
|
|
89
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "00a62f630c19341ce399cec3a45563b1ead6e3b8"
|
|
90
91
|
}
|
package/src/keys.ts
CHANGED
|
@@ -92,7 +92,7 @@ export namespace RestBindings {
|
|
|
92
92
|
* Binding key for setting and injecting Reject action's error handling
|
|
93
93
|
* options.
|
|
94
94
|
*
|
|
95
|
-
* See https://github.com/
|
|
95
|
+
* See https://github.com/loopbackio/strong-error-handler#options for
|
|
96
96
|
* the list of available options. Please note that the flag `log` is not used
|
|
97
97
|
* by `@loopback/rest`.
|
|
98
98
|
*/
|
package/src/parser.ts
CHANGED
|
@@ -79,7 +79,7 @@ async function buildOperationArguments(
|
|
|
79
79
|
for (const paramSpec of operationSpec.parameters ?? []) {
|
|
80
80
|
if (isReferenceObject(paramSpec)) {
|
|
81
81
|
// TODO(bajtos) implement $ref parameters
|
|
82
|
-
// See https://github.com/
|
|
82
|
+
// See https://github.com/loopbackio/loopback-next/issues/435
|
|
83
83
|
throw new Error('$ref parameters are not supported yet.');
|
|
84
84
|
}
|
|
85
85
|
const spec = paramSpec as ParameterObject;
|
|
@@ -116,7 +116,7 @@ function getParamFromRequest(
|
|
|
116
116
|
// @jannyhou TBD: check edge cases
|
|
117
117
|
return request.headers[spec.name.toLowerCase()];
|
|
118
118
|
// TODO(jannyhou) to support `cookie`,
|
|
119
|
-
// see issue https://github.com/
|
|
119
|
+
// see issue https://github.com/loopbackio/loopback-next/issues/997
|
|
120
120
|
default:
|
|
121
121
|
throw RestHttpErrors.invalidParamLocation(spec.in);
|
|
122
122
|
}
|
package/src/rest.server.ts
CHANGED
|
@@ -398,7 +398,7 @@ export class RestServer
|
|
|
398
398
|
if (this._httpHandler) return;
|
|
399
399
|
|
|
400
400
|
// Watch for binding events
|
|
401
|
-
// See https://github.com/
|
|
401
|
+
// See https://github.com/loopbackio/loopback-next/issues/433
|
|
402
402
|
const routesObserver: ContextObserver = {
|
|
403
403
|
filter: binding =>
|
|
404
404
|
filterByKey(RestBindings.API_SPEC.key)(binding) ||
|
|
@@ -1147,7 +1147,7 @@ export interface ApiExplorerOptions {
|
|
|
1147
1147
|
* URL for the API explorer served over `http` protocol to deal with mixed
|
|
1148
1148
|
* content security imposed by browsers as the spec is exposed over `http` by
|
|
1149
1149
|
* default.
|
|
1150
|
-
* See https://github.com/
|
|
1150
|
+
* See https://github.com/loopbackio/loopback-next/issues/1603
|
|
1151
1151
|
*/
|
|
1152
1152
|
httpUrl?: string;
|
|
1153
1153
|
|
|
@@ -53,7 +53,7 @@ export interface ResolvedRoute extends RouteEntry {
|
|
|
53
53
|
* Server/application wide schemas shared by multiple routes,
|
|
54
54
|
* e.g. model schemas. This is a temporary workaround for
|
|
55
55
|
* missing support for $ref references, see
|
|
56
|
-
* https://github.com/
|
|
56
|
+
* https://github.com/loopbackio/loopback-next/issues/435
|
|
57
57
|
*/
|
|
58
58
|
readonly schemas: SchemasObject;
|
|
59
59
|
}
|
|
@@ -61,7 +61,7 @@ export class RoutingTable {
|
|
|
61
61
|
*/
|
|
62
62
|
registerRoute(route: RouteEntry) {
|
|
63
63
|
// TODO(bajtos) handle the case where opSpec.parameters contains $ref
|
|
64
|
-
// See https://github.com/
|
|
64
|
+
// See https://github.com/loopbackio/loopback-next/issues/435
|
|
65
65
|
/* istanbul ignore if */
|
|
66
66
|
if (debug.enabled) {
|
|
67
67
|
debug(
|
package/src/types.ts
CHANGED
|
@@ -5,7 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
import {HandlerContext, Request, Response} from '@loopback/express';
|
|
7
7
|
import {ReferenceObject, SchemaObject} from '@loopback/openapi-v3';
|
|
8
|
-
import
|
|
8
|
+
import Ajv, {
|
|
9
|
+
ErrorObject,
|
|
10
|
+
FormatDefinition,
|
|
11
|
+
KeywordDefinition,
|
|
12
|
+
Options as AjvOptions,
|
|
13
|
+
ValidateFunction,
|
|
14
|
+
} from 'ajv';
|
|
15
|
+
import {ErrorMessageOptions} from 'ajv-errors';
|
|
9
16
|
import {
|
|
10
17
|
Options,
|
|
11
18
|
OptionsJson,
|
|
@@ -82,31 +89,29 @@ export type LogError = (
|
|
|
82
89
|
*/
|
|
83
90
|
export type SchemaValidatorCache = WeakMap<
|
|
84
91
|
SchemaObject | ReferenceObject, // First keyed by schema object
|
|
85
|
-
Map<string,
|
|
92
|
+
Map<string, ValidateFunction> // Second level keyed by stringified AJV options
|
|
86
93
|
>;
|
|
87
94
|
|
|
88
95
|
/**
|
|
89
96
|
* Options for AJV errors
|
|
90
97
|
*/
|
|
91
|
-
export type AjvErrorOptions =
|
|
92
|
-
keepErrors?: boolean;
|
|
93
|
-
singleError?: boolean;
|
|
94
|
-
};
|
|
98
|
+
export type AjvErrorOptions = ErrorMessageOptions;
|
|
95
99
|
|
|
96
100
|
/**
|
|
97
101
|
* Factory function for Ajv instances
|
|
98
102
|
*/
|
|
99
|
-
export type AjvFactory = (options?:
|
|
103
|
+
export type AjvFactory = (options?: AjvOptions) => Ajv;
|
|
100
104
|
|
|
101
105
|
/**
|
|
102
106
|
* Ajv keyword definition with a name
|
|
103
107
|
*/
|
|
104
|
-
export type AjvKeyword = KeywordDefinition
|
|
108
|
+
export type AjvKeyword = KeywordDefinition;
|
|
105
109
|
|
|
106
110
|
/**
|
|
107
111
|
* Ajv format definition with a name
|
|
108
112
|
*/
|
|
109
|
-
export type AjvFormat
|
|
113
|
+
export type AjvFormat<T extends string | number = string> =
|
|
114
|
+
FormatDefinition<T> & {name: string};
|
|
110
115
|
|
|
111
116
|
/**
|
|
112
117
|
* Options for any value validation using AJV
|
|
@@ -127,7 +132,7 @@ export interface ValueValidationOptions extends ValidationOptions {
|
|
|
127
132
|
/**
|
|
128
133
|
* Options for request body validation using AJV
|
|
129
134
|
*/
|
|
130
|
-
export interface ValidationOptions extends
|
|
135
|
+
export interface ValidationOptions extends AjvOptions {
|
|
131
136
|
/**
|
|
132
137
|
* Custom cache for compiled schemas by AJV. This setting makes it possible
|
|
133
138
|
* to skip the default cache.
|
|
@@ -135,27 +140,26 @@ export interface ValidationOptions extends ajv.Options {
|
|
|
135
140
|
compiledSchemaCache?: SchemaValidatorCache;
|
|
136
141
|
/**
|
|
137
142
|
* Enable additional AJV keywords from https://github.com/epoberezkin/ajv-keywords
|
|
138
|
-
* - `true`: Add all keywords from `ajv-keywords`
|
|
139
143
|
* - `string[]`: Add an array of keywords from `ajv-keywords`
|
|
140
144
|
*/
|
|
141
|
-
ajvKeywords?:
|
|
145
|
+
ajvKeywords?: string[];
|
|
142
146
|
/**
|
|
143
147
|
* Enable custom error messages in JSON-Schema for AJV validator
|
|
144
148
|
* from https://github.com/epoberezkin/ajv-errors
|
|
145
149
|
* - `true`: Enable `ajv-errors`
|
|
146
150
|
* - `AjvErrorOptions`: Enable `ajv-errors` with options
|
|
147
151
|
*/
|
|
148
|
-
ajvErrors?:
|
|
152
|
+
ajvErrors?: AjvErrorOptions;
|
|
149
153
|
/**
|
|
150
154
|
* A function that transform the `ErrorObject`s reported by AJV.
|
|
151
155
|
* This could be used for error messages customization, localization, etc.
|
|
152
156
|
*/
|
|
153
|
-
ajvErrorTransformer?: (errors:
|
|
157
|
+
ajvErrorTransformer?: (errors: ErrorObject[]) => ErrorObject[];
|
|
154
158
|
|
|
155
159
|
/**
|
|
156
160
|
* A factory to create Ajv instance
|
|
157
161
|
*/
|
|
158
|
-
ajvFactory?: (options:
|
|
162
|
+
ajvFactory?: (options: AjvOptions) => Ajv;
|
|
159
163
|
|
|
160
164
|
/**
|
|
161
165
|
* An array of keys to be rejected, such as `__proto__`.
|
|
@@ -11,6 +11,9 @@ import {
|
|
|
11
11
|
Provider,
|
|
12
12
|
} from '@loopback/core';
|
|
13
13
|
import AjvCtor from 'ajv';
|
|
14
|
+
import ajvErrors from 'ajv-errors';
|
|
15
|
+
import ajvFormats from 'ajv-formats';
|
|
16
|
+
import ajvKeywords from 'ajv-keywords';
|
|
14
17
|
import debugModule from 'debug';
|
|
15
18
|
import {RestBindings, RestTags} from '../keys';
|
|
16
19
|
import {AjvFactory, AjvFormat, AjvKeyword, ValidationOptions} from '../types';
|
|
@@ -18,13 +21,8 @@ import {openapiFormats} from './openapi-formats';
|
|
|
18
21
|
|
|
19
22
|
const debug = debugModule('loopback:rest:ajv');
|
|
20
23
|
|
|
21
|
-
const ajvKeywords = require('ajv-keywords');
|
|
22
|
-
const ajvErrors = require('ajv-errors');
|
|
23
|
-
|
|
24
24
|
export const DEFAULT_AJV_VALIDATION_OPTIONS: ValidationOptions = {
|
|
25
25
|
$data: true,
|
|
26
|
-
ajvKeywords: true,
|
|
27
|
-
ajvErrors: true,
|
|
28
26
|
};
|
|
29
27
|
|
|
30
28
|
/**
|
|
@@ -55,34 +53,29 @@ export class AjvFactoryProvider implements Provider<AjvFactory> {
|
|
|
55
53
|
// See https://github.com/epoberezkin/ajv#options
|
|
56
54
|
validationOptions = {
|
|
57
55
|
allErrors: true,
|
|
58
|
-
|
|
59
|
-
// nullable: support keyword "nullable" from Open API 3 specification.
|
|
60
|
-
nullable: true,
|
|
56
|
+
strictTypes: false,
|
|
61
57
|
...validationOptions,
|
|
62
58
|
};
|
|
63
59
|
|
|
64
60
|
debug('AJV options', validationOptions);
|
|
65
|
-
const
|
|
61
|
+
const ajvOptions = {...validationOptions};
|
|
62
|
+
delete ajvOptions.ajvErrors;
|
|
63
|
+
const ajvInst = new AjvCtor(ajvOptions);
|
|
64
|
+
ajvInst.addKeyword('components');
|
|
65
|
+
ajvInst.addKeyword('x-typescript-type');
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
ajvKeywords(ajvInst);
|
|
69
|
-
} else if (Array.isArray(validationOptions.ajvKeywords)) {
|
|
70
|
-
ajvKeywords(ajvInst, validationOptions.ajvKeywords);
|
|
71
|
-
}
|
|
67
|
+
ajvKeywords(ajvInst, validationOptions.ajvKeywords);
|
|
72
68
|
|
|
73
|
-
|
|
74
|
-
ajvErrors(ajvInst);
|
|
75
|
-
} else if (validationOptions.ajvErrors?.constructor === Object) {
|
|
76
|
-
ajvErrors(ajvInst, validationOptions.ajvErrors);
|
|
77
|
-
}
|
|
69
|
+
ajvErrors(ajvInst, validationOptions.ajvErrors);
|
|
78
70
|
|
|
79
71
|
if (this.keywords) {
|
|
80
72
|
this.keywords.forEach(keyword => {
|
|
81
|
-
debug('Adding Ajv keyword %s', keyword.
|
|
82
|
-
ajvInst.addKeyword(keyword
|
|
73
|
+
debug('Adding Ajv keyword %s', keyword.keyword);
|
|
74
|
+
ajvInst.addKeyword(keyword);
|
|
83
75
|
});
|
|
84
76
|
}
|
|
85
77
|
|
|
78
|
+
ajvFormats(ajvInst);
|
|
86
79
|
for (const format of openapiFormats) {
|
|
87
80
|
ajvInst.addFormat(format.name, format);
|
|
88
81
|
}
|
|
@@ -8,7 +8,7 @@ import {AjvFormat} from '../types';
|
|
|
8
8
|
/**
|
|
9
9
|
* int32: [-2147483648, 21474836 47]
|
|
10
10
|
*/
|
|
11
|
-
export const int32Format: AjvFormat = {
|
|
11
|
+
export const int32Format: AjvFormat<number> = {
|
|
12
12
|
name: 'int32',
|
|
13
13
|
type: 'number',
|
|
14
14
|
validate: (value: number) => {
|
|
@@ -22,7 +22,7 @@ export const int32Format: AjvFormat = {
|
|
|
22
22
|
/**
|
|
23
23
|
* int64: [-9223372036854775808, 9223372036854775807]
|
|
24
24
|
*/
|
|
25
|
-
export const int64Format: AjvFormat = {
|
|
25
|
+
export const int64Format: AjvFormat<number> = {
|
|
26
26
|
name: 'int64',
|
|
27
27
|
type: 'number',
|
|
28
28
|
validate: (value: number) => {
|
|
@@ -36,7 +36,7 @@ export const int64Format: AjvFormat = {
|
|
|
36
36
|
/**
|
|
37
37
|
* float: [-2^128, 2^128]
|
|
38
38
|
*/
|
|
39
|
-
export const floatFormat: AjvFormat = {
|
|
39
|
+
export const floatFormat: AjvFormat<number> = {
|
|
40
40
|
name: 'float',
|
|
41
41
|
type: 'number',
|
|
42
42
|
validate: (value: number) => {
|
|
@@ -48,7 +48,7 @@ export const floatFormat: AjvFormat = {
|
|
|
48
48
|
/**
|
|
49
49
|
* double: [-2^1024, 2^1024]
|
|
50
50
|
*/
|
|
51
|
-
export const doubleFormat: AjvFormat = {
|
|
51
|
+
export const doubleFormat: AjvFormat<number> = {
|
|
52
52
|
name: 'double',
|
|
53
53
|
type: 'number',
|
|
54
54
|
validate: (value: number) => {
|
|
@@ -82,7 +82,7 @@ export const binaryFormat: AjvFormat = {
|
|
|
82
82
|
async: false,
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
-
export const openapiFormats: AjvFormat[] = [
|
|
85
|
+
export const openapiFormats: (AjvFormat<string> | AjvFormat<number>)[] = [
|
|
86
86
|
int32Format,
|
|
87
87
|
int64Format,
|
|
88
88
|
floatFormat,
|
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
SchemaObject,
|
|
11
11
|
SchemasObject,
|
|
12
12
|
} from '@loopback/openapi-v3';
|
|
13
|
-
import
|
|
13
|
+
import Ajv, {AsyncValidateFunction, ErrorObject} from 'ajv';
|
|
14
|
+
import {AnyValidateFunction, AsyncSchema} from 'ajv/dist/core';
|
|
14
15
|
import debugModule from 'debug';
|
|
15
16
|
import util from 'util';
|
|
16
17
|
import {HttpErrors, RequestBody, RestHttpErrors} from '..';
|
|
@@ -131,12 +132,12 @@ export async function validateValueAgainstSchema(
|
|
|
131
132
|
globalSchemas: SchemasObject = {},
|
|
132
133
|
options: ValueValidationOptions = {},
|
|
133
134
|
) {
|
|
134
|
-
let validate:
|
|
135
|
+
let validate: AnyValidateFunction | undefined;
|
|
135
136
|
|
|
136
137
|
const cache = options.compiledSchemaCache ?? DEFAULT_COMPILED_SCHEMA_CACHE;
|
|
137
138
|
const key = getKeyForOptions(options);
|
|
138
139
|
|
|
139
|
-
let validatorMap: Map<string,
|
|
140
|
+
let validatorMap: Map<string, AnyValidateFunction> | undefined;
|
|
140
141
|
if (cache.has(schema)) {
|
|
141
142
|
validatorMap = cache.get(schema)!;
|
|
142
143
|
validate = validatorMap.get(key);
|
|
@@ -152,14 +153,14 @@ export async function validateValueAgainstSchema(
|
|
|
152
153
|
cache.set(schema, validatorMap);
|
|
153
154
|
}
|
|
154
155
|
|
|
155
|
-
let validationErrors:
|
|
156
|
+
let validationErrors: ErrorObject[] = [];
|
|
156
157
|
try {
|
|
157
|
-
const validationResult =
|
|
158
|
+
const validationResult = validate(value);
|
|
158
159
|
debug(
|
|
159
160
|
`Value from ${options.source} passed AJV validation.`,
|
|
160
161
|
validationResult,
|
|
161
162
|
);
|
|
162
|
-
return validationResult;
|
|
163
|
+
return await validationResult;
|
|
163
164
|
} catch (error) {
|
|
164
165
|
validationErrors = error.errors;
|
|
165
166
|
}
|
|
@@ -193,12 +194,12 @@ export async function validateValueAgainstSchema(
|
|
|
193
194
|
}
|
|
194
195
|
|
|
195
196
|
function buildErrorDetails(
|
|
196
|
-
validationErrors:
|
|
197
|
+
validationErrors: ErrorObject[],
|
|
197
198
|
): RestHttpErrors.ValidationErrorDetails[] {
|
|
198
199
|
return validationErrors.map(
|
|
199
|
-
(e:
|
|
200
|
+
(e: ErrorObject): RestHttpErrors.ValidationErrorDetails => {
|
|
200
201
|
return {
|
|
201
|
-
path: e.
|
|
202
|
+
path: e.instancePath,
|
|
202
203
|
code: e.keyword,
|
|
203
204
|
message: e.message ?? `must pass validation rule ${e.keyword}`,
|
|
204
205
|
info: e.params,
|
|
@@ -217,18 +218,18 @@ function createValidator(
|
|
|
217
218
|
schema: SchemaObject,
|
|
218
219
|
globalSchemas: SchemasObject = {},
|
|
219
220
|
ajvInst: Ajv,
|
|
220
|
-
):
|
|
221
|
+
): AsyncValidateFunction {
|
|
221
222
|
const jsonSchema = convertToJsonSchema(schema);
|
|
222
223
|
|
|
223
224
|
// Clone global schemas to set `$async: true` flag
|
|
224
225
|
const schemas: SchemasObject = {};
|
|
225
226
|
for (const name in globalSchemas) {
|
|
226
|
-
// See https://github.com/
|
|
227
|
+
// See https://github.com/loopbackio/loopback-next/issues/4939
|
|
227
228
|
schemas[name] = {...globalSchemas[name], $async: true};
|
|
228
229
|
}
|
|
229
|
-
const schemaWithRef = {components: {schemas}, ...jsonSchema};
|
|
230
|
+
const schemaWithRef: AsyncSchema = {components: {schemas}, ...jsonSchema};
|
|
230
231
|
|
|
231
|
-
// See https://
|
|
232
|
+
// See https://js.org/#asynchronous-validation for async validation
|
|
232
233
|
schemaWithRef.$async = true;
|
|
233
234
|
|
|
234
235
|
return ajvInst.compile(schemaWithRef);
|
package/src/writer.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
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 {OperationRetval, Response} from './types';
|
|
7
6
|
import {Readable} from 'stream';
|
|
7
|
+
import {OperationRetval, Response} from './types';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Writes the result from Application controller method
|
|
@@ -48,7 +48,7 @@ export function writeResultToResponse(
|
|
|
48
48
|
response.setHeader('Content-Type', 'application/octet-stream');
|
|
49
49
|
} else {
|
|
50
50
|
// TODO(ritch) remove this, should be configurable
|
|
51
|
-
// See https://github.com/
|
|
51
|
+
// See https://github.com/loopbackio/loopback-next/issues/436
|
|
52
52
|
response.setHeader('Content-Type', 'application/json');
|
|
53
53
|
// TODO(bajtos) handle errors - JSON.stringify can throw
|
|
54
54
|
result = JSON.stringify(result);
|