@opra/core 0.0.5 → 0.0.8

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 (74) hide show
  1. package/cjs/exception/api-exception.js +22 -14
  2. package/cjs/exception/errors/bad-request.error.js +3 -2
  3. package/cjs/exception/errors/failed-dependency.error.js +3 -2
  4. package/cjs/exception/errors/forbidden.error.js +3 -2
  5. package/cjs/exception/errors/internal-server.error.js +3 -2
  6. package/cjs/exception/errors/method-not-allowed.error.js +3 -2
  7. package/cjs/exception/errors/not-found.error.js +3 -2
  8. package/cjs/exception/errors/unauthorized.error.js +3 -2
  9. package/cjs/exception/errors/unprocessable-entity.error.js +3 -2
  10. package/cjs/exception/wrap-error.js +17 -0
  11. package/cjs/implementation/adapter/adapter.js +72 -44
  12. package/cjs/implementation/adapter/express-adapter.js +4 -4
  13. package/cjs/implementation/adapter/http-adapter.js +26 -43
  14. package/cjs/implementation/opra-service.js +3 -3
  15. package/cjs/implementation/resource/container-resource-handler.js +30 -0
  16. package/cjs/implementation/resource/entity-resource-handler.js +76 -0
  17. package/cjs/implementation/resource/{resource-info.js → resource-handler.js} +10 -3
  18. package/cjs/implementation/schema-generator.js +8 -5
  19. package/cjs/index.js +5 -3
  20. package/cjs/interfaces/execution-query.interface.js +6 -6
  21. package/cjs/interfaces/{entity-resource.interface.js → user-context.interface.js} +0 -0
  22. package/cjs/services/entity-resource-controller.js +30 -0
  23. package/esm/exception/api-exception.d.ts +5 -4
  24. package/esm/exception/api-exception.js +22 -14
  25. package/esm/exception/errors/bad-request.error.d.ts +1 -1
  26. package/esm/exception/errors/bad-request.error.js +3 -2
  27. package/esm/exception/errors/failed-dependency.error.d.ts +1 -1
  28. package/esm/exception/errors/failed-dependency.error.js +3 -2
  29. package/esm/exception/errors/forbidden.error.d.ts +1 -1
  30. package/esm/exception/errors/forbidden.error.js +3 -2
  31. package/esm/exception/errors/internal-server.error.d.ts +1 -1
  32. package/esm/exception/errors/internal-server.error.js +3 -2
  33. package/esm/exception/errors/method-not-allowed.error.d.ts +1 -1
  34. package/esm/exception/errors/method-not-allowed.error.js +3 -2
  35. package/esm/exception/errors/not-found.error.d.ts +1 -1
  36. package/esm/exception/errors/not-found.error.js +3 -2
  37. package/esm/exception/errors/unauthorized.error.d.ts +1 -1
  38. package/esm/exception/errors/unauthorized.error.js +3 -2
  39. package/esm/exception/errors/unprocessable-entity.error.d.ts +1 -1
  40. package/esm/exception/errors/unprocessable-entity.error.js +3 -2
  41. package/esm/exception/wrap-error.d.ts +2 -0
  42. package/esm/exception/wrap-error.js +13 -0
  43. package/esm/implementation/adapter/adapter.d.ts +43 -8
  44. package/esm/implementation/adapter/adapter.js +73 -45
  45. package/esm/implementation/adapter/express-adapter.d.ts +3 -4
  46. package/esm/implementation/adapter/express-adapter.js +4 -4
  47. package/esm/implementation/adapter/http-adapter.d.ts +6 -5
  48. package/esm/implementation/adapter/http-adapter.js +26 -43
  49. package/esm/implementation/opra-service.d.ts +6 -6
  50. package/esm/implementation/opra-service.js +3 -3
  51. package/esm/implementation/resource/container-resource-handler.d.ts +14 -0
  52. package/esm/implementation/resource/{container-resource-controller.js → container-resource-handler.js} +8 -4
  53. package/esm/implementation/resource/{entity-resource-info.d.ts → entity-resource-handler.d.ts} +4 -10
  54. package/esm/implementation/resource/entity-resource-handler.js +71 -0
  55. package/esm/implementation/resource/resource-handler.d.ts +15 -0
  56. package/esm/implementation/resource/{resource-info.js → resource-handler.js} +8 -1
  57. package/esm/implementation/schema-generator.js +8 -5
  58. package/esm/index.d.ts +5 -3
  59. package/esm/index.js +5 -3
  60. package/esm/interfaces/execution-query.interface.d.ts +19 -19
  61. package/esm/interfaces/execution-query.interface.js +6 -6
  62. package/esm/interfaces/resource-container.interface.d.ts +4 -4
  63. package/esm/interfaces/user-context.interface.d.ts +3 -0
  64. package/esm/interfaces/{entity-resource.interface.js → user-context.interface.js} +0 -0
  65. package/esm/services/entity-resource-controller.d.ts +17 -0
  66. package/esm/services/entity-resource-controller.js +26 -0
  67. package/esm/types.d.ts +1 -1
  68. package/package.json +8 -9
  69. package/cjs/implementation/resource/container-resource-controller.js +0 -26
  70. package/cjs/implementation/resource/entity-resource-info.js +0 -68
  71. package/esm/implementation/resource/container-resource-controller.d.ts +0 -12
  72. package/esm/implementation/resource/entity-resource-info.js +0 -63
  73. package/esm/implementation/resource/resource-info.d.ts +0 -10
  74. package/esm/interfaces/entity-resource.interface.d.ts +0 -9
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntityResourceHandler = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const lodash_1 = tslib_1.__importDefault(require("lodash"));
6
+ const execution_query_interface_js_1 = require("../../interfaces/execution-query.interface.js");
7
+ const entity_type_js_1 = require("../data-type/entity-type.js");
8
+ const resource_handler_js_1 = require("./resource-handler.js");
9
+ var isSearchQuery = execution_query_interface_js_1.ExecutionQuery.isSearchQuery;
10
+ class EntityResourceHandler extends resource_handler_js_1.ResourceHandler {
11
+ service;
12
+ dataType;
13
+ constructor(args) {
14
+ super({
15
+ kind: 'EntityResource',
16
+ ...lodash_1.default.omit(args, ['dataType', 'service'])
17
+ });
18
+ this.dataType = args.dataType;
19
+ this.service = args.service;
20
+ // noinspection SuspiciousTypeOfGuard
21
+ if (!(args.dataType instanceof entity_type_js_1.EntityType))
22
+ throw new TypeError(`You should provide an EntityType for EntityResourceController`);
23
+ }
24
+ async execute(ctx) {
25
+ const { query } = ctx.request;
26
+ if (isSearchQuery(query)) {
27
+ const promises = [];
28
+ let search;
29
+ let count;
30
+ promises.push(this._executeFn(ctx, query.queryType)
31
+ .then(v => search = v));
32
+ if (query.count) {
33
+ promises.push(this._executeFn(ctx, 'count')
34
+ .then(v => count = v));
35
+ }
36
+ await Promise.all(promises);
37
+ ctx.response.value = {
38
+ ...search,
39
+ ...count
40
+ };
41
+ return;
42
+ }
43
+ ctx.response.value = await this._executeFn(ctx, query.queryType);
44
+ }
45
+ async _executeFn(ctx, fnName) {
46
+ const fn = this._args[fnName];
47
+ let result = typeof fn === 'function' ? (await fn(ctx)) : undefined;
48
+ switch (fnName) {
49
+ case 'search':
50
+ return { items: Array.isArray(result) ? result : (ctx.response.value ? [result] : []) };
51
+ case 'count':
52
+ return { count: result || 0 };
53
+ case 'delete':
54
+ case 'deleteMany':
55
+ case 'updateMany':
56
+ let affectedRecords;
57
+ if (typeof result === 'number')
58
+ affectedRecords = result;
59
+ if (typeof result === 'boolean')
60
+ affectedRecords = result ? 1 : 0;
61
+ if (typeof result === 'object')
62
+ affectedRecords = result.affectedRows || result.affectedRecords;
63
+ return { affectedRecords };
64
+ default:
65
+ result = Array.isArray(result) ? result[0] : result;
66
+ if (result && ctx.request.resultPath) {
67
+ const pathArray = ctx.request.resultPath.split('.');
68
+ for (const property of pathArray) {
69
+ result = result && typeof result === 'object' && result[property];
70
+ }
71
+ }
72
+ return result;
73
+ }
74
+ }
75
+ }
76
+ exports.EntityResourceHandler = EntityResourceHandler;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ResourceInfo = void 0;
3
+ exports.ResourceHandler = void 0;
4
4
  const terminal_utils_js_1 = require("../../utils/terminal-utils.js");
