UNPKG

@aws-amplify/graphql-types-generator

Version:

Generate API code or type annotations based on a GraphQL schema and statements

344 lines 16.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.pickedPropertyDeclarations = exports.propertyFromField = exports.propertiesFromFields = exports.interfaceDeclarationForFragment = exports.interfaceDeclarationForOperation = exports.updateTypeNameField = exports.interfaceVariablesDeclarationForOperation = exports.interfaceVariablesNameFromOperation = exports.interfaceNameFromOperation = exports.typeDeclarationForGraphQLType = exports.generateSource = void 0; const graphql_1 = require("graphql"); const printing_1 = require("../utilities/printing"); const CodeGenerator_1 = require("../utilities/CodeGenerator"); const language_1 = require("./language"); const types_1 = require("./types"); function generateSource(context) { const generator = new CodeGenerator_1.CodeGenerator(context); generator.printOnNewline('/* tslint:disable */'); generator.printOnNewline('/* eslint-disable */'); generator.printOnNewline('// This file was automatically generated and should not be edited.'); context.typesUsed.forEach(type => typeDeclarationForGraphQLType(generator, type)); Object.values(context.operations).forEach(operation => { interfaceVariablesDeclarationForOperation(generator, operation); interfaceDeclarationForOperation(generator, operation); }); Object.values(context.fragments).forEach(operation => interfaceDeclarationForFragment(generator, operation)); generator.printNewline(); return generator.output; } exports.generateSource = generateSource; function typeDeclarationForGraphQLType(generator, type) { if ((0, graphql_1.isEnumType)(type)) { enumerationDeclaration(generator, type); } else if ((0, graphql_1.isUnionType)(type)) { unionDeclaration(generator, type); } else if ((0, graphql_1.isInputObjectType)(type)) { structDeclarationForInputObjectType(generator, type); } else if ((0, graphql_1.isObjectType)(type)) { structDeclarationForObjectType(generator, type); } else if ((0, graphql_1.isInterfaceType)(type)) { structDeclarationForInterfaceType(generator, type); } } exports.typeDeclarationForGraphQLType = typeDeclarationForGraphQLType; function enumerationDeclaration(generator, type) { const { name, description } = type; const values = type.getValues(); generator.printNewlineIfNeeded(); if (description) { description.split('\n').forEach(line => { generator.printOnNewline(`// ${line.trim()}`); }); } generator.printOnNewline(`export enum ${name} {`); values.forEach(value => { if (!value.description || value.description.indexOf('\n') === -1) { generator.printOnNewline(` ${value.value} = "${value.value}",${(0, printing_1.wrap)(' // ', value.description || '')}`); } else { if (value.description) { value.description.split('\n').forEach(line => { generator.printOnNewline(` // ${line.trim()}`); }); } generator.printOnNewline(` ${value.value} = "${value.value}",`); } }); generator.printOnNewline(`}`); generator.printNewline(); } function unionDeclaration(generator, type) { const { name, description } = type; const value = type .getTypes() .map(type => type.name) .join(' | '); generator.printNewlineIfNeeded(); if (description) { description.split('\n').forEach(line => { generator.printOnNewline(`// ${line.trim()}`); }); } generator.printOnNewline(`export type ${name} = ${value}`); generator.printNewline(); } function structDeclarationForInputObjectType(generator, type) { const interfaceName = type.name; (0, language_1.interfaceDeclaration)(generator, { interfaceName, }, () => { const properties = propertiesFromFields(generator.context, Object.values(type.getFields())); properties.forEach(property => (0, language_1.propertyDeclaration)(generator, Object.assign({}, property))); }); } function structDeclarationForObjectType(generator, type) { const interfaceName = type.name; (0, language_1.interfaceDeclaration)(generator, { interfaceName, }, () => { const properties = propertiesFromFields(generator.context, Object.values(type.getFields())); (0, language_1.propertyDeclaration)(generator, { fieldName: '__typename', typeName: `"${interfaceName}"` }); properties.forEach(property => (0, language_1.propertyDeclaration)(generator, Object.assign({}, property))); }); } function structDeclarationForInterfaceType(generator, type) { const interfaceName = type.name; (0, language_1.interfaceDeclaration)(generator, { interfaceName, }, () => { const properties = propertiesFromFields(generator.context, Object.values(type.getFields())); (0, language_1.propertyDeclaration)(generator, { fieldName: '__typename', typeName: `"${interfaceName}"` }); properties.forEach(property => (0, language_1.propertyDeclaration)(generator, Object.assign({}, property))); }); } function interfaceNameFromOperation({ operationName, operationType }) { switch (operationType) { case 'query': return `${operationName}Query`; break; case 'mutation': return `${operationName}Mutation`; break; case 'subscription': return `${operationName}Subscription`; break; default: throw new graphql_1.GraphQLError(`Unsupported operation type "${operationType}"`); } } exports.interfaceNameFromOperation = interfaceNameFromOperation; function interfaceVariablesNameFromOperation({ operationName, operationType }) { return `${interfaceNameFromOperation({ operationName, operationType })}Variables`; } exports.interfaceVariablesNameFromOperation = interfaceVariablesNameFromOperation; function interfaceVariablesDeclarationForOperation(generator, { operationName, operationType, variables }) { const interfaceName = interfaceVariablesNameFromOperation({ operationName, operationType }); (0, language_1.interfaceDeclaration)(generator, { interfaceName, }, () => { const properties = propertiesFromFields(generator.context, variables !== null && variables !== void 0 ? variables : []); pickedPropertyDeclarations(generator, properties); }); } exports.interfaceVariablesDeclarationForOperation = interfaceVariablesDeclarationForOperation; function getObjectTypeName(type) { if ((0, graphql_1.isListType)(type)) { return getObjectTypeName(type.ofType); } if ((0, graphql_1.isNonNullType)(type)) { return getObjectTypeName(type.ofType); } if ((0, graphql_1.isObjectType)(type)) { return `"${type.name}"`; } if ((0, graphql_1.isUnionType)(type)) { return type .getTypes() .map(type => getObjectTypeName(type)) .join(' | '); } return `"${type.name}"`; } function updateTypeNameField(rootField) { const fields = rootField.fields && rootField.fields.map(field => { if (field.fieldName === '__typename') { const objectTypeName = getObjectTypeName(rootField.type); return Object.assign(Object.assign({}, field), { typeName: objectTypeName, type: { name: objectTypeName } }); } if (field.fields) { return updateTypeNameField(field); } return field; }); return Object.assign(Object.assign({}, rootField), { fields }); } exports.updateTypeNameField = updateTypeNameField; function interfaceDeclarationForOperation(generator, { operationName, operationType, fields }) { const interfaceName = interfaceNameFromOperation({ operationName, operationType }); fields = fields.map(field => updateTypeNameField(field)); const properties = propertiesFromFields(generator.context, fields); (0, language_1.interfaceDeclaration)(generator, { interfaceName, }, () => { pickedPropertyDeclarations(generator, properties); }); } exports.interfaceDeclarationForOperation = interfaceDeclarationForOperation; function interfaceDeclarationForFragment(generator, fragment) { const { fragmentName, typeCondition, fields, inlineFragments } = fragment; const interfaceName = `${fragmentName}Fragment`; (0, language_1.interfaceDeclaration)(generator, { interfaceName, noBrackets: (0, graphql_1.isAbstractType)(typeCondition), }, () => { if ((0, graphql_1.isAbstractType)(typeCondition)) { const propertySets = fragment.possibleTypes.map(type => { const inlineFragment = inlineFragments.find(inlineFragment => { return inlineFragment.typeCondition.toString() == type.toString(); }); if (inlineFragment) { const fields = inlineFragment.fields.map(field => { if (field.fieldName === '__typename') { return Object.assign(Object.assign({}, field), { typeName: `"${inlineFragment.typeCondition}"`, type: { name: `"${inlineFragment.typeCondition}"` } }); } else { return field; } }); return propertiesFromFields(generator.context, fields); } else { const fragmentFields = fields.map(field => { if (field.fieldName === '__typename') { return Object.assign(Object.assign({}, field), { typeName: `"${type}"`, type: { name: `"${type}"` } }); } else { return field; } }); return propertiesFromFields(generator.context, fragmentFields); } }); (0, language_1.pickedPropertySetsDeclaration)(generator, fragment, propertySets, true); } else { const fragmentFields = fields.map(field => { if (field.fieldName === '__typename') { return Object.assign(Object.assign({}, field), { typeName: `"${fragment.typeCondition}"`, type: { name: `"${fragment.typeCondition}"` } }); } else { return updateTypeNameField(field); } }); const properties = propertiesFromFields(generator.context, fragmentFields); pickedPropertyDeclarations(generator, properties); } }); } exports.interfaceDeclarationForFragment = interfaceDeclarationForFragment; function propertiesFromFields(context, fields) { return fields.map(field => propertyFromField(context, field)); } exports.propertiesFromFields = propertiesFromFields; function propertyFromField(context, field) { let { name: fieldName, type: fieldType, description, fragmentSpreads, inlineFragments } = field; fieldName = fieldName || field.responseName; const propertyName = fieldName; let property = { fieldName, fieldType, propertyName, description }; const namedType = (0, graphql_1.getNamedType)(fieldType); let isNullable = true; if ((0, graphql_1.isNonNullType)(fieldType)) { isNullable = false; } if ((0, graphql_1.isCompositeType)(namedType)) { let typeName = namedType.toString(); let isArray = false; let isArrayElementNullable = null; if ((0, graphql_1.isListType)(fieldType)) { isArray = true; isArrayElementNullable = !(0, graphql_1.isNonNullType)(fieldType.ofType); } else if ((0, graphql_1.isNonNullType)(fieldType) && (0, graphql_1.isListType)(fieldType.ofType)) { isArray = true; isArrayElementNullable = !(0, graphql_1.isNonNullType)(fieldType.ofType.ofType); } else if (!(0, graphql_1.isNonNullType)(fieldType)) { typeName = (0, types_1.typeNameFromGraphQLType)(context, fieldType, null, isNullable); } return Object.assign(Object.assign({}, property), { typeName, fields: field.fields, isComposite: true, fragmentSpreads, inlineFragments, fieldType, isArray, isNullable, isArrayElementNullable }); } else { if (field.fieldName === '__typename') { const typeName = (0, types_1.typeNameFromGraphQLType)(context, fieldType, null, false); return Object.assign(Object.assign({}, property), { typeName, isComposite: false, fieldType, isNullable: false }); } else { const typeName = (0, types_1.typeNameFromGraphQLType)(context, fieldType, null, isNullable); return Object.assign(Object.assign({}, property), { typeName, isComposite: false, fieldType, isNullable }); } } } exports.propertyFromField = propertyFromField; function pickedPropertyDeclarations(generator, properties, isOptional = false) { if (!properties) return; properties.forEach(property => { if ((0, graphql_1.isAbstractType)((0, graphql_1.getNamedType)(property.type || property.fieldType))) { const propertySets = getPossibleTypeNames(generator, property).map(type => { const inlineFragment = property.inlineFragments && property.inlineFragments.find(inlineFragment => { return inlineFragment.typeCondition.toString() == type; }); if (inlineFragment) { const fields = inlineFragment.fields.map(field => { if (field.fieldName === '__typename') { return Object.assign(Object.assign({}, field), { typeName: `"${inlineFragment.typeCondition}"`, type: { name: `"${inlineFragment.typeCondition}"` } }); } else { return field; } }); return propertiesFromFields(generator.context, fields); } else { const fields = property.fields.map(field => { if (field.fieldName === '__typename') { return Object.assign(Object.assign({}, field), { typeName: `"${type}"`, type: { name: `"${type}"` } }); } else { return field; } }); return propertiesFromFields(generator.context, fields); } }); (0, language_1.pickedPropertySetsDeclaration)(generator, property, propertySets); } else { if ((property.fields && property.fields.length > 0) || (property.inlineFragments && property.inlineFragments.length > 0) || (property.fragmentSpreads && property.fragmentSpreads.length > 0)) { (0, language_1.propertyDeclaration)(generator, property, () => { const properties = propertiesFromFields(generator.context, property.fields); pickedPropertyDeclarations(generator, properties, isOptional); }); } else { (0, language_1.propertyDeclaration)(generator, Object.assign(Object.assign({}, property), { isOptional })); } } }); } exports.pickedPropertyDeclarations = pickedPropertyDeclarations; function getPossibleTypeNames(generator, property) { const type = (0, graphql_1.getNamedType)(property.fieldType || property.type); if ((0, graphql_1.isUnionType)(type) || (0, graphql_1.isInterfaceType)(type)) { return generator.context.schema.getPossibleTypes(type).map(type => type.name); } return []; } //# sourceMappingURL=codeGeneration.js.map