Skip to content

Commit b7d365e

Browse files
feat(overmind): statemachines best of both worlds
BREAKING CHANGE: instead of generic single signature, we now have two signatures
1 parent 574e486 commit b7d365e

File tree

2 files changed

+65
-30
lines changed

2 files changed

+65
-30
lines changed

packages/node_modules/overmind/src/statemachine.test.ts

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ describe('Statemachine', () => {
1212
}
1313

1414
const state = statemachine<States, { type: 'TEST'}>({
15-
TEST: () => {}
15+
FOO: {},
16+
BAR: {}
1617
}).create({
1718
current: 'FOO'
1819
})
19-
2020

2121
const config = {
2222
state,
@@ -40,7 +40,8 @@ describe('Statemachine', () => {
4040
}
4141

4242
const state = statemachine<States, { type: 'TEST' }, BaseState>({
43-
TEST: () => {}
43+
FOO: {},
44+
BAR: {}
4445
}).create({
4546
current: 'FOO',
4647
}, {
@@ -59,7 +60,7 @@ describe('Statemachine', () => {
5960
})
6061

6162

62-
test('should transition state', () => {
63+
test('should transition state using function', () => {
6364
type States = {
6465
current: 'FOO'
6566
} | {
@@ -70,8 +71,8 @@ describe('Statemachine', () => {
7071
type: 'TOGGLE',
7172
}
7273

73-
const state = statemachine<States, Events>({
74-
TOGGLE: (state) => ({ current: state.current === 'FOO' ? 'BAR' : 'FOO' })
74+
const state = statemachine<States, Events>((_, state) => {
75+
return ({ current: state.current === 'FOO' ? 'BAR' : 'FOO' })
7576
}).create({
7677
current: 'FOO'
7778
})
@@ -111,7 +112,12 @@ describe('Statemachine', () => {
111112
}
112113

113114
const state = statemachine<States, Events>({
114-
TOGGLE: () => ({ current: 'BAR' })
115+
FOO: {
116+
TOGGLE: () => ({ current: 'BAR' })
117+
},
118+
BAR: {
119+
TOGGLE: () => ({ current: 'FOO', foo: 'foo' })
120+
}
115121
}).create({
116122
current: 'FOO',
117123
foo: 'bar'
@@ -154,14 +160,12 @@ describe('Statemachine', () => {
154160
type: 'TOGGLE',
155161
}
156162

157-
const state = statemachine<States, Events>({
158-
TOGGLE: (state) => {
159-
if (state.current === 'FOO') {
160-
return { current: 'BAR' }
161-
}
162-
163-
return { current: 'FOO', foo: 'bar'}
163+
const state = statemachine<States, Events>((_, state) => {
164+
if (state.current === 'FOO') {
165+
return { current: 'BAR' }
164166
}
167+
168+
return { current: 'FOO', foo: 'bar'}
165169
}).create({
166170
current: 'FOO',
167171
foo: 'bar'
@@ -204,7 +208,12 @@ describe('Statemachine', () => {
204208
}
205209

206210
const state = statemachine<States, Events>({
207-
TOGGLE: () => {}
211+
FOO: {
212+
TOGGLE: () => {}
213+
},
214+
BAR: {
215+
TOGGLE: () => {}
216+
}
208217
}).create({
209218
current: 'FOO'
210219
})
@@ -247,7 +256,10 @@ describe('Statemachine', () => {
247256
}
248257

249258
const state = statemachine<States, Events>({
250-
TOGGLE: () => ({ current: 'BAR' })
259+
FOO: {
260+
TOGGLE: () => ({ current: 'BAR' })
261+
},
262+
BAR: {}
251263
}).create({
252264
current: 'FOO'
253265
})
@@ -289,7 +301,12 @@ describe('Statemachine', () => {
289301
}
290302

291303
const state = statemachine<States, { type: 'TEST'}>({
292-
TEST: () => {}
304+
FOO: {
305+
TEST: () => {}
306+
},
307+
BAR: {
308+
TEST: () => {}
309+
}
293310
}).create({
294311
current: 'FOO',
295312
obj: {

packages/node_modules/overmind/src/statemachine.ts

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,25 @@ export type StatemachineTransitions<
2020
States extends TState,
2121
Events extends TEvents,
2222
BaseState extends TBaseState
23-
> = {
24-
[Type in Events['type']]: [BaseState] extends [never]
25-
? ((
26-
state: States,
27-
payload: Events extends { type: Type } ? Events['data'] : never
28-
) => States | void)
29-
: ((
30-
state: States & BaseState,
31-
payload: Events extends { type: Type } ? Events['data'] : never
32-
) => States | void)
33-
}
23+
> =
24+
| ([BaseState] extends [never]
25+
? (event: Events, state: States) => States | void
26+
: (event: Events, state: States & BaseState) => States | void)
27+
| {
28+
[State in States['current']]: {
29+
[Type in Events['type']]?: [BaseState] extends [never]
30+
? ((
31+
state: States extends { current: State } ? States : never,
32+
payload: Events extends { type: Type } ? Events['data'] : never
33+
) => States | void)
34+
: ((
35+
state: States extends { current: State }
36+
? States & BaseState
37+
: never,
38+
payload: Events extends { type: Type } ? Events['data'] : never
39+
) => States | void)
40+
}
41+
}
3442

3543
export interface MachineMethods<
3644
States extends TState,
@@ -147,10 +155,20 @@ export class StateMachine<
147155
}
148156

149157
const tree = this[PROXY_TREE].master.mutationTree || this[PROXY_TREE]
150-
const transition = this[VALUE][TRANSITIONS][type]
151158

152159
tree.enableMutations()
153-
const result = transition(this, data)
160+
161+
let result
162+
163+
if (typeof this[VALUE][TRANSITIONS] === 'function') {
164+
const transition = this[VALUE][TRANSITIONS]
165+
166+
result = transition({ type, data }, this)
167+
} else {
168+
const transition = this[VALUE][TRANSITIONS][this[VALUE].current][type]
169+
170+
result = transition(data, this)
171+
}
154172

155173
if (result) {
156174
this[VALUE][CURRENT_KEYS].forEach((key) => {

0 commit comments

Comments
 (0)