ai-chatbot/tests/helpers/canvas-download-server-loader.ts

72 lines
2.3 KiB
TypeScript

import { readFileSync } from "node:fs";
import { createRequire } from "node:module";
import path from "node:path";
import vm from "node:vm";
import * as crypto from "node:crypto";
import ts from "typescript";
const root = path.resolve(__dirname, "../..");
export function serverLoader(mocks: Record<string, unknown>, env: Record<string, string> = {}) {
const modules = new Map<string, { exports: any }>();
const runtimeGlobal = {};
const load = (relative: string): any => {
const filename = path.resolve(root, relative);
if (modules.has(filename)) return modules.get(filename)!.exports;
const module = { exports: {} };
modules.set(filename, module);
const source = ts.transpileModule(readFileSync(filename, "utf8"), {
fileName: filename,
compilerOptions: {
jsx: ts.JsxEmit.ReactJSX,
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2022,
esModuleInterop: true,
},
}).outputText;
const nativeRequire = createRequire(filename);
const requireMock = (name: string) => {
if (name === "server-only") return {};
if (Object.prototype.hasOwnProperty.call(mocks, name)) return mocks[name];
if (name.startsWith("@/")) return load(`${name.slice(2)}.ts`);
if (name.startsWith("."))
return load(path.relative(root, path.resolve(path.dirname(filename), `${name}.ts`)));
return nativeRequire(name);
};
const context = vm.createContext({
module,
exports: module.exports,
require: requireMock,
globalThis: runtimeGlobal,
process: { env, pid: process.pid, kill: process.kill },
Buffer,
URL,
URLSearchParams,
DOMException,
Response,
crypto,
setTimeout: mocks.setTimeout || setTimeout,
clearTimeout,
TextEncoder,
sessionStorage: mocks.sessionStorage,
setImmediate,
AbortSignal,
AbortController,
ReadableStream,
Headers,
Blob,
Request,
Date: mocks.Date || Date,
document: mocks.document,
window: mocks.window,
console: { log() {}, warn() {}, error() {}, info() {} },
fetch:
mocks.fetch ||
(() => {
throw new Error("Unexpected network call");
}),
});
new vm.Script(source, { filename }).runInContext(context);
return module.exports;
};
return load;
}