Files
speckle-server/packages/frontend-2/plugins/060-dataPreload.ts
T
Kristaps Fabians Geikins 624b56eacf chore(fe2): even more performant and even less hydration mismatches (#5292)
* fix(fe2): more preview related mismatch fixes

* moar

* a bunch of preloads

* more preloads

* batchlink

* undo cache only

* lint fix

* more query opt

* rate limiter adjustments to account for batched reqs
2025-08-22 08:22:18 +03:00

143 lines
4.1 KiB
TypeScript

import { activeUserQuery } from '~/lib/auth/composables/activeUser'
import {
authLoginPanelQuery,
authLoginPanelWorkspaceInviteQuery
} from '~/lib/auth/graphql/queries'
import {
activeWorkspacePlanPricesQuery,
workspacePlanPricesQuery
} from '~/lib/billing/composables/prices'
import { usePreloadApolloQueries } from '~/lib/common/composables/graphql'
import { WorkspaceJoinRequestStatus } from '~/lib/common/generated/gql/graphql'
import { serverInfoBlobSizeLimitQuery } from '~/lib/common/graphql/queries'
import { useMiddlewareQueryFetchPolicy } from '~/lib/core/composables/navigation'
import { mainServerInfoDataQuery } from '~/lib/core/composables/server'
import {
navigationProjectInvitesQuery,
navigationWorkspaceInvitesQuery,
navigationWorkspaceSwitcherQuery,
workspaceSwitcherHeaderWorkspaceQuery
} from '~/lib/navigation/graphql/queries'
import {
discoverableWorkspacesQuery,
workspacePlanQuery
} from '~/lib/workspaces/graphql/queries'
import {
buildActiveUserWorkspaceExistenceCheckQuery,
buildWorkspaceAccessCheckQuery
} from '~/lib/workspaces/helpers/middleware'
/**
* Prefetches data for specific routes to avoid the problem of serial API requests
* (e.g. in the case of multiple middlewares)
*
* TODO: Some of these could be merged for even further gains
*/
export default defineNuxtPlugin(async (ctx) => {
const logger = useLogger()
const route = ctx._route
const preload = usePreloadApolloQueries()
const isWorkspacesEnabled = useIsWorkspacesEnabled()
const isBillingEnabled = useIsBillingIntegrationEnabled()
const fetchPolicy = useMiddlewareQueryFetchPolicy()
if (!route) {
logger.info('No route obj found, skipping data preload...')
return
}
const promises: Promise<unknown>[] = []
// Standard/global
promises.push(
preload({
queries: [
{ query: activeUserQuery },
{ query: mainServerInfoDataQuery },
{ query: serverInfoBlobSizeLimitQuery },
{ query: navigationProjectInvitesQuery },
...(isWorkspacesEnabled.value
? [
...(isBillingEnabled.value
? [
{
query: workspacePlanPricesQuery
}
]
: []),
{
query: discoverableWorkspacesQuery
},
{
query: navigationWorkspaceInvitesQuery
},
{
query: navigationWorkspaceSwitcherQuery
},
{
query: navigationWorkspaceSwitcherQuery,
variables: {
joinRequestFilter: {
status: WorkspaceJoinRequestStatus.Pending
}
}
},
buildActiveUserWorkspaceExistenceCheckQuery()
]
: [])
]
})
)
// Preload viewer data
if (route.meta.key === '/projects/:id/models/resources') {
// Unable to preload this from vue components due to SSR being essentially turned off for the viewer
promises.push(
preload({
queries: [
{ query: authLoginPanelQuery },
...(isWorkspacesEnabled.value
? [{ query: authLoginPanelWorkspaceInviteQuery }]
: [])
]
})
)
}
// Preload workspace access check
const workspaceSlug = route.params.slug as string
if (workspaceSlug && isWorkspacesEnabled.value) {
promises.push(
preload({
queries: [
buildWorkspaceAccessCheckQuery(workspaceSlug, fetchPolicy(route)),
{
query: workspacePlanQuery,
variables: {
slug: workspaceSlug
}
},
{
query: workspaceSwitcherHeaderWorkspaceQuery,
variables: {
slug: workspaceSlug
}
},
...(isBillingEnabled.value
? [
{
query: activeWorkspacePlanPricesQuery,
variables: {
slug: workspaceSlug
}
}
]
: [])
]
})
)
}
await Promise.all(promises)
})