deno.land / x / xstate@xstate@4.33.6 / src / json.ts
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116import { StateNode, ActionObject, Guard, InvokeDefinition } from './';import { mapValues, isFunction } from './utils';
interface JSONFunction { $function: string;}
// tslint:disable-next-line:ban-typesexport function stringifyFunction(fn: Function): JSONFunction { return { $function: fn.toString() };}
function getStateNodeId(stateNode: StateNode): string { return `#${stateNode.id}`;}
interface TransitionConfig { target: string[]; source: string; actions: Array<ActionObject<any, any>>; cond: Guard<any, any> | undefined; eventType: string;}
interface StateNodeConfig { type: StateNode['type']; id: string; key: string; initial?: string; entry: Array<ActionObject<any, any>>; exit: Array<ActionObject<any, any>>; on: { [key: string]: TransitionConfig[]; }; invoke: Array<InvokeDefinition<any, any>>; states: Record<string, StateNodeConfig>;}
// derive config from machineexport function machineToJSON(stateNode: StateNode): StateNodeConfig { const config = { type: stateNode.type, initial: stateNode.initial === undefined ? undefined : String(stateNode.initial), id: stateNode.id, key: stateNode.key, entry: stateNode.onEntry, exit: stateNode.onExit, on: mapValues(stateNode.on, (transition) => { return transition.map((t) => { return { target: t.target ? t.target.map(getStateNodeId) : [], source: getStateNodeId(t.source), actions: t.actions, cond: t.cond, eventType: t.eventType }; }); }), invoke: stateNode.invoke, states: {} };
Object.values(stateNode.states).forEach((sn) => { config.states[sn.key] = machineToJSON(sn); });
return config;}
export function stringify(machine: StateNode): string { return JSON.stringify(machineToJSON(machine), (_, value) => { if (isFunction(value)) { return { $function: value.toString() }; } return value; });}
export function parse(machineString: string): StateNodeConfig { const config = JSON.parse(machineString, (_, value) => { if (typeof value === 'object' && '$function' in value) { return new Function(value.value); }
return value; });
return config;}
export function jsonify<T extends Record<string, any>>(value: T): T { Object.defineProperty(value, 'toJSON', { value: () => mapValues(value, (subValue) => { if (isFunction(subValue)) { return stringifyFunction(subValue); } else if (typeof subValue === 'object' && !Array.isArray(subValue)) { // mostly for assignments return mapValues(subValue, (subSubValue) => { if (isFunction(subSubValue)) { return stringifyFunction(subSubValue); } return subSubValue; }); }
return subValue; }) });
return value;}
Version Info