Created
March 2, 2020 23:19
-
-
Save mergebandit/934387e319551a67fc979c0efff03624 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
const service = { | |
addMfa: mfaOpt => { | |
console.log("service call: addMfa", mfaOpt); | |
return Promise.resolve(mfaOpt); | |
}, | |
deleteMfa: mfaOpt => { | |
console.log("service call: deleteMfa", mfaOpt); | |
return Promise.resolve(mfaOpt.mfaId); | |
}, | |
verifyMfa: mfaOpt => { | |
console.log("service call: verifyMfa", mfaOpt); | |
return Promise.resolve(mfaOpt.mfaId); | |
}, | |
sendCode: selectedMfaOption => { | |
console.log("service call: sendCode", selectedMfaOption); | |
return Promise.resolve(selectedMfaOption); | |
}, | |
verifyCode: (code, mfaOpt) => { | |
console.log("service call: verifyCode", code, mfaOpt.mfaType); | |
return Promise.resolve({ | |
...mfaOpt, | |
mfaIdentifier: "vcxjklvxjkjfsjkljfasjklfsdjkl" | |
}); | |
} | |
}; | |
const createCodeMachine = context => | |
Machine( | |
{ | |
context: { | |
code: "1234", | |
errorMessage: "", | |
selectedMfaOption: undefined, | |
...context | |
}, | |
id: "code", | |
initial: "sending", | |
meta: { | |
nextLabel: "Confirm", | |
pageTitle: "Enter Confirmation Code", | |
prevLabel: "Back" | |
}, | |
on: { | |
PREV: { | |
actions: sendParent("PREV") | |
}, | |
RESEND: "sending", | |
UPDATE: { | |
actions: "setCode" | |
} | |
}, | |
states: { | |
sending: { | |
invoke: { | |
id: "sendingCode", | |
src: "sendCode", | |
onError: { | |
actions: "setError", | |
target: "failure" | |
}, | |
onDone: { | |
target: "idle" | |
} | |
} | |
}, | |
complete: { | |
data: { | |
code: ({ code }) => code | |
}, | |
type: "final" | |
}, | |
idle: { | |
on: { | |
NEXT: "saving" | |
} | |
}, | |
failure: { | |
on: { | |
NEXT: "saving" | |
} | |
}, | |
saving: { | |
invoke: { | |
id: "saving", | |
src: "verifyCode", | |
onError: { | |
actions: "setError", | |
target: "failure" | |
}, | |
onDone: { | |
target: "complete", | |
actions: "foo" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
actions: { | |
foo: sendParent((_, evt) => ({ | |
type: "COMPLETE", | |
data: evt.data | |
})), | |
setCode: assign({ | |
code: (_, event) => event.value | |
}), | |
setError: assign({ | |
errorMessage: (_, event) => event.data | |
}) | |
}, | |
services: { | |
sendCode: ({ selectedMfaOption }) => | |
service.sendCode(selectedMfaOption), | |
verifyCode: ({ code, selectedMfaOption }) => | |
service.verifyCode(code, selectedMfaOption) | |
} | |
} | |
); | |
const notificationMachine = Machine( | |
{ | |
id: "notification", | |
initial: "idle", | |
context: { | |
message: "" | |
}, | |
states: { | |
idle: { | |
on: { | |
NOTIFY: { | |
target: "visible", | |
actions: assign({ | |
message: (_, e) => e.data | |
}) | |
} | |
} | |
}, | |
visible: { | |
entry: "addNotification", | |
on: { | |
"": "idle" | |
} | |
} | |
} | |
}, | |
{ | |
actions: { | |
addNotification: ctx => { | |
console.error("Notification:", ctx.message); | |
} | |
} | |
} | |
); | |
const notificationFactory = payload => ({ | |
type: "setNotificationMessage", | |
payload | |
}); | |
const manageMachine = Machine( | |
{ | |
id: "manage", | |
initial: "list", | |
entry: assign({ | |
notificationMachine: () => spawn(notificationMachine) | |
}), | |
context: { | |
mfaOptions: [ | |
{ | |
mfaIdentier: "afkalasjlkdjklsfsd", | |
mfaId: "1234567890", | |
mfaType: "sms" | |
}, | |
{ | |
mfaIdentier: "bnwrkenrkkrewnkrejw", | |
mfaId: "0987654321", | |
mfaType: "sms" | |
}, | |
{ | |
mfaIdentier: "buiyryuiryuertuiyuit", | |
mfaId: "initial@init.ial", | |
mfaType: "email" | |
} | |
], | |
// selectedMfaOption: { mfaId: "1234567890" }, | |
selectedMfaOption: null, | |
phoneMethod: null, | |
email: null, | |
phone: null, | |
notificationMessage: null, | |
frequency: null, | |
deleteMachine: null, | |
addMachine: null, | |
frequencyMachine: null, | |
codeMachine: null, | |
notificationMachine: null | |
}, | |
states: { | |
profile: { | |
after: { | |
750: "list" | |
} | |
}, | |
list: { | |
id: "list", | |
on: { | |
DELETE_MFA: { | |
target: "delete", | |
actions: "selectMfa" | |
}, | |
ADD_EMAIL: "add.email", | |
ADD_PHONE: "add.phone", | |
PREV: "#manage.profile" | |
} | |
}, | |
add: { | |
states: { | |
email: { | |
initial: "idle", | |
on: { | |
PREV: "#list", | |
NEXT: ".adding" | |
}, | |
states: { | |
error: {}, | |
idle: { | |
on: { | |
UPDATE: { | |
actions: "setEmail" | |
} | |
} | |
}, | |
adding: { | |
entry: "selectMfa", | |
invoke: { | |
id: "addMfa", | |
src: "addMfa", | |
onDone: { | |
target: "#enterCode", | |
actions: [ | |
notificationFactory("Email address added"), | |
"clearEmail" | |
] | |
}, | |
onError: "error" | |
} | |
} | |
} | |
}, | |
phone: { | |
initial: "idle", | |
on: { | |
PREV: "#list", | |
UPDATE: { | |
target: ".idle", | |
actions: "setPhone" | |
} | |
}, | |
states: { | |
error: {}, | |
idle: { | |
on: { | |
NEXT: "method" | |
} | |
}, | |
method: { | |
on: { | |
CHANGE: { | |
actions: "setPhoneMethod" | |
}, | |
NEXT: "adding" | |
} | |
}, | |
adding: { | |
entry: "selectMfa", | |
invoke: { | |
id: "addMfa", | |
src: "addMfa", | |
onDone: { | |
target: "#enterCode", | |
actions: [ | |
notificationFactory("Phone Number added"), | |
'clearPhone' | |
] | |
}, | |
onError: "error" | |
} | |
} | |
} | |
} | |
} | |
}, | |
// code: { | |
// id: "code", | |
// on: { | |
// NEXT: ".verifying" | |
// }, | |
// states: { | |
// addEmail: { | |
// on: { | |
// PREV: "#manage.add.email.idle" | |
// } | |
// }, | |
// addPhone: { | |
// on: { | |
// PREV: "#manage.add.phone" | |
// } | |
// }, | |
// error: {}, | |
// verifying: { | |
// invoke: { | |
// id: "verifyMfa", | |
// src: "verifyMfa", | |
// onDone: { | |
// target: "#list", | |
// actions: [ | |
// "sendNotification", | |
// "clearMfaOption", | |
// "clearEmail", | |
// "clearPhone" | |
// ] | |
// }, | |
// onError: "error" | |
// } | |
// } | |
// } | |
// }, | |
delete: { | |
initial: "idle", | |
states: { | |
error: {}, | |
idle: { | |
on: { | |
PREV: "#list", | |
NEXT: "deleting" | |
} | |
}, | |
deleting: { | |
invoke: { | |
id: "deleteMfa", | |
src: "deleteMfa", | |
onDone: { | |
target: "#list", | |
actions: [ | |
assign({ | |
notificationMessage: (ctx, { data }) => | |
`${ | |
data.mfaType === "email" ? "Email" : "Phone Number" | |
} Deleted` | |
}), | |
"sendNotification", | |
"deleteMfaFromCtx" | |
] | |
}, | |
onError: "error" | |
} | |
} | |
} | |
}, | |
enteringCode: { | |
id: "enterCode", | |
initial: "idle", | |
entry: [ | |
assign({ | |
codeMachine: ({ selectedMfaOption }) => | |
spawn(createCodeMachine({ selectedMfaOption })) | |
}) | |
], | |
states: { | |
idle: { | |
on: { | |
NEXT: { | |
actions: send("NEXT", { to: ctx => ctx.codeMachine }) | |
}, | |
COMPLETE: { | |
target: "#list", | |
actions: ["updateMfa", "sendNotification"] | |
} | |
} | |
} | |
}, | |
on: { | |
PREV: "#list" | |
} | |
}, | |
complete: { | |
type: "final" | |
} | |
} | |
}, | |
{ | |
actions: { | |
updateMfa: assign({ | |
selectedMfaOption: null, | |
mfaOptions: (ctx, evt) => [...ctx.mfaOptions, evt.data] | |
}), | |
addMfaToCtx: assign({ | |
mfaOptions: (ctx, evt) => [...ctx.mfaOptions, evt.data] | |
}), | |
deleteMfaFromCtx: assign({ | |
mfaOptions: (ctx, evt) => | |
ctx.mfaOptions.filter(opt => opt.mfaId !== evt.data), | |
selectedMfaOption: null | |
}), | |
selectMfa: assign({ | |
selectedMfaOption: ({ email, phone, mfaOptions }, { data }) => | |
data | |
? mfaOptions.find(opt => opt.mfaId === data) | |
: { | |
mfaId: email || phone, | |
mfaType: email ? "email" : "sms" | |
} | |
}), | |
setNotificationMessage: assign({ | |
notificationMessage: 'notif sent' | |
}), | |
sendNotification: send( | |
ctx => ({ | |
type: "NOTIFY", | |
data: ctx.notificationMessage | |
}), | |
{ | |
to: ctx => ctx.notificationMachine | |
} | |
), | |
setEmail: assign({ | |
email: (_, evt) => evt.data | |
}), | |
setPhone: assign({ | |
phone: (_, evt) => evt.data | |
}), | |
setPhoneMethod: assign({ | |
phoneMethod: (_, evt) => evt.data | |
}), | |
clearMfaOption: assign({ | |
selectedMfaOption: null | |
}), | |
clearPhone: assign({ | |
phone: null | |
}), | |
clearEmail: assign({ | |
email: null | |
}) | |
}, | |
services: { | |
addMfa: ({ email, phone }) => | |
service.addMfa({ | |
mfaId: email || phone, | |
mfaType: email ? "email" : "phone" | |
}), | |
deleteMfa: (ctx, evt) => service.deleteMfa(ctx.selectedMfaOption), | |
verifyMfa: (ctx, evt) => service.verifyMfa(ctx.selectedMfaOption) | |
}, | |
guards: { | |
isMfaOptionSelected: ctx => | |
ctx.selectedMfaOption ? !!ctx.selectedMfaOption.mfaId : false | |
} | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment