/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ const explicitExtensionRe = /\.[mc]?js$/; const explicitJsExtensionRe = /\.js$/; const builtinNamespaceImportRe = /^node:/; /* * NodeJS resolver that enables the interop with the current Bazel setup. * * The loader will attempt resolution by replacing explicit extension with * their ESM variants. It also tries completing import specifiers in case no * extension of explicit file is specified. * * There are a few cases: * * * Relative imports without an extension. This happens because our * source files cannot use explicit `.mjs` extensions yet. * * Relative imports with an explicit extension to `.js`. This may * be generated by TypeScript as we have `.ts` source files. * * Local module imports. In NPM, extensions are not needed as the * `package.json` `exports` help resolving. In Bazel when dealing with * 1st-party packages- `package.json` is not consulted in resolution. * 1. The NPM artifacts differ from the source compilation output. * 2. It results in additional churn, having to put `package.json` into `bin`. */ export async function resolve(specifier, context, nextResolve) { const interopAttempts = []; if (explicitJsExtensionRe.test(specifier)) { interopAttempts.push(specifier.replace(explicitJsExtensionRe, '.mjs')); } // If there is no explicit extension and we are not dealing with a // builtin namespace module, attempt various subpaths to prioritize ESM. if (!explicitExtensionRe.test(specifier) && !builtinNamespaceImportRe.test(specifier)) { interopAttempts.push(`${specifier}.mjs`); interopAttempts.push(`${specifier}/index.mjs`); // Last attempts are normal `.js` extensions. These could still // be valid ESM when there is an type:module `package.json` file interopAttempts.push(`${specifier}.js`); interopAttempts.push(`${specifier}/index.js`); } for (const attempt of interopAttempts) { try { return await nextResolve(attempt, context); } catch {} } // Original specifier is attempted at the end because // we want to prioritize the ESM variants first. return await nextResolve(specifier, context); }