/** * GET /api/mobile/app-download — public (no session) download pointer for the Android app, * used by the sign-in page's "Get the LogShip app for Android" card on phones. * * Serves the CURRENT build from the ERP release channel (data/mobile-releases/, see * server/utils/mobileReleases.ts) through a signed, expiring URL — the same mechanism the * authenticated install page uses — so the public card can never hand out a stale build from the * legacy web root. Falls back to the legacy public manifest on www.logyou.de only when no release * has been published to the channel yet. Returns version + URL only, never history or notes. */ import { readManifest, enrichManifest, signDownloadUrl, isDownloadSecretConfigured, legacyFallbackEnabled, TTL_INSTALL_PAGE, CURRENT_APK } from '../../utils/mobileReleases' const LEGACY_BASE = 'https://www.logyou.de/logship' export default defineEventHandler(async (event) => { setHeader(event, 'Cache-Control', 'no-store') const manifest = readManifest() if (manifest && isDownloadSecretConfigured()) { try { const m = enrichManifest(manifest) return { status: 200, source: 'channel', versionName: m.versionName, versionCode: m.versionCode, releaseDate: m.releaseDate ?? null, size: m.size ?? null, url: signDownloadUrl(CURRENT_APK, TTL_INSTALL_PAGE), } } catch (err: any) { console.error('[app-download] cannot sign download url:', err?.message || err) } } if (!legacyFallbackEnabled()) { setResponseStatus(event, 404) return { status: 404, message: 'No release published' } } try { const response = await fetch(`${LEGACY_BASE}/version.json`, { cache: 'no-store' } as any) if (!response.ok) throw new Error(`legacy manifest ${response.status}`) const legacy: any = await response.json() const rel = String(legacy?.apkUrl || CURRENT_APK).replace(/^\/+/, '') return { status: 200, source: 'legacy', versionName: legacy?.versionName ?? null, versionCode: Number(legacy?.versionCode) || null, releaseDate: legacy?.releaseDate ?? null, size: null, url: /^https?:\/\//i.test(rel) ? rel : `${LEGACY_BASE}/${rel}`, } } catch (err: any) { setResponseStatus(event, 404) return { status: 404, message: err?.message || 'No release available' } } })