fix: invalidate tanstack caches on user auth (#5341)
* fix: invalidate tanstack caches on user auth * refactor: clean up invalidate flow * fix: lint
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import type { AbstractModrinthClient } from '@modrinth/api-client'
|
||||
|
||||
const STALE_TIME = 1000 * 60 * 5 // 5 minutes
|
||||
export const STALE_TIME = 1000 * 60 * 5 // 5 minutes
|
||||
export const STALE_TIME_LONG = 1000 * 60 * 10 // 10 minutes
|
||||
|
||||
export const projectQueryOptions = {
|
||||
v2: (projectId: string, client: AbstractModrinthClient) => ({
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { useAppQueryClient } from '@/composables/query-client'
|
||||
|
||||
export const useUser = async (force = false) => {
|
||||
const user = useState('user', () => {})
|
||||
|
||||
@@ -158,5 +160,6 @@ export const logout = async () => {
|
||||
|
||||
await useAuth('none')
|
||||
useCookie('auth-token').value = null
|
||||
useAppQueryClient().clear()
|
||||
stopLoading()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useGeneratedState } from '~/composables/generated'
|
||||
import { projectQueryOptions } from '~/composables/queries/project'
|
||||
import { useAppQueryClient } from '~/composables/query-client'
|
||||
import { getProjectTypeForUrlShorthand } from '~/helpers/projects.js'
|
||||
import { useServerModrinthClient } from '~/server/utils/api-client'
|
||||
@@ -21,11 +22,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
||||
try {
|
||||
// Fetch v2 project for redirect check AND cache it for the page
|
||||
// Using fetchQuery ensures the page's useQuery gets this cached result
|
||||
const project = await queryClient.fetchQuery({
|
||||
queryKey: ['project', 'v2', projectId],
|
||||
queryFn: () => client.labrinth.projects_v2.get(projectId),
|
||||
staleTime: 1000 * 60 * 5,
|
||||
})
|
||||
const project = await queryClient.fetchQuery(projectQueryOptions.v2(projectId, client))
|
||||
|
||||
// Let page handle 404
|
||||
if (!project) return
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
:is-settings="route.name.startsWith('type-id-settings')"
|
||||
:set-processing="setProcessing"
|
||||
:all-members="allMembers"
|
||||
:update-members="refreshMembers"
|
||||
:update-members="invalidateProject"
|
||||
:auth="auth"
|
||||
:tags="tags"
|
||||
/>
|
||||
@@ -747,7 +747,7 @@
|
||||
:collapsed="collapsedChecklist"
|
||||
:toggle-collapsed="() => (collapsedChecklist = !collapsedChecklist)"
|
||||
:all-members="allMembers"
|
||||
:update-members="updateMembers"
|
||||
:update-members="invalidateProject"
|
||||
:auth="auth"
|
||||
:tags="tags"
|
||||
/>
|
||||
@@ -1008,6 +1008,7 @@ import ModerationChecklist from '~/components/ui/moderation/checklist/Moderation
|
||||
import NavTabs from '~/components/ui/NavTabs.vue'
|
||||
import ProjectMemberHeader from '~/components/ui/ProjectMemberHeader.vue'
|
||||
import { saveFeatureFlags } from '~/composables/featureFlags.ts'
|
||||
import { STALE_TIME, STALE_TIME_LONG } from '~/composables/queries/project'
|
||||
import { userCollectProject, userFollowProject } from '~/composables/user.js'
|
||||
import { useModerationStore } from '~/store/moderation.ts'
|
||||
import { reportProject } from '~/utils/report-helpers.ts'
|
||||
@@ -1472,14 +1473,10 @@ const client = injectModrinthClient()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
// V2 Project - hits middleware cache (uses route param for lookup)
|
||||
const {
|
||||
data: projectRaw,
|
||||
error: projectV2Error,
|
||||
refetch: resetProjectV2,
|
||||
} = useQuery({
|
||||
const { data: projectRaw, error: projectV2Error } = useQuery({
|
||||
queryKey: computed(() => ['project', 'v2', routeProjectId.value]),
|
||||
queryFn: () => client.labrinth.projects_v2.get(routeProjectId.value),
|
||||
staleTime: 1000 * 60 * 5,
|
||||
staleTime: STALE_TIME,
|
||||
})
|
||||
|
||||
// Handle project not found - use showError since watch runs outside Nuxt context
|
||||
@@ -1522,26 +1519,18 @@ const project = computed(() => {
|
||||
const projectId = computed(() => projectRaw.value?.id)
|
||||
|
||||
// V3 Project
|
||||
const {
|
||||
data: projectV3,
|
||||
error: _projectV3Error,
|
||||
refetch: resetProjectV3,
|
||||
} = useQuery({
|
||||
const { data: projectV3, error: _projectV3Error } = useQuery({
|
||||
queryKey: computed(() => ['project', 'v3', projectId.value]),
|
||||
queryFn: () => client.labrinth.projects_v3.get(projectId.value),
|
||||
staleTime: 1000 * 60 * 5,
|
||||
staleTime: STALE_TIME,
|
||||
enabled: computed(() => !!projectId.value),
|
||||
})
|
||||
|
||||
// Members
|
||||
const {
|
||||
data: allMembersRaw,
|
||||
error: _membersError,
|
||||
refetch: _resetMembers,
|
||||
} = useQuery({
|
||||
const { data: allMembersRaw, error: _membersError } = useQuery({
|
||||
queryKey: computed(() => ['project', projectId.value, 'members']),
|
||||
queryFn: () => client.labrinth.projects_v3.getMembers(projectId.value),
|
||||
staleTime: 1000 * 60 * 5,
|
||||
staleTime: STALE_TIME,
|
||||
enabled: computed(() => !!projectId.value),
|
||||
})
|
||||
|
||||
@@ -1556,25 +1545,26 @@ const allMembers = computed(() => {
|
||||
})
|
||||
|
||||
// Dependencies - lazy loaded client-side only
|
||||
const dependenciesEnabled = ref(false)
|
||||
const {
|
||||
data: dependenciesRaw,
|
||||
error: _dependenciesError,
|
||||
isFetching: dependenciesLoading,
|
||||
refetch: refetchDependencies,
|
||||
} = useQuery({
|
||||
queryKey: computed(() => ['project', projectId.value, 'dependencies']),
|
||||
queryFn: () => client.labrinth.projects_v2.getDependencies(projectId.value),
|
||||
staleTime: 1000 * 60 * 10,
|
||||
staleTime: STALE_TIME_LONG,
|
||||
enabled: computed(() => !!projectId.value && dependenciesEnabled.value),
|
||||
})
|
||||
|
||||
const dependencies = computed(() => dependenciesRaw.value ?? null)
|
||||
|
||||
// V3 Versions - lazy loaded client-side only
|
||||
const versionsEnabled = ref(false)
|
||||
const {
|
||||
data: versionsV3,
|
||||
error: _versionsV3Error,
|
||||
isFetching: versionsV3Loading,
|
||||
refetch: resetVersionsV3,
|
||||
} = useQuery({
|
||||
queryKey: computed(() => ['project', projectId.value, 'versions', 'v3']),
|
||||
queryFn: () =>
|
||||
@@ -1582,15 +1572,16 @@ const {
|
||||
include_changelog: false,
|
||||
apiVersion: 3,
|
||||
}),
|
||||
staleTime: 1000 * 60 * 10,
|
||||
staleTime: STALE_TIME_LONG,
|
||||
enabled: computed(() => !!projectId.value && versionsEnabled.value),
|
||||
})
|
||||
|
||||
// Organization
|
||||
// Only fetch organization if project belongs to one
|
||||
const { data: organization, refetch: _resetOrganization } = useQuery({
|
||||
const { data: organization } = useQuery({
|
||||
queryKey: computed(() => ['project', projectId.value, 'organization']),
|
||||
queryFn: () => client.labrinth.projects_v3.getOrganization(projectId.value),
|
||||
staleTime: 1000 * 60 * 5,
|
||||
staleTime: STALE_TIME,
|
||||
enabled: computed(() => !!projectId.value && !!projectRaw.value?.organization),
|
||||
})
|
||||
|
||||
@@ -1616,17 +1607,13 @@ const versions = computed(() => {
|
||||
const versionsLoading = computed(() => versionsV3Loading.value)
|
||||
|
||||
// Load versions on demand (client-side only)
|
||||
async function loadVersions() {
|
||||
// Skip if already loaded or loading
|
||||
if (versionsV3.value || versionsV3Loading.value) return
|
||||
await resetVersionsV3()
|
||||
function loadVersions() {
|
||||
versionsEnabled.value = true
|
||||
}
|
||||
|
||||
// Load dependencies on demand (client-side only)
|
||||
async function loadDependencies() {
|
||||
// Skip if already loaded or loading
|
||||
if (dependenciesRaw.value || dependenciesLoading.value) return
|
||||
await refetchDependencies()
|
||||
function loadDependencies() {
|
||||
dependenciesEnabled.value = true
|
||||
}
|
||||
|
||||
// Check if project has versions using the ID array from the V2 project
|
||||
@@ -1654,25 +1641,13 @@ async function updateProjectRoute() {
|
||||
}
|
||||
}
|
||||
|
||||
async function resetProject() {
|
||||
await invalidateProjectQueries(projectId.value)
|
||||
await resetProjectV2()
|
||||
await resetProjectV3()
|
||||
}
|
||||
|
||||
async function resetVersions() {
|
||||
await invalidateProjectQueries(projectId.value)
|
||||
await resetVersionsV3()
|
||||
}
|
||||
|
||||
// Helper to invalidate project queries after mutations settle
|
||||
async function invalidateProjectQueries(projectId) {
|
||||
async function invalidateProject() {
|
||||
await queryClient.invalidateQueries({ queryKey: ['project', 'v2', routeProjectId.value] })
|
||||
if (routeProjectId.value !== projectId) {
|
||||
await queryClient.invalidateQueries({ queryKey: ['project', 'v2', projectId] })
|
||||
if (routeProjectId.value !== projectId.value) {
|
||||
await queryClient.invalidateQueries({ queryKey: ['project', 'v2', projectId.value] })
|
||||
}
|
||||
await queryClient.invalidateQueries({ queryKey: ['project', 'v3', projectId] })
|
||||
await queryClient.invalidateQueries({ queryKey: ['project', projectId, 'versions', 'v3'] })
|
||||
// Prefix match — invalidates members, versions, dependencies, organization
|
||||
await queryClient.invalidateQueries({ queryKey: ['project', projectId.value] })
|
||||
}
|
||||
|
||||
// Mutation for patching project data
|
||||
@@ -1718,8 +1693,8 @@ const patchProjectMutation = useMutation({
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||
},
|
||||
|
||||
onSettled: async (_data, _error, { projectId }) => {
|
||||
await invalidateProjectQueries(projectId)
|
||||
onSettled: async () => {
|
||||
await invalidateProject()
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1763,8 +1738,8 @@ const patchStatusMutation = useMutation({
|
||||
})
|
||||
},
|
||||
|
||||
onSettled: async (_data, _error, { projectId }) => {
|
||||
await invalidateProjectQueries(projectId)
|
||||
onSettled: async () => {
|
||||
await invalidateProject()
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1797,8 +1772,8 @@ const patchIconMutation = useMutation({
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||
},
|
||||
|
||||
onSettled: async (_data, _error, { projectId }) => {
|
||||
await invalidateProjectQueries(projectId)
|
||||
onSettled: async () => {
|
||||
await invalidateProject()
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1860,8 +1835,8 @@ const createGalleryItemMutation = useMutation({
|
||||
})
|
||||
},
|
||||
|
||||
onSettled: async (_data, _error, { projectId }) => {
|
||||
await invalidateProjectQueries(projectId)
|
||||
onSettled: async () => {
|
||||
await invalidateProject()
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1922,8 +1897,8 @@ const editGalleryItemMutation = useMutation({
|
||||
})
|
||||
},
|
||||
|
||||
onSettled: async (_data, _error, { projectId }) => {
|
||||
await invalidateProjectQueries(projectId)
|
||||
onSettled: async () => {
|
||||
await invalidateProject()
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1961,8 +1936,8 @@ const deleteGalleryItemMutation = useMutation({
|
||||
})
|
||||
},
|
||||
|
||||
onSettled: async (_data, _error, { projectId }) => {
|
||||
await invalidateProjectQueries(projectId)
|
||||
onSettled: async () => {
|
||||
await invalidateProject()
|
||||
},
|
||||
})
|
||||
|
||||
@@ -2202,15 +2177,6 @@ async function deleteGalleryItem(imageUrl) {
|
||||
})
|
||||
}
|
||||
|
||||
async function refreshMembers() {
|
||||
// Simply invalidate and refetch - the computed allMembers will auto-update
|
||||
await queryClient.invalidateQueries({ queryKey: ['project', projectId.value, 'members'] })
|
||||
}
|
||||
|
||||
async function refreshOrganization() {
|
||||
await queryClient.invalidateQueries({ queryKey: ['project', projectId.value, 'organization'] })
|
||||
}
|
||||
|
||||
async function copyId() {
|
||||
await navigator.clipboard.writeText(project.value.id)
|
||||
}
|
||||
@@ -2266,8 +2232,7 @@ async function deleteVersion(id) {
|
||||
method: 'DELETE',
|
||||
})
|
||||
|
||||
// Refetch versions to reflect deletion (versions is a computed ref)
|
||||
await resetVersions()
|
||||
await invalidateProject()
|
||||
|
||||
stopLoading()
|
||||
}
|
||||
@@ -2320,11 +2285,8 @@ provideProjectPageContext({
|
||||
dependencies,
|
||||
dependenciesLoading: computed(() => dependenciesLoading.value),
|
||||
|
||||
// Refresh functions (invalidate + refetch)
|
||||
refreshProject: resetProject,
|
||||
refreshVersions: resetVersions,
|
||||
refreshMembers,
|
||||
refreshOrganization,
|
||||
// Invalidate all project queries (auto-refetches active ones)
|
||||
invalidate: invalidateProject,
|
||||
|
||||
// Lazy loading
|
||||
loadVersions,
|
||||
|
||||
@@ -340,7 +340,6 @@ import {
|
||||
ConfirmModal,
|
||||
DropArea,
|
||||
FileInput,
|
||||
injectNotificationManager,
|
||||
injectProjectPageContext,
|
||||
NewModal as Modal,
|
||||
} from '@modrinth/ui'
|
||||
@@ -352,8 +351,13 @@ import { isPermission } from '~/utils/permissions.ts'
|
||||
const router = useRouter()
|
||||
|
||||
// Single DI injection
|
||||
const { addNotification } = injectNotificationManager()
|
||||
const { projectV2: project, currentMember, refreshProject } = injectProjectPageContext()
|
||||
const {
|
||||
projectV2: project,
|
||||
currentMember,
|
||||
createGalleryItem: contextCreateGalleryItem,
|
||||
editGalleryItem: contextEditGalleryItem,
|
||||
deleteGalleryItem: contextDeleteGalleryItem,
|
||||
} = injectProjectPageContext()
|
||||
|
||||
// Template refs
|
||||
const modalEditItem = useTemplateRef('modal_edit_item')
|
||||
@@ -486,37 +490,16 @@ async function createGalleryItem() {
|
||||
shouldPreventActions.value = true
|
||||
startLoading()
|
||||
|
||||
try {
|
||||
let url = `project/${project.value.id}/gallery?ext=${
|
||||
editFile.value
|
||||
? editFile.value.type.split('/')[editFile.value.type.split('/').length - 1]
|
||||
: null
|
||||
}&featured=${editFeatured.value}`
|
||||
|
||||
if (editTitle.value) {
|
||||
url += `&title=${encodeURIComponent(editTitle.value)}`
|
||||
}
|
||||
if (editDescription.value) {
|
||||
url += `&description=${encodeURIComponent(editDescription.value)}`
|
||||
}
|
||||
if (editOrder.value) {
|
||||
url += `&ordering=${editOrder.value}`
|
||||
}
|
||||
|
||||
await useBaseFetch(url, {
|
||||
method: 'POST',
|
||||
body: editFile.value,
|
||||
})
|
||||
await refreshProject()
|
||||
const success = await contextCreateGalleryItem(
|
||||
editFile.value!,
|
||||
editTitle.value || undefined,
|
||||
editDescription.value || undefined,
|
||||
editFeatured.value,
|
||||
editOrder.value ? Number(editOrder.value) : undefined,
|
||||
)
|
||||
|
||||
if (success) {
|
||||
modalEditItem.value?.hide()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { data?: { description?: string } }
|
||||
addNotification({
|
||||
title: 'An error occurred',
|
||||
text: error.data?.description ?? String(err),
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
|
||||
stopLoading()
|
||||
@@ -526,34 +509,18 @@ async function createGalleryItem() {
|
||||
async function editGalleryItem() {
|
||||
shouldPreventActions.value = true
|
||||
startLoading()
|
||||
try {
|
||||
let url = `project/${project.value.id}/gallery?url=${encodeURIComponent(
|
||||
project.value!.gallery![editIndex.value].url,
|
||||
)}&featured=${editFeatured.value}`
|
||||
|
||||
if (editTitle.value) {
|
||||
url += `&title=${encodeURIComponent(editTitle.value)}`
|
||||
}
|
||||
if (editDescription.value) {
|
||||
url += `&description=${encodeURIComponent(editDescription.value)}`
|
||||
}
|
||||
if (editOrder.value) {
|
||||
url += `&ordering=${editOrder.value}`
|
||||
}
|
||||
const imageUrl = project.value!.gallery![editIndex.value].url
|
||||
const success = await contextEditGalleryItem(
|
||||
imageUrl,
|
||||
editTitle.value || undefined,
|
||||
editDescription.value || undefined,
|
||||
editFeatured.value,
|
||||
editOrder.value ? Number(editOrder.value) : undefined,
|
||||
)
|
||||
|
||||
await useBaseFetch(url, {
|
||||
method: 'PATCH',
|
||||
})
|
||||
|
||||
await refreshProject()
|
||||
if (success) {
|
||||
modalEditItem.value?.hide()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { data?: { description?: string } }
|
||||
addNotification({
|
||||
title: 'An error occurred',
|
||||
text: error.data?.description ?? String(err),
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
|
||||
stopLoading()
|
||||
@@ -563,25 +530,8 @@ async function editGalleryItem() {
|
||||
async function deleteGalleryImage() {
|
||||
startLoading()
|
||||
|
||||
try {
|
||||
await useBaseFetch(
|
||||
`project/${project.value.id}/gallery?url=${encodeURIComponent(
|
||||
project.value!.gallery![deleteIndex.value].url!,
|
||||
)}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
},
|
||||
)
|
||||
|
||||
await refreshProject()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { data?: { description?: string } }
|
||||
addNotification({
|
||||
title: 'An error occurred',
|
||||
text: error.data?.description ?? String(err),
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
const imageUrl = project.value!.gallery![deleteIndex.value].url!
|
||||
await contextDeleteGalleryItem(imageUrl)
|
||||
|
||||
stopLoading()
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ import {
|
||||
} from '~/helpers/projects.js'
|
||||
|
||||
const { addNotification } = injectNotificationManager()
|
||||
const { projectV2: project, currentMember, refreshProject } = injectProjectPageContext()
|
||||
const { projectV2: project, currentMember, invalidate } = injectProjectPageContext()
|
||||
|
||||
const auth = await useAuth()
|
||||
|
||||
@@ -134,7 +134,7 @@ async function setStatus(status) {
|
||||
})
|
||||
|
||||
project.value.status = status
|
||||
await refreshProject()
|
||||
await invalidate()
|
||||
thread.value = await useBaseFetch(`thread/${thread.value.id}`)
|
||||
} catch (err) {
|
||||
addNotification({
|
||||
|
||||
@@ -274,7 +274,7 @@ const {
|
||||
currentMember,
|
||||
patchProject,
|
||||
patchIcon,
|
||||
refreshProject,
|
||||
invalidate,
|
||||
} = injectProjectPageContext()
|
||||
|
||||
const flags = useFeatureFlags()
|
||||
@@ -407,7 +407,7 @@ const deleteIcon = async () => {
|
||||
await useBaseFetch(`project/${project.value.id}/icon`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
await refreshProject()
|
||||
await invalidate()
|
||||
addNotification({
|
||||
title: 'Project icon removed',
|
||||
text: "Your project's icon has been removed.",
|
||||
|
||||
@@ -562,9 +562,7 @@ const {
|
||||
organization,
|
||||
allMembers,
|
||||
currentMember,
|
||||
refreshProject,
|
||||
refreshOrganization,
|
||||
refreshMembers,
|
||||
invalidate,
|
||||
} = injectProjectPageContext()
|
||||
|
||||
const cosmetics = useCosmetics()
|
||||
@@ -838,7 +836,7 @@ async function updateOrgMember(index) {
|
||||
}
|
||||
|
||||
const updateMembers = async () => {
|
||||
await Promise.all([refreshProject(), refreshOrganization(), refreshMembers()])
|
||||
await invalidate()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ const {
|
||||
projectV2: project,
|
||||
currentMember,
|
||||
versions,
|
||||
refreshVersions,
|
||||
invalidate,
|
||||
loadVersions,
|
||||
} = injectProjectPageContext()
|
||||
|
||||
@@ -387,7 +387,7 @@ async function deleteVersion() {
|
||||
})
|
||||
}
|
||||
|
||||
refreshVersions()
|
||||
await invalidate()
|
||||
selectedVersion.value = null
|
||||
|
||||
stopLoading()
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
<template>
|
||||
<div v-if="version" class="version-page">
|
||||
<CreateProjectVersionModal
|
||||
v-if="currentMember"
|
||||
ref="createProjectVersionModal"
|
||||
@save="handleVersionSaved"
|
||||
/>
|
||||
<CreateProjectVersionModal v-if="currentMember" ref="createProjectVersionModal" />
|
||||
<ConfirmModal
|
||||
v-if="currentMember"
|
||||
ref="modal_confirm"
|
||||
@@ -470,8 +466,7 @@ const {
|
||||
loadVersions,
|
||||
dependencies: contextDependencies,
|
||||
loadDependencies,
|
||||
refreshVersions,
|
||||
refreshProject,
|
||||
invalidate,
|
||||
} = injectProjectPageContext()
|
||||
|
||||
// Load versions and dependencies in parallel
|
||||
@@ -619,8 +614,8 @@ if (route.params.version === 'create') {
|
||||
)) as any
|
||||
if (versionV3) {
|
||||
version.value = versionV3
|
||||
// Refresh versions cache to include this version
|
||||
await refreshVersions()
|
||||
// Refresh cache to include this version
|
||||
await invalidate()
|
||||
}
|
||||
} catch {
|
||||
// API fetch failed - version truly doesn't exist, will 404 below
|
||||
@@ -733,10 +728,6 @@ function handleOpenEditVersionModal(versionId: string, projectId: string, stageI
|
||||
createProjectVersionModal.value?.openEditVersionModal(versionId, projectId, stageId)
|
||||
}
|
||||
|
||||
async function handleVersionSaved() {
|
||||
router.go(0) // reload page for new data
|
||||
}
|
||||
|
||||
async function _onImageUpload(file: File) {
|
||||
const response = await useImageUpload(file, { context: 'version' })
|
||||
|
||||
@@ -1070,7 +1061,7 @@ async function createDataPackVersionHandler() {
|
||||
}
|
||||
|
||||
async function resetProjectVersions() {
|
||||
await Promise.all([refreshVersions(), refreshProject()])
|
||||
await invalidate()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ const { addNotification } = injectNotificationManager()
|
||||
const {
|
||||
projectV2: project,
|
||||
currentMember,
|
||||
refreshVersions,
|
||||
invalidate,
|
||||
versions,
|
||||
versionsLoading,
|
||||
loadVersions,
|
||||
@@ -379,7 +379,7 @@ async function deleteVersion() {
|
||||
})
|
||||
}
|
||||
|
||||
refreshVersions()
|
||||
await invalidate()
|
||||
selectedVersion.value = null
|
||||
|
||||
stopLoading()
|
||||
|
||||
@@ -149,10 +149,12 @@ import {
|
||||
IntlFormatted,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { useQueryClient } from '@tanstack/vue-query'
|
||||
|
||||
import HCaptcha from '@/components/ui/HCaptcha.vue'
|
||||
import { getAuthUrl, getLauncherRedirectUrl } from '@/composables/auth.js'
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const { addNotification } = injectNotificationManager()
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
@@ -306,6 +308,7 @@ async function finishSignIn(token) {
|
||||
if (token) {
|
||||
await useAuth(token)
|
||||
await useUser()
|
||||
queryClient.clear()
|
||||
}
|
||||
|
||||
if (route.query.redirect) {
|
||||
|
||||
@@ -57,7 +57,9 @@ import {
|
||||
normalizeChildren,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { useQueryClient } from '@tanstack/vue-query'
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const route = useRoute()
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
@@ -96,6 +98,7 @@ const subscribe = ref(true)
|
||||
onMounted(async () => {
|
||||
await useAuth(route.query.authToken)
|
||||
await useUser()
|
||||
queryClient.clear()
|
||||
})
|
||||
|
||||
async function continueSignUp() {
|
||||
|
||||
@@ -166,7 +166,7 @@ export function createManageVersionContext(
|
||||
): ManageVersionContextValue {
|
||||
const { labrinth } = injectModrinthClient()
|
||||
const { addNotification } = injectNotificationManager()
|
||||
const { refreshVersions, projectV2 } = injectProjectPageContext()
|
||||
const { invalidate, projectV2 } = injectProjectPageContext()
|
||||
|
||||
// State
|
||||
const draftVersion = ref<Labrinth.Versions.v3.DraftVersion>(structuredClone(EMPTY_DRAFT_VERSION))
|
||||
@@ -660,7 +660,7 @@ export function createManageVersionContext(
|
||||
text: 'The version has been successfully added to your project.',
|
||||
type: 'success',
|
||||
})
|
||||
await refreshVersions()
|
||||
await invalidate()
|
||||
onSave?.()
|
||||
} catch (err: any) {
|
||||
addNotification({
|
||||
@@ -734,7 +734,7 @@ export function createManageVersionContext(
|
||||
text: 'The version has been successfully saved to your project.',
|
||||
type: 'success',
|
||||
})
|
||||
await refreshVersions()
|
||||
await invalidate()
|
||||
onSave?.()
|
||||
} catch (err: any) {
|
||||
addNotification({
|
||||
|
||||
@@ -140,7 +140,7 @@ export class NuxtModrinthClient extends XHRUploadClient {
|
||||
|
||||
protected async executeRequest<T>(url: string, options: RequestOptions): Promise<T> {
|
||||
try {
|
||||
// @ts-expect-error - $fetch is provided by Nuxt runtime
|
||||
// @ts-expect-error - $fetch is provided by Nuxt
|
||||
const response = await $fetch<T>(url, {
|
||||
method: options.method ?? 'GET',
|
||||
headers: options.headers,
|
||||
@@ -148,6 +148,8 @@ export class NuxtModrinthClient extends XHRUploadClient {
|
||||
params: options.params,
|
||||
timeout: options.timeout,
|
||||
signal: options.signal,
|
||||
// @ts-expect-error - import.meta is provided by Nuxt
|
||||
cache: import.meta.server ? undefined : 'no-store',
|
||||
})
|
||||
|
||||
return response
|
||||
|
||||
@@ -17,15 +17,12 @@ export interface ProjectPageContext {
|
||||
dependencies: Ref<Labrinth.Projects.v2.DependencyInfo | null>
|
||||
dependenciesLoading: Ref<boolean>
|
||||
|
||||
// Refresh functions (invalidate + refetch)
|
||||
refreshProject: () => Promise<void>
|
||||
refreshVersions: () => Promise<void>
|
||||
refreshMembers: () => Promise<void>
|
||||
refreshOrganization: () => Promise<void>
|
||||
// Invalidate all project queries (auto-refetches active ones)
|
||||
invalidate: () => Promise<void>
|
||||
|
||||
// Lazy loading
|
||||
loadVersions: () => Promise<void>
|
||||
loadDependencies: () => Promise<void>
|
||||
loadVersions: () => void
|
||||
loadDependencies: () => void
|
||||
|
||||
// Mutation functions
|
||||
patchProject: (data: Record<string, unknown>, quiet?: boolean) => Promise<boolean>
|
||||
|
||||
Reference in New Issue
Block a user