Code Monkey home page Code Monkey logo

dotansimha / graphql-yoga Goto Github PK

View Code? Open in Web Editor NEW
8.1K 73.0 561.0 54.23 MB

🧘 Rewrite of a fully-featured GraphQL Server with focus on easy setup, performance & great developer experience. The core of Yoga implements WHATWG Fetch API and can run/deploy on any JS environment.

Home Page: https://the-guild.dev/graphql/yoga-server

License: MIT License

TypeScript 60.96% JavaScript 1.44% CSS 0.01% Shell 0.01% HTML 1.76% MDX 35.82%
graphql graphql-server javascript typescript w3c fetch whatwg nodejs bun deno

graphql-yoga's Introduction

GraphQL Yoga

Fully-featured GraphQL Server with focus on easy setup, performance & great developer experience
Go to documenation

npm bundlephobia minified size bundlephobia minified+zipped size bundlephobia treeshaking license

Quick start

Install

pnpm add graphql-yoga graphql

Start

Make a schema, create Yoga and start a Node server:

import { createServer } from 'node:http'
import { createSchema, createYoga } from 'graphql-yoga'

const yoga = createYoga({
  schema: createSchema({
    typeDefs: /* GraphQL */ `
      type Query {
        hello: String
      }
    `,
    resolvers: {
      Query: {
        hello: () => 'Hello from Yoga!'
      }
    }
  })
})

const server = createServer(yoga)

server.listen(4000, () => {
  console.info('Server is running on http://localhost:4000/graphql')
})

Overview

  • Easiest way to run a GraphQL server: Sensible defaults & includes everything you need with minimal setup (we also export a platform/env-agnostic handler so you can build your own wrappers easily).
  • Includes Subscriptions: Built-in support for GraphQL subscriptions using Server-Sent Events.
  • Compatible: Works with all GraphQL clients (Apollo, Relay, Urql...) and fits seamless in your GraphQL workflow.
  • WHATWG Fetch API: the core package depends on WHATWG Fetch API so it can run and deploy on any environment (Serverless, Workers, Deno, Node).
  • Easily Extendable: New GraphQL-Yoga support all envelop plugins.

Our documentation website will help you get started.

We've made sure developers can quickly start with GraphQL Yoga by providing a comprehensive set of examples. See all of them in the examples/ folder.

Read more about how GraphQL Yoga compares to other servers in the ecosystem here.

Contributing

If this is your first time contributing to this project, please do read our Contributor Workflow Guide before you get started off.

For this project in particular, to get started on stage/2-failing-test:

  1. Install Node.js
  2. Run in your terminal: npm i -g pnpm@8 && pnpm install && pnpm build
  3. Add tests to packages/graphql-yoga/__tests__ using Jest APIs
  4. Run the tests with pnpm test

Feel free to open issues and pull requests. We're always welcome support from the community.

Code of Conduct

Help us keep Yoga open and inclusive. Please read and follow our Code of Conduct as adopted from Contributor Covenant.

License

MIT

graphql-yoga's People

Contributors

0xdaksh avatar al1l avatar ardatan avatar charlypoly avatar dimamachina avatar dotansimha avatar eduardomoroni avatar emrysmyrddin avatar enisdenjo avatar fabien0102 avatar giautm avatar gilgardosh avatar github-actions[bot] avatar jycouet avatar kachkaev avatar kbrandwijk avatar lfades avatar maticzav avatar n1ru4l avatar nikolasburk avatar notrab avatar renovate-bot avatar renovate[bot] avatar saihaj avatar schickling avatar theguild-bot avatar timsuchanek avatar trixobird avatar tuvalsimha avatar urigo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql-yoga's Issues

Expose express library to end users?

I would like to serve my build/dist folder for my static assets when developing/deploying to now or any server. For that I need to install express again and use the static function from there.
It would be great if graphql-yoga had this inbuilt for my static assets otherwise it would good enough to re-export the express library for public use.

This is what I'm doing now

import express from 'express';
server.express.use(express.static('dist'));

Something like this would be more easier,

