streamops-twitch-connector 0.2.1 → 0.3.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 +7 -0
- package/dist/auth/token-manager.d.ts +3 -0
- package/dist/auth/token-manager.d.ts.map +1 -1
- package/dist/auth/token-manager.js +29 -6
- package/dist/auth/token-manager.js.map +1 -1
- package/dist/eventsub/eventsub-client.d.ts +6 -0
- package/dist/eventsub/eventsub-client.d.ts.map +1 -1
- package/dist/eventsub/eventsub-client.js +69 -9
- package/dist/eventsub/eventsub-client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -87,6 +87,8 @@ await twitch.connectEventSub();
|
|
|
87
87
|
- `twitch.tokens.refresh()` is available to request a refresh explicitly.
|
|
88
88
|
Listen to `twitch.tokens.onAuthError()` for background validation failures;
|
|
89
89
|
a `reauthentication_required` error means the user must authorize again.
|
|
90
|
+
Background validation retries with exponential backoff from one to five
|
|
91
|
+
minutes, and errors are logged when no handler is registered.
|
|
90
92
|
The connector cannot complete that interactive step itself: the consuming
|
|
91
93
|
app should subscribe to `onAuthError()` and prompt the user to run the
|
|
92
94
|
existing `startLogin()` / `completeLogin()` flow. Restarting the app is not
|
|
@@ -100,6 +102,11 @@ await twitch.connectEventSub();
|
|
|
100
102
|
- Helix requests automatically include the Client ID and access token.
|
|
101
103
|
- Chat messages are received through EventSub and sent through Helix.
|
|
102
104
|
- EventSub subscriptions use the active WebSocket session ID.
|
|
105
|
+
- Register `twitch.eventSub.onError()` to receive unexpected disconnects,
|
|
106
|
+
subscription revocations, and processing failures. If a session handler
|
|
107
|
+
fails (for example, when subscribing after a reconnect), the connector
|
|
108
|
+
reports the error and reconnects so session handlers can run again.
|
|
109
|
+
Reconnect attempts back off from two to thirty seconds.
|
|
103
110
|
|
|
104
111
|
## Notes
|
|
105
112
|
|
|
@@ -10,6 +10,7 @@ export declare class TokenManager {
|
|
|
10
10
|
private validationTimer;
|
|
11
11
|
private lastValidatedAt;
|
|
12
12
|
private lastAuthError;
|
|
13
|
+
private validationFailureCount;
|
|
13
14
|
private validationMonitoring;
|
|
14
15
|
private readonly authErrorHandlers;
|
|
15
16
|
constructor(config: Pick<TwitchConnectorConfig, 'clientId' | 'clientSecret' | 'scopes' | 'fetch'>, tokenStore: TwitchTokenStore, deviceCodeFlow: DeviceCodeFlow);
|
|
@@ -35,6 +36,8 @@ export declare class TokenManager {
|
|
|
35
36
|
private validateCurrentTokens;
|
|
36
37
|
private validate;
|
|
37
38
|
private scheduleValidation;
|
|
39
|
+
private notifyAuthError;
|
|
40
|
+
private scheduleValidationRetry;
|
|
38
41
|
private stopValidationTimer;
|
|
39
42
|
private refreshTokens;
|
|
40
43
|
private performRefresh;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAkBvE,qBAAa,YAAY;IAWrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAIvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAfjC,OAAO,CAAC,cAAc,CAAsC;IAC5D,OAAO,CAAC,iBAAiB,CAA8C;IACvE,OAAO,CAAC,eAAe,CAA8C;IACrE,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,oBAAoB,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqC;gBAGpD,MAAM,EAAE,IAAI,CAC3B,qBAAqB,EACrB,UAAU,GAAG,cAAc,GAAG,QAAQ,GAAG,OAAO,CACjD,EACgB,UAAU,EAAE,gBAAgB,EAC5B,cAAc,EAAE,cAAc;IAGjD,OAAO,KAAK,OAAO,GAElB;IAED,iFAAiF;IAC3E,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC;IAUlC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAKjC,iBAAiB,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAIxD,8EAA8E;IACxE,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC;IAUtC;;;OAGG;IACG,wBAAwB,CAC5B,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,MAAM,CAAC;IAeZ,UAAU;IAIV,aAAa,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAmB1D,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAS7B,WAAW,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI;IAKxD,IAAI,SAAS,IAAI,KAAK,GAAG,IAAI,CAE5B;IAED,OAAO,IAAI,IAAI;YAKD,aAAa;YA2Bb,qBAAqB;IAuDnC,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,kBAAkB;IA+B1B,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;YAYP,cAAc;CAqD7B"}
|
|
@@ -3,6 +3,8 @@ const TWITCH_VALIDATE_URL = 'https://id.twitch.tv/oauth2/validate';
|
|
|
3
3
|
const TWITCH_TOKEN_URL = 'https://id.twitch.tv/oauth2/token';
|
|
4
4
|
const TOKEN_VALIDATION_INTERVAL_MS = 50 * 60 * 1000;
|
|
5
5
|
const TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1000;
|
|
6
|
+
const INITIAL_VALIDATION_RETRY_MS = 60 * 1000;
|
|
7
|
+
const MAX_VALIDATION_RETRY_MS = 5 * 60 * 1000;
|
|
6
8
|
export class TokenManager {
|
|
7
9
|
config;
|
|
8
10
|
tokenStore;
|
|
@@ -12,6 +14,7 @@ export class TokenManager {
|
|
|
12
14
|
validationTimer = null;
|
|
13
15
|
lastValidatedAt = 0;
|
|
14
16
|
lastAuthError = null;
|
|
17
|
+
validationFailureCount = 0;
|
|
15
18
|
validationMonitoring = true;
|
|
16
19
|
authErrorHandlers = new Set();
|
|
17
20
|
constructor(config, tokenStore, deviceCodeFlow) {
|
|
@@ -71,7 +74,10 @@ export class TokenManager {
|
|
|
71
74
|
scopes: response.scope,
|
|
72
75
|
};
|
|
73
76
|
await this.tokenStore.save(tokens);
|
|
77
|
+
this.stopValidationTimer();
|
|
74
78
|
this.lastValidatedAt = 0;
|
|
79
|
+
this.lastAuthError = null;
|
|
80
|
+
this.validationFailureCount = 0;
|
|
75
81
|
this.validationMonitoring = true;
|
|
76
82
|
return tokens;
|
|
77
83
|
}
|
|
@@ -80,6 +86,7 @@ export class TokenManager {
|
|
|
80
86
|
this.stopValidationTimer();
|
|
81
87
|
this.lastValidatedAt = 0;
|
|
82
88
|
this.lastAuthError = null;
|
|
89
|
+
this.validationFailureCount = 0;
|
|
83
90
|
await this.tokenStore.clear();
|
|
84
91
|
}
|
|
85
92
|
onAuthError(handler) {
|
|
@@ -140,6 +147,7 @@ export class TokenManager {
|
|
|
140
147
|
}
|
|
141
148
|
this.lastValidatedAt = Date.now();
|
|
142
149
|
this.lastAuthError = null;
|
|
150
|
+
this.validationFailureCount = 0;
|
|
143
151
|
this.scheduleValidation(expiresAt);
|
|
144
152
|
return validated;
|
|
145
153
|
}
|
|
@@ -163,17 +171,32 @@ export class TokenManager {
|
|
|
163
171
|
.catch((error) => {
|
|
164
172
|
const authError = error instanceof Error ? error : new Error(String(error));
|
|
165
173
|
this.lastAuthError = authError;
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
this.scheduleValidation(Date.now() +
|
|
170
|
-
TOKEN_VALIDATION_INTERVAL_MS +
|
|
171
|
-
TOKEN_REFRESH_BUFFER_MS);
|
|
174
|
+
this.notifyAuthError(authError);
|
|
175
|
+
this.scheduleValidationRetry();
|
|
172
176
|
});
|
|
173
177
|
}, delay);
|
|
174
178
|
const timer = this.validationTimer;
|
|
175
179
|
timer.unref?.();
|
|
176
180
|
}
|
|
181
|
+
notifyAuthError(error) {
|
|
182
|
+
if (this.authErrorHandlers.size === 0) {
|
|
183
|
+
console.error('[Twitch] Background token validation failed:', error);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
for (const handler of this.authErrorHandlers) {
|
|
187
|
+
try {
|
|
188
|
+
handler(error);
|
|
189
|
+
}
|
|
190
|
+
catch (handlerError) {
|
|
191
|
+
console.error('[Twitch] Auth error handler failed:', handlerError);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
scheduleValidationRetry() {
|
|
196
|
+
const delay = Math.min(INITIAL_VALIDATION_RETRY_MS * 2 ** this.validationFailureCount, MAX_VALIDATION_RETRY_MS);
|
|
197
|
+
this.validationFailureCount += 1;
|
|
198
|
+
this.scheduleValidation(Date.now() + delay + TOKEN_REFRESH_BUFFER_MS);
|
|
199
|
+
}
|
|
177
200
|
stopValidationTimer() {
|
|
178
201
|
if (this.validationTimer) {
|
|
179
202
|
clearTimeout(this.validationTimer);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAIxD,MAAM,mBAAmB,GAAG,sCAAsC,CAAC;AACnE,MAAM,gBAAgB,GAAG,mCAAmC,CAAC;AAU7D,MAAM,4BAA4B,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACpD,MAAM,uBAAuB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE9C,MAAM,OAAO,YAAY;
|
|
1
|
+
{"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { EventSubConnectionState, EventSubNotificationHandler } from './types.js';
|
|
2
2
|
export type EventSubSessionHandler = (sessionId: string, isReconnectHandover: boolean) => Promise<void> | void;
|
|
3
|
+
export type EventSubErrorHandler = (error: Error) => void;
|
|
3
4
|
export declare class EventSubClient {
|
|
4
5
|
private readonly onStateChange?;
|
|
5
6
|
private socket;
|
|
@@ -8,21 +9,26 @@ export declare class EventSubClient {
|
|
|
8
9
|
private keepaliveTimeoutSeconds;
|
|
9
10
|
private keepaliveTimer;
|
|
10
11
|
private reconnectTimer;
|
|
12
|
+
private reconnectAttempts;
|
|
11
13
|
private intentionalClose;
|
|
12
14
|
private state;
|
|
13
15
|
private readonly handlers;
|
|
14
16
|
private readonly sessionHandlers;
|
|
17
|
+
private readonly errorHandlers;
|
|
15
18
|
constructor(onStateChange?: ((state: EventSubConnectionState) => void) | undefined);
|
|
16
19
|
get connectionState(): EventSubConnectionState;
|
|
17
20
|
get currentSessionId(): string | null;
|
|
18
21
|
onNotification(handler: EventSubNotificationHandler): () => void;
|
|
19
22
|
onSession(handler: EventSubSessionHandler): () => void;
|
|
23
|
+
onError(handler: EventSubErrorHandler): () => void;
|
|
20
24
|
connect(): Promise<void>;
|
|
21
25
|
disconnect(): Promise<void>;
|
|
22
26
|
private openSocket;
|
|
23
27
|
private handleMessage;
|
|
24
28
|
private resetKeepaliveTimer;
|
|
25
29
|
private scheduleReconnect;
|
|
30
|
+
private reconnectAfterSessionError;
|
|
31
|
+
private reportError;
|
|
26
32
|
private setState;
|
|
27
33
|
private clearKeepaliveTimer;
|
|
28
34
|
private clearReconnectTimer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventsub-client.d.ts","sourceRoot":"","sources":["../../src/eventsub/eventsub-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,uBAAuB,EAEvB,2BAA2B,EAC5B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"eventsub-client.d.ts","sourceRoot":"","sources":["../../src/eventsub/eventsub-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,uBAAuB,EAEvB,2BAA2B,EAC5B,MAAM,YAAY,CAAC;AAOpB,MAAM,MAAM,sBAAsB,GAAG,CACnC,SAAS,EAAE,MAAM,EACjB,mBAAmB,EAAE,OAAO,KACzB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1B,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAE1D,qBAAa,cAAc;IAgBvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAfjC,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,uBAAuB,CAAM;IACrC,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,KAAK,CAA2C;IAExD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IACnE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqC;IACrE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmC;gBAG9C,aAAa,CAAC,GAAE,CAC/B,KAAK,EAAE,uBAAuB,KAC3B,IAAI,aAAA;IAGX,IAAI,eAAe,IAAI,uBAAuB,CAE7C;IAED,IAAI,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEpC;IAED,cAAc,CAAC,OAAO,EAAE,2BAA2B,GAAG,MAAM,IAAI;IAKhE,SAAS,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,IAAI;IAKtD,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,IAAI;IAK5C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBjC,OAAO,CAAC,UAAU;YAsFJ,aAAa;IAkH3B,OAAO,CAAC,mBAAmB;IAsB3B,OAAO,CAAC,iBAAiB;IA2BzB,OAAO,CAAC,0BAA0B;IAYlC,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,WAAW;CAIpB"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { TwitchError } from '../errors/twitch-error.js';
|
|
2
2
|
const EVENTSUB_URL = 'wss://eventsub.wss.twitch.tv/ws';
|
|
3
|
+
const INITIAL_RECONNECT_DELAY_MS = 2_000;
|
|
4
|
+
const MAX_RECONNECT_DELAY_MS = 30_000;
|
|
3
5
|
export class EventSubClient {
|
|
4
6
|
onStateChange;
|
|
5
7
|
socket = null;
|
|
@@ -8,10 +10,12 @@ export class EventSubClient {
|
|
|
8
10
|
keepaliveTimeoutSeconds = 10;
|
|
9
11
|
keepaliveTimer = null;
|
|
10
12
|
reconnectTimer = null;
|
|
13
|
+
reconnectAttempts = 0;
|
|
11
14
|
intentionalClose = false;
|
|
12
15
|
state = 'disconnected';
|
|
13
16
|
handlers = new Set();
|
|
14
17
|
sessionHandlers = new Set();
|
|
18
|
+
errorHandlers = new Set();
|
|
15
19
|
constructor(onStateChange) {
|
|
16
20
|
this.onStateChange = onStateChange;
|
|
17
21
|
}
|
|
@@ -29,6 +33,10 @@ export class EventSubClient {
|
|
|
29
33
|
this.sessionHandlers.add(handler);
|
|
30
34
|
return () => this.sessionHandlers.delete(handler);
|
|
31
35
|
}
|
|
36
|
+
onError(handler) {
|
|
37
|
+
this.errorHandlers.add(handler);
|
|
38
|
+
return () => this.errorHandlers.delete(handler);
|
|
39
|
+
}
|
|
32
40
|
async connect() {
|
|
33
41
|
this.intentionalClose = false;
|
|
34
42
|
this.clearReconnectTimer();
|
|
@@ -64,6 +72,7 @@ export class EventSubClient {
|
|
|
64
72
|
}
|
|
65
73
|
const previousSocket = this.socket;
|
|
66
74
|
this.socket = socket;
|
|
75
|
+
let socketErrorReported = false;
|
|
67
76
|
// Logging suppressed; retain original connection behavior.
|
|
68
77
|
void previousSocket;
|
|
69
78
|
socket.addEventListener('open', () => {
|
|
@@ -77,21 +86,27 @@ export class EventSubClient {
|
|
|
77
86
|
return;
|
|
78
87
|
}
|
|
79
88
|
const raw = String(message.data);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// EventSub processing errors suppressed.
|
|
89
|
+
void this.handleMessage(raw, isReconnectHandover).catch((error) => {
|
|
90
|
+
this.reportError(error);
|
|
83
91
|
});
|
|
84
92
|
});
|
|
85
93
|
socket.addEventListener('error', () => {
|
|
86
|
-
|
|
94
|
+
if (this.socket !== socket) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
socketErrorReported = true;
|
|
98
|
+
this.reportError(new TwitchError('Twitch EventSub WebSocket encountered a connection error.'));
|
|
87
99
|
});
|
|
88
|
-
socket.addEventListener('close', (
|
|
100
|
+
socket.addEventListener('close', (event) => {
|
|
89
101
|
if (this.socket !== socket) {
|
|
90
102
|
return;
|
|
91
103
|
}
|
|
92
104
|
this.socket = null;
|
|
93
105
|
this.clearKeepaliveTimer();
|
|
94
106
|
if (!this.intentionalClose) {
|
|
107
|
+
if (!socketErrorReported) {
|
|
108
|
+
this.reportError(new TwitchError(`Twitch EventSub WebSocket closed unexpectedly (code: ${event.code}${event.reason ? `, reason: ${event.reason}` : ''}).`));
|
|
109
|
+
}
|
|
95
110
|
this.setState('reconnecting');
|
|
96
111
|
this.scheduleReconnect();
|
|
97
112
|
}
|
|
@@ -118,8 +133,16 @@ export class EventSubClient {
|
|
|
118
133
|
this.reconnectUrl = null;
|
|
119
134
|
this.resetKeepaliveTimer();
|
|
120
135
|
for (const handler of this.sessionHandlers) {
|
|
121
|
-
|
|
136
|
+
try {
|
|
137
|
+
await handler(session.id, isReconnectHandover);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
this.reportError(error);
|
|
141
|
+
this.reconnectAfterSessionError();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
122
144
|
}
|
|
145
|
+
this.reconnectAttempts = 0;
|
|
123
146
|
break;
|
|
124
147
|
}
|
|
125
148
|
case 'session_keepalive':
|
|
@@ -128,6 +151,7 @@ export class EventSubClient {
|
|
|
128
151
|
case 'session_reconnect': {
|
|
129
152
|
const reconnectUrl = envelope.payload.session?.reconnect_url;
|
|
130
153
|
if (!reconnectUrl) {
|
|
154
|
+
this.reportError(new TwitchError('Twitch EventSub reconnect message did not include a reconnect URL.'));
|
|
131
155
|
return;
|
|
132
156
|
}
|
|
133
157
|
this.reconnectUrl = reconnectUrl;
|
|
@@ -149,11 +173,14 @@ export class EventSubClient {
|
|
|
149
173
|
break;
|
|
150
174
|
}
|
|
151
175
|
case 'session_reconnect_failed':
|
|
176
|
+
this.reportError(new TwitchError('Twitch EventSub session handover failed.'));
|
|
152
177
|
this.reconnectUrl = null;
|
|
153
178
|
this.scheduleReconnect();
|
|
154
179
|
break;
|
|
155
180
|
case 'revocation':
|
|
156
|
-
|
|
181
|
+
this.reportError(new TwitchError(`Twitch revoked the EventSub subscription${envelope.payload.subscription?.type
|
|
182
|
+
? ` "${envelope.payload.subscription.type}"`
|
|
183
|
+
: ''} (status: ${envelope.payload.subscription?.status ?? 'unknown'}).`));
|
|
157
184
|
break;
|
|
158
185
|
default:
|
|
159
186
|
// Unknown message logging suppressed.
|
|
@@ -165,6 +192,7 @@ export class EventSubClient {
|
|
|
165
192
|
this.keepaliveTimer = setTimeout(() => {
|
|
166
193
|
const socket = this.socket;
|
|
167
194
|
this.socket = null;
|
|
195
|
+
this.reportError(new TwitchError(`Twitch EventSub did not receive a keepalive or notification within ${this.keepaliveTimeoutSeconds} seconds.`));
|
|
168
196
|
if (socket && socket.readyState !== WebSocket.CLOSED) {
|
|
169
197
|
socket.close();
|
|
170
198
|
}
|
|
@@ -178,13 +206,45 @@ export class EventSubClient {
|
|
|
178
206
|
return;
|
|
179
207
|
}
|
|
180
208
|
this.setState('reconnecting');
|
|
209
|
+
const delay = Math.min(INITIAL_RECONNECT_DELAY_MS * 2 ** this.reconnectAttempts, MAX_RECONNECT_DELAY_MS);
|
|
210
|
+
this.reconnectAttempts += 1;
|
|
181
211
|
this.reconnectTimer = setTimeout(() => {
|
|
182
212
|
this.reconnectTimer = null;
|
|
183
213
|
this.sessionId = null;
|
|
184
214
|
if (!this.intentionalClose) {
|
|
185
|
-
|
|
215
|
+
try {
|
|
216
|
+
this.openSocket(this.reconnectUrl ?? EVENTSUB_URL);
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
this.reportError(error);
|
|
220
|
+
}
|
|
186
221
|
}
|
|
187
|
-
},
|
|
222
|
+
}, delay);
|
|
223
|
+
}
|
|
224
|
+
reconnectAfterSessionError() {
|
|
225
|
+
const socket = this.socket;
|
|
226
|
+
if (!socket || this.intentionalClose) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
this.socket = null;
|
|
230
|
+
this.clearKeepaliveTimer();
|
|
231
|
+
socket.close();
|
|
232
|
+
this.scheduleReconnect();
|
|
233
|
+
}
|
|
234
|
+
reportError(error) {
|
|
235
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
236
|
+
if (this.errorHandlers.size === 0) {
|
|
237
|
+
console.error('[EventSub] Error:', normalizedError);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
for (const handler of this.errorHandlers) {
|
|
241
|
+
try {
|
|
242
|
+
handler(normalizedError);
|
|
243
|
+
}
|
|
244
|
+
catch (handlerError) {
|
|
245
|
+
console.error('[EventSub] Error handler failed:', handlerError);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
188
248
|
}
|
|
189
249
|
setState(state) {
|
|
190
250
|
this.state = state;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventsub-client.js","sourceRoot":"","sources":["../../src/eventsub/eventsub-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,MAAM,YAAY,GAAG,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"eventsub-client.js","sourceRoot":"","sources":["../../src/eventsub/eventsub-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,MAAM,YAAY,GAAG,iCAAiC,CAAC;AACvD,MAAM,0BAA0B,GAAG,KAAK,CAAC;AACzC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAStC,MAAM,OAAO,cAAc;IAgBN;IAfX,MAAM,GAAqB,IAAI,CAAC;IAChC,YAAY,GAAkB,IAAI,CAAC;IACnC,SAAS,GAAkB,IAAI,CAAC;IAChC,uBAAuB,GAAG,EAAE,CAAC;IAC7B,cAAc,GAAyC,IAAI,CAAC;IAC5D,cAAc,GAAyC,IAAI,CAAC;IAC5D,iBAAiB,GAAG,CAAC,CAAC;IACtB,gBAAgB,GAAG,KAAK,CAAC;IACzB,KAAK,GAA4B,cAAc,CAAC;IAEvC,QAAQ,GAAG,IAAI,GAAG,EAA+B,CAAC;IAClD,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;IACpD,aAAa,GAAG,IAAI,GAAG,EAAwB,CAAC;IAEjE,YACmB,aAER;QAFQ,kBAAa,GAAb,aAAa,CAErB;IACR,CAAC;IAEJ,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,cAAc,CAAC,OAAoC;QACjD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,SAAS,CAAC,OAA+B;QACvC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,CAAC,OAA6B;QACnC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAC9B,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAE3B,IACE,IAAI,CAAC,MAAM;YACX,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,UAAU;gBAC9C,IAAI,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,CAAC,EAC5C,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAEtB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;QAC1C,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAChC,CAAC;IAEO,UAAU,CAChB,GAAW,EACX,mBAAmB,GAAG,KAAK;QAE3B,IAAI,MAAiB,CAAC;QAEtB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,sBAAsB;YACtB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAEzB,MAAM,IAAI,WAAW,CACnB,6CAA6C,EAC7C,SAAS,EACT,SAAS,EACT,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,mBAAmB,GAAG,KAAK,CAAC;QAEhC,2DAA2D;QAC3D,KAAK,cAAc,CAAC;QAEpB,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;YACnC,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,OAAqB,EAAE,EAAE;YAC3D,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAEjC,KAAK,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC,KAAK,CACrD,CAAC,KAAc,EAAE,EAAE;gBACjB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YACpC,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,mBAAmB,GAAG,IAAI,CAAC;YAC3B,IAAI,CAAC,WAAW,CACd,IAAI,WAAW,CAAC,2DAA2D,CAAC,CAC7E,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAiB,EAAE,EAAE;YACrD,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAE3B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,IAAI,CAAC,mBAAmB,EAAE,CAAC;oBACzB,IAAI,CAAC,WAAW,CACd,IAAI,WAAW,CACb,wDAAwD,KAAK,CAAC,IAAI,GAChE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAC/C,IAAI,CACL,CACF,CAAC;gBACJ,CAAC;gBACD,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAC9B,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,GAAW,EACX,mBAA4B;QAE5B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAC;QACrD,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;QAEpD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,QAAQ,WAAW,EAAE,CAAC;YACpB,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;gBAEzC,IAAI,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC;oBACjB,MAAM,IAAI,WAAW,CACnB,+DAA+D,CAChE,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC,uBAAuB;oBAC1B,OAAO,CAAC,yBAAyB,IAAI,EAAE,CAAC;gBAC1C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;gBACzB,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAE3B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC3C,IAAI,CAAC;wBACH,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,mBAAmB,CAAC,CAAC;oBACjD,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;wBACxB,IAAI,CAAC,0BAA0B,EAAE,CAAC;wBAClC,OAAO;oBACT,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;gBAC3B,MAAM;YACR,CAAC;YAED,KAAK,mBAAmB;gBACtB,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC3B,MAAM;YAER,KAAK,mBAAmB,CAAC,CAAC,CAAC;gBACzB,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC;gBAE7D,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,IAAI,CAAC,WAAW,CACd,IAAI,WAAW,CACb,oEAAoE,CACrE,CACF,CAAC;oBACF,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;gBACjC,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAE3B,+CAA+C;gBAC/C,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;gBACpC,MAAM;YACR,CAAC;YAED,KAAK,cAAc,CAAC,CAAC,CAAC;gBACpB,MAAM,gBAAgB,GACpB,QAAQ,CAAC,QAAQ,CAAC,iBAAiB;oBACnC,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC;gBAEtC,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBACtB,OAAO;gBACT,CAAC;gBAED,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACpC,MAAM,OAAO,CACX,gBAAgB,EAChB,QAAQ,CAAC,OAAO,CAAC,KAAK,EACtB,QAAQ,CACT,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC3B,MAAM;YACR,CAAC;YAED,KAAK,0BAA0B;gBAC7B,IAAI,CAAC,WAAW,CACd,IAAI,WAAW,CAAC,0CAA0C,CAAC,CAC5D,CAAC;gBACF,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;gBACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBACzB,MAAM;YAER,KAAK,YAAY;gBACf,IAAI,CAAC,WAAW,CACd,IAAI,WAAW,CACb,2CACE,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI;oBACjC,CAAC,CAAC,KAAK,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,GAAG;oBAC5C,CAAC,CAAC,EACN,aACE,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,IAAI,SAC3C,IAAI,CACL,CACF,CAAC;gBACF,MAAM;YAER;gBACE,sCAAsC;gBACtC,MAAM;QACV,CAAC;IACH,CAAC;IAEO,mBAAmB;QACzB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAE3B,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,WAAW,CACd,IAAI,WAAW,CACb,sEAAsE,IAAI,CAAC,uBAAuB,WAAW,CAC9G,CACF,CAAC;YAEF,IAAI,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;gBACrD,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC,EAAE,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;IAC1C,CAAC;IAEO,iBAAiB;QACvB,IAAI,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACjD,OAAO;QACT,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QAE9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,0BAA0B,GAAG,CAAC,IAAI,IAAI,CAAC,iBAAiB,EACxD,sBAAsB,CACvB,CAAC;QACF,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC;QAE5B,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;YACpC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YAEtB,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,IAAI,CAAC;oBACH,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,CAAC;gBACrD,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC;IAEO,0BAA0B;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACrC,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAEO,WAAW,CAAC,KAAc;QAChC,MAAM,eAAe,GACnB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAE5D,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;YACpD,OAAO;QACT,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACzC,IAAI,CAAC;gBACH,OAAO,CAAC,eAAe,CAAC,CAAC;YAC3B,CAAC;YAAC,OAAO,YAAY,EAAE,CAAC;gBACtB,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,YAAY,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;IACH,CAAC;IAEO,QAAQ,CAAC,KAA8B;QAC7C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAEO,mBAAmB;QACzB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAEO,mBAAmB;QACzB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { TokenManager } from './auth/token-manager.js';
|
|
|
5
5
|
export type { TwitchTokenStore, TwitchTokens, } from './auth/token-store.js';
|
|
6
6
|
export { TwitchChatClient } from './chat/twitch-chat-client.js';
|
|
7
7
|
export type { SendChatMessageOptions, SendChatMessageResult, TwitchChatMessage, TwitchChatMessageHandler, } from './chat/types.js';
|
|
8
|
-
export { EventSubClient } from './eventsub/eventsub-client.js';
|
|
8
|
+
export { EventSubClient, type EventSubErrorHandler, } from './eventsub/eventsub-client.js';
|
|
9
9
|
export { EventSubSubscriptions } from './eventsub/eventsub-subscription.js';
|
|
10
10
|
export type { EventSubConnectionState, EventSubEnvelope, EventSubNotificationHandler, } from './eventsub/types.js';
|
|
11
11
|
export { TwitchError } from './errors/twitch-error.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,YAAY,EACV,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,YAAY,EACV,gBAAgB,EAChB,YAAY,GACb,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,YAAY,EACV,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,YAAY,EACV,gBAAgB,EAChB,YAAY,GACb,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,cAAc,EACd,KAAK,oBAAoB,GAC1B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,YAAY,EACV,uBAAuB,EACvB,gBAAgB,EAChB,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { TwitchClient } from './twitch/twitch-client.js';
|
|
|
2
2
|
export { TwitchApiClient } from './api/twitch-api-client.js';
|
|
3
3
|
export { TokenManager } from './auth/token-manager.js';
|
|
4
4
|
export { TwitchChatClient } from './chat/twitch-chat-client.js';
|
|
5
|
-
export { EventSubClient } from './eventsub/eventsub-client.js';
|
|
5
|
+
export { EventSubClient, } from './eventsub/eventsub-client.js';
|
|
6
6
|
export { EventSubSubscriptions } from './eventsub/eventsub-subscription.js';
|
|
7
7
|
export { TwitchError } from './errors/twitch-error.js';
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAM7D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAMvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAQhE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAM7D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAMvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAQhE,OAAO,EACL,cAAc,GAEf,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAO5E,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC"}
|