itty-sockets 0.5.4-next.0 → 0.5.4-next.1

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.
Files changed (2) hide show
  1. package/README.md +33 -185
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -18,204 +18,52 @@
18
18
 
19
19
  ---
20
20
 
21
- # WebSockets : simplified and minified.
22
-
23
- Zero-config. Pick a [public channel](https://ittysockets.io) and go.
21
+ ## Type-safe WebSocket routing in 540 bytes
22
+
23
+ ## Features
24
+ 1. **Quality of Life Improvements (over native WebSocket)**
25
+ - auto JSON handling
26
+ - top-level payload access (`text` instead of `e.data.text`)
27
+ - easy reconnections
28
+ - message queuing eliminates race conditions
29
+ - chainable API
30
+ 1. **Powerful Routing**
31
+ - all messages - `.on('message', data => console.log(data))`
32
+ - custom types - `.on('chat', ({ text }) => console.log(text))`
33
+ - custom filters - `.on(isOver20, ({ value }) => console.log(value))`
34
+ 1. **Type-safety**
35
+ - `.on<Chat>('chat', ({ text }) => console.log(text))`
36
+ - `.send<Chat>({ type: 'chat', text: 'hello' })`
37
+ 1. **Works with any JSON-based WebSocket server**
38
+ 1. **Tiny footprint** - 540 bytes is smaller than most WebSocket boilerplate
39
+
40
+ ## Basic Example
24
41
  ```ts
25
- // CLIENT 1 (listens for messages)
26
- connect('unique-channel-name')
27
- // listen for all messages
28
- .on('message', e => console.log(e.message))
42
+ import { connect } from 'itty-sockets'
29
43
 
30
- // or just our custom messages
31
- .on('greeting',
32
- ({ user, text }) => console.log(user, 'says:', text)
33
- )
34
- ```
44
+ const ws = connect('wss://example.com')
35
45
 
36
- ```ts
37
- // CLIENT 2 (sends messages)
38
- const channel = connect('unique-channel-name')
46
+ ws
47
+ .on('message', e => console.log(e.message))
48
+ .send('hey!')
39
49
  .send({ foo: 'bar' })
40
- .send({ type: 'greeting', user: 'Halsey', text: 'Meow!' })
41
-
42
-
43
- channel.send('what else can this do?')
44
50
  ```
45
51
 
52
+ ## Installation
46
53
 
47
- ## Or simply use `connect` as a tiny WebSocket client that brings the following:
48
-
49
- - JSON parsing/stringifying
50
- - message queing - sending automatically connects and queue is flushed on open
51
- - easy reconnection (listeners keep working)
52
- - custom listeners/filters
53
- - chainable syntax (it's just handy)
54
-
55
- ```ts
56
- const ws = connect('wss://somewhere.else')
57
- .on('message', console.log) // log all messages
58
- .send({ foo: 'bar' }) // send immediately, no waiting
59
-
60
- // optional - reconnect every second (no effect if open)
61
- setInterval(ws.open, 1000)
62
- ```
63
-
64
- <br />
65
-
66
- # Getting Started
67
-
68
- ### 1. Import the [tiny client](https://npmjs.com/package/itty-sockets).
54
+ **Option 1: Import**
69
55
  ```ts
70
56
  import { connect } from 'itty-sockets'
71
57
  ```
72
58
 
73
- ...or simply paste this into your environment/console:
74
- <!-- BEGIN SNIPPET -->
75
- ```ts
76
- let connect=(e,s={})=>{let p,a=0,n=[],t=[],o={},l=()=>(p||(p=new WebSocket((/^wss?:/.test(e)?e:"wss://c.itty.ws/"+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};
77
- ```
78
- <!-- END SNIPPET -->
79
-
80
- <br />
81
-
82
- ### 2. Connect to a Channel (or external server)
83
- To start, simply connect to a channel based on a unique name (this can be anything).
84
-
85
- > **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.
86
-
87
- ```ts
88
- import { connect } from 'itty-sockets'
89
-
90
- // basic connection
91
- const channel = connect('my-super-secret-channel')
92
-
93
- // with options
94
- const channel = connect('my-super-secret-channel', {
95
- alias: 'Kevin', // optional non-unique identifier, visible in messages
96
- announce: true, // shares your uid/alias with the channel on joining
97
- echo: true // echos your own messages back to you (for testing)
98
- })
99
-
100
- // or any external JSON WebSocket server
101
- const channel = connect('wss://somewhere.else.entirely')
59
+ **Option 2: Just copy this snippet:**
60
+ ```js
61
+ let connect=(e,s={})=>{let p,t=0,a=[],n=[],o={},l=()=>(p||(p=new WebSocket((/^wss?:/.test(e)?e:"wss://ittysockets.io/c/"+e)+"?"+new URLSearchParams(s)),p.onmessage=(e,s=JSON.parse(e.data),p=s?.message,t={...null==p?.[0]&&p,...s})=>{o[s?.type??p?.type]?.map((e=>e(t))),s?.type||o.message?.map((e=>e(t))),n.map((([e,s])=>e(t)&&s(t)))},p.onopen=()=>(a.splice(0).map((e=>p?.send(e))),o.open?.map((e=>e())),t&&p?.close()),p.onclose=()=>(t=0,p=null,o.close?.map((e=>e())))),c),c=new Proxy(l,{get:(e,s)=>({open:l,close:()=>(1==p?.readyState?p.close():t=1,c),push:(e,s)=>(t=1,c.send(e,s)),send:(e,s)=>(e=JSON.stringify(e),e=s?""+s+""+e:e,1==p?.readyState?(p.send(e),c):(a.push(e),l())),on:(e,s)=>(s&&(e?.[0]?(o[e]??=[]).push(s):n.push([e,s])),l()),remove:(e,s,p=o[e],t=p?.indexOf(s)??-1)=>(~t&&p?.splice(t,1),l())}[s])});return c};
102
62
  ```
63
+ Note: This will lose TypeScript support, but is great for adding to your browser console (via script extensions, etc).
103
64
 
104
- #### Connection Options
105
-
106
- | option | default value | description |
107
- | --- | --- | --- |
108
- | `{ alias: 'any-string' }` | `undefined` | An optional display name to be included in your messages. |
109
- | `{ as: 'any-string' }` | `undefined` | An optional display name to be included in your message (same as alias). |
110
- | `{ announce: true }` | `false` | Shares your uid/alias when joining/leaving. |
111
- | `{ echo: true }` | `false` | Echos messages back to original sender (good for testing). |
112
-
113
- <br />
114
-
115
- ### 3. Use the channel.
116
- With the channel connected, simply call methods on it. Every method is chainable, returning the connection again (for more chaining).
117
-
118
- | method | description | example |
119
- | --- | --- | --- |
120
- | **`.open()`** | Opens/re-opens the connection (manually, usually not needed). |
121
- | **`.close()`** | Closes the connection. | `channel.close()` |
122
- | **`.send(message: any)`** | Sends a message to the channel. This can be anything serializable with JSON.stringify. | `channel.send({ type: 'chat', text: 'hello' })` |
123
- | **`.push(message: any)`** | Sends a message and immediately closes the connection. | `channel.push('Hello World!')` |
124
- | **`.on(eventName: string, listener)`** | Add an event listener. | `channel.on('close', () => console.log('channel closed'))` |
125
- | **`.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)` |
126
-
127
- #### Example
128
-
129
- ```ts
130
-
131
- // connect
132
- const channel = connect('my-secret-channel')
133
-
134
- // add event listeners or send messages
135
-
136
- channel
137
- .on('message', ({ alias, uid, message, date }) =>
138
- console.log(`${alias ?? uid} says: ${message} @ ${date.toLocaleTimeString()}`)
139
- )
140
- .on('join', ({ users }) =>
141
- console.log(`A user has joined. There are now ${users} in the channel.`)
142
- )
143
- .on('leave', ({ users }) =>
144
- console.log(`A user has left. There are now ${users} in the channel.`)
145
- )
146
- .send('Hello World!') // this will queue up and send the message once connected
147
- ```
148
-
149
- <br />
150
-
151
- # Events
152
- Each event can have multiple listeners registered on it. These are stable, even if the underlying WebSocket is broken/re-established.
153
- | event name | description | payload | example |
154
- | --- | --- | --- | --- |
155
- | `message` | Triggered when receiving a message event. | [MessageEvent](#messageevent) | `channel.on<MessageType = any>('message', listener)` |
156
- | `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.')` |
157
- | `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.')` |
158
- | `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)` |
159
- | `open` | Triggered when the connection is established. | none | `channel.on('open', () => console.log('connected to channel.')` |
160
- | `close` | Triggered when the connection is closed. | none | `channel.on('close', () => console.log('disconnected from channel.')` |
161
-
162
-
163
- <br />
164
-
165
- ## EventTypes
166
- All event types *other* than `message` are identified with a `type` attribute. For the sake of smaller payloads, `type` is omitted on normal messages.
167
-
168
- #### MessageEvent
169
- ```ts
170
- type MessageEvent = {
171
- id: string // unique message ID
172
- uid: string // unique user ID
173
- alias: string? // optional display name
174
- date: Date // JavaScript Date object
175
- message: any // the message payload
176
- }
177
- ```
178
-
179
- #### JoinEvent <a id="joinevent" />
180
- ```ts
181
- type JoinEvent = {
182
- type: 'join' // type of event
183
- uid?: string // uid of joiner if { announce: true }
184
- alias: string? // alias of joiner if { announce: true }
185
- date: Date // date of event
186
- users: number // new number of users in the channel
187
- }
188
- ```
189
-
190
- #### LeaveEvent
191
- ```ts
192
- type LeaveEvent = {
193
- type: 'leave' // type of event
194
- uid?: string // uid of leaver if { announce: true }
195
- alias: string? // alias of leaver if { announce: true }
196
- date: Date // date of event
197
- users: number // new number of users in the channel
198
- }
199
- ```
200
-
201
- #### ErrorEvent
202
- ```ts
203
- type MessageEvent = {
204
- type: 'error' // error event identifier
205
- date: Date // JavaScript Date object
206
- message: any // the message payload
207
- }
208
- ```
209
-
210
- <br />
211
-
212
- # Privacy
213
- [ittysockets.io](https://ittysockets.io) is a free, public-use, but _private_ service.
214
-
215
- It was designed by me (a developer), to help myself and other developers achieve cool things. As such:
216
-
217
- 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.
218
65
 
219
- 2. I ask that you please use the channels responsibly. We're all sharing this space!
66
+ ## Next Steps
220
67
 
68
+ - [Getting Started](https://itty.dev/itty-sockets/getting-started) - Basic setup and first connections
221
69
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itty-sockets",
3
- "version": "0.5.4-next.0",
3
+ "version": "0.5.4-next.1",
4
4
  "description": "WebSockets : simplified and minified.",
5
5
  "type": "module",
6
6
  "exports": {