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 hidden or 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