servant-pagination-1.0.0: Type-safe pagination for Servant APIs

Safe HaskellNone
LanguageHaskell2010

Servant.Pagination

Contents

Synopsis

Types

data Range (field :: Symbol) typ Source #

Constructors

Range 

Fields

Instances

Functor (Range field) Source # 

Methods

fmap :: (a -> b) -> Range field a -> Range field b #

(<$) :: a -> Range field b -> Range field a #

(ToHttpApiData typ, KnownSymbol field) => ToHttpApiData (NextRange (Range field typ)) Source # 

Methods

toUrlPiece :: NextRange (Range field typ) -> Text #

toEncodedUrlPiece :: NextRange (Range field typ) -> Builder #

toHeader :: NextRange (Range field typ) -> ByteString #

toQueryParam :: NextRange (Range field typ) -> Text #

(ToHttpApiData typ, KnownSymbol field) => ToHttpApiData (ContentRange (Range field typ)) Source # 
Eq typ => Eq (Range field typ) Source # 

Methods

(==) :: Range field typ -> Range field typ -> Bool #

(/=) :: Range field typ -> Range field typ -> Bool #

Show typ => Show (Range field typ) Source # 

Methods

showsPrec :: Int -> Range field typ -> ShowS #

show :: Range field typ -> String #

showList :: [Range field typ] -> ShowS #

Generic (Range field typ) Source # 

Associated Types

type Rep (Range field typ) :: * -> * #

Methods

from :: Range field typ -> Rep (Range field typ) x #

to :: Rep (Range field typ) x -> Range field typ #

(ToHttpApiData typ, KnownSymbol field) => ToHttpApiData (Range field typ) Source # 

Methods

toUrlPiece :: Range field typ -> Text #

toEncodedUrlPiece :: Range field typ -> Builder #

toHeader :: Range field typ -> ByteString #

toQueryParam :: Range field typ -> Text #

(FromHttpApiData typ, KnownSymbol field) => FromHttpApiData (Range field typ) Source # 

Methods

parseUrlPiece :: Text -> Either Text (Range field typ) #

parseHeader :: ByteString -> Either Text (Range field typ) #

parseQueryParam :: Text -> Either Text (Range field typ) #

KnownSymbol field => ToAcceptRanges (Range field typ) Source # 

Methods

toAcceptRanges :: Proxy * (Range field typ) -> Text Source #

(FromHttpApiData typ, KnownSymbol field) => FromRange (Range field typ) Source # 

Methods

parseRange :: FromRangeOptions -> Text -> Either Text (Range field typ) Source #

type Rep (Range field typ) Source # 
type Rep (Range field typ) = D1 * (MetaData "Range" "Servant.Pagination" "servant-pagination-1.0.0-5A49ASMmXjrCvOpna7rcJk" False) (C1 * (MetaCons "Range" PrefixI True) ((:*:) * ((:*:) * (S1 * (MetaSel (Just Symbol "rangeValue") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * (Maybe typ))) (S1 * (MetaSel (Just Symbol "rangeLimit") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Int))) ((:*:) * (S1 * (MetaSel (Just Symbol "rangeOffset") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * Int)) (S1 * (MetaSel (Just Symbol "rangeOrder") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 * RangeOrder)))))

data RangeOrder Source #

Define the sorting order of the paginated resources (ascending or descending)

Constructors

RangeAsc 
RangeDesc 

data AcceptRanges range Source #

Accepted Ranges in the `Accept-Ranges` response's header

Constructors

AcceptRanges 

data ContentRange range Source #

Actual range returned, in the `Content-Range` response's header

Constructors

ContentRange 

Fields

data NextRange range Source #

Range to provide to retrieve the next batch of resource, in the `Next-Range` response's header

Constructors

NextRange range 

type PageHeaders range = '[Header "Accept-Ranges" (AcceptRanges range), Header "Content-Range" (ContentRange range), Header "Next-Range" (NextRange range), Header "Total-Count" Natural] Source #

Type alias to declare response headers related to pagination

Declare Ranges

class FromRange a where Source #

Parse a Range object from a Range request's header. Any `Range field typ` and combinations of any `Range field typ` provide instance of this class. It is a signature similar to parseUrlPiece from the FromHttpApiData class and can be used as a drop-in replacement to define instance of this class.

type MyRange = Range "created_at" UTCTime

instance FromHttpApiData UTCTime => FromHttpApiData MyRange where
    parseUrlPiece =
        fromRange defaultOptions

Minimal complete definition

parseRange

Instances

(FromHttpApiData typ, KnownSymbol field) => FromRange (Range field typ) Source # 

Methods

parseRange :: FromRangeOptions -> Text -> Either Text (Range field typ) Source #

class FromHttpApiData a where #

Parse value from HTTP API data.

WARNING: Do not derive this using DeriveAnyClass as the generated instance will loop indefinitely.

