Skip to content

Instantly share code, notes, and snippets.

@colebemis
Last active March 28, 2020 20:02
Show Gist options
  • Save colebemis/94600ad030c25f65251e6a4ab9215fd5 to your computer and use it in GitHub Desktop.
Save colebemis/94600ad030c25f65251e6a4ab9215fd5 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
// Available variables:
// - Machine
// - interpret
// - assign
// - send
// - sendParent
// - spawn
// - raise
// - actions
// - XState (all XState exports)
const commitMachine = Machine(
{
id: 'commit',
initial: 'authenticating',
context: {
accessToken: '',
username: '',
branches: [],
selection: [],
commitMessage: '',
defaultCommitMessage: '',
newBranchName: '',
existingBranchName: '',
error: ''
},
on: {
SIGN_OUT: {
target: 'signedOut',
actions: ['figmaClearAccessToken', 'clearAccessToken']
}
},
states: {
authenticating: {
entry: ['figmaAuthenticate'],
on: {
'SIGNED_IN': {
target: 'fetching',
actions: ['setAccessToken']
},
'NOT_SIGNED_IN': 'signedOut'
}
},
signedOut: {
on: {
SIGN_IN: {
target: 'fetching',
actions: ['setAccessToken', 'figmaSetAccessToken']
}
}
},
fetching: {
type: 'parallel',
onDone: 'editing',
states: {
username: {
initial: 'fetching',
states: {
fetching: {
invoke: {
id: 'fetchUsername',
src: 'fetchUsername',
onDone: {
target: 'done',
actions: ['setUsername']
},
onError: {
target: 'error',
actions: ['setError']
}
}
},
done: {
type: 'final'
},
error: {
on: {
RETRY: {
target:'fetching',
actions: ['clearError']
},
SIGN_OUT: {
target: '#commit.signedOut',
actions: ['clearAccessToken', 'figmaClearAccessToken']
}
}
},
}
},
branches: {
initial: 'fetching',
states: {
fetching: {
invoke: {
id: 'fetchBranches',
src: 'fetchBranches',
onDone: {
target: 'done',
actions: ['setBranches']
},
onError: {
target: 'error',
actions: ['setError']
}
}
},
done: {
type: 'final'
},
error: {
on: {
RETRY: {
target:'fetching',
actions: ['clearError']
}
}
},
}
},
},
},
editing: {
type: 'parallel',
entry: ['figmaGetSelection'],
on: {
COMMIT_MESSAGE_CHANGE: {
actions: ['setCommitMessage']
},
COMMIT: [
{
in: {editing: {selection: 'valid', branch: {newBranch: 'valid'}}},
target: 'committingToNewBranch',
actions: ['clearError']
},
{
in: {editing: {selection: 'valid', branch: {existingBranch: 'valid'}}},
target: 'committingToExistingBranch',
actions: ['clearError']
}
],
},
states: {
selection: {
initial: 'empty',
on: {
SELECTION_CHANGE: [
{
target: '.empty',
cond: 'isEmpty',
actions: ['setSelection', 'setDefaultCommitMessage']
},
{
target: '.valid',
actions: ['setSelection', 'setDefaultCommitMessage']
}
]
},
states: {
hist: {type: 'history'},
empty: {},
valid: {}
}
},
branch: {
initial: 'newBranch',
states: {
hist: {
type: 'history',
history: 'deep'
},
newBranch: {
initial: 'empty',
on: {
NEW_BRANCH_NAME_CHANGE: [
{
target: '.empty',
cond: 'isEmpty',
actions: ['setNewBranchName']
},
{
target: '.valid',
actions: ['setNewBranchName']
}
],
SWITCH_TO_EXISTING_BRANCH: [
{
cond: 'isExistingBranchNameEmpty',
target: 'existingBranch.empty'
},
{
target: 'existingBranch.valid'
}
]
},
states: {
empty: {},
valid: {}
}
},
existingBranch: {
initial: 'empty',
on: {
EXISTING_BRANCH_NAME_CHANGE: [
{
target: '.empty',
cond: 'isEmpty',
actions: ['setExistingBranchName']
},
{
target: '.valid',
actions: ['setExistingBranchName']
}
],
SWITCH_TO_NEW_BRANCH: [
{
target: 'newBranch.empty',
cond: 'isNewBranchNameEmpty'
},
{
target: 'newBranch.valid'
}
]
},
states: {
empty: {},
valid: {}
}
}
}
}
}
},
committingToNewBranch: {
invoke: {
id: 'commitToNewBranch',
src: 'commitToNewBranch',
onDone: {
target: 'doneCommittingToNewBranch',
actions: ['addNewBranchToBranches']
},
onError: {
target: 'errorCommitting',
actions: ['setError']
}
}
},
committingToExistingBranch: {
invoke: {
id: 'commitToNewBranch',
src: 'commitToNewBranch',
onDone: {
target: 'editing.branch.existingBranch.valid',
actions: ['figmaNotifySuccess',
'figmaClearSelection',
'clearSelection',
'clearDefaultCommitMessage','clearCommitMessage']
},
onError: {
target: 'errorCommitting',
actions: ['setError']
}
}
},
doneCommittingToNewBranch: {
on: {
COPY_TO_CLIPBOARD: {
actions: ['copyToClipboard', 'figmaNotifyCopied']
},
DONE: {
target: 'editing.branch.existingBranch.valid',
actions: ['figmaClearSelection', 'clearSelection', 'clearCommitMessage',
'clearDefaultCommitMessage', 'moveNewBranchNameToExistingBranchName']
}
}
},
errorCommitting: {
on: {
BACK: {
target: ['editing.selection.hist', 'editing.branch.hist'],
actions: ['clearError']
}
}
}
}
},
{
actions: {
setAccessToken: assign({
accessToken: (context, event) => event.data
}),
setBranches: assign({
branches: (context, event) => event.data
}),
setUsername: assign({
username: (context, event) => event.data
}),
setSelection: assign({
selection: (context, event) => event.data
}),
setCommitMessage: assign({
commitMessage: (context, event) => event.data
}),
setNewBranchName: assign({
newBranchName: (context, event) => event.data
}),
setExistingBranchName: assign({
existingBranchName: (context, event) => event.data
}),
setError: assign({
error: (context, event) => event.data
})
},
guards: {
isEmpty: (context, event) => {
if (typeof event.data === 'string') {
return event.data === ''
}
if (Array.isArray(event.data)) {
return event.data.length === 0
}
return true
},
isExistingBranchNameEmpty: (context) => context.existingBranchName === '',
isNewBranchNameEmpty: (context) => context.newBranchName === ''
},
services: {
fetchBranches: async (context, events) => {
await sleep(500)
//return ['branch-1', 'branch-2', 'branch-3']
return Promise.reject('Failed fetching branches')
},
fetchUsername: async (context, events) => {
await sleep(500)
return Promise.reject('Failed fetching username')
},
commitToNewBranch: async (context, events) => {
await sleep(500)
},
commitToExistingBranch: async (context, events) => {
await sleep(500)
}
}
}
)
function sleep(milliseconds) {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment