@opra/core 0.0.9 → 0.0.11
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/exception/api-exception.js +5 -5
- package/cjs/exception/{errors → http-errors}/bad-request.error.js +1 -1
- package/cjs/exception/{errors → http-errors}/failed-dependency.error.js +1 -1
- package/cjs/exception/{errors → http-errors}/forbidden.error.js +1 -1
- package/cjs/exception/{errors → http-errors}/internal-server.error.js +1 -1
- package/cjs/exception/{errors → http-errors}/method-not-allowed.error.js +1 -1
- package/cjs/exception/{errors → http-errors}/not-found.error.js +0 -0
- package/cjs/exception/{errors → http-errors}/unauthorized.error.js +0 -0
- package/cjs/exception/{errors → http-errors}/unprocessable-entity.error.js +1 -1
- package/cjs/exception/index.js +9 -7
- package/cjs/exception/resource-errors/resource-conflict.error.js +19 -0
- package/cjs/exception/wrap-error.js +1 -1
- package/cjs/implementation/adapter/adapter.js +3 -4
- package/cjs/implementation/adapter/http-adapter.js +2 -2
- package/cjs/interfaces/query.interface.js +8 -8
- package/cjs/utils/create-i18n.js +21 -0
- package/cjs/utils/get-caller-file.util.js +19 -0
- package/esm/exception/api-exception.js +5 -5
- package/esm/exception/{errors → http-errors}/bad-request.error.d.ts +0 -0
- package/esm/exception/{errors → http-errors}/bad-request.error.js +1 -1
- package/esm/exception/{errors → http-errors}/failed-dependency.error.d.ts +0 -0
- package/esm/exception/{errors → http-errors}/failed-dependency.error.js +1 -1
- package/esm/exception/{errors → http-errors}/forbidden.error.d.ts +0 -0
- package/esm/exception/{errors → http-errors}/forbidden.error.js +1 -1
- package/esm/exception/{errors → http-errors}/internal-server.error.d.ts +0 -0
- package/esm/exception/{errors → http-errors}/internal-server.error.js +1 -1
- package/esm/exception/{errors → http-errors}/method-not-allowed.error.d.ts +0 -0
- package/esm/exception/{errors → http-errors}/method-not-allowed.error.js +1 -1
- package/esm/exception/{errors → http-errors}/not-found.error.d.ts +0 -0
- package/esm/exception/{errors → http-errors}/not-found.error.js +0 -0
- package/esm/exception/{errors → http-errors}/unauthorized.error.d.ts +0 -0
- package/esm/exception/{errors → http-errors}/unauthorized.error.js +0 -0
- package/esm/exception/{errors → http-errors}/unprocessable-entity.error.d.ts +0 -0
- package/esm/exception/{errors → http-errors}/unprocessable-entity.error.js +1 -1
- package/esm/exception/index.d.ts +9 -7
- package/esm/exception/index.js +9 -7
- package/esm/exception/resource-errors/resource-conflict.error.d.ts +4 -0
- package/esm/exception/resource-errors/resource-conflict.error.js +15 -0
- package/esm/exception/wrap-error.js +1 -1
- package/esm/implementation/adapter/adapter.js +3 -4
- package/esm/implementation/adapter/http-adapter.js +2 -2
- package/esm/interfaces/query.interface.d.ts +16 -16
- package/esm/interfaces/query.interface.js +8 -8
- package/esm/types.d.ts +1 -3
- package/esm/utils/create-i18n.d.ts +3 -0
- package/esm/utils/create-i18n.js +16 -0
- package/esm/utils/get-caller-file.util.d.ts +1 -0
- package/esm/utils/get-caller-file.util.js +15 -0
- package/i18n/en/error.json +12 -0
- package/package.json +9 -6
|
@@ -17,11 +17,6 @@ class ApiException extends Error {
|
|
|
17
17
|
cause = cause || (response instanceof Error ? response : undefined);
|
|
18
18
|
if (cause)
|
|
19
19
|
Object.defineProperty(this, 'cause', { enumerable: false, configurable: true, writable: true, value: cause });
|
|
20
|
-
if (this.cause instanceof Error && this.cause.stack) {
|
|
21
|
-
if (ApiException.stackAsDiagnostics)
|
|
22
|
-
this.response.diagnostics = this.cause.stack.split('\n');
|
|
23
|
-
this.stack = this.cause.stack;
|
|
24
|
-
}
|
|
25
20
|
if (response instanceof Error)
|
|
26
21
|
this._initErrorInstance(response);
|
|
27
22
|
else if (typeof response === 'string')
|
|
@@ -33,6 +28,11 @@ class ApiException extends Error {
|
|
|
33
28
|
this.response.severity = 'fatal';
|
|
34
29
|
else
|
|
35
30
|
this.response.severity = 'error';
|
|
31
|
+
if (this.cause instanceof Error && this.cause.stack) {
|
|
32
|
+
if (ApiException.stackAsDiagnostics)
|
|
33
|
+
this.response.diagnostics = this.cause.stack.split('\n');
|
|
34
|
+
this.stack = this.cause.stack;
|
|
35
|
+
}
|
|
36
36
|
}
|
|
37
37
|
setStatus(status) {
|
|
38
38
|
this.status = status;
|
|
@@ -16,7 +16,7 @@ class BadRequestError extends api_exception_js_1.ApiException {
|
|
|
16
16
|
}
|
|
17
17
|
_initResponse(response) {
|
|
18
18
|
super._initResponse({
|
|
19
|
-
message: (0, i18n_1.translate)('error:BAD_REQUEST'
|
|
19
|
+
message: (0, i18n_1.translate)('error:BAD_REQUEST'),
|
|
20
20
|
severity: 'error',
|
|
21
21
|
code: 'BAD_REQUEST',
|
|
22
22
|
...response
|
|
@@ -15,7 +15,7 @@ class FailedDependencyError extends api_exception_js_1.ApiException {
|
|
|
15
15
|
}
|
|
16
16
|
_initResponse(response) {
|
|
17
17
|
super._initResponse({
|
|
18
|
-
message: (0, i18n_1.translate)('error:FAILED_DEPENDENCY'
|
|
18
|
+
message: (0, i18n_1.translate)('error:FAILED_DEPENDENCY'),
|
|
19
19
|
severity: 'error',
|
|
20
20
|
code: 'FAILED_DEPENDENCY',
|
|
21
21
|
...response
|
|
@@ -17,7 +17,7 @@ class ForbiddenError extends api_exception_js_1.ApiException {
|
|
|
17
17
|
}
|
|
18
18
|
_initResponse(response) {
|
|
19
19
|
super._initResponse({
|
|
20
|
-
message: (0, i18n_1.translate)('error:FORBIDDEN'
|
|
20
|
+
message: (0, i18n_1.translate)('error:FORBIDDEN'),
|
|
21
21
|
severity: 'error',
|
|
22
22
|
code: 'FORBIDDEN',
|
|
23
23
|
...response
|
|
@@ -17,7 +17,7 @@ class InternalServerError extends api_exception_js_1.ApiException {
|
|
|
17
17
|
}
|
|
18
18
|
_initResponse(response) {
|
|
19
19
|
super._initResponse({
|
|
20
|
-
message: (0, i18n_1.translate)('error:INTERNAL_SERVER_ERROR'
|
|
20
|
+
message: (0, i18n_1.translate)('error:INTERNAL_SERVER_ERROR'),
|
|
21
21
|
severity: 'error',
|
|
22
22
|
code: 'INTERNAL_SERVER_ERROR',
|
|
23
23
|
...lodash_1.default.omitBy(response, lodash_1.default.isNil)
|
|
@@ -16,7 +16,7 @@ class MethodNotAllowedError extends api_exception_js_1.ApiException {
|
|
|
16
16
|
}
|
|
17
17
|
_initResponse(response) {
|
|
18
18
|
super._initResponse({
|
|
19
|
-
message: (0, i18n_1.translate)('error:METHOD_NOT_ALLOWED'
|
|
19
|
+
message: (0, i18n_1.translate)('error:METHOD_NOT_ALLOWED'),
|
|
20
20
|
severity: 'error',
|
|
21
21
|
code: 'METHOD_NOT_ALLOWED',
|
|
22
22
|
...response
|
|
File without changes
|
|
File without changes
|
|
@@ -15,7 +15,7 @@ class UnprocessableEntityError extends api_exception_js_1.ApiException {
|
|
|
15
15
|
}
|
|
16
16
|
_initResponse(response) {
|
|
17
17
|
super._initResponse({
|
|
18
|
-
message: (0, i18n_1.translate)('error:UNPROCESSABLE_ENTITY'
|
|
18
|
+
message: (0, i18n_1.translate)('error:UNPROCESSABLE_ENTITY'),
|
|
19
19
|
severity: 'error',
|
|
20
20
|
code: 'UNPROCESSABLE_ENTITY',
|
|
21
21
|
...response
|
package/cjs/exception/index.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./api-exception.js"), exports);
|
|
5
|
-
tslib_1.__exportStar(require("./errors/bad-request.error.js"), exports);
|
|
6
|
-
tslib_1.__exportStar(require("./errors/failed-dependency.error.js"), exports);
|
|
7
|
-
tslib_1.__exportStar(require("./errors/
|
|
8
|
-
tslib_1.__exportStar(require("./errors/
|
|
9
|
-
tslib_1.__exportStar(require("./errors/not-
|
|
10
|
-
tslib_1.__exportStar(require("./errors/
|
|
11
|
-
tslib_1.__exportStar(require("./errors/
|
|
5
|
+
tslib_1.__exportStar(require("./http-errors/bad-request.error.js"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./http-errors/failed-dependency.error.js"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./http-errors/forbidden.error.js"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./http-errors/internal-server.error.js"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./http-errors/method-not-allowed.error.js"), exports);
|
|
10
|
+
tslib_1.__exportStar(require("./http-errors/not-found.error.js"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./http-errors/unauthorized.error.js"), exports);
|
|
12
|
+
tslib_1.__exportStar(require("./http-errors/unprocessable-entity.error.js"), exports);
|
|
13
|
+
tslib_1.__exportStar(require("./resource-errors/resource-conflict.error.js"), exports);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ResourceConflictError = void 0;
|
|
4
|
+
const i18n_1 = require("@opra/i18n");
|
|
5
|
+
const index_js_1 = require("../../enums/index.js");
|
|
6
|
+
const api_exception_js_1 = require("../api-exception.js");
|
|
7
|
+
class ResourceConflictError extends api_exception_js_1.ApiException {
|
|
8
|
+
constructor(resource, fields, cause) {
|
|
9
|
+
super({
|
|
10
|
+
message: (0, i18n_1.translate)(`error:RESOURCE_CONFLICT`, { resource, fields }),
|
|
11
|
+
severity: 'error',
|
|
12
|
+
code: 'RESOURCE_CONFLICT',
|
|
13
|
+
subject: resource,
|
|
14
|
+
location: fields
|
|
15
|
+
}, cause);
|
|
16
|
+
this.status = index_js_1.HttpStatus.CONFLICT;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.ResourceConflictError = ResourceConflictError;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.wrapError = void 0;
|
|
4
4
|
const api_exception_js_1 = require("./api-exception.js");
|
|
5
|
-
const internal_server_error_js_1 = require("./errors/internal-server.error.js");
|
|
5
|
+
const internal_server_error_js_1 = require("./http-errors/internal-server.error.js");
|
|
6
6
|
function wrapError(response) {
|
|
7
7
|
if (response instanceof api_exception_js_1.ApiException)
|
|
8
8
|
return response;
|
|
@@ -5,6 +5,7 @@ const strict_typed_events_1 = require("strict-typed-events");
|
|
|
5
5
|
const i18n_1 = require("@opra/i18n");
|
|
6
6
|
const index_js_1 = require("../../exception/index.js");
|
|
7
7
|
const wrap_error_js_1 = require("../../exception/wrap-error.js");
|
|
8
|
+
const create_i18n_js_1 = require("../../utils/create-i18n.js");
|
|
8
9
|
class OpraAdapter {
|
|
9
10
|
service;
|
|
10
11
|
i18n;
|
|
@@ -27,7 +28,7 @@ class OpraAdapter {
|
|
|
27
28
|
let promises;
|
|
28
29
|
let exclusive = false;
|
|
29
30
|
for (const context of queryContexts) {
|
|
30
|
-
exclusive = exclusive || context.query.
|
|
31
|
+
exclusive = exclusive || context.query.operation !== 'read';
|
|
31
32
|
// Wait previous read requests before executing update request
|
|
32
33
|
if (exclusive && promises) {
|
|
33
34
|
await Promise.allSettled(promises);
|
|
@@ -95,9 +96,7 @@ class OpraAdapter {
|
|
|
95
96
|
return options.i18n;
|
|
96
97
|
if (typeof options?.i18n === 'function')
|
|
97
98
|
return options.i18n();
|
|
98
|
-
|
|
99
|
-
await instance.init();
|
|
100
|
-
return instance;
|
|
99
|
+
return (0, create_i18n_js_1.createI18n)(options?.i18n);
|
|
101
100
|
}
|
|
102
101
|
}
|
|
103
102
|
exports.OpraAdapter = OpraAdapter;
|
|
@@ -41,7 +41,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
41
41
|
query,
|
|
42
42
|
headers,
|
|
43
43
|
params: url.searchParams,
|
|
44
|
-
continueOnError: query.
|
|
44
|
+
continueOnError: query.operation === 'read'
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
buildQuery(url, method, body) {
|
|
@@ -215,7 +215,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
215
215
|
}
|
|
216
216
|
else {
|
|
217
217
|
delete body.errors;
|
|
218
|
-
status = status || (query.
|
|
218
|
+
status = status || (query.operation === 'create' ? index_js_1.HttpStatus.CREATED : index_js_1.HttpStatus.OK);
|
|
219
219
|
}
|
|
220
220
|
body = this.i18n.deep(body);
|
|
221
221
|
return {
|
|
@@ -17,7 +17,7 @@ var OpraQuery;
|
|
|
17
17
|
const out = {
|
|
18
18
|
queryType: 'create',
|
|
19
19
|
scope: 'collection',
|
|
20
|
-
|
|
20
|
+
operation: 'create',
|
|
21
21
|
resource,
|
|
22
22
|
data: values
|
|
23
23
|
};
|
|
@@ -36,7 +36,7 @@ var OpraQuery;
|
|
|
36
36
|
const out = {
|
|
37
37
|
queryType: 'get',
|
|
38
38
|
scope: 'instance',
|
|
39
|
-
|
|
39
|
+
operation: 'read',
|
|
40
40
|
resource,
|
|
41
41
|
keyValue: key
|
|
42
42
|
};
|
|
@@ -56,7 +56,7 @@ var OpraQuery;
|
|
|
56
56
|
const out = {
|
|
57
57
|
queryType: 'search',
|
|
58
58
|
scope: 'collection',
|
|
59
|
-
|
|
59
|
+
operation: 'read',
|
|
60
60
|
resource
|
|
61
61
|
};
|
|
62
62
|
Object.assign(out, lodash_1.default.omit(options, Object.keys(out)));
|
|
@@ -67,7 +67,7 @@ var OpraQuery;
|
|
|
67
67
|
const out = {
|
|
68
68
|
queryType: 'get',
|
|
69
69
|
scope: 'property',
|
|
70
|
-
|
|
70
|
+
operation: 'read',
|
|
71
71
|
property
|
|
72
72
|
};
|
|
73
73
|
Object.assign(out, lodash_1.default.omit(options, Object.keys(out)));
|
|
@@ -85,7 +85,7 @@ var OpraQuery;
|
|
|
85
85
|
const out = {
|
|
86
86
|
queryType: 'update',
|
|
87
87
|
scope: 'instance',
|
|
88
|
-
|
|
88
|
+
operation: 'update',
|
|
89
89
|
resource,
|
|
90
90
|
keyValue,
|
|
91
91
|
data: values
|
|
@@ -98,7 +98,7 @@ var OpraQuery;
|
|
|
98
98
|
const out = {
|
|
99
99
|
queryType: 'updateMany',
|
|
100
100
|
scope: 'collection',
|
|
101
|
-
|
|
101
|
+
operation: 'update',
|
|
102
102
|
resource,
|
|
103
103
|
data: values
|
|
104
104
|
};
|
|
@@ -111,7 +111,7 @@ var OpraQuery;
|
|
|
111
111
|
return {
|
|
112
112
|
queryType: 'delete',
|
|
113
113
|
scope: 'instance',
|
|
114
|
-
|
|
114
|
+
operation: 'delete',
|
|
115
115
|
resource,
|
|
116
116
|
keyValue: key
|
|
117
117
|
};
|
|
@@ -121,7 +121,7 @@ var OpraQuery;
|
|
|
121
121
|
const out = {
|
|
122
122
|
queryType: 'deleteMany',
|
|
123
123
|
scope: 'collection',
|
|
124
|
-
|
|
124
|
+
operation: 'delete',
|
|
125
125
|
resource,
|
|
126
126
|
};
|
|
127
127
|
Object.assign(out, lodash_1.default.omit(options, Object.keys(out)));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createI18n = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
6
|
+
const i18n_1 = require("@opra/i18n");
|
|
7
|
+
const get_caller_file_util_js_1 = require("./get-caller-file.util.js");
|
|
8
|
+
async function createI18n(options) {
|
|
9
|
+
const opts = {
|
|
10
|
+
...options,
|
|
11
|
+
resourceDirs: undefined
|
|
12
|
+
};
|
|
13
|
+
const instance = i18n_1.I18n.createInstance(opts);
|
|
14
|
+
await instance.init();
|
|
15
|
+
await instance.loadResourceDir(path_1.default.resolve((0, get_caller_file_util_js_1.getCallerFile)(), '../../../i18n'));
|
|
16
|
+
if (options?.resourceDirs)
|
|
17
|
+
for (const dir of options.resourceDirs)
|
|
18
|
+
await instance.loadResourceDir(dir);
|
|
19
|
+
return instance;
|
|
20
|
+
}
|
|
21
|
+
exports.createI18n = createI18n;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCallerFile = void 0;
|
|
4
|
+
function getCallerFile(position = 1) {
|
|
5
|
+
if (position >= Error.stackTraceLimit) {
|
|
6
|
+
throw new TypeError('getCallerFile(position) requires position be less then Error.stackTraceLimit but position was: `' +
|
|
7
|
+
position + '` and Error.stackTraceLimit was: `' + Error.stackTraceLimit + '`');
|
|
8
|
+
}
|
|
9
|
+
const oldPrepareStackTrace = Error.prepareStackTrace;
|
|
10
|
+
Error.prepareStackTrace = (_, stack) => stack;
|
|
11
|
+
const stack = new Error().stack;
|
|
12
|
+
Error.prepareStackTrace = oldPrepareStackTrace;
|
|
13
|
+
if (stack !== null && typeof stack === 'object') {
|
|
14
|
+
// stack[0] holds this file
|
|
15
|
+
// stack[1] holds where this function was called
|
|
16
|
+
return stack[position] ? stack[position].getFileName() : undefined;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.getCallerFile = getCallerFile;
|
|
@@ -14,11 +14,6 @@ export class ApiException extends Error {
|
|
|
14
14
|
cause = cause || (response instanceof Error ? response : undefined);
|
|
15
15
|
if (cause)
|
|
16
16
|
Object.defineProperty(this, 'cause', { enumerable: false, configurable: true, writable: true, value: cause });
|
|
17
|
-
if (this.cause instanceof Error && this.cause.stack) {
|
|
18
|
-
if (ApiException.stackAsDiagnostics)
|
|
19
|
-
this.response.diagnostics = this.cause.stack.split('\n');
|
|
20
|
-
this.stack = this.cause.stack;
|
|
21
|
-
}
|
|
22
17
|
if (response instanceof Error)
|
|
23
18
|
this._initErrorInstance(response);
|
|
24
19
|
else if (typeof response === 'string')
|
|
@@ -30,6 +25,11 @@ export class ApiException extends Error {
|
|
|
30
25
|
this.response.severity = 'fatal';
|
|
31
26
|
else
|
|
32
27
|
this.response.severity = 'error';
|
|
28
|
+
if (this.cause instanceof Error && this.cause.stack) {
|
|
29
|
+
if (ApiException.stackAsDiagnostics)
|
|
30
|
+
this.response.diagnostics = this.cause.stack.split('\n');
|
|
31
|
+
this.stack = this.cause.stack;
|
|
32
|
+
}
|
|
33
33
|
}
|
|
34
34
|
setStatus(status) {
|
|
35
35
|
this.status = status;
|
|
File without changes
|
|
@@ -13,7 +13,7 @@ export class BadRequestError extends ApiException {
|
|
|
13
13
|
}
|
|
14
14
|
_initResponse(response) {
|
|
15
15
|
super._initResponse({
|
|
16
|
-
message: translate('error:BAD_REQUEST'
|
|
16
|
+
message: translate('error:BAD_REQUEST'),
|
|
17
17
|
severity: 'error',
|
|
18
18
|
code: 'BAD_REQUEST',
|
|
19
19
|
...response
|
|
File without changes
|
|
@@ -12,7 +12,7 @@ export class FailedDependencyError extends ApiException {
|
|
|
12
12
|
}
|
|
13
13
|
_initResponse(response) {
|
|
14
14
|
super._initResponse({
|
|
15
|
-
message: translate('error:FAILED_DEPENDENCY'
|
|
15
|
+
message: translate('error:FAILED_DEPENDENCY'),
|
|
16
16
|
severity: 'error',
|
|
17
17
|
code: 'FAILED_DEPENDENCY',
|
|
18
18
|
...response
|
|
File without changes
|
|
@@ -14,7 +14,7 @@ export class ForbiddenError extends ApiException {
|
|
|
14
14
|
}
|
|
15
15
|
_initResponse(response) {
|
|
16
16
|
super._initResponse({
|
|
17
|
-
message: translate('error:FORBIDDEN'
|
|
17
|
+
message: translate('error:FORBIDDEN'),
|
|
18
18
|
severity: 'error',
|
|
19
19
|
code: 'FORBIDDEN',
|
|
20
20
|
...response
|
|
File without changes
|
|
@@ -13,7 +13,7 @@ export class InternalServerError extends ApiException {
|
|
|
13
13
|
}
|
|
14
14
|
_initResponse(response) {
|
|
15
15
|
super._initResponse({
|
|
16
|
-
message: translate('error:INTERNAL_SERVER_ERROR'
|
|
16
|
+
message: translate('error:INTERNAL_SERVER_ERROR'),
|
|
17
17
|
severity: 'error',
|
|
18
18
|
code: 'INTERNAL_SERVER_ERROR',
|
|
19
19
|
..._.omitBy(response, _.isNil)
|
|
File without changes
|
|
@@ -13,7 +13,7 @@ export class MethodNotAllowedError extends ApiException {
|
|
|
13
13
|
}
|
|
14
14
|
_initResponse(response) {
|
|
15
15
|
super._initResponse({
|
|
16
|
-
message: translate('error:METHOD_NOT_ALLOWED'
|
|
16
|
+
message: translate('error:METHOD_NOT_ALLOWED'),
|
|
17
17
|
severity: 'error',
|
|
18
18
|
code: 'METHOD_NOT_ALLOWED',
|
|
19
19
|
...response
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -12,7 +12,7 @@ export class UnprocessableEntityError extends ApiException {
|
|
|
12
12
|
}
|
|
13
13
|
_initResponse(response) {
|
|
14
14
|
super._initResponse({
|
|
15
|
-
message: translate('error:UNPROCESSABLE_ENTITY'
|
|
15
|
+
message: translate('error:UNPROCESSABLE_ENTITY'),
|
|
16
16
|
severity: 'error',
|
|
17
17
|
code: 'UNPROCESSABLE_ENTITY',
|
|
18
18
|
...response
|
package/esm/exception/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from './api-exception.js';
|
|
2
|
-
export * from './errors/bad-request.error.js';
|
|
3
|
-
export * from './errors/failed-dependency.error.js';
|
|
4
|
-
export * from './errors/
|
|
5
|
-
export * from './errors/
|
|
6
|
-
export * from './errors/not-
|
|
7
|
-
export * from './errors/
|
|
8
|
-
export * from './errors/
|
|
2
|
+
export * from './http-errors/bad-request.error.js';
|
|
3
|
+
export * from './http-errors/failed-dependency.error.js';
|
|
4
|
+
export * from './http-errors/forbidden.error.js';
|
|
5
|
+
export * from './http-errors/internal-server.error.js';
|
|
6
|
+
export * from './http-errors/method-not-allowed.error.js';
|
|
7
|
+
export * from './http-errors/not-found.error.js';
|
|
8
|
+
export * from './http-errors/unauthorized.error.js';
|
|
9
|
+
export * from './http-errors/unprocessable-entity.error.js';
|
|
10
|
+
export * from './resource-errors/resource-conflict.error.js';
|
package/esm/exception/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from './api-exception.js';
|
|
2
|
-
export * from './errors/bad-request.error.js';
|
|
3
|
-
export * from './errors/failed-dependency.error.js';
|
|
4
|
-
export * from './errors/
|
|
5
|
-
export * from './errors/
|
|
6
|
-
export * from './errors/not-
|
|
7
|
-
export * from './errors/
|
|
8
|
-
export * from './errors/
|
|
2
|
+
export * from './http-errors/bad-request.error.js';
|
|
3
|
+
export * from './http-errors/failed-dependency.error.js';
|
|
4
|
+
export * from './http-errors/forbidden.error.js';
|
|
5
|
+
export * from './http-errors/internal-server.error.js';
|
|
6
|
+
export * from './http-errors/method-not-allowed.error.js';
|
|
7
|
+
export * from './http-errors/not-found.error.js';
|
|
8
|
+
export * from './http-errors/unauthorized.error.js';
|
|
9
|
+
export * from './http-errors/unprocessable-entity.error.js';
|
|
10
|
+
export * from './resource-errors/resource-conflict.error.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { translate } from '@opra/i18n';
|
|
2
|
+
import { HttpStatus } from '../../enums/index.js';
|
|
3
|
+
import { ApiException } from '../api-exception.js';
|
|
4
|
+
export class ResourceConflictError extends ApiException {
|
|
5
|
+
constructor(resource, fields, cause) {
|
|
6
|
+
super({
|
|
7
|
+
message: translate(`error:RESOURCE_CONFLICT`, { resource, fields }),
|
|
8
|
+
severity: 'error',
|
|
9
|
+
code: 'RESOURCE_CONFLICT',
|
|
10
|
+
subject: resource,
|
|
11
|
+
location: fields
|
|
12
|
+
}, cause);
|
|
13
|
+
this.status = HttpStatus.CONFLICT;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApiException } from './api-exception.js';
|
|
2
|
-
import { InternalServerError } from './errors/internal-server.error.js';
|
|
2
|
+
import { InternalServerError } from './http-errors/internal-server.error.js';
|
|
3
3
|
export function wrapError(response) {
|
|
4
4
|
if (response instanceof ApiException)
|
|
5
5
|
return response;
|
|
@@ -2,6 +2,7 @@ import { AsyncEventEmitter } from 'strict-typed-events';
|
|
|
2
2
|
import { I18n } from '@opra/i18n';
|
|
3
3
|
import { FailedDependencyError } from '../../exception/index.js';
|
|
4
4
|
import { wrapError } from '../../exception/wrap-error.js';
|
|
5
|
+
import { createI18n } from '../../utils/create-i18n.js';
|
|
5
6
|
export class OpraAdapter {
|
|
6
7
|
service;
|
|
7
8
|
i18n;
|
|
@@ -24,7 +25,7 @@ export class OpraAdapter {
|
|
|
24
25
|
let promises;
|
|
25
26
|
let exclusive = false;
|
|
26
27
|
for (const context of queryContexts) {
|
|
27
|
-
exclusive = exclusive || context.query.
|
|
28
|
+
exclusive = exclusive || context.query.operation !== 'read';
|
|
28
29
|
// Wait previous read requests before executing update request
|
|
29
30
|
if (exclusive && promises) {
|
|
30
31
|
await Promise.allSettled(promises);
|
|
@@ -92,8 +93,6 @@ export class OpraAdapter {
|
|
|
92
93
|
return options.i18n;
|
|
93
94
|
if (typeof options?.i18n === 'function')
|
|
94
95
|
return options.i18n();
|
|
95
|
-
|
|
96
|
-
await instance.init();
|
|
97
|
-
return instance;
|
|
96
|
+
return createI18n(options?.i18n);
|
|
98
97
|
}
|
|
99
98
|
}
|
|
@@ -38,7 +38,7 @@ export class OpraHttpAdapter extends OpraAdapter {
|
|
|
38
38
|
query,
|
|
39
39
|
headers,
|
|
40
40
|
params: url.searchParams,
|
|
41
|
-
continueOnError: query.
|
|
41
|
+
continueOnError: query.operation === 'read'
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
44
|
buildQuery(url, method, body) {
|
|
@@ -212,7 +212,7 @@ export class OpraHttpAdapter extends OpraAdapter {
|
|
|
212
212
|
}
|
|
213
213
|
else {
|
|
214
214
|
delete body.errors;
|
|
215
|
-
status = status || (query.
|
|
215
|
+
status = status || (query.operation === 'create' ? HttpStatus.CREATED : HttpStatus.OK);
|
|
216
216
|
}
|
|
217
217
|
body = this.i18n.deep(body);
|
|
218
218
|
return {
|
|
@@ -7,12 +7,12 @@ export declare type OpraQuery = OpraCreateQuery | OpraGetQuery | OpraSearchQuery
|
|
|
7
7
|
interface BaseOpraQuery {
|
|
8
8
|
queryType: QueryType;
|
|
9
9
|
scope: QueryScope;
|
|
10
|
-
|
|
10
|
+
operation: OperationType;
|
|
11
11
|
}
|
|
12
12
|
export interface OpraCreateQuery extends BaseOpraQuery {
|
|
13
13
|
queryType: 'create';
|
|
14
14
|
scope: 'collection';
|
|
15
|
-
|
|
15
|
+
operation: 'create';
|
|
16
16
|
resource: EntityResourceHandler;
|
|
17
17
|
data: {};
|
|
18
18
|
pick?: string[];
|
|
@@ -22,7 +22,7 @@ export interface OpraCreateQuery extends BaseOpraQuery {
|
|
|
22
22
|
export interface OpraGetQuery extends BaseOpraQuery {
|
|
23
23
|
queryType: 'get';
|
|
24
24
|
scope: 'instance';
|
|
25
|
-
|
|
25
|
+
operation: 'read';
|
|
26
26
|
resource: EntityResourceHandler;
|
|
27
27
|
keyValue: KeyValue;
|
|
28
28
|
pick?: string[];
|
|
@@ -33,14 +33,14 @@ export interface OpraGetQuery extends BaseOpraQuery {
|
|
|
33
33
|
export interface OpraPropertyQuery extends BaseOpraQuery {
|
|
34
34
|
queryType: 'get';
|
|
35
35
|
scope: 'property';
|
|
36
|
-
|
|
36
|
+
operation: 'read';
|
|
37
37
|
property: OpraSchema.Property;
|
|
38
38
|
nested?: OpraPropertyQuery;
|
|
39
39
|
}
|
|
40
40
|
export interface OpraUpdateQuery extends BaseOpraQuery {
|
|
41
41
|
queryType: 'update';
|
|
42
42
|
scope: 'instance';
|
|
43
|
-
|
|
43
|
+
operation: 'update';
|
|
44
44
|
resource: EntityResourceHandler;
|
|
45
45
|
keyValue: KeyValue;
|
|
46
46
|
data: {};
|
|
@@ -51,7 +51,7 @@ export interface OpraUpdateQuery extends BaseOpraQuery {
|
|
|
51
51
|
export interface OpraUpdateManyQuery extends BaseOpraQuery {
|
|
52
52
|
queryType: 'updateMany';
|
|
53
53
|
scope: 'collection';
|
|
54
|
-
|
|
54
|
+
operation: 'update';
|
|
55
55
|
resource: EntityResourceHandler;
|
|
56
56
|
filter?: string | Expression;
|
|
57
57
|
data: {};
|
|
@@ -59,21 +59,21 @@ export interface OpraUpdateManyQuery extends BaseOpraQuery {
|
|
|
59
59
|
export interface OpraDeleteQuery extends BaseOpraQuery {
|
|
60
60
|
queryType: 'delete';
|
|
61
61
|
scope: 'instance';
|
|
62
|
-
|
|
62
|
+
operation: 'delete';
|
|
63
63
|
resource: EntityResourceHandler;
|
|
64
64
|
keyValue: KeyValue;
|
|
65
65
|
}
|
|
66
66
|
export interface OpraDeleteManyQuery extends BaseOpraQuery {
|
|
67
67
|
queryType: 'deleteMany';
|
|
68
68
|
scope: 'collection';
|
|
69
|
-
|
|
69
|
+
operation: 'delete';
|
|
70
70
|
resource: EntityResourceHandler;
|
|
71
71
|
filter?: string | Expression;
|
|
72
72
|
}
|
|
73
73
|
export interface OpraSearchQuery extends BaseOpraQuery {
|
|
74
74
|
queryType: 'search';
|
|
75
75
|
scope: 'collection';
|
|
76
|
-
|
|
76
|
+
operation: 'read';
|
|
77
77
|
resource: EntityResourceHandler;
|
|
78
78
|
pick?: string[];
|
|
79
79
|
omit?: string[];
|
|
@@ -85,17 +85,17 @@ export interface OpraSearchQuery extends BaseOpraQuery {
|
|
|
85
85
|
count?: boolean;
|
|
86
86
|
sort?: string[];
|
|
87
87
|
}
|
|
88
|
-
export declare type CreateQueryOptions = StrictOmit<OpraCreateQuery, 'queryType' | 'scope' | '
|
|
89
|
-
export declare type GetQueryOptions = StrictOmit<OpraGetQuery, 'queryType' | 'scope' | '
|
|
90
|
-
export declare type SearchQueryOptions = StrictOmit<OpraSearchQuery, 'queryType' | 'scope' | '
|
|
91
|
-
export declare type UpdateQueryOptions = StrictOmit<OpraUpdateQuery, 'queryType' | 'scope' | '
|
|
92
|
-
export declare type UpdateManyQueryOptions = StrictOmit<OpraUpdateManyQuery, 'queryType' | 'scope' | '
|
|
93
|
-
export declare type DeleteManyQueryOption = StrictOmit<OpraDeleteManyQuery, 'queryType' | 'scope' | '
|
|
88
|
+
export declare type CreateQueryOptions = StrictOmit<OpraCreateQuery, 'queryType' | 'scope' | 'operation' | 'resource' | 'data'>;
|
|
89
|
+
export declare type GetQueryOptions = StrictOmit<OpraGetQuery, 'queryType' | 'scope' | 'operation' | 'resource' | 'keyValue'>;
|
|
90
|
+
export declare type SearchQueryOptions = StrictOmit<OpraSearchQuery, 'queryType' | 'scope' | 'operation' | 'resource'>;
|
|
91
|
+
export declare type UpdateQueryOptions = StrictOmit<OpraUpdateQuery, 'queryType' | 'scope' | 'operation' | 'resource' | 'keyValue' | 'data'>;
|
|
92
|
+
export declare type UpdateManyQueryOptions = StrictOmit<OpraUpdateManyQuery, 'queryType' | 'scope' | 'operation' | 'resource' | 'data'>;
|
|
93
|
+
export declare type DeleteManyQueryOption = StrictOmit<OpraDeleteManyQuery, 'queryType' | 'scope' | 'operation' | 'resource'>;
|
|
94
94
|
export declare namespace OpraQuery {
|
|
95
95
|
function forCreate(resource: EntityResourceHandler, values: {}, options?: CreateQueryOptions): OpraCreateQuery;
|
|
96
96
|
function forGet(resource: EntityResourceHandler, key: KeyValue, options?: GetQueryOptions): OpraGetQuery;
|
|
97
97
|
function forSearch(resource: EntityResourceHandler, options?: SearchQueryOptions): OpraSearchQuery;
|
|
98
|
-
function forGetProperty(property: OpraSchema.Property, options?: StrictOmit<OpraPropertyQuery, 'queryType' | 'scope' | '
|
|
98
|
+
function forGetProperty(property: OpraSchema.Property, options?: StrictOmit<OpraPropertyQuery, 'queryType' | 'scope' | 'operation' | 'property'>): OpraPropertyQuery;
|
|
99
99
|
function forUpdate(resource: EntityResourceHandler, keyValue: KeyValue, values: any, options?: UpdateQueryOptions): OpraUpdateQuery;
|
|
100
100
|
function forUpdateMany(resource: EntityResourceHandler, values: any, options?: UpdateManyQueryOptions): OpraUpdateManyQuery;
|
|
101
101
|
function forDelete(resource: EntityResourceHandler, key: KeyValue): OpraDeleteQuery;
|
|
@@ -13,7 +13,7 @@ export var OpraQuery;
|
|
|
13
13
|
const out = {
|
|
14
14
|
queryType: 'create',
|
|
15
15
|
scope: 'collection',
|
|
16
|
-
|
|
16
|
+
operation: 'create',
|
|
17
17
|
resource,
|
|
18
18
|
data: values
|
|
19
19
|
};
|
|
@@ -32,7 +32,7 @@ export var OpraQuery;
|
|
|
32
32
|
const out = {
|
|
33
33
|
queryType: 'get',
|
|
34
34
|
scope: 'instance',
|
|
35
|
-
|
|
35
|
+
operation: 'read',
|
|
36
36
|
resource,
|
|
37
37
|
keyValue: key
|
|
38
38
|
};
|
|
@@ -52,7 +52,7 @@ export var OpraQuery;
|
|
|
52
52
|
const out = {
|
|
53
53
|
queryType: 'search',
|
|
54
54
|
scope: 'collection',
|
|
55
|
-
|
|
55
|
+
operation: 'read',
|
|
56
56
|
resource
|
|
57
57
|
};
|
|
58
58
|
Object.assign(out, _.omit(options, Object.keys(out)));
|
|
@@ -63,7 +63,7 @@ export var OpraQuery;
|
|
|
63
63
|
const out = {
|
|
64
64
|
queryType: 'get',
|
|
65
65
|
scope: 'property',
|
|
66
|
-
|
|
66
|
+
operation: 'read',
|
|
67
67
|
property
|
|
68
68
|
};
|
|
69
69
|
Object.assign(out, _.omit(options, Object.keys(out)));
|
|
@@ -81,7 +81,7 @@ export var OpraQuery;
|
|
|
81
81
|
const out = {
|
|
82
82
|
queryType: 'update',
|
|
83
83
|
scope: 'instance',
|
|
84
|
-
|
|
84
|
+
operation: 'update',
|
|
85
85
|
resource,
|
|
86
86
|
keyValue,
|
|
87
87
|
data: values
|
|
@@ -94,7 +94,7 @@ export var OpraQuery;
|
|
|
94
94
|
const out = {
|
|
95
95
|
queryType: 'updateMany',
|
|
96
96
|
scope: 'collection',
|
|
97
|
-
|
|
97
|
+
operation: 'update',
|
|
98
98
|
resource,
|
|
99
99
|
data: values
|
|
100
100
|
};
|
|
@@ -107,7 +107,7 @@ export var OpraQuery;
|
|
|
107
107
|
return {
|
|
108
108
|
queryType: 'delete',
|
|
109
109
|
scope: 'instance',
|
|
110
|
-
|
|
110
|
+
operation: 'delete',
|
|
111
111
|
resource,
|
|
112
112
|
keyValue: key
|
|
113
113
|
};
|
|
@@ -117,7 +117,7 @@ export var OpraQuery;
|
|
|
117
117
|
const out = {
|
|
118
118
|
queryType: 'deleteMany',
|
|
119
119
|
scope: 'collection',
|
|
120
|
-
|
|
120
|
+
operation: 'delete',
|
|
121
121
|
resource,
|
|
122
122
|
};
|
|
123
123
|
Object.assign(out, _.omit(options, Object.keys(out)));
|
package/esm/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Type } from 'ts-gems';
|
|
2
2
|
export declare type Thunk<T> = T | (() => T);
|
|
3
3
|
export declare type ThunkAsync<T> = T | Promise<T> | (() => T) | (() => Promise<T>);
|
|
4
4
|
export declare type TypeThunk<T = any> = Thunk<Type<T>>;
|
|
@@ -7,5 +7,3 @@ export declare type QueryScope = 'collection' | 'instance' | 'property';
|
|
|
7
7
|
export declare type QueryType = 'create' | 'get' | 'update' | 'patch' | 'delete' | 'execute' | 'search' | 'updateMany' | 'patchMany' | 'deleteMany';
|
|
8
8
|
export declare type OperationType = 'create' | 'read' | 'update' | 'patch' | 'delete' | 'execute';
|
|
9
9
|
export declare type KeyValue = string | number | boolean | object;
|
|
10
|
-
export declare type PartialInput<T> = DeepPartial<DeepPickWritable<DeepPickJson<T>>>;
|
|
11
|
-
export declare type PartialOutput<T> = DeepPartial<DeepPickJson<T>>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { I18n } from '@opra/i18n';
|
|
3
|
+
import { getCallerFile } from './get-caller-file.util.js';
|
|
4
|
+
export async function createI18n(options) {
|
|
5
|
+
const opts = {
|
|
6
|
+
...options,
|
|
7
|
+
resourceDirs: undefined
|
|
8
|
+
};
|
|
9
|
+
const instance = I18n.createInstance(opts);
|
|
10
|
+
await instance.init();
|
|
11
|
+
await instance.loadResourceDir(path.resolve(getCallerFile(), '../../../i18n'));
|
|
12
|
+
if (options?.resourceDirs)
|
|
13
|
+
for (const dir of options.resourceDirs)
|
|
14
|
+
await instance.loadResourceDir(dir);
|
|
15
|
+
return instance;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getCallerFile(position?: number): any;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function getCallerFile(position = 1) {
|
|
2
|
+
if (position >= Error.stackTraceLimit) {
|
|
3
|
+
throw new TypeError('getCallerFile(position) requires position be less then Error.stackTraceLimit but position was: `' +
|
|
4
|
+
position + '` and Error.stackTraceLimit was: `' + Error.stackTraceLimit + '`');
|
|
5
|
+
}
|
|
6
|
+
const oldPrepareStackTrace = Error.prepareStackTrace;
|
|
7
|
+
Error.prepareStackTrace = (_, stack) => stack;
|
|
8
|
+
const stack = new Error().stack;
|
|
9
|
+
Error.prepareStackTrace = oldPrepareStackTrace;
|
|
10
|
+
if (stack !== null && typeof stack === 'object') {
|
|
11
|
+
// stack[0] holds this file
|
|
12
|
+
// stack[1] holds where this function was called
|
|
13
|
+
return stack[position] ? stack[position].getFileName() : undefined;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"BAD_REQUEST": "Bad request",
|
|
3
|
+
"FAILED_DEPENDENCY": "The request failed due to failure of a previous request",
|
|
4
|
+
"FORBIDDEN": "You are not authorized to perform this action",
|
|
5
|
+
"INTERNAL_SERVER_ERROR": "Internal server error",
|
|
6
|
+
"METHOD_NOT_ALLOWED": "Method Not Allowed",
|
|
7
|
+
"NOT_FOUND": "Not found",
|
|
8
|
+
"UNAUTHORIZED": "You have not been authenticated to perform this action",
|
|
9
|
+
"UNPROCESSABLE_ENTITY": "Unprocessable entity",
|
|
10
|
+
|
|
11
|
+
"RESOURCE_CONFLICT": "There is already an other {{resource}} resource with same field values ({{fields}})"
|
|
12
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"description": "Opra schema package",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
"build": "npm run build:cjs && npm run build:esm",
|
|
16
16
|
"build:cjs": "tsc -b tsconfig-build-cjs.json",
|
|
17
17
|
"build:esm": "tsc -b tsconfig-build-esm.json",
|
|
18
|
-
"postbuild": "
|
|
18
|
+
"postbuild": "npm run _copyi18n && npm run _copy_pkg_files",
|
|
19
|
+
"_copy_pkg_files": "cp README.md package.json ../../LICENSE ../../build/core && cp ../../package.cjs.json ../../build/core/cjs/package.json",
|
|
20
|
+
"_copyi18n": "cp -R i18n ../../build/core/i18n",
|
|
19
21
|
"lint": "eslint .",
|
|
20
22
|
"test": "jest",
|
|
21
23
|
"cover": "jest --collect-coverage",
|
|
@@ -25,10 +27,10 @@
|
|
|
25
27
|
"clean:cover": "rimraf ../../coverage/core"
|
|
26
28
|
},
|
|
27
29
|
"dependencies": {
|
|
28
|
-
"@opra/i18n": "^0.0.
|
|
29
|
-
"@opra/optionals": "^0.0.
|
|
30
|
-
"@opra/schema": "^0.0.
|
|
31
|
-
"@opra/url": "^0.0.
|
|
30
|
+
"@opra/i18n": "^0.0.11",
|
|
31
|
+
"@opra/optionals": "^0.0.11",
|
|
32
|
+
"@opra/schema": "^0.0.11",
|
|
33
|
+
"@opra/url": "^0.0.11",
|
|
32
34
|
"lodash": "^4.17.21",
|
|
33
35
|
"putil-isplainobject": "^1.1.4",
|
|
34
36
|
"putil-varhelpers": "^1.6.4",
|
|
@@ -60,6 +62,7 @@
|
|
|
60
62
|
"bin/",
|
|
61
63
|
"cjs/",
|
|
62
64
|
"esm/",
|
|
65
|
+
"i18n/",
|
|
63
66
|
"LICENSE",
|
|
64
67
|
"README.md"
|
|
65
68
|
],
|