sleepy-serv 0.24.0 → 0.25.0

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 CHANGED
@@ -590,6 +590,49 @@ export default function (req) {
590
590
 
591
591
  This works from both HTTP and WebSocket transports.
592
592
 
593
+ ### Typed Connection Data
594
+
595
+ All WebSocket types accept an optional generic parameter `<T>` that
596
+ constrains `session.data` in filter functions and query results:
597
+
598
+ ```ts
599
+ type ConnectionData = {
600
+ userId: string
601
+ role: 'player' | 'spectator'
602
+ }
603
+
604
+ const app = createApp<ConnectionData>(3000, { ws: true })
605
+
606
+ // session.data is typed as ConnectionData
607
+ app.ws.send('event', body, session => {
608
+ return session.data.userId !== excludedId
609
+ })
610
+
611
+ const players = app.ws.query(session => {
612
+ return session.data.role === 'player'
613
+ })
614
+ ```
615
+
616
+ The type parameter propagates through `Request<T>`, `Middleware<T>`, and
617
+ `Handler<T>`, so typed handler and middleware functions also get typed
618
+ session data through `req.ws`:
619
+
620
+ ```ts
621
+ import type { Request, AsyncHandlerResult } from 'sleepy-serv'
622
+
623
+ type ConnectionData = { userId: string }
624
+
625
+ export default async function (
626
+ req: Request<ConnectionData>,
627
+ ): AsyncHandlerResult {
628
+ req.ws.send('joined', {}, session => {
629
+ return session.data.userId !== 'some-id'
630
+ })
631
+
632
+ return new Response('', { status: 204 })
633
+ }
634
+ ```
635
+
593
636
  ## Exports
594
637
 
595
638
  `sleepy-serv` exports several runtime constants and types:
@@ -600,9 +643,9 @@ This works from both HTTP and WebSocket transports.
600
643
  - `HttpMethod`: HTTP verbs: `Head`, `Get`, `Post`, `Put`, `Patch`, `Delete`
601
644
  - `SessionType`: session state: `Active` (`'active'`), `Inactive` (`'inactive'`)
602
645
  - `SessionFilter`: session filter: `Active` (`'active'`), `Inactive` (`'inactive'`), `All` (`'all'`)
603
- - `SessionEntry`: the shape returned by `query()` and received by filter callbacks: `{ clientId: string, type: SessionType, data: unknown }`
604
- - `FilterFn`: the filter callback type: `(session: SessionEntry, index: number) => boolean`
605
- - `SocketCommands`: the type for `app.ws` and `req.ws`
646
+ - `SessionEntry<T>`: the shape returned by `query()` and received by filter callbacks: `{ clientId: string, type: SessionType, data: T }`
647
+ - `FilterFn<T>`: the filter callback type: `(session: SessionEntry<T>, index: number) => boolean`
648
+ - `SocketCommands<T>`: the type for `app.ws` and `req.ws`
606
649
  - Error classes for every 4xx and 5xx status (e.g. `NotFoundError`, `UnauthorizedError`, `InternalServerError`)
607
650
  - Middleware helpers: `parseJsonBody`, `validateSchemas`, `setValidationFormats`
608
651
 
@@ -8,33 +8,33 @@ export { parseJsonBody, setValidationFormats, validateSchemas, } from './middlew
8
8
  export type { ActiveSession, ActiveSessions, InactiveSession, SocketConnection, SocketOptions, } from './socket';
9
9
  export type { AsyncHandlerResult, BaseRequest, CloseSignal, EndpointRequest, FilterFn, FormattedError, Handler, HandlerResult, Middleware, MiddlewareChain, NextFn, Request, Server, SessionEntry, SocketCommands, SocketData, WebSocketRequest, } from './utils';
10
10
  export type { FormatterField, FormatterSchema, ValidationSchemas, } from './middleware';
11
- export type RouteDefinition = {
11
+ export type RouteDefinition<T = void> = {
12
12
  method: HttpMethod;
13
13
  path: string;
14
- chain: Handler | MiddlewareChain;
14
+ chain: Handler<T> | MiddlewareChain<T>;
15
15
  };
16
- export type MetaEntry = {
16
+ export type MetaEntry<T = void> = {
17
17
  path: string;
18
- middleware: Middleware[];
18
+ middleware: Middleware<T>[];
19
19
  };
20
- export type RouteConfig = {
21
- routes: RouteDefinition[];
22
- meta?: MetaEntry[];
20
+ export type RouteConfig<T = void> = {
21
+ routes: RouteDefinition<T>[];
22
+ meta?: MetaEntry<T>[];
23
23
  };
24
- export type AppOptions = {
24
+ export type AppOptions<T = void> = {
25
25
  hostname?: string;
26
26
  mountPath?: string;
27
- middleware?: Middleware[];
27
+ middleware?: Middleware<T>[];
28
28
  ws?: boolean | SocketOptions;
29
29
  onClose?: () => Promise<void> | void;
30
30
  };
31
31
  type OutputRoutes = Record<string, string[]>;
32
32
  type CloseFn = (force?: boolean) => Promise<void>;
33
- export type App = {
34
- server: Server;
33
+ export type App<T = void> = {
34
+ server: Server<T>;
35
35
  routes: OutputRoutes;
36
- ws: SocketCommands;
36
+ ws: SocketCommands<T>;
37
37
  close: CloseFn;
38
38
  };
39
- export declare function createApp(port: number, config: RouteConfig, opts?: AppOptions): App;
39
+ export declare function createApp<T = void>(port: number, config: RouteConfig<T>, opts?: AppOptions<T>): App<T>;
40
40
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAEV,UAAU,EACV,UAAU,EACV,eAAe,EAEf,OAAO,EACP,MAAM,EACP,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,EACV,cAAc,EACf,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,EACV,aAAa,EAGd,MAAM,UAAU,CAAA;AAEjB,cAAc,UAAU,CAAA;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAE7C,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,EACX,aAAa,GACd,MAAM,SAAS,CAAA;AAEhB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,eAAe,GAChB,MAAM,cAAc,CAAA;AAErB,YAAY,EACV,aAAa,EACb,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,aAAa,GACd,MAAM,UAAU,CAAA;AAEjB,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,eAAe,EACf,QAAQ,EACR,cAAc,EACd,OAAO,EACP,aAAa,EACb,UAAU,EACV,eAAe,EACf,MAAM,EACN,OAAO,EACP,MAAM,EACN,YAAY,EACZ,cAAc,EACd,UAAU,EACV,gBAAgB,GACjB,MAAM,SAAS,CAAA;AAEhB,YAAY,EACV,cAAc,EACd,eAAe,EACf,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,GAAG,eAAe,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,UAAU,EAAE,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,IAAI,CAAC,EAAE,SAAS,EAAE,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,UAAU,EAAE,CAAA;IACzB,EAAE,CAAC,EAAE,OAAO,GAAG,aAAa,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CACrC,CAAA;AAED,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;AA0B5C,KAAK,OAAO,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEjD,MAAM,MAAM,GAAG,GAAG;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,YAAY,CAAA;IACpB,EAAE,EAAE,cAAc,CAAA;IAClB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAsRD,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,EACnB,IAAI,GAAE,UAAe,GACpB,GAAG,CAqBL"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAEV,UAAU,EACV,UAAU,EACV,eAAe,EAEf,OAAO,EACP,MAAM,EACP,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,OAAO,KAAK,EACV,aAAa,EAGd,MAAM,UAAU,CAAA;AAEjB,cAAc,UAAU,CAAA;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAE7C,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,EACX,aAAa,GACd,MAAM,SAAS,CAAA;AAEhB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,eAAe,GAChB,MAAM,cAAc,CAAA;AAErB,YAAY,EACV,aAAa,EACb,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,aAAa,GACd,MAAM,UAAU,CAAA;AAEjB,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,eAAe,EACf,QAAQ,EACR,cAAc,EACd,OAAO,EACP,aAAa,EACb,UAAU,EACV,eAAe,EACf,MAAM,EACN,OAAO,EACP,MAAM,EACN,YAAY,EACZ,cAAc,EACd,UAAU,EACV,gBAAgB,GACjB,MAAM,SAAS,CAAA;AAEhB,YAAY,EACV,cAAc,EACd,eAAe,EACf,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,MAAM,MAAM,eAAe,CAAC,CAAC,GAAG,IAAI,IAAI;IACtC,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;CACvC,CAAA;AAED,MAAM,MAAM,SAAS,CAAC,CAAC,GAAG,IAAI,IAAI;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,IAAI,IAAI;IAClC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5B,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,IAAI,IAAI;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5B,EAAE,CAAC,EAAE,OAAO,GAAG,aAAa,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CACrC,CAAA;AAED,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;AA4B5C,KAAK,OAAO,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEjD,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,IAAI;IAC1B,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;IACjB,MAAM,EAAE,YAAY,CAAA;IACpB,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,CAAA;IACrB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AA0RD,wBAAgB,SAAS,CAAC,CAAC,GAAG,IAAI,EAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,IAAI,GAAE,UAAU,CAAC,CAAC,CAAM,GACvB,GAAG,CAAC,CAAC,CAAC,CAqBR"}
@@ -12,8 +12,8 @@ export type ValidationSchemas = {
12
12
  body?: Schema;
13
13
  };
14
14
  export type SchemaKey = keyof ValidationSchemas;
15
- export declare function parseJsonBody(): Middleware;
15
+ export declare function parseJsonBody<T = void>(): Middleware<T>;
16
16
  export declare function setValidationFormats(formats: Record<string, Format>): void;
17
17
  export declare function resetValidationFormatsState(): void;
18
- export declare function validateSchemas(schemas: ValidationSchemas): Middleware;
18
+ export declare function validateSchemas<T = void>(schemas: ValidationSchemas): Middleware<T>;
19
19
  //# sourceMappingURL=middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/core/middleware.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAoB,MAAM,KAAK,CAAA;AAE3D,OAAO,KAAK,EAIV,UAAU,EAGX,MAAM,SAAS,CAAA;AAEhB,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;AAE5D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAA;AAmF/C,wBAAgB,aAAa,IAAK,UAAU,CAoB3C;AAED,wBAAgB,oBAAoB,CAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAU3E;AAID,wBAAgB,2BAA2B,IAAK,IAAI,CAGnD;AAcD,wBAAgB,eAAe,CAAE,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAgCvE"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/core/middleware.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAoB,MAAM,KAAK,CAAA;AAE3D,OAAO,KAAK,EAIV,UAAU,EAGX,MAAM,SAAS,CAAA;AAEhB,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;AAE5D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAA;AAmF/C,wBAAgB,aAAa,CAAC,CAAC,GAAG,IAAI,KAAM,UAAU,CAAC,CAAC,CAAC,CAoBxD;AAED,wBAAgB,oBAAoB,CAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAU3E;AAID,wBAAgB,2BAA2B,IAAK,IAAI,CAGnD;AAcD,wBAAgB,eAAe,CAAC,CAAC,GAAG,IAAI,EACtC,OAAO,EAAE,iBAAiB,GACzB,UAAU,CAAC,CAAC,CAAC,CAgCf"}
@@ -1,29 +1,29 @@
1
1
  import type { WebSocketHandler } from 'bun';
2
2
  import type { AsyncHandlerResult, CloseSignal, HttpMethod, Request, MiddlewareChain, SocketCommands, SocketData } from './utils';
3
- type SocketHandler = (req: Request, res: unknown) => AsyncHandlerResult;
4
- type SocketEndpoint = {
3
+ type SocketHandler<T = void> = (req: Request<T>, res: unknown) => AsyncHandlerResult;
4
+ type SocketEndpoint<T = void> = {
5
5
  method: HttpMethod;
6
6
  path: string;
7
- handler: SocketHandler;
7
+ handler: SocketHandler<T>;
8
8
  };
9
- export type SocketConnection = {
10
- data: SocketData;
9
+ export type SocketConnection<T = void> = {
10
+ data: SocketData<T>;
11
11
  send: (data: string) => unknown;
12
12
  close: (code?: number, reason?: string) => void;
13
13
  };
14
- export type ActiveSession = {
14
+ export type ActiveSession<T = void> = {
15
15
  token: string;
16
- ws: SocketConnection;
16
+ ws: SocketConnection<T>;
17
17
  };
18
- export type InactiveSession = {
18
+ export type InactiveSession<T = void> = {
19
19
  token: string;
20
20
  expiresAt: number;
21
- data: unknown;
21
+ data: T;
22
22
  };
23
- export type ActiveSessions = ReadonlyMap<string, ActiveSession>;
23
+ export type ActiveSessions<T = void> = ReadonlyMap<string, ActiveSession<T>>;
24
24
  export declare const ServerCloseSignals: Record<string, CloseSignal>;
25
25
  export type ServerCloseSignals = typeof ServerCloseSignals[keyof typeof ServerCloseSignals];
26
- export type Session = ActiveSession | InactiveSession;
26
+ export type Session<T = void> = ActiveSession<T> | InactiveSession<T>;
27
27
  export type SocketOptions = {
28
28
  dropThreshold?: number;
29
29
  heartbeatInterval?: number;
@@ -33,33 +33,33 @@ export type SocketOptions = {
33
33
  onOpen?: (clientId: string) => void;
34
34
  onClose?: (clientId: string, signal: CloseSignal) => void;
35
35
  };
36
- export type Ticket = {
36
+ export type Ticket<T = void> = {
37
37
  clientId: string;
38
38
  expiresAt: number;
39
- data: unknown;
39
+ data: T;
40
40
  };
41
- export type SocketState = {
41
+ export type SocketState<T = void> = {
42
42
  dropThreshold: number;
43
43
  heartbeatInterval: number;
44
44
  maxTickets: number;
45
45
  reclaimTtl: number;
46
46
  ticketTtl: number;
47
- tickets: Map<string, Ticket>;
48
- activeSessions: Map<string, ActiveSession>;
49
- inactiveSessions: Map<string, InactiveSession>;
47
+ tickets: Map<string, Ticket<T>>;
48
+ activeSessions: Map<string, ActiveSession<T>>;
49
+ inactiveSessions: Map<string, InactiveSession<T>>;
50
50
  onOpen: ((clientId: string) => void) | null;
51
51
  onClose: ((clientId: string, signal: CloseSignal) => void) | null;
52
52
  };
53
- export type SocketRoute = {
53
+ export type SocketRoute<T = void> = {
54
54
  method: HttpMethod;
55
55
  path: string;
56
56
  segments: string[];
57
- chain: MiddlewareChain;
57
+ chain: MiddlewareChain<T>;
58
58
  };
59
- export declare function buildSocketState(opts?: SocketOptions): SocketState;
60
- export declare function buildSocketServer(routes: SocketRoute[], state: SocketState, commands: SocketCommands): WebSocketHandler<SocketData>;
61
- export declare function buildSocketHandlers(state: SocketState): SocketEndpoint[];
62
- export declare function buildDisabledSocketCommands(): SocketCommands;
63
- export declare function buildSocketCommands(state: SocketState): SocketCommands;
59
+ export declare function buildSocketState<T = void>(opts?: SocketOptions): SocketState<T>;
60
+ export declare function buildSocketServer<T = void>(routes: SocketRoute<T>[], state: SocketState<T>, commands: SocketCommands<T>): WebSocketHandler<SocketData<T>>;
61
+ export declare function buildSocketHandlers<T = void>(state: SocketState<T>): SocketEndpoint<T>[];
62
+ export declare function buildDisabledSocketCommands<T = void>(): SocketCommands<T>;
63
+ export declare function buildSocketCommands<T = void>(state: SocketState<T>): SocketCommands<T>;
64
64
  export {};
65
65
  //# sourceMappingURL=socket.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../src/core/socket.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../src/core/socket.ts"],"names":[],"mappings":"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"}
@@ -83,19 +83,19 @@ export type FormattedError = {
83
83
  export type AsyncHandlerResult = Promise<Response>;
84
84
  export type HandlerResult = Response | AsyncHandlerResult;
85
85
  export type NextFn = (data?: unknown) => HandlerResult;
86
- export type Middleware = (req: Request, res: unknown, next: NextFn) => HandlerResult;
87
- export type Handler = (req: Request, res: unknown) => HandlerResult;
88
- export type MiddlewareChain = (Middleware | Handler)[];
86
+ export type Middleware<T = void> = (req: Request<T>, res: unknown, next: NextFn) => HandlerResult;
87
+ export type Handler<T = void> = (req: Request<T>, res: unknown) => HandlerResult;
88
+ export type MiddlewareChain<T = void> = (Middleware<T> | Handler<T>)[];
89
89
  export type CloseSignal = {
90
90
  code: number;
91
91
  reason: string;
92
92
  };
93
- export type SocketData = {
93
+ export type SocketData<T = void> = {
94
94
  clientId: string;
95
95
  superseded: boolean;
96
96
  reaped: boolean;
97
97
  reaperHandle: TimeoutHandle | null;
98
- data: unknown;
98
+ data: T;
99
99
  };
100
100
  export declare const SessionType: {
101
101
  readonly Active: "active";
@@ -108,38 +108,38 @@ export declare const SessionFilter: {
108
108
  readonly All: "all";
109
109
  };
110
110
  export type SessionFilter = typeof SessionFilter[keyof typeof SessionFilter];
111
- export type SessionEntry = {
111
+ export type SessionEntry<T = void> = {
112
112
  clientId: string;
113
113
  type: SessionType;
114
- data: unknown;
114
+ data: T;
115
115
  };
116
- export type FilterFn = (session: SessionEntry, index: number) => boolean;
117
- export type SocketCommands = {
116
+ export type FilterFn<T = void> = (session: SessionEntry<T>, index: number) => boolean;
117
+ export type SocketCommands<T = void> = {
118
118
  broadcast: (event: string, body: unknown) => void;
119
- send: (event: string, body: unknown, fn: FilterFn) => void;
120
- drop: (signal: CloseSignal, fn: FilterFn) => void;
121
- query: (fn: FilterFn, filter?: SessionFilter) => SessionEntry[];
119
+ send: (event: string, body: unknown, fn: FilterFn<T>) => void;
120
+ drop: (signal: CloseSignal, fn: FilterFn<T>) => void;
121
+ query: (fn: FilterFn<T>, filter?: SessionFilter) => SessionEntry<T>[];
122
122
  };
123
- export type BaseRequest = {
123
+ export type BaseRequest<T = void> = {
124
124
  method: HttpMethod;
125
125
  route: string;
126
126
  headers: Headers;
127
127
  params: Record<string, string>;
128
128
  query: Record<string, unknown>;
129
129
  json: () => Promise<unknown>;
130
- ws: SocketCommands;
130
+ ws: SocketCommands<T>;
131
131
  };
132
- export type EndpointRequest = BaseRequest & {
132
+ export type EndpointRequest<T = void> = BaseRequest<T> & {
133
133
  raw: BunRequest;
134
- server: Server;
134
+ server: Server<T>;
135
135
  };
136
- export type WebSocketRequest = BaseRequest & {
136
+ export type WebSocketRequest<T = void> = BaseRequest<T> & {
137
137
  id: string;
138
138
  clientId: string;
139
139
  };
140
- export type Request = EndpointRequest | WebSocketRequest;
141
- export type Server = BunServer<SocketData>;
140
+ export type Request<T = void> = EndpointRequest<T> | WebSocketRequest<T>;
141
+ export type Server<T = void> = BunServer<SocketData<T>>;
142
142
  export declare function toSegments(pathString: string): string[];
143
143
  export declare function formatError(prefix: string, input: ValidationError): FormattedError;
144
- export declare function executeMiddlewareChain(req: Request, chain: MiddlewareChain): AsyncHandlerResult;
144
+ export declare function executeMiddlewareChain<T = void>(req: Request<T>, chain: MiddlewareChain<T>): AsyncHandlerResult;
145
145
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/core/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/core/utils.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from './core';
2
2
  import type { AppOptions, App } from './core';
3
- export declare function createApp(port: number, opts?: AppOptions): App;
3
+ export declare function createApp<T = void>(port: number, opts?: AppOptions<T>): App<T>;
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA;AAEtB,OAAO,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAA;AAE7C,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,UAAU,GAChB,GAAG,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA;AAEtB,OAAO,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAA;AAE7C,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,CAAC,GAAG,IAAI,EACxC,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GACnB,GAAG,CAAC,CAAC,CAAC,CAAA"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A more opinionated web server for building REST-ful applications",
4
4
  "author": "Travis J True",
5
5
  "license": "MIT",
6
- "version": "0.24.0",
6
+ "version": "0.25.0",
7
7
  "type": "module",
8
8
  "bin": {
9
9
  "sleepy": "./src/cli/index.ts"
package/src/core/index.ts CHANGED
@@ -35,9 +35,7 @@ import type {
35
35
  Server,
36
36
  } from './utils'
37
37
 
38
- import type {
39
- SocketCommands,
40
- } from './utils'
38
+ import type { SocketCommands } from './utils'
41
39
 
42
40
  import type {
43
41
  SocketOptions,
@@ -95,62 +93,64 @@ export type {
95
93
  ValidationSchemas,
96
94
  } from './middleware'
97
95
 
98
- export type RouteDefinition = {
96
+ export type RouteDefinition<T = void> = {
99
97
  method: HttpMethod
100
98
  path: string
101
- chain: Handler | MiddlewareChain
99
+ chain: Handler<T> | MiddlewareChain<T>
102
100
  }
103
101
 
104
- export type MetaEntry = {
102
+ export type MetaEntry<T = void> = {
105
103
  path: string
106
- middleware: Middleware[]
104
+ middleware: Middleware<T>[]
107
105
  }
108
106
 
109
- export type RouteConfig = {
110
- routes: RouteDefinition[]
111
- meta?: MetaEntry[]
107
+ export type RouteConfig<T = void> = {
108
+ routes: RouteDefinition<T>[]
109
+ meta?: MetaEntry<T>[]
112
110
  }
113
111
 
114
- export type AppOptions = {
112
+ export type AppOptions<T = void> = {
115
113
  hostname?: string
116
114
  mountPath?: string
117
- middleware?: Middleware[]
115
+ middleware?: Middleware<T>[]
118
116
  ws?: boolean | SocketOptions
119
117
  onClose?: () => Promise<void> | void
120
118
  }
121
119
 
122
120
  type OutputRoutes = Record<string, string[]>
123
- type ServerRoutes = Record<string, Record<string, EndpointHandler>>
124
121
 
125
- type EndpointHandler = (
122
+ type ServerRoutes<T = void> =
123
+ Record<string, Record<string, EndpointHandler<T>>>
124
+
125
+ type EndpointHandler<T = void> = (
126
126
  bunReq: BunRequest,
127
- server: Server,
127
+ server: Server<T>,
128
128
  ) => AsyncHandlerResult
129
129
 
130
- type ChainRoute = {
130
+ type ChainRoute<T = void> = {
131
131
  method: HttpMethod
132
132
  path: string
133
- chain: MiddlewareChain
133
+ chain: MiddlewareChain<T>
134
134
  }
135
135
 
136
- type ModuleRoute = {
136
+ type ModuleRoute<T = void> = {
137
137
  method: HttpMethod
138
138
  path: string
139
- handler: EndpointHandler
139
+ handler: EndpointHandler<T>
140
140
  }
141
141
 
142
- type AppRoutes = {
143
- server: ServerRoutes
142
+ type AppRoutes<T = void> = {
143
+ server: ServerRoutes<T>
144
144
  output: OutputRoutes
145
- socket: SocketRoute[]
145
+ socket: SocketRoute<T>[]
146
146
  }
147
147
 
148
148
  type CloseFn = (force?: boolean) => Promise<void>
149
149
 
150
- export type App = {
151
- server: Server
150
+ export type App<T = void> = {
151
+ server: Server<T>
152
152
  routes: OutputRoutes
153
- ws: SocketCommands
153
+ ws: SocketCommands<T>
154
154
  close: CloseFn
155
155
  }
156
156
 
@@ -158,7 +158,7 @@ function methodNotAllowedHandler (_req: unknown): never {
158
158
  throw new MethodNotAllowedError()
159
159
  }
160
160
 
161
- function defaultMethodMap (): Record<string, EndpointHandler> {
161
+ function defaultMethodMap<T> (): Record<string, EndpointHandler<T>> {
162
162
  return {
163
163
  HEAD: methodNotAllowedHandler,
164
164
  GET: methodNotAllowedHandler,
@@ -183,11 +183,11 @@ function resolveSocketOptions (
183
183
  return ws
184
184
  }
185
185
 
186
- function buildEndpointRequest (
186
+ function buildEndpointRequest<T> (
187
187
  bunReq: BunRequest,
188
- server: Server,
189
- ws: SocketCommands,
190
- ): EndpointRequest {
188
+ server: Server<T>,
189
+ ws: SocketCommands<T>,
190
+ ): EndpointRequest<T> {
191
191
  const url = new URL(bunReq.url)
192
192
  const qs = url.search.replace('?', '')
193
193
 
@@ -214,7 +214,7 @@ function buildEndpointRequest (
214
214
  }
215
215
  }
216
216
 
217
- function normalizeChain (route: RouteDefinition): ChainRoute {
217
+ function normalizeChain<T> (route: RouteDefinition<T>): ChainRoute<T> {
218
218
  const chain = Array.isArray(route.chain)
219
219
  ? route.chain
220
220
  : [route.chain]
@@ -226,13 +226,13 @@ function normalizeChain (route: RouteDefinition): ChainRoute {
226
226
  }
227
227
  }
228
228
 
229
- function buildMergedRoutes (
230
- routePaths: ChainRoute[],
231
- middleware: Middleware[],
232
- meta: MetaEntry[],
233
- state: SocketState,
229
+ function buildMergedRoutes<T> (
230
+ routePaths: ChainRoute<T>[],
231
+ middleware: Middleware<T>[],
232
+ meta: MetaEntry<T>[],
233
+ state: SocketState<T>,
234
234
  mountPath: string,
235
- ): ChainRoute[] {
235
+ ): ChainRoute<T>[] {
236
236
  const socketRoutes = buildSocketHandlers(state)
237
237
 
238
238
  for (const socketRoute of socketRoutes) {
@@ -268,19 +268,21 @@ function buildMergedRoutes (
268
268
  return routePaths
269
269
  }
270
270
 
271
- function buildSocketRoutes (mergedRoutes: ChainRoute[]): SocketRoute[] {
271
+ function buildSocketRoutes<T> (
272
+ mergedRoutes: ChainRoute<T>[],
273
+ ): SocketRoute<T>[] {
272
274
  return mergedRoutes.map(route => ({
273
275
  ...route,
274
276
  segments: toSegments(route.path),
275
277
  }))
276
278
  }
277
279
 
278
- function buildModuleRoutes (
279
- socketRoutes: SocketRoute[],
280
- ws: SocketCommands,
281
- ): ModuleRoute[] {
280
+ function buildModuleRoutes<T> (
281
+ socketRoutes: SocketRoute<T>[],
282
+ ws: SocketCommands<T>,
283
+ ): ModuleRoute<T>[] {
282
284
  return socketRoutes.map(route => {
283
- const handler: EndpointHandler = async (bunReq, server) => {
285
+ const handler: EndpointHandler<T> = async (bunReq, server) => {
284
286
  const req = buildEndpointRequest(bunReq, server, ws)
285
287
 
286
288
  return executeMiddlewareChain(req, route.chain)
@@ -294,11 +296,13 @@ function buildModuleRoutes (
294
296
  })
295
297
  }
296
298
 
297
- function buildServerRoutes (moduleRoutes: ModuleRoute[]): ServerRoutes {
298
- return moduleRoutes.reduce<ServerRoutes>(
299
+ function buildServerRoutes<T> (
300
+ moduleRoutes: ModuleRoute<T>[],
301
+ ): ServerRoutes<T> {
302
+ return moduleRoutes.reduce<ServerRoutes<T>>(
299
303
  (accum, curr) => {
300
304
  if (!accum[curr.path]) {
301
- accum[curr.path] = defaultMethodMap()
305
+ accum[curr.path] = defaultMethodMap<T>()
302
306
  }
303
307
 
304
308
  accum[curr.path][curr.method] = curr.handler
@@ -307,7 +311,7 @@ function buildServerRoutes (moduleRoutes: ModuleRoute[]): ServerRoutes {
307
311
  }, {})
308
312
  }
309
313
 
310
- function buildOutputRoutes (moduleRoutes: ModuleRoute[]): OutputRoutes {
314
+ function buildOutputRoutes<T> (moduleRoutes: ModuleRoute<T>[]): OutputRoutes {
311
315
  return moduleRoutes.reduce<OutputRoutes>((accum, curr) => {
312
316
  accum[curr.path] = accum[curr.path] || []
313
317
  accum[curr.path].push(curr.method)
@@ -316,12 +320,12 @@ function buildOutputRoutes (moduleRoutes: ModuleRoute[]): OutputRoutes {
316
320
  }, {})
317
321
  }
318
322
 
319
- function buildRoutes (
320
- config: RouteConfig,
321
- state: SocketState | null,
322
- ws: SocketCommands,
323
- opts: AppOptions,
324
- ): AppRoutes {
323
+ function buildRoutes<T> (
324
+ config: RouteConfig<T>,
325
+ state: SocketState<T> | null,
326
+ ws: SocketCommands<T>,
327
+ opts: AppOptions<T>,
328
+ ): AppRoutes<T> {
325
329
  const mountPath = opts.mountPath || ''
326
330
  const middleware = opts.middleware || []
327
331
  const meta = config.meta || []
@@ -360,13 +364,13 @@ function buildRoutes (
360
364
  }
361
365
  }
362
366
 
363
- function buildServer (
367
+ function buildServer<T> (
364
368
  port: number,
365
- routes: AppRoutes,
366
- state: SocketState | null,
367
- ws: SocketCommands,
368
- opts: AppOptions,
369
- ): Server {
369
+ routes: AppRoutes<T>,
370
+ state: SocketState<T> | null,
371
+ ws: SocketCommands<T>,
372
+ opts: AppOptions<T>,
373
+ ): Server<T> {
370
374
  const hostname = opts.hostname || '0.0.0.0'
371
375
 
372
376
  const websocket = state
@@ -390,10 +394,10 @@ function buildServer (
390
394
 
391
395
  return Response.json(httpError.output, { status })
392
396
  },
393
- }) as Server
397
+ }) as Server<T>
394
398
  }
395
399
 
396
- function processIO (server: Server, opts: AppOptions): CloseFn {
400
+ function processIO<T> (server: Server<T>, opts: AppOptions<T>): CloseFn {
397
401
  const onClose = opts.onClose || (() => {})
398
402
 
399
403
  console.info(`Running on port: ${server.port}`)
@@ -430,20 +434,20 @@ function processIO (server: Server, opts: AppOptions): CloseFn {
430
434
  }
431
435
  }
432
436
 
433
- export function createApp (
437
+ export function createApp<T = void> (
434
438
  port: number,
435
- config: RouteConfig,
436
- opts: AppOptions = {},
437
- ): App {
439
+ config: RouteConfig<T>,
440
+ opts: AppOptions<T> = {},
441
+ ): App<T> {
438
442
  const socketOpts = resolveSocketOptions(opts.ws)
439
443
 
440
444
  const state = socketOpts
441
- ? buildSocketState(socketOpts)
445
+ ? buildSocketState<T>(socketOpts)
442
446
  : null
443
447
 
444
448
  const ws = state
445
- ? buildSocketCommands(state)
446
- : buildDisabledSocketCommands()
449
+ ? buildSocketCommands<T>(state)
450
+ : buildDisabledSocketCommands<T>()
447
451
 
448
452
  const routes = buildRoutes(config, state, ws, opts)
449
453
  const server = buildServer(port, routes, state, ws, opts)
@@ -39,7 +39,7 @@ export type SchemaKey = keyof ValidationSchemas
39
39
  let _schemasCompiled = false
40
40
  let _customFormats: Record<string, Format> | null = null
41
41
 
42
- async function parseBody (req: Request): Promise<unknown> {
42
+ async function parseBody<T> (req: Request<T>): Promise<unknown> {
43
43
  try {
44
44
  const result = await req.json()
45
45
 
@@ -117,9 +117,9 @@ function compileSchemas (
117
117
  })
118
118
  }
119
119
 
120
- export function parseJsonBody (): Middleware {
120
+ export function parseJsonBody<T = void> (): Middleware<T> {
121
121
  return async (
122
- req: Request,
122
+ req: Request<T>,
123
123
  res: unknown,
124
124
  next: NextFn,
125
125
  ): AsyncHandlerResult => {
@@ -158,8 +158,8 @@ export function resetValidationFormatsState (): void {
158
158
  _schemasCompiled = false
159
159
  }
160
160
 
161
- function buildValidationSource (
162
- req: Request,
161
+ function buildValidationSource<T> (
162
+ req: Request<T>,
163
163
  res: unknown,
164
164
  ): Record<SchemaKey, unknown> {
165
165
  return {
@@ -170,13 +170,15 @@ function buildValidationSource (
170
170
  }
171
171
  }
172
172
 
173
- export function validateSchemas (schemas: ValidationSchemas): Middleware {
173
+ export function validateSchemas<T = void> (
174
+ schemas: ValidationSchemas,
175
+ ): Middleware<T> {
174
176
  const entries = compileSchemas(schemas)
175
177
 
176
178
  _schemasCompiled = true
177
179
 
178
180
  return (
179
- req: Request,
181
+ req: Request<T>,
180
182
  res: unknown,
181
183
  next: NextFn,
182
184
  ): HandlerResult => {
@@ -50,7 +50,10 @@ import type {
50
50
  ResponseMessage,
51
51
  } from './messages'
52
52
 
53
- type SocketHandler = (req: Request, res: unknown) => AsyncHandlerResult
53
+ type SocketHandler<T = void> = (
54
+ req: Request<T>,
55
+ res: unknown,
56
+ ) => AsyncHandlerResult
54
57
 
55
58
  type UpgradeData = {
56
59
  clientId?: string
@@ -62,10 +65,10 @@ type UpgradeContext = {
62
65
  [key: string]: unknown
63
66
  }
64
67
 
65
- type SocketEndpoint = {
68
+ type SocketEndpoint<T = void> = {
66
69
  method: HttpMethod
67
70
  path: string
68
- handler: SocketHandler
71
+ handler: SocketHandler<T>
69
72
  }
70
73
 
71
74
  type CreateSocketRequest = {
@@ -87,24 +90,24 @@ type UpdateTicketRequest = {
87
90
  }
88
91
  }
89
92
 
90
- export type SocketConnection = {
91
- data: SocketData
93
+ export type SocketConnection<T = void> = {
94
+ data: SocketData<T>
92
95
  send: (data: string) => unknown
93
96
  close: (code?: number, reason?: string) => void
94
97
  }
95
98
 
96
- export type ActiveSession = {
99
+ export type ActiveSession<T = void> = {
97
100
  token: string
98
- ws: SocketConnection
101
+ ws: SocketConnection<T>
99
102
  }
100
103
 
101
- export type InactiveSession = {
104
+ export type InactiveSession<T = void> = {
102
105
  token: string
103
106
  expiresAt: number
104
- data: unknown
107
+ data: T
105
108
  }
106
109
 
107
- export type ActiveSessions = ReadonlyMap<string, ActiveSession>
110
+ export type ActiveSessions<T = void> = ReadonlyMap<string, ActiveSession<T>>
108
111
 
109
112
  export const ServerCloseSignals: Record<string, CloseSignal> = {
110
113
  Ok: {
@@ -124,7 +127,7 @@ export const ServerCloseSignals: Record<string, CloseSignal> = {
124
127
  export type ServerCloseSignals =
125
128
  typeof ServerCloseSignals[keyof typeof ServerCloseSignals]
126
129
 
127
- export type Session = ActiveSession | InactiveSession
130
+ export type Session<T = void> = ActiveSession<T> | InactiveSession<T>
128
131
 
129
132
  export type SocketOptions = {
130
133
  dropThreshold?: number
@@ -136,30 +139,30 @@ export type SocketOptions = {
136
139
  onClose?: (clientId: string, signal: CloseSignal) => void
137
140
  }
138
141
 
139
- export type Ticket = {
142
+ export type Ticket<T = void> = {
140
143
  clientId: string
141
144
  expiresAt: number
142
- data: unknown
145
+ data: T
143
146
  }
144
147
 
145
- export type SocketState = {
148
+ export type SocketState<T = void> = {
146
149
  dropThreshold: number
147
150
  heartbeatInterval: number
148
151
  maxTickets: number
149
152
  reclaimTtl: number
150
153
  ticketTtl: number
151
- tickets: Map<string, Ticket>
152
- activeSessions: Map<string, ActiveSession>
153
- inactiveSessions: Map<string, InactiveSession>
154
+ tickets: Map<string, Ticket<T>>
155
+ activeSessions: Map<string, ActiveSession<T>>
156
+ inactiveSessions: Map<string, InactiveSession<T>>
154
157
  onOpen: ((clientId: string) => void) | null
155
158
  onClose: ((clientId: string, signal: CloseSignal) => void) | null
156
159
  }
157
160
 
158
- export type SocketRoute = {
161
+ export type SocketRoute<T = void> = {
159
162
  method: HttpMethod
160
163
  path: string
161
164
  segments: string[]
162
- chain: MiddlewareChain
165
+ chain: MiddlewareChain<T>
163
166
  }
164
167
 
165
168
  const ajv = new Ajv({
@@ -263,7 +266,7 @@ const updateTicketValidator = ajv.compile<UpdateTicketRequest>({
263
266
  },
264
267
  })
265
268
 
266
- function isSessionActive (session: InactiveSession): boolean {
269
+ function isSessionActive<T> (session: InactiveSession<T>): boolean {
267
270
  return !session.expiresAt || session.expiresAt > Date.now()
268
271
  }
269
272
 
@@ -285,7 +288,7 @@ function parseMessage (raw: string | Buffer): RawMessage | undefined {
285
288
  }
286
289
  }
287
290
 
288
- function sweepInactiveSessions (state: SocketState): void {
291
+ function sweepInactiveSessions<T> (state: SocketState<T>): void {
289
292
  for (const [key, session] of state.inactiveSessions) {
290
293
  if (!isSessionActive(session)) {
291
294
  state.inactiveSessions.delete(key)
@@ -335,10 +338,10 @@ function matchesSegments (
335
338
  )
336
339
  }
337
340
 
338
- function matchRoute (
339
- routes: SocketRoute[],
341
+ function matchRoute<T> (
342
+ routes: SocketRoute<T>[],
340
343
  message: RequestMessage,
341
- ): SocketRoute {
344
+ ): SocketRoute<T> {
342
345
  const requestSegments = toSegments(message.route)
343
346
 
344
347
  const matchingPaths = routes.filter(route =>
@@ -358,8 +361,8 @@ function matchRoute (
358
361
  return route
359
362
  }
360
363
 
361
- function buildParams (
362
- route: SocketRoute,
364
+ function buildParams<T> (
365
+ route: SocketRoute<T>,
363
366
  message: RequestMessage,
364
367
  ): Record<string, string> {
365
368
  const requestSegments = toSegments(message.route)
@@ -372,11 +375,11 @@ function buildParams (
372
375
  } : accum, {})
373
376
  }
374
377
 
375
- function buildRequest (
378
+ function buildRequest<T> (
376
379
  params: Record<string, string>,
377
380
  message: RequestMessage,
378
- ws: SocketCommands,
379
- ): WebSocketRequest {
381
+ ws: SocketCommands<T>,
382
+ ): WebSocketRequest<T> {
380
383
  const { id, clientId, method, route } = message
381
384
  const headers = new Headers(message.headers ?? {})
382
385
  const query = message.query ?? {}
@@ -431,7 +434,9 @@ function buildErrorMessage (
431
434
  })
432
435
  }
433
436
 
434
- export function buildSocketState (opts: SocketOptions = {}): SocketState {
437
+ export function buildSocketState<T = void> (
438
+ opts: SocketOptions = {},
439
+ ): SocketState<T> {
435
440
  return {
436
441
  dropThreshold: opts.dropThreshold ?? 120_000,
437
442
  heartbeatInterval: opts.heartbeatInterval ?? 30_000,
@@ -446,11 +451,11 @@ export function buildSocketState (opts: SocketOptions = {}): SocketState {
446
451
  }
447
452
  }
448
453
 
449
- export function buildSocketServer (
450
- routes: SocketRoute[],
451
- state: SocketState,
452
- commands: SocketCommands,
453
- ): WebSocketHandler<SocketData> {
454
+ export function buildSocketServer<T = void> (
455
+ routes: SocketRoute<T>[],
456
+ state: SocketState<T>,
457
+ commands: SocketCommands<T>,
458
+ ): WebSocketHandler<SocketData<T>> {
454
459
  const {
455
460
  dropThreshold,
456
461
  heartbeatInterval,
@@ -461,7 +466,7 @@ export function buildSocketServer (
461
466
  onClose,
462
467
  } = state
463
468
 
464
- function armReaper (ws: SocketConnection) {
469
+ function armReaper (ws: SocketConnection<T>) {
465
470
  if (ws.data.reaperHandle) {
466
471
  clearTimeout(ws.data.reaperHandle)
467
472
  }
@@ -476,7 +481,7 @@ export function buildSocketServer (
476
481
  }, dropThreshold)
477
482
  }
478
483
 
479
- function invokeOpen (ws: SocketConnection) {
484
+ function invokeOpen (ws: SocketConnection<T>) {
480
485
  if (onOpen) {
481
486
  try {
482
487
  onOpen(ws.data.clientId)
@@ -486,7 +491,7 @@ export function buildSocketServer (
486
491
  }
487
492
  }
488
493
 
489
- function invokeClose (ws: SocketConnection, signal: CloseSignal) {
494
+ function invokeClose (ws: SocketConnection<T>, signal: CloseSignal) {
490
495
  if (onClose) {
491
496
  try {
492
497
  onClose(ws.data.clientId, signal)
@@ -497,7 +502,7 @@ export function buildSocketServer (
497
502
  }
498
503
 
499
504
  return {
500
- open (ws: SocketConnection): void {
505
+ open (ws: SocketConnection<T>): void {
501
506
  sweepInactiveSessions(state)
502
507
 
503
508
  const token = randomToken()
@@ -536,7 +541,7 @@ export function buildSocketServer (
536
541
  ws.send(JSON.stringify(welcomeMessage))
537
542
  invokeOpen(ws)
538
543
  },
539
- close (ws: SocketConnection, code: number, reason: string): void {
544
+ close (ws: SocketConnection<T>, code: number, reason: string): void {
540
545
  const signal: CloseSignal = {
541
546
  code,
542
547
  reason,
@@ -570,7 +575,10 @@ export function buildSocketServer (
570
575
 
571
576
  invokeClose(ws, signal)
572
577
  },
573
- async message (ws: SocketConnection, raw: string | Buffer): Promise<void> {
578
+ async message (
579
+ ws: SocketConnection<T>,
580
+ raw: string | Buffer,
581
+ ): Promise<void> {
574
582
  const incomingMsg = parseMessage(raw)
575
583
 
576
584
  if (incomingMsg === undefined) {
@@ -610,7 +618,9 @@ export function buildSocketServer (
610
618
  }
611
619
  }
612
620
 
613
- export function buildSocketHandlers (state: SocketState): SocketEndpoint[] {
621
+ export function buildSocketHandlers<T = void> (
622
+ state: SocketState<T>,
623
+ ): SocketEndpoint<T>[] {
614
624
  const {
615
625
  maxTickets,
616
626
  ticketTtl,
@@ -619,7 +629,7 @@ export function buildSocketHandlers (state: SocketState): SocketEndpoint[] {
619
629
  inactiveSessions,
620
630
  } = state
621
631
 
622
- function issueTicket (clientId: string, data: unknown): string {
632
+ function issueTicket (clientId: string, data: T): string {
623
633
  for (const [key, entry] of tickets) {
624
634
  if (entry.expiresAt > Date.now()) {
625
635
  break
@@ -644,7 +654,7 @@ export function buildSocketHandlers (state: SocketState): SocketEndpoint[] {
644
654
  return hash
645
655
  }
646
656
 
647
- function redeemTicket (hash: string): Ticket | undefined {
657
+ function redeemTicket (hash: string): Ticket<T> | undefined {
648
658
  const entry = hash ? tickets.get(hash) : undefined
649
659
 
650
660
  if (!entry) {
@@ -661,7 +671,7 @@ export function buildSocketHandlers (state: SocketState): SocketEndpoint[] {
661
671
  {
662
672
  method: 'GET',
663
673
  path: '/ws',
664
- handler (req: Request, res: unknown): AsyncHandlerResult {
674
+ handler (req: Request<T>, res: unknown): AsyncHandlerResult {
665
675
  const validReq = validateSchema(req, createSocketValidator)
666
676
 
667
677
  if (typeof res !== 'object') {
@@ -694,11 +704,11 @@ export function buildSocketHandlers (state: SocketState): SocketEndpoint[] {
694
704
  {
695
705
  method: 'POST',
696
706
  path: '/ws',
697
- async handler (req: Request, res: unknown): AsyncHandlerResult {
707
+ async handler (req: Request<T>, res: unknown): AsyncHandlerResult {
698
708
  validateSchema(req, createTicketValidator)
699
709
 
700
710
  const clientId = crypto.randomUUID()
701
- const ticket = issueTicket(clientId, res)
711
+ const ticket = issueTicket(clientId, res as T)
702
712
 
703
713
  return Response.json({
704
714
  clientId,
@@ -710,12 +720,12 @@ export function buildSocketHandlers (state: SocketState): SocketEndpoint[] {
710
720
  {
711
721
  method: 'PUT',
712
722
  path: '/ws/:clientId',
713
- async handler (req: Request, res: unknown): AsyncHandlerResult {
723
+ async handler (req: Request<T>, res: unknown): AsyncHandlerResult {
714
724
  const validReq = validateSchema(req, updateTicketValidator)
715
725
  const authHeader = validReq.headers.get('authorization')!
716
726
  const token = authHeader.slice('Bearer '.length)
717
727
 
718
- let session: Session | undefined =
728
+ let session: Session<T> | undefined =
719
729
  activeSessions.get(validReq.params.clientId)
720
730
 
721
731
  if (!session) {
@@ -748,7 +758,7 @@ export function buildSocketHandlers (state: SocketState): SocketEndpoint[] {
748
758
  ]
749
759
  }
750
760
 
751
- export function buildDisabledSocketCommands (): SocketCommands {
761
+ export function buildDisabledSocketCommands<T = void> (): SocketCommands<T> {
752
762
  const msg = 'WebSocket support is not enabled'
753
763
 
754
764
  return {
@@ -759,7 +769,9 @@ export function buildDisabledSocketCommands (): SocketCommands {
759
769
  }
760
770
  }
761
771
 
762
- export function buildSocketCommands (state: SocketState): SocketCommands {
772
+ export function buildSocketCommands<T = void> (
773
+ state: SocketState<T>,
774
+ ): SocketCommands<T> {
763
775
  function sendToClient (clientId: string, event: string, body: unknown) {
764
776
  const session = state.activeSessions.get(clientId)
765
777
 
@@ -782,12 +794,12 @@ export function buildSocketCommands (state: SocketState): SocketCommands {
782
794
  sendToClient(clientId, event, body)
783
795
  }
784
796
  },
785
- send (event: string, body: unknown, fn: FilterFn) {
797
+ send (event: string, body: unknown, fn: FilterFn<T>) {
786
798
  let index = 0
787
799
 
788
800
  /* TODO: look into concurrency at some point */
789
801
  for (const [clientId, session] of state.activeSessions) {
790
- const entry: SessionEntry = {
802
+ const entry: SessionEntry<T> = {
791
803
  clientId,
792
804
  type: SessionType.Active,
793
805
  data: session.ws.data.data,
@@ -800,7 +812,7 @@ export function buildSocketCommands (state: SocketState): SocketCommands {
800
812
  index += 1
801
813
  }
802
814
  },
803
- drop (signal: CloseSignal, fn: FilterFn) {
815
+ drop (signal: CloseSignal, fn: FilterFn<T>) {
804
816
  const { code, reason } = signal
805
817
 
806
818
  let index = 0
@@ -812,7 +824,7 @@ export function buildSocketCommands (state: SocketState): SocketCommands {
812
824
  }
813
825
 
814
826
  for (const [clientId, session] of state.activeSessions) {
815
- const entry: SessionEntry = {
827
+ const entry: SessionEntry<T> = {
816
828
  clientId,
817
829
  type: SessionType.Active,
818
830
  data: session.ws.data.data,
@@ -826,10 +838,10 @@ export function buildSocketCommands (state: SocketState): SocketCommands {
826
838
  }
827
839
  },
828
840
  query (
829
- fn: FilterFn,
841
+ fn: FilterFn<T>,
830
842
  filter: SessionFilter = SessionFilter.Active,
831
843
  ) {
832
- const results: SessionEntry[] = []
844
+ const results: SessionEntry<T>[] = []
833
845
 
834
846
  function processSessions (
835
847
  type: SessionType,
@@ -849,7 +861,7 @@ export function buildSocketCommands (state: SocketState): SocketCommands {
849
861
  for (const [clientId, session] of sessions) {
850
862
  const data = 'ws' in session ? session.ws.data.data : session.data
851
863
 
852
- const entry: SessionEntry = {
864
+ const entry: SessionEntry<T> = {
853
865
  clientId,
854
866
  type,
855
867
  data,
package/src/core/utils.ts CHANGED
@@ -96,30 +96,30 @@ export type AsyncHandlerResult = Promise<Response>
96
96
  export type HandlerResult = Response | AsyncHandlerResult
97
97
  export type NextFn = (data?: unknown) => HandlerResult
98
98
 
99
- export type Middleware = (
100
- req: Request,
99
+ export type Middleware<T = void> = (
100
+ req: Request<T>,
101
101
  res: unknown,
102
102
  next: NextFn,
103
103
  ) => HandlerResult
104
104
 
105
- export type Handler = (
106
- req: Request,
105
+ export type Handler<T = void> = (
106
+ req: Request<T>,
107
107
  res: unknown,
108
108
  ) => HandlerResult
109
109
 
110
- export type MiddlewareChain = (Middleware | Handler)[]
110
+ export type MiddlewareChain<T = void> = (Middleware<T> | Handler<T>)[]
111
111
 
112
112
  export type CloseSignal = {
113
113
  code: number
114
114
  reason: string
115
115
  }
116
116
 
117
- export type SocketData = {
117
+ export type SocketData<T = void> = {
118
118
  clientId: string
119
119
  superseded: boolean
120
120
  reaped: boolean
121
121
  reaperHandle: TimeoutHandle | null
122
- data: unknown
122
+ data: T
123
123
  }
124
124
 
125
125
  export const SessionType = {
@@ -137,47 +137,47 @@ export const SessionFilter = {
137
137
 
138
138
  export type SessionFilter = typeof SessionFilter[keyof typeof SessionFilter]
139
139
 
140
- export type SessionEntry = {
140
+ export type SessionEntry<T = void> = {
141
141
  clientId: string
142
142
  type: SessionType
143
- data: unknown
143
+ data: T
144
144
  }
145
145
 
146
- export type FilterFn = (
147
- session: SessionEntry,
146
+ export type FilterFn<T = void> = (
147
+ session: SessionEntry<T>,
148
148
  index: number,
149
149
  ) => boolean
150
150
 
151
- export type SocketCommands = {
151
+ export type SocketCommands<T = void> = {
152
152
  broadcast: (event: string, body: unknown) => void
153
- send: (event: string, body: unknown, fn: FilterFn) => void
154
- drop: (signal: CloseSignal, fn: FilterFn) => void
155
- query: (fn: FilterFn, filter?: SessionFilter) => SessionEntry[]
153
+ send: (event: string, body: unknown, fn: FilterFn<T>) => void
154
+ drop: (signal: CloseSignal, fn: FilterFn<T>) => void
155
+ query: (fn: FilterFn<T>, filter?: SessionFilter) => SessionEntry<T>[]
156
156
  }
157
157
 
158
- export type BaseRequest = {
158
+ export type BaseRequest<T = void> = {
159
159
  method: HttpMethod
160
160
  route: string
161
161
  headers: Headers
162
162
  params: Record<string, string>
163
163
  query: Record<string, unknown>
164
164
  json: () => Promise<unknown>
165
- ws: SocketCommands
165
+ ws: SocketCommands<T>
166
166
  }
167
167
 
168
- export type EndpointRequest = BaseRequest & {
168
+ export type EndpointRequest<T = void> = BaseRequest<T> & {
169
169
  raw: BunRequest
170
- server: Server
170
+ server: Server<T>
171
171
  }
172
172
 
173
- export type WebSocketRequest = BaseRequest & {
173
+ export type WebSocketRequest<T = void> = BaseRequest<T> & {
174
174
  id: string
175
175
  clientId: string
176
176
  }
177
177
 
178
- export type Request = EndpointRequest | WebSocketRequest
178
+ export type Request<T = void> = EndpointRequest<T> | WebSocketRequest<T>
179
179
 
180
- export type Server = BunServer<SocketData>
180
+ export type Server<T = void> = BunServer<SocketData<T>>
181
181
 
182
182
  export function toSegments (pathString: string): string[] {
183
183
  const [pathname] = String(pathString).split('?')
@@ -207,9 +207,9 @@ export function formatError (
207
207
  }
208
208
  }
209
209
 
210
- export async function executeMiddlewareChain (
211
- req: Request,
212
- chain: MiddlewareChain,
210
+ export async function executeMiddlewareChain<T = void> (
211
+ req: Request<T>,
212
+ chain: MiddlewareChain<T>,
213
213
  ): AsyncHandlerResult {
214
214
  if (!chain.length) {
215
215
  throw new RangeError('Middleware chain is empty')
@@ -224,8 +224,8 @@ export async function executeMiddlewareChain (
224
224
  const next = (data?: unknown) => executeMiddleware(index + 1, data)
225
225
 
226
226
  const result = isLast
227
- ? await (fn as Handler)(req, res)
228
- : await (fn as Middleware)(req, res, next)
227
+ ? await (fn as Handler<T>)(req, res)
228
+ : await (fn as Middleware<T>)(req, res, next)
229
229
 
230
230
  if (result instanceof Response) {
231
231
  return result
package/src/index.ts CHANGED
@@ -2,7 +2,7 @@ export * from './core'
2
2
 
3
3
  import type { AppOptions, App } from './core'
4
4
 
5
- export declare function createApp (
5
+ export declare function createApp<T = void> (
6
6
  port: number,
7
- opts?: AppOptions,
8
- ): App
7
+ opts?: AppOptions<T>,
8
+ ): App<T>