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