@cocreate/socket-server 1.18.1 → 1.19.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ ## [1.19.1](https://github.com/CoCreate-app/CoCreate-socket-server/compare/v1.19.0...v1.19.1) (2023-10-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * authentication ([ccc5e1d](https://github.com/CoCreate-app/CoCreate-socket-server/commit/ccc5e1d4aa50e3dc2ea627200c634a0ca7c83721))
7
+ * bump cocreate dependency versions ([6c74306](https://github.com/CoCreate-app/CoCreate-socket-server/commit/6c7430664987fdfe955fe705c413a7313e5dca51))
8
+ * this to self ([24119fb](https://github.com/CoCreate-app/CoCreate-socket-server/commit/24119fb5583ad34fd2210befad92fba1743ce804))
9
+
10
+ # [1.19.0](https://github.com/CoCreate-app/CoCreate-socket-server/compare/v1.18.1...v1.19.0) (2023-10-09)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * added '@cocreate/utlis' ([cc8267a](https://github.com/CoCreate-app/CoCreate-socket-server/commit/cc8267abf7ded45033929bd4c4997eb9adc89d42))
16
+ * handling of socket.id and clientId ([9e66f16](https://github.com/CoCreate-app/CoCreate-socket-server/commit/9e66f16f4e869e7ec29a261068fb61c46569f408))
17
+ * Improved handling of data.sync ([190ebd6](https://github.com/CoCreate-app/CoCreate-socket-server/commit/190ebd6c10f337fbd4e8be81caba865cfffb5c0a))
18
+ * send _id with syncMessage ([e37e2de](https://github.com/CoCreate-app/CoCreate-socket-server/commit/e37e2de8aff8945a3884c416514adc1e89fc54e2))
19
+ * update to use data.socketId and data.clientId ([125f2be](https://github.com/CoCreate-app/CoCreate-socket-server/commit/125f2bedd6090488ae26dc2228b53bb4aa63d4ff))
20
+ * use message_log ([d4b4c4a](https://github.com/CoCreate-app/CoCreate-socket-server/commit/d4b4c4ad2708cd61567d7172ac7bcb0635349a6a))
21
+
22
+
23
+ ### Features
24
+
25
+ * Authentication happens during upgrade ([c01cb0e](https://github.com/CoCreate-app/CoCreate-socket-server/commit/c01cb0eeb5fc4e135a8d9855fbab7e8b9535423d))
26
+ * get, set, delete socket functions ([9066911](https://github.com/CoCreate-app/CoCreate-socket-server/commit/9066911016072841cd08463c8354eeef892b41e3))
27
+ * method sync sent to server with sync details ([3c914b7](https://github.com/CoCreate-app/CoCreate-socket-server/commit/3c914b74d720949c8ae56f3f9159041ef1d5f24f))
28
+ * on socket connection the data is parsed from ([0b69b35](https://github.com/CoCreate-app/CoCreate-socket-server/commit/0b69b357c891da63c3e94aaca8361866f252de98))
29
+
1
30
  ## [1.18.1](https://github.com/CoCreate-app/CoCreate-socket-server/compare/v1.18.0...v1.18.1) (2023-09-18)
2
31
 
3
32
 
package/docs/index.html CHANGED
@@ -218,7 +218,6 @@
218
218
  </div>
219
219
  </div>
220
220
  </div>
221
- <script src="/apikey.js"></script>
222
221
  <script src="https://CoCreate.app/dist/CoCreate.js"></script>
223
222
  </body>
224
223
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/socket-server",
3
- "version": "1.18.1",
3
+ "version": "1.19.1",
4
4
  "description": "CoCreate-socket-server",
5
5
  "keywords": [
6
6
  "cocreate-socket",
@@ -40,8 +40,9 @@
40
40
  },
41
41
  "homepage": "https://cocreate.app/docs/CoCreate-socket-server",
42
42
  "dependencies": {
43
- "@cocreate/config": "^1.5.1",
44
- "@cocreate/uuid": "^1.7.1",
43
+ "@cocreate/config": "^1.6.0",
44
+ "@cocreate/uuid": "^1.7.2",
45
+ "@cocreate/utils": "^1.25.0",
45
46
  "ws": "7.5.9"
46
47
  }
47
48
  }
package/src/index.js CHANGED
@@ -2,105 +2,268 @@ const WebSocket = require('ws');
2
2
  const { URL } = require("url");
3
3
  const EventEmitter = require("events").EventEmitter;
4
4
  const uid = require('@cocreate/uuid')
5
+ const { ObjectId } = require('@cocreate/utils')
5
6
  const config = require('@cocreate/config')
6
7
 
7
8
  class SocketServer extends EventEmitter {
8
- constructor(server, prefix) {
9
+ constructor(server) {
9
10
  super();
11
+ this.serverId = uid.generate(12)
10
12
  this.organizations = new Map();
11
13
  this.clients = new Map();
12
- this.prefix = prefix || "ws";
14
+ this.sockets = new Map();
15
+ this.users = new Map();
16
+
13
17
  config({ organization_id: { prompt: 'Enter your organization_id: ' } })
14
18
 
15
19
  this.wss = new WebSocket.Server({ noServer: true });
20
+
16
21
  this.wss.on('headers', (headers, request) => {
17
22
  headers.push('Access-Control-Allow-Origin: *');
18
23
  });
19
24
 
25
+ this.wss.on('error', (error) => {
26
+ socket.destroy();
27
+ });
28
+
20
29
  server.on('upgrade', (request, socket, head) => {
21
- if (!this.handleUpgrade(request, socket, head)) {
22
- socket.destroy();
30
+ const self = this;
31
+ let organization_id = request.url.split('/')
32
+ organization_id = organization_id[organization_id.length - 1]
33
+
34
+ if (organization_id) {
35
+ this.wss.handleUpgrade(request, socket, head, function (socket) {
36
+ let options = decodeURIComponent(request.headers['sec-websocket-protocol'])
37
+ options = JSON.parse(options)
38
+
39
+ socket.organization_id = organization_id
40
+ socket.id = options.socketId;
41
+ socket.clientId = options.clientId;
42
+ socket.pathname = request.url
43
+ socket.origin = request.headers.origin || request.headers.host
44
+
45
+ if (socket.origin.startsWith('http'))
46
+ socket.origin = socket.origin.replace('http', 'ws')
47
+
48
+ socket.socketUrl = socket.origin + socket.pathname
49
+
50
+ if (socket.origin && socket.origin !== 'null') {
51
+ const url = new URL(socket.origin);
52
+ socket.host = url.host || socket.origin;
53
+ }
54
+
55
+ let data = {
56
+ socket,
57
+ method: 'read.object',
58
+ array: 'message_log',
59
+ $filter: {
60
+ sort: [
61
+ { key: '_id', direction: 'desc' }
62
+ ]
63
+ },
64
+ sync: true,
65
+ organization_id
66
+ }
67
+
68
+ if (options.lastSynced)
69
+ data.$filter.query = [
70
+ { key: '_id', value: options.lastSynced, operator: '$gt' }
71
+ ]
72
+ else
73
+ data.$filter.limit = 1
74
+
75
+ self.emit('read.object', data);
76
+
77
+ if (self.authenticate && options.token) {
78
+ let { user_id, expires } = self.authenticate.decodeToken(options.token)
79
+ // self.authenticate.decodeToken(options.token).then(({ user_id, expires }) => {
80
+ if (user_id) {
81
+ socket.user_id = user_id;
82
+ socket.expires = expires;
83
+ self.emit('userStatus', { socket, method: 'userStatus', user_id, userStatus: 'on', organization_id });
84
+ } else
85
+ self.emit('userStatus', { socket, user_id, status: 'off', organization_id });
86
+
87
+ self.onWebSocket(socket);
88
+ // })
89
+ }
90
+ else
91
+ self.onWebSocket(socket);
92
+ })
23
93
  }
24
94
  });
25
95
  }
26
96
 
27
- handleUpgrade(req, socket, head) {
97
+ onWebSocket(socket) {
28
98
  const self = this;
29
- // const url = new URL(req.url);
30
- // const pathname = req.url;
31
- const config = this.getKeyFromUrl(req.url)
32
- if (config.type == this.prefix) {
33
- this.wss.handleUpgrade(req, socket, head, function (socket) {
34
- socket.config = config
35
- self.onWebSocket(req, socket);
36
- })
37
- return true;
38
- }
39
- return false;
40
- }
41
-
42
- onWebSocket(req, socket) {
43
- const self = this;
44
-
45
- this.addClient(socket);
99
+ this.add(socket);
46
100
 
47
101
  socket.on('message', async (message) => {
48
- self.onMessage(req, socket, message);
102
+ self.onMessage(socket, message);
49
103
  })
50
104
 
51
- socket.on('close', function () {
52
- self.removeClient(socket)
105
+ socket.on('close', () => {
106
+ self.delete(socket)
53
107
  })
54
108
 
55
109
  socket.on("error", () => {
56
- self.removeClient(socket)
110
+ self.delete(socket)
57
111
  });
58
112
 
59
- this.send(socket, { socket, method: 'connect', connectedKey: socket.config.key });
113
+ socket.send(JSON.stringify({ method: 'connect', connectedKey: socket.pathname }))
60
114
 
61
115
  }
62
116
 
63
- addClient(socket) {
64
- let organization_id = socket.config.organization_id
65
- if (!this.organizations.has(organization_id))
66
- this.organizations.set(organization_id, true)
67
-
68
- let user_id = socket.config.user_id
69
- let key = socket.config.key
70
- let clients = this.clients.get(key);
71
- if (!clients) {
72
- clients = new Map();
73
- this.clients.set(key, clients);
117
+ add(socket) {
118
+ let organization_id = socket.organization_id
119
+
120
+ let organization = this.organizations.get(organization_id)
121
+ if (!organization) {
122
+ organization = {
123
+ status: true,
124
+ clients: {}
125
+ }
126
+
127
+ this.organizations.set(organization_id, organization)
128
+
129
+ this.emit('update.object', {
130
+ method: 'update.object',
131
+ array: 'organizations',
132
+ object: {
133
+ _id: organization_id, ['$push.activeHost']: socket.socketUrl // needs socketId
134
+ },
135
+ organization_id
136
+ });
137
+
138
+ this.emit('mesh.create', {
139
+ url: socket.socketUrl,
140
+ organization_id
141
+ });
142
+
143
+ }
144
+
145
+ if (!this.clients.has(socket.clientId)) {
146
+ this.clients.set(socket.clientId, []);
147
+ organization.clients[socket.clientId] = []
148
+ }
149
+
150
+ if (!this.sockets.has(socket.id)) {
151
+ this.sockets.set(socket.id, socket);
152
+ this.clients.get(socket.clientId).push(socket);
153
+ organization.clients[socket.clientId].push(socket)
154
+ }
155
+
156
+ if (socket.user_id) {
157
+ this.emit('userStatus', { socket, user_id: socket.user_id, userStatus: 'on', organization_id });
158
+
159
+ if (!this.users.has(socket.user_id)) {
160
+ this.users.set(socket.user_id, [socket])
161
+ } else {
162
+ this.users.get(socket.user_id).push(socket)
163
+ }
164
+ }
165
+
166
+ }
167
+
168
+ get(data) {
169
+ let sockets = []
170
+ if (data.broadcast !== false) {
171
+ let organization = this.organizations.get(data.organization_id)
172
+ if (organization) {
173
+ const clients = organization.clients
174
+ for (let client of Object.keys(clients)) {
175
+ if (data.broadcastSender === false && client === data.clientId) continue
176
+
177
+ if (data.broadcastClient)
178
+ sockets.push(clients[client][0])
179
+ else
180
+ sockets.push(...clients[client])
181
+ }
182
+ } else {
183
+ // TODO: requires a messageQueue that expires
184
+ console.log('organization could not be found', data)
185
+ }
186
+ } else if (data.broadcastSender !== false) {
187
+ sockets.push(data.socket)
74
188
  }
75
- if (!clients.has(socket))
76
- clients.set(socket, true);
77
- else
78
- console.log('has client')
79
- if (user_id)
80
- this.emit('userStatus', socket, { socket, user_id, userStatus: 'on', organization_id });
189
+ return sockets
81
190
  }
82
191
 
83
- removeClient(socket) {
84
- let organization_id = socket.config.organization_id
85
- let user_id = socket.config.user_id
86
- let key = socket.config.key
87
- let clients = this.clients.get(key);
88
- clients.delete(socket);
192
+ delete(socket) {
193
+ let organization_id = socket.organization_id
194
+ if (this.organizations.has(organization_id)) {
195
+ const clients = this.organizations.get(organization_id).clients;
89
196
 
90
- if (user_id)
91
- this.emit('userStatus', socket, { socket, user_id, status: 'off', organization_id });
197
+ // Check if the client exists
198
+ if (clients && clients[socket.clientId]) {
199
+ const client = clients[socket.clientId]
92
200
 
93
- if (clients.size == 0) {
94
- this.organizations.delete(organization_id)
95
- // this.clients.delete(key);
96
- this.emit('disconnect', organization_id)
201
+ // Check if the socket exists in the client's sockets
202
+ const index = client.findIndex(item => item.id === socket.id);
203
+ if (index !== -1) {
204
+ client.splice(index, 1);
205
+ }
206
+
207
+ if (!client.length) {
208
+ delete clients[socket.clientId];
209
+ }
210
+
211
+ if (!Object.keys(clients).length) {
212
+ this.organizations.delete(socket.organization_id);
213
+ this.emit('update.object', {
214
+ method: 'update.object',
215
+ array: 'organizations',
216
+ object: {
217
+ _id: organization_id, ['$pull.activeHost']: socket.socketUrl
218
+ },
219
+ organization_id
220
+ });
221
+
222
+ this.emit('mesh.update', {
223
+ url: socket.socketUrl,
224
+ organization_id
225
+ });
226
+ }
227
+
228
+ }
97
229
  }
98
230
 
231
+ if (this.clients.has(socket.clientId)) {
232
+ const client = this.clients.get(socket.clientId)
233
+ const index = client.findIndex(item => item.id === socket.id);
234
+ if (index !== -1) {
235
+ client.splice(index, 1);
236
+ }
237
+
238
+ if (!client.length) {
239
+ this.clients.delete(socket.clientId);
240
+ }
241
+ }
242
+
243
+ if (this.clients.size === 0) {
244
+ this.organizations.delete(socket.organization_id);
245
+ }
246
+
247
+ this.sockets.delete(socket.id);
248
+
249
+ if (socket.user_id) {
250
+ let sockets = this.users.get(socket.user_id)
251
+ if (sockets) {
252
+ const index = sockets.findIndex(item => item.id === socket.id);
253
+ if (index !== -1) {
254
+ sockets.splice(index, 1);
255
+ }
256
+ if (!sockets.length) {
257
+ this.users.delete(socket.user_id);
258
+ this.emit('userStatus', { socket, user_id, status: 'off', organization_id });
259
+ }
260
+ }
261
+ }
99
262
  }
100
263
 
101
- async onMessage(req, socket, message) {
264
+ async onMessage(socket, message) {
102
265
  try {
103
- const organization_id = socket.config.organization_id
266
+ const organization_id = socket.organization_id
104
267
 
105
268
  this.emit("setBandwidth", {
106
269
  type: 'in',
@@ -108,34 +271,37 @@ class SocketServer extends EventEmitter {
108
271
  organization_id
109
272
  });
110
273
 
111
- let active = this.organizations.get(organization_id)
112
- if (active === false)
274
+ if (this.organizations.has(organization_id) && !this.organizations.get(organization_id).status)
113
275
  return this.send({ socket, method: 'Access Denied', balance: 'Your balance has fallen bellow 0' })
114
276
 
115
277
  let data = JSON.parse(message)
116
-
117
278
  if (data.method) {
118
- let user_id = null;
119
- if (this.authenticate)
120
- user_id = await this.authenticate.decodeToken(req);
279
+ if (data.method === 'region.added' || data.method === 'region.removed')
280
+ console.log('data.method: ', data.method)
281
+
282
+ if (socket.user_id && socket.expires && new Date().getTime() >= socket.expires) {
283
+ socket.user_id = socket.expires = null
284
+ this.send({ socket, method: 'updateUserStatus', userStatus: 'off', socketId: data.socketId, organization_id })
285
+ }
121
286
 
122
287
  if (this.authorize) {
288
+ if (!this.sockets.has(socket.id)) {
289
+ if (!this.organizations.get(organization_id).status)
290
+ return this.send({ socket, method: 'Access Denied', balance: 'Your balance has fallen bellow 0' })
291
+ }
292
+
123
293
  data.socket = socket
124
294
 
125
- data.host = this.getHost(req)
126
- const authorized = await this.authorize.check(data, user_id)
295
+ const authorized = await this.authorize.check(data, socket.user_id)
127
296
  if (authorized.storage === false) {
128
297
  data.database = process.env.organization_id
129
298
  data.organization_id = process.env.organization_id
130
299
 
131
- const authorized2 = await this.authorize.check(data, req, user_id)
300
+ const authorized2 = await this.authorize.check(data, req, socket.user_id)
132
301
  if (!authorized2 || authorized2.error) {
133
302
  return this.send({ socket, method: 'Access Denied', authorized2, ...data })
134
303
  }
135
304
  } else if (!authorized || authorized.error) {
136
- if (!user_id)
137
- this.send({ socket, method: 'updateUserStatus', userStatus: 'off', clientId: data.clientId, organization_id })
138
-
139
305
  return this.send({ socket, method: 'Access Denied', authorized, ...data })
140
306
  }
141
307
  // dburl is true and db does not have 'keys' array
@@ -148,15 +314,6 @@ class SocketServer extends EventEmitter {
148
314
  if (authorized.authorized)
149
315
  data = authorized.authorized
150
316
 
151
- if (user_id) {
152
- if (!socket.config.user_id) {
153
- socket.config.user_id = user_id
154
- this.emit('userStatus', { socket, method: 'userStatus', user_id, userStatus: 'on', organization_id });
155
- }
156
- } else {
157
- this.send({ socket, method: 'updateUserStatus', userStatus: 'off', clientId: data.clientId, organization_id })
158
- }
159
-
160
317
  this.emit(data.method, data);
161
318
 
162
319
  }
@@ -166,85 +323,77 @@ class SocketServer extends EventEmitter {
166
323
  }
167
324
  }
168
325
 
169
- broadcast(data) {
170
- if (!data.uid)
171
- data.uid = uid.generate()
172
-
173
- let organization_id = data.socket.config.organization_id;
174
- let url = `/${this.prefix}/${organization_id}`;
175
-
176
- let namespace = data.namespace;
177
- if (namespace) {
178
- url += `/${namespace}`
179
- }
326
+ async send(data) {
327
+ // const socket = this.sockets.get(data.socketId)
328
+ const socket = data.socket
180
329
 
330
+ if (data.sync) {
331
+ if (!data.object || !data.object.length)
332
+ return
181
333
 
182
- let rooms = data.room;
183
- if (rooms) {
184
- if (!rooms.isArray())
185
- rooms = [rooms]
186
- for (let room of rooms) {
187
- let url = url;
188
- url += `/${room}`;
334
+ for (let i = 0; i < data.object.length; i++) {
335
+ data.object[i].data._id = data.object[i]._id
336
+ data.object[i].data.sync = true
189
337
 
190
- this.send(data, url)
338
+ const authorized = await this.authorize.check(data.object[i].data, socket.user_id)
339
+ if (authorized && authorized.authorized)
340
+ socket.send(JSON.stringify(authorized.authorized));
341
+ else
342
+ socket.send(JSON.stringify(data.object[i].data));
191
343
  }
192
344
  } else {
193
- this.send(data, url)
194
- }
195
- }
345
+ const sent = []
346
+
347
+ const authorized = await this.authorize.check(data, socket.user_id)
348
+ if (authorized && authorized.authorized)
349
+ data = authorized.authorized
350
+
351
+ if (!data.method.startsWith('read.') || data.log) {
352
+ let object = { url: socket.socketUrl, data }
353
+ delete object.socket
354
+ this.emit('create.object', {
355
+ method: 'create.object',
356
+ array: 'message_log',
357
+ object,
358
+ organization_id: data.organization_id
359
+ });
360
+ }
196
361
 
197
- async send(data, url) {
198
- const socket = data.socket
199
- delete data.socket
200
-
201
- let clients
202
- if (!url)
203
- clients = new Map([[socket, true]])
204
- else
205
- clients = this.clients.get(url);
206
-
207
- if (clients) {
208
- for (let client of clients.keys()) {
209
- if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
210
- const authorized = await this.authorize.check(data, socket.config.user_id)
211
- if (authorized && authorized.authorized)
212
- data = authorized.authorized
213
- let responseData = JSON.stringify(data);
214
- client.send(responseData);
215
-
216
- if (socket.config && socket.config.organization_id)
217
- this.emit("setBandwidth", {
218
- type: 'out',
219
- data: responseData,
220
- organization_id: socket.config.organization_id
221
- })
222
- }
362
+ let sockets = this.get(data);
363
+
364
+ delete data.socket
365
+
366
+ for (let i = 0; i < sockets.length; i++) {
367
+ const authorized = await this.authorize.check(data, sockets[i].user_id)
368
+ if (authorized && authorized.authorized)
369
+ sockets[i].send(JSON.stringify(authorized.authorized));
370
+ else
371
+ sockets[i].send(JSON.stringify(data));
372
+ sent.push(socket.clientId)
373
+ this.emit("setBandwidth", {
374
+ type: 'out',
375
+ data: authorized.authorized || data,
376
+ organization_id: socket.organization_id
377
+ })
223
378
  }
224
- }
225
379
 
380
+ // TODO: sent is an array of clientId's so that notification can send to subscribed clients that are not currently connected
381
+ this.emit("notification", { sent })
382
+ }
226
383
  }
227
384
 
228
- getKeyFromUrl(pathname) {
229
- var path = pathname.split("/");
230
- var params = {
231
- type: null,
232
- key: pathname
385
+ getConfigFromUrl(pathname) {
386
+ const path = pathname.split("/");
387
+ if (path[2]) {
388
+ path[2] = decodeURIComponent(path[2]);
389
+ path[2] = JSON.parse(path[2]) || {};
233
390
  }
234
- if (path.length > 0) {
235
- params.type = path[1];
236
- params.organization_id = path[2]
237
- }
238
- return params
239
- }
240
391
 
241
- getHost(req) {
242
- if (req.headers.origin && req.headers.origin !== 'null') {
243
- const url = new URL(req.headers.origin);
244
- return url.host;
245
- } else if (req.headers.host && req.headers.host !== 'null') {
246
- return req.headers.host;
392
+ const config = {
393
+ organization_id: path[1],
394
+ ...path[2]
247
395
  }
396
+ return config
248
397
  }
249
398
 
250
399
  }
package/src/mesh.js ADDED
@@ -0,0 +1,71 @@
1
+ const socket = require('@cocreate/socket-client')
2
+ const crud = require('@cocreate/crud-client')
3
+ const EventEmitter = require('events');
4
+ const eventEmitter = new EventEmitter();
5
+
6
+
7
+ const organizations = {}
8
+ const urls = new Map()
9
+ const servers = {}
10
+
11
+ async function addServer(data) {
12
+ if (!servers[data.url])
13
+ servers[data.url] = { [data.serverId]: { [data.organization_id]: true } }
14
+ else
15
+ servers[data.url][data.serverId][data.organization_id] = true
16
+
17
+ // TODO: needs to get orgaizations activeRegions
18
+ let activeRegions = await crud.send({
19
+ method: 'read.object',
20
+ array: 'organizations',
21
+ object: { _id: data.organization_id },
22
+ organization_id: data.organization_id
23
+ })
24
+
25
+ console.log('mesh activeRegions: ', activeRegions)
26
+ // socket.send({
27
+ // method: 'region.added',
28
+ // host: data.url,
29
+ // activeRegions: '',
30
+ // serverId: data.serverId,
31
+ // broadcast: false,
32
+ // broadcastSender: false,
33
+ // organization_id: data.organization_id
34
+ // })
35
+ }
36
+
37
+ function deleteServer(data) {
38
+ delete servers[data.url][data.serverId][data.organization_id]
39
+ if (!Object.keys(servers[data.url][data.serverId]).length)
40
+ delete servers[data.url][data.serverId]
41
+ if (!Object.keys(servers[data.url]).length) {
42
+ console.log('mesh deleteServer: ', data.url)
43
+
44
+ // socket.send({
45
+ // method: 'region.removed', // delete.region
46
+ // host: data.url,
47
+ // serverId: data.serverId,
48
+ // organization_id: data.organization_id
49
+ // })
50
+ socket.delete(data.url)
51
+ }
52
+
53
+ }
54
+
55
+ socket.listen('region.added', function (data) {
56
+ addServer(data)
57
+ });
58
+
59
+ socket.listen('region.removed', function (data) {
60
+ delete servers[data.url][data.serverId]
61
+ if (!Object.keys(servers[data.url]).length)
62
+ socket.delete(data.url)
63
+ });
64
+
65
+ eventEmitter.on('mesh.create', addServer);
66
+ eventEmitter.on('mesh.delete', deleteServer);
67
+
68
+ // eventEmitter.emit('customEvent', 'Hello, Node.js!');
69
+
70
+
71
+ // let response = await crud.send(request)