@trayio/cdk-runtime 3.0.0 → 3.1.1-unstable

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.
@@ -1,14 +1,17 @@
1
+ import * as O from 'fp-ts/Option';
1
2
  import { OperationHandlerAuth, OperationHandlerContext, OperationHandlerResult } from '@trayio/cdk-dsl/connector/operation/OperationHandler';
2
3
  import { HttpOperationHandler } from '@trayio/cdk-dsl/connector/operation/HttpOperationHandler';
3
4
  import { HttpClient } from '@trayio/commons/http/HttpClient';
4
5
  import { FileStorage } from '@trayio/commons/file/File';
6
+ import { HttpGlobalHandler } from '@trayio/cdk-dsl/connector/operation/GlobalHandler';
5
7
  import { OperationExecution } from './OperationExecution';
6
8
  export declare class HttpOperationExecution<AUTH extends OperationHandlerAuth<unknown, unknown>, IN, OUT> implements OperationExecution<AUTH, IN, OUT> {
7
9
  private jsonSerialization;
8
10
  private httpClient;
9
11
  private handler;
12
+ private globalHandler;
10
13
  private fileStorage;
11
- constructor(httpClient: HttpClient, fileStorage: FileStorage, handler: HttpOperationHandler<AUTH, IN, OUT>);
14
+ constructor(httpClient: HttpClient, fileStorage: FileStorage, handler: HttpOperationHandler<AUTH, IN, OUT>, globalHandler: O.Option<HttpGlobalHandler<AUTH>>);
12
15
  execute(ctx: OperationHandlerContext<AUTH>, input: IN): Promise<OperationHandlerResult<OUT>>;
13
16
  private operationRequestToHttpRequest;
14
17
  private serializeAsJson;
@@ -1 +1 @@
1
- {"version":3,"file":"HttpOperationExecution.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/HttpOperationExecution.ts"],"names":[],"mappings":"AASA,OAAO,EACN,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EAGtB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EAGN,oBAAoB,EAKpB,MAAM,0DAA0D,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAW7D,OAAO,EAAQ,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAO1D,qBAAa,sBAAsB,CAClC,IAAI,SAAS,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,EACnD,EAAE,EACF,GAAG,CACF,YAAW,kBAAkB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC;IAE7C,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,WAAW,CAAc;gBAGhC,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,oBAAoB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC;IAQvC,OAAO,CACZ,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,EAClC,KAAK,EAAE,EAAE,GACP,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAiDvC,OAAO,CAAC,6BAA6B;IAiCrC,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,oBAAoB;IAyD5B,OAAO,CAAC,eAAe;IA0BvB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,oBAAoB;IAc5B,OAAO,CAAC,aAAa;IAiCrB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,eAAe;IA2CvB,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,qBAAqB;CAwC7B"}
1
+ {"version":3,"file":"HttpOperationExecution.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/HttpOperationExecution.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAKlC,OAAO,EACN,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EAGtB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EAGN,oBAAoB,EAKpB,MAAM,0DAA0D,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAW7D,OAAO,EAAQ,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAO1D,qBAAa,sBAAsB,CAClC,IAAI,SAAS,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,EACnD,EAAE,EACF,GAAG,CACF,YAAW,kBAAkB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC;IAE7C,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,WAAW,CAAc;gBAGhC,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,oBAAoB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,EAC5C,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAS3C,OAAO,CACZ,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,EAClC,KAAK,EAAE,EAAE,GACP,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAiEvC,OAAO,CAAC,6BAA6B;IAiCrC,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,oBAAoB;IAuD5B,OAAO,CAAC,eAAe;IA0BvB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,oBAAoB;IAc5B,OAAO,CAAC,aAAa;IAiCrB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,eAAe;IA2CvB,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,qBAAqB;CAwC7B"}
@@ -48,15 +48,16 @@ const BufferExtensions_1 = require("@trayio/commons/buffer/BufferExtensions");
48
48
  const mime = require('mime');
49
49
  const { AWS_LAMBDA_FUNCTION_MEMORY_SIZE, CONNECTOR_MAX_ALLOCATED_RAM_MB } = process.env;