Minimal complete definition

parseUrlPiece | parseQueryParam

Methods

parseUrlPiece :: Text -> Either Text a #

Parse URL path piece.

parseHeader :: ByteString -> Either Text a #

Parse HTTP header value.

parseQueryParam :: Text -> Either Text a #

Parse query param value.

Instances

FromHttpApiData Bool 
FromHttpApiData Char 
FromHttpApiData Double 
FromHttpApiData Float 
FromHttpApiData Int 
FromHttpApiData Int8 
FromHttpApiData Int16 
FromHttpApiData Int32 
FromHttpApiData Int64 
FromHttpApiData Integer 
FromHttpApiData Natural 
FromHttpApiData Ordering 
FromHttpApiData Word 
FromHttpApiData Word8 
FromHttpApiData Word16 
FromHttpApiData Word32 
FromHttpApiData Word64 
FromHttpApiData ()
>>> parseUrlPiece "_" :: Either Text ()
Right ()
FromHttpApiData String 
FromHttpApiData Text 
FromHttpApiData UTCTime
>>> parseUrlPiece "2015-10-03T00:14:24Z" :: Either Text UTCTime
Right 2015-10-03 00:14:24 UTC
FromHttpApiData Text 
FromHttpApiData Void

Parsing a Void value is always an error, considering Void as a data type with no constructors.

FromHttpApiData Version
>>> showVersion <$> parseUrlPiece "1.2.3"
Right "1.2.3"
FromHttpApiData All 
FromHttpApiData Any 
FromHttpApiData ZonedTime
>>> parseUrlPiece "2015-10-03T14:55:01+0000" :: Either Text ZonedTime
Right 2015-10-03 14:55:01 +0000
>>> parseQueryParam "2016-12-31T01:00:00Z" :: Either Text ZonedTime
Right 2016-12-31 01:00:00 +0000
FromHttpApiData LocalTime
>>> parseUrlPiece "2015-10-03T14:55:01" :: Either Text LocalTime
Right 2015-10-03 14:55:01
FromHttpApiData TimeOfDay
>>> parseUrlPiece "14:55:01.333" :: Either Text TimeOfDay
Right 14:55:01.333
FromHttpApiData NominalDiffTime 
FromHttpApiData Day
>>> toGregorian <$> parseUrlPiece "2016-12-01"
Right (2016,12,1)
FromHttpApiData UUID 
FromHttpApiData RangeOrder # 
FromHttpApiData a => FromHttpApiData (Maybe a)
>>> parseUrlPiece "Just 123" :: Either Text (Maybe Int)
Right (Just 123)
FromHttpApiData a => FromHttpApiData (Dual a) 
FromHttpApiData a => FromHttpApiData (Sum a) 
FromHttpApiData a => FromHttpApiData (Product a) 
FromHttpApiData a => FromHttpApiData (First a) 
FromHttpApiData a => FromHttpApiData (Last a) 
FromHttpApiData a => FromHttpApiData (LenientData a) 
(FromHttpApiData a, FromHttpApiData b) => FromHttpApiData (Either a b)
>>> parseUrlPiece "Right 123" :: Either Text (Either String Int)
Right (Right 123)
(FromHttpApiData a, FromHttpApiData b) => FromHttpApiData ((:|:) a b) # 
(FromHttpApiData typ, KnownSymbol field) => FromHttpApiData (Range field typ) # 

Methods

parseUrlPiece :: Text -> Either Text (Range field typ) #

parseHeader :: ByteString -> Either Text (Range field typ) #

parseQueryParam :: Text -> Either Text (Range field typ) #

defaultOptions :: FromRangeOptions Source #

Some default options of default values for a Range (limit 100; offset 0; order desc)

defaultRange :: Maybe a -> FromRangeOptions -> Range field a Source #

Some default range based on the default options

Use Ranges

class KnownSymbol field => HasPagination resource field where Source #

In addition to the FromHttpApiData instance, one can provide an instance for this type-class to easily lift a list of response to a Servant handler. By providing a getter to retrieve the value of an actual range from a resource, the HasPagination class provides returnPage to handle the plumbering of declaring response headers related to pagination.

Minimal complete definition

getRangeField

Associated Types

type RangeType resource field :: * Source #

Methods

getRangeField :: Proxy field -> resource -> RangeType resource field Source #

returnPage_ :: forall m ranges. (Monad m, Range field (RangeType resource field) :<: ranges, ToAcceptRanges ranges, ToHttpApiData (ContentRange ranges), ToHttpApiData (NextRange ranges), Ord (RangeType resource field)) => Range field (RangeType resource field) -> [resource] -> m (Headers (PageHeaders ranges) [resource]) Source #

