Skip to content

Commit 283834b

Browse files
authored
0.5.1. (#8)
1 parent c945fac commit 283834b

File tree

9 files changed

+88
-14
lines changed

9 files changed

+88
-14
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
## 0.5.1
2+
3+
This version adds a new feature to the `fork` activity. Now it's possible to skip all branches. The handler of the `fork` activity should return a value returned by the `skip()` function.
4+
5+
```js
6+
createForkActivity<BranchedStep, TestGlobalState>('if', {
7+
init: () => ({ /* ... */ }),
8+
handler: async (step, globalState, activityState) => {
9+
// ...
10+
return skip();
11+
}
12+
})
13+
```
14+
115
## 0.5.0
216

317
This version simplifies error handling:

machine/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "sequential-workflow-machine",
33
"description": "Powerful sequential workflow machine for frontend and backend applications.",
4-
"version": "0.5.0",
4+
"version": "0.5.1",
55
"type": "module",
66
"main": "./lib/esm/index.js",
77
"types": "./lib/index.d.ts",

machine/src/activities/fork-activity/fork-activity-node-builder.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { getBranchNodeId, getStepNodeId } from '../../core/safe-node-id';
1414
import { BranchedStep } from 'sequential-workflow-model';
1515
import { isBranchNameResult } from '../results/branch-name-result';
1616
import { isInterruptResult } from '../results/interrupt-result';
17+
import { isSkipResult } from '../results';
1718

1819
export class ForkActivityNodeBuilder<TStep extends BranchedStep, TGlobalState, TActivityState extends object>
1920
implements ActivityNodeBuilder<TGlobalState>
@@ -55,6 +56,13 @@ export class ForkActivityNodeBuilder<TStep extends BranchedStep, TGlobalState, T
5556
throw new Error(`Branch ${result.branchName} does not exist`);
5657
}
5758
internalState.targetBranchName = result.branchName;
59+
internalState.skipped = undefined;
60+
return;
61+
}
62+
63+
if (isSkipResult(result)) {
64+
internalState.targetBranchName = undefined;
65+
internalState.skipped = true;
5866
return;
5967
}
6068

