UNPKG

saasify-openapi-utils

Version:
104 lines (83 loc) 2.74 kB
'use strict' const cloneDeep = require('clone-deep') const parser = require('swagger-parser') const slugify = require('@sindresorhus/slugify') const getExamplesFromPathItem = require('./get-examples-from-path-item') const isHttpMethod = require('./is-http-method') /** * Converts an OpenAPI spec to Saasify's `Service` format. * * @param {object} spec - OpenAPI spec. * @param {object} config - Parsed Saasify project configuration. * * @return {Promise} */ module.exports = async (spec, config) => { const openapi = await parser.dereference(cloneDeep(spec)) const origServices = config.services.slice() const services = [] const firstService = origServices[0] let defaultService = false for (const path of Object.keys(openapi.paths)) { const pathItem = openapi.paths[path] const httpMethods = Object.keys(pathItem).filter(isHttpMethod) for (const httpMethod of httpMethods) { const op = pathItem[httpMethod] let name = op.operationId if (!name) { name = path.slice(1) if (!name) { name = 'Default' } else if (name.includes('/')) { name = slugify(name) } } let index = origServices.findIndex( (s) => s.path === path && (httpMethods.length === 1 || (s.httpMethod || 'get').toLowerCase() === httpMethod) ) let origService if ( index < 0 && origServices.length === 1 && origServices[0].path === undefined ) { if (defaultService) { throw new Error( 'Error resolving OpenAPI spec to services: include "path" in services to disambiguate' ) } index = 0 defaultService = true } if (index >= 0) { origService = origServices[index] origServices.splice(index, 1) } const service = { name, path, src: firstService ? firstService.src : undefined, ...origService } service.httpMethod = httpMethod // extract any examples from the OpenAPI PathItem for this service // TODO: restrict this only to an operation const examples = await getExamplesFromPathItem(pathItem, httpMethod) service.examples = (service.examples || []).concat(examples) services.push(service) } } // console.log(JSON.stringify(services, null, 2)) // if there are any origServices that were not matched, throw an error if (origServices.length > 0) { const extra = origServices[0] const extraLabel = extra.name || extra.path throw new Error( `Error mapping OpenAPI spec to services: found extra unmatched service "${extraLabel}"}` ) } return services }