Erstellen Sie GraphQL -APIs mit Ihrer bevorzugten funktionalen Sprache!
Morpheus GraphQL (Server & Client) hilft Ihnen beim Erstellen von GraphQL -APIs in Haskell mit nativen Haskell -Typen. Morpheus wandelt Ihre Haskell -Typen in ein GraphQL -Schema um und alle Ihre Resolver sind nur native Haskell -Funktionen. Morpheus GraphQL kann auch Ihr GraphQL -Schema oder Ihre Abfrage in Haskell -Typen konvertieren und sie in Kompilierungszeit validieren.
Morpheus befindet sich noch in einem frühen Entwicklungsstadium, daher ist jedes Feedback mehr als willkommen, und wir schätzen jeden Beitrag! Öffnen Sie hier einfach ein Problem auf Github oder schließen Sie sich unserem Slack -Kanal an, um uns in Verbindung zu setzen.
Bitte beachten Sie, dass diese Readme -Datei nur eine kurze Einführung in die Bibliothek enthält. Wenn Sie an fortgeschritteneren Themen interessiert sind, besuchen Sie Dokumente.
Seit Version V0.28.0 implementiert Morpheus GraphQL die [https://github.com/enisdenjo/graphql-ws/blob/master/protocol.md weibliche(Graphql-Ws Graphql über das Websocket-Protokoll) und verwendet das nicht mehr die https://github.com/apolographql/subscriptions-transport-ws/blob/master/protocol.md Protocol.
Um mit Morpheus zu beginnen, müssen Sie es zuerst den Abhängigkeiten Ihres Projekts wie folgt hinzufügen (vorausgesetzt, Sie verwenden HPack):
package.yml
dependencies :
- morpheus-graphql
- morpheus-graphql-core
- morpheus-graphql-subscriptionsZusätzlich sollten Sie Stack mit sagen, welche Version auswählen soll:
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 Template Haskell generiert Typen: Query , Deity , DeityArgs , die von rootResolver verwendet werden können
descriptions und deprecations werden in Selbstbeobachtung angezeigt.
importGQLDocumentWithNamespace generiert Typen mit Namenspiegel. Wenn Sie keinen Namespace benötigen, verwenden Sie importGQLDocument
Um eine GraphQL -API mit Morpheus zu definieren, beginnen wir zunächst das API -Schema als native Haskell -Datentyp, der die Generic Typklasse ableitet. Mit der Sprachweiterung der DeriveAnyClass leiten wir dann auch Instanzen für die Klasse GQLType -Typ ab. Faul auflösbare Felder in diesem Query werden über a -> ResolverQ () IO b definiert, was die Lösung einer Reihe von Argumenten a zu einem konkreten Wert 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 ) Für jedes Feld im Query definieren wir eine Resolver -Implementierung, die die Werte während der Laufzeit liefert a -> mb indem wir deity auf eine Datenquelle, z. B. eine Datenbank oder eine andere API, verweisen. Felder, die ohne a -> mb definiert sind, können Sie nur einen Wert liefern.
Im obigen where könnte das Gebiet der DeityArgs auch mithilfe ' reservierten Identitäten (z type Zum Beispiel können Sie:
data DeityArgs = DeityArgs
{ name :: Text -- Required Argument
, mythology :: Maybe Text -- Optional Argument
, type' :: Text
} deriving ( Generic , GQLType ) Der Feldname in der endgültigen Anforderung ist type anstelle von type' . Der Morpheus Request -Parser konvertiert jede der reservierten Identitäten in Haskell 2010 in ihre entsprechenden Namen. Dies gilt auch für die Auswahl.
resolveDeity :: DeityArgs -> ResolverQ () IO Deity
resolveDeity DeityArgs { name, mythology } = liftEither $ dbDeity name mythology
askDB :: Text -> Maybe Text -> IO ( Either String Deity )
askDB = ... Um diesen Query als API verfügbar zu machen, definieren wir einen RootResolver und füttern ihn dem Morpheus interpreter . Ein RootResolver besteht aus query , mutation und subscription , während wir letztere für dieses Beispiel weglassen:
rootResolver :: RootResolver IO () Query Undefined Undefined
rootResolver =
RootResolver
{ queryResolver = Query {deity = resolveDeity}
, mutationResolver = Undefined
, subscriptionResolver = Undefined
}
gqlApi :: ByteString -> IO ByteString
gqlApi = interpreter rootResolver Wie Sie sehen können, ist die API als ByteString -> IO ByteString definiert, die wir entweder direkt aufrufen oder in einem willkürlichen Web -Framework wie scotty oder serverless-haskell verwenden können. In diesem Beispiel gehen wir für scotty :
main :: IO ()
main = scotty 3000 $ post " /api " $ raw =<< (liftIO . gqlApi =<< body) Wenn wir jetzt eine Postanforderung an http://localhost:3000/api mit einer GraphQL -Abfrage als Körper in einem Tool wie Insomnia senden:
query GetDeity {
deity ( name : " Morpheus " ) {
fullName
power
}
}Unsere Frage wird gelöst!
{
"data" : {
"deity" : {
"fullName" : " Morpheus " ,
"power" : " Shapeshifting "
}
}
} Wenn Sie daran interessiert sind, eine Morpheus GraphQL -API mit Serverless zu erstellen, sollten Sie sich unser Beispiel in diesem Repository: Mythology-API ansehen. Es ist unser Beispielprojektaufbau mit Morpheus GraphQL und Serverless-Haskell , in dem Sie verschiedene Mythologiezeichen mit GraphiQL abfragen können.
Die Mythologie -API wird auf: api.morpheugraphql.com bereitgestellt, wo Sie sie mit GraphiQL testen können
Im Folgenden finden Sie die Liste der Projekte, die Morpheus GraphQL verwenden. Wenn Sie Morpheus GraphQL verwenden möchten, sind sie zunächst gute Vorlagen.
Bearbeiten Sie diesen Abschnitt und senden Sie PR, wenn Sie Ihr Projekt teilen möchten .
Morpheus ist der griechische Gott des Schlafes und der Träume, deren Name aus dem griechischen Wort μορφή bedeutet, was Form oder Form bedeutet. Er soll in der Lage sein, verschiedene Formen nachzuahmen, und GraphQL ist gut darin, genau das zu tun: Daten in der Form vieler verschiedener APIs zu transformieren.
Morpheus wird von Nalchevanidze geschrieben und gepflegt