itty-sockets 0.5.4 → 0.6.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
@@ -6,212 +6,143 @@
6
6
  </a>
7
7
  </p>
8
8
 
9
+ [![GitHub](https://img.shields.io/badge/GitHub-%23555.svg?style=flat-square&logo=github&logoColor=#fff)](https://github.com/kwhitley/itty-sockets)
9
10
  [![Version](https://img.shields.io/npm/v/itty-sockets.svg?style=flat-square)](https://npmjs.com/package/itty-sockets)
10
11
  [![Bundle Size](https://deno.bundlejs.com/?q=itty-sockets&badge&badge-style=flat-square)](https://deno.bundlejs.com/?q=itty-sockets)
12
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/kwhitley/itty-sockets/verify.yml?branch=v0.x&style=flat-square)](https://github.com/kwhitley/itty-sockets/actions/workflows/verify.yml)
11
13
  [![Coverage Status](https://img.shields.io/coveralls/github/kwhitley/itty-sockets?style=flat-square)](https://coveralls.io/github/kwhitley/itty-sockets)
12
14
  [![Issues](https://img.shields.io/github/issues/kwhitley/itty-sockets?style=flat-square)](https://github.com/kwhitley/itty-sockets/issues)
13
15
  [![Discord](https://img.shields.io/discord/832353585802903572?label=Discord&logo=Discord&style=flat-square&logoColor=fff)](https://discord.gg/53vyrZAu9u)
14
16
 
15
- ### [Documentation](https://ittysockets.io) &nbsp;| &nbsp; [Discord](https://discord.gg/53vyrZAu9u)
17
+ ### [Documentation](https://itty.dev/itty-sockets) &nbsp;| &nbsp; [Discord](https://discord.gg/53vyrZAu9u)
16
18
 
17
19
  ---
18
20
 
19
- # WebSockets : simplified and minified.
20
-
21
- Zero-config. Pick a channel and go.
21
+ ### The last WebSocket client you'll need : 512 bytes, all-in.
22
+
23
+ ## Features
24
+ 1. **DX perks** - JSON-in/out, queued messages, easy-reconnect, chainable everything.
25
+ 1. **Works with any JSON-based WebSocket server**
26
+ 1. **Powerful Routing**
27
+ - Listen for all messages
28
+ ```ts
29
+ .on('message', data => console.log(data))
30
+ ```
31
+ - Only specific types
32
+ ```ts
33
+ // matches any data with { type: 'chat' }
34
+ .on('chat', ({ text }) => console.log(text))
35
+ ```
36
+ - or fully custom filters
37
+ ```ts
38
+ // matches only messages where data.value > 20
39
+ .on(
40
+ ({ value }) => value > 20), // filter function
41
+ ({ value }) => console.log(value),
42
+ )
43
+ ```
44
+ 1. **Type-safe message handling**
45
+ 1. **Tiny footprint** - 512 bytes, all-in.
46
+ 1. **Optional usage with free/public/zero-config [itty.ws](https://itty.ws) service**
47
+
48
+ ## Basic Example
22
49
  ```ts
23
- // CLIENT 1 (listens for messages)
24
- connect('unique-channel-name')
25
- // listen for all messages
26
- .on('message', e => console.log(e.message))
27
-
28
- // or just our custom messages
29
- .on('my-chat-message', ({ user, text }) => console.log(user, 'says:', text))
30
- ```
50
+ import { connect } from 'itty-sockets'
31
51
 
32
- ```ts
33
- // CLIENT 2 (sends messages)
34
- const channel = connect('unique-channel-name')
35
- .send({ foo: 'bar' })
36
- .send({ type: 'my-chat-message', user: 'Halsey', text: 'Meow!' })
52
+ // connect to the channel
53
+ const channel = connect('wss://example.com')
37
54
 
55
+ channel
56
+ // log all messages
57
+ .on('message', e => console.log(e.message))
38
58
 
39
- channel.send('what else can this do?')
59
+ // send some messages
60
+ .send('hey!')
61
+ .send({ foo: 'bar' })
40
62
  ```
41
63
 
64
+ ## Optional use with `itty.ws` public, privacy-first server
65
+ `itty-sockets` has been designed to work with the public [itty.ws](https://itty.ws) service for even easier integrations. With this path, it's possible to add realtime features without hosting a backend server at all. We recommend using this for testing, prototyping, or simple projects. As your needs expand, you can always replace [itty.ws](https://itty.ws) with your own server(s) - nothing in the client changes.
42
66
 
43
- ## Or simply use `connect` as a tiny WebSocket client that brings the following:
67
+ Using [itty.ws](https://itty.ws) channels provides a few features to the client (fully typed by passing the `UseItty` generic to `connect`):
44
68
 
45
- - JSON parsing/stringifying
46
- - message queing - sending automatically connects and queue is flushed on open
47
- - easy reconnection (listeners keep working)
48
- - custom listeners/filters
49
- - chainable syntax (it's just handy)
69
+ 1. `connect<UseItty>('my-channel')` - connect to a channel and go
70
+ 1. adds `uid`, `alias`, and `date` to all messages
71
+ 1. adds `join` and `leave` events to announce user changes
72
+ 1. allows private messaging (by uid)
50
73
 
51
- ```ts
52
- const ws = connect('wss://somewhere.else')
53
- .on('message', console.log) // log all messages
54
- .send({ foo: 'bar' }) // send immediately, no waiting
74
+ ## Installation
55
75
 
56
- // optional - reconnect every second (no effect if open)
57
- setInterval(ws.open, 1000)
76
+ **Option 1: Import**
77
+ ```bash
78
+ npm install itty-sockets
58
79
  ```
59
80
 
60
- <br />
61
-
62
- # Getting Started
63
-
64
- ### 1. Import the [tiny client](https://npmjs.com/package/itty-sockets).
65
81
  ```ts
66
82
  import { connect } from 'itty-sockets'
67
83
  ```
68
84
 
69
- ...or simply paste this into your environment/console:
85
+ **Option 2: Just copy this snippet:**
70
86
  <!-- BEGIN SNIPPET -->
71
87
  ```ts
72
- let connect=(e,s={})=>{let t,a=0,n=[],p=[],o={},l=()=>(t||(t=new WebSocket((/^wss?:/.test(e)?e:"wss://ittysockets.io/c/"+e)+"?"+new URLSearchParams(s)),t.onmessage=(e,s=JSON.parse(e.data),t=s?.message,a={...null==t?.[0]&&t,...s,...s.date&&{date:new Date(s.date)}})=>{o[s?.type??t?.type]?.map(e=>e(a)),s?.type||o.message?.map(e=>e(a)),p.map(([e,s])=>e(a)&&s(a))},t.onopen=()=>(n.splice(0).map(e=>t?.send(e)),o.open?.map(e=>e()),a&&t?.close()),t.onclose=()=>(a=0,t=null,o.close?.map(e=>e()))),c),c=new Proxy(l,{get:(e,s)=>({open:l,close:()=>(1==t?.readyState?t.close():a=1,c),push:(e,s)=>(a=1,c.send(e,s)),send:(e,s)=>(e=JSON.stringify(e),e=s?"@@"+s+"@@"+e:e,1==t?.readyState?(t.send(e),c):(n.push(e),l())),on:(e,s)=>(s&&(e?.[0]?(o[e]??=[]).push(s):p.push([e,s])),l()),remove:(e,s,t=o[e],a=t?.indexOf(s)??-1)=>(~a&&t?.splice(a,1),l())}[s])});return c};
88
+ let connect=(e,s={})=>{let p,a=0,n=[],t=[],o={},l=()=>(p||(p=new WebSocket((/^wss?:/.test(e)?e:"wss://itty.ws/c/"+e)+"?"+new URLSearchParams(s)),p.onmessage=(e,s=JSON.parse(e.data),p=s?.message,a={...null==p?.[0]&&p,...s})=>{o[s?.type??p?.type]?.map(e=>e(a)),s?.type||o.message?.map(e=>e(a)),t.map(([e,s])=>e(a)&&s(a))},p.onopen=()=>(n.splice(0).map(e=>p?.send(e)),o.open?.map(e=>e()),a&&p?.close()),p.onclose=()=>(a=0,p=null,o.close?.map(e=>e()))),m),m=new Proxy(l,{get:(e,s)=>({open:l,close:()=>(1==p?.readyState?p.close():a=1,m),push:(e,s)=>(a=1,m.send(e,s)),send:(e,s)=>(e=JSON.stringify(e),e=s?""+s+""+e:e,1==p?.readyState?(p.send(e),m):(n.push(e),l())),on:(e,s)=>(s&&(e?.[0]?(o[e]??=[]).push(s):t.push([e,s])),l()),remove:(e,s,p=o[e],a=p?.indexOf(s)??-1)=>(~a&&p?.splice(a,1),l())}[s])});return m};
73
89
  ```
74
90
  <!-- END SNIPPET -->
91
+ *Note: This will lose TypeScript support.*
75
92
 
76
- <br />
77
-
78
- ### 2. Connect to a Channel (or external server)
79
- To start, simply connect to a channel based on a unique name (this can be anything).
80
-
81
- > **NOTE:** Pass a valid `ws://` or `wss://` URL as the channel identifier to bypass the public [ittysockets.io](https://ittysockets.io) service and use your own.
82
-
93
+ ## Example 2 - Receiving basic messages
94
+ Assume the following simple client
83
95
  ```ts
84
96
  import { connect } from 'itty-sockets'
85
97
 
86
- // basic connection
87
- const channel = connect('my-super-secret-channel')
88
-
89
- // with options
90
- const channel = connect('my-super-secret-channel', {
91
- alias: 'Kevin', // optional non-unique identifier, visible in messages
92
- announce: true, // shares your uid/alias with the channel on joining
93
- echo: true // echos your own messages back to you (for testing)
94
- })
95
-
96
- // or any external JSON WebSocket server
97
- const channel = connect('wss://somewhere.else.entirely')
98
- ```
99
-
100
- #### Connection Options
101
-
102
- | option | default value | description |
103
- | --- | --- | --- |
104
- | `{ alias: 'any-string' }` | `undefined` | An optional display name to be included in your messages. |
105
- | `{ as: 'any-string' }` | `undefined` | An optional display name to be included in your message (same as alias). |
106
- | `{ announce: true }` | `false` | Shares your uid/alias when joining/leaving. |
107
- | `{ echo: true }` | `false` | Echos messages back to original sender (good for testing). |
108
-
109
- <br />
110
-
111
- ### 3. Use the channel.
112
- With the channel connected, simply call methods on it. Every method is chainable, returning the connection again (for more chaining).
113
-
114
- | method | description | example |
115
- | --- | --- | --- |
116
- | **`.open()`** | Opens/re-opens the connection (manually, usually not needed). |
117
- | **`.close()`** | Closes the connection. | `channel.close()` |
118
- | **`.send(message: any)`** | Sends a message to the channel. This can be anything serializable with JSON.stringify. | `channel.send({ type: 'chat', text: 'hello' })` |
119
- | **`.push(message: any)`** | Sends a message and immediately closes the connection. | `channel.push('Hello World!')` |
120
- | **`.on(eventName: string, listener)`** | Add an event listener. | `channel.on('close', () => console.log('channel closed'))` |
121
- | **`.remove(eventName: string, listener)`** | Remove an event listener. The 2nd argument must be the same listener function registered in the `on` method. | `channel.remove('open', myListenerFunction)` |
98
+ connect('wss://example.com')
122
99
 
123
- #### Example
100
+ // listen for every message
101
+ .on('message', console.log)
124
102
 
125
- ```ts
126
-
127
- // connect
128
- const channel = connect('my-secret-channel')
129
-
130
- // add event listeners or send messages
131
-
132
- channel
133
- .on('message', ({ alias, uid, message, date }) =>
134
- console.log(`${alias ?? uid} says: ${message} @ ${date.toLocaleTimeString()}`)
135
- )
136
- .on('join', ({ users }) =>
137
- console.log(`A user has joined. There are now ${users} in the channel.`)
138
- )
139
- .on('leave', ({ users }) =>
140
- console.log(`A user has left. There are now ${users} in the channel.`)
103
+ // and just { type: 'chat' }
104
+ .on('chat',
105
+ ({ user, text }) => console.log(`${user} says: ${text}`)
141
106
  )
142
- .send('Hello World!') // this will queue up and send the message once connected
143
- ```
144
-
145
- <br />
146
-
147
- # Events
148
- Each event can have multiple listeners registered on it. These are stable, even if the underlying WebSocket is broken/re-established.
149
- | event name | description | payload | example |
150
- | --- | --- | --- | --- |
151
- | `message` | Triggered when receiving a message event. | [MessageEvent](#messageevent) | `channel.on<MessageType = any>('message', listener)` |
152
- | `join` | Triggered when a user (including self) joins the channel. This alerts all users that someone has joined, and informs them of the total number of users in the channel. If the joining party connected with { announce: true }, their user details will be shared with the channel. | [JoinEvent](#joineevent) | `channel.on('join', e => console.log('There are now', e.users, 'users in the channel.')` |
153
- | `leave` | Triggered when a user leaves the channel. This alerts all users that someone has left, and informs them of the total number of users in the channel. If the leaving party connected with { announce: true }, their user details will be shared with the channel. | [LeaveEvent](#leaveeevent) | `channel.on('leave', e => console.log('There are now', e.users, 'users in the channel.')` |
154
- | `error` | Triggered when the server sends an error to the user. This is rare. | [ErrorEvent](#error) | `channel.on('error', e => console.error('IttySockets Error:', e.message)` |
155
- | `open` | Triggered when the connection is established. | none | `channel.on('open', () => console.log('connected to channel.')` |
156
- | `close` | Triggered when the connection is closed. | none | `channel.on('close', () => console.log('disconnected from channel.')` |
157
-
158
-
159
- <br />
160
-
161
- ## EventTypes
162
- All event types *other* than `message` are identified with a `type` attribute. For the sake of smaller payloads, `type` is omitted on normal messages.
163
-
164
- #### MessageEvent
165
- ```ts
166
- type MessageEvent = {
167
- id: string // unique message ID
168
- uid: string // unique user ID
169
- alias: string? // optional display name
170
- date: Date // JavaScript Date object
171
- message: any // the message payload
172
- }
173
107
  ```
174
108
 
175
- #### JoinEvent <a id="joinevent" />
176
- ```ts
177
- type JoinEvent = {
178
- type: 'join' // type of event
179
- uid?: string // uid of joiner if { announce: true }
180
- alias: string? // alias of joiner if { announce: true }
181
- date: Date // date of event
182
- users: number // new number of users in the channel
109
+ Now let's assume the following 2 messages are sent:
110
+ ```json
111
+ {
112
+ "type": "chat",
113
+ "user": "Kevin",
114
+ "text": "Hey!"
183
115
  }
184
116
  ```
185
117
 
186
- #### LeaveEvent
187
- ```ts
188
- type LeaveEvent = {
189
- type: 'leave' // type of event
190
- uid?: string // uid of leaver if { announce: true }
191
- alias: string? // alias of leaver if { announce: true }
192
- date: Date // date of event
193
- users: number // new number of users in the channel
118
+ ```json
119
+ {
120
+ "date": 1754659171196,
121
+ "items": [1, 2, 3],
194
122
  }
195
123
  ```
196
124
 
197
- #### ErrorEvent
198
- ```ts
199
- type MessageEvent = {
200
- type: 'error' // error event identifier
201
- date: Date // JavaScript Date object
202
- message: any // the message payload
203
- }
125
+ This will output the following to the console:
204
126
  ```
127
+ { type: "chat", user: "Kevin", text: "Hey!" }
205
128
 
206
- <br />
129
+ { date: 1754659171196, items: [1, 2, 3] }
207
130
 
208
- # Privacy
209
- [ittysockets.io](https://ittysockets.io) is a free, public-use, but _private_ service.
131
+ "Kevin says: Hey!"
132
+ ```
210
133
 
211
- It was designed by me (a developer), to help myself and other developers achieve cool things. As such:
134
+ ## Example 3 - Reconnection
135
+ Using `itty-sockets`, you can safely fire `.open()` on the connection at any time, even if already connected. All listeners will continue to work perfectly once reconnected.
212
136
 
213
- 1. Your messages are never transmitted to anything other than the sockets on the channel you're connected to. No third-party service, no loggers, no storage (local or otherwise), not even a collection in memory. This protects your privacy/data, but keeps my costs to virtually zero, allowing me to share this service with the world... hopefully indefinitely.
137
+ ```ts
138
+ const channel = connect('wss://example.com')
139
+ .on('message', console.log)
140
+ .on('open', () => console.log('connected'))
141
+ .on('close', () => console.log('disconnected'))
214
142
 
215
- 2. I ask that you please use the channels responsibly. We're all sharing this space!
143
+ // we'll just reconnect every second - this is safe!
144
+ setInterval(channel.open, 1000)
145
+ ```
216
146
 
147
+ ## See the [full documentation](https://itty.dev/itty-sockets) to continue your journey!
217
148
 
package/connect.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type IttySocketEvent = 'open' | 'close' | 'message' | 'join' | 'leave';
1
+ type IttySocketEvent<BaseFormat> = BaseFormat extends UseItty ? 'open' | 'close' | 'message' | 'join' | 'leave' : 'open' | 'close' | 'message';
2
2
  type Date = {
3
3
  date: Date;
4
4
  };
@@ -10,9 +10,9 @@ type OptionalUserDetails = {
10
10
  uid?: string;
11
11
  alias?: string;
12
12
  };
13
- export type MessageEvent<MessageType = any> = {
13
+ export type UseItty<MessageType = any> = {
14
14
  message: MessageType;
15
- } & Date & UserDetails & MessageType;
15
+ } & UserDetails & Date;
16
16
  export type JoinEvent = {
17
17
  type: 'join';
18
18
  users: number;
@@ -25,30 +25,37 @@ export type ErrorEvent = {
25
25
  type: 'error';
26
26
  message: string;
27
27
  } & Date;
28
- export type SendMessage = <MessageFormat = any>(message: MessageFormat, recipient?: string) => IttySocket;
29
- export type IttySocket = {
30
- open: () => IttySocket;
31
- close: () => IttySocket;
32
- connected: boolean;
33
- send: SendMessage;
34
- push: SendMessage;
35
- on(type: 'join', listener: (event: JoinEvent) => any): IttySocket;
36
- on(type: 'leave', listener: (event: LeaveEvent) => any): IttySocket;
37
- on(type: 'error', listener: (event: ErrorEvent) => any): IttySocket;
38
- on<MessageFormat = any>(type: 'message', listener: (event: MessageEvent<MessageFormat>) => any): IttySocket;
39
- on<MessageFormat = any>(type: string, listener: (event: MessageEvent<MessageFormat & {
40
- type: string;
41
- }>) => any): IttySocket;
42
- on<MessageFormat = any>(type: (event?: any) => any, listener: (event: MessageEvent<MessageFormat & {
43
- type: string;
44
- }>) => any): IttySocket;
45
- remove(type: IttySocketEvent, listener: () => any): IttySocket;
46
- };
47
28
  export type IttySocketOptions = {
48
29
  as?: string;
49
30
  alias?: string;
50
31
  echo?: true;
51
32
  announce?: true;
52
33
  };
53
- export declare let connect: (channelId: string, options?: IttySocketOptions) => IttySocket;
34
+ export interface IttySocketConnect {
35
+ <BaseFormat = object>(...args: BaseFormat extends UseItty ? [channelID: string, options?: IttySocketOptions] : [url: string, queryParams?: any]): IttySocket<BaseFormat>;
36
+ }
37
+ type UseIttyEvents<BaseFormat> = {
38
+ on(type: 'join', listener: (event: JoinEvent) => any): IttySocket<BaseFormat>;
39
+ on(type: 'leave', listener: (event: LeaveEvent) => any): IttySocket<BaseFormat>;
40
+ on(type: 'error', listener: (event: ErrorEvent) => any): IttySocket<BaseFormat>;
41
+ };
42
+ type SendMessage<BaseFormat> = BaseFormat extends UseItty ? <MessageFormat = any>(message: MessageFormat, uid?: string) => IttySocket<BaseFormat> : <MessageFormat = any>(message: MessageFormat) => IttySocket<BaseFormat>;
43
+ export type IttySocket<BaseFormat = object> = {
44
+ open: () => IttySocket<BaseFormat>;
45
+ close: () => IttySocket<BaseFormat>;
46
+ send: SendMessage<BaseFormat>;
47
+ push: SendMessage<BaseFormat>;
48
+ remove(type: IttySocketEvent<BaseFormat>, listener: () => any): IttySocket<BaseFormat>;
49
+ remove(type: string, listener: () => any): IttySocket<BaseFormat>;
50
+ on(type: 'open', listener: () => any): IttySocket<BaseFormat>;
51
+ on(type: 'close', listener: () => any): IttySocket<BaseFormat>;
52
+ on<MessageFormat = BaseFormat>(type: 'message', listener: (event: BaseFormat & MessageFormat) => any): IttySocket<BaseFormat>;
53
+ on<MessageFormat = BaseFormat>(type: string, listener: (event: BaseFormat & MessageFormat & {
54
+ type: string;
55
+ }) => any): IttySocket<BaseFormat>;
56
+ on<MessageFormat = BaseFormat>(type: (event?: any) => any, listener: (event: BaseFormat & MessageFormat & {
57
+ type: string;
58
+ }) => any): IttySocket<BaseFormat>;
59
+ } & (BaseFormat extends UseItty ? UseIttyEvents<BaseFormat> : object);
60
+ export declare let connect: IttySocketConnect;
54
61
  export {};
package/connect.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";exports.connect=(e,s={})=>{let n,t=0,p=[],a=[],o={},c=()=>(n||(n=new WebSocket((/^wss?:/.test(e)?e:"wss://itty.ws/c/"+e)+"?"+new URLSearchParams(s)),n.onmessage=(e,s=JSON.parse(e.data),n=s?.message,t={...null==n?.[0]&&n,...s})=>{o[s?.type??n?.type]?.map(e=>e(t)),s?.type||o.message?.map(e=>e(t)),a.map(([e,s])=>e(t)&&s(t))},n.onopen=()=>(p.splice(0).map(e=>n?.send(e)),o.open?.map(e=>e()),t&&n?.close()),n.onclose=()=>(t=0,n=null,o.close?.map(e=>e()))),l),l=new Proxy(c,{get:(e,s)=>({open:c,close:()=>(1==n?.readyState?n.close():t=1,l),push:(e,s)=>(t=1,l.send(e,s)),send:(e,s)=>(e=JSON.stringify(e),e=s?""+s+""+e:e,1==n?.readyState?(n.send(e),l):(p.push(e),c())),on:(e,s)=>(s&&(e?.[0]?(o[e]??=[]).push(s):a.push([e,s])),c()),remove:(e,s,n=o[e],t=n?.indexOf(s)??-1)=>(~t&&n?.splice(t,1),c())}[s])});return l};
package/connect.mjs CHANGED
@@ -1 +1 @@
1
- let e=(e,s={})=>{let t,a=0,n=[],p=[],o={},l=()=>(t||(t=new WebSocket((/^wss?:/.test(e)?e:"wss://ittysockets.io/c/"+e)+"?"+new URLSearchParams(s)),t.onmessage=(e,s=JSON.parse(e.data),t=s?.message,a={...null==t?.[0]&&t,...s,...s.date&&{date:new Date(s.date)}})=>{o[s?.type??t?.type]?.map(e=>e(a)),s?.type||o.message?.map(e=>e(a)),p.map(([e,s])=>e(a)&&s(a))},t.onopen=()=>(n.splice(0).map(e=>t?.send(e)),o.open?.map(e=>e()),a&&t?.close()),t.onclose=()=>(a=0,t=null,o.close?.map(e=>e()))),c),c=new Proxy(l,{get:(e,s)=>({open:l,close:()=>(1==t?.readyState?t.close():a=1,c),push:(e,s)=>(a=1,c.send(e,s)),send:(e,s)=>(e=JSON.stringify(e),e=s?"@@"+s+"@@"+e:e,1==t?.readyState?(t.send(e),c):(n.push(e),l())),on:(e,s)=>(s&&(e?.[0]?(o[e]??=[]).push(s):p.push([e,s])),l()),remove:(e,s,t=o[e],a=t?.indexOf(s)??-1)=>(~a&&t?.splice(a,1),l())}[s])});return c};export{e as connect};
1
+ let e=(e,s={})=>{let p,a=0,n=[],t=[],o={},l=()=>(p||(p=new WebSocket((/^wss?:/.test(e)?e:"wss://itty.ws/c/"+e)+"?"+new URLSearchParams(s)),p.onmessage=(e,s=JSON.parse(e.data),p=s?.message,a={...null==p?.[0]&&p,...s})=>{o[s?.type??p?.type]?.map(e=>e(a)),s?.type||o.message?.map(e=>e(a)),t.map(([e,s])=>e(a)&&s(a))},p.onopen=()=>(n.splice(0).map(e=>p?.send(e)),o.open?.map(e=>e()),a&&p?.close()),p.onclose=()=>(a=0,p=null,o.close?.map(e=>e()))),m),m=new Proxy(l,{get:(e,s)=>({open:l,close:()=>(1==p?.readyState?p.close():a=1,m),push:(e,s)=>(a=1,m.send(e,s)),send:(e,s)=>(e=JSON.stringify(e),e=s?""+s+""+e:e,1==p?.readyState?(p.send(e),m):(n.push(e),l())),on:(e,s)=>(s&&(e?.[0]?(o[e]??=[]).push(s):t.push([e,s])),l()),remove:(e,s,p=o[e],a=p?.indexOf(s)??-1)=>(~a&&p?.splice(a,1),l())}[s])});return m};export{e as connect};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itty-sockets",
3
- "version": "0.5.4",
3
+ "version": "0.6.0",
4
4
  "description": "WebSockets : simplified and minified.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -34,6 +34,6 @@
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/bun": "^1.2.3",
37
- "itty-packager": "^1.6.7"
37
+ "itty-packager": "^1.6.10"
38
38
  }
39
39
  }
package/connect.cjs DELETED
@@ -1 +0,0 @@
1
- "use strict";exports.connect=(e,s={})=>{let t,a=0,n=[],p=[],o={},c=()=>(t||(t=new WebSocket((/^wss?:/.test(e)?e:"wss://ittysockets.io/c/"+e)+"?"+new URLSearchParams(s)),t.onmessage=(e,s=JSON.parse(e.data),t=s?.message,a={...null==t?.[0]&&t,...s,...s.date&&{date:new Date(s.date)}})=>{o[s?.type??t?.type]?.map(e=>e(a)),s?.type||o.message?.map(e=>e(a)),p.map(([e,s])=>e(a)&&s(a))},t.onopen=()=>(n.splice(0).map(e=>t?.send(e)),o.open?.map(e=>e()),a&&t?.close()),t.onclose=()=>(a=0,t=null,o.close?.map(e=>e()))),l),l=new Proxy(c,{get:(e,s)=>({open:c,close:()=>(1==t?.readyState?t.close():a=1,l),push:(e,s)=>(a=1,l.send(e,s)),send:(e,s)=>(e=JSON.stringify(e),e=s?"@@"+s+"@@"+e:e,1==t?.readyState?(t.send(e),l):(n.push(e),c())),on:(e,s)=>(s&&(e?.[0]?(o[e]??=[]).push(s):p.push([e,s])),c()),remove:(e,s,t=o[e],a=t?.indexOf(s)??-1)=>(~a&&t?.splice(a,1),c())}[s])});return l};