Skip to content

Commit

Permalink
feat(overmind): statemachines now has explicit effects and state call…
Browse files Browse the repository at this point in the history
…back
  • Loading branch information
christianalfoni committed Sep 21, 2020
1 parent e676aa2 commit cb4c6bf
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 7 deletions.
38 changes: 38 additions & 0 deletions packages/node_modules/overmind/src/statemachine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,4 +456,42 @@ describe('Statemachine', () => {

expect(() => overmind.actions.transition()).not.toThrow()
})
test('should deal with transition effects', async () => {
type States = {
current: 'FOO'
} | {
current: 'BAR',
number: number
}

const state = statemachine<States>({
FOO: ['BAR'],
BAR: ['FOO']
}, {
current: 'FOO',
})
const transition: Action = ({ state }) => {
return state.transition('BAR', { number: 123 }, () => {
return Promise.resolve(4321)
}, (barState, value) => {
barState.number = value
})
}

const config = {
state,
actions: {
transition
}
}

interface Action extends IAction<typeof config, void, Promise<void>> {}

const overmind = createOvermindMock(config)
// @ts-ignore
overmind.isStrict = true

await overmind.actions.transition()
expect(overmind.state.current === 'BAR' && overmind.state.number === 4321).toBe(true)
})
})
29 changes: 22 additions & 7 deletions packages/node_modules/overmind/src/statemachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,18 @@ export interface MachineMethods<States extends TStates, Base extends IState = {}
matches<T extends States["current"], O = void>(state: T | T[], cb: (current: Statemachine<Base, States, States extends {
current: T
} ? States : never>) => O): O;
transition<T extends States["current"], O = void>(
transition<T extends States["current"], O = void, O2 = O>(
state: T,
newState: States extends {
current: T
} ? Exact<Omit<States, 'current'>, {}> extends never ? Omit<States, 'current'> & Partial<Base> : Exact<Partial<Base>, {}> extends never ? Partial<Base> : { [NO_PROP]?: true} : never,
callback?: ((current: Statemachine<Base, States, States extends {
effectsCallback?: ((current: Statemachine<Base, States, States extends {
current: T
} ? States : never>) => O)
): O;
} ? States : never>) => O),
stateCallback?: ((current: Statemachine<Base, States, States extends {
current: T
} ? States : never>, value: O extends Promise<infer V> ? V : O) => O2)
): O extends Promise<any> ? Promise<O2> : O2;
}

export type Statemachine<Base extends IState, States extends TStates, State extends TStates = States> = Base extends never ? State & MachineMethods<States> : Base & State & MachineMethods<States, Base>
Expand Down Expand Up @@ -86,7 +89,7 @@ export class StateMachine<Base extends IState, States extends TStates, State ext
return result
}
}
transition(state, newState, callback) {
transition(state, newState, effectsCallback, stateCallback) {
const transitions = this[VALUE][TRANSITIONS]

if (transitions[this.current].includes(state)) {
Expand All @@ -108,8 +111,20 @@ export class StateMachine<Base extends IState, States extends TStates, State ext
tree.blockMutations()

let result
if (callback) {
result = callback(this)
if (effectsCallback) {
result = effectsCallback(this)
}

if (stateCallback && result instanceof Promise) {
return result.then((value) => {
if (this.current !== state) {
return value
}
tree.enableMutations()
const result = stateCallback(this, value)
tree.blockMutations()
return result
})
}

return result
Expand Down

0 comments on commit cb4c6bf

Please sign in to comment.