@opra/core 0.23.0 → 0.23.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.
- package/cjs/adapter/http/http-adapter-base.js +4 -4
- package/cjs/adapter/http/request-handlers/entity-request-handler.js +33 -6
- package/esm/adapter/http/http-adapter-base.js +4 -4
- package/esm/adapter/http/request-handlers/entity-request-handler.js +34 -7
- package/i18n/en/error.json +2 -0
- package/package.json +7 -7
|
@@ -100,7 +100,7 @@ class HttpAdapterBase extends platform_adapter_host_js_1.PlatformAdapterHost {
|
|
|
100
100
|
const wrappedErrors = errors.map(common_1.wrapException);
|
|
101
101
|
// Sort errors from fatal to info
|
|
102
102
|
wrappedErrors.sort((a, b) => {
|
|
103
|
-
const i = common_1.IssueSeverity.Keys.indexOf(a.
|
|
103
|
+
const i = common_1.IssueSeverity.Keys.indexOf(a.severity) - common_1.IssueSeverity.Keys.indexOf(b.severity);
|
|
104
104
|
if (i === 0)
|
|
105
105
|
return b.status - a.status;
|
|
106
106
|
return i;
|
|
@@ -112,9 +112,9 @@ class HttpAdapterBase extends platform_adapter_host_js_1.PlatformAdapterHost {
|
|
|
112
112
|
status = common_1.HttpStatusCodes.INTERNAL_SERVER_ERROR;
|
|
113
113
|
}
|
|
114
114
|
outgoing.statusCode = status;
|
|
115
|
-
const body =
|
|
116
|
-
errors: wrappedErrors.map(x => x.
|
|
117
|
-
}
|
|
115
|
+
const body = {
|
|
116
|
+
errors: wrappedErrors.map(x => this._i18n.deep(x.toJSON()))
|
|
117
|
+
};
|
|
118
118
|
outgoing.setHeader(common_1.HttpHeaderCodes.Content_Type, 'application/json; charset=utf-8');
|
|
119
119
|
outgoing.setHeader(common_1.HttpHeaderCodes.Cache_Control, 'no-cache');
|
|
120
120
|
outgoing.setHeader(common_1.HttpHeaderCodes.Pragma, 'no-cache');
|
|
@@ -4,6 +4,7 @@ exports.EntityRequestHandler = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const body_parser_1 = tslib_1.__importDefault(require("body-parser"));
|
|
6
6
|
const putil_varhelpers_1 = require("putil-varhelpers");
|
|
7
|
+
const valgen = tslib_1.__importStar(require("valgen"));
|
|
7
8
|
const common_1 = require("@opra/common");
|
|
8
9
|
const operation_context_js_1 = require("../../operation-context.js");
|
|
9
10
|
const request_host_js_1 = require("../../request.host.js");
|
|
@@ -33,7 +34,21 @@ class EntityRequestHandler extends request_handler_base_js_1.RequestHandlerBase
|
|
|
33
34
|
context.errors.push(...response.errors);
|
|
34
35
|
return;
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
try {
|
|
38
|
+
await this.sendResponse(context);
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
if (e instanceof common_1.OpraException)
|
|
42
|
+
throw e;
|
|
43
|
+
if (e instanceof valgen.ValidationError) {
|
|
44
|
+
throw new common_1.InternalServerError({
|
|
45
|
+
message: (0, common_1.translate)('error:RESPONSE_VALIDATION,', 'Response validation failed'),
|
|
46
|
+
code: 'RESPONSE_VALIDATION',
|
|
47
|
+
details: e.issues
|
|
48
|
+
}, e);
|
|
49
|
+
}
|
|
50
|
+
throw new common_1.InternalServerError(e);
|
|
51
|
+
}
|
|
37
52
|
}
|
|
38
53
|
async parseRequest(incoming) {
|
|
39
54
|
const p = incoming.parsedUrl.path[0];
|
|
@@ -47,6 +62,13 @@ class EntityRequestHandler extends request_handler_base_js_1.RequestHandlerBase
|
|
|
47
62
|
catch (e) {
|
|
48
63
|
if (e instanceof common_1.OpraException)
|
|
49
64
|
throw e;
|
|
65
|
+
if (e instanceof valgen.ValidationError) {
|
|
66
|
+
throw new common_1.BadRequestError({
|
|
67
|
+
message: (0, common_1.translate)('error:REQUEST_VALIDATION,', 'Request validation failed'),
|
|
68
|
+
code: 'REQUEST_VALIDATION',
|
|
69
|
+
details: e.issues
|
|
70
|
+
}, e);
|
|
71
|
+
}
|
|
50
72
|
throw new common_1.BadRequestError(e);
|
|
51
73
|
}
|
|
52
74
|
}
|
|
@@ -136,7 +158,8 @@ class EntityRequestHandler extends request_handler_base_js_1.RequestHandlerBase
|
|
|
136
158
|
const operationMeta = await this.assertOperation(resource, 'create');
|
|
137
159
|
const jsonReader = this.getBodyLoader(operationMeta);
|
|
138
160
|
const decode = resource.getDecoder('create');
|
|
139
|
-
|
|
161
|
+
let data = await jsonReader(incoming);
|
|
162
|
+
data = decode(data, { coerce: true });
|
|
140
163
|
const pick = (0, query_parsers_js_1.parseArrayParam)(params.get('$pick'));
|
|
141
164
|
const omit = (0, query_parsers_js_1.parseArrayParam)(params.get('$omit'));
|
|
142
165
|
const include = (0, query_parsers_js_1.parseArrayParam)(params.get('$include'));
|
|
@@ -228,7 +251,8 @@ class EntityRequestHandler extends request_handler_base_js_1.RequestHandlerBase
|
|
|
228
251
|
const operationMeta = await this.assertOperation(resource, 'update');
|
|
229
252
|
const jsonReader = this.getBodyLoader(operationMeta);
|
|
230
253
|
const decode = resource.getDecoder('update');
|
|
231
|
-
|
|
254
|
+
let data = await jsonReader(incoming);
|
|
255
|
+
data = decode(data, { coerce: true });
|
|
232
256
|
const pick = (0, query_parsers_js_1.parseArrayParam)(params.get('$pick'));
|
|
233
257
|
const omit = (0, query_parsers_js_1.parseArrayParam)(params.get('$omit'));
|
|
234
258
|
const include = (0, query_parsers_js_1.parseArrayParam)(params.get('$include'));
|
|
@@ -250,7 +274,8 @@ class EntityRequestHandler extends request_handler_base_js_1.RequestHandlerBase
|
|
|
250
274
|
const operationMeta = await this.assertOperation(resource, 'updateMany');
|
|
251
275
|
const jsonReader = this.getBodyLoader(operationMeta);
|
|
252
276
|
const decode = resource.getDecoder('updateMany');
|
|
253
|
-
|
|
277
|
+
let data = await jsonReader(incoming);
|
|
278
|
+
data = decode(data, { coerce: true });
|
|
254
279
|
const filter = resource.normalizeFilter(params.get('$filter'));
|
|
255
280
|
return new request_host_js_1.RequestHost({
|
|
256
281
|
controller: operationMeta.controller,
|
|
@@ -280,7 +305,8 @@ class EntityRequestHandler extends request_handler_base_js_1.RequestHandlerBase
|
|
|
280
305
|
const operationMeta = await this.assertOperation(resource, 'create');
|
|
281
306
|
const jsonReader = this.getBodyLoader(operationMeta);
|
|
282
307
|
const decode = resource.getDecoder('create');
|
|
283
|
-
|
|
308
|
+
let data = await jsonReader(incoming);
|
|
309
|
+
data = decode(data, { coerce: true });
|
|
284
310
|
const pick = (0, query_parsers_js_1.parseArrayParam)(params.get('$pick'));
|
|
285
311
|
const omit = (0, query_parsers_js_1.parseArrayParam)(params.get('$omit'));
|
|
286
312
|
const include = (0, query_parsers_js_1.parseArrayParam)(params.get('$include'));
|
|
@@ -330,7 +356,8 @@ class EntityRequestHandler extends request_handler_base_js_1.RequestHandlerBase
|
|
|
330
356
|
const operationMeta = await this.assertOperation(resource, 'update');
|
|
331
357
|
const jsonReader = this.getBodyLoader(operationMeta);
|
|
332
358
|
const decode = resource.getDecoder('update');
|
|
333
|
-
|
|
359
|
+
let data = await jsonReader(incoming);
|
|
360
|
+
data = decode(data, { coerce: true });
|
|
334
361
|
const pick = (0, query_parsers_js_1.parseArrayParam)(params.get('$pick'));
|
|
335
362
|
const omit = (0, query_parsers_js_1.parseArrayParam)(params.get('$omit'));
|
|
336
363
|
const include = (0, query_parsers_js_1.parseArrayParam)(params.get('$include'));
|
|
@@ -97,7 +97,7 @@ export class HttpAdapterBase extends PlatformAdapterHost {
|
|
|
97
97
|
const wrappedErrors = errors.map(wrapException);
|
|
98
98
|
// Sort errors from fatal to info
|
|
99
99
|
wrappedErrors.sort((a, b) => {
|
|
100
|
-
const i = IssueSeverity.Keys.indexOf(a.
|
|
100
|
+
const i = IssueSeverity.Keys.indexOf(a.severity) - IssueSeverity.Keys.indexOf(b.severity);
|
|
101
101
|
if (i === 0)
|
|
102
102
|
return b.status - a.status;
|
|
103
103
|
return i;
|
|
@@ -109,9 +109,9 @@ export class HttpAdapterBase extends PlatformAdapterHost {
|
|
|
109
109
|
status = HttpStatusCodes.INTERNAL_SERVER_ERROR;
|
|
110
110
|
}
|
|
111
111
|
outgoing.statusCode = status;
|
|
112
|
-
const body =
|
|
113
|
-
errors: wrappedErrors.map(x => x.
|
|
114
|
-
}
|
|
112
|
+
const body = {
|
|
113
|
+
errors: wrappedErrors.map(x => this._i18n.deep(x.toJSON()))
|
|
114
|
+
};
|
|
115
115
|
outgoing.setHeader(HttpHeaderCodes.Content_Type, 'application/json; charset=utf-8');
|
|
116
116
|
outgoing.setHeader(HttpHeaderCodes.Cache_Control, 'no-cache');
|
|
117
117
|
outgoing.setHeader(HttpHeaderCodes.Pragma, 'no-cache');
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import bodyParser from 'body-parser';
|
|
2
2
|
import { toBoolean, toInt } from 'putil-varhelpers';
|
|
3
|
-
import
|
|
3
|
+
import * as valgen from 'valgen';
|
|
4
|
+
import { BadRequestError, Collection, HttpHeaderCodes, HttpStatusCodes, InternalServerError, MethodNotAllowedError, OpraException, ResourceNotFoundError, Singleton, translate, } from '@opra/common';
|
|
4
5
|
import { OperationContext } from '../../operation-context.js';
|
|
5
6
|
import { RequestHost } from '../../request.host.js';
|
|
6
7
|
import { ResponseHost } from '../../response.host.js';
|
|
@@ -29,7 +30,21 @@ export class EntityRequestHandler extends RequestHandlerBase {
|
|
|
29
30
|
context.errors.push(...response.errors);
|
|
30
31
|
return;
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
try {
|
|
34
|
+
await this.sendResponse(context);
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
if (e instanceof OpraException)
|
|
38
|
+
throw e;
|
|
39
|
+
if (e instanceof valgen.ValidationError) {
|
|
40
|
+
throw new InternalServerError({
|
|
41
|
+
message: translate('error:RESPONSE_VALIDATION,', 'Response validation failed'),
|
|
42
|
+
code: 'RESPONSE_VALIDATION',
|
|
43
|
+
details: e.issues
|
|
44
|
+
}, e);
|
|
45
|
+
}
|
|
46
|
+
throw new InternalServerError(e);
|
|
47
|
+
}
|
|
33
48
|
}
|
|
34
49
|
async parseRequest(incoming) {
|
|
35
50
|
const p = incoming.parsedUrl.path[0];
|
|
@@ -43,6 +58,13 @@ export class EntityRequestHandler extends RequestHandlerBase {
|
|
|
43
58
|
catch (e) {
|
|
44
59
|
if (e instanceof OpraException)
|
|
45
60
|
throw e;
|
|
61
|
+
if (e instanceof valgen.ValidationError) {
|
|
62
|
+
throw new BadRequestError({
|
|
63
|
+
message: translate('error:REQUEST_VALIDATION,', 'Request validation failed'),
|
|
64
|
+
code: 'REQUEST_VALIDATION',
|
|
65
|
+
details: e.issues
|
|
66
|
+
}, e);
|
|
67
|
+
}
|
|
46
68
|
throw new BadRequestError(e);
|
|
47
69
|
}
|
|
48
70
|
}
|
|
@@ -132,7 +154,8 @@ export class EntityRequestHandler extends RequestHandlerBase {
|
|
|
132
154
|
const operationMeta = await this.assertOperation(resource, 'create');
|
|
133
155
|
const jsonReader = this.getBodyLoader(operationMeta);
|
|
134
156
|
const decode = resource.getDecoder('create');
|
|
135
|
-
|
|
157
|
+
let data = await jsonReader(incoming);
|
|
158
|
+
data = decode(data, { coerce: true });
|
|
136
159
|
const pick = parseArrayParam(params.get('$pick'));
|
|
137
160
|
const omit = parseArrayParam(params.get('$omit'));
|
|
138
161
|
const include = parseArrayParam(params.get('$include'));
|
|
@@ -224,7 +247,8 @@ export class EntityRequestHandler extends RequestHandlerBase {
|
|
|
224
247
|
const operationMeta = await this.assertOperation(resource, 'update');
|
|
225
248
|
const jsonReader = this.getBodyLoader(operationMeta);
|
|
226
249
|
const decode = resource.getDecoder('update');
|
|
227
|
-
|
|
250
|
+
let data = await jsonReader(incoming);
|
|
251
|
+
data = decode(data, { coerce: true });
|
|
228
252
|
const pick = parseArrayParam(params.get('$pick'));
|
|
229
253
|
const omit = parseArrayParam(params.get('$omit'));
|
|
230
254
|
const include = parseArrayParam(params.get('$include'));
|
|
@@ -246,7 +270,8 @@ export class EntityRequestHandler extends RequestHandlerBase {
|
|
|
246
270
|
const operationMeta = await this.assertOperation(resource, 'updateMany');
|
|
247
271
|
const jsonReader = this.getBodyLoader(operationMeta);
|
|
248
272
|
const decode = resource.getDecoder('updateMany');
|
|
249
|
-
|
|
273
|
+
let data = await jsonReader(incoming);
|
|
274
|
+
data = decode(data, { coerce: true });
|
|
250
275
|
const filter = resource.normalizeFilter(params.get('$filter'));
|
|
251
276
|
return new RequestHost({
|
|
252
277
|
controller: operationMeta.controller,
|
|
@@ -276,7 +301,8 @@ export class EntityRequestHandler extends RequestHandlerBase {
|
|
|
276
301
|
const operationMeta = await this.assertOperation(resource, 'create');
|
|
277
302
|
const jsonReader = this.getBodyLoader(operationMeta);
|
|
278
303
|
const decode = resource.getDecoder('create');
|
|
279
|
-
|
|
304
|
+
let data = await jsonReader(incoming);
|
|
305
|
+
data = decode(data, { coerce: true });
|
|
280
306
|
const pick = parseArrayParam(params.get('$pick'));
|
|
281
307
|
const omit = parseArrayParam(params.get('$omit'));
|
|
282
308
|
const include = parseArrayParam(params.get('$include'));
|
|
@@ -326,7 +352,8 @@ export class EntityRequestHandler extends RequestHandlerBase {
|
|
|
326
352
|
const operationMeta = await this.assertOperation(resource, 'update');
|
|
327
353
|
const jsonReader = this.getBodyLoader(operationMeta);
|
|
328
354
|
const decode = resource.getDecoder('update');
|
|
329
|
-
|
|
355
|
+
let data = await jsonReader(incoming);
|
|
356
|
+
data = decode(data, { coerce: true });
|
|
330
357
|
const pick = parseArrayParam(params.get('$pick'));
|
|
331
358
|
const omit = parseArrayParam(params.get('$omit'));
|
|
332
359
|
const include = parseArrayParam(params.get('$include'));
|
package/i18n/en/error.json
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
"NOT_FOUND": "Not found",
|
|
9
9
|
"UNAUTHORIZED": "You have not been authenticated to perform this action",
|
|
10
10
|
"UNPROCESSABLE_ENTITY": "Unprocessable entity",
|
|
11
|
+
"REQUEST_VALIDATION": "Request validation failed",
|
|
12
|
+
"RESPONSE_VALIDATION": "Response validation failed",
|
|
11
13
|
"RESOURCE_NOT_FOUND": "Resource not found: '{{resource}}'",
|
|
12
14
|
"RESOURCE_CONFLICT": "There is already an other {{resource}} resource with same field values ({{fields}})",
|
|
13
15
|
"RESOLVER_FORBIDDEN": "The {{resource}} endpoint does not accept '{{operation}}' operations",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/core",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.1",
|
|
4
4
|
"description": "Opra schema package",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"clean:cover": "rimraf ../../coverage/core"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@opra/common": "^0.23.
|
|
30
|
+
"@opra/common": "^0.23.1",
|
|
31
31
|
"accepts": "^1.3.8",
|
|
32
32
|
"content-disposition": "^0.5.4",
|
|
33
33
|
"content-type": "^1.0.5",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"formidable": "^3.5.0",
|
|
38
38
|
"fresh": "^0.5.2",
|
|
39
39
|
"mime-types": "^2.1.35",
|
|
40
|
-
"power-tasks": "^1.7.
|
|
41
|
-
"putil-varhelpers": "^1.6.5",
|
|
40
|
+
"power-tasks": "^1.7.1",
|
|
42
41
|
"putil-isplainobject": "^1.1.5",
|
|
42
|
+
"putil-varhelpers": "^1.6.5",
|
|
43
43
|
"range-parser": "^1.2.1",
|
|
44
|
-
"strict-typed-events": "^2.3.
|
|
44
|
+
"strict-typed-events": "^2.3.2",
|
|
45
45
|
"type-is": "^1.6.18",
|
|
46
46
|
"vary": "^1.1.2"
|
|
47
47
|
},
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@types/cookie-signature": "^1.1.0",
|
|
58
58
|
"@types/encodeurl": "^1.0.0",
|
|
59
59
|
"@types/express": "^4.17.17",
|
|
60
|
-
"@types/formidable": "^3.4.
|
|
60
|
+
"@types/formidable": "^3.4.1",
|
|
61
61
|
"@types/fresh": "^0.5.0",
|
|
62
62
|
"@types/mime-types": "^2.1.1",
|
|
63
63
|
"@types/range-parser": "^1.2.4",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@types/vary": "^1.1.0",
|
|
66
66
|
"crypto-browserify": "^3.12.0",
|
|
67
67
|
"path-browserify": "^1.0.1",
|
|
68
|
-
"ts-gems": "^2.4.
|
|
68
|
+
"ts-gems": "^2.4.1"
|
|
69
69
|
},
|
|
70
70
|
"type": "module",
|
|
71
71
|
"types": "types/index.d.ts",
|