rest-core-0.31: src/Rest/Schema.hs
{-# LANGUAGE ExistentialQuantification #-}
-- | This module contains data types and combinators for defining a
-- 'Schema' for your 'Resource'. A 'Schema' has three type parameters,
-- specifying the identifiers for a single resource, a listing, and a
-- top-level (static) action. After routing, these identifiers will be
-- passed to the 'Handler'.
module Rest.Schema
( -- * A set of combinators for creating schemas.
-- ** Top level
withListing
, noListing
, singleton
-- ** Named endpoints
, named
, static
, single
, singleBy
, singleRead
, listing
, listingBy
, listingRead
-- ** Unnamed endpoints
, unnamedSingle
, unnamedSingleRead
, unnamedListing
, unnamedListingRead
-- * The core schema data types.
, Schema (..)
, Step (..)
, Cardinality (..)
, Getter (..)
, Id (..)
, Endpoint
) where
import Rest.Dictionary (Ident (..))
import Rest.Info (Info)
-- * A set of combinators for creating schemas.
-- ** Top level
-- | A schema with a top level listing.
withListing :: mid -> Step sid mid aid -> Schema sid mid aid
withListing mid = Schema (Just (Many mid))
-- | A schema with no top level listing.
noListing :: Step sid mid aid -> Schema sid mid aid
noListing = Schema Nothing
-- | A schema with a singleton at the top level.
singleton :: sid -> Step sid mid aid -> Schema sid mid aid
singleton sid = Schema (Just (Single sid))
-- ** Named endpoints
-- | A list of named endpoints.
named :: [(String, Endpoint sid mid aid)] -> Step sid mid aid
named = Named
-- | A top level action endpoint for this resource.
static :: aid -> Endpoint sid mid aid
static = Left
-- | A singleton resource endpoint.
single :: sid -> Endpoint sid mid aid
single = Right . Single . Singleton
-- | A single resource endpoint with a string identifier.
singleBy :: (String -> sid) -> Endpoint sid mid aid
singleBy = singleIdent StringId
-- | A single resource endpoint with an identifier that can be read.
singleRead :: (Show a, Read a, Info a) => (a -> sid) -> Endpoint sid mid aid
singleRead = singleIdent ReadId
-- | A single resource identified as specified by the 'Ident'.
singleIdent :: Ident a -> (a -> sid) -> Endpoint sid mid aid
singleIdent ident = Right . Single . By . Id ident
-- | A listing endpoint.
listing :: mid -> Endpoint sid mid aid
listing = Right . Many . Singleton
-- | A listing endpoint with a string identifier.
listingBy :: (String -> mid) -> Endpoint sid mid aid
listingBy = listingIdent StringId
-- | A listing with an identifier that can be read.
listingRead :: (Show a, Read a, Info a) => (a -> mid) -> Endpoint sid mid aid
listingRead = listingIdent ReadId
-- | A listing identified as specified by the 'Ident'.
listingIdent :: Ident a -> (a -> mid) -> Endpoint sid mid aid
listingIdent ident = Right . Many . By . Id ident
-- ** Unnamed endpoints
-- | An unnamed single resource with a string identifier.
unnamedSingle :: (String -> sid) -> Step sid mid aid
unnamedSingle = unnamedSingleIdent StringId
-- | An unnamed single resource with an identifier that can be read.
unnamedSingleRead :: (Show a, Read a, Info a) => (a -> sid) -> Step sid mid aid
unnamedSingleRead = unnamedSingleIdent ReadId
-- | An unnamed single resource identified as specified by the
-- 'Ident'.
unnamedSingleIdent :: Ident a -> (a -> sid) -> Step sid mid aid
unnamedSingleIdent ident = Unnamed . Single . Id ident
-- | An unnamed listing with a string identifier.
unnamedListing :: (String -> mid) -> Step sid mid aid
unnamedListing = unnamedListingIdent StringId
-- | An unnamed listing with an identifier that can be read.
unnamedListingRead :: (Show a, Read a, Info a) => (a -> mid) -> Step sid mid aid
unnamedListingRead = unnamedListingIdent ReadId
-- | An unnamed listing identified as specified by the 'Ident'.
unnamedListingIdent :: Ident a -> (a -> mid) -> Step sid mid aid
unnamedListingIdent ident = Unnamed . Many . Id ident
-- * The core schema data types.
-- | A 'Schema' describes how (part of the) route to a resource looks,
-- and returns an identifier for a single resource ('sid'), many
-- resources ('mid') or a static action ('aid').
-- The first argument specifies the top level resource (no path
-- segments). The second specifies a what happens at the first step in
-- the path.
data Schema sid mid aid = Schema (Maybe (Cardinality sid mid)) (Step sid mid aid)
-- | A step in the routing of a resource. A part of the uri either
-- identifies a 'Named' resource, or an 'Unnamed' resource. Named
-- resources can be static actions ('Left') or one or many singletons or
-- by's.
data Step sid mid aid = Named [(String, Endpoint sid mid aid)]
| Unnamed (Cardinality (Id sid) (Id mid))
-- | Specifies if we're identifying a single resource, or many (a
-- listing).
data Cardinality s m = Single s
| Many m
-- | A 'Getter' can either be a 'Singleton' (there is only one) or it
-- can be identified 'By' an 'Id'entifier.
data Getter id = Singleton id | By (Id id)
-- | An identification of an item in a resource. It contains a
-- dictionary describing how to identify the resource, and a function
-- for this identification type to an @id@.
data Id id = forall a. Id (Ident a) (a -> id)
-- | A named endpoint: an static action, a single item of many items.
type Endpoint sid mid aid = Either aid (Cardinality (Getter sid) (Getter mid))