UNPKG

@tsed/schema

Version:
161 lines (160 loc) 5.41 kB
import { __decorate, __metadata } from "tslib"; import { DecoratorTypes, deepMerge, descriptorOf, isFunction, prototypeOf, Store } from "@tsed/core"; import { JsonEntityComponent } from "../decorators/config/jsonEntityComponent.js"; import { isSuccessStatus } from "../utils/isSuccessStatus.js"; import { JsonEntityStore } from "./JsonEntityStore.js"; import { JsonOperation } from "./JsonOperation.js"; import { JsonSchema } from "./JsonSchema.js"; let JsonMethodStore = class JsonMethodStore extends JsonEntityStore { constructor(options) { super({ store: Store.fromMethod(options.target, options.propertyKey), descriptor: descriptorOf(options.target, options.propertyKey), ...options }); this.parent = JsonEntityStore.from(this.target); this.middlewares = []; this.beforeMiddlewares = []; this.afterMiddlewares = []; /** * Ref to JsonOperation when the decorated object is a method. */ this.operation = new JsonOperation(); /** * List of children JsonEntityStore (properties or methods or params) */ this.children = new Map(); const { beforeMiddlewares = [], middlewares = [], afterMiddlewares = [] } = options; this.after(afterMiddlewares); this.before(beforeMiddlewares); this.use(middlewares); } get params() { return this.parameters; } get view() { return this.store.get("view"); } set view(view) { this.store.set("view", view); } get acceptMimes() { return this.store.get("acceptMimes", []); } set acceptMimes(mimes) { this.store.set("acceptMimes", mimes); } get parameters() { return [...this.children.values()]; } get operationPaths() { return this.operation.operationPaths; } get collectionType() { return this.schema.getTarget(); } set collectionType(type) { console.trace("collectionType is deprecated, use schema.collectionClass instead"); } get isCollection() { return this.schema.isCollection; } get schema() { if (this._schema) { return this._schema; } const responses = this.operation.getResponses(); const [, response] = [...responses.entries()].find(([key, response]) => { return isSuccessStatus(key); }) || []; if (response) { const firstMediaType = response.getContent().values().next().value; if (firstMediaType) { this._schema = firstMediaType.schema(); } } else { this._schema = new JsonSchema(); } return this._schema; } /** * Get an endpoint. * @param target * @param propertyKey * @param descriptor */ static get(target, propertyKey, descriptor) { descriptor = descriptor || descriptorOf(prototypeOf(target), propertyKey); return JsonEntityStore.from(prototypeOf(target), propertyKey, descriptor); } /** * TODO must be located on JsonOperation level directly * @param status * @param contentType * @param includes */ getResponseOptions(status, { contentType = "application/json", includes } = {}) { const media = this.operation.getResponseOf(status).getMedia(contentType, false); if (media && media.has("schema")) { const allowedGroups = media.schema().getAllowedGroups(); let groups = media.schema().getGroups(); if (includes && allowedGroups?.size) { groups = [...(groups || []), ...includes.filter((include) => allowedGroups.has(include))]; } return { type: media.schema().collectionClass, groups }; } return { type: this.type || Object }; } /** * Append middlewares to the beforeMiddlewares list. * @param args * @returns {EndpointMetadata} */ before(args) { this.beforeMiddlewares = this.beforeMiddlewares.concat(args).filter(isFunction); return this; } /** * Append middlewares to the afterMiddlewares list. * @param args * @returns {EndpointMetadata} */ after(args) { this.afterMiddlewares = this.afterMiddlewares.concat(args).filter(isFunction); return this; } /** * Store all arguments collected via Annotation. * @param args */ use(args) { this.middlewares = this.middlewares.concat(args).filter(isFunction); return this; } /** * Find the value at the controller level. Let this value be extended or overridden by the endpoint itself. * * @param key * @returns {any} */ get(key) { const ctrlValue = Store.from(this.target).get(key); return deepMerge(ctrlValue, this.store.get(key)); } getParamTypes() { return [...this.children.values()].reduce((obj, item) => ({ ...obj, [item.paramType]: true }), {}); } build() { this.parent.children.set(this.propertyName, this); } }; JsonMethodStore = __decorate([ JsonEntityComponent(DecoratorTypes.METHOD), __metadata("design:paramtypes", [Object]) ], JsonMethodStore); export { JsonMethodStore }; export const EndpointMetadata = JsonMethodStore;