-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Auto-generate a server for your datatype -- -- This library auto-generates a REST API from any datatype that derives -- the Generic interface -- -- See the documentation in Server.Generic for an example of how -- to use this library @package server-generic @version 1.0.0 -- | This library auto-generates API services for data types using -- Haskell's built-in support for generic programming. The best way to -- understand how this library works is to walk through a few examples. -- -- For example, suppose that you define the following type: -- --
--   -- Example.hs
--   
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   import Server.Generic
--   
--   data Example = Example { foo :: Int, bar :: Double }
--       deriving (Generic)
--   
--   instance ParseRecord Example
--   instance ToJSON      Example
--   
--   handler :: Example -> IO Example
--   handler = return
--   
--   main :: IO ()
--   main = serveJSON 8080 handler
--   
-- -- Named fields translate to query parameters which you can provide in -- any order: -- --
--   $ stack build server-generic
--   $ stack runghc Example.hs
--   ...
--   {in another terminal}
--   $ curl 'localhost:8080/example?bar=2.5&foo=1'
--   {"foo":1,"bar":2.5}
--   
-- -- serveJSON performs the following steps: -- -- -- -- Let's write a more interesting handler that creates files: -- --
--   -- Create.hs
--   
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   import Server.Generic
--   
--   data Create = Create { filepath :: FilePath, contents :: String }
--       deriving (Generic)
--   
--   instance ParseRecord Create
--   
--   handler :: Create -> IO ()
--   handler create = writeFile (filepath create) (contents create)
--   
--   main :: IO ()
--   main = serveJSON 8080 handler
--   
-- -- If we run that then it will create a file any time we hit the -- /create endpoint with the appropriate query parameters: -- --
--   $ curl 'localhost:8080/create?filepath=test.txt&contents=ABC'
--   []
--   $ cat test.txt
--   ABC
--   
-- -- The [] in the response is just how the aeson library -- encodes the empty () return value of the handler. -- -- Unlabeled fields translate to path tokens in the route. For example, -- this type: -- --
--   -- Example.hs
--   
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   import Server.Generic
--   
--   data Example = Example Int Double Text
--       deriving (Generic)
--   
--   instance ParseRecord Example
--   instance ToJSON      Example
--   
--   handler :: Example -> IO Example
--   handler = return
--   
--   main :: IO ()
--   main = serveJSON 8080 handler
--   
-- -- ... translates to a /example/:int/:double/:text route that -- captures the last three tokens as the fields of the Example -- type: -- --
--   $ curl 'localhost:8080/example/1/2.5/foo'
--   [1,2.5,"foo"]
--   
-- -- Also, unlabeled data types get converted to an array when rendered as -- JSON. -- -- Certain types of fields are given special treatment, such as in this -- example: -- --
--   data Example = Example
--       { list     :: [Int]
--       , optional :: Maybe   Int
--       , first    :: First   Int
--       , last     :: Last    Int
--       } deriving (Generic)
--   
-- -- This gives the following behavior: -- --
--   $ curl 'localhost:8080/example?optional=1&list=1&list=2&first=1&first=2&last=1&last=2'
--   {"list":[1,2],"first":1,"last":2,"optional":1}
--   
--   $ curl 'localhost:8080/example'
--   {"list":[],"first":null,"last":null,"optional":null}
--   
-- -- If a datatype has multiple constructors: -- --
--   data Example
--       = Create { name :: Text, duration :: Maybe Int }
--       | Kill   { name :: Text }
--       deriving (Generic)
--   
-- -- ... then they will translate into multiple API endpoints: -- --
--   $ curl 'localhost:8080/create?name=foo&duration=60'
--   {"tag":"Create","name":"foo","duration":60}
--   $ curl 'localhost:8080/kill?name=foo'
--   {"tag":"Kill","name":"foo"}
--   
-- -- This library also provides out-of-the-box support for many existing -- types, like tuples and Either: -- --
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   import Server.Generic
--   
--   handler :: Either Int Double -> IO (Either Int Double)
--   handler = return
--   
--   main :: IO ()
--   main = serveJSON 8080 handler
--   
-- --
--   $ curl 'localhost:8080/left/1'
--   {"Left":1}
--   $ curl 'localhost:8080/right/2.5'
--   {"Right":2.5}
--   
-- --
--   handler :: (Int, Double) -> IO (Int, Double)
--   handler = return
--   
-- --
--   $ curl 'localhost:8080/1/2.5'
--   [1,2.5]
--   
-- -- ... and you can also just parse a single value: -- --
--   handler :: Int -> IO Int
--   handler = return
--   
-- --
--   $ curl 'localhost:8080/1'
--   1
--   
-- -- However, there are some types that this library cannot generate -- sensible routes for, such as: -- -- -- --
--   data Example = Example { foo :: Example }
--   
-- -- -- --
--   data Outer = Outer { foo :: Inner } deriving (Show, Generic)
--   data Inner = Inner { bar :: Int   } deriving (Show, Generic)
--   
-- -- -- --
--   data Example = Example { foo :: Maybe (Maybe Int) }
--   data Example = Example { foo :: [[Int]]           }
--   
-- -- If you try to auto-generate a parser for these types you will get an -- error at compile time that will look something like this: -- --
--   No instance for (ParseFields TheTypeOfYourField)
--     arising from a use of ‘Server.Generic.$gdmparseRecord’
--   In the expression: Server.Generic.$gdmparseRecord
--   In an equation for ‘parseRecord’:
--       parseRecord = Server.Generic.$gdmparseRecord
--   In the instance declaration for ‘ParseRecord TheTypeOfYourRecord’
--   
module Server.Generic -- | Simple server that listens on the given Port and runs the -- handler for each incoming connection -- -- The value supplied to the handler is automatically parsed from the -- route -- -- The request method is ignored -- -- Failure to parse a value from the route results in a response with a -- 404 status code serve :: ParseRecord a => Port -> (a -> IO Response) -> IO () -- | Like serve except the handler result is automatically encoded -- as JSON and served as the Response serveJSON :: (ParseRecord a, ToJSON b) => Port -> (a -> IO b) -> IO () -- | Like serve except the Response is always "200 -- OK" serveOK :: ParseRecord a => Port -> (a -> IO ()) -> IO () -- | A list of path tokens which were originally separated by -- /s data Route Route :: [Text] -> [(ByteString, ByteString)] -> Route path :: Route -> [Text] query :: Route -> [(ByteString, ByteString)] -- | A backtracking Route parser newtype Parser a Parser :: StateT Route [] a -> Parser a unParser :: Parser a -> StateT Route [] a -- | A class for types that can be parsed from path tokens or query -- parameters -- -- This class has a default implementation for any type that implements -- Generic and you can derive Generic for many types by -- enabling the DeriveGeneric language extension -- -- You can also use getOnly to create a ParseRecord -- instance from a ParseFields instance: -- --
--   instance ParseRecord MyType where
--       parseRecord = fmap getOnly parseRecord
--   
class ParseRecord a where parseRecord = fmap to genericParseRecord parseRecord :: ParseRecord a => Parser a -- | A class for all types that can be parsed from zero or more path tokens -- or query parameters -- -- parseFields has a default implementation for any type that -- implements ParseField class ParseRecord a => ParseFields a where parseFields = parseField parseFields :: ParseFields a => Maybe Text -> Parser a -- | A class for all record fields that can be parsed from exactly one path -- token or query parameter -- -- parseField has a default implementation for any type that -- implements Read class ParseField a where parseField m = do { text <- parseField m; case readMaybe (unpack text) of { Nothing -> empty Just a -> return a } } parseListOfField m = many (parseField m) parseField :: ParseField a => Maybe Text -> Parser a parseListOfField :: ParseField a => Maybe Text -> Parser [a] -- | A 1-tuple, used solely to translate ParseFields instances into -- ParseRecord instances newtype Only a Only :: a -> Only a -- | This is a convenience function that you can use if you want to create -- a ParseRecord instance that just defers to the -- ParseFields instance for the same type: -- --
--   instance ParseRecord MyType where
--       parseRecord = fmap getOnly parseRecord
--   
getOnly :: Only a -> a -- | Representable types of kind *. This class is derivable in GHC with the -- DeriveGeneric flag on. class Generic a -- | A type that can be converted to JSON. -- -- An example type and instance: -- --
--   {-# LANGUAGE OverloadedStrings #-}
--   
--   data Coord = Coord { x :: Double, y :: Double }
--   
--   instance ToJSON Coord where
--      toJSON (Coord x y) = object ["x" .= x, "y" .= y]
--   
-- -- Note the use of the OverloadedStrings language extension -- which enables Text values to be written as string literals. -- -- Instead of manually writing your ToJSON instance, there are -- three options to do it automatically: -- -- -- -- To use the latter option, simply add a deriving -- Generic clause to your datatype and declare a -- ToJSON instance for your datatype without giving a definition -- for toJSON. -- -- For example the previous example can be simplified to just: -- --
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   import GHC.Generics
--   
--   data Coord = Coord { x :: Double, y :: Double } deriving Generic
--   
--   instance ToJSON Coord
--   
-- -- Note that, instead of using DefaultSignatures, it's also -- possible to parameterize the generic encoding using -- genericToJSON applied to your encoding/decoding Options: -- --
--   instance ToJSON Coord where
--       toJSON = genericToJSON defaultOptions
--   
class ToJSON a -- | A space efficient, packed, unboxed Unicode text type. data Text :: * -- | Boolean monoid under conjunction. newtype All :: * All :: Bool -> All getAll :: All -> Bool -- | Boolean monoid under disjunction. newtype Any :: * Any :: Bool -> Any getAny :: Any -> Bool -- | Maybe monoid returning the leftmost non-Nothing value. newtype First a :: * -> * First :: Maybe a -> First a getFirst :: First a -> Maybe a -- | Maybe monoid returning the rightmost non-Nothing value. newtype Last a :: * -> * Last :: Maybe a -> Last a getLast :: Last a -> Maybe a -- | Monoid under addition. newtype Sum a :: * -> * Sum :: a -> Sum a getSum :: Sum a -> a -- | Monoid under multiplication. newtype Product a :: * -> * Product :: a -> Product a getProduct :: Product a -> a instance Show Route instance Functor Parser instance Applicative Parser instance Monad Parser instance Alternative Parser instance MonadPlus Parser instance MonadState Route Parser instance Generic (Only a) instance Show a => Show (Only a) instance Datatype D1Only instance Constructor C1_0Only instance ParseField Any instance ParseField All instance ParseField () instance ParseField Char instance ParseField String instance ParseField Void instance ParseField Ordering instance ParseField Integer instance ParseField Int instance ParseField Float instance ParseField Double instance ParseField Bool instance ParseField ByteString instance ParseField Text instance ParseField Text instance ParseField ByteString instance ParseField a => ParseFields [a] instance (Num a, ParseField a) => ParseFields (Product a) instance (Num a, ParseField a) => ParseFields (Sum a) instance ParseField a => ParseFields (Last a) instance ParseField a => ParseFields (First a) instance ParseField a => ParseFields (Maybe a) instance ParseFields All instance ParseFields Any instance ParseFields () instance ParseFields Bool instance ParseFields Text instance ParseFields Text instance ParseFields ByteString instance ParseFields ByteString instance ParseFields Void instance ParseFields Ordering instance ParseFields Integer instance ParseFields Int instance ParseFields Float instance ParseFields Double instance ParseFields Char instance (Selector s, ParseFields a) => GenericParseRecord (M1 S s (K1 i a)) instance GenericParseRecord f => GenericParseRecord (M1 D c f) instance (Constructor c, GenericParseRecord f) => GenericParseRecord (M1 C c f) instance (GenericParseRecord f, GenericParseRecord g) => GenericParseRecord (f :*: g) instance (GenericParseRecord f, GenericParseRecord g) => GenericParseRecord (f :+: g) instance GenericParseRecord V1 instance GenericParseRecord U1 instance (ParseFields a, ParseFields b) => ParseRecord (Either a b) instance (ParseFields a, ParseFields b, ParseFields c, ParseFields d, ParseFields e, ParseFields f, ParseFields g) => ParseRecord (a, b, c, d, e, f, g) instance (ParseFields a, ParseFields b, ParseFields c, ParseFields d, ParseFields e, ParseFields f) => ParseRecord (a, b, c, d, e, f) instance (ParseFields a, ParseFields b, ParseFields c, ParseFields d, ParseFields e) => ParseRecord (a, b, c, d, e) instance (ParseFields a, ParseFields b, ParseFields c, ParseFields d) => ParseRecord (a, b, c, d) instance (ParseFields a, ParseFields b, ParseFields c) => ParseRecord (a, b, c) instance (ParseFields a, ParseFields b) => ParseRecord (a, b) instance ParseRecord Void instance ParseRecord Ordering instance ParseRecord Bool instance ParseField a => ParseRecord [a] instance (Num a, ParseField a) => ParseRecord (Product a) instance (Num a, ParseField a) => ParseRecord (Sum a) instance ParseField a => ParseRecord (Last a) instance ParseField a => ParseRecord (First a) instance ParseField a => ParseRecord (Maybe a) instance ParseRecord Text instance ParseRecord Text instance ParseRecord ByteString instance ParseRecord ByteString instance ParseRecord All instance ParseRecord Any instance ParseRecord () instance ParseRecord Integer instance ParseRecord Int instance ParseRecord Float instance ParseRecord Double instance ParseRecord Char instance ParseFields a => ParseRecord (Only a)