Compare commits
15 Commits
v0.1.0
...
a88b4d112f
| Author | SHA1 | Date | |
|---|---|---|---|
|
a88b4d112f
|
|||
|
4f2b65049f
|
|||
| c9de4669c7 | |||
|
a1ce30627c
|
|||
|
5118a19aea
|
|||
| 0a09c8c324 | |||
| b9d25f23fc | |||
| 92f09e6e60 | |||
|
03115464e0
|
|||
| 11a2273240 | |||
|
1233a0b720
|
|||
| 195619ca99 | |||
|
9d5db4f414
|
|||
|
16c0053964
|
|||
|
04029f87a3
|
@@ -1,7 +1,6 @@
|
||||
name: Auto Changelog & Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
@@ -69,7 +68,7 @@ jobs:
|
||||
- name: Generate unreleased changelog
|
||||
run: git-cliff -c cliff.toml -o CHANGELOG.md
|
||||
|
||||
- name: Commit updated CHANGELOG.md
|
||||
- name: Commit updated CHANGELOG
|
||||
run: |
|
||||
git add CHANGELOG.md
|
||||
if git diff --cached --quiet; then
|
||||
@@ -142,7 +141,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
22
.gitea/workflows/test.yml
Normal 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
|
||||
22
CHANGELOG.md
22
CHANGELOG.md
@@ -2,6 +2,28 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [unreleased]
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- *(workflows)* Add CI for Deno project tests - ([9d5db4f](https://git.0xmax42.io/maxp/http-kernel/commit/9d5db4f414cf961248f2b879f2b132b81a32cb92))
|
||||
|
||||
### 🚜 Refactor
|
||||
|
||||
- *(workflows)* Rename changelog file for consistency - ([b9d25f2](https://git.0xmax42.io/maxp/http-kernel/commit/b9d25f23fc6ad7696deee319024aa5b1af4d98c0))
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
- 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
|
||||
|
||||
- *(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
18
LICENSE
Normal 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
135
README.md
Normal 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)
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user