1+ import { events , NetSocketClientOptions , callback , HostOptions } from './types.ts'
2+ import { getUUIDfromUrl , parseEvent , parseMessage } from './methods.ts'
3+
4+ export class NetSocket {
5+ private socket ! : WebSocket
6+ get _socket ( ) : WebSocket {
7+ return this . _socket
8+ }
9+ private events : events
10+ get _events ( ) : events {
11+ return this . events
12+ }
13+ private _uuid ! : string
14+ get uuid ( ) {
15+ return this . _uuid
16+ }
17+ #FirstConnected: boolean
18+ private _status : 'connecting' | 'connected' | 'disconnected'
19+ get status ( ) : 'connecting' | 'connected' | 'disconnected' {
20+ return this . _status
21+ }
22+ public readonly _listeners : Map < string , Set < callback > >
23+ public readonly Timeout : number
24+ #options: NetSocketClientOptions
25+ constructor ( options ?: NetSocketClientOptions ) {
26+ this . #FirstConnected = false
27+ this . _listeners = new Map ( )
28+ this . _status = 'connecting'
29+ this . events = {
30+ open : ( ) => {
31+ this . _status = 'connected'
32+ if ( this . #FirstConnected) {
33+ this . #emit( 'reconnect' )
34+ this . #emit( 'connect' )
35+ } else {
36+ const pong = ( { uuid } : { uuid : string } ) => {
37+ this . #emit( 'firstconnect' , this )
38+ this . #emit( 'connect' )
39+ this . _uuid = uuid
40+ this . #FirstConnected = true
41+ this . off ( 'pong' , pong )
42+ }
43+ this . on ( 'pong' , pong )
44+ this . emit ( 'ping' )
45+ }
46+ } ,
47+ close : ( ) => {
48+ this . _status = 'connecting'
49+ const Interval = setInterval ( ( ) => {
50+ this . bindSocket ( this . generateSocket ( this . #options, this . uuid ) )
51+ } , 2000 )
52+ const Timeout = setTimeout ( ( ) => {
53+ clearInterval ( Interval )
54+ this . #emit( 'disconnect' , this )
55+ } , this . Timeout )
56+ const connect = ( ) => {
57+ clearInterval ( Interval )
58+ clearTimeout ( Timeout )
59+ this . off ( 'connect' , connect )
60+ }
61+ this . on ( 'connect' , connect )
62+ } ,
63+ message : ( ev ) => {
64+ const event = parseEvent ( ev . data )
65+ this . #emit( event . event , ...event . data )
66+ } ,
67+ error : ( ) => {
68+ this . #emit( 'error' , this )
69+ }
70+ }
71+ const _options : NetSocketClientOptions = {
72+ Timeout : 10000 ,
73+ connection : {
74+ hostname : 'localhost' ,
75+ tls : false ,
76+ path : '/NetSocket' ,
77+ port : false
78+ } ,
79+ ...options
80+ }
81+ this . on ( 'disconnect' , ( ) => {
82+ this . _status = 'disconnected'
83+ } )
84+ this . #options = _options
85+ this . Timeout = _options . Timeout !
86+ this . bindSocket ( this . generateSocket ( _options ) )
87+ }
88+ private generateSocket ( options : NetSocketClientOptions , uuid ?: string ) : WebSocket {
89+ if ( typeof options . connection === 'string' ) {
90+ const url = new URL ( options . connection )
91+ return new WebSocket ( `${ url . origin } ${ url . pathname } ` , options . protocols )
92+ } else {
93+ const host : HostOptions = options . connection !
94+ const connection = `${ host . tls ? 'wss' : 'ws' } ://${ host . hostname } :${ host . port ? host . port : host . port === false ? '' : host . tls ? 443 : 80 } ${ host . path ? host . path : '' } /${ uuid ? `?_id=${ uuid } ` : '' } `
95+ return new WebSocket ( connection , options . protocols )
96+ }
97+ }
98+ bindSocket ( socket : WebSocket ) {
99+ if ( this . socket ) {
100+ this . socket . removeEventListener ( 'open' , this . events . open )
101+ this . socket . removeEventListener ( 'close' , this . events . close )
102+ this . socket . removeEventListener ( 'message' , this . events . message )
103+ this . socket . removeEventListener ( 'error' , this . events . error )
104+ this . socket . close ( )
105+ }
106+ this . socket = socket
107+ this . socket . addEventListener ( 'open' , this . events . open )
108+ this . socket . addEventListener ( 'close' , this . events . close )
109+ this . socket . addEventListener ( 'message' , this . events . message )
110+ this . socket . addEventListener ( 'error' , this . events . error )
111+ }
112+ emit ( event : string , ...data : unknown [ ] ) {
113+ let Interval : number
114+ new Promise < void > ( ( res , rej ) => {
115+ if ( this . _status === 'connected' && this . socket . readyState === WebSocket . OPEN ) {
116+ res ( )
117+ } else if ( this . _status === 'disconnected' ) {
118+ rej ( )
119+ } else {
120+ Interval = setInterval ( ( ) => {
121+ if ( this . _status === 'connected' && this . socket . readyState === WebSocket . OPEN ) {
122+ res ( )
123+ } else if ( this . _status === 'disconnected' ) {
124+ rej ( )
125+ }
126+ } , 500 )
127+ }
128+ } )
129+ . then ( ( ) => this . socket . send ( parseMessage ( event , data ) ) )
130+ . catch ( ( ) => console . error ( 'cannot use emit while disconnected.' , { event, data } ) )
131+ . finally ( ( ) => Interval && clearInterval ( Interval ) )
132+ }
133+ #emit( event : string , ...data : unknown [ ] ) {
134+ const listeners = this . _listeners . get ( event )
135+ listeners ?. forEach ( ( callback ) => callback ( ...data ) )
136+
137+ const anyListeners = this . _listeners . get ( 'any' )
138+ if ( anyListeners ) {
139+ anyListeners . forEach ( ( callback ) => callback ( event , ...data ) )
140+ }
141+ }
142+ on ( event : string | 'any' , callback : callback ) {
143+ let Events : Set < callback > = this . _listeners . get ( event ) !
144+ if ( ! Events ) { Events = new Set ( ) ; this . _listeners . set ( event , Events ) }
145+ Events . add ( callback )
146+ }
147+ off ( event : string , callback : callback ) {
148+ const Events : Set < callback > = this . _listeners . get ( event ) !
149+ Events ?. delete ( callback )
150+ if ( Events . size === 0 ) {
151+ this . _listeners . delete ( event )
152+ }
153+ }
154+ }
0 commit comments