diff --git a/Makefile b/Makefile index 5648165..3ea60f5 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ IMAGE?=localstack/localstack-docker-desktop -TAG?=0.5.4 +TAG?=0.5.5 BUILDER=buildx-multi-arch diff --git a/ui/src/services/hooks/api.ts b/ui/src/services/hooks/api.ts index 5dc623c..b72fce6 100644 --- a/ui/src/services/hooks/api.ts +++ b/ui/src/services/hooks/api.ts @@ -1,29 +1,53 @@ import useSWR from 'swr'; -import { STORAGE_KEY_ENVVARS, STORAGE_KEY_LOCALSTACK, STORAGE_KEY_MOUNT } from '../../constants'; -import { ConfigData, DockerContainer, mountPointData, RunConfig } from '../../types'; +import { + STORAGE_KEY_ENVVARS, + STORAGE_KEY_LOCALSTACK, + STORAGE_KEY_MOUNT, +} from '../../constants'; +import { + ConfigData, + DockerContainer, + mountPointData, + RunConfig, +} from '../../types'; import { isALocalStackContainer, isJson } from '../util'; import { useDDClient } from './utils'; interface useRunConfigsReturn { - configData: ConfigData, - isLoading: boolean, + configData: ConfigData; + isLoading: boolean; setRunningConfig: (data: string) => unknown; createConfig: (data: RunConfig) => unknown; updateConfig: (data: RunConfig) => unknown; deleteConfig: (data: string) => unknown; } -interface HTTPMessage { - data: { - Message: string, - }, -} +// This is what backend calls send in MacOS +type BaseMessage = { + Message: string; +}; + +// This is what backend calls send on Linux +type LinuxMessage = { + data: BaseMessage; +}; + +type HTTPMessage = LinuxMessage | BaseMessage; + +const isBaseMessage = (msg: HTTPMessage): msg is BaseMessage => (msg as BaseMessage).Message !== undefined; + +const resolveOSMessage = (message: HTTPMessage | undefined): BaseMessage | undefined => { + if (!message) return undefined; + if (isBaseMessage(message)) return message; + return message.data; +}; const adaptVersionData = (message: HTTPMessage, error: Error) => { - const newData = (!message || !message.data?.Message || error) ? - { configs: [], runningConfig: null } - : - JSON.parse(message.data?.Message); + const data = resolveOSMessage(message); + const newData = + !data || !data?.Message || error + ? { configs: [], runningConfig: null } + : JSON.parse(data?.Message); if (Array.isArray(newData)) { return { configs: newData, runningConfig: newData.at(0).id ?? null }; } @@ -35,21 +59,27 @@ export const useRunConfigs = (): useRunConfigsReturn => { const { client: ddClient } = useDDClient(); const { data, mutate, isValidating, error } = useSWR( cacheKey, - () => (ddClient.extension.vm.service.get('/configs') as Promise), + () => ddClient.extension.vm.service.get('/configs') as Promise, ); const updateConfig = async (newData: RunConfig) => { - await ddClient.extension.vm.service.put('/configs', { Data: JSON.stringify(newData) }); + await ddClient.extension.vm.service.put('/configs', { + Data: JSON.stringify(newData), + }); mutate(); }; const setRunningConfig = async (configId: string) => { - await ddClient.extension.vm.service.put('/configs/running', { Data: JSON.stringify(configId) }); + await ddClient.extension.vm.service.put('/configs/running', { + Data: JSON.stringify(configId), + }); mutate(); }; const createConfig = async (newData: RunConfig) => { - await ddClient.extension.vm.service.post('/configs', { Data: JSON.stringify(newData) }); + await ddClient.extension.vm.service.post('/configs', { + Data: JSON.stringify(newData), + }); mutate(); }; @@ -58,7 +88,6 @@ export const useRunConfigs = (): useRunConfigsReturn => { mutate(); }; - return { configData: adaptVersionData(data, error), isLoading: isValidating || (!error && !data), @@ -70,12 +99,12 @@ export const useRunConfigs = (): useRunConfigsReturn => { }; interface useMountPointReturn { - user: string | null, - os: string | null, - showForm: boolean, - showSetupWarning: boolean, - hasSkippedConfiguration: boolean, - isLoading: boolean, + user: string | null; + os: string | null; + showForm: boolean; + showSetupWarning: boolean; + hasSkippedConfiguration: boolean; + isLoading: boolean; setMountPointData: (data: mountPointData) => void; } @@ -85,30 +114,41 @@ export const useMountPoint = (): useMountPointReturn => { const { data, mutate, isValidating, error } = useSWR( cacheKey, - async () => (ddClient.extension.vm.service.get('/mount') as Promise), + async () => + ddClient.extension.vm.service.get('/mount') as Promise, ); const setMountPointData = async (data: mountPointData) => { - await ddClient.extension.vm.service.post('/mount', { Data: JSON.stringify(data) }); + await ddClient.extension.vm.service.post('/mount', { + Data: JSON.stringify(data), + }); mutate(); }; - const fileContent = (!error && data) ? data.data.Message : null; - const mountPointData = isJson(fileContent) ? JSON.parse(fileContent) as mountPointData : null; + const adaptedData = resolveOSMessage(data); + + const fileContent = !error && adaptedData ? adaptedData.Message : null; + const mountPointData = isJson(fileContent) + ? (JSON.parse(fileContent) as mountPointData) + : null; return { user: mountPointData?.user, os: mountPointData?.os, - showForm: mountPointData?.showForm == null ? true : mountPointData?.showForm, - showSetupWarning: mountPointData?.showSetupWarning == null ? true : mountPointData?.showSetupWarning, + showForm: + mountPointData?.showForm == null ? true : mountPointData?.showForm, + showSetupWarning: + mountPointData?.showSetupWarning == null + ? true + : mountPointData?.showSetupWarning, hasSkippedConfiguration: mountPointData?.hasSkippedConfiguration || false, - isLoading: isValidating || (!error && !data), + isLoading: isValidating || (!error && !adaptedData), setMountPointData, }; }; interface useLocalStackReturn { - data: DockerContainer | null, + data: DockerContainer | null; mutate: () => void; } @@ -118,15 +158,21 @@ export const useLocalStack = (): useLocalStackReturn => { const { data, mutate } = useSWR( cacheKey, - async () => (await ddClient.docker.listContainers() as [DockerContainer]) - .find(container => - isALocalStackContainer(container) && container.Command !== 'bin/localstack update docker-images', - ), { - refreshInterval: 2000, compare: - /* - * compares whether the old (b) status aligns with that of new (a) status - */ - (a, b) => a?.Id === b?.Id && a?.Status.includes('unhealthy') === b?.Status.includes('unhealthy'), + async () => + ((await ddClient.docker.listContainers()) as [DockerContainer]).find( + (container) => + isALocalStackContainer(container) && + container.Command !== 'bin/localstack update docker-images', + ), + { + refreshInterval: 2000, + compare: + /* + * compares whether the old (b) status aligns with that of new (a) status + */ + (a, b) => + a?.Id === b?.Id && + a?.Status.includes('unhealthy') === b?.Status.includes('unhealthy'), }, );