ecluse:ecluse-core
Safe HaskellNone
LanguageGHC2021

Ecluse.Core.Server.Contract

Description

The response-contract algebra: one value read as both wire behaviour and OpenAPI documentation. The constructor is private, so a route builds a ResponseContract only from this module's leaves and chooseContract, and cannot supply the docs and the renderer separately. A leaf reads its media type off the BodySchema it documents, so the wire type and the manifest type are one spelling. A transparent upstream relay (passthroughContract) documents an OpenAPI default response rather than a closed status set it cannot honour.

Synopsis

Documented body shapes

data BodySchema Source #

The structural shape of a response body and the media type it is served under, kept OpenAPI-free in the core.

Constructors

SchemaEmpty

No body at all.

SchemaOpaque ByteString

Opaque bytes under one known media type.

SchemaText ByteString

Text under one known media type.

SchemaJson ByteString (JSONCodec a)

Encoded from the same codec the manifest renders as a schema.

SchemaDocumented ByteString Text

An imperatively assembled document with a named manifest schema.

SchemaPassthrough

An upstream-controlled body under an upstream-controlled media type.

data RequestSpec Source #

A request body a route accepts. A hand-authored request schema still owes the separate conformance check the API-surface architecture describes.

Constructors

RequestSpec 

Fields

data ResponseStatus Source #

Whether a documented response has one exact status or covers every other status.

data ResponseDoc Source #

One response entry for the OpenAPI spec. This is a projection of a ResponseContract leaf, never independently supplied by a route.

Constructors

ResponseDoc 

Fields

A response contract

data ResponseContract response Source #

A response contract indexed by the only value its handler may answer with.

responseDocs :: ResponseContract response -> [ResponseDoc] Source #

The manifest projection of a response contract.

responseToWai :: ResponseContract response -> response -> Response Source #

Render one value through its contract and into WAI. This is the only application boundary at which a route response becomes an unrestricted WAI Response.

bodilessContract :: ResponseContract response -> ResponseContract response Source #

Derive the HEAD interpretation of a contract: the same response alternatives, statuses, and headers, with no documented or emitted body.

Exact response leaves

data ResponseValue a Source #

A payload for an exact-status response, carrying additional response headers.

responseValue :: [Header] -> a -> ResponseValue a Source #

Supply the additional headers and payload for an exact response leaf.

jsonContract :: Status -> Text -> JSONCodec a -> ResponseContract (ResponseValue a) Source #

One exact JSON response, encoded through the codec its manifest schema uses.

mediaJsonContract :: ByteString -> Status -> Text -> JSONCodec a -> ResponseContract (ResponseValue a) Source #

One exact response encoded through its codec and served under media, for a JSON-family media type an ecosystem names itself.

documentedJsonContract :: Status -> Text -> Text -> ResponseContract (ResponseValue LByteString) Source #

One exact JSON response whose bytes are assembled imperatively and whose schema is the named hand-authored component in the manifest.

mediaContract :: Status -> Text -> BodySchema -> ResponseContract (ResponseValue LByteString) Source #

One exact response, served under the media type its BodySchema names and documented as that same type. A schema naming no media type (SchemaEmpty, SchemaPassthrough) emits no body.

optionalBodyContract :: Status -> Text -> BodySchema -> ResponseContract (ResponseValue (Maybe LByteString)) Source #

One exact response whose body is optional, the refusal shape of an ecosystem whose upstream answers a bare status. Both forms are one documented response rather than two.

emptyContract :: Status -> Text -> ResponseContract (ResponseValue ()) Source #

One exact bodiless response.

Open response leaves

data VariableResponse a Source #

A response whose status is supplied by the handler while its media type remains fixed by the contract. Used for the publication target's arbitrary JSON-labelled status.

variableResponse :: Status -> [Header] -> a -> VariableResponse a Source #

Supply a dynamic status, additional headers, and body to a variable-status leaf.

variableOpaqueContract :: ByteString -> Text -> ResponseContract (VariableResponse LByteString) Source #

An OpenAPI default response carrying opaque bytes under a fixed media type.

The schema is intentionally binary even for application/json. The proxy relays the publication target's bytes without parsing them, so it must not promise they satisfy a JSON schema it never checks.

data PassthroughBody Source #

The body of a transparent upstream response.

data PassthroughResponse Source #

A transparent upstream response: status, headers, and body all remain upstream's.

passthroughContract :: Text -> ResponseContract PassthroughResponse Source #

An OpenAPI default contract for a transparent upstream relay. The proxy forwards arbitrary upstream statuses and media types, so any finite status set beside it would be inaccurate.

Combining closed alternatives

data ResponseChoice a b Source #

A binary response choice. Nesting these forms a closed route response sum without type-level programming, and chooseContract builds the two matching interpretations together.

Constructors

FirstResponse a 
SecondResponse b 

chooseContract :: ResponseContract a -> ResponseContract b -> ResponseContract (ResponseChoice a b) Source #

Combine two response contracts into a closed choice of their alternatives.

Rendering JSON through a codec

encodeBody :: JSONCodec a -> a -> LByteString Source #

Encode a JSON value to bytes through its autodocodec codec.