UNPKG

sofa-api

Version:

Create REST APIs with GraphQL

166 lines (165 loc) 6.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildPathFromOperation = buildPathFromOperation; exports.resolveRequestBody = resolveRequestBody; exports.resolveParamSchema = resolveParamSchema; exports.resolveResponse = resolveResponse; exports.isInPath = isInPath; exports.resolveVariableDescription = resolveVariableDescription; const graphql_1 = require("graphql"); const ast_js_1 = require("../ast.js"); const utils_js_1 = require("./utils.js"); const types_js_1 = require("./types.js"); const title_case_1 = require("title-case"); function buildPathFromOperation({ url, schema, operation, useRequestBody, tags, description, customScalars, }) { const info = (0, ast_js_1.getOperationInfo)(operation); const enumTypes = resolveEnumTypes(schema); const summary = resolveDescription(schema, info.operation); const variables = info.operation.variableDefinitions; const pathParams = variables?.filter((variable) => isInPath(url, variable.variable.name.value)); const bodyParams = variables?.filter((variable) => !isInPath(url, variable.variable.name.value)); return { tags, description, summary, operationId: info.name, ...(useRequestBody ? { parameters: resolveParameters(url, pathParams, schema, info.operation, { customScalars, enumTypes }), requestBody: { content: { 'application/json': { schema: resolveRequestBody(bodyParams, schema, info.operation, { customScalars, enumTypes, }), }, }, }, } : { parameters: resolveParameters(url, variables, schema, info.operation, { customScalars, enumTypes }), }), responses: { 200: { description: summary, content: { 'application/json': { schema: resolveResponse({ schema, operation: info.operation, opts: { customScalars, enumTypes }, }), }, }, }, }, }; } function resolveEnumTypes(schema) { const enumTypes = Object.values(schema.getTypeMap()).filter(graphql_1.isEnumType); return Object.fromEntries(enumTypes.map((type) => [ type.name, { type: 'string', enum: type.getValues().map((value) => value.name), }, ])); } function resolveParameters(url, variables, schema, operation, opts) { if (!variables) { return []; } return variables.map((variable) => { return { in: isInPath(url, variable.variable.name.value) ? 'path' : 'query', name: variable.variable.name.value, required: variable.type.kind === graphql_1.Kind.NON_NULL_TYPE, schema: resolveParamSchema(variable.type, opts), description: resolveVariableDescription(schema, operation, variable), }; }); } function resolveRequestBody(variables, schema, operation, opts) { if (!variables) { return {}; } const properties = {}; const required = []; variables.forEach((variable) => { if (variable.type.kind === graphql_1.Kind.NON_NULL_TYPE) { required.push(variable.variable.name.value); } properties[variable.variable.name.value] = { ...resolveParamSchema(variable.type, opts), description: resolveVariableDescription(schema, operation, variable), }; }); return { type: 'object', properties, ...(required.length ? { required } : {}), }; } // array -> [type] // type -> $ref // scalar -> swagger primitive function resolveParamSchema(type, opts) { if (type.kind === graphql_1.Kind.NON_NULL_TYPE) { return resolveParamSchema(type.type, opts); } if (type.kind === graphql_1.Kind.LIST_TYPE) { return { type: 'array', items: resolveParamSchema(type.type, opts), }; } const primitive = (0, utils_js_1.mapToPrimitive)(type.name.value); return (primitive || opts.customScalars[type.name.value] || opts.enumTypes[type.name.value] || { $ref: (0, utils_js_1.mapToRef)(type.name.value) }); } function resolveResponse({ schema, operation, opts, }) { const operationType = operation.operation; const rootField = operation.selectionSet.selections[0]; if (rootField.kind === graphql_1.Kind.FIELD) { if (operationType === 'query') { const queryType = schema.getQueryType(); const field = queryType.getFields()[rootField.name.value]; return (0, types_js_1.resolveFieldType)(field.type, opts); } if (operationType === 'mutation') { const mutationType = schema.getMutationType(); const field = mutationType.getFields()[rootField.name.value]; return (0, types_js_1.resolveFieldType)(field.type, opts); } } } function isInPath(url, param) { return url.includes(`:${param}`) || url.includes(`{${param}}`); } function getOperationFieldNode(schema, operation) { const selection = operation.selectionSet.selections[0]; const fieldName = selection.name.value; const typeDefinition = schema.getType((0, title_case_1.titleCase)(operation.operation)); if (!typeDefinition) { return undefined; } const definitionNode = typeDefinition.astNode || (0, graphql_1.parse)((0, graphql_1.printType)(typeDefinition)).definitions[0]; if (!isObjectTypeDefinitionNode(definitionNode)) { return undefined; } return definitionNode.fields.find((field) => field.name.value === fieldName); } function resolveDescription(schema, operation) { const fieldNode = getOperationFieldNode(schema, operation); return fieldNode?.description?.value || ''; } function resolveVariableDescription(schema, operation, variable) { const fieldNode = getOperationFieldNode(schema, operation); const argument = fieldNode?.arguments?.find((arg) => arg.name.value === variable.variable.name.value); return argument?.description?.value; } function isObjectTypeDefinitionNode(node) { return node.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION; }