From 4647037dc1ea288e40e67200b2327c044d217d69 Mon Sep 17 00:00:00 2001 From: Pive01 Date: Thu, 12 Jun 2025 15:07:39 +0200 Subject: [PATCH 1/5] Fixed startup issue --- ui/src/components/Header/Controller.tsx | 152 ++++++++++++++++-------- ui/src/services/hooks/api.ts | 107 +++++++++++------ 2 files changed, 173 insertions(+), 86 deletions(-) diff --git a/ui/src/components/Header/Controller.tsx b/ui/src/components/Header/Controller.tsx index 09afea4..dfbbdef 100644 --- a/ui/src/components/Header/Controller.tsx +++ b/ui/src/components/Header/Controller.tsx @@ -1,5 +1,14 @@ import React, { ReactElement, useEffect, useState } from 'react'; -import { Chip, ButtonGroup, Select, MenuItem, FormControl, Box, Badge, Tooltip } from '@mui/material'; +import { + Chip, + ButtonGroup, + Select, + MenuItem, + FormControl, + Box, + Badge, + Tooltip, +} from '@mui/material'; import { PlayArrow, Stop } from '@mui/icons-material'; import { isALocalStackContainer, @@ -23,11 +32,21 @@ import { ProgressButton } from '../Feedback'; const EXCLUDED_ERROR_TOAST = ['INFO', 'WARN', 'DEBUG']; export const Controller = (): ReactElement => { - const { configData, isLoading, setRunningConfig: setBackendRunningConfig, createConfig } = useRunConfigs(); + const { + configData, + isLoading, + setRunningConfig: setBackendRunningConfig, + createConfig, + } = useRunConfigs(); const { data, mutate } = useLocalStack(); const { user, os, hasSkippedConfiguration } = useMountPoint(); - const [runningConfig, setRunningConfig] = useState(configData.runningConfig ?? DEFAULT_CONFIGURATION_ID); - const [downloadProps, setDownloadProps] = useState({ open: false, image: COMMUNITY_IMAGE }); + const [runningConfig, setRunningConfig] = useState( + configData.runningConfig ?? DEFAULT_CONFIGURATION_ID, + ); + const [downloadProps, setDownloadProps] = useState({ + open: false, + image: COMMUNITY_IMAGE, + }); const [isStarting, setIsStarting] = useState(false); const [isStopping, setIsStopping] = useState(false); const { client: ddClient, getBinary } = useDDClient(); @@ -36,10 +55,17 @@ export const Controller = (): ReactElement => { const tooltipLabel = isUnhealthy ? 'Unhealthy' : 'Healthy'; useEffect(() => { - if (!isLoading && - (!configData?.configs || !configData.configs?.find(item => item.id === DEFAULT_CONFIGURATION_ID))) { + if ( + !isLoading && + (!configData?.configs || + !configData.configs?.find( + (item) => item.id === DEFAULT_CONFIGURATION_ID, + )) + ) { createConfig({ - name: 'Default', id: DEFAULT_CONFIGURATION_ID, vars: [], + name: 'Default', + id: DEFAULT_CONFIGURATION_ID, + vars: [], }); } if (!isLoading) { @@ -66,8 +92,9 @@ export const Controller = (): ReactElement => { }; const normalizeArguments = (): NodeJS.ProcessEnv => { - const addedArgs = configData.configs.find(config => config.id === runningConfig) - .vars.map(item => { + const addedArgs = configData.configs + .find((config) => config.id === runningConfig) + .vars.map((item) => { if (item.variable === 'DOCKER_FLAGS') { return { [item.variable]: `${FLAGS_AS_STRING} ${item.value}` }; } @@ -76,7 +103,7 @@ export const Controller = (): ReactElement => { }); return [...addedArgs, buildHostArgs()].reduce((acc, obj) => { - const [key, value] = Object.entries(obj)[0]; + const [key, value] = Object.entries(obj)[0]; acc[key] = value; return acc; }, {} as NodeJS.ProcessEnv); @@ -85,26 +112,35 @@ export const Controller = (): ReactElement => { const start = async () => { setIsStarting(true); - const images = await ddClient.docker.listImages() as [DockerImage]; + const images = (await ddClient.docker.listImages()) as [DockerImage]; - const isPro = configData.configs.find(config => config.id === runningConfig) - .vars.some(item => (item.variable === 'LOCALSTACK_API_KEY' || - item.variable === 'LOCALSTACK_AUTH_TOKEN') && item.value); + const isPro = configData.configs + .find((config) => config.id === runningConfig) + .vars.some( + (item) => + (item.variable === 'LOCALSTACK_API_KEY' || + item.variable === 'LOCALSTACK_AUTH_TOKEN') && + item.value, + ); - const havePro = images.some(image => removeTagFromImage(image) === PRO_IMAGE); + const havePro = images.some( + (image) => removeTagFromImage(image) === PRO_IMAGE, + ); if (!havePro && isPro) { setDownloadProps({ open: true, image: PRO_IMAGE }); return; } - const haveCommunity = images.some(image => removeTagFromImage(image) === COMMUNITY_IMAGE); + const haveCommunity = images.some( + (image) => removeTagFromImage(image) === COMMUNITY_IMAGE, + ); if (!haveCommunity) { setDownloadProps({ open: true, image: COMMUNITY_IMAGE }); return; } const args = normalizeArguments(); - + const binary = getBinary(); if (!binary) { setIsStarting(false); @@ -115,7 +151,9 @@ export const Controller = (): ReactElement => { env: args, stream: { onOutput(data): void { - const shouldDisplayError = !EXCLUDED_ERROR_TOAST.some(item => data.stderr?.includes(item)) && data.stderr; + const shouldDisplayError = + !EXCLUDED_ERROR_TOAST.some((item) => data.stderr?.includes(item)) && + data.stderr; if (shouldDisplayError) { ddClient.desktopUI.toast.error(data.stderr); setIsStarting(false); @@ -133,23 +171,31 @@ export const Controller = (): ReactElement => { const stop = async () => { setIsStopping(true); - const containers = await ddClient.docker.listContainers({ 'all': true }) as [DockerContainer]; + const containers = (await ddClient.docker.listContainers({ + all: true, + })) as [DockerContainer]; - const stoppedContainer = containers.find(container => - isALocalStackContainer(container) - && !Object.keys(containers[0].Labels).some(key => key === 'cloud.localstack.spawner') - && container.Command === 'docker-entrypoint.sh'); + const stoppedContainer = containers.find( + (container) => + isALocalStackContainer(container) && + !Object.keys(containers[0].Labels).some( + (key) => key === 'cloud.localstack.spawner', + ) && + container.Command === 'docker-entrypoint.sh', + ); - const spawnerContainer = containers.find(container => - Object.keys(container.Labels).includes('cloud.localstack.spawner')); + const spawnerContainer = containers.find((container) => + Object.keys(container.Labels).includes('cloud.localstack.spawner'), + ); if (spawnerContainer) { await ddClient.docker.cli.exec('stop', [spawnerContainer.Id]); // stop the spawner } if (stoppedContainer) { - if (stoppedContainer.State === 'created') { // not started - await ddClient.docker.cli.exec('rm', [stoppedContainer.Id]); // remove it + if (stoppedContainer.State === 'created') { + // not started + await ddClient.docker.cli.exec('rm', [stoppedContainer.Id]); // remove it } else { await ddClient.docker.cli.exec('stop', [stoppedContainer.Id]); } @@ -165,53 +211,63 @@ export const Controller = (): ReactElement => { }; return ( - + - - {(isRunning && !isStarting) ? + + {isRunning && !isStarting ? ( }> + startIcon={} + > Stop - : - - + ) : ( + + }> + startIcon={} + > Start - - } + )} - - + + diff --git a/ui/src/services/hooks/api.ts b/ui/src/services/hooks/api.ts index 01aa9cc..18b0af1 100644 --- a/ui/src/services/hooks/api.ts +++ b/ui/src/services/hooks/api.ts @@ -1,27 +1,37 @@ 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 HTTPMessageBody { - Message: string, +interface HTTPMessage { + data: { Message: string }; } -const adaptVersionData = (data: HTTPMessageBody, error: Error) => { - const newData = (!data || !data?.Message || error) ? - { configs: [], runningConfig: null } - : - JSON.parse(data?.Message); +const adaptVersionData = (message: HTTPMessage, error: Error) => { + console.log(message); + const newData = + !message || !message?.data.Message || error + ? { configs: [], runningConfig: null } + : JSON.parse(message?.data.Message); if (Array.isArray(newData)) { return { configs: newData, runningConfig: newData.at(0).id ?? null }; } @@ -33,21 +43,28 @@ 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(); }; @@ -56,7 +73,6 @@ export const useRunConfigs = (): useRunConfigsReturn => { mutate(); }; - return { configData: adaptVersionData(data, error), isLoading: isValidating || (!error && !data), @@ -68,12 +84,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; } @@ -83,22 +99,31 @@ 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.Message : null; - const mountPointData = isJson(fileContent) ? JSON.parse(fileContent) as mountPointData : null; + const fileContent = !error && data ? data.data.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), setMountPointData, @@ -106,7 +131,7 @@ export const useMountPoint = (): useMountPointReturn => { }; interface useLocalStackReturn { - data: DockerContainer | null, + data: DockerContainer | null; mutate: () => void; } @@ -116,15 +141,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'), }, ); From 31ae2dd6bb41f5e377ec8940b6eaabb9a1dd5705 Mon Sep 17 00:00:00 2001 From: Pive01 Date: Thu, 12 Jun 2025 15:14:16 +0200 Subject: [PATCH 2/5] Revert "Fixed startup issue" This reverts commit 4647037dc1ea288e40e67200b2327c044d217d69. --- ui/src/components/Header/Controller.tsx | 152 ++++++++---------------- ui/src/services/hooks/api.ts | 107 ++++++----------- 2 files changed, 86 insertions(+), 173 deletions(-) diff --git a/ui/src/components/Header/Controller.tsx b/ui/src/components/Header/Controller.tsx index dfbbdef..09afea4 100644 --- a/ui/src/components/Header/Controller.tsx +++ b/ui/src/components/Header/Controller.tsx @@ -1,14 +1,5 @@ import React, { ReactElement, useEffect, useState } from 'react'; -import { - Chip, - ButtonGroup, - Select, - MenuItem, - FormControl, - Box, - Badge, - Tooltip, -} from '@mui/material'; +import { Chip, ButtonGroup, Select, MenuItem, FormControl, Box, Badge, Tooltip } from '@mui/material'; import { PlayArrow, Stop } from '@mui/icons-material'; import { isALocalStackContainer, @@ -32,21 +23,11 @@ import { ProgressButton } from '../Feedback'; const EXCLUDED_ERROR_TOAST = ['INFO', 'WARN', 'DEBUG']; export const Controller = (): ReactElement => { - const { - configData, - isLoading, - setRunningConfig: setBackendRunningConfig, - createConfig, - } = useRunConfigs(); + const { configData, isLoading, setRunningConfig: setBackendRunningConfig, createConfig } = useRunConfigs(); const { data, mutate } = useLocalStack(); const { user, os, hasSkippedConfiguration } = useMountPoint(); - const [runningConfig, setRunningConfig] = useState( - configData.runningConfig ?? DEFAULT_CONFIGURATION_ID, - ); - const [downloadProps, setDownloadProps] = useState({ - open: false, - image: COMMUNITY_IMAGE, - }); + const [runningConfig, setRunningConfig] = useState(configData.runningConfig ?? DEFAULT_CONFIGURATION_ID); + const [downloadProps, setDownloadProps] = useState({ open: false, image: COMMUNITY_IMAGE }); const [isStarting, setIsStarting] = useState(false); const [isStopping, setIsStopping] = useState(false); const { client: ddClient, getBinary } = useDDClient(); @@ -55,17 +36,10 @@ export const Controller = (): ReactElement => { const tooltipLabel = isUnhealthy ? 'Unhealthy' : 'Healthy'; useEffect(() => { - if ( - !isLoading && - (!configData?.configs || - !configData.configs?.find( - (item) => item.id === DEFAULT_CONFIGURATION_ID, - )) - ) { + if (!isLoading && + (!configData?.configs || !configData.configs?.find(item => item.id === DEFAULT_CONFIGURATION_ID))) { createConfig({ - name: 'Default', - id: DEFAULT_CONFIGURATION_ID, - vars: [], + name: 'Default', id: DEFAULT_CONFIGURATION_ID, vars: [], }); } if (!isLoading) { @@ -92,9 +66,8 @@ export const Controller = (): ReactElement => { }; const normalizeArguments = (): NodeJS.ProcessEnv => { - const addedArgs = configData.configs - .find((config) => config.id === runningConfig) - .vars.map((item) => { + const addedArgs = configData.configs.find(config => config.id === runningConfig) + .vars.map(item => { if (item.variable === 'DOCKER_FLAGS') { return { [item.variable]: `${FLAGS_AS_STRING} ${item.value}` }; } @@ -103,7 +76,7 @@ export const Controller = (): ReactElement => { }); return [...addedArgs, buildHostArgs()].reduce((acc, obj) => { - const [key, value] = Object.entries(obj)[0]; + const [key, value] = Object.entries(obj)[0]; acc[key] = value; return acc; }, {} as NodeJS.ProcessEnv); @@ -112,35 +85,26 @@ export const Controller = (): ReactElement => { const start = async () => { setIsStarting(true); - const images = (await ddClient.docker.listImages()) as [DockerImage]; + const images = await ddClient.docker.listImages() as [DockerImage]; - const isPro = configData.configs - .find((config) => config.id === runningConfig) - .vars.some( - (item) => - (item.variable === 'LOCALSTACK_API_KEY' || - item.variable === 'LOCALSTACK_AUTH_TOKEN') && - item.value, - ); + const isPro = configData.configs.find(config => config.id === runningConfig) + .vars.some(item => (item.variable === 'LOCALSTACK_API_KEY' || + item.variable === 'LOCALSTACK_AUTH_TOKEN') && item.value); - const havePro = images.some( - (image) => removeTagFromImage(image) === PRO_IMAGE, - ); + const havePro = images.some(image => removeTagFromImage(image) === PRO_IMAGE); if (!havePro && isPro) { setDownloadProps({ open: true, image: PRO_IMAGE }); return; } - const haveCommunity = images.some( - (image) => removeTagFromImage(image) === COMMUNITY_IMAGE, - ); + const haveCommunity = images.some(image => removeTagFromImage(image) === COMMUNITY_IMAGE); if (!haveCommunity) { setDownloadProps({ open: true, image: COMMUNITY_IMAGE }); return; } const args = normalizeArguments(); - + const binary = getBinary(); if (!binary) { setIsStarting(false); @@ -151,9 +115,7 @@ export const Controller = (): ReactElement => { env: args, stream: { onOutput(data): void { - const shouldDisplayError = - !EXCLUDED_ERROR_TOAST.some((item) => data.stderr?.includes(item)) && - data.stderr; + const shouldDisplayError = !EXCLUDED_ERROR_TOAST.some(item => data.stderr?.includes(item)) && data.stderr; if (shouldDisplayError) { ddClient.desktopUI.toast.error(data.stderr); setIsStarting(false); @@ -171,31 +133,23 @@ export const Controller = (): ReactElement => { const stop = async () => { setIsStopping(true); - const containers = (await ddClient.docker.listContainers({ - all: true, - })) as [DockerContainer]; + const containers = await ddClient.docker.listContainers({ 'all': true }) as [DockerContainer]; - const stoppedContainer = containers.find( - (container) => - isALocalStackContainer(container) && - !Object.keys(containers[0].Labels).some( - (key) => key === 'cloud.localstack.spawner', - ) && - container.Command === 'docker-entrypoint.sh', - ); + const stoppedContainer = containers.find(container => + isALocalStackContainer(container) + && !Object.keys(containers[0].Labels).some(key => key === 'cloud.localstack.spawner') + && container.Command === 'docker-entrypoint.sh'); - const spawnerContainer = containers.find((container) => - Object.keys(container.Labels).includes('cloud.localstack.spawner'), - ); + const spawnerContainer = containers.find(container => + Object.keys(container.Labels).includes('cloud.localstack.spawner')); if (spawnerContainer) { await ddClient.docker.cli.exec('stop', [spawnerContainer.Id]); // stop the spawner } if (stoppedContainer) { - if (stoppedContainer.State === 'created') { - // not started - await ddClient.docker.cli.exec('rm', [stoppedContainer.Id]); // remove it + if (stoppedContainer.State === 'created') { // not started + await ddClient.docker.cli.exec('rm', [stoppedContainer.Id]); // remove it } else { await ddClient.docker.cli.exec('stop', [stoppedContainer.Id]); } @@ -211,63 +165,53 @@ export const Controller = (): ReactElement => { }; return ( - + - - {isRunning && !isStarting ? ( + + {(isRunning && !isStarting) ? } - > + startIcon={}> Stop - ) : ( - - + : + + } - > + startIcon={}> Start + - )} + } - - + + diff --git a/ui/src/services/hooks/api.ts b/ui/src/services/hooks/api.ts index 18b0af1..01aa9cc 100644 --- a/ui/src/services/hooks/api.ts +++ b/ui/src/services/hooks/api.ts @@ -1,37 +1,27 @@ 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 }; +interface HTTPMessageBody { + Message: string, } -const adaptVersionData = (message: HTTPMessage, error: Error) => { - console.log(message); - const newData = - !message || !message?.data.Message || error - ? { configs: [], runningConfig: null } - : JSON.parse(message?.data.Message); +const adaptVersionData = (data: HTTPMessageBody, error: Error) => { + 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 }; } @@ -43,28 +33,21 @@ 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(); }; @@ -73,6 +56,7 @@ export const useRunConfigs = (): useRunConfigsReturn => { mutate(); }; + return { configData: adaptVersionData(data, error), isLoading: isValidating || (!error && !data), @@ -84,12 +68,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; } @@ -99,31 +83,22 @@ 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 fileContent = (!error && data) ? data.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), setMountPointData, @@ -131,7 +106,7 @@ export const useMountPoint = (): useMountPointReturn => { }; interface useLocalStackReturn { - data: DockerContainer | null; + data: DockerContainer | null, mutate: () => void; } @@ -141,21 +116,15 @@ 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'), }, ); From 985bc032e6273a4f540edd1b3cca85ba32e07f7e Mon Sep 17 00:00:00 2001 From: Pive01 Date: Thu, 12 Jun 2025 15:19:01 +0200 Subject: [PATCH 3/5] Re-did changes but without formatting --- ui/src/services/hooks/api.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ui/src/services/hooks/api.ts b/ui/src/services/hooks/api.ts index 01aa9cc..5dc623c 100644 --- a/ui/src/services/hooks/api.ts +++ b/ui/src/services/hooks/api.ts @@ -13,15 +13,17 @@ interface useRunConfigsReturn { deleteConfig: (data: string) => unknown; } -interface HTTPMessageBody { - Message: string, +interface HTTPMessage { + data: { + Message: string, + }, } -const adaptVersionData = (data: HTTPMessageBody, error: Error) => { - const newData = (!data || !data?.Message || error) ? +const adaptVersionData = (message: HTTPMessage, error: Error) => { + const newData = (!message || !message.data?.Message || error) ? { configs: [], runningConfig: null } : - JSON.parse(data?.Message); + JSON.parse(message.data?.Message); if (Array.isArray(newData)) { return { configs: newData, runningConfig: newData.at(0).id ?? null }; } @@ -33,7 +35,7 @@ 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) => { @@ -83,7 +85,7 @@ 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) => { @@ -91,7 +93,7 @@ export const useMountPoint = (): useMountPointReturn => { mutate(); }; - const fileContent = (!error && data) ? data.Message : null; + const fileContent = (!error && data) ? data.data.Message : null; const mountPointData = isJson(fileContent) ? JSON.parse(fileContent) as mountPointData : null; return { From eadf03d10bef7ad542b4f661e92b8ceda488ae1c Mon Sep 17 00:00:00 2001 From: Pive01 Date: Thu, 12 Jun 2025 15:21:46 +0200 Subject: [PATCH 4/5] Update tag version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3120f24..5648165 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ IMAGE?=localstack/localstack-docker-desktop -TAG?=0.5.3 +TAG?=0.5.4 BUILDER=buildx-multi-arch From d2780b3eb9c2b633912a2486ae7c7b8d12606320 Mon Sep 17 00:00:00 2001 From: Pive01 Date: Thu, 12 Jun 2025 15:36:29 +0200 Subject: [PATCH 5/5] Updated changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d879a6..28c3318 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.5.4] — 2025-06-12 + +### Changed + +- Fixed bug that prevented correct startup of extension + ## [0.5.3] — 2024-01-11 ### Changed