fix: window on ssr error + cors problem with launcher meta (#5856)
This commit is contained in:
@@ -13,6 +13,11 @@ export class LauncherMetaManifestV0Module extends AbstractModule {
|
|||||||
/**
|
/**
|
||||||
* Get the loader manifest for a given loader platform.
|
* Get the loader manifest for a given loader platform.
|
||||||
*
|
*
|
||||||
|
* launcher-meta refuses CORS preflights that ask for the `Content-Type`
|
||||||
|
* header (returns 403), so we strip the default `Content-Type: application/json`
|
||||||
|
* the abstract client sets — these are body-less GETs and don't need it.
|
||||||
|
* Without this the browser preflight is rejected and the GET never fires.
|
||||||
|
*
|
||||||
* @param loader - Loader platform (fabric, forge, quilt, neo)
|
* @param loader - Loader platform (fabric, forge, quilt, neo)
|
||||||
*/
|
*/
|
||||||
public async getManifest(loader: string): Promise<LauncherMeta.Manifest.v0.Manifest> {
|
public async getManifest(loader: string): Promise<LauncherMeta.Manifest.v0.Manifest> {
|
||||||
@@ -21,6 +26,7 @@ export class LauncherMetaManifestV0Module extends AbstractModule {
|
|||||||
version: `${loader}/v0`,
|
version: `${loader}/v0`,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
skipAuth: true,
|
skipAuth: true,
|
||||||
|
headers: { 'Content-Type': '' },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
<!-- eslint-disable no-console -->
|
<!-- eslint-disable no-console -->
|
||||||
<script setup>
|
<script setup>
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { defineAsyncComponent, ref } from 'vue'
|
import { defineAsyncComponent, onMounted, ref } from 'vue'
|
||||||
|
|
||||||
import { useFormatNumber } from '../../composables/index.ts'
|
import { useFormatNumber } from '../../composables/index.ts'
|
||||||
import Button from '../base/Button.vue'
|
import Button from '../base/Button.vue'
|
||||||
import Checkbox from '../base/Checkbox.vue'
|
import Checkbox from '../base/Checkbox.vue'
|
||||||
|
|
||||||
const VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
|
const VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
|
||||||
|
|
||||||
|
// apexcharts touches `window` at module load time, so we must not let SSR
|
||||||
|
// resolve the async component. Render only after mount on the client.
|
||||||
|
const isClient = ref(false)
|
||||||
|
onMounted(() => {
|
||||||
|
isClient.value = true
|
||||||
|
})
|
||||||
|
|
||||||
const formatNumber = useFormatNumber()
|
const formatNumber = useFormatNumber()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -232,7 +240,14 @@ defineExpose({
|
|||||||
<slot name="toolbar" />
|
<slot name="toolbar" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<VueApexCharts ref="chart" :type="type" :options="chartOptions" :series="data" class="chart" />
|
<VueApexCharts
|
||||||
|
v-if="isClient"
|
||||||
|
ref="chart"
|
||||||
|
:type="type"
|
||||||
|
:options="chartOptions"
|
||||||
|
:series="data"
|
||||||
|
class="chart"
|
||||||
|
/>
|
||||||
<div v-if="!hideLegend" class="legend">
|
<div v-if="!hideLegend" class="legend">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
v-for="legend in legendValues"
|
v-for="legend in legendValues"
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
<!-- eslint-disable eslint-comments/require-description -->
|
<!-- eslint-disable eslint-comments/require-description -->
|
||||||
<script setup>
|
<script setup>
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { defineAsyncComponent, ref } from 'vue'
|
import { defineAsyncComponent, onMounted, ref } from 'vue'
|
||||||
|
|
||||||
import { useFormatNumber } from '../../composables/index.ts'
|
import { useFormatNumber } from '../../composables/index.ts'
|
||||||
import Card from '../base/Card.vue'
|
import Card from '../base/Card.vue'
|
||||||
|
|
||||||
const VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
|
const VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
|
||||||
|
|
||||||
|
// apexcharts touches `window` at module load time, so we must not let SSR
|
||||||
|
// resolve the async component. Render only after mount on the client.
|
||||||
|
const isClient = ref(false)
|
||||||
|
onMounted(() => {
|
||||||
|
isClient.value = true
|
||||||
|
})
|
||||||
|
|
||||||
const formatNumber = useFormatNumber()
|
const formatNumber = useFormatNumber()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -148,6 +155,7 @@ const chartOptions = ref({
|
|||||||
{{ title }}
|
{{ title }}
|
||||||
</div>
|
</div>
|
||||||
<VueApexCharts
|
<VueApexCharts
|
||||||
|
v-if="isClient"
|
||||||
ref="chart"
|
ref="chart"
|
||||||
type="area"
|
type="area"
|
||||||
height="120"
|
height="120"
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
<div v-if="metric.showGraph" class="chart-space absolute bottom-0 left-0 right-0">
|
<div v-if="metric.showGraph" class="chart-space absolute bottom-0 left-0 right-0">
|
||||||
<VueApexCharts
|
<VueApexCharts
|
||||||
v-if="!loading && metric.chartOptions"
|
v-if="isClient && !loading && metric.chartOptions"
|
||||||
type="area"
|
type="area"
|
||||||
height="142"
|
height="142"
|
||||||
:options="metric.chartOptions"
|
:options="metric.chartOptions"
|
||||||
@@ -62,13 +62,20 @@
|
|||||||
import { CpuIcon, DatabaseIcon, FolderOpenIcon } from '@modrinth/assets'
|
import { CpuIcon, DatabaseIcon, FolderOpenIcon } from '@modrinth/assets'
|
||||||
import type { Stats } from '@modrinth/utils'
|
import type { Stats } from '@modrinth/utils'
|
||||||
import { useStorage } from '@vueuse/core'
|
import { useStorage } from '@vueuse/core'
|
||||||
import { computed, defineAsyncComponent, ref, shallowRef, watch } from 'vue'
|
import { computed, defineAsyncComponent, onMounted, ref, shallowRef, watch } from 'vue'
|
||||||
import { RouterLink } from 'vue-router'
|
import { RouterLink } from 'vue-router'
|
||||||
|
|
||||||
import { injectModrinthServerContext, injectPageContext } from '#ui/providers'
|
import { injectModrinthServerContext, injectPageContext } from '#ui/providers'
|
||||||
|
|
||||||
const VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
|
const VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
|
||||||
|
|
||||||
|
// apexcharts touches `window` at module load time, so we must not let SSR
|
||||||
|
// resolve the async component. Render only after mount on the client.
|
||||||
|
const isClient = ref(false)
|
||||||
|
onMounted(() => {
|
||||||
|
isClient.value = true
|
||||||
|
})
|
||||||
|
|
||||||
const { serverId } = injectModrinthServerContext()
|
const { serverId } = injectModrinthServerContext()
|
||||||
const { featureFlags } = injectPageContext()
|
const { featureFlags } = injectPageContext()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user