relayx-webjs 1.0.0 → 1.0.2
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 +6 -5
- package/package.json +1 -1
- package/realtime/realtime.js +133 -29
- package/tests/test.js +158 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
V1.0.
|
|
2
|
-
-
|
|
1
|
+
V1.0.2
|
|
2
|
+
- Wildcard topics for pub / sub fixes
|
|
3
|
+
- Unit tests added for wildcard pattern matching
|
|
3
4
|
|
|
4
|
-
V1.0.
|
|
5
|
-
-
|
|
6
|
-
-
|
|
5
|
+
V1.0.1
|
|
6
|
+
- Wildcard topics for pub / sub
|
|
7
|
+
- Message replay on reconnection
|
package/package.json
CHANGED
package/realtime/realtime.js
CHANGED
|
@@ -11,6 +11,7 @@ export class Realtime {
|
|
|
11
11
|
#codec = JSONCodec();
|
|
12
12
|
#jetstream = null;
|
|
13
13
|
#consumerMap = {};
|
|
14
|
+
#consumer = null;
|
|
14
15
|
|
|
15
16
|
#event_func = {};
|
|
16
17
|
#topicMap = [];
|
|
@@ -223,7 +224,6 @@ export class Realtime {
|
|
|
223
224
|
this.#log(`client disconnected - ${s.data}`);
|
|
224
225
|
|
|
225
226
|
this.connected = false;
|
|
226
|
-
this.#consumerMap = {};
|
|
227
227
|
|
|
228
228
|
if (DISCONNECTED in this.#event_func){
|
|
229
229
|
if (this.#event_func[DISCONNECTED] !== null || this.#event_func[DISCONNECTED] !== undefined){
|
|
@@ -282,13 +282,15 @@ export class Realtime {
|
|
|
282
282
|
/**
|
|
283
283
|
* Closes connection
|
|
284
284
|
*/
|
|
285
|
-
close(){
|
|
285
|
+
async close(){
|
|
286
286
|
if(this.#natsClient !== null){
|
|
287
287
|
this.reconnected = false;
|
|
288
288
|
this.disconnected = true;
|
|
289
289
|
|
|
290
290
|
this.#offlineMessageBuffer.length = 0;
|
|
291
291
|
|
|
292
|
+
await this.#deleteConsumer();
|
|
293
|
+
|
|
292
294
|
this.#natsClient.close();
|
|
293
295
|
}else{
|
|
294
296
|
this.#log("Null / undefined socket, cannot close connection");
|
|
@@ -299,10 +301,9 @@ export class Realtime {
|
|
|
299
301
|
* Start consumers for topics initialized by user
|
|
300
302
|
*/
|
|
301
303
|
async #subscribeToTopics(){
|
|
302
|
-
this.#topicMap.
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
});
|
|
304
|
+
if(this.#topicMap.length > 0){
|
|
305
|
+
await this.#startConsumer();
|
|
306
|
+
}
|
|
306
307
|
}
|
|
307
308
|
|
|
308
309
|
/**
|
|
@@ -323,8 +324,6 @@ export class Realtime {
|
|
|
323
324
|
this.#topicMap = this.#topicMap.filter(item => item !== topic);
|
|
324
325
|
|
|
325
326
|
delete this.#event_func[topic];
|
|
326
|
-
|
|
327
|
-
return await this.#deleteConsumer(topic);
|
|
328
327
|
}
|
|
329
328
|
|
|
330
329
|
/**
|
|
@@ -467,6 +466,10 @@ export class Realtime {
|
|
|
467
466
|
throw new Error(`Expected $topic type -> string. Instead receieved -> ${typeof topic}`);
|
|
468
467
|
}
|
|
469
468
|
|
|
469
|
+
if(!this.isTopicValid(topic)){
|
|
470
|
+
throw new Error("Invalid topic, use isTopicValid($topic) to validate topic")
|
|
471
|
+
}
|
|
472
|
+
|
|
470
473
|
if(start == undefined || start == null){
|
|
471
474
|
throw new Error(`$start must be provided. $start is => ${start}`)
|
|
472
475
|
}
|
|
@@ -568,39 +571,49 @@ export class Realtime {
|
|
|
568
571
|
* @param {string} topic
|
|
569
572
|
*/
|
|
570
573
|
async #startConsumer(topic){
|
|
574
|
+
if(this.#consumer != null){
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
|
|
571
578
|
this.#log(`Starting consumer for topic: ${topic}_${uuidv4()}`)
|
|
572
579
|
|
|
573
580
|
var opts = {
|
|
574
|
-
name: `${
|
|
575
|
-
filter_subjects: [this.#getStreamTopic(
|
|
581
|
+
name: `${uuidv4()}`,
|
|
582
|
+
filter_subjects: [this.#getStreamTopic(">")],
|
|
576
583
|
replay_policy: ReplayPolicy.Instant,
|
|
577
584
|
opt_start_time: new Date(),
|
|
578
585
|
ack_policy: AckPolicy.Explicit,
|
|
579
586
|
delivery_policy: DeliverPolicy.New
|
|
580
587
|
}
|
|
581
588
|
|
|
582
|
-
|
|
589
|
+
this.#consumer = await this.#jetstream.consumers.get(this.#getStreamName(), opts);
|
|
583
590
|
this.#log(this.#topicMap)
|
|
584
591
|
|
|
585
|
-
this.#
|
|
586
|
-
|
|
587
|
-
await consumer.consume({
|
|
592
|
+
await this.#consumer.consume({
|
|
588
593
|
callback: async (msg) => {
|
|
589
594
|
try{
|
|
590
595
|
const now = Date.now();
|
|
591
596
|
this.#log("Decoding msgpack message...")
|
|
592
597
|
var data = decode(msg.data);
|
|
593
598
|
|
|
594
|
-
var room =
|
|
599
|
+
var room = this.#stripStreamHash(msg.subject);
|
|
595
600
|
|
|
596
601
|
this.#log(data);
|
|
597
602
|
|
|
598
603
|
// Push topic message to main thread
|
|
599
|
-
if (
|
|
600
|
-
this.#
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
+
if (data.client_id != this.#getClientId()){
|
|
605
|
+
var topics = this.#getCallbackTopics(room);
|
|
606
|
+
this.#log(topics)
|
|
607
|
+
|
|
608
|
+
for(let i = 0; i < topics.length; i++){
|
|
609
|
+
var top = topics[i];
|
|
610
|
+
|
|
611
|
+
this.#event_func[top]({
|
|
612
|
+
"id": data.id,
|
|
613
|
+
"topic": room,
|
|
614
|
+
"data": data.message
|
|
615
|
+
});
|
|
616
|
+
}
|
|
604
617
|
}
|
|
605
618
|
|
|
606
619
|
msg.ack();
|
|
@@ -608,7 +621,7 @@ export class Realtime {
|
|
|
608
621
|
await this.#logLatency(now, data);
|
|
609
622
|
}catch(err){
|
|
610
623
|
this.#log("Consumer err " + err);
|
|
611
|
-
msg.
|
|
624
|
+
msg.nak(5000);
|
|
612
625
|
}
|
|
613
626
|
}
|
|
614
627
|
});
|
|
@@ -619,19 +632,15 @@ export class Realtime {
|
|
|
619
632
|
* Deletes consumer
|
|
620
633
|
* @param {string} topic
|
|
621
634
|
*/
|
|
622
|
-
async #deleteConsumer(
|
|
623
|
-
const consumer = this.#consumerMap[topic]
|
|
624
|
-
|
|
635
|
+
async #deleteConsumer(){
|
|
625
636
|
var del = false;
|
|
626
637
|
|
|
627
|
-
if (consumer != null && consumer != undefined){
|
|
628
|
-
del = await consumer.delete();
|
|
638
|
+
if (this.#consumer != null && this.#consumer != undefined){
|
|
639
|
+
del = await this.#consumer.delete();
|
|
629
640
|
}else{
|
|
630
641
|
del = false
|
|
631
642
|
}
|
|
632
643
|
|
|
633
|
-
delete this.#consumerMap[topic];
|
|
634
|
-
|
|
635
644
|
return del;
|
|
636
645
|
}
|
|
637
646
|
|
|
@@ -734,7 +743,9 @@ export class Realtime {
|
|
|
734
743
|
var arrayCheck = ![CONNECTED, DISCONNECTED, RECONNECT, this.#RECONNECTED,
|
|
735
744
|
this.#RECONNECTING, this.#RECONN_FAIL, MESSAGE_RESEND, SERVER_DISCONNECT].includes(topic);
|
|
736
745
|
|
|
737
|
-
|
|
746
|
+
const TOPIC_REGEX = /^(?!.*\$)(?:[A-Za-z0-9_*~-]+(?:\.[A-Za-z0-9_*~-]+)*(?:\.>)?|>)$/u;
|
|
747
|
+
|
|
748
|
+
var spaceStarCheck = !topic.includes(" ") && TOPIC_REGEX.test(topic);
|
|
738
749
|
|
|
739
750
|
return arrayCheck && spaceStarCheck;
|
|
740
751
|
}else{
|
|
@@ -789,6 +800,91 @@ export class Realtime {
|
|
|
789
800
|
}
|
|
790
801
|
}
|
|
791
802
|
|
|
803
|
+
#stripStreamHash(topic){
|
|
804
|
+
return topic.replace(`${this.topicHash}.`, "")
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
#getCallbackTopics(topic){
|
|
808
|
+
var validTopics = [];
|
|
809
|
+
|
|
810
|
+
var topicPatterns = Object.keys(this.#event_func);
|
|
811
|
+
|
|
812
|
+
for(let i = 0; i < topicPatterns.length; i++){
|
|
813
|
+
var pattern = topicPatterns[i];
|
|
814
|
+
|
|
815
|
+
if([CONNECTED, RECONNECT, MESSAGE_RESEND, DISCONNECTED, SERVER_DISCONNECT].includes(pattern)){
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
var match = this.#topicPatternMatcher(pattern, topic);
|
|
820
|
+
|
|
821
|
+
if(match){
|
|
822
|
+
validTopics.push(pattern)
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
return validTopics;
|
|
827
|
+
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
#topicPatternMatcher(patternA, patternB) {
|
|
831
|
+
const a = patternA.split(".");
|
|
832
|
+
const b = patternB.split(".");
|
|
833
|
+
|
|
834
|
+
let i = 0, j = 0; // cursors in a & b
|
|
835
|
+
let starAi = -1, starAj = -1; // last '>' position in A and the token count it has consumed
|
|
836
|
+
let starBi = -1, starBj = -1; // same for pattern B
|
|
837
|
+
|
|
838
|
+
while (i < a.length || j < b.length) {
|
|
839
|
+
const tokA = a[i];
|
|
840
|
+
const tokB = b[j];
|
|
841
|
+
|
|
842
|
+
/*──────────── literal match or single‑token wildcard on either side ────────────*/
|
|
843
|
+
const singleWildcard =
|
|
844
|
+
(tokA === "*" && j < b.length) ||
|
|
845
|
+
(tokB === "*" && i < a.length);
|
|
846
|
+
|
|
847
|
+
if (
|
|
848
|
+
(tokA !== undefined && tokA === tokB) ||
|
|
849
|
+
singleWildcard
|
|
850
|
+
) {
|
|
851
|
+
i++; j++;
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
/*────────────────── multi‑token wildcard ">" — must be **final** ───────────────*/
|
|
856
|
+
if (tokA === ">") {
|
|
857
|
+
if (i !== a.length - 1) return false; // '>' not in last position → invalid
|
|
858
|
+
if (j >= b.length) return false; // must consume at least one token
|
|
859
|
+
starAi = i++; // remember where '>' is
|
|
860
|
+
starAj = ++j; // gobble one token from B
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
if (tokB === ">") {
|
|
864
|
+
if (j !== b.length - 1) return false; // same rule for patternB
|
|
865
|
+
if (i >= a.length) return false;
|
|
866
|
+
starBi = j++;
|
|
867
|
+
starBj = ++i;
|
|
868
|
+
continue;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
/*───────────────────────────── back‑track using last '>' ───────────────────────*/
|
|
872
|
+
if (starAi !== -1) { // let patternA's '>' absorb one more token of B
|
|
873
|
+
j = ++starAj;
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
876
|
+
if (starBi !== -1) { // let patternB's '>' absorb one more token of A
|
|
877
|
+
i = ++starBj;
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/*────────────────────────────────── dead‑end ───────────────────────────────────*/
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
return true;
|
|
886
|
+
}
|
|
887
|
+
|
|
792
888
|
sleep(ms) {
|
|
793
889
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
794
890
|
}
|
|
@@ -927,6 +1023,14 @@ ${secret}
|
|
|
927
1023
|
return null;
|
|
928
1024
|
}
|
|
929
1025
|
}
|
|
1026
|
+
|
|
1027
|
+
testPatternMatcher(){
|
|
1028
|
+
if(process.env.NODE_ENV == "test"){
|
|
1029
|
+
return this.#topicPatternMatcher.bind(this)
|
|
1030
|
+
}else{
|
|
1031
|
+
return null;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
930
1034
|
}
|
|
931
1035
|
|
|
932
1036
|
export const CONNECTED = "CONNECTED";
|
package/tests/test.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Realtime, CONNECTED, RECONNECT, DISCONNECTED, MESSAGE_RESEND } from "../realtime/realtime.js";
|
|
2
|
-
import axios from "axios";
|
|
3
2
|
import { test, before, after } from 'node:test';
|
|
4
3
|
import assert from 'node:assert';
|
|
5
4
|
|
|
@@ -8,8 +7,8 @@ let realTimeEnabled;
|
|
|
8
7
|
before(async () => {
|
|
9
8
|
// Start server for testing. Run local server!!
|
|
10
9
|
realTimeEnabled = new Realtime({
|
|
11
|
-
api_key: process.env.
|
|
12
|
-
secret: process.env.
|
|
10
|
+
api_key: process.env.AUTH_JWT,
|
|
11
|
+
secret: process.env.AUTH_SECRET
|
|
13
12
|
});
|
|
14
13
|
await realTimeEnabled.init(false, {
|
|
15
14
|
debug: true
|
|
@@ -55,8 +54,8 @@ test("No creds in constructor", async () => {
|
|
|
55
54
|
|
|
56
55
|
test('init() function test', async () => {
|
|
57
56
|
var realtime = new Realtime({
|
|
58
|
-
api_key: process.env.
|
|
59
|
-
secret: process.env.
|
|
57
|
+
api_key: process.env.AUTH_JWT,
|
|
58
|
+
secret: process.env.AUTH_SECRET
|
|
60
59
|
});
|
|
61
60
|
await realtime.init(true);
|
|
62
61
|
|
|
@@ -148,8 +147,8 @@ test("Retry method test", async () => {
|
|
|
148
147
|
|
|
149
148
|
test("get publish retry count test based in init()", async () => {
|
|
150
149
|
var realtime = new Realtime({
|
|
151
|
-
api_key: process.env.
|
|
152
|
-
secret: process.env.
|
|
150
|
+
api_key: process.env.AUTH_JWT,
|
|
151
|
+
secret: process.env.AUTH_SECRET
|
|
153
152
|
});
|
|
154
153
|
|
|
155
154
|
await realtime.init({
|
|
@@ -271,8 +270,8 @@ test("Testing publish(topic, data) with invalid inputs", async () => {
|
|
|
271
270
|
|
|
272
271
|
test("on() test", async () => {
|
|
273
272
|
var realtime = new Realtime({
|
|
274
|
-
api_key: process.env.
|
|
275
|
-
secret: process.env.
|
|
273
|
+
api_key: process.env.AUTH_JWT,
|
|
274
|
+
secret: process.env.AUTH_SECRET
|
|
276
275
|
});
|
|
277
276
|
|
|
278
277
|
await assert.rejects(async () => {
|
|
@@ -349,8 +348,8 @@ test("on() test", async () => {
|
|
|
349
348
|
|
|
350
349
|
test("off() test", async () => {
|
|
351
350
|
var realtime = new Realtime({
|
|
352
|
-
api_key: process.env.
|
|
353
|
-
secret: process.env.
|
|
351
|
+
api_key: process.env.AUTH_JWT,
|
|
352
|
+
secret: process.env.AUTH_SECRET
|
|
354
353
|
});
|
|
355
354
|
|
|
356
355
|
await assert.rejects(async () => {
|
|
@@ -397,8 +396,8 @@ test("off() test", async () => {
|
|
|
397
396
|
|
|
398
397
|
test("Get stream name test", () => {
|
|
399
398
|
var realtime = new Realtime({
|
|
400
|
-
api_key: process.env.
|
|
401
|
-
secret: process.env.
|
|
399
|
+
api_key: process.env.AUTH_JWT,
|
|
400
|
+
secret: process.env.AUTH_SECRET
|
|
402
401
|
});
|
|
403
402
|
|
|
404
403
|
realtime.namespace = "spacex-dragon-program"
|
|
@@ -449,10 +448,82 @@ test("Test isTopicValidMethod()", () => {
|
|
|
449
448
|
assert.strictEqual(valid, false);
|
|
450
449
|
});
|
|
451
450
|
|
|
452
|
-
|
|
451
|
+
unreservedInvalidTopics = [
|
|
452
|
+
"$foo",
|
|
453
|
+
"foo$",
|
|
454
|
+
"foo.$.bar",
|
|
455
|
+
"foo..bar",
|
|
456
|
+
".foo",
|
|
457
|
+
"foo.",
|
|
458
|
+
"foo.>.bar",
|
|
459
|
+
">foo",
|
|
460
|
+
"foo>bar",
|
|
461
|
+
"foo.>bar",
|
|
462
|
+
"foo.bar.>.",
|
|
463
|
+
"foo bar",
|
|
464
|
+
"foo/bar",
|
|
465
|
+
"foo#bar",
|
|
466
|
+
"",
|
|
467
|
+
" ",
|
|
468
|
+
"..",
|
|
469
|
+
".>",
|
|
470
|
+
"foo..",
|
|
471
|
+
".",
|
|
472
|
+
">.",
|
|
473
|
+
"foo,baz",
|
|
474
|
+
"αbeta",
|
|
475
|
+
"foo|bar",
|
|
476
|
+
"foo;bar",
|
|
477
|
+
"foo:bar",
|
|
478
|
+
"foo%bar",
|
|
479
|
+
"foo.*.>.bar",
|
|
480
|
+
"foo.*.>.",
|
|
481
|
+
"foo.*..bar",
|
|
482
|
+
"foo.>.bar",
|
|
483
|
+
"foo>"
|
|
484
|
+
];
|
|
485
|
+
|
|
486
|
+
unreservedInvalidTopics.forEach(topic => {
|
|
487
|
+
var valid = realTimeEnabled.isTopicValid(topic);
|
|
488
|
+
assert.strictEqual(valid, false);
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
var unreservedValidTopics = [
|
|
492
|
+
"foo",
|
|
493
|
+
"foo.bar",
|
|
494
|
+
"foo.bar.baz",
|
|
495
|
+
"*",
|
|
496
|
+
"foo.*",
|
|
497
|
+
"*.bar",
|
|
498
|
+
"foo.*.baz",
|
|
499
|
+
">",
|
|
500
|
+
"foo.>",
|
|
501
|
+
"foo.bar.>",
|
|
502
|
+
"*.*.>",
|
|
503
|
+
"alpha_beta",
|
|
504
|
+
"alpha-beta",
|
|
505
|
+
"alpha~beta",
|
|
506
|
+
"abc123",
|
|
507
|
+
"123abc",
|
|
508
|
+
"~",
|
|
509
|
+
"alpha.*.>",
|
|
510
|
+
"alpha.*",
|
|
511
|
+
"alpha.*.*",
|
|
512
|
+
"-foo",
|
|
513
|
+
"foo_bar-baz~qux",
|
|
514
|
+
"A.B.C",
|
|
515
|
+
"sensor.temperature",
|
|
516
|
+
"metric.cpu.load",
|
|
517
|
+
"foo.*.*",
|
|
518
|
+
"foo.*.>",
|
|
519
|
+
"foo_bar.*",
|
|
520
|
+
"*.*",
|
|
521
|
+
"metrics.>"
|
|
522
|
+
];
|
|
453
523
|
|
|
454
524
|
unreservedValidTopics.forEach(topic => {
|
|
455
525
|
var valid = realTimeEnabled.isTopicValid(topic);
|
|
526
|
+
console.log(topic)
|
|
456
527
|
assert.strictEqual(valid, true);
|
|
457
528
|
});
|
|
458
529
|
});
|
|
@@ -511,4 +582,77 @@ test("History test", async () => {
|
|
|
511
582
|
},
|
|
512
583
|
new Error("$start must be a Date object"),
|
|
513
584
|
"Expected error was not thrown");
|
|
585
|
+
})
|
|
586
|
+
|
|
587
|
+
test("Pattern matcher test", async () => {
|
|
588
|
+
var cases = [
|
|
589
|
+
["foo", "foo", true], // 1
|
|
590
|
+
["foo", "bar", false], // 2
|
|
591
|
+
["foo.*", "foo.bar", true], // 3
|
|
592
|
+
["foo.bar", "foo.*", true], // 4
|
|
593
|
+
["*", "token", true], // 5
|
|
594
|
+
["*", "*", true], // 6
|
|
595
|
+
["foo.*", "foo.bar.baz", false], // 7
|
|
596
|
+
["foo.>", "foo.bar.baz", true], // 8
|
|
597
|
+
["foo.>", "foo", false], // 9 (zero‑token '>' now invalid)
|
|
598
|
+
["foo.bar.baz", "foo.>", true], // 10
|
|
599
|
+
["foo.bar.>", "foo.bar", false], // 11
|
|
600
|
+
["foo", "foo.>", false], // 12
|
|
601
|
+
["foo.*.>", "foo.bar.baz.qux", true], // 13
|
|
602
|
+
["foo.*.baz", "foo.bar.>", true], // 14
|
|
603
|
+
["alpha.*", "beta.gamma", false], // 15
|
|
604
|
+
["alpha.beta", "alpha.*.*", false], // 16
|
|
605
|
+
["foo.>.bar", "foo.any.bar", false], // 17 ('>' mid‑pattern)
|
|
606
|
+
[">", "foo.bar", true], // 18
|
|
607
|
+
[">", ">", true], // 19
|
|
608
|
+
["*", ">", true], // 20
|
|
609
|
+
["*.>", "foo.bar", true], // 21
|
|
610
|
+
["*.*.*", "a.b.c", true], // 22
|
|
611
|
+
["*.*.*", "a.b", false], // 23
|
|
612
|
+
["a.b.c.d.e", "a.b.c.d.e", true], // 24
|
|
613
|
+
["a.b.c.d.e", "a.b.c.d.f", false], // 25
|
|
614
|
+
["a.b.*.d", "a.b.c.d", true], // 26
|
|
615
|
+
["a.b.*.d", "a.b.c.e", false], // 27
|
|
616
|
+
["a.b.>", "a.b", false], // 28
|
|
617
|
+
["a.b", "a.b.c.d.>", false], // 29
|
|
618
|
+
["a.b.>.c", "a.b.x.c", false], // 30
|
|
619
|
+
["a.*.*", "a.b", false], // 31
|
|
620
|
+
["a.*", "a.b.c", false], // 32
|
|
621
|
+
["metrics.cpu.load", "metrics.*.load", true], // 33
|
|
622
|
+
["metrics.cpu.load", "metrics.cpu.*", true], // 34
|
|
623
|
+
["metrics.cpu.load", "metrics.>.load", false], // 35
|
|
624
|
+
["metrics.>", "metrics", false], // 36
|
|
625
|
+
["metrics.>", "othermetrics.cpu", false], // 37
|
|
626
|
+
["*.*.>", "a.b", false], // 38
|
|
627
|
+
["*.*.>", "a.b.c.d", true], // 39
|
|
628
|
+
["a.b.c", "*.*.*", true], // 40
|
|
629
|
+
["a.b.c", "*.*", false], // 41
|
|
630
|
+
["alpha.*.>", "alpha", false], // 42
|
|
631
|
+
["alpha.*.>", "alpha.beta", false], // 43
|
|
632
|
+
["alpha.*.>", "alpha.beta.gamma", true], // 44
|
|
633
|
+
["alpha.*.>", "beta.alpha.gamma", false], // 45
|
|
634
|
+
["foo-bar_baz", "foo-bar_baz", true], // 46
|
|
635
|
+
["foo-bar_*", "foo-bar_123", false], // 47 ( '*' here is literal )
|
|
636
|
+
["foo-bar_*", "foo-bar_*", true], // 48
|
|
637
|
+
["order-*", "order-123", false], // 49
|
|
638
|
+
["hello.hey.*", "hello.hey.>", true] // 50
|
|
639
|
+
];
|
|
640
|
+
|
|
641
|
+
var realtime = new Realtime({
|
|
642
|
+
api_key: process.env.AUTH_JWT,
|
|
643
|
+
secret: process.env.AUTH_SECRET
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
var patternMatcher = realtime.testPatternMatcher();
|
|
647
|
+
|
|
648
|
+
cases.forEach(testCase => {
|
|
649
|
+
var tokenA = testCase[0];
|
|
650
|
+
var tokenB = testCase[1];
|
|
651
|
+
var expectedResult = testCase[2];
|
|
652
|
+
|
|
653
|
+
console.log(`${tokenA} ⇆ ${tokenB} → ${expectedResult}`)
|
|
654
|
+
|
|
655
|
+
var result = patternMatcher(tokenA, tokenB)
|
|
656
|
+
assert.strictEqual(expectedResult, result)
|
|
657
|
+
});
|
|
514
658
|
})
|