mongo-realtime 2.0.3 → 2.0.4
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/index.js +87 -112
- package/package.json +4 -4
package/index.js
CHANGED
|
@@ -41,7 +41,7 @@ class MongoRealtime {
|
|
|
41
41
|
/**@type {Record<String, {collection:String,filter: (doc:Object)=>Promise<boolean>}>} */
|
|
42
42
|
static #streams = {};
|
|
43
43
|
|
|
44
|
-
/**@type {Record<String,
|
|
44
|
+
/**@type {Record<String, Record<String,{}>>} */
|
|
45
45
|
static #data = {};
|
|
46
46
|
|
|
47
47
|
/** @type {[String]} - All DB collections */
|
|
@@ -51,6 +51,13 @@ class MongoRealtime {
|
|
|
51
51
|
|
|
52
52
|
static version = version;
|
|
53
53
|
|
|
54
|
+
static #resolvePromise;
|
|
55
|
+
static #rejectPromise;
|
|
56
|
+
|
|
57
|
+
static get(coll) {
|
|
58
|
+
return Object.values(this.#data[coll] ?? {});
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
static #check(fn, err) {
|
|
55
62
|
const result = fn();
|
|
56
63
|
if (!result) {
|
|
@@ -138,6 +145,11 @@ class MongoRealtime {
|
|
|
138
145
|
cacheDelay = 5,
|
|
139
146
|
allowDbOperations = true,
|
|
140
147
|
}) {
|
|
148
|
+
const promise = new Promise((resolve, reject) => {
|
|
149
|
+
this.#resolvePromise = resolve;
|
|
150
|
+
this.#rejectPromise = reject;
|
|
151
|
+
});
|
|
152
|
+
|
|
141
153
|
this.#log(`MongoRealtime version (${this.version})`, 2);
|
|
142
154
|
|
|
143
155
|
if (this.io) this.io.close();
|
|
@@ -148,12 +160,12 @@ class MongoRealtime {
|
|
|
148
160
|
this.io = new Server(server);
|
|
149
161
|
this.connection.once("open", async () => {
|
|
150
162
|
this.collections = (await this.connection.listCollections()).map(
|
|
151
|
-
(c) => c.name
|
|
163
|
+
(c) => c.name,
|
|
152
164
|
);
|
|
153
165
|
this.#debugLog(
|
|
154
166
|
`${this.collections.length} collections found : ${this.collections.join(
|
|
155
|
-
", "
|
|
156
|
-
)}
|
|
167
|
+
", ",
|
|
168
|
+
)}`,
|
|
157
169
|
);
|
|
158
170
|
|
|
159
171
|
let pipeline = [];
|
|
@@ -184,11 +196,11 @@ class MongoRealtime {
|
|
|
184
196
|
if (autoStream == null) collectionsToStream = this.collections;
|
|
185
197
|
else
|
|
186
198
|
collectionsToStream = this.collections.filter((c) =>
|
|
187
|
-
autoStream.includes(c)
|
|
199
|
+
autoStream.includes(c),
|
|
188
200
|
);
|
|
189
201
|
for (let col of collectionsToStream) this.addStream(col, col);
|
|
190
202
|
this.#debugLog(
|
|
191
|
-
`Auto stream on collections : ${collectionsToStream.join(", ")}
|
|
203
|
+
`Auto stream on collections : ${collectionsToStream.join(", ")}`,
|
|
192
204
|
);
|
|
193
205
|
|
|
194
206
|
/** Emit listen events on change */
|
|
@@ -241,18 +253,17 @@ class MongoRealtime {
|
|
|
241
253
|
}
|
|
242
254
|
});
|
|
243
255
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
doc._id = id;
|
|
252
|
-
this.#data[k].result[id] = doc;
|
|
253
|
-
}
|
|
256
|
+
switch (change.operationType) {
|
|
257
|
+
case "delete":
|
|
258
|
+
delete this.#data[coll][id];
|
|
259
|
+
break;
|
|
260
|
+
default:
|
|
261
|
+
doc._id = id;
|
|
262
|
+
this.#data[coll][id] = doc;
|
|
254
263
|
}
|
|
255
264
|
});
|
|
265
|
+
|
|
266
|
+
this.#getAllData();
|
|
256
267
|
});
|
|
257
268
|
|
|
258
269
|
try {
|
|
@@ -305,100 +316,43 @@ class MongoRealtime {
|
|
|
305
316
|
|
|
306
317
|
const stream = this.#streams[streamId];
|
|
307
318
|
const coll = stream.collection;
|
|
308
|
-
|
|
309
|
-
const default_limit = 100;
|
|
310
|
-
limit ??= default_limit;
|
|
311
|
-
try {
|
|
312
|
-
limit = parseInt(limit);
|
|
313
|
-
} catch (_) {
|
|
314
|
-
limit = default_limit;
|
|
315
|
-
}
|
|
319
|
+
const data = this.#data[coll];
|
|
316
320
|
|
|
317
|
-
reverse = reverse == true;
|
|
318
321
|
registerId ??= "";
|
|
319
|
-
this.#debugLog(
|
|
320
|
-
|
|
321
|
-
);
|
|
322
|
-
|
|
323
|
-
let
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
cachedResult = this.#data[cachedKey];
|
|
343
|
-
|
|
344
|
-
const result = cachedResult
|
|
345
|
-
? Object.values(cachedResult.result)
|
|
346
|
-
: await this.connection.db
|
|
347
|
-
.collection(coll)
|
|
348
|
-
.find({
|
|
349
|
-
_id: {
|
|
350
|
-
$nin: ids,
|
|
351
|
-
},
|
|
352
|
-
})
|
|
353
|
-
.limit(limit)
|
|
354
|
-
.sort({ _id: reverse ? -1 : 1 })
|
|
355
|
-
.toArray();
|
|
356
|
-
|
|
357
|
-
ids.push(...result.map((d) => d._id));
|
|
358
|
-
|
|
359
|
-
const delayInMin = cacheDelay;
|
|
360
|
-
const expiration = new Date(now.getTime() + delayInMin * 60 * 1000);
|
|
361
|
-
const resultMap = result.reduce((acc, item) => {
|
|
362
|
-
item._id = item._id.toString();
|
|
363
|
-
acc[item._id] = item;
|
|
364
|
-
return acc;
|
|
365
|
-
}, {});
|
|
366
|
-
|
|
367
|
-
if (!cachedResult) {
|
|
368
|
-
this.#data[cachedKey] = {
|
|
369
|
-
expiration,
|
|
370
|
-
result: resultMap,
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
const filtered = (
|
|
375
|
-
await Promise.all(
|
|
376
|
-
result.map(async (doc) => {
|
|
377
|
-
try {
|
|
378
|
-
return {
|
|
379
|
-
doc,
|
|
380
|
-
ok: await stream.filter(doc),
|
|
381
|
-
};
|
|
382
|
-
} catch (e) {
|
|
383
|
-
return {
|
|
384
|
-
doc,
|
|
385
|
-
ok: false,
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
})
|
|
389
|
-
)
|
|
322
|
+
// this.#debugLog(
|
|
323
|
+
// `Socket '${socket.id}' registred for realtime '${coll}:${registerId}'. Limit ${limit}. Reversed ${reverse}`,
|
|
324
|
+
// );
|
|
325
|
+
|
|
326
|
+
let result = Object.values(data);
|
|
327
|
+
|
|
328
|
+
const filtered = (
|
|
329
|
+
await Promise.all(
|
|
330
|
+
result.map(async (doc) => {
|
|
331
|
+
try {
|
|
332
|
+
return {
|
|
333
|
+
doc,
|
|
334
|
+
ok: await stream.filter(doc),
|
|
335
|
+
};
|
|
336
|
+
} catch (e) {
|
|
337
|
+
return {
|
|
338
|
+
doc,
|
|
339
|
+
ok: false,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
}),
|
|
390
343
|
)
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
344
|
+
)
|
|
345
|
+
.filter((item) => item.ok)
|
|
346
|
+
.map((item) => item.doc);
|
|
347
|
+
|
|
348
|
+
limit ??= filtered.length;
|
|
349
|
+
for (let i = 0; i < filtered.length; i += limit) {
|
|
350
|
+
socket.emit(`realtime:${streamId}:${registerId}`, {
|
|
351
|
+
added: filtered.slice(i, i + limit),
|
|
396
352
|
removed: [],
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
} while (ids.length < total);
|
|
401
|
-
}
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
},
|
|
402
356
|
);
|
|
403
357
|
if (allowDbOperations) {
|
|
404
358
|
socket.on("realtime:count", async ({ coll, query }, ack) => {
|
|
@@ -416,7 +370,7 @@ class MongoRealtime {
|
|
|
416
370
|
"realtime:find",
|
|
417
371
|
async (
|
|
418
372
|
{ coll, query, limit, sortBy, project, one, skip, id },
|
|
419
|
-
ack
|
|
373
|
+
ack,
|
|
420
374
|
) => {
|
|
421
375
|
if (!coll) return ack(null);
|
|
422
376
|
const c = this.connection.db.collection(coll);
|
|
@@ -447,14 +401,14 @@ class MongoRealtime {
|
|
|
447
401
|
|
|
448
402
|
let cursor = c.find(query, options);
|
|
449
403
|
ack(await cursor.toArray());
|
|
450
|
-
}
|
|
404
|
+
},
|
|
451
405
|
);
|
|
452
406
|
|
|
453
407
|
socket.on(
|
|
454
408
|
"realtime:update",
|
|
455
409
|
async (
|
|
456
410
|
{ coll, query, limit, sortBy, project, one, skip, id, update },
|
|
457
|
-
ack
|
|
411
|
+
ack,
|
|
458
412
|
) => {
|
|
459
413
|
if (!coll || !notEmpty(update)) return ack(0);
|
|
460
414
|
const c = this.connection.db.collection(coll);
|
|
@@ -462,7 +416,7 @@ class MongoRealtime {
|
|
|
462
416
|
if (id) {
|
|
463
417
|
ack(
|
|
464
418
|
(await c.updateOne({ _id: toObjectId(id) }, update))
|
|
465
|
-
.modifiedCount
|
|
419
|
+
.modifiedCount,
|
|
466
420
|
);
|
|
467
421
|
return;
|
|
468
422
|
}
|
|
@@ -488,7 +442,7 @@ class MongoRealtime {
|
|
|
488
442
|
|
|
489
443
|
let cursor = await c.updateMany(query, update, options);
|
|
490
444
|
ack(cursor.modifiedCount);
|
|
491
|
-
}
|
|
445
|
+
},
|
|
492
446
|
);
|
|
493
447
|
}
|
|
494
448
|
|
|
@@ -499,7 +453,7 @@ class MongoRealtime {
|
|
|
499
453
|
if (onSocket) onSocket(socket);
|
|
500
454
|
});
|
|
501
455
|
|
|
502
|
-
|
|
456
|
+
return promise;
|
|
503
457
|
}
|
|
504
458
|
|
|
505
459
|
/**
|
|
@@ -516,6 +470,27 @@ class MongoRealtime {
|
|
|
516
470
|
}
|
|
517
471
|
}
|
|
518
472
|
|
|
473
|
+
static #getAllData() {
|
|
474
|
+
const total = this.collections.length;
|
|
475
|
+
for (let coll of this.collections) {
|
|
476
|
+
this.connection.db
|
|
477
|
+
.collection(coll)
|
|
478
|
+
.find()
|
|
479
|
+
.toArray()
|
|
480
|
+
.then((r) => {
|
|
481
|
+
this.#data[coll] = r.reduce((acc, doc) => {
|
|
482
|
+
acc[doc._id] = doc;
|
|
483
|
+
return acc;
|
|
484
|
+
}, {});
|
|
485
|
+
|
|
486
|
+
if (Object.keys(this.#data).length == total) {
|
|
487
|
+
this.#log(`Initialized`, 1);
|
|
488
|
+
this.#resolvePromise(this.#data);
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
519
494
|
/**
|
|
520
495
|
* Subscribe to an event
|
|
521
496
|
*
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongo-realtime",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"main": "index.js",
|
|
5
|
-
"scripts": {},
|
|
6
5
|
"keywords": [
|
|
7
6
|
"mongo",
|
|
8
7
|
"mongoose",
|
|
@@ -23,5 +22,6 @@
|
|
|
23
22
|
"chalk": "^4.1.2",
|
|
24
23
|
"mongoose": "^8.17.0",
|
|
25
24
|
"socket.io": "^4.8.1"
|
|
26
|
-
}
|
|
27
|
-
}
|
|
25
|
+
},
|
|
26
|
+
"scripts": {}
|
|
27
|
+
}
|