import {StateNodeConfig, DoneInvokeEvent, TransitionConfig} from 'xstate'; export function unreachable(x: never) { return x; } export const exists = (t: T | undefined): t is T => !!t; const throwError = (fn: (t1: any) => boolean, t) => { throw new Error(`not valid, ${fn.name} failed on ${t}`); }; type TypeGuard = (t1: T | S) => t1 is T; export function checkThat(t: T | S, isTypeT: TypeGuard): T { if (!isTypeT(t)) { throwError(isTypeT, t); // Typescrypt doesn't know that throwError throws an error. throw 'Unreachable'; } return t; } type Opts = { onDone?: string | TransitionConfig; id?: string; onError?: string | TransitionConfig; entry?: string; exit?: string; }; export function getDataAndInvoke( data: {src: Services; opts?: Opts}, service: {src: Services; opts?: Opts}, onDone?: string | TransitionConfig | TransitionConfig[] ): StateNodeConfig> { return { initial: data.src, states: { [data.src]: {invoke: {src: data.src, onDone: service.src, onError: data.opts?.onError}}, [service.src]: { invoke: { id: service?.opts?.id, src: service.src, data: (_, {data}: DoneInvokeEvent) => data, onDone: 'done', onError: service.opts?.onError }, entry: service.opts?.entry }, done: {type: 'final'} }, onDone }; } export function arrayToRecord( array: Array, idProperty: K ): Record { return array.reduce((obj, item) => { obj[item[idProperty]] = item; return obj; }, {} as any); } export function recordToArray(record: Record): Array { return Object.keys(record) .map(k => record[k]) .filter(e => e !== undefined) as Array; }