UNPKG

graphql-from-swagger

Version:

<a href="http://badge.fury.io/js/graphql-from-swagger"><img src="https://badge.fury.io/js/graphql-from-swagger.svg"></a>

282 lines (281 loc) 13.5 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const node_fetch_1 = __importDefault(require("node-fetch")); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const yamljs_1 = __importDefault(require("yamljs")); const utils_1 = require("./utils"); function createRESTDataSource(swaggerPaths, typesFiles, restDataSourceOutputFiles) { return __awaiter(this, void 0, void 0, function* () { const totalLength = swaggerPaths.length; const currentDir = process.cwd(); const result = []; for (let i = 0; i < totalLength; i++) { const imports = []; imports.push(`import { RESTDataSource } from 'apollo-datasource-rest';`); imports.push(`import { URLSearchParams } from 'url';`); let swaggerString; if (utils_1.checkUrlForm(swaggerPaths[i])) { swaggerString = yield (yield node_fetch_1.default(swaggerPaths[i])).text(); } else { swaggerString = yield fs_1.default.readFileSync(path_1.default.join(currentDir, swaggerPaths[i]), 'utf-8'); } let swaggerJSON; if (swaggerPaths[i].endsWith('.json')) { swaggerJSON = JSON.parse(swaggerString); } else if (swaggerPaths[i].endsWith('.yaml')) { swaggerJSON = yamljs_1.default.parse(swaggerString); } else { throw new Error('Swagger is Invalid!'); } const className = path_1.default.basename(restDataSourceOutputFiles[i], '.ts'); const classSentences = []; let hostUrl = ''; if (swaggerJSON.host) { hostUrl = swaggerJSON.host.startsWith('http') ? swaggerJSON.host : 'http://' + swaggerJSON.host; if (swaggerJSON.basePath) { hostUrl += swaggerJSON.basePath; } } else if (swaggerJSON.servers && swaggerJSON.servers.length > 0 && swaggerJSON.servers[0].url) { hostUrl = swaggerJSON.servers[0].url.startsWith('http') ? swaggerJSON.servers[0].url : 'http://' + swaggerJSON.servers[0].url; } else { throw new Error('hostUrl is not exist!'); } classSentences.push(` export class ${className} extends RESTDataSource { constructor() { super(); this.baseURL = '${hostUrl}'; } `.trim()); const functions = []; const argTypes = []; for (const endpoint in swaggerJSON.paths) { for (const method in swaggerJSON.paths[endpoint]) { if (method === 'parameters') continue; const field = swaggerJSON.paths[endpoint][method]; const operationId = field.operationId ? utils_1.replaceOddChars(field.operationId) : utils_1.getGQLTypeNameFromURL(method, endpoint); const parameters = {}; if (field.parameters) { for (const parameter of field.parameters) { if (parameters[parameter.in] !== undefined) { parameters[parameter.in].push(parameter.name); } else { parameters[parameter.in] = [parameter.name]; } } } const args = Object.keys(parameters).reduce((result, param) => { if (parameters[param] === undefined) return result; return [...result, ...parameters[param]]; }, []); const func = []; func.push(''); func.push(...getCommentBlocks(field)); const argumentsString = args.length ? `{ ${args.join(', ')} }: ${utils_1.getArgsStringFromOperationId(operationId, method)}` : ''; if (args.length) argTypes.push(`${utils_1.getArgsStringFromOperationId(operationId, method)}`); func.push(utils_1.indent(`async ${operationId}(${argumentsString}) {`)); if (parameters['query']) func.push(utils_1.indent(`const queries = { ${parameters['query'].join(', ')} };`, 2)); const queryString = parameters['query'] ? `?\${new URLSearchParams(queries as { [key: string]: any })}` : ''; let bodyString = parameters['body'] && method !== 'get' ? `, { ${parameters['body'].join(', ')} }` : ''; let requestInitString = ''; let headerStrings = []; const isXWwwFormUrlEncoded = field.consumes && field.consumes.includes('application/x-www-form-urlencoded'); if (isXWwwFormUrlEncoded) { headerStrings.push(`'Content-Type': 'application/x-www-form-urlencoded'`); bodyString = parameters['formData'] && method !== 'get' ? `, { ${parameters['formData'].join(', ')} }` : ''; } if (parameters['header']) { headerStrings.push(...parameters['header']); } if (headerStrings && headerStrings.length > 0) { requestInitString = `, { headers: { ${headerStrings.join(',\n') + ','} }, }`; } func.push(utils_1.indent(`return this.${method}(\`${endpoint.replace('{', '${')}${queryString}\`${bodyString}${requestInitString});`, 2)); func.push(utils_1.indent(`}`)); functions.push(func.join('\n')); } } imports.push(` import { ${argTypes.join(',\n ')} } from '${utils_1.getRelativePath(restDataSourceOutputFiles[i], typesFiles[i])}'; `.trim()); result.push([...imports, '', ...classSentences, ...functions, '}'].join('\n')); } return result; }); } exports.createRESTDataSource = createRESTDataSource; function getCommentBlocks(field) { const blocks = []; blocks.push(utils_1.indent(`/**`)); if (field.deprecated) blocks.push(utils_1.indent(` * @deprecated`)); if (field.tags && field.tags.length > 0) blocks.push(utils_1.indent(` * @tags ${field.tags.join(', ')}`)); if (field.summary) blocks.push(utils_1.indent(` * @summary ${field.summary}`)); if (field.description) blocks.push(utils_1.indent(` * @description ${field.description}`)); if (field.parameters) { for (const parameter of field.parameters) { let type; if (parameter.type) { if (parameter.type !== 'array') { type = parameter.type; } else { type = parameter.items.type + '[]'; } } else if (parameter.schema) { if (parameter.schema.$ref) { type = parameter.schema.$ref.split('#/definitions/').pop(); } else if (parameter.schema.items && parameter.schema.type === 'array') { if (parameter.schema.items.type) { type = parameter.schema.items.type + '[]'; } else if (parameter.schema.items.$ref) { type = parameter.schema.items.$ref.split('#/definitions/').pop() + '[]'; } } } blocks.push(utils_1.indent(` * @param${type ? ` {${type}}` : ''} ${parameter.name} ${parameter.description ? '- ' + parameter.description : ''} @${parameter.in} ${parameter.required ? '@required' : ''}`)); } } blocks.push(utils_1.indent(` */`)); return blocks; } function createResolvers(swaggerPaths, typesFiles, restDataSourceFiles, resolversOutputFiles) { return __awaiter(this, void 0, void 0, function* () { const totalLength = swaggerPaths.length; const currentDir = process.cwd(); const result = []; for (let i = 0; i < totalLength; i++) { const imports = []; const queries = []; const mutations = []; const resolvers = []; const argTypes = []; const typeDefs = []; let swaggerString; if (utils_1.checkUrlForm(swaggerPaths[i])) { swaggerString = yield (yield node_fetch_1.default(swaggerPaths[i])).text(); } else { swaggerString = yield fs_1.default.readFileSync(path_1.default.join(currentDir, swaggerPaths[i]), 'utf-8'); } let swaggerJSON; if (swaggerPaths[i].endsWith('.json')) { swaggerJSON = JSON.parse(swaggerString); } else if (swaggerPaths[i].endsWith('.yaml')) { swaggerJSON = yamljs_1.default.parse(swaggerString); } else { throw new Error('Swagger is Invalid!'); } const className = path_1.default.basename(restDataSourceFiles[i], '.ts'); for (const endpoint in swaggerJSON.paths) { for (const method in swaggerJSON.paths[endpoint]) { if (method === 'parameters') continue; const field = swaggerJSON.paths[endpoint][method]; const operationId = field.operationId ? utils_1.replaceOddChars(field.operationId) : utils_1.getGQLTypeNameFromURL(method, endpoint); const parameters = {}; if (field.parameters) { for (const parameter of field.parameters) { if (parameters[parameter.in] !== undefined) { parameters[parameter.in].push(parameter.name); } else { parameters[parameter.in] = [parameter.name]; } } } const args = Object.keys(parameters).reduce((result, param) => { if (parameters[param] === undefined) return result; return [...result, ...parameters[param]]; }, []); if (args.length) argTypes.push(`${utils_1.getArgsStringFromOperationId(operationId, method)}`); if (method === 'get') { queries.push(utils_1.indent(` ${operationId}: (parent: Query, args: ${args.length ? utils_1.getArgsStringFromOperationId(operationId, method) : 'null'}, context: Context, info: GraphQLResolveInfo) => { return context.dataSources.${utils_1.getInstanceNameFromClass(className)}.${operationId}(${args.length ? 'args' : ''}); }, `.trim(), 2)); } else { mutations.push(utils_1.indent(` ${operationId}: (parent: Mutation, args: ${args.length ? utils_1.getArgsStringFromOperationId(operationId, method) : 'null'}, context: Context, info: GraphQLResolveInfo) => { return context.dataSources.${utils_1.getInstanceNameFromClass(className)}.${operationId}(${args.length ? 'args' : ''}); }, `.trim(), 2)); } } } resolvers.push(` export const resolvers = { Query: { ${queries.join('\n')} }, Mutation: { ${mutations.join('\n')} } } `.trim()); imports.push(`import { GraphQLResolveInfo } from 'graphql';`); imports.push(` import { ${['Query', 'Mutation', ...argTypes].join(',\n ')} } from '${utils_1.getRelativePath(resolversOutputFiles[i], typesFiles[i])}'; `.trim()); imports.push(` import { ${className} } from '${utils_1.getRelativePath(resolversOutputFiles[i], restDataSourceFiles[i])}'; `.trim()); typeDefs.push(` type DataSources = { ${utils_1.getInstanceNameFromClass(className)}: ${className}; }; `.trim()); typeDefs.push(` type Context = { dataSources: DataSources; }; `.trim()); result.push([...imports, '', ...typeDefs, '', resolvers].join('\n')); } return result; }); } exports.createResolvers = createResolvers;