parcoursup/node_modules/rawth/index.next.js

154 lines
4.9 KiB
JavaScript
Raw Normal View History

2023-03-05 13:23:23 +01:00
import {compile, pathToRegexp} from 'path-to-regexp'
import erre from 'erre'
// check whether the window object is defined
const isNode = typeof process !== 'undefined'
const isString = str => typeof str === 'string'
// the url parsing function depends on the platform, on node we rely on the 'url' module
/* istanbul ignore next */
const parseURL = (...args) => isNode ? require('url').parse(...args) : new URL(...args)
/**
* Replace the base path from a path
* @param {string} path - router path string
* @returns {string} path cleaned up without the base
*/
const replaceBase = path => path.replace(defaults.base, '')
/**
* Try to match the current path or skip it
* @param {RegEx} pathRegExp - target path transformed by pathToRegexp
* @returns {string|Symbol} if the path match we return it otherwise we cancel the stream
*/
const matchOrSkip = pathRegExp => path => match(path, pathRegExp) ? path : erre.cancel()
/**
* Combine 2 streams connecting the events of dispatcherStream to the receiverStream
* @param {Stream} dispatcherStream - main stream dispatching events
* @param {Stream} receiverStream - sub stream receiving events from the dispatcher
* @returns {Stream} receiverStream
*/
const joinStreams = (dispatcherStream, receiverStream) => {
dispatcherStream.on.value(receiverStream.push)
receiverStream.on.end(() => {
dispatcherStream.off.value(receiverStream.push)
})
return receiverStream
}
/**
* Error handling function
* @param {Error} error - error to catch
* @returns {void}
*/
const panic = error => {
if (defaults.silentErrors) return
throw new Error(error)
}
// make sure that the router will always receive strings params
export const filterStrings = str => isString(str) ? str : erre.cancel()
// create the streaming router
export const router = erre(filterStrings).on.error(panic) // cast the values of this stream always to string
/* @type {object} general configuration object */
export const defaults = {
// custom option
base: '',
silentErrors: false,
// pathToRegexp options
sensitive: false,
strict: false,
end: true,
start: true,
delimiter: '/#?',
encode: undefined,
endsWith: undefined,
prefixes: './'
}
/**
* Merge the user options with the defaults
* @param {Object} options - custom user options
* @returns {Object} options object merged with defaults
*/
export const mergeOptions = options => ({...defaults, ...options})
/* {@link https://github.com/pillarjs/path-to-regexp#usage} */
export const toRegexp = (path, keys, options) => pathToRegexp(path, keys, mergeOptions(options))
/**
* Convert a router entry to a real path computing the url parameters
* @param {string} path - router path string
* @param {Object} params - named matched parameters
* @param {Object} options - pathToRegexp options object
* @returns {string} computed url string
*/
export const toPath = (path, params, options) => compile(path, mergeOptions(options))(params)
/**
* Parse a string path generating an object containing
* @param {string} path - target path
* @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
* @param {Object} options - object containing the base path
* @returns {URL} url object enhanced with the `match` attribute
*/
export const toURL = (path, pathRegExp, options = {}) => {
const {base} = mergeOptions(options)
const [, ...params] = pathRegExp.exec(path)
const url = parseURL(path, base)
// extend the url object adding the matched params
url.params = params.reduce((acc, param, index) => {
const key = options.keys && options.keys[index]
if (key) acc[key.name] = param ? decodeURIComponent(param) : param
return acc
}, {})
return url
}
/**
* Return true if a path will be matched
* @param {string} path - target path
* @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
* @returns {boolean} true if the path matches the regexp
*/
export const match = (path, pathRegExp) => pathRegExp.test(path)
/**
* Factory function to create an sequence of functions to pass to erre.js
* This function will be used in the erre stream
* @param {RegExp} pathRegExp - path transformed to regexp via pathToRegexp
* @param {Object} options - pathToRegexp options object
* @returns {Array} a functions array that will be used as stream pipe for erre.js
*/
export const createURLStreamPipe = (pathRegExp, options) => [
decodeURI,
replaceBase,
matchOrSkip(pathRegExp, options),
path => toURL(path, pathRegExp, options)
]
/**
* Create a fork of the main router stream
* @param {string} path - route to match
* @param {Object} options - pathToRegexp options object
* @returns {Stream} new route stream
*/
export default function createRoute(path, options) {
const keys = []
const pathRegExp = pathToRegexp(path, keys, options)
const URLStream = erre(...createURLStreamPipe(pathRegExp, {
...options,
keys
}))
return joinStreams(router, URLStream).on.error(panic)
}