/**
* useSiteVersion Composable
*
* Gets the current site version for footer badges and version displays.
* Fetches the latest release version from the DCS Portal API.
*
* @example
* ```vue
*
*
*
*
*
* ```
*/
import { platformFetch } from '@duffcloudservices/cms-core'
import { ref, computed, onMounted } from 'vue'
import type { SiteVersionReturn } from '../types/release-notes'
/**
* Get environment variable value.
*/
function getEnvVar(key: string, defaultValue = ''): string {
try {
if (typeof import.meta !== 'undefined' && import.meta.env) {
const value = (import.meta.env as Record)[key]
if (value !== undefined) return value
}
} catch {
// import.meta not available
}
return defaultValue
}
// Cache for site version
let versionCache: { version: string; expiresAt: number } | null = null
const CACHE_TTL = 10 * 60 * 1000 // 10 minutes
/**
* useSiteVersion composable for displaying the current site version.
*
* @param options - Optional configuration
* @returns Site version data and computed URL
*/
export function useSiteVersion(options: { fetchOnMount?: boolean } = {}): SiteVersionReturn {
const { fetchOnMount = true } = options
const apiBaseUrl = getEnvVar('VITE_API_BASE_URL', 'https://portal.duffcloudservices.com')
// @deprecated VITE_SITE_SLUG: the site is now resolved server-side from the
// request Host or the dedicated Container App's DCS_SITE_SLUG. It is no longer
// used for routing; retained only for source compatibility.
void getEnvVar('VITE_SITE_SLUG', '')
const version = ref(null)
const isLoading = ref(false)
const releaseNotesUrl = computed(() => {
if (!version.value) return '/releaseNotes/latest'
return `/releaseNotes/${version.value}`
})
async function fetchVersion(): Promise {
// Check cache
if (versionCache && versionCache.expiresAt > Date.now()) {
version.value = versionCache.version
return
}
isLoading.value = true
try {
// Fetch the latest release notes to get the version
const url = `${apiBaseUrl}/api/v1/release-notes/latest`
// C-298 layer 2 — see useReleaseNotes: an HTML body is a misroute, not "no release
// notes yet", and this composable's catch would otherwise swallow it silently.
const response = await platformFetch(url, {
headers: {
Accept: 'application/json',
},
})
if (!response.ok) {
// No release notes yet - that's fine
return
}
const data = await response.json()
const latestVersion = data.version
// Cache the result
versionCache = {
version: latestVersion,
expiresAt: Date.now() + CACHE_TTL,
}
version.value = latestVersion
} catch (e) {
console.error('[@duffcloudservices/cms] Failed to fetch site version:', e)
} finally {
isLoading.value = false
}
}
// Fetch on mount if enabled
if (fetchOnMount && typeof window !== 'undefined') {
onMounted(() => {
fetchVersion()
})
}
return {
version,
isLoading,
releaseNotesUrl,
}
}