@nanolink/mirrors 1.0.9 → 1.0.12
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/dist/DelegateMap.js +42 -37
- package/dist/DelegateMap.js.map +1 -1
- package/dist/MirrorSync.d.ts +2 -1
- package/dist/MirrorSync.js +216 -113
- package/dist/MirrorSync.js.map +1 -1
- package/dist/SubscriptionClient.js +176 -109
- package/dist/SubscriptionClient.js.map +1 -1
- package/dist/index.js +115 -45
- package/dist/index.js.map +1 -1
- package/dist-compat/index.js +739 -18
- package/dist-compat/index.js.map +1 -1
- package/package.json +32 -11
package/dist-compat/index.js
CHANGED
|
@@ -7,6 +7,7 @@ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
9
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
10
|
+
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
10
11
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
12
|
var __spreadValues = (a, b) => {
|
|
12
13
|
for (var prop in b || (b = {}))
|
|
@@ -40,6 +41,22 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
40
41
|
mod
|
|
41
42
|
));
|
|
42
43
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
44
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
45
|
+
var __await = function(promise, isYieldStar) {
|
|
46
|
+
this[0] = promise;
|
|
47
|
+
this[1] = isYieldStar;
|
|
48
|
+
};
|
|
49
|
+
var __asyncGenerator = (__this, __arguments, generator) => {
|
|
50
|
+
var resume = (k, v, yes, no) => {
|
|
51
|
+
try {
|
|
52
|
+
var x = generator[k](v), isAwait = (v = x.value) instanceof __await, done = x.done;
|
|
53
|
+
Promise.resolve(isAwait ? v[0] : v).then((y) => isAwait ? resume(k === "return" ? k : "next", v[1] ? { done: y.done, value: y.value } : y, yes, no) : yes({ value: y, done })).catch((e) => resume("throw", e, yes, no));
|
|
54
|
+
} catch (e) {
|
|
55
|
+
no(e);
|
|
56
|
+
}
|
|
57
|
+
}, method = (k) => it[k] = (x) => new Promise((yes, no) => resume(k, x, yes, no)), it = {};
|
|
58
|
+
return generator = generator.apply(__this, __arguments), it[__knownSymbol("asyncIterator")] = () => it, method("next"), method("throw"), method("return"), it;
|
|
59
|
+
};
|
|
43
60
|
|
|
44
61
|
// src/index.ts
|
|
45
62
|
var index_exports = {};
|
|
@@ -156,7 +173,7 @@ var MirrorSync = class extends import_eventemitter3.default {
|
|
|
156
173
|
this.onConnected = () => {
|
|
157
174
|
if ((this.currentVersion === -1 || this.currentOpVersion === null) && !this.unsub) {
|
|
158
175
|
this.l("initial connected subscribe", { version: this.currentVersion, opVersion: this.currentOpVersion });
|
|
159
|
-
this.
|
|
176
|
+
this.subscribeInternal(this.currentVersion, this.currentOpVersion);
|
|
160
177
|
}
|
|
161
178
|
};
|
|
162
179
|
this.client.on("reconnected", this.onReconnected);
|
|
@@ -184,7 +201,7 @@ var MirrorSync = class extends import_eventemitter3.default {
|
|
|
184
201
|
advanceOp(v) {
|
|
185
202
|
if (v && (!this.currentOpVersion || v > this.currentOpVersion)) this.currentOpVersion = v;
|
|
186
203
|
}
|
|
187
|
-
|
|
204
|
+
subscribeInternal(version, opVersion) {
|
|
188
205
|
if (!this.client) throw new Error("SubscriptionClient missing");
|
|
189
206
|
if (this.unsub) {
|
|
190
207
|
this.unsub();
|
|
@@ -209,19 +226,23 @@ var MirrorSync = class extends import_eventemitter3.default {
|
|
|
209
226
|
);
|
|
210
227
|
}
|
|
211
228
|
resubscribe() {
|
|
212
|
-
this.
|
|
229
|
+
this.subscribeInternal(this.currentVersion, this.currentOpVersion);
|
|
213
230
|
}
|
|
214
231
|
start() {
|
|
215
232
|
if (!this.client.isConnected()) {
|
|
216
233
|
this.l("start deferred (not connected)");
|
|
217
234
|
return;
|
|
218
235
|
}
|
|
219
|
-
this.
|
|
236
|
+
this.subscribeInternal(this.currentVersion, this.currentOpVersion);
|
|
220
237
|
}
|
|
221
238
|
load() {
|
|
222
239
|
if (!this.unsub) this.start();
|
|
223
240
|
return this.loaded;
|
|
224
241
|
}
|
|
242
|
+
async subscribe() {
|
|
243
|
+
if (!this.unsub) this.start();
|
|
244
|
+
await this.loaded;
|
|
245
|
+
}
|
|
225
246
|
resetLoaded() {
|
|
226
247
|
this.loaded = new Promise((resolve) => {
|
|
227
248
|
this.resolveLoaded = resolve;
|
|
@@ -272,7 +293,7 @@ var MirrorSync = class extends import_eventemitter3.default {
|
|
|
272
293
|
this.currentOpVersion = null;
|
|
273
294
|
this.buffer = null;
|
|
274
295
|
this.resetLoaded();
|
|
275
|
-
this.
|
|
296
|
+
this.subscribeInternal(this.currentVersion, this.currentOpVersion);
|
|
276
297
|
break;
|
|
277
298
|
}
|
|
278
299
|
}
|
|
@@ -340,8 +361,702 @@ var MirrorSync = class extends import_eventemitter3.default {
|
|
|
340
361
|
}
|
|
341
362
|
};
|
|
342
363
|
|
|
364
|
+
// node_modules/graphql-ws/dist/common-CGW11Fyb.js
|
|
365
|
+
function extendedTypeof(val) {
|
|
366
|
+
if (val === null) {
|
|
367
|
+
return "null";
|
|
368
|
+
}
|
|
369
|
+
if (Array.isArray(val)) {
|
|
370
|
+
return "array";
|
|
371
|
+
}
|
|
372
|
+
return typeof val;
|
|
373
|
+
}
|
|
374
|
+
function isObject(val) {
|
|
375
|
+
return extendedTypeof(val) === "object";
|
|
376
|
+
}
|
|
377
|
+
function areGraphQLFormattedErrors(obj) {
|
|
378
|
+
return Array.isArray(obj) && // must be at least one error
|
|
379
|
+
obj.length > 0 && // error has at least a message
|
|
380
|
+
obj.every((ob) => "message" in ob);
|
|
381
|
+
}
|
|
382
|
+
function limitCloseReason(reason, whenTooLong) {
|
|
383
|
+
return reason.length < 124 ? reason : whenTooLong;
|
|
384
|
+
}
|
|
385
|
+
var GRAPHQL_TRANSPORT_WS_PROTOCOL = "graphql-transport-ws";
|
|
386
|
+
var CloseCode = /* @__PURE__ */ ((CloseCode2) => {
|
|
387
|
+
CloseCode2[CloseCode2["InternalServerError"] = 4500] = "InternalServerError";
|
|
388
|
+
CloseCode2[CloseCode2["InternalClientError"] = 4005] = "InternalClientError";
|
|
389
|
+
CloseCode2[CloseCode2["BadRequest"] = 4400] = "BadRequest";
|
|
390
|
+
CloseCode2[CloseCode2["BadResponse"] = 4004] = "BadResponse";
|
|
391
|
+
CloseCode2[CloseCode2["Unauthorized"] = 4401] = "Unauthorized";
|
|
392
|
+
CloseCode2[CloseCode2["Forbidden"] = 4403] = "Forbidden";
|
|
393
|
+
CloseCode2[CloseCode2["SubprotocolNotAcceptable"] = 4406] = "SubprotocolNotAcceptable";
|
|
394
|
+
CloseCode2[CloseCode2["ConnectionInitialisationTimeout"] = 4408] = "ConnectionInitialisationTimeout";
|
|
395
|
+
CloseCode2[CloseCode2["ConnectionAcknowledgementTimeout"] = 4504] = "ConnectionAcknowledgementTimeout";
|
|
396
|
+
CloseCode2[CloseCode2["SubscriberAlreadyExists"] = 4409] = "SubscriberAlreadyExists";
|
|
397
|
+
CloseCode2[CloseCode2["TooManyInitialisationRequests"] = 4429] = "TooManyInitialisationRequests";
|
|
398
|
+
return CloseCode2;
|
|
399
|
+
})(CloseCode || {});
|
|
400
|
+
var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
401
|
+
MessageType2["ConnectionInit"] = "connection_init";
|
|
402
|
+
MessageType2["ConnectionAck"] = "connection_ack";
|
|
403
|
+
MessageType2["Ping"] = "ping";
|
|
404
|
+
MessageType2["Pong"] = "pong";
|
|
405
|
+
MessageType2["Subscribe"] = "subscribe";
|
|
406
|
+
MessageType2["Next"] = "next";
|
|
407
|
+
MessageType2["Error"] = "error";
|
|
408
|
+
MessageType2["Complete"] = "complete";
|
|
409
|
+
return MessageType2;
|
|
410
|
+
})(MessageType || {});
|
|
411
|
+
function validateMessage(val) {
|
|
412
|
+
if (!isObject(val)) {
|
|
413
|
+
throw new Error(
|
|
414
|
+
`Message is expected to be an object, but got ${extendedTypeof(val)}`
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
if (!val.type) {
|
|
418
|
+
throw new Error(`Message is missing the 'type' property`);
|
|
419
|
+
}
|
|
420
|
+
if (typeof val.type !== "string") {
|
|
421
|
+
throw new Error(
|
|
422
|
+
`Message is expects the 'type' property to be a string, but got ${extendedTypeof(
|
|
423
|
+
val.type
|
|
424
|
+
)}`
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
switch (val.type) {
|
|
428
|
+
case "connection_init":
|
|
429
|
+
case "connection_ack":
|
|
430
|
+
case "ping":
|
|
431
|
+
case "pong": {
|
|
432
|
+
if (val.payload != null && !isObject(val.payload)) {
|
|
433
|
+
throw new Error(
|
|
434
|
+
`"${val.type}" message expects the 'payload' property to be an object or nullish or missing, but got "${val.payload}"`
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
case "subscribe": {
|
|
440
|
+
if (typeof val.id !== "string") {
|
|
441
|
+
throw new Error(
|
|
442
|
+
`"${val.type}" message expects the 'id' property to be a string, but got ${extendedTypeof(
|
|
443
|
+
val.id
|
|
444
|
+
)}`
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
if (!val.id) {
|
|
448
|
+
throw new Error(
|
|
449
|
+
`"${val.type}" message requires a non-empty 'id' property`
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
if (!isObject(val.payload)) {
|
|
453
|
+
throw new Error(
|
|
454
|
+
`"${val.type}" message expects the 'payload' property to be an object, but got ${extendedTypeof(
|
|
455
|
+
val.payload
|
|
456
|
+
)}`
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
if (typeof val.payload.query !== "string") {
|
|
460
|
+
throw new Error(
|
|
461
|
+
`"${val.type}" message payload expects the 'query' property to be a string, but got ${extendedTypeof(
|
|
462
|
+
val.payload.query
|
|
463
|
+
)}`
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
if (val.payload.variables != null && !isObject(val.payload.variables)) {
|
|
467
|
+
throw new Error(
|
|
468
|
+
`"${val.type}" message payload expects the 'variables' property to be a an object or nullish or missing, but got ${extendedTypeof(
|
|
469
|
+
val.payload.variables
|
|
470
|
+
)}`
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
if (val.payload.operationName != null && extendedTypeof(val.payload.operationName) !== "string") {
|
|
474
|
+
throw new Error(
|
|
475
|
+
`"${val.type}" message payload expects the 'operationName' property to be a string or nullish or missing, but got ${extendedTypeof(
|
|
476
|
+
val.payload.operationName
|
|
477
|
+
)}`
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
if (val.payload.extensions != null && !isObject(val.payload.extensions)) {
|
|
481
|
+
throw new Error(
|
|
482
|
+
`"${val.type}" message payload expects the 'extensions' property to be a an object or nullish or missing, but got ${extendedTypeof(
|
|
483
|
+
val.payload.extensions
|
|
484
|
+
)}`
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
break;
|
|
488
|
+
}
|
|
489
|
+
case "next": {
|
|
490
|
+
if (typeof val.id !== "string") {
|
|
491
|
+
throw new Error(
|
|
492
|
+
`"${val.type}" message expects the 'id' property to be a string, but got ${extendedTypeof(
|
|
493
|
+
val.id
|
|
494
|
+
)}`
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
if (!val.id) {
|
|
498
|
+
throw new Error(
|
|
499
|
+
`"${val.type}" message requires a non-empty 'id' property`
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
if (!isObject(val.payload)) {
|
|
503
|
+
throw new Error(
|
|
504
|
+
`"${val.type}" message expects the 'payload' property to be an object, but got ${extendedTypeof(
|
|
505
|
+
val.payload
|
|
506
|
+
)}`
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
case "error": {
|
|
512
|
+
if (typeof val.id !== "string") {
|
|
513
|
+
throw new Error(
|
|
514
|
+
`"${val.type}" message expects the 'id' property to be a string, but got ${extendedTypeof(
|
|
515
|
+
val.id
|
|
516
|
+
)}`
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
if (!val.id) {
|
|
520
|
+
throw new Error(
|
|
521
|
+
`"${val.type}" message requires a non-empty 'id' property`
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
if (!areGraphQLFormattedErrors(val.payload)) {
|
|
525
|
+
throw new Error(
|
|
526
|
+
`"${val.type}" message expects the 'payload' property to be an array of GraphQL errors, but got ${JSON.stringify(
|
|
527
|
+
val.payload
|
|
528
|
+
)}`
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
case "complete": {
|
|
534
|
+
if (typeof val.id !== "string") {
|
|
535
|
+
throw new Error(
|
|
536
|
+
`"${val.type}" message expects the 'id' property to be a string, but got ${extendedTypeof(
|
|
537
|
+
val.id
|
|
538
|
+
)}`
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
if (!val.id) {
|
|
542
|
+
throw new Error(
|
|
543
|
+
`"${val.type}" message requires a non-empty 'id' property`
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
default:
|
|
549
|
+
throw new Error(`Invalid message 'type' property "${val.type}"`);
|
|
550
|
+
}
|
|
551
|
+
return val;
|
|
552
|
+
}
|
|
553
|
+
function parseMessage(data, reviver) {
|
|
554
|
+
return validateMessage(
|
|
555
|
+
typeof data === "string" ? JSON.parse(data, reviver) : data
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
function stringifyMessage(msg, replacer) {
|
|
559
|
+
validateMessage(msg);
|
|
560
|
+
return JSON.stringify(msg, replacer);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// node_modules/graphql-ws/dist/client.js
|
|
564
|
+
function createClient(options) {
|
|
565
|
+
const {
|
|
566
|
+
url,
|
|
567
|
+
connectionParams,
|
|
568
|
+
lazy = true,
|
|
569
|
+
onNonLazyError = console.error,
|
|
570
|
+
lazyCloseTimeout: lazyCloseTimeoutMs = 0,
|
|
571
|
+
keepAlive = 0,
|
|
572
|
+
disablePong,
|
|
573
|
+
connectionAckWaitTimeout = 0,
|
|
574
|
+
retryAttempts = 5,
|
|
575
|
+
retryWait = async function randomisedExponentialBackoff(retries2) {
|
|
576
|
+
const retryDelaySeconds = Math.pow(2, retries2);
|
|
577
|
+
await new Promise(
|
|
578
|
+
(resolve) => setTimeout(
|
|
579
|
+
resolve,
|
|
580
|
+
retryDelaySeconds * 1e3 + // add random timeout from 300ms to 3s
|
|
581
|
+
Math.floor(Math.random() * (3e3 - 300) + 300)
|
|
582
|
+
)
|
|
583
|
+
);
|
|
584
|
+
},
|
|
585
|
+
shouldRetry = isLikeCloseEvent,
|
|
586
|
+
on,
|
|
587
|
+
webSocketImpl,
|
|
588
|
+
/**
|
|
589
|
+
* Generates a v4 UUID to be used as the ID using `Math`
|
|
590
|
+
* as the random number generator. Supply your own generator
|
|
591
|
+
* in case you need more uniqueness.
|
|
592
|
+
*
|
|
593
|
+
* Reference: https://gist.github.com/jed/982883
|
|
594
|
+
*/
|
|
595
|
+
generateID = function generateUUID() {
|
|
596
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
597
|
+
const r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
|
|
598
|
+
return v.toString(16);
|
|
599
|
+
});
|
|
600
|
+
},
|
|
601
|
+
jsonMessageReplacer: replacer,
|
|
602
|
+
jsonMessageReviver: reviver
|
|
603
|
+
} = options;
|
|
604
|
+
let ws;
|
|
605
|
+
if (webSocketImpl) {
|
|
606
|
+
if (!isWebSocket(webSocketImpl)) {
|
|
607
|
+
throw new Error("Invalid WebSocket implementation provided");
|
|
608
|
+
}
|
|
609
|
+
ws = webSocketImpl;
|
|
610
|
+
} else if (typeof WebSocket !== "undefined") {
|
|
611
|
+
ws = WebSocket;
|
|
612
|
+
} else if (typeof global !== "undefined") {
|
|
613
|
+
ws = global.WebSocket || // @ts-expect-error: Support more browsers
|
|
614
|
+
global.MozWebSocket;
|
|
615
|
+
} else if (typeof window !== "undefined") {
|
|
616
|
+
ws = window.WebSocket || // @ts-expect-error: Support more browsers
|
|
617
|
+
window.MozWebSocket;
|
|
618
|
+
}
|
|
619
|
+
if (!ws)
|
|
620
|
+
throw new Error(
|
|
621
|
+
"WebSocket implementation missing; on Node you can `import WebSocket from 'ws';` and pass `webSocketImpl: WebSocket` to `createClient`"
|
|
622
|
+
);
|
|
623
|
+
const WebSocketImpl = ws;
|
|
624
|
+
const emitter = (() => {
|
|
625
|
+
const message = /* @__PURE__ */ (() => {
|
|
626
|
+
const listeners2 = {};
|
|
627
|
+
return {
|
|
628
|
+
on(id, listener) {
|
|
629
|
+
listeners2[id] = listener;
|
|
630
|
+
return () => {
|
|
631
|
+
delete listeners2[id];
|
|
632
|
+
};
|
|
633
|
+
},
|
|
634
|
+
emit(message2) {
|
|
635
|
+
var _a;
|
|
636
|
+
if ("id" in message2) (_a = listeners2[message2.id]) == null ? void 0 : _a.call(listeners2, message2);
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
})();
|
|
640
|
+
const listeners = {
|
|
641
|
+
connecting: (on == null ? void 0 : on.connecting) ? [on.connecting] : [],
|
|
642
|
+
opened: (on == null ? void 0 : on.opened) ? [on.opened] : [],
|
|
643
|
+
connected: (on == null ? void 0 : on.connected) ? [on.connected] : [],
|
|
644
|
+
ping: (on == null ? void 0 : on.ping) ? [on.ping] : [],
|
|
645
|
+
pong: (on == null ? void 0 : on.pong) ? [on.pong] : [],
|
|
646
|
+
message: (on == null ? void 0 : on.message) ? [message.emit, on.message] : [message.emit],
|
|
647
|
+
closed: (on == null ? void 0 : on.closed) ? [on.closed] : [],
|
|
648
|
+
error: (on == null ? void 0 : on.error) ? [on.error] : []
|
|
649
|
+
};
|
|
650
|
+
return {
|
|
651
|
+
onMessage: message.on,
|
|
652
|
+
on(event, listener) {
|
|
653
|
+
const l = listeners[event];
|
|
654
|
+
l.push(listener);
|
|
655
|
+
return () => {
|
|
656
|
+
l.splice(l.indexOf(listener), 1);
|
|
657
|
+
};
|
|
658
|
+
},
|
|
659
|
+
emit(event, ...args) {
|
|
660
|
+
for (const listener of [...listeners[event]]) {
|
|
661
|
+
listener(...args);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
})();
|
|
666
|
+
function errorOrClosed(cb) {
|
|
667
|
+
const listening = [
|
|
668
|
+
// errors are fatal and more critical than close events, throw them first
|
|
669
|
+
emitter.on("error", (err) => {
|
|
670
|
+
listening.forEach((unlisten) => unlisten());
|
|
671
|
+
cb(err);
|
|
672
|
+
}),
|
|
673
|
+
// closes can be graceful and not fatal, throw them second (if error didnt throw)
|
|
674
|
+
emitter.on("closed", (event) => {
|
|
675
|
+
listening.forEach((unlisten) => unlisten());
|
|
676
|
+
cb(event);
|
|
677
|
+
})
|
|
678
|
+
];
|
|
679
|
+
}
|
|
680
|
+
let connecting, locks = 0, lazyCloseTimeout, retrying = false, retries = 0, disposed = false;
|
|
681
|
+
async function connect() {
|
|
682
|
+
clearTimeout(lazyCloseTimeout);
|
|
683
|
+
const [socket, throwOnClose] = await (connecting != null ? connecting : connecting = new Promise(
|
|
684
|
+
(connected, denied) => (async () => {
|
|
685
|
+
if (retrying) {
|
|
686
|
+
await retryWait(retries);
|
|
687
|
+
if (!locks) {
|
|
688
|
+
connecting = void 0;
|
|
689
|
+
return denied({ code: 1e3, reason: "All Subscriptions Gone" });
|
|
690
|
+
}
|
|
691
|
+
retries++;
|
|
692
|
+
}
|
|
693
|
+
emitter.emit("connecting", retrying);
|
|
694
|
+
const socket2 = new WebSocketImpl(
|
|
695
|
+
typeof url === "function" ? await url() : url,
|
|
696
|
+
GRAPHQL_TRANSPORT_WS_PROTOCOL
|
|
697
|
+
);
|
|
698
|
+
let connectionAckTimeout, queuedPing;
|
|
699
|
+
function enqueuePing() {
|
|
700
|
+
if (isFinite(keepAlive) && keepAlive > 0) {
|
|
701
|
+
clearTimeout(queuedPing);
|
|
702
|
+
queuedPing = setTimeout(() => {
|
|
703
|
+
if (socket2.readyState === WebSocketImpl.OPEN) {
|
|
704
|
+
socket2.send(stringifyMessage({ type: MessageType.Ping }));
|
|
705
|
+
emitter.emit("ping", false, void 0);
|
|
706
|
+
}
|
|
707
|
+
}, keepAlive);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
errorOrClosed((errOrEvent) => {
|
|
711
|
+
connecting = void 0;
|
|
712
|
+
clearTimeout(connectionAckTimeout);
|
|
713
|
+
clearTimeout(queuedPing);
|
|
714
|
+
denied(errOrEvent);
|
|
715
|
+
if (errOrEvent instanceof TerminatedCloseEvent) {
|
|
716
|
+
socket2.close(4499, "Terminated");
|
|
717
|
+
socket2.onerror = null;
|
|
718
|
+
socket2.onclose = null;
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
socket2.onerror = (err) => emitter.emit("error", err);
|
|
722
|
+
socket2.onclose = (event) => emitter.emit("closed", event);
|
|
723
|
+
socket2.onopen = async () => {
|
|
724
|
+
try {
|
|
725
|
+
emitter.emit("opened", socket2);
|
|
726
|
+
const payload = typeof connectionParams === "function" ? await connectionParams() : connectionParams;
|
|
727
|
+
if (socket2.readyState !== WebSocketImpl.OPEN) return;
|
|
728
|
+
socket2.send(
|
|
729
|
+
stringifyMessage(
|
|
730
|
+
payload ? {
|
|
731
|
+
type: MessageType.ConnectionInit,
|
|
732
|
+
payload
|
|
733
|
+
} : {
|
|
734
|
+
type: MessageType.ConnectionInit
|
|
735
|
+
// payload is completely absent if not provided
|
|
736
|
+
},
|
|
737
|
+
replacer
|
|
738
|
+
)
|
|
739
|
+
);
|
|
740
|
+
if (isFinite(connectionAckWaitTimeout) && connectionAckWaitTimeout > 0) {
|
|
741
|
+
connectionAckTimeout = setTimeout(() => {
|
|
742
|
+
socket2.close(
|
|
743
|
+
CloseCode.ConnectionAcknowledgementTimeout,
|
|
744
|
+
"Connection acknowledgement timeout"
|
|
745
|
+
);
|
|
746
|
+
}, connectionAckWaitTimeout);
|
|
747
|
+
}
|
|
748
|
+
enqueuePing();
|
|
749
|
+
} catch (err) {
|
|
750
|
+
emitter.emit("error", err);
|
|
751
|
+
socket2.close(
|
|
752
|
+
CloseCode.InternalClientError,
|
|
753
|
+
limitCloseReason(
|
|
754
|
+
err instanceof Error ? err.message : String(err),
|
|
755
|
+
"Internal client error"
|
|
756
|
+
)
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
let acknowledged = false;
|
|
761
|
+
socket2.onmessage = ({ data }) => {
|
|
762
|
+
try {
|
|
763
|
+
const message = parseMessage(data, reviver);
|
|
764
|
+
emitter.emit("message", message);
|
|
765
|
+
if (message.type === "ping" || message.type === "pong") {
|
|
766
|
+
emitter.emit(message.type, true, message.payload);
|
|
767
|
+
if (message.type === "pong") {
|
|
768
|
+
enqueuePing();
|
|
769
|
+
} else if (!disablePong) {
|
|
770
|
+
socket2.send(
|
|
771
|
+
stringifyMessage(
|
|
772
|
+
message.payload ? {
|
|
773
|
+
type: MessageType.Pong,
|
|
774
|
+
payload: message.payload
|
|
775
|
+
} : {
|
|
776
|
+
type: MessageType.Pong
|
|
777
|
+
// payload is completely absent if not provided
|
|
778
|
+
}
|
|
779
|
+
)
|
|
780
|
+
);
|
|
781
|
+
emitter.emit("pong", false, message.payload);
|
|
782
|
+
}
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
if (acknowledged) return;
|
|
786
|
+
if (message.type !== MessageType.ConnectionAck)
|
|
787
|
+
throw new Error(
|
|
788
|
+
`First message cannot be of type ${message.type}`
|
|
789
|
+
);
|
|
790
|
+
clearTimeout(connectionAckTimeout);
|
|
791
|
+
acknowledged = true;
|
|
792
|
+
emitter.emit("connected", socket2, message.payload, retrying);
|
|
793
|
+
retrying = false;
|
|
794
|
+
retries = 0;
|
|
795
|
+
connected([
|
|
796
|
+
socket2,
|
|
797
|
+
new Promise((_, reject) => errorOrClosed(reject))
|
|
798
|
+
]);
|
|
799
|
+
} catch (err) {
|
|
800
|
+
socket2.onmessage = null;
|
|
801
|
+
emitter.emit("error", err);
|
|
802
|
+
socket2.close(
|
|
803
|
+
CloseCode.BadResponse,
|
|
804
|
+
limitCloseReason(
|
|
805
|
+
err instanceof Error ? err.message : String(err),
|
|
806
|
+
"Bad response"
|
|
807
|
+
)
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
})()
|
|
812
|
+
));
|
|
813
|
+
if (socket.readyState === WebSocketImpl.CLOSING) await throwOnClose;
|
|
814
|
+
let release = () => {
|
|
815
|
+
};
|
|
816
|
+
const released = new Promise((resolve) => release = resolve);
|
|
817
|
+
return [
|
|
818
|
+
socket,
|
|
819
|
+
release,
|
|
820
|
+
Promise.race([
|
|
821
|
+
// wait for
|
|
822
|
+
released.then(() => {
|
|
823
|
+
if (!locks) {
|
|
824
|
+
const complete = () => socket.close(1e3, "Normal Closure");
|
|
825
|
+
if (isFinite(lazyCloseTimeoutMs) && lazyCloseTimeoutMs > 0) {
|
|
826
|
+
lazyCloseTimeout = setTimeout(() => {
|
|
827
|
+
if (socket.readyState === WebSocketImpl.OPEN) complete();
|
|
828
|
+
}, lazyCloseTimeoutMs);
|
|
829
|
+
} else {
|
|
830
|
+
complete();
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}),
|
|
834
|
+
// or
|
|
835
|
+
throwOnClose
|
|
836
|
+
])
|
|
837
|
+
];
|
|
838
|
+
}
|
|
839
|
+
function shouldRetryConnectOrThrow(errOrCloseEvent) {
|
|
840
|
+
if (isLikeCloseEvent(errOrCloseEvent) && (isFatalInternalCloseCode(errOrCloseEvent.code) || [
|
|
841
|
+
CloseCode.InternalServerError,
|
|
842
|
+
CloseCode.InternalClientError,
|
|
843
|
+
CloseCode.BadRequest,
|
|
844
|
+
CloseCode.BadResponse,
|
|
845
|
+
CloseCode.Unauthorized,
|
|
846
|
+
// CloseCode.Forbidden, might grant access out after retry
|
|
847
|
+
CloseCode.SubprotocolNotAcceptable,
|
|
848
|
+
// CloseCode.ConnectionInitialisationTimeout, might not time out after retry
|
|
849
|
+
// CloseCode.ConnectionAcknowledgementTimeout, might not time out after retry
|
|
850
|
+
CloseCode.SubscriberAlreadyExists,
|
|
851
|
+
CloseCode.TooManyInitialisationRequests
|
|
852
|
+
// 4499, // Terminated, probably because the socket froze, we want to retry
|
|
853
|
+
].includes(errOrCloseEvent.code)))
|
|
854
|
+
throw errOrCloseEvent;
|
|
855
|
+
if (disposed) return false;
|
|
856
|
+
if (isLikeCloseEvent(errOrCloseEvent) && errOrCloseEvent.code === 1e3)
|
|
857
|
+
return locks > 0;
|
|
858
|
+
if (!retryAttempts || retries >= retryAttempts) throw errOrCloseEvent;
|
|
859
|
+
if (!shouldRetry(errOrCloseEvent)) throw errOrCloseEvent;
|
|
860
|
+
return retrying = true;
|
|
861
|
+
}
|
|
862
|
+
if (!lazy) {
|
|
863
|
+
(async () => {
|
|
864
|
+
locks++;
|
|
865
|
+
for (; ; ) {
|
|
866
|
+
try {
|
|
867
|
+
const [, , throwOnClose] = await connect();
|
|
868
|
+
await throwOnClose;
|
|
869
|
+
} catch (errOrCloseEvent) {
|
|
870
|
+
try {
|
|
871
|
+
if (!shouldRetryConnectOrThrow(errOrCloseEvent)) return;
|
|
872
|
+
} catch (errOrCloseEvent2) {
|
|
873
|
+
return onNonLazyError == null ? void 0 : onNonLazyError(errOrCloseEvent2);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
})();
|
|
878
|
+
}
|
|
879
|
+
function subscribe(payload, sink) {
|
|
880
|
+
const id = generateID(payload);
|
|
881
|
+
let done = false, errored = false, releaser = () => {
|
|
882
|
+
locks--;
|
|
883
|
+
done = true;
|
|
884
|
+
};
|
|
885
|
+
(async () => {
|
|
886
|
+
locks++;
|
|
887
|
+
for (; ; ) {
|
|
888
|
+
try {
|
|
889
|
+
const [socket, release, waitForReleaseOrThrowOnClose] = await connect();
|
|
890
|
+
if (done) return release();
|
|
891
|
+
const unlisten = emitter.onMessage(id, (message) => {
|
|
892
|
+
switch (message.type) {
|
|
893
|
+
case MessageType.Next: {
|
|
894
|
+
sink.next(message.payload);
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
case MessageType.Error: {
|
|
898
|
+
errored = true, done = true;
|
|
899
|
+
sink.error(message.payload);
|
|
900
|
+
releaser();
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
case MessageType.Complete: {
|
|
904
|
+
done = true;
|
|
905
|
+
releaser();
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
});
|
|
910
|
+
socket.send(
|
|
911
|
+
stringifyMessage(
|
|
912
|
+
{
|
|
913
|
+
id,
|
|
914
|
+
type: MessageType.Subscribe,
|
|
915
|
+
payload
|
|
916
|
+
},
|
|
917
|
+
replacer
|
|
918
|
+
)
|
|
919
|
+
);
|
|
920
|
+
releaser = () => {
|
|
921
|
+
if (!done && socket.readyState === WebSocketImpl.OPEN)
|
|
922
|
+
socket.send(
|
|
923
|
+
stringifyMessage(
|
|
924
|
+
{
|
|
925
|
+
id,
|
|
926
|
+
type: MessageType.Complete
|
|
927
|
+
},
|
|
928
|
+
replacer
|
|
929
|
+
)
|
|
930
|
+
);
|
|
931
|
+
locks--;
|
|
932
|
+
done = true;
|
|
933
|
+
release();
|
|
934
|
+
};
|
|
935
|
+
await waitForReleaseOrThrowOnClose.finally(unlisten);
|
|
936
|
+
return;
|
|
937
|
+
} catch (errOrCloseEvent) {
|
|
938
|
+
if (!shouldRetryConnectOrThrow(errOrCloseEvent)) return;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
})().then(() => {
|
|
942
|
+
if (!errored) sink.complete();
|
|
943
|
+
}).catch((err) => {
|
|
944
|
+
sink.error(err);
|
|
945
|
+
});
|
|
946
|
+
return () => {
|
|
947
|
+
if (!done) releaser();
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
return {
|
|
951
|
+
on: emitter.on,
|
|
952
|
+
subscribe,
|
|
953
|
+
iterate(request) {
|
|
954
|
+
const pending = [];
|
|
955
|
+
const deferred = {
|
|
956
|
+
done: false,
|
|
957
|
+
error: null,
|
|
958
|
+
resolve: () => {
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
const dispose = subscribe(request, {
|
|
962
|
+
next(val) {
|
|
963
|
+
pending.push(val);
|
|
964
|
+
deferred.resolve();
|
|
965
|
+
},
|
|
966
|
+
error(err) {
|
|
967
|
+
deferred.done = true;
|
|
968
|
+
deferred.error = err;
|
|
969
|
+
deferred.resolve();
|
|
970
|
+
},
|
|
971
|
+
complete() {
|
|
972
|
+
deferred.done = true;
|
|
973
|
+
deferred.resolve();
|
|
974
|
+
}
|
|
975
|
+
});
|
|
976
|
+
const iterator = (function iterator2() {
|
|
977
|
+
return __asyncGenerator(this, null, function* () {
|
|
978
|
+
for (; ; ) {
|
|
979
|
+
if (!pending.length) {
|
|
980
|
+
yield new __await(new Promise((resolve) => deferred.resolve = resolve));
|
|
981
|
+
}
|
|
982
|
+
while (pending.length) {
|
|
983
|
+
yield pending.shift();
|
|
984
|
+
}
|
|
985
|
+
if (deferred.error) {
|
|
986
|
+
throw deferred.error;
|
|
987
|
+
}
|
|
988
|
+
if (deferred.done) {
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
})();
|
|
994
|
+
iterator.throw = async (err) => {
|
|
995
|
+
if (!deferred.done) {
|
|
996
|
+
deferred.done = true;
|
|
997
|
+
deferred.error = err;
|
|
998
|
+
deferred.resolve();
|
|
999
|
+
}
|
|
1000
|
+
return { done: true, value: void 0 };
|
|
1001
|
+
};
|
|
1002
|
+
iterator.return = async () => {
|
|
1003
|
+
dispose();
|
|
1004
|
+
return { done: true, value: void 0 };
|
|
1005
|
+
};
|
|
1006
|
+
return iterator;
|
|
1007
|
+
},
|
|
1008
|
+
async dispose() {
|
|
1009
|
+
disposed = true;
|
|
1010
|
+
if (connecting) {
|
|
1011
|
+
const [socket] = await connecting;
|
|
1012
|
+
socket.close(1e3, "Normal Closure");
|
|
1013
|
+
}
|
|
1014
|
+
},
|
|
1015
|
+
terminate() {
|
|
1016
|
+
if (connecting) {
|
|
1017
|
+
emitter.emit("closed", new TerminatedCloseEvent());
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
var TerminatedCloseEvent = class extends Error {
|
|
1023
|
+
constructor() {
|
|
1024
|
+
super(...arguments);
|
|
1025
|
+
__publicField(this, "name", "TerminatedCloseEvent");
|
|
1026
|
+
__publicField(this, "message", "4499: Terminated");
|
|
1027
|
+
__publicField(this, "code", 4499);
|
|
1028
|
+
__publicField(this, "reason", "Terminated");
|
|
1029
|
+
__publicField(this, "wasClean", false);
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
function isLikeCloseEvent(val) {
|
|
1033
|
+
return isObject(val) && "code" in val && "reason" in val;
|
|
1034
|
+
}
|
|
1035
|
+
function isFatalInternalCloseCode(code) {
|
|
1036
|
+
if ([
|
|
1037
|
+
1e3,
|
|
1038
|
+
// Normal Closure is not an erroneous close code
|
|
1039
|
+
1001,
|
|
1040
|
+
// Going Away
|
|
1041
|
+
1006,
|
|
1042
|
+
// Abnormal Closure
|
|
1043
|
+
1005,
|
|
1044
|
+
// No Status Received
|
|
1045
|
+
1012,
|
|
1046
|
+
// Service Restart
|
|
1047
|
+
1013,
|
|
1048
|
+
// Try Again Later
|
|
1049
|
+
1014
|
|
1050
|
+
// Bad Gateway
|
|
1051
|
+
].includes(code))
|
|
1052
|
+
return false;
|
|
1053
|
+
return code >= 1e3 && code <= 1999;
|
|
1054
|
+
}
|
|
1055
|
+
function isWebSocket(val) {
|
|
1056
|
+
return typeof val === "function" && "constructor" in val && "CLOSED" in val && "CLOSING" in val && "CONNECTING" in val && "OPEN" in val;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
343
1059
|
// src/SubscriptionClient.ts
|
|
344
|
-
var import_graphql_ws = require("graphql-ws");
|
|
345
1060
|
var import_eventemitter32 = __toESM(require("eventemitter3"));
|
|
346
1061
|
var SubscriptionClient = class extends import_eventemitter32.default {
|
|
347
1062
|
constructor(opts) {
|
|
@@ -365,21 +1080,27 @@ var SubscriptionClient = class extends import_eventemitter32.default {
|
|
|
365
1080
|
}
|
|
366
1081
|
resolveWebSocketImpl() {
|
|
367
1082
|
if (this.options.webSocketImpl) return this.options.webSocketImpl;
|
|
368
|
-
|
|
369
|
-
|
|
1083
|
+
if (true) {
|
|
1084
|
+
const g = globalThis;
|
|
1085
|
+
if (typeof g.WebSocket === "function") return g.WebSocket;
|
|
1086
|
+
throw new Error("No WebSocket implementation found in browser. Provide webSocketImpl.");
|
|
1087
|
+
} else {
|
|
1088
|
+
const proxyEnv = process.env.ALL_PROXY || process.env.HTTPS_PROXY || process.env.HTTP_PROXY || process.env.GLOBAL_AGENT_HTTP_PROXY;
|
|
1089
|
+
if (proxyEnv) {
|
|
1090
|
+
try {
|
|
1091
|
+
return null;
|
|
1092
|
+
} catch (e) {
|
|
1093
|
+
this.log("Proxy detected but failed to load ws package", e);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
const g = globalThis;
|
|
1097
|
+
if (typeof g.WebSocket === "function") return g.WebSocket;
|
|
370
1098
|
try {
|
|
371
|
-
return
|
|
1099
|
+
return null;
|
|
372
1100
|
} catch (e) {
|
|
373
|
-
|
|
1101
|
+
throw new Error("No WebSocket implementation found. Provide webSocketImpl in SubscriptionClientOptions.");
|
|
374
1102
|
}
|
|
375
1103
|
}
|
|
376
|
-
const g = globalThis;
|
|
377
|
-
if (typeof g.WebSocket === "function") return g.WebSocket;
|
|
378
|
-
try {
|
|
379
|
-
return require("ws");
|
|
380
|
-
} catch (e) {
|
|
381
|
-
throw new Error("No WebSocket implementation found. Provide webSocketImpl in SubscriptionClientOptions.");
|
|
382
|
-
}
|
|
383
1104
|
}
|
|
384
1105
|
/** Returns true if an underlying websocket client exists (connected or in-flight). */
|
|
385
1106
|
isConnected() {
|
|
@@ -392,7 +1113,7 @@ var SubscriptionClient = class extends import_eventemitter32.default {
|
|
|
392
1113
|
if (this.client) return;
|
|
393
1114
|
const { url, connectionParams } = this.options;
|
|
394
1115
|
const webSocketImpl = this.resolveWebSocketImpl();
|
|
395
|
-
this.client =
|
|
1116
|
+
this.client = createClient({
|
|
396
1117
|
url,
|
|
397
1118
|
connectionParams,
|
|
398
1119
|
webSocketImpl,
|