50
50
  class HttpOperationExecution {
51
- constructor(httpClient, fileStorage, handler) {
51
+ constructor(httpClient, fileStorage, handler, globalHandler) {
52
52
  this.jsonSerialization = new JsonSerialization_1.JsonSerialization();
53
53
  this.httpClient = httpClient;
54
54
  this.fileStorage = fileStorage;
55
55
  this.handler = handler;
56
+ this.globalHandler = globalHandler;
56
57
  }
57
58
  execute(ctx, input) {
58
59
  return __awaiter(this, void 0, void 0, function* () {
59
- const operationRequest = this.handler.requestHandler(ctx, input, this.handler.request);
60
+ const operationRequest = (0, function_1.pipe)(this.globalHandler, O.match(() => this.handler.requestHandler(ctx, input, this.handler.request), (globalHandler) => (0, function_1.pipe)(globalHandler.beforeRequest, O.match(() => this.handler.requestHandler(ctx, input, this.handler.request), (beforeRequest) => beforeRequest(this.handler.requestHandler, ctx, input, this.handler.request)))));
60
61
  const httpRequestE = yield this.operationRequestToHttpRequest(operationRequest)();
61
62
  if (E.isLeft(httpRequestE)) {
62
63
  return OperationHandler_1.OperationHandlerResult.failure(OperationHandler_1.OperationHandlerError.connectorError(httpRequestE.left.message));
@@ -106,9 +107,7 @@ class HttpOperationExecution {
106
107
  const fileStreamsFromReferencesTasks = Object.keys(body.files).map((fileKey) => {
107
108
  const fileRef = body.files[fileKey];
108
109
  return (0, function_1.pipe)(this.httpClient.execute(Http_1.HttpMethod.Get, fileRef.url, {
109
- headers: {
110
- [Http_1.HttpHeader.ContentType]: Http_1.HttpContentType.OctetStream,
111
- },
110
+ headers: {},
112
111
  pathParams: {},
113
112
  queryString: {},
114
113
  body: BufferExtensions_1.BufferExtensions.arrayBufferToReadable(new ArrayBuffer(0)),
@@ -140,7 +139,7 @@ class HttpOperationExecution {
140
139
  }
141
140
  serializeAsFile(operationRequest) {
142
141
  const downloadFilefromReference = this.httpClient.execute(Http_1.HttpMethod.Get, operationRequest.body.url, {
143
- headers: { [Http_1.HttpHeader.ContentType]: Http_1.HttpContentType.OctetStream },
142
+ headers: {},
144
143
  pathParams: {},
145
144
  queryString: {},
146
145
  body: BufferExtensions_1.BufferExtensions.arrayBufferToReadable(new ArrayBuffer(0)),
@@ -1,12 +1,14 @@
1
1
  import { OperationHandlerAuth } from '@trayio/cdk-dsl/connector/operation/OperationHandler';
2
2
  import { HttpOperationHandler } from '@trayio/cdk-dsl/connector/operation/HttpOperationHandler';
3
3
  import { HttpClient } from '@trayio/commons/http/HttpClient';
4
- import { FileStorage } from '@trayio/commons/dist/file/File';
4
+ import { FileStorage } from '@trayio/commons/file/File';
5
+ import { HttpGlobalHandler } from '@trayio/cdk-dsl/connector/operation/GlobalHandler';
6
+ import * as O from 'fp-ts/Option';
5
7
  import { OperationExecution } from './OperationExecution';
6
8
  export declare class HttpOperationExecutionFactory {
7
9
  private httpClient;
8
10
  private fileStorage;
9
11
  constructor(httpClient: HttpClient, fileStorage: FileStorage);
10
- executionFrom<AUTH extends OperationHandlerAuth<unknown, unknown>, IN, OUT>(handler: HttpOperationHandler<AUTH, IN, OUT>): OperationExecution<AUTH, IN, OUT>;
12
+ executionFrom<AUTH extends OperationHandlerAuth<unknown, unknown>, IN, OUT>(handler: HttpOperationHandler<AUTH, IN, OUT>, globalHandler: O.Option<HttpGlobalHandler<AUTH>>): OperationExecution<AUTH, IN, OUT>;
11
13
  }
12
14
  //# sourceMappingURL=HttpOperationExecutionFactory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HttpOperationExecutionFactory.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/HttpOperationExecutionFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AAC5F,OAAO,EAAE,oBAAoB,EAAE,MAAM,0DAA0D,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,qBAAa,6BAA6B;IAExC,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,WAAW;gBADX,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW;IAGjC,aAAa,CAAC,IAAI,SAAS,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EACzE,OAAO,EAAE,oBAAoB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,GAC1C,kBAAkB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC;CAOpC"}
1
+ {"version":3,"file":"HttpOperationExecutionFactory.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/HttpOperationExecutionFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AAC5F,OAAO,EAAE,oBAAoB,EAAE,MAAM,0DAA0D,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AACtF,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,qBAAa,6BAA6B;IAExC,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,WAAW;gBADX,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW;IAGjC,aAAa,CAAC,IAAI,SAAS,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EACzE,OAAO,EAAE,oBAAoB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,EAC5C,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,GAC9C,kBAAkB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC;CAQpC"}
@@ -7,8 +7,8 @@ class HttpOperationExecutionFactory {
7
7
  this.httpClient = httpClient;
8
8
  this.fileStorage = fileStorage;
9
9
  }
10
- executionFrom(handler) {
11
- return new HttpOperationExecution_1.HttpOperationExecution(this.httpClient, this.fileStorage, handler);
10
+ executionFrom(handler, globalHandler) {
11
+ return new HttpOperationExecution_1.HttpOperationExecution(this.httpClient, this.fileStorage, handler, globalHandler);
12
12
  }
13
13
  }
14
14
  exports.HttpOperationExecutionFactory = HttpOperationExecutionFactory;
@@ -1 +1 @@
1
- {"version":3,"file":"OperationExecutionFactory.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/OperationExecutionFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,gBAAgB,EAEhB,MAAM,2DAA2D,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AAGxF,qBAAa,yBAAyB;IACrC,OAAO,CAAC,mCAAmC,CAAsC;IACjF,OAAO,CAAC,6BAA6B,CAAgC;IACrE,OAAO,CAAC,kCAAkC,CAAqC;gBAG9E,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,EACxB,iCAAiC,EAAE,iCAAiC;IAYrE,aAAa,CAAC,IAAI,SAAS,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EACzE,OAAO,EAAE,gBAAgB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,GACtC,kBAAkB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC;IAYpC,OAAO,CAAC,2BAA2B;CAoBnC"}
1
+ {"version":3,"file":"OperationExecutionFactory.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/OperationExecutionFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AAGxF,qBAAa,yBAAyB;IACrC,OAAO,CAAC,mCAAmC,CAAsC;IACjF,OAAO,CAAC,6BAA6B,CAAgC;IACrE,OAAO,CAAC,kCAAkC,CAAqC;gBAG9E,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,EACxB,iCAAiC,EAAE,iCAAiC;IAYrE,aAAa,CAAC,IAAI,SAAS,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EACzE,OAAO,EAAE,gBAAgB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,GACtC,kBAAkB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC;IAYpC,OAAO,CAAC,2BAA2B;CAqBnC"}
@@ -13,16 +13,16 @@ class OperationExecutionFactory {
13
13
  new CompositeOperationExecutionFactory_1.CompositeOperationExecutionFactory(operationHandlerInvocationFactory);
14
14
  }
15
15
  executionFrom(handler) {
16
- const executionFromImplementation = this.executionFromImplementation(handler.implementation);
16
+ const executionFromImplementation = this.executionFromImplementation(handler);
17
17
  const execution = this.operationExecutionValidationFactory.decorateExecution(executionFromImplementation, handler.validation);
18
18
  return execution;
19
19
  }
20
- executionFromImplementation(implementation) {
21
- switch (implementation._tag) {
20
+ executionFromImplementation(handler) {
21
+ switch (handler.implementation._tag) {
22
22
  case 'HttpOperationHandler':
23
- return this.httpOperationExecutionFactory.executionFrom(implementation);
23
+ return this.httpOperationExecutionFactory.executionFrom(handler.implementation, handler.globalHandler);
24
24
  case 'CompositeOperationHandler':
25
- return this.compositeOperationExecutionFactory.executionFrom(implementation);
25
+ return this.compositeOperationExecutionFactory.executionFrom(handler.implementation);
26
26
  }
27
27
  }
28
28
  }
@@ -36,6 +36,7 @@ const ExpressHttpServer_1 = require("@trayio/express/http/ExpressHttpServer");
36
36
  const ExpressHttpController_1 = require("@trayio/express/http/ExpressHttpController");
37
37
  const NodeFsFileStorage_1 = require("@trayio/commons/file/NodeFsFileStorage");
38
38
  require("./OperationHandlerTestRunner");
39
+ const GlobalHandler_1 = require("@trayio/cdk-dsl/connector/operation/GlobalHandler");
39
40
  const fileStorage = new NodeFsFileStorage_1.NodeFsFileStorage('/tmp');
40
41
  class TestControllerHttp {
41
42
  constructor() {
@@ -185,6 +186,41 @@ describe('OperationExecutionGateway', () => {
185
186
  .finallyDoNothing())
186
187
  .nothingAfterAll());
187
188
  });
189
+ describe('add path parameter using global handler', () => {
190
+ const globalHandler = GlobalHandler_1.HttpGlobalHandler.create().withBeforeRequest((handler, ctx, input, request) => {
191
+ const newRequest = request.addPathParameter('id', input.id.toString());
192
+ return handler(ctx, input, newRequest);
193
+ });
194
+ const getProductOperationAsText = OperationHandlerSetup_1.OperationHandlerSetup.configureHandler((handler) => handler
195
+ .addInputValidation((inputValidation) => inputValidation
196
+ .condition((ctx, input) => input.id > 0)
197
+ .errorMessage(() => 'id must be bigger than zero'))
198
+ .withGlobalHandler(globalHandler)
199
+ .usingHttp((http) => http
200
+ .get('http://localhost:3000/posts/:id')
201
+ .handleRequest((ctx, input, request) => request.withoutBody())
202
+ .handleResponse((ctx, input, response) => response.parseWithBodyAsText((text) => OperationHandler_1.OperationHandlerResult.success({ textField: text })))));
203
+ OperationHandlerTest_1.OperationHandlerTestSetup.configureHandlerTest(getProductOperationAsText, (handlerTest) => handlerTest
204
+ .usingHandlerContext('test')
205
+ .nothingBeforeAll()
206
+ .testCase('should get a product as text', (testCase) => testCase
207
+ .usingHandlerContext('test')
208
+ .givenNothing()
209
+ .when(() => ({ id: 2 }))
210
+ .then(({ output }) => {
211
+ const outputValue = OperationHandler_1.OperationHandlerResult.getSuccessfulValueOrFail(output);
212
+ expect(outputValue.textField).toContain(`"id":2`);
213
+ })
214
+ .finallyDoNothing())
215
+ .testCase('should validate id', (testCase) => testCase
216
+ .givenNothing()
217
+ .when(() => ({ id: -1 }))
218
+ .then(({ output }) => {
219
+ expect(output.isFailure).toBe(true);
220
+ })
221
+ .finallyDoNothing())
222
+ .nothingAfterAll());
223
+ });
188
224
  describe('post a product as form url encoded', () => {
189
225
  const postProductOperation = OperationHandlerSetup_1.OperationHandlerSetup.configureHandler((handler) => handler.usingHttp((http) => http
190
226
  .post('http://localhost:3000/posts/create')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trayio/cdk-runtime",
3
- "version": "3.0.0",
3
+ "version": "3.1.1-unstable",
4
4
  "description": "A Runtime that executes connector operations defined using the CDK DSL",
5
5
  "exports": {
6
6
  "./*": "./dist/*.js"
@@ -14,10 +14,10 @@
14
14
  "node": ">=18.x"
15
15
  },
16
16
  "dependencies": {
17
- "@trayio/axios": "3.0.0",
18
- "@trayio/cdk-dsl": "3.0.0",
19
- "@trayio/express": "3.0.0",
20
- "@trayio/winston": "3.0.0",
17
+ "@trayio/axios": "3.1.1-unstable",
18
+ "@trayio/cdk-dsl": "3.1.1-unstable",
19
+ "@trayio/express": "3.1.1-unstable",
20
+ "@trayio/winston": "3.1.1-unstable",
21
21
  "mime": "3.0.0",
22
22
  "uuid": "9.0.0"
23
23
  },