@cocreate/socket-server 1.7.7 → 1.8.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/package.json +1 -1
  3. package/src/index.js +323 -306
package/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ # [1.8.0](https://github.com/CoCreate-app/CoCreate-socket-server/compare/v1.7.7...v1.8.0) (2023-05-19)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Refactor index.js to remove unused code and improve readability ([8b71373](https://github.com/CoCreate-app/CoCreate-socket-server/commit/8b71373fc453d247389b786530c491754f8104d5))
7
+ * SocketServer class methods and properties ([9dd6f1d](https://github.com/CoCreate-app/CoCreate-socket-server/commit/9dd6f1d25b7bbe6a107d9076db31b73ac8a464b3))
8
+
9
+
10
+ ### Features
11
+
12
+ * handle dbUrl false session ([61f64d2](https://github.com/CoCreate-app/CoCreate-socket-server/commit/61f64d2d02327ef3bec2821e8f3f083cc449a753))
13
+
1
14
  ## [1.7.7](https://github.com/CoCreate-app/CoCreate-socket-server/compare/v1.7.6...v1.7.7) (2023-05-11)
2
15
 
3
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/socket-server",
3
- "version": "1.7.7",
3
+ "version": "1.8.0",
4
4
  "description": "CoCreate-socket-server",
5
5
  "keywords": [
6
6
  "cocreate-socket",
package/src/index.js CHANGED
@@ -4,312 +4,329 @@ const EventEmitter = require("events").EventEmitter;
4
4
  const AsyncMessage = require("./AsyncMessage")
5
5
  const uid = require('@cocreate/uuid')
6
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
- this.permissionInstance = null;
19
- this.authInstance = null;
20
- }
21
-
22
- setPermission(instance) {
23
- this.permissionInstance = instance;
24
- }
25
-
26
- setAuth(instance) {
27
- this.authInstance = instance
28
- }
29
-
30
- handleUpgrade(req, socket, head) {
31
- const self = this;
32
- const pathname = url.parse(req.url).pathname;
33
- const config = this.getKeyFromUrl(pathname)
34
- if (config.type == this.prefix) {
35
- self.wss.handleUpgrade(req, socket, head, function(socket) {
36
- socket.config = config
37
- self.onWebSocket(req, socket);
38
- })
39
- return true;
40
- }
41
- return false;
42
- }
43
-
44
- onWebSocket(req, socket) {
45
- const self = this;
46
-
47
- this.addClient(socket);
48
-
49
- socket.on('message', async (message) => {
50
- self.onMessage(req, socket, message);
51
- })
52
-
53
- socket.on('close', function () {
54
- self.removeClient(socket)
55
- })
56
-
57
- socket.on("error", () => {
58
- self.removeClient(socket)
59
- });
60
-
61
- this.send(socket, 'connect', socket.config.key);
62
-
63
- }
64
-
65
- addClient(socket) {
66
- let organization_id = socket.config.organization_id
67
- let user_id = socket.config.user_id
68
- let key = socket.config.key
69
- let room_clients = this.clients.get(key);
70
- if (room_clients) {
71
- room_clients.push(socket);
72
- } else {
73
- room_clients = [socket];
74
- }
75
- this.clients.set(key, room_clients);
76
- // this.addAsyncMessage(key)
77
-
78
- let asyncMessage = this.asyncMessages.get(key)
79
- if (!asyncMessage) {
80
- this.asyncMessages.set(key, new AsyncMessage(key));
81
- }
82
-
83
- if (user_id)
84
- this.emit('userStatus', socket, {user_id, userStatus: 'on', organization_id});
85
-
86
- //. add metrics
87
- let total_cnt = 0;
88
- this.clients.forEach((c) => total_cnt += c.length)
89
-
90
- this.emit("createMetrics", null, {
91
- organization_id,
92
- client_cnt: room_clients.length,
93
- total_cnt: total_cnt
94
- });
95
- }
96
-
97
- removeClient(socket) {
98
- let organization_id = socket.config.organization_id
99
- let user_id = socket.config.user_id
100
- let key = socket.config.key
101
- let room_clients = this.clients.get(key)
102
- const index = room_clients.indexOf(socket);
103
-
104
- if (index > -1) {
105
- room_clients.splice(index, 1);
106
- }
107
-
108
- if (room_clients.length == 0) {
109
- if (user_id)
110
- this.emit('userStatus', socket, {user_id, status: 'off', organization_id});
111
-
112
- this.emit("deleteMetrics", null, { organization_id });
113
- this.emit("deletePermissions", organization_id );
114
- this.emit('disconnect', organization_id)
115
- this.asyncMessages.delete(key);
116
- } else {
117
- let total_cnt = 0;
118
- this.clients.forEach((c) => total_cnt += c.length)
119
-
120
- this.emit("changeCountMetrics", null, {
121
- organization_id,
122
- total_cnt,
123
- client_cnt: room_clients.length
124
- });
125
- }
126
-
127
- }
128
-
129
- async onMessage(req, socket, message) {
130
- try {
131
- const organization_id = socket.config.organization_id
132
-
133
- // ToDo: remove
134
- // if (message instanceof Buffer) {
135
- // this.emit('importFile2DB', socket, message);
136
- // console.log('importFile2DB', socket, message);
137
- // return;
138
- // }
139
-
140
- const {action, data} = JSON.parse(message)
141
-
142
- if (action) {
143
- this.recordTransfer('in', message, organization_id)
144
-
145
- let user_id = null;
146
- if (this.authInstance)
147
- user_id = await this.authInstance.getUserId(req);
148
-
149
- if (this.permissionInstance) {
150
- const permission = await this.permissionInstance.check(action, data, req, user_id)
151
- if (!permission || permission.error) {
152
- // if (action == 'syncServer' && permission.database === true)
153
- // if (action == 'syncServer')
154
- // this.emit('createDocument', socket, data);
155
- // else
156
- if (action !== 'createOrg')
157
- return this.send(socket, 'Access Denied', {action, permission, ...data})
158
- else
159
- this.send(socket, 'Access Denied', {action, permission})
160
-
161
- }
162
- }
163
-
164
- if (user_id) {
165
- if (!socket.config.user_id ) {
166
- socket.config.user_id = user_id
167
- this.emit('userStatus', socket, {user_id, userStatus: 'on', organization_id});
168
- }
169
- } else {
170
- this.send(socket, 'updateUserStatus', {userStatus: 'off', clientId: data.clientId, organization_id})
171
- }
172
-
173
- //. checking async status....
174
- if (data.async == true) {
175
- console.log('async true')
176
- const asyncMessage = this.asyncMessages.get(socket.config.key);
177
- socket.config.asyncId = uid.generate();
178
- if (asyncMessage) {
179
- asyncMessage.defineMessage(socket.config.asyncId);
180
- }
181
- }
182
-
183
- this.emit(action, socket, data);
184
- }
185
-
186
- } catch(e) {
187
- console.log(e);
188
- }
189
- }
190
-
191
- broadcast(socket, action, data) {
192
- const self = this;
193
- if (!data.uid)
194
- data.uid = uid.generate()
195
- const responseData = JSON.stringify({
196
- action,
197
- data
198
- });
199
-
200
- const asyncId = socket.config.asyncId
201
- let isAsync = false;
202
- let asyncData = [];
203
- if (asyncId && socket.config && socket.config.key) {
204
- isAsync = true;
205
- }
206
-
207
- let organization_id = socket.config.organization_id;
208
- let url = `/${this.prefix}/${organization_id}`;
209
-
210
- let namespace = data.namespace;
211
- if (namespace) {
212
- url += `/${namespace}`
213
- }
214
-
215
- let rooms = data.room;
216
- if (rooms) {
217
- if (!rooms.isArray())
218
- rooms = [rooms]
219
- for (let room of rooms) {
220
- let url = url;
221
- url += `/${room}`;
222
-
223
- const clients = this.clients.get(url);
224
- if (clients) {
225
- clients.forEach((client) => {
226
- if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
227
- if (isAsync) {
228
- asyncData.push({socket: client, message: responseData})
229
- } else {
230
- client.send(responseData);
231
- }
232
- self.recordTransfer('out', responseData, organization_id)
233
- }
234
- })
235
- }
236
- }
237
-
238
- } else {
239
- this.clients.forEach((value, key) => {
240
- if (key.includes(url)) {
241
- value.forEach(client => {
242
- if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
243
- if (isAsync) {
244
- asyncData.push({socket: client, message: responseData})
245
- } else {
246
- client.send(responseData);
247
- }
248
- self.recordTransfer('out', responseData, organization_id)
249
- }
250
- })
251
- }
252
- })
253
- }
254
-
255
- //. set async processing
256
- if (isAsync) {
257
- this.asyncMessages.get(socket.config.key).setMessage(asyncId, asyncData)
258
- }
259
-
260
- }
261
-
262
- send(socket, action, data){
263
- const asyncId = socket.config.asyncId
264
- let responseData = JSON.stringify({
265
- action,
266
- data
267
- });
268
-
269
- if (asyncId && socket.config && socket.config.key) {
270
- this.asyncMessages.get(socket.config.key).setMessage(asyncId, [{socket, message: responseData}]);
271
- } else {
272
- socket.send(responseData);
273
- }
274
-
275
- if (socket.config && socket.config.organization_id)
276
- this.recordTransfer('out', responseData, socket.config.organization_id)
277
-
278
- }
279
-
280
- // addAsyncMessage(key) {
281
- // let asyncMessage = this.asyncMessages.get(key)
282
- // if (!asyncMessage) {
283
- // this.asyncMessages.set(key, new AsyncMessage(key));
284
- // }
285
- // }
286
-
287
- getKeyFromUrl(pathname) {
288
- var path = pathname.split("/");
289
- var params = {
290
- type: null,
291
- key: pathname
292
- }
293
- if (path.length > 0) {
294
- params.type = path[1];
295
- params.organization_id = path[2]
296
- }
297
- return params
298
- }
299
-
300
-
301
- sendBinary(socket, data, organization_id) {
302
- socket.send(data, {binary: true});
303
- this.recordTransfer('out', data, organization_id)
304
- }
305
-
306
- recordTransfer(type, data, organization_id) {
307
- this.emit("setBandwidth", null, {
308
- type,
309
- data,
310
- organization_id
311
- });
312
- }
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
+ this.permissionInstance = null;
19
+ this.authInstance = null;
20
+ }
21
+
22
+ setPermission(instance) {
23
+ this.permissionInstance = instance;
24
+ }
25
+
26
+ setAuth(instance) {
27
+ this.authInstance = instance
28
+ }
29
+
30
+ handleUpgrade(req, socket, head) {
31
+ const self = this;
32
+ const pathname = url.parse(req.url).pathname;
33
+ const config = this.getKeyFromUrl(pathname)
34
+ if (config.type == this.prefix) {
35
+ self.wss.handleUpgrade(req, socket, head, function (socket) {
36
+ socket.config = config
37
+ self.onWebSocket(req, socket);
38
+ })
39
+ return true;
40
+ }
41
+ return false;
42
+ }
43
+
44
+ onWebSocket(req, socket) {
45
+ const self = this;
46
+
47
+ this.addClient(socket);
48
+
49
+ socket.on('message', async (message) => {
50
+ self.onMessage(req, socket, message);
51
+ })
52
+
53
+ socket.on('close', function () {
54
+ self.removeClient(socket)
55
+ })
56
+
57
+ socket.on("error", () => {
58
+ self.removeClient(socket)
59
+ });
60
+
61
+ this.send(socket, 'connect', socket.config.key);
62
+
63
+ }
64
+
65
+ addClient(socket) {
66
+ let organization_id = socket.config.organization_id
67
+ let user_id = socket.config.user_id
68
+ let key = socket.config.key
69
+ let room_clients = this.clients.get(key);
70
+ if (room_clients) {
71
+ room_clients.push(socket);
72
+ } else {
73
+ room_clients = [socket];
74
+ }
75
+ this.clients.set(key, room_clients);
76
+ // this.addAsyncMessage(key)
77
+
78
+ let asyncMessage = this.asyncMessages.get(key)
79
+ if (!asyncMessage) {
80
+ this.asyncMessages.set(key, new AsyncMessage(key));
81
+ }
82
+
83
+ if (user_id)
84
+ this.emit('userStatus', socket, { user_id, userStatus: 'on', organization_id });
85
+
86
+ //. add metrics
87
+ let total_cnt = 0;
88
+ this.clients.forEach((c) => total_cnt += c.length)
89
+
90
+ this.emit("createMetrics", null, {
91
+ organization_id,
92
+ client_cnt: room_clients.length,
93
+ total_cnt: total_cnt
94
+ });
95
+ }
96
+
97
+ removeClient(socket) {
98
+ let organization_id = socket.config.organization_id
99
+ let user_id = socket.config.user_id
100
+ let key = socket.config.key
101
+ let room_clients = this.clients.get(key)
102
+ const index = room_clients.indexOf(socket);
103
+
104
+ if (index > -1) {
105
+ room_clients.splice(index, 1);
106
+ }
107
+
108
+ if (room_clients.length == 0) {
109
+ if (user_id)
110
+ this.emit('userStatus', socket, { user_id, status: 'off', organization_id });
111
+
112
+ this.emit("deleteMetrics", null, { organization_id });
113
+ this.emit("deletePermissions", organization_id);
114
+ this.emit('disconnect', organization_id)
115
+ this.asyncMessages.delete(key);
116
+ } else {
117
+ let total_cnt = 0;
118
+ this.clients.forEach((c) => total_cnt += c.length)
119
+
120
+ this.emit("changeCountMetrics", null, {
121
+ organization_id,
122
+ total_cnt,
123
+ client_cnt: room_clients.length
124
+ });
125
+ }
126
+
127
+ }
128
+
129
+ async onMessage(req, socket, message) {
130
+ try {
131
+ const organization_id = socket.config.organization_id
132
+
133
+ // TODO: remove
134
+ // if (message instanceof Buffer) {
135
+ // this.emit('importFile2DB', socket, message);
136
+ // console.log('importFile2DB', socket, message);
137
+ // return;
138
+ // }
139
+
140
+ const { action, data } = JSON.parse(message)
141
+
142
+ if (action) {
143
+ this.recordTransfer('in', message, organization_id)
144
+
145
+ let user_id = null;
146
+ if (this.authInstance)
147
+ user_id = await this.authInstance.getUserId(req);
148
+
149
+ if (this.permissionInstance) {
150
+ const permission = await this.permissionInstance.check(action, data, req, user_id)
151
+ if (!permission || permission.error) {
152
+ // if (action == 'syncServer' && permission.database === true)
153
+ // if (action == 'syncServer')
154
+ // this.emit('createDocument', socket, data);
155
+ // else
156
+ if (user_id && permission.dbUrl === false && action.includes('Document') && (data.collection == 'organizations' || data.collection == 'users')) {
157
+ data.database = process.env.organization_id
158
+ data.organization_id = process.env.organization_id
159
+ if (data.document) {
160
+ if (Array.isArray(data.document) && data.document[0])
161
+ data.document = data.document[0]
162
+
163
+ if (data.collection == 'organizations' && data.document._id !== socket.config.organization_id)
164
+ return this.send(socket, 'Access Denied', { action, permission, ...data })
165
+ else if (data.collection == 'users' && data.document._id !== user_id)
166
+ return this.send(socket, 'Access Denied', { action, permission, ...data })
167
+ }
168
+ delete data.filter
169
+ delete data.document.organization_id
170
+ if (action == 'updateDocument')
171
+ data.upsert = false
172
+ } else if (action === 'createOrganization' || action === 'signIn') {
173
+ data.database = process.env.organization_id
174
+ data.organization_id = process.env.organization_id
175
+ } else {
176
+ return this.send(socket, 'Access Denied', { action, permission, ...data })
177
+ }
178
+ }
179
+ }
180
+
181
+ if (user_id) {
182
+ if (!socket.config.user_id) {
183
+ socket.config.user_id = user_id
184
+ this.emit('userStatus', socket, { user_id, userStatus: 'on', organization_id });
185
+ }
186
+ } else {
187
+ this.send(socket, 'updateUserStatus', { userStatus: 'off', clientId: data.clientId, organization_id })
188
+ }
189
+
190
+ //. checking async status....
191
+ if (data.async == true) {
192
+ console.log('async true')
193
+ const asyncMessage = this.asyncMessages.get(socket.config.key);
194
+ socket.config.asyncId = uid.generate();
195
+ if (asyncMessage) {
196
+ asyncMessage.defineMessage(socket.config.asyncId);
197
+ }
198
+ }
199
+
200
+ this.emit(action, socket, data);
201
+ }
202
+
203
+ } catch (e) {
204
+ console.log(e);
205
+ }
206
+ }
207
+
208
+ broadcast(socket, action, data) {
209
+ const self = this;
210
+ if (!data.uid)
211
+ data.uid = uid.generate()
212
+ const responseData = JSON.stringify({
213
+ action,
214
+ data
215
+ });
216
+
217
+ const asyncId = socket.config.asyncId
218
+ let isAsync = false;
219
+ let asyncData = [];
220
+ if (asyncId && socket.config && socket.config.key) {
221
+ isAsync = true;
222
+ }
223
+
224
+ let organization_id = socket.config.organization_id;
225
+ let url = `/${this.prefix}/${organization_id}`;
226
+
227
+ let namespace = data.namespace;
228
+ if (namespace) {
229
+ url += `/${namespace}`
230
+ }
231
+
232
+ let rooms = data.room;
233
+ if (rooms) {
234
+ if (!rooms.isArray())
235
+ rooms = [rooms]
236
+ for (let room of rooms) {
237
+ let url = url;
238
+ url += `/${room}`;
239
+
240
+ const clients = this.clients.get(url);
241
+ if (clients) {
242
+ clients.forEach((client) => {
243
+ if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
244
+ if (isAsync) {
245
+ asyncData.push({ socket: client, message: responseData })
246
+ } else {
247
+ client.send(responseData);
248
+ }
249
+ self.recordTransfer('out', responseData, organization_id)
250
+ }
251
+ })
252
+ }
253
+ }
254
+
255
+ } else {
256
+ this.clients.forEach((value, key) => {
257
+ if (key.includes(url)) {
258
+ value.forEach(client => {
259
+ if (socket != client && data.broadcast != false || socket == client && data.broadcastSender != false) {
260
+ if (isAsync) {
261
+ asyncData.push({ socket: client, message: responseData })
262
+ } else {
263
+ client.send(responseData);
264
+ }
265
+ self.recordTransfer('out', responseData, organization_id)
266
+ }
267
+ })
268
+ }
269
+ })
270
+ }
271
+
272
+ //. set async processing
273
+ if (isAsync) {
274
+ this.asyncMessages.get(socket.config.key).setMessage(asyncId, asyncData)
275
+ }
276
+
277
+ }
278
+
279
+ send(socket, action, data) {
280
+ const asyncId = socket.config.asyncId
281
+ let responseData = JSON.stringify({
282
+ action,
283
+ data
284
+ });
285
+
286
+ if (asyncId && socket.config && socket.config.key) {
287
+ this.asyncMessages.get(socket.config.key).setMessage(asyncId, [{ socket, message: responseData }]);
288
+ } else {
289
+ socket.send(responseData);
290
+ }
291
+
292
+ if (socket.config && socket.config.organization_id)
293
+ this.recordTransfer('out', responseData, socket.config.organization_id)
294
+
295
+ }
296
+
297
+ // addAsyncMessage(key) {
298
+ // let asyncMessage = this.asyncMessages.get(key)
299
+ // if (!asyncMessage) {
300
+ // this.asyncMessages.set(key, new AsyncMessage(key));
301
+ // }
302
+ // }
303
+
304
+ getKeyFromUrl(pathname) {
305
+ var path = pathname.split("/");
306
+ var params = {
307
+ type: null,
308
+ key: pathname
309
+ }
310
+ if (path.length > 0) {
311
+ params.type = path[1];
312
+ params.organization_id = path[2]
313
+ }
314
+ return params
315
+ }
316
+
317
+
318
+ sendBinary(socket, data, organization_id) {
319
+ socket.send(data, { binary: true });
320
+ this.recordTransfer('out', data, organization_id)
321
+ }
322
+
323
+ recordTransfer(type, data, organization_id) {
324
+ this.emit("setBandwidth", null, {
325
+ type,
326
+ data,
327
+ organization_id
328
+ });
329
+ }
313
330
  }
314
331
 
315
332