@@ -7,34 +7,22 @@ import type { Server as HttpsServer, ServerOptions as HttpsServerOptions } from
77import type { AddressInfo } from 'node:net'
88import type { Duplex } from 'node:stream'
99import type { RpcFunctionDefinitionAny } from '../types'
10+ import type { DevframeNodeRpcSessionMeta , DevframeRpcConnection } from './session'
1011import { createServer as createHttpServer } from 'node:http'
1112import { createServer as createHttpsServer } from 'node:https'
1213import crossws from 'crossws/adapters/node'
1314import { DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM , DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM } from 'devframe/constants'
1415import { randomToken , timingSafeEqual } from 'devframe/utils/crypto-token'
1516import { structuredCloneParse , structuredCloneStringify } from 'devframe/utils/structured-clone'
1617import { strictJsonStringify , STRUCTURED_CLONE_PREFIX } from '../serialization'
18+ import { createRpcSessionMeta } from './session'
1719
18- export interface DevframeNodeRpcSessionMeta {
19- id : number
20- /** The crossws peer backing this session's socket. */
21- peer ?: Peer
22- clientAuthToken ?: string
23- isTrusted ?: boolean
24- subscribedStates : Set < string >
25- /**
26- * Streams this session has subscribed to via
27- * `rpc.streaming.subscribe(channel, id)`. Tracked here for O(1) cleanup
28- * on disconnect; the wire format is `${channel}\x1F${id}`.
29- */
30- subscribedStreams ?: Set < string >
31- /**
32- * Inbound streams this session is currently uploading to (via
33- * `rpc.streaming.upload(channel, id)`). Tracked for cleanup on
34- * disconnect; same wire format as `subscribedStreams`.
35- */
36- uploadingStreams ?: Set < string >
37- }
20+ export type {
21+ DevframeNodeRpcSessionMeta ,
22+ DevframeRpcConnection ,
23+ DevframeRpcConnectionRequest ,
24+ DevframeRpcTransportKind ,
25+ } from './session'
3826
3927export interface WsRpcTransportOptions {
4028 /**
@@ -94,8 +82,8 @@ export interface WsRpcTransportOptions {
9482 * loses dev-time validation for `jsonSerializable: true` declarations.
9583 */
9684 definitions ?: ReadonlyMap < string , Pick < RpcFunctionDefinitionAny , 'jsonSerializable' > >
97- onConnected ?: ( peer : Peer , meta : DevframeNodeRpcSessionMeta ) => void
98- onDisconnected ?: ( peer : Peer , meta : DevframeNodeRpcSessionMeta ) => void
85+ onConnected ?: ( connection : DevframeRpcConnection , meta : DevframeNodeRpcSessionMeta ) => void
86+ onDisconnected ?: ( connection : DevframeRpcConnection , meta : DevframeNodeRpcSessionMeta ) => void
9987 /** Override the default per-call serializer. Most callers should leave this unset. */
10088 serialize ?: ChannelOptions [ 'serialize' ]
10189 /** Override the default per-call deserializer. Most callers should leave this unset. */
@@ -208,8 +196,6 @@ export interface WsRpcTransport {
208196 close : ( ) => Promise < void >
209197}
210198
211- let sessionId = 0
212-
213199const EMPTY_DEFS : ReadonlyMap < string , Pick < RpcFunctionDefinitionAny , 'jsonSerializable' > > = new Map ( )
214200
215201function NOOP ( ) { }
@@ -342,6 +328,7 @@ export function createWsRpcPeerHooks<
342328
343329 interface PeerState {
344330 meta : DevframeNodeRpcSessionMeta
331+ connection : DevframeRpcConnection
345332 channel : ChannelOptions
346333 /** birpc's inbound-message handler, registered via the channel's `on`. */
347334 onMessage ?: ( data : string ) => void
@@ -350,18 +337,23 @@ export function createWsRpcPeerHooks<
350337
351338 return {
352339 open : ( peer ) => {
353- const meta : DevframeNodeRpcSessionMeta = {
354- id : sessionId ++ ,
340+ const meta = createRpcSessionMeta ( )
341+ meta . peer = peer
342+ const connection : DevframeRpcConnection = {
343+ id : meta . id ,
344+ transport : 'websocket' ,
345+ request : peer . request ,
346+ send : data => peer . send ( data ) ,
347+ close : ( code , reason ) => peer . close ( code , reason ) ,
355348 peer,
356- subscribedStates : new Set ( ) ,
357349 }
358350
359351 // Per-connection state: maps an incoming request id to its method
360352 // name so the matching outgoing response can look the method back
361353 // up in `definitions` and pick the right encoder. One map per
362354 // session — request-id spaces don't collide across sessions.
363355 const pendingRequestMethods = new Map < string , string > ( )
364- const state : PeerState = { meta, channel : undefined as unknown as ChannelOptions }
356+ const state : PeerState = { meta, connection , channel : undefined as unknown as ChannelOptions }
365357 const channel : ChannelOptions = {
366358 post : ( data ) => {
367359 peer . send ( data )
@@ -404,7 +396,7 @@ export function createWsRpcPeerHooks<
404396 rpcGroup . updateChannels ( ( channels ) => {
405397 channels . push ( channel )
406398 } )
407- onConnected ( peer , meta )
399+ onConnected ( connection , meta )
408400 } ,
409401 message : ( peer , message ) => {
410402 states . get ( peer ) ?. onMessage ?.( message . text ( ) )
@@ -419,7 +411,7 @@ export function createWsRpcPeerHooks<
419411 if ( index >= 0 )
420412 channels . splice ( index , 1 )
421413 } )
422- onDisconnected ( peer , state . meta )
414+ onDisconnected ( state . connection , state . meta )
423415 } ,
424416 }
425417}
0 commit comments