mongo-realtime 1.1.1 → 1.1.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.
Files changed (3) hide show
  1. package/README.md +16 -2
  2. package/index.js +27 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -259,7 +259,8 @@ MongoRealtime.init({
259
259
  The server will automatically emit a list of filtered documents from the specified collections after each change.\
260
260
  Each list stream requires an unique `streamId`, the `collection` name, and an optional `filter` function that returns a boolean or a promise resolving to a boolean.
261
261
  Clients receive the list on the event `db:stream:{streamId}`.\
262
- For best practice, two list streams can't have the same `streamId` or else an error will be thrown. This will prevent accidental overrides. You can still remove a stream with `MongoRealtime.removeListStream(streamId)` and add it again or use inside a `try-catch` scope.
262
+
263
+ On init, when `safeListStream` is `true`(default), two list streams can't have the same `streamId` or else an error will be thrown. This will prevent accidental overrides. You can still remove a stream with `MongoRealtime.removeListStream(streamId)` and add it again or use inside a `try-catch` scope.
263
264
 
264
265
  ```javascript
265
266
  MongoRealtime.init({
@@ -280,15 +281,28 @@ MongoRealtime.addListStream("usersWithEmail", "users", (doc) => !!doc.email); //
280
281
 
281
282
  When `autoListStream` is not set, all collections are automatically streamed and WITHOUT any filter.\
282
283
  That means that if you have a `posts` collection, all documents from this collection will be sent to the clients on each change.\
283
- And as two list streams can't have the same `streamId`, if you want to add a filtered list stream with id `posts`, you must set `autoListStream` to an array NOT containing `"posts"`or `MongoRealtime.removeListStream("posts")` after initialization.\
284
+
285
+ Also, `safeListStream` is enabled by default. So, you can't add a list stream with id `posts` if `autoListStream` contains `"posts"` or is not set.\
286
+
287
+ If you want to add a filtered list stream with id `posts`, you must set `autoListStream` to an array NOT containing `"posts"`or call `MongoRealtime.removeListStream("posts")` after initialization.\
284
288
  Therefore, if you want to add a filtered list stream for all collections, you must set `autoListStream` to an empty array.
285
289
 
290
+ To avoid all these issues, you can set `safeListStream` to `false` in the init options but be careful as this will allow you to override existing streams.
291
+
286
292
  ```javascript
287
293
  MongoRealtime.init({
288
294
  connection: mongoose.connection,
289
295
  server: server,
290
296
  autoListStream: [], // stream no collection automatically (you can add your own filtered streams later)
291
297
  });
298
+ // or
299
+ MongoRealtime.init({
300
+ connection: mongoose.connection,
301
+ server: server,
302
+ safeListStream: false, // disable safe mode (you can override existing streams)
303
+ // Still stream all collections automatically but you can override them
304
+ }):
305
+
292
306
  MongoRealtime.addListStream("posts", "posts", (doc) => !!doc.title); // client can listen to db:stream:posts
293
307
  MongoRealtime.addListStream("users", "users", (doc) => !!doc.email); // will not throw an error
294
308
  ```
package/index.js CHANGED
@@ -51,6 +51,8 @@ class MongoRealtime {
51
51
  /** @type {[String]} - All DB collections */
52
52
  static collections = [];
53
53
 
54
+ static #safeListStream = true;
55
+
54
56
  /**
55
57
  * Initializes the socket system.
56
58
  *
@@ -64,6 +66,7 @@ class MongoRealtime {
64
66
  * @param {[String]} options.autoListStream - Collections to stream automatically. If empty, will stream no collection. If null, will stream all collections.
65
67
  * @param {[String]} options.watch - Collections to watch. If empty, will watch all collections
66
68
  * @param {[String]} options.ignore - Collections to ignore. Can override `watch`
69
+ * @param {bool} options.safeListStream - If true(default), declaring an existing streamId will throw an error
67
70
  *
68
71
  */
69
72
  static init({
@@ -74,12 +77,14 @@ class MongoRealtime {
74
77
  autoListStream,
75
78
  onSocket,
76
79
  offSocket,
80
+ safeListStream = true,
77
81
  watch = [],
78
82
  ignore = [],
79
83
  }) {
80
84
  if (this.io) this.io.close();
81
85
  this.io = new Server(server);
82
86
  this.connection = connection;
87
+ this.#safeListStream = !!safeListStream;
83
88
 
84
89
  watch = watch.map((s) => s.toLowerCase());
85
90
  ignore = ignore.map((s) => s.toLowerCase());
@@ -111,6 +116,27 @@ class MongoRealtime {
111
116
  this.io.on("connection", (socket) => {
112
117
  if (onSocket) onSocket(socket);
113
118
 
119
+ socket.on("db:stream[register]", async (streamId, registerId) => {
120
+ const stream = this.#streams[streamId];
121
+ if (!stream) return;
122
+ const coll = stream.collection;
123
+
124
+ if (!this.#cache[coll]) {
125
+ this.#cache[coll] = await connection.db
126
+ .collection(coll)
127
+ .find({})
128
+ .toArray();
129
+ }
130
+ const filterResults = await Promise.allSettled(
131
+ this.#cache[coll].map((doc) => stream.filter(doc))
132
+ );
133
+
134
+ const filtered = this.#cache[coll].filter(
135
+ (_, i) => filterResults[i] && filterResults[i].value
136
+ );
137
+ this.io.emit(`db:stream[register][${registerId}]`, filtered);
138
+ });
139
+
114
140
  socket.on("disconnect", (r) => {
115
141
  if (offSocket) offSocket(socket, r);
116
142
  });
@@ -199,7 +225,6 @@ class MongoRealtime {
199
225
 
200
226
  this.io.emit(`db:stream:${key}`, filtered);
201
227
  this.notifyListeners(`db:stream:${key}`, filtered);
202
-
203
228
  });
204
229
  });
205
230
 
@@ -275,7 +300,7 @@ class MongoRealtime {
275
300
  if (!collection) throw new Error("Collection is required");
276
301
 
277
302
  filter ??= (_, __) => true;
278
- if (this.#streams[streamId]) {
303
+ if (this.#safeListStream && this.#streams[streamId]) {
279
304
  throw new Error(
280
305
  `Stream '${streamId}' already registered or is reserved.`
281
306
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongo-realtime",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "main": "index.js",
5
5
  "scripts": {},
6
6
  "keywords": [