@kaleido-io/workflow-engine-sdk 0.0.1 → 0.9.2
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/LICENSE +201 -0
- package/README.md +1121 -0
- package/bin/init.js +200 -0
- package/bin/wesdk.js +57 -0
- package/dist/package.json +3 -0
- package/dist/src/client/client.d.ts +24 -0
- package/dist/src/client/client.d.ts.map +1 -0
- package/dist/src/client/client.js +58 -0
- package/dist/src/client/client.js.map +1 -0
- package/dist/src/client/rest-client.d.ts +222 -0
- package/dist/src/client/rest-client.d.ts.map +1 -0
- package/dist/src/client/rest-client.js +242 -0
- package/dist/src/client/rest-client.js.map +1 -0
- package/dist/src/config/config.d.ts +60 -0
- package/dist/src/config/config.d.ts.map +1 -0
- package/dist/src/config/config.js +117 -0
- package/dist/src/config/config.js.map +1 -0
- package/dist/src/factories/event_source.d.ts +54 -0
- package/dist/src/factories/event_source.d.ts.map +1 -0
- package/dist/src/factories/event_source.js +170 -0
- package/dist/src/factories/event_source.js.map +1 -0
- package/dist/src/factories/transaction_handler.d.ts +27 -0
- package/dist/src/factories/transaction_handler.d.ts.map +1 -0
- package/dist/src/factories/transaction_handler.js +66 -0
- package/dist/src/factories/transaction_handler.js.map +1 -0
- package/dist/src/helpers/stage_director.d.ts +42 -0
- package/dist/src/helpers/stage_director.d.ts.map +1 -0
- package/dist/src/helpers/stage_director.js +304 -0
- package/dist/src/helpers/stage_director.js.map +1 -0
- package/dist/src/i18n/errors.d.ts +61 -0
- package/dist/src/i18n/errors.d.ts.map +1 -0
- package/dist/src/i18n/errors.js +90 -0
- package/dist/src/i18n/errors.js.map +1 -0
- package/dist/src/index.d.ts +20 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +85 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces/handlers.d.ts +112 -0
- package/dist/src/interfaces/handlers.d.ts.map +1 -0
- package/dist/src/interfaces/handlers.js +18 -0
- package/dist/src/interfaces/handlers.js.map +1 -0
- package/dist/src/interfaces/messages.d.ts +6 -0
- package/dist/src/interfaces/messages.d.ts.map +1 -0
- package/dist/src/interfaces/messages.js +18 -0
- package/dist/src/interfaces/messages.js.map +1 -0
- package/dist/src/log/logger.d.ts +8 -0
- package/dist/src/log/logger.d.ts.map +1 -0
- package/dist/src/log/logger.js +39 -0
- package/dist/src/log/logger.js.map +1 -0
- package/dist/src/runtime/engine_client.d.ts +37 -0
- package/dist/src/runtime/engine_client.d.ts.map +1 -0
- package/dist/src/runtime/engine_client.js +99 -0
- package/dist/src/runtime/engine_client.js.map +1 -0
- package/dist/src/runtime/handler_runtime.d.ts +124 -0
- package/dist/src/runtime/handler_runtime.d.ts.map +1 -0
- package/dist/src/runtime/handler_runtime.js +623 -0
- package/dist/src/runtime/handler_runtime.js.map +1 -0
- package/dist/src/types/core.d.ts +258 -0
- package/dist/src/types/core.d.ts.map +1 -0
- package/dist/src/types/core.js +71 -0
- package/dist/src/types/core.js.map +1 -0
- package/dist/src/types/flows.d.ts +144 -0
- package/dist/src/types/flows.d.ts.map +1 -0
- package/dist/src/types/flows.js +30 -0
- package/dist/src/types/flows.js.map +1 -0
- package/dist/src/utils/errors.d.ts +2 -0
- package/dist/src/utils/errors.d.ts.map +1 -0
- package/dist/src/utils/errors.js +23 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/patch.d.ts +9 -0
- package/dist/src/utils/patch.d.ts.map +1 -0
- package/dist/src/utils/patch.js +99 -0
- package/dist/src/utils/patch.js.map +1 -0
- package/dist-esm/src/client/client.js +54 -0
- package/dist-esm/src/client/client.js.map +1 -0
- package/dist-esm/src/client/rest-client.js +238 -0
- package/dist-esm/src/client/rest-client.js.map +1 -0
- package/dist-esm/src/config/config.js +113 -0
- package/dist-esm/src/config/config.js.map +1 -0
- package/dist-esm/src/factories/event_source.js +167 -0
- package/dist-esm/src/factories/event_source.js.map +1 -0
- package/dist-esm/src/factories/transaction_handler.js +63 -0
- package/dist-esm/src/factories/transaction_handler.js.map +1 -0
- package/dist-esm/src/helpers/stage_director.js +298 -0
- package/dist-esm/src/helpers/stage_director.js.map +1 -0
- package/dist-esm/src/i18n/errors.js +85 -0
- package/dist-esm/src/i18n/errors.js.map +1 -0
- package/dist-esm/src/index.js +51 -0
- package/dist-esm/src/index.js.map +1 -0
- package/dist-esm/src/interfaces/handlers.js +17 -0
- package/dist-esm/src/interfaces/handlers.js.map +1 -0
- package/dist-esm/src/interfaces/messages.js +17 -0
- package/dist-esm/src/interfaces/messages.js.map +1 -0
- package/dist-esm/src/log/logger.js +36 -0
- package/dist-esm/src/log/logger.js.map +1 -0
- package/dist-esm/src/runtime/engine_client.js +95 -0
- package/dist-esm/src/runtime/engine_client.js.map +1 -0
- package/dist-esm/src/runtime/handler_runtime.js +586 -0
- package/dist-esm/src/runtime/handler_runtime.js.map +1 -0
- package/dist-esm/src/types/core.js +68 -0
- package/dist-esm/src/types/core.js.map +1 -0
- package/dist-esm/src/types/flows.js +27 -0
- package/dist-esm/src/types/flows.js.map +1 -0
- package/dist-esm/src/utils/errors.js +19 -0
- package/dist-esm/src/utils/errors.js.map +1 -0
- package/dist-esm/src/utils/patch.js +56 -0
- package/dist-esm/src/utils/patch.js.map +1 -0
- package/package.json +79 -11
- package/template/.env.sample +14 -0
- package/template/.vscode/launch.json +23 -0
- package/template/README.md +37 -0
- package/template/package.json +36 -0
- package/template/src/connect.ts +58 -0
- package/template/src/provider.ts +24 -0
- package/template/src/samples/event-source/README.md +50 -0
- package/template/src/samples/event-source/echo-handler.ts +65 -0
- package/template/src/samples/event-source/event-processor.ts +46 -0
- package/template/src/samples/event-source/event-source.ts +70 -0
- package/template/src/samples/event-source/stream.ts +34 -0
- package/template/src/samples/hello/README.md +52 -0
- package/template/src/samples/hello/flow.ts +74 -0
- package/template/src/samples/hello/handlers.test.ts +147 -0
- package/template/src/samples/hello/handlers.ts +72 -0
- package/template/src/samples/hello/transaction.ts +24 -0
- package/template/src/samples/http-invoke/README.md +42 -0
- package/template/src/samples/http-invoke/flow.ts +63 -0
- package/template/src/samples/http-invoke/handlers.ts +66 -0
- package/template/src/samples/http-invoke/transaction.ts +22 -0
- package/template/src/samples/snap/README.md +98 -0
- package/template/src/samples/snap/event-source.ts +104 -0
- package/template/src/samples/snap/flow.ts +85 -0
- package/template/src/samples/snap/snap-handler.ts +84 -0
- package/template/src/samples/snap/stream.ts +26 -0
- package/template/src/samples/snap/transaction.ts +26 -0
- package/template/src/utils/post-stream.ts +67 -0
- package/template/src/utils/post-transaction.ts +64 -0
- package/template/src/utils/post-workflow.ts +63 -0
- package/template/tsconfig.json +24 -0
- package/template/vitest.config.ts +42 -0
- package/CODEOWNERS +0 -5
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Snap handler sample
|
|
2
|
+
|
|
3
|
+
This example demonstrates how to set up a transaction handler that uses event triggers to wait for and respond to external events, implementing a "snap" card game mechanic. It showcases the use of a **correlation stream** to match events from any event source with inflight transactions.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The snap handler sample consists of four main components:
|
|
8
|
+
|
|
9
|
+
1. **Transaction handler** (`snap-handler.ts`) - Implements a card game "snap" mechanic with three actions
|
|
10
|
+
2. **Event source** (`event-source.ts`) - Acts as a card dealer, dealing cards from a shuffled deck
|
|
11
|
+
3. **Correlation stream** (`stream.ts`) - Connects events from the event source to inflight transactions
|
|
12
|
+
4. **Workflow** (`flow.ts`) - Defines the workflow stages and event bindings
|
|
13
|
+
|
|
14
|
+
## How it works
|
|
15
|
+
|
|
16
|
+
### The snap game flow
|
|
17
|
+
|
|
18
|
+
The snap game works by setting a "trap" for a specific playing card (suit and rank) and waiting for that card to be dealt. Here's how the complete flow works:
|
|
19
|
+
|
|
20
|
+
1. **Transaction Creation**: A transaction is created with a suit and rank (e.g., "hearts" and "king")
|
|
21
|
+
2. **Trap Setup**: The transaction handler sets up a trigger for that specific card
|
|
22
|
+
3. **Waiting State**: The transaction enters a waiting state, listening for matching events
|
|
23
|
+
4. **Card Dealing**: The event source (dealer) deals cards from a shuffled deck
|
|
24
|
+
5. **Event Correlation**: The correlation stream receives card events and determines if they match any inflight transactions
|
|
25
|
+
6. **Match Detection**: When a matching card is dealt, the stream adds a transaction event to the database
|
|
26
|
+
7. **Handler Invocation**: The transaction handler is invoked with the matching event, completing the "snap"
|
|
27
|
+
|
|
28
|
+
### Transaction handler
|
|
29
|
+
|
|
30
|
+
The snap handler (`snap-handler.ts`) implements a card game where you can "set a trap" for a specific playing card (suit and rank) and wait for that card to be played. The handler has three actions:
|
|
31
|
+
|
|
32
|
+
1. **`set-trap`** - Sets up a trigger for a specific card by creating an event topic based on the suit and rank (e.g., `suit.hearts.rank.king`)
|
|
33
|
+
2. **`trap-set`** - Marks that the trap is active and waits for the matching card to be played
|
|
34
|
+
3. **`trap-fired`** - Handles when a matching card is played via an event, completing the "snap" and returning the card data
|
|
35
|
+
|
|
36
|
+
### Event source
|
|
37
|
+
|
|
38
|
+
The event source (`event-source.ts`) acts as a card dealer that generates card play events. It maintains a shuffled deck of 52 playing cards and deals random batches of cards (1-9 cards per poll) when polled by the workflow engine. Each card dealt generates an event with:
|
|
39
|
+
|
|
40
|
+
- A topic matching the pattern `suit.<suit>.rank.<rank>` (e.g., `suit.hearts.rank.king`)
|
|
41
|
+
- A data payload containing the card's description, suit, and rank
|
|
42
|
+
- A unique idempotency key
|
|
43
|
+
|
|
44
|
+
The event source tracks how many cards have been dealt and stops generating events when the deck is exhausted.
|
|
45
|
+
|
|
46
|
+
### Correlation stream
|
|
47
|
+
|
|
48
|
+
The correlation stream (`stream.ts`) is a key component that demonstrates how events from any event source can be correlated with inflight transactions. The stream:
|
|
49
|
+
|
|
50
|
+
- **Type**: `correlation_stream` - This type of stream evaluates events against all inflight transactions
|
|
51
|
+
- **Event source**: Connects to the `snap-dealer` event source to receive card events
|
|
52
|
+
- **Matching Logic**: When a card event is received, the workflow engine checks if any inflight transactions have event listeners that match the event's topic pattern
|
|
53
|
+
- **Transaction Event**: If a match is found, the engine adds a transaction event to the database and invokes the corresponding transaction handler
|
|
54
|
+
|
|
55
|
+
This is different from an `event_stream`, which routes events to event processors. A correlation stream allows transactions to wait for and respond to events from any source, making it ideal for event-driven workflows where transactions need to react to external events.
|
|
56
|
+
|
|
57
|
+
### Workflow
|
|
58
|
+
|
|
59
|
+
The workflow (`flow.ts`) defines the stages and event bindings:
|
|
60
|
+
|
|
61
|
+
- **`set-trap` stage**: Initializes the trap by calling the `set-trap` action
|
|
62
|
+
- **`trap-set` stage**: Confirms the trap is set and enters a waiting state
|
|
63
|
+
- **Event listener**: Listens for card play events matching the pattern `suit.<suit>.rank.<rank>`
|
|
64
|
+
- **`snap` stage**: Final success stage reached when the matching card is played
|
|
65
|
+
|
|
66
|
+
When the correlation stream receives a card event that matches an inflight transaction's event listener, the workflow engine automatically adds the event to that transaction and invokes the handler, causing the workflow to transition to the `snap` stage.
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
|
|
70
|
+
1. Register the snap handler in your provider's main file:
|
|
71
|
+
```typescript
|
|
72
|
+
const snapHandler = newDirectedTransactionHandler('snap-watcher', snapActionMap);
|
|
73
|
+
client.registerTransactionHandler('snap-watcher', snapHandler);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
2. Register the dealer event source:
|
|
77
|
+
```typescript
|
|
78
|
+
client.registerEventSource('snap-dealer', dealerEventSource);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
3. Start your application to register your provider and handlers with the workflow engine.
|
|
82
|
+
|
|
83
|
+
4. Post the workflow to the workflow engine using the utility scripts:
|
|
84
|
+
```bash
|
|
85
|
+
npm run create-workflow src/samples/snap/flow.ts
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
5. Post the correlation stream to connect the dealer event source to the workflow engine:
|
|
89
|
+
```bash
|
|
90
|
+
npm run create-stream src/samples/snap/stream.ts
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
6. Create a transaction with a suit and rank to set a trap:
|
|
94
|
+
```bash
|
|
95
|
+
npm run create-transaction src/samples/snap/transaction.json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Once configured, the event source will deal cards from a shuffled deck. The correlation stream will evaluate each card event against all inflight transactions. When a card matching a transaction's trap is dealt, the stream will add the event to that transaction, causing the handler to be invoked and the workflow to transition to the `snap` stage, completing the transaction.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Copyright © 2026 Kaleido, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
|
|
17
|
+
import { EventSourceConf, newEventSource, newLogger, WSEventStreamInfo } from "@kaleido-io/workflow-engine-sdk";
|
|
18
|
+
|
|
19
|
+
const log = newLogger('dealer-event-source');
|
|
20
|
+
|
|
21
|
+
export interface PlayingCard {
|
|
22
|
+
description: string;
|
|
23
|
+
suit: string;
|
|
24
|
+
rank: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface DealerEventSourceConfig {
|
|
28
|
+
resetInterval: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const suits = ['clubs', 'diamonds', 'hearts', 'spades'];
|
|
32
|
+
export const ranks = ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'jack', 'queen', 'king'];
|
|
33
|
+
|
|
34
|
+
const newDeck = (): PlayingCard[] => {
|
|
35
|
+
const deck: PlayingCard[] = [];
|
|
36
|
+
for (const suit of suits) {
|
|
37
|
+
for (const rank of ranks) {
|
|
38
|
+
deck.push({
|
|
39
|
+
description: `${rank} of ${suit}`,
|
|
40
|
+
suit,
|
|
41
|
+
rank
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return deck;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const shuffleDeck = (deck: PlayingCard[]): void => {
|
|
49
|
+
for (let i = deck.length - 1; i > 0; i--) {
|
|
50
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
51
|
+
[deck[i], deck[j]] = [deck[j], deck[i]];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let deck: PlayingCard[] = newDeck();
|
|
56
|
+
shuffleDeck(deck);
|
|
57
|
+
|
|
58
|
+
let dealt = 0;
|
|
59
|
+
|
|
60
|
+
interface DealerEventSourceCheckpoint {
|
|
61
|
+
dealt: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const dealerEventSource = newEventSource<DealerEventSourceCheckpoint, DealerEventSourceConfig, PlayingCard>(
|
|
65
|
+
'snap-dealer',
|
|
66
|
+
async (_config: EventSourceConf<DealerEventSourceConfig>, _checkpoint: DealerEventSourceCheckpoint | null) => {
|
|
67
|
+
const toDeal = Math.min(Math.floor(Math.random() * 9) + 1, deck.length - dealt);
|
|
68
|
+
const dealSet = deck.slice(dealt, dealt + toDeal);
|
|
69
|
+
|
|
70
|
+
const events = dealSet.map(card => ({
|
|
71
|
+
idempotencyKey: `${card.suit}-${card.rank}-${Date.now()}-${Math.random()}`,
|
|
72
|
+
topic: `suit.${card.suit}.rank.${card.rank}`,
|
|
73
|
+
data: card
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
dealt += toDeal;
|
|
77
|
+
|
|
78
|
+
log.info(`Dealt ${toDeal} cards, total: ${dealt}/${deck.length}`);
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
checkpointOut: { dealt },
|
|
82
|
+
events
|
|
83
|
+
};
|
|
84
|
+
})
|
|
85
|
+
.withInitialCheckpoint(async () => ({
|
|
86
|
+
dealt: 0
|
|
87
|
+
}))
|
|
88
|
+
.withConfigParser(async (_, config: DealerEventSourceConfig) => {
|
|
89
|
+
log.info('Reset interval:', config.resetInterval || 10000);
|
|
90
|
+
setInterval(() => {
|
|
91
|
+
log.info('Resetting deck');
|
|
92
|
+
deck = newDeck();
|
|
93
|
+
shuffleDeck(deck);
|
|
94
|
+
dealt = 0;
|
|
95
|
+
}, config.resetInterval || 10000);
|
|
96
|
+
return {
|
|
97
|
+
resetInterval: config.resetInterval || 10000
|
|
98
|
+
};
|
|
99
|
+
})
|
|
100
|
+
.withDeleteFn(async (info: WSEventStreamInfo) => {
|
|
101
|
+
log.info(`Cleaning up event source ${info.streamName} (${info.streamId})`);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export const eventSource = dealerEventSource;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Copyright © 2026 Kaleido, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
import provider from '../../provider.js';
|
|
19
|
+
export const flow = {
|
|
20
|
+
"operations": [
|
|
21
|
+
{
|
|
22
|
+
"name": "play",
|
|
23
|
+
"type": "asynchronous",
|
|
24
|
+
"stage": "set-trap",
|
|
25
|
+
"inputSchema": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"properties": {
|
|
28
|
+
"suit": {
|
|
29
|
+
"type": "string"
|
|
30
|
+
},
|
|
31
|
+
"rank": {
|
|
32
|
+
"type": "string"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"required": [
|
|
36
|
+
"suit",
|
|
37
|
+
"rank"
|
|
38
|
+
],
|
|
39
|
+
"additionalProperties": false
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"stages": [
|
|
44
|
+
{
|
|
45
|
+
"name": "set-trap",
|
|
46
|
+
"type": "pending",
|
|
47
|
+
"handler": "watcher",
|
|
48
|
+
"inputMap": {
|
|
49
|
+
"jsonata": "{\n \"action\": \"set-trap\",\n \"nextStage\": \"trap-set\",\n \"failureStage\": \"fail\",\n \"suit\": state.input.suit,\n \"rank\": state.input.rank\n}\n"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "trap-set",
|
|
54
|
+
"type": "pending",
|
|
55
|
+
"handler": "watcher",
|
|
56
|
+
"inputMap": {
|
|
57
|
+
"jsonata": "{\n \"action\": \"trap-set\",\n \"nextStage\": \"success\",\n \"failureStage\": \"fail\",\n \"suit\": state.input.suit,\n \"rank\": state.input.rank\n}\n"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "snap",
|
|
62
|
+
"type": "success"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "fail",
|
|
66
|
+
"type": "failure"
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"events": [
|
|
70
|
+
{
|
|
71
|
+
"name": "played",
|
|
72
|
+
"topicMatch": "suit\\.(.*)\\.rank\\.(.*)",
|
|
73
|
+
"handler": "watcher",
|
|
74
|
+
"inputMap": {
|
|
75
|
+
"jsonata": "{\n \"action\": \"trap-fired\",\n \"nextStage\": \"snap\",\n \"failureStage\": \"fail\",\n \"outputPath\": \"/data\",\n \"suit\": state.input.suit,\n \"rank\": state.input.rank\n}\n"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
"handlerBindings": {
|
|
80
|
+
"watcher": {
|
|
81
|
+
"provider": provider.name,
|
|
82
|
+
"providerHandler": "snap-watcher"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Copyright © 2026 Kaleido, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
|
|
17
|
+
import { BasicStageDirector, EvalResult, InvocationMode, WithStageDirector, WSEvaluateTransaction } from "@kaleido-io/workflow-engine-sdk";
|
|
18
|
+
|
|
19
|
+
import { newLogger } from "@kaleido-io/workflow-engine-sdk";
|
|
20
|
+
|
|
21
|
+
const log = newLogger('snap-handler');
|
|
22
|
+
|
|
23
|
+
class SnapHandlerInput implements WithStageDirector {
|
|
24
|
+
public stageDirector: BasicStageDirector;
|
|
25
|
+
public suit: string;
|
|
26
|
+
public rank: string;
|
|
27
|
+
|
|
28
|
+
constructor(input: any) {
|
|
29
|
+
this.stageDirector = new BasicStageDirector(
|
|
30
|
+
input.action || 'set-trap',
|
|
31
|
+
input.outputPath || '/output',
|
|
32
|
+
input.nextStage || 'success',
|
|
33
|
+
input.failureStage || 'fail'
|
|
34
|
+
);
|
|
35
|
+
this.suit = input.suit;
|
|
36
|
+
this.rank = input.rank;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getStageDirector() {
|
|
40
|
+
return this.stageDirector;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const trapsSet = new Map<string, boolean>();
|
|
44
|
+
|
|
45
|
+
const map = new Map();
|
|
46
|
+
|
|
47
|
+
// Set trap action
|
|
48
|
+
map.set('set-trap', {
|
|
49
|
+
invocationMode: InvocationMode.PARALLEL,
|
|
50
|
+
handler: async (transaction: WSEvaluateTransaction, input: SnapHandlerInput) => {
|
|
51
|
+
const cardTopic = `suit.${input.suit}.rank.${input.rank}`;
|
|
52
|
+
return {
|
|
53
|
+
result: EvalResult.COMPLETE,
|
|
54
|
+
triggers: [{ topic: cardTopic }]
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Trap set action
|
|
60
|
+
map.set('trap-set', {
|
|
61
|
+
invocationMode: InvocationMode.PARALLEL,
|
|
62
|
+
handler: async (transaction: WSEvaluateTransaction, input: SnapHandlerInput) => {
|
|
63
|
+
const cardTopic = `suit.${input.suit}.rank.${input.rank}`;
|
|
64
|
+
log.info(`Trap set: ${cardTopic}`);
|
|
65
|
+
trapsSet.set(cardTopic, true);
|
|
66
|
+
return {
|
|
67
|
+
result: EvalResult.WAITING
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Trap fired action
|
|
73
|
+
map.set('trap-fired', {
|
|
74
|
+
invocationMode: InvocationMode.PARALLEL,
|
|
75
|
+
handler: async (transaction: WSEvaluateTransaction, _input: SnapHandlerInput) => {
|
|
76
|
+
const snap = transaction.events![0];
|
|
77
|
+
return {
|
|
78
|
+
result: EvalResult.COMPLETE,
|
|
79
|
+
output: snap.data
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export const actionMap = map;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright © 2026 Kaleido, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
|
|
17
|
+
import provider from '../../provider.js';
|
|
18
|
+
|
|
19
|
+
export const stream = {
|
|
20
|
+
name: 'snap-dealer-stream',
|
|
21
|
+
started: true,
|
|
22
|
+
type: 'correlation_stream',
|
|
23
|
+
listenerHandler: 'snap-dealer',
|
|
24
|
+
listenerHandlerProvider: provider.name,
|
|
25
|
+
config: { resetInterval: 10000 }
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright © 2026 Kaleido, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
|
|
17
|
+
import { suits, ranks } from "./event-source.js";
|
|
18
|
+
|
|
19
|
+
export const transaction = {
|
|
20
|
+
"input": {
|
|
21
|
+
"suit": suits[Math.floor(Math.random() * suits.length)],
|
|
22
|
+
"rank": ranks[Math.floor(Math.random() * ranks.length)]
|
|
23
|
+
},
|
|
24
|
+
"operation": "play",
|
|
25
|
+
"workflow": "snap-flow"
|
|
26
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Copyright © 2026 Kaleido, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
CreateStreamRequest,
|
|
20
|
+
WorkflowEngineRestClient
|
|
21
|
+
} from '@kaleido-io/workflow-engine-sdk';
|
|
22
|
+
|
|
23
|
+
import dotenv from 'dotenv';
|
|
24
|
+
|
|
25
|
+
dotenv.config();
|
|
26
|
+
async function main() {
|
|
27
|
+
try {
|
|
28
|
+
// Get the flow name from command line arguments
|
|
29
|
+
const streamPath = process.argv[2];
|
|
30
|
+
|
|
31
|
+
if (!streamPath) {
|
|
32
|
+
console.error('Error: Please provide a stream TypeScript file as an argument.');
|
|
33
|
+
console.error('Usage: tsx post-stream.ts <stream>');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Import the workflow from the TypeScript file
|
|
38
|
+
let stream: CreateStreamRequest;
|
|
39
|
+
try {
|
|
40
|
+
const streamModule = await import(`../../${streamPath}`);
|
|
41
|
+
if (!streamModule.stream) {
|
|
42
|
+
console.error(`Error: The file ${streamPath} does not export a 'stream' constant.`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
stream = streamModule.stream;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(`Error importing stream file at ${streamPath}:`, error);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log('Posting stream:', JSON.stringify(stream, null, 2));
|
|
52
|
+
|
|
53
|
+
// Create the workflow engine REST client
|
|
54
|
+
const client = new WorkflowEngineRestClient();
|
|
55
|
+
|
|
56
|
+
// Post the workflow
|
|
57
|
+
const response = await client.createStream(stream);
|
|
58
|
+
|
|
59
|
+
console.log('Stream posted successfully!');
|
|
60
|
+
console.log('Response:', JSON.stringify(response, null, 2));
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error('Error posting stream:', error);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
main();
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Copyright © 2026 Kaleido, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
import { WorkflowEngineRestClient, CreateTransactionRequest } from '@kaleido-io/workflow-engine-sdk';
|
|
19
|
+
import dotenv from 'dotenv';
|
|
20
|
+
|
|
21
|
+
dotenv.config();
|
|
22
|
+
|
|
23
|
+
async function main() {
|
|
24
|
+
try {
|
|
25
|
+
// Get the flow name from command line arguments
|
|
26
|
+
const transactionPath = process.argv[2];
|
|
27
|
+
|
|
28
|
+
if (!transactionPath) {
|
|
29
|
+
console.error('Error: Please provide a transaction JSON file as an argument.');
|
|
30
|
+
console.error('Usage: tsx post-transaction.ts <transaction>');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Import the transaction from the TypeScript file
|
|
35
|
+
let transaction: CreateTransactionRequest;
|
|
36
|
+
try {
|
|
37
|
+
const transactionModule = await import(`../../${transactionPath}`);
|
|
38
|
+
if (!transactionModule.transaction) {
|
|
39
|
+
console.error(`Error: The file ${transactionPath} does not export a 'transaction' constant.`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
transaction = transactionModule.transaction;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error(`Error importing transaction file at ${transactionPath}:`, error);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log('Posting transaction:', JSON.stringify(transaction, null, 2));
|
|
49
|
+
|
|
50
|
+
// Create the transaction engine REST client
|
|
51
|
+
const client = new WorkflowEngineRestClient();
|
|
52
|
+
|
|
53
|
+
// Post the transaction
|
|
54
|
+
const response = await client.createTransaction(transaction);
|
|
55
|
+
|
|
56
|
+
console.log('Transaction posted successfully!');
|
|
57
|
+
console.log('Response:', JSON.stringify(response, null, 2));
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error('Error posting transaction:', error);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
main();
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright © 2026 Kaleido, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
import { WorkflowEngineRestClient, CreateWorkflowRequest } from '@kaleido-io/workflow-engine-sdk';
|
|
19
|
+
import dotenv from 'dotenv';
|
|
20
|
+
|
|
21
|
+
dotenv.config();
|
|
22
|
+
async function main() {
|
|
23
|
+
try {
|
|
24
|
+
// Get the flow name from command line arguments
|
|
25
|
+
const workflowPath = process.argv[2];
|
|
26
|
+
|
|
27
|
+
if (!workflowPath) {
|
|
28
|
+
console.error('Error: Please provide a workflow TypeScript file as an argument.');
|
|
29
|
+
console.error('Usage: tsx post-workflow.ts <workflow>');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Import the workflow from the TypeScript file
|
|
34
|
+
let workflow: CreateWorkflowRequest;
|
|
35
|
+
try {
|
|
36
|
+
const workflowModule = await import(`../../${workflowPath}`);
|
|
37
|
+
if (!workflowModule.flow) {
|
|
38
|
+
console.error(`Error: The file ${workflowPath} does not export a 'flow' constant.`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
workflow = workflowModule.flow;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(`Error importing workflow file at ${workflowPath}:`, error);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log('Posting workflow:', JSON.stringify(workflow, null, 2));
|
|
48
|
+
|
|
49
|
+
// Create the workflow engine REST client
|
|
50
|
+
const client = new WorkflowEngineRestClient();
|
|
51
|
+
|
|
52
|
+
// Post the workflow
|
|
53
|
+
const response = await client.createWorkflow(workflow);
|
|
54
|
+
|
|
55
|
+
console.log('Workflow posted successfully!');
|
|
56
|
+
console.log('Response:', JSON.stringify(response, null, 2));
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error('Error posting workflow:', error);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
main();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "nodenext",
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"allowSyntheticDefaultImports": true,
|
|
8
|
+
"strict": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"outDir": "./dist",
|
|
13
|
+
"rootDir": "./",
|
|
14
|
+
"baseUrl": "./"
|
|
15
|
+
},
|
|
16
|
+
"include": [
|
|
17
|
+
"**/*.ts"
|
|
18
|
+
],
|
|
19
|
+
"exclude": [
|
|
20
|
+
"**/*.test.ts",
|
|
21
|
+
"node_modules",
|
|
22
|
+
"dist"
|
|
23
|
+
]
|
|
24
|
+
}
|