Mirror: The spec-compliant minimum of client-side GraphQL.

Backport GraphQL-Tag fix (#38)

Changed files
+41 -5
.changeset
src
+5
.changeset/tiny-gifts-exercise.md
···
+
---
+
'@0no-co/graphql.web': patch
+
---
+
+
Add `loc` getter to parsed `DocumentNode` fragment outputs to ensure that using fragments created by `gql.tada`'s `graphql()` function with `graphql-tag` doesn't crash. `graphql-tag` does not treat the `DocumentNode.loc` property as optional on interpolations, which leads to intercompatibility issues.
+1 -1
src/__tests__/parser.test.ts
···
describe('parse', () => {
it('parses the kitchen sink document like graphql.js does', () => {
-
const doc = parse(kitchenSinkDocument);
+
const doc = parse(kitchenSinkDocument, { noLocation: true });
expect(doc).toMatchSnapshot();
});
+35 -4
src/parser.ts
···
*/
import type { Kind, OperationTypeNode } from './kind';
import { GraphQLError } from './error';
-
import type { Source } from './types';
+
import type { Location, Source } from './types';
import type * as ast from './ast';
let input: string;
···
}
}
-
function document(): ast.DocumentNode {
+
function document(input: string, noLoc: boolean): ast.DocumentNode {
let match: string | undefined;
let definition: ast.OperationDefinitionNode | undefined;
ignored();
···
throw error('Document');
}
} while (idx < input.length);
+
+
if (!noLoc) {
+
let loc: Location | undefined;
+
return {
+
kind: 'Document' as Kind.DOCUMENT,
+
definitions,
+
/* v8 ignore start */
+
set loc(_loc: Location) {
+
loc = _loc;
+
},
+
/* v8 ignore stop */
+
// @ts-ignore
+
get loc() {
+
if (!loc) {
+
loc = {
+
start: 0,
+
end: input.length,
+
startToken: undefined,
+
endToken: undefined,
+
source: {
+
body: input,
+
name: 'graphql.web',
+
locationOffset: { line: 1, column: 1 },
+
},
+
};
+
}
+
return loc;
+
},
+
};
+
}
+
return {
kind: 'Document' as Kind.DOCUMENT,
definitions,
···
export function parse(
string: string | Source,
-
_options?: ParseOptions | undefined
+
options?: ParseOptions | undefined
): ast.DocumentNode {
input = typeof string.body === 'string' ? string.body : string;
idx = 0;
-
return document();
+
return document(input, options && options.noLocation);
}
export function parseValue(