Created
March 13, 2020 13:39
-
-
Save simlrh/a84952a304c57959fd7170f885fd8353 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
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
// Available variables: | |
// - Machine | |
// - interpret | |
// - assign | |
// - send | |
// - sendParent | |
// - spawn | |
// - raise | |
// - actions | |
// - XState (all XState exports) | |
const enterEmail = { | |
initial: 'idle', | |
states: { | |
idle: { | |
on: { | |
SET_EMAIL: { | |
target: 'saving', | |
actions: 'setEmail', | |
}, | |
}, | |
}, | |
saving: { | |
invoke: { | |
id: 'saveEmail', | |
src: 'saveEmail', | |
onDone: 'saved', | |
onError: 'idle', | |
}, | |
}, | |
saved: { | |
type: 'final', | |
}, | |
}, | |
onDone: { | |
target: 'startPasswordless', | |
actions: 'navigateSendMagicLink', | |
}, | |
on: { | |
BACK: 'loggedOut', | |
}, | |
}; | |
const startPasswordless = { | |
initial: 'idle', | |
entry: 'clearPasswordlessErrors', | |
states: { | |
idle: { | |
id: 'startPasswordless-idle', | |
on: { | |
SEND_MAGIC_LINK: 'requesting', | |
}, | |
}, | |
requesting: { | |
entry: 'clearPasswordlessErrors', | |
initial: 'sending', | |
states: { | |
sending: { | |
invoke: { | |
id: 'sendMagicLink', | |
src: 'sendMagicLink', | |
onDone: { | |
target: 'savingSessionToken', | |
actions: 'setSessionToken', | |
}, | |
onError: { | |
target: '#startPasswordless-idle', | |
actions: 'setPasswordlessErrors', | |
}, | |
}, | |
}, | |
savingSessionToken: { | |
invoke: { | |
id: 'saveSessionToken', | |
src: 'saveSessionToken', | |
onDone: '#startPasswordless-sent', | |
onError: { | |
target: '#startPasswordless-idle', | |
actions: 'setPasswordlessErrors', | |
}, | |
}, | |
}, | |
}, | |
}, | |
sent: { | |
id: 'startPasswordless-sent', | |
after: { | |
10000: 'canResend', | |
}, | |
}, | |
canResend: { | |
on: { | |
SEND_MAGIC_LINK: 'requesting', | |
}, | |
}, | |
}, | |
on: { | |
USE_PASSWORD: { | |
target: 'enterPassword', | |
actions: 'navigateEnterPassword', | |
}, | |
BACK: 'enterEmail', | |
}, | |
}; | |
const verifyPasswordless = { | |
initial: 'attempting', | |
entry: ['clearPasswordlessErrors', 'setPasswordlessCode'], | |
states: { | |
attempting: { | |
initial: 'loading', | |
states: { | |
loading: { | |
initial: 'checking', | |
states: { | |
checking: { | |
on: { | |
'': [ | |
{ | |
target: '#verifyPasswordless-verifying', | |
cond: 'hasEmailAndToken', | |
}, | |
{ target: 'loading' }, | |
], | |
}, | |
}, | |
loading: { | |
invoke: { | |
id: 'loadData', | |
src: 'loadData', | |
onDone: { | |
target: 'loaded', | |
actions: 'setData', | |
}, | |
}, | |
}, | |
loaded: { | |
on: { | |
'': [ | |
{ | |
target: '#verifyPasswordless-verifying', | |
cond: 'hasEmailAndToken', | |
}, | |
{ target: '#verifyPasswordless-failed' }, | |
], | |
}, | |
}, | |
}, | |
}, | |
verifying: { | |
id: 'verifyPasswordless-verifying', | |
invoke: { | |
id: 'verifyPasswordless', | |
src: 'verifyPasswordless', | |
onDone: { | |
target: '#verifyPasswordless-succeeded', | |
actions: ['setAuthTokens', 'clearSessionToken'], | |
}, | |
onError: { | |
target: '#verifyPasswordless-failed', | |
actions: 'setPasswordlessErrors', | |
}, | |
}, | |
}, | |
}, | |
}, | |
failed: { | |
id: 'verifyPasswordless-failed', | |
type: 'final', | |
}, | |
succeeded: { | |
id: 'verifyPasswordless-succeeded', | |
type: 'final', | |
}, | |
}, | |
onDone: 'createPin', | |
on: { | |
BACK: 'loggedIn', | |
}, | |
}; | |
const enterPassword = { | |
entry: 'clearLoginErrors', | |
initial: 'idle', | |
states: { | |
idle: { | |
on: { SET_PASSWORD: 'attempting' }, | |
}, | |
attempting: { | |
entry: 'clearLoginErrors', | |
invoke: { | |
id: 'login', | |
src: 'login', | |
onDone: { | |
target: 'succeeded', | |
actions: 'setAuthTokens', | |
}, | |
onError: { | |
target: 'idle', | |
actions: 'setLoginErrors', | |
}, | |
}, | |
}, | |
succeeded: { | |
type: 'final', | |
}, | |
}, | |
on: { | |
BACK: 'startPasswordless', | |
}, | |
onDone: 'createPin', | |
}; | |
const createPin = { | |
entry: 'clearPinErrors', | |
initial: 'idle', | |
states: { | |
idle: { | |
on: { | |
SET_PIN: { | |
target: 'saving', | |
actions: 'setPin', | |
}, | |
}, | |
}, | |
saving: { | |
entry: 'clearPinErrors', | |
invoke: { | |
id: 'encryptRefreshToken', | |
src: 'encryptRefreshToken', | |
onDone: { | |
target: 'saved', | |
actions: 'storeEncryptedToken', | |
}, | |
onError: { | |
target: 'idle', | |
actions: 'setPinErrors', | |
}, | |
}, | |
}, | |
saved: { | |
invoke: { | |
id: 'checkBiometricsCapability', | |
src: 'checkBiometricsCapability', | |
onDone: { | |
target: 'biometricsChecked', | |
actions: 'setBiometricsCapability', | |
}, | |
}, | |
}, | |
biometricsChecked: { | |
type: 'final', | |
}, | |
}, | |
onDone: [ | |
{ | |
target: 'useBiometrics', | |
cond: 'hasBiometricsCapabilityAndEnabled', | |
}, | |
{ | |
target: 'loggedIn', | |
actions: 'clearPin', | |
}, | |
], | |
}; | |
const useBiometrics = { | |
entry: 'clearBiometricsErrors', | |
initial: 'idle', | |
states: { | |
idle: { | |
on: { | |
SET_BIOMETRICS: 'saving', | |
}, | |
}, | |
saving: { | |
entry: 'clearBiometricsErrors', | |
invoke: { | |
id: 'saveBiometrics', | |
src: 'saveBiometrics', | |
onDone: { | |
target: 'saved', | |
actions: 'clearPin', | |
}, | |
onError: { | |
target: 'idle', | |
actions: 'setBiometricsErrors', | |
}, | |
}, | |
}, | |
saved: { | |
type: 'final', | |
}, | |
}, | |
onDone: 'loggedIn', | |
}; | |
const loggedIn = { | |
initial: 'watching', | |
states: { | |
watching: { | |
invoke: { | |
id: 'watch', | |
src: 'watch', | |
}, | |
on: { | |
ACCESS_TOKEN_EXPIRED: 'refreshing', | |
}, | |
}, | |
refreshing: { | |
invoke: { | |
id: 'refresh', | |
src: 'refresh', | |
onDone: { | |
target: 'watching', | |
actions: 'setAuthTokens', | |
}, | |
onError: 'refreshTokenExpired', | |
}, | |
}, | |
refreshTokenExpired: { | |
type: 'final', | |
entry: 'clearAuthTokens', | |
}, | |
}, | |
on: { | |
LOG_OUT: 'loggedOut', | |
}, | |
onDone: 'loggedOut', | |
}; | |
const machine = Machine({ | |
id: 'auth', | |
initial: 'loading', | |
states: { | |
loading: { | |
invoke: { | |
id: 'loadData', | |
src: 'loadData', | |
onDone: { | |
target: 'loggedOut', | |
actions: 'setData', | |
}, | |
}, | |
on: { | |
BACK: undefined, | |
}, | |
}, | |
loggedOut: { | |
entry: 'clearAuthTokens', | |
on: { | |
START_LOGIN: { | |
target: 'enterEmail', | |
actions: 'navigateEnterEmail', | |
}, | |
BACK: undefined, | |
}, | |
}, | |
enterEmail, | |
startPasswordless, | |
verifyPasswordless, | |
enterPassword, | |
createPin, | |
useBiometrics, | |
loggedIn, | |
}, | |
on: { | |
USE_PASSWORDLESS_CODE: 'verifyPasswordless', | |
}, | |
}, { | |
guards: { | |
hasEmailAndToken: () => true, | |
hasBiometricsCapabilityAndEnabled: () => true | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment