Compare commits
15 Commits
feature/pi
...
d9a984cbea
| Author | SHA1 | Date | |
|---|---|---|---|
|
d9a984cbea
|
|||
|
ec1697df94
|
|||
| e416af9754 | |||
|
b83aa330b3
|
|||
|
c28eb7f28d
|
|||
| d7460c4b1d | |||
|
6a0f1c774b
|
|||
| 7327ed5c1b | |||
|
b44bb2ddaf
|
|||
| dd60c2cdc7 | |||
|
6399113e12
|
|||
| 813c734ae6 | |||
|
3707242d27
|
|||
| adc1a4276e | |||
|
71ea4247b3
|
29
.gitea/workflows/ci.yml
Normal file
29
.gitea/workflows/ci.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up Deno
|
||||||
|
uses: denoland/setup-deno@v1
|
||||||
|
with:
|
||||||
|
deno-version: v2.x
|
||||||
|
|
||||||
|
- name: Run CI Checks
|
||||||
|
run: |
|
||||||
|
deno fmt --check
|
||||||
|
deno lint
|
||||||
|
deno task test
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
name: Test http-kernel
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- '**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
run-test:
|
|
||||||
name: Run Tests
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Deno
|
|
||||||
uses: denoland/setup-deno@v2
|
|
||||||
|
|
||||||
- name: Run Tests
|
|
||||||
run: deno task test
|
|
||||||
15
CHANGELOG.md
15
CHANGELOG.md
@@ -6,30 +6,29 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
### 🚀 Features
|
### 🚀 Features
|
||||||
|
|
||||||
- *(workflows)* Conditionally generate changelog - ([2ab6f1b](https://git.0xmax42.io/maxp/http-kernel/commit/2ab6f1b8db2d7bd31ca30248d0de183f17a5738c))
|
- *(workflows)* Conditionally generate changelog - ([b44bb2d](https://git.0xmax42.io/maxp/http-kernel/commit/b44bb2ddafe99c85b25229d2c4a0dfeacf750052))
|
||||||
- *(interfaces)* Add pipeline executor interface - ([927a908](https://git.0xmax42.io/maxp/http-kernel/commit/927a9081d4f363202520d017eb424c7c097ced94))
|
|
||||||
- *(pipeline)* Add configuration and hooks for pipeline execution - ([3f114bb](https://git.0xmax42.io/maxp/http-kernel/commit/3f114bb68d94c48a53514752d57cb4f01adeaae3))
|
|
||||||
- *(workflows)* Add CI for Deno project tests - ([9d5db4f](https://git.0xmax42.io/maxp/http-kernel/commit/9d5db4f414cf961248f2b879f2b132b81a32cb92))
|
- *(workflows)* Add CI for Deno project tests - ([9d5db4f](https://git.0xmax42.io/maxp/http-kernel/commit/9d5db4f414cf961248f2b879f2b132b81a32cb92))
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
- *(workflows)* Ensure version detection output is always set - ([abd2d6e](https://git.0xmax42.io/maxp/http-kernel/commit/abd2d6e8402662f863d9974aaa0bc228a4777724))
|
- *(workflows)* Ensure version detection output is always set - ([3707242](https://git.0xmax42.io/maxp/http-kernel/commit/3707242d278e15c55a41056bb64810f6824d24b3))
|
||||||
|
|
||||||
### 🚜 Refactor
|
### 🚜 Refactor
|
||||||
|
|
||||||
|
- *(imports)* Use explicit type-only imports across codebase - ([b83aa33](https://git.0xmax42.io/maxp/http-kernel/commit/b83aa330b34523e5102ab98ee61dedbbd62d4656))
|
||||||
- *(workflows)* Rename changelog file for consistency - ([b9d25f2](https://git.0xmax42.io/maxp/http-kernel/commit/b9d25f23fc6ad7696deee319024aa5b1af4d98c0))
|
- *(workflows)* Rename changelog file for consistency - ([b9d25f2](https://git.0xmax42.io/maxp/http-kernel/commit/b9d25f23fc6ad7696deee319024aa5b1af4d98c0))
|
||||||
|
|
||||||
### 📚 Documentation
|
### 📚 Documentation
|
||||||
|
|
||||||
- *(release)* Update guidelines for handling changelog - ([6ce73c1](https://git.0xmax42.io/maxp/http-kernel/commit/6ce73c14fa6736b622e646feb61522e6ec1f4c5a))
|
- *(release)* Update guidelines for handling changelog - ([6a0f1c7](https://git.0xmax42.io/maxp/http-kernel/commit/6a0f1c774bc01ab976090612bbc361576feb3942))
|
||||||
- *(pipeline)* Add design plan for PipelineExecutor class - ([0846dbb](https://git.0xmax42.io/maxp/http-kernel/commit/0846dbb758ba788f969a381c56498920ee0f9562))
|
|
||||||
- Add README for HttpKernel project - ([a1ce306](https://git.0xmax42.io/maxp/http-kernel/commit/a1ce30627c68a3f869eb6a104308322af8596dc1))
|
- Add README for HttpKernel project - ([a1ce306](https://git.0xmax42.io/maxp/http-kernel/commit/a1ce30627c68a3f869eb6a104308322af8596dc1))
|
||||||
- Add MIT license file - ([5118a19](https://git.0xmax42.io/maxp/http-kernel/commit/5118a19aeaa1102591aa7fe093fdec1aa19dc7f5))
|
- Add MIT license file - ([5118a19](https://git.0xmax42.io/maxp/http-kernel/commit/5118a19aeaa1102591aa7fe093fdec1aa19dc7f5))
|
||||||
|
|
||||||
### ⚙️ Miscellaneous Tasks
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
- *(git)* Ignore merge conflicts for CHANGELOG.md - ([d04dfcd](https://git.0xmax42.io/maxp/http-kernel/commit/d04dfcd63ea2478ffdff2e966d310194dafd8d7d))
|
- *(config)* Add exports field to module metadata - ([c28eb7f](https://git.0xmax42.io/maxp/http-kernel/commit/c28eb7f28dfaa8d3fdc540c4bcc306a3a8b9d6f8))
|
||||||
- *(workflows)* Refine branch handling in release process - ([8f94cc9](https://git.0xmax42.io/maxp/http-kernel/commit/8f94cc915c75a11efa1a8e3bdc51ffea9c2f19b5))
|
- *(git)* Ignore merge conflicts for CHANGELOG.md - ([6399113](https://git.0xmax42.io/maxp/http-kernel/commit/6399113e122e1207ebf4113aebd250358e31f461))
|
||||||
|
- *(workflows)* Refine branch handling in release process - ([71ea424](https://git.0xmax42.io/maxp/http-kernel/commit/71ea4247b35dc4afe5090d3c6502bfa936b5a947))
|
||||||
- *(workflows)* Update changelog file extension to .md and revert b9d25f23fc - ([a88b4d1](https://git.0xmax42.io/maxp/http-kernel/commit/a88b4d112f5c07664d41f6e9d03246307551f25d))
|
- *(workflows)* Update changelog file extension to .md and revert b9d25f23fc - ([a88b4d1](https://git.0xmax42.io/maxp/http-kernel/commit/a88b4d112f5c07664d41f6e9d03246307551f25d))
|
||||||
- Rename changelog and readme files to use .md extension - ([4f2b650](https://git.0xmax42.io/maxp/http-kernel/commit/4f2b65049f461ef377e7231905fd066cbc3c7fe0))
|
- Rename changelog and readme files to use .md extension - ([4f2b650](https://git.0xmax42.io/maxp/http-kernel/commit/4f2b65049f461ef377e7231905fd066cbc3c7fe0))
|
||||||
- *(workflows)* Update test workflow for http-kernel project - ([0311546](https://git.0xmax42.io/maxp/http-kernel/commit/03115464e0fb01b8ca00a2fdabde013d004ae8a2))
|
- *(workflows)* Update test workflow for http-kernel project - ([0311546](https://git.0xmax42.io/maxp/http-kernel/commit/03115464e0fb01b8ca00a2fdabde013d004ae8a2))
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "@0xmax42/http-kernel",
|
"name": "@0xmax42/http-kernel",
|
||||||
"description": "A simple HTTP kernel for Deno",
|
"description": "A simple HTTP kernel for Deno",
|
||||||
|
"exports": {
|
||||||
|
"./mod.ts": "./src/mod.ts"
|
||||||
|
},
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"test": "deno test --allow-net --allow-env --unstable-kv --allow-read --allow-write --coverage **/__tests__/*.test.ts",
|
"test": "deno test --allow-net --allow-env --unstable-kv --allow-read --allow-write --coverage **/__tests__/*.test.ts",
|
||||||
"test:watch": "deno test --watch --allow-net --allow-env --unstable-kv --allow-read --allow-write **/__tests__/*.test.ts"
|
"test:watch": "deno test --watch --allow-net --allow-env --unstable-kv --allow-read --allow-write **/__tests__/*.test.ts",
|
||||||
|
"benchmark": "deno bench --allow-net --allow-env --unstable-kv --allow-read --allow-write **/__bench__/*.bench.ts",
|
||||||
|
"fmt": "deno fmt --check",
|
||||||
|
"lint": "deno lint"
|
||||||
},
|
},
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": [
|
"lib": [
|
||||||
@@ -26,5 +32,4 @@
|
|||||||
"main.ts"
|
"main.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
//"importMap": "./import_map.json"
|
|
||||||
}
|
}
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
# 🧩 Plan: `PipelineExecutor<TContext>`
|
|
||||||
|
|
||||||
## 🎯 Ziel
|
|
||||||
Eine eigenständige, testbare Klasse zur Ausführung einer Middleware- und Handler-Pipeline, die:
|
|
||||||
- Linear und sauber das `next()`-Verhalten abbildet
|
|
||||||
- Typvalidierung durchführt (`isMiddleware`, `isHandler`)
|
|
||||||
- Fehler behandelt und an konfigurierbare Handler weiterleitet
|
|
||||||
- Optionale Hooks zur Tracing-Integration bietet (z. B. für Zeitmessung, Logging)
|
|
||||||
- Am Ende eine dekorierte `Response` zurückliefert
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧩 Schnittstelle (API)
|
|
||||||
|
|
||||||
```ts
|
|
||||||
class PipelineExecutor<TContext extends IContext> {
|
|
||||||
constructor(cfg: IHttpKernelConfig<TContext>);
|
|
||||||
|
|
||||||
run(
|
|
||||||
ctx: TContext,
|
|
||||||
middleware: Middleware<TContext>[],
|
|
||||||
handler: Handler<TContext>,
|
|
||||||
hooks?: IPipelineHooks<TContext>, // optional
|
|
||||||
): Promise<Response>;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🪝 Hook-Schnittstelle (`IPipelineHooks`)
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface IPipelineHooks<TContext> {
|
|
||||||
onPipelineStart?(ctx: TContext): void;
|
|
||||||
onStepStart?(name: string | undefined, ctx: TContext): void;
|
|
||||||
onStepEnd?(name: string | undefined, ctx: TContext, duration: number): void;
|
|
||||||
onPipelineEnd?(ctx: TContext, totalDuration: number): void;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `name` ist `undefined`, wenn keine `.name` am Handler/Middleware gesetzt ist
|
|
||||||
- Diese Hooks ermöglichen später Logging, Zeitmessung, Statistiken etc.
|
|
||||||
- Der `TraceManager` wird dieses Interface implementieren
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠️ Interne Aufgaben / Ablauf
|
|
||||||
|
|
||||||
1. `run(...)` beginnt mit Aufruf `onPipelineStart(ctx)`
|
|
||||||
2. Zeitmessung (`performance.now()`)
|
|
||||||
3. Dispatcher-Funktion führt jede Middleware mit `next()`-Kette aus
|
|
||||||
4. Vor jedem Aufruf: `onStepStart(name, ctx)`
|
|
||||||
5. Nach jedem Aufruf: `onStepEnd(name, ctx, duration)`
|
|
||||||
6. Nach letztem Handler: `onPipelineEnd(ctx, totalDuration)`
|
|
||||||
7. Ergebnis wird durch `cfg.decorateResponse(res, ctx)` geschickt
|
|
||||||
8. Im Fehlerfall: `cfg.httpErrorHandlers[500](ctx, error)`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Vorteile
|
|
||||||
|
|
||||||
- `HttpKernel` ist von Ausführungsdetails entkoppelt
|
|
||||||
- Tracing-/Logging-System kann ohne Invasivität angeschlossen werden
|
|
||||||
- Sehr gut testbar (z. B. Middleware-Mock + Hook-Aufrufe prüfen)
|
|
||||||
- Erweiterbar für Timeout, Async-Context, Abbruchlogik etc.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 Dateiname-Vorschlag
|
|
||||||
|
|
||||||
- `src/Core/PipelineExecutor.ts` oder
|
|
||||||
- `src/HttpKernel/PipelineExecutor.ts`
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import {
|
import type {
|
||||||
IContext,
|
IContext,
|
||||||
IHttpKernel,
|
IHttpKernel,
|
||||||
IHttpKernelConfig,
|
IHttpKernelConfig,
|
||||||
@@ -7,14 +7,14 @@ import {
|
|||||||
IRouteDefinition,
|
IRouteDefinition,
|
||||||
} from './Interfaces/mod.ts';
|
} from './Interfaces/mod.ts';
|
||||||
import {
|
import {
|
||||||
DeepPartial,
|
type DeepPartial,
|
||||||
Handler,
|
type Handler,
|
||||||
HTTP_404_NOT_FOUND,
|
HTTP_404_NOT_FOUND,
|
||||||
HTTP_500_INTERNAL_SERVER_ERROR,
|
HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
HttpStatusTextMap,
|
HttpStatusTextMap,
|
||||||
isHandler,
|
isHandler,
|
||||||
isMiddleware,
|
isMiddleware,
|
||||||
Middleware,
|
type Middleware,
|
||||||
} from './Types/mod.ts';
|
} from './Types/mod.ts';
|
||||||
import { RouteBuilder } from './RouteBuilder.ts';
|
import { RouteBuilder } from './RouteBuilder.ts';
|
||||||
import { createEmptyContext, normalizeError } from './Utils/mod.ts';
|
import { createEmptyContext, normalizeError } from './Utils/mod.ts';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Params, Query, State } from '../Types/mod.ts';
|
import type { Params, Query, State } from '../Types/mod.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the complete context for a single HTTP request,
|
* Represents the complete context for a single HTTP request,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { IContext } from '../Interfaces/mod.ts';
|
import type { IContext } from '../Interfaces/mod.ts';
|
||||||
import { HttpErrorHandler, validHttpErrorCodes } from '../Types/mod.ts';
|
import type { HttpErrorHandler, validHttpErrorCodes } from '../Types/mod.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapping of HTTP status codes to their corresponding error handlers.
|
* A mapping of HTTP status codes to their corresponding error handlers.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { IContext } from './IContext.ts';
|
import type { IContext } from './IContext.ts';
|
||||||
import { IRouteBuilder } from './IRouteBuilder.ts';
|
import type { IRouteBuilder } from './IRouteBuilder.ts';
|
||||||
import { IRouteDefinition } from './IRouteDefinition.ts';
|
import type { IRouteDefinition } from './IRouteDefinition.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `IHttpKernel` interface defines the public API for a type-safe, middleware-driven HTTP dispatching system.
|
* The `IHttpKernel` interface defines the public API for a type-safe, middleware-driven HTTP dispatching system.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ResponseDecorator } from '../Types/mod.ts';
|
import type { ResponseDecorator } from '../Types/mod.ts';
|
||||||
import { IContext } from './IContext.ts';
|
import type { IContext } from './IContext.ts';
|
||||||
import { IHttpErrorHandlers } from './IHttpErrorHandlers.ts';
|
import type { IHttpErrorHandlers } from './IHttpErrorHandlers.ts';
|
||||||
import { IRouteBuilderFactory } from './IRouteBuilder.ts';
|
import type { IRouteBuilderFactory } from './IRouteBuilder.ts';
|
||||||
|
|
||||||
export interface IHttpKernelConfig<TContext extends IContext = IContext> {
|
export interface IHttpKernelConfig<TContext extends IContext = IContext> {
|
||||||
decorateResponse: ResponseDecorator<TContext>;
|
decorateResponse: ResponseDecorator<TContext>;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Handler, HttpMethod, Middleware } from '../Types/mod.ts';
|
import type { Handler, HttpMethod, Middleware } from '../Types/mod.ts';
|
||||||
import { IContext, IRouteMatcher } from './mod.ts';
|
import type { IContext, IRouteMatcher } from './mod.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an internally registered route within the HttpKernel.
|
* Represents an internally registered route within the HttpKernel.
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
import { Handler, Middleware } from '../Types/mod.ts';
|
|
||||||
import { IContext } from './IContext.ts';
|
|
||||||
import { IPipelineExecutorConfig } from './IPipelineExecutorConfig.ts';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor type for a class implementing the IPipelineExecutor interface.
|
|
||||||
*
|
|
||||||
* This can be used for dependency injection, factory-based initialization,
|
|
||||||
* or dynamic instantiation of pipeline executors.
|
|
||||||
*
|
|
||||||
* @template TContext - The extended context type passed through the pipeline.
|
|
||||||
*/
|
|
||||||
export interface PipelineExecutorFactory<TContext extends IContext = IContext> {
|
|
||||||
/**
|
|
||||||
* Creates a new instance of a pipeline executor.
|
|
||||||
*
|
|
||||||
* @param config - Configuration used to control error handling,
|
|
||||||
* response decoration and lifecycle hooks.
|
|
||||||
*/
|
|
||||||
new (
|
|
||||||
config: IPipelineExecutorConfig<TContext>,
|
|
||||||
): IPipelineExecutor<TContext>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the contract for executing a middleware and handler pipeline.
|
|
||||||
*
|
|
||||||
* The pipeline is responsible for:
|
|
||||||
* - Executing middleware in order with `next()` chaining
|
|
||||||
* - Invoking the final handler
|
|
||||||
* - Applying optional lifecycle hooks
|
|
||||||
* - Producing and decorating a Response
|
|
||||||
*
|
|
||||||
* @template TContext - The context type flowing through the pipeline.
|
|
||||||
*/
|
|
||||||
export interface IPipelineExecutor<TContext extends IContext = IContext> {
|
|
||||||
/**
|
|
||||||
* Executes the middleware pipeline and returns the final Response.
|
|
||||||
*
|
|
||||||
* @param ctx - The context object representing the current HTTP request state.
|
|
||||||
* @param middleware - An ordered array of middleware functions to be executed.
|
|
||||||
* @param handler - The final route handler to be called after all middleware.
|
|
||||||
* @returns A Promise resolving to the final HTTP Response.
|
|
||||||
*/
|
|
||||||
run(
|
|
||||||
ctx: TContext,
|
|
||||||
middleware: Middleware<TContext>[],
|
|
||||||
handler: Handler<TContext>,
|
|
||||||
): Promise<Response>;
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { ResponseDecorator } from '../Types/ResponseDecorator.ts';
|
|
||||||
import { IContext } from './IContext.ts';
|
|
||||||
import { IHttpErrorHandlers } from './IHttpErrorHandlers.ts';
|
|
||||||
import { IPipelineHooks } from './IPipelineHooks.ts';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration object for the PipelineExecutor, defining how to handle
|
|
||||||
* errors, responses, and tracing hooks.
|
|
||||||
*
|
|
||||||
* This allows the execution logic to remain decoupled from kernel-level behavior
|
|
||||||
* while still supporting custom behavior injection.
|
|
||||||
*
|
|
||||||
* @template TContext - The context type propagated during pipeline execution.
|
|
||||||
*/
|
|
||||||
export interface IPipelineExecutorConfig<TContext extends IContext = IContext> {
|
|
||||||
/**
|
|
||||||
* Optional function used to transform or decorate the final Response object
|
|
||||||
* before it is returned to the client.
|
|
||||||
*/
|
|
||||||
decorateResponse?: ResponseDecorator<TContext>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional map of error handlers, keyed by HTTP status codes (e.g., 404, 500).
|
|
||||||
* These handlers are invoked if an error occurs during middleware or handler execution.
|
|
||||||
*/
|
|
||||||
errorHandlers?: IHttpErrorHandlers<TContext>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional hooks that allow tracing and lifecycle monitoring during pipeline execution.
|
|
||||||
* Each hook is called at a specific phase of the middleware/handler lifecycle.
|
|
||||||
*/
|
|
||||||
pipelineHooks?: IPipelineHooks<TContext>;
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import {
|
|
||||||
OnPipelineEnd,
|
|
||||||
OnPipelineStart,
|
|
||||||
OnStepEnd,
|
|
||||||
OnStepStart,
|
|
||||||
} from '../Types/mod.ts';
|
|
||||||
import { IContext } from './IContext.ts';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A set of optional hook functions that can be triggered during pipeline execution.
|
|
||||||
* These hooks allow tracing, performance measurement, and logging to be integrated
|
|
||||||
* without altering middleware or handler logic.
|
|
||||||
*
|
|
||||||
* @template TContext - The custom context type used within the application.
|
|
||||||
*/
|
|
||||||
export interface IPipelineHooks<TContext extends IContext = IContext> {
|
|
||||||
/**
|
|
||||||
* Triggered once before any middleware or handler is executed.
|
|
||||||
*/
|
|
||||||
onPipelineStart?: OnPipelineStart<TContext>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered immediately before each middleware or handler runs.
|
|
||||||
*/
|
|
||||||
onStepStart?: OnStepStart<TContext>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered immediately after each middleware or handler has finished executing.
|
|
||||||
*/
|
|
||||||
onStepEnd?: OnStepEnd<TContext>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggered after the entire pipeline completes execution.
|
|
||||||
*/
|
|
||||||
onPipelineEnd?: OnPipelineEnd<TContext>;
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Handler, Middleware } from '../Types/mod.ts';
|
import type { Handler, Middleware } from '../Types/mod.ts';
|
||||||
import { IInternalRoute } from './IInternalRoute.ts';
|
import type { IInternalRoute } from './IInternalRoute.ts';
|
||||||
import { IRouteDefinition } from './IRouteDefinition.ts';
|
import type { IRouteDefinition } from './IRouteDefinition.ts';
|
||||||
import { IContext } from './mod.ts';
|
import type { IContext } from './mod.ts';
|
||||||
|
|
||||||
export interface IRouteBuilderFactory<TContext extends IContext = IContext> {
|
export interface IRouteBuilderFactory<TContext extends IContext = IContext> {
|
||||||
new (
|
new (
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { HttpMethod, isHttpMethod } from '../Types/mod.ts';
|
import { type HttpMethod, isHttpMethod } from '../Types/mod.ts';
|
||||||
import { IRouteMatcher } from './IRouteMatcher.ts';
|
import type { IRouteMatcher } from './IRouteMatcher.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a static route using a path pattern with optional parameters.
|
* Defines a static route using a path pattern with optional parameters.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Params, Query } from '../Types/mod.ts';
|
import type { Params, Query } from '../Types/mod.ts';
|
||||||
|
|
||||||
export interface IRouteMatch {
|
export interface IRouteMatch {
|
||||||
params?: Params;
|
params?: Params;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Params } from '../Types/mod.ts';
|
import type { IRouteDefinition } from './IRouteDefinition.ts';
|
||||||
import { IRouteDefinition } from './IRouteDefinition.ts';
|
import type { IRouteMatch } from './IRouteMatch.ts';
|
||||||
import { IRouteMatch } from './IRouteMatch.ts';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a route matcher function that evaluates whether a route applies to a given request.
|
* Defines a route matcher function that evaluates whether a route applies to a given request.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { assertEquals } from 'https://deno.land/std@0.204.0/assert/mod.ts';
|
import { assertEquals } from 'https://deno.land/std@0.204.0/assert/mod.ts';
|
||||||
import {
|
import {
|
||||||
IRouteDefinition,
|
type IRouteDefinition,
|
||||||
isDynamicRouteDefinition,
|
isDynamicRouteDefinition,
|
||||||
isStaticRouteDefinition,
|
isStaticRouteDefinition,
|
||||||
} from '../IRouteDefinition.ts';
|
} from '../IRouteDefinition.ts';
|
||||||
|
|||||||
@@ -5,12 +5,6 @@ export type { IHttpErrorHandlers } from './IHttpErrorHandlers.ts';
|
|||||||
export type { IHttpKernel } from './IHttpKernel.ts';
|
export type { IHttpKernel } from './IHttpKernel.ts';
|
||||||
export type { IHttpKernelConfig } from './IHttpKernelConfig.ts';
|
export type { IHttpKernelConfig } from './IHttpKernelConfig.ts';
|
||||||
export type { IInternalRoute } from './IInternalRoute.ts';
|
export type { IInternalRoute } from './IInternalRoute.ts';
|
||||||
export type {
|
|
||||||
IPipelineExecutor,
|
|
||||||
PipelineExecutorFactory,
|
|
||||||
} from './IPipelineExecutor.ts';
|
|
||||||
export type { IPipelineExecutorConfig } from './IPipelineExecutorConfig.ts';
|
|
||||||
export type { IPipelineHooks } from './IPipelineHooks.ts';
|
|
||||||
export type { IRouteBuilder, IRouteBuilderFactory } from './IRouteBuilder.ts';
|
export type { IRouteBuilder, IRouteBuilderFactory } from './IRouteBuilder.ts';
|
||||||
export {
|
export {
|
||||||
isDynamicRouteDefinition,
|
isDynamicRouteDefinition,
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { IRouteMatcherFactory } from './Interfaces/IRouteMatcher.ts';
|
import type { IRouteMatcherFactory } from './Interfaces/IRouteMatcher.ts';
|
||||||
import { IContext, IRouteBuilder, IRouteDefinition } from './Interfaces/mod.ts';
|
import type {
|
||||||
import { Handler, Middleware, RegisterRoute } from './Types/mod.ts';
|
IContext,
|
||||||
|
IRouteBuilder,
|
||||||
|
IRouteDefinition,
|
||||||
|
} from './Interfaces/mod.ts';
|
||||||
|
import type { Handler, Middleware, RegisterRoute } from './Types/mod.ts';
|
||||||
import { createRouteMatcher } from './Utils/createRouteMatcher.ts';
|
import { createRouteMatcher } from './Utils/createRouteMatcher.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IContext } from '../Interfaces/mod.ts';
|
import type { IContext } from '../Interfaces/mod.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a final request handler responsible for producing an HTTP response.
|
* Represents a final request handler responsible for producing an HTTP response.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IContext } from '../Interfaces/mod.ts';
|
import type { IContext } from '../Interfaces/mod.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a handler function for errors that occur during the execution
|
* Defines a handler function for errors that occur during the execution
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IContext } from '../Interfaces/IContext.ts';
|
import type { IContext } from '../Interfaces/IContext.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a middleware function in the HTTP request pipeline.
|
* Represents a middleware function in the HTTP request pipeline.
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
import { IContext } from '../Interfaces/mod.ts';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A callback invoked when the middleware pipeline starts.
|
|
||||||
*
|
|
||||||
* @template TContext - The context type passed throughout the pipeline.
|
|
||||||
* @param ctx - The context object for the current request.
|
|
||||||
*/
|
|
||||||
export type OnPipelineStart<TContext extends IContext> = (
|
|
||||||
ctx: TContext,
|
|
||||||
) => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A callback invoked immediately before a middleware or handler is executed.
|
|
||||||
*
|
|
||||||
* @template TContext - The context type passed throughout the pipeline.
|
|
||||||
* @param name - Optional name of the current middleware or handler, if defined.
|
|
||||||
* @param ctx - The context object for the current request.
|
|
||||||
*/
|
|
||||||
export type OnStepStart<TContext extends IContext> = (
|
|
||||||
name: string | undefined,
|
|
||||||
ctx: TContext,
|
|
||||||
) => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A callback invoked immediately after a middleware or handler has completed.
|
|
||||||
*
|
|
||||||
* @template TContext - The context type passed throughout the pipeline.
|
|
||||||
* @param name - Optional name of the current middleware or handler, if defined.
|
|
||||||
* @param ctx - The context object for the current request.
|
|
||||||
* @param duration - Execution time in milliseconds.
|
|
||||||
*/
|
|
||||||
export type OnStepEnd<TContext extends IContext> = (
|
|
||||||
name: string | undefined,
|
|
||||||
ctx: TContext,
|
|
||||||
duration: number,
|
|
||||||
) => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A callback invoked after the entire pipeline has completed execution.
|
|
||||||
*
|
|
||||||
* @template TContext - The context type passed throughout the pipeline.
|
|
||||||
* @param ctx - The context object for the current request.
|
|
||||||
* @param totalDuration - Total execution time of the pipeline in milliseconds.
|
|
||||||
*/
|
|
||||||
export type OnPipelineEnd<TContext extends IContext> = (
|
|
||||||
ctx: TContext,
|
|
||||||
totalDuration: number,
|
|
||||||
) => void;
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { IContext } from '../Interfaces/IContext.ts';
|
import type { IContext } from '../Interfaces/IContext.ts';
|
||||||
import { IInternalRoute } from '../Interfaces/mod.ts';
|
import type { IInternalRoute } from '../Interfaces/mod.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type alias for the internal route registration function used by the `HttpKernel`.
|
* A type alias for the internal route registration function used by the `HttpKernel`.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IContext } from '../Interfaces/mod.ts';
|
import type { IContext } from '../Interfaces/mod.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function that modifies or enriches an outgoing HTTP response before it is returned to the client.
|
* A function that modifies or enriches an outgoing HTTP response before it is returned to the client.
|
||||||
|
|||||||
@@ -39,12 +39,6 @@ export type { HttpStatusCode } from './HttpStatusCode.ts';
|
|||||||
export { isMiddleware } from './Middleware.ts';
|
export { isMiddleware } from './Middleware.ts';
|
||||||
export type { Middleware } from './Middleware.ts';
|
export type { Middleware } from './Middleware.ts';
|
||||||
export type { Params } from './Params.ts';
|
export type { Params } from './Params.ts';
|
||||||
export type {
|
|
||||||
OnPipelineEnd,
|
|
||||||
OnPipelineStart,
|
|
||||||
OnStepEnd,
|
|
||||||
OnStepStart,
|
|
||||||
} from './PipelineHooks.ts';
|
|
||||||
export type { Query } from './Query.ts';
|
export type { Query } from './Query.ts';
|
||||||
export type { RegisterRoute } from './RegisterRoute.ts';
|
export type { RegisterRoute } from './RegisterRoute.ts';
|
||||||
export type { ResponseDecorator } from './ResponseDecorator.ts';
|
export type { ResponseDecorator } from './ResponseDecorator.ts';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { assertEquals } from 'https://deno.land/std/assert/mod.ts';
|
import { assertEquals } from 'https://deno.land/std/assert/mod.ts';
|
||||||
import { createEmptyContext } from '../createEmptyContext.ts';
|
import { createEmptyContext } from '../createEmptyContext.ts';
|
||||||
import { IContext } from '../../Interfaces/mod.ts';
|
import type { IContext } from '../../Interfaces/mod.ts';
|
||||||
|
|
||||||
Deno.test('createEmptyContext: returns default-initialized context', () => {
|
Deno.test('createEmptyContext: returns default-initialized context', () => {
|
||||||
const request = new Request('http://localhost');
|
const request = new Request('http://localhost');
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
assertEquals,
|
assertEquals,
|
||||||
assertStrictEquals,
|
assertStrictEquals,
|
||||||
} from 'https://deno.land/std/assert/mod.ts';
|
} from 'https://deno.land/std/assert/mod.ts';
|
||||||
import { IRouteDefinition } from '../../Interfaces/mod.ts';
|
import type { IRouteDefinition } from '../../Interfaces/mod.ts';
|
||||||
import { createRouteMatcher } from '../../mod.ts';
|
import { createRouteMatcher } from '../../mod.ts';
|
||||||
|
|
||||||
// Dummy request
|
// Dummy request
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { IContext } from '../Interfaces/mod.ts';
|
import type { IContext } from '../Interfaces/mod.ts';
|
||||||
import { Params, Query, State } from '../Types/mod.ts';
|
import type { Params, Query, State } from '../Types/mod.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty request context suitable for fallback handlers (e.g., 404 or 500 errors).
|
* Creates an empty request context suitable for fallback handlers (e.g., 404 or 500 errors).
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
// createRouteMatcher.ts
|
// createRouteMatcher.ts
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IRouteDefinition,
|
type IRouteDefinition,
|
||||||
IRouteMatch,
|
type IRouteMatch,
|
||||||
IRouteMatcher,
|
type IRouteMatcher,
|
||||||
isDynamicRouteDefinition,
|
isDynamicRouteDefinition,
|
||||||
} from '../Interfaces/mod.ts';
|
} from '../Interfaces/mod.ts';
|
||||||
import { Params, Query } from '../Types/mod.ts';
|
import type { Params, Query } from '../Types/mod.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms a route definition into a matcher using Deno's URLPattern API.
|
* Transforms a route definition into a matcher using Deno's URLPattern API.
|
||||||
|
|||||||
@@ -22,9 +22,7 @@
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function normalizeError(unknownError: unknown): Error {
|
export function normalizeError(unknownError: unknown): Error {
|
||||||
return unknownError instanceof Error
|
return unknownError instanceof Error ? unknownError : new Error(
|
||||||
? unknownError
|
|
||||||
: new Error(
|
|
||||||
typeof unknownError === 'string'
|
typeof unknownError === 'string'
|
||||||
? unknownError
|
? unknownError
|
||||||
: JSON.stringify(unknownError),
|
: JSON.stringify(unknownError),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { assertEquals } from 'https://deno.land/std@0.204.0/assert/mod.ts';
|
import { assertEquals } from 'https://deno.land/std@0.204.0/assert/mod.ts';
|
||||||
import { HttpKernel } from '../HttpKernel.ts';
|
import { HttpKernel } from '../HttpKernel.ts';
|
||||||
import { IRouteDefinition } from '../Interfaces/mod.ts';
|
import type { IRouteDefinition } from '../Interfaces/mod.ts';
|
||||||
|
|
||||||
Deno.test('HttpKernel: matches static route and executes handler', async () => {
|
Deno.test('HttpKernel: matches static route and executes handler', async () => {
|
||||||
const kernel = new HttpKernel();
|
const kernel = new HttpKernel();
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import {
|
|||||||
assertNotEquals,
|
assertNotEquals,
|
||||||
assertThrows,
|
assertThrows,
|
||||||
} from 'https://deno.land/std@0.204.0/assert/mod.ts';
|
} from 'https://deno.land/std@0.204.0/assert/mod.ts';
|
||||||
import { IInternalRoute, IRouteDefinition } from '../Interfaces/mod.ts';
|
import type { IInternalRoute, IRouteDefinition } from '../Interfaces/mod.ts';
|
||||||
import { RouteBuilder } from '../mod.ts';
|
import { RouteBuilder } from '../mod.ts';
|
||||||
import { Handler, Middleware } from '../Types/mod.ts';
|
import type { Handler, Middleware } from '../Types/mod.ts';
|
||||||
|
|
||||||
// Dummy objects
|
// Dummy objects
|
||||||
// deno-lint-ignore require-await
|
// deno-lint-ignore require-await
|
||||||
@@ -91,7 +91,7 @@ Deno.test('handle: works with no middleware', async () => {
|
|||||||
Deno.test('handle: uses custom matcher factory', () => {
|
Deno.test('handle: uses custom matcher factory', () => {
|
||||||
let called = false;
|
let called = false;
|
||||||
|
|
||||||
const factory = (def: IRouteDefinition) => {
|
const factory = (_def: IRouteDefinition) => {
|
||||||
called = true;
|
called = true;
|
||||||
return dummyMatcher;
|
return dummyMatcher;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user