graphql-compose
    TypeScript icon, indicating that this package has built-in type declarations

    9.0.4 • Public • Published

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

    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

    Install

    npm i graphql-compose

    DownloadsWeekly Downloads

    399,599

    Version

    9.0.4

    License

    MIT

    Unpacked Size

    906 kB

    Total Files

    159

    Last publish

    Collaborators

    • nodkz