@opra/core 0.20.3 → 0.22.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 (77) hide show
  1. package/cjs/adapter/adapter.js +2 -2
  2. package/cjs/adapter/http/express-adapter.js +29 -7
  3. package/cjs/adapter/http/helpers/common.js +66 -0
  4. package/cjs/adapter/http/helpers/convert-to-headers.js +65 -0
  5. package/cjs/adapter/http/helpers/convert-to-raw-headers.js +25 -0
  6. package/cjs/adapter/http/helpers/match-known-fields.js +47 -0
  7. package/cjs/adapter/http/http-adapter.js +82 -440
  8. package/cjs/adapter/http/impl/http-incoming-message-host.js +127 -0
  9. package/cjs/adapter/http/impl/http-outgoing-message-host.js +210 -0
  10. package/cjs/adapter/http/impl/http-server-request.js +125 -0
  11. package/cjs/adapter/http/impl/http-server-response.js +226 -0
  12. package/cjs/adapter/http/request-parsers/batch-request-parser.js +169 -0
  13. package/cjs/adapter/http/request-parsers/parse-collection-request.js +165 -0
  14. package/cjs/adapter/http/request-parsers/parse-request.js +24 -0
  15. package/cjs/adapter/http/request-parsers/parse-singleton-request.js +96 -0
  16. package/cjs/adapter/request-context.host.js +17 -3
  17. package/cjs/adapter/request.host.js +6 -3
  18. package/cjs/adapter/response.host.js +5 -3
  19. package/cjs/index.js +4 -2
  20. package/esm/adapter/adapter.js +2 -2
  21. package/esm/adapter/http/express-adapter.js +6 -6
  22. package/esm/adapter/http/helpers/common.js +60 -0
  23. package/esm/adapter/http/helpers/convert-to-headers.js +60 -0
  24. package/esm/adapter/http/helpers/convert-to-raw-headers.js +21 -0
  25. package/esm/adapter/http/helpers/match-known-fields.js +43 -0
  26. package/esm/adapter/http/http-adapter.js +83 -441
  27. package/esm/adapter/http/impl/http-incoming-message-host.js +122 -0
  28. package/esm/adapter/http/impl/http-outgoing-message-host.js +205 -0
  29. package/esm/adapter/http/impl/http-server-request.js +121 -0
  30. package/esm/adapter/http/impl/http-server-response.js +222 -0
  31. package/esm/adapter/http/request-parsers/batch-request-parser.js +169 -0
  32. package/esm/adapter/http/request-parsers/parse-collection-request.js +161 -0
  33. package/esm/adapter/http/request-parsers/parse-request.js +20 -0
  34. package/esm/adapter/http/request-parsers/parse-singleton-request.js +92 -0
  35. package/esm/adapter/request-context.host.js +17 -3
  36. package/esm/adapter/request.host.js +6 -3
  37. package/esm/adapter/response.host.js +5 -3
  38. package/esm/index.js +4 -2
  39. package/package.json +19 -15
  40. package/types/adapter/adapter.d.ts +1 -1
  41. package/types/adapter/http/helpers/common.d.ts +17 -0
  42. package/types/adapter/http/helpers/convert-to-headers.d.ts +2 -0
  43. package/types/adapter/http/helpers/convert-to-raw-headers.d.ts +3 -0
  44. package/types/adapter/http/helpers/match-known-fields.d.ts +6 -0
  45. package/types/adapter/http/http-adapter.d.ts +7 -12
  46. package/types/adapter/http/impl/http-incoming-message-host.d.ts +58 -0
  47. package/types/adapter/http/impl/http-outgoing-message-host.d.ts +72 -0
  48. package/types/adapter/http/{http-request-message.d.ts → impl/http-server-request.d.ts} +52 -85
  49. package/types/adapter/http/impl/http-server-response.d.ts +137 -0
  50. package/types/adapter/http/request-parsers/batch-request-parser.d.ts +0 -0
  51. package/types/adapter/http/request-parsers/parse-collection-request.d.ts +4 -0
  52. package/types/adapter/http/request-parsers/parse-request.d.ts +4 -0
  53. package/types/adapter/http/request-parsers/parse-singleton-request.d.ts +4 -0
  54. package/types/adapter/interfaces/request-context.interface.d.ts +14 -10
  55. package/types/adapter/interfaces/request.interface.d.ts +3 -2
  56. package/types/adapter/interfaces/response.interface.d.ts +2 -2
  57. package/types/adapter/request-context.host.d.ts +9 -6
  58. package/types/adapter/request.host.d.ts +8 -4
  59. package/types/adapter/response.host.d.ts +6 -4
  60. package/types/index.d.ts +4 -2
  61. package/cjs/adapter/http/http-message.host.js +0 -251
  62. package/cjs/adapter/http/http-request-context.host.js +0 -28
  63. package/cjs/adapter/http/http-request-message.js +0 -152
  64. package/cjs/adapter/http/http-request.host.js +0 -14
  65. package/cjs/adapter/http/http-response-message.js +0 -238
  66. package/cjs/adapter/http/http-response.host.js +0 -14
  67. package/esm/adapter/http/http-message.host.js +0 -246
  68. package/esm/adapter/http/http-request-context.host.js +0 -24
  69. package/esm/adapter/http/http-request-message.js +0 -148
  70. package/esm/adapter/http/http-request.host.js +0 -10
  71. package/esm/adapter/http/http-response-message.js +0 -233
  72. package/esm/adapter/http/http-response.host.js +0 -10
  73. package/types/adapter/http/http-message.host.d.ts +0 -122
  74. package/types/adapter/http/http-request-context.host.d.ts +0 -16
  75. package/types/adapter/http/http-request.host.d.ts +0 -7
  76. package/types/adapter/http/http-response-message.d.ts +0 -321
  77. package/types/adapter/http/http-response.host.d.ts +0 -7
