Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 562cead

Browse files
authored
Allow providing an object of arguments to graphql(). (graphql#867)
As well as execute() and subscribe() Closes graphql#356
1 parent 1b41959 commit 562cead

File tree

8 files changed

+553
-284
lines changed

8 files changed

+553
-284
lines changed

.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@
202202
"quote-props": [2, "as-needed", {"numbers": true}],
203203
"quotes": [2, "single"],
204204
"radix": 2,
205-
"require-yield": 2,
205+
"require-yield": 0,
206206
"semi": [2, "always"],
207207
"semi-spacing": [2, {"before": false, "after": true}],
208208
"sort-vars": 0,

src/__tests__/starWarsQuery-test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,27 @@ describe('Star Wars Query Tests', () => {
3636
});
3737
});
3838

39+
it('Accepts an object with named properties to graphql()', async () => {
40+
const query = `
41+
query HeroNameQuery {
42+
hero {
43+
name
44+
}
45+
}
46+
`;
47+
const result = await graphql({
48+
schema: StarWarsSchema,
49+
source: query,
50+
});
51+
expect(result).to.deep.equal({
52+
data: {
53+
hero: {
54+
name: 'R2-D2'
55+
}
56+
}
57+
});
58+
});
59+
3960
it('Allows us to query for the ID and friends of R2-D2', async () => {
4061
const query = `
4162
query HeroNameAndFriendsQuery {

src/execution/__tests__/executor-test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,45 @@ describe('Execute: Handles basic execution tasks', () => {
3838
);
3939
});
4040

41+
it('throws if no schema is provided', () => {
42+
expect(() => execute({
43+
document: parse('{ field }')
44+
})).to.throw(
45+
'Must provide schema'
46+
);
47+
});
48+
49+
it('accepts an object with named properties as arguments', async () => {
50+
const doc = 'query Example { a }';
51+
52+
const data = 'rootValue';
53+
54+
const schema = new GraphQLSchema({
55+
query: new GraphQLObjectType({
56+
name: 'Type',
57+
fields: {
58+
a: {
59+
type: GraphQLString,
60+
resolve(rootValue) {
61+
return rootValue;
62+
}
63+
}
64+
}
65+
})
66+
});
67+
68+
const result = await execute({
69+
schema,
70+
document: parse(doc),
71+
rootValue: data
72+
});
73+
74+
expect(result).to.jsonEqual({
75+
data: { a: 'rootValue' }
76+
});
77+
});
78+
79+
4180
it('executes arbitrary code', async () => {
4281
const data = {
4382
a() { return 'Apple'; },

src/execution/execute.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,51 @@ export type ExecutionResult = {
109109
*
110110
* If the arguments to this function do not result in a legal execution context,
111111
* a GraphQLError will be thrown immediately explaining the invalid input.
112+
*
113+
* Accepts either an object with named arguments, or individual arguments.
112114
*/
113-
export function execute(
115+
declare function execute({|
116+
schema: GraphQLSchema,
117+
document: DocumentNode,
118+
rootValue?: mixed,
119+
contextValue?: mixed,
120+
variableValues?: ?{[key: string]: mixed},
121+
operationName?: ?string,
122+
fieldResolver?: ?GraphQLFieldResolver<any, any>
123+
|}, ..._: []): Promise<ExecutionResult>;
124+
/* eslint-disable no-redeclare */
125+
declare function execute(
114126
schema: GraphQLSchema,
115127
document: DocumentNode,
116128
rootValue?: mixed,
117129
contextValue?: mixed,
118130
variableValues?: ?{[key: string]: mixed},
119131
operationName?: ?string,
120132
fieldResolver?: ?GraphQLFieldResolver<any, any>
121-
): Promise<ExecutionResult> {
133+
): Promise<ExecutionResult>;
134+
export function execute(
135+
argsOrSchema,
136+
document,
137+
rootValue,
138+
contextValue,
139+
variableValues,
140+
operationName,
141+
fieldResolver
142+
) {
143+
// Extract arguments from object args if provided.
144+
const args = arguments.length === 1 ? argsOrSchema : undefined;
145+
const schema = args ? args.schema : argsOrSchema;
146+
if (args) {
147+
/* eslint-disable no-param-reassign */
148+
document = args.document;
149+
rootValue = args.rootValue;
150+
contextValue = args.contextValue;
151+
variableValues = args.variableValues;
152+
operationName = args.operationName;
153+
fieldResolver = args.fieldResolver;
154+
/* eslint-enable no-param-reassign, no-redeclare */
155+
}
156+
122157
// If a valid context cannot be created due to incorrect arguments,
123158
// this will throw an error.
124159
const context = buildExecutionContext(

src/graphql.js

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import type { GraphQLFieldResolver } from './type/definition';
1616
import type { GraphQLSchema } from './type/schema';
1717
import type { ExecutionResult } from './execution/execute';
1818

19-
2019
/**
2120
* This is the primary entry point function for fulfilling GraphQL operations
2221
* by parsing, validating, and executing a GraphQL document along side a
@@ -26,6 +25,8 @@ import type { ExecutionResult } from './execution/execute';
2625
* may wish to separate the validation and execution phases to a static time
2726
* tooling step, and a server runtime step.
2827
*
28+
* Accepts either an object with named arguments, or individual arguments:
29+
*
2930
* schema:
3031
* The GraphQL type system to use when validating and executing a query.
3132
* source:
@@ -45,25 +46,58 @@ import type { ExecutionResult } from './execution/execute';
4546
* If not provided, the default field resolver is used (which looks for a
4647
* value or method on the source value with the field's name).
4748
*/
48-
export function graphql(
49+
declare function graphql({|
4950
schema: GraphQLSchema,
5051
source: string | Source,
5152
rootValue?: mixed,
5253
contextValue?: mixed,
5354
variableValues?: ?{[key: string]: mixed},
5455
operationName?: ?string,
5556
fieldResolver?: ?GraphQLFieldResolver<any, any>
56-
): Promise<ExecutionResult> {
57+
|}, ..._: []): Promise<ExecutionResult>;
58+
/* eslint-disable no-redeclare */
59+
declare function graphql(
60+
schema: GraphQLSchema,
61+
source: Source | string,
62+
rootValue?: mixed,
63+
contextValue?: mixed,
64+
variableValues?: ?{[key: string]: mixed},
65+
operationName?: ?string,
66+
fieldResolver?: ?GraphQLFieldResolver<any, any>
67+
): Promise<ExecutionResult>;
68+
export function graphql(
69+
argsOrSchema,
70+
source,
71+
rootValue,
72+
contextValue,
73+
variableValues,
74+
operationName,
75+
fieldResolver
76+
) {
77+
// Extract arguments from object args if provided.
78+
const args = arguments.length === 1 ? argsOrSchema : undefined;
79+
const schema = args ? args.schema : argsOrSchema;
80+
if (args) {
81+
/* eslint-disable no-param-reassign */
82+
source = args.source;
83+
rootValue = args.rootValue;
84+
contextValue = args.contextValue;
85+
variableValues = args.variableValues;
86+
operationName = args.operationName;
87+
fieldResolver = args.fieldResolver;
88+
/* eslint-enable no-param-reassign, no-redeclare */
89+
}
90+
5791
return new Promise(resolve => {
58-
const documentAST = parse(source);
59-
const validationErrors = validate(schema, documentAST);
92+
const document = parse(source);
93+
const validationErrors = validate(schema, document);
6094
if (validationErrors.length > 0) {
6195
resolve({ errors: validationErrors });
6296
} else {
6397
resolve(
6498
execute(
6599
schema,
66-
documentAST,
100+
document,
67101
rootValue,
68102
contextValue,
69103
variableValues,

src/subscription/__tests__/subscribe-test.js

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,62 @@ describe('Subscribe', () => {
127127
subscription: subscribe(
128128
schema,
129129
ast,
130-
data,
131-
null
130+
data
132131
),
133132
};
134133
}
135134

135+
it('accepts an object with named properties as arguments', async () => {
136+
const document = parse(`
137+
subscription {
138+
importantEmail
139+
}
140+
`);
141+
142+
async function* emptyAsyncIterator() {
143+
// Empty
144+
}
145+
146+
const ai = await subscribe({
147+
schema: emailSchema,
148+
document,
149+
rootValue: {
150+
importantEmail: emptyAsyncIterator
151+
}
152+
});
153+
154+
ai.return();
155+
});
156+
157+
it('throws when missing schema', async () => {
158+
const document = parse(`
159+
subscription {
160+
importantEmail
161+
}
162+
`);
163+
164+
expect(() =>
165+
subscribe(
166+
null,
167+
document
168+
)
169+
).to.throw('Must provide schema');
170+
171+
expect(() =>
172+
subscribe({ document })
173+
).to.throw('Must provide schema');
174+
});
175+
176+
it('throws when missing document', async () => {
177+
expect(() =>
178+
subscribe(emailSchema, null)
179+
).to.throw('Must provide document');
180+
181+
expect(() =>
182+
subscribe({ schema: emailSchema })
183+
).to.throw('Must provide document');
184+
});
185+
136186
it('multiple subscription fields defined in schema', async () => {
137187
const pubsub = new EventEmitter();
138188
const SubscriptionTypeMultiple = new GraphQLObjectType({

src/subscription/subscribe.js

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ import type { GraphQLFieldResolver } from '../type/definition';
3535
*
3636
* If the arguments to this function do not result in a legal execution context,
3737
* a GraphQLError will be thrown immediately explaining the invalid input.
38+
*
39+
* Accepts either an object with named arguments, or individual arguments.
3840
*/
39-
export function subscribe(
41+
declare function subscribe({|
4042
schema: GraphQLSchema,
4143
document: DocumentNode,
4244
rootValue?: mixed,
@@ -45,7 +47,43 @@ export function subscribe(
4547
operationName?: ?string,
4648
fieldResolver?: ?GraphQLFieldResolver<any, any>,
4749
subscribeFieldResolver?: ?GraphQLFieldResolver<any, any>
48-
): AsyncIterator<ExecutionResult> {
50+
|}, ..._: []): AsyncIterator<ExecutionResult>;
51+
/* eslint-disable no-redeclare */
52+
declare function subscribe(
53+
schema: GraphQLSchema,
54+
document: DocumentNode,
55+
rootValue?: mixed,
56+
contextValue?: mixed,
57+
variableValues?: ?{[key: string]: mixed},
58+
operationName?: ?string,
59+
fieldResolver?: ?GraphQLFieldResolver<any, any>,
60+
subscribeFieldResolver?: ?GraphQLFieldResolver<any, any>
61+
): AsyncIterator<ExecutionResult>;
62+
export function subscribe(
63+
argsOrSchema,
64+
document,
65+
rootValue,
66+
contextValue,
67+
variableValues,
68+
operationName,
69+
fieldResolver,
70+
subscribeFieldResolver
71+
) {
72+
// Extract arguments from object args if provided.
73+
const args = arguments.length === 1 ? argsOrSchema : undefined;
74+
const schema = args ? args.schema : argsOrSchema;
75+
if (args) {
76+
/* eslint-disable no-param-reassign */
77+
document = args.document;
78+
rootValue = args.rootValue;
79+
contextValue = args.contextValue;
80+
variableValues = args.variableValues;
81+
operationName = args.operationName;
82+
fieldResolver = args.fieldResolver;
83+
subscribeFieldResolver = args.subscribeFieldResolver;
84+
/* eslint-enable no-param-reassign, no-redeclare */
85+
}
86+
4987
const subscription = createSourceEventStream(
5088
schema,
5189
document,

0 commit comments

Comments
 (0)