import * as Serialize from "typescript-dotnet-core/Serialization/Utility" ; import UriComponent from "./UriComponent" ; import QueryParam from "./QueryParam" ; import Type from "typescript-dotnet-core/Types" ; import { extractKeyValue } from "typescript-dotnet-core/KeyValueExtract" ; import { forEach , isFiniteEnumerableOrArrayLike } from "typescript-dotnet-core/Collections/Enumeration/Enumerator" ; import IMap from "typescript-dotnet-core/IMap" ; import Primitive from "typescript-dotnet-core/Primitive" ; import { StringKeyValuePair } from "typescript-dotnet-core/KeyValuePair" ; import FiniteEnumerableOrArrayLike from "typescript-dotnet-core/Collections/FiniteEnumerableOrArrayLike" ; const EMPTY = "" , QUERY_SEPARATOR = "?" , ENTRY_SEPARATOR = "&" , KEY_VALUE_SEPARATOR = "=" , TO_URI_COMPONENT = "toUriComponent" ; param values param prefixIfNotEmpty returns { string } export function encode ( values , prefixIfNotEmpty ? ) { if ( ! values ) return EMPTY ; const entries = [ ] ; if ( isFiniteEnumerableOrArrayLike ( values ) ) { forEach ( values , entry => extractKeyValue ( entry , ( key , value ) => appendKeyValue ( entries , key , value ) ) ) ; } else { Object . keys ( values ) . forEach ( key => appendKeyValue ( entries , key , values [ key ] ) ) ; } return ( entries . length && prefixIfNotEmpty ? QUERY_SEPARATOR : EMPTY ) + entries . join ( ENTRY_SEPARATOR ) ; } function appendKeyValueSingle ( entries , key , value ) { entries . push ( key + KEY_VALUE_SEPARATOR + encodeValue ( value ) ) ; } function appendKeyValue ( entries , key , value ) { if ( isFiniteEnumerableOrArrayLike ( value ) ) { forEach ( value , v => appendKeyValueSingle ( entries , key , v ) ) ; } else { appendKeyValueSingle ( entries , key , value ) ; } } param value returns { string } export function encodeValue ( value ) { if ( isUriComponentFormattable ( value ) ) { const v = value . toUriComponent ( ) ; if ( v && v . indexOf ( ENTRY_SEPARATOR ) != 1 ) throw '.toUriComponent() did not encode the value.' ; return v ; } else { return encodeURIComponent ( Serialize . toString ( value ) ) ; } } param instance returns { boolean } export function isUriComponentFormattable ( instance ) { return Type . hasMemberOfType < UriComponent . Formattable > ( instance , TO_URI_COMPONENT , Type . FUNCTION ) ; } param query param entryHandler param deserialize param decodeValues export function parse ( query , entryHandler , deserialize = true , decodeValues = true ) { if ( query && ( query = query . replace ( /^\s*\?+/ , '' ) ) ) { const entries = query . split ( ENTRY_SEPARATOR ) ; for ( let entry of entries ) { const si = entry . indexOf ( KEY_VALUE_SEPARATOR ) ; if ( si != - 1 ) { let key = entry . substring ( 0 , si ) ; let value = < any > entry . substring ( si + 1 ) ; if ( decodeValues ) value = decodeURIComponent ( value ) ; if ( deserialize ) value = Serialize . toPrimitive ( value ) ; entryHandler ( key , value ) ; } } } } param query param deserialize param decodeValues returns { IMap < Primitive > } export function parseToMap ( query , deserialize = true , decodeValues = true ) { const result = { } ; parse ( query , ( key , value ) => { if ( ( key ) in ( result ) ) { let prev = result [ key ] ; if ( ! ( ( prev ) instanceof ( Array ) ) ) result [ key ] = prev = [ prev ] ; prev . push ( value ) ; } else result [ key ] = value ; } , deserialize , decodeValues ) ; return result ; } param query param deserialize param decodeValues returns { StringKeyValuePair < string , Primitive > [ ] } export function parseToArray ( query , deserialize = true , decodeValues = true ) { const result = [ ] ; parse ( query , ( key , value ) => { result . push ( { key : key , value : value } ) ; } , deserialize , decodeValues ) ; return result ; } export module Separator { export const Query = QUERY_SEPARATOR ; export const Entry = ENTRY_SEPARATOR ; export const KeyValue = KEY_VALUE_SEPARATOR ; } Object . freeze ( Separator ) ;