relayx-js 1.0.9 → 1.0.10

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.
@@ -8,10 +8,10 @@ const rl = readline.createInterface({
8
8
 
9
9
  async function run(){
10
10
  var realtime = new Realtime({
11
- api_key: "eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJhdWQiOiJOQVRTIiwibmFtZSI6IjY3ZmZhMWVkMzk0NDRlODMwOGIxMDBiNCIsInN1YiI6IlVENUtRN0hNU01IMlNVWklCTTNCU1IyMjdQNUw3NFZKVTNUS0tPMk5XT1U2Qkg2S0pEV0JCNEFNIiwibmF0cyI6eyJkYXRhIjotMSwicGF5bG9hZCI6LTEsInN1YnMiOi0xLCJwdWIiOnsiZGVueSI6WyI-Il19LCJzdWIiOnsiZGVueSI6WyI-Il19LCJvcmdfZGF0YSI6eyJvcmdfaWQiOiI2N2ZmYTFkMzRmMDQ5MTAzNGQ5ZWJiNzIiLCJvcmdfbmFtZSI6IlNwYWNlWCIsInZhbGlkaXR5X2tleSI6IjU3NjUyM2UwLWM3ZGMtNGVlMS04OTFjLTAzNTFmMDgxOTkzYyIsInJvbGUiOiJ1c2VyIiwicHJvamVjdF9pZCI6IjY3ZmZhMWVkMzk0NDRlODMwOGIxMDBiNCJ9LCJpc3N1ZXJfYWNjb3VudCI6IkFCMzczR0JSWkVMNEhLNUdXWkJNNFNVTEFLVUhZSTVNUE9UWVNKQUpCVVVNU01KT09XREhFMjVYIiwidHlwZSI6InVzZXIiLCJ2ZXJzaW9uIjoyfSwiaXNzIjoiQUIzNzNHQlJaRUw0SEs1R1daQk00U1VMQUtVSFlJNU1QT1RZU0pBSkJVVU1TTUpPT1dESEUyNVgiLCJpYXQiOjE3NDQ4MDYzOTQsImp0aSI6Im5ZczM4MEZxa1dnNis3eGl4Wnl6VjJWS0ZLSVFNOEJrOG9ESFFzTjdBcW1YaUNmd05HTnNkQnVNK21YMW8xN0dFM2YxeEJXSFFGU1VUSmFrTmN1MGNnPT0ifQ.FVRHylWkCyIN0Axed0Z-H2Zgfh3HjEHGkjWQfUe70O3hl3OQYkQa1Ka-IYilGPB2fpd272t3VJarMvF1e5OSCw",
12
- secret: "SUAC7MP5AIOVJJTV2DCKRQRVAANBETTVYP26O4YE2BXELFOCURXLMEX5YE"
11
+ api_key: process.env.user_key,
12
+ secret: process.env.secret
13
13
  });
14
- await realtime.init(true, {
14
+ await realtime.init(false, {
15
15
  max_retries: 2,
16
16
  debug: true
17
17
  });
@@ -32,8 +32,8 @@ async function run(){
32
32
  console.log("power-telemetry", data);
33
33
  });
34
34
 
35
- await realtime.on("hello1", (data) => {
36
- console.log("hello1", data);
35
+ await realtime.on("test232", (data) => {
36
+ console.log("test232", data);
37
37
  });
38
38
 
39
39
  realtime.on(MESSAGE_RESEND, (data) => {
@@ -57,11 +57,11 @@ async function run(){
57
57
  var pastDate = new Date(past)
58
58
 
59
59
  var end = new Date();
60
- var past = end.setDate(end.getDate() - 2)
60
+ var past = end.setDate(end.getDate())
61
61
  var endDate = new Date(past)
62
62
 
63
- var history = await realtime.history(topic, pastDate, endDate)
64
- // console.log(history)
63
+ var history = await realtime.history(topic, pastDate)
64
+ console.log(history)
65
65
  })
66
66
  }else if(input == "off"){
67
67
  rl.question("topic to off(): ", async (topic) => {
@@ -83,9 +83,7 @@ async function run(){
83
83
  })
84
84
  }else{
85
85
  rl.question("topic: ", async (topic) => {
86
- var output = await realtime.publish(topic, {
87
- "data": input
88
- });
86
+ var output = await realtime.publish(topic, input);
89
87
  })
90
88
  }
91
89
  });
@@ -2,8 +2,8 @@ import { Realtime, CONNECTED, RECONNECT, DISCONNECTED, MESSAGE_RESEND } from "..
2
2
 
3
3
  async function run(){
4
4
  var realtime = new Realtime({
5
- api_key: "eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJhdWQiOiJOQVRTIiwibmFtZSI6IjY3ZmY5OGEwMTQ4NTgwYTcwY2U4ZThjMiIsInN1YiI6IlVBRlc1MkU0TEZDNERSSDI2M0M3SUlNS1ZTWU1WU1hYTjZSMkxMUDNBUVI0RExIQTI1WFc1RlpZIiwibmF0cyI6eyJkYXRhIjotMSwicGF5bG9hZCI6LTEsInN1YnMiOi0xLCJwdWIiOnsiZGVueSI6WyI-Il19LCJzdWIiOnsiZGVueSI6WyI-Il19LCJvcmdfZGF0YSI6eyJvcmdfaWQiOiI2N2ZmOTg3YzE1NDU5ZDc3MTAzMDVlY2IiLCJvcmdfbmFtZSI6IlNwYWNlWCIsInZhbGlkaXR5X2tleSI6IjY1NWU3N2ZhLTgxZTEtNDNhOS1hZTdhLWIyODA0M2MxNGFjMSIsInJvbGUiOiJ1c2VyIiwicHJvamVjdF9pZCI6IjY3ZmY5OGEwMTQ4NTgwYTcwY2U4ZThjMiJ9LCJpc3N1ZXJfYWNjb3VudCI6IkFCMzczR0JSWkVMNEhLNUdXWkJNNFNVTEFLVUhZSTVNUE9UWVNKQUpCVVVNU01KT09XREhFMjVYIiwidHlwZSI6InVzZXIiLCJ2ZXJzaW9uIjoyfSwiaXNzIjoiQUIzNzNHQlJaRUw0SEs1R1daQk00U1VMQUtVSFlJNU1QT1RZU0pBSkJVVU1TTUpPT1dESEUyNVgiLCJpYXQiOjE3NDQ4MDQwOTYsImp0aSI6Im5SdnRiUkhFWEtZVjhQRXoxeXhZQjFMRUVHNkU0ZlRndCs3cmZRWGdEZUNGM1ZSNXlsbGFiR3ZsaWxBSGR6dThkeXQvM3lxcVl3MDg1eUhSS1ZHT1R3PT0ifQ.tGj1iL8537ttVqQlTrW3qLrpYOb19I5VFZYurEltIA2aKgRrFLhz08qRtO1tm-GKVwgonM_10P_Aj1MnhzbeCw",
6
- secret: "SUALQKYAGDY6HHMW7NCHMKV6RAWSZPS2USQD6MIWIZWW6DATMSZ7MOCLUM"
5
+ api_key: process.env.user_key,
6
+ secret: process.env.secret
7
7
  });
8
8
  await realtime.init(true, {
9
9
  max_retries: 2,
@@ -16,19 +16,13 @@ async function run(){
16
16
  for (let angle = 0; angle <= 18000; angle++){
17
17
 
18
18
  var value = Math.floor(Math.random() * (100 + 1))
19
- // console.log(value)
20
-
21
- // await realtime.publish("test-power", {
22
- // "value": value,
23
- // "time": Date.now() + 2000
24
- // })
25
19
 
26
20
  var sent = await realtime.publish("power-telemetry", {
27
21
  "value": value,
28
22
  "time": Date.now()
29
23
  });
30
24
 
31
- // console.log(`Message sent => ${sent}`);
25
+ console.log(`Message sent => ${sent}`);
32
26
 
33
27
  await realtime.sleep(100)
34
28
  }
package/package.json CHANGED
@@ -1,20 +1,28 @@
1
1
  {
2
2
  "name": "relayx-js",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "main": "realtime/realtime.js",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "test": "NODE_ENV=test node tests/test.js"
8
8
  },
9
- "keywords": ["realtime", "realtime-communication", "relay", "relay-x", "relay-x-js"],
9
+ "keywords": [
10
+ "realtime",
11
+ "realtime-communication",
12
+ "relay",
13
+ "relay-x",
14
+ "relay-x-js"
15
+ ],
10
16
  "author": "Relay",
11
17
  "license": "Apache 2.0",
12
18
  "description": "A powerful library for integrating real-time communication into your software stack, powered by the Relay Network.",
13
19
  "dependencies": {
20
+ "@msgpack/msgpack": "^3.1.1",
14
21
  "@nats-io/jetstream": "^3.0.0-35",
15
- "axios": "1.7.7",
22
+ "axios": "^1.8.4",
16
23
  "jest": "^29.7.0",
17
- "nats": "^2.28.2"
24
+ "nats": "^2.28.2",
25
+ "uuid": "^11.1.0"
18
26
  },
19
27
  "devDependencies": {
20
28
  "@babel/core": "^7.26.0",
@@ -1,7 +1,8 @@
1
1
  import axios from 'axios';
2
2
  import { connect, JSONCodec, Events, DebugEvents, AckPolicy, ReplayPolicy, credsAuthenticator } from "nats";
3
- import { DeliverPolicy, jetstream, jetstreamManager } from "@nats-io/jetstream";
4
- import { readFileSync } from "fs"
3
+ import { DeliverPolicy, jetstream } from "@nats-io/jetstream";
4
+ import { encode, decode } from "@msgpack/msgpack";
5
+ import { v4 as uuidv4 } from 'uuid';
5
6
 
6
7
  export class Realtime {
7
8
 
@@ -10,8 +11,6 @@ export class Realtime {
10
11
  #natsClient = null;
11
12
  #codec = JSONCodec();
12
13
  #jetstream = null;
13
- #jsManager = null;
14
- #streamTracker = [];
15
14
  #consumerMap = {};
16
15
 
17
16
  #event_func = {};
@@ -36,9 +35,6 @@ export class Realtime {
36
35
  // Offline messages
37
36
  #offlineMessageBuffer = [];
38
37
 
39
- // Test Variables
40
- #timeout = 1000;
41
-
42
38
  #maxPublishRetries = 5;
43
39
 
44
40
  constructor(config){
@@ -62,6 +58,7 @@ export class Realtime {
62
58
  }
63
59
 
64
60
  this.namespace = null;
61
+ this.topicHash = null;
65
62
  }
66
63
 
67
64
  /*
@@ -161,8 +158,10 @@ export class Realtime {
161
158
 
162
159
  if(data["status"] == "NAMESPACE_RETRIEVE_SUCCESS"){
163
160
  this.namespace = data["data"]["namespace"]
161
+ this.topicHash = data["data"]["hash"]
164
162
  }else{
165
163
  this.namespace = null;
164
+ this.topicHash = null;
166
165
  return
167
166
  }
168
167
  }
@@ -189,7 +188,6 @@ export class Realtime {
189
188
  token: this.api_key,
190
189
  });
191
190
 
192
- this.#jsManager = await jetstreamManager(this.#natsClient);
193
191
  this.#jetstream = await jetstream(this.#natsClient);
194
192
 
195
193
  await this.#getNameSpace()
@@ -225,7 +223,6 @@ export class Realtime {
225
223
  this.#log(`client disconnected - ${s.data}`);
226
224
 
227
225
  this.connected = false;
228
- this.#streamTracker = [];
229
226
  this.#consumerMap = {};
230
227
 
231
228
  if (DISCONNECTED in this.#event_func){
@@ -248,8 +245,6 @@ export class Realtime {
248
245
  this.reconnecting = false;
249
246
  this.connected = true;
250
247
 
251
- // this.#subscribeToTopics();
252
-
253
248
  if(RECONNECT in this.#event_func){
254
249
  this.#event_func[RECONNECT](this.#RECONNECTED);
255
250
  }
@@ -418,13 +413,12 @@ export class Realtime {
418
413
  "start": Date.now()
419
414
  }
420
415
 
421
- var encodedMessage = this.#codec.encode(message)
416
+ this.#log("Encoding message via msg pack...")
417
+ var encodedMessage = encode(message);
422
418
 
423
419
  if(this.connected){
424
420
  if(!this.#topicMap.includes(topic)){
425
421
  this.#topicMap.push(topic);
426
-
427
- await this.#createOrGetStream();
428
422
  }else{
429
423
  this.#log(`${topic} exists locally, moving on...`)
430
424
  }
@@ -487,12 +481,8 @@ export class Realtime {
487
481
  end = end.toISOString();
488
482
  }
489
483
 
490
- console.log(`END => ${end}`)
491
-
492
- await this.#createOrGetStream();
493
-
494
484
  var opts = {
495
- name: topic,
485
+ name: `${topic}_${uuidv4()}_history`,
496
486
  filter_subjects: [this.#getStreamTopic(topic)],
497
487
  replay_policy: ReplayPolicy.Instant,
498
488
  opt_start_time: start,
@@ -503,30 +493,33 @@ export class Realtime {
503
493
  this.#log(this.#topicMap)
504
494
  this.#log("Consumer is consuming");
505
495
 
506
- this.#consumerMap[topic] = consumer;
507
-
508
- const msgs = await consumer.consume();
509
-
510
496
  var history = [];
511
497
 
512
- for await (const m of msgs){
513
- m.ack();
498
+ while(true){
499
+ var msg = await consumer.next({
500
+ expires: 1000
501
+ });
502
+
503
+ if(msg == null){
504
+ break;
505
+ }
514
506
 
515
507
  if(end != null || end != undefined){
516
- if(m.timestamp > end){
508
+ if(msg.timestamp > end){
517
509
  break
518
510
  }
519
511
  }
520
512
 
521
- console.log(m.timestamp)
522
-
523
- var data = m.json();
513
+ this.#log("Decoding msgpack message...")
514
+ var data = decode(msg.data);
515
+ this.#log(data);
516
+
524
517
  history.push(data.message);
525
518
  }
526
519
 
527
520
  var del = await consumer.delete();
528
521
 
529
- this.#log("History pull done", del)
522
+ this.#log("History pull done: " + del);
530
523
 
531
524
  return history;
532
525
  }
@@ -569,10 +562,8 @@ export class Realtime {
569
562
  * @param {string} topic
570
563
  */
571
564
  async #startConsumer(topic){
572
- await this.#createOrGetStream();
573
-
574
565
  var opts = {
575
- name: topic,
566
+ name: `${topic}_${uuidv4()}`,
576
567
  filter_subjects: [this.#getStreamTopic(topic), this.#getStreamTopic(topic) + "_presence"],
577
568
  replay_policy: ReplayPolicy.Instant,
578
569
  opt_start_time: new Date(),
@@ -587,11 +578,10 @@ export class Realtime {
587
578
 
588
579
  await consumer.consume({
589
580
  callback: (msg) => {
590
- console.log("TIMESTAMP", msg.info)
591
-
592
- msg.ack();
593
581
  try{
594
- var data = this.#codec.decode(msg.data);
582
+ this.#log("Decoding msgpack message...")
583
+ var data = decode(msg.data);
584
+
595
585
  var room = data.room;
596
586
 
597
587
  this.#log(data);
@@ -605,9 +595,11 @@ export class Realtime {
605
595
  "data": data.message
606
596
  });
607
597
  }
598
+
599
+ msg.ack();
608
600
  }catch(err){
609
601
  this.#log("Consumer err " + err);
610
- msg.nack();
602
+ msg.nack(5000);
611
603
  }
612
604
  }
613
605
  });
@@ -634,40 +626,6 @@ export class Realtime {
634
626
  return del;
635
627
  }
636
628
 
637
- /**
638
- * Gets stream if it exists or creates one
639
- * @param {string} streamName
640
- */
641
- async #createOrGetStream(){
642
- const streamName = this.#getStreamName();
643
- var stream = null;
644
-
645
- try{
646
- stream = await this.#jsManager.streams.info(streamName);
647
- }catch(err){
648
- stream = null;
649
- }
650
-
651
- this.#log(`STREAM => ${stream}`)
652
-
653
- if (stream == null){
654
- // Stream does not exist, create one
655
- await this.#jsManager.streams.add({
656
- name: streamName,
657
- subjects: [...this.#getStreamTopicList(), ...this.#getPresenceTopics()],
658
- num_replicas: 3
659
- });
660
-
661
- this.#log(`${streamName} created`);
662
- }else{
663
- var subs = [...stream.config.subjects, ...this.#getStreamTopicList(), ...this.#getPresenceTopics()];
664
- stream.config.subjects = [...new Set(subs)];
665
- await this.#jsManager.streams.update(streamName, stream.config);
666
-
667
- this.#log(`${streamName} exists, updating and moving on...`);
668
- }
669
- }
670
-
671
629
  // Utility functions
672
630
  #getClientId(){
673
631
  return this.#natsClient?.info?.client_id
@@ -701,34 +659,14 @@ export class Realtime {
701
659
  }
702
660
 
703
661
  #getStreamTopic(topic){
704
- if(this.namespace != null){
705
- return this.namespace + "_stream_" + topic;
662
+ if(this.topicHash != null){
663
+ return this.topicHash + "." + topic;
706
664
  }else{
707
665
  this.close();
708
- throw new Error("$namespace is null. Cannot initialize program with null $namespace")
666
+ throw new Error("$topicHash is null. Cannot initialize program with null $topicHash")
709
667
  }
710
668
  }
711
669
 
712
- #getStreamTopicList(){
713
- var topics = [];
714
-
715
- this.#topicMap.forEach((topic) => {
716
- topics.push(this.#getStreamTopic(topic))
717
- })
718
-
719
- return topics
720
- }
721
-
722
- #getPresenceTopics(){
723
- var presence = [];
724
-
725
- this.#topicMap.forEach((topic) => {
726
- presence.push(this.#getStreamTopic(topic) + "_presence")
727
- })
728
-
729
- return presence
730
- }
731
-
732
670
  sleep(ms) {
733
671
  return new Promise(resolve => setTimeout(resolve, ms));
734
672
  }
package/tests/test.js CHANGED
@@ -116,6 +116,7 @@ test('init() function test', async () => {
116
116
 
117
117
  test("Namespace check test", async () => {
118
118
  assert.strictEqual(realTimeEnabled.namespace.length > 0, true)
119
+ assert.strictEqual(realTimeEnabled.topicHash.length > 0, true)
119
120
  });
120
121
 
121
122
  test("Retry method test", async () => {
@@ -401,17 +402,19 @@ test("Get stream name test", () => {
401
402
  });
402
403
 
403
404
  realtime.namespace = "spacex-dragon-program"
405
+ realtime.topicHash = "topic_hash";
404
406
 
405
407
  var getStreamName = realtime.testGetStreamName();
406
408
  var getStreamTopic = realtime.testGetStreamTopic();
407
409
 
408
410
  var name = getStreamName();
409
- assert.strictEqual(name, "spacex-dragon-program_stream")
411
+ assert.strictEqual(name, `${realtime.namespace}_stream`);
410
412
 
411
413
  var topic = getStreamTopic("hello_world")
412
- assert.strictEqual(topic, "spacex-dragon-program_stream_hello_world")
414
+ assert.strictEqual(topic, `${realtime.topicHash}.hello_world`)
413
415
 
414
416
  realtime.namespace = null;
417
+ realtime.topicHash = null;
415
418
 
416
419
  assert.throws(() => {
417
420
  getStreamName();
@@ -422,7 +425,7 @@ test("Get stream name test", () => {
422
425
  assert.throws(() => {
423
426
  getStreamTopic("hello_world");
424
427
  },
425
- new Error("$namespace is null. Cannot initialize program with null $namespace"),
428
+ new Error("$topicHash is null. Cannot initialize program with null $topicHash"),
426
429
  "Expected error was not thrown")
427
430
  });
428
431
 
@@ -508,19 +511,4 @@ test("History test", async () => {
508
511
  },
509
512
  new Error("$start must be a Date object"),
510
513
  "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
514
  })