angelia.io 2.3.68 → 2.4.71

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "angelia.io",
3
- "version": "2.3.68",
3
+ "version": "2.4.71",
4
4
  "description": "WebSockets Server and Client API for node.js and the browser, with rooms support.",
5
5
  "homepage": "https://github.com/titoBouzout/angelia.io",
6
6
  "repository": {
package/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # angelia.io
2
2
 
3
- WebSockets Server and Client API for node.js and the browser, with rooms support.
3
+ WebSockets Server and Client API for node.js and the browser, (with rooms support in development).
4
4
 
5
5
  The goal of this project is to provide a developer friendly API that just works™.
6
6
 
@@ -12,18 +12,24 @@ If you fancy for Client side a regular JavaScript file, then use https://github.
12
12
 
13
13
  ## Simple Example
14
14
 
15
- ### Server (Node.js)
16
-
17
15
  ```JavaScript
18
16
  // server.js (node.js)
19
17
  import Server from 'angelia.io/server';
20
18
 
21
- class Connection {
22
- async listen() {
23
- console.log('-'.repeat(60));
24
- console.log('Server started listening on port ' + this.server.port);
25
- console.log(this.server);
19
+ class FancyChat {
20
+ async typing(socket, data, callback) {
21
+ console.log('Im', data ? ' typing' : ' not typing')
26
22
  }
23
+ async theMessage(socket, data, callback) {
24
+ console.log('the message is', data, socket)
25
+ socket.emit('gotIt', 'thanks')
26
+ callback('yes Im sure')
27
+ }
28
+ }
29
+
30
+ Server.on(FancyChat);
31
+
32
+ class Connection {
27
33
  async connect(socket, request) {
28
34
  console.log('socket connected', socket)
29
35
  }
@@ -33,42 +39,30 @@ class Connection {
33
39
  }
34
40
  Server.on(Connection);
35
41
 
36
- class FancyChat {
37
- async chatMessage(socket, message, callback) {
38
- console.log('socket sent', message)
39
- socket.emit('chatMessage', 'Hi client nice to meet you')
40
- callback('yes, got it')
41
- }
42
- }
43
- Server.on(FancyChat);
44
-
45
- const server = new Server.listen({
42
+ Server.listen({
46
43
  port: 3001,
47
44
  });
48
- ```
49
-
50
- ### Client (Browser)
51
45
 
52
- ```JavaScript
53
46
  // index.js (browser)
54
47
  import Client from 'angelia.io/client';
55
48
 
56
- const socket = new Client({
57
- url: 'ws://localhost:3001',
58
- });
49
+ const socket = new Client('ws://localhost:3001');
59
50
 
60
- socket.on('chatMessage', (message) => {
61
- console.log('Server sent', message)
62
- })
51
+ socket.emit('typing', true)
63
52
 
64
- socket.emit('chatMessage', 'Hi there server, Im client', (data) =>{
65
- console.log('you got it?', data)
53
+ setTimeout(() => {
54
+ socket.emit('typing', false)
55
+ socket.emit('theMessage', 'hi there!', (data) =>{
56
+ console.log('you sure?', data)
57
+ })
58
+ }, 10000)
59
+
60
+ socket.on('gotIt', (message) => {
61
+ console.log('Server got it yey', message)
66
62
  })
67
63
  ```
68
64
 
69
- ## Server (Node.js)
70
-
71
- ### Options
65
+ ## Server Documentation (Node.js)
72
66
 
73
67
  A call to `Server.listen` starts the server. `Server` is a singleton and can only have running 1 server.
74
68
 
@@ -76,7 +70,7 @@ A call to `Server.listen` starts the server. `Server` is a singleton and can onl
76
70
  // server.js (node.js)
77
71
  import Server from 'angelia.io/server'
78
72
 
79
- const server = new Server.listen({
73
+ Server.listen({
80
74
  hostname: 'localhost',
81
75
  port: 3001,
82
76
  maxMessageSize: 5,
@@ -85,13 +79,14 @@ const server = new Server.listen({
85
79
  })
86
80
  ```
87
81
 
82
+ ### `Server` Options
83
+
88
84
  | name | kind | default | description |
89
85
  | -------------------- | ------- | ------- | --------------------------------------------------- |
90
86
  | `hostname` | String | '' | the hostname if any |
91
87
  | `port` | Number | 3001 | the port to use for this server |
92
88
  | `maxMessageSize` | Number | 5 | max size in mb of a message received |
93
89
  | `skipUTF8Validation` | Boolean | false | allows to skip utf8 validation |
94
- | `dontConnect` | Boolean | false | allows to instance the socket without connecting |
95
90
  | `cert` | String | '' | path to the cert file for using https fullchain.pem |
96
91
  | `key` | String | '' | path to the key file for using https privkey.pem |
97
92
 
@@ -110,12 +105,15 @@ class _ {
110
105
  }
111
106
  Server.on(_)
112
107
 
113
- const server = new Server.listen({
108
+ Server.listen({
114
109
  port: 3001,
115
110
  })
116
111
  ```
117
112
 
118
- #### Server Properties
113
+ #### List of `Server` Object Properties
114
+
115
+ <details>
116
+ <summary><b>Expand</b></summary>
119
117
 
120
118
  | signature | kind | description |
121
119
  | ------------------------------------- | -------- | ---------------------------------------------------------------------------------------------- |
@@ -141,7 +139,9 @@ const server = new Server.listen({
141
139
  | `broadcastOnce(sender, key, [value])` | Function | emits to the sockets except sender and replace if exists a pending message with the same `key` |
142
140
  | `sockets` | Set | a Set() with all the current connected sockets |
143
141
 
144
- ### Socket Object
142
+ </details>
143
+
144
+ ### `Socket` Object
145
145
 
146
146
  The `socket` object is given to you by a listener
147
147
 
@@ -156,12 +156,15 @@ class _ {
156
156
  }
157
157
  Server.on(_)
158
158
 
159
- new Server.listen({
159
+ Server.listen({
160
160
  port: 3001,
161
161
  })
162
162
  ```
163
163
 
164
- #### Socket Properties
164
+ #### List of `Socket` Object Properties
165
+
166
+ <details>
167
+ <summary><b>Expand</b></summary>
165
168
 
166
169
  | signature | kind | description |
167
170
  | --------------------------- | -------- | ----------------------------------------------------------------------------- |
@@ -182,72 +185,23 @@ new Server.listen({
182
185
  | `once(key, [value])` | Function | replace if exists a pending message with the same `key` from emit queue |
183
186
  | `disconnect([noReconnect])` | Function | disconnects the socket from the server, pass `true` to prevent re-connections |
184
187
 
188
+ </details>
189
+
185
190
  ### Listeners
186
191
 
187
192
  To listen for a client message/event you may do the familiar way `Server.on('connect', (socket) => {console.log('socket connected!', socket)})`
188
193
 
189
194
  However, to ease organization and development you may listen to an event by creating a class with any name, and give to methods the name of the things you want to listen to. You then add your class to the listeners as `Server.on(MyClass);` and you are done.
190
195
 
191
- On user defined listeners, the listener receives three things as sent by the client: `socket`, `data` and a `callback`; Example `class FancyChat { async typing(socket, data, callback) {console.log(socket, data);callback('got it')}}`.
192
-
193
- If you are building a chat you may write something like this
194
-
195
- ```JavaScript
196
- // server.js (node.js)
197
- import Server from 'angelia.io/server';
198
-
199
- class FancyChat {
200
- async typing(socket, data, callback) {
201
- console.log('Im', data ? ' typing' : ' not typing')
202
- }
203
- async theMessage(socket, data, callback) {
204
- console.log('the message is', data, socket)
205
- socket.emit('gotIt', 'thanks')
206
- callback('yes Im sure')
207
- }
208
- }
209
-
210
- Server.on(FancyChat);
211
-
212
- class Connection {
213
- async connect(socket, request) {
214
- console.log('socket connected', socket)
215
- }
216
- async disconnect(socket, code, message) {
217
- console.log('socket disconnected', code, message, socket);
218
- }
219
- }
220
- Server.on(Connection);
221
-
222
- const server = new Server.listen({
223
- port: 3001,
224
- });
225
-
226
- // index.js (browser)
227
- import Client from 'angelia.io/client';
228
-
229
- const socket = new Client({
230
- url: 'ws://localhost:3001',
231
- });
232
-
233
- socket.emit('typing', true)
234
-
235
- setTimeout(() => {
236
- socket.emit('typing', false)
237
- socket.emit('theMessage', 'hi there!', (data) =>{
238
- console.log('you sure?', data)
239
- })
240
- }, 10000)
241
-
242
- socket.on('gotIt', (message) => {
243
- console.log('Server got it yey', message)
244
- })
245
- ```
196
+ On user defined listeners, the listener receives three things as sent by the client: `socket`, `data` and a `callback`; Example `class FancyChat { async typing(socket, data, callback) {console.log(socket, data);}}`.
246
197
 
247
198
  #### Syntax For Listeners
248
199
 
249
200
  Listeners have the following alternative syntax if you feel like
250
201
 
202
+ <details>
203
+ <summary><b>Expand</b></summary>
204
+
251
205
  ```javascript
252
206
  // server.js (node.js)
253
207
  import Server from 'angelia.io/server'
@@ -290,12 +244,14 @@ Server.on('connect', function fancyConnect(socket, request) {
290
244
  onsole.log('connect in named function')
291
245
  })
292
246
 
293
- const server = new Server.listen({
247
+ Server.listen({
294
248
  port: 3001,
295
249
  })
296
250
  ```
297
251
 
298
- ### Predefined Events
252
+ </details>
253
+
254
+ ### Predefined `Server` Events
299
255
 
300
256
  There's a bunch of handy predefined events dispatched whenever you add listeners for them.
301
257
 
@@ -315,12 +271,15 @@ class _ {
315
271
 
316
272
  Server.on(_);
317
273
 
318
- const server = new Server.listen({
274
+ Server.listen({
319
275
  port: 3001,
320
276
  });
321
277
  ```
322
278
 
323
- #### List of Predefined Events
279
+ #### List of Predefined `Server` Events
280
+
281
+ <details>
282
+ <summary><b>Expand</b></summary>
324
283
 
325
284
  | signature | description |
326
285
  | ----------------------------------- | ----------------------------------------------------------------------------------------- |
@@ -341,16 +300,20 @@ const server = new Server.listen({
341
300
  | `events` | reference to event dispatcher, ex: `this.events.typing()` will dispatch the `typing` event to anyone listening to it |
342
301
  | `classes` | reference to all functions that have been attached as listeners , ex: `this.classes.MyFancyChat.typing` |
343
302
 
303
+ </details>
304
+
344
305
  ## Client API (Browser)
345
306
 
346
- ### Options
307
+ ### `Client` Options
347
308
 
348
309
  Configurable options used by the constructor
349
310
 
350
311
  ```javascript
351
312
  const socket = new Client({
352
313
  url: 'ws://localhost:3001',
353
- params: function (){ return { fast: 'data', test: 'a space' })
314
+ params: function () {
315
+ return { fast: 'data', test: 'a space' }
316
+ },
354
317
  })
355
318
  ```
356
319
 
@@ -359,6 +322,7 @@ const socket = new Client({
359
322
  | `url` | string | 'ws(s)://\${window.location.hostname}:3001' | url of the socket server, example 'ws://localhost:3001' |
360
323
  | `params` | Function | {} | to send data while connecting, accesible via `socket.params` server side |
361
324
  | `longLiveFlash` | boolean | false | browsers throw when calling swf functions via ExternalInterface after events like WebSocket.onmesssage; setting this to `true` fix it by dispatching them in a setTimeout |
325
+ | `dontConnect` | Boolean | false | allows to instance the socket without connecting |
362
326
 
363
327
  You may also do like this if you don't need any option
364
328
 
@@ -366,10 +330,13 @@ You may also do like this if you don't need any option
366
330
  const socket = new Client('ws://localhost:3001')
367
331
  ```
368
332
 
369
- ### API
333
+ ### `Client` API
370
334
 
371
335
  The client API is similar to regular event handling
372
336
 
337
+ <details>
338
+ <summary><b>Expand</b></summary>
339
+
373
340
  | signature | kind | description |
374
341
  | ------------------------------ | -------- | ------------------------------------------------------------------ |
375
342
  | `connected` | Boolean | `true` when the socket is connected else `false` |
@@ -380,15 +347,23 @@ The client API is similar to regular event handling
380
347
  | `emit(key, [value, callback])` | Function | emits data to the server |
381
348
  | `decode(data)` | Function | for decoding binary data, returns a promise |
382
349
 
383
- #### List of Predefined Events
350
+ </details>
351
+
352
+ #### List of Predefined `Client` Events
384
353
 
385
354
  As in `socket.on('connect', () => console.log('connect happened!'))`
386
355
 
356
+ <details>
357
+ <summary><b>Expand</b></summary>
358
+
387
359
  | signature | description |
388
360
  | ------------ | ------------------------------------------------------------------------------------------------------- |
389
361
  | `connect` | **this happens only once** when we connect to the server, any future connection is a `reconnect` |
390
362
  | `reconnect` | if we were connected at least once, then any reconnection will dispatch this event instead of `connect` |
391
363
  | `disconnect` | when we disconnect from the server |
364
+ | |
365
+
366
+ </details>
392
367
 
393
368
  ## Authors
394
369
 
package/server/Server.js CHANGED
@@ -141,7 +141,11 @@ class ServerSingleton {
141
141
  process.on(m, () => {
142
142
  if (!io.closing) {
143
143
  io.closing = true
144
- console.log('Server Shutting Down\n', this)
144
+ if (options.debug) {
145
+ console.log('Server Shutting Down\n', this)
146
+ } else {
147
+ console.log('Server Shutting Down\n')
148
+ }
145
149
  io.close()
146
150
  if (options.debug) {
147
151
  process.exit()
@@ -150,7 +154,7 @@ class ServerSingleton {
150
154
  })
151
155
  }
152
156
 
153
- console.log('Server Started Listening On Port ' + this.port)
157
+ console.log('Socket Server Started Listening On Port ', this.port)
154
158
  this.events.listen && this.events.listen()
155
159
 
156
160
  return this
@@ -103,7 +103,7 @@ class ManagerSingleton {
103
103
  }
104
104
 
105
105
  [Symbol.iterator]() {
106
- return this.rooms
106
+ return this.rooms[Symbol.iterator]()
107
107
  }
108
108
  }
109
109
 
@@ -1,90 +1,100 @@
1
1
  'use strict'
2
2
 
3
- const { join, leave, parent } = require('./constants.js')
3
+ const { join, leave, parent, add, remove } = require('./constants.js')
4
4
 
5
5
  class Room {
6
6
  constructor() {
7
- this.users = []
7
+ this.sockets = new Set()
8
8
  }
9
9
  has(socket) {
10
- return this.users.indexOf(socket) !== -1
10
+ return this.sockets.has(socket)
11
11
  }
12
+ get size() {
13
+ return this.sockets.size
14
+ }
15
+ // private
12
16
  [join](roomList, socket) {
13
17
  // add to list of room list
14
18
  if (!this[parent]) {
15
19
  this[parent] = roomList
16
- this[parent].add(this)
20
+ this[parent][add](this)
17
21
  }
18
22
 
19
23
  // add user
20
- this.users.push(socket)
24
+ this.sockets.add(socket)
21
25
 
22
- // to be able to list rooms for socket
26
+ // to be able to list rooms for a socket
23
27
  socket.rooms.add(this)
24
28
 
25
- if (this.users.length === 1) {
29
+ // if the room has the property "persistent"
30
+ // then maybe the room is old and someone just joined
31
+ // for this reason we dont dispatch onCreate for persistent rooms
32
+ // as that would be misleading
33
+ if (!this.persistent && this.sockets.size === 1) {
26
34
  // dispatch create
27
- this.create && this.create(socket)
35
+ this.onCreate && this.onCreate(socket)
28
36
  }
29
37
 
30
38
  // dispatch join
31
- this.join && this.join(socket)
39
+ this.onJoin && this.onJoin(socket)
32
40
  }
33
41
  [leave](socket) {
34
42
  // remove user
35
- let index = this.users.indexOf(socket)
36
- if (index !== -1) this.users.splice(index, 1)
43
+ this.sockets.delete(socket)
37
44
 
38
45
  // to be able to list rooms for socket
39
46
  socket.rooms.delete(this)
40
47
 
41
- // check removal
42
- if (this.users.length === 0 && !this.persistent) {
48
+ // check room deletion
49
+ if (!this.persistent && this.sockets.size === 0) {
43
50
  // remove room from list
44
- this[parent].delete(this)
51
+ this[parent][remove](this)
45
52
 
46
53
  // dispatch leave
47
- this.leave && this.leave(socket)
54
+ this.onLeave && this.onLeave(socket)
48
55
 
49
56
  // dispatch that the room has been deleted
50
- this.delete && this.delete(socket)
57
+ this.onDelete && this.onDelete(socket)
51
58
  } else {
52
59
  // dispatch leave
53
- this.leave && this.leave(socket)
60
+ this.onLeave && this.onLeave(socket)
54
61
  }
55
62
  }
56
63
 
57
64
  emit(k, v) {
58
65
  let d = [k, v]
59
66
 
60
- for (let socket of this.users) {
67
+ for (let socket of this.sockets) {
61
68
  socket.emit(d)
62
69
  }
63
70
  }
64
71
  once(k, v) {
65
72
  let d = [k, v]
66
73
 
67
- for (let socket of this.users) {
74
+ for (let socket of this.sockets) {
68
75
  socket.once(d)
69
76
  }
70
77
  }
71
78
  broadcast(me, k, v) {
72
79
  let d = [k, v]
73
80
 
74
- for (let socket of this.users) {
81
+ for (let socket of this.sockets) {
75
82
  if (me != socket) socket.emit(d)
76
83
  }
77
84
  }
78
85
  broadcastOnce(me, k, v) {
79
86
  let d = [k, v]
80
87
 
81
- for (let socket of this.users) {
88
+ for (let socket of this.sockets) {
82
89
  if (me != socket) socket.once(d)
83
90
  }
84
91
  }
85
92
 
93
+ toJSON() {
94
+ return this.sockets
95
+ }
86
96
  [Symbol.iterator]() {
87
- return this.users
97
+ return this.sockets[Symbol.iterator]()
88
98
  }
89
99
  }
90
100
 
@@ -1,85 +1,39 @@
1
1
  'use strict'
2
2
 
3
- const { parent } = require('./constants.js')
3
+ const { add, remove } = require('./constants.js')
4
4
 
5
5
  class Rooms {
6
6
  constructor(path) {
7
7
  Object.assign(this, {
8
8
  path: path,
9
- rooms: [],
9
+ rooms: new Set(),
10
10
  roomsById: new Map(),
11
11
  })
12
12
  }
13
13
 
14
- has(room) {
15
- return this.rooms.indexOf(room) !== -1
16
- }
17
-
18
14
  get(id) {
19
15
  return this.roomsById.get(id)
20
16
  }
21
-
22
- add(room) {
23
- if (!this.has(room)) {
24
- this.rooms.push(room)
25
- this.roomsById.set(room.id, room)
26
- }
27
- }
28
- delete(room) {
29
- if (!room.persistent) {
30
- let index = this.rooms.indexOf(room)
31
- if (index !== -1) this.rooms.splice(index, 1)
32
- this.roomsById.delete(room.id)
33
- }
34
- }
35
-
36
- emit(k, v) {
37
- let d = [k, v]
38
-
39
- for (let room of this.rooms) {
40
- for (let socket of room.users) {
41
- socket.emit(d)
42
- }
43
- }
44
- }
45
- once(k, v) {
46
- let d = [k, v]
47
-
48
- for (let room of this.rooms) {
49
- for (let socket of room.users) {
50
- socket.once(d)
51
- }
52
- }
17
+ get size() {
18
+ return this.rooms.size
53
19
  }
54
- broadcast(me, k, v) {
55
- let d = [k, v]
56
-
57
- for (let room of this.rooms) {
58
- for (let socket of room.users) {
59
- if (me != socket) {
60
- socket.emit(d)
61
- }
62
- }
20
+ // private
21
+ [add](room) {
22
+ if (!this.rooms.has(room)) {
23
+ this.rooms.add(room)
24
+ this.roomsById.set(room.id, room)
63
25
  }
64
26
  }
65
- broadcastOnce(me, k, v) {
66
- let d = [k, v]
67
-
68
- for (let room of this.rooms) {
69
- for (let socket of room.users) {
70
- if (me != socket) {
71
- socket.once(d)
72
- }
73
- }
74
- }
27
+ [remove](room) {
28
+ this.rooms.delete(room)
29
+ this.roomsById.delete(room.id)
75
30
  }
76
31
 
77
32
  toJSON() {
78
33
  return this.rooms
79
34
  }
80
-
81
35
  [Symbol.iterator]() {
82
- return this.rooms
36
+ return this.rooms[Symbol.iterator]()
83
37
  }
84
38
  }
85
39
 
@@ -2,8 +2,16 @@ const join = Symbol.for('Room.join')
2
2
  const leave = Symbol.for('Room.leave')
3
3
  const parent = Symbol.for('Room.parent')
4
4
 
5
+ const add = Symbol.for('Rooms.add')
6
+ const remove = Symbol.for('Rooms.remove')
7
+
5
8
  module.exports = {
9
+ // Room
6
10
  join,
7
11
  leave,
8
12
  parent,
13
+
14
+ // Rooms
15
+ add,
16
+ remove,
9
17
  }