vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
51 lines (50 loc) • 2.34 kB
JavaScript
export { resolveRedirects };
// For ./resolveRedirects.spec.ts
export { resolveRouteStringRedirect };
export { redirectsErrPrefix };
import { assertIsNotBrowser } from '../../../utils/assertIsNotBrowser.js';
import { assert, assertUsage, assertUsageUrlRedirectTarget, isUrlRedirectTarget } from '../../../shared/utils.js';
import { resolveUrlPathname } from '../../../shared/route/resolveUrlPathname.js';
import { assertRouteString, resolveRouteString } from '../../../shared/route/resolveRouteString.js';
import pc from '@brillout/picocolors';
assertIsNotBrowser(); // Don't bloat the client
const redirectsErrPrefix = '[+redirects]';
function resolveRedirects(redirectsAll, urlPathname) {
const redirects = merge(redirectsAll);
for (const [urlSource, urlTarget] of Object.entries(redirects)) {
const urlResolved = resolveRouteStringRedirect(urlSource, urlTarget, urlPathname);
if (urlResolved)
return urlResolved;
}
return null;
}
function resolveRouteStringRedirect(urlSource, urlTarget, urlPathname) {
assertRouteString(urlSource, `${redirectsErrPrefix} Invalid`);
// Is allowing any protocol a safety issue? https://github.com/vikejs/vike/pull/1292#issuecomment-1828043917
assertUsageUrlRedirectTarget(urlTarget, `${redirectsErrPrefix} The URL redirection target`, true);
assertParams(urlSource, urlTarget);
const match = resolveRouteString(urlSource, urlPathname);
if (!match)
return null;
const urlResolved = resolveUrlPathname(urlTarget, match.routeParams);
if (urlResolved === urlPathname)
return null;
assert(isUrlRedirectTarget(urlResolved));
return urlResolved;
}
function assertParams(urlSource, urlTarget) {
const routeSegments = urlTarget.split('/');
routeSegments.forEach((routeSegment) => {
if (routeSegment.startsWith('@') || routeSegment.startsWith('*')) {
const segments = urlSource.split('/');
assertUsage(segments.includes(routeSegment), `${redirectsErrPrefix} The redirection source URL ${pc.string(urlSource)} is missing the URL parameter ${pc.string(routeSegment)} used by the redirection target URL ${pc.string(urlTarget)}`);
}
});
}
function merge(objs) {
const obj = {};
objs.forEach((e) => {
Object.assign(obj, e);
});
return obj;
}