graphql-compose vs apollo-server vs graphql-tools vs type-graphql
GraphQL Server and Schema Design
graphql-composeapollo-servergraphql-toolstype-graphqlSimilar Packages:

GraphQL Server and Schema Design

GraphQL is a query language for APIs and a runtime for executing those queries by using a type system you define for your data. It allows clients to request only the data they need, making APIs more efficient and flexible. GraphQL servers are responsible for processing these queries and returning the requested data. They handle the execution of queries, mutations, and subscriptions based on the schema defined by the developer. These servers can be implemented in various programming languages and frameworks, providing a way to expose data and functionality to clients in a structured and efficient manner. apollo-server is a fully-featured GraphQL server implementation that is easy to set up and integrates well with various data sources. graphql-compose is a library that helps you build complex GraphQL schemas in a more modular and reusable way, especially when working with large schemas or multiple data sources. graphql-tools is a set of utilities for building and stitching GraphQL schemas, allowing you to create schemas from multiple sources and combine them into a single unified schema. type-graphql is a framework that leverages TypeScript decorators to build GraphQL schemas using classes and types, providing a more type-safe and intuitive way to define your schema.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
graphql-compose499,7881,210909 kB85a year agoMIT
apollo-server013,94926.6 kB792 years agoMIT
graphql-tools05,4202.61 kB1532 months agoMIT
type-graphql08,093351 kB111a month agoMIT

Feature Comparison: graphql-compose vs apollo-server vs graphql-tools vs type-graphql

Schema Definition

  • graphql-compose:

    graphql-compose provides tools for defining schemas in a more modular way, allowing you to create reusable schema components and compose them together. This is especially useful for large schemas or when working with multiple data sources.

  • apollo-server:

    apollo-server allows you to define your schema using the Schema Definition Language (SDL) or programmatically. It provides a simple way to create a schema and resolvers, making it easy to set up a GraphQL server quickly.

  • graphql-tools:

    graphql-tools focuses on schema stitching and federation, allowing you to combine schemas from multiple sources into a single unified schema. It provides utilities for creating schemas programmatically and merging them.

  • type-graphql:

    type-graphql uses TypeScript classes and decorators to define the schema, providing a more type-safe and intuitive way to create your schema. This approach leverages TypeScript's type system to ensure consistency between your schema and resolvers.

Integration with Data Sources

  • graphql-compose:

    graphql-compose is designed to work with multiple data sources, allowing you to create schema components that can be reused across different parts of your application. It is particularly useful for integrating with databases, REST APIs, and other GraphQL schemas.

  • apollo-server:

    apollo-server integrates seamlessly with various data sources, including REST APIs, databases, and third-party services. It provides a flexible resolver system that allows you to fetch data from multiple sources and combine them in your GraphQL API.

  • graphql-tools:

    graphql-tools supports schema stitching, which allows you to combine schemas from different data sources into a single schema. This is useful for creating a unified API from multiple services or microservices.

  • type-graphql:

    type-graphql integrates well with TypeScript-based data sources, such as ORMs (e.g., TypeORM, Prisma). It allows you to define your data models and resolvers in a type-safe manner, making it easier to work with databases and other data sources.

Code Example

  • graphql-compose:

    graphql-compose example

    const { schemaComposer } = require('graphql-compose');
    
    // Create a simple type
    const UserTC = schemaComposer.createObjectTC({
      name: 'User',
      fields: {
        id: 'ID!',
        name: 'String!',
      },
    });
    
    // Add a query
    schemaComposer.Query.addFields({
      user: {
        type: UserTC,
        resolve: () => ({ id: '1', name: 'John Doe' }),
      },
    });
    
    // Build schema
    const schema = schemaComposer.buildSchema();
    
  • apollo-server:

    apollo-server example

    const { ApolloServer, gql } = require('apollo-server');
    
    // Define schema
    const typeDefs = gql`
      type Query {
        hello: String
      }
    `;
    
    // Define resolvers
    const resolvers = {
      Query: {
        hello: () => 'Hello, world!',
      },
    };
    
    // Create server
    const server = new ApolloServer({ typeDefs, resolvers });
    
    // Start server
    server.listen().then(({ url }) => {
      console.log(`Server ready at ${url}`);
    });
    
  • graphql-tools:

    graphql-tools example

    const { makeExecutableSchema } = require('@graphql-tools/schema');
    
    // Define type definitions
    const typeDefs = `
      type Query {
        hello: String
      }
    `;
    
    // Define resolvers
    const resolvers = {
      Query: {
        hello: () => 'Hello, world!',
      },
    };
    
    // Create executable schema
    const schema = makeExecutableSchema({ typeDefs, resolvers });
    
  • type-graphql:

    type-graphql example

    import 'reflect-metadata';
    import { ObjectType, Field, ID, Resolver, Query, buildSchema } from 'type-graphql';
    import { ApolloServer } from 'apollo-server';
    
    @ObjectType()
    class User {
      @Field(type => ID)
      id: string;
    
      @Field()
      name: string;
    }
    
    @Resolver()
    class UserResolver {
      @Query(returns => User)
      user() {
        return { id: '1', name: 'John Doe' };
      }
    }
    
    async function main() {
      const schema = await buildSchema({
        resolvers: [UserResolver],
      });
    
      const server = new ApolloServer({ schema });
      server.listen(4000, () => {
        console.log('Server is running on http://localhost:4000');
      });
    }
    
    main();
    

