qws-browser 1.1.1 → 2.1.0
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/README.md +21 -0
- package/dist/browser/messageencode.d.ts +2 -1
- package/dist/browser/messageencode.d.ts.map +1 -0
- package/dist/browser/messageencode.js +32 -25
- package/dist/browser/messageencode.js.map +1 -0
- package/dist/browser/wrappedws.d.ts +25 -2
- package/dist/browser/wrappedws.d.ts.map +1 -0
- package/dist/browser/wrappedws.js +57 -20
- package/dist/browser/wrappedws.js.map +1 -0
- package/dist/common/discriminator.d.ts +2 -1
- package/dist/common/discriminator.d.ts.map +1 -0
- package/dist/common/discriminator.js +2 -2
- package/dist/common/discriminator.js.map +1 -0
- package/dist/common/logger.d.ts +11 -10
- package/dist/common/logger.d.ts.map +1 -0
- package/dist/common/logger.js +8 -13
- package/dist/common/logger.js.map +1 -0
- package/dist/common/message.d.ts +31 -27
- package/dist/common/message.d.ts.map +1 -0
- package/dist/common/message.js +2 -2
- package/dist/common/message.js.map +1 -0
- package/dist/common/queryparser.d.ts +1 -4
- package/dist/common/queryparser.d.ts.map +1 -0
- package/dist/common/queryparser.js +6 -82
- package/dist/common/queryparser.js.map +1 -0
- package/dist/common/queue.d.ts +4 -3
- package/dist/common/queue.d.ts.map +1 -0
- package/dist/common/queue.js +10 -12
- package/dist/common/queue.js.map +1 -0
- package/dist/common/queuews.d.ts +41 -12
- package/dist/common/queuews.d.ts.map +1 -0
- package/dist/common/queuews.js +153 -83
- package/dist/common/queuews.js.map +1 -0
- package/dist/common/router.d.ts +9 -0
- package/dist/common/router.d.ts.map +1 -0
- package/dist/common/router.js +8 -0
- package/dist/common/router.js.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -25
- package/dist/index.js.map +1 -0
- package/package.json +29 -30
package/README.md
CHANGED
|
@@ -9,6 +9,27 @@ Safe queueing with auto-reconnect for WebSockets
|
|
|
9
9
|
- Automatic two-way acknowledgment stream of messages - all messages are retained in-memory until acknowledgment is provided
|
|
10
10
|
- Configurable headers per message, even when body is binary
|
|
11
11
|
- Simple message routing (via [route-recognizer](https://github.com/tildeio/route-recognizer))
|
|
12
|
+
- Heartbeats detecting dead connections
|
|
13
|
+
- Waiting for the acknowledgment of a given message
|
|
14
|
+
|
|
15
|
+
Since version 2, `qws-browser` is an ES module only (no CommonJS build), meant to be consumed via a bundler such as Vite.
|
|
16
|
+
|
|
17
|
+
# Heartbeats
|
|
18
|
+
|
|
19
|
+
Every `heartbeatIntervalMillis` (default 25s, `0` disables), a connection sends a heartbeat. If nothing arrives, not even the answer, until the next one, the connection is considered dead and is terminated, which triggers the usual close/reconnect logic. This catches connections that died silently (sleeping devices, network switches), on which no close event would arrive for minutes.
|
|
20
|
+
|
|
21
|
+
- Node uses protocol-level pings, which every WebSocket peer (including browsers) answers.
|
|
22
|
+
- Browsers can't send protocol-level pings, so they send qws `ping` messages, answered with `pong` by qws 2.1+ peers. Until the first `pong` arrives on a connection, a missing answer is not treated as a dead connection, so older servers keep working.
|
|
23
|
+
- `QWebSocketServer` takes the options of the connections it creates as second argument: `new QWebSocketServer({ port }, { heartbeatIntervalMillis: 10_000 })`.
|
|
24
|
+
|
|
25
|
+
# Waiting for acknowledgment
|
|
26
|
+
|
|
27
|
+
`send`/`sendToRoute` return the message index. `waitForAck(idx)` resolves once the other side acknowledged that message (after its handler finished), and rejects if the connection closes for good before that. Reconnecting connections keep and resend unacknowledged messages, so they don't reject on a reconnect.
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
const idx = qws.sendToRoute('handout', message);
|
|
31
|
+
await qws.waitForAck(idx);
|
|
32
|
+
```
|
|
12
33
|
|
|
13
34
|
# Examples
|
|
14
35
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { QwsMessage } from '../common/message';
|
|
1
|
+
import { QwsMessage } from '../common/message.js';
|
|
2
2
|
/**
|
|
3
3
|
* Convert binary data received through underlying WS into WSQ message
|
|
4
4
|
* Changes type based on type header
|
|
@@ -8,3 +8,4 @@ export declare function deserializeMessage(blob: Blob): Promise<QwsMessage>;
|
|
|
8
8
|
* Converts WSQ message into Blob to be sent through underlying WebSocket
|
|
9
9
|
*/
|
|
10
10
|
export declare function serializeMessage(message: QwsMessage): Blob;
|
|
11
|
+
//# sourceMappingURL=messageencode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messageencode.d.ts","sourceRoot":"","sources":["../../src/browser/messageencode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAoC,MAAM,sBAAsB,CAAC;AAwBpF;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAiDxE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAkC1D"}
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.serializeMessage = exports.deserializeMessage = void 0;
|
|
7
|
-
const logger_1 = __importDefault(require("../common/logger"));
|
|
1
|
+
import logger from '../common/logger.js';
|
|
8
2
|
/**
|
|
9
3
|
* Converts generic object into base64-encoded JSON.
|
|
10
4
|
* Used in headers and optionally JSON-style body.
|
|
11
5
|
*/
|
|
12
6
|
function objectToJsonBinary(object) {
|
|
13
7
|
const objectJson = JSON.stringify(object);
|
|
14
|
-
|
|
8
|
+
// base64 of the UTF-8 bytes, same as Buffer.from(json).toString('base64') on Node.js
|
|
9
|
+
const bytes = new TextEncoder().encode(objectJson);
|
|
10
|
+
return btoa(Array.from(bytes, (byte) => String.fromCodePoint(byte)).join(''));
|
|
15
11
|
}
|
|
16
12
|
/**
|
|
17
13
|
* Deserializes base64-json buffers
|
|
@@ -19,16 +15,17 @@ function objectToJsonBinary(object) {
|
|
|
19
15
|
*/
|
|
20
16
|
async function jsonBinaryToObject(jsonBinary) {
|
|
21
17
|
const jsonBinaryText = await jsonBinary.text();
|
|
22
|
-
const
|
|
18
|
+
const bytes = Uint8Array.from(atob(jsonBinaryText), (char) => char.codePointAt(0));
|
|
19
|
+
const objectJson = new TextDecoder().decode(bytes);
|
|
23
20
|
return JSON.parse(objectJson);
|
|
24
21
|
}
|
|
25
22
|
/**
|
|
26
23
|
* Convert binary data received through underlying WS into WSQ message
|
|
27
24
|
* Changes type based on type header
|
|
28
25
|
*/
|
|
29
|
-
async function deserializeMessage(blob) {
|
|
26
|
+
export async function deserializeMessage(blob) {
|
|
30
27
|
if (blob.size < 4) {
|
|
31
|
-
|
|
28
|
+
logger.error('Invalid blob size');
|
|
32
29
|
return {
|
|
33
30
|
headers: { type: 'bin' },
|
|
34
31
|
body: blob,
|
|
@@ -39,7 +36,7 @@ async function deserializeMessage(blob) {
|
|
|
39
36
|
const headersSizeArray = new Uint32Array(headersSizeBlob);
|
|
40
37
|
const headersSize = headersSizeArray[0];
|
|
41
38
|
if (headersSize > blob.size - 4) {
|
|
42
|
-
|
|
39
|
+
logger.error(`Invalid header size ${headersSize} > ${blob.size - 4}`);
|
|
43
40
|
return {
|
|
44
41
|
headers: { type: 'bin' },
|
|
45
42
|
body: blob,
|
|
@@ -53,47 +50,57 @@ async function deserializeMessage(blob) {
|
|
|
53
50
|
// body is either JSON Blob, original binary data or nothing
|
|
54
51
|
let body;
|
|
55
52
|
switch (type) {
|
|
56
|
-
case 'bin':
|
|
53
|
+
case 'bin': {
|
|
57
54
|
body = bodyBlob;
|
|
58
55
|
break;
|
|
59
|
-
|
|
56
|
+
}
|
|
57
|
+
case 'json': {
|
|
60
58
|
body = await jsonBinaryToObject(bodyBlob);
|
|
61
59
|
break;
|
|
60
|
+
}
|
|
62
61
|
default:
|
|
63
62
|
}
|
|
64
63
|
return { headers, body };
|
|
65
64
|
}
|
|
66
|
-
catch (
|
|
67
|
-
|
|
65
|
+
catch (error) {
|
|
66
|
+
logger.error('Could not decode message', error);
|
|
68
67
|
return {
|
|
69
68
|
headers: { type: 'bin' },
|
|
70
69
|
body: blob,
|
|
71
70
|
};
|
|
72
71
|
}
|
|
73
72
|
}
|
|
74
|
-
exports.deserializeMessage = deserializeMessage;
|
|
75
73
|
/**
|
|
76
74
|
* Converts WSQ message into Blob to be sent through underlying WebSocket
|
|
77
75
|
*/
|
|
78
|
-
function serializeMessage(message) {
|
|
76
|
+
export function serializeMessage(message) {
|
|
79
77
|
// headers encoded into base64(json)
|
|
80
78
|
const headersEncoded = objectToJsonBinary(message.headers);
|
|
81
79
|
const headersSize = Uint32Array.from([headersEncoded.length]);
|
|
82
80
|
// body is either JSON Blob, original binary data or nothing
|
|
83
81
|
let bodyEncoded;
|
|
84
82
|
switch (message.headers.type) {
|
|
85
|
-
case 'bin':
|
|
83
|
+
case 'bin': {
|
|
86
84
|
bodyEncoded = message.body;
|
|
87
85
|
break;
|
|
88
|
-
|
|
86
|
+
}
|
|
87
|
+
case 'json': {
|
|
89
88
|
bodyEncoded = objectToJsonBinary(message.body);
|
|
90
89
|
break;
|
|
91
|
-
|
|
90
|
+
}
|
|
91
|
+
case 'ready':
|
|
92
|
+
case 'ack':
|
|
93
|
+
case 'err':
|
|
94
|
+
case 'ping':
|
|
95
|
+
case 'pong': {
|
|
96
|
+
// no body
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
92
99
|
}
|
|
93
100
|
return new Blob([
|
|
94
|
-
headersSize,
|
|
95
|
-
headersEncoded,
|
|
96
|
-
bodyEncoded, // binary, json or
|
|
101
|
+
headersSize, // first 4 bytes = uint32 how long is header section
|
|
102
|
+
headersEncoded, // headers in base64(json) format
|
|
103
|
+
...(bodyEncoded === undefined ? [] : [bodyEncoded]), // binary, json or no body
|
|
97
104
|
], { type: 'application/octet-stream' });
|
|
98
105
|
}
|
|
99
|
-
|
|
106
|
+
//# sourceMappingURL=messageencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messageencode.js","sourceRoot":"","sources":["../../src/browser/messageencode.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { QwsMessage, AckQwsMessage, BinaryQwsMessage, ErrorQwsMessage, JsonQwsMessage, ReadyQwsMessage } from '../common/message';
|
|
2
|
-
import { Binary } from '../common/discriminator';
|
|
1
|
+
import { QwsMessage, AckQwsMessage, BinaryQwsMessage, ErrorQwsMessage, HeartbeatQwsMessage, JsonQwsMessage, ReadyQwsMessage } from '../common/message.js';
|
|
2
|
+
import { Binary } from '../common/discriminator.js';
|
|
3
3
|
/**
|
|
4
4
|
* Wrapper around WebSocket, built to serialize/deserialize
|
|
5
5
|
* WSQ formatted messages.
|
|
@@ -12,8 +12,17 @@ export default class WrappedWebSocket {
|
|
|
12
12
|
ready?: (message: ReadyQwsMessage) => void;
|
|
13
13
|
ack?: (message: AckQwsMessage) => void;
|
|
14
14
|
err?: (message: ErrorQwsMessage) => void;
|
|
15
|
+
ping?: (message: HeartbeatQwsMessage) => void;
|
|
16
|
+
pong?: (message: HeartbeatQwsMessage) => void;
|
|
15
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* Time of the last message or heartbeat answer received, to detect dead connections
|
|
20
|
+
*/
|
|
21
|
+
lastActivity: number;
|
|
22
|
+
private closeCallbacks;
|
|
23
|
+
private closed;
|
|
16
24
|
constructor(wsOrUrl: WebSocket | string);
|
|
25
|
+
private fireClose;
|
|
17
26
|
/**
|
|
18
27
|
* Proxy callbacks
|
|
19
28
|
*/
|
|
@@ -33,10 +42,24 @@ export default class WrappedWebSocket {
|
|
|
33
42
|
onReady(callback: (message: ReadyQwsMessage) => void): void;
|
|
34
43
|
onAck(callback: (message: AckQwsMessage) => void): void;
|
|
35
44
|
onErr(callback: (message: ErrorQwsMessage) => void): void;
|
|
45
|
+
onPing(callback: (message: HeartbeatQwsMessage) => void): void;
|
|
46
|
+
onPong(callback: (message: HeartbeatQwsMessage) => void): void;
|
|
36
47
|
/**
|
|
37
48
|
* Proxy methods
|
|
38
49
|
*/
|
|
39
50
|
send(message: QwsMessage): void;
|
|
40
51
|
sendRaw(data: Binary): void;
|
|
41
52
|
close(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Browsers can't send protocol-level pings, so heartbeats are qws ping messages,
|
|
55
|
+
* answered only by peers that know them (qws 2.1+)
|
|
56
|
+
*/
|
|
57
|
+
readonly heartbeatAnsweredByProtocol = false;
|
|
58
|
+
sendHeartbeat(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Give up on the connection right away: on a dead connection the closing handshake
|
|
61
|
+
* can take minutes before the close event fires
|
|
62
|
+
*/
|
|
63
|
+
terminate(): void;
|
|
42
64
|
}
|
|
65
|
+
//# sourceMappingURL=wrappedws.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrappedws.d.ts","sourceRoot":"","sources":["../../src/browser/wrappedws.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEpD;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC,EAAE,EAAE,SAAS,CAAC;IAEd,SAAS,EAAE;QACT,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;QAC1C,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;QACzC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;QAC3C,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;QACvC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;QACzC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;QAC9C,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;KAC/C,CAAC;IAEF;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,MAAM,CAAU;gBAEZ,OAAO,EAAE,SAAS,GAAG,MAAM;IAgCvC,OAAO,CAAC,SAAS;IAUjB;;OAEG;IAEH,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIpC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIrC,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAIjD;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;OAEG;IAEH,KAAK,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI;IAI1D,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAIzD,OAAO,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAI3D,KAAK,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;IAIvD,KAAK,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAIzD,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI;IAI9D,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI;IAI9D;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAM/B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK3B,KAAK,IAAI,IAAI;IAIb;;;OAGG;IACH,QAAQ,CAAC,2BAA2B,SAAS;IAE7C,aAAa,IAAI,IAAI;IAIrB;;;OAGG;IACH,SAAS,IAAI,IAAI;CAIlB"}
|
|
@@ -1,43 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const auto_bind_1 = __importDefault(require("auto-bind"));
|
|
7
|
-
const messageencode_1 = require("./messageencode");
|
|
1
|
+
import autoBind from 'auto-bind';
|
|
2
|
+
import { deserializeMessage, serializeMessage } from './messageencode.js';
|
|
8
3
|
/**
|
|
9
4
|
* Wrapper around WebSocket, built to serialize/deserialize
|
|
10
5
|
* WSQ formatted messages.
|
|
11
6
|
*/
|
|
12
|
-
class WrappedWebSocket {
|
|
7
|
+
export default class WrappedWebSocket {
|
|
13
8
|
constructor(wsOrUrl) {
|
|
14
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Browsers can't send protocol-level pings, so heartbeats are qws ping messages,
|
|
11
|
+
* answered only by peers that know them (qws 2.1+)
|
|
12
|
+
*/
|
|
13
|
+
this.heartbeatAnsweredByProtocol = false;
|
|
15
14
|
this.callbacks = {};
|
|
16
|
-
|
|
15
|
+
this.lastActivity = Date.now();
|
|
16
|
+
this.closeCallbacks = [];
|
|
17
|
+
this.closed = false;
|
|
18
|
+
if (wsOrUrl instanceof WebSocket || wsOrUrl?.constructor?.name === 'WebSocket') {
|
|
17
19
|
this.ws = wsOrUrl;
|
|
18
20
|
}
|
|
19
21
|
else {
|
|
20
22
|
this.ws = new WebSocket(wsOrUrl);
|
|
21
23
|
}
|
|
22
|
-
this.ws.
|
|
23
|
-
|
|
24
|
+
this.ws.addEventListener('message', async (event) => {
|
|
25
|
+
// terminated sockets may still deliver, those messages belong to a connection we gave up on
|
|
26
|
+
if (this.closed) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this.lastActivity = Date.now();
|
|
30
|
+
const message = await deserializeMessage(event.data);
|
|
24
31
|
// logger.info('WRAPPER received', message);
|
|
25
32
|
const callback = this.callbacks[message.headers.type];
|
|
26
|
-
callback
|
|
27
|
-
};
|
|
28
|
-
(
|
|
33
|
+
callback?.(message);
|
|
34
|
+
});
|
|
35
|
+
this.ws.addEventListener('close', () => {
|
|
36
|
+
this.fireClose();
|
|
37
|
+
});
|
|
38
|
+
autoBind(this);
|
|
39
|
+
}
|
|
40
|
+
// close callbacks fire once, either on the close event or on terminate()
|
|
41
|
+
fireClose() {
|
|
42
|
+
if (this.closed) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
this.closed = true;
|
|
46
|
+
for (const callback of this.closeCallbacks) {
|
|
47
|
+
callback();
|
|
48
|
+
}
|
|
29
49
|
}
|
|
30
50
|
/**
|
|
31
51
|
* Proxy callbacks
|
|
32
52
|
*/
|
|
33
53
|
onWsOpen(callback) {
|
|
34
|
-
this.ws.
|
|
54
|
+
this.ws.addEventListener('open', callback);
|
|
35
55
|
}
|
|
36
56
|
onWsClose(callback) {
|
|
37
|
-
this.
|
|
57
|
+
this.closeCallbacks.push(callback);
|
|
38
58
|
}
|
|
39
59
|
onWsError(callback) {
|
|
40
|
-
this.ws.
|
|
60
|
+
this.ws.addEventListener('error', callback);
|
|
41
61
|
}
|
|
42
62
|
/**
|
|
43
63
|
* Proxy others
|
|
@@ -66,12 +86,18 @@ class WrappedWebSocket {
|
|
|
66
86
|
onErr(callback) {
|
|
67
87
|
this.callbacks.err = callback;
|
|
68
88
|
}
|
|
89
|
+
onPing(callback) {
|
|
90
|
+
this.callbacks.ping = callback;
|
|
91
|
+
}
|
|
92
|
+
onPong(callback) {
|
|
93
|
+
this.callbacks.pong = callback;
|
|
94
|
+
}
|
|
69
95
|
/**
|
|
70
96
|
* Proxy methods
|
|
71
97
|
*/
|
|
72
98
|
send(message) {
|
|
73
99
|
// logger.info('WRAPPER sending', message);
|
|
74
|
-
const data =
|
|
100
|
+
const data = serializeMessage(message);
|
|
75
101
|
this.ws.send(data);
|
|
76
102
|
}
|
|
77
103
|
sendRaw(data) {
|
|
@@ -81,5 +107,16 @@ class WrappedWebSocket {
|
|
|
81
107
|
close() {
|
|
82
108
|
this.ws.close();
|
|
83
109
|
}
|
|
110
|
+
sendHeartbeat() {
|
|
111
|
+
this.send({ headers: { type: 'ping' } });
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Give up on the connection right away: on a dead connection the closing handshake
|
|
115
|
+
* can take minutes before the close event fires
|
|
116
|
+
*/
|
|
117
|
+
terminate() {
|
|
118
|
+
this.ws.close(4000, 'Heartbeat timeout');
|
|
119
|
+
this.fireClose();
|
|
120
|
+
}
|
|
84
121
|
}
|
|
85
|
-
|
|
122
|
+
//# sourceMappingURL=wrappedws.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrappedws.js","sourceRoot":"","sources":["../../src/browser/wrappedws.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type Binary = Blob;
|
|
2
|
+
//# sourceMappingURL=discriminator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discriminator.d.ts","sourceRoot":"","sources":["../../src/common/discriminator.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,MAAM,GAAG,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discriminator.js","sourceRoot":"","sources":["../../src/common/discriminator.ts"],"names":[],"mappings":"AAAA,OAAO;AACP,+BAA+B"}
|
package/dist/common/logger.d.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pluggable logger interface
|
|
3
3
|
*/
|
|
4
|
-
export
|
|
5
|
-
debug(...data:
|
|
6
|
-
info(...data:
|
|
7
|
-
warn(...data:
|
|
8
|
-
error(...data:
|
|
9
|
-
}
|
|
4
|
+
export type QwsLogger = {
|
|
5
|
+
debug(...data: unknown[]): void;
|
|
6
|
+
info(...data: unknown[]): void;
|
|
7
|
+
warn(...data: unknown[]): void;
|
|
8
|
+
error(...data: unknown[]): void;
|
|
9
|
+
};
|
|
10
10
|
export declare class QwsLoggerWrapper implements QwsLogger {
|
|
11
11
|
backend: QwsLogger;
|
|
12
12
|
constructor(logger?: QwsLogger);
|
|
13
|
-
debug(...data:
|
|
14
|
-
info(...data:
|
|
15
|
-
warn(...data:
|
|
16
|
-
error(...data:
|
|
13
|
+
debug(...data: unknown[]): void;
|
|
14
|
+
info(...data: unknown[]): void;
|
|
15
|
+
warn(...data: unknown[]): void;
|
|
16
|
+
error(...data: unknown[]): void;
|
|
17
17
|
/**
|
|
18
18
|
* Overwrite default logger used by qws, which is the console.
|
|
19
19
|
* Allows plugging of external tools, such as yall2
|
|
@@ -29,3 +29,4 @@ export default logger;
|
|
|
29
29
|
* Export setBackend method for easy external setup
|
|
30
30
|
*/
|
|
31
31
|
export declare const setQwsLoggingBackend: (newBackend: QwsLogger) => void;
|
|
32
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/common/logger.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,qBAAa,gBAAiB,YAAW,SAAS;IAChD,OAAO,EAAE,SAAS,CAAC;gBAEP,MAAM,GAAE,SAAmB;IAKvC,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI9B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/B;;;OAGG;IACH,UAAU,CAAC,UAAU,EAAE,SAAS,GAAG,IAAI;CAGxC;AAED;;GAEG;AACH,QAAA,MAAM,MAAM,kBAAyB,CAAC;AACtC,eAAe,MAAM,CAAC;AAEtB;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,YAAY,SAAS,KAAG,IAE5D,CAAC"}
|
package/dist/common/logger.js
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.setQwsLoggingBackend = exports.QwsLoggerWrapper = void 0;
|
|
7
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
8
|
-
const auto_bind_1 = __importDefault(require("auto-bind"));
|
|
9
|
-
class QwsLoggerWrapper {
|
|
1
|
+
import autoBind from 'auto-bind';
|
|
2
|
+
export class QwsLoggerWrapper {
|
|
10
3
|
constructor(logger = console) {
|
|
11
4
|
this.backend = logger;
|
|
12
|
-
(
|
|
5
|
+
autoBind(this);
|
|
13
6
|
}
|
|
14
7
|
debug(...data) {
|
|
15
8
|
this.backend.debug(...data);
|
|
@@ -31,13 +24,15 @@ class QwsLoggerWrapper {
|
|
|
31
24
|
this.backend = newBackend;
|
|
32
25
|
}
|
|
33
26
|
}
|
|
34
|
-
exports.QwsLoggerWrapper = QwsLoggerWrapper;
|
|
35
27
|
/**
|
|
36
28
|
* Export default instance
|
|
37
29
|
*/
|
|
38
30
|
const logger = new QwsLoggerWrapper();
|
|
39
|
-
|
|
31
|
+
export default logger;
|
|
40
32
|
/**
|
|
41
33
|
* Export setBackend method for easy external setup
|
|
42
34
|
*/
|
|
43
|
-
|
|
35
|
+
export const setQwsLoggingBackend = (newBackend) => {
|
|
36
|
+
logger.setBackend(newBackend);
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/common/logger.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,WAAW,CAAC;AAYjC,MAAM,OAAO,gBAAgB;IAG3B,YAAY,SAAoB,OAAO;QACrC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,CAAC,GAAG,IAAe;QACrB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,GAAG,IAAe;QACtB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,UAAqB;QAC9B,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC;IAC5B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;AACtC,eAAe,MAAM,CAAC;AAEtB;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,UAAqB,EAAQ,EAAE;IAClE,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC,CAAC"}
|
package/dist/common/message.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* - next n bytes: base64(json)-encoded headers
|
|
5
5
|
* - remaining bytes: actual body - could be binary or base64(json), denoted in headers
|
|
6
6
|
*/
|
|
7
|
-
import { Binary } from './discriminator';
|
|
7
|
+
import { Binary } from './discriminator.js';
|
|
8
8
|
/**
|
|
9
9
|
* Denotes message type, must be included in header.
|
|
10
10
|
* 'bin' - payload message with binary body
|
|
@@ -12,26 +12,18 @@ import { Binary } from './discriminator';
|
|
|
12
12
|
* 'ready' - ready message sent after connection and setup
|
|
13
13
|
* 'ack' - acknowledgment message for a payload message received from other side
|
|
14
14
|
* 'err' - error
|
|
15
|
+
* 'ping' - heartbeat request, answered by a 'pong' from the other side
|
|
16
|
+
* 'pong' - heartbeat answer
|
|
15
17
|
*/
|
|
16
|
-
export
|
|
18
|
+
export type QwsMessageType = 'bin' | 'json' | 'ready' | 'ack' | 'err' | 'ping' | 'pong';
|
|
17
19
|
/**
|
|
18
20
|
* Headers are sent in base64(json) format.
|
|
19
21
|
*/
|
|
20
|
-
export
|
|
21
|
-
/**
|
|
22
|
-
* Other X-headers
|
|
23
|
-
*/
|
|
24
|
-
[key: string]: unknown;
|
|
25
|
-
};
|
|
22
|
+
export type QwsMessageExtraHeaders = Record<string, unknown>;
|
|
26
23
|
/**
|
|
27
24
|
* Path parameters decodable with route-recognizer when using routed messages.
|
|
28
25
|
*/
|
|
29
|
-
export
|
|
30
|
-
/**
|
|
31
|
-
* Other X-headers
|
|
32
|
-
*/
|
|
33
|
-
[key: string]: string;
|
|
34
|
-
};
|
|
26
|
+
export type QwsParams = Record<string, string>;
|
|
35
27
|
/**
|
|
36
28
|
* Message types
|
|
37
29
|
*/
|
|
@@ -39,7 +31,7 @@ export declare type QwsParams = {
|
|
|
39
31
|
* Binary payload messages
|
|
40
32
|
* Contain binary body (like video data)
|
|
41
33
|
*/
|
|
42
|
-
export
|
|
34
|
+
export type BinaryQwsMessageHeaders = QwsMessageExtraHeaders & {
|
|
43
35
|
type: 'bin';
|
|
44
36
|
/**
|
|
45
37
|
* Message index in order. Helps in acknowledgments
|
|
@@ -50,7 +42,7 @@ export declare type BinaryQwsMessageHeaders = QwsMessageExtraHeaders & {
|
|
|
50
42
|
*/
|
|
51
43
|
route?: string;
|
|
52
44
|
};
|
|
53
|
-
export
|
|
45
|
+
export type BinaryQwsMessage = {
|
|
54
46
|
headers: BinaryQwsMessageHeaders;
|
|
55
47
|
body: Binary;
|
|
56
48
|
};
|
|
@@ -58,7 +50,7 @@ export declare type BinaryQwsMessage = {
|
|
|
58
50
|
* JSON payload message
|
|
59
51
|
* Contain base64-JSON encoded data
|
|
60
52
|
*/
|
|
61
|
-
export
|
|
53
|
+
export type JsonQwsMessageHeaders = QwsMessageExtraHeaders & {
|
|
62
54
|
type: 'json';
|
|
63
55
|
/**
|
|
64
56
|
* Message index in order. Helps in acknowledgments
|
|
@@ -69,7 +61,7 @@ export declare type JsonQwsMessageHeaders = QwsMessageExtraHeaders & {
|
|
|
69
61
|
*/
|
|
70
62
|
route?: string;
|
|
71
63
|
};
|
|
72
|
-
export
|
|
64
|
+
export type JsonQwsMessage = {
|
|
73
65
|
headers: JsonQwsMessageHeaders;
|
|
74
66
|
body: Record<string, unknown>;
|
|
75
67
|
};
|
|
@@ -78,47 +70,59 @@ export declare type JsonQwsMessage = {
|
|
|
78
70
|
* Sent back after successful connect, signalling we are ready to receive events
|
|
79
71
|
* Optionally contains a message index denoting how many messages we already have received previously
|
|
80
72
|
*/
|
|
81
|
-
export
|
|
73
|
+
export type ReadyQwsMessageHeaders = QwsMessageExtraHeaders & {
|
|
82
74
|
type: 'ready';
|
|
83
75
|
/**
|
|
84
76
|
* Message index we have already received previously that may be omitted.
|
|
85
77
|
*/
|
|
86
78
|
readyIdx: number;
|
|
87
79
|
};
|
|
88
|
-
export
|
|
80
|
+
export type ReadyQwsMessage = {
|
|
89
81
|
headers: ReadyQwsMessageHeaders;
|
|
90
82
|
};
|
|
91
83
|
/**
|
|
92
84
|
* Acknowledgment message
|
|
93
85
|
* Sent back for every payload message
|
|
94
86
|
*/
|
|
95
|
-
export
|
|
87
|
+
export type AckQwsMessageHeaders = {
|
|
96
88
|
type: 'ack';
|
|
97
89
|
/**
|
|
98
90
|
* Message index from other side we are acknowledging
|
|
99
91
|
*/
|
|
100
92
|
ackIdx: number;
|
|
101
93
|
};
|
|
102
|
-
export
|
|
94
|
+
export type AckQwsMessage = {
|
|
103
95
|
headers: AckQwsMessageHeaders;
|
|
104
96
|
};
|
|
105
97
|
/**
|
|
106
98
|
* Error message
|
|
107
99
|
* Sent back if processing a message is unsuccessful
|
|
108
100
|
*/
|
|
109
|
-
export
|
|
101
|
+
export type ErrorQwsMessageHeaders = {
|
|
110
102
|
type: 'err';
|
|
111
103
|
/**
|
|
112
104
|
* Message of error
|
|
113
105
|
*/
|
|
114
106
|
error: string;
|
|
115
107
|
};
|
|
116
|
-
export
|
|
108
|
+
export type ErrorQwsMessage = {
|
|
117
109
|
headers: ErrorQwsMessageHeaders;
|
|
118
110
|
};
|
|
111
|
+
/**
|
|
112
|
+
* Heartbeat messages
|
|
113
|
+
* Used where protocol-level pings are not available (the browser).
|
|
114
|
+
* Peers that don't know these types ignore them.
|
|
115
|
+
*/
|
|
116
|
+
export type HeartbeatQwsMessageHeaders = {
|
|
117
|
+
type: 'ping' | 'pong';
|
|
118
|
+
};
|
|
119
|
+
export type HeartbeatQwsMessage = {
|
|
120
|
+
headers: HeartbeatQwsMessageHeaders;
|
|
121
|
+
};
|
|
119
122
|
/**
|
|
120
123
|
* Common names for WSQ message
|
|
121
124
|
*/
|
|
122
|
-
export
|
|
123
|
-
export
|
|
124
|
-
export
|
|
125
|
+
export type PayloadQwsMessage = BinaryQwsMessage | JsonQwsMessage;
|
|
126
|
+
export type QwsMessage = BinaryQwsMessage | JsonQwsMessage | ReadyQwsMessage | AckQwsMessage | ErrorQwsMessage | HeartbeatQwsMessage;
|
|
127
|
+
export type QwsMessageHeader = BinaryQwsMessageHeaders | JsonQwsMessageHeaders | ReadyQwsMessageHeaders | AckQwsMessageHeaders | ErrorQwsMessageHeaders | HeartbeatQwsMessageHeaders;
|
|
128
|
+
//# sourceMappingURL=message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/common/message.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAExF;;GAEG;AAEH,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE7D;;GAEG;AAEH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE/C;;GAEG;AAEH;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,sBAAsB,GAAG;IAC7D,IAAI,EAAE,KAAK,CAAC;IACZ;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,uBAAuB,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;GAGG;AAEH,MAAM,MAAM,qBAAqB,GAAG,sBAAsB,GAAG;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,qBAAqB,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAEF;;;;GAIG;AAEH,MAAM,MAAM,sBAAsB,GAAG,sBAAsB,GAAG;IAC5D,IAAI,EAAE,OAAO,CAAC;IAEd;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,sBAAsB,CAAC;CACjC,CAAC;AAEF;;;GAGG;AAEH,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,KAAK,CAAC;IAEZ;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,oBAAoB,CAAC;CAC/B,CAAC;AAEF;;;GAGG;AAEH,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,KAAK,CAAC;IAEZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,sBAAsB,CAAC;CACjC,CAAC;AAEF;;;;GAIG;AAEH,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,0BAA0B,CAAC;CACrC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG,cAAc,CAAC;AAClE,MAAM,MAAM,UAAU,GACpB,gBAAgB,GAAG,cAAc,GAAG,eAAe,GAAG,aAAa,GAAG,eAAe,GAAG,mBAAmB,CAAC;AAC9G,MAAM,MAAM,gBAAgB,GACxB,uBAAuB,GACvB,qBAAqB,GACrB,sBAAsB,GACtB,oBAAoB,GACpB,sBAAsB,GACtB,0BAA0B,CAAC"}
|
package/dist/common/message.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Custom message format for WSQ messages:
|
|
4
3
|
* - first 4 bytes: uint32 saying how long the header information is
|
|
5
4
|
* - next n bytes: base64(json)-encoded headers
|
|
6
5
|
* - remaining bytes: actual body - could be binary or base64(json), denoted in headers
|
|
7
6
|
*/
|
|
8
|
-
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/common/message.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
export declare const parseUrl: (urlString: string) => Record<string, string>;
|
|
2
|
-
export declare const parseQuery: (search: string) => Record<string, string>;
|
|
3
1
|
export declare const addQueryParamsToUrl: (urlString: string, params: Record<string, unknown>) => string;
|
|
4
|
-
|
|
5
|
-
export declare const toUrlParams: (query?: {}, defaultParams?: {}) => string;
|
|
2
|
+
//# sourceMappingURL=queryparser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queryparser.d.ts","sourceRoot":"","sources":["../../src/common/queryparser.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,mBAAmB,GAAI,WAAW,MAAM,EAAE,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAQxF,CAAC"}
|