{-# Language EmptyDataDecls #-} module Uri where import FFI import Prelude -- | Creation and conversion -- Choose to make Uri an opaque data type. If the accessors on the -- jsUri objects were properties and not functions we could have -- defined Uri as a record instead. data Uri -- To make Google Closure play nice we use [] instead of . for accessing properties. currentUri :: Fay String currentUri = ffi "window['location']['href']" -- This assumes that Uri is defined globally, which it is by default. newUri :: String -> Uri newUri = ffi "new window['Uri'](%1)" toString :: Uri -> String toString = ffi "%1['toString']()" -- If we ever want to pass a Uri back to JS we need to make sure we keep persistance internally. clone :: Uri -> Uri clone = ffi "%1['clone']()" -- | Getters -- All getters (except query! But lets be consistent) may return null if the value isn't set so we use -- Language.FFI.Nullable here which converts null -> Null and String -> Nullable String. -- Nullable is distinguished from Maybe to not break haskell compatibility. -- If we want to decode null into Nullable (Nullable a) there is no way of -- knowing if Null or Nullable Null is correct. This problem does not exist when -- working with Maybe values in client server communication. protocol :: Uri -> Nullable String protocol = ffi "%1['protocol']()" userInfo :: Uri -> Nullable String userInfo = ffi "%1['userInfo']()" host :: Uri -> Nullable String host = ffi "%1['host']()" port :: Uri -> Nullable String port = ffi "%1['port']()" path :: Uri -> Nullable String path = ffi "%1['path']()" query :: Uri -> Nullable String query = ffi "%1['query']()" anchor :: Uri -> Nullable String anchor = ffi "%1['anchor']()" -- | Other getters queryParamValue :: String -> Uri -> String queryParamValue = ffi "%2['getQueryParamValue'](%1)" queryParamValues :: String -> Uri -> [String] queryParamValues = ffi "%2['getQueryParamValues'](%1)" -- | Setters -- We could use Nullable here to combine the with* and remove* functions -- but usage would be more verbose that way. -- JsUri has clone() conveniently defined so we use it to get -- persistence, otherwise our types would be `-> Fay Uri` which is of -- course worse. withProtocol :: String -> Uri -> Uri withProtocol = ffi "%2['clone']()['setProtocol'](%1)" withUserInfo :: String -> Uri -> Uri withUserInfo = ffi "%2['clone']()['setUserInfo'](%1)" withHost :: String -> Uri -> Uri withHost = ffi "%2['clone']()['setHost'](%1)" withPort :: String -> Uri -> Uri withPort = ffi "%2['clone']()['setPort'](%1)" withPath :: String -> Uri -> Uri withPath = ffi "%2['clone']()['setPath'](%1)" withQuery :: String -> Uri -> Uri withQuery = ffi "%2['clone']()['setQuery'](%1)" withAnchor :: String -> Uri -> Uri withAnchor = ffi "%2['clone']()['setAnchor'](%1)" -- | Removals removeProtocol :: Uri -> Uri removeProtocol = ffi "%1['clone']()['setProtocol'](null)" removeUserInfo :: Uri -> Uri removeUserInfo = ffi "%1['clone']()['setUserInfo'](null)" removeHost :: Uri -> Uri removeHost = ffi "%1['clone']()['setHost'](null)" removePort :: Uri -> Uri removePort = ffi "%1['clone']()['setPort'](null)" removePath :: Uri -> Uri removePath = ffi "%1['clone']()['setPath'](null)" removeQuery :: Uri -> Uri removeQuery = ffi "%1['clone']()['setQuery'](null)" removeAnchor :: Uri -> Uri removeAnchor = ffi "%1['clone']()['setAnchor'](null)" -- | Other setters addQueryParam :: String -> String -> Uri -> Uri addQueryParam = ffi "%3['clone']()['addQueryParam'](%1,%2)" replaceQueryParam :: String -> String -> Uri -> Uri replaceQueryParam = ffi "%3['clone']()['replaceQueryParam'](%1,%2)" -- The order of the arguments differ from the jsUri api, it is now -- key -> oldValue -> newValue -> Uri -> Uri replaceQueryParamValue :: String -> String -> String -> Uri -> Uri replaceQueryParamValue = ffi "%4['clone']()['replaceQueryParam'](%1, %3, %2)" deleteQueryParam :: String -> Uri -> Uri deleteQueryParam = ffi "%2['clone']()['deleteQueryParam'](%1)" deleteQueryParamValue :: String -> String -> Uri -> Uri deleteQueryParamValue = ffi "%3['clone']()['deleteQueryParam'](%1,%2)"