diff --git a/src/app/app.vue b/src/app/app.vue index a8f0a0f7..636ca56d 100644 --- a/src/app/app.vue +++ b/src/app/app.vue @@ -10,6 +10,7 @@ const globalStore = useGlobalStore(); globalStore.fetchFeatures(); globalStore.fetchRelease(); +globalStore.setLanguage(); useHead({ bodyAttrs: { class: 'bg-gray-50 dark:bg-neutral-800', diff --git a/src/app/layouts/Footer.vue b/src/app/layouts/Footer.vue index 3a3108b9..7d9fbbd2 100644 --- a/src/app/layouts/Footer.vue +++ b/src/app/layouts/Footer.vue @@ -7,7 +7,7 @@ href="https://github.com/wg-easy/wg-easy" >WireGuard Easy - © 2021-2024 by + ({{ globalStore.currentRelease }}) © 2021-2024 by - + diff --git a/src/app/layouts/Header.vue b/src/app/layouts/Header.vue index 5023a8ca..3ea58a0d 100644 --- a/src/app/layouts/Header.vue +++ b/src/app/layouts/Header.vue @@ -63,7 +63,7 @@
diff --git a/src/app/stores/global.ts b/src/app/stores/global.ts index 598b406f..7dc21848 100644 --- a/src/app/stores/global.ts +++ b/src/app/stores/global.ts @@ -6,6 +6,7 @@ export const useGlobalStore = defineStore('Global', () => { const latestRelease = ref( null ); + const updateAvailable = ref(false); const features = ref({ trafficStats: { enabled: false, @@ -25,7 +26,7 @@ export const useGlobalStore = defineStore('Global', () => { const { availableLocales, locale } = useI18n(); - async function fetchRelease() { + async function setLanguage() { const { data: lang } = await api.getLang(); if ( lang.value !== getItem('lang') && @@ -34,19 +35,18 @@ export const useGlobalStore = defineStore('Global', () => { setItem('lang', lang.value!); locale.value = lang.value!; } + } + async function fetchRelease() { const { data: release } = await api.getRelease(); if (!release.value) { return; } - if (!release.value.updateAvailable) { - return; - } - currentRelease.value = release.value.currentRelease; latestRelease.value = release.value.latestRelease; + updateAvailable.value = release.value.updateAvailable; } async function fetchFeatures() { @@ -67,7 +67,9 @@ export const useGlobalStore = defineStore('Global', () => { features, currentRelease, latestRelease, + updateAvailable, fetchRelease, fetchFeatures, + setLanguage, }; }); diff --git a/src/server/api/release.get.ts b/src/server/api/release.get.ts index daf40ba7..8a6fa12f 100644 --- a/src/server/api/release.get.ts +++ b/src/server/api/release.get.ts @@ -1,8 +1,7 @@ import { gt } from 'semver'; export default defineEventHandler(async () => { - // TODO: cache this - const latestRelease = await fetchLatestRelease(); + const latestRelease = await cachedFetchLatestRelease(); const updateAvailable = gt(latestRelease.version, RELEASE); return { currentRelease: RELEASE, diff --git a/src/server/utils/config.ts b/src/server/utils/config.ts index a3630bcb..65f4da3b 100644 --- a/src/server/utils/config.ts +++ b/src/server/utils/config.ts @@ -5,7 +5,7 @@ import type { Database } from '~~/services/database/repositories/database'; import { parseCidr } from 'cidr-tools'; import { stringifyIp } from 'ip-bigint'; -export const RELEASE = packageJson.version; +export const RELEASE = 'v' + packageJson.version; export const SERVER_DEBUG = debug('Server'); diff --git a/src/server/utils/release.ts b/src/server/utils/release.ts index b76b66ba..c23cae64 100644 --- a/src/server/utils/release.ts +++ b/src/server/utils/release.ts @@ -3,7 +3,30 @@ type GithubRelease = { body: string; }; -export async function fetchLatestRelease() { +/** + * Cache function for 1 hour + */ +function cacheFunction(fn: () => T): () => T { + let cache: { value: T; expiry: number } | null = null; + + return (): T => { + const now = Date.now(); + + if (cache && cache.expiry > now) { + return cache.value; + } + + const result = fn(); + cache = { + value: result, + expiry: now + 3600000, + }; + + return result; + }; +} + +async function fetchLatestRelease() { try { const response = await $fetch( 'https://api.github.com/repos/wg-easy/wg-easy/releases/latest', @@ -25,3 +48,5 @@ export async function fetchLatestRelease() { }); } } + +export const cachedFetchLatestRelease = cacheFunction(fetchLatestRelease);