relayx-js 1.0.6 → 1.0.7

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/CHANGELOG.md CHANGED
@@ -0,0 +1,3 @@
1
+ V1.0.7
2
+ - History API added
3
+ - README updated to explain history API usage
package/README.md CHANGED
@@ -65,21 +65,43 @@ Unsubscribe from a topic:<br>
65
65
  console.log("Unable to unsubscribe from power_telemetry");
66
66
  }
67
67
  ```
68
- 4. <b>Valid Topic Check</b><br>
68
+ 4. <b>History</b><br>
69
+ Get previously published messages between a start date and end date
70
+ ```javascript
71
+ var start = new Date();
72
+ var past = start.setDate(start.getDate() - 4) // Get start date from 4 days ago
73
+ var startDate = new Date(past)
74
+
75
+ var end = new Date();
76
+ var past = end.setDate(end.getDate() - 2) // Get end date from 2 days ago
77
+ var endDate = new Date(past)
78
+
79
+ var history = await realtime.history(topic, startDate, endDate)
80
+ ```
81
+ The end date is optional. Supplying only the start time will fetch all messages from the start time to now.
82
+ ```javascript
83
+ var start = new Date();
84
+ var past = start.setDate(start.getDate() - 4) // Get start date from 4 days ago
85
+ var startDate = new Date(past)
86
+
87
+ // This will get all messages from 4 days ago to now
88
+ var history = await realtime.history(topic, startDate)
89
+ ```
90
+ 5. <b>Valid Topic Check</b><br>
69
91
  Utility function to check if a particular topic is valid
70
92
  ```javascript
71
93
  var isValid = realtime.isTopicValid("topic");
72
94
 
73
95
  console.log(`Topic Valid => ${isValid}`);
74
96
  ```
75
- 5. <b>Sleep</b><br>
97
+ 6. <b>Sleep</b><br>
76
98
  Utility async function to delay code execution
77
99
  ```javascript
78
100
  console.log("Starting code execution...");
79
101
  await realtime.sleep(2000) // arg is in ms
80
102
  console.log("This line executed after 2 seconds");
81
103
  ```
82
- 6. <b>Close Connection to Relay</b><br>
104
+ 7. <b>Close Connection to Relay</b><br>
83
105
  Manually disconnect from the Relay Network
84
106
  ```javascript
85
107
  // Logic here
@@ -148,9 +170,16 @@ Subscribes to a topic. This is an async function.
148
170
  Deletes reference to user defined event callback for a topic. This will stop listening to a topic. This is an async function.
149
171
  * @param {string} topic
150
172
  * @returns {boolean} - To check if topic unsubscribe was successful
151
- 4. isTopicValid()<br>
173
+ 4. history()<br>
174
+ Get a list of messages published in the past. This is an async function.<br>
175
+ A list of messages can be obtained using a start time and end time. End time is optional. If end time is not specified, all messages from the start time to now is returned.
176
+ * @param {string} topic
177
+ * @param {Date} start
178
+ * @param {Date} end
179
+ * @returns {JSON Array} - List of messages published in the past
180
+ 5. isTopicValid()<br>
152
181
  Checks if a topic can be used to send messages to.
153
182
  * @param {string} topic - Name of event
154
183
  * @returns {boolean} - If topic is valid or not
155
- 5. sleep()<br>
184
+ 6. sleep()<br>
156
185
  Pauses code execution for a user defined time. Time passed into the method is in milliseconds. This is an async function.
