Socket
Socket
Sign inDemoInstall

apollo-codegen

Package Overview
Dependencies
Maintainers
1
Versions
102
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

apollo-codegen - npm Package Compare versions

Comparing version 0.17.0-alpha.1 to 0.17.0-alpha.2

lib/compiler/visitors/collectAndMergeFields.js

45

lib/compiler/index.js

@@ -5,19 +5,2 @@ "use strict";

const graphql_2 = require("../utilities/graphql");
class CompilerContext {
constructor(schema, typesUsed, operations, fragments, options) {
this.schema = schema;
this.typesUsed = typesUsed;
this.operations = operations;
this.fragments = fragments;
this.options = options;
}
fragmentNamed(fragmentName) {
const fragment = this.fragments[fragmentName];
if (!fragment) {
throw new Error(`Cannot find fragment "${fragmentName}"`);
}
return fragment;
}
}
exports.CompilerContext = CompilerContext;
function argumentsFromAST(args) {

@@ -48,4 +31,16 @@ return (args &&

}
for (const fragmentSpread of compiler.unresolvedFragmentSpreads) {
const fragment = fragments[fragmentSpread.fragmentName];
if (!fragment) {
throw new Error(`Cannot find fragment "${fragmentSpread.fragmentName}"`);
}
const possibleTypes = fragment.selectionSet.possibleTypes.filter(type => fragmentSpread.selectionSet.possibleTypes.includes(type));
fragmentSpread.isConditional = fragment.selectionSet.possibleTypes.some(type => !fragmentSpread.selectionSet.possibleTypes.includes(type));
fragmentSpread.selectionSet = {
possibleTypes,
selections: fragment.selectionSet.selections
};
}
const typesUsed = compiler.typesUsed;
return new CompilerContext(schema, typesUsed, operations, fragments, options);
return { schema, typesUsed, operations, fragments, options };
}

@@ -55,2 +50,3 @@ exports.compileToIR = compileToIR;

constructor(schema, options) {
this.unresolvedFragmentSpreads = [];
this.schema = schema;

@@ -161,3 +157,2 @@ this.options = options;

return field;
break;
}

@@ -173,3 +168,2 @@ case graphql_1.Kind.INLINE_FRAGMENT: {

};
break;
}

@@ -181,7 +175,12 @@ case graphql_1.Kind.FRAGMENT_SPREAD: {

visitedFragments.add(fragmentName);
return {
const fragmentSpread = {
kind: 'FragmentSpread',
fragmentName
fragmentName,
selectionSet: {
possibleTypes,
selections: []
}
};
break;
this.unresolvedFragmentSpreads.push(fragmentSpread);
return fragmentSpread;
}

@@ -188,0 +187,0 @@ }

@@ -13,7 +13,7 @@ "use strict";

