@sourceregistry/node-webserver 1.7.4 → 1.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/dist/enhance.d.ts +2 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -413,6 +413,45 @@ app.GET("/admin", enhance(
|
|
|
413
413
|
));
|
|
414
414
|
```
|
|
415
415
|
|
|
416
|
+
### Typed enhancers
|
|
417
|
+
|
|
418
|
+
You can define reusable enhancers with the `EventEnhancer` type. The fifth type parameter (`TExtra`) controls whether the enhancer receives extra event properties like `websocket`.
|
|
419
|
+
|
|
420
|
+
Without WebSocket — works in any HTTP route:
|
|
421
|
+
|
|
422
|
+
```ts
|
|
423
|
+
import type { EventEnhancer } from "@sourceregistry/node-webserver";
|
|
424
|
+
|
|
425
|
+
const withAuth: EventEnhancer<any, any, App.Locals, { user: { id: string; role: string } }> = async (event) => {
|
|
426
|
+
const token = event.request.headers.get("authorization");
|
|
427
|
+
if (!token) error(401, { message: "Unauthorized" });
|
|
428
|
+
return { user: await verifyToken(token) };
|
|
429
|
+
};
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
With WebSocket — only usable in `router.WS()` routes:
|
|
433
|
+
|
|
434
|
+
```ts
|
|
435
|
+
import type { EventEnhancer } from "@sourceregistry/node-webserver";
|
|
436
|
+
import type { WebSocket } from "ws";
|
|
437
|
+
|
|
438
|
+
const withWsAuth: EventEnhancer<any, any, App.Locals, { user: { id: string } }, { websocket: WebSocket }> = async (event) => {
|
|
439
|
+
// event.websocket is available here
|
|
440
|
+
const token = event.request.headers.get("authorization");
|
|
441
|
+
if (!token) error(401, { message: "Unauthorized" });
|
|
442
|
+
return { user: await verifyToken(token) };
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
router.WS("/ws/chat", enhance(
|
|
446
|
+
async ({ context, websocket }) => {
|
|
447
|
+
websocket.send(`hello ${context.user.id}`);
|
|
448
|
+
},
|
|
449
|
+
withWsAuth
|
|
450
|
+
));
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
Plain HTTP enhancers (`TExtra = {}`) can still be passed to a WS `enhance()` call — they just won't have access to `websocket`.
|
|
454
|
+
|
|
416
455
|
## Router Lifecycle Hooks
|
|
417
456
|
|
|
418
457
|
Use `pre()` for logic that should run before route resolution, and `post()` for logic that should run after a response has been produced.
|
|
@@ -486,6 +525,32 @@ app.WS("/ws/chat/[room]", async (event) => {
|
|
|
486
525
|
});
|
|
487
526
|
```
|
|
488
527
|
|
|
528
|
+
`enhance()` works with WebSocket handlers too. When your handler includes `websocket` in the event type, the returned function requires it automatically:
|
|
529
|
+
|
|
530
|
+
```ts
|
|
531
|
+
import { enhance, error } from "@sourceregistry/node-webserver";
|
|
532
|
+
|
|
533
|
+
app.WS("/ws/chat/[room]", enhance(
|
|
534
|
+
async ({ context, params, websocket }) => {
|
|
535
|
+
websocket.send(`joined:${params.room} as ${context.user.id}`);
|
|
536
|
+
|
|
537
|
+
websocket.on("message", (message) => {
|
|
538
|
+
websocket.send(`echo:${message.toString()}`);
|
|
539
|
+
});
|
|
540
|
+
},
|
|
541
|
+
async (event) => {
|
|
542
|
+
const token = event.request.headers.get("authorization");
|
|
543
|
+
if (!token) {
|
|
544
|
+
error(401, { message: "Unauthorized" });
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
return { user: { id: "u_1", role: "member" } };
|
|
548
|
+
}
|
|
549
|
+
));
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
If an enhancer returns a `Response` (or throws via `error()`), the WebSocket handler is skipped and the connection closes.
|
|
553
|
+
|
|
489
554
|
## Static Files
|
|
490
555
|
|
|
491
556
|
Use `dir()` to expose a directory through a route, or `serveStatic()` directly if you want manual control.
|
package/dist/enhance.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { MaybePromise } from './types/MaybePromise';
|
|
|
3
3
|
import { WebSocket } from 'ws';
|
|
4
4
|
type AnyFn = (...args: any[]) => any;
|
|
5
5
|
type ConcatReturnTypes<T extends AnyFn[]> = T extends [] ? {} : T extends [infer First, ...infer Rest] ? First extends AnyFn ? Awaited<ReturnType<First>> & ConcatReturnTypes<Rest extends AnyFn[] ? Rest : []> : {} : {};
|
|
6
|
-
export type EventEnhancer<Params extends Partial<Record<string, string>> = Partial<Record<string, string>>, RouteId extends string | null = string | null, Locals extends App.Locals = App.Locals, Context extends Record<string, any> = Record<string, any
|
|
6
|
+
export type EventEnhancer<Params extends Partial<Record<string, string>> = Partial<Record<string, string>>, RouteId extends string | null = string | null, Locals extends App.Locals = App.Locals, Context extends Record<string, any> = Record<string, any>, TExtra extends object = {}> = (event: RequestEvent<Params, RouteId, Locals> & TExtra) => MaybePromise<Context | void | undefined | Response>;
|
|
7
7
|
export type EnhancedRequestEvent<Params extends Partial<Record<string, string>> = Partial<Record<string, string>>, RouteId extends string | null = string | null, Locals extends App.Locals = App.Locals, Context extends Record<string, any> = Record<string, any>> = RequestEvent<Params, RouteId, Locals> & {
|
|
8
8
|
context: Context;
|
|
9
9
|
};
|
|
@@ -11,5 +11,5 @@ export type EnhancedRouteHandler<Params extends Partial<Record<string, string>>
|
|
|
11
11
|
export type EnhancedWebSocketHandler<Params extends Partial<Record<string, string>> = Partial<Record<string, string>>, RouteId extends string | null = string | null, Locals extends App.Locals = App.Locals, Context extends Record<string, any> = Record<string, any>> = (event: EnhancedRequestEvent<Params, RouteId, Locals, Context> & {
|
|
12
12
|
websocket: WebSocket;
|
|
13
13
|
}) => MaybePromise<any>;
|
|
14
|
-
export declare const enhance: <Params extends Partial<Record<string, string>> = Partial<Record<string, string>>, RouteId extends string | null = string | null, Locals extends App.Locals = App.Locals, Enhancers extends EventEnhancer<Params, RouteId, Locals, any>[] = EventEnhancer<Params, RouteId, Locals, any>[], Context extends Awaited<ConcatReturnTypes<Enhancers>> = Awaited<ConcatReturnTypes<Enhancers
|
|
14
|
+
export declare const enhance: <Params extends Partial<Record<string, string>> = Partial<Record<string, string>>, RouteId extends string | null = string | null, Locals extends App.Locals = App.Locals, TExtra extends object = {}, TReturn = unknown, Enhancers extends EventEnhancer<Params, RouteId, Locals, any, TExtra>[] = EventEnhancer<Params, RouteId, Locals, any, TExtra>[], Context extends Awaited<ConcatReturnTypes<Enhancers>> = Awaited<ConcatReturnTypes<Enhancers>>>(handler: (event: EnhancedRequestEvent<Params, RouteId, Locals, Context> & TExtra) => MaybePromise<TReturn>, ...enhancers: Enhancers) => (event: RequestEvent<Params, RouteId, Locals> & TExtra) => Promise<TReturn | Response>;
|
|
15
15
|
export {};
|