{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Polytropos.OpenApi
(
AllToSchema (..)
, AllCtorsToSchema (..)
) where
import Control.Lens ((&), (.~), (?~))
import Data.Proxy (Proxy (..))
import Data.Typeable (Typeable)
import Data.Text (Text)
import qualified Data.Text as T
import GHC.TypeLits (KnownSymbol, symbolVal)
import Data.OpenApi
import Data.OpenApi.Declare (Declare)
import qualified Data.HashMap.Strict.InsOrd.Compat as IOHM
import Polytropos (Record, Variant)
import Polytropos.Core (Pair (..), Row, SumRow)
class AllToSchema (r :: Row) where
fieldSchemas :: Proxy r -> Declare (Definitions Schema) [(Text, Referenced Schema)]
instance AllToSchema '[] where
fieldSchemas :: Proxy '[]
-> Declare (Definitions Schema) [(Text, Referenced Schema)]
fieldSchemas Proxy '[]
_ = [(Text, Referenced Schema)]
-> Declare (Definitions Schema) [(Text, Referenced Schema)]
forall a. a -> DeclareT (Definitions Schema) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
instance (KnownSymbol n, ToSchema a, AllToSchema r)
=> AllToSchema ((n ':= a) ': r) where
fieldSchemas :: Proxy ((n ':= a) : r)
-> Declare (Definitions Schema) [(Text, Referenced Schema)]
fieldSchemas Proxy ((n ':= a) : r)
_ = do
s <- Proxy a -> Declare (Definitions Schema) (Referenced Schema)
forall a.
ToSchema a =>
Proxy a -> Declare (Definitions Schema) (Referenced Schema)
declareSchemaRef (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @a)
ss <- fieldSchemas (Proxy @r)
pure ((T.pack (symbolVal (Proxy @n)), s) : ss)
class AllCtorsToSchema (s :: SumRow) where
ctorSchemas :: Proxy s -> Declare (Definitions Schema) [Schema]
instance AllCtorsToSchema '[] where
ctorSchemas :: Proxy '[] -> Declare (Definitions Schema) [Schema]
ctorSchemas Proxy '[]
_ = [Schema] -> Declare (Definitions Schema) [Schema]
forall a. a -> DeclareT (Definitions Schema) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
instance (KnownSymbol c, AllToSchema fs, AllCtorsToSchema s)
=> AllCtorsToSchema ((c ':= fs) ': s) where
ctorSchemas :: Proxy ((c ':= fs) : s) -> Declare (Definitions Schema) [Schema]
ctorSchemas Proxy ((c ':= fs) : s)
_ = do
fields <- Proxy fs
-> Declare (Definitions Schema) [(Text, Referenced Schema)]
forall (r :: Row).
AllToSchema r =>
Proxy r -> Declare (Definitions Schema) [(Text, Referenced Schema)]
fieldSchemas (forall (t :: Row). Proxy t
forall {k} (t :: k). Proxy t
Proxy @fs)
let fieldsObj = Schema
forall a. Monoid a => a
mempty
Schema -> (Schema -> Schema) -> Schema
forall a b. a -> (a -> b) -> b
& (Maybe OpenApiType -> Identity (Maybe OpenApiType))
-> Schema -> Identity Schema
forall s a. HasType s a => Lens' s a
Lens' Schema (Maybe OpenApiType)
type_ ((Maybe OpenApiType -> Identity (Maybe OpenApiType))
-> Schema -> Identity Schema)
-> OpenApiType -> Schema -> Schema
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ OpenApiType
OpenApiObject
Schema -> (Schema -> Schema) -> Schema
forall a b. a -> (a -> b) -> b
& (InsOrdHashMap Text (Referenced Schema)
-> Identity (InsOrdHashMap Text (Referenced Schema)))
-> Schema -> Identity Schema
forall s a. HasProperties s a => Lens' s a
Lens' Schema (InsOrdHashMap Text (Referenced Schema))
properties ((InsOrdHashMap Text (Referenced Schema)
-> Identity (InsOrdHashMap Text (Referenced Schema)))
-> Schema -> Identity Schema)
-> InsOrdHashMap Text (Referenced Schema) -> Schema -> Schema
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [(Text, Referenced Schema)]
-> InsOrdHashMap Text (Referenced Schema)
forall k v. Hashable k => [(k, v)] -> InsOrdHashMap k v
IOHM.fromList [(Text, Referenced Schema)]
fields
Schema -> (Schema -> Schema) -> Schema
forall a b. a -> (a -> b) -> b
& ([Text] -> Identity [Text]) -> Schema -> Identity Schema
forall s a. HasRequired s a => Lens' s a
Lens' Schema [Text]
required (([Text] -> Identity [Text]) -> Schema -> Identity Schema)
-> [Text] -> Schema -> Schema
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ((Text, Referenced Schema) -> Text)
-> [(Text, Referenced Schema)] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text, Referenced Schema) -> Text
forall a b. (a, b) -> a
fst [(Text, Referenced Schema)]
fields
tagged = Schema
forall a. Monoid a => a
mempty
Schema -> (Schema -> Schema) -> Schema
forall a b. a -> (a -> b) -> b
& (Maybe OpenApiType -> Identity (Maybe OpenApiType))
-> Schema -> Identity Schema
forall s a. HasType s a => Lens' s a
Lens' Schema (Maybe OpenApiType)
type_ ((Maybe OpenApiType -> Identity (Maybe OpenApiType))
-> Schema -> Identity Schema)
-> OpenApiType -> Schema -> Schema
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ OpenApiType
OpenApiObject
Schema -> (Schema -> Schema) -> Schema
forall a b. a -> (a -> b) -> b
& (InsOrdHashMap Text (Referenced Schema)
-> Identity (InsOrdHashMap Text (Referenced Schema)))
-> Schema -> Identity Schema
forall s a. HasProperties s a => Lens' s a
Lens' Schema (InsOrdHashMap Text (Referenced Schema))
properties ((InsOrdHashMap Text (Referenced Schema)
-> Identity (InsOrdHashMap Text (Referenced Schema)))
-> Schema -> Identity Schema)
-> InsOrdHashMap Text (Referenced Schema) -> Schema -> Schema
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [(Text, Referenced Schema)]
-> InsOrdHashMap Text (Referenced Schema)
forall k v. Hashable k => [(k, v)] -> InsOrdHashMap k v
IOHM.fromList [(String -> Text
T.pack (Proxy c -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @c)), Schema -> Referenced Schema
forall a. a -> Referenced a
Inline Schema
fieldsObj)]
Schema -> (Schema -> Schema) -> Schema
forall a b. a -> (a -> b) -> b
& ([Text] -> Identity [Text]) -> Schema -> Identity Schema
forall s a. HasRequired s a => Lens' s a
Lens' Schema [Text]
required (([Text] -> Identity [Text]) -> Schema -> Identity Schema)
-> [Text] -> Schema -> Schema
forall s t a b. ASetter s t a b -> b -> s -> t
.~ [String -> Text
T.pack (Proxy c -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @c))]
(tagged :) <$> ctorSchemas (Proxy @s)
instance (Typeable r, AllToSchema r) => ToSchema (Record r) where
declareNamedSchema :: Proxy (Record r) -> Declare (Definitions Schema) NamedSchema
declareNamedSchema Proxy (Record r)
_ = do
fields <- Proxy r -> Declare (Definitions Schema) [(Text, Referenced Schema)]
forall (r :: Row).
AllToSchema r =>
Proxy r -> Declare (Definitions Schema) [(Text, Referenced Schema)]
fieldSchemas (forall (t :: Row). Proxy t
forall {k} (t :: k). Proxy t
Proxy @r)
pure $ NamedSchema Nothing $ mempty
& type_ ?~ OpenApiObject
& properties .~ IOHM.fromList fields
& required .~ map fst fields
instance (Typeable s, AllCtorsToSchema s) => ToSchema (Variant s) where
declareNamedSchema :: Proxy (Variant s) -> Declare (Definitions Schema) NamedSchema
declareNamedSchema Proxy (Variant s)
_ = do
ctors <- Proxy s -> Declare (Definitions Schema) [Schema]
forall (s :: SumRow).
AllCtorsToSchema s =>
Proxy s -> Declare (Definitions Schema) [Schema]
ctorSchemas (forall (t :: SumRow). Proxy t
forall {k} (t :: k). Proxy t
Proxy @s)
pure $ NamedSchema Nothing $ mempty
& oneOf ?~ map Inline ctors