UNPKG

@creamapi/cream

Version:

Concise REST API Maker - An extension library for express to create REST APIs faster

272 lines (271 loc) 13.1 kB
import 'reflect-metadata'; import { HttpMethod } from '../HttpUtils/HttpMethod'; import { ExpressModule } from './ExpressModule'; export declare const BODY_METADATA_KEY: unique symbol; export declare const PARAMS_METADATA_KEY: unique symbol; export declare const HEADERS_METADATA_KEY: unique symbol; export declare const MIDDLEWARE_METADATA_KEY: unique symbol; export declare const TRANSACTION_MANAGER_METADATA_KEY: unique symbol; /** * This method is used to declare a method of a class (that must extend {@link ExpressModule}) * to be an API endpoint. This endpoint is bound to the router representing the class basepoint. * The basepoint (or zone) is defined by using {@link ExpressController} decorator.\ * The decorated method is not altered and that means it can be used as a normal method. * * @remarks * It is suggested to use {@link Get}, {@link Post}, {@link Put} and {@link Delete}\ * Methods are bound to the router in a topdown approach, this means that from Express's point of * view the top method is called first if two paths collide. Two paths collide when both the path and the http ù * method is the same so a path x bound to a Get request will not collide to the same path bound to a Post request. * @example * ```ts * import { ExpressController, ExpressModule, ExpressCall, HttpMethod } from "@creamapi/cream"; * * \@ExpressController("/my-base-route") * export class MyController extends ExpressModule { * \@ExpressCall("/hello-world", HttpMethod.GET) * myMethod(): string{ * return "hello, world"; * } * * // It also works with asynchronous methods * \@ExpressCall("/hello-world-async", HttpMethod.GET) * async myMethodAsync(): Promise<string> { * return "hello, async world!"; * } * } * ``` * @param relativePath Is the path relative to the basepoint. The path must follow the Express path definition * @param httpMethod The HTTP Method that must be used for the path. See {@link HttpMethod} for available methods * @returns returns the descriptor of the method. */ export declare function ExpressCall<T extends ExpressModule>(relativePath: string, httpMethod: HttpMethod): (target: T, propertyName: string, descriptor: PropertyDescriptor) => PropertyDescriptor; /** * This method is used to declare a method of a class (that must extend {@link ExpressModule}) * to be an API endpoint as a GET http method. * * This method just works by calling {@link ExpressCall} with {@link HttpMethod.GET} as the second parameter * To understand its behaviour please see {@link ExpressCall}. * * @remarks Methods are bound to the router in a topdown approach, this means that from Express's point of * view the top method is called first if two paths collide. Two paths collide when both the path and the http ù * method is the same so a path x bound to a Get request will not collide to the same path bound to a Post request. * @example * ```ts * import { ExpressController, ExpressModule, ExpressCall, HttpMethod } from "@creamapi/cream"; * * \@ExpressController("/my-base-route") * export class MyController extends ExpressModule { * \@Get("/hello-world") * myMethod(): string{ * return "hello, world"; * } * * // It also works with asynchronous methods * \@Get("/hello-world-async") * async myMethodAsync(): Promise<string> { * return "hello, async world!"; * } * } * ``` * @param relativePath Is the path relative to the basepoint. The path must follow the Express path definition * @returns returns the descriptor of the method. */ export declare function Get<T extends ExpressModule>(relativePath: string): (target: T, propertyName: string, descriptor: PropertyDescriptor) => PropertyDescriptor; /** * This method is used to declare a method of a class (that must extend {@link ExpressModule}) * to be an API endpoint as a POST http method. * * To retrieve the body passed as an argument just use {@link Body} or {@link BodyField}. * * This method just works by calling {@link ExpressCall} with {@link HttpMethod.GET} as the second parameter * To understand its behaviour please see {@link ExpressCall}. * * @remarks * Methods are bound to the router in a topdown approach, this means that from Express's point of * view the top method is called first if two paths collide. Two paths collide when both the path and the http ù * method is the same so a path x bound to a Get request will not collide to the same path bound to a Post request. * * @example * ```ts * import { ExpressController, ExpressModule, ExpressCall, HttpMethod } from "@creamapi/cream"; * * \@ExpressController("/my-base-route") * export class MyController extends ExpressModule { * \@Post("/hello-world") * myMethod(@Body body: any): string{ * return "hello, world"; * } * * // It also works with asynchronous methods * \@Post("/hello-world-async") * async myMethodAsync(@BodyField("myField") myField: string): Promise<string> { * return myField; * } * } * ``` * @param relativePath Is the path relative to the basepoint. The path must follow the Express path definition * @returns returns the descriptor of the method. */ export declare function Post<T extends ExpressModule>(relativePath: string): (target: T, propertyName: string, descriptor: PropertyDescriptor) => PropertyDescriptor; /** * This method is used to declare a method of a class (that must extend {@link ExpressModule}) * to be an API endpoint as a PUT http method. * * To retrieve the body passed as an argument just use {@link Body} or {@link BodyField}. * * This method just works by calling {@link ExpressCall} with {@link HttpMethod.GET} as the second parameter * To understand its behaviour please see {@link ExpressCall}. * * @remarks Methods are bound to the router in a topdown approach, this means that from Express's point of * view the top method is called first if two paths collide. Two paths collide when both the path and the http ù * method is the same so a path x bound to a Get request will not collide to the same path bound to a Post request. * @example * ```ts * import { ExpressController, ExpressModule, ExpressCall, HttpMethod } from "@creamapi/cream"; * * \@ExpressController("/my-base-route") * export class MyController extends ExpressModule { * \@Put("/hello-world") * myMethod(@Body body: any): string{ * return "hello, world"; * } * * // It also works with asynchronous methods * \@Put("/hello-world-async") * async myMethodAsync(@BodyField("myField") myField: string): Promise<string> { * return myField; * } * } * ``` * @param relativePath Is the path relative to the basepoint. The path must follow the Express path definition * @returns returns the descriptor of the method. */ export declare function Put<T extends ExpressModule>(relativePath: string): (target: T, propertyName: string, descriptor: PropertyDescriptor) => PropertyDescriptor; /** * This method is used to declare a method of a class (that must extend {@link ExpressModule}) * to be an API endpoint as a DELETE http method. * * To retrieve the body passed as an argument just use {@link Body} or {@link BodyField}. * * This method just works by calling {@link ExpressCall} with {@link HttpMethod.GET} as the second parameter * To understand its behaviour please see {@link ExpressCall}. * * @remarks * Methods are bound to the router in a topdown approach, this means that from Express's point of * view the top method is called first if two paths collide. Two paths collide when both the path and the http ù * method is the same so a path x bound to a Get request will not collide to the same path bound to a Post request. * * @example * ```ts * import { ExpressController, ExpressModule, ExpressCall, HttpMethod } from "@creamapi/cream"; * * \@ExpressController("/my-base-route") * export class MyController extends ExpressModule { * \@Delete("/hello-world") * myMethod(@Body body: any): string{ * return "hello, world"; * } * * // It also works with asynchronous methods * \@Delete("/hello-world-async") * async myMethodAsync(@BodyField("myField") myField: string): Promise<string> { * return myField; * } * } * ``` * @param relativePath Is the path relative to the basepoint. The path must follow the Express path definition * @returns returns the descriptor of the method. */ export declare function Delete<T extends ExpressModule>(relativePath: string): (target: T, propertyName: string, descriptor: PropertyDescriptor) => PropertyDescriptor; /** * This decorator is used to make a class to be a controller that handles HTTP requests. * The class decorated as a controller must inherit from {@link ExpressModule}. * In practice this will bound any {@link ExpressCall}-decorated method to an express router. * The router is also bound to the baseRoute parameter.\ * The call tree will look something like this: * ``` * / <- this is the basepoint (parameter baseRoute) a controller is bound to * |- router1 <- This is one controller * | |- GET * | | |- /path1 * | | | |- method1-1 <- this is a endpoint * | | | |- method1-2 <- multiple methods can be bound to the same route (aka they collide) * | | |- /path2 * | | | |- method1-3 * | | |- / <- this will look like it is bound to the base path * | | |- method1-4 * | |- POST * | |- PUT * | |- DELETE * |- router2 <- multiple controller can be bound to the same basepoint * | |- GET * | | |- /path1 * | | |- method2-1 <- this method is bound to the same path as method1-1 * | |- POST * | |- PUT * | |- DELETE * |- /new-endpoint <- this is another basepoint. Any method bound to this method will be bound to the base path /new-endpoint * | |- router1 * | |- GET * | |- POST * | |- PUT * | |- DELETE * ``` * @remarks * For whom want to work on low lever prototyping this decorator will alter the prototype of the * decorated class by adding functionalities without altering its behavior, including the constructor. * @param baseRoute the URL to which the controller is bound to * @returns a new class that extends the base decorated class that implements a few functions * that will bound routes to the router. Albeit it is a brand new class its usage is completely * transparent for the users. */ export declare function ExpressController<T extends { new (...args: any[]): ExpressModule; }>(baseRoute: string): (target: T) => T; /** * This parameter decorator will decorate a method parameter by associating it with a field in the body. * This permits the autofill of the parameter with the corresponding field (named fieldName) in the body. * @remarks * If the field is undefined the field will be filled as undefined.\ * If no body is provided to the request then all parameters decorated with BodyField will be undefined * @param fieldName the field name in the body * @returns the decorator function */ export declare function BodyField(fieldName: string): (target: Object, propertyKey: string | symbol, parameterIndex: number) => void; /** * This parameter decorator will decorate a method parameter by associating it with the whole body. * If no body is provided to the request then all attributes decorated with Body will be undefined * @returns the decorator function */ export declare function Body(): (target: Object, propertyKey: string | symbol, parameterIndex: number) => void; /** * This parameter decorator will decorate a method parameter by associating it with a field in the URL. * This field must be defined in the url like normally done in express. * @example * ```ts * // we are in a controller class * * \@Get("/concat-space/:myParam1/:myParam2") * concatWithSpace( * \@UrlParameter("myParam1") param1: string, * \@UrlParameter("myParam2") param2: string * ): string { * return param1 + " " + param2; * } * //... * ``` * @remarks If the field is undefined in the URL request the field will be filled as undefined.\ * In general parameters are non-null because missing one parameter when making the request * will result to a different HTTP call and by extension a different controller method. * @param fieldName the field name in the body * @returns the decorator function */ export declare function UrlParameter(fieldName: string): (target: Object, propertyKey: string | symbol, parameterIndex: number) => void; /** * This parameter decorator will decorate a method parameter by associating it with a Request Header (eg. content-type). * @remarks If the header is undefined the field will be filled as undefined. * @param headerName the http header name * @returns the decorator function */ export declare function Header(headerName: string): (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;