graphql-compose
raw JSON → 9.1.0 verified Sat Apr 25 auth: no javascript
Programmatic GraphQL schema builder with a type registry for constructing and editing output/input types, fields, arguments, and interfaces. v9.1.0 (stable) supports GraphQL v14–16, ships TypeScript definitions, and is ESM-only. Key differentiators vs graphql-tools: Resolver abstraction for CRUD operations, built-in projection parser from AST, OutputType-to-InputType converter, and plugin ecosystem (mongoose, JSON, Elasticsearch). Releases ~monthly; recent fixes address security (removed object-path) and TypeScript compatibility.
Common errors
error TypeError: Cannot read properties of undefined (reading 'getType') ↓
cause Resolver referenced a type that hasn't been added to the schemaComposer yet.
fix
Ensure the type is created (e.g., schemaComposer.createObjectTC) before referencing it in resolver type field.
error Error: Schema must contain uniquely named types but contains multiple types named "Query". ↓
cause Accidentally created duplicate root types via schemaComposer.Query.addFields() and schemaComposer.createObjectTC({ name: 'Query'}).
fix
Do not create an object type composer with same name as root types. Use schemaComposer.Query directly.
error GraphQLError: Field "user" must not have a selection since type "User" has no subfields. ↓
cause Resolver type is set to UserTC but resolver does not return object; or query selects subfields but schema built incorrectly.
fix
Verify resolver returns an object matching UserTC fields and that schemaComposer.buildSchema() is called after adding resolvers.
error Module not found: Can't resolve 'graphql' in ... ↓
cause Missing graphql peer dependency.
fix
npm install graphql@^14.2.0 || ^15.0.0 || ^16.0.0
Warnings
breaking v9 dropped support for GraphQL v13 and older; peer dependency now requires graphql@^14.2.0 || ^15.0.0 || ^16.0.0 ↓
fix Upgrade graphql to v14, v15, or v16. If locked to v13, stay on graphql-compose v8.
breaking v9 is ESM-only; CommonJS require() will fail. ↓
fix Use import statements or dynamic import(). If CJS required, stick with v8.
deprecated Removed object-path dependency due to security alerts; use native lodash.get or optional chaining. ↓
fix If using deep path access, migrate to ES2020 optional chaining or lodash.get.
gotcha schemaComposer is a singleton; importing it multiple times yields the same instance. Do not create new instances with new SchemaComposer() unless you intend separate registries. ↓
fix Use import { schemaComposer } for shared app schema; use new SchemaComposer() for isolated test contexts.
deprecated ObjectTypeComposer.setField() mutates the type in-place; future versions may prefer immutable patterns. ↓
fix Consider using addFields or removeField methods; check for deprecation warnings in v10.
Install
npm install graphql-compose yarn add graphql-compose pnpm add graphql-compose Imports
- schemaComposer wrong
const schemaComposer = require('graphql-compose').schemaComposercorrectimport { schemaComposer } from 'graphql-compose' - ObjectTypeComposer wrong
import ObjectTypeComposer from 'graphql-compose'correctimport { ObjectTypeComposer } from 'graphql-compose' - Resolver
import { Resolver } from 'graphql-compose' - GraphQLDate wrong
const { GraphQLDate } = require('graphql-compose')correctimport { GraphQLDate } from 'graphql-compose' - graphql-compose types
import type { ObjectTypeComposer } from 'graphql-compose'
Quickstart
import { schemaComposer, ObjectTypeComposer, Resolver } from 'graphql-compose';
import { GraphQLSchema, GraphQLObjectType, GraphQLString } from 'graphql';
const UserTC = schemaComposer.createObjectTC({
name: 'User',
fields: {
id: 'ID!',
name: 'String!',
},
});
UserTC.addResolver({
name: 'findById',
type: UserTC,
args: { id: 'ID!' },
resolve: async ({ args }) => {
// pretend to fetch from DB
return { id: args.id, name: 'John' };
},
});
schemaComposer.Query.addFields({
user: UserTC.getResolver('findById'),
});
const schema = schemaComposer.buildSchema();
console.log(schema);
// schema ready to be used with express-graphql or other server