typescript-rest-swagger
Version:
Generate Swagger files from a typescript-rest project
275 lines • 13.7 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 decoratorUtils_1 = require("../utils/decoratorUtils");
var metadataGenerator_1 = require("./metadataGenerator");
var resolveType_1 = require("./resolveType");
var ParameterGenerator = /** @class */ (function () {
function ParameterGenerator(parameter, method, path, genericTypeMap) {
this.parameter = parameter;
this.method = method;
this.path = path;
this.genericTypeMap = genericTypeMap;
}
ParameterGenerator.prototype.generate = function () {
var _this = this;
var decoratorName = decoratorUtils_1.getDecoratorName(this.parameter, function (identifier) { return _this.supportParameterDecorator(identifier.text); });
switch (decoratorName) {
case 'Param':
return this.getRequestParameter(this.parameter);
case 'CookieParam':
return this.getCookieParameter(this.parameter);
case 'FormParam':
return this.getFormParameter(this.parameter);
case 'HeaderParam':
return this.getHeaderParameter(this.parameter);
case 'QueryParam':
return this.getQueryParameter(this.parameter);
case 'PathParam':
return this.getPathParameter(this.parameter);
case 'FileParam':
return this.getFileParameter(this.parameter);
case 'FilesParam':
return this.getFilesParameter(this.parameter);
case 'Context':
case 'ContextRequest':
case 'ContextResponse':
case 'ContextNext':
case 'ContextLanguage':
case 'ContextAccept':
return this.getContextParameter(this.parameter);
default:
return this.getBodyParameter(this.parameter);
}
};
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 (parameter) {
var parameterName = parameter.name.text;
var type = this.getValidatedType(parameter);
if (!this.supportsBodyParameters(this.method)) {
throw new Error("Param can't support '" + this.getCurrentLocation() + "' method.");
}
return {
description: this.getParameterDescription(parameter),
in: 'param',
name: decoratorUtils_1.getDecoratorTextValue(this.parameter, function (ident) { return ident.text === 'Param'; }) || parameterName,
parameterName: parameterName,
required: !parameter.questionToken,
type: type
};
};
ParameterGenerator.prototype.getContextParameter = function (parameter) {
var parameterName = parameter.name.text;
return {
description: this.getParameterDescription(parameter),
in: 'context',
name: parameterName,
parameterName: parameterName,
required: !parameter.questionToken,
type: { typeName: '' }
};
};
ParameterGenerator.prototype.getFileParameter = function (parameter) {
var parameterName = parameter.name.text;
if (!this.supportsBodyParameters(this.method)) {
throw new Error("FileParam can't support '" + this.getCurrentLocation() + "' method.");
}
return {
description: this.getParameterDescription(parameter),
in: 'formData',
name: decoratorUtils_1.getDecoratorTextValue(this.parameter, function (ident) { return ident.text === 'FileParam'; }) || parameterName,
parameterName: parameterName,
required: !parameter.questionToken,
type: { typeName: 'file' }
};
};
ParameterGenerator.prototype.getFilesParameter = function (parameter) {
var parameterName = parameter.name.text;
if (!this.supportsBodyParameters(this.method)) {
throw new Error("FilesParam can't support '" + this.getCurrentLocation() + "' method.");
}
return {
description: this.getParameterDescription(parameter),
in: 'formData',
name: decoratorUtils_1.getDecoratorTextValue(this.parameter, function (ident) { return ident.text === 'FilesParam'; }) || parameterName,
parameterName: parameterName,
required: !parameter.questionToken,
type: { typeName: 'file' }
};
};
ParameterGenerator.prototype.getFormParameter = function (parameter) {
var parameterName = parameter.name.text;
var type = this.getValidatedType(parameter);
if (!this.supportsBodyParameters(this.method)) {
throw new Error("Form can't support '" + this.getCurrentLocation() + "' method.");
}
return {
description: this.getParameterDescription(parameter),
in: 'formData',
name: decoratorUtils_1.getDecoratorTextValue(this.parameter, function (ident) { return ident.text === 'FormParam'; }) || parameterName,
parameterName: parameterName,
required: !parameter.questionToken && !parameter.initializer,
type: type
};
};
ParameterGenerator.prototype.getCookieParameter = function (parameter) {
var parameterName = parameter.name.text;
// const type = this.getValidatedType(parameter);
// if (!this.supportPathDataType(type)) {
// throw new Error(`Cookie can't support '${this.getCurrentLocation()}' method.`);
// }
return {
description: this.getParameterDescription(parameter),
in: 'cookie',
name: decoratorUtils_1.getDecoratorTextValue(this.parameter, function (ident) { return ident.text === 'CookieParam'; }) || parameterName,
parameterName: parameterName,
required: !parameter.questionToken && !parameter.initializer,
type: { typeName: '' }
};
};
ParameterGenerator.prototype.getBodyParameter = function (parameter) {
var parameterName = parameter.name.text;
var type = this.getValidatedType(parameter);
if (!this.supportsBodyParameters(this.method)) {
throw new Error("Body can't support " + this.method + " method");
}
return {
description: this.getParameterDescription(parameter),
in: 'body',
name: parameterName,
parameterName: parameterName,
required: !parameter.questionToken && !parameter.initializer,
type: type
};
};
ParameterGenerator.prototype.getHeaderParameter = function (parameter) {
var parameterName = parameter.name.text;
var type = this.getValidatedType(parameter);
if (!this.supportPathDataType(type)) {
throw new InvalidParameterException("Parameter '" + parameterName + "' can't be passed as a header parameter in '" + this.getCurrentLocation() + "'.");
}
return {
description: this.getParameterDescription(parameter),
in: 'header',
name: decoratorUtils_1.getDecoratorTextValue(this.parameter, function (ident) { return ident.text === 'HeaderParam'; }) || parameterName,
parameterName: parameterName,
required: !parameter.questionToken && !parameter.initializer,
type: type
};
};
ParameterGenerator.prototype.getQueryParameter = function (parameter) {
var parameterName = parameter.name.text;
var parameterOptions = decoratorUtils_1.getDecoratorOptions(this.parameter, function (ident) { return ident.text === 'QueryParam'; }) || {};
var type = this.getValidatedType(parameter);
if (!this.supportQueryDataType(type)) {
var arrayType = resolveType_1.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() + "'.");
}
}
return {
// allowEmptyValue: parameterOptions.allowEmptyValue,
collectionFormat: parameterOptions.collectionFormat,
default: this.getDefaultValue(parameter.initializer),
description: this.getParameterDescription(parameter),
in: 'query',
// maxItems: parameterOptions.maxItems,
// minItems: parameterOptions.minItems,
name: decoratorUtils_1.getDecoratorTextValue(this.parameter, function (ident) { return ident.text === 'QueryParam'; }) || parameterName,
parameterName: parameterName,
required: !parameter.questionToken && !parameter.initializer,
type: type
};
};
ParameterGenerator.prototype.getPathParameter = function (parameter) {
var parameterName = parameter.name.text;
var type = this.getValidatedType(parameter);
var pathName = decoratorUtils_1.getDecoratorTextValue(this.parameter, function (ident) { return ident.text === 'PathParam'; }) || parameterName;
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(parameter),
in: 'path',
name: pathName,
parameterName: parameterName,
required: true,
type: type
};
};
ParameterGenerator.prototype.getParameterDescription = function (node) {
var symbol = metadataGenerator_1.MetadataGenerator.current.typeChecker.getSymbolAtLocation(node.name);
if (symbol) {
var comments = symbol.getDocumentationComment(metadataGenerator_1.MetadataGenerator.current.typeChecker);
if (comments.length) {
return ts.displayPartsToString(comments);
}
}
return '';
};
ParameterGenerator.prototype.supportsBodyParameters = function (method) {
return ['delete', 'post', 'put', 'patch'].some(function (m) { return m === method; });
};
ParameterGenerator.prototype.supportParameterDecorator = function (decoratorName) {
return ['HeaderParam', 'QueryParam', 'Param', 'FileParam',
'PathParam', 'FilesParam', 'FormParam', 'CookieParam',
'Context', 'ContextRequest', 'ContextResponse', 'ContextNext',
'ContextLanguage', 'ContextAccept'].some(function (d) { return d === decoratorName; });
};
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'].find(function (t) { return t === parameterType.typeName; });
};
ParameterGenerator.prototype.getValidatedType = function (parameter) {
if (!parameter.type) {
throw new Error("Parameter " + parameter.name + " doesn't have a valid type assigned in '" + this.getCurrentLocation() + "'.");
}
return resolveType_1.resolveType(parameter.type, this.genericTypeMap);
};
ParameterGenerator.prototype.getDefaultValue = function (initializer) {
if (!initializer) {
return;
}
return resolveType_1.getLiteralValue(initializer);
};
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