feat(typedrouter): add middleware support to TypedRouter and export middleware type

This commit is contained in:
2026-03-03 20:22:01 +00:00
parent a1f5916faf
commit ee820dd126
11 changed files with 1187 additions and 453 deletions

View File

@@ -1,6 +1,6 @@
# @api.global/typedrequest
A TypeScript library for making **fully typed request/response cycles** across any transport — HTTP, WebSockets, broadcast channels, or custom protocols. Define your API contract once as a TypeScript interface, then use it on both client and server with compile-time safety, automatic routing, virtual streams for real-time data, and built-in traffic monitoring hooks.
A TypeScript library for making **fully typed request/response cycles** across any transport — HTTP, WebSockets, broadcast channels, or custom protocols. Define your API contract once as a TypeScript interface, then use it on both client and server with compile-time safety, automatic routing, middleware chains, virtual streams for real-time data, and built-in traffic monitoring hooks.
## Issue Reporting and Security
@@ -12,6 +12,12 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
pnpm install @api.global/typedrequest
```
You'll also want the interfaces package for defining stream types:
```bash
pnpm install @api.global/typedrequest-interfaces
```
## Usage
All examples use ESM imports and TypeScript.
@@ -114,6 +120,32 @@ mainRouter.addTypedRouter(coreRouter);
mainRouter.addTypedRouter(authRouter);
```
### 🛡️ Middleware
Add middleware functions to a `TypedRouter` that run **before** any handler on that router executes. Middleware is great for authentication, logging, rate limiting, or input validation:
```typescript
const router = new TypedRouter();
// Add authentication middleware
router.addMiddleware(async (typedRequest) => {
const token = typedRequest.localData?.authToken;
if (!token || !isValidToken(token)) {
throw new TypedResponseError('Unauthorized', { reason: 'invalid_token' });
}
});
// Add logging middleware
router.addMiddleware(async (typedRequest) => {
console.log(`Processing ${typedRequest.method}`);
});
// Handlers are only reached if all middleware passes
router.addTypedHandler(secureHandler);
```
Middleware functions receive the full `ITypedRequest` object and run in the order they were added. Throw a `TypedResponseError` from any middleware to reject the request before it reaches the handler.
### 🎯 Custom Targets with TypedTarget
For non-HTTP transports (WebSockets, broadcast channels, IPC), use `TypedTarget` with a custom post function:
@@ -261,6 +293,8 @@ const internalReq = new TypedRequest<IHealthCheck>(target, 'healthCheck');
internalReq.skipHooks = true;
```
Global hooks are shared across all bundles via `globalThis`, making them ideal for application-wide observability.
### 🏗️ Architecture Overview
```
@@ -270,18 +304,25 @@ internalReq.skipHooks = true;
└─────────────┘ └──────────────┘ └──────┬───────┘
┌──────▼───────┐
│ Middleware │
└──────┬───────┘
┌──────▼───────┐
│ TypedHandler │
│ (your logic) │
└──────────────┘
```
- **TypedRequest** — fires typed requests against a URL or TypedTarget
- **TypedTarget** — abstracts the transport layer (HTTP, WebSocket, custom)
- **TypedRouter** — routes incoming requests to the correct handler; composable via `addTypedRouter()`
- **TypedHandler** — processes a single method and returns a typed response
- **VirtualStream** — bidirectional binary streaming with backpressure over any supported transport
- **TypedResponseError** — structured error propagation
- **TypedTools** — guard validation and transport-layer context in handlers
| Component | Role |
|---|---|
| **TypedRequest** | Fires typed requests against a URL or TypedTarget |
| **TypedTarget** | Abstracts the transport layer (HTTP, WebSocket, custom) |
| **TypedRouter** | Routes incoming requests to the correct handler; composable via `addTypedRouter()` |
| **TypedHandler** | Processes a single method and returns a typed response |
| **Middleware** | Pre-handler functions for auth, validation, logging — throw `TypedResponseError` to reject |
| **VirtualStream** | Bidirectional binary streaming with backpressure over any supported transport |
| **TypedResponseError** | Structured error propagation across the wire |
| **TypedTools** | Guard validation and transport-layer context available inside handlers |
## License and Legal Information