@opra/core 1.0.0-alpha.29 → 1.0.0-alpha.30

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.
@@ -72,7 +72,7 @@ class HttpContext extends execution_context_js_1.ExecutionContext {
72
72
  this._body = [...parts];
73
73
  return this._body;
74
74
  }
75
- this._body = await this.request.readBody({ limit: operation.requestBody?.maxContentSize });
75
+ this._body = await this.request.readBody({ limit: operation?.requestBody?.maxContentSize });
76
76
  if (this._body != null) {
77
77
  // Convert Buffer to string if media is text
78
78
  if (Buffer.isBuffer(this._body) && request.is(['json', 'xml', 'txt', 'text'])) {
@@ -89,7 +89,7 @@ class HttpContext extends execution_context_js_1.ExecutionContext {
89
89
  if (!decode) {
90
90
  decode =
91
91
  mediaType.type?.generateCodec('decode', {
92
- partial: operation.requestBody?.partial,
92
+ partial: operation?.requestBody?.partial,
93
93
  projection: '*',
94
94
  ignoreReadonlyFields: true,
95
95
  }) || valgen_1.vg.isAny();
@@ -94,7 +94,7 @@ class HttpHandler {
94
94
  async parseRequest(context) {
95
95
  await this._parseParameters(context);
96
96
  await this._parseContentType(context);
97
- if (context.operation.requestBody?.immediateFetch)
97
+ if (context.operation?.requestBody?.immediateFetch)
98
98
  await context.getBody();
99
99
  /** Set default status code as the first status code between 200 and 299 */
100
100
  if (context.operation) {
@@ -114,6 +114,8 @@ class HttpHandler {
114
114
  */
115
115
  async _parseParameters(context) {
116
116
  const { operation, request } = context;
117
+ if (!operation)
118
+ return;
117
119
  let key = '';
118
120
  try {
119
121
  const onFail = (issue) => {
@@ -241,6 +243,8 @@ class HttpHandler {
241
243
  */
242
244
  async _parseContentType(context) {
243
245
  const { request, operation } = context;
246
+ if (!operation)
247
+ return;
244
248
  if (operation.requestBody?.content.length) {
245
249
  let mediaType;
246
250
  let contentType = request.header('content-type');
@@ -291,7 +295,10 @@ class HttpHandler {
291
295
  const operationResultType = document.node.getDataType(common_1.OperationResult);
292
296
  let operationResultEncoder = this[constants_1.kAssetCache].get(operationResultType, 'encode');
293
297
  if (!operationResultEncoder) {
294
- operationResultEncoder = operationResultType.generateCodec('encode', { ignoreWriteonlyFields: true });
298
+ operationResultEncoder = operationResultType.generateCodec('encode', {
299
+ ignoreWriteonlyFields: true,
300
+ ignoreHiddenFields: true,
301
+ });
295
302
  this[constants_1.kAssetCache].set(operationResultType, 'encode', operationResultEncoder);
296
303
  }
297
304
  /** Validate response */
@@ -302,8 +309,9 @@ class HttpHandler {
302
309
  if (!encode) {
303
310
  encode = operationResponse.type.generateCodec('encode', {
304
311
  partial: operationResponse.partial,
305
- projection: '*',
312
+ projection: responseArgs.projection || '*',
306
313
  ignoreWriteonlyFields: true,
314
+ ignoreHiddenFields: true,
307
315
  onFail: issue => `Response body validation failed: ` + issue.message,
308
316
  });
309
317
  if (operationResponse) {
@@ -475,7 +483,7 @@ class HttpHandler {
475
483
  let responseArgs = this[constants_1.kAssetCache].get(response, cacheKey);
476
484
  if (!responseArgs) {
477
485
  responseArgs = { statusCode, contentType };
478
- if (operation.responses.length) {
486
+ if (operation?.responses.length) {
479
487
  /** Filter available HttpOperationResponse instances according to status code. */
480
488
  const filteredResponses = operation.responses.filter(r => r.statusCode.find(sc => sc.start <= statusCode && sc.end >= statusCode));
481
489
  /** Throw InternalServerError if controller returns non-configured status code */
@@ -520,6 +528,10 @@ class HttpHandler {
520
528
  }
521
529
  if (!hasBody)
522
530
  delete responseArgs.contentType;
531
+ if (operation?.composition?.startsWith('Entity.')) {
532
+ if (context.queryParams.projection)
533
+ responseArgs.projection = context.queryParams.projection;
534
+ }
523
535
  this[constants_1.kAssetCache].set(response, cacheKey, { ...responseArgs });
524
536
  }
525
537
  /** Fix response value according to composition */
@@ -102,7 +102,7 @@ class MultipartReader extends events_1.EventEmitter {
102
102
  if (!field)
103
103
  throw new common_1.BadRequestError(`Unknown multipart field (${item.field})`);
104
104
  if (item.kind === 'field') {
105
- const decode = field.generateCodec('decode');
105
+ const decode = field.generateCodec('decode', { ignoreReadonlyFields: true, projection: '*' });
106
106
  item.value = decode(item.value, {
107
107
  onFail: issue => `Multipart field (${item.field}) validation failed: ` + issue.message,
108
108
  });
@@ -68,7 +68,7 @@ export class HttpContext extends ExecutionContext {
68
68
  this._body = [...parts];
69
69
  return this._body;
70
70
  }
71
- this._body = await this.request.readBody({ limit: operation.requestBody?.maxContentSize });
71
+ this._body = await this.request.readBody({ limit: operation?.requestBody?.maxContentSize });
72
72
  if (this._body != null) {
73
73
  // Convert Buffer to string if media is text
74
74
  if (Buffer.isBuffer(this._body) && request.is(['json', 'xml', 'txt', 'text'])) {
@@ -85,7 +85,7 @@ export class HttpContext extends ExecutionContext {
85
85
  if (!decode) {
86
86
  decode =
87
87
  mediaType.type?.generateCodec('decode', {
88
- partial: operation.requestBody?.partial,
88
+ partial: operation?.requestBody?.partial,
89
89
  projection: '*',
90
90
  ignoreReadonlyFields: true,
91
91
  }) || vg.isAny();
@@ -90,7 +90,7 @@ export class HttpHandler {
90
90
  async parseRequest(context) {
91
91
  await this._parseParameters(context);
92
92
  await this._parseContentType(context);
93
- if (context.operation.requestBody?.immediateFetch)
93
+ if (context.operation?.requestBody?.immediateFetch)
94
94
  await context.getBody();
95
95
  /** Set default status code as the first status code between 200 and 299 */
96
96
  if (context.operation) {
@@ -110,6 +110,8 @@ export class HttpHandler {
110
110
  */
111
111
  async _parseParameters(context) {
112
112
  const { operation, request } = context;
113
+ if (!operation)
114
+ return;
113
115
  let key = '';
114
116
  try {
115
117
  const onFail = (issue) => {
@@ -237,6 +239,8 @@ export class HttpHandler {
237
239
  */
238
240
  async _parseContentType(context) {
239
241
  const { request, operation } = context;
242
+ if (!operation)
243
+ return;
240
244
  if (operation.requestBody?.content.length) {
241
245
  let mediaType;
242
246
  let contentType = request.header('content-type');
@@ -287,7 +291,10 @@ export class HttpHandler {
287
291
  const operationResultType = document.node.getDataType(OperationResult);
288
292
  let operationResultEncoder = this[kAssetCache].get(operationResultType, 'encode');
289
293
  if (!operationResultEncoder) {
290
- operationResultEncoder = operationResultType.generateCodec('encode', { ignoreWriteonlyFields: true });
294
+ operationResultEncoder = operationResultType.generateCodec('encode', {
295
+ ignoreWriteonlyFields: true,
296
+ ignoreHiddenFields: true,
297
+ });
291
298
  this[kAssetCache].set(operationResultType, 'encode', operationResultEncoder);
292
299
  }
293
300
  /** Validate response */
@@ -298,8 +305,9 @@ export class HttpHandler {
298
305
  if (!encode) {
299
306
  encode = operationResponse.type.generateCodec('encode', {
300
307
  partial: operationResponse.partial,
301
- projection: '*',
308
+ projection: responseArgs.projection || '*',
302
309
  ignoreWriteonlyFields: true,
310
+ ignoreHiddenFields: true,
303
311
  onFail: issue => `Response body validation failed: ` + issue.message,
304
312
  });
305
313
  if (operationResponse) {
@@ -471,7 +479,7 @@ export class HttpHandler {
471
479
  let responseArgs = this[kAssetCache].get(response, cacheKey);
472
480
  if (!responseArgs) {
473
481
  responseArgs = { statusCode, contentType };
474
- if (operation.responses.length) {
482
+ if (operation?.responses.length) {
475
483
  /** Filter available HttpOperationResponse instances according to status code. */
476
484
  const filteredResponses = operation.responses.filter(r => r.statusCode.find(sc => sc.start <= statusCode && sc.end >= statusCode));
477
485
  /** Throw InternalServerError if controller returns non-configured status code */
@@ -516,6 +524,10 @@ export class HttpHandler {
516
524
  }
517
525
  if (!hasBody)
518
526
  delete responseArgs.contentType;
527
+ if (operation?.composition?.startsWith('Entity.')) {
528
+ if (context.queryParams.projection)
529
+ responseArgs.projection = context.queryParams.projection;
530
+ }
519
531
  this[kAssetCache].set(response, cacheKey, { ...responseArgs });
520
532
  }
521
533
  /** Fix response value according to composition */
@@ -98,7 +98,7 @@ export class MultipartReader extends EventEmitter {
98
98
  if (!field)
99
99
  throw new BadRequestError(`Unknown multipart field (${item.field})`);
100
100
  if (item.kind === 'field') {
101
- const decode = field.generateCodec('decode');
101
+ const decode = field.generateCodec('decode', { ignoreReadonlyFields: true, projection: '*' });
102
102
  item.value = decode(item.value, {
103
103
  onFail: issue => `Multipart field (${item.field}) validation failed: ` + issue.message,
104
104
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/core",
3
- "version": "1.0.0-alpha.29",
3
+ "version": "1.0.0-alpha.30",
4
4
  "description": "Opra schema package",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -33,7 +33,7 @@
33
33
  "dependencies": {
34
34
  "@browsery/http-parser": "^0.5.8",
35
35
  "@browsery/type-is": "^1.6.18-r2",
36
- "@opra/common": "^1.0.0-alpha.29",
36
+ "@opra/common": "^1.0.0-alpha.30",
37
37
  "accepts": "^1.3.8",
38
38
  "base64-stream": "^1.0.0",
39
39
  "busboy": "^1.6.0",
@@ -49,12 +49,13 @@
49
49
  "mime-types": "^2.1.35",
50
50
  "power-tasks": "^1.7.7",
51
51
  "putil-isplainobject": "^1.1.5",
52
- "putil-merge": "^3.12.1",
52
+ "putil-merge": "^3.13.0",
53
53
  "putil-varhelpers": "^1.6.5",
54
54
  "range-parser": "^1.2.1",
55
55
  "raw-body": "^3.0.0",
56
56
  "reflect-metadata": "^0.2.2",
57
57
  "strict-typed-events": "^2.4.0",
58
+ "tslib": "^2.6.3",
58
59
  "vary": "^1.1.2"
59
60
  },
60
61
  "optionalDependencies": {
@@ -26,9 +26,9 @@ export declare class HttpContext extends ExecutionContext {
26
26
  protected _multipartReader?: MultipartReader;
27
27
  readonly protocol: OpraSchema.Protocol;
28
28
  readonly adapter: HttpAdapter;
29
- readonly controller: HttpController;
29
+ readonly controller?: HttpController;
30
30
  readonly controllerInstance?: any;
31
- readonly operation: HttpOperation;
31
+ readonly operation?: HttpOperation;
32
32
  readonly operationHandler?: Function;
33
33
  readonly request: HttpIncoming;
34
34
  readonly response: HttpOutgoing;
@@ -15,6 +15,7 @@ export declare namespace HttpHandler {
15
15
  contentType?: string;
16
16
  operationResponse?: HttpOperationResponse;
17
17
  body?: any;
18
+ projection?: string[] | '*';
18
19
  }
19
20
  }
20
21
  /**
@@ -15,8 +15,8 @@ declare global {
15
15
  * @class NodeOutgoingMessageHost
16
16
  */
17
17
  export declare class NodeOutgoingMessageHost extends Duplex implements NodeOutgoingMessage {
18
- protected [kOutHeaders]: Record<string, any>;
19
- protected [kOutTrailers]: Record<string, any>;
18
+ protected [kOutHeaders]?: Record<string, any>;
19
+ protected [kOutTrailers]?: Record<string, any>;
20
20
  protected _headersSent: boolean;
21
21
  protected _httpVersionMajor?: number;
22
22
  protected _httpVersionMinor?: number;
@@ -18,7 +18,7 @@ type Callback = (...args: any[]) => any;
18
18
  export declare class BodyReader extends EventEmitter {
19
19
  readonly req: HttpIncoming;
20
20
  limit?: number;
21
- protected _stream: nodeStream.Readable;
21
+ protected _stream?: nodeStream.Readable;
22
22
  protected _buffer?: string | Buffer[];
23
23
  protected _completed?: boolean | undefined;
24
24
  protected _receivedSize: number;