@@ -4,9 +4,9 @@ exports.OpraHttpAdapter = void 0;
4
4
  const power_tasks_1 = require("power-tasks");
5
5
  const common_1 = require("@opra/common");
6
6
  const adapter_js_1 = require("../adapter.js");
7
- const http_request_host_js_1 = require("./http-request.host.js");
8
- const http_request_context_host_js_1 = require("./http-request-context.host.js");
9
- const http_response_host_js_1 = require("./http-response.host.js");
7
+ const request_context_host_js_1 = require("../request-context.host.js");
8
+ const response_host_js_1 = require("../response.host.js");
9
+ const parse_request_js_1 = require("./request-parsers/parse-request.js");
10
10
  /**
11
11
  *
12
12
  * @class OpraHttpAdapter
@@ -20,43 +20,83 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
20
20
  */
21
21
  async handler(incoming, outgoing) {
22
22
  try {
23
- // Batch
24
- if (incoming.is('multipart/mixed')) {
25
- throw new common_1.BadRequestError({ message: 'Not implemented yet' });
23
+ try {
24
+ const request = await (0, parse_request_js_1.parseRequest)(this._apiRoot, incoming);
25
+ const task = this.createRequestTask(request, outgoing);
26
+ await task.toPromise();
26
27
  }
27
- if (!(incoming.method === 'POST' || incoming.method === 'PATCH') || incoming.is('json')) {
28
- const request = await this.parseRequest(incoming);
29
- const response = new http_response_host_js_1.HttpResponseHost({}, outgoing);
30
- const context = new http_request_context_host_js_1.HttpRequestContextHost(this.platform, this.api, request, response);
31
- const task = new power_tasks_1.Task(async () => {
32
- try {
33
- await this.executeRequest(context);
34
- if (request.operation === 'findMany' && request.args.count && response.count != null) {
35
- response.switchToHttp().header(common_1.HttpHeaderCodes.X_Opra_Total_Matches, String(response.count));
36
- }
37
- }
38
- catch (error) {
39
- return this.errorHandler(incoming, outgoing, [error]);
40
- }
41
- await this.sendResponse(context);
42
- }, {
43
- id: incoming.get('content-id'),
44
- exclusive: request.crud !== 'read'
45
- });
46
- await task.toPromise().catch(e => {
47
- this.logger?.error?.(e);
48
- outgoing.sendStatus(500);
49
- });
50
- await this.emitAsync('request-finish', context);
51
- return;
28
+ catch (e) {
29
+ if (e instanceof common_1.OpraException)
30
+ throw e;
31
+ throw new common_1.BadRequestError(e);
52
32
  }
53
- throw new common_1.BadRequestError({ message: 'Unsupported Content-Type' });
54
33
  }
55
34
  catch (error) {
56
- await this.errorHandler(incoming, outgoing, [error]);
35
+ await this.handleError(incoming, outgoing, [error]);
57
36
  }
58
37
  }
59
- async errorHandler(incoming, outgoing, errors) {
38
+ createRequestTask(request, outgoing) {
39
+ return new power_tasks_1.Task(async () => {
40
+ const response = new response_host_js_1.ResponseHost({ http: outgoing });
41
+ const context = new request_context_host_js_1.RequestContextHost('http', this.platform, this.api, request, response);
42
+ return this.executeRequest(context);
43
+ }, {
44
+ id: request.contentId,
45
+ exclusive: request.crud !== 'read'
46
+ });
47
+ }
48
+ async executeRequest(context) {
49
+ const { request, response } = context;
50
+ await super.executeRequest(context)
51
+ .catch(e => {
52
+ response.errors = response.errors || [];
53
+ response.errors.push(e);
54
+ });
55
+ const outgoing = response.switchToHttp();
56
+ if (response.errors?.length) {
57
+ const errors = response.errors.map(e => (0, common_1.wrapException)(e));
58
+ await this.handleError(request.switchToHttp(), outgoing, errors);
59
+ return;
60
+ }
61
+ if (request.crud === 'create') {
62
+ if (!response.value)
63
+ throw new common_1.InternalServerError();
64
+ // todo validate
65
+ outgoing.statusCode = 201;
66
+ }
67
+ if (request.resource instanceof common_1.Collection &&
68
+ request.crud === 'read' && request.many && request.args.count >= 0) {
69
+ outgoing.setHeader(common_1.HttpHeaderCodes.X_Total_Count, String(response.count));
70
+ }
71
+ outgoing.statusCode = outgoing.statusCode || common_1.HttpStatusCodes.OK;
72
+ outgoing.setHeader(common_1.HttpHeaderCodes.Cache_Control, 'no-cache');
73
+ outgoing.setHeader(common_1.HttpHeaderCodes.Pragma, 'no-cache');
74
+ outgoing.setHeader(common_1.HttpHeaderCodes.Expires, '-1');
75
+ outgoing.setHeader(common_1.HttpHeaderCodes.X_Opra_Version, common_1.OpraSchema.SpecVersion);
76
+ // Expose headers if cors enabled
77
+ if (outgoing.getHeader(common_1.HttpHeaderCodes.Access_Control_Allow_Origin)) {
78
+ // Expose X-Total-Count header
79
+ outgoing.appendHeader(common_1.HttpHeaderCodes.Access_Control_Expose_Headers, [common_1.HttpHeaderCodes.X_Total_Count]);
80
+ // Expose X-Opra-* headers
81
+ outgoing.appendHeader(common_1.HttpHeaderCodes.Access_Control_Expose_Headers, Object.values(common_1.HttpHeaderCodes)
82
+ .filter(k => k.toLowerCase().startsWith('x-opra-')));
83
+ }
84
+ if (response.value) {
85
+ if (typeof response.value === 'object') {
86
+ if ((0, common_1.isReadable)(response.value) || Buffer.isBuffer(response.value))
87
+ outgoing.send(response.value);
88
+ else {
89
+ const body = this.i18n.deep(response.value);
90
+ outgoing.setHeader(common_1.HttpHeaderCodes.Content_Type, 'application/json; charset=utf-8');
91
+ outgoing.send(JSON.stringify(body));
92
+ }
93
+ }
94
+ else
95
+ outgoing.send(JSON.stringify(response.value));
96
+ }
97
+ outgoing.end();
98
+ }
99
+ async handleError(incoming, outgoing, errors) {
60
100
  errors.forEach(e => {
61
101
  this.log((e instanceof common_1.OpraException) ? 'error' : 'fatal', incoming, e); // todo. implement a better logger
62
102
  });
@@ -69,20 +109,20 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
69
109
  return b.status - a.status;
70
110
  return i;
71
111
  });
72
- if (!status || status < common_1.HttpStatusCodes.BAD_REQUEST) {
112
+ if (!status || status < Number(common_1.HttpStatusCodes.BAD_REQUEST)) {
73
113
  status = errors[0].status;
74
- if (status < common_1.HttpStatusCodes.BAD_REQUEST)
114
+ if (status < Number(common_1.HttpStatusCodes.BAD_REQUEST))
75
115
  status = common_1.HttpStatusCodes.INTERNAL_SERVER_ERROR;
76
116
  }
77
117
  const body = this.i18n.deep({
78
118
  errors: errors.map(e => e.issue)
79
119
  });
80
- outgoing.set(common_1.HttpHeaderCodes.Content_Type, 'application/json; charset=utf-8');
81
- outgoing.set(common_1.HttpHeaderCodes.Cache_Control, 'no-cache');
82
- outgoing.set(common_1.HttpHeaderCodes.Pragma, 'no-cache');
83
- outgoing.set(common_1.HttpHeaderCodes.Expires, '-1');
84
- outgoing.set(common_1.HttpHeaderCodes.X_Opra_Version, common_1.OpraSchema.SpecVersion);
85
- outgoing.status(status);
120
+ outgoing.statusCode = status;
121
+ outgoing.setHeader(common_1.HttpHeaderCodes.Content_Type, 'application/json; charset=utf-8');
122
+ outgoing.setHeader(common_1.HttpHeaderCodes.Cache_Control, 'no-cache');
123
+ outgoing.setHeader(common_1.HttpHeaderCodes.Pragma, 'no-cache');
124
+ outgoing.setHeader(common_1.HttpHeaderCodes.Expires, '-1');
125
+ outgoing.setHeader(common_1.HttpHeaderCodes.X_Opra_Version, common_1.OpraSchema.SpecVersion);
86
126
  outgoing.send(JSON.stringify(body));
87
127
  outgoing.end();
88
128
  }
@@ -94,403 +134,5 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
94
134
  return;
95
135
  logFn.apply(this.logger, [String(message), ...optionalParams]);
96
136
  }
97
- async executeRequest(context) {
98
- await super.executeRequest(context);
99
- const { request } = context;
100
- const response = context.response;
101
- const { crud } = request;
102
- const httpResponse = response.switchToHttp();
103
- if (request.resource instanceof common_1.Singleton || request.resource instanceof common_1.Collection) {
104
- httpResponse.set(common_1.HttpHeaderCodes.X_Opra_Data_Type, request.resource.type.name);
105
- httpResponse.set(common_1.HttpHeaderCodes.X_Opra_Operation, request.operation);
106
- }
107
- if (crud === 'create') {
108
- if (!response.value)
109
- throw new common_1.InternalServerError();
110
- // todo validate
111
- httpResponse.status(201);
112
- }
113
- }
114
- /**
115
- *
116
- * @param incoming
117
- * @protected
118
- */
119
- async parseRequest(incoming) {
120
- try {
121
- const url = new common_1.OpraURL();
122
- url.searchParams.define({
123
- '$search': { codec: 'string' },
124
- '$pick': { codec: 'string', array: 'strict' },
125
- '$omit': { codec: 'string', array: 'strict' },
126
- '$include': { codec: 'string', array: 'strict' },
127
- '$sort': { codec: 'string', array: 'strict' },
128
- '$filter': { codec: 'filter' },
129
- '$limit': { codec: 'number' },
130
- '$skip': { codec: 'number' },
131
- '$distinct': { codec: 'boolean' },
132
- '$count': { codec: 'boolean' },
133
- });
134
- url.parse(incoming.url);
135
- // const {context, url, method, headers, body, contentId} = args;
136
- if (!url.path.size)
137
- throw new common_1.BadRequestError();
138
- const method = incoming.method;
139
- if (method !== 'GET' && url.path.size > 1)
140
- throw new common_1.BadRequestError();
141
- // const pathLen = url.path.size;
142
- // let pathIndex = 0;
143
- const params = url.searchParams;
144
- const p = url.path.get(0);
145
- const resource = this._internalDoc.getResource(p.resource);
146
- // let container: IResourceContainer | undefined;
147
- // while (resource && resource instanceof ContainerResourceInfo) {
148
- // container = resource;
149
- // p = url.path.get(++pathIndex);
150
- // resource = container.getResource(p.resource);
151
- // }
152
- // const headers = incoming.headers;
153
- /*
154
- * Collection
155
- */
156
- if (resource instanceof common_1.Collection) {
157
- switch (method) {
158
- case 'POST': {
159
- if (!p.key) {
160
- const pick = params.get('$pick');
161
- const omit = params.get('$omit');
162
- const include = params.get('$include');
163
- return new http_request_host_js_1.HttpRequestHost({
164
- kind: 'CollectionCreateRequest',
165
- resource,
166
- operation: 'create',
167
- crud: 'create',
168
- many: false,
169
- args: {
170
- data: incoming.body,
171
- pick: pick && resource.normalizeFieldPath(pick),
172
- omit: omit && resource.normalizeFieldPath(omit),
173
- include: include && resource.normalizeFieldPath(include)
174
- }
175
- }, incoming);
176
- }
177
- break;
178
- }
179
- case 'DELETE': {
180
- if (p.key) {
181
- return new http_request_host_js_1.HttpRequestHost({
182
- kind: 'CollectionDeleteRequest',
183
- resource,
184
- operation: 'delete',
185
- crud: 'delete',
186
- many: false,
187
- args: {
188
- key: resource.parseKeyValue(p.key)
189
- }
190
- }, incoming);
191
- }
192
- const filter = resource.normalizeFilter(params.get('$filter'));
193
- return new http_request_host_js_1.HttpRequestHost({
194
- kind: 'CollectionDeleteManyRequest',
195
- resource,
196
- operation: 'deleteMany',
197
- crud: 'delete',
198
- many: true,
199
- args: {
200
- filter
201
- }
202
- }, incoming);
203
- }
204
- case 'GET': {
205
- const pick = params.get('$pick');
206
- const omit = params.get('$omit');
207
- const include = params.get('$include');
208
- if (p.key) {
209
- return new http_request_host_js_1.HttpRequestHost({
210
- kind: 'CollectionGetRequest',
211
- resource,
212
- operation: 'get',
213
- crud: 'read',
214
- many: false,
215
- args: {
216
- key: resource.parseKeyValue(p.key),
217
- pick: pick && resource.normalizeFieldPath(pick),
218
- omit: omit && resource.normalizeFieldPath(omit),
219
- include: include && resource.normalizeFieldPath(include)
220
- }
221
- }, incoming);
222
- }
223
- const filter = resource.normalizeFilter(params.get('$filter'));
224
- const sort = params.get('$sort');
225
- return new http_request_host_js_1.HttpRequestHost({
226
- kind: 'CollectionFindManyRequest',
227
- resource,
228
- operation: 'findMany',
229
- crud: 'read',
230
- many: true,
231
- args: {
232
- pick: pick && resource.normalizeFieldPath(pick),
233
- omit: omit && resource.normalizeFieldPath(omit),
234
- include: include && resource.normalizeFieldPath(include),
235
- sort: sort && resource.normalizeSortFields(sort),
236
- filter,
237
- limit: params.get('$limit'),
238
- skip: params.get('$skip'),
239
- distinct: params.get('$distinct'),
240
- count: params.get('$count'),
241
- }
242
- }, incoming);
243
- }
244
- case 'PATCH': {
245
- if (p.key) {
246
- const pick = params.get('$pick');
247
- const omit = params.get('$omit');
248
- const include = params.get('$include');
249
- return new http_request_host_js_1.HttpRequestHost({
250
- kind: 'CollectionUpdateRequest',
251
- resource,
252
- operation: 'update',
253
- crud: 'update',
254
- many: false,
255
- args: {
256
- key: resource.parseKeyValue(p.key),
257
- data: incoming.body,
258
- pick: pick && resource.normalizeFieldPath(pick),
259
- omit: omit && resource.normalizeFieldPath(omit),
260
- include: include && resource.normalizeFieldPath(include),
261
- }
262
- }, incoming);
263
- }
264
- const filter = resource.normalizeFilter(params.get('$filter'));
265
- return new http_request_host_js_1.HttpRequestHost({
266
- kind: 'CollectionUpdateManyRequest',
267
- resource,
268
- operation: 'updateMany',
269
- crud: 'update',
270
- many: true,
271
- args: {
272
- data: incoming.body,
273
- filter,
274
- }
275
- }, incoming);
276
- }
277
- default:
278
- throw new common_1.BadRequestError();
279
- }
280
- }
281
- else
282
- /*
283
- * Singleton
284
- */
285
- if (resource instanceof common_1.Singleton) {
286
- if (p.key)
287
- throw new common_1.BadRequestError();
288
- switch (method) {
289
- case 'POST': {
290
- const pick = params.get('$pick');
291
- const omit = params.get('$omit');
292
- const include = params.get('$include');
293
- return new http_request_host_js_1.HttpRequestHost({
294
- kind: 'SingletonCreateRequest',
295
- resource,
296
- operation: 'create',
297
- crud: 'create',
298
- many: false,
299
- args: {
300
- data: incoming.body,
301
- pick: pick && resource.normalizeFieldPath(pick),
302
- omit: omit && resource.normalizeFieldPath(omit),
303
- include: include && resource.normalizeFieldPath(include),
304
- }
305
- }, incoming);
306
- }
307
- case 'DELETE': {
308
- return new http_request_host_js_1.HttpRequestHost({
309
- kind: 'SingletonDeleteRequest',
310
- resource,
311
- operation: 'delete',
312
- crud: 'delete',
313
- many: false,
314
- args: {}
315
- }, incoming);
316
- }
317
- case 'GET': {
318
- const pick = params.get('$pick');
319
- const omit = params.get('$omit');
320
- const include = params.get('$include');
321
- return new http_request_host_js_1.HttpRequestHost({
322
- kind: 'SingletonGetRequest',
323
- resource,
324
- operation: 'get',
325
- crud: 'read',
326
- many: false,
327
- args: {
328
- pick: pick && resource.normalizeFieldPath(pick),
329
- omit: omit && resource.normalizeFieldPath(omit),
330
- include: include && resource.normalizeFieldPath(include),
331
- }
332
- }, incoming);
333
- }
334
- case 'PATCH': {
335
- const pick = params.get('$pick');
336
- const omit = params.get('$omit');
337
- const include = params.get('$include');
338
- return new http_request_host_js_1.HttpRequestHost({
339
- kind: 'SingletonUpdateRequest',
340
- resource,
341
- operation: 'update',
342
- crud: 'update',
343
- many: false,
344
- args: {
345
- data: incoming.body,
346
- pick: pick && resource.normalizeFieldPath(pick),
347
- omit: omit && resource.normalizeFieldPath(omit),
348
- include: include && resource.normalizeFieldPath(include),
349
- }
350
- }, incoming);
351
- }
352
- default:
353
- throw new common_1.BadRequestError();
354
- }
355
- }
356
- else
357
- throw new common_1.InternalServerError();
358
- // if (query instanceof SingletonGetQuery || query instanceof CollectionGetQuery || query instanceof ElementReadQuery) {
359
- // // Move through properties
360
- // let parentType: DataType;
361
- // const curPath: string[] = [];
362
- // let parent: SingletonGetQuery | CollectionGetQuery | ElementReadQuery = query;
363
- // while (++pathIndex < pathLen) {
364
- // p = url.path.get(pathIndex);
365
- // parentType = parent.type;
366
- // if (parent.type instanceof UnionType) {
367
- // if (parent.type.name === 'any')
368
- // parentType = this.document.getComplexType('object');
369
- // else
370
- // throw new TypeError(`"${resource.name}.${curPath.join()}" is a UnionType and needs type casting.`);
371
- // }
372
- // if (!(parentType instanceof ComplexType))
373
- // throw new TypeError(`"${resource.name}.${curPath.join()}" is not a ComplexType and has no fields.`);
374
- // curPath.push(p.resource);
375
- // parent.child = new ElementReadQuery(parent, p.resource, {castingType: parentType});
376
- // parent = parent.child;
377
- // }
378
- // }
379
- throw new common_1.MethodNotAllowedError({
380
- message: `Method "${method}" is not allowed by target endpoint`
381
- });
382
- }
383
- catch (e) {
384
- if (e instanceof common_1.OpraException)
385
- throw e;
386
- throw new common_1.BadRequestError(e);
387
- }
388
- }
389
- // async parseMultiPart(
390
- // context: TExecutionContext,
391
- // url: OpraURL,
392
- // headers: IncomingHttpHeaders,
393
- // input: Readable,
394
- // boundary: string
395
- // ): Promise<BatchRequestContext> {
396
- // return await new Promise((resolve, reject) => {
397
- // let _resolved = false;
398
- // const dicer = new Dicer({boundary});
399
- // const doReject = (e) => {
400
- // if (_resolved) return;
401
- // _resolved = true;
402
- // reject(e);
403
- // taskQueue.clearQueue();
404
- // dicer.destroy();
405
- // }
406
- // const taskQueue = new TaskQueue({concurrency: 1});
407
- // taskQueue.on('error', doReject);
408
- //
409
- // const queries: SingleRequestContext[] = [];
410
- // let partCounter = 0;
411
- // dicer.on('error', doReject);
412
- // dicer.on('part', part => {
413
- // const partIndex = partCounter++;
414
- // let header: any;
415
- // const chunks: Buffer[] = [];
416
- // part.on('error', doReject);
417
- // part.on('header', (_header) => header = normalizeHeaders(_header));
418
- // part.on('data', (chunk: Buffer) => chunks.push(chunk));
419
- // part.on('end', () => {
420
- // if (_resolved || !(header || chunks.length))
421
- // return;
422
- // const ct = header['content-type'];
423
- // if (ct === 'application/http') {
424
- // taskQueue.enqueue(async () => {
425
- // const data = Buffer.concat(chunks);
426
- // if (!(data && data.length))
427
- // return;
428
- // const r = HttpRequest.parse(data);
429
- // await callMiddlewares(r, [jsonBodyParser]);
430
- // const subUrl = new OpraURL(r.url);
431
- // const contentId = header && header['content-id'];
432
- // queries.push(this.parseSingleQuery({
433
- // context,
434
- // url: subUrl,
435
- // method: r.method,
436
- // headers: r.headers,
437
- // body: r.body,
438
- // contentId
439
- // }));
440
- // });
441
- // } else doReject(new BadRequestError({
442
- // message: 'Unaccepted "content-type" header in multipart data',
443
- // details: {
444
- // position: `${boundary}[${partIndex}]`
445
- // }
446
- // }))
447
- // });
448
- // });
449
- // dicer.on('finish', () => {
450
- // taskQueue.enqueue(() => {
451
- // if (_resolved) return;
452
- // _resolved = true;
453
- // const batch = new BatchRequestContext({
454
- // service: this.document,
455
- // context,
456
- // headers,
457
- // queries,
458
- // params: url.searchParams,
459
- // continueOnError: false
460
- // });
461
- // resolve(batch);
462
- // });
463
- // });
464
- // input.pipe(dicer);
465
- // });
466
- // }
467
- async sendResponse(context) {
468
- const { request, response } = context;
469
- const outgoing = response.switchToHttp();
470
- const errors = response.errors?.map(e => (0, common_1.wrapException)(e));
471
- if (errors && errors.length) {
472
- await this.errorHandler(request.switchToHttp(), outgoing, errors);
473
- return;
474
- }
475
- outgoing.set(common_1.HttpHeaderCodes.Cache_Control, 'no-cache');
476
- outgoing.set(common_1.HttpHeaderCodes.Pragma, 'no-cache');
477
- outgoing.set(common_1.HttpHeaderCodes.Expires, '-1');
478
- outgoing.set(common_1.HttpHeaderCodes.X_Opra_Version, common_1.OpraSchema.SpecVersion);
479
- outgoing.status(outgoing.statusCode || common_1.HttpStatusCodes.OK);
480
- if (response.value) {
481
- if (typeof response.value === 'object') {
482
- if ((0, common_1.isReadable)(response.value) || Buffer.isBuffer(response.value))
483
- outgoing.send(response.value);
484
- else {
485
- const body = this.i18n.deep(response.value);
486
- outgoing.set(common_1.HttpHeaderCodes.Content_Type, 'application/json; charset=utf-8');
487
- outgoing.send(JSON.stringify(body));
488
- }
489
- }
490
- else
491
- outgoing.send(JSON.stringify(response.value));
492
- }
493
- outgoing.end();
494
- }
495
137
  }
496
138
  exports.OpraHttpAdapter = OpraHttpAdapter;