vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
214 lines (213 loc) • 9.78 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.requireResolveOptional = requireResolveOptional;
exports.requireResolveOptionalDir = requireResolveOptionalDir;
exports.requireResolveNpmPackage = requireResolveNpmPackage;
exports.requireResolveVikeDistFile = requireResolveVikeDistFile;
exports.getVikeNodeModulesRoot = getVikeNodeModulesRoot;
const assert_js_1 = require("./assert.js");
const assertIsNotBrowser_js_1 = require("./assertIsNotBrowser.js");
const assertSetup_js_1 = require("./assertSetup.js");
const path_js_1 = require("./path.js");
const isScriptFile_js_1 = require("./isScriptFile.js");
const node_module_1 = require("node:module");
const node_path_1 = __importDefault(require("node:path"));
const parseNpmPackage_js_1 = require("./parseNpmPackage.js");
const isNullish_js_1 = require("./isNullish.js");
const debug_js_1 = require("./debug.js");
// @ts-ignore `file:///${__filename.split('\\').join('/')}` is shimmed at dist/cjs by dist-cjs-fixup.js.
const importMetaUrl = `file:///${__filename.split('\\').join('/')}`;
(0, path_js_1.assertPosixPath)(importMetaUrl);
(0, assertIsNotBrowser_js_1.assertIsNotBrowser)();
(0, assertSetup_js_1.assertIsNotProductionRuntime)();
const debug = (0, debug_js_1.createDebugger)('vike:resolve');
// - We still can't use import.meta.resolve() as of 23.1.0 (November 2024) because `parent` argument requires an experimental flag.
// - https://stackoverflow.com/questions/54977743/do-require-resolve-for-es-modules#comment139581675_62272600
// - Passing context to createRequire(context) isn't equivalent to passing it to the `paths` argument of require.resolve()
// - https://github.com/brillout/require-test
// - In practice, I guess it doesn't make a difference? It just seems to be small Node.js weirdness.
// - The argument createRequire(argument) seems to be overridden by the `paths` argument require.resolve()
// - For example, passing an empty array to `paths` kills the argument passed to `createRequire()`
// - Thus, when `paths` is defined, then the context needs to be passed to both createRequire() as well as the `paths` argument of require.resolve()
function requireResolve_(importPath, importerFilePath, userRootDir, doNotHandleFileExtension = false) {
(0, path_js_1.assertPosixPath)(importPath);
const contexts = importerFilePath
? [importerFilePath]
: [userRootDir ? getFakeImporterFile(userRootDir) : importMetaUrl];
addExtraContextForNpmPackageImport(contexts, importPath, userRootDir);
let importPathResolvedFilePath;
let failure;
for (const context of contexts) {
(0, path_js_1.assertPosixPath)(context);
const contextNode = makeNodeFriendly(ensureFilePrefix(context));
let importPathNode = makeNodeFriendly(importPath);
const require_ = (0, node_module_1.createRequire)(contextNode);
if (!doNotHandleFileExtension) {
addFileExtensionsToRequireResolve(require_);
importPathNode = removeFileExtension(importPathNode);
}
try {
importPathResolvedFilePath = require_.resolve(importPathNode);
}
catch (err) {
if (debug.isActivated) {
const stack = new Error().stack;
debug('ERROR', { err, importPath, context }, stack);
}
failure ?? (failure = { err });
}
if (importPathResolvedFilePath)
break;
}
if (!importPathResolvedFilePath) {
(0, assert_js_1.assert)(failure);
if (debug.isActivated) {
debug('FAILURE', {
importPath,
importerFilePath,
userRootDir,
doNotHandleFileExtension,
importMetaUrl,
contexts,
});
}
return { importPathResolvedFilePath: undefined, err: failure.err, hasFailed: true };
}
else {
if (failure && debug.isActivated) {
debug('SUCCESS', {
importPath,
contexts,
});
}
(0, assert_js_1.assert)(importPathResolvedFilePath);
importPathResolvedFilePath = (0, path_js_1.toPosixPath)(importPathResolvedFilePath);
return { importPathResolvedFilePath, err: undefined, hasFailed: false };
}
}
function requireResolveOptional({ importPath, importerFilePath, userRootDir, }) {
const res = requireResolve_(importPath, importerFilePath, userRootDir);
if (res.hasFailed)
return null;
return res.importPathResolvedFilePath;
}
function requireResolveOptionalDir({ importPath, importerDir, userRootDir, }) {
const importerFilePath = getFakeImporterFile(importerDir);
const res = requireResolve_(importPath, importerFilePath, userRootDir);
if (res.hasFailed)
return null;
return res.importPathResolvedFilePath;
}
function requireResolveNpmPackage({ importPathNpmPackage, userRootDir, }) {
(0, parseNpmPackage_js_1.assertIsImportPathNpmPackage)(importPathNpmPackage);
const importerFilePath = getFakeImporterFile(userRootDir);
const res = requireResolve_(importPathNpmPackage, importerFilePath, userRootDir);
if (res.hasFailed)
throw res.err;
return res.importPathResolvedFilePath;
}
function requireResolveVikeDistFile(vikeDistFile) {
const vikeNodeModulesRoot = getVikeNodeModulesRoot();
(0, path_js_1.assertPosixPath)(vikeNodeModulesRoot);
(0, path_js_1.assertPosixPath)(vikeDistFile);
const importPathResolvedFilePath = makeNodeFriendly(node_path_1.default.posix.join(vikeNodeModulesRoot, vikeDistFile));
// Double check
{
const res = requireResolve_(importPathResolvedFilePath,
// No context needed: importPathResolvedFilePath is already resolved and absolute
null, null, true);
if (res.hasFailed)
throw res.err;
(0, assert_js_1.assert)(res.importPathResolvedFilePath === importPathResolvedFilePath);
}
return importPathResolvedFilePath;
}
function addExtraContextForNpmPackageImport(contexts, importPath, userRootDir) {
// We should add extra context only for npm packages, but unfortunately we cannot always disambiguate between npm package imports and path aliases.
if (!(0, parseNpmPackage_js_1.isImportPathNpmPackageOrPathAlias)(importPath))
return;
const userRootDirFakeFile = userRootDir && getFakeImporterFile(userRootDir);
[
// Workaround for monorepo resolve issue: https://github.com/vikejs/vike-react/pull/161/commits/dbaa6643e78015ac2797c237552800fef29b72a7
userRootDirFakeFile,
// I can't think of a use case where this would be needed, but let's add one extra last chance to successfully resolve some complex monorepo setups
importMetaUrl,
]
.filter(isNullish_js_1.isNotNullish)
.forEach((context) => {
const alreadyHasContext = contexts.includes(context) || contexts.includes(ensureFilePrefix(context));
if (alreadyHasContext)
return;
contexts.push(context);
});
}
function removeFileExtension(importPath) {
// Skip for Bun: https://github.com/vikejs/vike/issues/2204
//@ts-ignore
if (typeof Bun !== 'undefined') {
// https://bun.sh/guides/util/detect-bun
(0, assert_js_1.assert)(process.versions.bun);
return importPath;
}
for (const ext of isScriptFile_js_1.scriptFileExtensionList) {
const suffix = `.${ext}`;
if (importPath.endsWith(suffix)) {
return importPath.slice(0, -1 * suffix.length);
}
}
return importPath;
}
function addFileExtensionsToRequireResolve(require_) {
const added = [];
isScriptFile_js_1.scriptFileExtensionList.forEach((ext) => {
(0, assert_js_1.assert)(!ext.includes('.'));
ext = `.${ext}`;
if (!require_.extensions[ext]) {
require_.extensions[ext] = require_.extensions['.js'];
added.push(ext);
}
});
}
function getVikeNodeModulesRoot() {
// [RELATIVE_PATH_FROM_DIST] Current file: vike/dist/esm/utils/requireResolve.js
(0, assert_js_1.assert)(importMetaUrl.includes('/dist/esm/') || importMetaUrl.includes('/dist/cjs/'));
const vikeNodeModulesRoot = node_path_1.default.posix.join(removeFilePrefix(importMetaUrl), '../../../../');
return vikeNodeModulesRoot;
}
function getFakeImporterFile(dirPath) {
(0, path_js_1.assertPosixPath)(dirPath);
(0, assert_js_1.assert)(!dirPath.startsWith('file')); // The file:// prefix is bogus when used with path.posix.join()
const importerFilePath = node_path_1.default.posix.join(dirPath, 'fakeFileForNodeResolve.js');
return importerFilePath;
}
function ensureFilePrefix(filePath) {
(0, path_js_1.assertPosixPath)(filePath);
const filePrefix = getFilePrefix();
if (!filePath.startsWith(filePrefix)) {
(0, assert_js_1.assert)(!filePath.startsWith('file'));
filePath = filePrefix + filePath;
}
(0, assert_js_1.assert)(filePath.startsWith(filePrefix));
return filePath;
}
function removeFilePrefix(filePath) {
const filePrefix = getFilePrefix();
if (filePath.startsWith(filePrefix)) {
filePath = filePath.slice(filePrefix.length);
}
(0, assert_js_1.assert)(!filePath.startsWith('file'));
return filePath;
}
function getFilePrefix() {
let prefix = 'file://';
if (process.platform === 'win32')
prefix += '/';
return prefix;
}
function makeNodeFriendly(filePath) {
// https://github.com/vikejs/vike/issues/2436#issuecomment-2849145340
return decodeURIComponent(filePath);
}