@cocreate/socket-server 1.10.1 → 1.10.3

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/src/index.js CHANGED
@@ -1,306 +1,251 @@
1
- const WebSocket = require('ws');
2
- const url = require("url");
3
- const EventEmitter = require("events").EventEmitter;
4
- const AsyncMessage = require("./AsyncMessage")
5
- const uid = require('@cocreate/uuid')
6
-
7
- class SocketServer extends EventEmitter {
8
- constructor(prefix) {
9
- super();
10
-
11
- this.clients = new Map();
12
- this.asyncMessages = new Map();
13
-
14
- this.prefix = prefix || "crud";
15
-
16
- //. websocket server
17
- this.wss = new WebSocket.Server({ noServer: true });
18
- }
19
-
20
- handleUpgrade(req, socket, head) {
21
- const self = this;
22
- const pathname = url.parse(req.url).pathname;
23
- const config = this.getKeyFromUrl(pathname)
24
- if (config.type == this.prefix) {
25
- self.wss.handleUpgrade(req, socket, head, function (socket) {
26
- socket.config = config
27
- self.onWebSocket(req, socket);
28
- })
29
- return true;
30
- }
31
- return false;
32
- }
33
-
34
- onWebSocket(req, socket) {
35
- const self = this;
36
-
37
- this.addClient(socket);
38
-
39
- socket.on('message', async (message) => {
40
- self.onMessage(req, socket, message);
41
- })
42
-
43
- socket.on('close', function () {
44
- self.removeClient(socket)
45
- })
46
-
47
- socket.on("error", () => {
48
- self.removeClient(socket)
49
- });
50
-
51
- this.send(socket, 'connect', socket.config.key);
52
-
53
- }
54
-
55
- addClient(socket) {
56
- let organization_id = socket.config.organization_id
57
- let user_id = socket.config.user_id
58
- let key = socket.config.key
59
- let room_clients = this.clients.get(key);
60
- if (room_clients) {
61
- room_clients.push(socket);
62
- } else {
63
- room_clients = [socket];
64
- }
65
- this.clients.set(key, room_clients);
66
- // this.addAsyncMessage(key)
67
-
68
- let asyncMessage = this.asyncMessages.get(key)
69
- if (!asyncMessage) {
70
- this.asyncMessages.set(key, new AsyncMessage(key));
71
- }
72
-
73
- if (user_id)
74
- this.emit('userStatus', socket, { user_id, userStatus: 'on', organization_id });
75
-
76
- //. add metrics
77
- let total_cnt = 0;
78
- this.clients.forEach((c) => total_cnt += c.length)
79
-
80
- this.emit("createMetrics", {
81
- organization_id,
82
- client_cnt: room_clients.length,
83
- total_cnt: total_cnt
84
- });
85
- }
86
-
87
- removeClient(socket) {
88
- let organization_id = socket.config.organization_id
89
- let user_id = socket.config.user_id
90
- let key = socket.config.key
91
- let room_clients = this.clients.get(key)
92
- const index = room_clients.indexOf(socket);
93
-
94
- if (index > -1) {
95
- room_clients.splice(index, 1);
96
- }
97
-
98
- if (room_clients.length == 0) {
99
- if (user_id)
100
- this.emit('userStatus', socket, { user_id, status: 'off', organization_id });
101
-
102
- this.emit("deleteMetrics", { organization_id });
103
- this.emit("deletePermissions", organization_id);
104
- this.emit('disconnect', organization_id)
105
- this.asyncMessages.delete(key);
106
- } else {
107
- let total_cnt = 0;
108
- this.clients.forEach((c) => total_cnt += c.length)
109
-
110
- this.emit("changeCountMetrics", {
111
- organization_id,
112
- total_cnt,
113
- client_cnt: room_clients.length
114
- });
115
- }
116
-
117
- }
118
-
119
- async onMessage(req, socket, message) {
120
- try {
121
- const organization_id = socket.config.organization_id
122
- let { action, data } = JSON.parse(message)
123
-
124
- if (action) {
125
- this.emit("setBandwidth", {
126
- type: 'in',
127
- data: message,
128
- organization_id
129
- });
130
- let user_id = null;
131
- if (this.authenticate)
132
- user_id = await this.authenticate.getUserId(req);
133
-
134
- if (this.authorize) {
135
- data.host = this.getHost(req)
136
- const permission = await this.authorize.check(action, data, user_id)
137
- if (permission.dbUrl === false) {
138
- data.database = process.env.organization_id
139
- data.organization_id = process.env.organization_id
140
-
141
- const permission2 = await this.authorize.check(action, data, req, user_id)
142
- if (!permission2 || permission2.error) {
143
- return this.send(socket, 'Access Denied', { action, permission2, ...data })
144
- }
145
- } else if (!permission || permission.error) {
146
- if (!user_id)
147
- this.send(socket, 'updateUserStatus', { userStatus: 'off', clientId: data.clientId, organization_id })
148
-
149
- return this.send(socket, 'Access Denied', { action, permission, ...data })
150
- }
151
- // dburl is true and db does not have 'keys' collection
152
- // action: syncCollection data{collection: 'keys', document[]}
153
- // actions: add keys as once keys are added admin user can do anything
154
-
155
-
156
- // }
157
-
158
- if (permission.authorized)
159
- data = permission.authorized
160
-
161
- if (user_id) {
162
- if (!socket.config.user_id) {
163
- socket.config.user_id = user_id
164
- this.emit('userStatus', socket, { user_id, userStatus: 'on', organization_id });
165
- }
166
- } else {
167
- this.send(socket, 'updateUserStatus', { userStatus: 'off', clientId: data.clientId, organization_id })
168
- }
169
-
170
- //. checking async status....
171
- if (data.async == true) {
172
- console.log('async true')
173
- const asyncMessage = this.asyncMessages.get(socket.config.key);
174
- socket.config.asyncId = uid.generate();
175
- if (asyncMessage) {
176
- asyncMessage.defineMessage(socket.config.asyncId);
177
- }
178
- }
179
-
180
- this.emit(action, socket, data);
181
-
182
- }
183
- }
184
- } catch (e) {
185
- console.log(e);
186
- }
187
- }
188
-
189
- broadcast(socket, action, data) {
190
- if (!data.uid)
191
- data.uid = uid.generate()
192
-
193
- const asyncId = socket.config.asyncId
194
- let isAsync = false;
195
- let asyncData = [];
196
- if (asyncId && socket.config && socket.config.key) {
197
- isAsync = true;
198
- }
199
-
200
- let organization_id = socket.config.organization_id;
201
- let url = `/${this.prefix}/${organization_id}`;
202
-
203
- let namespace = data.namespace;
204
- if (namespace) {
205
- url += `/${namespace}`
206
- }
207
-
208
-
209
- let rooms = data.room;
210
- if (rooms) {
211
- if (!rooms.isArray())
212
- rooms = [rooms]
213
- for (let room of rooms) {
214
- let url = url;
215
- url += `/${room}`;
216
-
217
- this.send(socket, action, data, url, isAsync, asyncData)
218
- }
219
- } else {
220
- this.send(socket, action, data, url, isAsync, asyncData)
221
- }
222
-
223
- if (isAsync) {
224
- this.asyncMessages.get(socket.config.key).setMessage(asyncId, asyncData)
225
- }
226
-
227
- }
228
-
229
- async send(socket, action, data, url, isAsync, asyncData) {
230
- const asyncId = socket.config.asyncId
231
-
232
- if (!url && asyncId && socket.config && socket.config.key) {
233
- let responseData = JSON.stringify({
234
- action,
235
- data
236
- });
237
- this.asyncMessages.get(socket.config.key).setMessage(asyncId, [{ socket, message: responseData }]);
238
- } else {
239
- let clients
240
- if (!url)
241
- clients = [socket]
242
- else
243
- clients = this.clients.get(url);
244
-
245
- if (clients) {
246
- for (let client of clients) {
247
- if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
248
- if (isAsync) {
249
- asyncData.push({ socket, message: JSON.stringify({ action, data }) })
250
- } else {
251
- const permission = await this.authorize.check(action, data, socket.config.user_id)
252
- if (permission && permission.authorized)
253
- data = permission.authorized
254
-
255
- let responseData = JSON.stringify({
256
- action,
257
- data
258
- });
259
-
260
- socket.send(responseData);
261
-
262
- if (socket.config && socket.config.organization_id)
263
- this.emit("setBandwidth", {
264
- type: 'out',
265
- data: responseData,
266
- organization_id: socket.config.organization_id
267
- })
268
- }
269
- }
270
- }
271
- }
272
- }
273
-
274
- }
275
-
276
- // addAsyncMessage(key) {
277
- // let asyncMessage = this.asyncMessages.get(key)
278
- // if (!asyncMessage) {
279
- // this.asyncMessages.set(key, new AsyncMessage(key));
280
- // }
281
- // }
282
-
283
- getKeyFromUrl(pathname) {
284
- var path = pathname.split("/");
285
- var params = {
286
- type: null,
287
- key: pathname
288
- }
289
- if (path.length > 0) {
290
- params.type = path[1];
291
- params.organization_id = path[2]
292
- }
293
- return params
294
- }
295
-
296
- getHost(req) {
297
- const headers = req['headers']
298
- let origin = headers['origin'];
299
- if (origin && origin !== 'null')
300
- return url.parse(origin).hostname;
301
- }
302
-
303
- }
304
-
305
-
306
- module.exports = SocketServer
1
+ const WebSocket = require('ws');
2
+ const url = require("url");
3
+ const EventEmitter = require("events").EventEmitter;
4
+ const uid = require('@cocreate/uuid')
5
+
6
+ class SocketServer extends EventEmitter {
7
+ constructor(prefix) {
8
+ super();
9
+ this.clients = new Map();
10
+ this.prefix = prefix || "crud";
11
+ this.wss = new WebSocket.Server({ noServer: true });
12
+ }
13
+
14
+ handleUpgrade(req, socket, head) {
15
+ const self = this;
16
+ const pathname = url.parse(req.url).pathname;
17
+ const config = this.getKeyFromUrl(pathname)
18
+ if (config.type == this.prefix) {
19
+ self.wss.handleUpgrade(req, socket, head, function (socket) {
20
+ socket.config = config
21
+ self.onWebSocket(req, socket);
22
+ })
23
+ return true;
24
+ }
25
+ return false;
26
+ }
27
+
28
+ onWebSocket(req, socket) {
29
+ const self = this;
30
+
31
+ this.addClient(socket);
32
+
33
+ socket.on('message', async (message) => {
34
+ self.onMessage(req, socket, message);
35
+ })
36
+
37
+ socket.on('close', function () {
38
+ self.removeClient(socket)
39
+ })
40
+
41
+ socket.on("error", () => {
42
+ self.removeClient(socket)
43
+ });
44
+
45
+ this.send(socket, 'connect', socket.config.key);
46
+
47
+ }
48
+
49
+ addClient(socket) {
50
+ let organization_id = socket.config.organization_id
51
+ let user_id = socket.config.user_id
52
+ let key = socket.config.key
53
+ let room_clients = this.clients.get(key);
54
+ if (room_clients) {
55
+ room_clients.push(socket);
56
+ } else {
57
+ room_clients = [socket];
58
+ }
59
+ this.clients.set(key, room_clients);
60
+
61
+ if (user_id)
62
+ this.emit('userStatus', socket, { user_id, userStatus: 'on', organization_id });
63
+
64
+ //. add metrics
65
+ let total_cnt = 0;
66
+ this.clients.forEach((c) => total_cnt += c.length)
67
+
68
+ this.emit("createMetrics", {
69
+ organization_id,
70
+ client_cnt: room_clients.length,
71
+ total_cnt: total_cnt
72
+ });
73
+ }
74
+
75
+ removeClient(socket) {
76
+ let organization_id = socket.config.organization_id
77
+ let user_id = socket.config.user_id
78
+ let key = socket.config.key
79
+ let room_clients = this.clients.get(key)
80
+ const index = room_clients.indexOf(socket);
81
+
82
+ if (index > -1) {
83
+ room_clients.splice(index, 1);
84
+ }
85
+
86
+ if (room_clients.length == 0) {
87
+ if (user_id)
88
+ this.emit('userStatus', socket, { user_id, status: 'off', organization_id });
89
+
90
+ // TODO: remove if no one else connected to organization
91
+ this.emit("deleteMetrics", { organization_id });
92
+ this.emit("deletePermissions", organization_id);
93
+ this.emit('disconnect', organization_id)
94
+ } else {
95
+ let total_cnt = 0;
96
+ this.clients.forEach((c) => total_cnt += c.length)
97
+
98
+ this.emit("changeCountMetrics", {
99
+ organization_id,
100
+ total_cnt,
101
+ client_cnt: room_clients.length
102
+ });
103
+ }
104
+
105
+ }
106
+
107
+ async onMessage(req, socket, message) {
108
+ try {
109
+ const organization_id = socket.config.organization_id
110
+ let { action, data } = JSON.parse(message)
111
+
112
+ if (action) {
113
+ this.emit("setBandwidth", {
114
+ type: 'in',
115
+ data: message,
116
+ organization_id
117
+ });
118
+ let user_id = null;
119
+ if (this.authenticate)
120
+ user_id = await this.authenticate.getUserId(req);
121
+
122
+ if (this.authorize) {
123
+ data.host = this.getHost(req)
124
+ const permission = await this.authorize.check(action, data, user_id)
125
+ if (permission.dbUrl === false) {
126
+ data.database = process.env.organization_id
127
+ data.organization_id = process.env.organization_id
128
+
129
+ const permission2 = await this.authorize.check(action, data, req, user_id)
130
+ if (!permission2 || permission2.error) {
131
+ return this.send(socket, 'Access Denied', { action, permission2, ...data })
132
+ }
133
+ } else if (!permission || permission.error) {
134
+ if (!user_id)
135
+ this.send(socket, 'updateUserStatus', { userStatus: 'off', clientId: data.clientId, organization_id })
136
+
137
+ return this.send(socket, 'Access Denied', { action, permission, ...data })
138
+ }
139
+ // dburl is true and db does not have 'keys' collection
140
+ // action: syncCollection data{collection: 'keys', document[]}
141
+ // actions: add keys as once keys are added admin user can do anything
142
+
143
+
144
+ // }
145
+
146
+ if (permission.authorized)
147
+ data = permission.authorized
148
+
149
+ if (user_id) {
150
+ if (!socket.config.user_id) {
151
+ socket.config.user_id = user_id
152
+ this.emit('userStatus', socket, { user_id, userStatus: 'on', organization_id });
153
+ }
154
+ } else {
155
+ this.send(socket, 'updateUserStatus', { userStatus: 'off', clientId: data.clientId, organization_id })
156
+ }
157
+
158
+ this.emit(action, socket, data);
159
+
160
+ }
161
+ }
162
+ } catch (e) {
163
+ console.log(e);
164
+ }
165
+ }
166
+
167
+ broadcast(socket, action, data) {
168
+ if (!data.uid)
169
+ data.uid = uid.generate()
170
+
171
+ let organization_id = socket.config.organization_id;
172
+ let url = `/${this.prefix}/${organization_id}`;
173
+
174
+ let namespace = data.namespace;
175
+ if (namespace) {
176
+ url += `/${namespace}`
177
+ }
178
+
179
+
180
+ let rooms = data.room;
181
+ if (rooms) {
182
+ if (!rooms.isArray())
183
+ rooms = [rooms]
184
+ for (let room of rooms) {
185
+ let url = url;
186
+ url += `/${room}`;
187
+
188
+ this.send(socket, action, data, url)
189
+ }
190
+ } else {
191
+ this.send(socket, action, data, url)
192
+ }
193
+ }
194
+
195
+ async send(socket, action, data, url) {
196
+ let clients
197
+ if (!url)
198
+ clients = [socket]
199
+ else
200
+ clients = this.clients.get(url);
201
+
202
+ if (clients) {
203
+ for (let client of clients) {
204
+ if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
205
+ const permission = await this.authorize.check(action, data, socket.config.user_id)
206
+ if (permission && permission.authorized)
207
+ data = permission.authorized
208
+
209
+ let responseData = JSON.stringify({
210
+ action,
211
+ data
212
+ });
213
+
214
+ socket.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
+ }
223
+ }
224
+ }
225
+
226
+ }
227
+
228
+ getKeyFromUrl(pathname) {
229
+ var path = pathname.split("/");
230
+ var params = {
231
+ type: null,
232
+ key: pathname
233
+ }
234
+ if (path.length > 0) {
235
+ params.type = path[1];
236
+ params.organization_id = path[2]
237
+ }
238
+ return params
239
+ }
240
+
241
+ getHost(req) {
242
+ const headers = req['headers']
243
+ let origin = headers['origin'];
244
+ if (origin && origin !== 'null')
245
+ return url.parse(origin).hostname;
246
+ }
247
+
248
+ }
249
+
250
+
251
+ module.exports = SocketServer
@@ -1,52 +0,0 @@
1
-
2
- class AsyncMessage {
3
- constructor(key) {
4
- this.key = key;
5
- this.messages = new Map();
6
- this.orders = [];
7
- }
8
-
9
- defineMessage(id) {
10
- this.orders.push(id);
11
- this.messages.set(id, null);
12
- }
13
-
14
- setMessage(id, data) {
15
- this.messages.set(id, data);
16
- if (this.orders.length > 0) {
17
- this.runMessage();
18
- }
19
-
20
- }
21
-
22
- runMessage() {
23
- let runIndex = -1;
24
- this.orders.some((key, index) => {
25
- let messageData = this.messages.get(key)
26
- if (messageData != null) {
27
- messageData.forEach(({socket, message}) => {
28
- try {
29
- if (socket) {
30
- socket.send(message);
31
- }
32
- } catch (error) {
33
- console.log(error);
34
- }
35
- })
36
-
37
- runIndex = index;
38
- this.messages.delete(key);
39
- return false;
40
- } else {
41
- return true;
42
- }
43
- })
44
-
45
- if (runIndex !== -1) {
46
- this.orders.splice(0, runIndex + 1);
47
- }
48
-
49
- }
50
- }
51
-
52
- module.exports = AsyncMessage;