@trayio/cdk-runtime 2.3.0 → 2.5.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.
@@ -1 +1 @@
1
- {"version":3,"file":"HttpOperationExecution.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/HttpOperationExecution.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EAEtB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EAEN,oBAAoB,EAKpB,MAAM,0DAA0D,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAQ7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,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;gBAGpD,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,oBAAoB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC;IAOvC,OAAO,CACZ,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,EAClC,KAAK,EAAE,EAAE,GACP,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAyCvC,OAAO,CAAC,6BAA6B;IA4BrC,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,oBAAoB;IAc5B,OAAO,CAAC,aAAa;IAiCrB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,gBAAgB;CAexB"}
1
+ {"version":3,"file":"HttpOperationExecution.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/HttpOperationExecution.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EAGtB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EAEN,oBAAoB,EAKpB,MAAM,0DAA0D,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAc7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,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;gBAGpD,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,oBAAoB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC;IAOvC,OAAO,CACZ,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,EAClC,KAAK,EAAE,EAAE,GACP,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAiDvC,OAAO,CAAC,6BAA6B;IA2BrC,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,oBAAoB;IAM5B,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;IAUvB,OAAO,CAAC,gBAAgB;CAexB"}
@@ -38,6 +38,7 @@ const HttpOperationHandler_1 = require("@trayio/cdk-dsl/connector/operation/Http
38
38
  const Http_1 = require("@trayio/commons/http/Http");
39
39
  const JsonSerialization_1 = require("@trayio/commons/serialization/JsonSerialization");
40
40
  const TE = __importStar(require("fp-ts/TaskEither"));
41
+ const E = __importStar(require("fp-ts/Either"));
41
42
  const O = __importStar(require("fp-ts/Option"));
42
43
  const function_1 = require("fp-ts/function");
43
44
  const BufferExtensions_1 = require("@trayio/commons/buffer/BufferExtensions");
@@ -50,8 +51,11 @@ class HttpOperationExecution {
50
51
  execute(ctx, input) {
51
52
  return __awaiter(this, void 0, void 0, function* () {
52
53
  const operationRequest = this.handler.requestHandler(ctx, input, this.handler.request);
53
- const httpRequest = this.operationRequestToHttpRequest(operationRequest);
54
- const resultTE = this.httpClient.execute(operationRequest.method, operationRequest.path, httpRequest);
54
+ const httpRequestE = yield this.operationRequestToHttpRequest(operationRequest)();
55
+ if (E.isLeft(httpRequestE)) {
56
+ return OperationHandler_1.OperationHandlerResult.failure(OperationHandler_1.OperationHandlerError.connectorError(httpRequestE.left.message));
57
+ }
58
+ const resultTE = this.httpClient.execute(operationRequest.method, operationRequest.path, httpRequestE.right);
55
59
  const operationResponseTE = (0, function_1.pipe)(resultTE,
56
60
  // get the dsl http response object
57
61
  TE.map((response) => this.handler.responseHandler(ctx, input, new HttpOperationHandler_1.HttpOperationResponseBuilder(response, this.defaultErrorHandling(response.statusCode)))),
@@ -62,14 +66,13 @@ class HttpOperationExecution {
62
66
  return TE.toUnion(operationResponseTE)();
63
67
  });
64
68
  }
65
- // TODO: Add file support, the output may need to be changed to TastEither<Error, HttpRequest>
66
69
  operationRequestToHttpRequest(operationRequest) {
67
- const serializedBody = (0, function_1.pipe)(operationRequest.contentType, O.map((contentType) => {
70
+ return (0, function_1.pipe)(operationRequest.contentType, O.map((contentType) => {
68
71
  switch (contentType) {
69
72
  case Http_1.HttpContentType.Json:
70
73
  return this.serializeAsJson(operationRequest.body);
71
74
  case Http_1.HttpContentType.OctetStream:
72
- return this.serializeAsFile(operationRequest.body);
75
+ return this.serializeAsFile(operationRequest);
73
76
  case Http_1.HttpContentType.MultipartRequestBody:
74
77
  return this.serializeAsMultipart(operationRequest.body);
75
78
  case Http_1.HttpContentType.Text:
@@ -77,25 +80,35 @@ class HttpOperationExecution {
77
80
  default:
78
81
  return this.serializeAsJson(operationRequest.body);
79
82
  }
80
- }), O.getOrElse(() => this.serializeEmptyBody()));
81
- return Object.assign(Object.assign({}, operationRequest.request), { body: serializedBody });
83
+ }), O.getOrElse(() => this.serializeEmptyBody()), TE.map((serializedBody) => (Object.assign(Object.assign({}, operationRequest.request), { body: serializedBody }))));
82
84
  }
83
85
  serializeAsJson(body) {
84
86
  const serializedBody = this.jsonSerialization.serialize(body);
85
- return BufferExtensions_1.BufferExtensions.arrayBufferToReadable(serializedBody);
87
+ return TE.right(BufferExtensions_1.BufferExtensions.arrayBufferToReadable(serializedBody));
86
88
  }
87
89
  serializeAsText(body) {
88
90
  const serializedBody = new TextEncoder().encode(body);
89
- return BufferExtensions_1.BufferExtensions.arrayBufferToReadable(serializedBody);
91
+ return TE.right(BufferExtensions_1.BufferExtensions.arrayBufferToReadable(serializedBody));
90
92
  }
91
93
  serializeAsMultipart(body) {
92
94
  throw new Error('unimplemented');
93
95
  }
94
- serializeAsFile(body) {
95
- throw new Error('unimplemented');
96
+ serializeAsFile(operationRequest) {
97
+ const downloadFilefromReference = this.httpClient.execute(Http_1.HttpMethod.Get, operationRequest.body.url, {
98
+ headers: { [Http_1.HttpHeader.ContentType]: Http_1.HttpContentType.OctetStream },
99
+ pathParams: {},
100
+ queryString: {},
101
+ body: BufferExtensions_1.BufferExtensions.arrayBufferToReadable(new ArrayBuffer(0)),
102
+ });
103
+ return (0, function_1.pipe)(downloadFilefromReference, TE.chain((response) => {
104
+ if (response.statusCode >= 300) {
105
+ return TE.left(Error('error downloading file from source'));
106
+ }
107
+ return TE.right(response.body);
108
+ }));
96
109
  }
97
110
  serializeEmptyBody() {
98
- return BufferExtensions_1.BufferExtensions.arrayBufferToReadable(new ArrayBuffer(0));
111
+ return TE.right(BufferExtensions_1.BufferExtensions.arrayBufferToReadable(new ArrayBuffer(0)));
99
112
  }
100
113
  defaultErrorHandling(statusCode) {
101
114
  return () => OperationHandler_1.OperationHandlerResult.failure(OperationHandler_1.OperationHandlerError.apiError(`API returned a status code of ${statusCode}`, {
@@ -1 +1 @@
1
- {"version":3,"file":"OperationExecutionGateway.unit.test.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/OperationExecutionGateway.unit.test.ts"],"names":[],"mappings":"AAGA,OAAO,8BAA8B,CAAC"}
1
+ {"version":3,"file":"OperationExecutionGateway.unit.test.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/OperationExecutionGateway.unit.test.ts"],"names":[],"mappings":"AAIA,OAAO,8BAA8B,CAAC"}
@@ -1,62 +1,178 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
26
  const OperationHandlerSetup_1 = require("@trayio/cdk-dsl/connector/operation/OperationHandlerSetup");
4
27
  const OperationHandlerTest_1 = require("@trayio/cdk-dsl/connector/operation/OperationHandlerTest");
5
28
  const OperationHandler_1 = require("@trayio/cdk-dsl/connector/operation/OperationHandler");
6
29
  require("./OperationHandlerTestRunner");
7
- const getProductOperation = OperationHandlerSetup_1.OperationHandlerSetup.configureHandler((handler) => handler
8
- .addInputValidation((inputValidation) => inputValidation
9
- .condition((ctx, input) => input.id > 0)
10
- .errorMessage(() => 'id must be bigger than zero'))
11
- .usingHttp((http) => http
12
- .get('https://jsonplaceholder.typicode.com/posts/:id')
13
- .handleRequest((ctx, input, request) => request.addPathParameter('id', input.id.toString()).withoutBody())
14
- .handleResponse((ctx, input, response) => response.parseWithBodyAsJson())));
15
- OperationHandlerTest_1.OperationHandlerTestSetup.configureHandlerTest(getProductOperation, (handlerTest) => handlerTest
16
- .usingHandlerContext('test')
17
- .nothingBeforeAll()
18
- .testCase('should get a product', (testCase) => testCase
19
- .usingHandlerContext('test')
20
- .givenNothing()
21
- .when(() => ({ id: 2 }))
22
- .then(({ output }) => {
23
- const outputValue = OperationHandler_1.OperationHandlerResult.getSuccessfulValueOrFail(output);
24
- expect(outputValue.id).toEqual(2);
25
- })
26
- .finallyDoNothing())
27
- .testCase('should validate id', (testCase) => testCase
28
- .givenNothing()
29
- .when(() => ({ id: -1 }))
30
- .then(({ output }) => {
31
- expect(output.isFailure).toBe(true);
32
- })
33
- .finallyDoNothing())
34
- .nothingAfterAll());
35
- const getProductOperationAsText = OperationHandlerSetup_1.OperationHandlerSetup.configureHandler((handler) => handler
36
- .addInputValidation((inputValidation) => inputValidation
37
- .condition((ctx, input) => input.id > 0)
38
- .errorMessage(() => 'id must be bigger than zero'))
39
- .usingHttp((http) => http
40
- .get('https://jsonplaceholder.typicode.com/posts/:id')
41
- .handleRequest((ctx, input, request) => request.addPathParameter('id', input.id.toString()).withoutBody())
42
- .handleResponse((ctx, input, response) => response.parseWithBodyAsText((text) => OperationHandler_1.OperationHandlerResult.success({ textField: text })))));
43
- OperationHandlerTest_1.OperationHandlerTestSetup.configureHandlerTest(getProductOperationAsText, (handlerTest) => handlerTest
44
- .usingHandlerContext('test')
45
- .nothingBeforeAll()
46
- .testCase('should get a product', (testCase) => testCase
47
- .usingHandlerContext('test')
48
- .givenNothing()
49
- .when(() => ({ id: 2 }))
50
- .then(({ output }) => {
51
- const outputValue = OperationHandler_1.OperationHandlerResult.getSuccessfulValueOrFail(output);
52
- expect(outputValue.textField).toContain(`"id": 2`);
53
- })
54
- .finallyDoNothing())
55
- .testCase('should validate id', (testCase) => testCase
56
- .givenNothing()
57
- .when(() => ({ id: -1 }))
58
- .then(({ output }) => {
59
- expect(output.isFailure).toBe(true);
60
- })
61
- .finallyDoNothing())
62
- .nothingAfterAll());
30
+ const T = __importStar(require("fp-ts/Task"));
31
+ const TE = __importStar(require("fp-ts/TaskEither"));
32
+ const function_1 = require("fp-ts/function");
33
+ const Http_1 = require("@trayio/commons/http/Http");
34
+ const stream_1 = require("stream");
35
+ const ExpressHttpServer_1 = require("@trayio/express/http/ExpressHttpServer");
36
+ const ExpressHttpController_1 = require("@trayio/express/http/ExpressHttpController");
37
+ const NodeFsFileStorage_1 = require("@trayio/commons/file/NodeFsFileStorage");
38
+ const fileStorage = new NodeFsFileStorage_1.NodeFsFileStorage('/tmp');
39
+ class TestControllerHttp {
40
+ constructor() {
41
+ this.getEndpoints = () => [
42
+ {
43
+ path: `/posts/:id`,
44
+ method: Http_1.HttpMethod.Get,
45
+ execute: (request) => {
46
+ const { id } = request.pathParams;
47
+ return T.of({
48
+ body: stream_1.Readable.from(JSON.stringify({
49
+ id: parseInt(id, 10),
50
+ title: 'test',
51
+ })),
52
+ headers: {},
53
+ statusCode: 200,
54
+ });
55
+ },
56
+ },
57
+ {
58
+ path: `/image-upload`,
59
+ method: Http_1.HttpMethod.Post,
60
+ execute: (request) => {
61
+ const { body } = request;
62
+ return (0, function_1.pipe)(fileStorage.write({
63
+ content: body,
64
+ metadata: {
65
+ key: 'test.ico',
66
+ },
67
+ }), TE.fold(() => T.of({
68
+ body: stream_1.Readable.from(JSON.stringify({
69
+ success: false,
70
+ })),
71
+ headers: {},
72
+ statusCode: 500,
73
+ }), () => T.of({
74
+ body: stream_1.Readable.from(JSON.stringify({
75
+ success: true,
76
+ })),
77
+ headers: {},
78
+ statusCode: 200,
79
+ })));
80
+ },
81
+ },
82
+ ];
83
+ }
84
+ }
85
+ const testHttpController = new ExpressHttpController_1.ExpressHttpController(new TestControllerHttp(), '/tmp');
86
+ describe('OperationExecutionGateway', () => {
87
+ let server;
88
+ beforeAll(() => {
89
+ server = (0, ExpressHttpServer_1.startServer)([testHttpController], { port: 3000 });
90
+ });
91
+ afterAll(() => {
92
+ server.close();
93
+ });
94
+ describe('get a product', () => {
95
+ const getProductOperation = OperationHandlerSetup_1.OperationHandlerSetup.configureHandler((handler) => handler
96
+ .addInputValidation((inputValidation) => inputValidation
97
+ .condition((ctx, input) => input.id > 0)
98
+ .errorMessage(() => 'id must be bigger than zero'))
99
+ .usingHttp((http) => http
100
+ .get('http://localhost:3000/posts/:id')
101
+ .handleRequest((ctx, input, request) => request.addPathParameter('id', input.id.toString()).withoutBody())
102
+ .handleResponse((ctx, input, response) => response.parseWithBodyAsJson())));
103
+ OperationHandlerTest_1.OperationHandlerTestSetup.configureHandlerTest(getProductOperation, (handlerTest) => handlerTest
104
+ .usingHandlerContext('test')
105
+ .nothingBeforeAll()
106
+ .testCase('should get a product', (testCase) => testCase
107
+ .usingHandlerContext('test')
108
+ .givenNothing()
109
+ .when(() => ({ id: 2 }))
110
+ .then(({ output }) => {
111
+ const outputValue = OperationHandler_1.OperationHandlerResult.getSuccessfulValueOrFail(output);
112
+ expect(outputValue.id).toEqual(2);
113
+ })
114
+ .finallyDoNothing())
115
+ .testCase('should validate id', (testCase) => testCase
116
+ .givenNothing()
117
+ .when(() => ({ id: -1 }))
118
+ .then(({ output }) => {
119
+ expect(output.isFailure).toBe(true);
120
+ })
121
+ .finallyDoNothing())
122
+ .nothingAfterAll());
123
+ });
124
+ describe('get a product as text', () => {
125
+ const getProductOperationAsText = OperationHandlerSetup_1.OperationHandlerSetup.configureHandler((handler) => handler
126
+ .addInputValidation((inputValidation) => inputValidation
127
+ .condition((ctx, input) => input.id > 0)
128
+ .errorMessage(() => 'id must be bigger than zero'))
129
+ .usingHttp((http) => http
130
+ .get('http://localhost:3000/posts/:id')
131
+ .handleRequest((ctx, input, request) => request.addPathParameter('id', input.id.toString()).withoutBody())
132
+ .handleResponse((ctx, input, response) => response.parseWithBodyAsText((text) => OperationHandler_1.OperationHandlerResult.success({ textField: text })))));
133
+ OperationHandlerTest_1.OperationHandlerTestSetup.configureHandlerTest(getProductOperationAsText, (handlerTest) => handlerTest
134
+ .usingHandlerContext('test')
135
+ .nothingBeforeAll()
136
+ .testCase('should get a product as text', (testCase) => testCase
137
+ .usingHandlerContext('test')
138
+ .givenNothing()
139
+ .when(() => ({ id: 2 }))
140
+ .then(({ output }) => {
141
+ const outputValue = OperationHandler_1.OperationHandlerResult.getSuccessfulValueOrFail(output);
142
+ expect(outputValue.textField).toContain(`"id":2`);
143
+ })
144
+ .finallyDoNothing())
145
+ .testCase('should validate id', (testCase) => testCase
146
+ .givenNothing()
147
+ .when(() => ({ id: -1 }))
148
+ .then(({ output }) => {
149
+ expect(output.isFailure).toBe(true);
150
+ })
151
+ .finallyDoNothing())
152
+ .nothingAfterAll());
153
+ });
154
+ describe('upload an image', () => {
155
+ const uploadImageOperation = OperationHandlerSetup_1.OperationHandlerSetup.configureHandler((handler) => handler.usingHttp((http) => http
156
+ .post('http://localhost:3000/image-upload')
157
+ .handleRequest((ctx, input, request) => request.withBodyAsFile({
158
+ name: 'test-image',
159
+ url: 'https://tray.io/favicon.ico',
160
+ mime_type: 'image/png',
161
+ expires: 0,
162
+ }))
163
+ .handleResponse((ctx, input, response) => response.parseWithBodyAsJson())));
164
+ OperationHandlerTest_1.OperationHandlerTestSetup.configureHandlerTest(uploadImageOperation, (handlerTest) => handlerTest
165
+ .usingHandlerContext('test')
166
+ .nothingBeforeAll()
167
+ .testCase('should upload an image', (testCase) => testCase
168
+ .usingHandlerContext('test')
169
+ .givenNothing()
170
+ .when(() => ({}))
171
+ .then(({ output }) => {
172
+ const outputValue = OperationHandler_1.OperationHandlerResult.getSuccessfulValueOrFail(output);
173
+ expect(outputValue.success).toEqual(true);
174
+ })
175
+ .finallyDoNothing())
176
+ .nothingAfterAll());
177
+ });
178
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trayio/cdk-runtime",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "description": "A Runtime that executes connector operations defined using the CDK DSL",
5
5
  "exports": {
6
6
  "./*": "./dist/*.js"
@@ -14,9 +14,10 @@
14
14
  "node": ">=18.x"
15
15
  },
16
16
  "dependencies": {
17
- "@trayio/axios": "2.3.0",
18
- "@trayio/cdk-dsl": "2.3.0",
19
- "@trayio/winston": "2.3.0"
17
+ "@trayio/axios": "2.5.0",
18
+ "@trayio/cdk-dsl": "2.5.0",
19
+ "@trayio/express": "2.5.0",
20
+ "@trayio/winston": "2.5.0"
20
21
  },
21
22
  "typesVersions": {
22
23
  "*": {