module Web.Minion.Examples.Json (app) where

import Data.Aeson (FromJSON (..), ToJSON (..), object, (.=))
import GHC.Generics
import Web.Minion

app :: ApplicationM IO
app :: ApplicationM IO
app = Router' Void Void IO -> ApplicationM IO
forall (m :: * -> *) i.
(MonadIO m, MonadCatch m) =>
Router' i Void m -> ApplicationM m
serve Router' Void Void IO
api

data FooRequest = FooRequest
  { FooRequest -> Int
foo :: Int
  , FooRequest -> Int
bar :: Int
  }
  deriving ((forall x. FooRequest -> Rep FooRequest x)
-> (forall x. Rep FooRequest x -> FooRequest) -> Generic FooRequest
forall x. Rep FooRequest x -> FooRequest
forall x. FooRequest -> Rep FooRequest x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. FooRequest -> Rep FooRequest x
from :: forall x. FooRequest -> Rep FooRequest x
$cto :: forall x. Rep FooRequest x -> FooRequest
to :: forall x. Rep FooRequest x -> FooRequest
Generic, Maybe FooRequest
Value -> Parser [FooRequest]
Value -> Parser FooRequest
(Value -> Parser FooRequest)
-> (Value -> Parser [FooRequest])
-> Maybe FooRequest
-> FromJSON FooRequest
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser FooRequest
parseJSON :: Value -> Parser FooRequest
$cparseJSONList :: Value -> Parser [FooRequest]
parseJSONList :: Value -> Parser [FooRequest]
$comittedField :: Maybe FooRequest
omittedField :: Maybe FooRequest
FromJSON)

data Response a = Success a | Failure Error

instance (ToJSON a) => ToJSON (Response a) where
  toJSON :: Response a -> Value
toJSON (Success a
a) = [Pair] -> Value
object [Key
"success" Key -> a -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= a
a]
  toJSON (Failure Error
a) = [Pair] -> Value
object [Key
"failure" Key -> Error -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Error
a]

data Error = Error
  { Error -> String
code :: String
  , Error -> String
message :: String
  }
  deriving ((forall x. Error -> Rep Error x)
-> (forall x. Rep Error x -> Error) -> Generic Error
forall x. Rep Error x -> Error
forall x. Error -> Rep Error x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Error -> Rep Error x
from :: forall x. Error -> Rep Error x
$cto :: forall x. Rep Error x -> Error
to :: forall x. Rep Error x -> Error
Generic, [Error] -> Value
[Error] -> Encoding
Error -> Bool
Error -> Value
Error -> Encoding
(Error -> Value)
-> (Error -> Encoding)
-> ([Error] -> Value)
-> ([Error] -> Encoding)
-> (Error -> Bool)
-> ToJSON Error
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: Error -> Value
toJSON :: Error -> Value
$ctoEncoding :: Error -> Encoding
toEncoding :: Error -> Encoding
$ctoJSONList :: [Error] -> Value
toJSONList :: [Error] -> Value
$ctoEncodingList :: [Error] -> Encoding
toEncodingList :: [Error] -> Encoding
$comitField :: Error -> Bool
omitField :: Error -> Bool
ToJSON)

data FooResponse = FooResponse
  { FooResponse -> Int
baz :: Int
  , FooResponse -> Int
qux :: Int
  }
  deriving ((forall x. FooResponse -> Rep FooResponse x)
-> (forall x. Rep FooResponse x -> FooResponse)
-> Generic FooResponse
forall x. Rep FooResponse x -> FooResponse
forall x. FooResponse -> Rep FooResponse x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. FooResponse -> Rep FooResponse x
from :: forall x. FooResponse -> Rep FooResponse x
$cto :: forall x. Rep FooResponse x -> FooResponse
to :: forall x. Rep FooResponse x -> FooResponse
Generic, [FooResponse] -> Value
[FooResponse] -> Encoding
FooResponse -> Bool
FooResponse -> Value
FooResponse -> Encoding
(FooResponse -> Value)
-> (FooResponse -> Encoding)
-> ([FooResponse] -> Value)
-> ([FooResponse] -> Encoding)
-> (FooResponse -> Bool)
-> ToJSON FooResponse
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: FooResponse -> Value
toJSON :: FooResponse -> Value
$ctoEncoding :: FooResponse -> Encoding
toEncoding :: FooResponse -> Encoding
$ctoJSONList :: [FooResponse] -> Value
toJSONList :: [FooResponse] -> Value
$ctoEncodingList :: [FooResponse] -> Encoding
toEncodingList :: [FooResponse] -> Encoding
$comitField :: FooResponse -> Bool
omitField :: FooResponse -> Bool
ToJSON)

api :: Router Void IO
api :: Router' Void Void IO
api = Router' Void Void IO -> Router' Void Void IO
"api" (Router' Void Void IO -> Router' Void Void IO)
-> Router' Void Void IO -> Router' Void Void IO
forall i ts (r :: * -> *).
(Router' i ts r -> Router' i ts r)
-> Router' i ts r -> Router' i ts r
/> Router' Void Void IO -> Router' Void Void IO
"json" (Router' Void Void IO -> Router' Void Void IO)
-> Router' Void Void IO -> Router' Void Void IO
forall i ts (r :: * -> *).
(Router' i ts r -> Router' i ts r)
-> Router' i ts r -> Router' i ts r
/> forall r (m :: * -> *) i ts.
(Introspection i 'Request (ReqBody '[Json] r), FromJSON r,
 MonadIO m, MonadThrow m) =>
ValueCombinator i (WithReq m (ReqBody '[Json] r)) ts m
reqJson @FooRequest ValueCombinator
  Void (WithReq IO (ReqBody '[Json] FooRequest)) Void IO
-> ValueCombinator
     Void (WithReq IO (ReqBody '[Json] FooRequest)) Void IO
forall i ts' (r :: * -> *) ts.
(Router' i ts' r -> Router' i ts r)
-> Router' i ts' r -> Router' i ts r
.> forall o (m :: * -> *) ts i (st :: [*]).
(HandleArgs ts st m, ToJSON o, MonadIO m,
 Introspection i 'Response (RespBody '[Json] o)) =>
Method -> (DelayedArgs st ~> m o) -> Router' i ts m
handleJson @(Response FooResponse) Method
POST DelayedArgs '[WithReq IO (ReqBody '[Json] FooRequest)]
~> IO (Response FooResponse)
FooRequest -> IO (Response FooResponse)
forall {f :: * -> *}.
Applicative f =>
FooRequest -> f (Response FooResponse)
endpoint
 where
  endpoint :: FooRequest -> f (Response FooResponse)
endpoint FooRequest{Int
$sel:foo:FooRequest :: FooRequest -> Int
$sel:bar:FooRequest :: FooRequest -> Int
foo :: Int
bar :: Int
..} = Response FooResponse -> f (Response FooResponse)
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure do
    if Int
foo Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
bar Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
      then Error -> Response FooResponse
forall a. Error -> Response a
Failure (String -> String -> Error
Error String
"you_died" String
"That's life")
      else FooResponse -> Response FooResponse
forall a. a -> Response a
Success (Int -> Int -> FooResponse
FooResponse Int
bar Int
foo)