Crie APIs GraphQL com sua linguagem funcional favorita!
O Morpheus GraphQL (servidor e cliente) ajuda você a criar APIs GraphQL em Haskell com os tipos nativos de Haskell. O Morpheus converterá seus tipos de haskell em um esquema GraphQL e todos os seus resolvedores são apenas funções nativas de Haskell. O Morpheus GraphQL também pode converter seu esquema grafql ou consulta em tipos Haskell e validá -los em tempo de compilação.
Morfeu ainda está em um estágio inicial de desenvolvimento; portanto, qualquer feedback é mais do que bem -vindo e apreciamos qualquer contribuição! Basta abrir um problema aqui no Github ou se juntar ao nosso canal Slack para entrar em contato.
Observe que este arquivo ReadMe fornece apenas uma breve introdução à biblioteca. Se você estiver interessado em tópicos mais avançados, visite os documentos.
Desde a versão v0.28.0, o Morpheus GraphQL implementa o [https://github.com/enisdenjo/graphql-ws/blob/master/protocol.md ](graphql-ws graphql sobre o protocolo WebSocket) e não usa mais o protocolo não mais https://github.com/apollographql/subscriptions-transport-ws/blob/master/protocol.md Protocol.
Para começar com Morfeu, primeiro você precisa adicioná -lo às dependências do seu projeto, como segue (supondo que você esteja usando o HPACK):
package.yml
dependencies :
- morpheus-graphql
- morpheus-graphql-core
- morpheus-graphql-subscriptionsAlém disso, você deve dizer a pilha qual versão escolher:
Stack.yml
resolver : lts-16.2
extra-deps :
- morpheus-graphql-0.28.0
- morpheus-graphql-core-0.28.0
- morpheus-graphql-app-0.28.0
- morpheus-graphql-code-gen-0.28.0
- morpheus-graphql-code-gen-utils-0.28.0
- morpheus-graphql-server-0.28.0
- morpheus-graphql-client-0.28.0
- morpheus-graphql-subscriptions-0.28.0schema.gql
type Query {
deity ( name : String ! = " Morpheus " ): Deity !
}
"""
Description for Deity
"""
type Deity {
"""
Description for name
"""
name : String !
power : String @deprecated ( reason : " some reason for " )
}API.HS
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module API ( api ) where
import Data.ByteString.Lazy.Char8 ( ByteString )
import Data.Morpheus ( interpreter )
import Data.Morpheus.Document ( importGQLDocument )
import Data.Morpheus.Types ( RootResolver ( .. ), Undefined ( .. ))
import Data.Text ( Text )
importGQLDocument " schema.gql "
rootResolver :: RootResolver IO () Query Undefined Undefined
rootResolver =
RootResolver
{ queryResolver = Query {deity},
mutationResolver = Undefined ,
subscriptionResolver = Undefined
}
where
deity DeityArgs {name} =
pure
Deity
{ name = pure name,
power = pure ( Just " Shapeshifting " )
}
api :: ByteString -> IO ByteString
api = interpreter rootResolver Modelo Haskell Gera tipos: Query , Deity , DeityArgs , que podem ser usados por rootResolver
descriptions e deprecations serão exibidas na introspecção.
importGQLDocumentWithNamespace gerará tipos com campos de namespaced. Se você não precisar de namespace, use importGQLDocument
Para definir uma API do GraphQL com Morfeu, começamos definindo o esquema da API como um tipo de dados nativo Haskell, que deriva a classe de tipo Generic . Usando a extensão da linguagem DeriveAnyClass , também derivamos instâncias para a classe do tipo GQLType . Os campos preguiçosamente resolvíveis nesse tipo Query são definidos através de a -> ResolverQ () IO b , representando a resolução de um conjunto de argumentos a a um valor concreto b .
data Query m = Query
{ deity :: DeityArgs -> m Deity
} deriving ( Generic , GQLType )
data Deity = Deity
{ fullName :: Text -- Non-Nullable Field
, power :: Maybe Text -- Nullable Field
} deriving ( Generic , GQLType )
data DeityArgs = DeityArgs
{ name :: Text -- Required Argument
, mythology :: Maybe Text -- Optional Argument
} deriving ( Generic , GQLType ) Para cada campo no tipo Query definido por a -> mb (como deity ), definiremos uma implementação do resolvedor que fornece os valores durante o tempo de execução, referindo -se a alguma fonte de dados, por exemplo, um banco de dados ou outra API. Campos definidos sem a -> mb Você pode apenas fornecer um valor.
No exemplo acima, o campo de DeityArgs também pode ser nomeado usando identidades reservadas (como: type , where , etc.), a fim de evitar conflitos, um símbolo principal ( ' ) deve ser anexado. Por exemplo, você pode ter:
data DeityArgs = DeityArgs
{ name :: Text -- Required Argument
, mythology :: Maybe Text -- Optional Argument
, type' :: Text
} deriving ( Generic , GQLType ) O nome do campo na solicitação final será type em vez de type' . O analisador de solicitação de Morfeu converte cada uma das identidades reservadas em Haskell 2010 em seus nomes correspondentes internamente. Isso também se aplica às seleções.
resolveDeity :: DeityArgs -> ResolverQ () IO Deity
resolveDeity DeityArgs { name, mythology } = liftEither $ dbDeity name mythology
askDB :: Text -> Maybe Text -> IO ( Either String Deity )
askDB = ... Para disponibilizar esse tipo Query como uma API, definimos um RootResolver e a alimentamos ao interpreter de Morfeus. Um RootResolver consiste em definições de query , mutation e subscription , enquanto omitimos o último para este exemplo:
rootResolver :: RootResolver IO () Query Undefined Undefined
rootResolver =
RootResolver
{ queryResolver = Query {deity = resolveDeity}
, mutationResolver = Undefined
, subscriptionResolver = Undefined
}
gqlApi :: ByteString -> IO ByteString
gqlApi = interpreter rootResolver Como você pode ver, a API é definida como ByteString -> IO ByteString que podemos invocar diretamente ou usar dentro de uma estrutura da Web arbitrária, como scotty ou serverless-haskell . Vamos para scotty neste exemplo:
main :: IO ()
main = scotty 3000 $ post " /api " $ raw =<< (liftIO . gqlApi =<< body) Se agora enviarmos uma solicitação de postagem para http://localhost:3000/api com uma consulta grafql como corpo, por exemplo, em uma ferramenta como Insomnia :
query GetDeity {
deity ( name : " Morpheus " ) {
fullName
power
}
}Nossa consulta será resolvida!
{
"data" : {
"deity" : {
"fullName" : " Morpheus " ,
"power" : " Shapeshifting "
}
}
} Se você estiver interessado em criar uma API Morpheus GraphQL com Serverless , deve dar uma olhada no nosso exemplo neste repositório: API de mitologia , é o nosso exemplo de criação de projeto com Morpheus GraphQL e Serverless-Haskell , onde você pode consultar diferentes caracteres de mitologia com GraphiQL .
A API da mitologia está implantada em: API.MorpheusGraphql.com , onde você pode testá -lo com GraphiQL
Abaixo estão a lista de projetos usando o Morpheus GraphQL. Se você deseja começar a usar o Morpheus GraphQL, eles são bons modelos para começar.
Edite esta seção e envie PR se quiser compartilhar seu projeto .
Morfeu é o deus grego do sono e os sonhos cujo nome vem da palavra grega μορφή significa forma ou forma. Diz -se que ele é capaz de imitar formas diferentes e o GraphQL é bom em fazer exatamente isso: transformar dados na forma de muitas APIs diferentes.
Morfeu é escrito e mantido por Nalchevanidze