mongo-realtime 1.0.1 → 1.0.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/README.md +49 -18
- package/index.js +27 -0
- package/logo.png +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A Node.js package that combines Socket.IO and MongoDB Change Streams to deliver real-time database updates to your WebSocket clients.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
## 🚀 Features
|
|
6
8
|
|
|
7
9
|
- **Real-time updates**: Automatically detects changes in MongoDB and broadcasts them via Socket.IO
|
|
@@ -69,6 +71,8 @@ Initializes the socket system and MongoDB Change Streams.
|
|
|
69
71
|
|-----------|------|-------------|
|
|
70
72
|
| `options.connection` | `mongoose.Connection`* | Active Mongoose connection |
|
|
71
73
|
| `options.server` | `http.Server`* | HTTP server to attach Socket.IO |
|
|
74
|
+
| `options.authentify` | `Function` | Function to authenticate socket connections. Should return true if authenticated |
|
|
75
|
+
| `options.middlewares` | `Array[Function]` | Array of Socket.IO middlewares |
|
|
72
76
|
| `options.onSocket` | `Function` | Callback on socket connection |
|
|
73
77
|
| `options.offSocket` | `Function` | Callback on socket disconnection |
|
|
74
78
|
| `options.watch` | `Array[String]` | Collections to only watch. Listen to all when is empty |
|
|
@@ -95,6 +99,35 @@ The package automatically emits six types of events for each database change:
|
|
|
95
99
|
| `db:change:{collection}:{id}` | Specific document | `db:change:users:507f1f77bcf86cd799439011` |
|
|
96
100
|
| `db:{type}:{collection}:{id}` | Type + document | `db:insert:users:507f1f77bcf86cd799439011` |
|
|
97
101
|
|
|
102
|
+
### Event listeners
|
|
103
|
+
|
|
104
|
+
You can add serverside listeners to those db events to trigger specific actions on the server:
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
function sendNotification(change){
|
|
108
|
+
const userId = change.docId; // or change.documentKey._id
|
|
109
|
+
NotificationService.send(userId,"Welcome to DB");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
MongoRealtime.listen("db:insert:users",sendNotification);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Adding many callback to one event
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
MongoRealtime.listen("db:insert:users",anotherAction);
|
|
119
|
+
MongoRealtime.listen("db:insert:users",anotherAction2);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### Removing event listeners
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
MongoRealtime.removeListener("db:insert:users",sendNotification); // remove this specific action from this event
|
|
126
|
+
MongoRealtime.removeListener("db:insert:users"); // remove all actions from this event
|
|
127
|
+
MongoRealtime.removeAllListeners(); // remove all listeners
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
|
|
98
131
|
### Event Payload Structure
|
|
99
132
|
|
|
100
133
|
Each event contains the full MongoDB change object:
|
|
@@ -102,6 +135,8 @@ Each event contains the full MongoDB change object:
|
|
|
102
135
|
```javascript
|
|
103
136
|
{
|
|
104
137
|
"_id": {...},
|
|
138
|
+
"col":"users", // same as ns.coll
|
|
139
|
+
"docId":"...", // same as documentKey._id
|
|
105
140
|
"operationType": "insert|update|delete|replace",
|
|
106
141
|
"documentKey": { "_id": "..." },
|
|
107
142
|
"ns": { "db": "mydb", "coll": "users" },
|
|
@@ -186,29 +221,25 @@ MongoRealtime.init({
|
|
|
186
221
|
### Socket Authentication
|
|
187
222
|
|
|
188
223
|
```javascript
|
|
189
|
-
function authenticateSocket(socket){
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
socket.use((packet, next) => {
|
|
200
|
-
if (socket.authenticated) {
|
|
201
|
-
next();
|
|
202
|
-
} else {
|
|
203
|
-
next(new Error('Unauthenticated'));
|
|
204
|
-
}
|
|
205
|
-
});
|
|
224
|
+
function authenticateSocket(token, socket){
|
|
225
|
+
const verify = AuthService.verifyToken(token);
|
|
226
|
+
if(verify){
|
|
227
|
+
socket.user = verify.user; // attach user info to socket
|
|
228
|
+
return true; // should return true to accept the connection
|
|
229
|
+
}
|
|
230
|
+
return false;
|
|
206
231
|
}
|
|
207
232
|
|
|
208
233
|
MongoRealtime.init({
|
|
209
234
|
connection: mongoose.connection,
|
|
210
235
|
server: server,
|
|
211
|
-
|
|
236
|
+
authentify: authenticateSocket,
|
|
237
|
+
middlewares: [
|
|
238
|
+
(socket, next) => {
|
|
239
|
+
console.log(`User is authenticated: ${socket.user.email}`);
|
|
240
|
+
next();
|
|
241
|
+
}
|
|
242
|
+
],
|
|
212
243
|
offSocket: (socket, reason) => {
|
|
213
244
|
console.log(`Socket ${socket.id} disconnected: ${reason}`);
|
|
214
245
|
}
|
package/index.js
CHANGED
|
@@ -12,6 +12,8 @@ class MongoRealtime {
|
|
|
12
12
|
*
|
|
13
13
|
* @param {Object} options
|
|
14
14
|
* @param {import("mongoose").Connection} options.connection - Active Mongoose connection
|
|
15
|
+
* @param {(token:String, socket: import("socket.io").Socket) => boolean | Promise<boolean>} options.authentify - Auth function that should return true if `token` is valid
|
|
16
|
+
* @param {[( socket: import("socket.io").Socket, next: (err?: ExtendedError) => void) => void]} options.middlewares - Register mmiddlewares on incoming socket
|
|
15
17
|
* @param {(socket: import("socket.io").Socket) => void} options.onSocket - Callback triggered when a socket connects
|
|
16
18
|
* @param {(socket: import("socket.io").Socket, reason: import("socket.io").DisconnectReason) => void} options.offSocket - Callback triggered when a socket disconnects
|
|
17
19
|
* @param {import("http").Server} options.server - HTTP server to attach Socket.IO to
|
|
@@ -22,6 +24,8 @@ class MongoRealtime {
|
|
|
22
24
|
static init({
|
|
23
25
|
connection,
|
|
24
26
|
server,
|
|
27
|
+
authentify,
|
|
28
|
+
middlewares=[],
|
|
25
29
|
onSocket,
|
|
26
30
|
offSocket,
|
|
27
31
|
watch = [],
|
|
@@ -37,6 +41,29 @@ class MongoRealtime {
|
|
|
37
41
|
watch = watch.map((s) => s.toLowerCase());
|
|
38
42
|
ignore = ignore.map((s) => s.toLowerCase());
|
|
39
43
|
|
|
44
|
+
this.io.use(async (socket, next) => {
|
|
45
|
+
if (!!authentify) {
|
|
46
|
+
try {
|
|
47
|
+
const token = socket.handshake.auth.token;
|
|
48
|
+
if (!token) return next(new Error("No token provided"));
|
|
49
|
+
|
|
50
|
+
const authorized =await authentify(token, socket);
|
|
51
|
+
if (authorized===true) return next(); // exactly returns true
|
|
52
|
+
|
|
53
|
+
return next(new Error("Unauthorized"));
|
|
54
|
+
} catch (error) {
|
|
55
|
+
return next(new Error("Authentication error"));
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
return next();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
for (let middleware of middlewares) {
|
|
64
|
+
this.io.use(middleware);
|
|
65
|
+
}
|
|
66
|
+
|
|
40
67
|
this.io.on("connection", (socket) => {
|
|
41
68
|
this.sockets = [...this.io.sockets.sockets.values()];
|
|
42
69
|
if (onSocket) onSocket(socket);
|
package/logo.png
ADDED
|
Binary file
|