fuzzyworld

fuzzyworld-tools / files / vite / index.js

index.js

2.2 KB · history · blame

1// Vite plugin for apps on apps.fuzzyworld.net.
2//
3// import fuzzyworld from 'fuzzyworld-tools/vite';
4// export default defineConfig({ plugins: [fuzzyworld()] });
5//
6// Sets `base` to `/<app>/`, where <app> is `fuzzyworld.app` in package.json, so every
7// asset URL stays inside the app's own path on the shared origin. `fw deploy` checks
8// the built output (manifest, service worker scope) before anything is uploaded.
9import fs from 'node:fs';
10import path from 'node:path';
11
12// Nearest package.json with a "fuzzyworld" section, from `start` upwards. Vite's `root`
13// is often a subfolder (e.g. root: 'src'), while package.json sits at the repo root.
14function findPackageJson(start) {
15 for (let dir = path.resolve(start); ; dir = path.dirname(dir)) {
16 const p = path.join(dir, 'package.json');
17 if (fs.existsSync(p) && JSON.parse(fs.readFileSync(p, 'utf8')).fuzzyworld) return p;
18 if (path.dirname(dir) === dir) return null;
19 }
20}
21
22export function readAppConfig(root = process.cwd()) {
23 const pkgPath = findPackageJson(root);
24 if (!pkgPath) {
25 throw new Error(`fuzzyworld: add "fuzzyworld": { "app": "<name>" } to package.json (searched upwards from ${root})`);
26 }
27 const cfg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')).fuzzyworld;
28 if (!cfg.app) {
29 throw new Error(`fuzzyworld: add "app" to the "fuzzyworld" section of ${pkgPath}`);
30 }
31 if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(cfg.app)) {
32 throw new Error(`fuzzyworld: invalid app name "${cfg.app}"`);
33 }
34 return cfg;
35}
36
37export default function fuzzyworld() {
38 return {
39 name: 'fuzzyworld',
40 config(config, { command }) {
41 const root = config.root ? path.resolve(config.root) : process.cwd();
42 // `fw deploy --as <name>` (lib/deploy.mjs) builds the same app under another path.
43 const app = process.env.FW_APP || readAppConfig(root).app;
44 const base = `/${app}/`;
45 // `vite dev` keeps the developer's own base; builds always use the app path.
46 if (command === 'build' && config.base && config.base !== base && config.base !== './') {
47 console.warn(`fuzzyworld: overriding base "${config.base}" with "${base}"`);
48 }
49 return command === 'build' ? { base } : {};
50 },
51 };
52}