All files index.js

91.67% Statements 33/36
68.75% Branches 22/32
100% Functions 4/4
96.97% Lines 32/33
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                                                    1x 1x 1x   1x       5x 5x 5x   5x   5x 5x 5x   5x 5x 5x     5x     1x   1x 2x 2x 2x     1x       4x       4x 4x 4x   4x   2x 2x   2x   2x         2x 2x            
// @flow
import pathToRegexp from 'path-to-regexp'
 
type CompileOptions = {
  end?: boolean,
  strict?: boolean
}
 
type MatchOptions = {
  exact?: boolean,
  strict?: boolean,
  path?: string
}
 
type Compiled = {
  re: RegExp,
  keys: Array<{ name: string }>
}
 
type Match = {
  path: string,
  url: string,
  isExact: boolean,
  params: Object
}
 
const patternCache = {}
const cacheLimit = 10000
let cacheCount = 0
 
export const compilePath = (
  pattern: string,
  options: CompileOptions = {}
): Compiled => {
  const { end = true, strict = false } = options
  const cacheKey = `${end ? 't' : 'f'}${strict ? 't' : 'f'}`
  const cache = patternCache[cacheKey] || (patternCache[cacheKey] = {})
 
  Iif (cache[pattern]) return cache[pattern]
 
  const keys = []
  const re = pathToRegexp(pattern, keys, options)
  const compiledPattern = { re, keys }
 
  Eif (cacheCount < cacheLimit) {
    cache[pattern] = compiledPattern
    cacheCount++
  }
 
  return compiledPattern
}
 
const toPathCache = {}
 
export const compileParamsToPath = (path: string, params: Object = {}) => {
  const toPath = toPathCache[path] || pathToRegexp.compile(path)
  toPathCache[path] = toPath
  return toPath(params)
}
 
const matchPath = (
  pathname: string,
  options: string | MatchOptions = {}
): ?Match => {
  Iif (typeof options === 'string') {
    options = { path: options, exact: false, strict: false }
  }
 
  const { path = '/', exact = false, strict = false } = options
  const { re, keys } = compilePath(path, { end: exact, strict })
  const match = re.exec(pathname)
 
  if (!match) return null
 
  const [url, ...values] = match
  const isExact = pathname === url
 
  Iif (exact && !isExact) return null
 
  return {
    path, // the path pattern used to match
    url: path === '/' && url === '' ? '/' : url, // the matched portion of the URL
    isExact, // whether or not we matched exactly
    params: keys.reduce((memo, key, index) => {
      memo[key.name] = values[index]
      return memo
    }, {})
  }
}
 
export default matchPath