export const jsonRoutePlugin = async (
route: string,
conf: RouteTypeJson
): Promise<HandledRoute[]> => {
// Parse the route pattern
const { params, createPath } = routeSplit(route);
// Validate that all parameters have configuration
const missingParams = params.filter(param => !conf.hasOwnProperty(param.part));
if (missingParams.length > 0) {
console.error(`Missing config for parameters (${missingParams.join(',')})`)
return [{ route, type: conf.type }];
}
// Fetch data for each parameter
const loadData = (param, context = {}): Promise<any[]> => {
const url = renderTemplate(conf[param.part].url, context).trim();
return httpGetJson(url, {
headers: conf[param.part].headers,
})
.then(rawData =>
conf[param.part].property === undefined
? rawData
: rawData.map(row => deepGet(conf[param.part].property, row))
);
};
// Build routes by combining data from all parameters
const routes = await params.reduce(async (total, param, col) => {
const foundRoutes = await total;
if (col === 0) {
return (await loadData(param)).map(r => [r]);
}
return await Promise.all(
foundRoutes.map(async (data) => {
const context = data.reduce((ctx, r, x) => {
return { ...ctx, [params[x].part]: r };
}, {});
const additionalRoutes = await loadData(param, context);
return additionalRoutes.map(r => [...data, r]);
})
).then(chunks => chunks.reduce((acc, cur) => acc.concat(cur)));
}, Promise.resolve([]));
return routes.map((routeData: string[]) => ({
route: createPath(...routeData),
type: conf.type,
}));
};
registerPlugin('router', 'json', jsonRoutePlugin);