UNPKG

@etsoo/react

Version:

TypeScript ReactJs UI Independent Framework

138 lines (122 loc) 3.16 kB
import { IAction, IUser, IUserData, UserKey } from "@etsoo/appscript"; import { Utils } from "@etsoo/shared"; import { IProviderProps, IUpdate } from "./IState"; import { State } from "./State"; /** * User action type * Style like 'const enum' will remove definition of the enum and cause module errors */ export enum UserActionType { // Login Login = "LOGIN", // Logout Logout = "LOGOUT", // Update Update = "UPDATE", // Unauthorized Unauthorized = "UNAUTHORIZED" } /** * User action to manage the user */ export interface UserAction<D extends IUser> extends IAction { /** * Action type */ type: UserActionType; /** * User data */ user?: IUserData; /** * User update callback */ update?: (state: D) => void; } /** * User provider props */ export type UserProviderProps<D extends IUser> = IProviderProps<UserAction<D>>; /** * Users calls with the state */ export interface UserCalls<D extends IUser> extends IUpdate<D, UserAction<D>> {} /** * User state */ export class UserState<D extends IUser> { /** * Context */ readonly context; /** * Provider */ readonly provider; /** * Constructor */ constructor() { const { context, provider } = State.create< D, UserAction<D>, UserCalls<D>, UserProviderProps<D> >( (state, action) => { // User reducer switch (action.type) { case UserActionType.Login: const lastChangedFields = state.authorized && action.user ? this.getChangedFields(action.user, state) : undefined; return { ...action.user!, authorized: true, lastChangedFields } as D; case UserActionType.Logout: return { ...state, // Keep other user data lastChangedFields: undefined, token: undefined, // Remove token authorized: false // Flag as unauthorized }; case UserActionType.Update: if (action.update) { var newState = { ...state }; action.update(newState); newState.lastChangedFields = this.getChangedFields( newState, state ); return newState; } return state; case UserActionType.Unauthorized: // Avoid multiple updates (For example, multiple API calls failed with 405) if (state.authorized === false) return state; return { ...state, // Keep other user data and token for refresh lastChangedFields: undefined, authorized: false // Flag as unauthorized }; default: return state; } }, {} as D, {} as UserCalls<D> ); this.context = context; this.provider = provider; } private getChangedFields(input: object, init: object) { return Utils.objectUpdated(input, init, [ "authorized", "seconds", "lastChangedFields" ]) as UserKey[]; } }