vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
106 lines (105 loc) • 6.11 kB
JavaScript
import '../../assertEnvVite.js';
export { resolvePointerImport };
export { resolvePointerImportData };
import pc from '@brillout/picocolors';
import { assert, assertUsage } from '../../../../utils/assert.js';
import { isFilePathAbsolute } from '../../../../utils/isFilePathAbsoluteFilesystem.js';
import { isImportPathRelative } from '../../../../utils/isImportPath.js';
import { isImportPathNpmPackageOrPathAlias } from '../../../../utils/parseNpmPackage.js';
import { assertPosixPath } from '../../../../utils/path.js';
import { requireResolveOptional } from '../../../../utils/requireResolve.js';
import { assertPointerImportPath, parsePointerImportData } from './pointerImports.js';
import { getFilePathAbsoluteUserRootDir, getFilePathResolved, getFilePathUnresolved } from '../getFilePath.js';
function resolvePointerImport(configValue, importerFilePath, userRootDir, configName) {
if (typeof configValue !== 'string')
return null;
const pointerImportData = parsePointerImportData(configValue);
if (!pointerImportData)
return null;
const { exportName } = pointerImportData;
const filePath = resolvePointerImportData(pointerImportData, importerFilePath, userRootDir);
const fileExportPathToShowToUser = exportName === 'default' || exportName === configName ? [] : [exportName];
const fileExportPath = {
...filePath,
fileExportName: exportName,
fileExportPathToShowToUser,
};
return { fileExportPath };
}
function resolvePointerImportData(pointerImportData, importerFilePath, userRootDir) {
const { importPath } = pointerImportData;
assertPointerImportPath(importPath);
const filePathAbsoluteFilesystem = resolveImportPathWithNode(pointerImportData, importerFilePath, userRootDir);
let filePath;
assertPosixPath(importPath);
if (isImportPathRelative(importPath) || isFilePathAbsolute(importPath)) {
// Pointer imports are included in virtual files, thus relative imports need to be resolved. (Virtual modules cannot contain relative imports.)
assertUsageResolutionSuccess(filePathAbsoluteFilesystem, pointerImportData, importerFilePath);
// Pointer imports are included in virtual files, and we need filePathAbsoluteUserRootDir because we didn't find a way to have filesystem absolute import paths in virtual files: https://gist.github.com/brillout/2315231c9a8164f950c64b4b4a7bbd39
const errSuffix = `outside of the ${userRootDir} directory which is forbidden: make sure your import paths resolve inside the ${userRootDir} directory, or import from an npm package.`;
const filePathAbsoluteUserRootDir = getFilePathAbsoluteUserRootDir({ filePathAbsoluteFilesystem, userRootDir });
if (isImportPathRelative(importPath)) {
assertUsage(filePathAbsoluteUserRootDir, `The relative import ${pc.cyan(importPath)} defined by ${importerFilePath.filePathToShowToUser} resolves to ${filePathAbsoluteFilesystem} ${errSuffix}`);
}
else {
assert(isFilePathAbsolute(importPath));
assertUsage(filePathAbsoluteUserRootDir, `The import path ${importPath} defined by ${importerFilePath.filePathToShowToUser} is ${errSuffix}`);
}
// Forbid node_modules/ because it's brittle: if node_modules/ lives outside of userRootDir then it crashes.
assertUsage(!filePathAbsoluteUserRootDir.includes('/node_modules/'), `The import path ${importPath} defined by ${importerFilePath.filePathToShowToUser} resolves to ${filePathAbsoluteFilesystem} inside of node_modules/ which is forbidden: use an npm package import instead.`);
filePath = getFilePathResolved({ filePathAbsoluteUserRootDir, userRootDir });
}
else {
assert(isImportPathNpmPackageOrPathAlias(importPath));
const importPathAbsolute = importPath;
if (filePathAbsoluteFilesystem) {
filePath = getFilePathResolved({
userRootDir,
filePathAbsoluteFilesystem,
importPathAbsolute,
});
}
else {
// We cannot resolve path aliases defined only in Vite
filePath = getFilePathUnresolved({
importPathAbsolute,
});
}
}
return filePath;
}
function resolveImportPathWithNode(pointerImportData, importerFilePath, userRootDir) {
const importerFilePathAbsolute = importerFilePath.filePathAbsoluteFilesystem;
assertPosixPath(importerFilePathAbsolute);
// filePathAbsoluteFilesystem is null when pointerImportData.importPath is a path alias that Node.js doesn't know about
const filePathAbsoluteFilesystem = requireResolveOptional({
importPath: pointerImportData.importPath,
importerFilePath: importerFilePathAbsolute,
userRootDir,
});
if (!filePathAbsoluteFilesystem) {
assert(!isImportPathRelative(pointerImportData.importPath));
/* This assertion fails if the npm package has a wrongly defined package.json#exports
// Libraries don't use path aliases => filePathAbsoluteFilesystem should be defined
assert(!importerFilePathAbsolute.includes('node_modules'))
*/
}
return filePathAbsoluteFilesystem;
}
function assertUsageResolutionSuccess(filePathAbsoluteFilesystem, pointerImportData, importerFilePath) {
const { importPath: importPath, importStringWasGenerated, importString } = pointerImportData;
const { filePathToShowToUser } = importerFilePath;
if (!filePathAbsoluteFilesystem) {
const importPathString = pc.code(`${importPath}`);
const errIntro = importStringWasGenerated
? `The import path ${importPathString} in ${filePathToShowToUser}`
: `The import ${pc.code(importString)} defined by ${filePathToShowToUser}`;
const errIntro2 = `${errIntro} couldn't be resolved: does ${importPathString}`;
if (isImportPathRelative(importPath)) {
assertUsage(false, `${errIntro2} point to an existing file?`);
}
else {
assertUsage(false, `${errIntro2} exist?`);
}
}
}