mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-23 11:37:02 -04:00
170 lines
4.6 KiB
TypeScript
170 lines
4.6 KiB
TypeScript
/*
|
|
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
import { applyDecorators, Header, HttpCode } from '@nestjs/common';
|
|
import {
|
|
ApiBadRequestResponse,
|
|
ApiConflictResponse,
|
|
ApiCreatedResponse,
|
|
ApiInternalServerErrorResponse,
|
|
ApiNoContentResponse,
|
|
ApiNotFoundResponse,
|
|
ApiOkResponse,
|
|
ApiProduces,
|
|
ApiUnauthorizedResponse,
|
|
} from '@nestjs/swagger';
|
|
|
|
import { BaseDto } from '../../utils/base.dto.';
|
|
import {
|
|
badRequestDescription,
|
|
conflictDescription,
|
|
createdDescription,
|
|
internalServerErrorDescription,
|
|
noContentDescription,
|
|
notFoundDescription,
|
|
okDescription,
|
|
unauthorizedDescription,
|
|
} from './descriptions';
|
|
|
|
export type HttpStatusCodes =
|
|
| 200
|
|
| 201
|
|
| 204
|
|
| 400
|
|
| 401
|
|
| 403
|
|
| 404
|
|
| 409
|
|
| 500;
|
|
|
|
/**
|
|
* Defines what the open api route should document.
|
|
*
|
|
* This makes it possible to document
|
|
* - description
|
|
* - return object
|
|
* - if the return object is an array
|
|
* - the mimeType of the response
|
|
*/
|
|
export interface HttpStatusCodeWithExtraInformation {
|
|
code: HttpStatusCodes;
|
|
description?: string;
|
|
isArray?: boolean;
|
|
dto?: BaseDto;
|
|
mimeType?: string;
|
|
}
|
|
|
|
/**
|
|
* This decorator is used to document what an api route returns.
|
|
*
|
|
* The decorator can be used on a controller method or on a whole controller class (if one wants to document that every method of the controller returns something).
|
|
*
|
|
* @param httpStatusCodesMaybeWithExtraInformation - list of parameters can either be just the {@link HttpStatusCodes} or a {@link HttpStatusCodeWithExtraInformation}.
|
|
* If only a {@link HttpStatusCodes} is provided a default description will be used.
|
|
*
|
|
* For non-200 successful responses the appropriate {@link HttpCode} decorator is set
|
|
* @constructor
|
|
*/
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention,func-style
|
|
export const OpenApi = (
|
|
...httpStatusCodesMaybeWithExtraInformation: (
|
|
| HttpStatusCodes
|
|
| HttpStatusCodeWithExtraInformation
|
|
)[]
|
|
): // eslint-disable-next-line @typescript-eslint/ban-types
|
|
(<TFunction extends Function, Y>(
|
|
target: object | TFunction,
|
|
propertyKey?: string | symbol,
|
|
descriptor?: TypedPropertyDescriptor<Y>,
|
|
) => void) => {
|
|
const decoratorsToApply: (MethodDecorator | ClassDecorator)[] = [];
|
|
for (const entry of httpStatusCodesMaybeWithExtraInformation) {
|
|
let code: HttpStatusCodes = 200;
|
|
let description: string | undefined = undefined;
|
|
let isArray: boolean | undefined = undefined;
|
|
let dto: BaseDto | undefined = undefined;
|
|
if (typeof entry == 'number') {
|
|
code = entry;
|
|
} else {
|
|
// We've got a HttpStatusCodeWithExtraInformation
|
|
code = entry.code;
|
|
description = entry.description;
|
|
isArray = entry.isArray;
|
|
dto = entry.dto;
|
|
if (entry.mimeType) {
|
|
decoratorsToApply.push(
|
|
ApiProduces(entry.mimeType),
|
|
Header('Content-Type', entry.mimeType),
|
|
);
|
|
}
|
|
}
|
|
switch (code) {
|
|
case 200:
|
|
decoratorsToApply.push(
|
|
ApiOkResponse({
|
|
description: description ?? okDescription,
|
|
isArray: isArray,
|
|
type: () => dto,
|
|
}),
|
|
);
|
|
break;
|
|
case 201:
|
|
decoratorsToApply.push(
|
|
ApiCreatedResponse({
|
|
description: description ?? createdDescription,
|
|
isArray: isArray,
|
|
type: () => dto,
|
|
}),
|
|
HttpCode(201),
|
|
);
|
|
break;
|
|
case 204:
|
|
decoratorsToApply.push(
|
|
ApiNoContentResponse({
|
|
description: description ?? noContentDescription,
|
|
}),
|
|
HttpCode(204),
|
|
);
|
|
break;
|
|
case 400:
|
|
decoratorsToApply.push(
|
|
ApiBadRequestResponse({
|
|
description: description ?? badRequestDescription,
|
|
}),
|
|
);
|
|
break;
|
|
case 401:
|
|
decoratorsToApply.push(
|
|
ApiUnauthorizedResponse({
|
|
description: description ?? unauthorizedDescription,
|
|
}),
|
|
);
|
|
break;
|
|
case 404:
|
|
decoratorsToApply.push(
|
|
ApiNotFoundResponse({
|
|
description: description ?? notFoundDescription,
|
|
}),
|
|
);
|
|
break;
|
|
case 409:
|
|
decoratorsToApply.push(
|
|
ApiConflictResponse({
|
|
description: description ?? conflictDescription,
|
|
}),
|
|
);
|
|
break;
|
|
case 500:
|
|
decoratorsToApply.push(
|
|
ApiInternalServerErrorResponse({
|
|
description: internalServerErrorDescription,
|
|
}),
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return applyDecorators(...decoratorsToApply);
|
|
};
|