How to Choose: graphql-compose vs apollo-server vs graphql-tools vs type-graphql

  • graphql-compose:

    Choose graphql-compose if you are working on a large or complex schema that requires modularity and reusability. It is particularly useful for projects where you need to compose schemas from multiple sources or want to create reusable schema components.

  • apollo-server:

    Choose apollo-server if you need a quick and easy way to set up a GraphQL server with minimal configuration. It is ideal for projects where you want a fully-featured server out of the box, with support for subscriptions, middleware, and integrations with various data sources.

  • graphql-tools:

    Choose graphql-tools if you need to stitch together schemas from multiple sources or create a schema programmatically. It is ideal for projects that require schema federation or need to combine schemas from different services.

  • type-graphql:

    Choose type-graphql if you are using TypeScript and want to leverage its type system to create your GraphQL schema. It is ideal for projects that prefer a code-first approach and want to benefit from type safety and decorators.

README for graphql-compose

graphql-compose

codecov coverage Travis npm Commitizen friendly TypeScript compatible Backers on Open Collective Sponsors on Open Collective

graphql-compose – provides a type registry with a bunch of methods for programmatic schema construction. It allows not only to extend types but also remove fields, interfaces, args. If you want to write your graphql schema generator – graphql-compose is a good instrument for you.

  • provides methods for editing GraphQL output/input types (add/remove fields/args/interfaces)
  • introduces Resolver's – the named graphql fieldConfigs, which can be used for finding, updating, removing records
  • provides an easy way for creating relations between types via Resolver's
  • provides converter from OutputType to InputType
  • provides projection parser from AST
  • provides GraphQL schema language for defining simple types
  • adds additional types Date, Json

And a little bit more

graphql-compose-[plugin] – are declarative generators/plugins built on top of graphql-compose, which take some ORMs, schema definitions and create GraphQL Models from them or modify existing GraphQL Types.

Type generators built on top graphql-compose

Utility plugins:

Documentation

graphql-compose.github.io

Live Demos

Examples

Please follow Quick Start Guide for the complete example.

Here is just a demo of ambiguity ways of types definitions:

import { schemaComposer} from 'graphql-compose';

// You may use SDL format for type definition
const CityTC = schemaComposer.createObjectTC(`
  type City {
    code: String!
    name: String!
    population: Number
    countryCode: String
    tz: String
  }
`);

// Define type via Config object
const CountryTC = schemaComposer.createObjectTC({
  name: 'Country',
  fields: {
    title: 'String',
    geo: `type LonLat { lon: Float, lat: Float }`,
    hoisting: {
      type: () => AnotherTC,
      description: `
        You may wrap type in thunk for solving
        hoisting problems when two types cross reference
        each other.
      `,
    }
  }
});

// Or via declarative methods define some additional fields
CityTC.addFields({
  country: CountryTC, // some another Type
  ucName: { // standard GraphQL like field definition
    type: GraphQLString,
    resolve: (source) => source.name.toUpperCase(),
  },
  currentLocalTime: { // extended GraphQL Compose field definition
    type: 'Date',
    resolve: (source) => moment().tz(source.tz).format(),
    projection: { tz: true }, // load `tz` from database, when requested only `localTime` field
  },
  counter: 'Int', // shortening for only type definition for field
  complex: `type ComplexType {
    subField1: String
    subField2: Float
    subField3: Boolean
    subField4: ID
    subField5: JSON
    subField6: Date
  }`,
  list0: {
    type: '[String]',
    description: 'Array of strings',
  },
  list1: '[String]',
  list2: ['String'],
  list3: [new GraphQLOutputType(...)],
  list4: [`type Complex2Type { f1: Float, f2: Int }`],
});

// Add resolver method
CityTC.addResolver({
  kind: 'query',
  name: 'findMany',
  args: {
    filter: `input CityFilterInput {
      code: String!
    }`,
    limit: {
      type: 'Int',
      defaultValue: 20,
    },
    skip: 'Int',
    // ... other args if needed
  },
  type: [CityTC], // array of cities
  resolve: async ({ args, context }) => {
    return context.someCityDB
      .findMany(args.filter)
      .limit(args.limit)
      .skip(args.skip);
  },
});

// Remove `tz` field from schema
CityTC.removeField('tz');

// Add description to field
CityTC.extendField('name', {
  description: 'City name',
});

schemaComposer.Query.addFields({
  cities: CityTC.getResolver('findMany'),
  currentTime: {
    type: 'Date',
    resolve: () => Date.now(),
  },
});

schemaComposer.Mutation.addFields({
  createCity: CityTC.getResolver('createOne'),
  updateCity: CityTC.getResolver('updateById'),
  ...adminAccess({
    removeCity: CityTC.getResolver('removeById'),
  }),
});

function adminAccess(resolvers) {
  Object.keys(resolvers).forEach(k => {
    resolvers[k] = resolvers[k].wrapResolve(next => rp => {
      // rp = resolveParams = { source, args, context, info }
      if (!rp.context.isAdmin) {
        throw new Error('You should be admin, to have access to this action.');
      }
      return next(rp);
    });
  });
  return resolvers;
}

// construct schema which can be passed to express-graphql, apollo-server or graphql-yoga
export const schema = schemaComposer.buildSchema();

Contributors

This project exists thanks to all the people who contribute.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

License

MIT