MCPcopy
hub / github.com/promptfoo/promptfoo / importModule

Function importModule

src/esm.ts:219–324  ·  view source on GitHub ↗
(modulePath: string, functionName?: string)

Source from the content-addressed store, hash-verified

217 * Uses Node.js native ESM import with proper URL resolution
218 */
219export async function importModule(modulePath: string, functionName?: string) {
220 logger.debug(
221 `Attempting to import module: ${JSON.stringify({ resolvedPath: safeResolve(modulePath), moduleId: modulePath })}`,
222 );
223
224 try {
225 await ensureTypescriptLoader(modulePath);
226
227 const resolvedPath = pathToFileURL(safeResolve(modulePath));
228 const resolvedPathStr = resolvedPath.toString();
229 logger.debug(`Attempting ESM import from: ${resolvedPathStr}`);
230
231 // Native dynamic import - no eval() needed in ESM-only environment
232 const importedModule = await import(resolvedPathStr);
233
234 const mod = importedModule?.default?.default || importedModule?.default || importedModule;
235 logger.debug(
236 `Successfully imported module: ${JSON.stringify({ resolvedPath, moduleId: modulePath })}`,
237 );
238
239 if (functionName) {
240 logger.debug(`Returning named export: ${functionName}`);
241 return mod[functionName];
242 }
243 return mod;
244 } catch (err) {
245 const errorMessage = err instanceof Error ? err.message : String(err);
246
247 // Fall back to vm-based CJS execution for .js files that use CJS syntax
248 // Note: createRequire() doesn't work for .js files in "type": "module" packages
249 // because Node.js still treats them as ESM based on package.json.
250 // We use Node's vm module to execute the code with proper CJS globals.
251 if (modulePath.endsWith('.js') && isCjsInEsmError(errorMessage)) {
252 logger.debug(
253 `ESM import failed for ${modulePath}, attempting vm-based CJS fallback: ${errorMessage}`,
254 );
255
256 try {
257 const resolvedPath = safeResolve(modulePath);
258 const mod = loadCjsModule(resolvedPath);
259 logger.debug(
260 `Successfully loaded module via CJS fallback: ${JSON.stringify({ resolvedPath, moduleId: modulePath })}`,
261 );
262
263 if (functionName) {
264 logger.debug(`Returning named export: ${functionName}`);
265 return mod[functionName];
266 }
267 return mod;
268 } catch (cjsErr) {
269 // If CJS fallback also fails, throw a combined error with both details
270 const cjsErrorMessage = cjsErr instanceof Error ? cjsErr.message : String(cjsErr);
271 logger.error(`ESM import failed for ${modulePath}: ${errorMessage}`);
272 logger.error(`CJS fallback also failed: ${cjsErrorMessage}`);
273
274 // Create a combined error that includes both failure reasons
275 const combinedError = new Error(
276 `Failed to load module ${modulePath}:\n` +

Callers 15

esm.test.tsFile · 0.90
renderPromptFunction · 0.90
loadFromJavaScriptFileFunction · 0.90
loadOpenCodeSDKFunction · 0.90
createSessionParserFunction · 0.90
createValidateStatusFunction · 0.90
loadTransformModuleFunction · 0.90
createStreamResponseFunction · 0.90
loadFromPackageFunction · 0.90
loadExternalFunctionMethod · 0.90
loadClaudeCodeSDKFunction · 0.90
registry.tsFile · 0.90

Calls 6

safeResolveFunction · 0.90
ensureTypescriptLoaderFunction · 0.85
isCjsInEsmErrorFunction · 0.85
loadCjsModuleFunction · 0.85
errorMethod · 0.80
toStringMethod · 0.65

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…