All files / packages/tao-router/src routeHandler.js

6.45% Statements 2/31
0% Branches 0/17
0% Functions 0/8
6.67% Lines 2/30
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146          1x 1x                                                                                                                                                                                                                                                                                      
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;