fix(common): correctly load mock servers on initialization and workspace change (#5832)

Co-authored-by: James George <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
Anwarul Islam 2026-02-05 16:09:47 +06:00 committed by GitHub
parent 20bfac04fe
commit ff906b7c96
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 42 additions and 17 deletions

View file

@ -32,7 +32,7 @@
<div class="flex flex-1 flex-col"> <div class="flex flex-1 flex-col">
<div <div
v-if="loading" v-if="isFetchingServers"
class="flex flex-1 flex-col items-center justify-center p-4" class="flex flex-1 flex-col items-center justify-center p-4"
> >
<HoppSmartSpinner class="mb-4" /> <HoppSmartSpinner class="mb-4" />
@ -209,12 +209,14 @@ import { computed, ref } from "vue"
import { TippyComponent } from "vue-tippy" import { TippyComponent } from "vue-tippy"
import { useMockServerStatus } from "~/composables/mockServer" import { useMockServerStatus } from "~/composables/mockServer"
import { useToast } from "~/composables/toast" import { useToast } from "~/composables/toast"
import { useReadonlyStream } from "~/composables/stream"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
import type { MockServer } from "~/newstore/mockServers" import type { MockServer } from "~/newstore/mockServers"
import { platform } from "~/platform" import { platform } from "~/platform"
import { import {
deleteMockServer as deleteMockServerInStore, deleteMockServer as deleteMockServerInStore,
loading$,
showCreateMockServerModal$, showCreateMockServerModal$,
updateMockServer as updateMockServerInStore, updateMockServer as updateMockServerInStore,
} from "~/newstore/mockServers" } from "~/newstore/mockServers"
@ -242,6 +244,7 @@ const t = useI18n()
const toast = useToast() const toast = useToast()
const colorMode = useColorMode() const colorMode = useColorMode()
const { mockServers } = useMockServerStatus() const { mockServers } = useMockServerStatus()
const isFetchingServers = useReadonlyStream(loading$, false)
const loading = ref(false) const loading = ref(false)
const showEditModal = ref(false) const showEditModal = ref(false)
const showLogsModal = ref(false) const showLogsModal = ref(false)

View file

@ -1,9 +1,10 @@
import { onMounted, watch } from "vue"
import { useService } from "dioc/vue" import { useService } from "dioc/vue"
import { WorkspaceService } from "~/services/workspace.service" import { watch } from "vue"
import { setMockServers, loadMockServers } from "~/newstore/mockServers" import { loadMockServers, setMockServers } from "~/newstore/mockServers"
import { platform } from "~/platform" import { platform } from "~/platform"
import { WorkspaceService } from "~/services/workspace.service"
import { useMockServerVisibility } from "./mockServerVisibility" import { useMockServerVisibility } from "./mockServerVisibility"
import { useReadonlyStream } from "./stream"
/** /**
* Composable to handle mock server state when workspace changes * Composable to handle mock server state when workspace changes
@ -13,19 +14,27 @@ import { useMockServerVisibility } from "./mockServerVisibility"
export function useMockServerWorkspaceSync() { export function useMockServerWorkspaceSync() {
const workspaceService = useService(WorkspaceService) const workspaceService = useService(WorkspaceService)
const { isMockServerVisible } = useMockServerVisibility() const { isMockServerVisible } = useMockServerVisibility()
const isAuthenticated = !!platform.auth.getCurrentUser()
// Initial load of mock servers for the current workspace const currentUser = useReadonlyStream(
onMounted(() => { platform.auth.getCurrentUserStream(),
if (!isAuthenticated || !isMockServerVisible.value) return platform.auth.getCurrentUser()
)
const loadServers = () => {
if (!currentUser.value || !isMockServerVisible.value) return
loadMockServers().catch(() => setMockServers([])) loadMockServers().catch(() => setMockServers([]))
}
// Load mock servers when authentication or visibility changes
watch([currentUser, isMockServerVisible], loadServers, {
immediate: true,
}) })
// Watch for workspace changes and clear mock servers immediately // Watch for workspace changes and clear mock servers immediately
watch( watch(
() => workspaceService.currentWorkspace.value, () => workspaceService.currentWorkspace.value,
(newWorkspace, oldWorkspace) => { (newWorkspace, oldWorkspace) => {
if (!isAuthenticated || !isMockServerVisible.value) return if (!currentUser.value || !isMockServerVisible.value) return
// Clear mock servers when workspace changes to prevent stale data // Clear mock servers when workspace changes to prevent stale data
if ( if (
@ -34,16 +43,10 @@ export function useMockServerWorkspaceSync() {
oldWorkspace?.type === "team" && oldWorkspace?.type === "team" &&
newWorkspace.teamID !== oldWorkspace.teamID) newWorkspace.teamID !== oldWorkspace.teamID)
) { ) {
// Clear mock servers immediately to prevent showing stale data
setMockServers([]) setMockServers([])
loadServers()
// If user is authenticated, reload mock servers for the new workspace
if (platform.auth.getCurrentUser()) {
// fire-and-forget; loadMockServers handles errors internally
loadMockServers().catch(() => setMockServers([]))
}
} }
}, },
{ deep: true, immediate: false } { deep: true }
) )
} }

View file

@ -62,6 +62,7 @@ export type CreateMockServerModalData = {
const defaultMockServerState = { const defaultMockServerState = {
mockServers: [] as MockServer[], mockServers: [] as MockServer[],
loading: false,
} }
type MockServerStoreType = typeof defaultMockServerState type MockServerStoreType = typeof defaultMockServerState
@ -73,6 +74,7 @@ const mockServerDispatchers = defineDispatchers({
) { ) {
return { return {
mockServers, mockServers,
loading: false,
} }
}, },
@ -104,6 +106,12 @@ const mockServerDispatchers = defineDispatchers({
mockServers: mockServers.filter((server) => server.id !== id), mockServers: mockServers.filter((server) => server.id !== id),
} }
}, },
setLoading(_: MockServerStoreType, { loading }: { loading: boolean }) {
return {
loading,
}
},
}) })
export const mockServerStore = new DispatchingStore( export const mockServerStore = new DispatchingStore(
@ -112,6 +120,7 @@ export const mockServerStore = new DispatchingStore(
) )
export const mockServers$ = mockServerStore.subject$.pipe(pluck("mockServers")) export const mockServers$ = mockServerStore.subject$.pipe(pluck("mockServers"))
export const loading$ = mockServerStore.subject$.pipe(pluck("loading"))
export function setMockServers(mockServers: MockServer[]) { export function setMockServers(mockServers: MockServer[]) {
mockServerStore.dispatch({ mockServerStore.dispatch({
@ -141,6 +150,13 @@ export function deleteMockServer(id: string) {
}) })
} }
export function setLoading(loading: boolean) {
mockServerStore.dispatch({
dispatcher: "setLoading",
payload: { loading },
})
}
// Modal state management // Modal state management
const defaultCreateMockServerModalState: CreateMockServerModalData = { const defaultCreateMockServerModalState: CreateMockServerModalData = {
show: false, show: false,
@ -161,6 +177,7 @@ export function loadMockServers(skip?: number, take?: number) {
if (currentWorkspace.type === "team" && currentWorkspace.teamID) { if (currentWorkspace.type === "team" && currentWorkspace.teamID) {
return loadTeamMockServers(currentWorkspace.teamID, skip, take) return loadTeamMockServers(currentWorkspace.teamID, skip, take)
} }
setLoading(true)
return pipe( return pipe(
getMyMockServers(skip, take), getMyMockServers(skip, take),
TE.match( TE.match(
@ -176,6 +193,7 @@ export function loadMockServers(skip?: number, take?: number) {
)() )()
} catch (_error) { } catch (_error) {
// Fallback to user mock servers if workspace service is not available // Fallback to user mock servers if workspace service is not available
setLoading(true)
return pipe( return pipe(
getMyMockServers(skip, take), getMyMockServers(skip, take),
TE.match( TE.match(
@ -198,6 +216,7 @@ export function loadTeamMockServers(
skip?: number, skip?: number,
take?: number take?: number
) { ) {
setLoading(true)
return pipe( return pipe(
getTeamMockServers(teamID, skip, take), getTeamMockServers(teamID, skip, take),
TE.match( TE.match(