vite-plugin-foundryvtt
Version:
Plugin for building for foundryvtt. Enables hmr and manifest substitution.
114 lines (108 loc) • 3.65 kB
JavaScript
;
const fs = require('node:fs');
const path = require('node:path');
const foundryvttCli = require('@foundryvtt/foundryvtt-cli');
const classicLevel = require('classic-level');
const vite = require('vite');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
async function isLocked(dest) {
try {
const db = new classicLevel.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 = vite.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__default.resolve(
outdir,
pack.path ?? path__default.resolve("packs", pack.name)
);
if (await isLocked(dest)) buildPacks = false;
}
},
generateBundle() {
const data = vite.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__default.resolve(packDir, p.name),
dest: path__default.resolve(outdir, p.path ?? path__default.resolve("packs", p.name))
}));
if (!buildPacks || !packs) return;
for (const p of packs) {
try {
await foundryvttCli.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__default.relative(pubdir, file);
const ext = path__default.extname(file_path).slice(1);
if (!extensions.includes(ext) || !paths.some((p) => file_path.startsWith(p)))
return;
const dest = path__default.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__default.copyFileSync(file, dest);
}
};
}
module.exports = foundryvtt;