Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 84 additions & 35 deletions src/execution/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,28 @@ export type RootSelectionSetExecutor = (
* import { buildSchema } from 'graphql/utilities';
* import { execute } from 'graphql/execution';
*
* const schema = buildSchema(`
* type Query {
* greeting(name: String!): String
* }
* `);
* const schema = buildSchema(
* `
* type Query {
* greeting(name: String!): String
* }
* `,
* {
* supplementalConfig: {
* objectTypes: {
* Query: {
* fields: {
* greeting: (_source, { name }) => `Hello, ${name}!`,
* },
* },
* },
* },
* },
* );
*
* const result = await execute({
* schema,
* document: parse('query ($name: String!) { greeting(name: $name) }'),
* rootValue: {
* greeting: ({ name }) => `Hello, ${name}!`,
* },
* variableValues: { name: 'Ada' },
* });
*
Expand Down Expand Up @@ -185,16 +195,28 @@ function executeImpl(args: ExecutionArgs): PromiseOrValue<ExecutionResult> {
* import { buildSchema } from 'graphql/utilities';
* import { experimentalExecuteIncrementally } from 'graphql/execution';
*
* const schema = buildSchema(`
* type Query {
* greeting: String
* }
* `);
* const schema = buildSchema(
* `
* type Query {
* greeting: String
* }
* `,
* {
* supplementalConfig: {
* objectTypes: {
* Query: {
* fields: {
* greeting: () => 'Hello',
* },
* },
* },
* },
* },
* );
*
* const result = await experimentalExecuteIncrementally({
* schema,
* document: parse('{ greeting }'),
* rootValue: { greeting: 'Hello' },
* });
*
* result; // => { data: { greeting: 'Hello' } }
Expand Down Expand Up @@ -455,7 +477,6 @@ export function executeSubscriptionEvent(
* @returns A response stream for a valid subscription, or an execution result containing errors.
* @example
* ```ts
* // Use a same-named rootValue function to provide the source event stream.
* import assert from 'node:assert';
* import { parse } from 'graphql/language';
* import { buildSchema } from 'graphql/utilities';
Expand All @@ -466,20 +487,34 @@ export function executeSubscriptionEvent(
* yield { greeting: 'Bonjour' };
* }
*
* const schema = buildSchema(`
* type Query {
* noop: String
* }
*
* type Subscription {
* greeting: String
* }
* `);
* const schema = buildSchema(
* `
* type Query {
* noop: String
* }
*
* type Subscription {
* greeting: String
* }
* `,
* {
* supplementalConfig: {
* objectTypes: {
* Subscription: {
* fields: {
* greeting: {
* subscribe: () => greetings(),
* },
* },
* },
* },
* },
* },
* );
*
* const result = await subscribe({
* schema,
* document: parse('subscription { greeting }'),
* rootValue: { greeting: () => greetings() },
* });
*
* assert('next' in result);
Expand Down Expand Up @@ -627,19 +662,33 @@ function subscribeImpl(
* yield { greeting: 'Hello' };
* }
*
* const schema = buildSchema(`
* type Query {
* noop: String
* }
*
* type Subscription {
* greeting: String
* }
* `);
* const schema = buildSchema(
* `
* type Query {
* noop: String
* }
*
* type Subscription {
* greeting: String
* }
* `,
* {
* supplementalConfig: {
* objectTypes: {
* Subscription: {
* fields: {
* greeting: {
* subscribe: () => greetings(),
* },
* },
* },
* },
* },
* },
* );
* const validatedArgs = validateSubscriptionArgs({
* schema,
* document: parse('subscription { greeting }'),
* rootValue: { greeting: () => greetings() },
* });
*
* assert('schema' in validatedArgs);
Expand Down
76 changes: 54 additions & 22 deletions src/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,28 @@ export interface GraphQLArgs
* // Execute a complete asynchronous request with variables.
* import { graphql, buildSchema } from 'graphql';
*
* const schema = buildSchema(`
* type Query {
* greeting(name: String!): String
* }
* `);
* const schema = buildSchema(
* `
* type Query {
* greeting(name: String!): String
* }
* `,
* {
* supplementalConfig: {
* objectTypes: {
* Query: {
* fields: {
* greeting: (_source, { name }) => `Hello, ${name}!`,
* },
* },
* },
* },
* },
* );
*
* const result = await graphql({
* schema,
* source: 'query SayHello($name: String!) { greeting(name: $name) }',
* rootValue: {
* greeting: ({ name }) => `Hello, ${name}!`,
* },
* variableValues: { name: 'Ada' },
* operationName: 'SayHello',
* });
Expand Down Expand Up @@ -124,11 +134,24 @@ export interface GraphQLArgs
* // This variant customizes the request pipeline with a harness.
* import { buildSchema, defaultHarness, graphql } from 'graphql';
*
* const schema = buildSchema(`
* type Query {
* greeting: String
* }
* `);
* const schema = buildSchema(
* `
* type Query {
* greeting: String
* }
* `,
* {
* supplementalConfig: {
* objectTypes: {
* Query: {
* fields: {
* greeting: () => 'Hello',
* },
* },
* },
* },
* },
* );
* const stages = [];
* const abortController = new AbortController();
* const harness = {
Expand All @@ -153,7 +176,6 @@ export interface GraphQLArgs
* const result = await graphql({
* schema,
* source: '{ greeting }',
* rootValue: { greeting: 'Hello' },
* rules: [],
* maxErrors: 25,
* hideSuggestions: true,
Expand Down Expand Up @@ -186,18 +208,28 @@ export function graphql(args: GraphQLArgs): Promise<ExecutionResult> {
* // Execute a complete synchronous request with variables.
* import { graphqlSync, buildSchema } from 'graphql';
*
* const schema = buildSchema(`
* type Query {
* greeting(name: String!): String
* }
* `);
* const schema = buildSchema(
* `
* type Query {
* greeting(name: String!): String
* }
* `,
* {
* supplementalConfig: {
* objectTypes: {
* Query: {
* fields: {
* greeting: (_source, { name }) => `Hello, ${name}!`,
* },
* },
* },
* },
* },
* );
*
* const result = graphqlSync({
* schema,
* source: 'query SayHello($name: String!) { greeting(name: $name) }',
* rootValue: {
* greeting: ({ name }) => `Hello, ${name}!`,
* },
* variableValues: { name: 'Ada' },
* operationName: 'SayHello',
* });
Expand Down
14 changes: 14 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,20 @@ export type {
IntrospectionEnumValue,
IntrospectionDirective,
BuildSchemaOptions,
ExtendSchemaOptions,
GraphQLSchemaSupplementalConfig,
GraphQLScalarTypeSupplementalConfig,
GraphQLObjectTypeSupplementalConfig,
GraphQLFieldSupplementalConfig,
GraphQLFieldSupplementalConfigMap,
GraphQLArgumentSupplementalConfig,
GraphQLInterfaceTypeSupplementalConfig,
GraphQLUnionTypeSupplementalConfig,
GraphQLEnumTypeSupplementalConfig,
GraphQLEnumValueSupplementalConfig,
GraphQLInputObjectTypeSupplementalConfig,
GraphQLInputFieldSupplementalConfig,
GraphQLDirectiveSupplementalConfig,
BreakingChange,
SafeChange,
DangerousChange,
Expand Down
14 changes: 10 additions & 4 deletions src/type/scalars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,14 +335,20 @@ export const specifiedScalarTypes: ReadonlyArray<GraphQLScalarType> =
* @example
* ```ts
* import {
* GraphQLScalarType,
* assertScalarType,
* GraphQLString,
* isSpecifiedScalarType,
* } from 'graphql/type';
* import { buildSchema } from 'graphql/utilities';
*
* const DateTime = new GraphQLScalarType({
* name: 'DateTime',
* });
* const schema = buildSchema(`
* scalar DateTime
*
* type Query {
* now: DateTime
* }
* `);
* const DateTime = assertScalarType(schema.getType('DateTime'));
*
* isSpecifiedScalarType(GraphQLString); // => true
* isSpecifiedScalarType(DateTime); // => false
Expand Down
27 changes: 27 additions & 0 deletions src/utilities/__tests__/buildASTSchema-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,33 @@ describe('Schema Builder', () => {
buildSchema(sdl, { assumeValidSDL: true });
});

it('Rejects invalid supplemental config by default', () => {
const supplementalConfig = {
objectTypes: {
Missing: {},
},
};

expect(() => buildSchema('type Query', { supplementalConfig })).to.throw(
'Type supplemental config "Missing" does not match a type declared by the document.',
);
});

it('Allows to disable supplemental config validation', () => {
const supplementalConfig = {
objectTypes: {
Missing: {},
},
};

expect(() =>
buildSchema('type Query', {
assumeValidSupplementalConfig: true,
supplementalConfig,
}),
).to.not.throw();
});

it('buildSchema parses directives on directive definitions', () => {
const schema = buildSchema(
dedent`
Expand Down
Loading
Loading