Skip to content

Commit 2e619ab

Browse files
committed
Merge branch 'master' into sogko/master
* master: (26 commits) 0.6.0 Validation: improving overlapping fields quality (graphql#386) Validation: context.getFragmentSpreads now accepts selectionSet rather than fragment AST node Factor out more closure functions Factor out closure functions to normal functions Deprecated directive (graphql#384) RFC: Directive location: schema definition (graphql#382) RFC: Schema Language Directives (graphql#376) Export introspection in public API Export directive definitions. (graphql#381) BUG: Ensure building AST schema does not exclude @Skip and @include (graphql#380) documentation of schema constructor Revert "Remove all 'instanceof GraphQLSchema' checks" (graphql#377) remove all 'instanceof GraphQLSchema' checks (graphql#371) Error logging for new interface type semantics (graphql#350) Nit: Missing case in grammar for TypeSystemDefinition in comment Bug: printer can print non-parsable value Factor out suggestion quoting utility Minor refactoring Minor refactoring of error messages for unknown fields ...
2 parents d29694c + 359ec76 commit 2e619ab

39 files changed

+2121
-466
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graphql",
3-
"version": "0.5.0",
3+
"version": "0.6.0",
44
"description": "A Query Language and Runtime which can target any service.",
55
"contributors": [
66
"Lee Byron <[email protected]> (http://leebyron.com/)",

src/execution/__tests__/directives-test.js

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,6 @@ describe('Execute: handles directives', () => {
153153
b
154154
}
155155
}
156-
fragment Frag on TestType {
157-
b
158-
}
159156
`;
160157
return expect(await executeTestQuery(q)).to.deep.equal({
161158
data: { a: 'a' }
@@ -170,9 +167,6 @@ describe('Execute: handles directives', () => {
170167
b
171168
}
172169
}
173-
fragment Frag on TestType {
174-
b
175-
}
176170
`;
177171
return expect(await executeTestQuery(q)).to.deep.equal({
178172
data: { a: 'a', b: 'b' }
@@ -186,9 +180,6 @@ describe('Execute: handles directives', () => {
186180
b
187181
}
188182
}
189-
fragment Frag on TestType {
190-
b
191-
}
192183
`;
193184
return expect(await executeTestQuery(q)).to.deep.equal({
194185
data: { a: 'a', b: 'b' }
@@ -202,9 +193,6 @@ describe('Execute: handles directives', () => {
202193
b
203194
}
204195
}
205-
fragment Frag on TestType {
206-
b
207-
}
208196
`;
209197
return expect(await executeTestQuery(q)).to.deep.equal({
210198
data: { a: 'a' }

src/execution/values.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export function getVariableValues(
5454
export function getArgumentValues(
5555
argDefs: ?Array<GraphQLArgument>,
5656
argASTs: ?Array<Argument>,
57-
variableValues: { [key: string]: mixed }
57+
variableValues?: ?{ [key: string]: mixed }
5858
): { [key: string]: mixed } {
5959
if (!argDefs || !argASTs) {
6060
return {};

src/index.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ export {
5151
GraphQLInputObjectType,
5252
GraphQLList,
5353
GraphQLNonNull,
54+
GraphQLDirective,
55+
56+
// "Enum" of Type Kinds
57+
TypeKind,
58+
59+
// "Enum" of Directive Locations
60+
DirectiveLocation,
5461

5562
// Scalars
5663
GraphQLInt,
@@ -59,6 +66,30 @@ export {
5966
GraphQLBoolean,
6067
GraphQLID,
6168

69+
// Built-in Directives defined by the Spec
70+
specifiedDirectives,
71+
GraphQLIncludeDirective,
72+
GraphQLSkipDirective,
73+
GraphQLDeprecatedDirective,
74+
75+
// Constant Deprecation Reason
76+
DEFAULT_DEPRECATION_REASON,
77+
78+
// Meta-field definitions.
79+
SchemaMetaFieldDef,
80+
TypeMetaFieldDef,
81+
TypeNameMetaFieldDef,
82+
83+
// GraphQL Types for introspection.
84+
__Schema,
85+
__Directive,
86+
__DirectiveLocation,
87+
__Type,
88+
__Field,
89+
__InputValue,
90+
__EnumValue,
91+
__TypeKind,
92+
6293
// Predicates
6394
isType,
6495
isInputType,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Copyright (c) 2015, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
import { expect } from 'chai';
11+
import { describe, it } from 'mocha';
12+
import quotedOrList from '../quotedOrList';
13+
14+
describe('quotedOrList', () => {
15+
16+
it('Does not accept an empty list', () => {
17+
expect(() => quotedOrList([])).to.throw(TypeError);
18+
});
19+
20+
it('Returns single quoted item', () => {
21+
expect(quotedOrList([ 'A' ])).to.equal('"A"');
22+
});
23+
24+
it('Returns two item list', () => {
25+
expect(quotedOrList([ 'A', 'B' ])).to.equal('"A" or "B"');
26+
});
27+
28+
it('Returns comma separated many item list', () => {
29+
expect(quotedOrList([ 'A', 'B', 'C' ])).to.equal('"A", "B", or "C"');
30+
});
31+
32+
it('Limits to five items', () => {
33+
expect(
34+
quotedOrList([ 'A', 'B', 'C', 'D', 'E', 'F' ])
35+
).to.equal(
36+
'"A", "B", "C", "D", or "E"'
37+
);
38+
});
39+
40+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Copyright (c) 2015, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
import { expect } from 'chai';
11+
import { describe, it } from 'mocha';
12+
import suggestionList from '../suggestionList';
13+
14+
describe('suggestionList', () => {
15+
16+
it('Returns results when input is empty', () => {
17+
expect(suggestionList('', [ 'a' ])).to.deep.equal([ 'a' ]);
18+
});
19+
20+
it('Returns empty array when there are no options', () => {
21+
expect(suggestionList('input', [])).to.deep.equal([]);
22+
});
23+
24+
it('Returns options sorted based on similarity', () => {
25+
expect(suggestionList('abc', [ 'a', 'ab', 'abc' ]))
26+
.to.deep.equal([ 'abc', 'ab' ]);
27+
});
28+
});

src/jsutils/quotedOrList.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* @flow */
2+
/**
3+
* Copyright (c) 2015, Facebook, Inc.
4+
* All rights reserved.
5+
*
6+
* This source code is licensed under the BSD-style license found in the
7+
* LICENSE file in the root directory of this source tree. An additional grant
8+
* of patent rights can be found in the PATENTS file in the same directory.
9+
*/
10+
11+
const MAX_LENGTH = 5;
12+
13+
/**
14+
* Given [ A, B, C ] return '"A", "B", or "C"'.
15+
*/
16+
export default function quotedOrList(items: Array<string>): string {
17+
const selected = items.slice(0, MAX_LENGTH);
18+
return selected
19+
.map(item => `"${item}"`)
20+
.reduce((list, quoted, index) =>
21+
list +
22+
(selected.length > 2 ? ', ' : ' ') +
23+
(index === selected.length - 1 ? 'or ' : '') +
24+
quoted
25+
);
26+
}

src/jsutils/suggestionList.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/* @flow */
2+
/**
3+
* Copyright (c) 2015, Facebook, Inc.
4+
* All rights reserved.
5+
*
6+
* This source code is licensed under the BSD-style license found in the
7+
* LICENSE file in the root directory of this source tree. An additional grant
8+
* of patent rights can be found in the PATENTS file in the same directory.
9+
*/
10+
11+
/**
12+
* Given an invalid input string and a list of valid options, returns a filtered
13+
* list of valid options sorted based on their similarity with the input.
14+
*/
15+
export default function suggestionList(
16+
input: string,
17+
options: Array<string>
18+
): Array<string> {
19+
const optionsByDistance = Object.create(null);
20+
const oLength = options.length;
21+
const inputThreshold = input.length / 2;
22+
for (let i = 0; i < oLength; i++) {
23+
const distance = lexicalDistance(input, options[i]);
24+
const threshold = Math.max(inputThreshold, options[i].length / 2, 1);
25+
if (distance <= threshold) {
26+
optionsByDistance[options[i]] = distance;
27+
}
28+
}
29+
return Object.keys(optionsByDistance).sort(
30+
(a , b) => optionsByDistance[a] - optionsByDistance[b]
31+
);
32+
}
33+
34+
/**
35+
* Computes the lexical distance between strings A and B.
36+
*
37+
* The "distance" between two strings is given by counting the minimum number
38+
* of edits needed to transform string A into string B. An edit can be an
39+
* insertion, deletion, or substitution of a single character, or a swap of two
40+
* adjacent characters.
41+
*
42+
* This distance can be useful for detecting typos in input or sorting
43+
*
44+
* @param {string} a
45+
* @param {string} b
46+
* @return {int} distance in number of edits
47+
*/
48+
function lexicalDistance(a, b) {
49+
let i;
50+
let j;
51+
const d = [];
52+
const aLength = a.length;
53+
const bLength = b.length;
54+
55+
for (i = 0; i <= aLength; i++) {
56+
d[i] = [ i ];
57+
}
58+
59+
for (j = 1; j <= bLength; j++) {
60+
d[0][j] = j;
61+
}
62+
63+
for (i = 1; i <= aLength; i++) {
64+
for (j = 1; j <= bLength; j++) {
65+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
66+
67+
d[i][j] = Math.min(
68+
d[i - 1][j] + 1,
69+
d[i][j - 1] + 1,
70+
d[i - 1][j - 1] + cost
71+
);
72+
73+
if (i > 1 && j > 1 &&
74+
a[i - 1] === b[j - 2] &&
75+
a[i - 2] === b[j - 1]) {
76+
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
77+
}
78+
}
79+
}
80+
81+
return d[aLength][bLength];
82+
}

src/language/__tests__/schema-kitchen-sink.graphql

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,54 @@ type Foo implements Bar {
1919
six(argument: InputType = {key: "value"}): Type
2020
}
2121

22+
type AnnotatedObject @onObject(arg: "value") {
23+
annotatedField(arg: Type = "default" @onArg): Type @onField
24+
}
25+
2226
interface Bar {
2327
one: Type
2428
four(argument: String = "string"): String
2529
}
2630

31+
interface AnnotatedInterface @onInterface {
32+
annotatedField(arg: Type @onArg): Type @onField
33+
}
34+
2735
union Feed = Story | Article | Advert
2836

37+
union AnnotatedUnion @onUnion = A | B
38+
2939
scalar CustomScalar
3040

41+
scalar AnnotatedScalar @onScalar
42+
3143
enum Site {
3244
DESKTOP
3345
MOBILE
3446
}
3547

48+
enum AnnotatedEnum @onEnum {
49+
ANNOTATED_VALUE @onEnumValue
50+
OTHER_VALUE
51+
}
52+
3653
input InputType {
3754
key: String!
3855
answer: Int = 42
3956
}
4057

58+
input AnnotatedInput @onInputObjectType {
59+
annotatedField: Type @onField
60+
}
61+
4162
extend type Foo {
4263
seven(argument: [String]): Type
4364
}
4465

66+
extend type Foo @onType {}
67+
68+
type NoFields {}
69+
4570
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
4671

4772
directive @include(if: Boolean!)

0 commit comments

Comments
 (0)