module Database.PostgreSQL.Simple.URL (parseDatabaseUrl, uriToConnectInfo) where
import Control.Applicative
import Data.List.Split
import Database.PostgreSQL.Simple
import Network.URI
import Prelude
parseDatabaseUrl :: String -> Maybe ConnectInfo
parseDatabaseUrl :: String -> Maybe ConnectInfo
parseDatabaseUrl String
databaseUrl = String -> Maybe URI
parseURI String
databaseUrl Maybe URI -> (URI -> Maybe ConnectInfo) -> Maybe ConnectInfo
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= URI -> Maybe ConnectInfo
uriToConnectInfo
uriToConnectInfo :: URI -> Maybe ConnectInfo
uriToConnectInfo :: URI -> Maybe ConnectInfo
uriToConnectInfo URI
uri
| URI -> String
uriScheme URI
uri String -> String -> Bool
forall a. Eq a => a -> a -> Bool
/= String
"postgres:" Bool -> Bool -> Bool
&& URI -> String
uriScheme URI
uri String -> String -> Bool
forall a. Eq a => a -> a -> Bool
/= String
"postgresql:" = Maybe ConnectInfo
forall a. Maybe a
Nothing
| Bool
otherwise = ((ConnectInfo -> ConnectInfo) -> ConnectInfo -> ConnectInfo
forall a b. (a -> b) -> a -> b
$ ConnectInfo
defaultConnectInfo) ((ConnectInfo -> ConnectInfo) -> ConnectInfo)
-> Maybe (ConnectInfo -> ConnectInfo) -> Maybe ConnectInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> URI -> Maybe (ConnectInfo -> ConnectInfo)
mkConnectInfo URI
uri
type ConnectInfoChange = ConnectInfo -> ConnectInfo
mkConnectInfo :: URI -> Maybe ConnectInfoChange
mkConnectInfo :: URI -> Maybe (ConnectInfo -> ConnectInfo)
mkConnectInfo URI
uri = case URI -> String
uriPath URI
uri of
(Char
'/' : String
rest) | Bool -> Bool
not (String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
rest) -> (ConnectInfo -> ConnectInfo) -> Maybe (ConnectInfo -> ConnectInfo)
forall a. a -> Maybe a
Just ((ConnectInfo -> ConnectInfo)
-> Maybe (ConnectInfo -> ConnectInfo))
-> (ConnectInfo -> ConnectInfo)
-> Maybe (ConnectInfo -> ConnectInfo)
forall a b. (a -> b) -> a -> b
$ URI -> ConnectInfo -> ConnectInfo
uriParameters URI
uri
String
_ -> Maybe (ConnectInfo -> ConnectInfo)
forall a. Maybe a
Nothing
uriParameters :: URI -> ConnectInfoChange
uriParameters :: URI -> ConnectInfo -> ConnectInfo
uriParameters URI
uri = (\ConnectInfo
info -> ConnectInfo
info { connectDatabase = tail $ uriPath uri }) (ConnectInfo -> ConnectInfo)
-> (ConnectInfo -> ConnectInfo) -> ConnectInfo -> ConnectInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ConnectInfo -> ConnectInfo)
-> (URIAuth -> ConnectInfo -> ConnectInfo)
-> Maybe URIAuth
-> ConnectInfo
-> ConnectInfo
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ConnectInfo -> ConnectInfo
forall a. a -> a
id URIAuth -> ConnectInfo -> ConnectInfo
uriAuthParameters (URI -> Maybe URIAuth
uriAuthority URI
uri)
dropLast :: [a] -> [a]
dropLast :: forall a. [a] -> [a]
dropLast [] = []
dropLast [a
_] = []
dropLast (a
x:[a]
xs) = a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> [a]
forall a. [a] -> [a]
dropLast [a]
xs
uriAuthParameters :: URIAuth -> ConnectInfoChange
uriAuthParameters :: URIAuth -> ConnectInfo -> ConnectInfo
uriAuthParameters URIAuth
uriAuth = ConnectInfo -> ConnectInfo
port (ConnectInfo -> ConnectInfo)
-> (ConnectInfo -> ConnectInfo) -> ConnectInfo -> ConnectInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnectInfo -> ConnectInfo
host (ConnectInfo -> ConnectInfo)
-> (ConnectInfo -> ConnectInfo) -> ConnectInfo -> ConnectInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnectInfo -> ConnectInfo
auth
where port :: ConnectInfo -> ConnectInfo
port = case URIAuth -> String
uriPort URIAuth
uriAuth of
(Char
':' : String
p) -> \ConnectInfo
info -> ConnectInfo
info { connectPort = read p }
String
_ -> ConnectInfo -> ConnectInfo
forall a. a -> a
id
host :: ConnectInfo -> ConnectInfo
host = case URIAuth -> String
uriRegName URIAuth
uriAuth of
String
h -> \ConnectInfo
info -> ConnectInfo
info { connectHost = h }
auth :: ConnectInfo -> ConnectInfo
auth = case String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn String
":" (URIAuth -> String
uriUserInfo URIAuth
uriAuth) of
[String
""] -> ConnectInfo -> ConnectInfo
forall a. a -> a
id
[String
u] -> \ConnectInfo
info -> ConnectInfo
info { connectUser = dropLast u }
[String
u, String
p] -> \ConnectInfo
info -> ConnectInfo
info { connectUser = u, connectPassword = dropLast p }
[String]
_ -> ConnectInfo -> ConnectInfo
forall a. a -> a
id