@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
@@ -2,20 +2,22 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ApiException = void 0;
4
4
  const index_js_1 = require("../enums/index.js");
5
- const nodeEnv = process.env.NODE_ENV || '';
6
5
  /**
7
6
  * Defines the base Opra exception, which is handled by the default Exceptions Handler.
8
7
  */
9
8
  class ApiException extends Error {
10
- originalError;
9
+ static stackAsDiagnostics = false;
11
10
  response;
12
11
  status;
13
- constructor(response, status) {
14
- super();
12
+ cause;
13
+ constructor(response, cause) {
14
+ super('');
15
15
  this._initName();
16
- this.setStatus(status || index_js_1.HttpStatus.INTERNAL_SERVER_ERROR);
17
- if (response instanceof Error)
18
- this.originalError = response;
16
+ if (cause)
17
+ Object.defineProperty(this, 'cause', { enumerable: false, configurable: true, writable: true, value: cause });
18
+ else if (response instanceof Error)
19
+ Object.defineProperty(this, 'cause', { enumerable: false, configurable: true, writable: true, value: response });
20
+ this.status = index_js_1.HttpStatus.INTERNAL_SERVER_ERROR;
19
21
  this._initResponse(response);
20
22
  }
21
23
  setStatus(status) {
@@ -38,11 +40,7 @@ class ApiException extends Error {
38
40
  this.response = {
39
41
  message: x.message || x.details || ('' + init),
40
42
  };
41
- if (init instanceof Error) {
42
- if (nodeEnv === 'dev' || nodeEnv === 'development')
43
- this.response.diagnostics = init.stack;
44
- }
45
- else
43
+ if (!(init instanceof Error))
46
44
  Object.assign(this.response, init);
47
45
  }
48
46
  else {
@@ -50,14 +48,24 @@ class ApiException extends Error {
50
48
  message: '' + init,
51
49
  };
52
50
  }
51
+ if (this.cause instanceof Error && this.cause.stack) {
52
+ if (ApiException.stackAsDiagnostics)
53
+ this.response.diagnostics = this.cause.stack.split('\n');
54
+ this.stack = this.cause.stack;
55
+ }
53
56
  if (!this.response.severity)
54
57
  if (this.status >= 500)
55
58
  this.response.severity = 'fatal';
56
59
  else
57
60
  this.response.severity = 'error';
58
61
  }
59
- static wrap(response, status) {
60
- return response instanceof ApiException ? response : new this(response, status);
62
+ static wrap(response) {
63
+ if (response instanceof ApiException)
64
+ return response;
65
+ const out = new this(response, response instanceof Error ? response : undefined);
66
+ if (response instanceof Error)
67
+ out.stack = response.stack;
68
+ return out;
61
69
  }
62
70
  }
63
71
  exports.ApiException = ApiException;
@@ -10,13 +10,14 @@ const api_exception_js_1 = require("../api-exception.js");
10
10
  * (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
11
11
  */
12
12
  class BadRequestError extends api_exception_js_1.ApiException {
13
- constructor(response) {
13
+ constructor(response, cause) {
14
14
  super({
15
15
  message: (0, i18n_1.translate)('error:BAD_REQUEST', 'Bad request'),
16
16
  severity: 'error',
17
17
  code: 'BAD_REQUEST',
18
18
  ...response
19
- }, index_js_1.HttpStatus.BAD_REQUEST);
19
+ }, cause);
20
+ this.status = index_js_1.HttpStatus.BAD_REQUEST;
20
21
  }
21
22
  }
22
23
  exports.BadRequestError = BadRequestError;
@@ -9,13 +9,14 @@ const api_exception_js_1 = require("../api-exception.js");
9
9
  * The request failed due to failure of a previous request.
10
10
  */
11
11
  class FailedDependencyError extends api_exception_js_1.ApiException {
12
- constructor(response) {
12
+ constructor(response, cause) {
13
13
  super({
14
14
  message: (0, i18n_1.translate)('error:FAILED_DEPENDENCY', 'The request failed due to failure of a previous request.'),
15
15
  severity: 'error',
16
16
  code: 'FAILED_DEPENDENCY',
17
17
  ...response
18
- }, index_js_1.HttpStatus.FAILED_DEPENDENCY);
18
+ }, cause);
19
+ this.status = index_js_1.HttpStatus.FAILED_DEPENDENCY;
19
20
  }
20
21
  }
21
22
  exports.FailedDependencyError = FailedDependencyError;
@@ -11,13 +11,14 @@ const api_exception_js_1 = require("../api-exception.js");
11
11
  * the client's identity is known to the server.
12
12
  */
13
13
  class ForbiddenError extends api_exception_js_1.ApiException {
14
- constructor(response) {
14
+ constructor(response, cause) {
15
15
  super({
16
16
  message: (0, i18n_1.translate)('error:FORBIDDEN', 'Forbidden'),
17
17
  severity: 'error',
18
18
  code: 'FORBIDDEN',
19
19
  ...response
20
- }, index_js_1.HttpStatus.FORBIDDEN);
20
+ }, cause);
21
+ this.status = index_js_1.HttpStatus.FORBIDDEN;
21
22
  }
22
23
  }
