Last active
May 3, 2021 01:27
-
-
Save airandopal/ac06dbaf108091de1490cfb2fa4c1bf6 to your computer and use it in GitHub Desktop.
Revisions
-
airandopal revised this gist
May 3, 2021 . No changes.There are no files selected for viewing
-
airandopal revised this gist
May 3, 2021 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -189,6 +189,7 @@ const dashboardStates = { on: { ACTIONS_COMPLETE: 'idle', BAD_REQUEST: 'error.badRequest', // rn, this doesnt work STRIPE_ERROR: 'error.stripe', // how to make it so i can just pass in the code and it puts it at the end of this, so i dont have to write out an ON for each code -
airandopal revised this gist
May 3, 2021 . 1 changed file with 14 additions and 3 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -51,7 +51,8 @@ const setupData = { // cant do const actions because it's already in use here actions: { 'logError': (...args) => { const [context, event, ...theRest] = args console.log(`on entry of ERROR state`, { context, event, theRest }) }, 'getUserProfile': () => { // do get profile and send something towards "actions completing", maybe other things have to be completed. when all actions have been completed then move to idle @@ -88,7 +89,6 @@ const addGlobalEntry = ({ states }) => { const [key, value] = curr if(value.states) { let result = performUpdates(value.states) acc[key] = { states: result } } else { acc[key] = { @@ -103,14 +103,22 @@ const addGlobalEntry = ({ states }) => { const updatedStates = performUpdates(states) return { states: updatedStates } } // actions on entry with conditions? like send pager if its xyz type of errors (array based) const errorStatesObj = { states: { // doesnt work here // entry: ['logError'], badRequest: {}, unknown: {}, stripe: { entry: ['logError'], on: { '': { entry: ['logError'], } }, states: { '': {}, 200: {}, 400: {}, 401: {}, @@ -182,6 +190,9 @@ const dashboardStates = { ACTIONS_COMPLETE: 'idle', BAD_REQUEST: 'error.badRequest', STRIPE_ERROR: 'error.stripe', // how to make it so i can just pass in the code and it puts it at the end of this, so i dont have to write out an ON for each code STRIPE_ERROR_500: 'error.stripe.500', UNKNOWN: 'error.unknown' } }, -
airandopal revised this gist
May 3, 2021 . 1 changed file with 66 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -50,6 +50,9 @@ const setupData = { guards, // cant do const actions because it's already in use here actions: { 'logError': (...args) => { console.log(`on entry of ERROR state`, args) }, 'getUserProfile': () => { // do get profile and send something towards "actions completing", maybe other things have to be completed. when all actions have been completed then move to idle // or send error [error getting profile] @@ -68,6 +71,64 @@ const setupData = { } } // 200 - OK Everything worked as expected. // 400 - Bad Request The request was unacceptable, often due to missing a required parameter. // 401 - Unauthorized No valid API key provided. // 402 - Request Failed The parameters were valid but the request failed. // 403 - Forbidden The API key doesn't have permissions to perform the request. // 404 - Not Found The requested resource doesn't exist. // 409 - Conflict The request conflicts with another request (perhaps due to using the same idempotent key). // 429 - Too Many Requests Too many requests hit the API too quickly. We recommend an exponential backoff of your requests. // 500, 502, 503, 504 - Server Errors Something went wrong on Stripe's end. const addGlobalEntry = ({ states }) => { // todo: make recursive, so liek stripe.states all the ones in there ge tit to const performUpdates = (states) => { return Object.entries(states).reduce((acc, curr) => { const [key, value] = curr if(value.states) { let result = performUpdates(value.states) console.log('see result', result) acc[key] = { states: result } } else { acc[key] = { entry: ['logError'], ...value } } return acc }, {}) } const updatedStates = performUpdates(states) return { states: updatedStates } } const errorStatesObj = { states: { // doesnt work here entry: ['logError'], badRequest: {}, unknown: {}, stripe: { states: { 200: {}, 400: {}, 401: {}, 402: {}, 403: {}, 404: {}, 409: {}, 429: {}, // how to handle 500-504 500: {}, } }, ui: {}, api: {}, } } // todo: really should have a "transformations" step, where i can do this for any objectis in the machine const errorStates = addGlobalEntry(errorStatesObj) const appStates = { 'loading': { on: { @@ -118,7 +179,10 @@ const dashboardStates = { entry: ['getUserProfile'], exit: [], on: { ACTIONS_COMPLETE: 'idle', BAD_REQUEST: 'error.badRequest', STRIPE_ERROR: 'error.stripe', UNKNOWN: 'error.unknown' } }, idle: {}, @@ -127,6 +191,7 @@ const dashboardStates = { returned: {}, // i.e .typing or clicking something takingAction: {}, error: errorStates } const states = { app: appStates, -
airandopal revised this gist
May 2, 2021 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -24,6 +24,7 @@ // FIRST TASK OF DAY // read: https://xstate.js.org/docs/guides/communication.html // then: https://egghead.io/lessons/react-handle-http-request-state-with-xstate // then: https://xstate.js.org/docs/tutorials/reddit.html#splitting-machines // how to handle hte "Switcher" with x state // handle: if on page like profile and is session is no longer valid, redirect to login page or show login modal // session tampered scenario - send alert to server and mark profile -
airandopal revised this gist
May 2, 2021 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -23,6 +23,7 @@ // FIRST TASK OF DAY // read: https://xstate.js.org/docs/guides/communication.html // then: https://egghead.io/lessons/react-handle-http-request-state-with-xstate // how to handle hte "Switcher" with x state // handle: if on page like profile and is session is no longer valid, redirect to login page or show login modal // session tampered scenario - send alert to server and mark profile -
airandopal revised this gist
May 2, 2021 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -22,6 +22,7 @@ // FIRST TASK OF DAY // read: https://xstate.js.org/docs/guides/communication.html // how to handle hte "Switcher" with x state // handle: if on page like profile and is session is no longer valid, redirect to login page or show login modal // session tampered scenario - send alert to server and mark profile -
airandopal revised this gist
May 2, 2021 . 1 changed file with 4 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -18,6 +18,8 @@ // seeding data with jotai like profile data // for every page, easily see, what actions can be taken from this page // add an on exit that logs page route changes // FIRST TASK OF DAY // how to handle hte "Switcher" with x state @@ -33,12 +35,13 @@ const defaults = { const guards = { isSessionPresent: (context, event) => { return null }, // todo: get info from global state about whether there is a user // todo: do i need two different ones, or if it returns true and false is that enough sessionNotPresent: (context, event) => { console.log({ context, event }) return null // return true }, isValidSubscription: () => {} } const setupData = { guards, -
airandopal revised this gist
May 2, 2021 . 1 changed file with 14 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -20,11 +20,13 @@ // FIRST TASK OF DAY // how to handle hte "Switcher" with x state // handle: if on page like profile and is session is no longer valid, redirect to login page or show login modal // session tampered scenario - send alert to server and mark profile // session expired // no previous session found // const defaults = { initialState: 'loading' } @@ -45,7 +47,18 @@ const setupData = { 'getUserProfile': () => { // do get profile and send something towards "actions completing", maybe other things have to be completed. when all actions have been completed then move to idle // or send error [error getting profile] }, 'getSubscriptionData': () => {}, 'updateEmail': () => {}, 'pauseSubscription': () => {}, 'resumeSubscription': () => {}, 'cancelSubscription': () => {}, 'deleteDataGDPR': () => {}, 'deleteAccount': () => {}, } } -
airandopal revised this gist
May 2, 2021 . 1 changed file with 123 additions and 116 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,14 +1,14 @@ // Available variables: // - Machine // - interpret // - assign // - send // - sendParent // - spawn // - raise // - actions // - XState (all XState exports) // lib // - actions // - guards @@ -26,131 +26,138 @@ // no previous session found const defaults = { initialState: 'loading' } const guards = { isSessionPresent: (context, event) => { return null }, // todo: get info from global state about whether there is a user sessionNotPresent: (context, event) => { console.log({ context, event }) return null // return true }, } const setupData = { guards, // cant do const actions because it's already in use here actions: { 'getUserProfile': () => { // do get profile and send something towards "actions completing", maybe other things have to be completed. when all actions have been completed then move to idle // or send error [error getting profile] } } } const appStates = { 'loading': { on: { // having this is same as having target at end // '': 'checkingForSession', // TRANSIENT TRANSITION '': [ { target: 'loggedIn', cond: 'isSessionPresent' }, { target: 'notLoggedIn', cond: 'sessionNotPresent' }, // this has to be last { target: 'checkingForSession' }, ], } }, // todo: should this be a parallel state or a state inside loading // i.e. inside loading, its checking session and also loading other things // think about what happens when a page is public vs private - public pages dont need to block content, but for any page, i guess it should know whether or not the user is logged in. 'checkingForSession': { on: { SUCCESS: 'loggedIn', FAILURE: 'notLoggedIn', // whats the difference between this and error ERROR: 'error', // must pass error along } }, 'loggedIn': { on: { LOGOUT: 'loggedOut' } }, 'notLoggedIn': { on: { LOGIN: 'tryingLogin' } }, 'tryingLogin': { on: { SUCCESS: 'loggedIn', FAILURE: 'notLoggedIn', // whats the difference between this and error ERROR: 'error', // must pass error along } }, // 'BAD_LOGIN': {}, 'loggedOut': {}, 'error': {}, } const dashboardStates = { loading: { entry: ['getUserProfile'], exit: [], on: { ACTIONS_COMPLETE: 'idle' } }, idle: {}, // i.e. from or to stripe. can tell if returned based on url params. redirecting: {}, returned: {}, // i.e .typing or clicking something takingAction: {}, } const states = { app: appStates, dashboard: dashboardStates } const configs = { app: { id: 'app', initial: defaults.initialState, context: {}, states: states.app }, pages: { index: { // aka dashboard page if logged in id: 'dashboard', initial: defaults.initialState, context: {}, states: states.dashboard } } } // Transient transition // Will transition to either 'win' or 'lose' immediately upon // (re)entering 'playing' state if the condition is met. const fetchMachine = Machine(configs.app, setupData); const dashbaordMachine = Machine(configs.pages.index, setupData); // how can another machine talk to this one - i.e. the profile machine talk to the parent machine // data / context parts // email // loading // error // userData // session // userDetails // isReceipt // checkedForUser // viewType // subscription // atoms // - providers // - get ? // - atom With machine // modal // - open // - modalType -
airandopal revised this gist
May 2, 2021 . 1 changed file with 21 additions and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -15,6 +15,20 @@ // - atoms // - pages // seeding data with jotai like profile data // for every page, easily see, what actions can be taken from this page // FIRST TASK OF DAY // handle: if on page like profile and is session is no longer valid, redirect to login page or show login modal // session tampered scenario - send alert to server and mark profile // session expired // no previous session found const defaults = { initialState: 'loading' } const guards = { isSessionPresent: (context, event) => { return null }, // todo: get info from global state about whether there is a user sessionNotPresent: (context, event) => { @@ -71,6 +85,11 @@ const appStates = { 'error': {}, } const dashboardStates = { loading: { on: { '': { actions: ['getUserProfile'] } } }, idle: {}, // i.e. from or to stripe. can tell if returned based on url params. redirecting: {}, @@ -85,15 +104,15 @@ const states = { const configs = { app: { id: 'app', initial: defaults.initialState, context: {}, states: states.app }, pages: { index: { // aka dashboard page if logged in id: 'dashboard', initial: defaults.initialState, context: {}, states: states.dashboard } -
airandopal revised this gist
May 2, 2021 . 1 changed file with 12 additions and 3 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -9,6 +9,11 @@ // - raise // - actions // - XState (all XState exports) // lib // - actions // - guards // - atoms // - pages const guards = { isSessionPresent: (context, event) => { return null }, // todo: get info from global state about whether there is a user @@ -20,7 +25,7 @@ const guards = { }, } const appStates = { 'loading': { on: { // having this is same as having target at end @@ -72,21 +77,25 @@ const dashboardStates = { returned: {}, // i.e .typing or clicking something takingAction: {}, } const states = { app: appStates, dashboard: dashboardStates } const configs = { app: { id: 'app', initial: 'loading', context: {}, states: states.app }, pages: { index: { // aka dashboard page if logged in id: 'dashboard', initial: 'idle', context: {}, states: states.dashboard } } } -
airandopal revised this gist
May 2, 2021 . 1 changed file with 64 additions and 6 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -12,21 +12,31 @@ const guards = { isSessionPresent: (context, event) => { return null }, // todo: get info from global state about whether there is a user sessionNotPresent: (context, event) => { console.log({ context, event }) return null // return true }, } const mainStates = { 'loading': { on: { // having this is same as having target at end // '': 'checkingForSession', // TRANSIENT TRANSITION '': [ { target: 'loggedIn', cond: 'isSessionPresent' }, { target: 'notLoggedIn', cond: 'sessionNotPresent' }, // this has to be last { target: 'checkingForSession' }, ], } }, // todo: should this be a parallel state or a state inside loading // i.e. inside loading, its checking session and also loading other things // think about what happens when a page is public vs private - public pages dont need to block content, but for any page, i guess it should know whether or not the user is logged in. 'checkingForSession': { on: { SUCCESS: 'loggedIn', @@ -55,16 +65,64 @@ const mainStates = { 'loggedOut': {}, 'error': {}, } const dashboardStates = { idle: {}, // i.e. from or to stripe. can tell if returned based on url params. redirecting: {}, returned: {}, // i.e .typing or clicking something takingAction: {}, } const configs = { app: { id: 'app', initial: 'loading', context: {}, states: mainStates }, pages: { index: { // aka dashboard page if logged in id: 'dashboard', initial: 'idle', context: {}, states: dashboardStates } } } // Transient transition // Will transition to either 'win' or 'lose' immediately upon // (re)entering 'playing' state if the condition is met. const dashbaordMachine = Machine(configs.pages.index); const fetchMachine = Machine(configs.app, { guards }); // how can another machine talk to this one - i.e. the profile machine talk to the parent machine // data / context parts // email // loading // error // userData // session // userDetails // isReceipt // checkedForUser // viewType // subscription // atoms // - providers // - get ? // - atom With machine // modal // - open // - modalType
-
airandopal created this gist
May 2, 2021 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,70 @@ // Available variables: // - Machine // - interpret // - assign // - send // - sendParent // - spawn // - raise // - actions // - XState (all XState exports) const guards = { isSessionPresent: (context, event) => { return null }, // todo: get info from global state about whether there is a user sessionNotPresent: (context, event) => { return null }, } const mainStates = { 'loading': { on: { '': 'checkingForSession', // TRANSIENT TRANSITION '': [ { target: 'checkingForSession' }, { target: 'loggedIn', cond: 'isSessionPresent' }, { target: 'notLoggedIn', cond: 'sessionNotPresent' } ], } }, 'checkingForSession': { on: { SUCCESS: 'loggedIn', FAILURE: 'notLoggedIn', // whats the difference between this and error ERROR: 'error', // must pass error along } }, 'loggedIn': { on: { LOGOUT: 'loggedOut' } }, 'notLoggedIn': { on: { LOGIN: 'tryingLogin' } }, 'tryingLogin': { on: { SUCCESS: 'loggedIn', FAILURE: 'notLoggedIn', // whats the difference between this and error ERROR: 'error', // must pass error along } }, // 'BAD_LOGIN': {}, 'loggedOut': {}, 'error': {}, } const config = { id: 'app', initial: 'loading', context: {}, states: mainStates } // Transient transition // Will transition to either 'win' or 'lose' immediately upon // (re)entering 'playing' state if the condition is met. const fetchMachine = Machine(config, { guards });