typescript-swagger
Version:
Generate Swagger files from a decorator library like typescript-rest or a @decorators/express.
375 lines (373 loc) • 17.4 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.ParameterGenerator = void 0;
var ts = require("typescript");
var type_1 = require("../decorator/type");
var utils_1 = require("../decorator/utils");
var resolver_1 = require("./resolver");
var utils_2 = require("./resolver/utils");
var supportedParameterKeys = [
'SERVER_CONTEXT',
'SERVER_PARAMS',
'SERVER_QUERY',
'SERVER_FORM',
'SERVER_BODY',
'SERVER_HEADERS',
'SERVER_COOKIES',
'SERVER_PATH_PARAMS',
'SERVER_FILES_PARAM'
];
var ParameterGenerator = /** @class */ (function () {
function ParameterGenerator(parameter, method, path, current) {
this.parameter = parameter;
this.method = method;
this.path = path;
this.current = current;
}
ParameterGenerator.prototype.generate = function () {
var decorators = utils_1.getDecorators(this.parameter);
var decoratorNames = decorators.map(function (decorator) { return decorator.text; });
for (var i = 0; i < supportedParameterKeys.length; i++) {
var handler = type_1.Decorator.getRepresentationHandler(supportedParameterKeys[i], this.current.decoratorMap);
var names = handler.getNames();
var index = -1;
for (var j = 0; j < names.length; j++) {
index = decoratorNames.indexOf(names[j]);
if (index !== -1) {
break;
}
}
if (index === -1) {
continue;
}
this.decorator = decorators[index];
this.decoratorHandler = handler;
switch (supportedParameterKeys[i]) {
case 'SERVER_CONTEXT':
return this.getContextParameter();
case 'SERVER_PARAMS':
return this.getRequestParameter();
case 'SERVER_FORM':
return this.getFormParameter();
case 'SERVER_QUERY':
return this.getQueryParameter();
case 'SERVER_BODY':
return this.getBodyParameter();
case 'SERVER_HEADERS':
return this.getHeaderParameter();
case 'SERVER_COOKIES':
return this.getCookieParameter();
case 'SERVER_PATH_PARAMS':
return this.getPathParameter();
case 'SERVER_FILE_PARAM':
return this.getFileParameter();
case 'SERVER_FILES_PARAM':
return this.getFileParameter(true);
}
}
return this.getBodyParameter();
};
ParameterGenerator.prototype.getCurrentLocation = function () {
var methodId = this.parameter.parent.name;
var controllerId = this.parameter.parent.parent.name;
return controllerId.text + "." + methodId.text;
};
ParameterGenerator.prototype.getRequestParameter = function () {
var parameterName = this.parameter.name.text;
var name = parameterName;
var type = this.getValidatedType(this.parameter);
if (!this.supportsBodyParameters(this.method)) {
throw new Error("Param can't support '" + this.getCurrentLocation() + "' method.");
}
if (typeof this.decoratorHandler !== 'undefined' && typeof this.decorator !== 'undefined') {
var argument = this.decoratorHandler.getDecoratorPropertyValueAsItem(this.decorator, this.decoratorHandler.getPropertyByType(this.decorator.text));
if (typeof argument === 'string') {
name = argument;
}
}
return {
description: this.getParameterDescription(this.parameter),
in: 'param',
name: name || parameterName,
parameterName: parameterName,
required: !this.parameter.questionToken,
type: type
};
};
ParameterGenerator.prototype.getContextParameter = function () {
var parameterName = this.parameter.name.text;
return {
description: this.getParameterDescription(this.parameter),
in: 'context',
name: parameterName,
parameterName: parameterName,
required: !this.parameter.questionToken,
type: null
};
};
/*
private getFileParameter(parameter: ts.ParameterDeclaration): Parameter {
const parameterName = (parameter.name as ts.Identifier).text;
if (!this.supportsBodyParameters(this.method)) {
throw new Error(`FileParam can't support '${this.getCurrentLocation()}' method.`);
}
return {
description: this.getParameterDescription(parameter),
in: 'formData',
name: getDecoratorTextValue(this.parameter, ident => ident.text === 'FileParam') || parameterName,
parameterName: parameterName,
required: !parameter.questionToken,
type: { typeName: 'file' }
};
}
*/
ParameterGenerator.prototype.getFileParameter = function (isArray) {
var parameterName = this.parameter.name.text;
var name = parameterName;
if (!this.supportsBodyParameters(this.method)) {
throw new Error("File(s)Param can't support '" + this.getCurrentLocation() + "' method.");
}
if (typeof this.decoratorHandler !== 'undefined' && typeof this.decorator !== 'undefined') {
var argument = this.decoratorHandler.getDecoratorPropertyValueAsItem(this.decorator, this.decoratorHandler.getPropertyByType(this.decorator.text));
if (typeof argument === 'string') {
name = argument;
}
}
var elementType = { typeName: 'file' };
var type;
if (isArray) {
type = { typeName: 'array', elementType: elementType };
}
else {
type = elementType;
}
return {
description: this.getParameterDescription(this.parameter),
in: 'formData',
name: name || parameterName,
parameterName: parameterName,
required: !this.parameter.questionToken && !this.parameter.initializer,
type: type
};
};
ParameterGenerator.prototype.getFormParameter = function () {
var parameterName = this.parameter.name.text;
var name = parameterName;
var type = this.getValidatedType(this.parameter);
if (!this.supportsBodyParameters(this.method)) {
throw new Error("Form can't support '" + this.getCurrentLocation() + "' method.");
}
if (typeof this.decoratorHandler !== 'undefined' && typeof this.decorator !== 'undefined') {
var argument = this.decoratorHandler.getDecoratorPropertyValueAsItem(this.decorator, this.decoratorHandler.getPropertyByType(this.decorator.text));
if (typeof argument === 'string') {
name = argument;
}
}
return {
description: this.getParameterDescription(this.parameter),
in: 'formData',
name: name || parameterName,
parameterName: parameterName,
required: !this.parameter.questionToken && !this.parameter.initializer,
type: type
};
};
ParameterGenerator.prototype.getCookieParameter = function () {
var parameterName = this.parameter.name.text;
var name = parameterName;
var type = this.getValidatedType(this.parameter);
if (!this.supportPathDataType(type)) {
throw new Error("Cookie can't support '" + this.getCurrentLocation() + "' method.");
}
if (typeof this.decoratorHandler !== 'undefined' && typeof this.decorator !== 'undefined') {
var argument = this.decoratorHandler.getDecoratorPropertyValueAsItem(this.decorator, this.decoratorHandler.getPropertyByType(this.decorator.text));
if (typeof argument === 'string') {
name = argument;
}
}
return {
description: this.getParameterDescription(this.parameter),
in: 'cookie',
name: name || parameterName,
parameterName: parameterName,
required: !this.parameter.questionToken && !this.parameter.initializer,
type: type
};
};
ParameterGenerator.prototype.getBodyParameter = function () {
var parameterName = this.parameter.name.text;
var name = parameterName;
var type = this.getValidatedType(this.parameter);
if (!this.supportsBodyParameters(this.method)) {
throw new Error("Body can't support " + this.method + " method");
}
if (typeof this.decoratorHandler !== 'undefined' && typeof this.decorator !== 'undefined') {
var argument = this.decoratorHandler.getDecoratorPropertyValueAsItem(this.decorator, this.decoratorHandler.getPropertyByType(this.decorator.text));
if (typeof argument === 'string') {
name = argument;
}
}
return {
description: this.getParameterDescription(this.parameter),
in: 'body',
name: name || parameterName,
parameterName: parameterName,
required: !this.parameter.questionToken && !this.parameter.initializer,
type: type
};
};
ParameterGenerator.prototype.getHeaderParameter = function () {
var parameterName = this.parameter.name.text;
var name = parameterName;
var type = this.getValidatedType(this.parameter);
if (!this.supportPathDataType(type)) {
throw new InvalidParameterException("Parameter '" + parameterName + "' can't be passed as a header parameter in '" + this.getCurrentLocation() + "'.");
}
if (typeof this.decoratorHandler !== 'undefined' && typeof this.decorator !== 'undefined') {
var argument = this.decoratorHandler.getDecoratorPropertyValueAsItem(this.decorator, this.decoratorHandler.getPropertyByType(this.decorator.text));
if (typeof argument === 'string') {
name = argument;
}
}
return {
description: this.getParameterDescription(this.parameter),
in: 'header',
name: name || parameterName,
parameterName: parameterName,
required: !this.parameter.questionToken && !this.parameter.initializer,
type: type
};
};
ParameterGenerator.prototype.getQueryParameter = function () {
var parameterName = this.parameter.name.text;
var type = this.getValidatedType(this.parameter);
if (!this.supportQueryDataType(type)) {
/*
const arrayType = getCommonPrimitiveAndArrayUnionType(parameter.type);
if (arrayType && this.supportQueryDataType(arrayType)) {
type = arrayType;
} else {
throw new InvalidParameterException(`Parameter '${parameterName}' can't be passed as a query parameter in '${this.getCurrentLocation()}'.`);
}
*/
// throw new InvalidParameterException(`Parameter '${parameterName}' can't be passed as a query parameter in '${this.getCurrentLocation()}'.`);
}
var name = parameterName;
var options = {};
if (typeof this.decoratorHandler !== 'undefined' && typeof this.decorator !== 'undefined') {
var properties = this.decoratorHandler.getPropertiesByTypes(this.decorator.text, ['SIMPLE', 'OPTIONS']);
// tslint:disable-next-line:forin
for (var key in properties) {
if (!properties.hasOwnProperty(key)) {
continue;
}
switch (key) {
case 'SIMPLE':
var propertyName = this.decoratorHandler.getDecoratorPropertyValueAsItem(this.decorator, properties[key]);
if (typeof propertyName !== 'undefined') {
name = propertyName;
}
break;
case 'OPTIONS':
var propertyOptions = this.decoratorHandler.getDecoratorPropertyValueAsItem(this.decorator, properties[key]);
if (typeof propertyOptions !== 'undefined') {
options = propertyOptions;
}
break;
}
}
}
return {
allowEmptyValue: options.allowEmptyValue,
collectionFormat: options.collectionFormat,
default: utils_2.getInitializerValue(this.parameter.initializer, this.current.typeChecker, type),
description: this.getParameterDescription(this.parameter),
in: 'query',
maxItems: options.maxItems,
minItems: options.minItems,
name: name,
parameterName: parameterName,
required: !this.parameter.questionToken && !this.parameter.initializer,
type: type
};
};
ParameterGenerator.prototype.getPathParameter = function () {
var parameterName = this.parameter.name.text;
var pathName = parameterName;
var type = this.getValidatedType(this.parameter);
if (typeof this.decoratorHandler !== 'undefined' && typeof this.decorator !== 'undefined') {
var argument = this.decoratorHandler.getDecoratorPropertyValueAsItem(this.decorator, this.decoratorHandler.getPropertyByType(this.decorator.text));
if (typeof argument === 'string') {
pathName = argument;
}
}
if (!this.supportPathDataType(type)) {
throw new InvalidParameterException("Parameter '" + parameterName + ":" + type + "' can't be passed as a path parameter in '" + this.getCurrentLocation() + "'.");
}
if ((!this.path.includes("{" + pathName + "}")) && (!this.path.includes(":" + pathName))) {
throw new Error("Parameter '" + parameterName + "' can't match in path: '" + this.path + "'");
}
return {
description: this.getParameterDescription(this.parameter),
in: 'path',
name: pathName,
parameterName: parameterName,
required: true,
type: type
};
};
ParameterGenerator.prototype.getParameterDescription = function (node) {
var symbol = this.current.typeChecker.getSymbolAtLocation(node.name);
if (symbol) {
var comments = symbol.getDocumentationComment(this.current.typeChecker);
if (comments.length) {
return ts.displayPartsToString(comments);
}
}
return '';
};
ParameterGenerator.prototype.supportsBodyParameters = function (method) {
return ['delete', 'post', 'put', 'patch', 'get'].some(function (m) { return m === method; });
};
ParameterGenerator.prototype.supportPathDataType = function (parameterType) {
return ['string', 'integer', 'long', 'float', 'double', 'date', 'datetime', 'buffer', 'boolean', 'enum'].find(function (t) { return t === parameterType.typeName; });
};
ParameterGenerator.prototype.supportQueryDataType = function (parameterType) {
// Copied from supportPathDataType and added 'array'. Not sure if all options apply to queries, but kept to avoid breaking change.
return ['string', 'integer', 'long', 'float', 'double', 'date',
'datetime', 'buffer', 'boolean', 'enum', 'array', 'object'].find(function (t) { return t === parameterType.typeName; });
};
ParameterGenerator.prototype.getValidatedType = function (parameter) {
var typeNode = parameter.type;
if (!typeNode) {
var type = this.current.typeChecker.getTypeAtLocation(parameter);
typeNode = this.current.typeChecker.typeToTypeNode(type, undefined, ts.NodeBuilderFlags.NoTruncation);
}
return new resolver_1.TypeNodeResolver(typeNode, this.current, parameter).resolve();
};
return ParameterGenerator;
}());
exports.ParameterGenerator = ParameterGenerator;
var InvalidParameterException = /** @class */ (function (_super) {
__extends(InvalidParameterException, _super);
function InvalidParameterException() {
return _super !== null && _super.apply(this, arguments) || this;
}
return InvalidParameterException;
}(Error));
//# sourceMappingURL=parameterGenerator.js.map