import { copyFileSync } from 'node:fs'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { defineConfig, type Plugin } from 'vite'; import { publishPlugins } from './tools/lib/plugins.mjs'; const __dirname = dirname(fileURLToPath(import.meta.url)); /** * The workspace folder itself is what nginx serves under https://nockal.com/game-maker/. * The Vite source pages live in `web/`: `index.html` is the editor, `play.html` a released game * (#266). The build writes hashed assets into `dist/` and this plugin copies the built pages to the * folder root, so that the site URLs load the production bundles while `api/` and `data/` sit next * to them. */ const PAGES = ['index.html', 'play.html']; function publishPages(): Plugin { return { name: 'game-maker:publish-pages', apply: 'build', closeBundle() { for (const page of PAGES) copyFileSync(resolve(__dirname, 'dist', page), resolve(__dirname, page)); }, }; } /** * Editor plugins are loaded from `data/plugins/`, which is not in the repository; the ones that * ship with it live in `plugins/` and are put there on every build. A file of the same name is * replaced, anything else in the folder is left alone. Whether one runs is the open project's * business, not the build's (#119). */ function shipPlugins(): Plugin { return { name: 'game-maker:publish-plugins', apply: 'build', closeBundle() { publishPlugins(__dirname); }, }; } export default defineConfig({ root: 'web', base: '/game-maker/dist/', publicDir: false, plugins: [publishPages(), shipPlugins()], build: { outDir: '../dist', emptyOutDir: true, target: 'es2022', sourcemap: true, rollupOptions: { input: Object.fromEntries( PAGES.map((page) => [page.replace('.html', ''), resolve(__dirname, 'web', page)]), ), }, }, server: { port: 5175, // During development the PHP API is served by the production nginx; proxy it. proxy: { '/game-maker/api': { target: 'https://nockal.com', changeOrigin: true, }, }, }, test: { root: '.', include: ['tests/**/*.test.ts'], environment: 'node', // Unset locally, so vitest keeps its own guess (one worker per core). CI sets it while the // gate runs next to the editor suite: the two jobs share four cores, and the suite measures // text widths and frame counts, which a machine under full load reports differently. maxWorkers: Number(process.env.GM_TEST_WORKERS) || undefined, }, });