Socket
Socket
Sign inDemoInstall

apollo-codegen-core

Package Overview
Dependencies
Maintainers
1
Versions
168
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

apollo-codegen-core - npm Package Compare versions

Comparing version 0.27.0 to 0.27.3

LICENSE

10

lib/compiler/index.d.ts

@@ -1,2 +0,2 @@

import { GraphQLOutputType, GraphQLInputType, GraphQLObjectType, GraphQLSchema, GraphQLType, GraphQLCompositeType, DocumentNode } from 'graphql';
import { GraphQLOutputType, GraphQLInputType, GraphQLObjectType, GraphQLSchema, GraphQLType, GraphQLCompositeType, DocumentNode } from "graphql";
export interface CompilerOptions {

@@ -53,3 +53,3 @@ addTypename?: boolean;

export interface Field {
kind: 'Field';
kind: "Field";
responseKey: string;

@@ -67,3 +67,3 @@ name: string;

export interface TypeCondition {
kind: 'TypeCondition';
kind: "TypeCondition";
type: GraphQLCompositeType;

@@ -73,3 +73,3 @@ selectionSet: SelectionSet;

export interface BooleanCondition {
kind: 'BooleanCondition';
kind: "BooleanCondition";
variableName: string;

@@ -80,3 +80,3 @@ inverted: boolean;

export interface FragmentSpread {
kind: 'FragmentSpread';
kind: "FragmentSpread";
fragmentName: string;

@@ -83,0 +83,0 @@ isConditional?: boolean;

@@ -66,3 +66,3 @@ "use strict";

if (!operationDefinition.name) {
throw new Error('Operations should be named');
throw new Error("Operations should be named");
}

@@ -116,18 +116,17 @@ const filePath = graphql_2.filePathForNode(operationDefinition);

const name = selectionNode.name.value;
const alias = selectionNode.alias ? selectionNode.alias.value : undefined;
const alias = selectionNode.alias
? selectionNode.alias.value
: undefined;
const fieldDef = graphql_2.getFieldDef(this.schema, parentType, selectionNode);
if (!fieldDef) {
throw new graphql_1.GraphQLError(`Cannot query field "${name}" on type "${String(parentType)}"`, [
selectionNode
]);
throw new graphql_1.GraphQLError(`Cannot query field "${name}" on type "${String(parentType)}"`, [selectionNode]);
}
if (fieldDef.astNode && fieldDef.astNode.__client && !(isClient || fieldIsClient)) {
throw new graphql_1.GraphQLError(`Cannot query client-side field "${name}" on type "${String(parentType)}" without @client directive`, [
selectionNode
]);
if (fieldDef.astNode &&
fieldDef.astNode.__client &&
!(isClient || fieldIsClient)) {
throw new graphql_1.GraphQLError(`Cannot query client-side field "${name}" on type "${String(parentType)}" without @client directive`, [selectionNode]);
}
if (!(fieldDef.astNode && fieldDef.astNode.__client) && fieldIsClient) {
throw new graphql_1.GraphQLError(`Cannot query server-side field "${name}" on type "${String(parentType)}" with @client directive`, [
selectionNode
]);
if (!(fieldDef.astNode && fieldDef.astNode.__client) &&
fieldIsClient) {
throw new graphql_1.GraphQLError(`Cannot query server-side field "${name}" on type "${String(parentType)}" with @client directive`, [selectionNode]);
}

@@ -151,3 +150,3 @@ const fieldType = fieldDef.type;

let field = {
kind: 'Field',
kind: "Field",
responseKey,

@@ -173,6 +172,8 @@ name,

const typeNode = selectionNode.typeCondition;
const type = typeNode ? graphql_1.typeFromAST(this.schema, typeNode) : parentType;
const type = typeNode
? graphql_1.typeFromAST(this.schema, typeNode)
: parentType;
const possibleTypesForTypeCondition = this.possibleTypesForType(type).filter(type => possibleTypes.includes(type));
return {
kind: 'TypeCondition',
kind: "TypeCondition",
type,

@@ -188,3 +189,3 @@ selectionSet: this.compileSelectionSet(selectionNode.selectionSet, type, isClient, possibleTypesForTypeCondition)

const fragmentSpread = {
kind: 'FragmentSpread',
kind: "FragmentSpread",
fragmentName,

@@ -217,3 +218,3 @@ selectionSet: {

const directiveName = directive.name.value;
if (directiveName === 'skip' || directiveName === 'include') {
if (directiveName === "skip" || directiveName === "include") {
if (!directive.arguments)

@@ -223,4 +224,4 @@ continue;

switch (value.kind) {
case 'BooleanValue':
if (directiveName === 'skip') {
case "BooleanValue":
if (directiveName === "skip") {
return value.value ? null : selection;

@@ -232,7 +233,7 @@ }

break;
case 'Variable':
case "Variable":
selection = {
kind: 'BooleanCondition',
kind: "BooleanCondition",
variableName: value.name.value,
inverted: directiveName === 'skip',
inverted: directiveName === "skip",
selectionSet: {

@@ -239,0 +240,0 @@ possibleTypes,

@@ -1,3 +0,3 @@

import { GraphQLSchema, GraphQLType, GraphQLObjectType, GraphQLCompositeType, GraphQLInputType, DocumentNode } from 'graphql';
import '../utilities/array';
import { GraphQLSchema, GraphQLType, GraphQLObjectType, GraphQLCompositeType, GraphQLInputType, DocumentNode } from "graphql";
import "../utilities/array";
export interface CompilerOptions {

@@ -4,0 +4,0 @@ addTypename?: boolean;

@@ -103,3 +103,5 @@ "use strict";

isDeprecated,
deprecationReason }, (selectionSet ? this.transformSelectionSetToLegacyIR(selectionSet) : {}));
deprecationReason }, (selectionSet
? this.transformSelectionSetToLegacyIR(selectionSet)
: {}));
});

@@ -111,6 +113,6 @@ }

switch (selection.kind) {
case 'FragmentSpread':
case "FragmentSpread":
fragmentSpreads.push(selection);
break;
case 'TypeCondition':
case "TypeCondition":
if (possibleTypes.every(type => selection.selectionSet.possibleTypes.includes(type))) {

@@ -120,3 +122,3 @@ fragmentSpreads.push(...this.collectFragmentSpreads(selection.selectionSet, possibleTypes));

break;
case 'BooleanCondition':
case "BooleanCondition":
fragmentSpreads.push(...this.collectFragmentSpreads(selection.selectionSet, possibleTypes));

@@ -123,0 +125,0 @@ break;

@@ -1,3 +0,3 @@

import { SelectionSet, Selection, Field, BooleanCondition } from '../';
declare module '../' {
import { SelectionSet, Selection, Field, BooleanCondition } from "../";
declare module "../" {
interface Field {

@@ -4,0 +4,0 @@ conditions?: BooleanCondition[];

@@ -10,3 +10,3 @@ "use strict";

switch (selection.kind) {
case 'Field':
case "Field":
let groupForResponseKey = groupedFields.get(selection.responseKey);

@@ -24,5 +24,5 @@ if (!groupForResponseKey) {

break;
case 'FragmentSpread':
case 'TypeCondition':
if (selection.kind === 'FragmentSpread' && !mergeInFragmentSpreads)
case "FragmentSpread":
case "TypeCondition":
if (selection.kind === "FragmentSpread" && !mergeInFragmentSpreads)
continue;

@@ -33,4 +33,7 @@ if (!possibleTypes.every(type => selection.selectionSet.possibleTypes.includes(type)))

break;
case 'BooleanCondition':
visitSelectionSet(selection.selectionSet.selections, possibleTypes, [...conditions, selection]);
case "BooleanCondition":
visitSelectionSet(selection.selectionSet.selections, possibleTypes, [
...conditions,
selection
]);
break;

@@ -45,3 +48,5 @@ }

.map(field => {
if (isFieldIncludedUnconditionally && field.isConditional && field.selectionSet) {
if (isFieldIncludedUnconditionally &&
field.isConditional &&
field.selectionSet) {
field.selectionSet.selections = wrapInBooleanConditionsIfNeeded(field.selectionSet.selections, field.conditions);

@@ -48,0 +53,0 @@ }

@@ -1,4 +0,4 @@

import { SelectionSet, Fragment } from '../';
import { SelectionSet, Fragment } from "../";
export declare function collectFragmentsReferenced(selectionSet: SelectionSet, fragments: {
[fragmentName: string]: Fragment;
}, fragmentsReferenced?: Set<string>): Set<string>;

@@ -6,3 +6,3 @@ "use strict";

switch (selection.kind) {
case 'FragmentSpread':
case "FragmentSpread":
fragmentsReferenced.add(selection.fragmentName);

@@ -15,5 +15,5 @@ const fragment = fragments[selection.fragmentName];

break;
case 'Field':
case 'TypeCondition':
case 'BooleanCondition':
case "Field":
case "TypeCondition":
case "BooleanCondition":
if (selection.selectionSet) {

@@ -20,0 +20,0 @@ collectFragmentsReferenced(selection.selectionSet, fragments, fragmentsReferenced);

@@ -1,2 +0,2 @@

import { Operation, Fragment } from '../';
import { Operation, Fragment } from "../";
export declare function generateOperationId(operation: Operation, fragments: {

@@ -3,0 +3,0 @@ [fragmentName: string]: Fragment;

@@ -18,6 +18,6 @@ "use strict";

})
].join('\n');
const hash = crypto_1.createHash('sha256');
].join("\n");
const hash = crypto_1.createHash("sha256");
hash.update(sourceWithFragments);
const operationId = hash.digest('hex');
const operationId = hash.digest("hex");
return { operationId, sourceWithFragments };

@@ -24,0 +24,0 @@ }

@@ -1,2 +0,2 @@

import { SelectionSet } from '../';
import { SelectionSet } from "../";
export declare function inlineRedundantTypeConditions(selectionSet: SelectionSet): SelectionSet;

@@ -6,3 +6,3 @@ "use strict";

for (const selection of selectionSet.selections) {
if (selection.kind === 'TypeCondition' &&
if (selection.kind === "TypeCondition" &&
selectionSet.possibleTypes.every(type => selection.selectionSet.possibleTypes.includes(type))) {

@@ -9,0 +9,0 @@ selections.push(...inlineRedundantTypeConditions(selection.selectionSet).selections);

@@ -1,3 +0,3 @@

import { GraphQLObjectType } from 'graphql';
import { SelectionSet, Selection, Field, FragmentSpread } from '../';
import { GraphQLObjectType } from "graphql";
import { SelectionSet, Selection, Field, FragmentSpread } from "../";
export declare class Variant implements SelectionSet {

@@ -4,0 +4,0 @@ possibleTypes: GraphQLObjectType[];

@@ -23,3 +23,3 @@ "use strict";

switch (selection.kind) {
case 'Field':
case "Field":
for (const variant of typeCase.disjointVariantsFor(selectionSet.possibleTypes)) {

@@ -29,3 +29,3 @@ variant.selections.push(selection);

break;
case 'FragmentSpread':
case "FragmentSpread":
if (typeCase.default.fragmentSpreads.some(fragmentSpread => fragmentSpread.fragmentName === selection.fragmentName))

@@ -46,3 +46,3 @@ continue;

break;
case 'TypeCondition':
case "TypeCondition":
typeCase.merge(typeCaseForSelectionSet({

@@ -53,3 +53,3 @@ possibleTypes: selectionSet.possibleTypes.filter(type => selection.selectionSet.possibleTypes.includes(type)),

break;
case 'BooleanCondition':
case "BooleanCondition":
typeCase.merge(typeCaseForSelectionSet(selection.selectionSet, mergeInFragmentSpreads), selectionSet => [

@@ -126,3 +126,6 @@ Object.assign({}, selection, { selectionSet })

if (otherVariant.fragmentSpreads.length > 0) {
variant.fragmentSpreads = [...variant.fragmentSpreads, ...otherVariant.fragmentSpreads].filter((a, index, array) => array.findIndex(b => b.fragmentName == a.fragmentName) == index);
variant.fragmentSpreads = [
...variant.fragmentSpreads,
...otherVariant.fragmentSpreads
].filter((a, index, array) => array.findIndex(b => b.fragmentName == a.fragmentName) == index);
}

@@ -136,3 +139,3 @@ variant.selections.push(...(transform ? transform(otherVariant) : otherVariant.selections));

` default -> ${util_1.inspect(this.default)}\n` +
this.variants.map(variant => ` ${util_1.inspect(variant)}\n`).join(''));
this.variants.map(variant => ` ${util_1.inspect(variant)}\n`).join(""));
}

@@ -139,0 +142,0 @@ }

@@ -8,3 +8,3 @@ "use strict";

super(message);
this.name = 'ToolError';
this.name = "ToolError";
this.message = message;

@@ -46,3 +46,7 @@ }

if (fileName) {
const truncatedFileName = '/' + fileName.split(path.sep).slice(-4).join(path.sep);
const truncatedFileName = "/" +
fileName
.split(path.sep)
.slice(-4)
.join(path.sep);
console.error(`...${truncatedFileName}: ${message}`);

@@ -49,0 +53,0 @@ }

@@ -1,1 +0,1 @@

import './polyfills';
import "./polyfills";

@@ -85,3 +85,4 @@ "use strict";

}
}).filter(source => source);
})
.filter(source => source);
return sources;

@@ -88,0 +89,0 @@ }

@@ -1,3 +0,3 @@

import 'core-js/fn/object/values';
import 'core-js/fn/object/entries';
import 'core-js/fn/array/flat-map';
import "core-js/fn/object/values";
import "core-js/fn/object/entries";
import "core-js/fn/array/flat-map";

@@ -1,3 +0,3 @@

import { LegacyCompilerContext } from './compiler/legacyIR';
import { LegacyCompilerContext } from "./compiler/legacyIR";
export default function serializeToJSON(context: LegacyCompilerContext): string;
export declare function serializeAST(ast: any, space?: string): string;

@@ -8,4 +8,4 @@ "use strict";

fragments: Object.values(context.fragments),
typesUsed: context.typesUsed.map(serializeType),
}, '\t');
typesUsed: context.typesUsed.map(serializeType)
}, "\t");
}

@@ -42,3 +42,3 @@ exports.default = serializeToJSON;

return {
kind: 'EnumType',
kind: "EnumType",
name,

@@ -58,3 +58,3 @@ description,

return {
kind: 'InputObjectType',
kind: "InputObjectType",
name,

@@ -73,3 +73,3 @@ description,

return {
kind: 'ScalarType',
kind: "ScalarType",
name,

@@ -76,0 +76,0 @@ description

@@ -10,3 +10,2 @@ "use strict";

exports.maybePush = maybePush;
;
//# sourceMappingURL=array.js.map

@@ -9,3 +9,3 @@ "use strict";

this.startOfIndentLevel = false;
this.output = '';
this.output = "";
}

@@ -20,3 +20,3 @@ pushScope(scope) {

if (this.scopeStack.length < 1)
throw new Error('No active scope');
throw new Error("No active scope");
return this.scopeStack[this.scopeStack.length - 1];

@@ -31,3 +31,3 @@ }

if (this.output) {
this.print('\n');
this.print("\n");
this.startOfIndentLevel = false;

@@ -49,3 +49,3 @@ }

printIndent() {
const indentation = ' '.repeat(this.indentLevel * this.indentWidth);
const indentation = " ".repeat(this.indentLevel * this.indentWidth);
this.output += indentation;

@@ -61,3 +61,3 @@ }

}
withinBlock(closure, open = ' {', close = '}') {
withinBlock(closure, open = " {", close = "}") {
this.print(open);

@@ -116,3 +116,3 @@ this.withIndent(closure);

}
withinBlock(closure, open = ' {', close = '}') {
withinBlock(closure, open = " {", close = "}") {
this.currentFile.withinBlock(closure, open, close);

@@ -119,0 +119,0 @@ }

@@ -1,10 +0,2 @@

import { GraphQLNamedType, GraphQLCompositeType, GraphQLObjectType, GraphQLEnumValue, GraphQLError, GraphQLSchema, GraphQLType, GraphQLScalarType, ASTNode, Location, ValueNode, OperationDefinitionNode, FieldNode, GraphQLField, DocumentNode } from 'graphql';
declare module "graphql" {
function isNamedType(type: GraphQLType): type is GraphQLNamedType;
const specifiedScalarTypes: GraphQLScalarType[];
function isSpecifiedScalarType(type: GraphQLType): boolean;
const introspectionTypes: GraphQLNamedType[];
function isIntrospectionType(type: GraphQLType): boolean;
function validateSchema(schema: GraphQLSchema): GraphQLError[];
}
import { GraphQLCompositeType, GraphQLObjectType, GraphQLEnumValue, GraphQLSchema, GraphQLType, ASTNode, Location, ValueNode, OperationDefinitionNode, FieldNode, GraphQLField, DocumentNode } from "graphql";
declare module "graphql/utilities/buildASTSchema" {

@@ -23,3 +15,3 @@ function buildASTSchema(ast: DocumentNode, options?: {

export declare function valueFromValueNode(valueNode: ValueNode): any | {
kind: 'Variable';
kind: "Variable";
variableName: string;

@@ -26,0 +18,0 @@ };

@@ -5,14 +5,18 @@ "use strict";

function sortEnumValues(values) {
return values.sort((a, b) => a.value < b.value ? -1 : a.value > b.value ? 1 : 0);
return values.sort((a, b) => (a.value < b.value ? -1 : a.value > b.value ? 1 : 0));
}
exports.sortEnumValues = sortEnumValues;
function isList(type) {
return type instanceof graphql_1.GraphQLList || (type instanceof graphql_1.GraphQLNonNull && type.ofType instanceof graphql_1.GraphQLList);
return (type instanceof graphql_1.GraphQLList ||
(type instanceof graphql_1.GraphQLNonNull && type.ofType instanceof graphql_1.GraphQLList));
}
exports.isList = isList;
function isMetaFieldName(name) {
return name.startsWith('__');
return name.startsWith("__");
}
exports.isMetaFieldName = isMetaFieldName;
const typenameField = { kind: graphql_1.Kind.FIELD, name: { kind: graphql_1.Kind.NAME, value: '__typename' } };
const typenameField = {
kind: graphql_1.Kind.FIELD,
name: { kind: graphql_1.Kind.NAME, value: "__typename" }
};
function withTypenameFieldAddedWhereNeeded(ast) {

@@ -22,7 +26,8 @@ return graphql_1.visit(ast, {

SelectionSet(node) {
return Object.assign({}, node, { selections: node.selections.filter(selection => !(selection.kind === 'Field' && selection.name.value === '__typename')) });
return Object.assign({}, node, { selections: node.selections.filter(selection => !(selection.kind === "Field" &&
selection.name.value === "__typename")) });
}
},
leave(node) {
if (!(node.kind === 'Field' || node.kind === 'FragmentDefinition'))
if (!(node.kind === "Field" || node.kind === "FragmentDefinition"))
return undefined;

@@ -55,10 +60,10 @@ if (!node.selectionSet)

switch (valueNode.kind) {
case 'IntValue':
case 'FloatValue':
case "IntValue":
case "FloatValue":
return Number(valueNode.value);
case 'NullValue':
case "NullValue":
return null;
case 'ListValue':
case "ListValue":
return valueNode.values.map(valueFromValueNode);
case 'ObjectValue':
case "ObjectValue":
return valueNode.fields.reduce((object, field) => {

@@ -68,4 +73,4 @@ object[field.name.value] = valueFromValueNode(field.value);

}, {});
case 'Variable':
return { kind: 'Variable', variableName: valueNode.name.value };
case "Variable":
return { kind: "Variable", variableName: valueNode.name.value };
default:

@@ -77,3 +82,6 @@ return valueNode.value;

function isTypeProperSuperTypeOf(schema, maybeSuperType, subType) {
return graphql_1.isEqualType(maybeSuperType, subType) || subType instanceof graphql_1.GraphQLObjectType && (graphql_1.isAbstractType(maybeSuperType) && schema.isPossibleType(maybeSuperType, subType));
return (graphql_1.isEqualType(maybeSuperType, subType) ||
(subType instanceof graphql_1.GraphQLObjectType &&
(graphql_1.isAbstractType(maybeSuperType) &&
schema.isPossibleType(maybeSuperType, subType))));
}

@@ -83,18 +91,22 @@ exports.isTypeProperSuperTypeOf = isTypeProperSuperTypeOf;

switch (operation.operation) {
case 'query':
case "query":
return schema.getQueryType();
case 'mutation':
case "mutation":
const mutationType = schema.getMutationType();
if (!mutationType) {
throw new graphql_1.GraphQLError('Schema is not configured for mutations', [operation]);
throw new graphql_1.GraphQLError("Schema is not configured for mutations", [
operation
]);
}
return mutationType;
case 'subscription':
case "subscription":
const subscriptionType = schema.getSubscriptionType();
if (!subscriptionType) {
throw new graphql_1.GraphQLError('Schema is not configured for subscriptions', [operation]);
throw new graphql_1.GraphQLError("Schema is not configured for subscriptions", [
operation
]);
}
return subscriptionType;
default:
throw new graphql_1.GraphQLError('Can only compile queries, mutations and subscriptions', [operation]);
throw new graphql_1.GraphQLError("Can only compile queries, mutations and subscriptions", [operation]);
}

@@ -109,4 +121,3 @@ }

}
if (name === graphql_1.TypeMetaFieldDef.name &&
schema.getQueryType() === parentType) {
if (name === graphql_1.TypeMetaFieldDef.name && schema.getQueryType() === parentType) {
return graphql_1.TypeMetaFieldDef;

@@ -113,0 +124,0 @@ }

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function join(maybeArray, separator) {
return maybeArray ? maybeArray.filter(x => x).join(separator || '') : '';
return maybeArray ? maybeArray.filter(x => x).join(separator || "") : "";
}
exports.join = join;
function block(array) {
return array && array.length !== 0 ?
indent('{\n' + join(array, '\n')) + '\n}' :
'{}';
return array && array.length !== 0
? indent("{\n" + join(array, "\n")) + "\n}"
: "{}";
}
exports.block = block;
function wrap(start, maybeString, end) {
return maybeString ?
start + maybeString + (end || '') :
'';
return maybeString ? start + maybeString + (end || "") : "";
}
exports.wrap = wrap;
function indent(maybeString) {
return maybeString && maybeString.replace(/\n/g, '\n ');
return maybeString && maybeString.replace(/\n/g, "\n ");
}
exports.indent = indent;
function commentBlockContent(commentString) {
return '*\n' + commentString
.split('\n')
.map(line => ` * ${line.replace('*/', '')}`)
.join('\n') + '\n ';
return ("*\n" +
commentString
.split("\n")
.map(line => ` * ${line.replace("*/", "")}`)
.join("\n") +
"\n ");
}
exports.commentBlockContent = commentBlockContent;
//# sourceMappingURL=printing.js.map
{
"name": "apollo-codegen-core",
"description": "Core generator APIs for Apollo Codegen",
"version": "0.27.0",
"main": "./lib/index.js",
"version": "0.27.3",
"author": "Apollo GraphQL <opensource@apollographql.com>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/apollographql/apollo-cli.git"
},
"homepage": "https://github.com/apollographql/apollo-cli",
"bugs": "https://github.com/apollographql/apollo-cli/issues",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"clean": "rm -rf lib",
"prebuild": "npm run clean",
"build": "tsc -p .",
"watch": "tsc -w -p .",
"test": "./node_modules/.bin/jest",
"prepack": "npm run build"
"build": "tsc",
"prepare": "npm run build"
},
"repository": {
"type": "git",
"url": "apollographql/apollo-cli"
},
"author": "Martijn Walraven <martijn@martijnwalraven.com>",
"license": "MIT",
"engines": {
"node": ">=6.0",
"npm": ">=5.0"
"node": ">=8",
"npm": ">=6"
},
"devDependencies": {
"@types/babel-generator": "^6.25.1",
"@types/babel-types": "^7.0.0",
"@types/common-tags": "^1.4.0",
"@types/graphql": "^0.13.1",
"@types/jest": "^21.1.8",
"graphql": "^0.13.1",
"jest": "^22.0.3",
"jest-matcher-utils": "^22.0.3",
"lerna": "^2.11.0",
"ts-jest": "^22.0.0",
"typescript": "^2.6.2"
},
"dependencies": {

@@ -43,5 +31,2 @@ "@babel/generator": "7.0.0-beta.38",

},
"peerDependencies": {
"graphql": "^0.11.0 || ^0.12.0 || ^0.13.0"
},
"jest": {

@@ -75,3 +60,4 @@ "testEnvironment": "node",

}
}
},
"gitHead": "e8d31998beae239ea92e140c670f45412ca0ffd4"
}

@@ -11,2 +11,2 @@ const query = gql`

}
`
`;

@@ -8,2 +8,2 @@ const query = gql`

}
`
`;

@@ -9,2 +9,2 @@ const query = gql`

}
`
`;

@@ -1,9 +0,14 @@

import { GraphQLSchema, buildSchema, parse } from 'graphql';
import { compileToLegacyIR } from '../compiler/legacyIR';
import serializeToJSON from '../serializeToJSON';
import { GraphQLSchema, buildSchema, parse } from "graphql";
import { compileToLegacyIR } from "../compiler/legacyIR";
import serializeToJSON from "../serializeToJSON";
import { loadSchema } from '../loading';
const starWarsSchema = loadSchema(require.resolve('../../../common-test/fixtures/starwars/schema.json'));
import { loadSchema } from "../loading";
const starWarsSchema = loadSchema(
require.resolve("../../../common-test/fixtures/starwars/schema.json")
);
function compileFromSource(source: string, schema: GraphQLSchema = starWarsSchema) {
function compileFromSource(
source: string,
schema: GraphQLSchema = starWarsSchema
) {
const document = parse(source);

@@ -16,3 +21,3 @@ return compileToLegacyIR(schema, document, {

describe('JSON output', function() {
describe("JSON output", function() {
test(`should generate JSON output for a query with an enum variable`, function() {

@@ -19,0 +24,0 @@ const context = compileFromSource(`

@@ -1,4 +0,4 @@

import { stripIndents } from 'common-tags';
import * as fs from 'fs';
import * as path from 'path';
import { stripIndents } from "common-tags";
import * as fs from "fs";
import * as path from "path";

@@ -8,11 +8,12 @@ import {

loadAndMergeQueryDocuments
} from '../loading';
} from "../loading";
// Test example javascript source files are located within __fixtures__
describe('extractDocumentFromJavascript', () => {
test('normal queries', () => {
const contents = fs.readFileSync(path.join(__dirname, '__fixtures__', 'normal.js')).toString();
expect(stripIndents`${extractDocumentFromJavascript(contents)}`)
.toMatch(
stripIndents`
describe("extractDocumentFromJavascript", () => {
test("normal queries", () => {
const contents = fs
.readFileSync(path.join(__dirname, "__fixtures__", "normal.js"))
.toString();
expect(stripIndents`${extractDocumentFromJavascript(contents)}`).toMatch(
stripIndents`
query UserProfileView {

@@ -26,10 +27,11 @@ me {

`
);
);
});
test('comments in template string', () => {
const contents = fs.readFileSync(path.join(__dirname, '__fixtures__', 'comments.js')).toString();
expect(stripIndents`${extractDocumentFromJavascript(contents)}`)
.toMatch(
stripIndents`
test("comments in template string", () => {
const contents = fs
.readFileSync(path.join(__dirname, "__fixtures__", "comments.js"))
.toString();
expect(stripIndents`${extractDocumentFromJavascript(contents)}`).toMatch(
stripIndents`
query UserProfileView {

@@ -45,22 +47,27 @@ me {

`
);
);
});
test('gql completely commented out', () => {
const contents = fs.readFileSync(path.join(__dirname, '__fixtures__', 'commentedOut.js')).toString();
expect(extractDocumentFromJavascript(contents))
.toBeNull();
test("gql completely commented out", () => {
const contents = fs
.readFileSync(path.join(__dirname, "__fixtures__", "commentedOut.js"))
.toString();
expect(extractDocumentFromJavascript(contents)).toBeNull();
});
test('invalid gql', () => {
const contents = fs.readFileSync(path.join(__dirname, '__fixtures__', 'invalid.js')).toString();
expect(extractDocumentFromJavascript(contents))
.toBeNull();
test("invalid gql", () => {
const contents = fs
.readFileSync(path.join(__dirname, "__fixtures__", "invalid.js"))
.toString();
expect(extractDocumentFromJavascript(contents)).toBeNull();
});
});
describe('Validation', () => {
describe("Validation", () => {
test(`should extract gql snippet from javascript file`, () => {
const inputPaths = [
path.join(__dirname, '../../../common-test/fixtures/starwars/gqlQueries.js'),
path.join(
__dirname,
"../../../common-test/fixtures/starwars/gqlQueries.js"
)
];

@@ -71,4 +78,3 @@

expect(document).toMatchSnapshot();
})
});
});

@@ -1,8 +0,8 @@

import { parseValue } from 'graphql';
import { parseValue } from "graphql";
import { valueFromValueNode } from '../utilities/graphql';
import { valueFromValueNode } from "../utilities/graphql";
describe('#valueFromValueNode', () => {
describe("#valueFromValueNode", () => {
test(`should return a number for an IntValue`, () => {
const valueNode = parseValue('1');
const valueNode = parseValue("1");
const value = valueFromValueNode(valueNode);

@@ -14,3 +14,3 @@

test(`should return a number for a FloatValue`, () => {
const valueNode = parseValue('1.0');
const valueNode = parseValue("1.0");
const value = valueFromValueNode(valueNode);

@@ -22,3 +22,3 @@

test(`should return a boolean for a BooleanValue`, () => {
const valueNode = parseValue('true');
const valueNode = parseValue("true");
const value = valueFromValueNode(valueNode);

@@ -30,3 +30,3 @@

test(`should return null for a NullValue`, () => {
const valueNode = parseValue('null');
const valueNode = parseValue("null");
const value = valueFromValueNode(valueNode);

@@ -41,17 +41,17 @@

expect(value).toBe('foo');
expect(value).toBe("foo");
});
test(`should return a string for an EnumValue`, () => {
const valueNode = parseValue('JEDI');
const valueNode = parseValue("JEDI");
const value = valueFromValueNode(valueNode);
expect(value).toBe('JEDI');
expect(value).toBe("JEDI");
});
test(`should return an object for a Variable`, () => {
const valueNode = parseValue('$something');
const valueNode = parseValue("$something");
const value = valueFromValueNode(valueNode);
expect(value).toEqual({ kind: 'Variable', variableName: 'something' });
expect(value).toEqual({ kind: "Variable", variableName: "something" });
});

@@ -63,16 +63,23 @@

expect(value).toEqual(['foo', 1, 'JEDI', { kind: 'Variable', variableName: 'something' }]);
expect(value).toEqual([
"foo",
1,
"JEDI",
{ kind: "Variable", variableName: "something" }
]);
});
test(`should return an object for an ObjectValue`, () => {
const valueNode = parseValue('{ foo: "foo", bar: 1, bla: JEDI, baz: $something }');
const valueNode = parseValue(
'{ foo: "foo", bar: 1, bla: JEDI, baz: $something }'
);
const value = valueFromValueNode(valueNode);
expect(value).toEqual({
foo: 'foo',
foo: "foo",
bar: 1,
bla: 'JEDI',
baz: { kind: 'Variable', variableName: 'something' }
bla: "JEDI",
baz: { kind: "Variable", variableName: "something" }
});
});
});

@@ -1,2 +0,2 @@

import { stripIndent } from 'common-tags'
import { stripIndent } from "common-tags";

@@ -10,8 +10,8 @@ import {

GraphQLNonNull
} from 'graphql';
} from "graphql";
import { loadSchema } from '../../loading'
import { loadSchema } from "../../loading";
import { compileToLegacyIR } from '../legacyIR'
import { serializeAST } from '../../serializeToJSON'
import { compileToLegacyIR } from "../legacyIR";
import { serializeAST } from "../../serializeToJSON";

@@ -22,5 +22,7 @@ function withStringifiedTypes(ir) {

const schema = loadSchema(require.resolve('../../../../common-test/fixtures/starwars/schema.json'));
const schema = loadSchema(
require.resolve("../../../../common-test/fixtures/starwars/schema.json")
);
describe('Compiling query documents to the legacy IR', () => {
describe("Compiling query documents to the legacy IR", () => {
it(`should include variables defined in operations`, () => {

@@ -50,22 +52,18 @@ const document = parse(`

const { operations } = withStringifiedTypes(compileToLegacyIR(schema, document));
expect(operations['HeroName'].variables).toEqual(
[
{ name: 'episode', type: 'Episode' }
]
const { operations } = withStringifiedTypes(
compileToLegacyIR(schema, document)
);
expect(operations['Search'].variables).toEqual(
[
{ name: 'text', type: 'String!' }
]
);
expect(operations["HeroName"].variables).toEqual([
{ name: "episode", type: "Episode" }
]);
expect(operations['CreateReviewForEpisode'].variables).toEqual(
[
{ name: 'episode', type: 'Episode!' },
{ name: 'review', type: 'ReviewInput!' }
]
);
expect(operations["Search"].variables).toEqual([
{ name: "text", type: "String!" }
]);
expect(operations["CreateReviewForEpisode"].variables).toEqual([
{ name: "episode", type: "Episode!" },
{ name: "review", type: "ReviewInput!" }
]);
});

@@ -97,5 +95,7 @@

const { typesUsed } = withStringifiedTypes(compileToLegacyIR(schema, document));
const { typesUsed } = withStringifiedTypes(
compileToLegacyIR(schema, document)
);
expect(typesUsed).toEqual(['Episode', 'ReviewInput', 'ColorInput']);
expect(typesUsed).toEqual(["Episode", "ReviewInput", "ColorInput"]);
});

@@ -117,5 +117,7 @@

const { typesUsed } = withStringifiedTypes(compileToLegacyIR(schema, document));
const { typesUsed } = withStringifiedTypes(
compileToLegacyIR(schema, document)
);
expect(typesUsed).toEqual(['Episode']);
expect(typesUsed).toEqual(["Episode"]);
});

@@ -132,6 +134,8 @@

const { typesUsed } = withStringifiedTypes(compileToLegacyIR(schema, document));
const { typesUsed } = withStringifiedTypes(
compileToLegacyIR(schema, document)
);
expect(typesUsed).toContain('ReviewInput');
expect(typesUsed).toContain('ColorInput');
expect(typesUsed).toContain("ReviewInput");
expect(typesUsed).toContain("ColorInput");
});

@@ -153,3 +157,3 @@

expect(operations['HeroName'].fields[0].fieldName).toBe("hero");
expect(operations["HeroName"].fields[0].fieldName).toBe("hero");
});

@@ -168,4 +172,5 @@

expect(operations['HeroName'].fields[0].args)
.toEqual([{ name: "episode", value: "EMPIRE", type: schema.getType("Episode") }]);
expect(operations["HeroName"].fields[0].args).toEqual([
{ name: "episode", value: "EMPIRE", type: schema.getType("Episode") }
]);
});

@@ -190,9 +195,13 @@

expect(operations['HeroNameConditionalInclusion'].fields[0].fields[0]).toMatchObject({
fieldName: 'name',
expect(
operations["HeroNameConditionalInclusion"].fields[0].fields[0]
).toMatchObject({
fieldName: "name",
isConditional: true
});
expect(operations['HeroNameConditionalExclusion'].fields[0].fields[0]).toMatchObject({
fieldName: 'name',
expect(
operations["HeroNameConditionalExclusion"].fields[0].fields[0]
).toMatchObject({
fieldName: "name",
isConditional: true

@@ -219,9 +228,13 @@ });

expect(operations['HeroNameConditionalInclusion'].fields[0].fields[0]).toMatchObject({
fieldName: 'name',
expect(
operations["HeroNameConditionalInclusion"].fields[0].fields[0]
).toMatchObject({
fieldName: "name",
isConditional: false
});
expect(operations['HeroNameConditionalExclusion'].fields[0].fields[0]).toMatchObject({
fieldName: 'name',
expect(
operations["HeroNameConditionalExclusion"].fields[0].fields[0]
).toMatchObject({
fieldName: "name",
isConditional: false

@@ -248,7 +261,11 @@ });

expect(operations['HeroNameConditionalInclusion'].fields[0].fields).toHaveLength(0);
expect(operations['HeroNameConditionalExclusion'].fields[0].fields).toHaveLength(0);
expect(
operations["HeroNameConditionalInclusion"].fields[0].fields
).toHaveLength(0);
expect(
operations["HeroNameConditionalExclusion"].fields[0].fields
).toHaveLength(0);
});
it(`should include isConditional if a field in inside an inline fragment with skip or include directives with variables`, () => {
it(`should include isConditional if a field in inside an inline fragment with skip or include directives with variables`, () => {
const document = parse(`

@@ -274,9 +291,13 @@ query HeroNameConditionalInclusion($includeName: Boolean!) {

expect(operations['HeroNameConditionalInclusion'].fields[0].fields[0]).toMatchObject({
fieldName: 'name',
expect(
operations["HeroNameConditionalInclusion"].fields[0].fields[0]
).toMatchObject({
fieldName: "name",
isConditional: true
});
expect(operations['HeroNameConditionalExclusion'].fields[0].fields[0]).toMatchObject({
fieldName: 'name',
expect(
operations["HeroNameConditionalExclusion"].fields[0].fields[0]
).toMatchObject({
fieldName: "name",
isConditional: true

@@ -307,17 +328,29 @@ });

expect(operations['HeroNameConditionalInclusion'].fields[0].fields[0]).toMatchObject({
fieldName: 'name',
expect(
operations["HeroNameConditionalInclusion"].fields[0].fields[0]
).toMatchObject({
fieldName: "name",
isConditional: true
});
expect(operations['HeroNameConditionalExclusion'].fields[0].fields[0]).toMatchObject({
fieldName: 'name',
expect(
operations["HeroNameConditionalExclusion"].fields[0].fields[0]
).toMatchObject({
fieldName: "name",
isConditional: true
});
expect(operations['HeroNameConditionalInclusion'].fragmentsReferenced).toEqual(['HeroName']);
expect(operations['HeroNameConditionalInclusion'].fields[0].fragmentSpreads).toEqual(['HeroName']);
expect(
operations["HeroNameConditionalInclusion"].fragmentsReferenced
).toEqual(["HeroName"]);
expect(
operations["HeroNameConditionalInclusion"].fields[0].fragmentSpreads
).toEqual(["HeroName"]);
expect(operations['HeroNameConditionalExclusion'].fragmentsReferenced).toEqual(['HeroName']);
expect(operations['HeroNameConditionalExclusion'].fields[0].fragmentSpreads).toEqual(['HeroName']);
expect(
operations["HeroNameConditionalExclusion"].fragmentsReferenced
).toEqual(["HeroName"]);
expect(
operations["HeroNameConditionalExclusion"].fields[0].fragmentSpreads
).toEqual(["HeroName"]);
});

@@ -344,4 +377,5 @@

expect(operations['Hero'].fields[0].fields.map(field => field.fieldName))
.toEqual(['id', 'name', 'appearsIn']);
expect(
operations["Hero"].fields[0].fields.map(field => field.fieldName)
).toEqual(["id", "name", "appearsIn"]);
});

@@ -371,14 +405,24 @@

expect(operations['Hero'].fields[0].fields.map(field => field.fieldName))
.toEqual(['id', 'name', 'appearsIn']);
expect(
operations["Hero"].fields[0].fields.map(field => field.fieldName)
).toEqual(["id", "name", "appearsIn"]);
expect(fragments['HeroDetails'].fields.map(field => field.fieldName))
.toEqual(['name', 'appearsIn', 'id']);
expect(
fragments["HeroDetails"].fields.map(field => field.fieldName)
).toEqual(["name", "appearsIn", "id"]);
expect(fragments['MoreHeroDetails'].fields.map(field => field.fieldName))
.toEqual(['appearsIn']);
expect(
fragments["MoreHeroDetails"].fields.map(field => field.fieldName)
).toEqual(["appearsIn"]);
expect(operations['Hero'].fragmentsReferenced).toEqual(['HeroDetails', 'MoreHeroDetails']);
expect(operations['Hero'].fields[0].fragmentSpreads).toEqual(['HeroDetails']);
expect(fragments['HeroDetails'].fragmentSpreads).toEqual(['MoreHeroDetails']);
expect(operations["Hero"].fragmentsReferenced).toEqual([
"HeroDetails",
"MoreHeroDetails"
]);
expect(operations["Hero"].fields[0].fragmentSpreads).toEqual([
"HeroDetails"
]);
expect(fragments["HeroDetails"].fragmentSpreads).toEqual([
"MoreHeroDetails"
]);
});

@@ -408,12 +452,23 @@

expect(operations['HeroAndFriends'].fields[0].fields.map(field => field.fieldName))
.toEqual(['name', 'id', 'appearsIn', 'friends']);
expect(operations['HeroAndFriends'].fields[0].fields[3].fields.map(field => field.fieldName))
.toEqual(['id', 'name']);
expect(
operations["HeroAndFriends"].fields[0].fields.map(
field => field.fieldName
)
).toEqual(["name", "id", "appearsIn", "friends"]);
expect(
operations["HeroAndFriends"].fields[0].fields[3].fields.map(
field => field.fieldName
)
).toEqual(["id", "name"]);
expect(fragments['HeroDetails'].fields.map(field => field.fieldName))
.toEqual(['name', 'id']);
expect(
fragments["HeroDetails"].fields.map(field => field.fieldName)
).toEqual(["name", "id"]);
expect(operations['HeroAndFriends'].fragmentsReferenced).toEqual(['HeroDetails']);
expect(operations['HeroAndFriends'].fields[0].fragmentSpreads).toEqual(['HeroDetails']);
expect(operations["HeroAndFriends"].fragmentsReferenced).toEqual([
"HeroDetails"
]);
expect(operations["HeroAndFriends"].fields[0].fragmentSpreads).toEqual([
"HeroDetails"
]);
});

@@ -438,14 +493,29 @@

expect(operations['Hero'].fields[0].fields.map(field => field.fieldName))
.toEqual(['name']);
expect(
operations["Hero"].fields[0].fields.map(field => field.fieldName)
).toEqual(["name"]);
return;
return;
expect(operations['Hero'].fields[0].inlineFragments["Droid"].typeCondition.toString()).toEqual('Droid');
expect(operations['Hero'].fields[0].inlineFragments["Droid"].fields.map(field => field.fieldName))
.toEqual(['name', 'primaryFunction']);
expect(
operations["Hero"].fields[0].inlineFragments[
"Droid"
].typeCondition.toString()
).toEqual("Droid");
expect(
operations["Hero"].fields[0].inlineFragments["Droid"].fields.map(
field => field.fieldName
)
).toEqual(["name", "primaryFunction"]);
expect(operations['Hero'].fields[0].inlineFragments["Human"].typeCondition.toString()).toEqual('Human');
expect(operations['Hero'].fields[0].inlineFragments["Human"].fields.map(field => field.fieldName))
.toEqual(['name', 'height']);
expect(
operations["Hero"].fields[0].inlineFragments[
"Human"
].typeCondition.toString()
).toEqual("Human");
expect(
operations["Hero"].fields[0].inlineFragments["Human"].fields.map(
field => field.fieldName
)
).toEqual(["name", "height"]);
});

@@ -474,15 +544,36 @@

expect(operations['Hero'].fields[0].fields.map(field => field.fieldName))
.toEqual(['name']);
expect(
operations["Hero"].fields[0].fields.map(field => field.fieldName)
).toEqual(["name"]);
expect(operations['Hero'].fields[0].inlineFragments["Droid"].typeCondition.toString()).toEqual('Droid');
expect(operations['Hero'].fields[0].inlineFragments["Droid"].fields.map(field => field.fieldName))
.toEqual(['name', 'primaryFunction']);
expect(
operations["Hero"].fields[0].inlineFragments[
"Droid"
].typeCondition.toString()
).toEqual("Droid");
expect(
operations["Hero"].fields[0].inlineFragments["Droid"].fields.map(
field => field.fieldName
)
).toEqual(["name", "primaryFunction"]);
expect(operations['Hero'].fields[0].inlineFragments['Human'].typeCondition.toString()).toEqual('Human');
expect(operations['Hero'].fields[0].inlineFragments['Human'].fields.map(field => field.fieldName))
.toEqual(['name', 'height']);
expect(
operations["Hero"].fields[0].inlineFragments[
"Human"
].typeCondition.toString()
).toEqual("Human");
expect(
operations["Hero"].fields[0].inlineFragments["Human"].fields.map(
field => field.fieldName
)
).toEqual(["name", "height"]);
expect(operations['Hero'].fragmentsReferenced).toEqual(['DroidDetails', 'HumanDetails']);
expect(operations['Hero'].fields[0].fragmentSpreads).toEqual(['DroidDetails', 'HumanDetails']);
expect(operations["Hero"].fragmentsReferenced).toEqual([
"DroidDetails",
"HumanDetails"
]);
expect(operations["Hero"].fields[0].fragmentSpreads).toEqual([
"DroidDetails",
"HumanDetails"
]);
});

@@ -506,5 +597,6 @@

expect(operations['Hero'].fields[0].fields.map(field => field.fieldName))
.toEqual(['name']);
expect(operations['Hero'].fields[0].inlineFragments).toEqual([]);
expect(
operations["Hero"].fields[0].fields.map(field => field.fieldName)
).toEqual(["name"]);
expect(operations["Hero"].fields[0].inlineFragments).toEqual([]);
});

@@ -533,15 +625,32 @@

expect(operations['Hero'].fields[0].fields.map(field => field.fieldName))
.toEqual(['name']);
expect(
operations["Hero"].fields[0].fields.map(field => field.fieldName)
).toEqual(["name"]);
expect(operations['Hero'].fields[0].inlineFragments['Droid'].typeCondition.toString()).toEqual('Droid');
expect(operations['Hero'].fields[0].inlineFragments['Droid'].fields.map(field => field.fieldName))
.toEqual(['name', 'primaryFunction']);
expect(
operations["Hero"].fields[0].inlineFragments[
"Droid"
].typeCondition.toString()
).toEqual("Droid");
expect(
operations["Hero"].fields[0].inlineFragments["Droid"].fields.map(
field => field.fieldName
)
).toEqual(["name", "primaryFunction"]);
expect(operations['Hero'].fields[0].inlineFragments['Human'].typeCondition.toString()).toEqual('Human');
expect(operations['Hero'].fields[0].inlineFragments['Human'].fields.map(field => field.fieldName))
.toEqual(['name', 'height']);
expect(
operations["Hero"].fields[0].inlineFragments[
"Human"
].typeCondition.toString()
).toEqual("Human");
expect(
operations["Hero"].fields[0].inlineFragments["Human"].fields.map(
field => field.fieldName
)
).toEqual(["name", "height"]);
expect(operations['Hero'].fragmentsReferenced).toEqual(['HeroDetails']);
expect(operations['Hero'].fields[0].fragmentSpreads).toEqual(['HeroDetails']);
expect(operations["Hero"].fragmentsReferenced).toEqual(["HeroDetails"]);
expect(operations["Hero"].fields[0].fragmentSpreads).toEqual([
"HeroDetails"
]);
});

@@ -564,7 +673,15 @@

expect(operations['HeroName'].fields[0].fields.map(field => field.fieldName))
.toEqual([]);
expect(operations['HeroName'].fields[0].inlineFragments['Droid'].typeCondition.toString()).toEqual('Droid');
expect(operations['HeroName'].fields[0].inlineFragments['Droid'].fields.map(field => field.fieldName))
.toEqual(['name']);
expect(
operations["HeroName"].fields[0].fields.map(field => field.fieldName)
).toEqual([]);
expect(
operations["HeroName"].fields[0].inlineFragments[
"Droid"
].typeCondition.toString()
).toEqual("Droid");
expect(
operations["HeroName"].fields[0].inlineFragments["Droid"].fields.map(
field => field.fieldName
)
).toEqual(["name"]);
});

@@ -587,7 +704,15 @@

expect(operations['HeroName'].fields[0].fields.map(field => field.fieldName))
.toEqual([]);
expect(operations['HeroName'].fields[0].inlineFragments['Droid'].typeCondition.toString()).toEqual('Droid');
expect(operations['HeroName'].fields[0].inlineFragments['Droid'].fields.map(field => field.fieldName))
.toEqual(['name']);
expect(
operations["HeroName"].fields[0].fields.map(field => field.fieldName)
).toEqual([]);
expect(
operations["HeroName"].fields[0].inlineFragments[
"Droid"
].typeCondition.toString()
).toEqual("Droid");
expect(
operations["HeroName"].fields[0].inlineFragments["Droid"].fields.map(
field => field.fieldName
)
).toEqual(["name"]);
});

@@ -612,11 +737,23 @@

expect(operations['HeroName'].fields[0].fields.map(field => field.fieldName))
.toEqual([]);
expect(operations['HeroName'].fields[0].inlineFragments["Droid"].typeCondition.toString()).toEqual('Droid');
expect(operations['HeroName'].fields[0].inlineFragments["Droid"].fields.map(field => field.fieldName))
.toEqual(['name']);
expect(operations['HeroName'].fields[0].inlineFragments["Droid"].fragmentSpreads).toEqual(['CharacterName']);
expect(
operations["HeroName"].fields[0].fields.map(field => field.fieldName)
).toEqual([]);
expect(
operations["HeroName"].fields[0].inlineFragments[
"Droid"
].typeCondition.toString()
).toEqual("Droid");
expect(
operations["HeroName"].fields[0].inlineFragments["Droid"].fields.map(
field => field.fieldName
)
).toEqual(["name"]);
expect(
operations["HeroName"].fields[0].inlineFragments["Droid"].fragmentSpreads
).toEqual(["CharacterName"]);
expect(operations['HeroName'].fragmentsReferenced).toEqual(['CharacterName']);
expect(operations['HeroName'].fields[0].fragmentSpreads).toEqual([]);
expect(operations["HeroName"].fragmentsReferenced).toEqual([
"CharacterName"
]);
expect(operations["HeroName"].fields[0].fragmentSpreads).toEqual([]);
});

@@ -641,10 +778,22 @@

expect(operations['HeroName'].fields[0].fields.map(field => field.fieldName))
.toEqual([]);
expect(operations['HeroName'].fields[0].inlineFragments["Droid"].typeCondition.toString()).toEqual('Droid');
expect(operations['HeroName'].fields[0].inlineFragments["Droid"].fields.map(field => field.fieldName))
.toEqual(['name']);
expect(operations['HeroName'].fields[0].inlineFragments["Droid"].fragmentSpreads).toEqual(['DroidName']);
expect(operations['HeroName'].fragmentsReferenced).toEqual(['DroidName']);
expect(operations['HeroName'].fields[0].fragmentSpreads).toEqual(['DroidName']);
expect(
operations["HeroName"].fields[0].fields.map(field => field.fieldName)
).toEqual([]);
expect(
operations["HeroName"].fields[0].inlineFragments[
"Droid"
].typeCondition.toString()
).toEqual("Droid");
expect(
operations["HeroName"].fields[0].inlineFragments["Droid"].fields.map(
field => field.fieldName
)
).toEqual(["name"]);
expect(
operations["HeroName"].fields[0].inlineFragments["Droid"].fragmentSpreads
).toEqual(["DroidName"]);
expect(operations["HeroName"].fragmentsReferenced).toEqual(["DroidName"]);
expect(operations["HeroName"].fields[0].fragmentSpreads).toEqual([
"DroidName"
]);
});

@@ -675,10 +824,13 @@

expect(operations['HumanAndDroid'].fields.map(field => field.fieldName))
.toEqual(['human', 'droid']);
expect(operations['HumanAndDroid'].fields[0].fields.map(field => field.fieldName))
.toEqual(['height']);
expect(operations['HumanAndDroid'].fields[0].inlineFragments).toEqual([]);
expect(operations['HumanAndDroid'].fields[1].fields.map(field => field.fieldName))
.toEqual(['primaryFunction']);
expect(operations['HumanAndDroid'].fields[1].inlineFragments).toEqual([]);
expect(
operations["HumanAndDroid"].fields.map(field => field.fieldName)
).toEqual(["human", "droid"]);
expect(
operations["HumanAndDroid"].fields[0].fields.map(field => field.fieldName)
).toEqual(["height"]);
expect(operations["HumanAndDroid"].fields[0].inlineFragments).toEqual([]);
expect(
operations["HumanAndDroid"].fields[1].fields.map(field => field.fieldName)
).toEqual(["primaryFunction"]);
expect(operations["HumanAndDroid"].fields[1].inlineFragments).toEqual([]);
});

@@ -713,10 +865,13 @@

expect(operations['HumanAndDroid'].fields.map(field => field.fieldName))
.toEqual(['human', 'droid']);
expect(operations['HumanAndDroid'].fields[0].fields.map(field => field.fieldName))
.toEqual(['height']);
expect(operations['HumanAndDroid'].fields[0].inlineFragments).toEqual([]);
expect(operations['HumanAndDroid'].fields[1].fields.map(field => field.fieldName))
.toEqual(['primaryFunction']);
expect(operations['HumanAndDroid'].fields[1].inlineFragments).toEqual([]);
expect(
operations["HumanAndDroid"].fields.map(field => field.fieldName)
).toEqual(["human", "droid"]);
expect(
operations["HumanAndDroid"].fields[0].fields.map(field => field.fieldName)
).toEqual(["height"]);
expect(operations["HumanAndDroid"].fields[0].inlineFragments).toEqual([]);
expect(
operations["HumanAndDroid"].fields[1].fields.map(field => field.fieldName)
).toEqual(["primaryFunction"]);
expect(operations["HumanAndDroid"].fields[1].inlineFragments).toEqual([]);
});

@@ -743,12 +898,27 @@

expect(operations['Search'].fields[0].fields.map(field => field.fieldName))
.toEqual([]);
expect(
operations["Search"].fields[0].fields.map(field => field.fieldName)
).toEqual([]);
expect(operations['Search'].fields[0].inlineFragments["Droid"].typeCondition.toString()).toEqual('Droid');
expect(operations['Search'].fields[0].inlineFragments["Droid"].fields.map(field => field.fieldName))
.toEqual(['name', 'primaryFunction']);
expect(
operations["Search"].fields[0].inlineFragments[
"Droid"
].typeCondition.toString()
).toEqual("Droid");
expect(
operations["Search"].fields[0].inlineFragments["Droid"].fields.map(
field => field.fieldName
)
).toEqual(["name", "primaryFunction"]);
expect(operations['Search'].fields[0].inlineFragments["Human"].typeCondition.toString()).toEqual('Human');
expect(operations['Search'].fields[0].inlineFragments["Human"].fields.map(field => field.fieldName))
.toEqual(['name', 'height']);
expect(
operations["Search"].fields[0].inlineFragments[
"Human"
].typeCondition.toString()
).toEqual("Human");
expect(
operations["Search"].fields[0].inlineFragments["Human"].fields.map(
field => field.fieldName
)
).toEqual(["name", "height"]);
});

@@ -773,4 +943,5 @@

expect(operations['Hero'].fields[0].fields.map(field => field.fieldName))
.toEqual(['name', 'appearsIn']);
expect(
operations["Hero"].fields[0].fields.map(field => field.fieldName)
).toEqual(["name", "appearsIn"]);
});

@@ -794,5 +965,10 @@

expect(fragments['HeroDetails'].inlineFragments['Droid'].typeCondition.toString()).toEqual('Droid');
expect(fragments['HeroDetails'].inlineFragments['Droid'].fields.map(field => field.fieldName))
.toEqual(['name', 'appearsIn']);
expect(
fragments["HeroDetails"].inlineFragments["Droid"].typeCondition.toString()
).toEqual("Droid");
expect(
fragments["HeroDetails"].inlineFragments["Droid"].fields.map(
field => field.fieldName
)
).toEqual(["name", "appearsIn"]);
});

@@ -818,3 +994,5 @@

expect(operations['HeroAndFriends'].fragmentsReferenced).toEqual(['HeroDetails']);
expect(operations["HeroAndFriends"].fragmentsReferenced).toEqual([
"HeroDetails"
]);
});

@@ -843,3 +1021,6 @@

expect(operations['HeroAndFriends'].fragmentsReferenced).toEqual(['HeroDetails', 'HeroName']);
expect(operations["HeroAndFriends"].fragmentsReferenced).toEqual([
"HeroDetails",
"HeroName"
]);
});

@@ -867,3 +1048,5 @@

expect(operations['HeroAndFriends'].fragmentsReferenced).toEqual(['HeroDetails']);
expect(operations["HeroAndFriends"].fragmentsReferenced).toEqual([
"HeroDetails"
]);
});

@@ -892,16 +1075,28 @@

const { operations, fragments } = compileToLegacyIR(schema, document, { mergeInFieldsFromFragmentSpreads: false });
const { operations, fragments } = compileToLegacyIR(schema, document, {
mergeInFieldsFromFragmentSpreads: false
});
expect(operations['Hero'].fields[0].fields.map(field => field.fieldName))
.toEqual(['id']);
expect(
operations["Hero"].fields[0].fields.map(field => field.fieldName)
).toEqual(["id"]);
expect(fragments['HeroDetails'].fields.map(field => field.fieldName))
.toEqual(['name', 'id']);
expect(
fragments["HeroDetails"].fields.map(field => field.fieldName)
).toEqual(["name", "id"]);
expect(fragments['MoreHeroDetails'].fields.map(field => field.fieldName))
.toEqual(['appearsIn']);
expect(
fragments["MoreHeroDetails"].fields.map(field => field.fieldName)
).toEqual(["appearsIn"]);
expect(operations['Hero'].fragmentsReferenced).toEqual(['HeroDetails', 'MoreHeroDetails']);
expect(operations['Hero'].fields[0].fragmentSpreads).toEqual(['HeroDetails']);
expect(fragments['HeroDetails'].fragmentSpreads).toEqual(['MoreHeroDetails']);
expect(operations["Hero"].fragmentsReferenced).toEqual([
"HeroDetails",
"MoreHeroDetails"
]);
expect(operations["Hero"].fields[0].fragmentSpreads).toEqual([
"HeroDetails"
]);
expect(fragments["HeroDetails"].fragmentSpreads).toEqual([
"MoreHeroDetails"
]);
});

@@ -929,14 +1124,27 @@

const { operations, fragments } = compileToLegacyIR(schema, document, { mergeInFieldsFromFragmentSpreads: false });
const { operations, fragments } = compileToLegacyIR(schema, document, {
mergeInFieldsFromFragmentSpreads: false
});
expect(operations['HeroAndFriends'].fields[0].fields.map(field => field.fieldName))
.toEqual(['appearsIn', 'id','friends']);
expect(operations['HeroAndFriends'].fields[0].fields[2].fields.map(field => field.fieldName))
.toEqual(['id']);
expect(
operations["HeroAndFriends"].fields[0].fields.map(
field => field.fieldName
)
).toEqual(["appearsIn", "id", "friends"]);
expect(
operations["HeroAndFriends"].fields[0].fields[2].fields.map(
field => field.fieldName
)
).toEqual(["id"]);
expect(fragments['HeroDetails'].fields.map(field => field.fieldName))
.toEqual(['name', 'id']);
expect(
fragments["HeroDetails"].fields.map(field => field.fieldName)
).toEqual(["name", "id"]);
expect(operations['HeroAndFriends'].fragmentsReferenced).toEqual(['HeroDetails']);
expect(operations['HeroAndFriends'].fields[0].fragmentSpreads).toEqual(['HeroDetails']);
expect(operations["HeroAndFriends"].fragmentsReferenced).toEqual([
"HeroDetails"
]);
expect(operations["HeroAndFriends"].fields[0].fragmentSpreads).toEqual([
"HeroDetails"
]);
});

@@ -963,11 +1171,20 @@

const { operations, fragments } = compileToLegacyIR(schema, document, { mergeInFieldsFromFragmentSpreads: false });
const { operations, fragments } = compileToLegacyIR(schema, document, {
mergeInFieldsFromFragmentSpreads: false
});
expect(operations['Hero'].fields[0].fields.map(field => field.fieldName))
.toEqual(['name']);
expect(
operations["Hero"].fields[0].fields.map(field => field.fieldName)
).toEqual(["name"]);
expect(operations['Hero'].fields[0].inlineFragment).toBeUndefined();
expect(operations["Hero"].fields[0].inlineFragment).toBeUndefined();
expect(operations['Hero'].fragmentsReferenced).toEqual(['DroidDetails', 'HumanDetails']);
expect(operations['Hero'].fields[0].fragmentSpreads).toEqual(['DroidDetails', 'HumanDetails']);
expect(operations["Hero"].fragmentsReferenced).toEqual([
"DroidDetails",
"HumanDetails"
]);
expect(operations["Hero"].fields[0].fragmentSpreads).toEqual([
"DroidDetails",
"HumanDetails"
]);
});

@@ -983,3 +1200,3 @@ });

}
`
`;
const document = parse(source);

