Giter Site home page Giter Site logo
apollo-server

apollographql / apollo-server Goto Github PK

View Code? Open in 1sVSCode Editor NEW
12.7K 212.0 1.9K 114.99 MB

🌍  Spec-compliant and production ready JavaScript GraphQL server that lets you develop in a schema-first way. Built for Express, Connect, Hapi, Koa, and more.

Home Page: https://www.apollographql.com/docs/apollo-server/

License: MIT License

TypeScript 72.13% JavaScript 27.80% Shell 0.07%
graphql graphql-server express-graphql express koa hapi node restify apollographql graphql-schema resolvers

apollo-server's Introduction

Apollo Server

A TypeScript GraphQL Server for Express, Koa, Hapi, Lambda, and more.

npm version Build Status Join the community forum Read CHANGELOG

Apollo Server is a community-maintained open-source GraphQL server. It works with many Node.js HTTP server frameworks, or can run on its own with a built-in Express server. Apollo Server works with any GraphQL schema built with GraphQL.js--or define a schema's type definitions using schema definition language (SDL).

Read the documentation for information on getting started and many other use cases and follow the CHANGELOG for updates.

Principles

Apollo Server is built with the following principles in mind:

  • By the community, for the community: Its development is driven by the needs of developers.
  • Simplicity: By keeping things simple, it is more secure and easier to implement and contribute.
  • Performance: It is well-tested and production-ready.

Anyone is welcome to contribute to Apollo Server, just read CONTRIBUTING.md, take a look at the roadmap and make your first PR!

Getting started

To get started with Apollo Server:

  • Install with npm install apollo-server-<integration> graphql
  • Write a GraphQL schema
  • Use one of the following snippets

There are two ways to install Apollo Server:

  • Standalone: For applications that do not require an existing web framework, use the apollo-server package.
  • Integrations: For applications with a web framework (e.g. express, koa, hapi, etc.), use the appropriate Apollo Server integration package.

For more info, please refer to the Apollo Server docs.

Installation: Standalone

In a new project, install the apollo-server and graphql dependencies using:

npm install apollo-server graphql

Then, create an index.js which defines the schema and its functionality (i.e. resolvers):

const { ApolloServer, gql } = require('apollo-server');

// The GraphQL schema
const typeDefs = gql`
  type Query {
    "A simple type for getting started!"
    hello: String
  }
`;

