Skip to content

Commit 20c6b4b

Browse files
authored
0.3.1. (#4)
* 0.3.1.
1 parent f4cc713 commit 20c6b4b

File tree

6 files changed

+91
-8
lines changed

6 files changed

+91
-8
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## 0.3.1
2+
3+
This version adds a new feature to the `break` activity. Now it is possible to break a parent loop without specifying the name of the loop. The previous approach is still supported.
4+
5+
```ts
6+
createBreakActivity<BreakStep>('break', {
7+
loopName: (step) => -1,
8+
// ...
9+
});
10+
```
11+
112
## 0.3.0
213

314
This version changes the syntax of all `create*Activity` functions. The first argument is the step type, the second argument is the configuration.

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.3.0",
4+
"version": "0.3.1",
55
"type": "module",
66
"main": "./lib/esm/index.js",
77
"types": "./lib/index.d.ts",

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ export class BreakActivityNodeBuilder<TStep extends Step, TGlobalState, TActivit
2626
});
2727
const nodeId = getStepNodeId(step.id);
2828

29-
const loopName = this.config.loopName(step);
30-
const leaveNodeTarget = getLoopStack(buildingContext).getNodeTarget(loopName);
29+
const loopNameOrIndex = this.config.loopName(step);
30+
const leaveNodeTarget = getLoopStack(buildingContext).getNodeTarget(loopNameOrIndex);
3131

3232
return {
3333
id: nodeId,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export type BreakActivityHandler<TStep extends Step, TGlobalState, TActivityStat
1212
export type BreakActivityHandlerResult = void | InterruptResult | BreakResult;
1313

1414
export interface BreakActivityConfig<TStep extends Step, TGlobalState, TActivityState extends object> {
15-
loopName: (step: TStep) => string;
15+
loopName: (step: TStep) => string | -1;
1616
init: ActivityStateInitializer<TStep, TGlobalState, TActivityState>;
1717
handler: BreakActivityHandler<TStep, TGlobalState, TActivityState>;
1818
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { LoopStack } from './loop-stack';
2+
3+
describe('LoopStack', () => {
4+
describe('when stack contains 3 loops', () => {
5+
let stack: LoopStack;
6+
7+
beforeEach(() => {
8+
stack = new LoopStack();
9+
stack.push('loop1', 'leave1');
10+
stack.push('loop2', 'leave2');
11+
stack.push('loop3', 'leave3');
12+
});
13+
14+
it('returns proper target when argument is name', () => {
15+
expect(stack.getNodeTarget('loop1')).toBe('leave1');
16+
expect(stack.getNodeTarget('loop2')).toBe('leave2');
17+
expect(stack.getNodeTarget('loop3')).toBe('leave3');
18+
});
19+
20+
it('returns proper target when argument is name', () => {
21+
expect(stack.getNodeTarget(-1)).toBe('leave3');
22+
});
23+
24+
it('throws error when index is 0', () => {
25+
expect(() => stack.getNodeTarget(0 as unknown as -1)).toThrowError('Index 0 is not supported');
26+
});
27+
28+
it('throws error when index is 1', () => {
29+
expect(() => stack.getNodeTarget(1 as unknown as -1)).toThrowError('Index 1 is not supported');
30+
});
31+
32+
it('throws error when name is not found', () => {
33+
expect(() => stack.getNodeTarget('foo')).toThrowError('Loop "foo" not found');
34+
});
35+
36+
it('pop() removes last item', () => {
37+
expect(stack.getCurrentName()).toBe('loop3');
38+
39+
stack.pop();
40+
expect(stack.getCurrentName()).toBe('loop2');
41+
42+
stack.pop();
43+
expect(stack.getCurrentName()).toBe('loop1');
44+
45+
stack.pop();
46+
expect(stack.getCurrentName()).toBe(null);
47+
});
48+
});
49+
50+
describe('when stack is empty', () => {
51+
it('throws error when index is -1', () => {
52+
const stack = new LoopStack();
53+
expect(() => stack.getNodeTarget(-1)).toThrowError('Cannot find any parent loop');
54+
});
55+
});
56+
});

machine/src/activities/loop-stack.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,26 @@ export class LoopStack {
3434
this.stack.pop();
3535
}
3636

37-
public getNodeTarget(name: string): string {
38-
const item = this.stack.find(item => item.name === name);
39-
if (!item) {
40-
throw new Error(`Loop with name "${name}" not found`);
37+
public getCurrentName(): string | null {
38+
const item = this.stack[this.stack.length - 1];
39+
return item ? item.name : null;
40+
}
41+
42+
public getNodeTarget(nameOrIndex: string | -1): string {
43+
let item: LoopStackItem | undefined;
44+
if (typeof nameOrIndex === 'number') {
45+
if (nameOrIndex !== -1) {
46+
throw new Error(`Index ${nameOrIndex} is not supported`);
47+
}
48+
item = this.stack[this.stack.length - 1];
49+
if (!item) {
50+
throw new Error('Cannot find any parent loop');
51+
}
52+
} else {
53+
item = this.stack.find(item => item.name === nameOrIndex);
54+
if (!item) {
55+
throw new Error(`Loop "${nameOrIndex}" not found`);
56+
}
4157
}
4258
return item.leaveNodeTarget;
4359
}

0 commit comments

Comments
 (0)