@nestia/sdk
Version:
Nestia SDK and Swagger generator
111 lines (102 loc) • 3.98 kB
text/typescript
import { OpenApi } from "@samchon/openapi";
import { VariadicSingleton } from "tstl";
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
import { ITypedHttpRoute } from "../../structures/ITypedHttpRoute";
import { StringUtil } from "../../utils/StringUtil";
import { SwaggerDescriptionComposer } from "./SwaggerDescriptionComposer";
export namespace SwaggerOperationResponseComposer {
export const compose = (props: {
schema: (metadata: Metadata) => OpenApi.IJsonSchema | undefined;
route: ITypedHttpRoute;
}): Record<string, OpenApi.IOperation.IResponse> => {
const output: Record<string, OpenApi.IOperation.IResponse> = {};
// FROM DECORATOR
for (const [status, error] of Object.entries(props.route.exceptions))
output[status] = {
description: error.description ?? undefined,
content: {
"application/json": {
schema: props.schema(error.metadata),
example: error.example,
examples: error.examples,
},
},
};
// FROM COMMENTS
for (const tag of props.route.jsDocTags) {
if (tag.name !== "throw" && tag.name !== "throws") continue;
const text: string | undefined = tag.text?.find(
(elem) => elem.kind === "text",
)?.text;
if (text === undefined) continue;
const elements: string[] = text.split(" ").map((str) => str.trim());
const status: string = elements[0];
if (
isNaN(Number(status)) &&
status !== "2XX" &&
status !== "3XX" &&
status !== "4XX" &&
status !== "5XX"
)
continue;
const description: string | undefined =
elements.length === 1 ? undefined : elements.slice(1).join(" ");
const oldbie = output[status];
if (description && oldbie !== undefined)
oldbie.description ??= description;
else if (oldbie === undefined)
output[status] = {
description: description,
content: {
"application/json": {
schema: {},
},
},
};
}
// SUCCESS
const description: string | undefined =
SwaggerDescriptionComposer.descriptionFromJsDocTag({
jsDocTags: props.route.jsDocTags,
tag: "returns",
}) ??
SwaggerDescriptionComposer.descriptionFromJsDocTag({
jsDocTags: props.route.jsDocTags,
tag: "return",
});
output[
props.route.success.status ??
(props.route.method.toLowerCase() === "post" ? 201 : 200)
] = {
description: props.route.success.encrypted
? `${warning.get(!!description, props.route.method)}${description ?? ""}`
: (description ?? ""),
content: props.route.success.contentType
? {
[props.route.success.contentType]: {
schema: props.schema(props.route.success.metadata),
example: props.route.success.example,
examples: props.route.success.examples,
},
}
: undefined,
...(props.route.success.encrypted ? { "x-nestia-encrypted": true } : {}),
};
return output;
};
}
const warning = new VariadicSingleton((described: boolean, method: string) => {
const summary: string = "Response data have been encrypted.";
const component: string = `[EncryptedRoute.${StringUtil.capitalize(method)}](https://github.com/samchon/@nestia/core#encryptedroute)`;
const content: string[] = [
"## Warning",
"",
summary,
"",
`The response body data would be encrypted as "AES-128(256) / CBC mode / PKCS#5 Padding / Base64 Encoding", through the ${component} component.`,
"",
`Therefore, just utilize this swagger editor only for referencing. If you need to call the real API, using [SDK](https://github.com/samchon/nestia#software-development-kit) would be much better.`,
];
if (described === true) content.push("", "----------------", "", "");
return content.join("\n");
});