23
24
  exports.ForbiddenError = ForbiddenError;
@@ -9,13 +9,14 @@ const api_exception_js_1 = require("../api-exception.js");
9
9
  * The server has encountered a situation it does not know how to handle.
10
10
  */
11
11
  class InternalServerError extends api_exception_js_1.ApiException {
12
- constructor(response) {
12
+ constructor(response, cause) {
13
13
  super({
14
14
  message: (0, i18n_1.translate)('error:INTERNAL_SERVER_ERROR', 'Internal server error'),
15
15
  severity: 'error',
16
16
  code: 'INTERNAL_SERVER_ERROR',
17
17
  ...response
18
- }, index_js_1.HttpStatus.INTERNAL_SERVER_ERROR);
18
+ }, cause);
19
+ this.status = index_js_1.HttpStatus.INTERNAL_SERVER_ERROR;
19
20
  }
20
21
  }
21
22
  exports.InternalServerError = InternalServerError;
@@ -10,13 +10,14 @@ const api_exception_js_1 = require("../api-exception.js");
10
10
  * For example, an API may not allow calling DELETE to remove a resource.
11
11
  */
12
12
  class MethodNotAllowedError extends api_exception_js_1.ApiException {
13
- constructor(response) {
13
+ constructor(response, cause) {
14
14
  super({
15
15
  message: (0, i18n_1.translate)('error:METHOD_NOT_ALLOWED', 'Method Not Allowed'),
16
16
  severity: 'error',
17
17
  code: 'METHOD_NOT_ALLOWED',
18
18
  ...response
19
- }, index_js_1.HttpStatus.METHOD_NOT_ALLOWED);
19
+ }, cause);
20
+ this.status = index_js_1.HttpStatus.METHOD_NOT_ALLOWED;
20
21
  }
21
22
  }
22
23
  exports.MethodNotAllowedError = MethodNotAllowedError;
@@ -13,13 +13,14 @@ const api_exception_js_1 = require("../api-exception.js");
13
13
  * frequent occurrence on the web.
14
14
  */
15
15
  class NotFoundError extends api_exception_js_1.ApiException {
16
- constructor(response) {
16
+ constructor(response, cause) {
17
17
  super({
18
18
  message: (0, i18n_1.translate)('error:NOT_FOUND', 'Not found'),
19
19
  severity: 'error',
20
20
  code: 'NOT_FOUND',
21
21
  ...response
22
- }, index_js_1.HttpStatus.NOT_FOUND);
22
+ }, cause);
23
+ this.status = index_js_1.HttpStatus.NOT_FOUND;
23
24
  }
24
25
  }
25
26
  exports.NotFoundError = NotFoundError;
@@ -10,13 +10,14 @@ const api_exception_js_1 = require("../api-exception.js");
10
10
  * That is, the client must authenticate itself to get the requested response.
11
11
  */
