UNPKG

@chezearth/swagger-node-runner

Version:
141 lines (108 loc) 5.54 kB
'use strict'; var debug = require('debug')('swagger:swagger_router'); var path = require('path'); var assert = require('assert'); var SWAGGER_ROUTER_CONTROLLER = 'x-swagger-router-controller'; var CONTROLLER_INTERFACE_TYPE = 'x-controller-interface'; var allowedCtrlInterfaces = ["middleware", "pipe", "auto-detect"]; var util = require('util'); module.exports = function create(fittingDef, bagpipes) { debug('config: %j', fittingDef); assert(Array.isArray(fittingDef.controllersDirs), 'controllersDirs must be an array'); assert(Array.isArray(fittingDef.mockControllersDirs), 'mockControllersDirs must be an array'); if (!fittingDef.controllersInterface) fittingDef.controllersInterface = "middleware"; assert( ~allowedCtrlInterfaces.indexOf(fittingDef.controllersInterface), 'value in swagger_router config.controllersInterface - can be one of ' + allowedCtrlInterfaces + ' but got: ' + fittingDef.controllersInterface ); var swaggerNodeRunner = bagpipes.config.swaggerNodeRunner; swaggerNodeRunner.api.getOperations().forEach(function(operation) { var interfaceType = operation.controllerInterface = operation.definition[CONTROLLER_INTERFACE_TYPE] || operation.pathObject.definition[CONTROLLER_INTERFACE_TYPE] || swaggerNodeRunner.api.definition[CONTROLLER_INTERFACE_TYPE] || fittingDef.controllersInterface; assert( ~allowedCtrlInterfaces.indexOf(interfaceType), 'whenever provided, value of ' + CONTROLLER_INTERFACE_TYPE + ' directive in openapi doc must be one of ' + allowedCtrlInterfaces + ' but got: ' + interfaceType); }) var appRoot = swaggerNodeRunner.config.swagger.appRoot; var dependencies = swaggerNodeRunner.config.swagger.dependencies var mockMode = !!fittingDef.mockMode || !!swaggerNodeRunner.config.swagger.mockMode; var controllersDirs = mockMode ? fittingDef.mockControllersDirs : fittingDef.controllersDirs; controllersDirs = controllersDirs.map(function(dir) { return path.resolve(appRoot, dir); }); var controllerFunctionsCache = {}; return function swagger_router(context, cb) { debug('exec'); var operation = context.request.swagger.operation; var controllerName = operation[SWAGGER_ROUTER_CONTROLLER] || operation.pathObject[SWAGGER_ROUTER_CONTROLLER]; var controller; if (controllerName in controllerFunctionsCache) { debug('controller in cache', controllerName); controller = controllerFunctionsCache[controllerName]; } else if (controllerName) { debug('loading controller %s from fs: %s', controllerName, controllersDirs); for (var i = 0; i < controllersDirs.length; i++) { var controllerPath = path.resolve(controllersDirs[i], controllerName); try { var ctrlObj = require(controllerPath) controller = dependencies && typeof ctrlObj === 'function' ? ctrlObj(dependencies) : ctrlObj controllerFunctionsCache[controllerName] = controller; debug('controller found', controllerPath); break; } catch (err) { if (!mockMode && i === controllersDirs.length - 1) { return cb(err); } debug('controller not in', controllerPath); } } } if (controller) { var operationId = operation.definition.operationId || context.request.method.toLowerCase(); var ctrlType = operation.definition['x-controller-type'] || operation.pathObject.definition['x-controller-type'] || operation.pathObject.api.definition['x-controller-type']; var controllerFunction = controller[operationId]; if (controllerFunction && typeof controllerFunction === 'function') { if (operation.controllerInterface == 'auto-detect') { operation.controllerInterface = controllerFunction.length == 3 ? 'middleware' : 'pipe'; debug("auto-detected interface-type for operation '%s' at [%s] as '%s'", operationId, operation.pathToDefinition, operation.controllerInterface) } debug('running controller, as %s', operation.controllerInterface); return operation.controllerInterface == 'pipe' ? controllerFunction(context, cb) : controllerFunction(context.request, context.response, cb); } var msg = util.format('Controller %s doesn\'t export handler function %s', controllerName, operationId); if (mockMode) { debug(msg); } else { return cb(new Error(msg)); } } if (mockMode) { var statusCode = parseInt(context.request.get('_mockreturnstatus')) || 200; var mimetype = context.request.get('accept') || 'application/json'; var response = operation.getResponse(statusCode) || operation.getResponse('default'); var mock = response.getExample(mimetype); if (mock) { debug('returning mock example value', mock); } else { var operationResponse = operation.getResponse(statusCode) || operation.getResponse('default'); mock = operationResponse.getSample(); debug('returning mock sample value', mock); } context.headers['Content-Type'] = mimetype; context.statusCode = statusCode; return cb(null, mock); } // for completeness, we should never actually get here cb(new Error(util.format('No controller found for %s in %j', controllerName, controllersDirs))); } };