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 +46 -3
- package/dist/core/index.d.ts +13 -13
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/middleware.d.ts +2 -2
- package/dist/core/middleware.d.ts.map +1 -1
- package/dist/core/socket.d.ts +24 -24
- package/dist/core/socket.d.ts.map +1 -1
- package/dist/core/utils.d.ts +20 -20
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/index.ts +72 -68
- package/src/core/middleware.ts +9 -7
- package/src/core/socket.ts +70 -58
- package/src/core/utils.ts +27 -27
- package/src/index.ts +3 -3
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
|
|
604
|
-
- `FilterFn
|
|
605
|
-
- `SocketCommands
|
|
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
|
|
package/dist/core/index.d.ts
CHANGED
|
@@ -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
|
|
39
|
+
export declare function createApp<T = void>(port: number, config: RouteConfig<T>, opts?: AppOptions<T>): App<T>;
|
|
40
40
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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,
|
|
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"}
|
package/dist/core/socket.d.ts
CHANGED
|
@@ -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
|
|
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:
|
|
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:
|
|
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
|
|
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":"AA8BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAA;AAE3C,OAAO,KAAK,EACV,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,OAAO,EAEP,eAAe,EACf,cAAc,EACd,UAAU,EAGX,MAAM,SAAS,CAAA;AAShB,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../src/core/socket.ts"],"names":[],"mappings":"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"}
|
package/dist/core/utils.d.ts
CHANGED
|
@@ -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
|
|
87
|
-
export type Handler = (req: Request
|
|
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:
|
|
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:
|
|
114
|
+
data: T;
|
|
115
115
|
};
|
|
116
|
-
export type FilterFn = (session: SessionEntry
|
|
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
|
|
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
|
|
144
|
+
export declare function executeMiddlewareChain<T = void>(req: Request<T>, chain: MiddlewareChain<T>): AsyncHandlerResult;
|
|
145
145
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/core/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/core/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAA;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,KAAK,CAAA;AAE1D,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;AAEzD,eAAO,MAAM,UAAU;;;;;;;CAOb,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,MAAM,OAAO,UAAU,CAAC,CAAA;AAEnE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmEb,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,MAAM,OAAO,UAAU,CAAC,CAAA;AAEnE,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;AAElD,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;AAClD,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,kBAAkB,CAAA;AACzD,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,aAAa,CAAA;AAEtD,MAAM,MAAM,UAAU,GAAG,
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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
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
|
|
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 (
|
|
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 (
|
|
298
|
-
|
|
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
|
|
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)
|
package/src/core/middleware.ts
CHANGED
|
@@ -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
|
|
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 => {
|
package/src/core/socket.ts
CHANGED
|
@@ -50,7 +50,10 @@ import type {
|
|
|
50
50
|
ResponseMessage,
|
|
51
51
|
} from './messages'
|
|
52
52
|
|
|
53
|
-
type SocketHandler =
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
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