当前位置: 首页 > 软件库 > 大数据 > 数据查询 >

morpheus-graphql

Haskell GraphQL Api, Client and Tools
授权协议 MIT License
开发语言 Java
所属分类 大数据、 数据查询
软件类型 开源软件
地区 不详
投 递 者 段干浩荡
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

Morpheus GraphQL CI

Build GraphQL APIs with your favorite functional language!

Morpheus GraphQL (Server & Client) helps you to build GraphQL APIs in Haskell with native Haskell types.Morpheus will convert your Haskell types to a GraphQL schema and all your resolvers are just native Haskell functions. Morpheus GraphQL can also convert your GraphQL Schema or Query to Haskell types and validate them in compile time.

Morpheus is still in an early stage of development, so any feedback is more than welcome, and we appreciate any contribution!Just open an issue here on GitHub, or join our Slack channel to get in touch.

Please note that this readme file provides only a brief introduction to the library. If you are interested in more advanced topics, visit Docs.

Getting Started

Setup

To get started with Morpheus, you first need to add it to your project's dependencies, as follows (assuming you're using hpack):

package.yml

dependencies:
  - morpheus-graphql

Additionally, you should tell stack which version to pick:

stack.yml

resolver: lts-16.2

extra-deps:
  - morpheus-graphql-0.17.0
  - morpheus-graphql-app-0.17.0
  - morpheus-graphql-core-0.17.0

As Morpheus is quite new, make sure stack can find morpheus-graphql by running stack upgrade and stack update

Building your first GraphQL API

with GraphQL syntax

schema.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 Generates types: Query , Deity, DeityArgs, that can be used by rootResolver

descriptions and deprecations will be displayed in introspection.

importGQLDocumentWithNamespace will generate Types with namespaced fields. If you don't need namespace use importGQLDocument

with Native Haskell Types

To define a GraphQL API with Morpheus we start by defining the API Schema as a native Haskell data type,which derives the Generic type class. Using the DeriveAnyClass language extension we then also derive instances for the GQLType type class. Lazily resolvable fields on this Query type are defined via a -> ResolverQ () IO b, representing resolving a set of arguments a to a concrete value 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)

For each field in the Query type defined via a -> m b (like deity) we will define a resolver implementation that provides the values during runtime by referring tosome data source, e.g. a database or another API. Fields that are defined without a -> m b you can just provide a value.

In above example, the field of DeityArgs could also be named using reserved identities (such as: type, where, etc), in order to avoid conflict, a prime symbol (') must be attached. For example, you can have:

data DeityArgs = DeityArgs
  { name      :: Text        -- Required Argument
  , mythology :: Maybe Text  -- Optional Argument
  , type'     :: Text
  } deriving (Generic, GQLType)

The field name in the final request will be type instead of type'. The Morpheus request parser converts each of the reserved identities in Haskell 2010 to their corresponding names internally. This also applies to selections.

resolveDeity :: DeityArgs -> ResolverQ () IO Deity
resolveDeity DeityArgs { name, mythology } = liftEither $ dbDeity name mythology

askDB :: Text -> Maybe Text -> IO (Either String Deity)
askDB = ...

To make this Query type available as an API, we define a RootResolver and feed it to the Morpheus interpreter. A RootResolver consists of query, mutation and subscription definitions, while we omit the latter for this example:

rootResolver :: RootResolver IO () Query Undefined Undefined
rootResolver =
  RootResolver
    { queryResolver = Query {deity = resolveDeity}
    , mutationResolver = Undefined
    , subscriptionResolver = Undefined
    }

gqlApi :: ByteString -> IO ByteString
gqlApi = interpreter rootResolver

As you can see, the API is defined as ByteString -> IO ByteString which we can either invoke directly or use inside an arbitrary web frameworksuch as scotty or serverless-haskell. We'll go for scotty in this example:

main :: IO ()
main = scotty 3000 $ post "/api" $ raw =<< (liftIO . gqlApi =<< body)

If we now send a POST request to http://localhost:3000/api with a GraphQL Query as body for example in a tool like Insomnia:

query GetDeity {
  deity (name: "Morpheus") {
    fullName
    power
  }
}

our query will be resolved!

{
  "data": {
    "deity": {
      "fullName": "Morpheus",
      "power": "Shapeshifting"
    }
  }
}

Serverless Example

If you are interested in creating a Morpheus GraphQL API with Serverless, you should take a look at our example in this repository:Mythology API it is our example project build with Morpheus GraphQL and Serverless-Haskell,where you can query different mythology characters with GraphiQL.

Mythology API is deployed on : api.morpheusgraphql.com where you can test it with GraphiQL

Mythology Api

Showcase

Below are the list of projects using Morpheus GraphQL. If you want to start using Morpheus GraphQL, they aregood templates to begin with.

Edit this section and send PR if you want to share your project.

About

The name

Morpheus is the greek god of sleep and dreams whose name comes from the greek word μορφή meaning form or shape.He is said to be able to mimic different forms and GraphQL is good at doing exactly that: Transforming data in the shapeof many different APIs.

Team

Morpheus is written and maintained by nalchevanidze

Roadmap

  • Medium future:
    • Stabilize API
    • Specification-isomorphic error handling
  • Long term:
    • Support all possible GQL features
    • Performance optimization
 相关资料
  • Morpheus 是用 React.js 创建的新一代 web 发布平台。 Morpheus 在第一次加载完全是在服务器端渲染。当一切完成后,React 会将事件连接到 DOM 上,这样,用户就能享受到单页应用程序的好处,在看到内容之前无需等待漫长乏味的 spinners 。 特性: 帖子和页面展示,markdown 渲染,帖子分页 服务器端渲染 Disqus 管理评论 配置固定链接 火力全开的自

  • SVG Morpheus 是 JavaScript 库,允许 SVG 图标变形成另外一个 SVG 图标,实现了 Material Design 的 Delightful Details 转换。 在线演示