fix: paper/purpur vers mismatch (#5687)

* fix: paper/purpur

* fix: use fill api

* fix: lint
This commit is contained in:
Calum H.
2026-03-27 17:24:16 +00:00
committed by GitHub
parent 87122cf9bd
commit e6b061f38c
8 changed files with 96 additions and 25 deletions

View File

@@ -256,6 +256,26 @@ const purpurBuildsQuery = useQuery({
staleTime: 5 * 60 * 1000, staleTime: 5 * 60 * 1000,
}) })
const paperSupportedVersionsQuery = useQuery({
queryKey: ['paper-supported-versions'] as const,
queryFn: async () => {
const project = await client.paper.versions_v3.getProject()
return new Set(Object.values(project.versions).flat())
},
enabled: computed(() => editingPlatform.value === 'paper'),
staleTime: 5 * 60 * 1000,
})
const purpurSupportedVersionsQuery = useQuery({
queryKey: ['purpur-supported-versions'] as const,
queryFn: async () => {
const project = await client.purpur.versions_v2.getProject()
return new Set(project.versions)
},
enabled: computed(() => editingPlatform.value === 'purpur'),
staleTime: 5 * 60 * 1000,
})
type LoaderVersionEntry = LauncherMeta.Manifest.v0.LoaderVersion type LoaderVersionEntry = LauncherMeta.Manifest.v0.LoaderVersion
function getLoaderVersionsForGameVersion( function getLoaderVersionsForGameVersion(
@@ -363,18 +383,34 @@ provideInstallationSettings({
? tags.gameVersions.value ? tags.gameVersions.value
: tags.gameVersions.value.filter((v) => v.version_type === 'release') : tags.gameVersions.value.filter((v) => v.version_type === 'release')
if (loader && loader !== 'vanilla' && !['paper', 'purpur'].includes(loader)) { if (loader && loader !== 'vanilla') {
const manifest = manifestQuery.data.value?.gameVersions if (loader === 'paper') {
if (manifest) { const supported = paperSupportedVersionsQuery.data.value
const hasPlaceholder = manifest.some((x) => x.id === '${modrinth.gameVersion}') if (supported) {
if (!hasPlaceholder) {
const supportedVersions = new Set(
manifest.filter((x) => x.loaders.length > 0).map((x) => x.id),
)
return versions return versions
.filter((v) => supportedVersions.has(v.version)) .filter((v) => supported.has(v.version))
.map((v) => ({ value: v.version, label: v.version })) .map((v) => ({ value: v.version, label: v.version }))
} }
} else if (loader === 'purpur') {
const supported = purpurSupportedVersionsQuery.data.value
if (supported) {
return versions
.filter((v) => supported.has(v.version))
.map((v) => ({ value: v.version, label: v.version }))
}
} else {
const manifest = manifestQuery.data.value?.gameVersions
if (manifest) {
const hasPlaceholder = manifest.some((x) => x.id === '${modrinth.gameVersion}')
if (!hasPlaceholder) {
const supportedVersions = new Set(
manifest.filter((x) => x.loaders.length > 0).map((x) => x.id),
)
return versions
.filter((v) => supportedVersions.has(v.version))
.map((v) => ({ value: v.version, label: v.version }))
}
}
} }
} }
@@ -387,9 +423,23 @@ provideInstallationSettings({
}, },
resolveHasSnapshots(loader) { resolveHasSnapshots(loader) {
if (loader === 'vanilla' || ['paper', 'purpur'].includes(loader)) { if (loader === 'vanilla') {
return tags.gameVersions.value.some((v) => v.version_type !== 'release') return tags.gameVersions.value.some((v) => v.version_type !== 'release')
} }
if (loader === 'paper') {
const supported = paperSupportedVersionsQuery.data.value
if (!supported) return false
return tags.gameVersions.value.some(
(v) => v.version_type !== 'release' && supported.has(v.version),
)
}
if (loader === 'purpur') {
const supported = purpurSupportedVersionsQuery.data.value
if (!supported) return false
return tags.gameVersions.value.some(
(v) => v.version_type !== 'release' && supported.has(v.version),
)
}
const manifest = manifestQuery.data.value?.gameVersions const manifest = manifestQuery.data.value?.gameVersions
if (!manifest) return false if (!manifest) return false
const hasPlaceholder = manifest.some((x) => x.id === '${modrinth.gameVersion}') const hasPlaceholder = manifest.some((x) => x.id === '${modrinth.gameVersion}')

View File

@@ -14,18 +14,18 @@ import { LabrinthAffiliateInternalModule } from './labrinth/affiliate/internal'
import { LabrinthAuthInternalModule } from './labrinth/auth/internal' import { LabrinthAuthInternalModule } from './labrinth/auth/internal'
import { LabrinthAuthV2Module } from './labrinth/auth/v2' import { LabrinthAuthV2Module } from './labrinth/auth/v2'
import { LabrinthBillingInternalModule } from './labrinth/billing/internal' import { LabrinthBillingInternalModule } from './labrinth/billing/internal'
import { LabrinthCollectionsModule } from './labrinth/collections'
import { LabrinthGlobalsInternalModule } from './labrinth/globals/internal' import { LabrinthGlobalsInternalModule } from './labrinth/globals/internal'
import { LabrinthLimitsV3Module } from './labrinth/limits/v3'
import { LabrinthNotificationsV2Module } from './labrinth/notifications/v2' import { LabrinthNotificationsV2Module } from './labrinth/notifications/v2'
import { LabrinthOAuthInternalModule } from './labrinth/oauth/internal' import { LabrinthOAuthInternalModule } from './labrinth/oauth/internal'
import { LabrinthCollectionsModule } from './labrinth/collections'
import { LabrinthOrganizationsV3Module } from './labrinth/organizations/v3' import { LabrinthOrganizationsV3Module } from './labrinth/organizations/v3'
import { LabrinthPatsV2Module } from './labrinth/pats/v2' import { LabrinthPatsV2Module } from './labrinth/pats/v2'
import { LabrinthLimitsV3Module } from './labrinth/limits/v3'
import { LabrinthPayoutV3Module } from './labrinth/payout/v3' import { LabrinthPayoutV3Module } from './labrinth/payout/v3'
import { LabrinthPayoutsV3Module } from './labrinth/payouts/v3' import { LabrinthPayoutsV3Module } from './labrinth/payouts/v3'
import { LabrinthReportsV3Module } from './labrinth/reports/v3'
import { LabrinthProjectsV2Module } from './labrinth/projects/v2' import { LabrinthProjectsV2Module } from './labrinth/projects/v2'
import { LabrinthProjectsV3Module } from './labrinth/projects/v3' import { LabrinthProjectsV3Module } from './labrinth/projects/v3'
import { LabrinthReportsV3Module } from './labrinth/reports/v3'
import { LabrinthServerPingInternalModule } from './labrinth/server-ping/internal' import { LabrinthServerPingInternalModule } from './labrinth/server-ping/internal'
import { LabrinthSessionsV2Module } from './labrinth/sessions/v2' import { LabrinthSessionsV2Module } from './labrinth/sessions/v2'
import { LabrinthStateModule } from './labrinth/state' import { LabrinthStateModule } from './labrinth/state'

View File

@@ -3,11 +3,11 @@ export * from './auth/v2'
export * from './billing/internal' export * from './billing/internal'
export * from './collections' export * from './collections'
export * from './globals/internal' export * from './globals/internal'
export * from './limits/v3'
export * from './notifications/v2' export * from './notifications/v2'
export * from './oauth/internal' export * from './oauth/internal'
export * from './organizations/v3' export * from './organizations/v3'
export * from './pats/v2' export * from './pats/v2'
export * from './limits/v3'
export * from './payout/v3' export * from './payout/v3'
export * from './payouts/v3' export * from './payouts/v3'
export * from './projects/v2' export * from './projects/v2'

View File

@@ -1,6 +1,11 @@
export namespace Paper { export namespace Paper {
export namespace Versions { export namespace Versions {
export namespace v3 { export namespace v3 {
export type Project = {
project: { id: string; name: string }
versions: Record<string, string[]>
}
export type VersionBuilds = { export type VersionBuilds = {
builds: number[] builds: number[]
} }

View File

@@ -12,6 +12,13 @@ export class PaperVersionsV3Module extends AbstractModule {
return 'paper_versions_v3' return 'paper_versions_v3'
} }
/**
* Get the Paper project info including all supported Minecraft versions.
*/
public async getProject(): Promise<Paper.Versions.v3.Project> {
return $fetch<Paper.Versions.v3.Project>(`${BASE_URL}/projects/paper`)
}
/** /**
* Get available Paper builds for a Minecraft version. * Get available Paper builds for a Minecraft version.
* *

View File

@@ -1,6 +1,11 @@
export namespace Purpur { export namespace Purpur {
export namespace Versions { export namespace Versions {
export namespace v2 { export namespace v2 {
export type Project = {
project: string
versions: string[]
}
export type VersionBuilds = { export type VersionBuilds = {
builds: { builds: {
all: string[] all: string[]

View File

@@ -12,6 +12,13 @@ export class PurpurVersionsV2Module extends AbstractModule {
return 'purpur_versions_v2' return 'purpur_versions_v2'
} }
/**
* Get the Purpur project info including all supported Minecraft versions.
*/
public async getProject(): Promise<Purpur.Versions.v2.Project> {
return $fetch<Purpur.Versions.v2.Project>(`${BASE_URL}/purpur`)
}
/** /**
* Get available Purpur builds for a Minecraft version. * Get available Purpur builds for a Minecraft version.
* *

View File

@@ -104,7 +104,7 @@ import { computed, onMounted, ref, watch } from 'vue'
import { useDebugLogger } from '#ui/composables/debug-logger' import { useDebugLogger } from '#ui/composables/debug-logger'
import { injectFilePicker, injectTags } from '../../../../providers' import { injectFilePicker, injectModrinthClient, injectTags } from '../../../../providers'
import Avatar from '../../../base/Avatar.vue' import Avatar from '../../../base/Avatar.vue'
import ButtonStyled from '../../../base/ButtonStyled.vue' import ButtonStyled from '../../../base/ButtonStyled.vue'
import Chips from '../../../base/Chips.vue' import Chips from '../../../base/Chips.vue'
@@ -116,6 +116,7 @@ import { injectCreationFlowContext } from '../creation-flow-context'
import { capitalize, formatLoaderLabel } from '../shared' import { capitalize, formatLoaderLabel } from '../shared'
const debug = useDebugLogger('CustomSetupStage') const debug = useDebugLogger('CustomSetupStage')
const client = injectModrinthClient()
const ctx = injectCreationFlowContext() const ctx = injectCreationFlowContext()
const { const {
selectedLoader, selectedLoader,
@@ -280,9 +281,8 @@ async function fetchLoaderManifest(loader: string) {
async function fetchPaperSupportedVersions() { async function fetchPaperSupportedVersions() {
if (paperSupportedVersions.value) return if (paperSupportedVersions.value) return
try { try {
const res = await fetch('https://api.papermc.io/v2/projects/paper') const project = await client.paper.versions_v3.getProject()
const data = (await res.json()) as { versions: string[] } paperSupportedVersions.value = new Set(Object.values(project.versions).flat())
paperSupportedVersions.value = new Set(data.versions)
} catch { } catch {
paperSupportedVersions.value = new Set() paperSupportedVersions.value = new Set()
} }
@@ -291,9 +291,8 @@ async function fetchPaperSupportedVersions() {
async function fetchPurpurSupportedVersions() { async function fetchPurpurSupportedVersions() {
if (purpurSupportedVersions.value) return if (purpurSupportedVersions.value) return
try { try {
const res = await fetch('https://api.purpurmc.org/v2/purpur') const project = await client.purpur.versions_v2.getProject()
const data = (await res.json()) as { versions: string[] } purpurSupportedVersions.value = new Set(project.versions)
purpurSupportedVersions.value = new Set(data.versions)
} catch { } catch {
purpurSupportedVersions.value = new Set() purpurSupportedVersions.value = new Set()
} }
@@ -302,8 +301,7 @@ async function fetchPurpurSupportedVersions() {
async function fetchPaperVersions(mcVersion: string) { async function fetchPaperVersions(mcVersion: string) {
if (paperVersions.value[mcVersion]) return if (paperVersions.value[mcVersion]) return
try { try {
const res = await fetch(`https://fill.papermc.io/v3/projects/paper/versions/${mcVersion}`) const data = await client.paper.versions_v3.getBuilds(mcVersion)
const data = (await res.json()) as { builds: number[] }
paperVersions.value[mcVersion] = data.builds.sort((a, b) => b - a) paperVersions.value[mcVersion] = data.builds.sort((a, b) => b - a)
} catch { } catch {
paperVersions.value[mcVersion] = [] paperVersions.value[mcVersion] = []
@@ -313,8 +311,7 @@ async function fetchPaperVersions(mcVersion: string) {
async function fetchPurpurVersions(mcVersion: string) { async function fetchPurpurVersions(mcVersion: string) {
if (purpurVersions.value[mcVersion]) return if (purpurVersions.value[mcVersion]) return
try { try {
const res = await fetch(`https://api.purpurmc.org/v2/purpur/${mcVersion}`) const data = await client.purpur.versions_v2.getBuilds(mcVersion)
const data = (await res.json()) as { builds: { all: string[] } }
purpurVersions.value[mcVersion] = data.builds.all.sort((a, b) => parseInt(b) - parseInt(a)) purpurVersions.value[mcVersion] = data.builds.all.sort((a, b) => parseInt(b) - parseInt(a))
} catch { } catch {
purpurVersions.value[mcVersion] = [] purpurVersions.value[mcVersion] = []