-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Injecting fields into aeson values
--   
--   See README.md
@package aeson-injector
@version 1.1.0.0


-- | Common problem in REST interfaces when you need to return nothing as
--   result, usage of `()` will produce `[]` JSON. That causes problems in
--   some JSON parsers in other languages.
--   
--   So, <a>Unit</a> serialises into empty JSON object:
--   
--   <pre>
--   &gt;&gt;&gt; encode Unit
--   "{}"
--   </pre>
module Data.Aeson.Unit

-- | Data type that serialise into empty object in aeson
--   
--   <pre>
--   &gt;&gt;&gt; encode Unit
--   "{}"
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; encode $ toSchema (Proxy :: Proxy Unit)
--   "{\"type\":\"object\"}"
--   </pre>
--   
--   Also the <a>FromJSON</a> instance is just `pure Unit`, so it never
--   fails.
data Unit
Unit :: Unit
instance GHC.Enum.Bounded Data.Aeson.Unit.Unit
instance GHC.Enum.Enum Data.Aeson.Unit.Unit
instance GHC.Read.Read Data.Aeson.Unit.Unit
instance GHC.Show.Show Data.Aeson.Unit.Unit
instance GHC.Classes.Eq Data.Aeson.Unit.Unit
instance GHC.Generics.Generic Data.Aeson.Unit.Unit
instance Data.Aeson.Types.ToJSON.ToJSON Data.Aeson.Unit.Unit
instance Data.Aeson.Types.FromJSON.FromJSON Data.Aeson.Unit.Unit
instance Data.Swagger.Internal.Schema.ToSchema Data.Aeson.Unit.Unit


-- | When builds a RESTful API one often faces the problem that some
--   methods need inbound data without unique identifier (for instance, a
--   creation of new resource) and some methods need the same outbound data
--   with additional fields attached to the response.
--   
--   The module provides you with <a>WithField</a> and <a>WithFields</a>
--   data types that help you to solve the issue without code duplication.
--   
--   It is small utility library that is intented to be used in RESTful
--   APIs, especially with <a>servant</a> and <a>Swagger</a>. Its main
--   purpose is simple injection of fields into JSONs produced by
--   <a>aeson</a> library.
--   
--   Consider the following common data type in web service developing:
--   
--   <pre>
--   data News = News {
--     title :: Text
--   , body :: Text
--   , author :: Text
--   , timestamp :: UTCTime
--   }
--   
--   -- Consider we have simple <a>ToJSON</a> and <a>FromJSON</a> instances
--   $(deriveJSON defaultOptions ''News)
--   </pre>
--   
--   <a>ToJSON</a> instance produces JSON's like:
--   
--   <pre>
--   {
--     "title": "Awesome piece of news!"
--   , "body": "Big chunk of text"
--   , "author": "Just Me"
--   , "timestamp": "2016-07-26T18:54:42.678999Z"
--   }
--   </pre>
--   
--   Now one can create a simple web server with servant DSL:
--   
--   <pre>
--   type NewsId = Word
--   
--   type NewsAPI =
--          ReqBody '[JSON] News :&gt; Post '[JSON] NewsId
--     :&lt;|&gt; Capture "news-id" NewsId :&gt; Get '[JSON] News
--     :&lt;|&gt; "list" :&gt; Get '[JSON] [News]
--   </pre>
--   
--   All seems legit, but, wait a second, an API user definitely would like
--   to know id of news in the "list" method. One way to do this is declare
--   new data type <tt>NewsInfo</tt> with additional field, but it is bad
--   solution as requires to code duplication for each resource.
--   
--   So, here <tt>aeson-injector</tt> steps in, now you can write:
--   
--   <pre>
--   type NewsAPI =
--          ReqBody '[JSON] News :&gt; Post '[JSON] NewsId
--     :&lt;|&gt; Capture "news-id" NewsId :&gt; Get '[JSON] News
--     :&lt;|&gt; "list" :&gt; Get '[JSON] [WithField "id" NewsId News]
--   </pre>
--   
--   <tt><a>WithField</a> "id" NewsId News</tt> or simply <tt><a>WithId</a>
--   NewsId News</tt> wraps you data type and injects "id" field in
--   produced JSON values:
--   
--   <pre>
--   &gt;&gt;&gt; encode (WithField 42 myNews :: WithField "id" NewsId News)
--   </pre>
--   
--   <pre>
--   {
--     "id": 42
--   , "title": "Awesome piece of news!"
--   , "body": "Big chunk of text"
--   , "author": "Just Me"
--   , "timestamp": "2016-07-26T18:54:42.678999Z"
--   }
--   </pre>
--   
--   <a>WithField</a> data type has <a>FromJSON</a> instance for seamless
--   parsing of data with injected fields and <a>ToSchema</a> instance for
--   <a>servant-swagger</a> support.
--   
--   <h1>Injecting multiple values</h1>
--   
--   The library also has more general data type 'WithFields a b' that
--   injects fields of 'toJSON a' into 'toJSON b'.
--   
--   <pre>
--    haskell
--   data NewsPatch = NewsPatch {
--     taggs :: [Text]
--   , rating :: Double
--   }
--   $(deriveJSON defaultOptions ''NewsPatch)
--   </pre>
--   
--   <pre>
--    haskell
--   let myNewsPatch = NewsPatch ["tag1", "tag2"] 42
--   in encode $ WithFields myNewsPatch myNews
--   </pre>
--   
--   <pre>
--   {
--     "title": "Awesome piece of news!"
--   , "body": "Big chunk of text"
--   , "author": "Just Me"
--   , "timestamp": "2016-07-26T18:54:42.678999Z"
--   , "tags": ["tag1", "tag2"]
--   , "rating": 42.0
--   }
--   </pre>
--   
--   <h1>Corner cases</h1>
--   
--   Unfortunately, we cannot inject in non object values of produced JSON,
--   so the library creates a wrapper object around non-object value:
--   
--   <pre>
--   encode (WithId 0 "non-object" :: WithId Int String)
--   </pre>
--   
--   <pre>
--   {
--     "id": 0
--   , "value": "non-object"
--   }
--   </pre>
--   
--   The same story is about <a>WithFields</a> data type:
--   
--   <pre>
--   encode (WithFields 0 "non-object" :: WithFields Int String)
--   </pre>
--   
--   <pre>
--   {
--     "injected": 0
--   , "value": "non-object"
--   }
--   </pre>
module Data.Aeson.WithField

