acolyte-core-0.1.0.0: src/Acolyte/Core/Negotiate.hs
{-# LANGUAGE OverloadedStrings #-}
-- | Type-level content negotiation.
--
-- A single endpoint can serve multiple content types. The handler
-- returns the domain value; the framework selects the serialization
-- format based on the @Accept@ header.
--
-- @
-- type GetArticle = Get '[ Lit "articles", Capture Int ]
-- (Negotiate '[JsonFormat, XmlFormat, TextFormat] Article)
-- @
--
-- All formats appear in the OpenAPI spec. The handler just returns
-- @Article@ — no format awareness needed.
module Acolyte.Core.Negotiate
( -- * Negotiated response type
Negotiate
-- * Content format class
, ContentFormat (..)
-- * Built-in format tags
, JsonFormat
, XmlFormat
, TextFormat
, HtmlFormat
, CsvFormat
) where
import Data.Kind (Type)
import Data.Text (Text)
-- | A response that supports multiple content types via negotiation.
--
-- @formats@ is a type-level list of format tags (e.g., @'[JsonFormat, XmlFormat]@).
-- @a@ is the domain type that can be rendered in each format.
--
-- The server package implements the runtime negotiation: parse the
-- @Accept@ header, select the best format, and serialize @a@ using
-- the appropriate @RenderAs@ instance.
type Negotiate :: [Type] -> Type -> Type
data Negotiate (formats :: [Type]) (a :: Type)
-- | A content format tag.
--
-- Each format declares its MIME type and quality. The server package
-- uses this to match against @Accept@ headers.
class ContentFormat (fmt :: Type) where
-- | The MIME type for this format (e.g., "application/json").
contentType :: Text
-- | Default quality weight for this format (0.0–1.0).
-- Used to break ties when the client has no preference.
defaultQuality :: Double
defaultQuality = 1.0
-- ===================================================================
-- Built-in format tags
-- ===================================================================
-- | JSON format (@application/json@).
data JsonFormat
instance ContentFormat JsonFormat where
contentType = "application/json"
-- | XML format (@application/xml@).
data XmlFormat
instance ContentFormat XmlFormat where
contentType = "application/xml"
defaultQuality = 0.9
-- | Plain text format (@text/plain@).
data TextFormat
instance ContentFormat TextFormat where
contentType = "text/plain"
defaultQuality = 0.5
-- | HTML format (@text/html@).
data HtmlFormat
instance ContentFormat HtmlFormat where
contentType = "text/html"
defaultQuality = 0.8
-- | CSV format (@text/csv@).
data CsvFormat
instance ContentFormat CsvFormat where
contentType = "text/csv"
defaultQuality = 0.3