streamops-twitch-connector 0.3.0 → 0.4.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 +143 -85
- package/dist/api/types.d.ts +1 -1
- package/dist/api/types.d.ts.map +1 -1
- package/dist/auth/authorization-code-flow.d.ts +29 -0
- package/dist/auth/authorization-code-flow.d.ts.map +1 -0
- package/dist/auth/authorization-code-flow.js +97 -0
- package/dist/auth/authorization-code-flow.js.map +1 -0
- package/dist/auth/token-manager.d.ts +8 -1
- package/dist/auth/token-manager.d.ts.map +1 -1
- package/dist/auth/token-manager.js +24 -3
- package/dist/auth/token-manager.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/twitch/twitch-client.d.ts.map +1 -1
- package/dist/twitch/twitch-client.js +8 -1
- package/dist/twitch/twitch-client.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,117 +1,175 @@
|
|
|
1
|
-
# streamops-twitch-connector
|
|
2
|
-
|
|
3
1
|
# StreamOps Twitch Connector
|
|
4
2
|
|
|
5
|
-
A framework-independent TypeScript
|
|
6
|
-
|
|
3
|
+
A small, framework-independent TypeScript library for Twitch OAuth, Helix,
|
|
4
|
+
chat, and EventSub. The product owns its Twitch application, callback route,
|
|
5
|
+
and secure token storage; the connector handles Twitch requests and token
|
|
6
|
+
refreshing. It supports both Device Code Grant (DCF) and Authorization Code
|
|
7
|
+
Grant (ACF); either flow uses the same API, chat, EventSub, and token store.
|
|
7
8
|
|
|
8
9
|
## Requirements
|
|
9
10
|
|
|
10
11
|
- Node.js 22 or newer
|
|
11
|
-
- A Twitch application
|
|
12
|
-
- A
|
|
12
|
+
- A Twitch application registered for each product
|
|
13
|
+
- A backend that can keep the client secret private if using Authorization
|
|
14
|
+
Code Grant
|
|
15
|
+
- A token store supplied by the product
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
Never put a Twitch client secret or refresh token in a browser or desktop
|
|
18
|
+
client. Have those clients call your backend instead.
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
npm install
|
|
18
|
-
```
|
|
20
|
+
## Quick start
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
Install the package and create one `TwitchClient` in your backend. Use a
|
|
23
|
+
durable `TwitchTokenStore` implementation from your app (for example, your
|
|
24
|
+
current JSON-backed store):
|
|
21
25
|
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
```typescript
|
|
27
|
+
import { TwitchClient, type TwitchTokenStore } from 'streamops-twitch-connector';
|
|
28
|
+
import { twitchTokenStore } from './twitch-token-store.js';
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
const tokenStore: TwitchTokenStore = twitchTokenStore;
|
|
27
31
|
|
|
28
|
-
|
|
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({
|
|
32
|
+
export const twitch = new TwitchClient({
|
|
51
33
|
clientId: process.env.TWITCH_CLIENT_ID!,
|
|
34
|
+
clientSecret: process.env.TWITCH_CLIENT_SECRET!,
|
|
52
35
|
scopes: ['user:read:chat', 'user:write:chat'],
|
|
53
36
|
tokenStore,
|
|
54
37
|
});
|
|
38
|
+
```
|
|
55
39
|
|
|
56
|
-
|
|
40
|
+
`TwitchTokenStore` has three methods: `load()` returns saved tokens or `null`,
|
|
41
|
+
`save(tokens)` persists the complete token set, and `clear()` removes it.
|
|
42
|
+
Persist every `save()` call because Twitch can rotate the refresh token.
|
|
43
|
+
Protect the file or database with appropriate server-side access controls.
|
|
44
|
+
|
|
45
|
+
## Choose an authorization flow
|
|
46
|
+
|
|
47
|
+
Use Device Code Grant for clients that cannot safely keep a client secret. It
|
|
48
|
+
preserves the original `0.3.0` login API:
|
|
57
49
|
|
|
50
|
+
```typescript
|
|
51
|
+
const login = await twitch.tokens.startLogin();
|
|
58
52
|
console.log('Open:', login.verificationUri);
|
|
59
53
|
console.log('Enter code:', login.userCode);
|
|
60
54
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
await twitch.tokens.completeLogin();
|
|
55
|
+
const tokens = await twitch.tokens.completeLogin();
|
|
56
|
+
```
|
|
64
57
|
|
|
65
|
-
|
|
58
|
+
DCF refresh behavior depends on Twitch's token policy. If the refresh token
|
|
59
|
+
is rejected, the user will need to authorize again.
|
|
60
|
+
|
|
61
|
+
Use Authorization Code Grant when your product has a trusted backend. The
|
|
62
|
+
backend must keep its app's client secret private. It creates an authorization
|
|
63
|
+
URL and associates the returned `state` with the user's server-side session.
|
|
64
|
+
Redirect the user's browser to the URL:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const callbackUri = 'https://your-product.example/api/twitch/callback';
|
|
68
|
+
const request = twitch.tokens.createAuthorizationRequest(callbackUri);
|
|
69
|
+
|
|
70
|
+
await session.set('twitchOAuthState', request.state);
|
|
71
|
+
return redirect(request.authorizationUrl);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The callback route receives `code` and `state` from Twitch. Retrieve the
|
|
75
|
+
expected state from that same user's session and pass both values to the
|
|
76
|
+
connector. The connector checks the state before exchanging the code and
|
|
77
|
+
saving the tokens:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
const expectedState = await session.get('twitchOAuthState');
|
|
81
|
+
const tokens = await twitch.tokens.completeAuthorization({
|
|
82
|
+
code: callbackQuery.code,
|
|
83
|
+
state: callbackQuery.state,
|
|
84
|
+
expectedState,
|
|
85
|
+
redirectUri: callbackUri,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
await session.delete('twitchOAuthState');
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Use the exact same registered `redirectUri` when creating the URL and
|
|
92
|
+
exchanging the code. Handle Twitch's `error` callback parameters in the
|
|
93
|
+
product's callback route and show an appropriate message to the user.
|
|
94
|
+
Keep the client secret on the backend; Authorization Code Grant requires it
|
|
95
|
+
for this confidential-server setup.
|
|
96
|
+
|
|
97
|
+
After authorization, normal API calls use the saved tokens:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
const user = await twitch.api.get('/users');
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The connector validates tokens, refreshes them after expiry or an API `401`,
|
|
104
|
+
and persists the new access and refresh tokens. If Twitch rejects a refresh
|
|
105
|
+
token, listen for `reauthentication_required` and send the user through the
|
|
106
|
+
connect flow again:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
twitch.tokens.onAuthError((error) => {
|
|
110
|
+
if ('errorCode' in error && error.errorCode === 'reauthentication_required') {
|
|
111
|
+
// Notify the product that this user must connect Twitch again.
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Receive and send chat messages
|
|
117
|
+
|
|
118
|
+
After connecting EventSub, subscribe to chat messages. The callback receives
|
|
119
|
+
a plain typed message object; log it, map it to your own model, or publish it
|
|
120
|
+
to another part of your app:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
twitch.chat.onMessage((message) => {
|
|
66
124
|
console.log(`${message.chatterName}: ${message.text}`);
|
|
125
|
+
|
|
126
|
+
const productMessage = {
|
|
127
|
+
user: message.chatterName,
|
|
128
|
+
text: message.text,
|
|
129
|
+
receivedAt: message.sentAt,
|
|
130
|
+
};
|
|
131
|
+
// Pass productMessage to your own event bus or application logic.
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
twitch.eventSub.onSession(async (sessionId) => {
|
|
135
|
+
await twitch.subscriptions.subscribeToChatMessages(
|
|
136
|
+
broadcasterUserId,
|
|
137
|
+
userId,
|
|
138
|
+
sessionId,
|
|
139
|
+
);
|
|
67
140
|
});
|
|
68
141
|
|
|
69
142
|
await twitch.connectEventSub();
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Send a chat message with:
|
|
70
146
|
|
|
71
|
-
|
|
72
|
-
|
|
147
|
+
```typescript
|
|
148
|
+
await twitch.chat.sendMessage({
|
|
149
|
+
broadcasterId,
|
|
150
|
+
message: 'Hello from my app!',
|
|
151
|
+
});
|
|
73
152
|
```
|
|
74
153
|
|
|
75
|
-
## Design
|
|
76
|
-
|
|
77
|
-
- No
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
- `twitch.tokens.
|
|
88
|
-
|
|
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.
|
|
92
|
-
The connector cannot complete that interactive step itself: the consuming
|
|
93
|
-
app should subscribe to `onAuthError()` and prompt the user to run the
|
|
94
|
-
existing `startLogin()` / `completeLogin()` flow. Restarting the app is not
|
|
95
|
-
required. Foreground API calls also reject with the auth error.
|
|
96
|
-
- Refresh tokens may rotate, so token stores must persist every `save()` call.
|
|
97
|
-
- Twitch documents silent refresh for Authorization Code Grant user tokens.
|
|
98
|
-
The built-in Device Code flow may therefore require interactive login again
|
|
99
|
-
when Twitch rejects its refresh token; the library reports this explicitly.
|
|
100
|
-
- A `clientSecret` may be provided for confidential applications only. Never
|
|
101
|
-
ship it in a desktop or other public client.
|
|
102
|
-
- Helix requests automatically include the Client ID and access token.
|
|
154
|
+
## Design and limitations
|
|
155
|
+
|
|
156
|
+
- No NestJS, Express, or other framework dependency. Products implement their
|
|
157
|
+
own routes, session/state storage, and token storage.
|
|
158
|
+
- Each product registers its own Twitch application and configures its own
|
|
159
|
+
Client ID, scopes, and token store. ACF additionally requires a private
|
|
160
|
+
client secret and registered redirect URI.
|
|
161
|
+
- The connector currently supports one authenticated Twitch account per
|
|
162
|
+
`TwitchClient` / token store. Products supporting multiple Twitch users
|
|
163
|
+
should create isolated clients and token stores per account.
|
|
164
|
+
- Tokens are checked with Twitch periodically and refreshed as needed. Helix
|
|
165
|
+
`401` responses trigger one refresh-and-retry attempt.
|
|
166
|
+
- Call `twitch.tokens.dispose()` when the client is no longer needed to stop
|
|
167
|
+
background token checks.
|
|
103
168
|
- Chat messages are received through EventSub and sent through Helix.
|
|
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.
|
|
110
|
-
|
|
111
|
-
## Notes
|
|
112
169
|
|
|
113
|
-
|
|
114
|
-
|
|
170
|
+
Treat access and refresh tokens as sensitive. Do not commit them to source
|
|
171
|
+
control.
|
|
115
172
|
|
|
116
|
-
|
|
117
|
-
|
|
173
|
+
The original Device Code `startLogin()` / `completeLogin()` API remains
|
|
174
|
+
available for existing products. ACF is opt-in through
|
|
175
|
+
`createAuthorizationRequest()` / `completeAuthorization()`.
|
package/dist/api/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TwitchTokenStore } from '../auth/token-store.js';
|
|
2
2
|
export interface TwitchConnectorConfig {
|
|
3
3
|
clientId: string;
|
|
4
|
-
/**
|
|
4
|
+
/** Required for Authorization Code Grant. Keep it on a trusted server; never expose it to clients. */
|
|
5
5
|
clientSecret?: string;
|
|
6
6
|
scopes: string[];
|
|
7
7
|
tokenStore: TwitchTokenStore;
|
package/dist/api/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TwitchConnectorConfig } from '../api/types.js';
|
|
2
|
+
export interface TwitchAuthorizationRequest {
|
|
3
|
+
redirectUri: string;
|
|
4
|
+
state: string;
|
|
5
|
+
}
|
|
6
|
+
export interface TwitchAuthorizationRequestResult {
|
|
7
|
+
authorizationUrl: string;
|
|
8
|
+
state: string;
|
|
9
|
+
}
|
|
10
|
+
export interface TwitchAuthorizationCallback {
|
|
11
|
+
code: string;
|
|
12
|
+
redirectUri: string;
|
|
13
|
+
state: string;
|
|
14
|
+
expectedState: string;
|
|
15
|
+
}
|
|
16
|
+
export interface AuthorizationCodeTokenResponse {
|
|
17
|
+
access_token: string;
|
|
18
|
+
refresh_token: string;
|
|
19
|
+
expires_in: number;
|
|
20
|
+
scope: string[];
|
|
21
|
+
}
|
|
22
|
+
export declare class AuthorizationCodeFlow {
|
|
23
|
+
private readonly config;
|
|
24
|
+
constructor(config: Pick<TwitchConnectorConfig, 'clientId' | 'clientSecret' | 'scopes' | 'fetch'>);
|
|
25
|
+
createAuthorizationRequest(redirectUri: string): TwitchAuthorizationRequestResult;
|
|
26
|
+
createAuthorizationUrl(request: TwitchAuthorizationRequest): string;
|
|
27
|
+
exchangeCode(callback: TwitchAuthorizationCallback): Promise<AuthorizationCodeTokenResponse>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=authorization-code-flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-code-flow.d.ts","sourceRoot":"","sources":["../../src/auth/authorization-code-flow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAM7D,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gCAAgC;IAC/C,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,8BAA8B;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,IAAI,CAC3B,qBAAqB,EACrB,UAAU,GAAG,cAAc,GAAG,QAAQ,GAAG,OAAO,CACjD;IAGH,0BAA0B,CACxB,WAAW,EAAE,MAAM,GAClB,gCAAgC;IA4BnC,sBAAsB,CAAC,OAAO,EAAE,0BAA0B,GAAG,MAAM;IAqB7D,YAAY,CAChB,QAAQ,EAAE,2BAA2B,GACpC,OAAO,CAAC,8BAA8B,CAAC;CAyG3C"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { TwitchError } from '../errors/twitch-error.js';
|
|
2
|
+
const TWITCH_AUTHORIZE_URL = 'https://id.twitch.tv/oauth2/authorize';
|
|
3
|
+
const TWITCH_TOKEN_URL = 'https://id.twitch.tv/oauth2/token';
|
|
4
|
+
export class AuthorizationCodeFlow {
|
|
5
|
+
config;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
}
|
|
9
|
+
createAuthorizationRequest(redirectUri) {
|
|
10
|
+
if (!redirectUri) {
|
|
11
|
+
throw new TwitchError('A redirect URI is required.', undefined, 'invalid_authorization_request');
|
|
12
|
+
}
|
|
13
|
+
if (!globalThis.crypto?.getRandomValues) {
|
|
14
|
+
throw new TwitchError('A secure random source is required to start Twitch authorization.', undefined, 'secure_random_unavailable');
|
|
15
|
+
}
|
|
16
|
+
const bytes = globalThis.crypto.getRandomValues(new Uint8Array(32));
|
|
17
|
+
const state = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
18
|
+
return {
|
|
19
|
+
authorizationUrl: this.createAuthorizationUrl({ redirectUri, state }),
|
|
20
|
+
state,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
createAuthorizationUrl(request) {
|
|
24
|
+
if (!request.redirectUri || !request.state) {
|
|
25
|
+
throw new TwitchError('A redirect URI and OAuth state are required.', undefined, 'invalid_authorization_request');
|
|
26
|
+
}
|
|
27
|
+
const url = new URL(TWITCH_AUTHORIZE_URL);
|
|
28
|
+
url.search = new URLSearchParams({
|
|
29
|
+
client_id: this.config.clientId,
|
|
30
|
+
redirect_uri: request.redirectUri,
|
|
31
|
+
response_type: 'code',
|
|
32
|
+
scope: this.config.scopes.join(' '),
|
|
33
|
+
state: request.state,
|
|
34
|
+
}).toString();
|
|
35
|
+
return url.toString();
|
|
36
|
+
}
|
|
37
|
+
async exchangeCode(callback) {
|
|
38
|
+
if (!this.config.clientSecret) {
|
|
39
|
+
throw new TwitchError('A client secret is required for Authorization Code Grant. Keep it on a trusted server.', undefined, 'client_secret_required');
|
|
40
|
+
}
|
|
41
|
+
if (!callback.code || !callback.redirectUri) {
|
|
42
|
+
throw new TwitchError('An authorization code and redirect URI are required.', undefined, 'invalid_authorization_callback');
|
|
43
|
+
}
|
|
44
|
+
if (!callback.expectedState || callback.state !== callback.expectedState) {
|
|
45
|
+
throw new TwitchError('Twitch authorization state did not match. Start login again.', undefined, 'authorization_state_mismatch');
|
|
46
|
+
}
|
|
47
|
+
const body = new URLSearchParams({
|
|
48
|
+
client_id: this.config.clientId,
|
|
49
|
+
client_secret: this.config.clientSecret,
|
|
50
|
+
code: callback.code,
|
|
51
|
+
grant_type: 'authorization_code',
|
|
52
|
+
redirect_uri: callback.redirectUri,
|
|
53
|
+
});
|
|
54
|
+
let response;
|
|
55
|
+
try {
|
|
56
|
+
response = await (this.config.fetch ?? fetch)(TWITCH_TOKEN_URL, {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
headers: {
|
|
59
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
60
|
+
},
|
|
61
|
+
body,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (cause) {
|
|
65
|
+
throw new TwitchError('Unable to contact Twitch to exchange the authorization code.', undefined, 'authorization_exchange_network_error', { cause });
|
|
66
|
+
}
|
|
67
|
+
let data;
|
|
68
|
+
try {
|
|
69
|
+
data = await response.json();
|
|
70
|
+
}
|
|
71
|
+
catch (cause) {
|
|
72
|
+
throw new TwitchError('Twitch returned an invalid authorization response.', response.status, 'invalid_oauth_response', { cause });
|
|
73
|
+
}
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
throw new TwitchError('Twitch authorization code exchange failed.', response.status, response.status === 400 || response.status === 401
|
|
76
|
+
? 'reauthentication_required'
|
|
77
|
+
: 'authorization_exchange_failed');
|
|
78
|
+
}
|
|
79
|
+
if (!data || typeof data !== 'object') {
|
|
80
|
+
throw new TwitchError('Twitch returned an invalid authorization token response.', response.status, 'invalid_token_response');
|
|
81
|
+
}
|
|
82
|
+
const token = data;
|
|
83
|
+
if (typeof token.access_token !== 'string' ||
|
|
84
|
+
!token.access_token ||
|
|
85
|
+
typeof token.refresh_token !== 'string' ||
|
|
86
|
+
!token.refresh_token ||
|
|
87
|
+
typeof token.expires_in !== 'number' ||
|
|
88
|
+
!Number.isFinite(token.expires_in) ||
|
|
89
|
+
token.expires_in <= 0 ||
|
|
90
|
+
!Array.isArray(token.scope) ||
|
|
91
|
+
!token.scope.every((scope) => typeof scope === 'string')) {
|
|
92
|
+
throw new TwitchError('Twitch returned an invalid authorization token response.', response.status, 'invalid_token_response');
|
|
93
|
+
}
|
|
94
|
+
return token;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=authorization-code-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-code-flow.js","sourceRoot":"","sources":["../../src/auth/authorization-code-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { TwitchConnectorConfig, TwitchValidatedToken } from '../api/types.js';
|
|
2
2
|
import type { DeviceCodeFlow } from './device-code-flow.js';
|
|
3
|
+
import { AuthorizationCodeFlow } from './authorization-code-flow.js';
|
|
4
|
+
import type { TwitchAuthorizationCallback, TwitchAuthorizationRequest, TwitchAuthorizationRequestResult } from './authorization-code-flow.js';
|
|
3
5
|
import type { TwitchTokenStore, TwitchTokens } from './token-store.js';
|
|
4
6
|
export declare class TokenManager {
|
|
5
7
|
private readonly config;
|
|
6
8
|
private readonly tokenStore;
|
|
7
9
|
private readonly deviceCodeFlow;
|
|
10
|
+
private readonly authorizationCodeFlow;
|
|
8
11
|
private refreshPromise;
|
|
9
12
|
private validationPromise;
|
|
10
13
|
private validationTimer;
|
|
@@ -13,7 +16,7 @@ export declare class TokenManager {
|
|
|
13
16
|
private validationFailureCount;
|
|
14
17
|
private validationMonitoring;
|
|
15
18
|
private readonly authErrorHandlers;
|
|
16
|
-
constructor(config: Pick<TwitchConnectorConfig, 'clientId' | 'clientSecret' | 'scopes' | 'fetch'>, tokenStore: TwitchTokenStore, deviceCodeFlow: DeviceCodeFlow);
|
|
19
|
+
constructor(config: Pick<TwitchConnectorConfig, 'clientId' | 'clientSecret' | 'scopes' | 'fetch'>, tokenStore: TwitchTokenStore, deviceCodeFlow: DeviceCodeFlow, authorizationCodeFlow?: AuthorizationCodeFlow);
|
|
17
20
|
private get fetcher();
|
|
18
21
|
/** Loads persisted token metadata without attempting an expiry-based refresh. */
|
|
19
22
|
getTokens(): Promise<TwitchTokens>;
|
|
@@ -26,8 +29,12 @@ export declare class TokenManager {
|
|
|
26
29
|
* already performed by another request when the store has the newer token.
|
|
27
30
|
*/
|
|
28
31
|
refreshAfterUnauthorized(rejectedAccessToken: string): Promise<string>;
|
|
32
|
+
createAuthorizationUrl(request: TwitchAuthorizationRequest): string;
|
|
33
|
+
createAuthorizationRequest(redirectUri: string): TwitchAuthorizationRequestResult;
|
|
29
34
|
startLogin(): Promise<import("./device-code-flow.js").DeviceCodeLogin>;
|
|
30
35
|
completeLogin(signal?: AbortSignal): Promise<TwitchTokens>;
|
|
36
|
+
completeAuthorization(callback: TwitchAuthorizationCallback): Promise<TwitchTokens>;
|
|
37
|
+
private saveLoginTokens;
|
|
31
38
|
logout(): Promise<void>;
|
|
32
39
|
onAuthError(handler: (error: Error) => void): () => void;
|
|
33
40
|
get authError(): Error | null;
|
|
@@ -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;AAkBvE,qBAAa,YAAY;
|
|
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,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EACV,2BAA2B,EAC3B,0BAA0B,EAC1B,gCAAgC,EACjC,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAkBvE,qBAAa,YAAY;IAYrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAIvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAhBjC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAwB;IAC9D,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,EAC/C,qBAAqB,CAAC,EAAE,qBAAqB;IAM/C,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;IAelB,sBAAsB,CAAC,OAAO,EAAE,0BAA0B,GAAG,MAAM;IAInE,0BAA0B,CACxB,WAAW,EAAE,MAAM,GAClB,gCAAgC;IAI7B,UAAU;IAIV,aAAa,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAW1D,qBAAqB,CACzB,QAAQ,EAAE,2BAA2B,GACpC,OAAO,CAAC,YAAY,CAAC;YAWV,eAAe;IAUvB,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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TwitchError } from '../errors/twitch-error.js';
|
|
2
|
+
import { AuthorizationCodeFlow } from './authorization-code-flow.js';
|
|
2
3
|
const TWITCH_VALIDATE_URL = 'https://id.twitch.tv/oauth2/validate';
|
|
3
4
|
const TWITCH_TOKEN_URL = 'https://id.twitch.tv/oauth2/token';
|
|
4
5
|
const TOKEN_VALIDATION_INTERVAL_MS = 50 * 60 * 1000;
|
|
@@ -9,6 +10,7 @@ export class TokenManager {
|
|
|
9
10
|
config;
|
|
10
11
|
tokenStore;
|
|
11
12
|
deviceCodeFlow;
|
|
13
|
+
authorizationCodeFlow;
|
|
12
14
|
refreshPromise = null;
|
|
13
15
|
validationPromise = null;
|
|
14
16
|
validationTimer = null;
|
|
@@ -17,10 +19,12 @@ export class TokenManager {
|
|
|
17
19
|
validationFailureCount = 0;
|
|
18
20
|
validationMonitoring = true;
|
|
19
21
|
authErrorHandlers = new Set();
|
|
20
|
-
constructor(config, tokenStore, deviceCodeFlow) {
|
|
22
|
+
constructor(config, tokenStore, deviceCodeFlow, authorizationCodeFlow) {
|
|
21
23
|
this.config = config;
|
|
22
24
|
this.tokenStore = tokenStore;
|
|
23
25
|
this.deviceCodeFlow = deviceCodeFlow;
|
|
26
|
+
this.authorizationCodeFlow =
|
|
27
|
+
authorizationCodeFlow ?? new AuthorizationCodeFlow(config);
|
|
24
28
|
}
|
|
25
29
|
get fetcher() {
|
|
26
30
|
return this.config.fetch ?? fetch;
|
|
@@ -62,17 +66,34 @@ export class TokenManager {
|
|
|
62
66
|
: tokens;
|
|
63
67
|
return refreshed.accessToken;
|
|
64
68
|
}
|
|
69
|
+
createAuthorizationUrl(request) {
|
|
70
|
+
return this.authorizationCodeFlow.createAuthorizationUrl(request);
|
|
71
|
+
}
|
|
72
|
+
createAuthorizationRequest(redirectUri) {
|
|
73
|
+
return this.authorizationCodeFlow.createAuthorizationRequest(redirectUri);
|
|
74
|
+
}
|
|
65
75
|
async startLogin() {
|
|
66
76
|
return this.deviceCodeFlow.startLogin();
|
|
67
77
|
}
|
|
68
78
|
async completeLogin(signal) {
|
|
69
79
|
const response = await this.deviceCodeFlow.waitForAuthorization(signal);
|
|
70
|
-
|
|
80
|
+
return this.saveLoginTokens({
|
|
71
81
|
accessToken: response.access_token,
|
|
72
82
|
refreshToken: response.refresh_token,
|
|
73
83
|
expiresAt: Date.now() + response.expires_in * 1000,
|
|
74
84
|
scopes: response.scope,
|
|
75
|
-
};
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async completeAuthorization(callback) {
|
|
88
|
+
const response = await this.authorizationCodeFlow.exchangeCode(callback);
|
|
89
|
+
return this.saveLoginTokens({
|
|
90
|
+
accessToken: response.access_token,
|
|
91
|
+
refreshToken: response.refresh_token,
|
|
92
|
+
expiresAt: Date.now() + response.expires_in * 1000,
|
|
93
|
+
scopes: response.scope,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
async saveLoginTokens(tokens) {
|
|
76
97
|
await this.tokenStore.save(tokens);
|
|
77
98
|
this.stopValidationTimer();
|
|
78
99
|
this.lastValidatedAt = 0;
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAQrE,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;AAC9C,MAAM,2BAA2B,GAAG,EAAE,GAAG,IAAI,CAAC;AAC9C,MAAM,uBAAuB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE9C,MAAM,OAAO,YAAY;IAYJ;IAIA;IACA;IAhBF,qBAAqB,CAAwB;IACtD,cAAc,GAAiC,IAAI,CAAC;IACpD,iBAAiB,GAAyC,IAAI,CAAC;IAC/D,eAAe,GAAyC,IAAI,CAAC;IAC7D,eAAe,GAAG,CAAC,CAAC;IACpB,aAAa,GAAiB,IAAI,CAAC;IACnC,sBAAsB,GAAG,CAAC,CAAC;IAC3B,oBAAoB,GAAG,IAAI,CAAC;IACnB,iBAAiB,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEvE,YACmB,MAGhB,EACgB,UAA4B,EAC5B,cAA8B,EAC/C,qBAA6C;QAN5B,WAAM,GAAN,MAAM,CAGtB;QACgB,eAAU,GAAV,UAAU,CAAkB;QAC5B,mBAAc,GAAd,cAAc,CAAgB;QAG/C,IAAI,CAAC,qBAAqB;YACxB,qBAAqB,IAAI,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC;IAED,IAAY,OAAO;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC;IACpC,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,SAAS;QACb,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAE5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,WAAW,CAAC,gCAAgC,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO,IAAI,CAAC,qBAAqB,EAAE,CAAC;IACtC,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,OAAO;QACX,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAE5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,WAAW,CAAC,gCAAgC,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,wBAAwB,CAC5B,mBAA2B;QAE3B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAE5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,WAAW,CAAC,gCAAgC,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,SAAS,GACb,MAAM,CAAC,WAAW,KAAK,mBAAmB;YACxC,CAAC,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;YAClC,CAAC,CAAC,MAAM,CAAC;QAEb,OAAO,SAAS,CAAC,WAAW,CAAC;IAC/B,CAAC;IAED,sBAAsB,CAAC,OAAmC;QACxD,OAAO,IAAI,CAAC,qBAAqB,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACpE,CAAC;IAED,0BAA0B,CACxB,WAAmB;QAEnB,OAAO,IAAI,CAAC,qBAAqB,CAAC,0BAA0B,CAAC,WAAW,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAAoB;QACtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAExE,OAAO,IAAI,CAAC,eAAe,CAAC;YAC1B,WAAW,EAAE,QAAQ,CAAC,YAAY;YAClC,YAAY,EAAE,QAAQ,CAAC,aAAa;YACpC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,UAAU,GAAG,IAAI;YAClD,MAAM,EAAE,QAAQ,CAAC,KAAK;SACvB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,qBAAqB,CACzB,QAAqC;QAErC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAEzE,OAAO,IAAI,CAAC,eAAe,CAAC;YAC1B,WAAW,EAAE,QAAQ,CAAC,YAAY;YAClC,YAAY,EAAE,QAAQ,CAAC,aAAa;YACpC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,UAAU,GAAG,IAAI;YAClD,MAAM,EAAE,QAAQ,CAAC,KAAK;SACvB,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,MAAoB;QAChD,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,sBAAsB,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACjC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;QAClC,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,sBAAsB,GAAG,CAAC,CAAC;QAChC,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAChC,CAAC;IAED,WAAW,CAAC,OAA+B;QACzC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,OAAO;QACL,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;QAClC,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,MAAM,YAAY,GAChB,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,uBAAuB,CAAC;QAE3D,IACE,CAAC,YAAY;YACb,IAAI,CAAC,eAAe,GAAG,CAAC;YACxB,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,eAAe,GAAG,4BAA4B,EAChE,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,iBAAiB,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC,OAAO,CAC3D,GAAG,EAAE;YACH,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAChC,CAAC,CACF,CAAC;QAEF,MAAM,IAAI,CAAC,iBAAiB,CAAC;IAC/B,CAAC;IAEO,KAAK,CAAC,qBAAqB;QACjC,IAAI,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACpC,MAAM,yBAAyB,GAC7B,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,uBAAuB,CAAC;QAE3D,IAAI,yBAAyB,EAAE,CAAC;YAC9B,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,yBAAyB,EAAE,CAAC;YAC1D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YACnD,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,WAAW,CACnB,iCAAiC,EACjC,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,SAAS,CAClE,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyB,CAAC;QAElE,IACE,SAAS,CAAC,SAAS,KAAK,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC5C,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC;YACtC,SAAS,CAAC,UAAU,IAAI,CAAC,EACzB,CAAC;YACD,MAAM,IAAI,WAAW,CACnB,4DAA4D,EAC5D,QAAQ,CAAC,MAAM,EACf,yBAAyB,CAC1B,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,UAAU,GAAG,IAAI,CAAC;QAC3D,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAEnD,IAAI,aAAa,EAAE,WAAW,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;YACtD,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBACzB,GAAG,aAAa;gBAChB,SAAS;aACV,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAClC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,sBAAsB,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACnC,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,QAAQ,CAAC,WAAmB;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE;YACvC,OAAO,EAAE;gBACP,aAAa,EAAE,SAAS,WAAW,EAAE;aACtC;SACF,CAAC,CAAC;IACL,CAAC;IAEO,kBAAkB,CAAC,SAAiB;QAC1C,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,uBAAuB,CAAC;QACrE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,4BAA4B,EAAE,WAAW,CAAC,CACpD,CAAC;QAEF,IAAI,CAAC,eAAe,GAAG,UAAU,CAAC,GAAG,EAAE;YACrC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;YAC5B,KAAK,IAAI,CAAC,qBAAqB,EAAE;iBAC9B,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBACxB,MAAM,SAAS,GACb,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC5D,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;gBAE/B,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;gBAChC,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACjC,CAAC,CAAC,CAAC;QACP,CAAC,EAAE,KAAK,CAAC,CAAC;QAEV,MAAM,KAAK,GAAG,IAAI,CAAC,eAElB,CAAC;QACF,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAClB,CAAC;IAEO,eAAe,CAAC,KAAY;QAClC,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtC,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,KAAK,CAAC,CAAC;YACrE,OAAO;QACT,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC7C,IAAI,CAAC;gBACH,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;YAAC,OAAO,YAAY,EAAE,CAAC;gBACtB,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,YAAY,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IAEO,uBAAuB;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,2BAA2B,GAAG,CAAC,IAAI,IAAI,CAAC,sBAAsB,EAC9D,uBAAuB,CACxB,CAAC;QACF,IAAI,CAAC,sBAAsB,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,uBAAuB,CAAC,CAAC;IACxE,CAAC;IAEO,mBAAmB;QACzB,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACnC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,OAAqB;QACzC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,cAAc,CAAC;QAC7B,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YAC9D,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,cAAc,CAC1B,OAAqB;QAErB,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC;YAC/B,UAAU,EAAE,eAAe;YAC3B,aAAa,EAAE,OAAO,CAAC,YAAY;YACnC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;SAChC,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC7B,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,mCAAmC;aACpD;YACD,IAAI;SACL,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,WAAW,CACnB,4DAA4D,EAC5D,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;gBAChD,CAAC,CAAC,2BAA2B;gBAC7B,CAAC,CAAC,sBAAsB,CAC3B,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAkB,CAAC;QAExD,IACE,CAAC,MAAM,CAAC,YAAY;YACpB,CAAC,MAAM,CAAC,aAAa;YACrB,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC;YACnC,MAAM,CAAC,UAAU,IAAI,CAAC,EACtB,CAAC;YACD,MAAM,IAAI,WAAW,CAAC,8CAA8C,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,MAAM,GAAiB;YAC3B,WAAW,EAAE,MAAM,CAAC,YAAY;YAChC,YAAY,EAAE,MAAM,CAAC,aAAa;YAClC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI;YAChD,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM;SACpE,CAAC;QAEF,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { TwitchClient } from './twitch/twitch-client.js';
|
|
|
2
2
|
export { TwitchApiClient } from './api/twitch-api-client.js';
|
|
3
3
|
export type { TwitchConnectorConfig, TwitchValidatedToken, } from './api/types.js';
|
|
4
4
|
export { TokenManager } from './auth/token-manager.js';
|
|
5
|
+
export type { TwitchAuthorizationCallback, TwitchAuthorizationRequest, TwitchAuthorizationRequestResult, } from './auth/authorization-code-flow.js';
|
|
5
6
|
export type { TwitchTokenStore, TwitchTokens, } from './auth/token-store.js';
|
|
6
7
|
export { TwitchChatClient } from './chat/twitch-chat-client.js';
|
|
7
8
|
export type { SendChatMessageOptions, SendChatMessageResult, TwitchChatMessage, TwitchChatMessageHandler, } from './chat/types.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,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"}
|
|
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,2BAA2B,EAC3B,0BAA0B,EAC1B,gCAAgC,GACjC,MAAM,mCAAmC,CAAC;AAC3C,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.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;
|
|
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;AAWvD,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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"twitch-client.d.ts","sourceRoot":"","sources":["../../src/twitch/twitch-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"twitch-client.d.ts","sourceRoot":"","sources":["../../src/twitch/twitch-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAG9D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,qBAAa,YAAY;IACvB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,eAAe,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC;gBAElC,MAAM,EAAE,qBAAqB;IAuCnC,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAKhC,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;CAG1C"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TwitchApiClient } from '../api/twitch-api-client.js';
|
|
2
|
+
import { AuthorizationCodeFlow } from '../auth/authorization-code-flow.js';
|
|
2
3
|
import { DeviceCodeFlow } from '../auth/device-code-flow.js';
|
|
3
4
|
import { TokenManager } from '../auth/token-manager.js';
|
|
4
5
|
import { TwitchChatClient } from '../chat/twitch-chat-client.js';
|
|
@@ -17,7 +18,13 @@ export class TwitchClient {
|
|
|
17
18
|
scopes: config.scopes,
|
|
18
19
|
fetch: config.fetch,
|
|
19
20
|
});
|
|
20
|
-
|
|
21
|
+
const authorizationCodeFlow = new AuthorizationCodeFlow({
|
|
22
|
+
clientId: config.clientId,
|
|
23
|
+
clientSecret: config.clientSecret,
|
|
24
|
+
scopes: config.scopes,
|
|
25
|
+
fetch: config.fetch,
|
|
26
|
+
});
|
|
27
|
+
this.tokens = new TokenManager(config, tokenStore, deviceCodeFlow, authorizationCodeFlow);
|
|
21
28
|
this.api = new TwitchApiClient(config, this.tokens);
|
|
22
29
|
this.chat = new TwitchChatClient(this.api);
|
|
23
30
|
this.eventSub = new EventSubClient();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"twitch-client.js","sourceRoot":"","sources":["../../src/twitch/twitch-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,MAAM,OAAO,YAAY;IACd,MAAM,CAAe;IACrB,GAAG,CAAkB;IACrB,IAAI,CAAmB;IACvB,QAAQ,CAAiB;IACzB,aAAa,CAAwB;IAE9C,YAAY,MAA6B;QACvC,MAAM,UAAU,GAAqB,MAAM,CAAC,UAAU,CAAC;QAEvD,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC;YACxC,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAC5B,MAAM,EACN,UAAU,EACV,cAAc,
|
|
1
|
+
{"version":3,"file":"twitch-client.js","sourceRoot":"","sources":["../../src/twitch/twitch-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,MAAM,OAAO,YAAY;IACd,MAAM,CAAe;IACrB,GAAG,CAAkB;IACrB,IAAI,CAAmB;IACvB,QAAQ,CAAiB;IACzB,aAAa,CAAwB;IAE9C,YAAY,MAA6B;QACvC,MAAM,UAAU,GAAqB,MAAM,CAAC,UAAU,CAAC;QAEvD,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC;YACxC,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;QAEH,MAAM,qBAAqB,GAAG,IAAI,qBAAqB,CAAC;YACtD,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAC5B,MAAM,EACN,UAAU,EACV,cAAc,EACd,qBAAqB,CACtB,CAAC;QAEF,IAAI,CAAC,GAAG,GAAG,IAAI,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;QACrC,IAAI,CAAC,aAAa,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEzD,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAC3D,IAAI,IAAI,KAAK,sBAAsB,EAAE,CAAC;gBACpC,MAAM,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAC/C,CAAC;YAED,4DAA4D;YAC5D,mCAAmC;YACnC,KAAK,QAAQ,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QACnC,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACnC,CAAC;CACF"}
|