analytics/services/collector/scripts/esm-loader.mjs

79 lines
2.3 KiB
JavaScript
Raw Normal View History

/**
* Custom ESM Loader that adds .js extensions to imports without extensions
*/
import { resolve as pathResolve, dirname, extname, isAbsolute } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { existsSync } from 'node:fs';
/**
* Resolve hook - adds .js extension to imports without extensions
*/
export async function resolve(specifier, context, nextResolve) {
// Log everything unconditionally
console.log(`[loader] resolve called: ${specifier}`);
// Skip node built-ins and package imports
if (specifier.startsWith('node:') || specifier.startsWith('@') || !specifier.includes('/')) {
return nextResolve(specifier, context);
}
// Check if specifier needs .js extension added
if (!extname(specifier)) {
// Calculate the absolute path
let absolutePath;
if (isAbsolute(specifier)) {
absolutePath = specifier;
} else if (specifier.startsWith('./') || specifier.startsWith('../')) {
// For relative imports, resolve from parent directory
const { parentURL } = context;
let parentDir;
if (parentURL) {
try {
parentDir = dirname(fileURLToPath(parentURL));
} catch {
parentDir = process.cwd();
}
} else {
parentDir = process.cwd();
}
absolutePath = pathResolve(parentDir, specifier);
} else {
// Not a path we handle
return nextResolve(specifier, context);
}
console.log(`[loader] absolute path: ${absolutePath}`);
// Try adding .js extension
const pathWithJs = absolutePath + '.js';
console.log(`[loader] trying: ${pathWithJs}, exists: ${existsSync(pathWithJs)}`);
if (existsSync(pathWithJs)) {
const url = pathToFileURL(pathWithJs).href;
console.log(`[loader] resolved to: ${url}`);
return {
shortCircuit: true,
url,
};
}
// Try as directory with index.js
const pathAsIndex = pathResolve(absolutePath, 'index.js');
console.log(`[loader] trying index: ${pathAsIndex}, exists: ${existsSync(pathAsIndex)}`);
if (existsSync(pathAsIndex)) {
const url = pathToFileURL(pathAsIndex).href;
console.log(`[loader] resolved to: ${url}`);
return {
shortCircuit: true,
url,
};
}
}
// Default resolution
return nextResolve(specifier, context);
}