@opra/core 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/cjs/adapter/adapter.js +103 -123
  2. package/cjs/adapter/classes/execution-context.host.js +17 -0
  3. package/cjs/adapter/classes/express-request-wrapper.host.js +37 -0
  4. package/cjs/adapter/classes/express-response-wrapper.host.js +56 -0
  5. package/cjs/adapter/classes/http-execution-context.host.js +31 -0
  6. package/cjs/adapter/{metadata-resource.js → classes/metadata.resource.js} +3 -3
  7. package/cjs/adapter/express-adapter.js +6 -104
  8. package/cjs/adapter/http-adapter.js +282 -81
  9. package/cjs/adapter/request-contexts/batch-request-context.js +12 -0
  10. package/cjs/adapter/{query-context.js → request-contexts/request-context.js} +9 -13
  11. package/cjs/adapter/request-contexts/single-request-context.js +15 -0
  12. package/cjs/index.js +2 -2
  13. package/cjs/interfaces/i18n-options.interface.js +2 -0
  14. package/cjs/services/json-collection-service.js +36 -39
  15. package/cjs/services/json-singleton-service.js +9 -10
  16. package/cjs/utils/create-i18n.js +2 -2
  17. package/esm/adapter/adapter.d.ts +13 -44
  18. package/esm/adapter/adapter.js +89 -109
  19. package/esm/adapter/classes/execution-context.host.d.ts +10 -0
  20. package/esm/adapter/classes/execution-context.host.js +13 -0
  21. package/esm/adapter/classes/express-request-wrapper.host.d.ts +19 -0
  22. package/esm/adapter/classes/express-request-wrapper.host.js +33 -0
  23. package/esm/adapter/classes/express-response-wrapper.host.d.ts +22 -0
  24. package/esm/adapter/classes/express-response-wrapper.host.js +52 -0
  25. package/esm/adapter/classes/http-execution-context.host.d.ts +13 -0
  26. package/esm/adapter/classes/http-execution-context.host.js +27 -0
  27. package/esm/adapter/classes/metadata.resource.d.ts +8 -0
  28. package/esm/adapter/{metadata-resource.js → classes/metadata.resource.js} +2 -2
  29. package/esm/adapter/express-adapter.d.ts +1 -1
  30. package/esm/adapter/express-adapter.js +5 -103
  31. package/esm/adapter/http-adapter.d.ts +23 -12
  32. package/esm/adapter/http-adapter.js +248 -47
  33. package/esm/adapter/request-contexts/batch-request-context.d.ts +7 -0
  34. package/esm/adapter/request-contexts/batch-request-context.js +8 -0
  35. package/esm/adapter/request-contexts/request-context.d.ts +22 -0
  36. package/esm/adapter/{query-context.js → request-contexts/request-context.js} +6 -10
  37. package/esm/adapter/request-contexts/single-request-context.d.ts +10 -0
  38. package/esm/adapter/request-contexts/single-request-context.js +11 -0
  39. package/esm/index.d.ts +2 -2
  40. package/esm/index.js +2 -2
  41. package/esm/interfaces/execution-context.interface.d.ts +19 -11
  42. package/esm/interfaces/i18n-options.interface.d.ts +28 -0
  43. package/esm/interfaces/i18n-options.interface.js +1 -0
  44. package/esm/interfaces/resource.interface.d.ts +1 -1
  45. package/esm/services/json-collection-service.d.ts +3 -4
  46. package/esm/services/json-collection-service.js +17 -20
  47. package/esm/services/json-singleton-service.d.ts +3 -3
  48. package/esm/services/json-singleton-service.js +8 -8
  49. package/esm/utils/create-i18n.d.ts +3 -3
  50. package/esm/utils/create-i18n.js +1 -1
  51. package/package.json +7 -8
  52. package/cjs/enums/http-headers.enum.js +0 -395
  53. package/cjs/enums/http-status.enum.js +0 -300
  54. package/cjs/enums/index.js +0 -5
  55. package/cjs/helpers/headers-map.js +0 -18
  56. package/cjs/utils/path-to-tree.js +0 -28
  57. package/esm/adapter/metadata-resource.d.ts +0 -8
  58. package/esm/adapter/query-context.d.ts +0 -25
  59. package/esm/enums/http-headers.enum.d.ts +0 -370
  60. package/esm/enums/http-headers.enum.js +0 -392
  61. package/esm/enums/http-status.enum.d.ts +0 -290
  62. package/esm/enums/http-status.enum.js +0 -297
  63. package/esm/enums/index.d.ts +0 -2
  64. package/esm/enums/index.js +0 -2
  65. package/esm/helpers/headers-map.d.ts +0 -5
  66. package/esm/helpers/headers-map.js +0 -14
  67. package/esm/utils/path-to-tree.d.ts +0 -4
  68. package/esm/utils/path-to-tree.js +0 -24