const _1 = require("./");
const mergeInFragmentSpreads_1 = require("./visitors/mergeInFragmentSpreads");
const collectFragmentsReferenced_1 = require("./visitors/collectFragmentsReferenced");
const flattenIR_1 = require("./flattenIR");
const generateOperationId_1 = require("./visitors/generateOperationId");
const typeCase_1 = require("./visitors/typeCase");
const collectAndMergeFields_1 = require("./visitors/collectAndMergeFields");
require("../utilities/array");
const generateOperationId_1 = require("./visitors/generateOperationId");
function compileToLegacyIR(schema, document, options = { mergeInFieldsFromFragmentSpreads: true }) {

@@ -34,4 +34,4 @@ const context = _1.compileToIR(schema, document, options);

const { filePath, operationType, rootType, variables, source, selectionSet } = operation;
const fragmentsReferenced = collectFragmentsReferenced_1.collectFragmentsReferenced(this.context, selectionSet);
const { sourceWithFragments, operationId } = generateOperationId_1.generateOperationId(this.context, operation, fragmentsReferenced);
const fragmentsReferenced = collectFragmentsReferenced_1.collectFragmentsReferenced(selectionSet, this.context.fragments);
const { sourceWithFragments, operationId } = generateOperationId_1.generateOperationId(operation, this.context.fragments, fragmentsReferenced);
operations[operationName] = Object.assign({ filePath,

@@ -60,13 +60,11 @@ operationName,

transformSelectionSetToLegacyIR(selectionSet) {
const typeCase = new flattenIR_1.TypeCase(this.options.mergeInFieldsFromFragmentSpreads
? mergeInFragmentSpreads_1.mergeInFragmentSpreads(this.context, selectionSet)
: selectionSet);
const fields = this.transformFieldsToLegacyIR(typeCase.default.fields);
const inlineFragments = typeCase.records
.filter(record => !selectionSet.possibleTypes.every(type => record.possibleTypes.includes(type)) &&
record.fieldMap.size > 0)
.flatMap(record => {
const fields = this.transformFieldsToLegacyIR(record.fields);
const fragmentSpreads = this.collectFragmentSpreads(selectionSet, record.possibleTypes).map((fragmentSpread) => fragmentSpread.fragmentName);
return record.possibleTypes.map(possibleType => {
const typeCase = new typeCase_1.TypeCase(selectionSet, this.options.mergeInFieldsFromFragmentSpreads);
const fields = this.transformFieldsToLegacyIR(collectAndMergeFields_1.collectAndMergeFields(typeCase.default));
const inlineFragments = typeCase.variants.flatMap(variant => {
const fields = this.transformFieldsToLegacyIR(collectAndMergeFields_1.collectAndMergeFields(variant));
if (selectionSet.possibleTypes.every(type => variant.possibleTypes.includes(type)) &&
fields.length < 1)
return undefined;
const fragmentSpreads = this.collectFragmentSpreads(selectionSet, variant.possibleTypes).map((fragmentSpread) => fragmentSpread.fragmentName);
return variant.possibleTypes.map(possibleType => {
return {

@@ -93,3 +91,3 @@ typeCondition: possibleType,

const { args, type, isConditional, description, isDeprecated, deprecationReason, selectionSet } = field;
const conditions = (field.conditions && field.conditions.length > 0)
const conditions = field.conditions && field.conditions.length > 0
? field.conditions.map(({ kind, variableName, inverted }) => {

@@ -129,5 +127,5 @@ return {

}
return fragmentSpreads;
return Array.from(new Set(fragmentSpreads));
}
}
//# sourceMappingURL=legacyIR.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function collectFragmentsReferenced(context, selectionSet, fragmentsReferenced = new Set()) {
function collectFragmentsReferenced(selectionSet, fragments, fragmentsReferenced = new Set()) {
for (const selection of selectionSet.selections) {

@@ -8,7 +8,7 @@ switch (selection.kind) {

fragmentsReferenced.add(selection.fragmentName);
const fragment = context.fragments[selection.fragmentName];
const fragment = fragments[selection.fragmentName];
if (!fragment) {
throw new Error(`Cannot find fragment "${selection.fragmentName}"`);
}
collectFragmentsReferenced(context, fragment.selectionSet, fragmentsReferenced);
collectFragmentsReferenced(fragment.selectionSet, fragments, fragmentsReferenced);
break;

@@ -19,3 +19,3 @@ case 'Field':

if (selection.selectionSet) {
collectFragmentsReferenced(context, selection.selectionSet, fragmentsReferenced);
collectFragmentsReferenced(selection.selectionSet, fragments, fragmentsReferenced);
}

@@ -22,0 +22,0 @@ break;

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

const crypto_1 = require("crypto");
function generateOperationId(context, operation, fragmentsReferenced) {
function generateOperationId(operation, fragments, fragmentsReferenced) {
if (!fragmentsReferenced) {
fragmentsReferenced = collectFragmentsReferenced_1.collectFragmentsReferenced(context, operation.selectionSet);
fragmentsReferenced = collectFragmentsReferenced_1.collectFragmentsReferenced(operation.selectionSet, fragments);
}

@@ -13,3 +13,7 @@ const sourceWithFragments = [

...Array.from(fragmentsReferenced).map(fragmentName => {
return context.fragments[fragmentName].source;
const fragment = fragments[fragmentName];
if (!fragment) {
throw new Error(`Cannot find fragment "${fragmentName}"`);
}
return fragment.source;
})

@@ -16,0 +20,0 @@ ].join('\n');

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function inlineRedundantTypeConditions(_, selectionSet) {
function inlineRedundantTypeConditions(selectionSet) {
const selections = [];

@@ -8,3 +8,3 @@ for (const selection of selectionSet.selections) {

selectionSet.possibleTypes.every(type => selection.selectionSet.possibleTypes.includes(type))) {
selections.push(...selection.selectionSet.selections);
selections.push(...inlineRedundantTypeConditions(selection.selectionSet).selections);
}

@@ -11,0 +11,0 @@ else {

@@ -44,3 +44,16 @@ "use strict";

const nValues = values.length;
values.forEach((value, i) => generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}${printing_1.wrap(' // ', value.description)}`));
values.forEach((value, i) => {
if (!value.description || value.description.indexOf('\n') === -1) {
generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}${printing_1.wrap(' // ', value.description)}`);
}
else {
if (value.description) {
value.description.split('\n')
.forEach(line => {
generator.printOnNewline(` // ${line.trim()}`);
});
}
generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}`);
}
});
generator.printNewline();

@@ -88,3 +101,3 @@ }

fields = fields.map(rootField => {
const fields = rootField.fields.map(field => {
const fields = rootField.fields && rootField.fields.map(field => {
if (field.fieldName === '__typename') {

@@ -91,0 +104,0 @@ return Object.assign({}, field, { typeName: `"${rootField.type.name}"`, type: { name: `"${rootField.type.name}"` } });

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const graphql_1 = require("graphql");
const flattenIR_1 = require("../compiler/flattenIR");
const typeCase_1 = require("../compiler/visitors/typeCase");
const printing_1 = require("../utilities/printing");

@@ -10,5 +10,5 @@ const language_1 = require("./language");

const collectFragmentsReferenced_1 = require("../compiler/visitors/collectFragmentsReferenced");
const mergeInFragmentSpreads_1 = require("../compiler/visitors/mergeInFragmentSpreads");
const generateOperationId_1 = require("../compiler/visitors/generateOperationId");
const inlineRedundantTypeConditions_1 = require("../compiler/visitors/inlineRedundantTypeConditions");
const collectAndMergeFields_1 = require("../compiler/visitors/collectAndMergeFields");
require("../utilities/array");
function generateSource(context) {

@@ -68,5 +68,5 @@ const generator = new SwiftAPIGenerator(context);

}
const fragmentsReferenced = collectFragmentsReferenced_1.collectFragmentsReferenced(this.context, operation.selectionSet);
const fragmentsReferenced = collectFragmentsReferenced_1.collectFragmentsReferenced(operation.selectionSet, this.context.fragments);
if (this.context.options.generateOperationIds) {
const { operationId } = generateOperationId_1.generateOperationId(this.context, operation, fragmentsReferenced);
const { operationId } = generateOperationId_1.generateOperationId(operation, this.context.fragments, fragmentsReferenced);
this.printNewlineIfNeeded();

@@ -125,2 +125,3 @@ this.printOnNewline(`public static let operationIdentifier: String? = "${operationId}"`);

structDeclarationForSelectionSet({ structName, adoptedProtocols = ['GraphQLSelectionSet'], selectionSet }, beforeClosure) {
const typeCase = new typeCase_1.TypeCase(selectionSet, this.context.options.mergeInFieldsFromFragmentSpreads);
this.structDeclaration({ structName, adoptedProtocols }, () => {

@@ -130,10 +131,9 @@ if (beforeClosure) {

}
const possibleTypes = selectionSet.possibleTypes;
this.printNewlineIfNeeded();
this.printOnNewline('public static let possibleTypes = [');
this.print(printing_1.join(possibleTypes.map(type => `"${type.name}"`), ', '));
this.print(printing_1.join(selectionSet.possibleTypes.map(type => `"${type.name}"`), ', '));
this.print(']');
this.printNewlineIfNeeded();
this.printOnNewline('public static let selections: [GraphQLSelection] = ');
this.selectionSetInitialization(selectionSet);
this.typeCaseInitialization(typeCase);
this.printNewlineIfNeeded();

@@ -149,15 +149,10 @@ this.propertyDeclaration({

});
const typeCase = new flattenIR_1.TypeCase(inlineRedundantTypeConditions_1.inlineRedundantTypeConditions(this.context, mergeInFragmentSpreads_1.mergeInFragmentSpreads(this.context, selectionSet)));
this.initializersForTypeCase(typeCase);
const fields = typeCase.default.fields.map(field => this.helpers.propertyFromField(field));
const typeConditions = selectionSet.selections
.filter((selection) => selection.kind === 'TypeCondition')
.map(this.helpers.propertyFromTypeCondition, this.helpers);
const fragmentSpreads = selectionSet.selections.filter((selection) => selection.kind === 'FragmentSpread').map(fragmentSpread => {
const fragment = this.context.fragmentNamed(fragmentSpread.fragmentName);
const isConditional = selectionSet.possibleTypes.some(type => !fragment.selectionSet.possibleTypes.includes(type));
const fields = collectAndMergeFields_1.collectAndMergeFields(typeCase.default, this.context.options.mergeInFieldsFromFragmentSpreads).map(field => this.helpers.propertyFromField(field));
const variants = typeCase.variants.map(this.helpers.propertyFromVariant, this.helpers);
const fragmentSpreads = typeCase.default.fragmentSpreads.map(fragmentSpread => {
const isConditional = selectionSet.possibleTypes.some(type => !fragmentSpread.selectionSet.possibleTypes.includes(type));
return this.helpers.propertyFromFragmentSpread(fragmentSpread, isConditional);
});
fields.forEach(this.propertyDeclarationForField, this);
typeConditions.forEach(this.propertyDeclarationForTypeCondition, this);
if (fragmentSpreads.length > 0) {

@@ -176,11 +171,2 @@ this.printNewlineIfNeeded();

});
}
for (const typeCondition of typeConditions) {
this.structDeclarationForSelectionSet({
structName: typeCondition.structName,
adoptedProtocols: ['GraphQLFragment'],
selectionSet: typeCondition.selectionSet
});
}
if (fragmentSpreads.length > 0) {
this.structDeclaration({

@@ -219,2 +205,9 @@ structName: 'Fragments'

}
for (const variant of variants) {
this.propertyDeclarationForVariant(variant);
this.structDeclarationForSelectionSet({
structName: variant.structName,
selectionSet: variant.selectionSet
});
}
for (const field of fields) {

@@ -231,16 +224,16 @@ if (graphql_1.isCompositeType(graphql_1.getNamedType(field.type)) && field.selectionSet) {

initializersForTypeCase(typeCase) {
const records = typeCase.records;
const propertiesForFields = (fields, namespace) => {
return fields
const variants = typeCase.variants;
const propertiesForSelectionSet = (selectionSet, namespace) => {
return collectAndMergeFields_1.collectAndMergeFields(selectionSet, true)
.filter(field => field.name != '__typename')
.map(field => this.helpers.propertyFromField(field, namespace));
};
if (records.length == 1 && records[0].possibleTypes.length == 1) {
if (variants.length == 0 && typeCase.default.possibleTypes.length == 1) {
this.printNewlineIfNeeded();
this.printOnNewline(`public init`);
const properties = propertiesForFields(records[0].fields);
const properties = propertiesForSelectionSet(typeCase.default);
this.parametersForProperties(properties);
this.withinBlock(() => {
this.printOnNewline(printing_1.wrap(`self.init(snapshot: [`, printing_1.join([
`"__typename": "${records[0].possibleTypes[0]}"`,
`"__typename": "${typeCase.default.possibleTypes[0]}"`,
...properties.map(({ responseKey, propertyName }) => `"${responseKey}": ${language_1.escapeIdentifierIfNeeded(propertyName)}`)

@@ -251,6 +244,10 @@ ], ', ') || ':', `])`));

else {
for (const record of records) {
const remainder = typeCase.remainder;
for (const variant of remainder ? [remainder, ...variants] : variants) {
const structName = this.scope.typeName;
for (const possibleType of record.possibleTypes) {
const properties = propertiesForFields(record.fields, records.length > 1 ? this.helpers.structNameForTypeCondition(possibleType) : undefined);
for (const possibleType of variant.possibleTypes) {
const properties = propertiesForSelectionSet({
possibleTypes: [possibleType],
selections: variant.selections
}, variant === remainder ? undefined : this.helpers.structNameForVariant(variant));
this.printNewlineIfNeeded();

@@ -282,4 +279,10 @@ this.printOnNewline(`public static func make${possibleType}`);

this.withinBlock(() => {
const snapshotTypeName = this.helpers.typeNameFromGraphQLType(type, 'Snapshot', isOptional);
let getter = `return (snapshot["${responseKey}"]! as! ${snapshotTypeName})`;
const snapshotTypeName = this.helpers.typeNameFromGraphQLType(type, 'Snapshot', false);
let getter;
if (isOptional) {
getter = `return (snapshot["${responseKey}"] as? ${snapshotTypeName})`;
}
else {
getter = `return (snapshot["${responseKey}"] as! ${snapshotTypeName})`;
}
getter += this.helpers.mapExpressionForType(type, `${structName}(snapshot: $0)`);

@@ -298,3 +301,3 @@ this.printOnNewline(getter);

if (isOptional) {
this.printOnNewline(`return (snapshot["${responseKey}"]! as! Snapshot?).flatMap { ${structName}(snapshot: $0) }`);
this.printOnNewline(`return (snapshot["${responseKey}"] as! Snapshot?).flatMap { ${structName}(snapshot: $0) }`);
}

@@ -321,3 +324,8 @@ else {

this.withinBlock(() => {
this.printOnNewline(`return snapshot["${responseKey}"]! as! ${typeName}`);
if (isOptional) {
this.printOnNewline(`return snapshot["${responseKey}"] as? ${typeName.slice(0, -1)}`);
}
else {
this.printOnNewline(`return snapshot["${responseKey}"]! as! ${typeName}`);
}
});

@@ -331,4 +339,4 @@ this.printOnNewline('set');

}
propertyDeclarationForTypeCondition(typeCondition) {
const { propertyName, typeName, structName } = typeCondition;
propertyDeclarationForVariant(variant) {
const { propertyName, typeName, structName } = variant;
this.printNewlineIfNeeded();

@@ -363,2 +371,26 @@ this.printOnNewline(`public var ${propertyName}: ${typeName}`);

}
typeCaseInitialization(typeCase) {
if (typeCase.variants.length < 1) {
this.selectionSetInitialization(typeCase.default);
return;
}
this.print('[');
this.withIndent(() => {
this.printOnNewline(`GraphQLTypeCase(`);
this.withIndent(() => {
this.printOnNewline(`variants: [`);
this.print(typeCase.variants
.flatMap(variant => {
const structName = this.helpers.structNameForVariant(variant);
return variant.possibleTypes.map(type => `"${type}": ${structName}.selections`);
})
.join(', '));
this.print('],');
this.printOnNewline(`default: `);
this.selectionSetInitialization(typeCase.default);
});
this.printOnNewline(')');
});
this.printOnNewline(']');
}
selectionSetInitialization(selectionSet) {

@@ -385,12 +417,2 @@ this.print('[');

}
case 'TypeCondition': {
const structName = this.helpers.structNameForTypeCondition(selection.type);
this.printOnNewline(`GraphQLFragmentSpread(${structName}.self),`);
break;
}
case 'FragmentSpread': {
const structName = this.helpers.structNameForFragmentName(selection.fragmentName);
this.printOnNewline(`GraphQLFragmentSpread(${structName}.self),`);
break;
}
case 'BooleanCondition':

@@ -406,2 +428,17 @@ this.printOnNewline(`GraphQLBooleanCondition(`);

break;
case 'TypeCondition': {
this.printOnNewline(`GraphQLTypeCondition(`);
this.print(printing_1.join([
`possibleTypes: [${printing_1.join(selection.selectionSet.possibleTypes.map(type => `"${type.name}"`), ', ')}]`,
'selections: '
], ', '));
this.selectionSetInitialization(selection.selectionSet);
this.print('),');
break;
}
case 'FragmentSpread': {
const structName = this.helpers.structNameForFragmentName(selection.fragmentName);
this.printOnNewline(`GraphQLFragmentSpread(${structName}.self),`);
break;
}
}

@@ -408,0 +445,0 @@ }

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

else if (graphql_1.isCompositeType(type)) {
return `.object(${structName}.self)`;
return `.object(${structName}.selections)`;
}

@@ -77,4 +77,4 @@ else {

}
structNameForTypeCondition(type) {
return 'As' + change_case_1.pascalCase(type.name);
structNameForVariant(variant) {
return 'As' + variant.possibleTypes.map(type => change_case_1.pascalCase(type.name)).join('Or');
}

@@ -101,9 +101,10 @@ propertyFromField(field, namespace) {

}
propertyFromTypeCondition(typeCondition) {
const structName = this.structNameForTypeCondition(typeCondition.type);
return Object.assign({}, typeCondition, {
propertyFromVariant(variant) {
const structName = this.structNameForVariant(variant);
return {
propertyName: change_case_1.camelCase(structName),
typeName: structName + '?',
structName
});
structName,
selectionSet: variant
};
}

@@ -129,3 +130,3 @@ propertyFromFragmentSpread(fragmentSpread, isConditional) {

if (value.kind === 'Variable') {
return `Variable("${value.variableName}")`;
return `GraphQLVariable("${value.variableName}")`;
}

@@ -132,0 +133,0 @@ else if (Array.isArray(value)) {

@@ -44,3 +44,16 @@ "use strict";

const nValues = values.length;
values.forEach((value, i) => generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}${printing_1.wrap(' // ', value.description)}`));
values.forEach((value, i) => {
if (!value.description || value.description.indexOf('\n') === -1) {
generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}${printing_1.wrap(' // ', value.description)}`);
}
else {
if (value.description) {
value.description.split('\n')
.forEach(line => {
generator.printOnNewline(` // ${line.trim()}`);
});
}
generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}`);
}
});
generator.printNewline();

@@ -47,0 +60,0 @@ }

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

...(target === 'swift' ? [NoExplicitTypename] : []),
...graphql_1.specifiedRules.filter(rule => specifiedRulesToBeRemoved.includes(rule))
...graphql_1.specifiedRules.filter(rule => !specifiedRulesToBeRemoved.includes(rule))
];

@@ -14,0 +14,0 @@ const validationErrors = graphql_1.validate(schema, document, rules);

{
"name": "apollo-codegen",
"version": "0.17.0-alpha.1",
"version": "0.17.0-alpha.2",
"description": "Generate API code or type annotations based on a GraphQL schema and query documents",

@@ -12,3 +12,3 @@ "main": "./lib/index.js",

"prepublish": "npm run clean && npm run compile",
"test": "jest",
"test": "./node_modules/.bin/jest",
"test:smoke": "rm -rf node_modules && npm install --prod && node ./lib/cli.js && echo 'Smoke Test Passed'"

@@ -56,2 +56,3 @@ },

],
"setupTestFrameworkScriptFile": "<rootDir>/test/test-utils/matchers.ts",
"testMatch": [

@@ -65,6 +66,6 @@ "**/test/**/*.(js|ts)",

"<rootDir>/test/fixtures/",
"<rootDir>/test/preprocessor.js"
"<rootDir>/test/test-utils"
],
"transform": {
".(js|ts)": "<rootDir>/test/preprocessor.js"
".(js|ts)": "<rootDir>/test/test-utils/preprocessor.js"
},

@@ -71,0 +72,0 @@ "moduleFileExtensions": [

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

export class CompilerContext {
constructor(
public schema: GraphQLSchema,
public typesUsed: GraphQLType[],
public operations: { [operationName: string]: Operation },
public fragments: { [fragmentName: string]: Fragment },
public options: CompilerOptions
) {}
fragmentNamed(fragmentName: string): Fragment {
const fragment = this.fragments[fragmentName];
if (!fragment) {
throw new Error(`Cannot find fragment "${fragmentName}"`);
}
return fragment;
}
export interface CompilerContext {
schema: GraphQLSchema;
typesUsed: GraphQLType[];
operations: { [operationName: string]: Operation };
fragments: { [fragmentName: string]: Fragment };
options: CompilerOptions;
}

@@ -136,2 +126,3 @@

isConditional?: boolean;
selectionSet: SelectionSet;
}

@@ -166,5 +157,26 @@

for (const fragmentSpread of compiler.unresolvedFragmentSpreads) {
const fragment = fragments[fragmentSpread.fragmentName];
if (!fragment) {
throw new Error(`Cannot find fragment "${fragmentSpread.fragmentName}"`);
}
// Compute the intersection between the possiblew types of the fragment spread and the fragment.
const possibleTypes = fragment.selectionSet.possibleTypes.filter(type =>
fragmentSpread.selectionSet.possibleTypes.includes(type)
);
fragmentSpread.isConditional = fragment.selectionSet.possibleTypes.some(type =>
!fragmentSpread.selectionSet.possibleTypes.includes(type)
);
fragmentSpread.selectionSet = {
possibleTypes,
selections: fragment.selectionSet.selections
}
}
const typesUsed = compiler.typesUsed;
return new CompilerContext(schema, typesUsed, operations, fragments, options);
return { schema, typesUsed, operations, fragments, options };
}

@@ -177,2 +189,4 @@

unresolvedFragmentSpreads: FragmentSpread[] = [];
constructor(schema: GraphQLSchema, options: CompilerOptions) {

@@ -332,3 +346,2 @@ this.schema = schema;

return field;
break;
}

@@ -350,3 +363,2 @@ case Kind.INLINE_FRAGMENT: {

};
break;
}

@@ -358,7 +370,12 @@ case Kind.FRAGMENT_SPREAD: {

return {
const fragmentSpread: FragmentSpread = {
kind: 'FragmentSpread',
fragmentName
fragmentName,
selectionSet: {
possibleTypes,
selections: []
}
};
break;
this.unresolvedFragmentSpreads.push(fragmentSpread);
return fragmentSpread;
}

@@ -365,0 +382,0 @@ }

@@ -5,9 +5,8 @@ import { GraphQLSchema, GraphQLType, GraphQLObjectType, GraphQLCompositeType, DocumentNode } from 'graphql';

import { mergeInFragmentSpreads } from './visitors/mergeInFragmentSpreads';
import { collectFragmentsReferenced } from './visitors/collectFragmentsReferenced';
import { generateOperationId } from './visitors/generateOperationId';
import { TypeCase } from './visitors/typeCase';
import { collectAndMergeFields } from './visitors/collectAndMergeFields';
import { TypeCase } from './flattenIR';
import '../utilities/array';
import { generateOperationId } from './visitors/generateOperationId';

@@ -113,7 +112,7 @@ export interface CompilerOptions {

const { filePath, operationType, rootType, variables, source, selectionSet } = operation;
const fragmentsReferenced = collectFragmentsReferenced(this.context, selectionSet);
const fragmentsReferenced = collectFragmentsReferenced(selectionSet, this.context.fragments);
const { sourceWithFragments, operationId } = generateOperationId(
this.context,
operation,
this.context.fragments,
fragmentsReferenced

@@ -160,32 +159,29 @@ );

transformSelectionSetToLegacyIR(selectionSet: SelectionSet) {
const typeCase = new TypeCase(
this.options.mergeInFieldsFromFragmentSpreads
? mergeInFragmentSpreads(this.context, selectionSet)
: selectionSet
);
const typeCase = new TypeCase(selectionSet, this.options.mergeInFieldsFromFragmentSpreads);
const fields: LegacyField[] = this.transformFieldsToLegacyIR(typeCase.default.fields);
const fields: LegacyField[] = this.transformFieldsToLegacyIR(collectAndMergeFields(typeCase.default));
const inlineFragments: LegacyInlineFragment[] = typeCase.records
.filter(
record =>
// Filter out records that represent the same possible types as the default record.
!selectionSet.possibleTypes.every(type => record.possibleTypes.includes(type)) &&
// Filter out empty records for consistency with legacy compiler.
record.fieldMap.size > 0
const inlineFragments: LegacyInlineFragment[] = typeCase.variants.flatMap(variant => {
const fields = this.transformFieldsToLegacyIR(collectAndMergeFields(variant));
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
)
.flatMap(record => {
const fields = this.transformFieldsToLegacyIR(record.fields);
const fragmentSpreads: string[] = this.collectFragmentSpreads(selectionSet, record.possibleTypes).map(
(fragmentSpread: FragmentSpread) => fragmentSpread.fragmentName
);
return record.possibleTypes.map(possibleType => {
return {
typeCondition: possibleType,
possibleTypes: [possibleType],
fields,
fragmentSpreads
} as LegacyInlineFragment;
});
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;
});
});

@@ -210,11 +206,12 @@ for (const inlineFragment of inlineFragments) {

const { args, type, isConditional, description, isDeprecated, deprecationReason, selectionSet } = field;
const conditions = (field.conditions && field.conditions.length > 0)
? field.conditions.map(({ kind, variableName, inverted }) => {
return {
kind,
variableName,
inverted
};
})
: undefined;
const conditions =
field.conditions && field.conditions.length > 0
? field.conditions.map(({ kind, variableName, inverted }) => {
return {
kind,
variableName,
inverted
};
})
: undefined;
return {

@@ -257,4 +254,5 @@ responseName: field.alias || field.name,

return fragmentSpreads;
// Unique the fragment spreads before returning them.
return Array.from(new Set(fragmentSpreads));
}
}

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

import { CompilerContext, SelectionSet } from '../';
import { SelectionSet, Fragment } from '../';
export function collectFragmentsReferenced(
context: CompilerContext,
selectionSet: SelectionSet,
fragments: { [fragmentName: string]: Fragment },
fragmentsReferenced: Set<string> = new Set()

@@ -13,3 +13,3 @@ ): Set<string> {

const fragment = context.fragments[selection.fragmentName];
const fragment = fragments[selection.fragmentName];
if (!fragment) {

@@ -19,3 +19,3 @@ throw new Error(`Cannot find fragment "${selection.fragmentName}"`);

collectFragmentsReferenced(context, fragment.selectionSet, fragmentsReferenced);
collectFragmentsReferenced(fragment.selectionSet, fragments, fragmentsReferenced);
break;

@@ -26,3 +26,3 @@ case 'Field':

if (selection.selectionSet) {
collectFragmentsReferenced(context, selection.selectionSet, fragmentsReferenced);
collectFragmentsReferenced(selection.selectionSet, fragments, fragmentsReferenced);
}

@@ -29,0 +29,0 @@ break;

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

import { CompilerContext, Operation } from '../';
import { Operation, Fragment } from '../';
import { collectFragmentsReferenced } from './collectFragmentsReferenced';

@@ -6,8 +6,8 @@ import { createHash } from 'crypto';

export function generateOperationId(
context: CompilerContext,
operation: Operation,
fragmentsReferenced?: Iterable<string>,
fragments: { [fragmentName: string]: Fragment },
fragmentsReferenced?: Iterable<string>
) {
if (!fragmentsReferenced) {
fragmentsReferenced = collectFragmentsReferenced(context, operation.selectionSet);
fragmentsReferenced = collectFragmentsReferenced(operation.selectionSet, fragments);
}

@@ -18,3 +18,7 @@

...Array.from(fragmentsReferenced).map(fragmentName => {
return context.fragments[fragmentName].source;
const fragment = fragments[fragmentName];
if (!fragment) {
throw new Error(`Cannot find fragment "${fragmentName}"`);
}
return fragment.source;
})

@@ -21,0 +25,0 @@ ].join('\n');

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

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

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

) {
selections.push(...selection.selectionSet.selections);
selections.push(...inlineRedundantTypeConditions(selection.selectionSet).selections);
} else {

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

@@ -76,5 +76,15 @@ import {

const nValues = values.length;
values.forEach((value, i) =>
generator.printOnNewline(` "${value.value}"${i === nValues-1 ? ';' : ' |'}${wrap(' // ', value.description)}`)
);
values.forEach((value, i) => {
if (!value.description || value.description.indexOf('\n') === -1) {
generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}${wrap(' // ', value.description)}`)
} else {
if (value.description) {
value.description.split('\n')
.forEach(line => {
generator.printOnNewline(` // ${line.trim()}`);
})
}
generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}`)
}
});
generator.printNewline();

@@ -150,3 +160,3 @@ }

fields = fields.map(rootField => {
const fields = rootField.fields.map(field => {
const fields = rootField.fields && rootField.fields.map(field => {
if (field.fieldName === '__typename') {

@@ -153,0 +163,0 @@ return {

@@ -12,13 +12,5 @@ import {

import {
CompilerContext,
Operation,
Fragment,
SelectionSet,
Field,
TypeCondition,
FragmentSpread
} from '../compiler';
import { CompilerContext, Operation, Fragment, SelectionSet, Field } from '../compiler';
import { TypeCase } from '../compiler/flattenIR';
import { TypeCase } from '../compiler/visitors/typeCase';

@@ -32,6 +24,7 @@ import { join, wrap } from '../utilities/printing';

import { collectFragmentsReferenced } from '../compiler/visitors/collectFragmentsReferenced';
import { mergeInFragmentSpreads } from '../compiler/visitors/mergeInFragmentSpreads';
import { generateOperationId } from '../compiler/visitors/generateOperationId';
import { inlineRedundantTypeConditions } from '../compiler/visitors/inlineRedundantTypeConditions';
import { collectAndMergeFields } from '../compiler/visitors/collectAndMergeFields';
import '../utilities/array';
export interface Options {

@@ -113,6 +106,9 @@ namespace?: string;

const fragmentsReferenced = collectFragmentsReferenced(this.context, operation.selectionSet);
const fragmentsReferenced = collectFragmentsReferenced(
operation.selectionSet,
this.context.fragments
);
if (this.context.options.generateOperationIds) {
const { operationId } = generateOperationId(this.context, operation, fragmentsReferenced);
const { operationId } = generateOperationId(operation, this.context.fragments, fragmentsReferenced);
this.printNewlineIfNeeded();

@@ -203,2 +199,4 @@ this.printOnNewline(`public static let operationIdentifier: String? = "${operationId}"`);

) {
const typeCase = new TypeCase(selectionSet, this.context.options.mergeInFieldsFromFragmentSpreads);
this.structDeclaration({ structName, adoptedProtocols }, () => {

@@ -209,7 +207,5 @@ if (beforeClosure) {

const possibleTypes = selectionSet.possibleTypes;
this.printNewlineIfNeeded();
this.printOnNewline('public static let possibleTypes = [');
this.print(join(possibleTypes.map(type => `"${type.name}"`), ', '));
this.print(join(selectionSet.possibleTypes.map(type => `"${type.name}"`), ', '));
this.print(']');

@@ -219,3 +215,3 @@

this.printOnNewline('public static let selections: [GraphQLSelection] = ');
this.selectionSetInitialization(selectionSet);
this.typeCaseInitialization(typeCase);

@@ -235,22 +231,16 @@ this.printNewlineIfNeeded();

const typeCase = new TypeCase(
inlineRedundantTypeConditions(this.context, mergeInFragmentSpreads(this.context, selectionSet))
);
this.initializersForTypeCase(typeCase);
const fields = typeCase.default.fields.map(field => this.helpers.propertyFromField(field as Field));
const fields = collectAndMergeFields(
typeCase.default,
this.context.options.mergeInFieldsFromFragmentSpreads
).map(field => this.helpers.propertyFromField(field as Field));
const typeConditions = selectionSet.selections
.filter((selection): selection is TypeCondition => selection.kind === 'TypeCondition')
.map(this.helpers.propertyFromTypeCondition, this.helpers);
const variants = typeCase.variants.map(this.helpers.propertyFromVariant, this.helpers);
// FIXME: Remove cast to FragmentSpread[] when proper typings for filter() land in TypeScript
const fragmentSpreads = (selectionSet.selections.filter(
(selection): selection is FragmentSpread => selection.kind === 'FragmentSpread'
) as FragmentSpread[]).map(fragmentSpread => {
const fragment = this.context.fragmentNamed(fragmentSpread.fragmentName);
const fragmentSpreads = typeCase.default.fragmentSpreads.map(fragmentSpread => {
const isConditional = selectionSet.possibleTypes.some(
type => !fragment.selectionSet.possibleTypes.includes(type)
type => !fragmentSpread.selectionSet.possibleTypes.includes(type)
);
return this.helpers.propertyFromFragmentSpread(fragmentSpread, isConditional);

@@ -261,4 +251,2 @@ });

typeConditions.forEach(this.propertyDeclarationForTypeCondition, this);
if (fragmentSpreads.length > 0) {

@@ -277,13 +265,3 @@ this.printNewlineIfNeeded();

});
}
for (const typeCondition of typeConditions) {
this.structDeclarationForSelectionSet({
structName: typeCondition.structName,
adoptedProtocols: ['GraphQLFragment'],
selectionSet: typeCondition.selectionSet
});
}
if (fragmentSpreads.length > 0) {
this.structDeclaration(

@@ -329,2 +307,11 @@ {

for (const variant of variants) {
this.propertyDeclarationForVariant(variant);
this.structDeclarationForSelectionSet({
structName: variant.structName,
selectionSet: variant.selectionSet
});
}
for (const field of fields) {

@@ -342,6 +329,9 @@ if (isCompositeType(getNamedType(field.type)) && field.selectionSet) {

initializersForTypeCase(typeCase: TypeCase) {
const records = typeCase.records;
const variants = typeCase.variants;
const propertiesForFields = (fields: Field[], namespace?: string): (Field & Property)[] => {
return fields
const propertiesForSelectionSet = (
selectionSet: SelectionSet,
namespace?: string
): (Field & Property)[] => {
return collectAndMergeFields(selectionSet, true)
.filter(field => field.name != '__typename')

@@ -351,7 +341,7 @@ .map(field => this.helpers.propertyFromField(field, namespace));

if (records.length == 1 && records[0].possibleTypes.length == 1) {
if (variants.length == 0 && typeCase.default.possibleTypes.length == 1) {
this.printNewlineIfNeeded();
this.printOnNewline(`public init`);
const properties = propertiesForFields(records[0].fields);
const properties = propertiesForSelectionSet(typeCase.default);

@@ -366,3 +356,3 @@ this.parametersForProperties(properties);

[
`"__typename": "${records[0].possibleTypes[0]}"`,
`"__typename": "${typeCase.default.possibleTypes[0]}"`,
...properties.map(

@@ -380,10 +370,14 @@ ({ responseKey, propertyName }) =>

} else {
for (const record of records) {
const remainder = typeCase.remainder;
for (const variant of remainder ? [remainder, ...variants] : variants) {
const structName = this.scope.typeName;
for (const possibleType of record.possibleTypes) {
// FIXME: Make sure there is a struct for possibleType
const properties = propertiesForFields(
record.fields,
records.length > 1 ? this.helpers.structNameForTypeCondition(possibleType) : undefined
for (const possibleType of variant.possibleTypes) {
const properties = propertiesForSelectionSet(
{
possibleTypes: [possibleType],
selections: variant.selections
},
variant === remainder ? undefined : this.helpers.structNameForVariant(variant)
);

@@ -438,4 +432,9 @@

this.withinBlock(() => {
const snapshotTypeName = this.helpers.typeNameFromGraphQLType(type, 'Snapshot', isOptional);
let getter = `return (snapshot["${responseKey}"]! as! ${snapshotTypeName})`;
const snapshotTypeName = this.helpers.typeNameFromGraphQLType(type, 'Snapshot', false);
let getter;
if (isOptional) {
getter = `return (snapshot["${responseKey}"] as? ${snapshotTypeName})`;
} else {
getter = `return (snapshot["${responseKey}"] as! ${snapshotTypeName})`;
}
getter += this.helpers.mapExpressionForType(type, `${structName}(snapshot: $0)`);

@@ -454,3 +453,3 @@ this.printOnNewline(getter);

this.printOnNewline(
`return (snapshot["${responseKey}"]! as! Snapshot?).flatMap { ${structName}(snapshot: $0) }`
`return (snapshot["${responseKey}"] as! Snapshot?).flatMap { ${structName}(snapshot: $0) }`
);

@@ -475,3 +474,7 @@ } else {

this.withinBlock(() => {
this.printOnNewline(`return snapshot["${responseKey}"]! as! ${typeName}`);
if (isOptional) {
this.printOnNewline(`return snapshot["${responseKey}"] as? ${typeName.slice(0, -1)}`);
} else {
this.printOnNewline(`return snapshot["${responseKey}"]! as! ${typeName}`);
}
});

@@ -486,4 +489,4 @@ this.printOnNewline('set');

propertyDeclarationForTypeCondition(typeCondition: TypeCondition & Property & Struct) {
const { propertyName, typeName, structName } = typeCondition;
propertyDeclarationForVariant(variant: Property & Struct) {
const { propertyName, typeName, structName } = variant;

@@ -530,2 +533,30 @@ this.printNewlineIfNeeded();

typeCaseInitialization(typeCase: TypeCase) {
if (typeCase.variants.length < 1) {
this.selectionSetInitialization(typeCase.default);
return;
}
this.print('[');
this.withIndent(() => {
this.printOnNewline(`GraphQLTypeCase(`);
this.withIndent(() => {
this.printOnNewline(`variants: [`);
this.print(
typeCase.variants
.flatMap(variant => {
const structName = this.helpers.structNameForVariant(variant);
return variant.possibleTypes.map(type => `"${type}": ${structName}.selections`);
})
.join(', ')
);
this.print('],');
this.printOnNewline(`default: `);
this.selectionSetInitialization(typeCase.default);
});
this.printOnNewline(')');
});
this.printOnNewline(']');
}
selectionSetInitialization(selectionSet: SelectionSet) {

@@ -558,12 +589,2 @@ this.print('[');

}
case 'TypeCondition': {
const structName = this.helpers.structNameForTypeCondition(selection.type);
this.printOnNewline(`GraphQLFragmentSpread(${structName}.self),`);
break;
}
case 'FragmentSpread': {
const structName = this.helpers.structNameForFragmentName(selection.fragmentName);
this.printOnNewline(`GraphQLFragmentSpread(${structName}.self),`);
break;
}
case 'BooleanCondition':

@@ -584,2 +605,25 @@ this.printOnNewline(`GraphQLBooleanCondition(`);

break;
case 'TypeCondition': {
this.printOnNewline(`GraphQLTypeCondition(`);
this.print(
join(
[
`possibleTypes: [${join(
selection.selectionSet.possibleTypes.map(type => `"${type.name}"`),
', '
)}]`,
'selections: '
],
', '
)
);
this.selectionSetInitialization(selection.selectionSet);
this.print('),');
break;
}
case 'FragmentSpread': {
const structName = this.helpers.structNameForFragmentName(selection.fragmentName);
this.printOnNewline(`GraphQLFragmentSpread(${structName}.self),`);
break;
}
}

@@ -586,0 +630,0 @@ }

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

GraphQLInputField,
GraphQLCompositeType
} from 'graphql';

@@ -25,5 +24,3 @@

import { Field, TypeCondition, FragmentSpread } from '../compiler';
import { CompilerOptions, Argument } from '../compiler';
import { CompilerOptions, SelectionSet, Field, FragmentSpread, Argument } from '../compiler';
import { isMetaFieldName } from "../utilities/graphql";

@@ -82,3 +79,3 @@

} else if (isCompositeType(type)) {
return `.object(${structName}.self)`;
return `.object(${structName}.selections)`;
} else {

@@ -107,4 +104,4 @@ throw new Error(`Unknown field type: ${type}`);

structNameForTypeCondition(type: GraphQLCompositeType) {
return 'As' + pascalCase(type.name);
structNameForVariant(variant: SelectionSet) {
return 'As' + variant.possibleTypes.map(type => pascalCase(type.name)).join('Or');
}

@@ -144,10 +141,11 @@

propertyFromTypeCondition(typeCondition: TypeCondition): TypeCondition & Property & Struct {
const structName = this.structNameForTypeCondition(typeCondition.type);
propertyFromVariant(variant: SelectionSet): { selectionSet: SelectionSet } & Property & Struct {
const structName = this.structNameForVariant(variant);
return Object.assign({}, typeCondition, {
return {
propertyName: camelCase(structName),
typeName: structName + '?',
structName
});
structName,
selectionSet: variant
};
}

@@ -179,3 +177,3 @@

if (value.kind === 'Variable') {
return `Variable("${value.variableName}")`;
return `GraphQLVariable("${value.variableName}")`;
} else if (Array.isArray(value)) {

@@ -182,0 +180,0 @@ return wrap('[', join(value.map(expressionFromValue), ', '), ']');

@@ -78,5 +78,15 @@ import { LegacyCompilerContext, LegacyInlineFragment, LegacyFragment, LegacyField, LegacyOperation } from '../compiler/legacyIR';

const nValues = values.length;
values.forEach((value, i) =>
generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}${wrap(' // ', value.description)}`)
);
values.forEach((value, i) => {
if (!value.description || value.description.indexOf('\n') === -1) {
generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}${wrap(' // ', value.description)}`)
} else {
if (value.description) {
value.description.split('\n')
.forEach(line => {
generator.printOnNewline(` // ${line.trim()}`);
})
}
generator.printOnNewline(` "${value.value}"${i === nValues - 1 ? ';' : ' |'}`)
}
});
generator.printNewline();

@@ -83,0 +93,0 @@ }

@@ -5,3 +5,3 @@ export {};

interface Array<T> {
flatMap<U>(callbackfn: (value: T, index: number, array: T[]) => U[], thisArg?: any): U[];
flatMap<U>(callbackfn: (value: T, index: number, array: T[]) => U[] | undefined, thisArg?: any): U[];
}

@@ -8,0 +8,0 @@ }

@@ -27,3 +27,3 @@ import {

...(target === 'swift' ? [NoExplicitTypename] : []),
...specifiedRules.filter(rule => specifiedRulesToBeRemoved.includes(rule))
...specifiedRules.filter(rule => !specifiedRulesToBeRemoved.includes(rule))
];

@@ -30,0 +30,0 @@

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