import GraphQLYoga from 'graphql-yoga';
const { GraphQLServer, express } = GraphQLYoga;

const server = new GraphQLServer({ typeDefs, resolvers, options })
server.express.use(express.static('dist'));

else more like this,

const server = new GraphQLServer({ typeDefs, resolvers, options: {
  static: 'dist',
 }});

BTW Great library. I had the same amount of code throughout my projects. This unifies it and also the apollo-upload-server is a plus that too it got recently released too.

Yoga options redesign

Yoga options redesign

Currently, yoga has the following options:

typeDefs?: string
resolvers?: IResolvers
schema?: GraphQLSchema
context?: Context | ContextCallback
cors?: CorsOptions | false
disableSubscriptions?: boolean
tracing?: boolean | TracingOptions
port?: number
endpoint?: string
subscriptionsEndpoint?: string
playgroundEndpoint?: string
disablePlayground?: boolean
uploads?: UploadOptions

These options can all be passed in to the constructor of the server.
Then there are the following apollo-server options that are not available yet:

rootValue?
formatError?
validationRules?
formatParams?
formatResponse?

Looking at these options, there are basically three categories of options:

  1. Server options
    • cors
    • port
    • routes:
      • endpoint?: string
      • subscriptionsEndpoint?: string
      • playgroundEndpoint?: string
  2. GraphQL options
    • schema: GraphQLSchema | { typeDefs, resolvers }
    • context
    • runtime:
      • tracing
      • rootValue?
      • formatError?
      • validationRules?
      • formatParams?
      • formatResponse?
  3. Features
    • playground true | false
    • uploads { ... }
    • subscriptions true | false

Some of these are needed to set up the server (so at constructor time), others might be easier to set when starting the server (after applying your own logic). I'm not really sure yet how that division should work. I'll update this issue with more ideas. Please share your feedback too!

Error: Field Query.user can only be defined once

When upgrading from 0.8.0 -> 1.x.x, I run into a number of errors when running a Query or Mutation:

Error: Field Query.user can only be defined once.

Field Query.class can only be defined once.

Field Query.classroom can only be defined once.

Field Mutation.updateUser can only be defined once.

Field Mutation.createClass can only be defined once.

Field Mutation.updateClass can only be defined once.

Field Mutation.deleteClass can only be defined once.

Field Mutation.createClassroom can only be defined once.

Field Mutation.updateClassroom can only be defined once.

Field Mutation.createMessage can only be defined once

Here's my server config:

const { GraphQLServer } = require('graphql-yoga')
const { Prisma } = require('prisma-binding')

const resolvers = require('./resolvers')

const server = new GraphQLServer({
  typeDefs: 'src/schema.graphql',
  resolvers,
  context: req => ({
    ...req,
    db: new Prisma({
      typeDefs: 'schemas/prisma.graphql',
      endpoint: process.env.PRISMA_ENDPOINT,
      secret: process.env.PRISMA_SECRET,
      debug: true,
    }),
  }),
})

server.start(() => {
  console.log('Server is running on http://localhost:4000')
})

I'm having a hard time identifying where the issue may be stemming from.

Playground subscription

Playground subscription seem to search on ws(s) endpoint property

Search in ws(s)://ip:port/graphql KO

const options = {
  disableSubscriptions: false,  // same as default value
  port: 8000,
  endpoint: '/graphql',
  subscriptionsEndpoint: '/subscriptions',
  playgroundEndpoint: '/playground',
  disablePlayground: false      // same as default value
}

Search in ws(s)://ip:port/ OK

const options = {
  disableSubscriptions: false,  // same as default value
  port: 8000,
  endpoint: '/',
  subscriptionsEndpoint: '/',
  playgroundEndpoint: '/',
  disablePlayground: false      // same as default value
}

Use graphql extensions to provide information about bindings in server response

There was a discussion a while ago about how to visualize the composition of a GraphQL server that uses multiple bindings. This proposal addresses this issue.

What information to provide

A 'best practice' GraphQL server uses a single schema, and using delegation in the resolvers to delegate queries and mutations to 1 or more bindings (back-end GraphQL endpoints). During development and testing, it would be great to know:

  • What binding(s) the different parts of a query response come from
  • Which connection settings where used for a binding

