@trayio/cdk-dsl 1.3.0 → 1.4.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 +56 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -216,7 +216,7 @@ export const myOperationHandler =
|
|
|
216
216
|
);
|
|
217
217
|
```
|
|
218
218
|
|
|
219
|
-
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
|
|
219
|
+
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.
|
|
220
220
|
|
|
221
221
|
|
|
222
222
|
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:
|
|
@@ -230,6 +230,22 @@ export const getProductsHandler =
|
|
|
230
230
|
|
|
231
231
|
The `getProductsHandler` constant contains the handler reference, which also has the input and output type information as part of its type, to make sure that when invoked or tested, only valid input and output values can be used.
|
|
232
232
|
|
|
233
|
+
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:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const productsResult: OperationHandlerResult<GetProductsOutput> = await invoke(getProductsHandler)({ storeId: input.storeId })
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
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}`.
|
|
240
|
+
|
|
241
|
+
To use it as the output, it is recommended to define a custom type for the operation as usual in `output.ts` that derives from `DDLOperationOutput<T>` specifying whether `T` is of type string or number, like this example `output.ts` file:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import { DDLOperationOutput } from '@trayio/cdk-dsl/connector/operation/OperationHandler';
|
|
245
|
+
|
|
246
|
+
export type GetProductListDdlOutput = DDLOperationOutput<number> //the values of the elements of the DDL are of type number
|
|
247
|
+
```
|
|
248
|
+
|
|
233
249
|
|
|
234
250
|
With that in mind, this is what the DDL handler would look like:
|
|
235
251
|
|
|
@@ -238,12 +254,30 @@ With that in mind, this is what the DDL handler would look like:
|
|
|
238
254
|
export const getProductsDDLHandler =
|
|
239
255
|
OperationHandlerSetup.configureHandler<AuthType, GetProductsDDLInput, GetProductsDDLOutput>((handler) =>
|
|
240
256
|
handler.usingComposite(async (auth, input, invoke) => {
|
|
241
|
-
|
|
257
|
+
//invoke the products operation
|
|
258
|
+
const productsResult: OperationHandlerResult<GetProductsOutput> =
|
|
242
259
|
await invoke(getProductsHandler)({ storeId: input.storeId })
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
260
|
+
|
|
261
|
+
//if the invocation failed, propagate the failure
|
|
262
|
+
if (productsResult.isFailure) {
|
|
263
|
+
return productsResult
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
//productsResult is of type `OperationHandlerSuccess` now, because we handled the failure case above, so we can get the value
|
|
267
|
+
const products = productsResult.value
|
|
268
|
+
|
|
269
|
+
//converts a product list into a list of text (label) and values (identifiers) for the DDL
|
|
270
|
+
const productsDDL = products.map((product) => {
|
|
271
|
+
return {
|
|
272
|
+
text: product.title,
|
|
273
|
+
value: product.id
|
|
274
|
+
}
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
//returns the DDL list in an object with a "result" value to match the GetProductsDDLOutput type
|
|
278
|
+
return OperationHandlerResult.success({
|
|
279
|
+
result: productsDDL
|
|
280
|
+
})
|
|
247
281
|
})
|
|
248
282
|
);
|
|
249
283
|
```
|
|
@@ -257,11 +291,24 @@ The result of that invocation is of type `Promise<OperationHandlerResult<GetProd
|
|
|
257
291
|
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.
|
|
258
292
|
|
|
259
293
|
There are multiple ways to do this
|
|
260
|
-
- Using `if` or `switch` statements to narrow down the type
|
|
294
|
+
- Using `if` or `switch` statements to narrow down the type as shown in the example
|
|
261
295
|
- Using the `OperationHandlerResult.getSuccessfulValueOrFail()` function which unwraps the value if successful or terminates the function propagating the error if it is not
|
|
262
|
-
-
|
|
296
|
+
- 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>`)
|
|
297
|
+
|
|
298
|
+
Once the handler has access to the product list value, it just needs to convert each element to a `{text: string, value: number}` pair and return that list in an object with a `result` property as shown above.
|
|
299
|
+
|
|
300
|
+
Finally, for DDL operations, we need to add an extra `type` property in the `operation.json` file with `ddl` as the value:
|
|
301
|
+
|
|
302
|
+
```json
|
|
303
|
+
{
|
|
304
|
+
"name": "get_products_ddl",
|
|
305
|
+
"title": "Get Products DDL",
|
|
306
|
+
"description": "Returns a DDL with product ids as values and product titles as labels",
|
|
307
|
+
"type": "ddl"
|
|
308
|
+
}
|
|
309
|
+
```
|
|
263
310
|
|
|
264
|
-
|
|
311
|
+
This will categorise this operation as a DDL and will exclude it from the list of visible operations of the connector.
|
|
265
312
|
|
|
266
313
|
## Testing
|
|
267
314
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trayio/cdk-dsl",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.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.4.0"
|
|
18
18
|
},
|
|
19
19
|
"typesVersions": {
|
|
20
20
|
"*": {
|