UNPKG

typescript-swagger

Version:

Generate Swagger files from a decorator library like typescript-rest or a @decorators/express.

169 lines 8.63 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.MethodGenerator = void 0; var pathUtil = require("path"); var ts = require("typescript"); var type_1 = require("../decorator/type"); var utils_1 = require("../decorator/utils"); var jsDocUtils_1 = require("../utils/jsDocUtils"); var endpointGenerator_1 = require("./endpointGenerator"); var parameterGenerator_1 = require("./parameterGenerator"); var resolver_1 = require("./resolver"); var type_2 = require("./resolver/type"); var MethodGenerator = /** @class */ (function (_super) { __extends(MethodGenerator, _super); // -------------------------------------------------------------------- function MethodGenerator(node, current, controllerPath) { var _this = _super.call(this, node, current) || this; _this.controllerPath = controllerPath; _this.processMethodDecorators(); return _this; } // -------------------------------------------------------------------- MethodGenerator.prototype.isValid = function () { return !!this.method; }; MethodGenerator.prototype.getMethodName = function () { var identifier = this.node.name; return identifier.text; }; MethodGenerator.prototype.generate = function () { if (!this.isValid()) { throw new Error('This isn\'t a valid controller method.'); } this.debugger('Generating Metadata for method %s', this.getCurrentLocation()); var nodeType = this.node.type; if (!nodeType) { var typeChecker = this.current.typeChecker; var signature = typeChecker.getSignatureFromDeclaration(this.node); var implicitType = typeChecker.getReturnTypeOfSignature(signature); nodeType = typeChecker.typeToTypeNode(implicitType, undefined, ts.NodeBuilderFlags.NoTruncation); } var type = new resolver_1.TypeNodeResolver(nodeType, this.current).resolve(); var responses = this.mergeResponses(this.getResponses(), this.getMethodSuccessResponse(type)); var methodMetadata = { consumes: this.getConsumes(), // todo: rework deprecated deprecated: jsDocUtils_1.isExistJSDocTag(this.node, 'deprecated'), description: jsDocUtils_1.getJSDocDescription(this.node), method: this.method, name: this.node.name.text, parameters: this.buildParameters(), path: this.path, produces: this.getProduces(), responses: responses, security: this.getSecurity(), // todo: rework summary summary: jsDocUtils_1.getJSDocTagComment(this.node, 'summary'), tags: this.getTags(), type: type }; this.debugger('Generated Metadata for method %s: %j', this.getCurrentLocation(), methodMetadata); return methodMetadata; }; MethodGenerator.prototype.getCurrentLocation = function () { var methodId = this.node.name; var controllerId = this.node.parent.name; return controllerId.text + "." + methodId.text; }; MethodGenerator.prototype.buildParameters = function () { var _this = this; this.debugger('Processing method %s parameters.', this.getCurrentLocation()); var parameters = this.node.parameters.map(function (p) { try { var path = pathUtil.posix.join('/', (_this.controllerPath ? _this.controllerPath : ''), _this.path); return new parameterGenerator_1.ParameterGenerator(p, _this.method, path, _this.current).generate(); } catch (e) { console.log(e); var methodId = _this.node.name; var controllerId = _this.node.parent.name; var parameterId = p.name; throw new Error("Error generate parameter method: '" + controllerId.text + "." + methodId.text + "' argument: " + parameterId.text + " " + e); } }).filter(function (p) { return (p.in !== 'context') && (p.in !== 'cookie'); }); var bodyParameters = parameters.filter(function (p) { return p.in === 'body'; }); var formParameters = parameters.filter(function (p) { return p.in === 'formData'; }); if (bodyParameters.length > 1) { throw new Error("Only one body parameter allowed in '" + this.getCurrentLocation() + "' method."); } if (bodyParameters.length > 0 && formParameters.length > 0) { throw new Error("Choose either during @FormParam and @FileParam or body parameter in '" + this.getCurrentLocation() + "' method."); } this.debugger('Parameters list for method %s: %j.', this.getCurrentLocation(), parameters); return parameters; }; MethodGenerator.prototype.processMethodDecorators = function () { var _this = this; var httpMethodDecorators = utils_1.getDecorators(this.node, function (decorator) { return _this.supportsPathMethod(decorator.text); }); if (!httpMethodDecorators || !httpMethodDecorators.length) { return; } if (httpMethodDecorators.length > 1) { throw new Error("Only one HTTP Method decorator in '" + this.getCurrentLocation + "' method is acceptable, Found: " + httpMethodDecorators.map(function (d) { return d.text; }).join(', ')); } var methodDecorator = httpMethodDecorators[0]; this.method = methodDecorator.text.toLowerCase(); this.debugger('Processing method %s decorators.', this.getCurrentLocation()); this.generatePath('METHOD_PATH'); this.debugger('Mapping endpoint %s %s', this.method, this.path); }; MethodGenerator.prototype.getMethodSuccessResponse = function (type) { var responseData = MethodGenerator.getMethodSuccessResponseData(type); return { description: type_2.Resolver.isVoidType(type) ? 'No content' : 'Ok', examples: this.getMethodSuccessExamples(), schema: responseData.type, status: responseData.status }; }; MethodGenerator.getMethodSuccessResponseData = function (type) { switch (type.typeName) { case 'void': return { status: '204', type: type }; default: return { status: '200', type: type }; } }; MethodGenerator.prototype.getMethodSuccessExamples = function () { var handler = type_1.Decorator.getRepresentationHandler('RESPONSE_EXAMPLE', this.current.decoratorMap); var config = handler.buildRepresentationConfigFromNode(this.node); var property = handler.getPropertiesByTypes(config.name, ['TYPE', 'PAYLOAD']); var example = handler.getDecoratorPropertyValueAsItem(config.decorator, property['PAYLOAD']); return this.getExamplesValue(example); }; MethodGenerator.prototype.mergeResponses = function (responses, defaultResponse) { if (!responses || !responses.length) { return [defaultResponse]; } var index = responses.findIndex(function (resp) { return resp.status === defaultResponse.status; }); if (index >= 0) { if (defaultResponse.examples && !responses[index].examples) { responses[index].examples = defaultResponse.examples; } } else { responses.push(defaultResponse); } return responses; }; MethodGenerator.prototype.supportsPathMethod = function (method) { return ['ALL', 'GET', 'POST', 'PATCH', 'DELETE', 'PUT', 'OPTIONS', 'HEAD'].some(function (m) { return m.toLowerCase() === method.toLowerCase(); }); }; return MethodGenerator; }(endpointGenerator_1.EndpointGenerator)); exports.MethodGenerator = MethodGenerator; //# sourceMappingURL=methodGenerator.js.map