// A map of functions which return data for the schema.
const resolvers = {
  Query: {
    hello: () => 'world',
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

Due to its human-readability, we recommend using schema-definition language (SDL) to define a GraphQL schema--a GraphQLSchema object from graphql-js can also be specified instead of typeDefs and resolvers using the schema property:

const server = new ApolloServer({
  schema: ...
});

Finally, start the server using node index.js and go to the URL returned on the console.

For more details, check out the Apollo Server Getting Started guide and the fullstack tutorial.

For questions, the Apollo community forum is a great place to get help.

Installation: Integrations

While the standalone installation above can be used without making a decision about which web framework to use, the Apollo Server integration packages are paired with specific web frameworks (e.g. Express, Koa, hapi).

The following web frameworks have Apollo Server integrations, and each of these linked integrations has its own installation instructions and examples on its package README.md:

Context

A request context is available for each request. When context is defined as a function, it will be called on each request and will receive an object containing a req property, which represents the request itself.

By returning an object from the context function, it will be available as the third positional parameter of the resolvers:

new ApolloServer({
  typeDefs,
  resolvers: {
    Query: {
      books: (parent, args, context, info) => {
        console.log(context.myProperty); // Will be `true`!
        return books;
      },
    }
  },
  context: async ({ req }) => {
    return {
      myProperty: true
    };
  },
})

Documentation

The Apollo Server documentation contains additional details on how to get started with GraphQL and Apollo Server.

The raw Markdown source of the documentation is available within the docs/ directory of this monorepo--to contribute, please use the Edit on GitHub buttons at the bottom of each page.

Development

If you wish to develop or contribute to Apollo Server, we suggest the following:

  • Fork this repository

  • Install Direnv (a tool that automatically sets up environment variables in project directories) or nvm. We use nvm to ensure we're running the expected version of Node (and we use Direnv to install and run nvm automatically).

  • Install the Apollo Server project on your computer

git clone https://github.com/[your-user]/apollo-server
cd apollo-server
direnv allow  # sets up nvm for you; if you installed nvm yourself, try `nvm install` instead
  • Build and test
npm install
npm test
  • To run individual test files, run npm run pretest && npx jest packages/apollo-server-foo/src/__tests__/bar.test.ts. Note that you do need to re-compile TypeScript before each time you run a test, or changes across packages may not be picked up. Instead of running npm run pretest from scratch before each test run, you can also run tsc --build tsconfig.json --watch in another shell, or use the VSCode Run Build Task to run that for you.

Community

Are you stuck? Want to contribute? Come visit us in the Apollo community forum!

Maintainers

Who is Apollo?

Apollo builds open-source software and a graph platform to unify GraphQL across your apps and services. We help you ship faster with:

  • Apollo Studio – A free, end-to-end platform for managing your GraphQL lifecycle. Track your GraphQL schemas in a hosted registry to create a source of truth for everything in your graph. Studio provides an IDE (Apollo Explorer) so you can explore data, collaborate on queries, observe usage, and safely make schema changes.
  • Apollo Federation – The industry-standard open architecture for building a distributed graph. Use Apollo’s gateway to compose a unified graph from multiple subgraphs, determine a query plan, and route requests across your services.
  • Apollo Client – The most popular GraphQL client for the web. Apollo also builds and maintains Apollo iOS and Apollo Android.
  • Apollo Server – A production-ready JavaScript GraphQL server that connects to any microservice, API, or database. Compatible with all popular JavaScript frameworks and deployable in serverless environments.

Learn how to build with Apollo

Check out the Odyssey learning platform, the perfect place to start your GraphQL journey with videos and interactive code challenges. Join the Apollo Community to interact with and get technical help from the GraphQL community.

apollo-server's People

Contributors

abernix avatar renovate[bot] avatar glasser avatar renovate-bot avatar evans avatar martijnwalraven avatar trevor-scheer avatar helfer avatar StephenBarlow avatar trevorblades avatar DxCx avatar cheapsteak avatar stubailo avatar nnance avatar jbaxleyiii avatar unicodeveloper avatar JakeDawkins avatar sachindshinde avatar addityasingh avatar greenkeeperio-bot avatar rkoron007 avatar zionts avatar Urigo avatar peggyrayzis avatar greenkeeper[bot] avatar freiksenet avatar nicolaslopezj avatar jsegaran avatar hwillson avatar IvanGoncharov avatar

Stargazers

Aykut Kilic avatar Somenath Choudhury avatar  avatar Orell Bühler avatar Autumn Yarborough-Cain avatar  avatar seanmamasde avatar Dean Friedland avatar Kevin Long avatar Hiran Ferreti Baccos avatar Pasindu Dilshan avatar peibin avatar  avatar Xolo avatar Felipe Luis avatar Furkan Gulsen avatar Kittipod Lambangchang avatar  avatar  avatar  avatar Mohamed Amine Fhal avatar Steven Bui avatar Jaimy Michiels avatar Jake Zhang avatar Adnan Ahmed avatar Christian Keck avatar Thomas avatar Stacy Chen avatar Ivan Zhang avatar Yoav Vainrich avatar William J. C. Nesbitt avatar Mesut Yiğit avatar Ali Goktug Yalcin avatar VarunBoi avatar Javier Pastor Sánchez avatar Mouaad avatar Alexey Sokolov avatar panda avatar Q1 Blue avatar Brent Lapierre avatar siham_amaro avatar Jose Escobar avatar Mak Fof avatar Nazır Doğan avatar Jim avatar Batnasan Byambasuren avatar  avatar  avatar Khemtat Lengpaiboon avatar Hwa Soo Kang avatar Nikolay Angelov avatar Ketut Sandiarsa avatar Nova avatar carimatics avatar Thanos Valimitis avatar  avatar Kai avatar Mr. Mime avatar Muhammed Rahif avatar  avatar Hellon Canella avatar daiwanwei avatar Erica Schulz avatar daweth avatar Thad Guidry avatar 0xgxthxb avatar Adam Smith avatar Alexandr Podoprigora avatar Efrain Peralta avatar Özgün Özdemir avatar  avatar Lukasz Ostrowski avatar Tona avatar Anjaneya Sivan avatar tflin avatar Solomon Hsu avatar  avatar Thomas Carmichael avatar Jaeyeoul Ahn avatar Karim Aljandali avatar Ize avatar Gerson Minichiello avatar KotikVacia avatar  avatar Wiput Pootong avatar  avatar WeiXi Zhang avatar Donny avatar  avatar Edier Heraldo Hernández Molano avatar _.fmendes._ avatar Alexandre Saraiva Moreira avatar Joan Sebastian Diaz del Castillo Posso avatar Richard Scarrott avatar Chandan avatar RyosukeKubota avatar Pedro Mascarenhas avatar Anson Lee avatar  avatar TheErraticDev avatar

Watchers

Ben Newman avatar David Glasser avatar vince avatar Noam  Vergain avatar Ashleigh Crosby avatar Nuba Princigalli avatar Mariusz Nowak avatar Adrian Lawrence avatar Ronald Hötschl avatar Ye Chuah avatar wooley avatar Cristiano Contin avatar Sharlon Balbalosa avatar Phil Prasek avatar Miguel Julio avatar Kevin avatar  avatar Alexey Neyasov avatar Mehdi Lefebvre avatar Yang Leijun avatar Marc Schipperheyn avatar Acellam G avatar Jean-Jacques Dubray avatar Maxim Mai avatar Jake Murzy avatar Martha Kelly Schumann avatar Sandesh Gade avatar Freeman Man avatar Giles avatar Chris Weller avatar Jacky avatar hz2004 avatar Bryn Cooke avatar Adam Torres avatar Cary Landholt avatar James Cloos avatar Shadi Ramadan avatar Alex Gitonga avatar murajun1978 avatar Ram avatar Douglas Eggleton avatar Ajit Singh avatar Sean Langford avatar zhangaz1 avatar Rashid Omar avatar Aleksei Tcelishchev avatar Uri Goldshtein avatar Firdaus Ramlan avatar Leonardo Turbiani avatar s3 avatar Stefan Mitev avatar Ivan Avila avatar Edward Xie avatar zhouguoqing917 avatar NoScripter avatar  avatar  avatar  avatar Namrata Patel avatar Chris Slater avatar timbotnik avatar  avatar Hadar Landao avatar chengzhangHu avatar Radu Alexandru Popescu avatar  avatar teppei shichiri avatar Tuna Aras avatar yang bo avatar sha avatar Fabio Dias Rollo avatar Pasquale Vazzana avatar Alin Porumb avatar Jorge Rodríguez Galán avatar Scott avatar Stephen Barlow avatar  avatar Mike Klein avatar David Miura avatar Kristy avatar Martin Eboh avatar Yared Getachew avatar Joe McLaughlin avatar  avatar Yaacov Rydzinski  avatar Duke avatar  avatar  avatar Abhishek avatar Marc Urbaitel avatar Shaded Pixel LLC avatar Alex Faunt avatar rudy avatar  avatar KoKo Puff avatar Venelin Petkov avatar Deejay Geroso avatar simon avatar CROTEL avatar  avatar

apollo-server's Issues

Typescript

Since the client is written in Typescript, I think it makes sense for server to be as well.

Is application/graphql supported?

I'm guessing that I'm doing something dumb here, but I can't see it :( Would appreciate some pointers!

Requesting via the JSON protocol works great:

> curl -H "Content-Type:application/json" -XPOST -d '{"query": "{ currentUser { id } }"}' http://localhost:3000/graphql
{
  "data": {
    "currentUser": {
      "id": "f9342aa2-7674-4050-9e6c-559f14c46b52"
    }
  }
}

But when I attempt to use the application/graphql protocol, I get:

> curl -H "Content-Type:application/graphql" -XPOST -d "{ currentUser { id } }" http://localhost:3000/graphql
{
  "errors": [
    {
      "message": "Must provide query string."
    }
  ]
}

Defining queries using structured data

I'm just exploring graphql and see existing way of doing requests from client is using string based queries. I see such approach as kinda error prone and unstructured. What are the advantages of this? Do you see any advantages (or maybe obvious disadvantages) if there would be a way in defining queries using json object instead of string?

Kind of:

user: {
  query: {id: 32423},
  fields: [
     'id', `name`, 
     {`profilePicture`: {
        query: {size: '50'}, 
        fields: ['uri', 'weigh', 'height']
     }}
  ]
}

Also I see thy way of defining schema using string based approach is too kind of error prone.

Test coverage

We should make sure all significant logic is covered by tests. Right now the line coverage is close to 100%, but it seems some features aren't tested.

Can't get meteor query result in resolver

root schema and resolver:

const rootSchema = `
   type RootQuery {
    user: User    
   ...
    allFeedbacks: [Feedback]
   }

   schema {
    query: RootQuery
  }
`


RootQuery: {
...

    async allFeedbacks(root, args, context) {
      const allFeedbacks = DB.Feedback.find({patientId: {$exists: 1}}).fetch()
      return await allFeedbacks
    },
...
}

feedback.js

export const schema = `
  type Feedback {
    _id: String
    patient: User
    opinion: String
    reply: String
  }
`;

export const resolvers = {
  Feedback: {
    _id  : ({_id}) => _id,
    patient: async ({patientId}) => {
      return await Meteor.users.findOne({_id:patientId})
    },
    opinion: ({opinion}) => opinion,
    reply: ({reply}) => reply,
  }
};

query in graphiql:
{ allFeedbacks { patient { username } _id opinion reply } }

Got result:

{
"data": {
"allFeedbacks": [
{
"patient": null,
"_id": "nyNP9wh9D5qmZixbn",
"opinion": "tesst",
"reply": "testst"
},
{
"patient": null,
"_id": "WgSoCgTGhHeZasFGQ",
"opinion": "tesst",
"reply": "testst"
},

...
}

It's strange when i test , the resolver could console log PatientId, Meteor, Meteor.users, But can't get the fetched data. I guess the problem is on async, but where is the problem?

Had checked sample repos, followed their pattern but no luck.

Ditching async

Guys, in all your examples you advocate using async with queries on server. Concerning that node 6.x can now run vanilla es2015 it is the only thing that requires transpilation. I tried not to use async call but I was running through poopstorm of problems with fibers and all. What would be a recommended strategy without asyns/await? Would you care to provide functioning example of e.g. a resolver or mutation without async call, for example based on Promises? I tried several startegies and none seems to work.

Meteor/Node version related issue I believe

Hi, I'm having an issue when I import apollo-server into my meteor project.

Below is the error:

/Users/davidyoung/Dev/gobeyond/.meteor/local/build/programs/server/packages/modules.js:41096 const graphql = require('graphql'); ^^^^^ SyntaxError: Use of const in strict mode. at /Users/davidyoung/Dev/gobeyond/.meteor/local/build/programs/server/boot.js:292:30 at Array.forEach (native) at Function._.each._.forEach (/Users/davidyoung/.meteor/packages/meteor-tool/.1.3.5_1.1fnktti++os.osx.x86_64+web.browser+web.cordova/mt-os.osx.x86_64/dev_bundle/server-lib/node_modules/underscore/underscore.js:79:11) at /Users/davidyoung/Dev/gobeyond/.meteor/local/build/programs/server/boot.js:133:5

Any way of sorting this?

Install fails at postinstall script 'typings install && npm dedupe'.

Hi there, jus tried to install through npm and this happened:

I had to install typings to fix it.

> [email protected] postinstall /Users/Empyreal/WebProjects/knex-2/node_modules/apollo-server
> typings install && npm dedupe

sh: typings: command not found
npm WARN enoent ENOENT: no such file or directory, open '/Users/Empyreal/WebProjects/knex-2/node_modules/db/package.json'
npm WARN [email protected] requires a peer of [email protected]^2.9.0 but none was installed.
npm WARN [email protected] requires a peer of [email protected]^1.2.0 but none was installed.
npm WARN [email protected] requires a peer of [email protected]^2.9.0 but none was installed.
npm WARN [email protected] No repository field.
npm ERR! Darwin 15.0.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "i" "-S" "apollo-server"
npm ERR! node v6.3.1
npm ERR! npm  v3.10.3
npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn

npm ERR! [email protected] postinstall: `typings install && npm dedupe`
npm ERR! spawn ENOENT
npm ERR!
npm ERR! Failed at the [email protected] postinstall script 'typings install && npm dedupe'.

Multiple types per field in schema?

Hello guys, I'm making a live music app that shows you who's playing, where and when. I want to enable a field to have two possible types.

There are two types of users that can post "events". Is this type thing possible? If yes, how would you make it work? I have an owner_type column in my database that can be 'artist' or 'venue', but I don't know how I can use it to set the type in Apollo.

type Event {
    owner: Artist || Venue,  // I want to set the type based on a value read from the DB using knex
    venue: Venue,
    artists: [Artist],
}

type Artist {
    events: [Event],
}

type Venue {
    events: [Event],
}

Currently I'm working around this by setting it like this:

type Event {
    owner_id: Int,
    owner_type: String,
    venue: Venue,
    artists: [Artist],
}

Error with `typings.json` when behind a firewall

I'm trying to install apollo-server in my project, but the installation happens in a corporate network that won't let me see type typings repository. The output that I get:

typings ERR! message Unable to connect to "https://api.typings.org/entries/npm/chai/tags/3.5.0%2B20160415060238"
typings ERR! caused by getaddrinfo ENOTFOUND api.typings.org api.typings.org:443

I haven't the foggiest how to fix this one, and the answer may be that I'm out of luck because of the weirdness of our networking stuff, but I figured I'd report it anyway. This one seems somewhat related to #54 in that the typings stuff is run post-install.

How to split schemas into separate files?

userSchema: (author schema like the same)

export const schema = [`
type Email {
address: String
verified: Boolean
}

type User {
emails: [Email]
username: String
randomString: String
}
`];

rootSchema:

import { schema as userSchema, resolvers as userResolver } from './user/schema';
const rootSchema = [`
type RootQuery {
author(name: String): Author
user: User
}

schema {
query: RootQuery
}
`]

export const schema = [...rootSchema, ...userSchema, ...authorSchema];


When I trying to contact schemas into 1 typedefinition in GitHunt way(seems its the only one example had separate schemas), I got this:
[ '\n type RootQuery {\n author(name: String): Author\n user: User\n }\n \n \n schema {\n query: RootQuery\n }\n', I20160704-11:08:53.149(8)? '\n type Email {\n address: String\n verified: Boolean\n }\n \n type User {\n emails: [Email]\n username: String\n randomString: String\n }\n', I20160704-11:08:53.149(8)? '\n# This uses the exact field names returned by the GitHub API for simplicity\ntype Author {\n name: String\n books: [Book]\n }\n \n type Book {\n name: String\n author: [Author]\n \n' ] { RootQuery: { user: [Function: user], author: [Function: author] }

Also I found the generateSchema in docs is deprecated. And I have no idea how to use the GraphQLSchema instance generated.

Simple mutation throw error "Can't wait without a fiber"

RootQuery :{
  ...
// works well 
    async oneFeedback(root, {feedbackId}, context) {
      const feedback = DB.Feedback.findOne({_id: feedbackId})
      return await feedback
    },
}

// mutate nothing but just for test , will throw an error
RootMutation: {
    async changeFeedbackText(root, {feedbackId, text}, context) {
      const feedback = DB.Feedback.findOne({_id: feedbackId})
      return await feedback
    }
// so does this one
   async changeFeedbackText(root, {feedbackId, text}, context) {
      DB.Feedback.update(feedbackId, {$set:{text: text}})
      return DB.Feedback.findOne(feedbackId)
    }
  }

Why same code in query don't throw an error?

Feature Request: graphql Server Chaining

With the current focus on small independent microservices in the REST world it would be good to be able to chain multiple apollo servers together.

For instance you may have a single user repository in the company. A apollo server would expose a graphql endpoint to query and mutate these users.

An app server then needs to query this database for user name and address etc. the app server would expose via proxy a subset of queries from the user repository server with the schema being read from their.

The graphql proxy connector could then have extension points to transform the incoming/outcoming queries and results from the chained server.

__parseLiteral (custom validation) not called when using mutation variables

Hi!

I've added a custom scalar for email, with validation method inside the __parseLiteral function. However, when I use variables, __parseLiteral is not being called and it skips my validation. The value is returned immediately.

This works, runs email validation:

mutation {
  createUser(email: "[email protected]", password: "password") {
    user {
      id
      email
    }
  }
}

This does not work, skips email validation:

mutation($email: Email!, $password: Password!) {
  createUser(email: $email, password: $password) {
    user {
      id
      email
    }
  }
}

Variables sent:

{
  "email": "[email protected]",
  "password": "password"
}

Email scalar type

import {GraphQLError} from 'graphql/error';

import {isEmail} from '../../../utils/validations';

export default {
  __parseValue: (value) => value.toLowerCase(),
  __serialize: (value) => value.toLowerCase(),
  __parseLiteral: ({value}) => {
    if (!isEmail(value)) {
      throw new GraphQLError('Email is not valid.');
    }

    return value.toLowerCase();
  }
};

Really appreciate if you could look into this, thank you. Let me know if you need any more details.

Feature request: Providing an array of resolvers

It would be really great if we could provide an array of resolvers and have them merged. Found myself in a scenario where I wanted to load the regular resolvers, but if the server was started with a certain flag it would load another set of resolvers which would override parts of the regular ones.

Specifically it would be great on the server to be able to provide an array of resolvers like so:

resolvers: [regularResolvers, sandboxResolvers]

In my case I needed sandboxResolvers to overwrite any resolvers with the same name in regularResolvers if a certain flag was set at server startup.

I tried with Object.assign but it didn't work in some situations. I'm doing it with deepmerge NPM for now. Would really appreciate any advice on how to do this in the best way until it's actually implemented as I'm out of my depth somewhat.

GraphiQL endpoint broken after migrating to 0.2? "Apollo Server supports only POST requests"

Hi guys. Thanks for the great work!
My small Apollo server example was working fine at 0.1, but after following the exact migration path to 0.2 and double checking against the Apollo Server GraphiQL docs page, the server no longer seems to serve GraphiQL correctly.

The page: localhost:9090/graphql always returns Apollo Server supports only POST requests and the GraphiQL GUI never shows up.
Now it's unclear to me if both can be at the same endpoint, as stated in both examples in the doc:

graphQLServer.use('/graphql', bodyParser.json(), apolloExpress({
  schema: executableSchema,
}));
graphQLServer.use('/graphiql', graphiqlExpress({
  endpointURL: '/graphql',
}));

but changing the GraphiQL endpoint to '/graphiql' will bring the UI back, but executing any GraphQL example there will still fail.
Thanks

Afterware for express?

Hi guys,

I'm try to implement 304 response to If-None-Match (by etag) from client.
And I need to calculate etag from response body around here if I understand it right.

So seem like I need an afterware supported there at server side. so the question is

  • Can I expect afterware supported there?
  • Or do I need to PR for afterware?

IMHO etag and last-modified is a must have (you guy aim for speed right?) so it should implement internally and can be turn on and off like express did for static etag do tell me if you want me to PR for 304 response internally instead of afterware approach.

Thanks

Facebook OAuth example?

Hello guys, noob here, I'm trying to figure out how to do this right. I'm getting authenticated by Facebook without a problem, but when I got to the part of using the actual data from Facebook I got stuck... I've been copying from here and there. How would you go about using the info received from the OAuth thing?

Here's my code, I've been referencing GitHunt and Jonas' auth article mainly.

import express from 'express';
import path from 'path';
import uuid from 'node-uuid';

// GraphQL
import { apolloServer } from 'apollo-server';
import schema from './postgres/schema';
import resolvers from './postgres/resolvers';

// Webpack
import webpack from 'webpack';
import webpackMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import config from '../webpack.config.dev.js';

// Authentication
import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
import session from 'express-session';
import passport from 'passport';
import { Strategy as FacebookStrategy } from 'passport-facebook';

import facebookStrategyOptions from './auth/config';


// Knex Session
import knex from './postgres/connectors';
const KnexSessionStore = require('connect-session-knex')(session);
const store = new KnexSessionStore({ knex });

import { User } from './postgres/models/User';
const userModel = new User();


// Routes
import routes from './routes';
import facebook from './routes/auth/facebook';
import local from './routes/auth/local';


const GRAPHQL_PORT = 3000;

const app = express();

const compiler = webpack(config);

app.use(webpackMiddleware(compiler, {
    hot: true,
    noInfo: true,
    publicPath: config.output.publicPath,
    stats: {
        colors: true,
        timings: true,
        modules: false
    }
}));

app.use(webpackHotMiddleware(compiler));

// React front end
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, '../client/index.html'));
});

app.get('/logout', (req, res) => {
    req.logout();
    res.redirect('/');
});

app.use('/graphql', apolloServer({
    graphiql: true, 
    pretty: true,
    schema,
    resolvers
}));


// Authentication
app.use(session({
    saveUninitialized: true,
    resave: true,
    genid: req => {
         return uuid.v4();
    },
    secret: 'Z3]GJW!?9uP”/Kpe',
    store
}));

app.use(passport.initialize());
app.use(passport.session());

app.get('/login/facebook',
    passport.authenticate('facebook', {
        scope: ['email']
    }));

app.get('/login/facebook/callback',
    passport.authenticate('facebook', {
        failureRedirect: '/bleh',
        successRedirect: '/'
    }),
    (req, res) => res.redirect('/')
);

// Parsing
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

passport.use(new FacebookStrategy(facebookStrategyOptions, (accessToken, refreshToken, profile, cb) => {
    console.log(profile); // The info I need is there, but I can't figure out how to use it
    userModel.findFacebook(profile)
        .then(user => {
            if(user) {
                return done(null, user)
            }

            else {
                userModel.createFacebook(profile)
                .then(newUser => {
                    return done(null, newUser)
                })
            }
        })
        .catch(error => console.log('Oh no...',error));

    cb(null, profile);
}));

passport.serializeUser((user, cb) => cb(null, user));
passport.deserializeUser((obj, cb) => cb(null, obj));

app.listen(GRAPHQL_PORT, () => console.log(
    `GraphQL Server is now running on http://localhost:${GRAPHQL_PORT}/graphql`
));

Design principles

We need a doc about design principles for the apollo server

  • What are the guiding principles
  • How is Apollo server it different from GraphQL-JS / express-graphql
  • What features should Apollo server have?

GraphQL 0.6.0 compatibility

Hey,

I've been using Apollo server for mocking the Graphene GraphQL schema in frontend (js).

I'm using @include and @skip directives for querying, which seemed were not added into the buildASTSchema until 0.6, so apollo-server doesn't recognize when you use it when querying.

For fixing this you can mimic what express-graphql is doing in it's peer dependencies and update the graphql version in package.json to 0.6.0

https://github.com/graphql/express-graphql/blob/master/package.json#L99

Trouble in initial set up.

Hey there, I'm a beginner and I'm having trouble setting up.

import express from 'express';
import { apolloServer } from 'apollo-server';

import Schema from './schema';
import Resolvers from './resolvers';

const GRAPHQL_PORT = 3000;

const app = express();

app.use('/graphql', apolloServer({
  graphiql: true, 
  pretty: true,
  schema: Schema,
  resolvers: Resolvers
}));

app.listen(GRAPHQL_PORT, () => console.log(
  `GraphQL Server is now running on http://localhost:${GRAPHQL_PORT}/graphql`
));

I've installed everything but I get this weird error:

app.use('/graphql', (0, _apolloServer.apolloServer)({
                                                   ^

TypeError: (0 , _apolloServer.apolloServer) is not a function
    at Object.<anonymous> (server.js:11:21)
    at Module._compile (module.js:541:32)
    at loader (/Users/Empyreal/WebProjects/knex-2/node_modules/babel-register/lib/node.js:158:5)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/Empyreal/WebProjects/knex-2/node_modules/babel-register/lib/node.js:168:7)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Function.Module.runMain (module.js:575:10)
    at /Users/Empyreal/WebProjects/knex-2/node_modules/babel-cli/lib/_babel-node.js:160:24
    at Object.<anonymous> (/Users/Empyreal/WebProjects/knex-2/node_modules/babel-cli/lib/_babel-node.js:161:7)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.runMain (module.js:575:10)

Benefits over express-graphql

Why would one want to use this module instead of express-graphql?
On a first look it seems it's basically the same.

Real-time / streaming / live query / RethinkDB support

Hey, I know this isn't on the near term radar, but I thought it would be helpful to have a single issue that we could always refer back to on this. Feel free to edit this first post as useful. I guess the main things are:

  • Ability to maintain an open websocket
    • Would be cool to (optionally) only open the websocket if active live queries are running, and disconnect after a configurable amount of time after all live queries have stopped.
  • Server API to invalidate queries / push new results
  • Client/server protocol for live query style add/update/change

Rough ETA: 2017 (expectation management :))

Related issues:

  • #18 - Support for deferred/partial responses
  • facebook/relay#541 - Support real-time updates via event subscriptions

Measuring server performance

At some point it will be nice to be able to recommend a way for devs to measure server-side performance, whether it's a guide to using a 3rd party package or tool, or something built into in apollo server.

Meteor example case

When I switched from DO to Galaxy, my pageload subscriptions ready time jumped due to the CPU maxing out. It was due to some combination of:

  • number of subs
  • amount of publish-with-relations use
  • total amount of data

But I didn't have visibility into how much each was responsible. One thing I could have done was copied the database and run locally with the Kadira CPU profiler.

Apollo server

I guess the Apollo equivalent is queries and resolvers. Is there a way to instrument for CPU, or can you just start and stop the v8-profiler? Instrumenting latency is helpful for working on response time – eg this query took X ms, and it was due to these db queries that took however long, some of which were in series (perhaps @arunoda /Kadira will be doing this?). And then the other thing to measure is the memory and cpu usage of whatever does the reactive part, so people have the information needed to decide what data in their app is worth – from a server resources perspective – being instantly reactive vs polling vs non-updating. And ideally you'd be able to measure this in your production environment (unlike Kadira CPU server profiler).

Related: profiling issue in apollo-client

connector[connectorName] is not a function

I'm getting a weird error in initial apollo server setup which seems to be swallowed by the GraphQL layer and it is frustrating because I don't see how I can track it down. I thought all I was doing was roughly copying the example while renaming things, but I must have miscopied something somewhere.

{ "data": { "getUsers": null }, "errors": [ { "message": "connectors[connectorName] is not a function", "locations": [ { "line": 2, "column": 3 } ] } ] }

Line 2, column 3 of what? It is definitely not within my own code. That error is not too helpful. What should I be doing to track this down?

Move express, hapi and koa to dev-dependencies

I just realized that these should be dev-dependencies, not dependencies. Anyone who installs apollo-server will have one of them installed anyway. We just need them to run tests (and for typings).

Making context available in schema parts resolvers

Hi, currently the context is not available when resolving parts of the schema.
This is sometimes needed. Actually in my case quite often, but maybe I'm doing something wrong.

Example:

type Schedule {
    _id: String
    name: String
    achievements: [Achievement]
  }

type Achievement {
 ...
}

In this case, when I resolve schedules achievements I want to resolve them for the currently logged in user. That is, I need userId to obtain achievements for the given schedule, this ID is available in the context.

Is this actually the place to do this? If not, what would be your recommendation?

Factor out core to support HAPI, Express, Koa and others

Add support for the HAPI web framework while continuing support for Express. The intent here is to offer support for both frameworks in a consistently or such that the API works well with each framework and detects which binding is being used.

I believe it is likely we will need an integration with HAPI much like express-graphql.

Improve logging function

Take a more TypeScript approach to logging

export enum LogAction {
request, parse, validation, execute
}

export enum LogStep {
start, end
}

export interface LogMessage {
action: LogAction;
step: LogStep;
data?: Object;
}

export interface LogFunction {
(message: LogMessage);
}

export interface QueryOptions {
...
logFunction?: LogFunction;
...
}

Then use it like this:
logFunction({action: LogAction.request, step: LogStep.start});

This is more verbose but avoids string matching / parsing and makes it much easier for the consumer.

apolloOptions.context type and default value

By default context is undefined and has a type to any.

attachConnectorsToContext from graphql-tools works only with an object typed context.
If context is undefined, it will raise an error for each requests.

So, we have to explicitely set context to an empty object to make it working :

server.use('/', bodyParser.json(), apolloExpress({
  schema: executableSchema,
  context: {},
}));

Maybe apolloOptions.context can have a default value setted to {} and be explicitely typed as Object.

Proposal: Restify support

Restify has been a popular option to create API servers a while back. As of today, at Jolicloud, we're using restify since it was decided a while back it was the right tool for the job. It is now wildly used in our codebase and we can't really detach ourselves from it.

Currently, we managed to get express-graphql work in it, even in production, but we'd like to have a really supported implementation with Apollo Server.

Since v0.2 was released, I was wondering if you planned to integrate it or if I could contribute by adding it as well.

Thank you!

Schema Descriptions

Hello guys, I'm trying to find a way to include schema descriptions (the ones that pop out in Graphiql)

I know the graphql-js way, but couldn't figure out how to do it in Apollo.

var PlanetType = new GraphQLObjectType({
  name: 'Planet',
  description: // <----------- this thing
`A large mass, planet or planetoid in the Star Wars Universe, at the time of
0 ABY.`,
  fields: () => { }
})

Support for deferred/partial responses

At some point in the future, apolloServer should support sending multiple partial responses (over a websocket connection for example). This issue is to keep that in mind while we build the first version which will not have such a feature.

File uploads

Is there any interest in having apollo server support file uploads like express-graphql does? I'm not sure if file uploads should really go through graphql, but if it's a feature many people want to use, we might consider implementing it.

async / await ... how to build with babel

Hi, I'm trying to build an NPM package that would provide some helper functions for meteor users. The issue is thta no matter how I build it from ES6/7 code, the async await functions always complain about fibers and they do not work.

What is the babel config that would work?
Here is my .bablerc

{
  "presets": ["es2015", "stage-0"],
  "plugins": [
    ["transform-runtime", {
      "polyfill": false,
      "regenerator": true
    }]
  ]
}

Koa: Cannot read property 'body' of undefined

When I use apolloKoa with koa-router like this:

const app = koa();
const router = new Router();
const apolloMiddleware = apolloKoa({ schema });

app.use(koaBody());

router.post('/api', apolloMiddleware);

app.use(router.routes());
app.use(router.allowedMethods());

I get the following error:

  TypeError: Cannot read property 'body' of undefined
      at /home/voodooattack/dev/foxls/node_modules/apollo-server/dist/integrations/koaApollo.js:35:25
      at undefined.next (native)
      at fulfilled (/home/voodooattack/dev/foxls/node_modules/apollo-server/dist/integrations/koaApollo.js:4:58)
      at run (/home/voodooattack/dev/foxls/node_modules/core-js/modules/es6.promise.js:87:22)
      at /home/voodooattack/dev/foxls/node_modules/core-js/modules/es6.promise.js:100:28
      at flush (/home/voodooattack/dev/foxls/node_modules/core-js/modules/_microtask.js:18:9)
      at _combinedTickCallback (internal/process/next_tick.js:67:7)
      at process._tickCallback (internal/process/next_tick.js:98:9)

package.json:

  "dependencies": {
    "apollo-client": "^0.4.11",
    "apollo-server": "^0.2.3",
  }

The Apollo Server GraphiQL interface specifies endpoint as undefined

I've hit a roadblock setting up HapiJS with the ApolloStack.

the error when I post to /graphql

{
  "errors": [
    {
      "message": "Cannot read property 'definitions' of undefined"
    }
  ]
}

With graphiql, the chrome console reports

2016-08-14 20:08:09.269 http://localhost:8000/undefined? Failed to load resource: the server responded with a status of 404 (Not Found)
2016-08-14 20:08:09.312 http://localhost:8000/undefined? Failed to load resource: the server responded with a status of 404 (Not Found)

I must have missed something.

my config

'use strict'

const Path = require('path')
const Hapi = require('hapi')

const { ApolloHAPI, GraphiQLHAPI } = require('apollo-server')

const { host, port } = require('./configs')

const { apolloOptions, graphiQLOptions } = require('./options/apollo')

const server = new Hapi.Server({
  connections: {
    routes: {
      files: {
        relativeTo: Path.join(__dirname, 'statics')
      }
    },
    router: {
      stripTrailingSlash: true
    }
  }
})

server.connection({ host, port: process.env.PORT || port })

// Plugins
const plugins = [
  {
    register: new ApolloHAPI(),
    options: apolloOptions,
    routes: { prefix: '/graphql' }
  },
  {
    register: new GraphiQLHAPI(),
    options: graphiQLOptions,
    routes: { prefix: '/graphiql' }
  },

]

server.register([...plugins], err => {
  if (err) throw err

  server.start(err => {
    if (err) throw err
    server.log('info', `Server running at ${server.info.uri}`) // eslint-disable-line
  })
})

the options passed in

const myGraphQLSchema = require('../schemas')

exports.apolloOptions = {
  schema: myGraphQLSchema
}

exports.graphiQLOptions = {
  endpointUrl: '/graphql'
}

My Schema

const {
  GraphQLObjectType,
  GraphQLSchema,
  GraphQLString,
  GraphQLInt,
  GraphQLList,
  GraphQLFloat,
  GraphQLEnumType,
  GraphQLNonNull,
  GraphQLInterfaceType
} = require('graphql')

const TodoType = new GraphQLEnumType({
  name: 'TodoType',
  description: 'A Type of the todo',
  values: {
    HOME: { value: 'home' },
    PLAY: { value: 'play' },
    WORK: { value: 'work' }
  }
})

const Todo = new GraphQLObjectType({
  name: 'Todo',
  description: 'Represent the todos',
  fields: () => ({
    _id: { type: GraphQLString },
    title: { type: GraphQLString },
    importance: { type: GraphQLInt },
    completed: { type: GraphQLInt },
    type: { type: TodoType },
    date: { type: GraphQLFloat },
  })
})

const TodoModel = require('../models/todos')

const Query = new GraphQLObjectType({
  name: 'MySchemaQuery',
  description: "Root of the My Schema",
  fields: () => ({
    todos: {
      type: new GraphQLList(Todo),
      description: "List of todos",
      args: {
        id: { type: GraphQLString },
        active: { type: GraphQLInt },
        importance: { type: GraphQLInt },
        type: { type: GraphQLString },
      },
      resolve: (source, { id, active, importance, type }) => {
        if (id) {
          return TodoModel.getById(id)
        } else if (active) {
          return TodoModel.activeTodos(active)
        } else if (importance) {
          return TodoModel.ofImportance(importance)
        } else if (type) {
          return TodoModel.ofType(type)
        } else {
          return TodoModel.allTodos();
        }
      }
    },

    todo: {
      type: Todo,
      description: "A todo",
      args: {
        id: { type: new GraphQLNonNull(GraphQLString) }
      },
      resolve: (source, { id }) =>
        TodoModel.getById(id)
    },

    latestTodos: {
      type: Todo,
      description: "Latest 5 todos added",
      resolve: () =>
        TodoModel.orderBy('id')
                  .limit(10)
                  .max('_id')
                  .run()
                  .then(todos => todos)
      }
    })
})

const Mutation = new GraphQLObjectType({
  name: "MySchemaMutations",
  fields: {
    createTodo: {
      type: Todo,
      description: "Create a new todo",
      args: {
        title: { type: new GraphQLNonNull(GraphQLString) },
        importance: { type: GraphQLInt },
        type: { type: new GraphQLNonNull(TodoType) }
      },
      resolve: (source, todo) => TodoModel.saveTodo(todo)
    }
  }
})

const Schema = new GraphQLSchema({
  query: Query,
  mutation: Mutation
});

module.exports = Schema

Readme.md missing resolvers

In https://github.com/apollostack/apollo-server#options it missing resolvers:

schema: the GraphQLSchema to be used
context: the context value passed to resolvers during GraphQL execution
rootValue: the value passed to the first resolve function
formatError: a function to apply to every error before sending the response to clients
validationRules: additional GraphQL validation rules to be applied to client-specified queries
formatParams: a function applied for each query in a batch to format parameters before execution
formatResponse: a function applied to each response after execution

It actually be like this in the GitHunt example:

    graphiql: true,
    pretty: true,
    resolvers,  // 为 Schema 取数据的秘书
    schema,    // 定义数据的大佬
    context: {
      ...
    },

seems missing something?

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.