-- | Injects field <tt>a</tt> into <tt>b</tt> with tag <tt>s</tt>. It has
--   special instances for <a>ToJSON</a> and <a>FromJSON</a> for such
--   injection and corresponding Swagger <a>ToSchema</a> instance.
--   
--   For instance:
--   
--   <pre>
--   &gt;&gt;&gt; encode (WithField "val" (Left 42) :: WithField "injected" String (Either Int Int))
--   "{\"Left\":42,\"id\":\"val\"}"
--   </pre>
--   
--   If the instance cannot inject field (in case of single values and
--   arrays), it wraps the result in the following way:
--   
--   <pre>
--   &gt;&gt;&gt; encode (WithField "val" 42 :: WithField "injected" String Int)
--   "{\"value\":42,\"injected\":\"val\"}"
--   </pre>
--   
--   `WithField s a b` always overwites field <tt>s</tt> in JSON produced
--   by <tt>b</tt>.
data WithField (s :: Symbol) a b
WithField :: !a -> !b -> WithField a b

-- | Workaround for a problem that is discribed as: sometimes I need a id
--   with the data, sometimes not.
--   
--   The important note that <a>ToJSON</a> and <a>FromJSON</a> instances
--   behaves as it is <tt>a</tt> but with additional <a>id</a> field.
type WithId i a = WithField "id" i a

-- | Merge fields of <tt>a</tt> into <tt>b</tt>, more general version of
--   <a>WithField</a>.
--   
--   The usual mode of the data type assumes that <a>ToJSON</a> instances
--   of <tt>a</tt> and <tt>b</tt> produce <a>Object</a> subtype of aeson
--   <a>Value</a>. If it is not true, a wrapper layer is introduced.
--   
--   If <tt>a</tt> is not a <a>Object</a>, the wrapper contains
--   <tt>injected</tt> field with body of <tt>a</tt>. If <tt>b</tt> is not
--   a <a>Object</a>, the wrapper contains <tt>value</tt> field with body
--   of <tt>b</tt>. If both are not <a>Object</a>, the wrapper contains
--   <tt>injected</tt> and <tt>value</tt> keys with <tt>a</tt> and
--   <tt>b</tt> respectively.
data WithFields a b
WithFields :: !a -> !b -> WithFields a b

-- | Special case, when you want to wrap your type <tt>a</tt> in field with
--   name <tt>s</tt>.
--   
--   <pre>
--   &gt;&gt;&gt; encode (OnlyField 0 :: OnlyField "id" Int)
--   "{\"id\":0}"
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; encode $ toSchema (Proxy :: Proxy (OnlyField "id" Int))
--   "{\"required\":[\"id\"],\"type\":\"object\",\"properties\":{\"id\":{\"maximum\":9223372036854775807,\"minimum\":-9223372036854775808,\"type\":\"integer\"}}}"
--   </pre>
--   
--   Also the type can be used as an endpoint for <a>WithField</a>:
--   
--   <pre>
--   &gt;&gt;&gt; encode (WithField True (OnlyField 0) :: WithField "val" Bool (OnlyField "id" Int))
--   "{\"id\":0,\"val\":true}"
--   </pre>
newtype OnlyField (s :: Symbol) a
OnlyField :: a -> OnlyField a
[unOnlyField] :: OnlyField a -> a

