type Awaitable = T | Promise; export function virtualFiles( map: Record Awaitable)>, ) { return { name: "clover vfs", setup(b) { b.onResolve( { filter: new RegExp( `^(?:${ Object.keys(map).map((file) => string.escapeRegExp(file)).join( "|", ) })\$`, ), }, ({ path }) => ({ path, namespace: "vfs" }), ); b.onLoad( { filter: /./, namespace: "vfs" }, async ({ path }) => { let entry = map[path]; if (typeof entry === 'function') entry = await entry(); return ({ resolveDir: ".", loader: "ts", ...typeof entry === "string" ? { contents: entry } : entry, }); }, ); }, } satisfies esbuild.Plugin; } export function banFiles( files: string[], ) { return { name: "clover vfs", setup(b) { b.onResolve( { filter: new RegExp( `^(?:${ files.map((file) => string.escapeRegExp(file)).join("|") })\$`, ), }, ({ path, importer }) => { throw new Error( `Loading ${path} (from ${importer}) is banned!`, ); }, ); }, } satisfies esbuild.Plugin; } export function projectRelativeResolution(root = process.cwd() + "/src") { return { name: "project relative resolution ('@/' prefix)", setup(b) { b.onResolve({ filter: /^@\// }, ({ path: id }) => { return { path: path.resolve(root, id.slice(2)), }; }); b.onResolve({ filter: /^#/ }, ({ path: id, importer }) => { return { path: hot.resolveFrom(importer, id), }; }); }, } satisfies esbuild.Plugin; } export function markoViaBuildCache(): esbuild.Plugin { return { name: "marko via build cache", setup(b) { b.onLoad( { filter: /\.marko$/ }, async ({ path: file }) => { const cacheEntry = markoCache.get(file); if (!cacheEntry) { if (!fs.existsSync(file)) { console.warn(`File does not exist: ${file}`); } console.log(markoCache.keys()); throw new Error("Marko file not in cache: " + file); } return ({ loader: "ts", contents: cacheEntry.src, resolveDir: path.dirname(file), }); }, ); }, }; } export function isIgnoredSource(source: string) { return source.includes("