Bringing local and remote repository in line with one another and adding Github Actions to publish package
This commit is contained in:
parent
28db152b87
commit
74997cb676
8 changed files with 479 additions and 0 deletions
21
src/decorators/DELETE.ts
Normal file
21
src/decorators/DELETE.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { NextFunction } from 'express';
|
||||
import { NextHandleFunction } from 'connect';
|
||||
|
||||
export const DELETE_METADATA_KEY = 'Delete';
|
||||
|
||||
/**
|
||||
* Method decorator intended to be used on methods of a class decorated with the `@Controller` decorator.
|
||||
*
|
||||
* This in conjunction with the `@Controller` decorator will automatically setup a DELETE route that executes the decorated method.
|
||||
* The specific path for the route is defined by the path parameter.
|
||||
* Controller authors can also specify middleware to be used with the DELETE route (because a middleware is commonly required to parse the body of a DELETE request).
|
||||
*
|
||||
* @param path The path for the DELETE route.
|
||||
* @param middleware The middleware to use with the DELETE route.
|
||||
*/
|
||||
export function DELETE(path: string, ...middleware: (NextHandleFunction | NextFunction)[]) {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
// Define a metadata key with the path and middleware as the value on the target's propertyKey
|
||||
Reflect.defineMetadata(DELETE_METADATA_KEY, { path, middleware }, target, propertyKey);
|
||||
};
|
||||
}
|
||||
62
src/decorators/ErrorHandler.ts
Normal file
62
src/decorators/ErrorHandler.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { Request, Response, NextFunction } from 'express';
|
||||
|
||||
import { ErrorController } from '../controllers/ErrorController';
|
||||
|
||||
/**
|
||||
* Class decorator to create custom error handling for the app.
|
||||
*
|
||||
* That is, so that custom error pages can easily be created and used in the app.
|
||||
*
|
||||
* @example
|
||||
* The following example show how to use the Controller decorator to setup a path `/path` with a GET, POST, PUT and DELETE method.
|
||||
* ```ts
|
||||
* import { Request, Response, NextFunction } from 'express';
|
||||
*
|
||||
* import { ErrorController, ErrorHandler } from '@BridgemanAccessible/ba-web-framework';
|
||||
*
|
||||
* @ErrorHandler(404)
|
||||
* export class Custom404PageController extends ErrorController {
|
||||
* handle(error: unknown, req: Request, res: Response, next: NextFunction) {
|
||||
* // ...
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param errorCode The error code to handle. This is the status code that will be returned by the server.
|
||||
* @param description A human readable string to describe the error this controller handles. This is used for debugging purposes only and is not used in the app itself.
|
||||
*/
|
||||
export function ErrorHandler<T extends { new(...args: any): ErrorController }>(errorCode: number, description?: string) {
|
||||
// Technically the function we return here with the target parameter is the actual decorator itself but we wrap it in case we ever want to add parameters to the decorator
|
||||
return function(target: T){
|
||||
Reflect.defineMetadata('errorHandler', target, target);
|
||||
|
||||
if(typeof target.prototype.handlesError === 'undefined') {
|
||||
// If the handlesError property is not set, we set it to the description passed to the decorator
|
||||
target.prototype.handlesError = description || `${errorCode}`;
|
||||
}
|
||||
|
||||
// We extend the class that is decorated and override the setup method to automatically setup the routes
|
||||
return class extends target {
|
||||
async handle(error: unknown, req: Request, res: Response, next: NextFunction) {
|
||||
// Because the headers have already been sent, we cannot send a response again.
|
||||
// So we check if the headers have been sent and if so, we call the next middleware (default) in the error chain.
|
||||
if(res.headersSent) {
|
||||
return next(error);
|
||||
}
|
||||
|
||||
// Create an instance of the decorated (original) class
|
||||
const controller: ErrorController = new (Reflect.getMetadata('errorHandler', target))();
|
||||
|
||||
// We only want to call the handle method if the error code matches the one denoted.
|
||||
if(res.statusCode === errorCode) {
|
||||
// Call the handle method of the controller and return the result
|
||||
return await controller.handle.bind(controller)(error, req, res, next);
|
||||
}
|
||||
else {
|
||||
// If the error code does not match, we call the next middleware in the error chain
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/decorators/PUT.ts
Normal file
21
src/decorators/PUT.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { NextFunction } from 'express';
|
||||
import { NextHandleFunction } from 'connect';
|
||||
|
||||
export const PUT_METADATA_KEY = 'Put';
|
||||
|
||||
/**
|
||||
* Method decorator intended to be used on methods of a class decorated with the `@Controller` decorator.
|
||||
*
|
||||
* This in conjunction with the `@Controller` decorator will automatically setup a PUT route that executes the decorated method.
|
||||
* The specific path for the route is defined by the path parameter.
|
||||
* Controller authors can also specify middleware to be used with the PUT route (because a middleware is commonly required to parse the body of a PUT request).
|
||||
*
|
||||
* @param path The path for the PUT route.
|
||||
* @param middleware The middleware to use with the PUT route.
|
||||
*/
|
||||
export function PUT(path: string, ...middleware: (NextHandleFunction | NextFunction)[]) {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
// Define a metadata key with the path and middleware as the value on the target's propertyKey
|
||||
Reflect.defineMetadata(PUT_METADATA_KEY, { path, middleware }, target, propertyKey);
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue