Skip to content

Instantly share code, notes, and snippets.

@wlee221
Created May 6, 2021 03:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wlee221/ffc08f7c9499cbc80625c264fb8f210b to your computer and use it in GitHub Desktop.
Save wlee221/ffc08f7c9499cbc80625c264fb8f210b 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 fetchMachine = Machine(
{
id: "auth",
initial: "idle",
context: {
inputError: {},
submitError: {},
formError: {},
user: undefined,
session: undefined,
formValues: {}
},
states: {
// See: https://xstate.js.org/docs/guides/communication.html#invoking-promises
idle: {
invoke: {
// TODO Wait for Auth to be configured
src: "getCurrentUser",
onDone: {
actions: "setUser",
target: "authenticated"
},
onError: "signIn"
}
},
authenticated: {
on: {
SIGN_OUT: "signOut"
}
},
signIn: {
id: "signIn",
initial: "edit",
onDone: "authenticated",
states: {
edit: {
on: {
INPUT: {
actions: "onInput"
},
SUBMIT: ["validate"],
ERROR: {
target: "",
actions: "setInputError"
}
}
},
validate: {
on: {
SIGN_IN: "signIn",
ERROR: {
target: "edit",
actions: "setValidationError"
}
}
},
signIn: {
invoke: {
src: "signIn",
onDone: {
actions: "setUser",
target: "resolved"
},
onError: {
target: "edit",
actions: assign({
submitError: (_, event) => {
const message = event.data?.message || event.data;
return { cross_field: [message] };
},
formError: (context, event) => {
const message = event.data?.message || event.data;
return { cross_field: [message] };
}
})
}
}
},
resolved: {
type: "final"
}
},
on: {
SIGN_UP: "#auth.signUp"
}
},
signUp: {
initial: "idle",
onDone: "confirmSignUp",
states: {
idle: {
on: {
SIGN_IN: "#auth.signIn",
SUBMIT: "pending"
}
},
pending: {
invoke: {
src: "signUp",
onDone: {
actions: "setUser",
target: "resolved"
},
onError: "rejected"
}
},
// TODO Set errors and go back to `idle`?
rejected: {
always: "idle"
},
resolved: {
type: "final"
}
}
},
confirmSignUp: {
initial: "idle",
onDone: "idle",
states: {
idle: {
on: {
CONFIRM_SIGN_UP: "#auth.confirmSignUp",
SUBMIT: "pending",
RESEND: "resend"
}
},
pending: {
invoke: {
src: "confirmSignUp",
onDone: {
target: "resolved"
},
onError: "rejected"
}
},
resend: {
invoke: {
src: "resendConfirmationCode",
onDone: {
target: "idle"
},
onError: "rejected"
}
},
rejected: {
always: "idle"
},
resolved: {
type: "final"
}
},
on: {
SIGN_IN: "#auth.signIn"
}
},
signOut: {
initial: "pending",
onDone: "idle",
states: {
pending: {
invoke: {
src: "signOut",
onDone: {
actions: "setUser",
target: "resolved"
},
// See: https://xstate.js.org/docs/guides/communication.html#the-invoke-property
onError: "rejected"
}
},
rejected: {
// TODO Why would signOut be rejected?
type: "final"
},
resolved: {
type: "final"
}
}
}
}
},
{
actions: {
setUser: assign({
user(context, event) {
return event.data?.user || event.data;
}
}),
setValidationError: assign({
submitError(_, event) {
return event.data || {};
}
}),
setInputError: assign({
inputError(_, event) {
return event.data;
},
formError: (context, event) => {
return mergeFormErrors(event.data, context.submitError);
}
}),
onInput: assign({
formValues(context, event) {
const { name, value } = event.data;
return {
...context.formValues,
[name]: value
};
}
})
},
// See: https://xstate.js.org/docs/guides/guards.html#guards-condition-functions
guards: {
noEditErrors: (context, event) => {
return Object.keys(context.inputError).length === 0;
}
},
services: {
async getCurrentUser() {
return Auth.currentAuthenticatedUser();
},
async signIn(context, event) {
const { username, password } = event.data;
return Auth.signIn(username, password);
},
async confirmSignUp(context, event) {
const { username, code } = event.data;
return Auth.confirmSignUp(username, code);
},
async resendConfirmationCode(context, event) {
const { username } = event.data;
return Auth.resendSignUp(username);
},
async signUp(context, event) {
const { username, password, ...attributes } = event.data;
const result = await Auth.signUp({
username,
password,
attributes
});
// TODO `cond`itionally transition to `signUp.confirm` or `resolved` based on result
return result;
},
async signOut() {
await Auth.signOut(/* global? */);
}
}
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment