streamops-twitch-connector 0.1.2 → 0.1.4
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
CHANGED
|
@@ -1,89 +1,89 @@
|
|
|
1
|
-
# streamops-twitch-connector
|
|
2
|
-
|
|
3
|
-
# StreamOps Twitch Connector
|
|
4
|
-
|
|
5
|
-
A framework-independent TypeScript connector for Twitch OAuth, Helix API
|
|
6
|
-
requests, chat messaging, and EventSub WebSocket notifications.
|
|
7
|
-
|
|
8
|
-
## Requirements
|
|
9
|
-
|
|
10
|
-
- Node.js 22 or newer
|
|
11
|
-
- A Twitch application with a registered Client ID
|
|
12
|
-
- A token store implementation supplied by the consuming application
|
|
13
|
-
|
|
14
|
-
## Install dependencies
|
|
15
|
-
|
|
16
|
-
```text
|
|
17
|
-
npm install
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Build
|
|
21
|
-
|
|
22
|
-
```text
|
|
23
|
-
npm run build
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Basic usage
|
|
27
|
-
|
|
28
|
-
```typescript
|
|
29
|
-
import {
|
|
30
|
-
TwitchClient,
|
|
31
|
-
type TwitchTokenStore,
|
|
32
|
-
type TwitchTokens,
|
|
33
|
-
} from 'streamops-twitch-connector';
|
|
34
|
-
|
|
35
|
-
const tokenStore: TwitchTokenStore = {
|
|
36
|
-
async load(): Promise<TwitchTokens | null> {
|
|
37
|
-
// Load tokens from your preferred secure storage.
|
|
38
|
-
return null;
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
async save(tokens: TwitchTokens): Promise<void> {
|
|
42
|
-
// Persist tokens securely.
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
async clear(): Promise<void> {
|
|
46
|
-
// Remove persisted tokens.
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const twitch = new TwitchClient({
|
|
51
|
-
clientId: process.env.TWITCH_CLIENT_ID!,
|
|
52
|
-
scopes: ['user:read:chat', 'user:write:chat'],
|
|
53
|
-
tokenStore,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const login = await twitch.tokens.startLogin();
|
|
57
|
-
|
|
58
|
-
console.log('Open:', login.verificationUri);
|
|
59
|
-
console.log('Enter code:', login.userCode);
|
|
60
|
-
|
|
61
|
-
// Call completeLogin() after starting the login flow.
|
|
62
|
-
// The method polls until authorization succeeds or fails.
|
|
63
|
-
await twitch.tokens.completeLogin();
|
|
64
|
-
|
|
65
|
-
twitch.chat.onMessage(async (message) => {
|
|
66
|
-
console.log(`${message.chatterName}: ${message.text}`);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
await twitch.connectEventSub();
|
|
70
|
-
|
|
71
|
-
// After receiving the EventSub session welcome, subscribe using
|
|
72
|
-
// twitch.eventSub.currentSessionId and twitch.subscriptions.
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Design
|
|
76
|
-
|
|
77
|
-
- No dependency on NestJS or Express.
|
|
78
|
-
- OAuth tokens are persisted through a caller-provided token store.
|
|
79
|
-
- Helix requests automatically include the Client ID and access token.
|
|
80
|
-
- Chat messages are received through EventSub and sent through Helix.
|
|
81
|
-
- EventSub subscriptions use the active WebSocket session ID.
|
|
82
|
-
|
|
83
|
-
## Notes
|
|
84
|
-
|
|
85
|
-
The initial implementation assumes one authenticated Twitch account.
|
|
86
|
-
A separate bot account and multi-account token management are not included.
|
|
87
|
-
|
|
88
|
-
Treat token storage as sensitive. Do not commit access tokens or refresh
|
|
89
|
-
tokens to source control.
|
|
1
|
+
# streamops-twitch-connector
|
|
2
|
+
|
|
3
|
+
# StreamOps Twitch Connector
|
|
4
|
+
|
|
5
|
+
A framework-independent TypeScript connector for Twitch OAuth, Helix API
|
|
6
|
+
requests, chat messaging, and EventSub WebSocket notifications.
|
|
7
|
+
|
|
8
|
+
## Requirements
|
|
9
|
+
|
|
10
|
+
- Node.js 22 or newer
|
|
11
|
+
- A Twitch application with a registered Client ID
|
|
12
|
+
- A token store implementation supplied by the consuming application
|
|
13
|
+
|
|
14
|
+
## Install dependencies
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
npm install
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Build
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
npm run build
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Basic usage
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import {
|
|
30
|
+
TwitchClient,
|
|
31
|
+
type TwitchTokenStore,
|
|
32
|
+
type TwitchTokens,
|
|
33
|
+
} from 'streamops-twitch-connector';
|
|
34
|
+
|
|
35
|
+
const tokenStore: TwitchTokenStore = {
|
|
36
|
+
async load(): Promise<TwitchTokens | null> {
|
|
37
|
+
// Load tokens from your preferred secure storage.
|
|
38
|
+
return null;
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
async save(tokens: TwitchTokens): Promise<void> {
|
|
42
|
+
// Persist tokens securely.
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
async clear(): Promise<void> {
|
|
46
|
+
// Remove persisted tokens.
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const twitch = new TwitchClient({
|
|
51
|
+
clientId: process.env.TWITCH_CLIENT_ID!,
|
|
52
|
+
scopes: ['user:read:chat', 'user:write:chat'],
|
|
53
|
+
tokenStore,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const login = await twitch.tokens.startLogin();
|
|
57
|
+
|
|
58
|
+
console.log('Open:', login.verificationUri);
|
|
59
|
+
console.log('Enter code:', login.userCode);
|
|
60
|
+
|
|
61
|
+
// Call completeLogin() after starting the login flow.
|
|
62
|
+
// The method polls until authorization succeeds or fails.
|
|
63
|
+
await twitch.tokens.completeLogin();
|
|
64
|
+
|
|
65
|
+
twitch.chat.onMessage(async (message) => {
|
|
66
|
+
console.log(`${message.chatterName}: ${message.text}`);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await twitch.connectEventSub();
|
|
70
|
+
|
|
71
|
+
// After receiving the EventSub session welcome, subscribe using
|
|
72
|
+
// twitch.eventSub.currentSessionId and twitch.subscriptions.
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Design
|
|
76
|
+
|
|
77
|
+
- No dependency on NestJS or Express.
|
|
78
|
+
- OAuth tokens are persisted through a caller-provided token store.
|
|
79
|
+
- Helix requests automatically include the Client ID and access token.
|
|
80
|
+
- Chat messages are received through EventSub and sent through Helix.
|
|
81
|
+
- EventSub subscriptions use the active WebSocket session ID.
|
|
82
|
+
|
|
83
|
+
## Notes
|
|
84
|
+
|
|
85
|
+
The initial implementation assumes one authenticated Twitch account.
|
|
86
|
+
A separate bot account and multi-account token management are not included.
|
|
87
|
+
|
|
88
|
+
Treat token storage as sensitive. Do not commit access tokens or refresh
|
|
89
|
+
tokens to source control.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { EventSubConnectionState, EventSubNotificationHandler } from './types.js';
|
|
2
|
+
export type EventSubSessionHandler = (sessionId: string, isReconnectHandover: boolean) => Promise<void> | void;
|
|
2
3
|
export declare class EventSubClient {
|
|
3
4
|
private readonly onStateChange?;
|
|
4
5
|
private socket;
|
|
@@ -10,10 +11,12 @@ export declare class EventSubClient {
|
|
|
10
11
|
private intentionalClose;
|
|
11
12
|
private state;
|
|
12
13
|
private readonly handlers;
|
|
14
|
+
private readonly sessionHandlers;
|
|
13
15
|
constructor(onStateChange?: ((state: EventSubConnectionState) => void) | undefined);
|
|
14
16
|
get connectionState(): EventSubConnectionState;
|
|
15
17
|
get currentSessionId(): string | null;
|
|
16
18
|
onNotification(handler: EventSubNotificationHandler): () => void;
|
|
19
|
+
onSession(handler: EventSubSessionHandler): () => void;
|
|
17
20
|
connect(): Promise<void>;
|
|
18
21
|
disconnect(): Promise<void>;
|
|
19
22
|
private openSocket;
|
|
@@ -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;AAKpB,qBAAa,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;AAKpB,MAAM,MAAM,sBAAsB,GAAG,CACnC,SAAS,EAAE,MAAM,EACjB,mBAAmB,EAAE,OAAO,KACzB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1B,qBAAa,cAAc;IAcvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAbjC,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,gBAAgB,CAAS;IACjC,OAAO,CAAC,KAAK,CAA2C;IAExD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IACnE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqC;gBAGlD,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;IAKhD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBjC,OAAO,CAAC,UAAU;YAsEJ,aAAa;IAyF3B,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,WAAW;CAIpB"}
|
|
@@ -11,6 +11,7 @@ export class EventSubClient {
|
|
|
11
11
|
intentionalClose = false;
|
|
12
12
|
state = 'disconnected';
|
|
13
13
|
handlers = new Set();
|
|
14
|
+
sessionHandlers = new Set();
|
|
14
15
|
constructor(onStateChange) {
|
|
15
16
|
this.onStateChange = onStateChange;
|
|
16
17
|
}
|
|
@@ -24,6 +25,10 @@ export class EventSubClient {
|
|
|
24
25
|
this.handlers.add(handler);
|
|
25
26
|
return () => this.handlers.delete(handler);
|
|
26
27
|
}
|
|
28
|
+
onSession(handler) {
|
|
29
|
+
this.sessionHandlers.add(handler);
|
|
30
|
+
return () => this.sessionHandlers.delete(handler);
|
|
31
|
+
}
|
|
27
32
|
async connect() {
|
|
28
33
|
this.intentionalClose = false;
|
|
29
34
|
this.clearReconnectTimer();
|
|
@@ -47,35 +52,40 @@ export class EventSubClient {
|
|
|
47
52
|
}
|
|
48
53
|
this.setState('disconnected');
|
|
49
54
|
}
|
|
50
|
-
openSocket(url) {
|
|
55
|
+
openSocket(url, isReconnectHandover = false) {
|
|
51
56
|
let socket;
|
|
52
57
|
try {
|
|
53
58
|
socket = new WebSocket(url);
|
|
54
59
|
}
|
|
55
60
|
catch (error) {
|
|
61
|
+
// Logging suppressed.
|
|
56
62
|
this.scheduleReconnect();
|
|
57
63
|
throw new TwitchError('Unable to create Twitch EventSub WebSocket.', undefined, undefined, { cause: error });
|
|
58
64
|
}
|
|
65
|
+
const previousSocket = this.socket;
|
|
59
66
|
this.socket = socket;
|
|
67
|
+
// Logging suppressed; retain original connection behavior.
|
|
68
|
+
void previousSocket;
|
|
60
69
|
socket.addEventListener('open', () => {
|
|
61
|
-
if (this.socket
|
|
62
|
-
|
|
70
|
+
if (this.socket !== socket) {
|
|
71
|
+
return;
|
|
63
72
|
}
|
|
73
|
+
this.setState('connected');
|
|
64
74
|
});
|
|
65
75
|
socket.addEventListener('message', (message) => {
|
|
66
76
|
if (this.socket !== socket) {
|
|
67
77
|
return;
|
|
68
78
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
const raw = String(message.data);
|
|
80
|
+
// Parse and handle the message as before, without routine log output.
|
|
81
|
+
void this.handleMessage(raw, isReconnectHandover).catch((_error) => {
|
|
82
|
+
// EventSub processing errors suppressed.
|
|
72
83
|
});
|
|
73
84
|
});
|
|
74
85
|
socket.addEventListener('error', () => {
|
|
75
|
-
//
|
|
86
|
+
// WebSocket error logging suppressed.
|
|
76
87
|
});
|
|
77
|
-
socket.addEventListener('close', () => {
|
|
78
|
-
// A replaced socket must not affect the active connection.
|
|
88
|
+
socket.addEventListener('close', (_event) => {
|
|
79
89
|
if (this.socket !== socket) {
|
|
80
90
|
return;
|
|
81
91
|
}
|
|
@@ -90,7 +100,7 @@ export class EventSubClient {
|
|
|
90
100
|
}
|
|
91
101
|
});
|
|
92
102
|
}
|
|
93
|
-
async handleMessage(raw) {
|
|
103
|
+
async handleMessage(raw, isReconnectHandover) {
|
|
94
104
|
const envelope = JSON.parse(raw);
|
|
95
105
|
const messageType = envelope.metadata?.message_type;
|
|
96
106
|
if (!messageType) {
|
|
@@ -107,6 +117,9 @@ export class EventSubClient {
|
|
|
107
117
|
session.keepalive_timeout_seconds ?? 10;
|
|
108
118
|
this.reconnectUrl = null;
|
|
109
119
|
this.resetKeepaliveTimer();
|
|
120
|
+
for (const handler of this.sessionHandlers) {
|
|
121
|
+
await handler(session.id, isReconnectHandover);
|
|
122
|
+
}
|
|
110
123
|
break;
|
|
111
124
|
}
|
|
112
125
|
case 'session_keepalive':
|
|
@@ -114,13 +127,13 @@ export class EventSubClient {
|
|
|
114
127
|
break;
|
|
115
128
|
case 'session_reconnect': {
|
|
116
129
|
const reconnectUrl = envelope.payload.session?.reconnect_url;
|
|
117
|
-
if (reconnectUrl) {
|
|
118
|
-
|
|
119
|
-
this.clearKeepaliveTimer();
|
|
120
|
-
// Twitch expects the existing socket to remain alive until
|
|
121
|
-
// the replacement connection is established.
|
|
122
|
-
this.openSocket(reconnectUrl);
|
|
130
|
+
if (!reconnectUrl) {
|
|
131
|
+
return;
|
|
123
132
|
}
|
|
133
|
+
this.reconnectUrl = reconnectUrl;
|
|
134
|
+
this.clearKeepaliveTimer();
|
|
135
|
+
// Preserve original session handover behavior.
|
|
136
|
+
this.openSocket(reconnectUrl, true);
|
|
124
137
|
break;
|
|
125
138
|
}
|
|
126
139
|
case 'notification': {
|
|
@@ -140,19 +153,19 @@ export class EventSubClient {
|
|
|
140
153
|
this.scheduleReconnect();
|
|
141
154
|
break;
|
|
142
155
|
case 'revocation':
|
|
143
|
-
|
|
156
|
+
// Revocation logging suppressed.
|
|
144
157
|
break;
|
|
145
158
|
default:
|
|
159
|
+
// Unknown message logging suppressed.
|
|
146
160
|
break;
|
|
147
161
|
}
|
|
148
162
|
}
|
|
149
163
|
resetKeepaliveTimer() {
|
|
150
164
|
this.clearKeepaliveTimer();
|
|
151
165
|
this.keepaliveTimer = setTimeout(() => {
|
|
152
|
-
console.warn('[EventSub] Keepalive timeout; reconnecting.');
|
|
153
166
|
const socket = this.socket;
|
|
154
167
|
this.socket = null;
|
|
155
|
-
if (socket) {
|
|
168
|
+
if (socket && socket.readyState !== WebSocket.CLOSED) {
|
|
156
169
|
socket.close();
|
|
157
170
|
}
|
|
158
171
|
if (!this.intentionalClose) {
|
|
@@ -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;AAOvD,MAAM,OAAO,cAAc;IAcN;IAbX,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,gBAAgB,GAAG,KAAK,CAAC;IACzB,KAAK,GAA4B,cAAc,CAAC;IAEvC,QAAQ,GAAG,IAAI,GAAG,EAA+B,CAAC;IAClD,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;IAErE,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,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;QAErB,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,sEAAsE;YACtE,KAAK,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC,KAAK,CACrD,CAAC,MAAe,EAAE,EAAE;gBAClB,yCAAyC;YAC3C,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YACpC,sCAAsC;QACxC,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,MAAkB,EAAE,EAAE;YACtD,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,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,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,mBAAmB,CAAC,CAAC;gBACjD,CAAC;gBAED,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,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,YAAY,GAAG,IAAI,CAAC;gBACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBACzB,MAAM;YAER,KAAK,YAAY;gBACf,iCAAiC;gBACjC,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;YAEnB,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,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,UAAU,CAAC,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,CAAC;YACrD,CAAC;QACH,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,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/package.json
CHANGED
|
@@ -1,31 +1,34 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "streamops-twitch-connector",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Framework-independent Twitch OAuth, EventSub, and chat connector",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"main": "./dist/index.js",
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/index.js"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"files": [
|
|
16
|
-
"dist"
|
|
17
|
-
],
|
|
18
|
-
"scripts": {
|
|
19
|
-
"build": "tsc",
|
|
20
|
-
"test": "vitest run",
|
|
21
|
-
"test:watch": "vitest"
|
|
22
|
-
},
|
|
23
|
-
"engines": {
|
|
24
|
-
"node": ">=22"
|
|
25
|
-
},
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"@types/node": "^24.0.0",
|
|
28
|
-
"typescript": "^6.0.2",
|
|
29
|
-
"vitest": "^4.1.2"
|
|
30
|
-
}
|
|
31
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "streamops-twitch-connector",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Framework-independent Twitch OAuth, EventSub, and chat connector",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=22"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^24.0.0",
|
|
28
|
+
"typescript": "^6.0.2",
|
|
29
|
+
"vitest": "^4.1.2"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"streamops-twitch-connector": "file:streamops-twitch-connector-0.1.2.tgz"
|
|
33
|
+
}
|
|
34
|
+
}
|