@noony-serverless/core
Version:
A Middy base framework compatible with Firebase and GCP Cloud Functions with TypeScript
151 lines • 5.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Handler = void 0;
// Container import removed - now using containerPool for performance
const core_1 = require("./core");
const containerPool_1 = require("./containerPool");
/**
* The Handler class is responsible for managing and executing middleware functions
* and a main handler function in a sequential and controlled manner.
*
* This class provides a mechanism for registering middlewares that can
* process a request/response flow either before the main handler (via `before`),
* after the main handler (via `after`), or handle errors (via `onError`).
*
* interface MessagePayload {
* action: string;
* data: Record<string, unknown>;
* }
*
* const handler = new Handler<MessagePayload>()
* .use(errorHandler())
* .use(bodyParser())
* .handle(async (context) => {
* const { req } = context;
* // Handle the request
* });
* @template T Type for the input request data.
* @template U Type for the additional context or response data.
*/
class Handler {
baseMiddlewares = [];
handler;
// Performance optimization: Pre-computed middleware arrays
reversedMiddlewares = [];
errorMiddlewares = [];
middlewaresPrecomputed = false;
static use(middleware) {
const handler = new Handler();
handler.baseMiddlewares.push(middleware);
return handler;
}
use(middleware) {
const handler = new Handler();
handler.baseMiddlewares = [
...this.baseMiddlewares,
middleware,
];
return handler;
}
handle(handler) {
this.handler = handler;
this.precomputeMiddlewareArrays();
return this;
}
/**
* Performance optimization: Pre-compute middleware arrays to avoid runtime array operations
*/
precomputeMiddlewareArrays() {
if (this.middlewaresPrecomputed)
return;
// Pre-compute reversed array for after/error middlewares
this.reversedMiddlewares = [...this.baseMiddlewares].reverse();
this.errorMiddlewares = this.reversedMiddlewares.filter((m) => m.onError);
this.middlewaresPrecomputed = true;
}
async execute(req, res) {
const genericReq = (0, core_1.adaptGCPRequest)(req);
const genericRes = (0, core_1.adaptGCPResponse)(res);
// Performance optimization: Use container pool instead of creating new containers
const container = containerPool_1.containerPool.acquire();
const context = (0, core_1.createContext)(genericReq, genericRes, {
container,
});
try {
// Execute before middlewares with performance optimizations
await this.executeBeforeMiddlewares(context);
await this.handler(context);
// Execute after middlewares in reverse order using pre-computed array
await this.executeAfterMiddlewares(context);
}
catch (error) {
context.error = error;
// Execute error handlers using pre-computed array
await this.executeErrorMiddlewares(error, context);
}
finally {
// Always return container to pool for reuse
containerPool_1.containerPool.release(container);
}
}
/**
* Execute before middlewares with optimized batching for independent middlewares
*/
async executeBeforeMiddlewares(context) {
// For backward compatibility and simpler logic, execute all before middlewares in order
for (const middleware of this.baseMiddlewares) {
if (middleware.before) {
await middleware.before(context);
}
}
}
/**
* Execute after middlewares using pre-computed reversed array
*/
async executeAfterMiddlewares(context) {
// For backward compatibility and simpler logic, execute all after middlewares in reverse order
for (const middleware of this.reversedMiddlewares) {
if (middleware.after) {
await middleware.after(context);
}
}
}
/**
* Execute error middlewares using pre-computed array
*/
async executeErrorMiddlewares(error, context) {
for (const middleware of this.errorMiddlewares) {
if (middleware.onError) {
await middleware.onError(error, context);
}
}
}
/**
* Framework-agnostic execute method that works with GenericRequest/GenericResponse
*/
async executeGeneric(req, res) {
// Performance optimization: Use container pool instead of creating new containers
const container = containerPool_1.containerPool.acquire();
const context = (0, core_1.createContext)(req, res, {
container,
});
try {
// Execute before middlewares with performance optimizations
await this.executeBeforeMiddlewares(context);
await this.handler(context);
// Execute after middlewares in reverse order using pre-computed array
await this.executeAfterMiddlewares(context);
}
catch (error) {
context.error = error;
// Execute error handlers using pre-computed array
await this.executeErrorMiddlewares(error, context);
}
finally {
// Always return container to pool for reuse
containerPool_1.containerPool.release(container);
}
}
}
exports.Handler = Handler;
//# sourceMappingURL=handler.js.map