GithubHelp home page GithubHelp logo

input-output-hk / morpheus-graphql Goto Github PK

View Code? Open in Web Editor NEW

This project forked from morpheusgraphql/morpheus-graphql

0.0 2.0 0.0 2.51 MB

Haskell GraphQL library

Home Page: https://morpheusgraphql.com

License: MIT License

Haskell 100.00%

morpheus-graphql's Introduction

Morpheus GraphQL

Build GraphQL APIs with your favourite functional language!

Morpheus GraphQL 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 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.

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-12.0 # or greater
extra-deps:
  - morpheus-graphql-0.0.1

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

Building your first API

To define a GraphQL API with Morpheus we start by defining the API Schema as a native Haskell data type, which derives the Genericand GQLQuery typeclasses. Lazily resolvable fields on this Query type are defined via the infix type ::->, representing resolving a set of arguments () to a concrete value.

data Query = Query
  { deity :: DeityArgs ::-> Deity
  } deriving (Generic , GQLQuery)
  
data Deity = Deity
  { fullname  :: Text          -- Non-Nullable Field
  , power     :: Maybe Text    -- Nullable Field
  } deriving (Generic, GQLKind, GQLObject, Typeable)
  
data DeityArgs = DeityArgs
  { name      :: Text        -- Required Argument
  , mythology :: Maybe Text  -- Optional Argument
  } deriving (Generic , GQLArgs)

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

resolveDeity :: DeityArgs ::-> Deity
resolveDeity = Resolver $ \args -> askDB (name args) (mythology args)

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

Note that the infix type a ::-> b is just syntactic sugar for Resolver (a -> IO (Either String b))

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

gqlApi :: ByteString -> IO ByteString
gqlApi = interpreter
    GQLRoot {
      query = Query {
        deity = resolveDeity
      },
      mutation = (),
      subscription = ()
    }

As you can see, the API is defined as ByteString -> IO ByteString which we can either invoke directly or use inside an arbitrary web framework such 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

Advanced topics

Enums

You can use Union Types as Enums, but they're not allowed to have any parameters. Wrap them with EnumOf inside your GQLType definition.

data City
  = Athens
  | Sparta
  | Corinth
  | Delphi
  | Argos
  deriving (Show, Generic, Typeable, GQLKind, GQLEnum)

data SomeGQLType = SomeGQLType
  { ...
  , city  :: EnumOf City
  } deriving ...

Scalar types

To use custom scalar types, you need to provide implementations for parseValue and serialize respectively. Wrap them with ScalarOf inside your GQLType definition.

data Odd = Int deriving (Show, Data, Generic, GQLKind)

instance GQLScalar Odd where
  parseValue (Int x) = pure $ Odd (...  )
  parseValue (String x) = pure $ Odd (...  )
  serialize  (Odd value) = Int value

data SomeGQLType = SomeGQLType { ...
 count :: ScalarOf Odd
} deriving ...

Introspection

Morpheus converts your schema to a GraphQL introspection automatically. You can use tools like Insomnia to take a look at the introspection and validate your schema. If you need a description for your GQLType inside of the introspection you can define the GQLKind instance manually and provide an implementation for the description function:

data Deity = Deity
{ ...
} deriving (Show, Generic, Data, GQLObject)

instance GQLKind Deity where
  description = const "A supernatural being considered divine and sacred"

screenshots from Insomnia

alt text alt text alt text

Mutations

In addition to queries, Morpheus also supports mutations. The behave just like regular queries and are defined similarly: Just exchange deriving GQLQuery for GQLMutation and declare them separately at the GQLRoot definition

newtype Mutation = Mutation
  { createDeity :: Form ::-> Deity
  } deriving (Show, Generic, Data, GQLMutation)

createDeityMutation :: Form ::-> Deity
createDeityMutation = ...

gqlApi :: ByteString -> IO ByteString
gqlApi = interpreter
  GQLRoot {
    query = Query {...},
    mutation = Mutation {
       createDeity = createDeityMutation
    },
    subscription = ()
  }

Subscriptions

TODO.

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 shape of many different APIs.

Team

Morpheus is written and maintained by nalchevanidze and PygmalionPolymorph.

Roadmap

  • Medium future:
    • Stabilize API
    • Specification-isomorphic introspection
    • Specification-isomorphic error handling
  • Long term:
    • Support all possible GQL features: Aliases, Unions, etc.
    • Performance optimization

morpheus-graphql's People

Contributors

krisajenkins avatar msvbg avatar nalchevanidze avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.