How to provide this information

The GraphQL spec allows extensions to be added to a server response. Tracing and cache control already use these extensions to provide additional information. I would propose to also use extension information to provide information about the bindings.
A sample bindings extension object could look like this:

bindings: [
  { 
    "path": ["post, "comments"],
    "binding": {
      "name": "mydatasource",
      "endpoint": "http://api.graph.cool/mydatasource/dev"
    }
  }
]

The path specification is identical to the cache control extension (for a uniform approach). Endpoint information will not always be easily available though. Graphcool bindings provide an explicit endpoint. Generic bindings provide an executableSchema, so that information might not be available at all. One option might be creating an apollo-link variation that supports keeping track of this. Another, more generic solution, might be to setup an inline proxy to route all outgoing traffic through, so the hosts can be gathered (this is a commonly used setup in express).

How to visualize this information

This information could be used by graphql-playground to provide some form of visual representation. This can be discussed further in the graphql-playground repo.

How to use union types with graphql-yoga?

Hi, is there any support for union types yet in graphql-yoga? It seems to need a resolveType function to determine the actual type of an object at runtime. I couldn't find any place refering to supporting this so far.

Taking this opportunity to express my deep admiration for the work you guys at graphcool have been doing. Amazing developer experience across the board since the release of the graphcool framework, and really excited at what the stack is becoming with native gql db + yoga as api gateway πŸ‘.

Yoga using [email protected] since v4.0.0 causes warnings

Yoga has switched to [email protected] since v4.0.0, but several dependencies still require previous versions, causing warning such as these:

with 0.4.0:

npm WARN [email protected] requires a peer of graphql@^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.

with 0.4.2:

npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.

with 0.4.3

npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of graphql@^0.10.0 || ^0.11.0 but none is installed. You must install peer dependencies yourself.

What's the best course of actions here? Downgrade Yoga's dependency back to [email protected]?

Allow passing in path to .graphql file for typeDefs

In most scenarios, the type definitions for the server live in their own .graphql file (best practices from the boilerplates). It would be convenient to pass in the file path, instead of having to load the file first, and pass in the contents to typeDefs.

This could be implemented either as a separate parameter (typeDefsPath?) or by reusing typeDefs.

Allow to access built-in schema

I want to attach directives to schema resolvers, one way to do this is manual setup schema and pass it to GraphQL server (to much imports are required). Easy way is allow to accees schema.

Remove bundling from yoga?

Currently, yoga supports schema bundling out of the box. This is nice, but it creates a lot of dependencies. And it feels a bit like Express running Webpack for you. It think there is a clear pattern emerging that you use graphql-cli and its config file to configure and run bundling on your schemas to process imports, and this task should no longer be included in yoga.

console.log not called in server.start callback

This issue appears with the switch from 0.9.0 to 1.0.0

I'm using graphcool beta and my server is defined in index.js which looks like this:

server.start(() => console.log("Server is running on http://localhost:4000"));

with graphql-yoga 0.9.0, I call yarn start and it prints the message as expected. In 1.0.0 it does nothing, which looks scary, like my server didn't start, but it did.

README.md of examples not updated

examples/hello-world/README.md

- server.start(4000, () => console.log('Server is running on localhost:4000'))
+ server.start(() => console.log('Server is running on localhost:4000'))

examples/subscriptions/README.md

- server.start(4000, () => console.log('Server is running on localhost:4000'))
+ server.start(() => console.log('Server is running on localhost:4000'))

Easily support multiple endpoints

It would be nice if there was an easy way to support multiple endpoints. This could be possible by allowing an array of option objects instead of just a single one, and creating Express endpoints for each of them.
Use cases for this include a admin endpoint, separate anonymous/authenticated endpoints and general flexibility.

Implement after hook or error handling?

Right now I generate and start a transaction in the context function and if the graphql request fails due to an error I would like inspect the result if it has any errors and based on that to rollback/commit the transaction. It would be nice if we could have a function similar to context but gets called after the graphql function to clean up connections/log stuff etc.

It seems apollo-server-express already exposes this in the options
If there could be some way we can pass the apollo server options directly to it using yoga for customizing the apollo server used underneath.

Schema is not configured for subscriptions

I am trying to mash up a simple subscriptions server stitching several different schemas

For reference:
https://www.apollographql.com/docs/graphql-tools/generate-schema.html#modularizing
https://github.com/apollographql/graphql-tools/blob/master/docs/source/schema-stitching.md#adding-resolvers-between-schemas

It all works fine with regular queries and mutations and I get expected results. However subscriptions do not seem comply and after stitching together I get "Schema is not configured for subscriptions"

{
  "data": null,
  "error": [
    {
      "message": "Schema is not configured for subscriptions.",
      "locations": [
        {
          "line": 1,
          "column": 1
        }
      ]
    }
  ]
}

Not sure if this is graphql-yoga or graphql-tools related...?

API requests fail with: Invalid options provided to ApolloServer

The last release seems to be broken. I was creating and starting my yoga server as follows:

const server = new GraphQLServer({
  typeDefs,
  resolvers,
  context: req => ({
    ...req,
    db: new Graphcool({
      schemaPath: './database/schema.graphql',
      endpoint: 'http://localhost:60000/api/database/dev',
      secret: 'mysecret123',
    }),
  }),
})
server.start(() => console.log('Server is running on http://localhost:4000'))

However, I was not able to access the API on http://localhost:4000, the Playground could not load the schema but failed with an internal server error and the message: Invalid options provided to ApolloServer:.

Rolling back to version 0.3.0 fixed the problem.

DateTime, Date, Time, JSON - scalars proposal

What do you think to add those scalars out of the box:
DateTime, Date, Time, JSON

and make it configurable to disable them.

I think I will need them in all of my apps, especially DateTime.

If you think it's good idea I can send PR.

Typescript example

Hello,

It should be awesome to have a typescript example in this repository (I have some issues with the resolvers types for example…).

Authentication

Would be cool to have an example that shows how to set up auth with passport, maybe with JWT. Even cooler if it was in the framework.

Startup validation

There are two areas where startup validation can be improved:

  • Parsing the options that were passed in (mainly for JS)
  • Validation the executable schema (no resolvers missing etc.)

This prevents errors on first query execution.

Init an demo locally according to the instruction in Graphcool Docs, encounter such error after 'prisma deploy' command

ERROR: Whoops. Looks like an internal server error. Please contact us from the Console (https://console.graph.cool) or via email ([email protected]) and include your Request ID: cluster:cluster:cjch2waig00040107kr7kcw5o

{
"data": {
"addProject": null
},
"errors": [
{
"message": "Whoops. Looks like an internal server error. Please contact us from the Console (https://console.graph.cool) or via email ([email protected]) and include your Request ID: cluster:cluster:cjch2waig00040107kr7kcw5o",
"path": [
"addProject"
],
"locations": [
{
"line": 2,
"column": 9
}
],
"requestId": "cluster:cluster:cjch2waig00040107kr7kcw5o"
}
],
"status": 200
}

return http server from .start

Hi,

I'm running some unit tests with yoga and I'd like to close the server programatically but the http server isn't accessible, and express doesn't offer .close(). Would you be open to a pr that adds the httpServer as a property? or is there a better way to achieve this result?

Ability / documentation to add Apollo Engine

There is a rather lengthy list of steps to add Apollo Engine to an Apollo Express server. I think this is a great opportunity to abstract those steps into something much easier to implement.

Update docs for context option

The readme shows that context is an object type but it also accepts a function. I found that out by reading the source code as I needed to intialize a new context object on every request. Its better if it would be a function always as the context is generally per graphql request.

Fail if context promise rejected

Hey,
Currently, errors are ignored when resolving the context. I think the context function would be a great way to for example do authentication by verifying a JWT token or to connect to the database.

Catching these and let lambda throw an error would be way better to just continue the request.

getRemoteSchema - function proposal

I think it would be useful to have such function in graphql-yoga:

export async function getRemoteSchema(uri) {
    const link = new HttpLink({ uri, fetch })
    const introspectionSchema = await introspectSchema(link);
    const graphcoolSchema = makeRemoteExecutableSchema({
        schema: introspectionSchema,
        link
    });

    return graphcoolSchema;
}

To create easily remote schemas and merge them all.

What do you think?

apollo-react error in fullstack example project

There is an error that happened due a confusion in port numbers, after running the server, the console outputs Server is running on localhost:4000, and the frontend part built with react-apollo is configured to fetch GraphQL data from localhost:4000:

const httpLink = new HttpLink({ uri: 'http://localhost:4000' })

but there is no configuration to tell the server to run on port 4000, so the server will run on the default port 3000:

// the server will run on port 3000
const server = new GraphQLServer({ typeDefs, resolvers })

// the fix
const options = { port: 4000 }
const server = new GraphQLServer({ typeDefs, resolvers, options })
server.start(() => console.log('Server is running on localhost:' + options.port))

I will create a pull request and mention this issue to fix it.

How to get nested fields arguments?

Hello,
I have a small and possible simple question about access to nested field arguments
Types:

  type NestedField  {
    value: String!
  }
  type Example {
    nestedField(arg: Int!): NestedField
  }

  type Query {
    getExample: Example!
  }

Query:

{
  getExample {
    nestedField(arg: 1) {
      value
    }
  }
}

Resolvers:

const resolvers = {
  Query: {
    getExample(_, args) {
      console.log('============================================');
      console.log(JSON.stringify(args, null, 2));
      return {
        nestedField: {
          value: 'test'
        }
      };
    }
  }
};

In args I have an empty object, but I checked query itself contains data about an argument. How can I get access to it in my resolver? Thanks!

AWS Lambda support

I've been prototyping an API to use with AWS Lambda and this is a basic example of what it could look like:

import { GraphQLLambda } from 'graphql-yoga';

const typeDefs = `
    type Query {
        hello(name: String): String!
    }
`;

const resolvers = {
    Query: {
        hello: (_, { name}) => `Hello ${name || 'World'}`,
    },
}

const handler = new GraphQLLambda({ typeDefs, resolvers });

export const graphql = handler.graphql;
export const playground = handler.playground;

The implementation would be simple to put together for basic use cases, but subscriptions and file-upload would be missing. Binary file-upload is possible already with AWS lambda through API gateway, but if you're using serverless framework (which I imagine most people are), it doesn't currently support it as a configuration option. I'll likely open an issue with serverless to add binary pass-through as an option. Following that, apollo-upload-server would also need lambda support, but that is a trivial addition that I can do.

Subscriptions are the one feature that cannot be entirely handled in lambda. What works instead is having a separate subscription server using express graphql-yoga or some other http server with websocket support and then use remoteSchemaStitching to then have the subscription server resolve queries through the lambda interface.

Looking for some feedback on this approach before anything gets implemented. Thanks!

GraphQLServer Endpoint Option Doesn't Take

Summary

When I pass in server options for endpoint, it doesn't seem to have any effect.

Code


const { GraphQLServer } = require('graphql-yoga')

const typeDefs = `
  type Query {
    hello(name: String): String!
  }
`

const resolvers = {
  Query: {
    hello: (_, { name }) => `Hello ${name || 'World'}`,
  },
}

const options = {
    port: 4000,
    endpoint: '/graphql',
}

const server = new GraphQLServer({ typeDefs, resolvers, options })
server.start(() => console.log(`Server is running on http://localhost:${options.port}${options.endpoint}`))

Expected Result

I expect to go to http://localhost:4000/graphql and see the playground

Actual Result

I get the playground at http://localhost:4000 (without the /graphql path)

Multi-project playground no longer works (based on NODE_ENV=dev)

This commit: a49583a

I don't want to have to start 2 webservers to be able to do it now and in my opinion it's a better option to educate the users instead of taking things away so you can't do anything wrong.

i.e. one solution would be a (big) warning in the console if NODE_ENV is set to dev, which should never happen in production

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.