vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
145 lines (144 loc) • 6.84 kB
JavaScript
export { parsePageConfigsSerialized };
export { parseConfigValuesSerialized };
import { assert, assertUsage } from '../../../utils/assert.js';
import { isCallable } from '../../../utils/isCallable.js';
import { getConfigDefinedAt } from '../getConfigDefinedAt.js';
import { parseTransform } from '@brillout/json-serializer/parse';
import { assertPlusFileExport } from '../assertPlusFileExport.js';
function parsePageConfigsSerialized(pageConfigsSerialized, pageConfigGlobalSerialized) {
// pageConfigs
const pageConfigs = pageConfigsSerialized.map((pageConfigSerialized) => {
const configValues = parseConfigValuesSerialized(pageConfigSerialized.configValuesSerialized);
assertRouteConfigValue(configValues);
const pageConfig = { ...pageConfigSerialized, configValues };
return pageConfig;
});
// pageConfigsGlobal
const pageConfigGlobal = { configValues: {} };
{
const configValues = parseConfigValuesSerialized(pageConfigGlobalSerialized.configValuesSerialized);
Object.assign(pageConfigGlobal.configValues, configValues);
}
return { pageConfigs, pageConfigGlobal };
}
function assertRouteConfigValue(configValues) {
const configName = 'route';
const configValue = configValues[configName];
if (!configValue)
return;
const { value, definedAtData } = configValue;
const configValueType = typeof value;
assert(definedAtData);
const configDefinedAt = getConfigDefinedAt('Config', configName, definedAtData);
assertUsage(configValueType === 'string' || isCallable(value), `${configDefinedAt} has an invalid type '${configValueType}': it should be a string or a function instead, see https://vike.dev/route`);
/* We don't use assertRouteString() in order to avoid unnecessarily bloating the client-side bundle when using Server Routing:
* - When using Server Routing, this file is loaded => loading assertRouteString() would bloat the client bundle.
* - assertRouteString() is already called on the server-side
* - When using Server Routing, client-side validation is superfluous as Route Strings only need to be validated on the server-side
if (typeof configValue === 'string') {
assertRouteString(configValue, `${configElement.configDefinedAt} defines an`)
}
*/
}
function parseConfigValuesSerialized(configValuesSerialized) {
const configValues = {};
Object.entries(configValuesSerialized).forEach(([configName, configValueSeriliazed]) => {
let configValue;
if (configValueSeriliazed.type === 'cumulative') {
const { valueSerialized, ...common } = configValueSeriliazed;
const value = valueSerialized.map((valueSerializedElement, i) => {
const { value, sideExports } = parseValueSerialized(valueSerializedElement, configName, () => {
const definedAtFile = configValueSeriliazed.definedAtData[i];
assert(definedAtFile);
return definedAtFile;
});
addSideExports(sideExports);
return value;
});
configValue = { value, ...common };
}
else {
const { valueSerialized, ...common } = configValueSeriliazed;
const { value, sideExports } = parseValueSerialized(valueSerialized, configName, () => {
assert(configValueSeriliazed.type !== 'computed');
const { definedAtData } = configValueSeriliazed;
const definedAtFile = Array.isArray(definedAtData) ? definedAtData[0] : definedAtData;
return definedAtFile;
});
addSideExports(sideExports);
configValue = { value, ...common };
}
configValues[configName] = configValue;
});
return configValues;
function addSideExports(sideExports) {
sideExports.forEach((sideExport) => {
const { configName, configValue } = sideExport;
if (!configValues[configName]) {
configValues[configName] = configValue;
}
else {
// Side-exports have lower precedence.
// We can't avoid side-export conflicts upstream. (We cannot know about side-exports at build-time.)
}
});
}
}
function parseValueSerialized(valueSerialized, configName, getDefinedAtFile) {
if (valueSerialized.type === 'js-serialized') {
let { value } = valueSerialized;
value = parseTransform(value);
return { value, sideExports: [] };
}
if (valueSerialized.type === 'pointer-import') {
const { value } = valueSerialized;
return { value, sideExports: [] };
}
if (valueSerialized.type === 'plus-file') {
const definedAtFile = getDefinedAtFile();
const { exportValues } = valueSerialized;
assert(!definedAtFile.definedBy);
assertPlusFileExport(exportValues, definedAtFile.filePathToShowToUser, configName);
let value;
let valueWasFound = false;
const sideExports = [];
Object.entries(exportValues).forEach(([exportName, exportValue]) => {
const isSideExport = exportName !== 'default' && exportName !== configName;
if (!isSideExport) {
value = exportValue;
// Already asserted by assertPlusFileExport() call above.
assert(!valueWasFound);
valueWasFound = true;
}
else {
sideExports.push({
configName: exportName,
configValue: {
type: 'standard', // We don't support side exports for cumulative values. We could support it but it isn't trivial.
value: exportValue,
definedAtData: {
filePathToShowToUser: definedAtFile.filePathToShowToUser,
fileExportPathToShowToUser: [exportName],
},
},
});
}
});
// Already asserted by assertPlusFileExport() call above.
assert(valueWasFound);
return { value, sideExports };
}
assert(false);
}
/* [NULL_HANDLING] Do we really need this?
function assertIsNotNull(configValue: unknown, configName: string, filePathToShowToUser: string) {
assert(!filePathToShowToUser.includes('+config.'))
// Re-use this for:
// - upcoming config.requestPageContextOnNavigation
// - for cumulative values in the future: we don't need this for now because, currently, cumulative values are never imported.
assertUsage(
configValue !== null,
`Set ${pc.cyan(configName)} to ${pc.cyan('null')} in a +config.js file instead of ${filePathToShowToUser}`
)
}
*/