@glade-chat/glade.js 0.1.0 → 0.1.1
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 +2 -3
- package/package.json +1 -1
- package/src/client/Client.js +1 -0
- package/src/gateway/Gateway.js +26 -0
- package/src/util/Constants.js +6 -0
- package/types/index.d.ts +3 -0
package/README.md
CHANGED
|
@@ -12,14 +12,13 @@ A powerful, fully-typed Node.js library for the [Glade](https://glade.chat) API
|
|
|
12
12
|
|
|
13
13
|
## About
|
|
14
14
|
|
|
15
|
-
glade.js is an object-oriented library that makes it easy to interact with Glade
|
|
16
|
-
Rooms, Messages, Members, Roles, DMs, friends, presence, and voice
|
|
15
|
+
glade.js is an object-oriented library that makes it easy to interact with Glade - Houses,
|
|
16
|
+
Rooms, Messages, Members, Roles, DMs, friends, presence, and voice - over REST and the
|
|
17
17
|
real-time gateway.
|
|
18
18
|
|
|
19
19
|
- Object-oriented
|
|
20
20
|
- Cache-backed and event-driven
|
|
21
21
|
- Handles login and token refresh for you
|
|
22
|
-
- First-class TypeScript types, zero build step (pure ESM)
|
|
23
22
|
|
|
24
23
|
## Installation
|
|
25
24
|
|
package/package.json
CHANGED
package/src/client/Client.js
CHANGED
package/src/gateway/Gateway.js
CHANGED
|
@@ -21,6 +21,7 @@ export class Gateway {
|
|
|
21
21
|
* @param {(err: Error) => void} [opts.onError]
|
|
22
22
|
* @param {(msg: string) => void} [opts.debug]
|
|
23
23
|
* @param {object} [opts.ws] Extra socket.io-client options.
|
|
24
|
+
* @param {number} [opts.heartbeatMs] Presence heartbeat interval; <=0 disables it.
|
|
24
25
|
*/
|
|
25
26
|
constructor(opts) {
|
|
26
27
|
this.url = opts.url;
|
|
@@ -42,6 +43,10 @@ export class Gateway {
|
|
|
42
43
|
this._handshakeRefreshAttempts = 0;
|
|
43
44
|
/** Cap on consecutive handshake refreshes to avoid a reconnect loop. */
|
|
44
45
|
this._maxHandshakeRefresh = opts.maxHandshakeRefresh ?? 5;
|
|
46
|
+
/** Presence heartbeat interval (ms); the server offlines us without it. */
|
|
47
|
+
this._heartbeatMs = opts.heartbeatMs ?? 30_000;
|
|
48
|
+
/** @type {ReturnType<typeof setInterval> | null} */
|
|
49
|
+
this._heartbeatTimer = null;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
/** Whether the underlying socket is currently connected. */
|
|
@@ -71,11 +76,13 @@ export class Gateway {
|
|
|
71
76
|
this.id = this.socket.id;
|
|
72
77
|
this._handshakeRefreshAttempts = 0;
|
|
73
78
|
this.#debug(`Connected (socket ${this.id})`);
|
|
79
|
+
this.#startHeartbeat();
|
|
74
80
|
this.onConnect();
|
|
75
81
|
});
|
|
76
82
|
|
|
77
83
|
this.socket.on('disconnect', (reason) => {
|
|
78
84
|
this.#debug(`Disconnected: ${reason}`);
|
|
85
|
+
this.#stopHeartbeat();
|
|
79
86
|
this.onDisconnect(reason);
|
|
80
87
|
});
|
|
81
88
|
|
|
@@ -113,6 +120,7 @@ export class Gateway {
|
|
|
113
120
|
|
|
114
121
|
/** Closes the gateway connection. */
|
|
115
122
|
disconnect() {
|
|
123
|
+
this.#stopHeartbeat();
|
|
116
124
|
if (this.socket) {
|
|
117
125
|
this.socket.disconnect();
|
|
118
126
|
this.socket = null;
|
|
@@ -120,6 +128,24 @@ export class Gateway {
|
|
|
120
128
|
}
|
|
121
129
|
}
|
|
122
130
|
|
|
131
|
+
/** Periodically tell the server we're alive so it keeps us marked online. */
|
|
132
|
+
#startHeartbeat() {
|
|
133
|
+
this.#stopHeartbeat();
|
|
134
|
+
if (!(this._heartbeatMs > 0)) return;
|
|
135
|
+
this._heartbeatTimer = setInterval(() => {
|
|
136
|
+
if (this.socket?.connected) this.socket.emit('presence:heartbeat');
|
|
137
|
+
}, this._heartbeatMs);
|
|
138
|
+
// Don't let the heartbeat keep the process alive on its own.
|
|
139
|
+
if (typeof this._heartbeatTimer.unref === 'function') this._heartbeatTimer.unref();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
#stopHeartbeat() {
|
|
143
|
+
if (this._heartbeatTimer) {
|
|
144
|
+
clearInterval(this._heartbeatTimer);
|
|
145
|
+
this._heartbeatTimer = null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
123
149
|
/**
|
|
124
150
|
* Emits an event to the server without waiting for an acknowledgement.
|
|
125
151
|
* @param {string} event
|
package/src/util/Constants.js
CHANGED
|
@@ -18,6 +18,11 @@ export const DefaultOptions = {
|
|
|
18
18
|
* Keeps a long-running gateway connection authenticated.
|
|
19
19
|
*/
|
|
20
20
|
refreshSkewMs: 60_000,
|
|
21
|
+
/**
|
|
22
|
+
* How often (ms) to send a presence heartbeat so the server keeps the
|
|
23
|
+
* connection marked online. Must stay below the server's liveness TTL.
|
|
24
|
+
*/
|
|
25
|
+
heartbeatMs: 30_000,
|
|
21
26
|
/** Whether to cache structures received from REST and the gateway. */
|
|
22
27
|
cache: true,
|
|
23
28
|
/**
|
|
@@ -132,6 +137,7 @@ export const GatewayCommand = {
|
|
|
132
137
|
TypingStart: 'typing:start',
|
|
133
138
|
TypingStop: 'typing:stop',
|
|
134
139
|
PresenceSet: 'presence:set',
|
|
140
|
+
PresenceHeartbeat: 'presence:heartbeat',
|
|
135
141
|
VoiceJoin: 'voice:join',
|
|
136
142
|
VoiceLeave: 'voice:leave',
|
|
137
143
|
VoiceSync: 'voice:sync',
|
package/types/index.d.ts
CHANGED
|
@@ -51,6 +51,8 @@ export interface ClientOptions {
|
|
|
51
51
|
autoRefresh?: boolean;
|
|
52
52
|
/** Ms before token expiry to refresh proactively. Default `60000`. */
|
|
53
53
|
refreshSkewMs?: number;
|
|
54
|
+
/** Presence heartbeat interval in ms; keeps the connection marked online. Default `30000`. */
|
|
55
|
+
heartbeatMs?: number;
|
|
54
56
|
/** Cache structures from REST/gateway. Default `true`. */
|
|
55
57
|
cache?: boolean;
|
|
56
58
|
/** Auto-subscribe to cached rooms' realtime events on ready. Default `true`. */
|
|
@@ -232,6 +234,7 @@ export class Gateway {
|
|
|
232
234
|
debug?: (msg: string) => void;
|
|
233
235
|
ws?: Record<string, unknown>;
|
|
234
236
|
maxHandshakeRefresh?: number;
|
|
237
|
+
heartbeatMs?: number;
|
|
235
238
|
});
|
|
236
239
|
socket: Socket | null;
|
|
237
240
|
id: string | null;
|