@@ -989,3 +1206,3 @@

expect(operations['HeroName'].source).toBe(source);
expect(operations["HeroName"].source).toBe(source);
});

@@ -998,3 +1215,3 @@

}
`
`;
const document = parse(source);

@@ -1004,3 +1221,3 @@

expect(fragments['HeroDetails'].source).toBe(source);
expect(fragments["HeroDetails"].source).toBe(source);
});

@@ -1015,8 +1232,10 @@

}
`
`;
const document = parse(source);
const { operations } = compileToLegacyIR(schema, document, { addTypename: true });
const { operations } = compileToLegacyIR(schema, document, {
addTypename: true
});
expect(operations['HeroName'].source).toBe(stripIndent`
expect(operations["HeroName"].source).toBe(stripIndent`
query HeroName {

@@ -1036,8 +1255,10 @@ hero {

}
`
`;
const document = parse(source);
const { fragments } = compileToLegacyIR(schema, document, { addTypename: true });
const { fragments } = compileToLegacyIR(schema, document, {
addTypename: true
});
expect(fragments['HeroDetails'].source).toBe(stripIndent`
expect(fragments["HeroDetails"].source).toBe(stripIndent`
fragment HeroDetails on Character {

@@ -1057,3 +1278,3 @@ __typename

}
`
`;
const document = parse(source);

@@ -1063,3 +1284,3 @@

expect(operations['HeroName'].operationType).toBe('query');
expect(operations["HeroName"].operationType).toBe("query");
});

@@ -1075,3 +1296,3 @@

}
`
`;
const document = parse(source);

