Last active
April 3, 2020 23:15
-
-
Save dsebastien/e66e863ccc7104ab88db37fdddbdd314 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Machine, StateSchema} from 'xstate'; | |
// TODO review/improve based on: https://xstate.js.org/docs/guides/typescript.html#using-typescript | |
/** | |
* Extended state of the machine (if any) | |
* Reference: https://xstate.js.org/docs/guides/context.html | |
*/ | |
// tslint:disable-next-line:no-empty-interface | |
interface MeetingStateMachineContext {} | |
/** | |
* The different states | |
*/ | |
export enum MeetingState { | |
DRAFT = "draft", | |
DELETED = 'deleted', | |
PLANNED = 'planned', | |
STARTED = 'started', | |
CANCELLED = 'cancelled', | |
ONGOING = 'ongoing', | |
PAUSED = 'paused', | |
FINISHED = 'finished', | |
FROZEN = 'frozen', | |
} | |
/** | |
* Supported event names | |
*/ | |
export enum MeetingStateMachineEventName { | |
DELETE = "DELETE", | |
SEND_INVITES = "SEND_INVITES", | |
START_WITHOUT_INVITES = "START_WITHOUT_INVITES", | |
CANCEL = "CANCEL", | |
PREPARE_START = "PREPARE_START", | |
START = "START", | |
PAUSE = "PAUSE", | |
UNPAUSE = "UNPAUSE", | |
STOP = "STOP", | |
FREEZE = "FREEZE", | |
} | |
/** | |
* Supported event types. | |
* Each can have additional properties if needed | |
*/ | |
type MeetingStateMachineEvent = | |
{ type: MeetingStateMachineEventName.DELETE } | | |
{ type: MeetingStateMachineEventName.SEND_INVITES } | | |
{ type: MeetingStateMachineEventName.START_WITHOUT_INVITES } | | |
{ type: MeetingStateMachineEventName.CANCEL } | | |
{ type: MeetingStateMachineEventName.PREPARE_START } | | |
{ type: MeetingStateMachineEventName.START } | | |
{ type: MeetingStateMachineEventName.PAUSE } | | |
{ type: MeetingStateMachineEventName.UNPAUSE } | | |
{ type: MeetingStateMachineEventName.STOP } | | |
{ type: MeetingStateMachineEventName.FREEZE }; | |
// type MeetingStateMachineEvent = | |
// { type: 'DELETE'} | | |
// { type: 'SEND_INVITES' } | | |
// { type: 'START_WITHOUT_INVITES' } | | |
// { type: 'CANCEL' } | | |
// { type: 'PREPARE_START' } | | |
// { type: 'START' } | | |
// { type: 'PAUSE' } | | |
// { type: 'UNPAUSE' } | | |
// { type: 'STOP' } | | |
// { type: 'FREEZE' }; | |
interface MeetingStateTransitionList extends StateSchema { | |
on?: { | |
[key in MeetingStateMachineEventName]: MeetingState; | |
} | |
} | |
interface MeetingStateMachineSchema extends StateSchema<MeetingStateTransitionList> { | |
states: { | |
[key in MeetingState]: MeetingStateTransitionList; | |
}, | |
} | |
/** | |
* State machine for meetings | |
*/ | |
export const meetingStateMachineDefinitionV1 = Machine<MeetingStateMachineContext, MeetingStateMachineSchema, MeetingStateMachineEvent>({ | |
version: "1", // WARNING: MUST be incremented whenever the structure changes | |
id: 'meetings', | |
initial: MeetingState.DRAFT, | |
strict: true, | |
context: { | |
}, | |
states: { | |
[MeetingState.DRAFT]: { | |
on: { | |
[MeetingStateMachineEventName.DELETE]: MeetingState.DELETED, | |
[MeetingStateMachineEventName.SEND_INVITES]: MeetingState.PLANNED, | |
[MeetingStateMachineEventName.START_WITHOUT_INVITES]: MeetingState.STARTED, | |
} | |
}, | |
[MeetingState.DELETED]: { | |
type: 'final' | |
}, | |
[MeetingState.PLANNED]: { | |
on: { | |
[MeetingStateMachineEventName.CANCEL]: MeetingState.CANCELLED, | |
[MeetingStateMachineEventName.PREPARE_START]: MeetingState.STARTED // replace PREPARE_START with '' to have an automatic transition | |
} | |
}, | |
[MeetingState.CANCELLED]: { | |
type: 'final' | |
}, | |
[MeetingState.STARTED]: { | |
on: { | |
[MeetingStateMachineEventName.START]: MeetingState.ONGOING, | |
} | |
}, | |
[MeetingState.ONGOING]: { | |
on: { | |
[MeetingStateMachineEventName.PAUSE]: MeetingState.PAUSED, | |
[MeetingStateMachineEventName.STOP]: MeetingState.FINISHED, | |
} | |
}, | |
[MeetingState.PAUSED]: { | |
on: { | |
[MeetingStateMachineEventName.UNPAUSE]: MeetingState.ONGOING, | |
} | |
}, | |
[MeetingState.FINISHED]: { | |
on: { | |
[MeetingStateMachineEventName.FREEZE]: MeetingState.FROZEN, | |
} | |
}, | |
[MeetingState.FROZEN]: { | |
type: 'final' | |
} | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const dummyMeetingStateMachine = interpret(meetingStateMachineDefinitionV1) | |
//.onTransition(state => console.log(state.value)) | |
.start(); | |
//console.log("Initial state: ", meetingStateMachineDefinitionV1.initialState); | |
const currentState = dummyMeetingStateMachine.state; | |
console.log("Next (allowed) events: ", currentState.nextEvents); | |
const canDelete = currentState.nextEvents.includes(MeetingStateMachineEvent.DELETE); | |
console.log("Can delete? ", canDelete); // true | |
const eventResult = dummyMeetingStateMachine.send( {type: MeetingStateMachineEvent.DELETE}).changed; | |
console.log("Delete event accepted?: ", eventResult); | |
//console.log(dummyMeetingStateMachine.state); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment