@creamapi/cream
Version:
Concise REST API Maker - An extension library for express to create REST APIs faster
272 lines (271 loc) • 13.1 kB
TypeScript
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;