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.4 to 0.17.0-alpha.5

2

lib/compiler/legacyIR.js

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

transformSelectionSetToLegacyIR(selectionSet) {
const typeCase = new typeCase_1.TypeCase(selectionSet, this.options.mergeInFieldsFromFragmentSpreads);
const typeCase = typeCase_1.typeCaseForSelectionSet(selectionSet, this.options.mergeInFieldsFromFragmentSpreads);
const fields = this.transformFieldsToLegacyIR(collectAndMergeFields_1.collectAndMergeFields(typeCase.default, false));

@@ -61,0 +61,0 @@ const inlineFragments = typeCase.variants.flatMap(variant => {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function collectAndMergeFields(selectionSet, mergeInFragmentSpreads = true) {
const fieldMap = new Map();
const groupedFields = new Map();
function visitSelectionSet(selections, possibleTypes, conditions = []) {

@@ -11,25 +11,13 @@ if (possibleTypes.length < 1)

case 'Field':
const field = selection;
const existingField = fieldMap.get(field.responseKey);
if (existingField) {
existingField.isConditional = existingField.isConditional && conditions.length > 0;
if (existingField.conditions && conditions.length > 0) {
existingField.conditions = [...existingField.conditions, ...conditions];
}
if (field.selectionSet && existingField.selectionSet) {
existingField.selectionSet.selections.push(...wrapInBooleanConditionsIfNeeded(field.selectionSet.selections, conditions));
}
let groupForResponseKey = groupedFields.get(selection.responseKey);
if (!groupForResponseKey) {
groupForResponseKey = [];
groupedFields.set(selection.responseKey, groupForResponseKey);
}
else {
const clonedField = Object.assign({}, field, { selectionSet: field.selectionSet
? {
possibleTypes: field.selectionSet.possibleTypes,
selections: [
...wrapInBooleanConditionsIfNeeded(field.selectionSet.selections, conditions)
]
}
: undefined });
clonedField.isConditional = conditions.length > 0;
fieldMap.set(field.responseKey, Object.assign({}, clonedField, { conditions }));
}
groupForResponseKey.push(Object.assign({}, selection, { isConditional: conditions.length > 0, conditions, selectionSet: selection.selectionSet
? {
possibleTypes: selection.selectionSet.possibleTypes,
selections: [...selection.selectionSet.selections]
}
: undefined }));
break;

@@ -51,13 +39,36 @@ case 'FragmentSpread':

visitSelectionSet(selectionSet.selections, selectionSet.possibleTypes);
const fields = Array.from(groupedFields.values()).map(fields => {
const isFieldIncludedUnconditionally = fields.some(field => !field.isConditional);
return fields
.map(field => {
if (isFieldIncludedUnconditionally && field.isConditional && field.selectionSet) {
field.selectionSet.selections = wrapInBooleanConditionsIfNeeded(field.selectionSet.selections, field.conditions);
}
return field;
})
.reduce((field, otherField) => {
field.isConditional = field.isConditional && otherField.isConditional;
if (field.conditions && otherField.conditions) {
field.conditions = [...field.conditions, ...otherField.conditions];
}
else {
field.conditions = undefined;
}
if (field.selectionSet && otherField.selectionSet) {
field.selectionSet.selections.push(...otherField.selectionSet.selections);
}
return field;
});
});
if (selectionSet.possibleTypes.length == 1) {
const type = selectionSet.possibleTypes[0];
const fieldDefMap = type.getFields();
for (const [responseKey, field] of fieldMap) {
for (const field of fields) {
const fieldDef = fieldDefMap[field.name];
if (fieldDef && fieldDef.description) {
fieldMap.set(responseKey, Object.assign({}, field, { description: fieldDef.description }));
field.description = fieldDef.description;
}
}
}
return Array.from(fieldMap.values());
return fields;
}

@@ -64,0 +75,0 @@ exports.collectAndMergeFields = collectAndMergeFields;

@@ -16,12 +16,65 @@ "use strict";

exports.Variant = Variant;
function typeCaseForSelectionSet(selectionSet, mergeInFragmentSpreads = true) {
const typeCase = new TypeCase(selectionSet.possibleTypes);
for (const selection of selectionSet.selections) {
switch (selection.kind) {
case 'Field':
for (const variant of typeCase.disjointVariantsFor(selectionSet.possibleTypes)) {
variant.selections.push(selection);
}
break;
case 'FragmentSpread':
for (const variant of typeCase.disjointVariantsFor(selectionSet.possibleTypes)) {
variant.fragmentSpreads.push(selection);
if (!mergeInFragmentSpreads) {
variant.selections.push(selection);
}
}
if (mergeInFragmentSpreads) {
for (const { possibleTypes, selections } of typeCaseForSelectionSet({
possibleTypes: selectionSet.possibleTypes.filter(type => selection.selectionSet.possibleTypes.includes(type)),
selections: selection.selectionSet.selections
}).defaultAndVariants) {
if (selections.length < 1)
continue;
for (const variant of typeCase.disjointVariantsFor(possibleTypes)) {
variant.selections.push(...selections);
}
}
}
break;
case 'TypeCondition':
for (const { possibleTypes, selections } of typeCaseForSelectionSet({
possibleTypes: selectionSet.possibleTypes.filter(type => selection.selectionSet.possibleTypes.includes(type)),
selections: selection.selectionSet.selections
}).defaultAndVariants) {
if (selections.length < 1)
continue;
for (const variant of typeCase.disjointVariantsFor(possibleTypes)) {
variant.selections.push(...selections);
}
}
break;
case 'BooleanCondition':
for (const { possibleTypes, selections } of typeCaseForSelectionSet(selection.selectionSet)
.defaultAndVariants) {
for (const variant of typeCase.disjointVariantsFor(possibleTypes)) {
if (selections.length < 1)
continue;
variant.selections.push(Object.assign({}, selection, { selectionSet: { possibleTypes: variant.possibleTypes, selections } }));
}
}
break;
}
}
return typeCase;
}
exports.typeCaseForSelectionSet = typeCaseForSelectionSet;
class TypeCase {
constructor(selectionSet, mergeInFragmentSpreads = true) {
this.mergeInFragmentSpreads = mergeInFragmentSpreads;
this.default = new Variant(selectionSet.possibleTypes);
this.variantsByType = new Map();
this.visitSelectionSet(selectionSet.selections, selectionSet.possibleTypes);
}
get variants() {
return Array.from(new Set(this.variantsByType.values()));
}
get defaultAndVariants() {
return [this.default, ...this.variants];
}
get remainder() {

@@ -38,3 +91,3 @@ if (this.default.possibleTypes.some(type => !this.variantsByType.has(type))) {

if (remainder) {
return [...this.variants, remainder];
return [remainder, ...this.variants];
}

@@ -45,33 +98,7 @@ else {

}
visitSelectionSet(selections, possibleTypes, conditions = []) {
if (possibleTypes.length < 1)
return;
for (const selection of selections) {
switch (selection.kind) {
case 'Field':
for (const variant of this.variantsFor(possibleTypes)) {
variant.selections.push(...collectAndMergeFields_1.wrapInBooleanConditionsIfNeeded([selection], conditions));
}
break;
case 'FragmentSpread':
for (const variant of this.variantsFor(possibleTypes)) {
variant.fragmentSpreads.push(selection);
if (!this.mergeInFragmentSpreads) {
variant.selections.push(...collectAndMergeFields_1.wrapInBooleanConditionsIfNeeded([selection], conditions));
}
}
if (this.mergeInFragmentSpreads) {
this.visitSelectionSet(selection.selectionSet.selections, possibleTypes.filter(type => selection.selectionSet.possibleTypes.includes(type)), conditions);
}
break;
case 'TypeCondition':
this.visitSelectionSet(selection.selectionSet.selections, possibleTypes.filter(type => selection.selectionSet.possibleTypes.includes(type)), conditions);
break;
case 'BooleanCondition':
this.visitSelectionSet(selection.selectionSet.selections, possibleTypes, [...conditions, selection]);
break;
}
}
constructor(possibleTypes) {
this.default = new Variant(possibleTypes);
this.variantsByType = new Map();
}
variantsFor(possibleTypes) {
disjointVariantsFor(possibleTypes) {
const variants = [];

@@ -78,0 +105,0 @@ const matchesDefault = this.default.possibleTypes.every(type => possibleTypes.includes(type));

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

@@ -9,2 +8,3 @@ const language_1 = require("./language");

const graphql_2 = require("../utilities/graphql");
const typeCase_1 = require("../compiler/visitors/typeCase");
const collectFragmentsReferenced_1 = require("../compiler/visitors/collectFragmentsReferenced");

@@ -124,3 +124,3 @@ const generateOperationId_1 = require("../compiler/visitors/generateOperationId");

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

@@ -127,0 +127,0 @@ if (beforeClosure) {

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

@@ -5,0 +5,0 @@ "main": "./lib/index.js",

@@ -7,3 +7,3 @@ import { GraphQLSchema, GraphQLType, GraphQLObjectType, GraphQLCompositeType, DocumentNode } from 'graphql';

import { generateOperationId } from './visitors/generateOperationId';
import { TypeCase } from './visitors/typeCase';
import { typeCaseForSelectionSet } from './visitors/typeCase';
import { collectAndMergeFields } from './visitors/collectAndMergeFields';

@@ -158,3 +158,3 @@

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

@@ -161,0 +161,0 @@ const fields: LegacyField[] = this.transformFieldsToLegacyIR(collectAndMergeFields(typeCase.default, false));

@@ -16,3 +16,3 @@ import { SelectionSet, Selection, Field, BooleanCondition } from '../';

): Field[] {
const fieldMap: Map<string, Field> = new Map();
const groupedFields: Map<string, Field[]> = new Map();

@@ -29,38 +29,20 @@ function visitSelectionSet(

case 'Field':
const field = selection;
const existingField = fieldMap.get(field.responseKey);
if (existingField) {
existingField.isConditional = existingField.isConditional && conditions.length > 0;
// FIXME: This is strictly taken incorrect, because the conditions should be ORed
// These conditions are only used in Android target however,
// and there is now way to express this in the legacy IR.
if (existingField.conditions && conditions.length > 0) {
existingField.conditions = [...existingField.conditions, ...conditions];
}
if (field.selectionSet && existingField.selectionSet) {
existingField.selectionSet.selections.push(
...wrapInBooleanConditionsIfNeeded(field.selectionSet.selections, conditions)
);
}
} else {
// Make sure to deep clone selections to avoid modifying the original field
// TODO: Should we use an object freezing / immutability solution?
const clonedField = {
...field,
selectionSet: field.selectionSet
? {
possibleTypes: field.selectionSet.possibleTypes,
selections: [
...wrapInBooleanConditionsIfNeeded(field.selectionSet.selections, conditions)
]
}
: undefined
};
clonedField.isConditional = conditions.length > 0;
fieldMap.set(field.responseKey, { ...clonedField, conditions });
let groupForResponseKey = groupedFields.get(selection.responseKey);
if (!groupForResponseKey) {
groupForResponseKey = [];
groupedFields.set(selection.responseKey, groupForResponseKey);
}
// Make sure to deep clone selections to avoid modifying the original field
// TODO: Should we use an object freezing / immutability solution?
groupForResponseKey.push({
...selection,
isConditional: conditions.length > 0,
conditions,
selectionSet: selection.selectionSet
? {
possibleTypes: selection.selectionSet.possibleTypes,
selections: [...selection.selectionSet.selections]
}
: undefined
});
break;

@@ -74,7 +56,3 @@ case 'FragmentSpread':

visitSelectionSet(
selection.selectionSet.selections,
possibleTypes,
conditions
);
visitSelectionSet(selection.selectionSet.selections, possibleTypes, conditions);
break;

@@ -90,2 +68,37 @@ case 'BooleanCondition':

// Merge selection sets
const fields = Array.from(groupedFields.values()).map(fields => {
const isFieldIncludedUnconditionally = fields.some(field => !field.isConditional);
return fields
.map(field => {
if (isFieldIncludedUnconditionally && field.isConditional && field.selectionSet) {
field.selectionSet.selections = wrapInBooleanConditionsIfNeeded(
field.selectionSet.selections,
field.conditions
);
}
return field;
})
.reduce((field, otherField) => {
field.isConditional = field.isConditional && otherField.isConditional;
// FIXME: This is strictly taken incorrect, because the conditions should be ORed
// These conditions are only used in Android target however,
// and there is now way to express this in the legacy IR.
if (field.conditions && otherField.conditions) {
field.conditions = [...field.conditions, ...otherField.conditions];
} else {
field.conditions = undefined;
}
if (field.selectionSet && otherField.selectionSet) {
field.selectionSet.selections.push(...otherField.selectionSet.selections);
}
return field;
});
});
// Replace field descriptions with type-specific descriptions if possible

@@ -96,7 +109,7 @@ if (selectionSet.possibleTypes.length == 1) {

for (const [responseKey, field] of fieldMap) {
for (const field of fields) {
const fieldDef = fieldDefMap[field.name];
if (fieldDef && fieldDef.description) {
fieldMap.set(responseKey, { ...field, description: fieldDef.description });
field.description = fieldDef.description;
}

@@ -106,3 +119,3 @@ }

return Array.from(fieldMap.values());
return fields;
}

@@ -109,0 +122,0 @@

@@ -5,4 +5,4 @@ import { inspect } from 'util';

import { SelectionSet, Selection, FragmentSpread, BooleanCondition } from '../';
import { collectAndMergeFields, wrapInBooleanConditionsIfNeeded } from './collectAndMergeFields';
import { SelectionSet, Selection, FragmentSpread } from '../';
import { collectAndMergeFields } from './collectAndMergeFields';

@@ -23,2 +23,67 @@ export class Variant implements SelectionSet {

export function typeCaseForSelectionSet(
selectionSet: SelectionSet,
mergeInFragmentSpreads: boolean = true
): TypeCase {
const typeCase = new TypeCase(selectionSet.possibleTypes);
for (const selection of selectionSet.selections) {
switch (selection.kind) {
case 'Field':
for (const variant of typeCase.disjointVariantsFor(selectionSet.possibleTypes)) {
variant.selections.push(selection);
}
break;
case 'FragmentSpread':
for (const variant of typeCase.disjointVariantsFor(selectionSet.possibleTypes)) {
variant.fragmentSpreads.push(selection);
if (!mergeInFragmentSpreads) {
variant.selections.push(selection);
}
}
if (mergeInFragmentSpreads) {
for (const { possibleTypes, selections } of typeCaseForSelectionSet({
possibleTypes: selectionSet.possibleTypes.filter(type =>
selection.selectionSet.possibleTypes.includes(type)
),
selections: selection.selectionSet.selections
}).defaultAndVariants) {
if (selections.length < 1) continue;
for (const variant of typeCase.disjointVariantsFor(possibleTypes)) {
variant.selections.push(...selections);
}
}
}
break;
case 'TypeCondition':
for (const { possibleTypes, selections } of typeCaseForSelectionSet({
possibleTypes: selectionSet.possibleTypes.filter(type =>
selection.selectionSet.possibleTypes.includes(type)
),
selections: selection.selectionSet.selections
}).defaultAndVariants) {
if (selections.length < 1) continue;
for (const variant of typeCase.disjointVariantsFor(possibleTypes)) {
variant.selections.push(...selections);
}
}
break;
case 'BooleanCondition':
for (const { possibleTypes, selections } of typeCaseForSelectionSet(selection.selectionSet)
.defaultAndVariants) {
for (const variant of typeCase.disjointVariantsFor(possibleTypes)) {
if (selections.length < 1) continue;
variant.selections.push({
...selection,
selectionSet: { possibleTypes: variant.possibleTypes, selections }
});
}
}
break;
}
}
return typeCase;
}
export class TypeCase {

@@ -33,2 +98,6 @@ default: Variant;

get defaultAndVariants(): Variant[] {
return [this.default, ...this.variants];
}
get remainder(): Variant | undefined {

@@ -49,3 +118,3 @@ if (this.default.possibleTypes.some(type => !this.variantsByType.has(type))) {

if (remainder) {
return [...this.variants, remainder];
return [remainder, ...this.variants];
} else {

@@ -56,61 +125,13 @@ return this.variants;

constructor(selectionSet: SelectionSet, private mergeInFragmentSpreads: boolean = true) {
constructor(possibleTypes: GraphQLObjectType[]) {
// We start out with a single default variant that represents all possible types of the selection set.
this.default = new Variant(selectionSet.possibleTypes);
this.default = new Variant(possibleTypes);
this.variantsByType = new Map();
this.visitSelectionSet(selectionSet.selections, selectionSet.possibleTypes);
}
private visitSelectionSet(
selections: Selection[],
possibleTypes: GraphQLObjectType[],
conditions: BooleanCondition[] = []
) {
if (possibleTypes.length < 1) return;
for (const selection of selections) {
switch (selection.kind) {
case 'Field':
// Add the field to all variants for the currently possible types.
for (const variant of this.variantsFor(possibleTypes)) {
variant.selections.push(...wrapInBooleanConditionsIfNeeded([selection], conditions));
}
break;
case 'FragmentSpread':
// Add the fragment spread to all variants variants for the currently possible types.
for (const variant of this.variantsFor(possibleTypes)) {
variant.fragmentSpreads.push(selection);
if (!this.mergeInFragmentSpreads) {
variant.selections.push(...wrapInBooleanConditionsIfNeeded([selection], conditions));
}
}
if (this.mergeInFragmentSpreads) {
this.visitSelectionSet(
selection.selectionSet.selections,
possibleTypes.filter(type => selection.selectionSet.possibleTypes.includes(type)),
conditions
);
}
break;
case 'TypeCondition':
this.visitSelectionSet(
selection.selectionSet.selections,
possibleTypes.filter(type => selection.selectionSet.possibleTypes.includes(type)),
conditions
);
break;
case 'BooleanCondition':
this.visitSelectionSet(selection.selectionSet.selections, possibleTypes, [...conditions, selection]);
break;
}
}
}
// Returns records representing a set of possible types, making sure they are disjoint with other possible types.
// That may involve refining the existing partition (https://en.wikipedia.org/wiki/Partition_refinement)
// with the passed in set of possible types.
private variantsFor(possibleTypes: GraphQLObjectType[]): Variant[] {
disjointVariantsFor(possibleTypes: GraphQLObjectType[]): Variant[] {
const variants: Variant[] = [];

@@ -117,0 +138,0 @@

@@ -14,4 +14,2 @@ import {

import { TypeCase } from '../compiler/visitors/typeCase';
import { join, wrap } from '../utilities/printing';

@@ -23,2 +21,3 @@

import { typeCaseForSelectionSet, TypeCase } from '../compiler/visitors/typeCase';
import { collectFragmentsReferenced } from '../compiler/visitors/collectFragmentsReferenced';

@@ -198,3 +197,3 @@ import { generateOperationId } from '../compiler/visitors/generateOperationId';

) {
const typeCase = new TypeCase(selectionSet, this.context.options.mergeInFieldsFromFragmentSpreads);
const typeCase = typeCaseForSelectionSet(selectionSet, this.context.options.mergeInFieldsFromFragmentSpreads);

@@ -201,0 +200,0 @@ this.structDeclaration({ structName, adoptedProtocols }, () => {

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