UNPKG

vite-plugin-foundryvtt

Version:

Plugin for building for foundryvtt. Enables hmr and manifest substitution.

107 lines (104 loc) 3.28 kB
import fs from 'node:fs'; import path from 'node:path'; import { compilePack } from '@foundryvtt/foundryvtt-cli'; import { ClassicLevel } from 'classic-level'; import { mergeConfig } from 'vite'; async function isLocked(dest) { try { const db = new ClassicLevel(dest); await db.open(); await db.close(); } catch { return true; } return false; } function foundryvtt(manifest, { substitutions = {}, type = "system", packDir = "src/packs", buildPacks = true, packOptions = { yaml: true } } = {}) { for (const [k, v] of Object.entries(substitutions)) if (v === void 0) delete substitutions[k]; let outdir; let pubdir; const hotReload = manifest.flags?.hotReload || null; const extensions = hotReload?.extensions.map((e) => e); const paths = hotReload?.paths?.map((e) => e) ?? [""]; return { name: "foundryvtt-config", config(cfg, { command }) { if (command === "build") cfg.base = "./"; cfg.build ??= {}; cfg.build.rollupOptions ??= {}; cfg.build.rollupOptions.output ??= {}; const afn = { assetFileNames: ({ names: [name] }) => name?.endsWith(".css") ? `styles/${name}` : name ?? "assets/[name]-[hash][extname]" }; if (Array.isArray(cfg.build.rollupOptions.output)) { cfg.build.rollupOptions.output.push(afn); } else { cfg.build.rollupOptions.output = mergeConfig( cfg.build.rollupOptions.output, afn ); } return cfg; }, async configResolved(cfg) { outdir = cfg.build.outDir; pubdir = cfg.publicDir; for (const pack of manifest.packs ?? []) { if (!buildPacks) break; const dest = path.resolve( outdir, pack.path ?? path.resolve("packs", pack.name) ); if (await isLocked(dest)) buildPacks = false; } }, generateBundle() { const data = mergeConfig(manifest, substitutions); const source = JSON.stringify(data, null, 2); this.emitFile({ type: "asset", fileName: `${type}.json`, source }); }, async writeBundle() { const packs = manifest.packs?.map((p) => ({ ...p, src: path.resolve(packDir, p.name), dest: path.resolve(outdir, p.path ?? path.resolve("packs", p.name)) })); if (!buildPacks || !packs) return; for (const p of packs) { try { await compilePack(p.src, p.dest, packOptions); this.info(`Built pack ${p.name}`); } catch (e) { if (e instanceof Error) this.warn(e); } } buildPacks = false; }, handleHotUpdate({ file }) { if (!hotReload || !extensions) return; if (!file.startsWith(pubdir)) return; const file_path = path.relative(pubdir, file); const ext = path.extname(file_path).slice(1); if (!extensions.includes(ext) || !paths.some((p) => file_path.startsWith(p))) return; const dest = path.resolve(outdir, file_path); const k = { css: "css", json: "language", html: "template", hbs: "template", "": "" }; console.log(`Hot updating ${k[ext.toLowerCase()]} file '${file_path}'`); fs.copyFileSync(file, dest); } }; } export { foundryvtt as default };