`apps/web/vite.config.ts` now injects three build-time constants via
`define`: `__APP_VERSION__` (root package.json), `__APP_COMMIT__`
(GIT_SHA env > local `git rev-parse` > 'dev'), `__BUILD_TIME__` (ISO
timestamp at build). They're declared in `apps/web/src/global.d.ts`
and re-exported through `$lib/version` — components consume the named
exports rather than the magic globals so an accidental tree-shake
would break the test, not the page silently.
`/settings` gains an "About" section at the bottom: a small chip
`v{version} · {commit} · {date}` in muted text. Not interactive,
purely diagnostic — useful when a user reports a bug from a stale
PWA install.
Deploy pipeline:
- `apps/web/Dockerfile` accepts a `GIT_SHA` build arg and exports
it as an env var for the SvelteKit build step.
- `infra/docker-compose.erosi.yml` forwards `${GIT_SHA:-dev}` into
the build args.
- `infra/scripts/deploy-erosi.sh` captures `git rev-parse --short
HEAD` locally (the deploy host has .git; the remote doesn't —
rsync excludes it) and forwards it via `ssh ... env GIT_SHA=…`
so the remote `docker compose build` sees it.
V-01/V-02 vitest: stub the three globals via `vi.stubGlobal` (vitest
doesn't run through the main vite.config so `define` isn't applied),
assert the named exports thread through and never collapse to
undefined or the 'dev' sentinel under a real build.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
92 lines
3.2 KiB
TypeScript
92 lines
3.2 KiB
TypeScript
import { defineConfig } from 'vite';
|
|
import { sveltekit } from '@sveltejs/kit/vite';
|
|
import { SvelteKitPWA } from '@vite-pwa/sveltekit';
|
|
import { paraglide } from '@inlang/paraglide-sveltekit/vite';
|
|
import { execSync } from 'node:child_process';
|
|
import { readFileSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
// Fase 14.3.1 — build-time version constants.
|
|
// Source order: explicit GIT_SHA env (used by `apps/web/Dockerfile`
|
|
// during `infra/scripts/deploy-erosi.sh`) > local `git rev-parse` >
|
|
// 'dev' fallback when neither path works (e.g. tarball builds).
|
|
const rootPkgUrl = new URL('../../package.json', import.meta.url);
|
|
const rootPkg = JSON.parse(readFileSync(fileURLToPath(rootPkgUrl), 'utf8')) as {
|
|
version?: string;
|
|
};
|
|
const APP_VERSION = rootPkg.version ?? '0.0.0';
|
|
let APP_COMMIT: string = process.env.GIT_SHA ?? '';
|
|
if (!APP_COMMIT) {
|
|
try {
|
|
APP_COMMIT = execSync('git rev-parse --short HEAD', { stdio: ['ignore', 'pipe', 'ignore'] })
|
|
.toString()
|
|
.trim();
|
|
} catch {
|
|
APP_COMMIT = 'dev';
|
|
}
|
|
}
|
|
const BUILD_TIME = new Date().toISOString();
|
|
|
|
export default defineConfig({
|
|
define: {
|
|
__APP_VERSION__: JSON.stringify(APP_VERSION),
|
|
__APP_COMMIT__: JSON.stringify(APP_COMMIT),
|
|
__BUILD_TIME__: JSON.stringify(BUILD_TIME)
|
|
},
|
|
plugins: [
|
|
paraglide({
|
|
project: './project.inlang',
|
|
outdir: './src/lib/paraglide'
|
|
}),
|
|
sveltekit(),
|
|
SvelteKitPWA({
|
|
// `generateSW` strategy: the plugin auto-generates a Workbox SW that
|
|
// precaches the built shell. Equivalent behavior to our previous
|
|
// `src/sw.ts` (a 5-line precacheAndRoute wrapper) without the
|
|
// injectManifest path, which in @vite-pwa/sveltekit 0.6.8 hardcodes
|
|
// the SW source filename to `service-worker.js` and breaks on any
|
|
// custom filename. The $lib/sync pending_ops queue handles offline
|
|
// writes; SyncBanner surfaces offline state to the user.
|
|
strategies: 'generateSW',
|
|
scope: '/',
|
|
base: '/',
|
|
manifest: {
|
|
name: 'Colectivo',
|
|
short_name: 'Colectivo',
|
|
description: 'Gestión colaborativa del hogar',
|
|
theme_color: '#0f172a',
|
|
background_color: '#f7f9fb',
|
|
display: 'standalone',
|
|
orientation: 'portrait',
|
|
scope: '/',
|
|
start_url: '/',
|
|
icons: [
|
|
{ src: '/icons/icon-192.png', sizes: '192x192', type: 'image/png' },
|
|
{ src: '/icons/icon-512.png', sizes: '512x512', type: 'image/png' },
|
|
{ src: '/icons/icon-512-maskable.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }
|
|
]
|
|
},
|
|
workbox: {
|
|
globPatterns: ['client/**/*.{js,css,ico,png,svg,webp,woff,woff2}'],
|
|
// Supabase paths: never cache — always hit the network.
|
|
navigateFallbackDenylist: [/^\/auth\//, /^\/rest\//, /^\/realtime\//, /^\/storage\//]
|
|
},
|
|
devOptions: {
|
|
enabled: true,
|
|
suppressWarnings: true,
|
|
type: 'module',
|
|
navigateFallback: '/'
|
|
}
|
|
})
|
|
],
|
|
server: {
|
|
port: 5173,
|
|
// Bind to all interfaces so the LAN (phone, tablet, other laptops on
|
|
// the same Wi-Fi) can reach the dev server at http://<LAN-IP>:5173.
|
|
// Auth flows will fail from non-laptop clients because Keycloak's
|
|
// issuer URL resolves to `keycloak:8080` only on the laptop's /etc/hosts
|
|
// — use this for layout/CSS visual checks, not for full login tests.
|
|
host: true
|
|
}
|
|
});
|