returnPage :: forall m ranges. (Monad m, Range field (RangeType resource field) :<: ranges, ToAcceptRanges ranges, ToHttpApiData (ContentRange ranges), ToHttpApiData (NextRange ranges), Ord (RangeType resource field)) => TotalCount -> Range field (RangeType resource field) -> [resource] -> m (Headers (PageHeaders ranges) [resource]) Source #

applyRange :: forall b field. (HasPagination b field, Ord (RangeType b field)) => Range field (RangeType b field) -> [b] -> [b] Source #

Apply a range to a list of element

Combine Ranges

data a :|: b infixl 7 Source #

Combine two ranges in a new range, parsing is done left-first

Constructors

InL a 
InR b 

Instances

r :<: ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) r r2) r3) r4) r5) r6) r7) r8) r9) Source # 

Methods

liftRange :: r -> (((((((r :|: r2) :|: r3) :|: r4) :|: r5) :|: r6) :|: r7) :|: r8) :|: r9 Source #

r :<: ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) r1 r) r3) r4) r5) r6) r7) r8) r9) Source # 

Methods

liftRange :: r -> (((((((r1 :|: r) :|: r3) :|: r4) :|: r5) :|: r6) :|: r7) :|: r8) :|: r9 Source #

r :<: ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) r r2) r3) r4) r5) r6) r7) r8) Source # 

Methods

liftRange :: r -> ((((((r :|: r2) :|: r3) :|: r4) :|: r5) :|: r6) :|: r7) :|: r8 Source #

r :<: ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) r1 r) r3) r4) r5) r6) r7) r8) Source # 

Methods

liftRange :: r -> ((((((r1 :|: r) :|: r3) :|: r4) :|: r5) :|: r6) :|: r7) :|: r8 Source #

r :<: ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) r r2) r3) r4) r5) r6) r7) Source # 

Methods

liftRange :: r -> (((((r :|: r2) :|: r3) :|: r4) :|: r5) :|: r6) :|: r7 Source #

r :<: ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) r1 r) r3) r4) r5) r6) r7) Source # 

Methods

liftRange :: r -> (((((r1 :|: r) :|: r3) :|: r4) :|: r5) :|: r6) :|: r7 Source #

r :<: ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) r r2) r3) r4) r5) r6) Source # 

Methods

liftRange :: r -> ((((r :|: r2) :|: r3) :|: r4) :|: r5) :|: r6 Source #

r :<: ((:|:) ((:|:) ((:|:) ((:|:) ((:|:) r1 r) r3) r4) r5) r6) Source # 

Methods

liftRange :: r -> ((((r1 :|: r) :|: r3) :|: r4) :|: r5) :|: r6 Source #

r :<: ((:|:) ((:|:) ((:|:) ((:|:) r r2) r3) r4) r5) Source # 

Methods

liftRange :: r -> (((r :|: r2) :|: r3) :|: r4) :|: r5 Source #

r :<: ((:|:) ((:|:) ((:|:) ((:|:) r1 r) r3) r4) r5) Source # 

Methods

liftRange :: r -> (((r1 :|: r) :|: r3) :|: r4) :|: r5 Source #

r :<: ((:|:) ((:|:) ((:|:) r r2) r3) r4) Source # 

Methods

liftRange :: r -> ((r :|: r2) :|: r3) :|: r4 Source #

r :<: ((:|:) ((:|:) ((:|:) r1 r) r3) r4) Source # 

Methods

liftRange :: r -> ((r1 :|: r) :|: r3) :|: r4 Source #

r :<: ((:|:) ((:|:) r r2) r3) Source # 

Methods

liftRange :: r -> (r :|: r2) :|: r3 Source #

r :<: ((:|:) ((:|:) r1 r) r3) Source # 

Methods

liftRange :: r -> (r1 :|: r) :|: r3 Source #

r :<: ((:|:) r1 r) Source # 

Methods

liftRange :: r -> r1 :|: r Source #

r :<: ((:|:) r r2) Source # 

Methods

liftRange :: r -> r :|: r2 Source #

(ToHttpApiData (NextRange a), ToHttpApiData (NextRange b)) => ToHttpApiData (NextRange ((:|:) a b)) # 
(ToHttpApiData (ContentRange a), ToHttpApiData (ContentRange b)) => ToHttpApiData (ContentRange ((:|:) a b)) # 
(ToHttpApiData a, ToHttpApiData b) => ToHttpApiData ((:|:) a b) Source # 

Methods

toUrlPiece :: (a :|: b) -> Text #

toEncodedUrlPiece :: (a :|: b) -> Builder #

toHeader :: (a :|: b) -> ByteString #

toQueryParam :: (a :|: b) -> Text #

(FromHttpApiData a, FromHttpApiData b) => FromHttpApiData ((:|:) a b) Source # 
(ToAcceptRanges a, ToAcceptRanges b) => ToAcceptRanges ((:|:) a b) Source # 

Methods

toAcceptRanges :: Proxy * (a :|: b) -> Text Source #