29 Commits

Author SHA1 Message Date
5d1b0517a5 chore(changelog): update unreleased changelog 2025-05-10 15:51:08 +00:00
6ce73c14fa docs(release): update guidelines for handling changelog
All checks were successful
Auto Changelog & Release / detect-version-change (push) Successful in 4s
Auto Changelog & Release / release (push) Has been skipped
Auto Changelog & Release / changelog-only (push) Successful in 8s
Test http-kernel / Run Tests (pull_request) Successful in 14s
- Add instructions to avoid merge conflicts in `CHANGELOG.md`
- Provide steps for using `.gitattributes` to automate conflict resolution
- Clarify recommended workflows for feature branches and merging
2025-05-10 17:50:05 +02:00
0aac2337a0 chore(changelog): update unreleased changelog 2025-05-10 15:42:59 +00:00
2ab6f1b8db feat(workflows): conditionally generate changelog
All checks were successful
Auto Changelog & Release / detect-version-change (push) Successful in 4s
Auto Changelog & Release / release (push) Has been skipped
Test http-kernel / Run Tests (pull_request) Successful in 12s
Auto Changelog & Release / changelog-only (push) Successful in 13s
- Add logic to generate changelog only if the file exists or on the main branch
- Prevent unnecessary changelog generation in other contexts
2025-05-10 17:42:19 +02:00
b69a51247d chore(changelog): update unreleased changelog 2025-05-10 15:28:39 +00:00
2ab74b9859 chore(changelog): update unreleased changelog
All checks were successful
Auto Changelog & Release / detect-version-change (push) Successful in 5s
Auto Changelog & Release / release (push) Has been skipped
Test http-kernel / Run Tests (pull_request) Successful in 14s
Auto Changelog & Release / changelog-only (push) Successful in 9s
2025-05-10 17:28:21 +02:00
d04dfcd63e chore(git): ignore merge conflicts for CHANGELOG.md 2025-05-10 17:27:55 +02:00
32f3fe5f52 chore(changelog): update unreleased changelog 2025-05-10 15:01:16 +00:00
abd2d6e840 fix(workflows): ensure version detection output is always set
All checks were successful
Auto Changelog & Release / detect-version-change (push) Successful in 4s
Auto Changelog & Release / release (push) Has been skipped
Test http-kernel / Run Tests (pull_request) Successful in 13s
Auto Changelog & Release / changelog-only (push) Successful in 10s
- Move VERSION file change detection behind a branch guard (main only)
- Use a fallback in the output step to ensure 'version_changed' is always defined
- Prevent job skipping and output access errors in feature branches
2025-05-10 16:59:53 +02:00
927a9081d4 feat(interfaces): add pipeline executor interface
All checks were successful
Auto Changelog & Release / detect-version-change (push) Has been skipped
Auto Changelog & Release / changelog-only (push) Has been skipped
Auto Changelog & Release / release (push) Has been skipped
Test http-kernel / Run Tests (pull_request) Successful in 13s
- Introduce `IPipelineExecutor` to define pipeline execution
- Add `PipelineExecutorFactory` for instantiating pipeline executors
- Export new types in the interfaces module for external use
2025-05-10 16:50:41 +02:00
8f94cc915c chore(workflows): refine branch handling in release process
All checks were successful
Test http-kernel / Run Tests (pull_request) Successful in 16s
Auto Changelog & Release / detect-version-change (push) Has been skipped
Auto Changelog & Release / changelog-only (push) Has been skipped
Auto Changelog & Release / release (push) Has been skipped
- Adjusts workflow to support pushes from all branches
- Ensures main branch-specific conditions for version detection
- Modifies changelog and release steps for non-main branch handling
2025-05-10 16:34:19 +02:00
3f114bb68d feat(pipeline): add configuration and hooks for pipeline execution
- Introduce `IPipelineExecutorConfig` to enable customizable pipeline behavior
- Add `IPipelineHooks` interface for tracing and monitoring lifecycle events
- Define callback types for pipeline start, step execution, and completion
- Export new types and interfaces for broader integration within the system
2025-05-10 16:21:16 +02:00
0846dbb758 docs(pipeline): add design plan for PipelineExecutor class
All checks were successful
Test http-kernel / Run Tests (pull_request) Successful in 10s
- Introduce a detailed plan for the PipelineExecutor class
- Describe its purpose, interface, hooks, and internal workflow
- Highlight advantages such as decoupling, testability, and extensibility
- Will be removed before merge
2025-05-08 22:05:30 +02:00
b624415320 chore(changelog): update unreleased changelog 2025-05-08 18:19:58 +00:00
a88b4d112f chore(workflows): update changelog file extension to .md and revert b9d25f23fc
All checks were successful
Auto Changelog & Release / detect-version-change (push) Successful in 5s
Auto Changelog & Release / release (push) Has been skipped
Auto Changelog & Release / changelog-only (push) Successful in 5s
2025-05-08 20:19:43 +02:00
4f2b65049f chore: rename changelog and readme files to use .md extension 2025-05-08 20:19:43 +02:00
c9de4669c7 chore(changelog): update unreleased changelog 2025-05-08 18:16:14 +00:00
a1ce30627c docs: add README for HttpKernel project
All checks were successful
Auto Changelog & Release / detect-version-change (push) Successful in 3s
Auto Changelog & Release / changelog-only (push) Successful in 7s
Auto Changelog & Release / release (push) Has been skipped
- Introduce HttpKernel with an overview of its purpose and features
- Provide a quick start guide and API reference for developers
- Include testing instructions, configuration options, and roadmap
- Add license information for clarity and compliance
2025-05-08 20:15:58 +02:00
5118a19aea docs: add MIT license file 2025-05-08 20:15:48 +02:00
0a09c8c324 chore(changelog): update unreleased changelog 2025-05-08 18:09:16 +00:00
b9d25f23fc refactor(workflows): rename changelog file for consistency
All checks were successful
Test http-kernel / Run Tests (pull_request) Successful in 10s
Auto Changelog & Release / detect-version-change (push) Successful in 7s
Auto Changelog & Release / release (push) Has been skipped
Auto Changelog & Release / changelog-only (push) Successful in 12s
- Rename `CHANGELOG.md` to `CHANGELOG` in workflows
- Update related commands and references for consistency
2025-05-08 19:49:24 +02:00
92f09e6e60 Merge pull request 'chore(workflows): update test workflow for http-kernel project' (#1) from fix/test-workflow into main
Some checks failed
Auto Changelog & Release / detect-version-change (push) Successful in 3s
Auto Changelog & Release / release (push) Has been skipped
Auto Changelog & Release / changelog-only (push) Failing after 10s
Reviewed-on: #1
2025-05-08 19:46:00 +02:00
03115464e0 chore(workflows): update test workflow for http-kernel project
All checks were successful
Test http-kernel / Run Tests (pull_request) Successful in 10s
- Rename workflow and job to align with the http-kernel project
- Improve clarity and maintain consistency in workflow naming
2025-05-08 19:38:49 +02:00
11a2273240 chore(changelog): update unreleased changelog 2025-05-08 17:35:37 +00:00
1233a0b720 chore(workflows): update Deno setup action to v2
All checks were successful
Auto Changelog & Release / detect-version-change (push) Successful in 6s
Auto Changelog & Release / release (push) Has been skipped
Auto Changelog & Release / changelog-only (push) Successful in 10s
- Updates the Deno setup action to the latest major version (v2)
- Ensures compatibility and benefits from improvements in the new version
2025-05-08 19:35:11 +02:00
195619ca99 chore(changelog): update unreleased changelog 2025-05-08 17:33:23 +00:00
9d5db4f414 feat(workflows): add CI for Deno project tests
Some checks are pending
Auto Changelog & Release / release (push) Blocked by required conditions
Auto Changelog & Release / detect-version-change (push) Successful in 5s
Auto Changelog & Release / changelog-only (push) Successful in 18s
- Introduce a GitHub Actions workflow to run tests for the Deno project
- Configure workflow to trigger on pull requests across all branches
- Include steps for repository checkout, Deno setup, and test execution
2025-05-08 19:32:51 +02:00
16c0053964 chore(workflows): remove unused workflow_dispatch trigger
- Eliminates the workflow_dispatch trigger from the release workflow
  as it is no longer required, simplifying the configuration.
2025-05-08 19:32:42 +02:00
04029f87a3 chore(tasks): remove commented-out start and watch scripts
- Cleans up unused task definitions for better maintainability
- Reduces clutter in the task configuration
2025-05-08 19:32:34 +02:00
15 changed files with 563 additions and 17 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
CHANGELOG.md merge=ours

View File

@@ -122,3 +122,77 @@ git commit -m "chore(version): bump to 1.2.3"
```
> Nur die ersten beiden erscheinen im Changelog – der dritte wird **automatisch übersprungen**.
---
## 🧾 Umgang mit `CHANGELOG.md` beim Mergen und Releasen
Wenn du automatisiert einen Changelog mit `git-cliff` erzeugst, ist `CHANGELOG.md` ein **generiertes Artefakt** – und kein handgepflegter Quelltext.
Beim Mergen von Feature-Branches in `main` kann es deshalb zu **unnötigen Konflikten** in dieser Datei kommen, obwohl der Inhalt später sowieso neu erzeugt wird.
---
## 🧼 Umgang mit `CHANGELOG.md` in Feature-Branches
Wenn du mit **Feature-Branches** arbeitest, wird `CHANGELOG.md` dort oft automatisch erzeugt.
Das kann beim späteren Merge in `main` zu **unnötigen Merge-Konflikten** führen.
### ✅ Empfohlene Vorgehensweise
**Bevor du den Branch mit `main` zusammenführst** (Merge oder Cherry-Pick):
```bash
git rm CHANGELOG.md
git commit -m "chore(changelog): remove generated CHANGELOG.md before merge"
git push
```
Dadurch:
* verhinderst du Merge-Konflikte mit `CHANGELOG.md`
* wird die Datei bei Feature-Branches nicht mehr automatisch erzeugt
* bleibt deine Historie sauber und konfliktfrei
> 💡 Der Workflow erzeugt `CHANGELOG.md` automatisch **nur**, wenn:
>
> * die Datei schon vorhanden ist **oder**
> * der Branch `main` heißt
---
## 🧩 Merge-Konflikte verhindern mit `.gitattributes`
Damit Git bei Konflikten in `CHANGELOG.md` **automatisch deine Version bevorzugt**, kannst du folgende Zeile in die Datei `.gitattributes` aufnehmen:
```gitattributes
CHANGELOG.md merge=ours
```
Das bedeutet:
* Beim Merge wird die Version aus dem aktuellen Branch (`ours`) behalten
* Änderungen aus dem Ziel-Branch (`theirs`) werden verworfen
### ✅ So verwendest du es richtig:
1. **Füge die Regel in `main` hinzu**:
```bash
echo "CHANGELOG.md merge=ours" >> .gitattributes
git add .gitattributes
git commit -m "chore(git): prevent merge conflicts in CHANGELOG.md"
git push origin main
```
2. **Hole sie in deinen Feature-Branch**:
```bash
git checkout feature/xyz
git rebase origin/main
```
3. **Ab sofort werden Konflikte in `CHANGELOG.md` automatisch aufgelöst** – lokal.
> ⚠️ Hinweis: Plattformen wie **Gitea, GitHub oder GitLab ignorieren `.gitattributes` beim Merge über die Web-Oberfläche**.
> Führe Merges daher **lokal** durch, wenn du Konflikte verhindern willst.

View File

@@ -1,42 +1,47 @@
name: Auto Changelog & Release
on:
workflow_dispatch:
push:
branches:
- main
- '**'
jobs:
detect-version-change:
runs-on: ubuntu-latest
outputs:
version_changed: ${{ steps.check.outputs.version_changed }}
version_changed: ${{ steps.set.outputs.version_changed }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check if VERSION file changed
id: check
if: github.ref == 'refs/heads/main'
run: |
echo "🔍 Vergleich mit github.event.before:"
echo "Before: ${{ github.event.before }}"
echo "After: ${{ github.sha }}"
echo "📄 Changed files between before and after:"
git diff --name-only ${{ github.event.before }} ${{ github.sha }} || echo "(diff failed)"
if git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep -q '^VERSION$'; then
echo "✅ VERSION file was changed between before and after"
echo "version_changed=true" >> $GITHUB_OUTPUT
echo "✅ VERSION file was changed"
echo "VERSION_CHANGED=true" >> $GITHUB_ENV
else
echo "ℹ️ VERSION file not changed between before and after"
echo "version_changed=false" >> $GITHUB_OUTPUT
echo "ℹ️ VERSION file not changed"
echo "VERSION_CHANGED=false" >> $GITHUB_ENV
fi
- name: Set output (always)
id: set
run: |
echo "version_changed=${VERSION_CHANGED:-false}" >> $GITHUB_OUTPUT
changelog-only:
needs: detect-version-change
if: needs.detect-version-change.outputs.version_changed == 'false'
if: github.ref != 'refs/heads/main' || needs.detect-version-change.outputs.version_changed == 'false'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -66,22 +71,28 @@ jobs:
run: |
cargo install git-cliff --version "${{ steps.cliff_version.outputs.version }}" --features gitea
- name: Generate unreleased changelog
run: git-cliff -c cliff.toml -o CHANGELOG.md
- name: Generate unreleased changelog (if file exists or on main)
run: |
if [[ -f CHANGELOG.md || "${GITHUB_REF##refs/heads/}" == "main" ]]; then
echo "Generating CHANGELOG.md..."
git-cliff -c cliff.toml -o CHANGELOG.md
else
echo "CHANGELOG.md does not exist and this is not 'main'. Skipping generation."
fi
- name: Commit updated CHANGELOG.md
- name: Commit updated CHANGELOG
run: |
git add CHANGELOG.md
if git diff --cached --quiet; then
echo "No changes to commit"
else
git commit -m "chore(changelog): update unreleased changelog"
git push origin main
git push origin "${GITHUB_REF##refs/heads/}"
fi
release:
needs: detect-version-change
if: needs.detect-version-change.outputs.version_changed == 'true'
if: needs.detect-version-change.outputs.version_changed == 'true' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -142,7 +153,7 @@ jobs:
echo "changelog_body_path=$BODY" >> $GITHUB_OUTPUT
- name: Commit updated CHANGELOG.md
- name: Commit updated CHANGELOG
run: |
git add CHANGELOG.md
if git diff --cached --quiet; then

22
.gitea/workflows/test.yml Normal file
View File

@@ -0,0 +1,22 @@
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

View File

@@ -2,6 +2,41 @@
All notable changes to this project will be documented in this file.
## [unreleased]
### 🚀 Features
- *(workflows)* Conditionally generate changelog - ([2ab6f1b](https://git.0xmax42.io/maxp/http-kernel/commit/2ab6f1b8db2d7bd31ca30248d0de183f17a5738c))
- *(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))
### 🐛 Bug Fixes
- *(workflows)* Ensure version detection output is always set - ([abd2d6e](https://git.0xmax42.io/maxp/http-kernel/commit/abd2d6e8402662f863d9974aaa0bc228a4777724))
### 🚜 Refactor
- *(workflows)* Rename changelog file for consistency - ([b9d25f2](https://git.0xmax42.io/maxp/http-kernel/commit/b9d25f23fc6ad7696deee319024aa5b1af4d98c0))
### 📚 Documentation
- *(release)* Update guidelines for handling changelog - ([6ce73c1](https://git.0xmax42.io/maxp/http-kernel/commit/6ce73c14fa6736b622e646feb61522e6ec1f4c5a))
- *(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 MIT license file - ([5118a19](https://git.0xmax42.io/maxp/http-kernel/commit/5118a19aeaa1102591aa7fe093fdec1aa19dc7f5))
### ⚙️ Miscellaneous Tasks
- *(git)* Ignore merge conflicts for CHANGELOG.md - ([d04dfcd](https://git.0xmax42.io/maxp/http-kernel/commit/d04dfcd63ea2478ffdff2e966d310194dafd8d7d))
- *(workflows)* Refine branch handling in release process - ([8f94cc9](https://git.0xmax42.io/maxp/http-kernel/commit/8f94cc915c75a11efa1a8e3bdc51ffea9c2f19b5))
- *(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))
- *(workflows)* Update test workflow for http-kernel project - ([0311546](https://git.0xmax42.io/maxp/http-kernel/commit/03115464e0fb01b8ca00a2fdabde013d004ae8a2))
- *(workflows)* Update Deno setup action to v2 - ([1233a0b](https://git.0xmax42.io/maxp/http-kernel/commit/1233a0b7204d12a60f4b7bd1199242a4cb7c4579))
- *(workflows)* Remove unused workflow_dispatch trigger - ([16c0053](https://git.0xmax42.io/maxp/http-kernel/commit/16c0053964c72d01e5f555ec8f33c9eead160e69))
- *(tasks)* Remove commented-out start and watch scripts - ([04029f8](https://git.0xmax42.io/maxp/http-kernel/commit/04029f87a3b9dd24e8792b852ead9097e18d23c7))
## [0.1.0] - 2025-05-08
### 🚀 Features

18
LICENSE Normal file
View File

@@ -0,0 +1,18 @@
MIT License
Copyright (c) 2025 0xMax42
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.

135
README.md Normal file
View File

@@ -0,0 +1,135 @@
# HttpKernel – A Type-Safe Router & Middleware Kernel for Deno
> Fluent routing • Zero-dependency core • 100 % TypeScript
HttpKernel is a small but powerful dispatching engine that turns an ordinary
`Deno.serve()` loop into a structured, middleware-driven HTTP server.
It focuses on **type safety**, **immutability**, and an **expressive builder API**
while staying framework-agnostic and dependency‑free.
---
## ✨ Key Features
* **Fluent Route Builder** – chain middleware and handlers without side effects
* **Static *and* Dynamic Matching** – use URL patterns *or* custom matcher functions
* **First-Class Generics** – strongly‑typed `ctx.params`, `ctx.query`, and `ctx.state`
* **Pluggable Error Handling** – override 404/500 (and any other status) per kernel
* **Response Decorators** – inject CORS headers, security headers, logging, … in one place
* **100 % Test Coverage** – built‑in unit tests ensure every edge case is covered
---
## 🚀 Quick Start
```ts
// Import directly from your repo or deno.land/x
import { HttpKernel } from "https://deno.land/x/httpkernel/mod.ts";
// 1) Create a kernel (optionally pass overrides)
const kernel = new HttpKernel();
// 2) Register a route with fluent chaining
kernel
.route({ method: "GET", path: "/hello/:name" })
.middleware(async (ctx, next) => {
console.log("Incoming request for", ctx.params.name);
return await next(); // continue pipeline
})
.handle(async (ctx) =>
new Response(`Hello ${ctx.params.name}!`, { status: 200 })
);
// 3) Let Deno serve the kernel
Deno.serve(kernel.handle);
```
Run it:
```bash
deno run --allow-net main.ts
# → GET http://localhost:8000/hello/Isaac
```
---
## 🧩 API Overview
| Method / Type | Purpose | Hints |
| --------------------- | ---------------------------------------------- | ------------------------------------------------------------- |
| `kernel.route(def)` | Begin defining a new route. Returns `RouteBuilder`. | `def` can be `{ method, path }` **or** `{ method, matcher }`. |
| `.middleware(fn)` | Add a middleware to the current builder. | Each call returns a *new* builder (immutability). |
| `.handle(fn)` | Finalise the route and register the handler. | Must be called exactly once per route. |
| `kernel.handle(req)` | Kernel entry point you pass to `Deno.serve()`. | Resolves to a `Response`. |
### Context Shape
```ts
interface Context<S = Record<string, unknown>> {
req: Request; // original request
params: Record<string>; // route params e.g. { id: "42" }
query: Record<string | string[]>; // parsed query string
state: S; // per‑request mutable storage
}
```
Generics let you supply your own param / query / state types for full IntelliSense.
---
## 🛠️ Configuration
```ts
new HttpKernel({
decorateResponse: (res, ctx) => {
// add CORS header globally
const headers = new Headers(res.headers);
headers.set("Access-Control-Allow-Origin", "*");
return new Response(res.body, { ...res, headers });
},
httpErrorHandlers: {
404: () => new Response("Nothing here ☹️", { status: 404 }),
500: (_ctx, err) => {
console.error(err);
return new Response("Custom 500", { status: 500 });
},
},
});
```
Everything is optional – omit what you do not override.
---
## 🧪 Testing
All logic is covered by unit tests using `std@0.204.0/testing`.
Run them with:
```bash
deno test -A
```
The CI suite checks:
* Route guards (`isStaticRouteDefinition`, `isDynamicRouteDefinition`)
* Builder immutability & middleware order
* 404 / 500 fall-backs and error propagation
* Middleware mis-use (double `next()`, wrong signatures, …)
---
## 📦 Roadmap
* 🔌 Adapter helpers for Oak / Fresh / any framework that can delegate to `kernel.handle`
* 🔍 Built‑in logger & timing middleware
* 🔒 CSRF & auth middleware presets
* 📝 OpenAPI route generator
Contributions & ideas are welcome – feel free to open an issue or PR.
---
## 📄 License
[MIT](LICENSE)

View File

@@ -2,8 +2,6 @@
"name": "@0xmax42/http-kernel",
"description": "A simple HTTP kernel for Deno",
"tasks": {
// "start": "deno run --allow-net --allow-env --unstable-kv --allow-read --allow-write --env-file src/main.ts -- --verbose",
// "watch": "deno run --watch --allow-net --allow-env --unstable-kv --allow-read --allow-write --env-file src/main.ts -- --verbose",
"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"
},

View File

@@ -0,0 +1,72 @@
# 🧩 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`

View File

@@ -0,0 +1,50 @@
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>;
}

View File

@@ -0,0 +1,33 @@
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>;
}

View File

@@ -0,0 +1,36 @@
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>;
}

View File

@@ -5,6 +5,12 @@ export type { IHttpErrorHandlers } from './IHttpErrorHandlers.ts';
export type { IHttpKernel } from './IHttpKernel.ts';
export type { IHttpKernelConfig } from './IHttpKernelConfig.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 {
isDynamicRouteDefinition,

View File

@@ -0,0 +1,49 @@
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;

View File

@@ -39,6 +39,12 @@ export type { HttpStatusCode } from './HttpStatusCode.ts';
export { isMiddleware } from './Middleware.ts';
export type { Middleware } from './Middleware.ts';
export type { Params } from './Params.ts';
export type {
OnPipelineEnd,
OnPipelineStart,
OnStepEnd,
OnStepStart,
} from './PipelineHooks.ts';
export type { Query } from './Query.ts';
export type { RegisterRoute } from './RegisterRoute.ts';
export type { ResponseDecorator } from './ResponseDecorator.ts';