@@ -51,10 +51,18 @@ async function run(){
51
51
 
52
52
  process.exit();
53
53
  }else if(input == "history"){
54
- var since = Date.now() - 1 * 60 * 60 * 1000; // 1 hour ago
54
+ rl.question("topic: ", async (topic) => {
55
+ var start = new Date();
56
+ var past = start.setDate(start.getDate() - 4)
57
+ var pastDate = new Date(past)
58
+
59
+ var end = new Date();
60
+ var past = end.setDate(end.getDate() - 2)
61
+ var endDate = new Date(past)
55
62
 
56
- var history = await realtime.history.getMessagesSince("hello", since, 1, 1000);
57
- console.log(history);
63
+ var history = await realtime.history(topic, pastDate, endDate)
64
+ console.log(history)
65
+ })
58
66
  }else if(input == "off"){
59
67
  rl.question("topic to off(): ", async (topic) => {
60
68
  await realtime.off(topic);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relayx-js",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "main": "realtime/realtime.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -1,4 +1,3 @@
1
- import { History } from "./history.js";
2
1
  import axios from 'axios';
3
2
  import { connect, JSONCodec, Events, DebugEvents, AckPolicy, ReplayPolicy, credsAuthenticator } from "nats";
4
3
  import { DeliverPolicy, jetstream, jetstreamManager } from "@nats-io/jetstream";
@@ -37,9 +36,6 @@ export class Realtime {
37
36
  // Offline messages
38
37
  #offlineMessageBuffer = [];
39
38
 
40
- // History API
41
- history = null;
42
-
43
39
  // Test Variables
44
40
  #timeout = 1000;
45
41
 
@@ -451,6 +447,86 @@ export class Realtime {
451
447
  }
452
448
  }
453
449
 
450
+ /**
451
+ * Starts consumer for particular topic if stream exists
452
+ * @param {string} topic
453
+ */
454
+ async history(topic, start, end){
455
+ this.#log(start)
456
+ if(topic == null || topic == undefined){
457
+ throw new Error("$topic is null or undefined");
458
+ }
459
+
460
+ if(topic == ""){
461
+ throw new Error("$topic cannot be an empty string")
462
+ }
463
+
464
+ if(typeof topic !== "string"){
465
+ throw new Error(`Expected $topic type -> string. Instead receieved -> ${typeof topic}`);
466
+ }
467
+
468
+ if(start == undefined || start == null){
469
+ throw new Error(`$start must be provided. $start is => ${start}`)
470
+ }
471
+
472
+ if(!(start instanceof Date)){
473
+ throw new Error(`$start must be a Date object`)
474
+ }
475
+
476
+ if(end != undefined && end != null){
477
+ if(!(end instanceof Date)){
478
+ throw new Error(`$end must be a Date object`)
479
+ }
480
+
481
+ if(start > end){
482
+ throw new Error("$start is greater than $end, must be before $end")
483
+ }
484
+
485
+ end = end.toISOString();
486
+ }
487
+
488
+ await this.#createOrGetStream();
489
+
490
+ var opts = {
491
+ name: topic,
492
+ filter_subjects: [this.#getStreamTopic(topic)],
493
+ replay_policy: ReplayPolicy.Instant,
494
+ opt_start_time: start,
495
+ ack_policy: AckPolicy.Explicit,
496
+ }
497
+
498
+ const consumer = await this.#jetstream.consumers.get(this.#getStreamName(), opts);
499
+ this.#log(this.#topicMap)
500
+ this.#log("Consumer is consuming");
501
+
502
+ this.#consumerMap[topic] = consumer;
503
+
504
+ const msgs = await consumer.fetch({
505
+ expires: 10000
506
+ });
507
+
508
+ var history = [];
509
+
510
+ for await (const m of msgs){
511
+ m.ack();
512
+
513
+ if(end != null || end != undefined){
514
+ if(m.timestamp > end){
515
+ break
516
+ }
517
+ }
518
+
519
+ var data = m.json();
520
+ history.push(data.message);
521
+ }
522
+
523
+ var del = await consumer.delete();
524
+
525
+ this.#log("History pull done", del)
526
+
527
+ return history;
528
+ }
529
+
454
530
  /**
455
531
  * Method resends messages when the client successfully connects to the
456
532
  * server again
@@ -510,7 +586,6 @@ export class Realtime {
510
586
  callback: (msg) => {
511
587
 
512
588
  msg.ack();
513
-
514
589
  try{
515
590
  var data = this.#codec.decode(msg.data);
516
591
  var room = data.room;
package/tests/test.js CHANGED
@@ -370,9 +370,10 @@ test("off() test", async () => {
370
370
  new Error("Expected $topic type -> string. Instead receieved -> number"),
371
371
  "Expected error was not thrown");
372
372
 
373
+ // Turning off topic multiple times to check for crashes.
374
+ // Since it is off already, output will be false
373
375
  var status = await realtime.off("hello");
374
-
375
- assert.strictEqual(status, true)
376
+ assert.strictEqual(status, false)
376
377
 
377
378
  var eventFunc = realtime.testGetEventMap();
378
379
  var topicMap = realtime.testGetTopicMap();
@@ -382,11 +383,6 @@ test("off() test", async () => {
382
383
  assert.strictEqual(eventFunc["hello"], undefined)
383
384
  assert.strictEqual(consumerMap["hello"], undefined)
384
385
 
385
- // Turning off topic multiple times to check for crashes.
386
- // Since it is off already, output will be false
387
- var status = await realtime.off("hello");
388
- assert.strictEqual(status, false)
389
-
390
386
  var status = await realtime.off("hello");
391
387
  assert.strictEqual(status, false)
392
388
 
@@ -456,4 +452,75 @@ test("Test isTopicValidMethod()", () => {
456
452
  var valid = realTimeEnabled.isTopicValid(topic);
457
453
  assert.strictEqual(valid, true);
458
454
  });
459
- });
455
+ });
456
+
457
+ test("History test", async () => {
458
+ await assert.rejects(async () => {
459
+ await realTimeEnabled.history(null);
460
+ },
461
+ new Error("$topic is null or undefined"),
462
+ "Expected error was not thrown");
463
+
464
+ await assert.rejects(async () => {
465
+ await realTimeEnabled.history(undefined);
466
+ },
467
+ new Error("$topic is null or undefined"),
468
+ "Expected error was not thrown");
469
+
470
+ await assert.rejects(async () => {
471
+ await realTimeEnabled.history("");
472
+ },
473
+ new Error("$topic cannot be an empty string"),
474
+ "Expected error was not thrown");
475
+
476
+ await assert.rejects(async () => {
477
+ await realTimeEnabled.history(1234);
478
+ },
479
+ new Error("Expected $topic type -> string. Instead receieved -> number"),
480
+ "Expected error was not thrown");
481
+
482
+ await assert.rejects(async () => {
483
+ await realTimeEnabled.history("hello", null);
484
+ },
485
+ new Error("$start must be provided. $start is => null"),
486
+ "Expected error was not thrown");
487
+
488
+ await assert.rejects(async () => {
489
+ await realTimeEnabled.history("hello", undefined);
490
+ },
491
+ new Error("$start must be provided. $start is => undefined"),
492
+ "Expected error was not thrown");
493
+
494
+ await assert.rejects(async () => {
495
+ await realTimeEnabled.history("hello", "undefined");
496
+ },
497
+ new Error("$start must be a Date object"),
498
+ "Expected error was not thrown");
499
+
500
+ await assert.rejects(async () => {
501
+ await realTimeEnabled.history("hello", 1234);
502
+ },
503
+ new Error("$start must be a Date object"),
504
+ "Expected error was not thrown");
505
+
506
+ await assert.rejects(async () => {
507
+ await realTimeEnabled.history("hello", {});
508
+ },
509
+ new Error("$start must be a Date object"),
510
+ "Expected error was not thrown");
511
+
512
+ await realTimeEnabled.history("hello", new Date());
513
+
514
+ await realTimeEnabled.history("hello", new Date(), new Date());
515
+
516
+ var start = new Date();
517
+ var past = start.setDate(start.getDate() - 4)
518
+ var pastDate = new Date(past)
519
+
520
+ var end = new Date();
521
+ var past = end.setDate(end.getDate() - 2)
522
+ var endDate = new Date(past)
523
+
524
+ var history = await realTimeEnabled.history("hello", pastDate, endDate)
525
+ assert.strictEqual(history.length > 0, true)
526
+ })