@@ -1081,4 +1302,4 @@

expect(operations['CreateReview'].operationType).toBe('mutation');
expect(operations["CreateReview"].operationType).toBe("mutation");
});
});

@@ -26,3 +26,3 @@ import {

GraphQLNonNull
} from 'graphql';
} from "graphql";

@@ -36,3 +36,3 @@ import {

isMetaFieldName
} from '../utilities/graphql';
} from "../utilities/graphql";

@@ -90,6 +90,10 @@ export interface CompilerOptions {

export type Selection = Field | TypeCondition | BooleanCondition | FragmentSpread;
export type Selection =
| Field
| TypeCondition
| BooleanCondition
| FragmentSpread;
export interface Field {
kind: 'Field';
kind: "Field";
responseKey: string;

@@ -108,3 +112,3 @@ name: string;

export interface TypeCondition {
kind: 'TypeCondition';
kind: "TypeCondition";
type: GraphQLCompositeType;

@@ -115,3 +119,3 @@ selectionSet: SelectionSet;

export interface BooleanCondition {
kind: 'BooleanCondition';
kind: "BooleanCondition";
variableName: string;

@@ -123,3 +127,3 @@ inverted: boolean;

export interface FragmentSpread {
kind: 'FragmentSpread';
kind: "FragmentSpread";
fragmentName: string;

@@ -141,3 +145,5 @@ isConditional?: boolean;

const operations: { [operationName: string]: Operation } = Object.create(null);
const operations: { [operationName: string]: Operation } = Object.create(
null
);
const fragments: { [fragmentName: string]: Fragment } = Object.create(null);

@@ -221,3 +227,3 @@

if (!operationDefinition.name) {
throw new Error('Operations should be named');
throw new Error("Operations should be named");
}

@@ -229,11 +235,16 @@

const variables = (operationDefinition.variableDefinitions || []).map(node => {
const name = node.variable.name.value;
const type = typeFromAST(this.schema, node.type as NonNullTypeNode);
this.addTypeUsed(getNamedType(type as GraphQLType));
return { name, type: type as GraphQLNonNull<any> };
});
const variables = (operationDefinition.variableDefinitions || []).map(
node => {
const name = node.variable.name.value;
const type = typeFromAST(this.schema, node.type as NonNullTypeNode);
this.addTypeUsed(getNamedType(type as GraphQLType));
return { name, type: type as GraphQLNonNull<any> };
}
);
const source = print(operationDefinition);
const rootType = getOperationRootType(this.schema, operationDefinition) as GraphQLObjectType;
const rootType = getOperationRootType(
this.schema,
operationDefinition
) as GraphQLObjectType;

@@ -247,7 +258,14 @@ return {

rootType,
selectionSet: this.compileSelectionSet(operationDefinition.selectionSet, rootType, false)
selectionSet: this.compileSelectionSet(
operationDefinition.selectionSet,
rootType,
false
)
};
}
compileFragment(fragmentDefinition: FragmentDefinitionNode, isClient: boolean): Fragment {
compileFragment(
fragmentDefinition: FragmentDefinitionNode,
isClient: boolean
): Fragment {
const fragmentName = fragmentDefinition.name.value;

@@ -258,3 +276,6 @@

const type = typeFromAST(this.schema, fragmentDefinition.typeCondition) as GraphQLCompositeType;
const type = typeFromAST(
this.schema,
fragmentDefinition.typeCondition
) as GraphQLCompositeType;

@@ -266,3 +287,7 @@ return {

type,
selectionSet: this.compileSelectionSet(fragmentDefinition.selectionSet, type, isClient)
selectionSet: this.compileSelectionSet(
fragmentDefinition.selectionSet,
type,
isClient
)
};

@@ -283,3 +308,9 @@ }

wrapInBooleanConditionsIfNeeded(
this.compileSelection(selectionNode, parentType, possibleTypes, visitedFragments, isClient),
this.compileSelection(
selectionNode,
parentType,
possibleTypes,
visitedFragments,
isClient
),
selectionNode,

@@ -302,23 +333,41 @@ possibleTypes

case Kind.FIELD: {
const fieldIsClient = (selectionNode.directives || []).some(d => d.name.value == "client");
const fieldIsClient = (selectionNode.directives || []).some(
d => d.name.value == "client"
);
const name = selectionNode.name.value;
const alias = selectionNode.alias ? selectionNode.alias.value : undefined;
const alias = selectionNode.alias
? selectionNode.alias.value
: undefined;
const fieldDef = getFieldDef(this.schema, parentType, selectionNode);
if (!fieldDef) {
throw new GraphQLError(`Cannot query field "${name}" on type "${String(parentType)}"`, [
selectionNode
]);
throw new GraphQLError(
`Cannot query field "${name}" on type "${String(parentType)}"`,
[selectionNode]
);
}
if (fieldDef.astNode && (fieldDef.astNode as any).__client && !(isClient || fieldIsClient)) {
throw new GraphQLError(`Cannot query client-side field "${name}" on type "${String(parentType)}" without @client directive`, [
selectionNode
]);
if (
fieldDef.astNode &&
(fieldDef.astNode as any).__client &&
!(isClient || fieldIsClient)
) {
throw new GraphQLError(
`Cannot query client-side field "${name}" on type "${String(
parentType
)}" without @client directive`,
[selectionNode]
);
}
if (!(fieldDef.astNode && (fieldDef.astNode as any).__client) && fieldIsClient) {
throw new GraphQLError(`Cannot query server-side field "${name}" on type "${String(parentType)}" with @client directive`, [
selectionNode
]);
if (
!(fieldDef.astNode && (fieldDef.astNode as any).__client) &&
fieldIsClient
) {
throw new GraphQLError(
`Cannot query server-side field "${name}" on type "${String(
parentType
)}" with @client directive`,
[selectionNode]
);
}

@@ -339,3 +388,5 @@

const name = arg.name.value;
const argDef = fieldDef.args.find(argDef => argDef.name === arg.name.value);
const argDef = fieldDef.args.find(
argDef => argDef.name === arg.name.value
);
return {

@@ -350,3 +401,3 @@ name,

let field: Field = {
kind: 'Field',
kind: "Field",
responseKey,

@@ -357,3 +408,4 @@ name,

type: fieldType,
description: !isMetaFieldName(name) && description ? description : undefined,
description:
!isMetaFieldName(name) && description ? description : undefined,
isDeprecated,

@@ -367,3 +419,5 @@ deprecationReason: deprecationReason || undefined

throw new GraphQLError(
`Composite field "${name}" on type "${String(parentType)}" requires selection set`,
`Composite field "${name}" on type "${String(
parentType
)}" requires selection set`,
[selectionNode]

@@ -383,8 +437,10 @@ );

const typeNode = selectionNode.typeCondition;
const type = typeNode ? (typeFromAST(this.schema, typeNode) as GraphQLCompositeType) : parentType;
const possibleTypesForTypeCondition = this.possibleTypesForType(type).filter(type =>
possibleTypes.includes(type)
);
const type = typeNode
? (typeFromAST(this.schema, typeNode) as GraphQLCompositeType)
: parentType;
const possibleTypesForTypeCondition = this.possibleTypesForType(
type
).filter(type => possibleTypes.includes(type));
return {
kind: 'TypeCondition',
kind: "TypeCondition",
type,

@@ -405,3 +461,3 @@ selectionSet: this.compileSelectionSet(

const fragmentSpread: FragmentSpread = {
kind: 'FragmentSpread',
kind: "FragmentSpread",
fragmentName,

@@ -440,3 +496,3 @@ selectionSet: {

if (directiveName === 'skip' || directiveName === 'include') {
if (directiveName === "skip" || directiveName === "include") {
if (!directive.arguments) continue;

@@ -447,4 +503,4 @@

switch (value.kind) {
case 'BooleanValue':
if (directiveName === 'skip') {
case "BooleanValue":
if (directiveName === "skip") {
return value.value ? null : selection;

@@ -455,7 +511,7 @@ } else {

break;
case 'Variable':
case "Variable":
selection = {
kind: 'BooleanCondition',
kind: "BooleanCondition",
variableName: value.name.value,
inverted: directiveName === 'skip',
inverted: directiveName === "skip",
selectionSet: {

@@ -462,0 +518,0 @@ possibleTypes,

@@ -8,12 +8,18 @@ import {

DocumentNode
} from 'graphql';
} from "graphql";
import { compileToIR, CompilerContext, SelectionSet, Field, FragmentSpread } from './';
import {
compileToIR,
CompilerContext,
SelectionSet,
Field,
FragmentSpread
} from "./";
import { collectFragmentsReferenced } from './visitors/collectFragmentsReferenced';
import { generateOperationId } from './visitors/generateOperationId';
import { typeCaseForSelectionSet } from './visitors/typeCase';
import { collectAndMergeFields } from './visitors/collectAndMergeFields';
import { collectFragmentsReferenced } from "./visitors/collectFragmentsReferenced";
import { generateOperationId } from "./visitors/generateOperationId";
import { typeCaseForSelectionSet } from "./visitors/typeCase";
import { collectAndMergeFields } from "./visitors/collectAndMergeFields";
import '../utilities/array';
import "../utilities/array";

@@ -116,7 +122,21 @@ export interface CompilerOptions {

transformIR(): LegacyCompilerContext {
const operations: { [operationName: string]: LegacyOperation } = Object.create({});
const operations: {
[operationName: string]: LegacyOperation;
} = Object.create({});
for (const [operationName, operation] of Object.entries(this.context.operations)) {
const { filePath, operationType, rootType, variables, source, selectionSet } = operation;
const fragmentsReferenced = collectFragmentsReferenced(selectionSet, this.context.fragments);
for (const [operationName, operation] of Object.entries(
this.context.operations
)) {
const {
filePath,
operationType,
rootType,
variables,
source,
selectionSet
} = operation;
const fragmentsReferenced = collectFragmentsReferenced(
selectionSet,
this.context.fragments
);

@@ -143,5 +163,9 @@ const { sourceWithFragments, operationId } = generateOperationId(

const fragments: { [fragmentName: string]: LegacyFragment } = Object.create({});
const fragments: { [fragmentName: string]: LegacyFragment } = Object.create(
{}
);
for (const [fragmentName, fragment] of Object.entries(this.context.fragments)) {
for (const [fragmentName, fragment] of Object.entries(
this.context.fragments
)) {
const { selectionSet, type, ...fragmentWithoutSelectionSet } = fragment;

@@ -168,3 +192,6 @@ fragments[fragmentName] = {

transformSelectionSetToLegacyIR(selectionSet: SelectionSet) {
const typeCase = typeCaseForSelectionSet(selectionSet, this.options.mergeInFieldsFromFragmentSpreads);
const typeCase = typeCaseForSelectionSet(
selectionSet,
this.options.mergeInFieldsFromFragmentSpreads
);

@@ -175,33 +202,42 @@ const fields: LegacyField[] = this.transformFieldsToLegacyIR(

const inlineFragments: LegacyInlineFragment[] = typeCase.variants.flatMap(variant => {
const fields = this.transformFieldsToLegacyIR(collectAndMergeFields(variant, false));
const inlineFragments: LegacyInlineFragment[] = typeCase.variants.flatMap(
variant => {
const fields = this.transformFieldsToLegacyIR(
collectAndMergeFields(variant, false)
);
if (
// Filter out records that represent the same possible types as the default record.
selectionSet.possibleTypes.every(type => variant.possibleTypes.includes(type)) &&
// Filter out empty records for consistency with legacy compiler.
fields.length < 1
)
return undefined;
if (
// Filter out records that represent the same possible types as the default record.
selectionSet.possibleTypes.every(type =>
variant.possibleTypes.includes(type)
) &&
// Filter out empty records for consistency with legacy compiler.
fields.length < 1
)
return undefined;
const fragmentSpreads: string[] = this.collectFragmentSpreads(selectionSet, variant.possibleTypes).map(
(fragmentSpread: FragmentSpread) => fragmentSpread.fragmentName
);
return variant.possibleTypes.map(possibleType => {
return {
typeCondition: possibleType,
possibleTypes: [possibleType],
fields,
fragmentSpreads
} as LegacyInlineFragment;
});
});
const fragmentSpreads: string[] = this.collectFragmentSpreads(
selectionSet,
variant.possibleTypes
).map((fragmentSpread: FragmentSpread) => fragmentSpread.fragmentName);
return variant.possibleTypes.map(possibleType => {
return {
typeCondition: possibleType,
possibleTypes: [possibleType],
fields,
fragmentSpreads
} as LegacyInlineFragment;
});
}
);
for (const inlineFragment of inlineFragments) {
inlineFragments[inlineFragment.typeCondition.name as any] = inlineFragment;
inlineFragments[
inlineFragment.typeCondition.name as any
] = inlineFragment;
}
const fragmentSpreads: string[] = this.collectFragmentSpreads(selectionSet).map(
(fragmentSpread: FragmentSpread) => fragmentSpread.fragmentName
);
const fragmentSpreads: string[] = this.collectFragmentSpreads(
selectionSet
).map((fragmentSpread: FragmentSpread) => fragmentSpread.fragmentName);

@@ -217,3 +253,11 @@ return {

return fields.map(field => {
const { args, type, isConditional, description, isDeprecated, deprecationReason, selectionSet } = field;
const {
args,
type,
isConditional,
description,
isDeprecated,
deprecationReason,
selectionSet
} = field;
const conditions =

@@ -239,3 +283,5 @@ field.conditions && field.conditions.length > 0

deprecationReason,
...(selectionSet ? this.transformSelectionSetToLegacyIR(selectionSet) : {})
...(selectionSet
? this.transformSelectionSetToLegacyIR(selectionSet)
: {})
} as LegacyField;

@@ -253,12 +299,26 @@ });

switch (selection.kind) {
case 'FragmentSpread':
case "FragmentSpread":
fragmentSpreads.push(selection);
break;
case 'TypeCondition':
if (possibleTypes.every(type => selection.selectionSet.possibleTypes.includes(type))) {
fragmentSpreads.push(...this.collectFragmentSpreads(selection.selectionSet, possibleTypes));
case "TypeCondition":
if (
possibleTypes.every(type =>
selection.selectionSet.possibleTypes.includes(type)
)
) {
fragmentSpreads.push(
...this.collectFragmentSpreads(
selection.selectionSet,
possibleTypes
)
);
}
break;
case 'BooleanCondition':
fragmentSpreads.push(...this.collectFragmentSpreads(selection.selectionSet, possibleTypes));
case "BooleanCondition":
fragmentSpreads.push(
...this.collectFragmentSpreads(
selection.selectionSet,
possibleTypes
)
);
break;

@@ -265,0 +325,0 @@ }

@@ -1,9 +0,9 @@

import { SelectionSet, Field, BooleanCondition } from '../..';
import { collectAndMergeFields } from '../collectAndMergeFields';
import { typeCaseForSelectionSet } from '../typeCase';
import { SelectionSet, Field, BooleanCondition } from "../..";
import { collectAndMergeFields } from "../collectAndMergeFields";
import { typeCaseForSelectionSet } from "../typeCase";
import { compile } from './test-utils/helpers';
import { compile } from "./test-utils/helpers";
describe('@skip/@include directives', () => {
it('should not mark a field as conditional when it has a no directives', () => {
describe("@skip/@include directives", () => {
it("should not mark a field as conditional when it has a no directives", () => {
const context = compile(`

@@ -17,10 +17,10 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(collectAndMergeFields(selectionSet)[0].isConditional).toBeFalsy();
});
it('should mark a field as conditional when it has a @skip directive', () => {
it("should mark a field as conditional when it has a @skip directive", () => {
const context = compile(`

@@ -34,12 +34,14 @@ query Hero($skipName: Boolean!) {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(collectAndMergeFields(selectionSet)[0].isConditional).toBeTruthy();
expect(selectionSet.selections[0]).toMatchObject({ variableName: 'skipName' });
expect(selectionSet.selections[0]).toMatchObject({
variableName: "skipName"
});
});
it('should not mark a field as conditional when it has a @skip directive that is always false', () => {
it("should not mark a field as conditional when it has a @skip directive that is always false", () => {
const context = compile(`

@@ -53,10 +55,10 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(collectAndMergeFields(selectionSet)[0].isConditional).toBeFalsy();
});
it('should not include a field when it has a @skip directive that is always true', () => {
it("should not include a field when it has a @skip directive that is always true", () => {
const context = compile(`

@@ -70,9 +72,9 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], []);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], []);
});
it('should mark a field as conditional when it has a @include directive', () => {
it("should mark a field as conditional when it has a @include directive", () => {
const context = compile(`

@@ -86,12 +88,14 @@ query Hero($includeName: Boolean!) {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(collectAndMergeFields(selectionSet)[0].isConditional).toBeTruthy();
expect(selectionSet.selections[0]).toMatchObject({ variableName: 'includeName' });
expect(selectionSet.selections[0]).toMatchObject({
variableName: "includeName"
});
});
it('should not mark a field as conditional when it has a @include directive that is always true', () => {
it("should not mark a field as conditional when it has a @include directive that is always true", () => {
const context = compile(`

@@ -105,10 +109,10 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(collectAndMergeFields(selectionSet)[0].isConditional).toBeFalsy();
});
it('should not include a field when it has a @include directive that is always false', () => {
it("should not include a field when it has a @include directive that is always false", () => {
const context = compile(`

@@ -122,9 +126,9 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], []);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], []);
});
it('should mark a field as conditional when it has both a @skip and an @include directive', () => {
it("should mark a field as conditional when it has both a @skip and an @include directive", () => {
const context = compile(`

@@ -138,15 +142,20 @@ query Hero($skipName: Boolean!, $includeName: Boolean!) {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(collectAndMergeFields(selectionSet)[0].isConditional).toBeTruthy();
expect(selectionSet.selections[0]).toMatchObject({ variableName: 'includeName' });
expect((selectionSet.selections[0] as BooleanCondition).selectionSet.selections[0]).toMatchObject({
variableName: 'skipName'
expect(selectionSet.selections[0]).toMatchObject({
variableName: "includeName"
});
expect(
(selectionSet.selections[0] as BooleanCondition).selectionSet
.selections[0]
).toMatchObject({
variableName: "skipName"
});
});
it('should mark a field as conditional when it is included twice, once with a @skip and once with an @include directive', () => {
it("should mark a field as conditional when it is included twice, once with a @skip and once with an @include directive", () => {
const context = compile(`

@@ -161,13 +170,17 @@ query Hero($skipName: Boolean!, $includeName: Boolean!) {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(collectAndMergeFields(selectionSet)[0].isConditional).toBeTruthy();
expect(selectionSet.selections[0]).toMatchObject({ variableName: 'skipName' });
expect(selectionSet.selections[1]).toMatchObject({ variableName: 'includeName' });
expect(selectionSet.selections[0]).toMatchObject({
variableName: "skipName"
});
expect(selectionSet.selections[1]).toMatchObject({
variableName: "includeName"
});
});
it('should not include a field when when it has both a @skip directive and an @include directive that is always false', () => {
it("should not include a field when when it has both a @skip directive and an @include directive that is always false", () => {
const context = compile(`

@@ -181,9 +194,9 @@ query Hero($skipName: Boolean!) {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], []);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], []);
});
it('should not mark a field as conditional when it is included twice, once with and once without an @include directive', () => {
it("should not mark a field as conditional when it is included twice, once with and once without an @include directive", () => {
const context = compile(`

@@ -198,10 +211,10 @@ query Hero($includeName: Boolean!) {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(collectAndMergeFields(selectionSet)[0].isConditional).toBeFalsy();
});
it('should not mark a field as conditional when it is included twice, once with an @include directive that is always false and once without', () => {
it("should not mark a field as conditional when it is included twice, once with an @include directive that is always false and once without", () => {
const context = compile(`

@@ -216,10 +229,10 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
expect(selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(selectionSet).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(collectAndMergeFields(selectionSet)[0].isConditional).toBeFalsy();
});
it('should not mark a field as conditional in a variant when it is included without a directive in an inline fragment', () => {
it("should not mark a field as conditional in a variant when it is included without a directive in an inline fragment", () => {
const context = compile(`

@@ -236,15 +249,22 @@ query Hero($skipName: Boolean!) {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(collectAndMergeFields(typeCase.default)[0].isConditional).toBeTruthy();
expect(typeCase.default).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(
collectAndMergeFields(typeCase.default)[0].isConditional
).toBeTruthy();
expect(typeCase.variants).toHaveLength(1);
expect(typeCase.variants).toContainSelectionSetMatching(['Droid'], ['name']);
expect(collectAndMergeFields(typeCase.variants[0])[0].isConditional).toBeFalsy();
expect(typeCase.variants).toContainSelectionSetMatching(
["Droid"],
["name"]
);
expect(
collectAndMergeFields(typeCase.variants[0])[0].isConditional
).toBeFalsy();
});
it('should not mark a field as conditional in a variant when it is included without a directive in the default case', () => {
it("should not mark a field as conditional in a variant when it is included without a directive in the default case", () => {
const context = compile(`

@@ -261,15 +281,22 @@ query Hero($skipName: Boolean!) {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(collectAndMergeFields(typeCase.default)[0].isConditional).toBeFalsy();
expect(typeCase.default).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(
collectAndMergeFields(typeCase.default)[0].isConditional
).toBeFalsy();
expect(typeCase.variants).toHaveLength(1);
expect(typeCase.variants).toContainSelectionSetMatching(['Droid'], ['name']);
expect(collectAndMergeFields(typeCase.variants[0])[0].isConditional).toBeFalsy();
expect(typeCase.variants).toContainSelectionSetMatching(
["Droid"],
["name"]
);
expect(
collectAndMergeFields(typeCase.variants[0])[0].isConditional
).toBeFalsy();
});
it('should not mark a field as conditional when the parent selection set is included conditionally', () => {
it("should not mark a field as conditional when the parent selection set is included conditionally", () => {
const context = compile(`

@@ -285,11 +312,19 @@ query Hero($includeFriends: Boolean!) {

const heroField = context.operations['Hero'].selectionSet.selections[0];
const friendsField = collectAndMergeFields(heroField.selectionSet as SelectionSet)[0];
const heroField = context.operations["Hero"].selectionSet.selections[0];
const friendsField = collectAndMergeFields(
heroField.selectionSet as SelectionSet
)[0];
expect(friendsField.isConditional).toBeTruthy();
expect(friendsField.selectionSet as SelectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(collectAndMergeFields(friendsField.selectionSet as SelectionSet)[0].isConditional).toBeFalsy();
expect(friendsField.selectionSet as SelectionSet).toMatchSelectionSet(
["Human", "Droid"],
["name"]
);
expect(
collectAndMergeFields(friendsField.selectionSet as SelectionSet)[0]
.isConditional
).toBeFalsy();
});
it('should mark a field as conditional when the parent selection set is first included conditionally and then the parent field is also included unconditionally', () => {
it("should mark a field as conditional when the parent selection set is first included conditionally and then the parent field is also included unconditionally", () => {
const context = compile(`

@@ -308,12 +343,23 @@ query Hero($includeFriends: Boolean!) {

const heroField = context.operations['Hero'].selectionSet.selections[0];
const friendsField = collectAndMergeFields(heroField.selectionSet as SelectionSet)[0];
const heroField = context.operations["Hero"].selectionSet.selections[0];
const friendsField = collectAndMergeFields(
heroField.selectionSet as SelectionSet
)[0];
expect(friendsField.isConditional).toBeFalsy();
expect(friendsField.selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['name', 'id']);
expect(collectAndMergeFields(friendsField.selectionSet as SelectionSet)[0].isConditional).toBeTruthy();
expect(collectAndMergeFields(friendsField.selectionSet as SelectionSet)[1].isConditional).toBeFalsy();
expect(friendsField.selectionSet).toMatchSelectionSet(
["Human", "Droid"],
["name", "id"]
);
expect(
collectAndMergeFields(friendsField.selectionSet as SelectionSet)[0]
.isConditional
).toBeTruthy();
expect(
collectAndMergeFields(friendsField.selectionSet as SelectionSet)[1]
.isConditional
).toBeFalsy();
});
it('should mark a field as conditional when the parent selection set is first included unconditionally and then the parent field is also included conditionally', () => {
it("should mark a field as conditional when the parent selection set is first included unconditionally and then the parent field is also included conditionally", () => {
const context = compile(`

@@ -332,10 +378,21 @@ query Hero($includeFriends: Boolean!) {

const heroField = context.operations['Hero'].selectionSet.selections[0];
const friendsField = collectAndMergeFields(heroField.selectionSet as SelectionSet)[0];
const heroField = context.operations["Hero"].selectionSet.selections[0];
const friendsField = collectAndMergeFields(
heroField.selectionSet as SelectionSet
)[0];
expect(friendsField.isConditional).toBeFalsy();
expect(friendsField.selectionSet).toMatchSelectionSet(['Human', 'Droid'], ['id', 'name']);
expect(collectAndMergeFields(friendsField.selectionSet as SelectionSet)[0].isConditional).toBeFalsy();
expect(collectAndMergeFields(friendsField.selectionSet as SelectionSet)[1].isConditional).toBeTruthy();
expect(friendsField.selectionSet).toMatchSelectionSet(
["Human", "Droid"],
["id", "name"]
);
expect(
collectAndMergeFields(friendsField.selectionSet as SelectionSet)[0]
.isConditional
).toBeFalsy();
expect(
collectAndMergeFields(friendsField.selectionSet as SelectionSet)[1]
.isConditional
).toBeTruthy();
});
});

@@ -1,5 +0,5 @@

import { generateOperationId } from '../generateOperationId';
import { stripIndent } from 'common-tags';
import { generateOperationId } from "../generateOperationId";
import { stripIndent } from "common-tags";
import { compile } from './test-utils/helpers';
import { compile } from "./test-utils/helpers";

@@ -19,3 +19,6 @@ describe(`generateOperationId()`, () => {

const { operationId: id1 } = generateOperationId(context1.operations['Hero'], context1.fragments);
const { operationId: id1 } = generateOperationId(
context1.operations["Hero"],
context1.fragments
);

@@ -33,3 +36,6 @@ const context2 = compile(`

const { operationId: id2 } = generateOperationId(context2.operations['Hero'], context2.fragments);
const { operationId: id2 } = generateOperationId(
context2.operations["Hero"],
context2.fragments
);

@@ -48,3 +54,6 @@ expect(id1).not.toBe(id2);

const { operationId: id1 } = generateOperationId(context1.operations['HeroName'], context1.fragments);
const { operationId: id1 } = generateOperationId(
context1.operations["HeroName"],
context1.fragments
);

@@ -57,3 +66,6 @@ const context2 = compile(`

const { operationId: id2 } = generateOperationId(context2.operations['HeroName'], context2.fragments);
const { operationId: id2 } = generateOperationId(
context2.operations["HeroName"],
context2.fragments
);

@@ -79,3 +91,6 @@ expect(id1).toBe(id2);

const { operationId: id1 } = generateOperationId(context1.operations['Hero'], context1.fragments);
const { operationId: id1 } = generateOperationId(
context1.operations["Hero"],
context1.fragments
);

@@ -97,3 +112,6 @@ const context2 = compile(`

const { operationId: id2 } = generateOperationId(context2.operations['Hero'], context2.fragments);
const { operationId: id2 } = generateOperationId(
context2.operations["Hero"],
context2.fragments
);

@@ -119,3 +137,6 @@ expect(id1).toBe(id2);

const { sourceWithFragments } = generateOperationId(context.operations['Hero'], context.fragments);
const { sourceWithFragments } = generateOperationId(
context.operations["Hero"],
context.fragments
);

@@ -122,0 +143,0 @@ expect(sourceWithFragments).toBe(stripIndent`

@@ -1,10 +0,16 @@

import { parse, GraphQLSchema } from 'graphql';
import { compileToIR, CompilerOptions, } from '../../..';
import { loadSchema } from '../../../../loading';
import { parse, GraphQLSchema } from "graphql";
import { compileToIR, CompilerOptions } from "../../..";
import { loadSchema } from "../../../../loading";
export const starWarsSchema = loadSchema(require.resolve('../../../../../../common-test/fixtures/starwars/schema.json'));
export const starWarsSchema = loadSchema(
require.resolve("../../../../../../common-test/fixtures/starwars/schema.json")
);
export function compile(source: string, schema: GraphQLSchema = starWarsSchema, options: CompilerOptions = {}) {
export function compile(
source: string,
schema: GraphQLSchema = starWarsSchema,
options: CompilerOptions = {}
) {
const document = parse(source);
return compileToIR(schema, document, options);
}

@@ -1,7 +0,7 @@

import { buildSchema } from 'graphql';
import { compile } from './test-utils/helpers';
import { buildSchema } from "graphql";
import { compile } from "./test-utils/helpers";
import { SelectionSet, Field } from '../..';
import { typeCaseForSelectionSet } from '../typeCase';
import { collectAndMergeFields } from '../collectAndMergeFields';
import { SelectionSet, Field } from "../..";
import { typeCaseForSelectionSet } from "../typeCase";
import { collectAndMergeFields } from "../collectAndMergeFields";

@@ -44,4 +44,4 @@ export const animalSchema = buildSchema(`

describe('TypeCase', () => {
it('should recursively include inline fragments with type conditions that match the parent type', () => {
describe("TypeCase", () => {
it("should recursively include inline fragments with type conditions that match the parent type", () => {
const context = compile(`

@@ -63,7 +63,10 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], ['id', 'name', 'appearsIn']);
expect(typeCase.default).toMatchSelectionSet(
["Human", "Droid"],
["id", "name", "appearsIn"]
);

@@ -74,8 +77,8 @@ expect(typeCase.variants).toHaveLength(0);

expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
['Human', 'Droid'],
['id', 'name', 'appearsIn']
["Human", "Droid"],
["id", "name", "appearsIn"]
);
});
it('should recursively include fragment spreads with type conditions that match the parent type', () => {
it("should recursively include fragment spreads with type conditions that match the parent type", () => {
const context = compile(`

@@ -100,8 +103,15 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], ['id', 'name', 'appearsIn']);
expect(typeCase.default.fragmentSpreads.map(fragmentSpread => fragmentSpread.fragmentName)).toEqual(['HeroDetails', 'MoreHeroDetails']);
expect(typeCase.default).toMatchSelectionSet(
["Human", "Droid"],
["id", "name", "appearsIn"]
);
expect(
typeCase.default.fragmentSpreads.map(
fragmentSpread => fragmentSpread.fragmentName
)
).toEqual(["HeroDetails", "MoreHeroDetails"]);

@@ -112,8 +122,8 @@ expect(typeCase.variants).toHaveLength(0);

expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
['Human', 'Droid'],
['id', 'name', 'appearsIn']
["Human", "Droid"],
["id", "name", "appearsIn"]
);
});
it('should include fragment spreads when nested within inline fragments', () => {
it("should include fragment spreads when nested within inline fragments", () => {
const context = compile(`

@@ -133,8 +143,12 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(typeCase.default.fragmentSpreads.map(fragmentSpread => fragmentSpread.fragmentName)).toEqual(['CharacterName']);
expect(typeCase.default).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(
typeCase.default.fragmentSpreads.map(
fragmentSpread => fragmentSpread.fragmentName
)
).toEqual(["CharacterName"]);

@@ -144,3 +158,3 @@ expect(typeCase.variants).toHaveLength(0);

it('should only include fragment spreads once even if included twice in different subselections', () => {
it("should only include fragment spreads once even if included twice in different subselections", () => {
const context = compile(`

@@ -165,11 +179,17 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(collectAndMergeFields(typeCaseForSelectionSet(selectionSet).variants[0])[0].selectionSet as SelectionSet);
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(collectAndMergeFields(
typeCaseForSelectionSet(selectionSet).variants[0]
)[0].selectionSet as SelectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(typeCase.default.fragmentSpreads.map(fragmentSpread => fragmentSpread.fragmentName)).toEqual(['CharacterName']);
expect(typeCase.default).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(
typeCase.default.fragmentSpreads.map(
fragmentSpread => fragmentSpread.fragmentName
)
).toEqual(["CharacterName"]);
});
it('should ignore type modifiers when matching the parent type', () => {
it("should ignore type modifiers when matching the parent type", () => {
const schema = buildSchema(`

@@ -206,7 +226,7 @@ type Query {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(typeCase.default).toMatchSelectionSet(["Human", "Droid"], ["name"]);

@@ -216,6 +236,9 @@ expect(typeCase.variants).toHaveLength(0);

expect(typeCase.exhaustiveVariants).toHaveLength(1);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(['Human', 'Droid'], ['name']);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
["Human", "Droid"],
["name"]
);
});
it('should merge fields from the default case into type conditions', () => {
it("should merge fields from the default case into type conditions", () => {
const context = compile(`

@@ -236,23 +259,29 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], ['name', 'appearsIn']);
expect(typeCase.default).toMatchSelectionSet(
["Human", "Droid"],
["name", "appearsIn"]
);
expect(typeCase.variants).toHaveLength(2);
expect(typeCase.variants).toContainSelectionSetMatching(
['Droid'],
['name', 'primaryFunction', 'appearsIn']
["Droid"],
["name", "primaryFunction", "appearsIn"]
);
expect(typeCase.variants).toContainSelectionSetMatching(['Human'], ['name', 'appearsIn', 'height']);
expect(typeCase.variants).toContainSelectionSetMatching(
["Human"],
["name", "appearsIn", "height"]
);
expect(typeCase.exhaustiveVariants).toHaveLength(2);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
['Droid'],
['name', 'primaryFunction', 'appearsIn']
["Droid"],
["name", "primaryFunction", "appearsIn"]
);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
['Human'],
['name', 'appearsIn', 'height']
["Human"],
["name", "appearsIn", "height"]
);

@@ -276,12 +305,12 @@ });

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], ['name']);
expect(typeCase.default).toMatchSelectionSet(["Human", "Droid"], ["name"]);
expect(typeCase.variants).toHaveLength(1);
expect(typeCase.variants).toContainSelectionSetMatching(
['Droid'],
['name', 'primaryFunction', 'appearsIn']
["Droid"],
["name", "primaryFunction", "appearsIn"]
);

@@ -291,9 +320,12 @@

expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
['Droid'],
['name', 'primaryFunction', 'appearsIn']
["Droid"],
["name", "primaryFunction", "appearsIn"]
);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(['Human'], ['name']);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
["Human"],
["name"]
);
});
it('should inherit type condition when nesting an inline fragment in an inline fragment with a more specific type condition', () => {
it("should inherit type condition when nesting an inline fragment in an inline fragment with a more specific type condition", () => {
const context = compile(`

@@ -311,17 +343,26 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], []);
expect(typeCase.default).toMatchSelectionSet(["Human", "Droid"], []);
expect(typeCase.variants).toHaveLength(1);
expect(typeCase.variants).toContainSelectionSetMatching(['Droid'], ['name']);
expect(typeCase.variants).toContainSelectionSetMatching(
["Droid"],
["name"]
);
expect(typeCase.exhaustiveVariants).toHaveLength(2);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(['Droid'], ['name']);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(['Human'], []);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
["Droid"],
["name"]
);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
["Human"],
[]
);
});
it('should not inherit type condition when nesting an inline fragment in an inline fragment with a less specific type condition', () => {
it("should not inherit type condition when nesting an inline fragment in an inline fragment with a less specific type condition", () => {
const context = compile(`

@@ -339,17 +380,26 @@ query Hero {

const selectionSet = (context.operations['Hero'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Hero"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Human', 'Droid'], []);
expect(typeCase.default).toMatchSelectionSet(["Human", "Droid"], []);
expect(typeCase.variants).toHaveLength(1);
expect(typeCase.variants).toContainSelectionSetMatching(['Droid'], ['name']);
expect(typeCase.variants).toContainSelectionSetMatching(
["Droid"],
["name"]
);
expect(typeCase.exhaustiveVariants).toHaveLength(2);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(['Droid'], ['name']);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(['Human'], []);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
["Droid"],
["name"]
);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
["Human"],
[]
);
});
it('should merge fields from the parent case into nested type conditions', () => {
it("should merge fields from the parent case into nested type conditions", () => {
const context = compile(

@@ -371,22 +421,34 @@ `

const selectionSet = (context.operations['Animal'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Animal"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Cat', 'Bird', 'Fish', 'Crocodile'], []);
expect(typeCase.default).toMatchSelectionSet(
["Cat", "Bird", "Fish", "Crocodile"],
[]
);
expect(typeCase.variants).toHaveLength(2);
expect(typeCase.variants).toContainSelectionSetMatching(['Cat', 'Bird'], ['name', 'bodyTemperature']);
expect(typeCase.variants).toContainSelectionSetMatching(['Fish'], ['name']);
expect(typeCase.variants).toContainSelectionSetMatching(
["Cat", "Bird"],
["name", "bodyTemperature"]
);
expect(typeCase.variants).toContainSelectionSetMatching(["Fish"], ["name"]);
expect(typeCase.exhaustiveVariants).toHaveLength(3);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
['Cat', 'Bird'],
['name', 'bodyTemperature']
["Cat", "Bird"],
["name", "bodyTemperature"]
);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(['Fish'], ['name']);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(['Crocodile'], []);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
["Fish"],
["name"]
);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
["Crocodile"],
[]
);
});
it('should merge fields from the parent case into nested type conditions', () => {
it("should merge fields from the parent case into nested type conditions", () => {
const context = compile(

@@ -414,22 +476,34 @@ `

const selectionSet = (context.operations['Animal'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Animal"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Cat', 'Bird', 'Fish', 'Crocodile'], []);
expect(typeCase.default).toMatchSelectionSet(
["Cat", "Bird", "Fish", "Crocodile"],
[]
);
expect(typeCase.variants).toHaveLength(2);
expect(typeCase.variants).toContainSelectionSetMatching(['Cat', 'Bird'], ['name', 'bodyTemperature']);
expect(typeCase.variants).toContainSelectionSetMatching(['Fish'], ['name']);
expect(typeCase.variants).toContainSelectionSetMatching(
["Cat", "Bird"],
["name", "bodyTemperature"]
);
expect(typeCase.variants).toContainSelectionSetMatching(["Fish"], ["name"]);
expect(typeCase.exhaustiveVariants).toHaveLength(3);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
['Cat', 'Bird'],
['name', 'bodyTemperature']
["Cat", "Bird"],
["name", "bodyTemperature"]
);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(['Fish'], ['name']);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(['Crocodile'], []);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
["Fish"],
["name"]
);
expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
["Crocodile"],
[]
);
});
it('should not keep type conditions when all possible objects match', () => {
it("should not keep type conditions when all possible objects match", () => {
const context = compile(

@@ -451,7 +525,10 @@ `

const selectionSet = (context.operations['Animal'].selectionSet.selections[0] as Field)
.selectionSet as SelectionSet;
const selectionSet = (context.operations["Animal"].selectionSet
.selections[0] as Field).selectionSet as SelectionSet;
const typeCase = typeCaseForSelectionSet(selectionSet);
expect(typeCase.default).toMatchSelectionSet(['Cat', 'Bird'], ['name', 'bodyTemperature']);
expect(typeCase.default).toMatchSelectionSet(
["Cat", "Bird"],
["name", "bodyTemperature"]
);
expect(typeCase.variants).toHaveLength(0);

@@ -461,6 +538,6 @@

expect(typeCase.exhaustiveVariants).toContainSelectionSetMatching(
['Cat', 'Bird'],
['name', 'bodyTemperature']
["Cat", "Bird"],
["name", "bodyTemperature"]
);
});
});

@@ -1,7 +0,7 @@

import { SelectionSet, Selection, Field, BooleanCondition } from '../';
import { GraphQLObjectType } from 'graphql';
import { SelectionSet, Selection, Field, BooleanCondition } from "../";
import { GraphQLObjectType } from "graphql";
// This is a temporary workaround to keep track of conditions on fields in the fields themselves.
// It is only added here because we want to expose it to the Android target, which relies on the legacy IR.
declare module '../' {
declare module "../" {
interface Field {

@@ -27,3 +27,3 @@ conditions?: BooleanCondition[];

switch (selection.kind) {
case 'Field':
case "Field":
let groupForResponseKey = groupedFields.get(selection.responseKey);

@@ -48,13 +48,26 @@ if (!groupForResponseKey) {

break;
case 'FragmentSpread':
case 'TypeCondition':
if (selection.kind === 'FragmentSpread' && !mergeInFragmentSpreads) continue;
case "FragmentSpread":
case "TypeCondition":
if (selection.kind === "FragmentSpread" && !mergeInFragmentSpreads)
continue;
// Only merge fragment spreads and type conditions if they match all possible types.
if (!possibleTypes.every(type => selection.selectionSet.possibleTypes.includes(type))) continue;
if (
!possibleTypes.every(type =>
selection.selectionSet.possibleTypes.includes(type)
)
)
continue;
visitSelectionSet(selection.selectionSet.selections, possibleTypes, conditions);
visitSelectionSet(
selection.selectionSet.selections,
possibleTypes,
conditions
);
break;
case 'BooleanCondition':
visitSelectionSet(selection.selectionSet.selections, possibleTypes, [...conditions, selection]);
case "BooleanCondition":
visitSelectionSet(selection.selectionSet.selections, possibleTypes, [
...conditions,
selection
]);
break;

@@ -70,7 +83,13 @@ }

const fields = Array.from(groupedFields.values()).map(fields => {
const isFieldIncludedUnconditionally = fields.some(field => !field.isConditional);
const isFieldIncludedUnconditionally = fields.some(
field => !field.isConditional
);
return fields
.map(field => {
if (isFieldIncludedUnconditionally && field.isConditional && field.selectionSet) {
if (
isFieldIncludedUnconditionally &&
field.isConditional &&
field.selectionSet
) {
field.selectionSet.selections = wrapInBooleanConditionsIfNeeded(

@@ -96,3 +115,5 @@ field.selectionSet.selections,

if (field.selectionSet && otherField.selectionSet) {
field.selectionSet.selections.push(...otherField.selectionSet.selections);
field.selectionSet.selections.push(
...otherField.selectionSet.selections
);
}

@@ -99,0 +120,0 @@

@@ -1,2 +0,2 @@

import { SelectionSet, Fragment } from '../';
import { SelectionSet, Fragment } from "../";

@@ -10,3 +10,3 @@ export function collectFragmentsReferenced(

switch (selection.kind) {
case 'FragmentSpread':
case "FragmentSpread":
fragmentsReferenced.add(selection.fragmentName);

@@ -19,9 +19,17 @@

collectFragmentsReferenced(fragment.selectionSet, fragments, fragmentsReferenced);
collectFragmentsReferenced(
fragment.selectionSet,
fragments,
fragmentsReferenced
);
break;
case 'Field':
case 'TypeCondition':
case 'BooleanCondition':
case "Field":
case "TypeCondition":
case "BooleanCondition":
if (selection.selectionSet) {
collectFragmentsReferenced(selection.selectionSet, fragments, fragmentsReferenced);
collectFragmentsReferenced(
selection.selectionSet,
fragments,
fragmentsReferenced
);
}

@@ -28,0 +36,0 @@ break;

@@ -1,4 +0,4 @@

import { Operation, Fragment } from '../';
import { collectFragmentsReferenced } from './collectFragmentsReferenced';
import { createHash } from 'crypto';
import { Operation, Fragment } from "../";
import { collectFragmentsReferenced } from "./collectFragmentsReferenced";
import { createHash } from "crypto";

@@ -11,3 +11,6 @@ export function generateOperationId(

if (!fragmentsReferenced) {
fragmentsReferenced = collectFragmentsReferenced(operation.selectionSet, fragments);
fragmentsReferenced = collectFragmentsReferenced(
operation.selectionSet,
fragments
);
}

@@ -24,9 +27,9 @@

})
].join('\n');
].join("\n");
const hash = createHash('sha256');
const hash = createHash("sha256");
hash.update(sourceWithFragments);
const operationId = hash.digest('hex');
const operationId = hash.digest("hex");
return { operationId, sourceWithFragments };
}

@@ -1,4 +0,6 @@

import { SelectionSet, Selection } from '../';
import { SelectionSet, Selection } from "../";
export function inlineRedundantTypeConditions(selectionSet: SelectionSet): SelectionSet {
export function inlineRedundantTypeConditions(
selectionSet: SelectionSet
): SelectionSet {
const selections: Selection[] = [];

@@ -8,6 +10,10 @@

if (
selection.kind === 'TypeCondition' &&
selectionSet.possibleTypes.every(type => selection.selectionSet.possibleTypes.includes(type))
selection.kind === "TypeCondition" &&
selectionSet.possibleTypes.every(type =>
selection.selectionSet.possibleTypes.includes(type)
)
) {
selections.push(...inlineRedundantTypeConditions(selection.selectionSet).selections);
selections.push(
...inlineRedundantTypeConditions(selection.selectionSet).selections
);
} else {

@@ -14,0 +20,0 @@ selections.push(selection);

@@ -1,7 +0,7 @@

import { inspect } from 'util';
import { inspect } from "util";
import { GraphQLObjectType } from 'graphql';
import { GraphQLObjectType } from "graphql";
import { SelectionSet, Selection, Field, FragmentSpread } from '../';
import { collectAndMergeFields } from './collectAndMergeFields';
import { SelectionSet, Selection, Field, FragmentSpread } from "../";
import { collectAndMergeFields } from "./collectAndMergeFields";

@@ -22,3 +22,5 @@ export class Variant implements SelectionSet {

collectAndMergeFields(this, false).map(field => field.responseKey)
)} ${inspect(this.fragmentSpreads.map(fragmentSpread => fragmentSpread.fragmentName))}\n`;
)} ${inspect(
this.fragmentSpreads.map(fragmentSpread => fragmentSpread.fragmentName)
)}\n`;
}

@@ -35,11 +37,14 @@ }

switch (selection.kind) {
case 'Field':
for (const variant of typeCase.disjointVariantsFor(selectionSet.possibleTypes)) {
case "Field":
for (const variant of typeCase.disjointVariantsFor(
selectionSet.possibleTypes
)) {
variant.selections.push(selection);
}
break;
case 'FragmentSpread':
case "FragmentSpread":
if (
typeCase.default.fragmentSpreads.some(
fragmentSpread => fragmentSpread.fragmentName === selection.fragmentName
fragmentSpread =>
fragmentSpread.fragmentName === selection.fragmentName
)

@@ -49,3 +54,5 @@ )

for (const variant of typeCase.disjointVariantsFor(selectionSet.possibleTypes)) {
for (const variant of typeCase.disjointVariantsFor(
selectionSet.possibleTypes
)) {
variant.fragmentSpreads.push(selection);

@@ -71,3 +78,3 @@

break;
case 'TypeCondition':
case "TypeCondition":
typeCase.merge(

@@ -85,5 +92,8 @@ typeCaseForSelectionSet(

break;
case 'BooleanCondition':
case "BooleanCondition":
typeCase.merge(
typeCaseForSelectionSet(selection.selectionSet, mergeInFragmentSpreads),
typeCaseForSelectionSet(
selection.selectionSet,
mergeInFragmentSpreads
),
selectionSet => [

@@ -117,5 +127,9 @@ {

get remainder(): Variant | undefined {
if (this.default.possibleTypes.some(type => !this.variantsByType.has(type))) {
if (
this.default.possibleTypes.some(type => !this.variantsByType.has(type))
) {
return new Variant(
this.default.possibleTypes.filter(type => !this.variantsByType.has(type)),
this.default.possibleTypes.filter(
type => !this.variantsByType.has(type)
),
this.default.selections,

@@ -151,3 +165,5 @@ this.default.fragmentSpreads

const matchesDefault = this.default.possibleTypes.every(type => possibleTypes.includes(type));
const matchesDefault = this.default.possibleTypes.every(type =>
possibleTypes.includes(type)
);

@@ -175,3 +191,7 @@ if (matchesDefault) {

if (!split) {
split = new Variant([], [...original.selections], [...original.fragmentSpreads]);
split = new Variant(
[],
[...original.selections],
[...original.fragmentSpreads]
);
splits.set(original, split);

@@ -192,13 +212,24 @@ variants.push(split);

merge(otherTypeCase: TypeCase, transform?: (selectionSet: SelectionSet) => Selection[]) {
merge(
otherTypeCase: TypeCase,
transform?: (selectionSet: SelectionSet) => Selection[]
) {
for (const otherVariant of otherTypeCase.defaultAndVariants) {
if (otherVariant.selections.length < 1) continue;
for (const variant of this.disjointVariantsFor(otherVariant.possibleTypes)) {
for (const variant of this.disjointVariantsFor(
otherVariant.possibleTypes
)) {
if (otherVariant.fragmentSpreads.length > 0) {
// Union of variant.fragmentSpreads and otherVariant.fragmentSpreads
variant.fragmentSpreads = [...variant.fragmentSpreads, ...otherVariant.fragmentSpreads].filter(
(a, index, array) => array.findIndex(b => b.fragmentName == a.fragmentName) == index
variant.fragmentSpreads = [
...variant.fragmentSpreads,
...otherVariant.fragmentSpreads
].filter(
(a, index, array) =>
array.findIndex(b => b.fragmentName == a.fragmentName) == index
);
}
variant.selections.push(...(transform ? transform(otherVariant) : otherVariant.selections));
variant.selections.push(
...(transform ? transform(otherVariant) : otherVariant.selections)
);
}

@@ -212,5 +243,5 @@ }

` default -> ${inspect(this.default)}\n` +
this.variants.map(variant => ` ${inspect(variant)}\n`).join('')
this.variants.map(variant => ` ${inspect(variant)}\n`).join("")
);
}
}

@@ -1,3 +0,3 @@

import { GraphQLError } from 'graphql';
import * as path from 'path';
import { GraphQLError } from "graphql";
import * as path from "path";

@@ -8,3 +8,3 @@ // ToolError is used for errors that are part of the expected flow

export class ToolError extends Error {
name: string = 'ToolError';
name: string = "ToolError";

@@ -36,3 +36,7 @@ constructor(message: string) {

export function logErrorMessage(message: string, fileName?: string, lineNumber?: number) {
export function logErrorMessage(
message: string,
fileName?: string,
lineNumber?: number
) {
if (isRunningFromXcodeScript) {

@@ -49,3 +53,8 @@ if (fileName && lineNumber) {

if (fileName) {
const truncatedFileName = '/' + fileName.split(path.sep).slice(-4).join(path.sep);
const truncatedFileName =
"/" +
fileName
.split(path.sep)
.slice(-4)
.join(path.sep);
console.error(`...${truncatedFileName}: ${message}`);

@@ -52,0 +61,0 @@ } else {

@@ -1,1 +0,1 @@

import './polyfills';
import "./polyfills";

@@ -119,3 +119,4 @@ import { fs } from "./localfs";

}
}).filter(source => source);
})
.filter(source => source);

@@ -122,0 +123,0 @@ return sources as DocumentNode[];

@@ -1,3 +0,3 @@

import 'core-js/fn/object/values';
import 'core-js/fn/object/entries';
import 'core-js/fn/array/flat-map';
import "core-js/fn/object/values";
import "core-js/fn/object/entries";
import "core-js/fn/array/flat-map";

@@ -6,23 +6,30 @@ import {

GraphQLEnumType,
GraphQLInputObjectType,
} from 'graphql';
GraphQLInputObjectType
} from "graphql";
import { LegacyCompilerContext } from './compiler/legacyIR';
import { LegacyCompilerContext } from "./compiler/legacyIR";
export default function serializeToJSON(context: LegacyCompilerContext) {
return serializeAST({
operations: Object.values(context.operations),
fragments: Object.values(context.fragments),
typesUsed: context.typesUsed.map(serializeType),
}, '\t');
return serializeAST(
{
operations: Object.values(context.operations),
fragments: Object.values(context.fragments),
typesUsed: context.typesUsed.map(serializeType)
},
"\t"
);
}
export function serializeAST(ast: any, space?: string) {
return JSON.stringify(ast, function(_, value) {
if (isType(value)) {
return String(value);
} else {
return value;
}
}, space);
return JSON.stringify(
ast,
function(_, value) {
if (isType(value)) {
return String(value);
} else {
return value;
}
},
space
);
}

@@ -47,14 +54,12 @@

return {
kind: 'EnumType',
kind: "EnumType",
name,
description,
values: values.map(value => (
{
name: value.name,
description: value.description,
isDeprecated: value.isDeprecated,
deprecationReason: value.deprecationReason
}
))
}
values: values.map(value => ({
name: value.name,
description: value.description,
isDeprecated: value.isDeprecated,
deprecationReason: value.deprecationReason
}))
};
}

@@ -67,3 +72,3 @@

return {
kind: 'InputObjectType',
kind: "InputObjectType",
name,

@@ -77,3 +82,3 @@ description,

}))
}
};
}

@@ -85,6 +90,6 @@

return {
kind: 'ScalarType',
kind: "ScalarType",
name,
description
}
};
}
declare global {
interface Array<T> {
flatMap<U>(callbackfn: (value: T, index: number, array: T[]) => U[] | undefined, thisArg?: any): U[];
flatMap<U>(
callbackfn: (value: T, index: number, array: T[]) => U[] | undefined,
thisArg?: any
): U[];
}

@@ -12,2 +15,2 @@ }

return list;
};
}
export interface BasicGeneratedFile {
output: string
output: string;
}
export class GeneratedFile<Scope = any> implements BasicGeneratedFile {

@@ -12,3 +11,3 @@ scopeStack: Scope[] = [];

public output = '';
public output = "";

@@ -24,3 +23,3 @@ pushScope(scope: Scope) {

get scope(): Scope {
if (this.scopeStack.length < 1) throw new Error('No active scope');
if (this.scopeStack.length < 1) throw new Error("No active scope");

@@ -38,3 +37,3 @@ return this.scopeStack[this.scopeStack.length - 1];

if (this.output) {
this.print('\n');
this.print("\n");
this.startOfIndentLevel = false;

@@ -59,3 +58,3 @@ }

printIndent() {
const indentation = ' '.repeat(this.indentLevel * this.indentWidth);
const indentation = " ".repeat(this.indentLevel * this.indentWidth);
this.output += indentation;

@@ -73,3 +72,3 @@ }

withinBlock(closure: Function, open = ' {', close = '}') {
withinBlock(closure: Function, open = " {", close = "}") {
this.print(open);

@@ -141,5 +140,5 @@ this.withIndent(closure);

withinBlock(closure: Function, open = ' {', close = '}') {
withinBlock(closure: Function, open = " {", close = "}") {
this.currentFile.withinBlock(closure, open, close);
}
}

@@ -9,3 +9,2 @@ import {

TypeNameMetaFieldDef,
GraphQLNamedType,
GraphQLCompositeType,

@@ -19,3 +18,2 @@ GraphQLObjectType,

GraphQLType,
GraphQLScalarType,
ASTNode,

@@ -31,17 +29,8 @@ Location,

DocumentNode
} from 'graphql';
} from "graphql";
declare module "graphql" {
function isNamedType(type: GraphQLType): type is GraphQLNamedType;
const specifiedScalarTypes: GraphQLScalarType[];
function isSpecifiedScalarType(type: GraphQLType): boolean;
const introspectionTypes: GraphQLNamedType[];
function isIntrospectionType(type: GraphQLType): boolean;
function validateSchema(schema: GraphQLSchema): GraphQLError[];
}
declare module "graphql/utilities/buildASTSchema" {
function buildASTSchema(
ast: DocumentNode,
options?: { assumeValid?: boolean, commentDescriptions?: boolean },
options?: { assumeValid?: boolean; commentDescriptions?: boolean }
): GraphQLSchema;

@@ -51,14 +40,22 @@ }

export function sortEnumValues(values: GraphQLEnumValue[]): GraphQLEnumValue[] {
return values.sort((a, b) => a.value < b.value ? -1 : a.value > b.value ? 1 : 0);
return values.sort(
(a, b) => (a.value < b.value ? -1 : a.value > b.value ? 1 : 0)
);
}
export function isList(type: GraphQLType): boolean {
return type instanceof GraphQLList || (type instanceof GraphQLNonNull && type.ofType instanceof GraphQLList);
return (
type instanceof GraphQLList ||
(type instanceof GraphQLNonNull && type.ofType instanceof GraphQLList)
);
}
export function isMetaFieldName(name: string) {
return name.startsWith('__');
return name.startsWith("__");
}
const typenameField = { kind: Kind.FIELD, name: { kind: Kind.NAME, value: '__typename' } };
const typenameField = {
kind: Kind.FIELD,
name: { kind: Kind.NAME, value: "__typename" }
};

@@ -72,3 +69,7 @@ export function withTypenameFieldAddedWhereNeeded(ast: ASTNode) {

selections: node.selections.filter(
selection => !(selection.kind === 'Field' && (selection as FieldNode).name.value === '__typename')
selection =>
!(
selection.kind === "Field" &&
(selection as FieldNode).name.value === "__typename"
)
)

@@ -79,3 +80,4 @@ };

leave(node: ASTNode) {
if (!(node.kind === 'Field' || node.kind === 'FragmentDefinition')) return undefined;
if (!(node.kind === "Field" || node.kind === "FragmentDefinition"))
return undefined;
if (!node.selectionSet) return undefined;

@@ -102,3 +104,3 @@

export function filePathForNode(node: ASTNode): string {
export function filePathForNode(node: ASTNode): string {
const name = node.loc && node.loc.source && node.loc.source.name;

@@ -111,18 +113,23 @@ if (!name || name === "GraphQL") {

export function valueFromValueNode(valueNode: ValueNode): any | { kind: 'Variable', variableName: string } {
export function valueFromValueNode(
valueNode: ValueNode
): any | { kind: "Variable"; variableName: string } {
switch (valueNode.kind) {
case 'IntValue':
case 'FloatValue':
case "IntValue":
case "FloatValue":
return Number(valueNode.value);
case 'NullValue':
case "NullValue":
return null;
case 'ListValue':
case "ListValue":
return valueNode.values.map(valueFromValueNode);
case 'ObjectValue':
return valueNode.fields.reduce((object, field) => {
object[field.name.value] = valueFromValueNode(field.value);
return object;
}, {} as any);
case 'Variable':
return { kind: 'Variable', variableName: valueNode.name.value };
case "ObjectValue":
return valueNode.fields.reduce(
(object, field) => {
object[field.name.value] = valueFromValueNode(field.value);
return object;
},
{} as any
);
case "Variable":
return { kind: "Variable", variableName: valueNode.name.value };
default:

@@ -133,4 +140,13 @@ return valueNode.value;

export function isTypeProperSuperTypeOf(schema: GraphQLSchema, maybeSuperType: GraphQLCompositeType, subType: GraphQLCompositeType) {
return isEqualType(maybeSuperType, subType) || subType instanceof GraphQLObjectType && (isAbstractType(maybeSuperType) && schema.isPossibleType(maybeSuperType, subType));
export function isTypeProperSuperTypeOf(
schema: GraphQLSchema,
maybeSuperType: GraphQLCompositeType,
subType: GraphQLCompositeType
) {
return (
isEqualType(maybeSuperType, subType) ||
(subType instanceof GraphQLObjectType &&
(isAbstractType(maybeSuperType) &&
schema.isPossibleType(maybeSuperType, subType)))
);
}

@@ -143,22 +159,23 @@

*/
export function getOperationRootType(schema: GraphQLSchema, operation: OperationDefinitionNode) {
export function getOperationRootType(
schema: GraphQLSchema,
operation: OperationDefinitionNode
) {
switch (operation.operation) {
case 'query':
case "query":
return schema.getQueryType();
case 'mutation':
case "mutation":
const mutationType = schema.getMutationType();
if (!mutationType) {
throw new GraphQLError(
'Schema is not configured for mutations',
[operation]
);
throw new GraphQLError("Schema is not configured for mutations", [
operation
]);
}
return mutationType;
case 'subscription':
case "subscription":
const subscriptionType = schema.getSubscriptionType();
if (!subscriptionType) {
throw new GraphQLError(
'Schema is not configured for subscriptions',
[operation]
);
throw new GraphQLError("Schema is not configured for subscriptions", [
operation
]);
}

@@ -168,3 +185,3 @@ return subscriptionType;

throw new GraphQLError(
'Can only compile queries, mutations and subscriptions',
"Can only compile queries, mutations and subscriptions",
[operation]

@@ -180,21 +197,29 @@ );

*/
export function getFieldDef(schema: GraphQLSchema, parentType: GraphQLCompositeType, fieldAST: FieldNode): GraphQLField<any, any> | undefined {
export function getFieldDef(
schema: GraphQLSchema,
parentType: GraphQLCompositeType,
fieldAST: FieldNode
): GraphQLField<any, any> | undefined {
const name = fieldAST.name.value;
if (name === SchemaMetaFieldDef.name &&
schema.getQueryType() === parentType) {
if (
name === SchemaMetaFieldDef.name &&
schema.getQueryType() === parentType
) {
return SchemaMetaFieldDef;
}
if (name === TypeMetaFieldDef.name &&
schema.getQueryType() === parentType) {
if (name === TypeMetaFieldDef.name && schema.getQueryType() === parentType) {
return TypeMetaFieldDef;
}
if (name === TypeNameMetaFieldDef.name &&
(parentType instanceof GraphQLObjectType ||
parentType instanceof GraphQLInterfaceType ||
parentType instanceof GraphQLUnionType)
if (
name === TypeNameMetaFieldDef.name &&
(parentType instanceof GraphQLObjectType ||
parentType instanceof GraphQLInterfaceType ||
parentType instanceof GraphQLUnionType)
) {
return TypeNameMetaFieldDef;
}
if (parentType instanceof GraphQLObjectType ||
parentType instanceof GraphQLInterfaceType) {
if (
parentType instanceof GraphQLObjectType ||
parentType instanceof GraphQLInterfaceType
) {
return parentType.getFields()[name];

@@ -201,0 +226,0 @@ }

@@ -8,3 +8,3 @@ // Code generation helper functions copied from graphql-js (https://github.com/graphql/graphql-js)

export function join(maybeArray?: any[], separator?: string) {
return maybeArray ? maybeArray.filter(x => x).join(separator || '') : '';
return maybeArray ? maybeArray.filter(x => x).join(separator || "") : "";
}

@@ -17,5 +17,5 @@

export function block(array: any[]) {
return array && array.length !== 0 ?
indent('{\n' + join(array, '\n')) + '\n}' :
'{}';
return array && array.length !== 0
? indent("{\n" + join(array, "\n")) + "\n}"
: "{}";
}

@@ -28,9 +28,7 @@

export function wrap(start: string, maybeString?: string, end?: string) {
return maybeString ?
start + maybeString + (end || '') :
'';
return maybeString ? start + maybeString + (end || "") : "";
}
export function indent(maybeString?: string) {
return maybeString && maybeString.replace(/\n/g, '\n ');
return maybeString && maybeString.replace(/\n/g, "\n ");
}

@@ -42,6 +40,10 @@

export function commentBlockContent(commentString: string) {
return '*\n' + commentString
.split('\n')
.map(line => ` * ${line.replace('*/', '')}`)
.join('\n') + '\n ';
return (
"*\n" +
commentString
.split("\n")
.map(line => ` * ${line.replace("*/", "")}`)
.join("\n") +
"\n "
);
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc