import { createRequire } from 'node:module' import { readdirSync, readFileSync } from 'node:fs' import { defineConfig } from 'vite' import type { Plugin } from 'vite' import react from '@vitejs/plugin-react' import path from 'path' // Backend port for dev server proxy (default: 8000) const backendPort = process.env.BACKEND_PORT || '8000' const backendUrl = `http://localhost:${backendPort}` // pdf.js keeps these out of its bundle and fetches them at runtime (#2976): // CJK text needs the CMaps, non-embedded fonts the standard font files, and // JPEG2000/JBIG2 images and ICC colour the wasm decoders. Published under the // bundle's own assets directory so the existing /assets mount serves them — // PdfPreviewModal builds the matching URLs from its PDFJS_ASSET_BASE. const PDFJS_RUNTIME_DIRS = ['cmaps', 'iccs', 'standard_fonts', 'wasm'] const PDFJS_RUNTIME_PREFIX = 'assets/pdfjs' /** Publish pdf.js's runtime data directories next to the bundle. */ function pdfjsRuntimeAssets(): Plugin { const require = createRequire(__filename) const packageDir = path.dirname(require.resolve('pdfjs-dist/package.json')) // Published path -> file on disk. Built once, and used as an allowlist by // the dev-server handler so no request can escape the package directory. const files = new Map() for (const dir of PDFJS_RUNTIME_DIRS) { for (const entry of readdirSync(path.join(packageDir, dir), { withFileTypes: true })) { if (!entry.isFile()) continue files.set(`${PDFJS_RUNTIME_PREFIX}/${dir}/${entry.name}`, path.join(packageDir, dir, entry.name)) } } return { name: 'bambuddy:pdfjs-runtime-assets', generateBundle() { for (const [fileName, source] of files) { this.emitFile({ type: 'asset', fileName, source: readFileSync(source) }) } }, configureServer(server) { server.middlewares.use((req, res, next) => { const source = files.get((req.url ?? '').split('?')[0].replace(/^\//, '')) if (!source) return next() res.setHeader('Content-Type', source.endsWith('.wasm') ? 'application/wasm' : 'application/octet-stream') res.end(readFileSync(source)) }) }, } } export default defineConfig({ // Default base ('/') emits absolute asset URLs (/assets/...). Required so // deep SPA routes (camera popup at /camera/, /projects/, kiosk // /spoolbuddy/ams, refresh on any nested route) resolve their