@@ -1,51 +1,139 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OpraHttpAdapter = void 0;
4
- const exception_1 = require("@opra/exception");
5
- const schema_1 = require("@opra/schema");
6
- const url_1 = require("@opra/url");
7
- const index_js_1 = require("../enums/index.js");
8
- const headers_map_js_1 = require("../helpers/headers-map.js");
4
+ const common_1 = require("@opra/common");
9
5
  const adapter_js_1 = require("./adapter.js");
10
- const query_context_js_1 = require("./query-context.js");
6
+ const single_request_context_js_1 = require("./request-contexts/single-request-context.js");
11
7
  class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
12
- prepareRequests(executionContext) {
13
- const req = executionContext.getRequestWrapper();
14
- // todo implement batch requests
15
- if (this.isBatch(executionContext)) {
16
- throw new Error('not implemented yet');
8
+ async parse(executionContext) {
9
+ const req = executionContext.getRequest();
10
+ const contentType = req.getHeader('content-type');
11
+ if (!contentType || contentType === 'application/json') {
12
+ const body = req.getBody();
13
+ const url = new common_1.OpraURL(req.getUrl());
14
+ return this.parseSingleQuery({
15
+ executionContext,
16
+ url,
17
+ method: req.getMethod(),
18
+ headers: req.getHeaders(),
19
+ body
20
+ });
21
+ }
22
+ if (typeof contentType === 'string' && contentType.startsWith('multipart/mixed')) {
23
+ // const m = BOUNDARY_PATTERN.exec(contentType);
24
+ // if (!m)
25
+ // throw new BadRequestError({message: 'Content-Type header does not match required format'});
26
+ // const url = new OpraURL(req.getUrl());
27
+ // return await this.parseMultiPart(executionContext, url, req.getHeaders(), req.getStream(), m[1]);
17
28
  }
18
- const url = new url_1.OpraURL(req.getUrl());
19
- return [
20
- this.prepareRequest(executionContext, url, req.getMethod(), new headers_map_js_1.HeadersMap(req.getHeaders()), req.getBody())
21
- ];
29
+ throw new common_1.BadRequestError({ message: 'Unsupported Content-Type' });
22
30
  }
23
- prepareRequest(executionContext, url, method, headers, body) {
31
+ parseSingleQuery(args) {
32
+ const { executionContext, url, method, headers, body, contentId } = args;
24
33
  if (!url.path.size)
25
- throw new exception_1.BadRequestError();
34
+ throw new common_1.BadRequestError();
26
35
  if (method !== 'GET' && url.path.size > 1)
27
- throw new exception_1.BadRequestError();
36
+ throw new common_1.BadRequestError();
28
37
  const query = this.buildQuery(url, method, body);
29
38
  if (!query)
30
- throw new exception_1.MethodNotAllowedError({
39
+ throw new common_1.MethodNotAllowedError({
31
40
  message: `Method "${method}" is not allowed by target endpoint`
32
41
  });
33
- return new query_context_js_1.QueryContext({
42
+ return new single_request_context_js_1.SingleRequestContext({
34
43
  service: this.document,
35
44
  executionContext,
45
+ headers,
36
46
  query,
37
- headers: new headers_map_js_1.HeadersMap(),
38
47
  params: url.searchParams,
48
+ contentId,
39
49
  continueOnError: query.operation === 'read'
40
50
  });
41
51
  }
52
+ // async parseMultiPart(
53
+ // executionContext: TExecutionContext,
54
+ // url: OpraURL,
55
+ // headers: IncomingHttpHeaders,
56
+ // input: Readable,
57
+ // boundary: string
58
+ // ): Promise<BatchRequestContext> {
59
+ // return await new Promise((resolve, reject) => {
60
+ // let _resolved = false;
61
+ // const dicer = new Dicer({boundary});
62
+ // const doReject = (e) => {
63
+ // if (_resolved) return;
64
+ // _resolved = true;
65
+ // reject(e);
66
+ // taskQueue.clearQueue();
67
+ // dicer.destroy();
68
+ // }
69
+ // const taskQueue = new TaskQueue({concurrency: 1});
70
+ // taskQueue.on('error', doReject);
71
+ //
72
+ // const queries: SingleRequestContext[] = [];
73
+ // let partCounter = 0;
74
+ // dicer.on('error', doReject);
75
+ // dicer.on('part', part => {
76
+ // const partIndex = partCounter++;
77
+ // let header: any;
78
+ // const chunks: Buffer[] = [];
79
+ // part.on('error', doReject);
80
+ // part.on('header', (_header) => header = normalizeHeaders(_header));
81
+ // part.on('data', (chunk: Buffer) => chunks.push(chunk));
82
+ // part.on('end', () => {
83
+ // if (_resolved || !(header || chunks.length))
84
+ // return;
85
+ // const ct = header['content-type'];
86
+ // if (ct === 'application/http') {
87
+ // taskQueue.enqueue(async () => {
88
+ // const data = Buffer.concat(chunks);
89
+ // if (!(data && data.length))
90
+ // return;
91
+ // const r = HttpRequest.parse(data);
92
+ // await callMiddlewares(r, [jsonBodyParser]);
93
+ // const subUrl = new OpraURL(r.url);
94
+ // const contentId = header && header['content-id'];
95
+ // queries.push(this.parseSingleQuery({
96
+ // executionContext,
97
+ // url: subUrl,
98
+ // method: r.method,
99
+ // headers: r.headers,
100
+ // body: r.body,
101
+ // contentId
102
+ // }));
103
+ // });
104
+ // } else doReject(new BadRequestError({
105
+ // message: 'Unaccepted "content-type" header in multipart data',
106
+ // details: {
107
+ // position: `${boundary}[${partIndex}]`
108
+ // }
109
+ // }))
110
+ // });
111
+ // });
112
+ // dicer.on('finish', () => {
113
+ // taskQueue.enqueue(() => {
114
+ // if (_resolved) return;
115
+ // _resolved = true;
116
+ // const batch = new BatchRequestContext({
117
+ // service: this.document,
118
+ // executionContext,
119
+ // headers,
120
+ // queries,
121
+ // params: url.searchParams,
122
+ // continueOnError: false
123
+ // });
124
+ // resolve(batch);
125
+ // });
126
+ // });
127
+ // input.pipe(dicer);
128
+ // });
129
+ // }
42
130
  buildQuery(url, method, body) {
43
131
  const pathLen = url.path.size;
44
132
  let p = url.path.get(0);
45
133
  let resource = this._internalResources.get(p.resource) || this.document.getResource(p.resource);
46
134
  let container;
47
135
  let pathIndex = 0;
48
- while (resource && resource instanceof schema_1.ContainerResourceInfo) {
136
+ while (resource && resource instanceof common_1.ContainerResourceInfo) {
49
137
  container = resource;
50
138
  p = url.path.get(++pathIndex);
51
139
  resource = container.getResource(p.resource);
@@ -53,19 +141,24 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
53
141
  try {
54
142
  method = method.toUpperCase();
55
143
  let query;
56
- if (resource instanceof schema_1.SingletonResourceInfo && !p.key) {
144
+ if (resource instanceof common_1.SingletonResourceInfo && !p.key) {
57
145
  switch (method) {
58
146
  case 'GET': {
59
- query = new schema_1.SingletonGetQuery(resource);
147
+ const searchParams = url.searchParams;
148
+ query = new common_1.SingletonGetQuery(resource, {
149
+ pick: searchParams.get('$pick'),
150
+ omit: searchParams.get('$omit'),
151
+ include: searchParams.get('$include')
152
+ });
60
153
  }
61
154
  }
62
155
  }
63
- else if (resource instanceof schema_1.CollectionResourceInfo) {
156
+ else if (resource instanceof common_1.CollectionResourceInfo) {
64
157
  switch (method) {
65
158
  case 'GET': {
66
159
  if (p.key) {
67
160
  const searchParams = url.searchParams;
68
- query = new schema_1.CollectionGetQuery(resource, p.key, {
161
+ query = new common_1.CollectionGetQuery(resource, p.key, {
69
162
  pick: searchParams.get('$pick'),
70
163
  omit: searchParams.get('$omit'),
71
164
  include: searchParams.get('$include')
@@ -73,7 +166,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
73
166
  }
74
167
  else {
75
168
  const searchParams = url.searchParams;
76
- query = new schema_1.CollectionSearchQuery(resource, {
169
+ query = new common_1.CollectionSearchQuery(resource, {
77
170
  filter: searchParams.get('$filter'),
78
171
  limit: searchParams.get('$limit'),
79
172
  skip: searchParams.get('$skip'),
@@ -90,8 +183,8 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
90
183
  case 'DELETE': {
91
184
  const searchParams = url.searchParams;
92
185
  query = p.key
93
- ? new schema_1.CollectionDeleteQuery(resource, p.key)
94
- : new schema_1.CollectionDeleteManyQuery(resource, {
186
+ ? new common_1.CollectionDeleteQuery(resource, p.key)
187
+ : new common_1.CollectionDeleteManyQuery(resource, {
95
188
  filter: searchParams.get('$filter'),
96
189
  });
97
190
  break;
@@ -99,7 +192,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
99
192
  case 'POST': {
100
193
  if (!p.key) {
101
194
  const searchParams = url.searchParams;
102
- query = new schema_1.CollectionCreateQuery(resource, body, {
195
+ query = new common_1.CollectionCreateQuery(resource, body, {
103
196
  pick: searchParams.get('$pick'),
104
197
  omit: searchParams.get('$omit'),
105
198
  include: searchParams.get('$include')
@@ -110,7 +203,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
110
203
  case 'PATCH': {
111
204
  if (p.key) {
112
205
  const searchParams = url.searchParams;
113
- query = new schema_1.CollectionUpdateQuery(resource, p.key, body, {
206
+ query = new common_1.CollectionUpdateQuery(resource, p.key, body, {
114
207
  pick: searchParams.get('$pick'),
115
208
  omit: searchParams.get('$omit'),
116
209
  include: searchParams.get('$include')
@@ -118,7 +211,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
118
211
  }
119
212
  else {
120
213
  const searchParams = url.searchParams;
121
- query = new schema_1.CollectionUpdateManyQuery(resource, body, {
214
+ query = new common_1.CollectionUpdateManyQuery(resource, body, {
122
215
  filter: searchParams.get('$filter')
123
216
  });
124
217
  }
@@ -127,8 +220,8 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
127
220
  }
128
221
  }
129
222
  else
130
- throw new exception_1.InternalServerError();
131
- if (query instanceof schema_1.SingletonGetQuery || query instanceof schema_1.CollectionGetQuery || query instanceof schema_1.FieldGetQuery) {
223
+ throw new common_1.InternalServerError();
224
+ if (query instanceof common_1.SingletonGetQuery || query instanceof common_1.CollectionGetQuery || query instanceof common_1.FieldGetQuery) {
132
225
  // Move through properties
133
226
  let parentType;
134
227
  const curPath = [];
@@ -136,101 +229,190 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
136
229
  while (++pathIndex < pathLen) {
137
230
  p = url.path.get(pathIndex);
138
231
  parentType = parent.dataType;
139
- if (parent.dataType instanceof schema_1.UnionType) {
232
+ if (parent.dataType instanceof common_1.UnionType) {
140
233
  if (parent.dataType.name === 'any')
141
234
  parentType = this.document.getComplexDataType('object');
142
235
  else
143
236
  throw new TypeError(`"${resource.name}.${curPath.join()}" is a UnionType and needs type casting.`);
144
237
  }
145
- if (!(parentType instanceof schema_1.ComplexType))
238
+ if (!(parentType instanceof common_1.ComplexType))
146
239
  throw new TypeError(`"${resource.name}.${curPath.join()}" is not a ComplexType and has no fields.`);
147
240
  curPath.push(p.resource);
148
- parent.child = new schema_1.FieldGetQuery(parent, p.resource, { castingType: parentType });
241
+ parent.child = new common_1.FieldGetQuery(parent, p.resource, { castingType: parentType });
149
242
  parent = parent.child;
150
243
  }
151
244
  }
152
245
  return query;
153
246
  }
154
247
  catch (e) {
155
- if (e instanceof exception_1.OpraException)
248
+ if (e instanceof common_1.OpraException)
156
249
  throw e;
157
- throw new exception_1.BadRequestError(e);
250
+ throw new common_1.BadRequestError(e);
158
251
  }
159
252
  }
160
- async sendResponse(executionContext, queryContexts) {
161
- const outputPackets = [];
162
- for (const ctx of queryContexts) {
163
- const v = this.createOutput(ctx);
164
- outputPackets.push(v);
165
- }
166
- if (this.isBatch(executionContext)) {
167
- // this.writeError([], new InternalServerError({message: 'Not implemented yet'}));
168
- return;
169
- }
170
- if (!outputPackets.length)
171
- return this.sendError(executionContext, new exception_1.NotFoundError());
172
- const out = outputPackets[0];
173
- const resp = executionContext.getResponseWrapper();
253
+ async sendResponse(executionContext, requestContext) {
254
+ // if (requestContext instanceof BatchRequestContext)
255
+ // return this.sendBatchResponse(executionContext, requestContext);
256
+ if (requestContext instanceof single_request_context_js_1.SingleRequestContext)
257
+ return this.sendSingleResponse(executionContext, requestContext);
258
+ /* istanbul ignore next */
259
+ throw new TypeError('Invalid request context instance');
260
+ }
261
+ // protected async sendBatchResponse(executionContext: TExecutionContext, requestContext: BatchRequestContext) {
262
+ // const resp = executionContext.getResponse();
263
+ // resp.setStatus(HttpStatus.OK);
264
+ // resp.setHeader(HttpHeaders.Cache_Control, 'no-cache');
265
+ // resp.setHeader(HttpHeaders.Pragma, 'no-cache');
266
+ // resp.setHeader(HttpHeaders.Expires, '-1');
267
+ // if (requestContext.headers) {
268
+ // for (const [k, v] of Object.entries(requestContext.headers)) {
269
+ // if (v)
270
+ // resp.setHeader(k, v);
271
+ // }
272
+ // }
273
+ // const boundary = 'batch_' + uuid();
274
+ // resp.setHeader(HttpHeaders.Content_Type, 'multipart/mixed;boundary=' + boundary);
275
+ // resp.setHeader(HttpHeaders.X_Opra_Version, OpraSchema.Version);
276
+ //
277
+ // const bodyBuilder = new HttpMultipartData();
278
+ //
279
+ // const chunks: any[] = [];
280
+ // let msgIdx = 0;
281
+ // for (const ctx of requestContext.queries) {
282
+ // msgIdx++;
283
+ // const out = this.createOutput(ctx);
284
+ //
285
+ //
286
+ // // chunks.push('--' + boundary + CRLF);
287
+ // // let s = 'Content-Type: application/http' + CRLF +
288
+ // // 'Content-Transfer-Encoding: binary' + CRLF +
289
+ // // 'Content-ID:' + (ctx.contentId || msgIdx) + CRLF +
290
+ // // CRLF +
291
+ // // 'HTTP/1.1 ' + out.status + (HttpStatus[out.status] || 'Unknown') + CRLF;
292
+ //
293
+ // let body = out.body;
294
+ // const headers = out.headers || {};
295
+ // if (body) {
296
+ // const contentType = String(headers['content-type'] || '').split(/\s*;\s*/);
297
+ // let charset = '';
298
+ // if (Highland.isStream(body)) {
299
+ // const l = parseInt(String(headers['content-length']), 10);
300
+ // if (isNaN(l))
301
+ // throw new TypeError('"content-length" header required for streamed responses');
302
+ // } else if (typeof body === 'object') {
303
+ // if (typeof body.stream === 'function') { // File and Blob
304
+ // contentType[0] = body.type || 'binary';
305
+ // headers['content-length'] = String(body.size);
306
+ // body = body.stream();
307
+ // } else if (Buffer.isBuffer(body)) {
308
+ // headers['content-length'] = String(body.length);
309
+ // } else {
310
+ // contentType[0] = contentType[0] || 'application/json';
311
+ // charset = 'utf-8';
312
+ // body = Buffer.from(JSON.stringify(body), 'utf-8');
313
+ // headers['content-length'] = String(body.length);
314
+ // }
315
+ // } else {
316
+ // contentType[0] = contentType[0] || 'text/plain';
317
+ // charset = 'utf-8';
318
+ // body = Buffer.from(String(body), 'utf-8');
319
+ // headers['content-length'] = String(body.length);
320
+ // }
321
+ // if (contentType[0]) {
322
+ // if (charset) {
323
+ // const i = contentType.findIndex(x => CHARSET_PATTERN.test(String(x)));
324
+ // if (i > 0) contentType[i] = 'charset=' + charset;
325
+ // else contentType.join('charset=' + charset);
326
+ // }
327
+ // headers['content-type'] = contentType.join(';');
328
+ // }
329
+ // }
330
+ // for (const [k, v] of Object.entries(headers))
331
+ // s += k + ': ' + (Array.isArray(v) ? v.join(';') : v) + CRLF
332
+ //
333
+ // chunks.push(s + CRLF);
334
+ //
335
+ // if (body) {
336
+ // if (typeof body === 'string')
337
+ // chunks.push(body + CRLF + CRLF);
338
+ // else {
339
+ // chunks.push(body);
340
+ // chunks.push(CRLF + CRLF);
341
+ // }
342
+ // }
343
+ // }
344
+ //
345
+ // chunks.push('--' + boundary + '--' + CRLF);
346
+ //
347
+ // resp.setHeader('content-type', 'multipart/mixed;boundary=' + boundary);
348
+ // resp.send(Highland(chunks).flatten());
349
+ // resp.end();
350
+ // }
351
+ async sendSingleResponse(executionContext, requestContext) {
352
+ const out = this.createOutput(requestContext);
353
+ const resp = executionContext.getResponse();
174
354
  resp.setStatus(out.status);
175
- resp.setHeader(index_js_1.HttpHeaders.Content_Type, 'application/json');
176
- resp.setHeader(index_js_1.HttpHeaders.Cache_Control, 'no-cache');
177
- resp.setHeader(index_js_1.HttpHeaders.Pragma, 'no-cache');
178
- resp.setHeader(index_js_1.HttpHeaders.Expires, '-1');
179
- resp.setHeader(index_js_1.HttpHeaders.X_Opra_Version, schema_1.OpraSchema.Version);
355
+ resp.setHeader(common_1.HttpHeaders.Cache_Control, 'no-cache');
356
+ resp.setHeader(common_1.HttpHeaders.Pragma, 'no-cache');
357
+ resp.setHeader(common_1.HttpHeaders.Expires, '-1');
180
358
  if (out.headers) {
181
359
  for (const [k, v] of Object.entries(out.headers)) {
182
- resp.setHeader(k, v);
360
+ if (v)
361
+ resp.setHeader(k, v);
183
362
  }
184
363
  }
185
- resp.send(JSON.stringify(out.body));
364
+ resp.setHeader(common_1.HttpHeaders.X_Opra_Version, common_1.OpraSchema.Version);
365
+ if (out.body)
366
+ resp.send(out.body);
186
367
  resp.end();
187
368
  }
188
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
189
- isBatch(executionContext) {
190
- return false;
191
- }
192
369
  createOutput(ctx) {
193
370
  const { query } = ctx;
194
371
  let body;
195
372
  let status = ctx.status || 0;
196
- const errors = ctx.errors.map(e => (0, exception_1.wrapException)(e));
373
+ const errors = ctx.errors.map(e => (0, common_1.wrapException)(e));
197
374
  if (errors && errors.length) {
198
375
  // Sort errors from fatal to info
199
376
  errors.sort((a, b) => {
200
- const i = exception_1.IssueSeverity.Keys.indexOf(a.issue.severity) - exception_1.IssueSeverity.Keys.indexOf(b.issue.severity);
377
+ const i = common_1.IssueSeverity.Keys.indexOf(a.issue.severity) - common_1.IssueSeverity.Keys.indexOf(b.issue.severity);
201
378
  if (i === 0)
202
379
  return b.status - a.status;
203
380
  return i;
204
381
  });
205
- if (!status || status < index_js_1.HttpStatus.BAD_REQUEST) {
382
+ if (!status || status < common_1.HttpStatus.BAD_REQUEST) {
206
383
  status = errors[0].status;
207
- if (status < index_js_1.HttpStatus.BAD_REQUEST)
208
- status = index_js_1.HttpStatus.INTERNAL_SERVER_ERROR;
384
+ if (status < common_1.HttpStatus.BAD_REQUEST)
385
+ status = common_1.HttpStatus.INTERNAL_SERVER_ERROR;
209
386
  }
210
- body = {
387
+ body = this.i18n.deep({
211
388
  operation: ctx.query.method,
212
389
  errors: errors.map(e => e.issue)
213
- };
390
+ });
391
+ body = JSON.stringify(body);
392
+ ctx.responseHeaders['content-type'] = 'application/json; charset=utf-8';
214
393
  }
215
394
  else {
216
- body = ctx.response;
217
- status = status || (query.operation === 'create' ? index_js_1.HttpStatus.CREATED : index_js_1.HttpStatus.OK);
395
+ if (typeof ctx.response === 'object' && !((0, common_1.isReadable)(ctx.response) || Buffer.isBuffer(ctx.response))) {
396
+ body = this.i18n.deep(ctx.response);
397
+ body = JSON.stringify(body);
398
+ ctx.responseHeaders['content-type'] = 'application/json; charset=utf-8';
399
+ }
400
+ status = status || (query.operation === 'create' ? common_1.HttpStatus.CREATED : common_1.HttpStatus.OK);
218
401
  }
219
- body = this.i18n.deep(body);
220
402
  return {
221
403
  status,
222
- headers: ctx.responseHeaders.toObject(),
404
+ headers: (0, common_1.normalizeHeaders)(ctx.responseHeaders),
223
405
  body
224
406
  };
225
407
  }
226
408
  async sendError(executionContext, error) {
227
- const resp = executionContext.getResponseWrapper();
409
+ const resp = executionContext.getResponse();
228
410
  resp.setStatus(error.status || 500);
229
- resp.setHeader(index_js_1.HttpHeaders.Content_Type, 'application/json');
230
- resp.setHeader(index_js_1.HttpHeaders.Cache_Control, 'no-cache');
231
- resp.setHeader(index_js_1.HttpHeaders.Pragma, 'no-cache');
232
- resp.setHeader(index_js_1.HttpHeaders.Expires, '-1');
233
- resp.setHeader(index_js_1.HttpHeaders.X_Opra_Version, schema_1.OpraSchema.Version);
411
+ resp.setHeader(common_1.HttpHeaders.Content_Type, 'application/json');
412
+ resp.setHeader(common_1.HttpHeaders.Cache_Control, 'no-cache');
413
+ resp.setHeader(common_1.HttpHeaders.Pragma, 'no-cache');
414
+ resp.setHeader(common_1.HttpHeaders.Expires, '-1');
415
+ resp.setHeader(common_1.HttpHeaders.X_Opra_Version, common_1.OpraSchema.Version);
234
416
  const issue = this.i18n.deep(error.issue);
235
417
  const body = {
236
418
  operation: 'unknown',
@@ -240,3 +422,22 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
240
422
  }
241
423
  }
242
424
  exports.OpraHttpAdapter = OpraHttpAdapter;
425
+ // async function callMiddlewares(req: HttpRequest, middlewares: NextHandleFunction[]): Promise<void> {
426
+ // return new Promise<void>((resolve, reject) => {
427
+ // let i = 0;
428
+ // const next = (err?: any) => {
429
+ // if (err)
430
+ // return reject(err);
431
+ // const fn = middlewares[i++];
432
+ // if (!fn)
433
+ // return resolve();
434
+ // try {
435
+ // fn(req as any, {} as any, next);
436
+ // } catch (e) {
437
+ // reject(e);
438
+ // }
439
+ // }
440
+ // next();
441
+ // });
442
+ //
443
+ // }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BatchRequestContext = void 0;
4
+ const request_context_js_1 = require("./request-context.js");
5
+ class BatchRequestContext extends request_context_js_1.RequestContext {
6
+ queries;
7
+ constructor(args) {
8
+ super(args);
9
+ this.queries = args.queries;
10
+ }
11
+ }
12
+ exports.BatchRequestContext = BatchRequestContext;
@@ -1,31 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.QueryContext = void 0;
4
- const url_1 = require("@opra/url");
5
- const headers_map_js_1 = require("../helpers/headers-map.js");
6
- class QueryContext {
3
+ exports.RequestContext = void 0;
4
+ const common_1 = require("@opra/common");
5
+ class RequestContext {
7
6
  service;
8
7
  executionContext;
9
- query;
10
8
  params;
11
9
  headers;
10
+ contentId;
12
11
  parentValue;
13
12
  resultPath;
14
13
  responseHeaders;
15
14
  response;
16
15
  errors = [];
17
16
  status;
18
- userContext;
19
17
  continueOnError;
20
18
  constructor(args) {
21
- // Object.assign(this, args);
22
19
  this.service = args.service;
23
20
  this.executionContext = args.executionContext;
24
- this.query = args.query;
25
- // this.response = new QueryResponse();
26
- this.params = this.params || new url_1.OpraURLSearchParams();
27
- this.headers = new headers_map_js_1.HeadersMap(args.headers);
28
- this.responseHeaders = new headers_map_js_1.HeadersMap();
21
+ this.params = this.params || new common_1.OpraURLSearchParams();
22
+ this.headers = args.headers;
23
+ this.contentId = args.contentId;
24
+ this.responseHeaders = {};
29
25
  this.resultPath = this.resultPath || '';
30
26
  }
31
27
  get type() {
@@ -37,4 +33,4 @@ class QueryContext {
37
33
  return this.executionContext;
38
34
  }
39
35
  }
40
- exports.QueryContext = QueryContext;
36
+ exports.RequestContext = RequestContext;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SingleRequestContext = void 0;
4
+ const request_context_js_1 = require("./request-context.js");
5
+ class SingleRequestContext extends request_context_js_1.RequestContext {
6
+ query;
7
+ constructor(args) {
8
+ super(args);
9
+ this.query = args.query;
10
+ }
11
+ get userContext() {
12
+ return this.executionContext.userContext;
13
+ }
14
+ }
15
+ exports.SingleRequestContext = SingleRequestContext;
package/cjs/index.js CHANGED
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  require("reflect-metadata");
5
5
  tslib_1.__exportStar(require("./types.js"), exports);
6
- tslib_1.__exportStar(require("./enums/index.js"), exports);
7
6
  tslib_1.__exportStar(require("./interfaces/execution-context.interface.js"), exports);
8
7
  tslib_1.__exportStar(require("./interfaces/resource.interface.js"), exports);
9
- tslib_1.__exportStar(require("./adapter/query-context.js"), exports);
8
+ tslib_1.__exportStar(require("./interfaces/i18n-options.interface.js"), exports);
9
+ tslib_1.__exportStar(require("./adapter/request-contexts/single-request-context.js"), exports);
10
10
  tslib_1.__exportStar(require("./adapter/adapter.js"), exports);
11
11
  tslib_1.__exportStar(require("./adapter/http-adapter.js"), exports);
12
12
  tslib_1.__exportStar(require("./adapter/express-adapter.js"), exports);
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });