Package Exports
- graphql-compose
- graphql-compose/lib/SchemaComposer
- graphql-compose/lib/graphql
- graphql-compose/lib/index
- graphql-compose/lib/type
- graphql-compose/lib/utils/configToDefine
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
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 works 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
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
toInputType
- provides
projection
parser from AST - provides
GraphQL schema language
for defining simple types - adds additional types
Date
,Json
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 generator plugins:
- graphql-compose-json - generates GraphQL type from JSON (a good helper for wrapping REST APIs)
- graphql-compose-mongoose - generates GraphQL types from mongoose (MongoDB models) with Resolvers.
- graphql-compose-elasticsearch - generates GraphQL types from elastic mappings; ElasticSearch REST API proxy via GraphQL.
- graphql-compose-aws - expose AWS Cloud API via GraphQL
Utility plugins:
- graphql-compose-relay - reassemble GraphQL types with
Relay
specific things, likeNode
type and interface,globalId
,clientMutationId
. - graphql-compose-connection - generates
connection
Resolver fromfindMany
andcount
Resolvers. - graphql-compose-dataloader - adds DataLoader to graphql-composer resolvers.
Documentation
Live Demos
- graphql-compose.herokuapp.com - Live demo of GraphQL Server (9 models, 14 files, ~750 LOC)
- nodkz.github.io/relay-northwind - Live demo of Relay client working with the server above (8 crazy pages, 47 files, ~3000 LOC)
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]