-- | Special case for the most common "id" field
type OnlyId i = OnlyField "id" i
instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Aeson.WithField.OnlyField s a)
instance GHC.Read.Read a => GHC.Read.Read (Data.Aeson.WithField.OnlyField s a)
instance GHC.Show.Show a => GHC.Show.Show (Data.Aeson.WithField.OnlyField s a)
instance GHC.Generics.Generic (Data.Aeson.WithField.OnlyField s a)
instance (GHC.Read.Read b, GHC.Read.Read a) => GHC.Read.Read (Data.Aeson.WithField.WithFields a b)
instance (GHC.Show.Show b, GHC.Show.Show a) => GHC.Show.Show (Data.Aeson.WithField.WithFields a b)
instance (GHC.Classes.Eq b, GHC.Classes.Eq a) => GHC.Classes.Eq (Data.Aeson.WithField.WithFields a b)
instance GHC.Generics.Generic (Data.Aeson.WithField.WithFields a b)
instance (GHC.Read.Read b, GHC.Read.Read a) => GHC.Read.Read (Data.Aeson.WithField.WithField s a b)
instance (GHC.Show.Show b, GHC.Show.Show a) => GHC.Show.Show (Data.Aeson.WithField.WithField s a b)
instance (GHC.Classes.Eq b, GHC.Classes.Eq a) => GHC.Classes.Eq (Data.Aeson.WithField.WithField s a b)
instance GHC.Generics.Generic (Data.Aeson.WithField.WithField s a b)
instance GHC.Base.Functor (Data.Aeson.WithField.OnlyField s)
instance Servant.Docs.Internal.ToSample a => Servant.Docs.Internal.ToSample (Data.Aeson.WithField.OnlyField s a)
instance (GHC.TypeLits.KnownSymbol s, Data.Aeson.Types.ToJSON.ToJSON a) => Data.Aeson.Types.ToJSON.ToJSON (Data.Aeson.WithField.OnlyField s a)
instance (GHC.TypeLits.KnownSymbol s, Data.Aeson.Types.FromJSON.FromJSON a) => Data.Aeson.Types.FromJSON.FromJSON (Data.Aeson.WithField.OnlyField s a)
instance (GHC.TypeLits.KnownSymbol s, Data.Swagger.Internal.Schema.ToSchema a) => Data.Swagger.Internal.Schema.ToSchema (Data.Aeson.WithField.OnlyField s a)
instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData b) => Control.DeepSeq.NFData (Data.Aeson.WithField.WithFields a b)
instance GHC.Base.Functor (Data.Aeson.WithField.WithFields a)
instance Data.Bifunctor.Bifunctor Data.Aeson.WithField.WithFields
instance (Servant.Docs.Internal.ToSample a, Servant.Docs.Internal.ToSample b) => Servant.Docs.Internal.ToSample (Data.Aeson.WithField.WithFields a b)
instance (Data.Aeson.Types.ToJSON.ToJSON a, Data.Aeson.Types.ToJSON.ToJSON b) => Data.Aeson.Types.ToJSON.ToJSON (Data.Aeson.WithField.WithFields a b)
instance (Data.Aeson.Types.ToJSON.ToJSON a, Data.Aeson.Types.FromJSON.FromJSON a, Data.Aeson.Types.FromJSON.FromJSON b) => Data.Aeson.Types.FromJSON.FromJSON (Data.Aeson.WithField.WithFields a b)
instance (Data.Swagger.Internal.Schema.ToSchema a, Data.Swagger.Internal.Schema.ToSchema b) => Data.Swagger.Internal.Schema.ToSchema (Data.Aeson.WithField.WithFields a b)
instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData b) => Control.DeepSeq.NFData (Data.Aeson.WithField.WithField s a b)
instance GHC.Base.Functor (Data.Aeson.WithField.WithField s a)
instance Data.Bifunctor.Bifunctor (Data.Aeson.WithField.WithField s)
instance (Servant.Docs.Internal.ToSample a, Servant.Docs.Internal.ToSample b) => Servant.Docs.Internal.ToSample (Data.Aeson.WithField.WithField s a b)
instance (GHC.TypeLits.KnownSymbol s, Data.Aeson.Types.ToJSON.ToJSON a, Data.Aeson.Types.ToJSON.ToJSON b) => Data.Aeson.Types.ToJSON.ToJSON (Data.Aeson.WithField.WithField s a b)
instance (GHC.TypeLits.KnownSymbol s, Data.Aeson.Types.FromJSON.FromJSON a, Data.Aeson.Types.FromJSON.FromJSON b) => Data.Aeson.Types.FromJSON.FromJSON (Data.Aeson.WithField.WithField s a b)
instance (GHC.TypeLits.KnownSymbol s, Data.Swagger.Internal.Schema.ToSchema a, Data.Swagger.Internal.Schema.ToSchema b) => Data.Swagger.Internal.Schema.ToSchema (Data.Aeson.WithField.WithField s a b)
