import resolveApi, { resolveApiHeaders } from './resolveApi'; import { writable } from 'svelte/store'; // import { cacheClean } from './cache'; import getElectron from './getElectron'; // import socket from './socket'; import { showSnackbarError } from '../utility/snackbar'; import { isOauthCallback, redirectToLogin } from '../clientAuth'; import { showModal } from '../modals/modalTools'; import DatabaseLoginModal, { isDatabaseLoginVisible } from '../modals/DatabaseLoginModal.svelte'; import _ from 'lodash'; let eventSource; let apiLogging = false; // let cacheCleanerRegistered; let apiDisabled = false; const disabledOnOauth = isOauthCallback(); const volatileConnectionMap = {}; const volatileConnectionMapInv = {}; export function disableApi() { apiDisabled = true; } export function enableApi() { apiDisabled = false; } export function setVolatileConnectionRemapping(existingConnectionId, volatileConnectionId) { volatileConnectionMap[existingConnectionId] = volatileConnectionId; volatileConnectionMapInv[volatileConnectionId] = existingConnectionId; } export function getVolatileRemapping(conid) { return volatileConnectionMap[conid] || conid; } export function getVolatileRemappingInv(conid) { return volatileConnectionMapInv[conid] || conid; } export function removeVolatileMapping(conid) { const mapped = volatileConnectionMap[conid]; if (mapped) { delete volatileConnectionMap[conid]; delete volatileConnectionMapInv[mapped]; } } function wantEventSource() { if (!eventSource) { eventSource = new EventSource(`${resolveApi()}/stream`); // eventSource.addEventListener('clean-cache', e => cacheClean(JSON.parse(e.data))); } } function processApiResponse(route, args, resp) { // if (apiLogging) { // console.log('<<< API RESPONSE', route, args, resp); // } if (resp?.missingCredentials) { if (!isDatabaseLoginVisible()) { showModal(DatabaseLoginModal, resp.detail); } return null; // return { // errorMessage: resp.apiErrorMessage, // missingCredentials: true, // }; } else if (resp?.apiErrorMessage) { showSnackbarError('API error:' + resp?.apiErrorMessage); return { errorMessage: resp.apiErrorMessage, }; } return resp; } export function transformApiArgs(args) { return _.mapValues(args, (v, k) => { if (k == 'conid' && v && volatileConnectionMap[v]) return volatileConnectionMap[v]; if (k == 'conidArray' && _.isArray(v)) return v.map(x => volatileConnectionMap[x] || x); return v; }); } export function transformApiArgsInv(args) { return _.mapValues(args, (v, k) => { if (k == 'conid' && v && volatileConnectionMapInv[v]) return volatileConnectionMapInv[v]; if (k == 'conidArray' && _.isArray(v)) return v.map(x => volatileConnectionMapInv[x] || x); return v; }); } export async function apiCall(route: string, args: {} = undefined) { if (apiLogging) { console.log('>>> API CALL', route, args); } if (apiDisabled) { console.log('API disabled!!', route); return; } if (disabledOnOauth && route != 'auth/oauth-token') { console.log('API disabled because oauth callback!!', route); return; } args = transformApiArgs(args); const electron = getElectron(); if (electron) { const resp = await electron.invoke(route.replace('/', '-'), args); return processApiResponse(route, args, resp); } else { const resp = await fetch(`${resolveApi()}/${route}`, { method: 'POST', cache: 'no-cache', headers: { 'Content-Type': 'application/json', ...resolveApiHeaders(), }, body: JSON.stringify(args), }); if (resp.status == 401 && !apiDisabled) { const params = new URLSearchParams(location.search); disableApi(); console.log('Disabling API', route); if (params.get('page') != 'login' && params.get('page') != 'not-logged') { // unauthorized redirectToLogin(); } return; } const json = await resp.json(); return processApiResponse(route, args, json); } } const apiHandlers = new WeakMap(); export function apiOn(event: string, handler: Function) { const electron = getElectron(); if (electron) { if (!apiHandlers.has(handler)) { const handlerProxy = (e, data) => { if (apiLogging) { console.log('@@@ API EVENT', event, data); } handler(data); }; apiHandlers.set(handler, handlerProxy); } electron.addEventListener(event, apiHandlers.get(handler)); } else { wantEventSource(); if (!apiHandlers.has(handler)) { const handlerProxy = e => { const json = JSON.parse(e.data); if (apiLogging) { console.log('@@@ API EVENT', event, json); } handler(json); }; apiHandlers.set(handler, handlerProxy); } eventSource.addEventListener(event, apiHandlers.get(handler)); } // if (!cacheCleanerRegistered) { // cacheCleanerRegistered = true; // apiOn('clean-cache', reloadTrigger => cacheClean(reloadTrigger)); // } } export function apiOff(event: string, handler: Function) { const electron = getElectron(); if (apiHandlers.has(handler)) { if (electron) { electron.removeEventListener(event, apiHandlers.get(handler)); } else { wantEventSource(); eventSource.removeEventListener(event, apiHandlers.get(handler)); } } } export function useApiCall(route, args, defaultValue) { const result = writable(defaultValue); apiCall(route, args).then(resp => { result.set(resp); }); return result; } function enableApiLog() { apiLogging = true; console.log('API loggin enabled'); } function disableApiLog() { apiLogging = false; console.log('API loggin disabled'); } window['enableApiLog'] = enableApiLog; window['disableApiLog'] = disableApiLog;