@nestjs/swagger
Version:
Nest - modern, fast, powerful node.js web framework (@swagger)
102 lines (101 loc) • 5.15 kB
JavaScript
import { isEmpty, isFunction, omit, pick } from 'es-toolkit/compat';
import { DECORATORS } from '../constants.js';
import { isBuiltInType } from '../utils/is-built-in-type.util.js';
import { MimetypeContentWrapper } from './mimetype-content-wrapper.js';
import { ModelPropertiesAccessor } from './model-properties-accessor.js';
import { ResponseObjectMapper } from './response-object-mapper.js';
import { SchemaObjectFactory } from './schema-object-factory.js';
import { StandardSchemaOpenApiConverter } from './standard-schema-openapi.converter.js';
import { SwaggerTypesMapper } from './swagger-types-mapper.js';
export class ResponseObjectFactory {
constructor(standardSchemaConverter) {
this.standardSchemaConverter = standardSchemaConverter;
this.mimetypeContentWrapper = new MimetypeContentWrapper();
this.modelPropertiesAccessor = new ModelPropertiesAccessor();
this.swaggerTypesMapper = new SwaggerTypesMapper();
this.standardSchemaOpenApiConverter = new StandardSchemaOpenApiConverter(this.standardSchemaConverter);
this.schemaObjectFactory = new SchemaObjectFactory(this.modelPropertiesAccessor, this.swaggerTypesMapper, this.standardSchemaConverter);
this.responseObjectMapper = new ResponseObjectMapper();
}
create(response, produces, schemas, factories) {
const { type, isArray } = response;
const schemaOverride = this.getSchemaOverride(response, schemas);
response = omit(response, ['isArray', 'standardSchema']);
if (schemaOverride) {
return this.responseObjectMapper.wrapSchemaWithContent({
...omit(response, ['type']),
schema: isArray
? { type: 'array', items: schemaOverride }
: schemaOverride
}, produces);
}
if (!type) {
return this.responseObjectMapper.wrapSchemaWithContent(response, produces);
}
if (isBuiltInType(type)) {
const typeName = type && isFunction(type) ? type.name : type;
const swaggerType = this.swaggerTypesMapper.mapTypeToOpenAPIType(typeName);
const exampleKeys = ['example', 'examples'];
const baseSchema = isArray
? { type: 'array', items: { type: swaggerType } }
: { type: swaggerType };
const schema = response.nullable
? { ...baseSchema, nullable: true }
: baseSchema;
const content = this.mimetypeContentWrapper.wrap(produces, {
schema,
...pick(response, exampleKeys)
});
return {
...omit(response, [...exampleKeys, 'nullable']),
...content
};
}
const name = this.schemaObjectFactory.exploreModelSchema(type, schemas);
if (isFunction(type) && type.prototype) {
const { prototype } = type;
const links = {};
const properties = this.modelPropertiesAccessor.getModelProperties(prototype);
const generateLink = (controllerPrototype, method, parameter, field) => {
if (!factories) {
return;
}
const linkName = factories.linkName(controllerPrototype.constructor.name, method.name, field);
links[linkName] = {
operationId: factories.operationId(controllerPrototype.constructor.name, method.name),
parameters: {
[parameter]: `$response.body#/${field}`
}
};
};
for (const key of properties) {
const metadata = Reflect.getMetadata(DECORATORS.API_MODEL_PROPERTIES, prototype, key) ?? {};
if (!metadata.link) {
continue;
}
const linkedType = metadata.link();
const linkedGetterInfo = Reflect.getMetadata(DECORATORS.API_DEFAULT_GETTER, linkedType.prototype);
if (!linkedGetterInfo) {
continue;
}
const { getter, parameter, prototype: controllerPrototype } = linkedGetterInfo;
generateLink(controllerPrototype, getter, parameter, key);
}
const customLinks = Reflect.getMetadata(DECORATORS.API_LINK, prototype);
for (const customLink of customLinks ?? []) {
const { method, parameter, field, prototype: controllerPrototype } = customLink;
generateLink(controllerPrototype, method, parameter, field);
}
if (!isEmpty(links)) {
response.links = Object.assign(links, response.links);
}
}
if (isArray) {
return this.responseObjectMapper.toArrayRefObject(response, name, produces);
}
return this.responseObjectMapper.toRefObject(response, name, produces);
}
getSchemaOverride(response, schemas) {
return this.standardSchemaOpenApiConverter.convertInto(response.standardSchema, schemas, 'output');
}
}