import { assign, createMachine, send, sendParent, spawn } from 'xstate'; import { QueryManager } from '$lib/services/query-manager-test'; import { fetchMachine } from './fetch.machine'; export type WithLocalCacheMachineContext = { cache: Record; errorMessage?: string; callsInFlight: any; broadcastEventType: string; manager: QueryManager } // utils const makeId = (context, event: any) => `${event.endpoint}${!!event.query ? ('?'+event.query) : ''}`; export const requestMachine = createMachine( { tsTypes: {} as import("./request.machine.typegen").Typegen0, schema: { context: {} as WithLocalCacheMachineContext, events: {} as { type: 'REQUEST', endpoint: string, query: string } | { type: 'RECEIVE_DATA', data: { id: string, endpoint: string, response: any } } | { type: 'CANCEL' } }, initial: 'idle', context: { errorMessage: null, cache: {}, callsInFlight: {}, broadcastEventType: null, manager: new QueryManager() }, states: { idle: { on: { 'REQUEST': [ { target: 'idle', cond: 'itemIsAlreadyInCache' }, { target: 'requesting' } ], 'RECEIVE_DATA': { actions: [ 'notifyParent', 'persistCallInStorage' , 'deassignMachine' ] // work in encryption here } } }, requesting: { entry: [ 'assignFetchMachine' ], always: { target: 'idle' } } }, }, { services: { // fetchMachine }, actions: { notifyParent: sendParent((context, event) => { return { type: context.broadcastEventType, response: event.data } }), assignFetchMachine: assign({ callsInFlight: (context, event) => { const id = makeId(context, event); const requestTimestamp = new Date(); // queries.getTimestamp(); // TODO: this should be fetched from prior call const call = spawn( fetchMachine.withContext({ id, endpoint: event.endpoint, query: event.query, verb: 'GET', body: null, requestTimestamp, responseTimestamp: null, response: null, errorMessage: null, manager: context.manager }), { name: id } ); return { ...context.callsInFlight, [ id ]: call } } }), deassignMachine: assign({ callsInFlight: (context: WithLocalCacheMachineContext, event) => { delete context.callsInFlight[ event.data.id ]; return context.callsInFlight; } }), persistCallInStorage: (context, event) => { // console.log("persisting in cache: ", context, event); const response = event.data; const url = '' // queries.persistCallInStorage(response); return !!context.cache[ url ] ; } }, guards: { itemIsAlreadyInCache: (context, event) => { // console.log("item in cache: ", context, event); const id = makeId(context, event); return !!context.cache[ id ] ; } } });