@@ -65,6 +73,13 @@ export class ForkActivityNodeBuilder<TStep extends BranchedStep, TGlobalState, T
6573
target: STATE_INTERRUPTED_TARGET,
6674
cond: (context: MachineContext<TGlobalState>) => Boolean(context.interrupted)
6775
},
76+
{
77+
target: nextNodeTarget,
78+
cond: (context: MachineContext<TGlobalState>) => {
79+
const activityState = activityStateProvider.get(context, nodeId);
80+
return Boolean(activityState.skipped);
81+
}
82+
},
6883
...branchNames.map(branchName => {
6984
return {
7085
target: getBranchNodeId(branchName),

machine/src/activities/fork-activity/fork-activity.spec.ts

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import { createForkActivity } from './fork-activity';
55
import { BranchedStep, Definition, Step } from 'sequential-workflow-model';
66
import { interrupt } from '../results/interrupt-result';
77
import { branchName } from '../results/branch-name-result';
8+
import { skip } from '../results';
89

910
interface TestGlobalState {
10-
temperature: number;
11+
mode: string;
1112
message: string;
1213
}
1314

@@ -52,16 +53,22 @@ const activitySet = createActivitySet<TestGlobalState>([
5253
createForkActivity<BranchedStep, TestGlobalState>('if', {
5354
init: () => ({}),
5455
handler: async (_, globalState) => {
55-
if (isNaN(globalState.temperature)) {
56-
throw new Error('TEST_ERROR');
57-
}
58-
if (globalState.temperature < 0) {
56+
if (globalState.mode === '[interrupt]') {
5957
return interrupt();
6058
}
61-
if (globalState.temperature > 10) {
59+
if (globalState.mode === '[fail]') {
60+
throw new Error('TEST_ERROR');
61+
}
62+
if (globalState.mode === '[true]') {
6263
return branchName('true');
6364
}
64-
return branchName('false');
65+
if (globalState.mode === '[false]') {
66+
return branchName('false');
67+
}
68+
if (globalState.mode === '[skip]') {
69+
return skip();
70+
}
71+
throw new Error('Unknown mode');
6572
}
6673
})
6774
]);
@@ -77,7 +84,7 @@ function run(definition: Definition, startGlobalState: TestGlobalState) {
7784
describe('ForkActivity', () => {
7885
it('should go by false branch', done => {
7986
const startGlobalState: TestGlobalState = {
80-
temperature: 0,
87+
mode: '[false]',
8188
message: ''
8289
};
8390

@@ -95,7 +102,7 @@ describe('ForkActivity', () => {
95102

96103
it('should go by true branch', done => {
97104
const startGlobalState: TestGlobalState = {
98-
temperature: 20,
105+
mode: '[true]',
99106
message: ''
100107
};
101108

@@ -114,7 +121,7 @@ describe('ForkActivity', () => {
114121

115122
it('should interrupt', done => {
116123
const startGlobalState: TestGlobalState = {
117-
temperature: -20,
124+
mode: '[interrupt]',
118125
message: ''
119126
};
120127

@@ -131,9 +138,30 @@ describe('ForkActivity', () => {
131138
interpreter.start();
132139
});
133140

141+
it('should skip', done => {
142+
const startGlobalState: TestGlobalState = {
143+
mode: '[skip]',
144+
message: ''
145+
};
146+
147+
const interpreter = run(definition, startGlobalState);
148+
149+
interpreter.onDone(() => {
150+
const snapshot = interpreter.getSnapshot();
151+
152+
expect(snapshot.isFinished()).toBe(true);
153+
expect(snapshot.isInterrupted()).toBe(false);
154+
expect(snapshot.isFailed()).toBe(false);
155+
expect(snapshot.globalState.message).toBe('(start)(end)');
156+
157+
done();
158+
});
159+
interpreter.start();
160+
});
161+
134162
it('should fail', done => {
135163
const startGlobalState: TestGlobalState = {
136-
temperature: NaN,
164+
mode: '[fail]',
137165
message: ''
138166
};
139167

@@ -143,6 +171,8 @@ describe('ForkActivity', () => {
143171
const snapshot = interpreter.getSnapshot();
144172

145173
expect(snapshot.isFailed()).toBe(true);
174+
expect(snapshot.isInterrupted()).toBe(false);
175+
expect(snapshot.isFinished()).toBe(false);
146176
expect(snapshot.unhandledError?.message).toBe('TEST_ERROR');
147177
expect(snapshot.unhandledError?.stepId).toBe('0x002');
148178
expect(snapshot.globalState.message).toBe('(start)');

machine/src/activities/fork-activity/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { BranchedStep } from 'sequential-workflow-model';
22
import { ActivityStateInitializer } from '../../types';
33
import { InterruptResult } from '../results/interrupt-result';
44
import { BranchNameResult } from '../results/branch-name-result';
5+
import { SkipResult } from '../results';
56

6-
export type ForkActivityHandlerResult = InterruptResult | BranchNameResult;
7+
export type ForkActivityHandlerResult = InterruptResult | BranchNameResult | SkipResult;
78
export type ForkActivityHandler<TStep extends BranchedStep, TGlobalState, TActivityState> = (
89
step: TStep,
910
globalState: TGlobalState,
@@ -17,5 +18,6 @@ export interface ForkActivityConfig<TStep extends BranchedStep, TGlobalState, TA
1718

1819
export interface ForkActivityState<TActivityState> {
1920
targetBranchName?: string;
21+
skipped?: true;
2022
activityState: TActivityState;
2123
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './branch-name-result';
22
export * from './interrupt-result';
3+
export * from './skip-result';

machine/src/activities/results/interrupt-result.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export interface InterruptResult {
33
}
44

55
export function isInterruptResult(result: unknown): result is InterruptResult {
6-
return typeof result === 'object' && (result as InterruptResult).interrupt;
6+
return typeof result === 'object' && (result as InterruptResult).interrupt === true;
77
}
88

99
export function interrupt(): InterruptResult {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export interface SkipResult {
2+
skip: true;
3+
}
4+
5+
export function isSkipResult(result: unknown): result is SkipResult {
6+
return typeof result === 'object' && (result as SkipResult).skip === true;
7+
}
8+
9+
export function skip(): SkipResult {
10+
return { skip: true };
11+
}

machine/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './activities';
22
export * from './core';
3+
export * from './machine-unhandled-error';
34
export * from './types';
45
export * from './core/activity-set';
56
export * from './workflow-machine-builder';

0 commit comments

Comments
 (0)