@trayio/cdk-dsl 1.12.0 → 1.13.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.
package/README.md
CHANGED
|
@@ -9,7 +9,6 @@ to execute a connector's operations.
|
|
|
9
9
|
|
|
10
10
|
The [Tray.io Developer Portal](https://developer.tray.io) has the most up to date documentation including a [quick start guide](https://developer.tray.io/developer-portal/cdk/quickstart/) for building connectors with the CDK
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
## Project Structure
|
|
14
13
|
|
|
15
14
|
A CDK project is just a regular npm typescript project, preconfigured with all the dependencies, linter rules and compiler options that will be used to build the connector during deployment, so it is not recommended to change those.
|
|
@@ -18,10 +17,10 @@ Other than the package.json, jest configuration and typescript configuration, a
|
|
|
18
17
|
|
|
19
18
|
- A `connector.json` file that includes metadata about the connector, such as the name, version, title, etc
|
|
20
19
|
- A `src` directory that has:
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
- An Authentication typescript file that contains the type of the `auth` property of the `ctx` context object that operations receive together with the input, this type is the same for all operation
|
|
21
|
+
- A `test.ctx.json` json file that contains a context value (including the auth) that can be used for tests.
|
|
23
22
|
**This file should not be committed to a repository as it will have sensitive information such as access tokens**
|
|
24
|
-
|
|
23
|
+
- One folder per operation
|
|
25
24
|
|
|
26
25
|
## Context and Authentication
|
|
27
26
|
|
|
@@ -50,7 +49,8 @@ This "successful value or failure error" result of running an operation is descr
|
|
|
50
49
|
So, the core of what an operation handler describes can be summarised as a function:
|
|
51
50
|
|
|
52
51
|
```typescript
|
|
53
|
-
(ctx: OperationHandlerContext<AuthType>, input: InputType) =>
|
|
52
|
+
(ctx: OperationHandlerContext<AuthType>, input: InputType) =>
|
|
53
|
+
OperationHandlerResult<OutputType>;
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
However, when defining a handler, we can also specify things like validation or whether or not the handler is private, and this is where the DSL comes in.
|
|
@@ -60,7 +60,7 @@ The `handler.ts` file needs to define a handler using the `OperationHandlerSetup
|
|
|
60
60
|
The `OperationHandlerSetup.configureHandler()` function takes a callback that is used to configure the handler, it looks like this:
|
|
61
61
|
|
|
62
62
|
```typescript
|
|
63
|
-
export const myOperationHandler =
|
|
63
|
+
export const myOperationHandler =
|
|
64
64
|
OperationHandlerSetup.configureHandler<AuthType, InputType, OutputType>((handler) =>
|
|
65
65
|
/* use the "handler" value to specify what implementation to use, validation, etc */
|
|
66
66
|
);
|
|
@@ -73,17 +73,25 @@ Handlers can have input validation (which runs before the handler implementation
|
|
|
73
73
|
To add validation just use the `handler` argument of the callback described in the previous section:
|
|
74
74
|
|
|
75
75
|
```typescript
|
|
76
|
-
export const myOperationHandler =
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
76
|
+
export const myOperationHandler = OperationHandlerSetup.configureHandler<
|
|
77
|
+
AuthType,
|
|
78
|
+
InputType,
|
|
79
|
+
OutputType
|
|
80
|
+
>((handler) =>
|
|
81
|
+
handler
|
|
82
|
+
.addInputValidation((validation) =>
|
|
83
|
+
validation
|
|
84
|
+
.condition((ctx, input) => input.id > 0)
|
|
85
|
+
.errorMessage((ctx, input) => `Id ${input.id} is not positive`)
|
|
86
|
+
)
|
|
87
|
+
.addOutputValidation((validation) =>
|
|
88
|
+
validation
|
|
89
|
+
.condition((ctx, input, output) => output.id === input.id)
|
|
90
|
+
.errorMessage(
|
|
91
|
+
(ctx, input, output) => `Output and Input ids don't match`
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
);
|
|
87
95
|
```
|
|
88
96
|
|
|
89
97
|
Note that validation is optional, the only thing that is necessary to define a handler is its implementation.
|
|
@@ -99,7 +107,7 @@ A handler can only have one implementation, it describes what the handler does w
|
|
|
99
107
|
A very simple handler that makes an HTTP call can be configured in the following way:
|
|
100
108
|
|
|
101
109
|
```typescript
|
|
102
|
-
export const myOperationHandler =
|
|
110
|
+
export const myOperationHandler =
|
|
103
111
|
OperationHandlerSetup.configureHandler<AuthType, InputType, OutputType>((handler) =>
|
|
104
112
|
handler.addInputValidation(...)
|
|
105
113
|
.addOutputValidation(...)
|
|
@@ -120,12 +128,12 @@ The previous handler makes a `GET` http request, which is defined by the `http.g
|
|
|
120
128
|
- `withBearerToken(token)`: Adds an `Authorization` header with a `Bearer` token
|
|
121
129
|
- `addQueryString(name, value)`: Adds a query string to the request, the value will be url encoded
|
|
122
130
|
- `withBodyAsJson(body)`: Adds a body to the request that will be sent as json.
|
|
123
|
-
|
|
131
|
+
- `withBodyAsText(body)`: Adds a body to the request that will be sent as a plain text.
|
|
124
132
|
|
|
125
133
|
A handler with an authenticated POST request would look like this:
|
|
126
134
|
|
|
127
135
|
```typescript
|
|
128
|
-
export const myOperationHandler =
|
|
136
|
+
export const myOperationHandler =
|
|
129
137
|
OperationHandlerSetup.configureHandler<AuthType, InputType, OutputType>((handler) =>
|
|
130
138
|
handler.addInputValidation(...)
|
|
131
139
|
.addOutputValidation(...)
|
|
@@ -143,26 +151,26 @@ export const myOperationHandler =
|
|
|
143
151
|
The input does not have to match what is sent as the body, if for example the input has other flags that specify how the connector needs to behave and only part of it contains the body, the `withBodyAsJson` method can be called in the following way:
|
|
144
152
|
|
|
145
153
|
```typescript
|
|
146
|
-
|
|
154
|
+
request.withBodyAsJson({ name: input.name, title: input.title });
|
|
147
155
|
```
|
|
148
156
|
|
|
149
157
|
So the `handlerRequest` function can transform the input in any way it needs to before sending the HTTP request and the same is true for the `handleResponse`, in the previous examples, the `handleResponse` simply read the response body as json and returned it, but it can be more complex if necessary.
|
|
150
158
|
|
|
151
|
-
The `parseWithBodyAsJson<T>()`
|
|
159
|
+
The `parseWithBodyAsJson<T>() and parseWithBodyAsText()` functions on the `response` argument returns a value of type `OperationHandlerResult<T>`, which can be a successful response or a failure based on the status code or if something went wrong executing the call.
|
|
152
160
|
|
|
153
161
|
Just like with the input type and the request, the type of the json body in the response can be different from the output type.
|
|
154
162
|
|
|
155
163
|
This is an example of a handler that transforms the response body into the output type:
|
|
156
164
|
|
|
157
165
|
```typescript
|
|
158
|
-
export const myOperationHandler =
|
|
166
|
+
export const myOperationHandler =
|
|
159
167
|
OperationHandlerSetup.configureHandler<AuthType, InputType, OutputType>((handler) =>
|
|
160
168
|
handler.addInputValidation(...)
|
|
161
169
|
.addOutputValidation(...)
|
|
162
170
|
.usingHttp((http) =>
|
|
163
171
|
http.post('https://someapi.com/someresource')
|
|
164
172
|
.handleRequest(...)
|
|
165
|
-
.handleResponse((response) => {
|
|
173
|
+
.handleResponse((response) => {
|
|
166
174
|
const httpResponseBody = response.parseWithBodyAsJson<{message: string}>()
|
|
167
175
|
if (httpResponseBody.isSuccess) {
|
|
168
176
|
const originalMessage = httpResponseBody.value.message
|
|
@@ -180,14 +188,14 @@ Instead of using an `if` in the previous case, there is also a `OperationHandler
|
|
|
180
188
|
The handler can also return successful responses for some failure cases or viceversa, this is an example of a handler that "recovers" from errors to always return a successful response:
|
|
181
189
|
|
|
182
190
|
```typescript
|
|
183
|
-
export const myOperationHandler =
|
|
191
|
+
export const myOperationHandler =
|
|
184
192
|
OperationHandlerSetup.configureHandler<AuthType, InputType, OutputType>((handler) =>
|
|
185
193
|
handler.addInputValidation(...)
|
|
186
194
|
.addOutputValidation(...)
|
|
187
195
|
.usingHttp((http) =>
|
|
188
196
|
http.post('https://someapi.com/someresource')
|
|
189
197
|
.handleRequest(...)
|
|
190
|
-
.handleResponse((response) => {
|
|
198
|
+
.handleResponse((response) => {
|
|
191
199
|
const httpResponseBody = response.withBodyAsJson()
|
|
192
200
|
if (httpResponseBody.isFailure) {
|
|
193
201
|
return OperationHandlerResult.success({ completed: false })
|
|
@@ -198,7 +206,6 @@ export const myOperationHandler =
|
|
|
198
206
|
);
|
|
199
207
|
```
|
|
200
208
|
|
|
201
|
-
|
|
202
209
|
## Composite Implementation
|
|
203
210
|
|
|
204
211
|
Composite handlers are used to define behaviours by invoking zero or more operations as part of their behaviour.
|
|
@@ -209,7 +216,7 @@ like an "upsert" that combines more granular "read, create and update" operation
|
|
|
209
216
|
A very simple composite handler, that just concatenates the `firstName` and `lastName` arguments it gets from the input into one string:
|
|
210
217
|
|
|
211
218
|
```typescript
|
|
212
|
-
export const myOperationHandler =
|
|
219
|
+
export const myOperationHandler =
|
|
213
220
|
OperationHandlerSetup.configureHandler<AuthType, InputType, OutputType>((handler) =>
|
|
214
221
|
handler.addInputValidation(...)
|
|
215
222
|
.addOutputValidation(...)
|
|
@@ -222,11 +229,10 @@ export const myOperationHandler =
|
|
|
222
229
|
|
|
223
230
|
As an example of more complex behaviour, this handler reads a list of products using another operation and converts the result into a simple list of text and value pairs, this is known as a Dynamic Data List (DDL) operation used to help users select values as part of configuring workflows within the tray builder.
|
|
224
231
|
|
|
225
|
-
|
|
226
232
|
To do this, the handler needs to invoke the regular `getProducts` operation, this is accomplished by using the `invoke` functions that composite handlers have access to, and passing it a **handler reference** and an input (no need to pass the auth value as it will be passed automatically), the handler reference passed to the `invoke` function is the result of the `OperationHandlerSetup.configureHandler()` function, which is why they are saved into a constant and exported like this:
|
|
227
233
|
|
|
228
234
|
```typescript
|
|
229
|
-
export const getProductsHandler =
|
|
235
|
+
export const getProductsHandler =
|
|
230
236
|
OperationHandlerSetup.configureHandler<AuthType, GetProductsInput, GetProductsOutput>((handler) =>
|
|
231
237
|
handler.usingHttp(...)
|
|
232
238
|
);
|
|
@@ -237,7 +243,9 @@ The `getProductsHandler` constant contains the handler reference, which also has
|
|
|
237
243
|
To invoke the handler it is a simple call to the `invoke` function that takes the handler reference as an argument, and returns another function that takes the input type of that handler and returns a `Promise<OperationHandlerResult<T>>` where `T` is the output type of the handler and `OperationHandlerResult` contains a failure response if the call failed or a success response with a value of type `T` if the call was successful:
|
|
238
244
|
|
|
239
245
|
```typescript
|
|
240
|
-
const productsResult: OperationHandlerResult<GetProductsOutput> = await invoke(
|
|
246
|
+
const productsResult: OperationHandlerResult<GetProductsOutput> = await invoke(
|
|
247
|
+
getProductsHandler
|
|
248
|
+
)({ storeId: input.storeId });
|
|
241
249
|
```
|
|
242
250
|
|
|
243
251
|
The output type of a DDL operation is defined by the `DDLOperationOutput<T>` type, where `T` is the type of the values and can be a string or a number, that type has one field called `results` which is an array of objects of type `{text: string, value: T}`.
|
|
@@ -247,46 +255,47 @@ To use it as the output, it is recommended to define a custom type for the opera
|
|
|
247
255
|
```typescript
|
|
248
256
|
import { DDLOperationOutput } from '@trayio/cdk-dsl/connector/operation/OperationHandler';
|
|
249
257
|
|
|
250
|
-
export type GetProductListDdlOutput = DDLOperationOutput<number
|
|
258
|
+
export type GetProductListDdlOutput = DDLOperationOutput<number>; //the values of the elements of the DDL are of type number
|
|
251
259
|
```
|
|
252
260
|
|
|
253
|
-
|
|
254
261
|
With that in mind, this is what the DDL handler would look like:
|
|
255
262
|
|
|
256
|
-
|
|
257
263
|
```typescript
|
|
258
|
-
export const getProductsDDLHandler =
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
264
|
+
export const getProductsDDLHandler = OperationHandlerSetup.configureHandler<
|
|
265
|
+
AuthType,
|
|
266
|
+
GetProductsDDLInput,
|
|
267
|
+
GetProductsDDLOutput
|
|
268
|
+
>((handler) =>
|
|
269
|
+
handler.usingComposite(async (auth, input, invoke) => {
|
|
270
|
+
//invoke the products operation
|
|
271
|
+
const productsResult: OperationHandlerResult<GetProductsOutput> =
|
|
272
|
+
await invoke(getProductsHandler)({ storeId: input.storeId });
|
|
273
|
+
|
|
274
|
+
//if the invocation failed, propagate the failure
|
|
275
|
+
if (productsResult.isFailure) {
|
|
276
|
+
return productsResult;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
//productsResult is of type `OperationHandlerSuccess` now, because we handled the failure case above, so we can get the value
|
|
280
|
+
const products = productsResult.value;
|
|
281
|
+
|
|
282
|
+
//converts a product list into a list of text (label) and values (identifiers) for the DDL
|
|
283
|
+
const productsDDL = products.map((product) => {
|
|
284
|
+
return {
|
|
285
|
+
text: product.title,
|
|
286
|
+
value: product.id,
|
|
287
|
+
};
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
//returns the DDL list in an object with a "result" value to match the GetProductsDDLOutput type
|
|
291
|
+
return OperationHandlerResult.success({
|
|
292
|
+
result: productsDDL,
|
|
293
|
+
});
|
|
294
|
+
})
|
|
295
|
+
);
|
|
287
296
|
```
|
|
288
297
|
|
|
289
|
-
There are several things to note about the handler, both the DDL handler and the `getProductsHandler` expect a `storeId` in the input to return a list of products for that store.
|
|
298
|
+
There are several things to note about the handler, both the DDL handler and the `getProductsHandler` expect a `storeId` in the input to return a list of products for that store.
|
|
290
299
|
|
|
291
300
|
The `getProductsHandler` is invoked using the `invoke` function that composite handlers receive as an argument, passing the handler reference, and then calling the result as a function passing the input that handler expects, in this case, just an object with a `storeId`
|
|
292
301
|
|
|
@@ -295,6 +304,7 @@ The result of that invocation is of type `Promise<OperationHandlerResult<GetProd
|
|
|
295
304
|
The `await` keyword unwraps the promise, and we are left with a `OperationHandlerResult<GetProductsOutput>`, which forces the handler to deal with both the failure case as well as the success case.
|
|
296
305
|
|
|
297
306
|
There are multiple ways to do this
|
|
307
|
+
|
|
298
308
|
- Using `if` or `switch` statements to narrow down the type as shown in the example
|
|
299
309
|
- Using the `OperationHandlerResult.getSuccessfulValueOrFail()` function which unwraps the value if successful or terminates the function propagating the error if it is not
|
|
300
310
|
- Using the `OperationHandlerResult.map()` function, which takes an `OperationHandlerResult<T>` as an argument and a function to convert `T` to another type in case it is successful, propagating the failure if it is not (works in the same way it works for the map function in `Array<T>`)
|
|
@@ -305,10 +315,10 @@ Finally, for DDL operations, we need to add an extra `type` property in the `ope
|
|
|
305
315
|
|
|
306
316
|
```json
|
|
307
317
|
{
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
318
|
+
"name": "get_products_ddl",
|
|
319
|
+
"title": "Get Products DDL",
|
|
320
|
+
"description": "Returns a DDL with product ids as values and product titles as labels",
|
|
321
|
+
"type": "ddl"
|
|
312
322
|
}
|
|
313
323
|
```
|
|
314
324
|
|
|
@@ -356,16 +366,14 @@ The structure of a test is well defined, and the type safe declarative DSL will
|
|
|
356
366
|
- Add a test case using the `testCase()` function.
|
|
357
367
|
- Run one or more operations (doesn't have to be the one being tested) after all test cases using the `afterAll()` function, or don't do anything after all test cases using the `nothingAfterAll()` function, these functions can only be used after defining test cases, and no test cases can be added after this (this is enforced by the type system)
|
|
358
368
|
|
|
359
|
-
|
|
360
369
|
As for the test cases, they use a BDD style Given/When/Then convention, in particular a test case has:
|
|
361
370
|
|
|
362
371
|
- An optional `usingHandlerContext()` function at the beginning of the test case to use a different context than the default for all test cases
|
|
363
|
-
- A `given()` function to run one or more operations at the beginning of the test case or `givenNothing()` to go straight to running the operation under test
|
|
372
|
+
- A `given()` function to run one or more operations at the beginning of the test case or `givenNothing()` to go straight to running the operation under test
|
|
364
373
|
- A `when()` function to create an input value that will be used to run the operation under test, that value needs to match the input type of the operation
|
|
365
374
|
- A `then()` function that gets the output, input, auth and optionally the result of `beforeAll()` and `given()` if present, which can be used to do the assertions of the test case using jest-style matchers
|
|
366
375
|
- A `finally()` function to run one or more operations at the end of the test case, usually for cleanup, or `finallyDoNothing()` to don't do anything else after the assertions.
|
|
367
376
|
|
|
368
|
-
|
|
369
377
|
Both the `beforeAll()` and `given()` functions allow to run multiple operations before all test cases or before a single test case, they receive the `invoke` function as an argument just like composite handlers and they return an object that can contain some of relevant information about the operations that ran if necessary (like ids of things created) in a value that can be accessed by the `when()`, `then()`, `finally()` and `afterAll()` functions, they receive them as arguments.
|
|
370
378
|
|
|
371
379
|
As an example, the following test is for an `updateProduct` operation, it creates a store for all test cases, and a product for every test case to test the update on, using `beforeAll` and `given` respectively, and accessing the identities of the created objects from the `testContext` (the output of `beforeAll`) and the `testCaseContext` (the output of `given`):
|
|
@@ -376,37 +384,52 @@ OperationHandlerTestSetup.configureHandlerTest(
|
|
|
376
384
|
(handlerTest) =>
|
|
377
385
|
handlerTest
|
|
378
386
|
.usingHandlerContext('test')
|
|
379
|
-
.beforeAll<{storeId: string}>(async (auth, invoke) => {
|
|
387
|
+
.beforeAll<{ storeId: string }>(async (auth, invoke) => {
|
|
380
388
|
//Creates an store that will be used by all tests
|
|
381
|
-
const createdStoreResult = invoke(createStoreHandler)({
|
|
389
|
+
const createdStoreResult = invoke(createStoreHandler)({
|
|
390
|
+
name: 'something',
|
|
391
|
+
});
|
|
382
392
|
return OperationHandlerResult.map(
|
|
383
|
-
createdStoreResult,
|
|
384
|
-
createdStoreOutput => {
|
|
385
|
-
|
|
393
|
+
createdStoreResult,
|
|
394
|
+
(createdStoreOutput) => {
|
|
395
|
+
storeId: createdStoreOutput.id;
|
|
396
|
+
}
|
|
397
|
+
);
|
|
386
398
|
})
|
|
387
399
|
.testCase('should do something', (testCase) =>
|
|
388
400
|
testCase
|
|
389
|
-
.given<{ productId: string}>((auth, testContext, invoke) => {
|
|
401
|
+
.given<{ productId: string }>((auth, testContext, invoke) => {
|
|
390
402
|
//Creates an product in the store to be used by the test
|
|
391
|
-
const createdProductResult = invoke(createProductHandler)({
|
|
403
|
+
const createdProductResult = invoke(createProductHandler)({
|
|
404
|
+
name: 'some product',
|
|
405
|
+
storeId: testContext.storeId,
|
|
406
|
+
});
|
|
392
407
|
return OperationHandlerResult.map(
|
|
393
|
-
createdProductResult,
|
|
394
|
-
createdProductOutput => {
|
|
395
|
-
|
|
408
|
+
createdProductResult,
|
|
409
|
+
(createdProductOutput) => {
|
|
410
|
+
productId: createdProductOutput.id;
|
|
411
|
+
}
|
|
412
|
+
);
|
|
396
413
|
})
|
|
397
|
-
.when((auth, testContext, testCaseContext) => ({
|
|
414
|
+
.when((auth, testContext, testCaseContext) => ({
|
|
415
|
+
productId: testCaseContext.productId,
|
|
416
|
+
name: 'updated name',
|
|
417
|
+
}))
|
|
398
418
|
.then(({ output }) => {
|
|
399
|
-
const outputValue =
|
|
419
|
+
const outputValue =
|
|
420
|
+
OperationHandlerResult.getSuccessfulValueOrFail(output);
|
|
400
421
|
expect(outputValue.name).toEqual('updated name');
|
|
401
422
|
})
|
|
402
423
|
.finally(({ testCaseContext }) => {
|
|
403
424
|
//Deletes the product created for the test
|
|
404
|
-
return invoke(deleteProductHandler)({
|
|
425
|
+
return invoke(deleteProductHandler)({
|
|
426
|
+
productId: testCaseContext.productId,
|
|
427
|
+
});
|
|
405
428
|
})
|
|
406
429
|
)
|
|
407
430
|
.afterAll(({ testContext }) => {
|
|
408
431
|
//Deletes the store created for all test cases
|
|
409
|
-
return invoke(deleteStoreHandler)({storeId: testContext.storeId})
|
|
432
|
+
return invoke(deleteStoreHandler)({ storeId: testContext.storeId });
|
|
410
433
|
})
|
|
411
434
|
);
|
|
412
435
|
```
|
|
@@ -7,6 +7,7 @@ export declare class HttpOperationRequest {
|
|
|
7
7
|
readonly request: HttpRequest;
|
|
8
8
|
constructor(method: HttpMethod, path: string, request: HttpRequest);
|
|
9
9
|
withBodyAsJson<T>(body: T): HttpOperationRequest;
|
|
10
|
+
withBodyAsText(body: string): HttpOperationRequest;
|
|
10
11
|
addPathParameter(name: string, value: string): HttpOperationRequest;
|
|
11
12
|
addQueryString(name: string, value: string): HttpOperationRequest;
|
|
12
13
|
withBearerToken(token: string): HttpOperationRequest;
|
|
@@ -20,6 +21,7 @@ export declare class HttpOperationResponse {
|
|
|
20
21
|
getStatusCode(): number;
|
|
21
22
|
getHeader(name: string): HttpHeaderValue | undefined;
|
|
22
23
|
parseWithEmptyBody(): OperationHandlerResult<undefined>;
|
|
24
|
+
parseWithBodyAsText(): OperationHandlerResult<string>;
|
|
23
25
|
parseWithBodyAsJson<T>(): OperationHandlerResult<T>;
|
|
24
26
|
}
|
|
25
27
|
export type HttpOperationResponseHandler<OUT> = (response: HttpOperationResponse) => OperationHandlerResult<OUT>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpOperationHandler.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/HttpOperationHandler.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HttpOperationHandler.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/HttpOperationHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,6 +51,9 @@ class HttpOperationRequest {
|
|
|
51
51
|
const serializedBody = this.jsonSerialization.serialize(body);
|
|
52
52
|
return new HttpOperationRequest(this.method, this.path, Object.assign(Object.assign({}, this.request), { body: BufferExtensions_1.BufferExtensions.arrayBufferToReadable(serializedBody) })).addHeader(Http_1.HttpHeader.ContentType, Http_1.HttpContentType.Json);
|
|
53
53
|
}
|
|
54
|
+
withBodyAsText(body) {
|
|
55
|
+
return new HttpOperationRequest(this.method, this.path, Object.assign(Object.assign({}, this.request), { body: BufferExtensions_1.BufferExtensions.arrayBufferToReadable(new TextEncoder().encode(body)) })).addHeader(Http_1.HttpHeader.ContentType, Http_1.HttpContentType.Text);
|
|
56
|
+
}
|
|
54
57
|
addPathParameter(name, value) {
|
|
55
58
|
return new HttpOperationRequest(this.method, this.path, Object.assign(Object.assign({}, this.request), { pathParams: Object.assign(Object.assign({}, this.request.pathParams), { [name]: value }) }));
|
|
56
59
|
}
|
|
@@ -84,6 +87,14 @@ class HttpOperationResponse {
|
|
|
84
87
|
}
|
|
85
88
|
return OperationHandler_1.OperationHandlerResult.success(undefined);
|
|
86
89
|
}
|
|
90
|
+
parseWithBodyAsText() {
|
|
91
|
+
if (this.response.statusCode >= 300) {
|
|
92
|
+
return OperationHandler_1.OperationHandlerResult.failure(OperationHandler_1.OperationHandlerError.apiError(`API returned a status code of ${this.response.statusCode}`, {
|
|
93
|
+
statusCode: this.response.statusCode,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
return OperationHandler_1.OperationHandlerResult.success(new TextDecoder().decode(this.response.body));
|
|
97
|
+
}
|
|
87
98
|
parseWithBodyAsJson() {
|
|
88
99
|
const deserializedBodyE = this.jsonSerialization.deserialize(this.response.body);
|
|
89
100
|
const result = E.match((error) => OperationHandler_1.OperationHandlerResult.failure(OperationHandler_1.OperationHandlerError.connectorError(`Could not deserialise the body of the response: ${error.message}`)), (deserializedBody) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trayio/cdk-dsl",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "A DSL for connector development",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./*": "./dist/*.js"
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"access": "public"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@trayio/commons": "1.
|
|
17
|
+
"@trayio/commons": "1.13.0"
|
|
18
18
|
},
|
|
19
19
|
"typesVersions": {
|
|
20
20
|
"*": {
|