import { stringify , StringifyOptions , parse as parseQueryString , parseUrl , } from 'query-string' ; import { EncodedQuery } from './types' ; /**
 * options passed to query-string stringify plus an
 * addition of transformSearchString: a function that takes
 * the result of stringify and runs a transformation on it.
 * (e.g. replacing all instances of character x with y)
 */ export type ExtendedStringifyOptions = StringifyOptions & { transformSearchString ? : ( searchString : string ) => string ; } ; /**
 * An example of a transformSearchString function that undoes encoding of
 * common JSON characters that are technically allowed in URLs.
 */ const JSON_SAFE_CHARS = `{}[],":` . split ( '' ) . map ( ( d ) => [ d , encodeURIComponent ( d ) ] ) ; export function transformSearchStringJsonSafe ( searchString ) { let str = searchString ; for ( let [ char , code ] of JSON_SAFE_CHARS ) { str = str . replace ( new RegExp ( '\\' + code , 'g' ) , char ) ; } return str ; } /**
 * Update a location, wiping out parameters not included in encodedQuery
 * If a param is set to undefined it will be removed from the URL.
 */ export function updateLocation ( encodedQuery , location , stringifyOptions ? ) { let encodedSearchString = stringify ( encodedQuery , stringifyOptions ) ; if ( stringifyOptions && stringifyOptions . transformSearchString ) { encodedSearchString = stringifyOptions . transformSearchString ( encodedSearchString ) ; } const search = encodedSearchString . length ? `?${ encodedSearchString }` : '' ; const href = parseUrl ( location . href || '' ) . url + search ; const newLocation = { ... location , key : `${ Date . now ( ) }` , href , search , query : encodedQuery , } ; return newLocation ; } /**
 * Update a location while retaining existing parameters.
 * If a param is set to undefined it will be removed from the URL.
 */ export function updateInLocation ( encodedQueryReplacements , location , stringifyOptions ? ) { const currQuery = parseQueryString ( location . search , { parseNumbers : false } ) as EncodedQuery ; const newQuery = { ... currQuery , ... encodedQueryReplacements , } ; return updateLocation ( newQuery , location , stringifyOptions ) ; }