JSPM

graphql-compose

1.21.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 530507
  • Score
    100M100P100Q180550F
  • License MIT

GraphQL schema builder from different data sources with middleware extensions.

Package Exports

  • graphql-compose
  • graphql-compose/lib/index
  • graphql-compose/lib/inputTypeComposer
  • graphql-compose/lib/type
  • graphql-compose/lib/typeComposer

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (graphql-compose) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

GraphQL-compose

codecov coverage Travis npm Join the chat at https://gitter.im/graphql-compose/Lobby Commitizen friendly

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:

Documentation

Live Demos

Example

city.js

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

export const CitySchema = new mongoose.Schema({
  name: String,
  population: Number,
  countryCode: String, // US
  tz: String, // 'America/Los_Angeles'
  // ...
});
export const City = mongoose.model('City', CitySchema);
export const CityTC = composeWithMongoose(CityModel);

// Define some additional fields
CityTC.addFields({
  ucName: { // standard GraphQL like field definition
    type: GraphQLString,
    resolve: (source) => source.name.toUpperCase(),
  },
  localTime: { // 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 relation between City and Country by `countryCode` field.
CityTC.addRelation( // GraphQL relation definition
  'country',
  () => ({
    resolver: CountryTC.getResolver('findOne'),
    args: {
      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 { GQC } from 'graphql-compose';
import { CityTC } from './city';
import { CountryTC } from './country';

GQC.rootQuery().addFields({
  city: CityTC.get('$findOne'),
  cityConnection: CityTC.get('$connection'),
  country: CountryTC.get('$findOne'),
  currentTime: {
    type: 'Date',
    resolve: () => Date.now(),
  },
});

GQC.rootMutation().addFields({
  createCity: CityTC.get('$createOne'),
  updateCity: CityTC.get('$updateById'),
  ...adminAccess({
    removeCity: CityTC.get('$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 GQC.buildSchema();

To-Do list

  • write DataLoader resolver's wrapper for reducing number of queries
  • add support for PubSub. Introduce subscriptions to your graphql schemas
  • write graphql-compose-remote-graphql module, for building your own types which will resolve from 3rd party graphql servers
  • write graphql-compose-rest module, for building your own types which will resolve from 3rd party REST api's. It will be prototype for simple and fast realization of your rest wrappers
  • [need help] find somebody who write graphql-compose-sequilze module like graphql-compose-mongoose (need to write types converter, and change resolver functions).

License

MIT