forked from loafle/openapi-generator-original
* handle Alias models with newtypes * add inlineConsumesContentTypes cli option * generate swagger.yaml instead of swagger.json * check for/validate unhandled authMethods * refactoring
176 lines
9.1 KiB
Plaintext
176 lines
9.1 KiB
Plaintext
{{>partial_header}}
|
|
{-|
|
|
Module : {{title}}.API
|
|
-}
|
|
|
|
{-# LANGUAGE ConstraintKinds #-}
|
|
{-# LANGUAGE ExistentialQuantification #-}
|
|
{-# LANGUAGE FlexibleContexts #-}
|
|
{-# LANGUAGE FlexibleInstances #-}
|
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
{-# LANGUAGE InstanceSigs #-}
|
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
{-# LANGUAGE RecordWildCards #-}
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
|
{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports #-}
|
|
|
|
module {{title}}.API where
|
|
|
|
import {{title}}.Core
|
|
import {{title}}.MimeTypes
|
|
import {{title}}.Model as M
|
|
|
|
import qualified Data.Aeson as A
|
|
import qualified Data.ByteString as B
|
|
import qualified Data.ByteString.Base64 as B64
|
|
import qualified Data.ByteString.Char8 as BC
|
|
import qualified Data.ByteString.Lazy as BL
|
|
import qualified Data.Data as P (Typeable, TypeRep, typeOf, typeRep)
|
|
import qualified Data.Foldable as P
|
|
import qualified Data.Map as Map
|
|
import qualified Data.Maybe as P
|
|
import qualified Data.Proxy as P (Proxy(..))
|
|
import qualified Data.Set as Set
|
|
import qualified Data.String as P
|
|
import qualified Data.Text as T
|
|
import qualified Data.Text.Encoding as T
|
|
import qualified Data.Text.Lazy as TL
|
|
import qualified Data.Text.Lazy.Encoding as TL
|
|
import qualified Data.Time as TI
|
|
import qualified GHC.Base as P (Alternative)
|
|
import qualified Lens.Micro as L
|
|
import qualified Network.HTTP.Client.MultipartFormData as NH
|
|
import qualified Network.HTTP.Media as ME
|
|
import qualified Network.HTTP.Types as NH
|
|
import qualified Web.FormUrlEncoded as WH
|
|
import qualified Web.HttpApiData as WH
|
|
|
|
import Data.Monoid ((<>))
|
|
import Data.Function ((&))
|
|
import Data.Text (Text)
|
|
import GHC.Base ((<|>))
|
|
|
|
import Prelude ((==),(/=),($), (.),(<$>),(<*>),(>>=),Maybe(..),Bool(..),Char,Double,FilePath,Float,Int,Integer,String,fmap,undefined,mempty,maybe,pure,Monad,Applicative,Functor)
|
|
import qualified Prelude as P
|
|
|
|
-- * Operations
|
|
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#vendorExtensions.x-hasNewTag}}
|
|
|
|
-- ** {{baseName}}{{/vendorExtensions.x-hasNewTag}}
|
|
|
|
-- *** {{operationId}}
|
|
|
|
-- | @{{{vendorExtensions.x-haddockPath}}}@
|
|
-- {{#summary}}
|
|
-- {{{.}}}
|
|
-- {{/summary}}{{#notes}}
|
|
-- {{{.}}}
|
|
-- {{/notes}}{{#hasAuthMethods}}
|
|
-- AuthMethod: {{#authMethods}}'{{{name}}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}
|
|
-- {{/hasAuthMethods}}{{#vendorExtensions.x-hasUnknownReturn}}
|
|
-- Note: Has 'Produces' instances, but no response schema
|
|
-- {{/vendorExtensions.x-hasUnknownReturn}}
|
|
{{operationId}}
|
|
:: {{#vendorExtensions.x-hasBodyOrFormParam}}(Consumes {{{vendorExtensions.x-operationType}}} {{>_contentType}}{{#allParams}}{{#isBodyParam}}{{#required}}, MimeRender {{>_contentType}} {{#vendorExtensions.x-paramNameType}}{{{.}}}{{/vendorExtensions.x-paramNameType}}{{^vendorExtensions.x-paramNameType}}{{{dataType}}}{{/vendorExtensions.x-paramNameType}}{{/required}}{{/isBodyParam}}{{/allParams}})
|
|
=> {{^vendorExtensions.x-inlineContentType}}contentType -- ^ request content-type ('MimeType')
|
|
-> {{/vendorExtensions.x-inlineContentType}}{{/vendorExtensions.x-hasBodyOrFormParam}}{{#allParams}}{{#required}}{{#vendorExtensions.x-paramNameType}}{{{.}}}{{/vendorExtensions.x-paramNameType}}{{^vendorExtensions.x-paramNameType}}{{{dataType}}}{{/vendorExtensions.x-paramNameType}} -- ^ "{{{paramName}}}"{{#description}} - {{/description}} {{{description}}}
|
|
-> {{/required}}{{/allParams}}{{requestType}} {{{vendorExtensions.x-operationType}}} {{#vendorExtensions.x-hasBodyOrFormParam}}{{>_contentType}}{{/vendorExtensions.x-hasBodyOrFormParam}}{{^vendorExtensions.x-hasBodyOrFormParam}}MimeNoContent{{/vendorExtensions.x-hasBodyOrFormParam}} {{vendorExtensions.x-returnType}}
|
|
{{operationId}} {{#vendorExtensions.x-hasBodyOrFormParam}}{{^vendorExtensions.x-inlineContentType}}_ {{/vendorExtensions.x-inlineContentType}}{{/vendorExtensions.x-hasBodyOrFormParam}}{{#allParams}}{{#required}}{{#isBodyParam}}{{{paramName}}}{{/isBodyParam}}{{^isBodyParam}}({{{vendorExtensions.x-paramNameType}}} {{{paramName}}}){{/isBodyParam}} {{/required}}{{/allParams}}=
|
|
_mkRequest "{{httpMethod}}" {{{vendorExtensions.x-path}}}{{#authMethods}}
|
|
`_hasAuthType` (P.Proxy :: P.Proxy {{name}}){{/authMethods}}{{#allParams}}{{#required}}{{#isHeaderParam}}
|
|
`setHeader` {{>_headerColl}} ("{{{baseName}}}", {{{paramName}}}){{/isHeaderParam}}{{#isQueryParam}}
|
|
`setQuery` {{>_queryColl}} ("{{{baseName}}}", Just {{{paramName}}}){{/isQueryParam}}{{#isFormParam}}{{#isFile}}
|
|
`_addMultiFormPart` NH.partFileSource "{{{baseName}}}" {{{paramName}}}{{/isFile}}{{^isFile}}{{#isMultipart}}
|
|
`_addMultiFormPart` NH.partLBS "{{{baseName}}}" (mimeRender' MimeMultipartFormData {{{paramName}}}){{/isMultipart}}{{^isMultipart}}
|
|
`addForm` {{>_formColl}} ("{{{baseName}}}", {{{paramName}}}){{/isMultipart}}{{/isFile}}{{/isFormParam}}{{#isBodyParam}}
|
|
`setBodyParam` {{{paramName}}}{{/isBodyParam}}{{/required}}{{/allParams}}{{#isDeprecated}}
|
|
|
|
{-# DEPRECATED {{operationId}} "" #-}{{/isDeprecated}}
|
|
|
|
data {{{vendorExtensions.x-operationType}}} {{#allParams}}{{#isBodyParam}}{{#description}}
|
|
|
|
-- | /Body Param/ "{{{baseName}}}" - {{{description}}}{{/description}}
|
|
instance HasBodyParam {{{vendorExtensions.x-operationType}}} {{#vendorExtensions.x-paramNameType}}{{{.}}}{{/vendorExtensions.x-paramNameType}}{{^vendorExtensions.x-paramNameType}}{{{dataType}}}{{/vendorExtensions.x-paramNameType}}{{/isBodyParam}}{{/allParams}} {{#vendorExtensions.x-hasOptionalParams}}{{#allParams}}{{^isBodyParam}}{{^required}}{{#description}}
|
|
|
|
-- | /Optional Param/ "{{{baseName}}}" - {{{description}}}{{/description}}
|
|
instance HasOptionalParam {{{vendorExtensions.x-operationType}}} {{{vendorExtensions.x-paramNameType}}} where
|
|
applyOptionalParam req ({{{vendorExtensions.x-paramNameType}}} xs) =
|
|
{{#isHeaderParam}}req `setHeader` {{>_headerColl}} ("{{{baseName}}}", xs){{/isHeaderParam}}{{#isQueryParam}}req `setQuery` {{>_queryColl}} ("{{{baseName}}}", Just xs){{/isQueryParam}}{{#isFormParam}}{{#isFile}}req `_addMultiFormPart` NH.partFileSource "{{{baseName}}}" xs{{/isFile}}{{^isFile}}{{#isMultipart}}req `_addMultiFormPart` NH.partLBS "{{{baseName}}}" (mimeRender' MimeMultipartFormData xs){{/isMultipart}}{{^isMultipart}}req `addForm` {{>_formColl}} ("{{{baseName}}}", xs){{/isMultipart}}{{/isFile}}{{/isFormParam}}{{/required}}{{/isBodyParam}}{{/allParams}}{{/vendorExtensions.x-hasOptionalParams}}{{#hasConsumes}}
|
|
|
|
{{#consumes}}-- | @{{{mediaType}}}@
|
|
instance Consumes {{{vendorExtensions.x-operationType}}} {{{x-mediaDataType}}}
|
|
{{/consumes}}{{/hasConsumes}}{{#hasProduces}}
|
|
{{#produces}}-- | @{{{mediaType}}}@
|
|
instance Produces {{{vendorExtensions.x-operationType}}} {{{x-mediaDataType}}}
|
|
{{/produces}}{{/hasProduces}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
|
|
|
|
|
-- * Parameter newtypes
|
|
|
|
{{#x-allUniqueParams}}
|
|
newtype {{{vendorExtensions.x-paramNameType}}} = {{{vendorExtensions.x-paramNameType}}} { un{{{vendorExtensions.x-paramNameType}}} :: {{{dataType}}} } deriving (P.Eq, P.Show{{#isBodyParam}}, A.ToJSON{{/isBodyParam}})
|
|
{{/x-allUniqueParams}}
|
|
|
|
-- * Auth Methods
|
|
|
|
{{#authMethods}}{{#isBasic}}-- ** {{name}}
|
|
data {{name}} =
|
|
{{name}} B.ByteString B.ByteString -- ^ username password
|
|
deriving (P.Eq, P.Show, P.Typeable)
|
|
|
|
instance AuthMethod {{name}} where
|
|
applyAuthMethod _ a@({{name}} user pw) req =
|
|
P.pure $
|
|
if (P.typeOf a `P.elem` rAuthTypes req)
|
|
then req `setHeader` toHeader ("Authorization", T.decodeUtf8 cred)
|
|
& L.over rAuthTypesL (P.filter (/= P.typeOf a))
|
|
else req
|
|
where cred = BC.append "Basic " (B64.encode $ BC.concat [ user, ":", pw ])
|
|
|
|
{{/isBasic}}{{#isApiKey}}-- ** {{name}}
|
|
data {{name}} =
|
|
{{name}} Text -- ^ secret
|
|
deriving (P.Eq, P.Show, P.Typeable)
|
|
|
|
instance AuthMethod {{name}} where
|
|
applyAuthMethod _ a@({{name}} secret) req =
|
|
P.pure $
|
|
if (P.typeOf a `P.elem` rAuthTypes req)
|
|
then req {{#isKeyInHeader}}`setHeader` toHeader ("{{keyParamName}}", secret){{/isKeyInHeader}}{{^isKeyInHeader}}`setQuery` toQuery ("{{keyParamName}}", Just secret){{/isKeyInHeader}}
|
|
& L.over rAuthTypesL (P.filter (/= P.typeOf a))
|
|
else req
|
|
|
|
{{/isApiKey}}{{#isOAuth}}-- ** {{name}}
|
|
data {{name}} =
|
|
{{name}} Text -- ^ secret
|
|
deriving (P.Eq, P.Show, P.Typeable)
|
|
|
|
instance AuthMethod {{name}} where
|
|
applyAuthMethod _ a@({{name}} secret) req =
|
|
P.pure $
|
|
if (P.typeOf a `P.elem` rAuthTypes req)
|
|
then req `setHeader` toHeader ("Authorization", "Bearer " <> secret)
|
|
& L.over rAuthTypesL (P.filter (/= P.typeOf a))
|
|
else req
|
|
|
|
{{/isOAuth}}{{/authMethods}}
|
|
|
|
{{#x-hasUnknownMimeTypes}}
|
|
-- * Custom Mime Types
|
|
|
|
{{#x-unknownMimeTypes}}-- ** {{{x-mediaDataType}}}
|
|
|
|
data {{{x-mediaDataType}}} = {{{x-mediaDataType}}} deriving (P.Typeable)
|
|
|
|
-- | @{{{mediaType}}}@
|
|
instance MimeType {{{x-mediaDataType}}} where
|
|
mimeType _ = Just $ P.fromString "{{{mediaType}}}"{{#x-mediaIsJson}}
|
|
instance A.ToJSON a => MimeRender {{{x-mediaDataType}}} a where mimeRender _ = A.encode
|
|
instance A.FromJSON a => MimeUnrender {{{x-mediaDataType}}} a where mimeUnrender _ = A.eitherDecode{{/x-mediaIsJson}}
|
|
-- instance MimeRender {{{x-mediaDataType}}} T.Text where mimeRender _ = undefined
|
|
-- instance MimeUnrender {{{x-mediaDataType}}} T.Text where mimeUnrender _ = undefined
|
|
|
|
{{/x-unknownMimeTypes}}{{/x-hasUnknownMimeTypes}}
|