12
12
  class UnauthorizedError extends api_exception_js_1.ApiException {
13
- constructor(response) {
13
+ constructor(response, cause) {
14
14
  super({
15
15
  message: (0, i18n_1.translate)('error:UNAUTHORIZED', 'Unauthorized'),
16
16
  severity: 'error',
17
17
  code: 'UNAUTHORIZED',
18
18
  ...response
19
- }, index_js_1.HttpStatus.UNAUTHORIZED);
19
+ }, cause);
20
+ this.status = index_js_1.HttpStatus.UNAUTHORIZED;
20
21
  }
21
22
  }
22
23
  exports.UnauthorizedError = UnauthorizedError;
@@ -9,13 +9,14 @@ const api_exception_js_1 = require("../api-exception.js");
9
9
  * The request was well-formed but was unable to be followed due to semantic errors.
10
10
  */
11
11
  class UnprocessableEntityError extends api_exception_js_1.ApiException {
12
- constructor(response) {
12
+ constructor(response, cause) {
13
13
  super({
14
14
  message: (0, i18n_1.translate)('error:UNPROCESSABLE_ENTITY', 'Unprocessable entity'),
15
15
  severity: 'error',
16
16
  code: 'UNPROCESSABLE_ENTITY',
17
17
  ...response
18
- }, index_js_1.HttpStatus.UNPROCESSABLE_ENTITY);
18
+ }, cause);
19
+ this.status = index_js_1.HttpStatus.UNPROCESSABLE_ENTITY;
19
20
  }
20
21
  }
21
22
  exports.UnprocessableEntityError = UnprocessableEntityError;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wrapError = void 0;
4
+ const api_exception_js_1 = require("./api-exception.js");
5
+ const internal_server_error_js_1 = require("./errors/internal-server.error.js");
6
+ function wrapError(response) {
7
+ if (response instanceof api_exception_js_1.ApiException)
8
+ return response;
9
+ if (response instanceof Error) {
10
+ const x = response;
11
+ if (typeof x.status === 'number' || typeof x.getStatus === 'function')
12
+ return new api_exception_js_1.ApiException(response);
13
+ return new internal_server_error_js_1.InternalServerError(undefined, response);
14
+ }
15
+ return new internal_server_error_js_1.InternalServerError();
16
+ }
17
+ exports.wrapError = wrapError;
@@ -1,72 +1,100 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OpraAdapter = void 0;
4
- const types_1 = require("util/types");
5
4
  const i18n_1 = require("@opra/i18n");
6
5
  const index_js_1 = require("../../exception/index.js");
