refactor(core): enhance HttpKernel pipeline and matcher system with full context and error handling
BREAKING CHANGE: `parseQuery` utility removed; `IRouteMatcher` now includes query parsing; `RouteBuilder.middleware` and `handle` are now strictly typed per builder instance.
- Add `isHandler` and `isMiddleware` runtime type guards for validation in `HttpKernel`.
- Introduce `createEmptyContext` for constructing default context objects.
- Support custom HTTP error handlers (`404`, `500`) via `IHttpKernelConfig.httpErrorHandlers`.
- Default error handlers return meaningful HTTP status text (e.g., "Not Found").
- Replace legacy `parseQuery` logic with integrated query extraction via `createRouteMatcher`.
- Strongly type `RouteBuilder.middleware()` and `.handle()` methods without generic overrides.
- Simplify `HttpKernel.handle()` and `executePipeline()` through precise control flow and validation.
- Remove deprecated `registerRoute.ts` and `HttpKernelConfig.ts` in favor of colocated type exports.
- Add tests for integrated query parsing in `createRouteMatcher`.
- Improve error handling tests: middleware/handler validation, double `next()` call, thrown exceptions.
- Replace `assertRejects` with plain response code checks (via updated error handling).
- Removed `parseQuery.ts` and all related tests — query parsing is now built into route matching.
- `IRouteMatcher` signature changed to return `{ params, query }` instead of only `params`.
- `HttpKernelConfig` now uses `DeepPartial` and includes `httpErrorHandlers`.
- `RouteBuilder`'s generics are simplified for better DX and improved type safety.
This refactor improves clarity, test coverage, and runtime safety of the request lifecycle while reducing boilerplate and eliminating duplicated query handling logic.
Signed-off-by: Max P. <Mail@MPassarello.de>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { HttpMethod } from '../Types/mod.ts';
|
||||
import { HttpMethod, isHttpMethod } from '../Types/mod.ts';
|
||||
import { IRouteMatcher } from './IRouteMatcher.ts';
|
||||
|
||||
/**
|
||||
@@ -45,3 +45,47 @@ export interface IDynamicRouteDefinition {
|
||||
* or a dynamic route with a custom matcher function for advanced matching logic.
|
||||
*/
|
||||
export type IRouteDefinition = IStaticRouteDefinition | IDynamicRouteDefinition;
|
||||
|
||||
/**
|
||||
* Type guard to check whether a route definition is a valid static route definition.
|
||||
*
|
||||
* Ensures that the object:
|
||||
* - has a `method` property of type `HttpMethod`
|
||||
* - has a `path` property of type `string`
|
||||
* - does NOT have a `matcher` function (to avoid ambiguous mixed types)
|
||||
*/
|
||||
export function isStaticRouteDefinition(
|
||||
def: IRouteDefinition,
|
||||
): def is IStaticRouteDefinition {
|
||||
return (
|
||||
def &&
|
||||
typeof def === 'object' &&
|
||||
'method' in def &&
|
||||
isHttpMethod(def.method) &&
|
||||
'path' in def &&
|
||||
typeof (def as { path?: unknown }).path === 'string' &&
|
||||
!('matcher' in def)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Type guard to check whether a route definition is a valid dynamic route definition.
|
||||
*
|
||||
* Ensures that the object:
|
||||
* - has a `method` property of type `HttpMethod`
|
||||
* - has a `matcher` property of type `function`
|
||||
* - does NOT have a `path` property (to avoid ambiguous mixed types)
|
||||
*/
|
||||
export function isDynamicRouteDefinition(
|
||||
def: IRouteDefinition,
|
||||
): def is IDynamicRouteDefinition {
|
||||
return (
|
||||
def &&
|
||||
typeof def === 'object' &&
|
||||
'method' in def &&
|
||||
isHttpMethod(def.method) &&
|
||||
'matcher' in def &&
|
||||
typeof (def as { matcher?: unknown }).matcher === 'function' &&
|
||||
!('path' in def)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user