node_modules.apollo-codegen.src.swift.helpers.ts Maven / Gradle / Ivy
import {
GraphQLType,
GraphQLString,
GraphQLInt,
GraphQLFloat,
GraphQLBoolean,
GraphQLID,
GraphQLList,
GraphQLNonNull,
GraphQLScalarType,
GraphQLEnumType,
isCompositeType,
getNamedType,
GraphQLInputField
} from 'graphql';
import { camelCase, pascalCase } from 'change-case';
import * as Inflector from 'inflected';
import { join, wrap } from '../utilities/printing';
import { Property, Struct } from './language';
import { CompilerOptions, SelectionSet, Field, FragmentSpread, Argument } from '../compiler';
import { isMetaFieldName } from '../utilities/graphql';
import { Variant } from '../compiler/visitors/typeCase';
import { collectAndMergeFields } from '../compiler/visitors/collectAndMergeFields';
const builtInScalarMap = {
[GraphQLString.name]: 'String',
[GraphQLInt.name]: 'Int',
[GraphQLFloat.name]: 'Double',
[GraphQLBoolean.name]: 'Bool',
[GraphQLID.name]: 'GraphQLID'
};
export class Helpers {
constructor(public options: CompilerOptions) {}
// Types
typeNameFromGraphQLType(type: GraphQLType, unmodifiedTypeName?: string, isOptional?: boolean): string {
if (type instanceof GraphQLNonNull) {
return this.typeNameFromGraphQLType(type.ofType, unmodifiedTypeName, false);
} else if (isOptional === undefined) {
isOptional = true;
}
let typeName;
if (type instanceof GraphQLList) {
typeName = '[' + this.typeNameFromGraphQLType(type.ofType, unmodifiedTypeName) + ']';
} else if (type instanceof GraphQLScalarType) {
typeName = this.typeNameForScalarType(type);
} else {
typeName = unmodifiedTypeName || type.name;
}
return isOptional ? typeName + '?' : typeName;
}
typeNameForScalarType(type: GraphQLScalarType): string {
return (
builtInScalarMap[type.name] ||
(this.options.passthroughCustomScalars
? this.options.customScalarsPrefix + type.name
: GraphQLString.name)
);
}
fieldTypeEnum(type: GraphQLType, structName: string): string {
if (type instanceof GraphQLNonNull) {
return `.nonNull(${this.fieldTypeEnum(type.ofType, structName)})`;
} else if (type instanceof GraphQLList) {
return `.list(${this.fieldTypeEnum(type.ofType, structName)})`;
} else if (type instanceof GraphQLScalarType) {
return `.scalar(${this.typeNameForScalarType(type)}.self)`;
} else if (type instanceof GraphQLEnumType) {
return `.scalar(${type.name}.self)`;
} else if (isCompositeType(type)) {
return `.object(${structName}.selections)`;
} else {
throw new Error(`Unknown field type: ${type}`);
}
}
// Names
enumCaseName(name: string) {
return camelCase(name);
}
enumDotCaseName(name: string) {
return `.${camelCase(name)}`;
}
operationClassName(name: string) {
return pascalCase(name);
}
structNameForPropertyName(propertyName: string) {
return pascalCase(Inflector.singularize(propertyName));
}
structNameForFragmentName(fragmentName: string) {
return pascalCase(fragmentName);
}
structNameForVariant(variant: SelectionSet) {
return 'As' + variant.possibleTypes.map(type => pascalCase(type.name)).join('Or');
}
// Properties
propertyFromField(field: Field, namespace?: string): Field & Property & Struct {
const { responseKey, isConditional } = field;
const propertyName = isMetaFieldName(responseKey) ? responseKey : camelCase(responseKey);
const structName = join([namespace, this.structNameForPropertyName(responseKey)], '.');
let type = field.type;
if (isConditional && type instanceof GraphQLNonNull) {
type = type.ofType;
}
const isOptional = !(type instanceof GraphQLNonNull);
const unmodifiedType = getNamedType(field.type);
const unmodifiedTypeName = isCompositeType(unmodifiedType) ? structName : unmodifiedType.name;
const typeName = this.typeNameFromGraphQLType(type, unmodifiedTypeName);
return Object.assign({}, field, {
responseKey,
propertyName,
typeName,
structName,
isOptional
});
}
propertyFromVariant(variant: Variant): Variant & Property & Struct {
const structName = this.structNameForVariant(variant);
return Object.assign(variant, {
propertyName: camelCase(structName),
typeName: structName + '?',
structName
});
}
propertyFromFragmentSpread(
fragmentSpread: FragmentSpread,
isConditional: boolean
): FragmentSpread & Property & Struct {
const structName = this.structNameForFragmentName(fragmentSpread.fragmentName);
return Object.assign({}, fragmentSpread, {
propertyName: camelCase(fragmentSpread.fragmentName),
typeName: isConditional ? structName + '?' : structName,
structName,
isConditional
});
}
propertyFromInputField(field: GraphQLInputField) {
return Object.assign({}, field, {
propertyName: camelCase(field.name),
typeName: this.typeNameFromGraphQLType(field.type),
isOptional: !(field.type instanceof GraphQLNonNull)
});
}
propertiesForSelectionSet(
selectionSet: SelectionSet,
namespace?: string
): (Field & Property & Struct)[] | undefined {
const properties = collectAndMergeFields(selectionSet, true)
.filter(field => field.name !== '__typename')
.map(field => this.propertyFromField(field, namespace));
// If we're not merging in fields from fragment spreads, there is no guarantee there will a generated
// type for a composite field, so to avoid compiler errors we skip the initializer for now.
if (
selectionSet.selections.some(selection => selection.kind === 'FragmentSpread') &&
properties.some(property => isCompositeType(getNamedType(property.type)))
) {
return undefined;
}
return properties;
}
// Expressions
dictionaryLiteralForFieldArguments(args: Argument[]) {
function expressionFromValue(value: any): string {
if (value.kind === 'Variable') {
return `GraphQLVariable("${value.variableName}")`;
} else if (Array.isArray(value)) {
return wrap('[', join(value.map(expressionFromValue), ', '), ']');
} else if (typeof value === 'object') {
return wrap(
'[',
join(
Object.entries(value).map(([key, value]) => {
return `"${key}": ${expressionFromValue(value)}`;
}),
', '
) || ':',
']'
);
} else {
return JSON.stringify(value);
}
}
return wrap(
'[',
join(
args.map(arg => {
return `"${arg.name}": ${expressionFromValue(arg.value)}`;
}),
', '
) || ':',
']'
);
}
mapExpressionForType(
type: GraphQLType,
isConditional: boolean = false,
makeExpression: (expression: string) => string,
expression: string,
inputTypeName: string,
outputTypeName: string
): string {
let isOptional;
if (type instanceof GraphQLNonNull) {
isOptional = !!isConditional;
type = type.ofType;
} else {
isOptional = true;
}
if (type instanceof GraphQLList) {
const elementType = type.ofType;
if (isOptional) {
return `${expression}.flatMap { ${makeClosureSignature(
this.typeNameFromGraphQLType(type, inputTypeName, false),
this.typeNameFromGraphQLType(type, outputTypeName, false)
)} value.map { ${makeClosureSignature(
this.typeNameFromGraphQLType(elementType, inputTypeName),
this.typeNameFromGraphQLType(elementType, outputTypeName)
)} ${this.mapExpressionForType(
elementType,
undefined,
makeExpression,
'value',
inputTypeName,
outputTypeName
)} } }`;
} else {
return `${expression}.map { ${makeClosureSignature(
this.typeNameFromGraphQLType(elementType, inputTypeName),
this.typeNameFromGraphQLType(elementType, outputTypeName)
)} ${this.mapExpressionForType(
elementType,
undefined,
makeExpression,
'value',
inputTypeName,
outputTypeName
)} }`;
}
} else if (isOptional) {
return `${expression}.flatMap { ${makeClosureSignature(
this.typeNameFromGraphQLType(type, inputTypeName, false),
this.typeNameFromGraphQLType(type, outputTypeName, false)
)} ${makeExpression('value')} }`;
} else {
return makeExpression(expression);
}
}
}
function makeClosureSignature(parameterTypeName: string, returnTypeName?: string) {
let closureSignature = `(value: ${parameterTypeName})`;
if (returnTypeName) {
closureSignature += ` -> ${returnTypeName}`;
}
closureSignature += ' in';
return closureSignature;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy