@vaadin/hilla-file-router
Version:
Hilla file-based router
83 lines • 3.27 kB
JavaScript
import { basename } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import { generateRuntimeFiles } from "./vite-plugin/generateRuntimeFiles.js";
const INJECTION = "if (Object.keys(nextExports).length === 2 && 'default' in nextExports && 'config' in nextExports) {nextExports = { ...nextExports, config: currentExports.config };}";
/**
* A Vite plugin that generates a router from the files in the specific directory.
*
* @param options - The plugin options.
* @returns A Vite plugin.
*/
export default function vitePluginFileSystemRouter({ viewsDir = "frontend/views/", generatedDir = "frontend/generated/", extensions = [".tsx", ".jsx"], isDevMode = false, debug = false } = {}) {
let _viewsDir;
let _outDir;
let _logger;
let runtimeUrls;
return {
name: "vite-plugin-file-router",
configResolved({ logger, root, build: { outDir } }) {
const _root = pathToFileURL(root);
const _generatedDir = new URL(generatedDir, _root);
_viewsDir = new URL(viewsDir, _root);
_outDir = pathToFileURL(outDir);
_logger = logger;
if (debug) {
_logger.info(`The directory of route files: ${String(_viewsDir)}`);
_logger.info(`The directory of generated files: ${String(_generatedDir)}`);
_logger.info(`The output directory: ${String(_outDir)}`);
}
runtimeUrls = {
json: new URL("file-routes.json", isDevMode ? _generatedDir : _outDir),
code: new URL("file-routes.ts", _generatedDir),
layouts: new URL("layouts.json", _generatedDir)
};
},
async buildStart() {
try {
await generateRuntimeFiles(_viewsDir, runtimeUrls, extensions, _logger, debug);
} catch (e) {
_logger.error(String(e));
}
},
configureServer(server) {
const dir = fileURLToPath(_viewsDir);
const changeListener = (file) => {
if (!file.startsWith(dir)) {
if (file === fileURLToPath(runtimeUrls.json)) {
server.hot.send({
type: "custom",
event: "fs-route-update"
});
} else if (file !== fileURLToPath(runtimeUrls.layouts)) {
return;
}
}
generateRuntimeFiles(_viewsDir, runtimeUrls, extensions, _logger, debug).catch((e) => _logger.error(String(e)));
};
server.watcher.on("add", changeListener);
server.watcher.on("change", changeListener);
server.watcher.on("unlink", changeListener);
},
transform(code, id) {
let modifiedCode = code;
const viewsDirUsingSlashes = fileURLToPath(_viewsDir).replaceAll("\\", "/");
if (id.startsWith(viewsDirUsingSlashes) && !basename(id).startsWith("_")) {
if (isDevMode) {
const injectionPattern = /import\.meta\.hot\.accept[\s\S]+if\s\(!nextExports\)\s+return;/gu;
if (injectionPattern.test(modifiedCode)) {
modifiedCode = `${modifiedCode.substring(0, injectionPattern.lastIndex)}${INJECTION}${modifiedCode.substring(injectionPattern.lastIndex)}`;
}
} else {
const functionNames = /export\s+default\s+(?:function\s+)?(\w+)/u.exec(modifiedCode);
if (functionNames?.length) {
const [, functionName] = functionNames;
modifiedCode += `Object.defineProperty(${functionName}, 'name', { value: '${functionName}' });\n`;
}
}
return { code: modifiedCode };
}
return undefined;
}
};
}
//# sourceMappingURL=./vite-plugin.js.map