import { readFile } from "node:fs/promises"; import { defineConfig } from "vite"; import { SERVICE_WORKER_CACHE_SCHEMA_VERSION, SERVICE_WORKER_PROTOCOL_VERSION, SERVICE_WORKER_SCRIPT_PATH, } from "./src/contracts/service-worker.ts"; import { INSTALLED_RUNTIME_CAPABILITIES } from "./src/features/installed-runtime-capabilities.ts"; import { resolveServiceWorkerBuildInput } from "./scripts/lib/service-worker-build-input.ts"; /** * §17.2.2 step 5. The Service Worker build. * * Runs only when the static selection is `ACTIVE`, after the app build has * completed and the hashed asset list has been generated. `emptyOutDir` is * false so it adds `service-worker.js` beside the already-built app rather than * replacing it. */ const selection = INSTALLED_RUNTIME_CAPABILITIES.serviceWorker; async function readGenerated(path: string, exportName: string): Promise { try { const module = (await import(path)) as Record; if (!(exportName in module)) { throw new TypeError(`Generated module does not export ${exportName}.`); } return module[exportName] as T; } catch (error) { throw new TypeError(`Required generated module is unavailable: ${path}`, { cause: error, }); } } const assets = await readGenerated( "./.generated/frontend-runtime/service-worker-assets.ts", "SERVICE_WORKER_ASSETS", ); const contractSet = await readGenerated<{ setDigest?: string }>( "./.generated/frontend-runtime/contract-set.ts", "BUILD_CONTRACT_SET", ); const runtimeConfig = JSON.parse( await readFile("public/config.json", "utf8"), ) as Record; const buildId = process.env.VITE_BUILD_ID ?? "local-build"; const releaseId = process.env.RELEASE_ID ?? "local-release"; const buildInput = resolveServiceWorkerBuildInput({ selection, assets, contractSet, runtimeConfig, buildId, releaseId, }); export default defineConfig({ build: { // §17.2.2: exactly one input, exactly one output, no additional chunk. emptyOutDir: false, sourcemap: false, rollupOptions: { input: "src/adapters/service-worker/service-worker-entry.ts", output: { format: "es", inlineDynamicImports: true, entryFileNames: SERVICE_WORKER_SCRIPT_PATH, }, }, }, define: { __CA_SERVICE_WORKER_BUILD_INFO__: JSON.stringify({ serviceWorkerProtocolVersion: SERVICE_WORKER_PROTOCOL_VERSION, cacheSchemaVersion: SERVICE_WORKER_CACHE_SCHEMA_VERSION, buildId, releaseId, contractSetDigest: buildInput.contractSetDigest, staticAssetSetDigest: buildInput.assets.setDigest, }), __CA_SERVICE_WORKER_ASSETS__: JSON.stringify(buildInput.assets), __CA_SERVICE_WORKER_HANDLERS__: JSON.stringify(buildInput.handlers), __CA_RUNTIME_CONFIG_URL__: JSON.stringify( process.env.VITE_RUNTIME_CONFIG_URL ?? "/config.json", ), __CA_RELEASE_MANIFEST_URL__: JSON.stringify( buildInput.releaseManifestUrl, ), }, });