typescript-swagger
Version:
Generate Swagger files from a decorator library like typescript-rest or a @decorators/express.
169 lines • 8.63 kB
JavaScript
"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