import pathToRegexp from 'path-to-regexp';
import get from 'get-value';
import { AppCtx } from '@tao.js/core';
const PATH_VAR_RE = /(\{([\w|\.]+)(\(.+\))?\})/m;
const DOT_REPLACER = '__0__';
// const ISM_MAP = {
// t: 'term',
// a: 'action',
// o: 'orient'
// };
// takes a path definition and provides:
// 1. a function that turns trigram into a path to push onto history
// 2. a function that receives a url and converts it to a trigram to set onto the TAO
export function deconstructPath(origPath) {
return origPath.split('/').map((p, i) => {
const match = PATH_VAR_RE.exec(p);
return {
part: p,
idx: i,
use: !match
? p
: p.replace(
match[1],
match[1]
.replace(/\./g, DOT_REPLACER)
.replace('{', ':')
.replace('}', '')
),
match: match
};
});
}
// convert path to usable path for path-to-regexp
export function convertPath(deconstruction) {
return deconstruction.map(p => p.use).join('/');
}
// function pathFlattenData(tao, data) {
// const pathData = { ...tao };
// for (let ism in tao) {
// const trigram = tao[ism];
// const taoism = ISM_MAP[ism];
// if (data[trigram] == null) {
// continue;
// }
// if (typeof data[trigram] !== 'object') {
// pathData[trigram] = data[trigram];
// pathData[taoism] = data[trigram];
// continue;
// }
// if (data[trigram] instanceof Array) {
// continue;
// }
// for (let prop in data[trigram]) {
// if (data[trigram][prop] == null) {
// continue;
// }
// const propData = data[trigram][prop];
// const propType = typeof propData;
// if (propType === 'object') {
// if (propData instanceof Array) {
// continue;
// }
// for (let subProp in propData) {
// const subPropData = propData[subProp];
// const subPropType = typeof subPropData;
// if (
// subPropData == null ||
// subPropType === 'object' ||
// subPropType === 'function'
// ) {
// continue;
// }
// pathData[
// `${trigram}${DOT_REPLACER}${prop}${DOT_REPLACER}${subPropData}`
// ] = propData;
// pathData[
// `${taoism}${DOT_REPLACER}${prop}${DOT_REPLACER}${subPropData}`
// ] = propData;
// }
// } else if (propType !== 'function') {
// pathData[`${trigram}${DOT_REPLACER}${prop}`] = propData;
// pathData[`${taoism}${DOT_REPLACER}${prop}`] = propData;
// }
// }
// }
// return pathData;
// }
function pathDataGet(tao, data, deconstructedPath) {
const allData = {
...tao,
...data,
term: data[tao.t],
action: data[tao.a],
orient: data[tao.o]
};
// console.log('pathDataGet::allData:', allData);
return deconstructedPath.reduce((pathData, item) => {
if (!item.match) {
// console.log('!item.match:', item);
return pathData;
}
const getDataFrom = item.match[2];
const needData = get(allData, getDataFrom);
// console.log('pathDataGet:', { getDataFrom, needData });
if (needData == null) {
return pathData;
}
pathData[item.use.substring(1)] = needData;
return pathData;
}, {});
}
function makeRouteHandler(history, route, debug = false) {
let pathString = route.path || route;
const deconstructedPath = deconstructPath(pathString);
const usablePath = convertPath(deconstructedPath);
const toPath = pathToRegexp.compile(usablePath);
return (tao, data) => {
debug && console.log('routeHandler::called with', { tao, data });
// const pathData = pathFlattenData(tao, data);
const pathData = pathDataGet(tao, data, deconstructedPath);
debug && console.log('routeHandler::pathData', pathData);
let routeValue = toPath(pathData);
if (route.lowerCase) {
routeValue = routeValue.toLowerCase();
}
if (history.location.pathname !== routeValue) {
history.push(routeValue);
return new AppCtx('Route', 'Set', tao.o, {
Route: route,
Set: routeValue
});
}
};
}
export default makeRouteHandler;
|