6
+ const wrap_error_js_1 = require("../../exception/wrap-error.js");
7
7
  class OpraAdapter {
8
8
  service;
9
9
  i18n;
10
- constructor(service, options) {
10
+ constructor(service, i18n) {
11
11
  this.service = service;
12
- this.i18n = options?.i18n || i18n_1.I18n.defaultInstance;
12
+ this.i18n = i18n || i18n_1.I18n.defaultInstance;
13
13
  }
14
- async handler(adapterContext, userContext) {
15
- let executionContexts;
14
+ async handler(adapterContext, userContextResolver) {
15
+ if (!this.i18n.isInitialized)
16
+ await this.i18n.init();
17
+ const executionContexts = [];
18
+ let requests;
19
+ let userContext;
16
20
  try {
17
- executionContexts = this.prepareExecutionContexts(adapterContext, userContext);
18
- }
19
- catch (e) {
20
- const error = index_js_1.InternalServerError.wrap(e);
21
- await this.sendError(adapterContext, error);
22
- return;
23
- }
24
- let stop = false;
25
- // Read requests can be executed simultaneously, write request should be executed one by one
26
- let promises;
27
- let exclusive = false;
28
- for (const ctx of executionContexts) {
29
- const request = ctx.request;
30
- const response = ctx.response;
31
- exclusive = exclusive || request.query.operationType !== 'read';
32
- try {
21
+ requests = this.prepareRequests(adapterContext);
22
+ let stop = false;
23
+ // Read requests can be executed simultaneously, write request should be executed one by one
24
+ let promises;
25
+ let exclusive = false;
26
+ for (const request of requests) {
27
+ exclusive = exclusive || request.query.operationType !== 'read';
33
28
  // Wait previous read requests before executing update request
34
29
  if (exclusive && promises) {
35
- await Promise.all(promises);
30
+ await Promise.allSettled(promises);
36
31
  promises = undefined;
37
32
  }
33
+ const resource = request.query.resource;
34
+ const context = this.createExecutionContext(adapterContext, request);
35
+ executionContexts.push(context);
38
36
  // If previous request in bucket had an error and executed an update
39
37
  // we do not execute next requests
40
38
  if (stop) {
41
- response.errors.push(new index_js_1.FailedDependencyError());
39
+ context.response.errors.push(new index_js_1.FailedDependencyError());
40
+ continue;
42
41
  }
43
- else {
44
- const resource = ctx.request.query.resource;
45
- const v = resource.execute(ctx);
46
- if ((0, types_1.isPromise)(v)) {
47
- if (exclusive)
48
- await v;
49
- else {
50
- promises = promises || [];
51
- promises.push(v);
52
- }
42
+ try {
43
+ const promise = (async () => {
44
+ await resource.prepare(context);
45
+ if (userContextResolver && !userContext)
46
+ userContext = userContextResolver(this.isBatch(adapterContext));
47
+ context.userContext = userContext;
48
+ await resource.execute(context);
49
+ })().catch(e => {
50
+ context.response.errors.push(e);
51
+ });
52
+ if (exclusive)
53
+ await promise;
54
+ else {
55
+ promises = promises || [];
56
+ promises.push(promise);
53
57
  }
54
58
  // todo execute sub property queries
55
59
  }
60
+ catch (e) {
61
+ context.response.errors.unshift(e);
62
+ }
63
+ if (context.response.errors.length) {
64
+ // noinspection SuspiciousTypeOfGuard
65
+ context.response.errors = context.response.errors.map(e => (0, wrap_error_js_1.wrapError)(e));
66
+ if (exclusive)
67
+ stop = stop || !!context.response.errors.find(e => !(e.response.severity === 'warning' || e.response.severity === 'info'));
68
+ }
56
69
  }
57
- catch (e) {
58
- response.errors.unshift(index_js_1.ApiException.wrap(e));
59
- }
60
- if (response.errors && response.errors.length) {
61
- // noinspection SuspiciousTypeOfGuard
62
- response.errors = response.errors.map(e => index_js_1.ApiException.wrap(e));
63
- if (exclusive)
64
- stop = stop || !!response.errors.find(e => !(e.response.severity === 'warning' || e.response.severity === 'info'));
70
+ if (promises)
71
+ await Promise.allSettled(promises);
72
+ if (userContext && typeof userContext.onRequestFinish === 'function') {
73
+ try {
74
+ const hasError = !!executionContexts.find(ctx => ctx.response.errors?.length);
75
+ await userContext.onRequestFinish(hasError);
76
+ }
77
+ catch (e) {
78
+ await this.sendError(adapterContext, (0, wrap_error_js_1.wrapError)(e));
79
+ return;
80
+ }
65
81
  }
82
+ await this.sendResponse(adapterContext, executionContexts);
66
83
  }
67
- if (promises)
68
- await Promise.all(promises);
69
- await this.sendResponse(adapterContext, executionContexts);
84
+ catch (e) {
85
+ const error = (0, wrap_error_js_1.wrapError)(e);
86
+ await this.sendError(adapterContext, error);
87
+ return;
88
+ }
89
+ }
90
+ static async initI18n(options) {
91
+ if (options?.i18n instanceof i18n_1.I18n)
92
+ return options.i18n;
93
+ if (typeof options?.i18n === 'function')
94
+ return options.i18n();
95
+ const instance = i18n_1.I18n.createInstance(options?.i18n);
96
+ await instance.init();
97
+ return instance;
70
98
  }
71
99
  }
72
100
  exports.OpraAdapter = OpraAdapter;
@@ -4,20 +4,20 @@ exports.OpraExpressAdapter = void 0;
4
4
  const url_1 = require("@opra/url");
5
5
  const http_adapter_js_1 = require("./http-adapter.js");
6
6
  class OpraExpressAdapter extends http_adapter_js_1.OpraHttpAdapter {
7
- static init(app, service, options) {
8
- const adapter = new OpraExpressAdapter(service, options);
7
+ static async init(app, service, options) {
8
+ const i18n = await this.initI18n(options);
9
+ const adapter = new OpraExpressAdapter(service, i18n);
9
10
  const prefix = '/' + (0, url_1.normalizePath)(options?.prefix, true);
10
11
  const userContextResolver = options?.userContext;
11
12
  app.use(prefix, (request, response, next) => {
12
13
  (async () => {
13
- const userContext = userContextResolver && await userContextResolver(request);
14
14
  const req = new ExpressRequestWrapper(request);
15
15
  const res = new ExpressResponseWrapper(response);
16
16
  const adapterContext = {
17
17
  getRequest: () => req,
18
18
  getResponse: () => res
19
19
  };
20
- await adapter.handler(adapterContext, userContext);
20
+ await adapter.handler(adapterContext, (isBatch) => userContextResolver && userContextResolver(request, { platform: 'express', isBatch }));
21
21
  })().catch(e => next(e));
22
22
  });
23
23
  return adapter;
@@ -5,24 +5,27 @@ const url_1 = require("@opra/url");
5
5
  const constants_js_1 = require("../../constants.js");
6
6
  const index_js_1 = require("../../enums/index.js");
7
7
  const index_js_2 = require("../../exception/index.js");
8
+ const wrap_error_js_1 = require("../../exception/wrap-error.js");
8
9
  const execution_query_interface_js_1 = require("../../interfaces/execution-query.interface.js");
9
10
  const headers_js_1 = require("../../utils/headers.js");
10
11
  const complex_type_js_1 = require("../data-type/complex-type.js");
11
12
  const execution_context_js_1 = require("../execution-context.js");
12
- const container_resource_controller_js_1 = require("../resource/container-resource-controller.js");
13
- const entity_resource_info_js_1 = require("../resource/entity-resource-info.js");
13
+ const container_resource_handler_js_1 = require("../resource/container-resource-handler.js");
14
+ const entity_resource_handler_js_1 = require("../resource/entity-resource-handler.js");
14
15
  const adapter_js_1 = require("./adapter.js");
15
16
  class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
16
- prepareExecutionContexts(adapterContext, userContext) {
17
+ prepareRequests(adapterContext) {
17
18
  const req = adapterContext.getRequest();
18
19
  // todo implement batch requests
19
20
  if (this.isBatch(adapterContext)) {
20
21
  throw new Error('not implemented yet');
21
22
  }
22
23
  const url = new url_1.OpraURL(req.getUrl());
23
- return [this.prepareExecutionContext(adapterContext, url, req.getMethod(), headers_js_1.Headers.from(req.getHeaders()), req.getBody(), userContext)];
24
+ return [
25
+ this.prepareRequest(adapterContext, url, req.getMethod(), headers_js_1.Headers.from(req.getHeaders()), req.getBody())
26
+ ];
24
27
  }
25
- prepareExecutionContext(adapterContext, url, method, headers, body, userContext) {
28
+ prepareRequest(adapterContext, url, method, headers, body) {
26
29
  if (!url.path.size)
27
30
  throw new index_js_2.BadRequestError();
28
31
  if (method !== 'GET' && url.path.size > 1)
@@ -32,23 +35,21 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
32
35
  throw new index_js_2.MethodNotAllowedError({
33
36
  message: `Method "${method}" is not allowed by target resource`
34
37
  });
35
- const request = new execution_context_js_1.ExecutionRequest({
38
+ return new execution_context_js_1.ExecutionRequest({
36
39
  query,
37
40
  headers,
38
41
  params: url.searchParams,
39
42
  });
40
- const response = new execution_context_js_1.ExecutionResponse();
41
- // noinspection UnnecessaryLocalVariableJS
42
- const executionContext = new execution_context_js_1.ExecutionContext({
43
+ }
44
+ createExecutionContext(adapterContext, request) {
45
+ return new execution_context_js_1.ExecutionContext({
43
46
  type: 'http',
44
47
  service: this.service,
45
48
  request,
46
- response,
49
+ response: new execution_context_js_1.ExecutionResponse(),
47
50
  adapterContext,
48
- userContext,
49
51
  continueOnError: request.query.operationType === 'read'
50
52
  });
51
- return executionContext;
52
53
  }
53
54
  buildQuery(url, method, body) {
54
55
  let container = this.service;
@@ -59,12 +60,12 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
59
60
  let p = url.path.get(pathIndex++);
60
61
  const resource = container.getResource(p.resource);
61
62
  // Move through path directories (containers)
62
- if (resource instanceof container_resource_controller_js_1.ContainerResourceController) {
63
+ if (resource instanceof container_resource_handler_js_1.ContainerResourceHandler) {
63
64
  container = resource;
64
65
  }
65
66
  else {
66
67
  method = method.toUpperCase();
67
- if (resource instanceof entity_resource_info_js_1.EntityResourceInfo) {
68
+ if (resource instanceof entity_resource_handler_js_1.EntityResourceHandler) {
68
69
  const scope = p.key ? 'instance' : 'collection';
69
70
  if (pathIndex < pathLen && !(method === 'GET' && scope === 'instance'))
70
71
  return;
@@ -77,7 +78,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
77
78
  limit: url.searchParams.get('$limit'),
78
79
  skip: url.searchParams.get('$skip'),
79
80
  distinct: url.searchParams.get('$distinct'),
80
- total: url.searchParams.get('$total'),
81
+ count: url.searchParams.get('$count'),
81
82
  sort: url.searchParams.get('$sort'),
82
83
  pick: url.searchParams.get('$pick'),
83
84
  omit: url.searchParams.get('$omit'),
@@ -85,7 +86,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
85
86
  });
86
87
  }
87
88
  else {
88
- query = execution_query_interface_js_1.ExecutionQuery.forRead(resource, p.key, {
89
+ query = execution_query_interface_js_1.ExecutionQuery.forGet(resource, p.key, {
89
90
  pick: url.searchParams.get('$pick'),
90
91
  omit: url.searchParams.get('$omit'),
91
92
  include: url.searchParams.get('$include')
@@ -104,7 +105,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
104
105
  const prop = dataType.properties?.[p.resource];
105
106
  if (!prop)
106
107
  throw new index_js_2.NotFoundError({ message: `Invalid or unknown resource path (${path})` });
107
- const q = execution_query_interface_js_1.ExecutionQuery.forProperty(prop);
108
+ const q = execution_query_interface_js_1.ExecutionQuery.forGetProperty(prop);
108
109
  if (nested) {
109
110
  nested.nested = q;
110
111
  }
@@ -205,43 +206,25 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
205
206
  }
206
207
  createOutput(ctx) {
207
208
  const { query } = ctx.request;
208
- // Determine response status
209
209
  let status = ctx.response.status;
210
- if (ctx.response.errors.length) {
210
+ let body = ctx.response.value || {};
211
+ const errors = ctx.response.errors?.map(e => (0, wrap_error_js_1.wrapError)(e));
212
+ if (errors && errors.length) {
211
213
  if (!status || status < 400) {
212
214
  status = 0;
213
- for (const e of ctx.response.errors) {
215
+ for (const e of errors) {
214
216
  status = Math.max(status, e.status || status);
215
217
  }
216
218
  if (status < index_js_1.HttpStatus.BAD_REQUEST)
217
219
  status = index_js_1.HttpStatus.INTERNAL_SERVER_ERROR;
218
220
  }
219
- }
220
- else
221
- status = status || (query.operationType === 'create' ? index_js_1.HttpStatus.CREATED : index_js_1.HttpStatus.OK);
222
- let body;
223
- let value = ctx.response.value;
224
- if (query.queryType === 'search') {
225
- body = {
226
- // '@origin': ctx.resource.name + (ctx.request.resultPath ? '.' + ctx.request.resultPath : ''),
227
- items: ctx.response.value,
228
- total: ctx.response.total
229
- };
221
+ body.errors = errors.map(e => e.response);
230
222
  }
231
223
  else {
232
- // Move to sub property if result path defined
233
- if (value && ctx.request.resultPath) {
234
- const pathArray = ctx.request.resultPath.split('.');
235
- for (const property of pathArray) {
236
- value = value && typeof value === 'object' && value[property];
237
- }
238
- }
239
- body = value;
240
- }
241
- if (ctx.response.errors?.length) {
242
- body = body || {};
243
- body.errors = ctx.response.errors.map(e => e.response);
224
+ delete body.errors;
225
+ status = status || (query.operationType === 'create' ? index_js_1.HttpStatus.CREATED : index_js_1.HttpStatus.OK);
244
226
  }
227
+ body = this.i18n.deep(body);
245
228
  return {
246
229
  status,
247
230
  headers: ctx.response.headers,
@@ -5,7 +5,7 @@ const schema_1 = require("@opra/schema");
5
5
  const responsive_object_js_1 = require("../utils/responsive-object.js");
6
6
  const entity_type_js_1 = require("./data-type/entity-type.js");
7
7
  const opra_document_js_1 = require("./opra-document.js");
8
- const entity_resource_info_js_1 = require("./resource/entity-resource-info.js");
8
+ const entity_resource_handler_js_1 = require("./resource/entity-resource-handler.js");
9
9
  const schema_generator_js_1 = require("./schema-generator.js");
10
10
  class OpraService extends opra_document_js_1.OpraDocument {
11
11
  _resources = (0, responsive_object_js_1.Responsive)();
@@ -28,7 +28,7 @@ class OpraService extends opra_document_js_1.OpraDocument {
28
28
  }
29
29
  getEntityResource(name) {
30
30
  const t = this.getResource(name);
31
- if (!(t instanceof entity_resource_info_js_1.EntityResourceInfo))
31
+ if (!(t instanceof entity_resource_handler_js_1.EntityResourceHandler))
32
32
  throw new Error(`"${name}" is not an EntityResource`);
33
33
  return t;
34
34
  }
@@ -40,7 +40,7 @@ class OpraService extends opra_document_js_1.OpraDocument {
40
40
  throw new TypeError(`Datatype "${r.type}" declared in EntityResource (${r.name}) does not exists`);
41
41
  if (!(dataType instanceof entity_type_js_1.EntityType))
42
42
  throw new TypeError(`${r.type} is not an EntityType`);
43
- this.resources[r.name] = new entity_resource_info_js_1.EntityResourceInfo({ ...r, service: this, dataType });
43
+ this.resources[r.name] = new entity_resource_handler_js_1.EntityResourceHandler({ ...r, service: this, dataType });
44
44
  }
45
45
  else
46
46
  throw new TypeError(`Unknown resource kind (${r.kind})`);
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContainerResourceHandler = void 0;
4
+ const entity_resource_handler_js_1 = require("./entity-resource-handler.js");
5
+ const resource_handler_js_1 = require("./resource-handler.js");
6
+ class ContainerResourceHandler extends resource_handler_js_1.ResourceHandler {
7
+ constructor(args) {
8
+ super({
9
+ kind: 'ContainerResource',
10
+ ...args
11
+ });
12
+ }
13
+ getResource(name) {
14
+ const t = this._args.resources[name];
15
+ if (!t)
16
+ throw new Error(`Resource "${name}" does not exists`);
17
+ return t;
18
+ }
19
+ getEntityResource(name) {
20
+ const t = this.getResource(name);
21
+ if (!(t instanceof entity_resource_handler_js_1.EntityResourceHandler))
22
+ throw new Error(`"${name}" is not an EntityResource`);
23
+ return t;
24
+ }
25
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
+ execute(ctx) {
27
+ return Promise.resolve(undefined);
28
+ }
29
+ }
30
+ exports.ContainerResourceHandler = ContainerResourceHandler;