@tsed/schema
Version:
JsonSchema module for Ts.ED Framework
179 lines (178 loc) • 5.7 kB
JavaScript
import { deepMerge, uniq, uniqBy } from "@tsed/core";
import { isRedirectionStatus, isSuccessStatus } from "../utils/isSuccessStatus.js";
import { JsonMap } from "./JsonMap.js";
import { JsonParameter } from "./JsonParameter.js";
import { JsonResponse } from "./JsonResponse.js";
import { JsonSchema } from "./JsonSchema.js";
export class JsonMethodPath extends JsonMap {
constructor(method, path) {
super();
this.method = method;
this.path = path;
}
summary(summary) {
super.set("summary", summary);
return this;
}
description(description) {
super.set("description", description);
return this;
}
}
export class JsonOperation extends JsonMap {
#status;
#redirection;
constructor(obj = {}) {
super({ parameters: [], responses: new JsonMap(), ...obj });
this.$kind = "operation";
this.operationPaths = new Map();
this.#redirection = false;
}
get response() {
return this.getResponses().get(this.getStatus().toString());
}
get status() {
return this.#status;
}
tags(tags) {
super.set("tags", tags);
return this;
}
addTags(tags) {
tags = uniqBy([...(this.get("tags") || []), ...tags], "name");
return this.tags(tags);
}
summary(summary) {
super.set("summary", summary);
return this;
}
operationId(operationId) {
this.set("operationId", operationId);
return this;
}
responses(responses) {
this.set("responses", responses);
return this;
}
defaultStatus(status) {
this.#status = status;
return this;
}
getStatus() {
return this.#status || 200;
}
setRedirection(status = 302) {
this.#redirection = true;
this.#status = status;
return this;
}
isRedirection(status) {
if (this.#redirection) {
if (status) {
return isRedirectionStatus(status);
}
}
return this.#redirection;
}
addResponse(statusCode, response) {
if ((isSuccessStatus(statusCode) || isRedirectionStatus(statusCode)) && !this.#status) {
const res = this.getResponseOf(200);
this.getResponses().set(statusCode.toString(), res).delete("200");
this.defaultStatus(Number(statusCode));
}
const currentCode = statusCode === "default" ? this.getStatus().toString() : statusCode.toString();
const currentResponse = this.getResponses().get(currentCode);
if (!currentResponse) {
response.status = Number(currentCode);
this.getResponses().set(currentCode, response);
}
else {
response.forEach((value, key) => {
if (!["content"].includes(key)) {
currentResponse.set(key, deepMerge(currentResponse.get(key), value));
}
});
currentResponse.status = Number(currentCode);
}
return this;
}
getResponses() {
return this.get("responses");
}
getResponseOf(status) {
return (status === "default" ? this.response : this.getResponses().get(String(status))) || new JsonResponse();
}
ensureResponseOf(status) {
this.addResponse(status, this.getResponseOf(status));
return this.getResponseOf(status);
}
getHeadersOf(status) {
return this.getResponseOf(status).get("headers") || {};
}
getContentTypeOf(status) {
return [...this.getResponseOf(status).get("content").keys()].slice(-1)[0];
}
security(security) {
this.set("security", security);
return this;
}
addSecurityScopes(name, scopes) {
const security = this.get("security") || {};
security[name] = uniq([...(security[name] || []), ...scopes]);
return this.security(security);
}
description(description) {
super.set("description", description);
return this;
}
deprecated(deprecated) {
super.set("deprecated", deprecated);
return this;
}
addAllowedGroupsParameter(allowedGroups) {
const jsonParameter = new JsonParameter();
jsonParameter.in("query").name("includes");
jsonParameter.schema(JsonSchema.from({
type: "array",
items: {
type: "string",
enum: [...allowedGroups]
}
}));
this.addParameter(-1, jsonParameter);
return this;
}
parameters(parameters) {
super.set("parameters", parameters);
return this;
}
addParameter(index, parameter) {
if (index === -1) {
index = this.get("parameters").length;
}
this.get("parameters")[index] = parameter;
}
consumes(consumes) {
super.set("consumes", consumes);
return this;
}
produces(produces) {
super.set("produces", produces);
return this;
}
addProduce(produce) {
const produces = uniq([].concat(this.get("produces"), produce)).filter(Boolean);
this.set("produces", produces);
}
addOperationPath(method, path) {
const operationPath = new JsonMethodPath(method, path);
this.operationPaths.set(String(method) + String(path), operationPath);
return operationPath;
}
getAllowedOperationPath(allowedVerbs) {
if (!allowedVerbs) {
return [...this.operationPaths.values()];
}
return [...this.operationPaths.values()].filter(({ method }) => method && allowedVerbs.includes(method.toUpperCase()));
}
}