Skip to content
Toolkit for generating complex GraphQL Schemas on Node.js
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.vscode
docs docs: Activating Open Collective 🍻(#118) May 16, 2018
examples docs(example) add basic example use of graphql compose (#98) Oct 23, 2017
flow-typed/npm chore(deps): update dependencies Feb 1, 2018
src fix(typings): fix ComposeOutputType it has TReturn generic instead of… Mar 17, 2019
.babelrc
.eslintignore
.eslintrc
.flowconfig feat: add mjs build (es6 modules) Jun 26, 2018
.gitignore
.markdownlint.json refactor: small fixes after checking with mongoose, pagination, conne… Mar 15, 2019
.npmignore chore(typescript): move type defs from types/ to src/ Sep 15, 2017
.prettierignore docs: Activating Open Collective 🍻(#118) May 16, 2018
.travis.yml chore: update flow-bin and using node 10 on travis Sep 5, 2018
AUTHORS Initial commit Jun 7, 2016
CHANGELOG.md docs(Changelog): See in the GitHub releases tab Jan 25, 2017
LICENSE.md
README.md docs(README): remove graphql-recompose Aug 20, 2018
jest.config.js
package.json
tsconfig.json
tslint.json
yarn.lock fix: errors from flow 0.95.1 Mar 15, 2019

README.md

GraphQL-compose

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

GraphQL – is a query language for APIs. graphql-js is the reference implementation of GraphQL for nodejs which introduce GraphQL type system for describing schema (definition over configuration) and executes queries on the server side. express-graphql is a HTTP server which gets request data, passes it to graphql-js and returned result passes to response.

graphql-compose – the imperative tool which worked on top of graphql-js. It provides some methods for creating types and GraphQL Models (so I call types with a list of common resolvers) for further building of complex relations in your schema.

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

graphql-compose-[plugin] – is a declarative generators/plugins that build on top of graphql-compose, which take some ORMs, schema definitions and creates GraphQL Models from them or modify existed GraphQL Types.

Type generator plugins:

Utility plugins:

Documentation

graphql-compose.github.io

Live Demos

Example

city.js

import { TypeComposer} from 'graphql-compose';
import { CountryTC } from './country';

export const CityTC = TypeComposer.create(`
  type City {
    code: String!
    name: String!
    population: Number
    countryCode: String
    tz: String
  }
`);

// Define some additional fields
CityTC.addFields({
  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);
  },
});

// Add relation between City and Country by `countryCode` field.
CityTC.addRelation( // GraphQL relation definition
  'country',
  {
    resolver: () => CountryTC.getResolver('findOne'),
    prepareArgs: {
      filter: source => ({ code: `${source.countryCode}` }),
    },
    projection: { countryCode: true },
  }
);

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

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

schema.js

import { schemaComposer } from 'graphql-compose';
import { CityTC } from './city';
import { CountryTC } from './country';

schemaComposer.Query.addFields({
  cities: CityTC.getResolver('findMany'),
  country: CountryTC.getResolver('findOne'),
  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;
}

export default 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

You can’t perform that action at this time.