Skip to content

Commit

Permalink
Merge pull request #46 from anton-k/th-derving-request-inputs
Browse files Browse the repository at this point in the history
Th derving request inputs
  • Loading branch information
anton-k authored Oct 21, 2023
2 parents b241624 + ab793a6 commit 75b7a26
Show file tree
Hide file tree
Showing 10 changed files with 579 additions and 201 deletions.
41 changes: 41 additions & 0 deletions docs/src/09-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,44 @@ getRespOrValue :: RespOr media BL.ByteString a -> Either BL.ByteString a

To unwrap `Resp` from response.

## Other utils

### deriving helpers

Sometimes we need to derive too many types at once
to use the type in the library. There are helpers to reduce deriving boiler-plate:


```haskell
deriveParam ''FooType -- derives parameter instances for a FooType
deriveNewtypeParam ''FooType -- derives parameter instances for a newtype FooType

deriveBody ''FooType -- derives request body instances for a FooType
deriveNewtypeBody ''FooType -- derives request body instances for a newtype FooType

deriveHttp ''FooType -- derives both parameter and request body instances for a FooType
deriveNewtypeHttp ''FooType -- derives both parameterrequest body instances for a newtype FooType

mapDerive fun [''Foo, ''Bar] -- maps deriving over several types
```
We need to activate `TemplateHaskell`, `StandaloneDeriving`, `DerivingStrategies`, `DeriveGeneric` extensions to use it.

Also note that for this to work all types should be in scope.
So it better to define derivings at the bottom of the module which is dedicated to types.

Also type should not have generic arguments for deriving to work.
If it does we have to declare the types manyally. For example:

```haskell
data Timed a = Timed
{ from :: Day
, content :: [a]
}
deriving (Generic, ToJSON, FromJSON)

deriving instance (ToSchema a) => ToSchema (Timed a)
```

The data type `Timed` has an argument and we have to define the instance
explicitly.

12 changes: 7 additions & 5 deletions examples/mig-example-apps/Html/src/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ module Types (
SubmitBlogPost (..),
) where

import Data.Aeson (FromJSON)
import Data.Text (Text)
import Data.Time
import Data.UUID
import GHC.Generics
import Mig (FromForm, FromHttpApiData, ToHttpApiData, ToParamSchema, ToSchema)
import Mig (deriveForm, deriveNewtypeParam, mapDerive)

-- | Web-page for our site
newtype Page a = Page a
Expand All @@ -32,7 +30,6 @@ newtype ListPosts = ListPosts [BlogPost]

-- | Blog post id
newtype BlogPostId = BlogPostId {unBlogPostId :: UUID}
deriving newtype (FromHttpApiData, ToHttpApiData, Eq, Show, FromJSON, ToParamSchema)

data BlogPostView
= ViewBlogPost BlogPost
Expand All @@ -57,4 +54,9 @@ data SubmitBlogPost = SubmitBlogPost
{ title :: Text
, content :: Text
}
deriving (Generic, FromForm, ToSchema)

--------------------------------------------
-- derivings

mapDerive deriveNewtypeParam [''BlogPostId]
deriveForm ''SubmitBlogPost
11 changes: 5 additions & 6 deletions examples/mig-example-apps/JsonApi/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,12 @@ data User = User
{ name :: Text
, pass :: Text
}
deriving (Generic, ToJSON, FromJSON, ToSchema)

newtype AuthToken = AuthToken Text
deriving newtype (ToJSON, FromJSON, FromHttpApiData, Eq, Ord, Show, ToParamSchema, ToSchema)

-- weather domain

newtype DayInterval = DayInterval Int
deriving newtype (ToJSON, FromJSON, FromHttpApiData, ToParamSchema)

data Timed a = Timed
{ from :: Day
Expand All @@ -43,20 +40,22 @@ data Timed a = Timed
deriving instance (ToSchema a) => ToSchema (Timed a)

newtype Location = Location Text
deriving newtype (ToJSON, FromJSON, FromHttpApiData, Eq, Ord, Show, ToParamSchema, ToSchema)

data WeatherData = WeatherData
{ temperature :: Int
, windSpeed :: Int
, sunRainRatio :: Int
, pressure :: Int
}
deriving (Generic, ToJSON, FromJSON, ToSchema)

-- | Update weather data
data UpdateData = UpdateData
{ day :: Day
, location :: Location
, content :: WeatherData
}
deriving (Generic, ToJSON, FromJSON, ToSchema)

-- derivings

mapDerive deriveNewtypeHttp [''AuthToken, ''DayInterval, ''Location]
mapDerive deriveBody [''User, ''WeatherData, ''UpdateData]
Loading

0 comments on commit 75b7a26

Please sign in to comment.