vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
71 lines (70 loc) • 4.04 kB
JavaScript
export { resolveRouteFunction };
export { assertRouteParams };
export { assertSyncRouting };
export { warnDeprecatedAllowKey };
import { execHookSingleSync } from '../hooks/execHook.js';
import { getPageContextPublicShared } from '../getPageContextPublicShared.js';
import { assert, assertUsage, assertWarning } from '../../utils/assert.js';
import { hasProp } from '../../utils/hasProp.js';
import { isPlainObject } from '../../utils/isPlainObject.js';
import { isPromise } from '../../utils/isPromise.js';
import pc from '@brillout/picocolors';
async function resolveRouteFunction(routeFunction, pageContext, routeFunctionFilePath) {
let { hookReturn: result } = execHookSingleSync({
hookFn: routeFunction,
hookFilePath: routeFunctionFilePath,
hookName: 'route',
}, pageContext._globalContext, pageContext, getPageContextPublicShared);
assertSyncRouting(result, `The Route Function ${routeFunctionFilePath}`);
// TO-DO/next-major-release: make resolveRouteFunction() and route() sync
//* We disallow asynchronous routing, because we need to check whether a link is a Vike link in a synchronous fashion before calling ev.preventDefault() in the 'click' event listener
result = await result;
//*/
if (result === false) {
return null;
}
if (result === true) {
result = {};
}
assertUsage(isPlainObject(result), `The Route Function ${routeFunctionFilePath} should return a boolean or a plain JavaScript object (but it's ${pc.cyan(`typeof result === ${JSON.stringify(typeof result)}`)} instead)`);
// AFAICT this return interface is superfluous. Should we soft-deprecate it and remove it?
if ('match' in result) {
const { match } = result;
assertUsage(typeof match === 'boolean', `The ${pc.cyan('match')} value returned by the Route Function ${routeFunctionFilePath} should be a boolean.`);
if (!match) {
return null;
}
}
let precedence = null;
if ('precedence' in result) {
precedence = result.precedence;
assertUsage(typeof precedence === 'number', `The ${pc.cyan('precedence')} value returned by the Route Function ${routeFunctionFilePath} should be a number.`);
}
assertRouteParams(result, `The ${pc.cyan('routeParams')} object returned by the Route Function ${routeFunctionFilePath} should`);
const routeParams = result.routeParams || {};
assertUsage(!('pageContext' in result), `Providing ${pc.cyan('pageContext')} in Route Functions is prohibited, see https://vike.dev/route-function#cannot-provide-pagecontext`);
assert(isPlainObject(routeParams));
Object.keys(result).forEach((key) => {
assertUsage(key === 'match' || key === 'routeParams' || key === 'precedence', `The Route Function ${routeFunctionFilePath} returned an object with an unknown property ${pc.cyan(key)} (the known properties are ${pc.cyan('match')}, ${pc.cyan('routeParams')}, and ${pc.cyan('precedence')})`);
});
return {
precedence,
routeParams,
};
}
// TO-DO/next-major-release: remove, and make routing synchronous (enabling Vike to synchronously check whether a link is a Vike link before even calling ev.preventDefault())
function assertSyncRouting(res, errPrefix) {
assertWarning(!isPromise(res), `${errPrefix} returned a promise, but asynchronous routing is deprecated and will be removed in the next major release, see https://vike.dev/route-function#async`, { onlyOnce: true });
}
// TO-DO/next-major-release: remove
function warnDeprecatedAllowKey() {
const allowKey = pc.cyan('iKnowThePerformanceRisksOfAsyncRouteFunctions');
assertWarning(false, `${allowKey} is deprecated and will be removed in the next major release`, { onlyOnce: true });
}
function assertRouteParams(result, errPrefix) {
assert(errPrefix.endsWith(' should'));
if (!hasProp(result, 'routeParams')) {
return;
}
assertUsage(hasProp(result, 'routeParams', 'string{}'), `${errPrefix} be ${pc.bold('Record<string, string>')}`);
}