167 lines
6.4 KiB
JavaScript
167 lines
6.4 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.loadStaticParamsAsync = loadStaticParamsAsync;
|
|
exports.evalStaticParamsAsync = evalStaticParamsAsync;
|
|
exports.assertStaticParams = assertStaticParams;
|
|
async function loadStaticParamsAsync(route) {
|
|
const expandedChildren = await Promise.all(route.children.map((route) => loadStaticParamsRecursive(route, { parentParams: {} })));
|
|
route.children = expandedChildren.flat();
|
|
return route;
|
|
}
|
|
async function evalStaticParamsAsync(route, props, generateStaticParams) {
|
|
if (!route.dynamic && generateStaticParams) {
|
|
throw new Error('Cannot use generateStaticParams in a route without dynamic segments: ' + route.contextKey);
|
|
}
|
|
if (generateStaticParams) {
|
|
const staticParams = await generateStaticParams({
|
|
params: props.parentParams || {},
|
|
});
|
|
assertStaticParamsType(staticParams);
|
|
// Assert that at least one param from each matches the dynamic route.
|
|
staticParams.forEach((params) => assertStaticParams(route, params));
|
|
return staticParams;
|
|
}
|
|
return null;
|
|
}
|
|
async function loadStaticParamsRecursive(route, props) {
|
|
if (!route?.dynamic && !route?.children?.length) {
|
|
return [route];
|
|
}
|
|
const loaded = await route.loadRoute();
|
|
const staticParams = (await evalStaticParamsAsync(route, props, loaded.generateStaticParams)) ?? [];
|
|
const traverseForNode = async (nextParams) => {
|
|
const nextChildren = [];
|
|
for (const child of route.children) {
|
|
const children = await loadStaticParamsRecursive(child, {
|
|
...props,
|
|
parentParams: nextParams,
|
|
});
|
|
nextChildren.push(...children);
|
|
}
|
|
return uniqBy(nextChildren, (i) => i.route);
|
|
};
|
|
if (!staticParams.length) {
|
|
const nextParams = {
|
|
...props.parentParams,
|
|
};
|
|
route.children = await traverseForNode(nextParams);
|
|
return [route];
|
|
}
|
|
const createParsedRouteName = (input, params) => {
|
|
let parsedRouteName = input;
|
|
route.dynamic?.map((query) => {
|
|
const param = params[query.name];
|
|
const formattedParameter = Array.isArray(param) ? param.join('/') : param;
|
|
if (query.deep) {
|
|
parsedRouteName = parsedRouteName.replace(`[...${query.name}]`, formattedParameter);
|
|
}
|
|
else {
|
|
parsedRouteName = parsedRouteName.replace(`[${query.name}]`, param);
|
|
}
|
|
});
|
|
return parsedRouteName;
|
|
};
|
|
const generatedRoutes = await Promise.all(staticParams.map(async (params) => {
|
|
const nextParams = {
|
|
...props.parentParams,
|
|
...params,
|
|
};
|
|
const dynamicChildren = await traverseForNode(nextParams);
|
|
const parsedRoute = createParsedRouteName(route.route, params);
|
|
const generatedContextKey = createParsedRouteName(route.contextKey, params);
|
|
const generatedRoute = {
|
|
...route,
|
|
// TODO: Add a new field for this
|
|
contextKey: generatedContextKey,
|
|
// Convert the dynamic route to a static route.
|
|
dynamic: null,
|
|
route: parsedRoute,
|
|
children: dynamicChildren,
|
|
};
|
|
if (route.type === 'route') {
|
|
generatedRoute.parentContextKey = route.contextKey;
|
|
}
|
|
return generatedRoute;
|
|
}));
|
|
return [route, ...generatedRoutes];
|
|
}
|
|
/** lodash.uniqBy */
|
|
function uniqBy(array, key) {
|
|
const seen = {};
|
|
return array.filter((item) => {
|
|
const k = key(item);
|
|
if (seen[k]) {
|
|
return false;
|
|
}
|
|
seen[k] = true;
|
|
return true;
|
|
});
|
|
}
|
|
function assertStaticParamsType(params) {
|
|
if (!Array.isArray(params)) {
|
|
throw new Error(`generateStaticParams() must return an array of params, received ${params}`);
|
|
}
|
|
}
|
|
function formatExpected(expected, received) {
|
|
const total = {
|
|
...received,
|
|
};
|
|
for (const item of expected) {
|
|
if (total[item] == null) {
|
|
total[item] = String(total[item]);
|
|
}
|
|
else {
|
|
total[item] = `"${total[item]}"`;
|
|
}
|
|
}
|
|
return [
|
|
'{',
|
|
Object.entries(total)
|
|
.map(([key, value]) => ` "${key}": ${value}`)
|
|
.join(',\n'),
|
|
'}',
|
|
].join('\n');
|
|
}
|
|
function assertStaticParams(route, params) {
|
|
// Type checking
|
|
if (!route.dynamic) {
|
|
throw new Error('assertStaticParams() must be called on a dynamic route.');
|
|
}
|
|
const matches = route.dynamic.every((dynamic) => {
|
|
const value = params[dynamic.name];
|
|
return value !== undefined && value !== null;
|
|
});
|
|
if (!matches) {
|
|
const plural = route.dynamic.length > 1 ? 's' : '';
|
|
const expected = route.dynamic.map((dynamic) => dynamic.name);
|
|
throw new Error(`[${route.contextKey}]: generateStaticParams() must return an array of params that match the dynamic route${plural}. Expected non-nullish values for key${plural}: ${expected
|
|
.map((v) => `"${v}"`)
|
|
.join(', ')}.\nReceived:\n${formatExpected(expected, params)}`);
|
|
}
|
|
const validateSingleParam = (dynamic, value, allowMultipleSegments) => {
|
|
if (typeof value !== 'string') {
|
|
throw new Error(`generateStaticParams() for route "${route.contextKey}" expected param "${dynamic.name}" to be of type string, instead found "${typeof value}" while parsing "${value}".`);
|
|
}
|
|
const parts = value.split('/').filter(Boolean);
|
|
if (parts.length > 1 && !allowMultipleSegments) {
|
|
throw new Error(`generateStaticParams() for route "${route.contextKey}" expected param "${dynamic.name}" to not contain "/" (multiple segments) while parsing "${value}".`);
|
|
}
|
|
if (parts.length === 0) {
|
|
throw new Error(`generateStaticParams() for route "${route.contextKey}" expected param "${dynamic.name}" not to be empty while parsing "${value}".`);
|
|
}
|
|
};
|
|
// `[shape]/bar/[...colors]` -> `[shape]`, `[...colors]`
|
|
for (const dynamic of route.dynamic) {
|
|
let parameter = params[dynamic.name];
|
|
if (dynamic.deep) {
|
|
if (Array.isArray(parameter)) {
|
|
parameter = parameter.filter(Boolean).join('/');
|
|
}
|
|
validateSingleParam(dynamic, parameter, true);
|
|
}
|
|
else {
|
|
validateSingleParam(dynamic, parameter);
|
|
}
|
|
}
|
|
}
|
|
//# sourceMappingURL=loadStaticParamsAsync.js.map
|