vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
115 lines (112 loc) • 5.91 kB
JavaScript
import '../../assertEnvVite.js';
export { getPlusFilesByLocationId };
import { assert } from '../../../../utils/assert.js';
import { configDefinitionsBuiltIn } from './configDefinitionsBuiltIn.js';
import { getLocationId } from './filesystemRouting.js';
import { crawlPlusFilePaths, getPlusFileValueConfigName } from './crawlPlusFilePaths.js';
import { getConfigFileExport } from './getConfigFileExport.js';
import { loadConfigFile, loadValueFile } from './loadFileAtConfigTime.js';
import { resolvePointerImport } from './resolvePointerImport.js';
import { getFilePathResolved } from '../getFilePath.js';
import { assertExtensionsConventions, assertExtensionsRequire } from './assertExtensions.js';
async function getPlusFilesByLocationId(userRootDir, esbuildCache) {
const plusFilePaths = (await crawlPlusFilePaths(userRootDir)).map(({ filePathAbsoluteUserRootDir }) => getFilePathResolved({ filePathAbsoluteUserRootDir, userRootDir }));
const plusFilesByLocationId = {};
await Promise.all(plusFilePaths.map(async (filePath) => {
if (getPlusFileValueConfigName(filePath.filePathAbsoluteFilesystem) === 'config') {
// +config.js files
const { filePathAbsoluteUserRootDir } = filePath;
assert(filePathAbsoluteUserRootDir);
const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, [], false, esbuildCache);
assert(filePath.filePathAbsoluteUserRootDir);
const locationId = getLocationId(filePathAbsoluteUserRootDir);
const plusFile = getPlusFileFromConfigFile(configFile, false, locationId, userRootDir);
plusFilesByLocationId[locationId] = plusFilesByLocationId[locationId] ?? [];
plusFilesByLocationId[locationId].push(plusFile);
extendsConfigs.forEach((extendsConfig) => {
/* We purposely use the same locationId because the Vike extension's config should only apply to where it's being extended from, for example:
```js
// /pages/admin/+config.js
import vikeVue from 'vike-vue/config'
// Should only apply to /pages/admin/**
export default { extends: [vikeVue] }
```
```js
// /pages/marketing/+config.js
import vikeReact from 'vike-react/config'
// Should only apply to /pages/marketing/**
export default { extends: [vikeReact] }
```
*/
const plusFile = getPlusFileFromConfigFile(extendsConfig, true, locationId, userRootDir);
assertExtensionsConventions(plusFile);
plusFilesByLocationId[locationId].push(plusFile);
});
}
else {
// +{configName}.js files
const { filePathAbsoluteUserRootDir } = filePath;
assert(filePathAbsoluteUserRootDir);
const configName = getPlusFileValueConfigName(filePathAbsoluteUserRootDir);
assert(configName);
const locationId = getLocationId(filePathAbsoluteUserRootDir);
const plusFile = {
locationId,
filePath,
isConfigFile: false,
isNotLoaded: true,
configName,
};
plusFilesByLocationId[locationId] = plusFilesByLocationId[locationId] ?? [];
plusFilesByLocationId[locationId].push(plusFile);
// We don't have access to the custom config definitions defined by the user yet.
// - If `configDef` is `undefined` => we load the file +{configName}.js later.
// - We already need to load +meta.js here (to get the custom config definitions defined by the user)
await loadValueFile(plusFile, configDefinitionsBuiltIn, userRootDir, esbuildCache);
}
}));
// Make lists element order deterministic
Object.entries(plusFilesByLocationId).forEach(([_locationId, plusFiles]) => {
plusFiles.sort(sortMakeDeterministic);
});
assertPlusFiles(plusFilesByLocationId);
return plusFilesByLocationId;
}
function assertPlusFiles(plusFilesByLocationId) {
const plusFiles = Object.values(plusFilesByLocationId).flat();
// The earlier we call it the better, so that +require can be used by Vike extensions to depend on new Vike features
assertExtensionsRequire(plusFiles);
}
function getPlusFileFromConfigFile(configFile, isExtensionConfig, locationId, userRootDir) {
const { fileExports, filePath, extendsFilePaths } = configFile;
const fileExportsByConfigName = {};
const pointerImportsByConfigName = {};
const fileExport = getConfigFileExport(fileExports, filePath.filePathToShowToUser);
Object.entries(fileExport).forEach(([configName, configValue]) => {
fileExportsByConfigName[configName] = configValue;
// Pointer imports
const values = Array.isArray(configValue) ? configValue : [configValue];
const pointerImports = values
.map((value) => resolvePointerImport(value, configFile.filePath, userRootDir, configName))
.filter((pointerImport) => pointerImport !== null)
.map((pointerImport) => ({ ...pointerImport, fileExportValueLoaded: false }));
if (pointerImports.length > 0) {
pointerImportsByConfigName[configName] = pointerImports;
}
});
const plusFile = {
locationId,
filePath,
fileExportsByConfigName,
pointerImportsByConfigName,
isConfigFile: true,
isExtensionConfig,
extendsFilePaths,
};
return plusFile;
}
// Make order deterministic (no other purpose)
function sortMakeDeterministic(plusFile1, plusFile2) {
// Sort by file path
return plusFile1.filePath.filePathAbsoluteVite < plusFile2.filePath.filePathAbsoluteVite ? -1 : 1;
}