5
- class ResourceInfo {
5
+ class ResourceHandler {
6
6
  _args;
7
7
  constructor(args) {
8
8
  this._args = args;
@@ -16,9 +16,16 @@ class ResourceInfo {
16
16
  toString() {
17
17
  return `[${Object.getPrototypeOf(this).constructor.name} ${this.name}]`;
18
18
  }
19
+ async prepare(ctx) {
20
+ const { query } = ctx.request;
21
+ const fn = this._args['pre_' + query.queryType];
22
+ if (fn && typeof fn === 'function') {
23
+ await fn(ctx);
24
+ }
25
+ }
19
26
  [terminal_utils_js_1.nodeInspectCustom]() {
20
27
  return `[${terminal_utils_js_1.colorFgYellow + Object.getPrototypeOf(this).constructor.name + terminal_utils_js_1.colorReset}` +
21
28
  ` ${terminal_utils_js_1.colorFgMagenta + this.name + terminal_utils_js_1.colorReset}]`;
22
29
  }
23
30
  }
24
- exports.ResourceInfo = ResourceInfo;
31
+ exports.ResourceHandler = ResourceHandler;
@@ -6,7 +6,7 @@ const schema_1 = require("@opra/schema");
6
6
  const constants_js_1 = require("../constants.js");
7
7
  const class_utils_js_1 = require("../utils/class-utils.js");
8
8
  const internal_data_types_js_1 = require("../utils/internal-data-types.js");
9
- const entityMethods = ['search', 'create', 'read', 'update', 'updateMany', 'delete', 'deleteMany'];
9
+ const entityMethods = ['search', 'count', 'create', 'get', 'update', 'updateMany', 'delete', 'deleteMany'];
10
10
  class SchemaGenerator {
11
11
  _dataTypes = {};
12
12
  _resources = {};
@@ -104,14 +104,17 @@ class SchemaGenerator {
104
104
  resourceSchema = {
105
105
  ...metadata,
106
106
  type,
107
- name
107
+ name,
108
+ instance
108
109
  };
109
110
  if (schema_1.OpraSchema.isEntityResource(resourceSchema)) {
110
111
  for (const methodName of entityMethods) {
111
- const fn = instance[methodName];
112
- if (typeof fn === 'function') {
112
+ let fn = instance['pre_' + methodName];
113
+ if (typeof fn === 'function')
114
+ resourceSchema['pre_' + methodName] = fn.bind(instance);
115
+ fn = instance[methodName];
116
+ if (typeof fn === 'function')
113
117
  resourceSchema[methodName] = fn.bind(instance);
114
- }
115
118
  }
116
119
  }
117
120
  }
package/cjs/index.js CHANGED
@@ -9,17 +9,19 @@ tslib_1.__exportStar(require("./exception/index.js"), exports);
9
9
  tslib_1.__exportStar(require("./decorators/entity-resource.decorator.js"), exports);
10
10
  tslib_1.__exportStar(require("./interfaces/http-context.interface.js"), exports);
11
11
  tslib_1.__exportStar(require("./interfaces/execution-query.interface.js"), exports);
12
- tslib_1.__exportStar(require("./interfaces/entity-resource.interface.js"), exports);
13
12
  tslib_1.__exportStar(require("./interfaces/resource-container.interface.js"), exports);
13
+ tslib_1.__exportStar(require("./interfaces/user-context.interface.js"), exports);
14
14
  tslib_1.__exportStar(require("./implementation/execution-context.js"), exports);
15
15
  tslib_1.__exportStar(require("./implementation/opra-document.js"), exports);
16
16
  tslib_1.__exportStar(require("./implementation/opra-service.js"), exports);
17
17
  tslib_1.__exportStar(require("./implementation/schema-generator.js"), exports);
18
18
  tslib_1.__exportStar(require("./implementation/adapter/adapter.js"), exports);
19
+ tslib_1.__exportStar(require("./implementation/adapter/http-adapter.js"), exports);
19
20
  tslib_1.__exportStar(require("./implementation/adapter/express-adapter.js"), exports);
20
21
  tslib_1.__exportStar(require("./implementation/data-type/data-type.js"), exports);
21
22
  tslib_1.__exportStar(require("./implementation/data-type/complex-type.js"), exports);
22
23
  tslib_1.__exportStar(require("./implementation/data-type/simple-type.js"), exports);
23
- tslib_1.__exportStar(require("./implementation/resource/resource-info.js"), exports);
24
- tslib_1.__exportStar(require("./implementation/resource/entity-resource-info.js"), exports);
24
+ tslib_1.__exportStar(require("./implementation/resource/resource-handler.js"), exports);
25
+ tslib_1.__exportStar(require("./implementation/resource/entity-resource-handler.js"), exports);
26
+ tslib_1.__exportStar(require("./services/entity-resource-controller.js"), exports);
25
27
  tslib_1.__exportStar(require("./services/json-data-service.js"), exports);
@@ -25,7 +25,7 @@ var ExecutionQuery;
25
25
  return out;
26
26
  }
27
27
  ExecutionQuery.forCreate = forCreate;
28
- function forRead(resource, key, options) {
28
+ function forGet(resource, key, options) {
29
29
  if (options?.pick)
30
30
  options.pick = normalizePick(resource, options.pick);
31
31
  if (options?.omit)
@@ -34,7 +34,7 @@ var ExecutionQuery;
34
34
  options.include = normalizePick(resource, options.include);
35
35
  checkKeyFields(resource, key);
36
36
  const out = {
37
- queryType: 'read',
37
+ queryType: 'get',
38
38
  scope: 'instance',
39
39
  operationType: 'read',
40
40
  resource,
@@ -43,7 +43,7 @@ var ExecutionQuery;
43
43
  Object.assign(out, lodash_1.default.omit(options, Object.keys(out)));
44
44
  return out;
45
45
  }
46
- ExecutionQuery.forRead = forRead;
46
+ ExecutionQuery.forGet = forGet;
47
47
  function forSearch(resource, options) {
48
48
  if (options?.pick)
49
49
  options.pick = normalizePick(resource, options.pick);
@@ -63,9 +63,9 @@ var ExecutionQuery;
63
63
  return out;
64
64
  }
65
65
  ExecutionQuery.forSearch = forSearch;
66
- function forProperty(property, options) {
66
+ function forGetProperty(property, options) {
67
67
  const out = {
68
- queryType: 'read',
68
+ queryType: 'get',
69
69
  scope: 'property',
70
70
  operationType: 'read',
71
71
  property
@@ -73,7 +73,7 @@ var ExecutionQuery;
73
73
  Object.assign(out, lodash_1.default.omit(options, Object.keys(out)));
74
74
  return out;
75
75
  }
76
- ExecutionQuery.forProperty = forProperty;
76
+ ExecutionQuery.forGetProperty = forGetProperty;
77
77
  function forUpdate(resource, keyValue, values, options) {
78
78
  if (options?.pick)
79
79
  options.pick = normalizePick(resource, options.pick);
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntityResourceController = void 0;
4
+ class EntityResourceController {
5
+ async search(ctx) {
6
+ return (await this.getService(ctx)).processRequest(ctx);
7
+ }
8
+ async get(ctx) {
9
+ return (await this.getService(ctx)).processRequest(ctx);
10
+ }
11
+ async count(ctx) {
12
+ return (await this.getService(ctx)).processRequest(ctx);
13
+ }
14
+ async create(ctx) {
15
+ return (await this.getService(ctx)).processRequest(ctx);
16
+ }
17
+ async update(ctx) {
18
+ return (await this.getService(ctx)).processRequest(ctx);
19
+ }
20
+ async updateMany(ctx) {
21
+ return (await this.getService(ctx)).processRequest(ctx);
22
+ }
23
+ async delete(ctx) {
24
+ return (await this.getService(ctx)).processRequest(ctx);
25
+ }
26
+ async deleteMany(ctx) {
27
+ return (await this.getService(ctx)).processRequest(ctx);
28
+ }
29
+ }
30
+ exports.EntityResourceController = EntityResourceController;
@@ -20,19 +20,20 @@ export interface ErrorResponse {
20
20
  /**
21
21
  * Additional diagnostic information about the issue. Error stack etc.
22
22
  */
23
- diagnostics?: string;
23
+ diagnostics?: string | string[];
24
24
  [index: string]: any;
25
25
  }
26
26
  /**
27
27
  * Defines the base Opra exception, which is handled by the default Exceptions Handler.
28
28
  */
29
29
  export declare class ApiException extends Error {
30
- readonly originalError?: Error;
30
+ static stackAsDiagnostics: boolean;
31
31
  response: ErrorResponse;
32
32
  status: number;
33
- constructor(response: string | ErrorResponse | Error, status?: number);
33
+ cause?: Error;
34
+ constructor(response: string | ErrorResponse | Error, cause?: Error);
34
35
  setStatus(status: number | HttpStatus): this;
35
36
  protected _initName(): void;
36
37
  protected _initResponse(init: string | ErrorResponse | Error): void;
37
- static wrap(response: string | ErrorResponse | Error, status?: number): ApiException;
38
+ static wrap(response: string | ErrorResponse | Error): ApiException;
38
39
  }
@@ -1,18 +1,20 @@
1
1
  import { HttpStatus } from '../enums/index.js';
2
- const nodeEnv = process.env.NODE_ENV || '';
3
2
  /**
4
3
  * Defines the base Opra exception, which is handled by the default Exceptions Handler.
5
4
  */
6
5
  export class ApiException extends Error {
7
- originalError;
6
+ static stackAsDiagnostics = false;
8
7
  response;
9
8
  status;
10
- constructor(response, status) {
11
- super();
9
+ cause;
10
+ constructor(response, cause) {
11
+ super('');
12
12
  this._initName();
13
- this.setStatus(status || HttpStatus.INTERNAL_SERVER_ERROR);
14
- if (response instanceof Error)
15
- this.originalError = response;
13
+ if (cause)
14
+ Object.defineProperty(this, 'cause', { enumerable: false, configurable: true, writable: true, value: cause });
15
+ else if (response instanceof Error)
16
+ Object.defineProperty(this, 'cause', { enumerable: false, configurable: true, writable: true, value: response });
17
+ this.status = HttpStatus.INTERNAL_SERVER_ERROR;
16
18
  this._initResponse(response);
17
19
  }
18
20
  setStatus(status) {
@@ -35,11 +37,7 @@ export class ApiException extends Error {
35
37
  this.response = {
36
38
  message: x.message || x.details || ('' + init),
37
39
  };
38
- if (init instanceof Error) {
39
- if (nodeEnv === 'dev' || nodeEnv === 'development')
40
- this.response.diagnostics = init.stack;
41
- }
42
- else
40
+ if (!(init instanceof Error))
43
41
  Object.assign(this.response, init);
44
42
  }
45
43
  else {
@@ -47,13 +45,23 @@ export class ApiException extends Error {
47
45
  message: '' + init,
48
46
  };
49
47
  }
48
+ if (this.cause instanceof Error && this.cause.stack) {
49
+ if (ApiException.stackAsDiagnostics)
50
+ this.response.diagnostics = this.cause.stack.split('\n');
51
+ this.stack = this.cause.stack;
52
+ }
50
53
  if (!this.response.severity)
51
54
  if (this.status >= 500)
52
55
  this.response.severity = 'fatal';
53
56
  else
54
57
  this.response.severity = 'error';
55
58
  }
56
- static wrap(response, status) {
57
- return response instanceof ApiException ? response : new this(response, status);
59
+ static wrap(response) {
60
+ if (response instanceof ApiException)
61
+ return response;
62
+ const out = new this(response, response instanceof Error ? response : undefined);
63
+ if (response instanceof Error)
64
+ out.stack = response.stack;
65
+ return out;
58
66
  }
59
67
  }
@@ -5,5 +5,5 @@ import { ApiException, ErrorResponse } from '../api-exception.js';
5
5
  * (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
6
6
  */
7
7
  export declare class BadRequestError extends ApiException {
8
- constructor(response?: ErrorResponse);
8
+ constructor(response?: ErrorResponse, cause?: Error);
9
9
  }
@@ -7,12 +7,13 @@ import { ApiException } from '../api-exception.js';
7
7
  * (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
8
8
  */
9
9
  export class BadRequestError extends ApiException {
10
- constructor(response) {
10
+ constructor(response, cause) {
11
11
  super({
12
12
  message: translate('error:BAD_REQUEST', 'Bad request'),
13
13
  severity: 'error',
14
14
  code: 'BAD_REQUEST',
15
15
  ...response
16
- }, HttpStatus.BAD_REQUEST);
16
+ }, cause);
17
+ this.status = HttpStatus.BAD_REQUEST;
17
18
  }
18
19
  }
@@ -4,5 +4,5 @@ import { ApiException, ErrorResponse } from '../api-exception.js';
4
4
  * The request failed due to failure of a previous request.
5
5
  */
6
6
  export declare class FailedDependencyError extends ApiException {
7
- constructor(response?: ErrorResponse);
7
+ constructor(response?: ErrorResponse, cause?: Error);
8
8
  }
@@ -6,12 +6,13 @@ import { ApiException } from '../api-exception.js';
6
6
  * The request failed due to failure of a previous request.
7
7
  */
8
8
  export class FailedDependencyError extends ApiException {
9
- constructor(response) {
9
+ constructor(response, cause) {
10
10
  super({
11
11
  message: translate('error:FAILED_DEPENDENCY', 'The request failed due to failure of a previous request.'),
12
12
  severity: 'error',
13
13
  code: 'FAILED_DEPENDENCY',
14
14
  ...response
15
- }, HttpStatus.FAILED_DEPENDENCY);
15
+ }, cause);
16
+ this.status = HttpStatus.FAILED_DEPENDENCY;
16
17
  }
17
18
  }
@@ -6,5 +6,5 @@ import { ApiException, ErrorResponse } from '../api-exception.js';
6
6
  * the client's identity is known to the server.
7
7
  */
8
8
  export declare class ForbiddenError extends ApiException {
9
- constructor(response?: ErrorResponse);
9
+ constructor(response?: ErrorResponse, cause?: Error);
10
10
  }
@@ -8,12 +8,13 @@ import { ApiException } from '../api-exception.js';
8
8
  * the client's identity is known to the server.
9
9
  */
10
10
  export class ForbiddenError extends ApiException {
11
- constructor(response) {
11
+ constructor(response, cause) {
12
12
  super({
13
13
  message: translate('error:FORBIDDEN', 'Forbidden'),
14
14
  severity: 'error',
15
15
  code: 'FORBIDDEN',
16
16
  ...response
17
- }, HttpStatus.FORBIDDEN);
17
+ }, cause);
18
+ this.status = HttpStatus.FORBIDDEN;
18
19
  }
19
20
  }
@@ -4,5 +4,5 @@ import { ApiException, ErrorResponse } from '../api-exception.js';
4
4
  * The server has encountered a situation it does not know how to handle.
5
5
  */
6
6
  export declare class InternalServerError extends ApiException {
7
- constructor(response?: ErrorResponse);
7
+ constructor(response?: ErrorResponse, cause?: Error);
8
8
  }
@@ -6,12 +6,13 @@ import { ApiException } from '../api-exception.js';
6
6
  * The server has encountered a situation it does not know how to handle.
7
7
  */
8
8
  export class InternalServerError extends ApiException {
9
- constructor(response) {
9
+ constructor(response, cause) {
10
10
  super({
11
11
  message: translate('error:INTERNAL_SERVER_ERROR', 'Internal server error'),
12
12
  severity: 'error',
13
13
  code: 'INTERNAL_SERVER_ERROR',
14
14
  ...response
15
- }, HttpStatus.INTERNAL_SERVER_ERROR);
15
+ }, cause);
16
+ this.status = HttpStatus.INTERNAL_SERVER_ERROR;
16
17
  }
17
18
  }
@@ -5,5 +5,5 @@ import { ApiException, ErrorResponse } from '../api-exception.js';
5
5
  * For example, an API may not allow calling DELETE to remove a resource.
6
6
  */
7
7
  export declare class MethodNotAllowedError extends ApiException {
8
- constructor(response?: ErrorResponse);
8
+ constructor(response?: ErrorResponse, cause?: Error);
9
9
  }
@@ -7,12 +7,13 @@ import { ApiException } from '../api-exception.js';
7
7
  * For example, an API may not allow calling DELETE to remove a resource.
8
8
  */
9
9
  export class MethodNotAllowedError extends ApiException {
10
- constructor(response) {
10
+ constructor(response, cause) {
11
11
  super({
12
12
  message: translate('error:METHOD_NOT_ALLOWED', 'Method Not Allowed'),
13
13
  severity: 'error',
14
14
  code: 'METHOD_NOT_ALLOWED',
15
15
  ...response
16
- }, HttpStatus.METHOD_NOT_ALLOWED);
16
+ }, cause);
17
+ this.status = HttpStatus.METHOD_NOT_ALLOWED;
17
18
  }
18
19
  }
@@ -8,5 +8,5 @@ import { ApiException, ErrorResponse } from '../api-exception.js';
8
8
  * frequent occurrence on the web.
9
9
  */
10
10
  export declare class NotFoundError extends ApiException {
11
- constructor(response?: ErrorResponse);
11
+ constructor(response?: ErrorResponse, cause?: Error);
12
12
  }
@@ -10,12 +10,13 @@ import { ApiException } from '../api-exception.js';
10
10
  * frequent occurrence on the web.
11
11
  */
12
12
  export class NotFoundError extends ApiException {
13
- constructor(response) {
13
+ constructor(response, cause) {
14
14
  super({
15
15
  message: translate('error:NOT_FOUND', 'Not found'),
16
16
  severity: 'error',
17
17
  code: 'NOT_FOUND',
18
18
  ...response
19
- }, HttpStatus.NOT_FOUND);
19
+ }, cause);
20
+ this.status = HttpStatus.NOT_FOUND;
20
21
  }
21
22
  }
@@ -5,5 +5,5 @@ import { ApiException, ErrorResponse } from '../api-exception.js';
5
5
  * That is, the client must authenticate itself to get the requested response.
6
6
  */
7
7
  export declare class UnauthorizedError extends ApiException {
8
- constructor(response?: ErrorResponse);
8
+ constructor(response?: ErrorResponse, cause?: Error);
9
9
  }
@@ -7,12 +7,13 @@ import { ApiException } from '../api-exception.js';
7
7
  * That is, the client must authenticate itself to get the requested response.
8
8
  */
9
9
  export class UnauthorizedError extends ApiException {
10
- constructor(response) {
10
+ constructor(response, cause) {
11
11
  super({
12
12
  message: translate('error:UNAUTHORIZED', 'Unauthorized'),
13
13
  severity: 'error',
14
14
  code: 'UNAUTHORIZED',
15
15
  ...response
16
- }, HttpStatus.UNAUTHORIZED);
16
+ }, cause);
17
+ this.status = HttpStatus.UNAUTHORIZED;
17
18
  }
18
19
  }
@@ -4,5 +4,5 @@ import { ApiException, ErrorResponse } from '../api-exception.js';
4
4
  * The request was well-formed but was unable to be followed due to semantic errors.
5
5
  */
6
6
  export declare class UnprocessableEntityError extends ApiException {
7
- constructor(response?: ErrorResponse);
7
+ constructor(response?: ErrorResponse, cause?: Error);
8
8
  }
@@ -6,12 +6,13 @@ import { ApiException } from '../api-exception.js';
6
6
  * The request was well-formed but was unable to be followed due to semantic errors.
7
7
  */
8
8
  export class UnprocessableEntityError extends ApiException {
9
- constructor(response) {
9
+ constructor(response, cause) {
10
10
  super({
11
11
  message: translate('error:UNPROCESSABLE_ENTITY', 'Unprocessable entity'),
12
12
  severity: 'error',
13
13
  code: 'UNPROCESSABLE_ENTITY',
14
14
  ...response
15
- }, HttpStatus.UNPROCESSABLE_ENTITY);
15
+ }, cause);
16
+ this.status = HttpStatus.UNPROCESSABLE_ENTITY;
16
17
  }
17
18
  }
@@ -0,0 +1,2 @@
1
+ import { ApiException, ErrorResponse } from './api-exception.js';
2
+ export declare function wrapError(response: string | ErrorResponse | Error): ApiException;
@@ -0,0 +1,13 @@
1
+ import { ApiException } from './api-exception.js';
2
+ import { InternalServerError } from './errors/internal-server.error.js';
3
+ export function wrapError(response) {
4
+ if (response instanceof ApiException)
5
+ return response;
6
+ if (response instanceof Error) {
7
+ const x = response;
8
+ if (typeof x.status === 'number' || typeof x.getStatus === 'function')
9
+ return new ApiException(response);
10
+ return new InternalServerError(undefined, response);
11
+ }
12
+ return new InternalServerError();
13
+ }
@@ -1,18 +1,53 @@
1
- import { I18n } from '@opra/i18n';
1
+ import { FallbackLng, I18n, LanguageResource } from '@opra/i18n';
2
2
  import { ApiException } from '../../exception/index.js';
3
- import { ExecutionContext } from '../execution-context.js';
3
+ import { ExecutionContext, ExecutionRequest } from '../execution-context.js';
4
4
  import { OpraService } from '../opra-service.js';
5
5
  export declare namespace OpraAdapter {
6
6
  interface Options {
7
- i18n?: I18n;
7
+ i18n?: I18n | I18nOptions | (() => Promise<I18n>);
8
+ userContext?: (request: any, options: {
9
+ platform: string;
10
+ isBatch: boolean;
11
+ }) => object | Promise<object>;
8
12
  }
13
+ interface I18nOptions {
14
+ /**
15
+ * Language to use
16
+ * @default undefined
17
+ */
18
+ lng?: string;
19
+ /**
20
+ * Language to use if translations in user language are not available.
21
+ * @default 'dev'
22
+ */
23
+ fallbackLng?: false | FallbackLng;
24
+ /**
25
+ * Default namespace used if not passed to translation function
26
+ * @default 'translation'
27
+ */
28
+ defaultNS?: string;
29
+ /**
30
+ * Resources to initialize with
31
+ * @default undefined
32
+ */
33
+ resources?: LanguageResource;
34
+ /**
35
+ * Resource directories to initialize with (if not using loading or not appending using addResourceBundle)
36
+ * @default undefined
37
+ */
38
+ resourceDirs?: string[];
39
+ }
40
+ type UserContextResolver = (isBatch: boolean) => any | Promise<any>;
9
41
  }
10
- export declare abstract class OpraAdapter<TAdapterContext = any, TOptions extends OpraAdapter.Options = OpraAdapter.Options> {
42
+ export declare abstract class OpraAdapter<TAdapterContext = any> {
11
43
  readonly service: OpraService;
12
- i18n: I18n;
13
- constructor(service: OpraService, options?: TOptions);
14
- protected abstract prepareExecutionContexts(adapterContext: TAdapterContext, userContext: any): ExecutionContext[];
44
+ readonly i18n: I18n;
45
+ constructor(service: OpraService, i18n?: I18n);
46
+ protected abstract prepareRequests(adapterContext: TAdapterContext): ExecutionRequest[];
47
+ protected abstract createExecutionContext(adapterContext: any, request: ExecutionRequest): ExecutionContext;
15
48
  protected abstract sendResponse(adapterContext: TAdapterContext, executionContexts: ExecutionContext[]): Promise<void>;
16
49
  protected abstract sendError(adapterContext: TAdapterContext, error: ApiException): Promise<void>;
17
- protected handler(adapterContext: TAdapterContext, userContext: any): Promise<void>;
50
+ protected abstract isBatch(adapterContext: TAdapterContext): boolean;
51
+ protected handler(adapterContext: TAdapterContext, userContextResolver?: OpraAdapter.UserContextResolver): Promise<void>;
52
+ protected static initI18n(options?: OpraAdapter.Options): Promise<I18n>;
18
53
  }