packages feed

servant-response (empty) → 0.1

raw patch · 5 files changed

+183/−0 lines, 5 filesdep +aesondep +basedep +http-typessetup-changed

Dependencies added: aeson, base, http-types, text

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Alp Mestanogullari++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Alp Mestanogullari nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ servant-response.cabal view
@@ -0,0 +1,24 @@+name:                servant-response+version:             0.1+synopsis:            Machinery to express how servant should turn results of database operations into proper JSON-encodable response types+description:         Machinery to express how servant should turn results of database operations into proper JSON-encodable response types+homepage:            http://github.com/zalora/servant+license:             BSD3+license-file:        LICENSE+author:              Alp Mestanogullari+maintainer:          alp@zalora.com+copyright:           2014 Zalora SEA+category:            Web+build-type:          Simple +cabal-version:       >=1.10++library+  exposed-modules:     Servant.Response, Servant.Response.Prelude +  build-depends:+      base >=4.5 && <5+    , aeson >= 0.7+    , http-types >= 0.8+    , text >= 1.0+  hs-source-dirs:      src+  default-language:    Haskell2010+  ghc-options:         -Wall
+ src/Servant/Response.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE FunctionalDependencies,+             MultiParamTypeClasses #-}+{- |+Module      :  Servant.Response+Copyright   :  (c) Zalora SEA 2014+License     :  BSD3+Maintainer  :  Alp Mestanogullari <alp@zalora.com>+Stability   :  experimental++This module contains a generic 'Response' class for tying the result+of some \"database operation\" to some response type of yours,+or to the standard ones from "Servant.Scotty.Prelude" for example.++-}+module Servant.Response+  ( -- * The 'Response' class+    Response(..)+  , -- * Useful for defining your instances+    module Network.HTTP.Types.Status+  ) where++import Data.Aeson hiding (json)+import Network.HTTP.Types.Status++-- | A class that ties return types of your database operations+--   and the output that will be generated to communicate+--   the result.+--+-- * The first type, @resp@, is the response type that will be encoded+--   in JSON and sent as the response body.+--+-- * The second type, @result@, is the result type of your \"database\"+--   or \"context\" operation.+--+--   For example, if you're adding an item, and if you're using+--   postgresql-simple, you'll probably want to use the+--   'Response' instances defined in the servant-postgresql package,+--   in the @Servant.PostgreSQL.Prelude@ module.+--+--   It lets you specify, given a value of your result, if no+--   exception is thrown, what response should be sent as JSON+--   to the client along with what HTTP status.+--+--   There's a functional dependency at play: the result type+--   of a database operation determines the representation that'll be+--   picked for generating the json output.+class ToJSON resp => Response resp result | result -> resp where+  toResponse :: result -> (resp, Status)
+ src/Servant/Response/Prelude.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE DeriveGeneric, MultiParamTypeClasses, OverloadedStrings #-}+module Servant.Response.Prelude+  ( -- * 'Response' class+  	module Servant.Response+  , -- * Useful reusable types and instances+    UpdateResponse(..)+  , LookupResponse(..)+  ) where++import Data.Aeson+import Data.Text+import GHC.Generics+import Network.HTTP.Types.Status+import Servant.Response++-- | A generic response type for any "effectul" operation+--   on a 'Resource', like adding, updating or deleting an item.+--+--   It simply holds a 'Bool' that indicates whether the operation+--   was successful or not, and if it wasn't, it'll embed a text+--   describing what went wrong and is meant to be tagged+--   (see the @o@ type parameter) with the operation it's associated to.+--+--   This lets us have different instances for the standard+--   /Add/ and /Update/ operations for example, where the former+--   should respond with HTTP status code /201/ if the entry was created,+--   whereas the latter should just use status code /200/.+--+--   You can of course skip this one and use a more appropriate+--   for your particular application.+data UpdateResponse o =+  UpdateResponse { success :: !Bool +                 , msg     :: !Text+                 }+  deriving (Eq, Show, Generic)++-- | e.g:+--+-- > { "success" : false, "msg" : "couldn't add item: blabla"}+instance ToJSON (UpdateResponse o) where++-- | A generic response type for an operation performing+--   some kind of (potentially failing) lookup of an item+--+--   This is useful when writing a web application, where you+--   want to send for example a JSON message saying the item wasn't found+--   along with status 404 when the item isn't found, but just send the item+--   if it could be found. This is (purposefully) isomorphic to 'Maybe'.+data LookupResponse a =+    NotFound+  | Found !a+  deriving (Eq, Show)++-- | If you have some type convertible to JSON,+--   you can wrap it in 'LookupResponse' whenever you are+--   looking up a value associated to some identifier+--   where the lookup may fail.+--   It'll send the JSON-encoded value if found or+--+-- > { "message" : "Not found" }+--+--   if not found. This makes sure you send /valid/+--   JSON through the wires even when the target doesn't exist.+instance ToJSON a => ToJSON (LookupResponse a) where+  toJSON NotFound  = object [ "message" .= ("Not found" :: Text) ]+  toJSON (Found x) = toJSON x++-- | Make 'LookupResponse' a proper 'Response' for+--   'Service.Context.Context' lookups returning a 'Maybe' value,+--   returning 404 when Nothing is returned, along with a not found+--   message in json. Used by 'View'.+instance ToJSON a => Response (LookupResponse a) (Maybe a) where+  toResponse Nothing  = (NotFound, status404)+  toResponse (Just v) = (Found v, status200)++-- | Just send the list of entries as a JSON array,+--   with status code 200. Used by 'ListAll'.+instance ToJSON a => Response [a] [a] where+  toResponse list = (list, status200)