UNPKG

@aws-amplify/graphql-types-generator

Version:

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

298 lines 13.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.propertyFromVar = exports.variablesFromField = exports.generateSource = void 0; const graphql_1 = require("graphql"); const prettier = require("prettier"); const CodeGenerator_1 = require("../utilities/CodeGenerator"); const codeGeneration_1 = require("../typescript/codeGeneration"); const types_1 = require("../typescript/types"); const language_1 = require("../typescript/language"); const graphql_2 = require("../utilities/graphql"); const codeGeneration_2 = require("../flow/codeGeneration"); function generateSource(context, options) { var _a; const isAngularV6 = (_a = options === null || options === void 0 ? void 0 : options.isAngularV6) !== null && _a !== void 0 ? _a : false; const importApiStatement = isAngularV6 ? `import { Client, generateClient, GraphQLResult } from 'aws-amplify/api';` : `import API, { graphqlOperation, GraphQLResult } from '@aws-amplify/api-graphql';`; const importObservable = isAngularV6 ? `import { Observable } from 'rxjs';` : `import { Observable } from 'zen-observable-ts';`; 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.'); generator.printOnNewline(`import { Injectable } from '@angular/core';`); generator.printOnNewline(importApiStatement); generator.printOnNewline(importObservable); generator.printNewline(); generateTypes(generator, context, { isAngularV6 }); generator.printNewline(); generateAngularService(generator, context, { isAngularV6 }); return prettier.format(generator.output, { parser: 'typescript' }); } exports.generateSource = generateSource; function generateTypes(generator, context, options) { var _a; const isAngularV6 = (_a = options === null || options === void 0 ? void 0 : options.isAngularV6) !== null && _a !== void 0 ? _a : false; if (context.schema.getSubscriptionType()) { if (!isAngularV6) { generateSubscriptionResponseWrapper(generator); } generateSubscriptionOperationTypes(generator, context); } context.typesUsed.forEach(type => (0, codeGeneration_1.typeDeclarationForGraphQLType)(generator, type)); Object.values(context.operations).forEach(operation => { interfaceDeclarationForOperation(generator, operation); }); Object.values(context.fragments).forEach(operation => (0, codeGeneration_1.interfaceDeclarationForFragment)(generator, operation)); } function generateSubscriptionResponseWrapper(generator) { generator.printOnNewline(` export interface SubscriptionResponse<T> { value: GraphQLResult<T>; }`); generator.printNewline(); } function generateSubscriptionOperationTypes(generator, context) { const typeName = '__SubscriptionContainer'; const properties = []; Object.values(context.operations) .filter(operation => operation.operationType === 'subscription') .forEach(operation => { const { operationName, operationType } = operation; const typeName = (0, codeGeneration_1.interfaceNameFromOperation)({ operationName, operationType }); if (operation.fields.length) { properties.push({ fieldName: operation.fields[0].responseName, typeName, }); } }); if (properties.length) { generator.printOnNewline(`export type ${typeName} = `); generator.pushScope({ typeName }); generator.withinBlock(() => (0, codeGeneration_2.propertyDeclarations)(generator, properties), '{', '}'); generator.popScope(); generator.print(';'); generator.printNewline(); } } function interfaceDeclarationForOperation(generator, { operationName, operationType, fields }) { const interfaceName = (0, codeGeneration_1.interfaceNameFromOperation)({ operationName, operationType }); fields = fields.map(field => (0, codeGeneration_1.updateTypeNameField)(field)); if (fields[0].fields) { const properties = (0, codeGeneration_1.propertiesFromFields)(generator.context, fields[0].fields); (0, language_1.interfaceDeclaration)(generator, { interfaceName, }, () => { (0, codeGeneration_1.pickedPropertyDeclarations)(generator, properties); }); } } function getOperationResultField(operation) { if (operation.fields.length) { return operation.fields[0]; } } function getReturnTypeName(generator, op) { const { operationName, operationType } = op; const { type } = op.fields[0]; if ((0, graphql_1.isListType)(type)) { const { ofType } = type; if ((0, graphql_1.isScalarType)(ofType) || (0, graphql_1.isEnumType)(ofType)) { return `Array<${(0, types_1.typeNameFromGraphQLType)(generator.context, ofType)}>`; } } if ((0, graphql_1.isScalarType)(type) || (0, graphql_1.isEnumType)(type)) { return (0, types_1.typeNameFromGraphQLType)(generator.context, type); } else { let returnType = (0, codeGeneration_1.interfaceNameFromOperation)({ operationName, operationType }); if (op.operationType === 'subscription' && op.fields.length) { returnType = `Pick<__SubscriptionContainer, "${op.fields[0].responseName}">`; } if ((0, graphql_2.isList)(type)) { returnType = `Array<${returnType}>`; } return returnType; } } function generateAngularService(generator, context, options) { var _a; const isAngularV6 = (_a = options === null || options === void 0 ? void 0 : options.isAngularV6) !== null && _a !== void 0 ? _a : false; const operations = context.operations; generator.printOnNewline(`@Injectable({ providedIn: 'root' })`); generator.printOnNewline(`export class APIService {`); generator.withIndent(() => { if (isAngularV6) { generator.printOnNewline('public client: Client;'); generateServiceConstructor(generator); } Object.values(operations).forEach((op) => { if (op.operationType === 'subscription') { return generateSubscriptionOperation(generator, op, { isAngularV6 }); } if (op.operationType === 'query' || op.operationType === 'mutation') { return generateQueryOrMutationOperation(generator, op, { isAngularV6 }); } }); generator.printOnNewline('}'); }); } function generateServiceConstructor(generator) { generator.printOnNewline(); generator.print(`constructor() {`); generator.withIndent(() => { generator.print(`this.client = generateClient();`); }); generator.printOnNewline('}'); } function generateSubscriptionOperation(generator, op, options) { var _a; const isAngularV6 = (_a = options === null || options === void 0 ? void 0 : options.isAngularV6) !== null && _a !== void 0 ? _a : false; const statement = formatTemplateString(generator, op.source); const { operationName } = op; const vars = variablesFromField(generator.context, op.variables); const returnType = getReturnTypeName(generator, op); generator.printNewline(); const subscriptionName = `${operationName}Listener`; if (!vars.length) { if (isAngularV6) { generator.print(`${subscriptionName}(): Observable<GraphQLResult<${returnType}>> { return this.client.graphql({ query: \n\`${statement}\` }) as any; }`); } else { generator.print(`${subscriptionName}: Observable<SubscriptionResponse<${returnType}>> = API.graphql(graphqlOperation(\n\`${statement}\`)) as Observable<SubscriptionResponse<${returnType}>>`); } } else { generator.print(`${subscriptionName}(`); variableDeclaration(generator, vars); if (isAngularV6) { generator.print(`) : Observable<GraphQLResult<${returnType}>> {`); } else { generator.print(`) : Observable<SubscriptionResponse<${returnType}>> {`); } generator.withIndent(() => { generator.printNewlineIfNeeded(); generator.print(`const statement = \`${statement}\``); const params = ['statement']; variableAssignmentToInput(generator, vars); params.push('gqlAPIServiceArguments'); if (isAngularV6) { generator.printOnNewline(`return this.client.graphql({ query: statement, variables: gqlAPIServiceArguments }) as any;`); } else { generator.printOnNewline(`return API.graphql(graphqlOperation(${params.join(', ')})) as Observable<SubscriptionResponse<${returnType}>>;`); } generator.printOnNewline('}'); }); } generator.printNewline(); } function generateQueryOrMutationOperation(generator, op, options) { var _a; const isAngularV6 = (_a = options === null || options === void 0 ? void 0 : options.isAngularV6) !== null && _a !== void 0 ? _a : false; const statement = formatTemplateString(generator, op.source); const vars = variablesFromField(generator.context, op.variables); const returnType = getReturnTypeName(generator, op); const resultField = getOperationResultField(op); const resultProp = resultField ? `.${resultField.responseName}` : ''; generator.printNewline(); generator.print(`async ${op.operationName}(`); variableDeclaration(generator, vars); generator.print(`) : Promise<${returnType}> {`); generator.withIndent(() => { generator.printNewlineIfNeeded(); generator.print(`const statement = \`${statement}\``); const params = ['statement']; if (op.variables.length) { variableAssignmentToInput(generator, vars); params.push('gqlAPIServiceArguments'); } if (isAngularV6) { generator.printOnNewline(`const response = await this.client.graphql({ query: statement, ${op.variables.length ? `variables: gqlAPIServiceArguments, ` : ''}}) as any;`); } else { generator.printOnNewline(`const response = await API.graphql(graphqlOperation(${params.join(', ')})) as any;`); } generator.printOnNewline(`return (<${returnType}>response.data${resultProp})`); }); generator.printOnNewline('}'); } function variablesFromField(context, fields) { return fields.map(field => propertyFromVar(context, field)); } exports.variablesFromField = variablesFromField; function propertyFromVar(context, field) { let { name: fieldName, type: fieldType } = field; fieldName = fieldName || field.responseName; const propertyName = fieldName; let property = { fieldName, fieldType, propertyName }; let isNullable = true; if (fieldType instanceof graphql_1.GraphQLNonNull) { isNullable = false; } const typeName = (0, types_1.typeNameFromGraphQLType)(context, fieldType, null, false); return Object.assign(Object.assign({}, property), { typeName, isComposite: false, fieldType, isNullable }); } exports.propertyFromVar = propertyFromVar; function variableDeclaration(generator, properties) { properties .sort((a, b) => { if (!a.isNullable && b.isNullable) { return -1; } if (!b.isNullable && a.isNullable) { return 1; } return 0; }) .forEach(property => { const { fieldName, typeName, isArray, isNullable } = property; generator.print(fieldName); if (isNullable) { generator.print('?'); } generator.print(':'); if (isArray) { generator.print(' Array<'); } generator.print(`${typeName}`); if (isArray) { generator.print('>'); } generator.print(', '); }); } function variableAssignmentToInput(generator, vars) { if (vars.length > 0) { generator.printOnNewline('const gqlAPIServiceArguments : any = '); generator.withinBlock(() => { vars .filter(v => !v.isNullable) .forEach(v => { generator.printOnNewline(`${v.fieldName},`); }); }, '{', '}'); vars .filter(v => v.isNullable) .forEach(v => { generator.printOnNewline(`if (${v.fieldName}) `); generator.withinBlock(() => { generator.printOnNewline(`gqlAPIServiceArguments.${v.fieldName} = ${v.fieldName}`); }, '{', '}'); }); } } function formatTemplateString(generator, str) { const indentation = ' '.repeat(generator.currentFile.indentWidth * (generator.currentFile.indentLevel + 2)); return str .split('\n') .map((line, idx) => (idx > 0 ? indentation + line : line)) .join('\n'); } //# sourceMappingURL=index.js.map