@dotdo/oauth 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/pkce.d.ts +103 -0
- package/dist/pkce.d.ts.map +1 -0
- package/dist/pkce.js +186 -0
- package/dist/pkce.js.map +1 -0
- package/dist/server.d.ts +67 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +579 -0
- package/dist/server.js.map +1 -0
- package/dist/storage.d.ts +204 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +191 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.d.ts +247 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +79 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dotdo/oauth - OAuth 2.1 Server Implementation
|
|
3
|
+
*
|
|
4
|
+
* Creates a Hono app that implements OAuth 2.1 authorization server endpoints:
|
|
5
|
+
* - /.well-known/oauth-authorization-server (RFC 8414)
|
|
6
|
+
* - /.well-known/oauth-protected-resource (draft-ietf-oauth-resource-metadata)
|
|
7
|
+
* - /authorize (authorization endpoint)
|
|
8
|
+
* - /callback (upstream OAuth callback)
|
|
9
|
+
* - /token (token endpoint)
|
|
10
|
+
* - /register (dynamic client registration - RFC 7591)
|
|
11
|
+
* - /revoke (token revocation - RFC 7009)
|
|
12
|
+
*
|
|
13
|
+
* This server acts as a federated OAuth 2.1 server:
|
|
14
|
+
* - It is an OAuth SERVER to downstream clients (Claude, ChatGPT, etc.)
|
|
15
|
+
* - It is an OAuth CLIENT to upstream providers (WorkOS, Auth0, etc.)
|
|
16
|
+
*/
|
|
17
|
+
import { Hono } from 'hono';
|
|
18
|
+
import { cors } from 'hono/cors';
|
|
19
|
+
import { generateAuthorizationCode, generateToken, generateState, verifyCodeChallenge, hashClientSecret, } from './pkce';
|
|
20
|
+
/**
|
|
21
|
+
* Create an OAuth 2.1 server as a Hono app
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { createOAuth21Server, MemoryOAuthStorage } from '@dotdo/oauth'
|
|
26
|
+
*
|
|
27
|
+
* const oauthServer = createOAuth21Server({
|
|
28
|
+
* issuer: 'https://mcp.do',
|
|
29
|
+
* storage: new MemoryOAuthStorage(),
|
|
30
|
+
* upstream: {
|
|
31
|
+
* provider: 'workos',
|
|
32
|
+
* apiKey: env.WORKOS_API_KEY,
|
|
33
|
+
* clientId: env.WORKOS_CLIENT_ID,
|
|
34
|
+
* },
|
|
35
|
+
* })
|
|
36
|
+
*
|
|
37
|
+
* // Mount on your main app
|
|
38
|
+
* app.route('/', oauthServer)
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export function createOAuth21Server(config) {
|
|
42
|
+
const { issuer, storage, upstream, scopes = ['openid', 'profile', 'email', 'offline_access'], accessTokenTtl = 3600, refreshTokenTtl = 2592000, authCodeTtl = 600, enableDynamicRegistration = true, onUserAuthenticated, debug = false, } = config;
|
|
43
|
+
const app = new Hono();
|
|
44
|
+
// CORS for all endpoints
|
|
45
|
+
app.use('*', cors({
|
|
46
|
+
origin: '*',
|
|
47
|
+
allowMethods: ['GET', 'POST', 'OPTIONS'],
|
|
48
|
+
allowHeaders: ['Content-Type', 'Authorization'],
|
|
49
|
+
exposeHeaders: ['WWW-Authenticate'],
|
|
50
|
+
}));
|
|
51
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
52
|
+
// Well-Known Endpoints
|
|
53
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
54
|
+
/**
|
|
55
|
+
* OAuth 2.1 Authorization Server Metadata (RFC 8414)
|
|
56
|
+
*/
|
|
57
|
+
app.get('/.well-known/oauth-authorization-server', (c) => {
|
|
58
|
+
const metadata = {
|
|
59
|
+
issuer,
|
|
60
|
+
authorization_endpoint: `${issuer}/authorize`,
|
|
61
|
+
token_endpoint: `${issuer}/token`,
|
|
62
|
+
registration_endpoint: enableDynamicRegistration ? `${issuer}/register` : undefined,
|
|
63
|
+
revocation_endpoint: `${issuer}/revoke`,
|
|
64
|
+
scopes_supported: scopes,
|
|
65
|
+
response_types_supported: ['code'],
|
|
66
|
+
grant_types_supported: ['authorization_code', 'refresh_token'],
|
|
67
|
+
token_endpoint_auth_methods_supported: ['none', 'client_secret_basic', 'client_secret_post'],
|
|
68
|
+
code_challenge_methods_supported: ['S256'],
|
|
69
|
+
};
|
|
70
|
+
return c.json(metadata);
|
|
71
|
+
});
|
|
72
|
+
/**
|
|
73
|
+
* OAuth 2.1 Protected Resource Metadata
|
|
74
|
+
*/
|
|
75
|
+
app.get('/.well-known/oauth-protected-resource', (c) => {
|
|
76
|
+
const metadata = {
|
|
77
|
+
resource: issuer,
|
|
78
|
+
authorization_servers: [issuer],
|
|
79
|
+
scopes_supported: scopes,
|
|
80
|
+
bearer_methods_supported: ['header'],
|
|
81
|
+
};
|
|
82
|
+
return c.json(metadata);
|
|
83
|
+
});
|
|
84
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
85
|
+
// Authorization Endpoint
|
|
86
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
87
|
+
/**
|
|
88
|
+
* Authorization endpoint - starts the OAuth flow
|
|
89
|
+
*
|
|
90
|
+
* Required parameters:
|
|
91
|
+
* - response_type: must be 'code'
|
|
92
|
+
* - client_id: registered client ID
|
|
93
|
+
* - redirect_uri: must match registered URI
|
|
94
|
+
* - code_challenge: PKCE code challenge
|
|
95
|
+
* - code_challenge_method: must be 'S256'
|
|
96
|
+
*
|
|
97
|
+
* Optional:
|
|
98
|
+
* - scope: requested scopes
|
|
99
|
+
* - state: CSRF protection
|
|
100
|
+
*/
|
|
101
|
+
app.get('/authorize', async (c) => {
|
|
102
|
+
const params = c.req.query();
|
|
103
|
+
// Validate required parameters
|
|
104
|
+
const clientId = params.client_id;
|
|
105
|
+
const redirectUri = params.redirect_uri;
|
|
106
|
+
const responseType = params.response_type;
|
|
107
|
+
const codeChallenge = params.code_challenge;
|
|
108
|
+
const codeChallengeMethod = params.code_challenge_method;
|
|
109
|
+
const scope = params.scope;
|
|
110
|
+
const state = params.state;
|
|
111
|
+
if (debug) {
|
|
112
|
+
console.log('[OAuth] Authorize request:', { clientId, redirectUri, responseType, scope });
|
|
113
|
+
}
|
|
114
|
+
// Validate response_type
|
|
115
|
+
if (responseType !== 'code') {
|
|
116
|
+
return c.json({ error: 'unsupported_response_type', error_description: 'Only code response type is supported' }, 400);
|
|
117
|
+
}
|
|
118
|
+
// Validate client
|
|
119
|
+
if (!clientId) {
|
|
120
|
+
return c.json({ error: 'invalid_request', error_description: 'client_id is required' }, 400);
|
|
121
|
+
}
|
|
122
|
+
const client = await storage.getClient(clientId);
|
|
123
|
+
if (!client) {
|
|
124
|
+
return c.json({ error: 'invalid_client', error_description: 'Client not found' }, 400);
|
|
125
|
+
}
|
|
126
|
+
// Validate redirect_uri
|
|
127
|
+
if (!redirectUri) {
|
|
128
|
+
return c.json({ error: 'invalid_request', error_description: 'redirect_uri is required' }, 400);
|
|
129
|
+
}
|
|
130
|
+
if (!client.redirectUris.includes(redirectUri)) {
|
|
131
|
+
return c.json({ error: 'invalid_request', error_description: 'redirect_uri not registered for this client' }, 400);
|
|
132
|
+
}
|
|
133
|
+
// Validate PKCE (required in OAuth 2.1)
|
|
134
|
+
if (!codeChallenge) {
|
|
135
|
+
return redirectWithError(redirectUri, 'invalid_request', 'code_challenge is required for OAuth 2.1', state);
|
|
136
|
+
}
|
|
137
|
+
if (codeChallengeMethod !== 'S256') {
|
|
138
|
+
return redirectWithError(redirectUri, 'invalid_request', 'code_challenge_method must be S256', state);
|
|
139
|
+
}
|
|
140
|
+
// Store the authorization request and redirect to upstream
|
|
141
|
+
const upstreamState = generateState(64);
|
|
142
|
+
// Store pending auth as a temporary authorization code that will be replaced
|
|
143
|
+
await storage.saveAuthorizationCode({
|
|
144
|
+
code: `pending:${upstreamState}`,
|
|
145
|
+
clientId,
|
|
146
|
+
userId: '', // Will be filled after upstream auth
|
|
147
|
+
redirectUri,
|
|
148
|
+
scope,
|
|
149
|
+
codeChallenge,
|
|
150
|
+
codeChallengeMethod: 'S256',
|
|
151
|
+
state,
|
|
152
|
+
issuedAt: Date.now(),
|
|
153
|
+
expiresAt: Date.now() + authCodeTtl * 1000,
|
|
154
|
+
});
|
|
155
|
+
// Build upstream authorization URL
|
|
156
|
+
const upstreamAuthUrl = buildUpstreamAuthUrl(upstream, {
|
|
157
|
+
redirectUri: `${issuer}/callback`,
|
|
158
|
+
state: upstreamState,
|
|
159
|
+
scope: scope || 'openid profile email',
|
|
160
|
+
});
|
|
161
|
+
if (debug) {
|
|
162
|
+
console.log('[OAuth] Redirecting to upstream:', upstreamAuthUrl);
|
|
163
|
+
}
|
|
164
|
+
return c.redirect(upstreamAuthUrl);
|
|
165
|
+
});
|
|
166
|
+
/**
|
|
167
|
+
* Callback from upstream OAuth provider
|
|
168
|
+
*/
|
|
169
|
+
app.get('/callback', async (c) => {
|
|
170
|
+
const code = c.req.query('code');
|
|
171
|
+
const upstreamState = c.req.query('state');
|
|
172
|
+
const error = c.req.query('error');
|
|
173
|
+
const errorDescription = c.req.query('error_description');
|
|
174
|
+
if (debug) {
|
|
175
|
+
console.log('[OAuth] Callback received:', { code: !!code, state: upstreamState, error });
|
|
176
|
+
}
|
|
177
|
+
if (error) {
|
|
178
|
+
// Retrieve pending auth to get redirect_uri
|
|
179
|
+
const pendingAuth = await storage.consumeAuthorizationCode(`pending:${upstreamState}`);
|
|
180
|
+
if (pendingAuth) {
|
|
181
|
+
return redirectWithError(pendingAuth.redirectUri, error, errorDescription, pendingAuth.state);
|
|
182
|
+
}
|
|
183
|
+
return c.json({ error, error_description: errorDescription }, 400);
|
|
184
|
+
}
|
|
185
|
+
if (!code || !upstreamState) {
|
|
186
|
+
return c.json({ error: 'invalid_request', error_description: 'Missing code or state' }, 400);
|
|
187
|
+
}
|
|
188
|
+
// Retrieve pending authorization
|
|
189
|
+
const pendingAuth = await storage.consumeAuthorizationCode(`pending:${upstreamState}`);
|
|
190
|
+
if (!pendingAuth) {
|
|
191
|
+
return c.json({ error: 'invalid_request', error_description: 'Invalid or expired state' }, 400);
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
// Exchange code with upstream provider
|
|
195
|
+
const upstreamTokens = await exchangeUpstreamCode(upstream, code, `${issuer}/callback`);
|
|
196
|
+
if (debug) {
|
|
197
|
+
console.log('[OAuth] Upstream tokens received:', { hasAccessToken: !!upstreamTokens.access_token });
|
|
198
|
+
}
|
|
199
|
+
// Get or create user
|
|
200
|
+
const user = await getOrCreateUser(storage, upstreamTokens.user, onUserAuthenticated);
|
|
201
|
+
// Generate our own authorization code
|
|
202
|
+
const authCode = generateAuthorizationCode();
|
|
203
|
+
await storage.saveAuthorizationCode({
|
|
204
|
+
code: authCode,
|
|
205
|
+
clientId: pendingAuth.clientId,
|
|
206
|
+
userId: user.id,
|
|
207
|
+
redirectUri: pendingAuth.redirectUri,
|
|
208
|
+
scope: pendingAuth.scope,
|
|
209
|
+
codeChallenge: pendingAuth.codeChallenge,
|
|
210
|
+
codeChallengeMethod: 'S256',
|
|
211
|
+
state: pendingAuth.state,
|
|
212
|
+
issuedAt: Date.now(),
|
|
213
|
+
expiresAt: Date.now() + authCodeTtl * 1000,
|
|
214
|
+
});
|
|
215
|
+
// Redirect back to client with our code
|
|
216
|
+
const redirectUrl = new URL(pendingAuth.redirectUri);
|
|
217
|
+
redirectUrl.searchParams.set('code', authCode);
|
|
218
|
+
if (pendingAuth.state) {
|
|
219
|
+
redirectUrl.searchParams.set('state', pendingAuth.state);
|
|
220
|
+
}
|
|
221
|
+
if (debug) {
|
|
222
|
+
console.log('[OAuth] Redirecting to client:', redirectUrl.toString());
|
|
223
|
+
}
|
|
224
|
+
return c.redirect(redirectUrl.toString());
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
if (debug) {
|
|
228
|
+
console.error('[OAuth] Callback error:', err);
|
|
229
|
+
}
|
|
230
|
+
return redirectWithError(pendingAuth.redirectUri, 'server_error', err instanceof Error ? err.message : 'Authentication failed', pendingAuth.state);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
234
|
+
// Token Endpoint
|
|
235
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
236
|
+
/**
|
|
237
|
+
* Token endpoint - exchanges authorization code for tokens
|
|
238
|
+
*/
|
|
239
|
+
app.post('/token', async (c) => {
|
|
240
|
+
const contentType = c.req.header('content-type');
|
|
241
|
+
let params;
|
|
242
|
+
if (contentType?.includes('application/json')) {
|
|
243
|
+
params = await c.req.json();
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
const formData = await c.req.parseBody();
|
|
247
|
+
params = Object.fromEntries(Object.entries(formData).map(([k, v]) => [k, String(v)]));
|
|
248
|
+
}
|
|
249
|
+
const grantType = params.grant_type;
|
|
250
|
+
if (debug) {
|
|
251
|
+
console.log('[OAuth] Token request:', { grantType, clientId: params.client_id });
|
|
252
|
+
}
|
|
253
|
+
if (grantType === 'authorization_code') {
|
|
254
|
+
return handleAuthorizationCodeGrant(c, params, storage, accessTokenTtl, refreshTokenTtl, debug);
|
|
255
|
+
}
|
|
256
|
+
else if (grantType === 'refresh_token') {
|
|
257
|
+
return handleRefreshTokenGrant(c, params, storage, accessTokenTtl, refreshTokenTtl, debug);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
return c.json({ error: 'unsupported_grant_type', error_description: 'Only authorization_code and refresh_token grants are supported' }, 400);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
264
|
+
// Dynamic Client Registration
|
|
265
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
266
|
+
if (enableDynamicRegistration) {
|
|
267
|
+
/**
|
|
268
|
+
* Client registration endpoint (RFC 7591)
|
|
269
|
+
*/
|
|
270
|
+
app.post('/register', async (c) => {
|
|
271
|
+
const body = await c.req.json();
|
|
272
|
+
if (debug) {
|
|
273
|
+
console.log('[OAuth] Client registration:', body);
|
|
274
|
+
}
|
|
275
|
+
if (!body.client_name) {
|
|
276
|
+
return c.json({ error: 'invalid_client_metadata', error_description: 'client_name is required' }, 400);
|
|
277
|
+
}
|
|
278
|
+
if (!body.redirect_uris || body.redirect_uris.length === 0) {
|
|
279
|
+
return c.json({ error: 'invalid_client_metadata', error_description: 'redirect_uris is required' }, 400);
|
|
280
|
+
}
|
|
281
|
+
// Generate client credentials
|
|
282
|
+
const clientId = `client_${generateToken(24)}`;
|
|
283
|
+
const clientSecret = generateToken(48);
|
|
284
|
+
const clientSecretHash = await hashClientSecret(clientSecret);
|
|
285
|
+
const client = {
|
|
286
|
+
clientId,
|
|
287
|
+
clientSecretHash,
|
|
288
|
+
clientName: body.client_name,
|
|
289
|
+
redirectUris: body.redirect_uris,
|
|
290
|
+
grantTypes: body.grant_types || ['authorization_code', 'refresh_token'],
|
|
291
|
+
responseTypes: body.response_types || ['code'],
|
|
292
|
+
tokenEndpointAuthMethod: body.token_endpoint_auth_method || 'client_secret_basic',
|
|
293
|
+
scope: body.scope,
|
|
294
|
+
createdAt: Date.now(),
|
|
295
|
+
};
|
|
296
|
+
await storage.saveClient(client);
|
|
297
|
+
// Return client credentials (secret is only shown once)
|
|
298
|
+
return c.json({
|
|
299
|
+
client_id: clientId,
|
|
300
|
+
client_secret: clientSecret,
|
|
301
|
+
client_id_issued_at: Math.floor(client.createdAt / 1000),
|
|
302
|
+
client_secret_expires_at: 0, // Never expires
|
|
303
|
+
client_name: client.clientName,
|
|
304
|
+
redirect_uris: client.redirectUris,
|
|
305
|
+
grant_types: client.grantTypes,
|
|
306
|
+
response_types: client.responseTypes,
|
|
307
|
+
token_endpoint_auth_method: client.tokenEndpointAuthMethod,
|
|
308
|
+
scope: client.scope,
|
|
309
|
+
}, 201);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
313
|
+
// Token Revocation
|
|
314
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
315
|
+
/**
|
|
316
|
+
* Token revocation endpoint (RFC 7009)
|
|
317
|
+
*/
|
|
318
|
+
app.post('/revoke', async (c) => {
|
|
319
|
+
const formData = await c.req.parseBody();
|
|
320
|
+
const token = String(formData.token || '');
|
|
321
|
+
const tokenTypeHint = String(formData.token_type_hint || '');
|
|
322
|
+
if (!token) {
|
|
323
|
+
return c.json({ error: 'invalid_request', error_description: 'token is required' }, 400);
|
|
324
|
+
}
|
|
325
|
+
// Try to revoke as access token first
|
|
326
|
+
if (tokenTypeHint !== 'refresh_token') {
|
|
327
|
+
await storage.revokeAccessToken(token);
|
|
328
|
+
}
|
|
329
|
+
// Then try as refresh token
|
|
330
|
+
if (tokenTypeHint !== 'access_token') {
|
|
331
|
+
await storage.revokeRefreshToken(token);
|
|
332
|
+
}
|
|
333
|
+
// RFC 7009 says to return 200 OK even if token was invalid
|
|
334
|
+
return c.json({ success: true });
|
|
335
|
+
});
|
|
336
|
+
return app;
|
|
337
|
+
}
|
|
338
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
339
|
+
// Helper Functions
|
|
340
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
341
|
+
function redirectWithError(redirectUri, error, description, state) {
|
|
342
|
+
const url = new URL(redirectUri);
|
|
343
|
+
url.searchParams.set('error', error);
|
|
344
|
+
if (description) {
|
|
345
|
+
url.searchParams.set('error_description', description);
|
|
346
|
+
}
|
|
347
|
+
if (state) {
|
|
348
|
+
url.searchParams.set('state', state);
|
|
349
|
+
}
|
|
350
|
+
return Response.redirect(url.toString(), 302);
|
|
351
|
+
}
|
|
352
|
+
function buildUpstreamAuthUrl(upstream, params) {
|
|
353
|
+
if (upstream.provider === 'workos') {
|
|
354
|
+
const url = new URL('https://api.workos.com/user_management/authorize');
|
|
355
|
+
url.searchParams.set('client_id', upstream.clientId);
|
|
356
|
+
url.searchParams.set('redirect_uri', params.redirectUri);
|
|
357
|
+
url.searchParams.set('response_type', 'code');
|
|
358
|
+
url.searchParams.set('state', params.state);
|
|
359
|
+
url.searchParams.set('provider', 'authkit');
|
|
360
|
+
return url.toString();
|
|
361
|
+
}
|
|
362
|
+
// Custom provider
|
|
363
|
+
if (!upstream.authorizationEndpoint) {
|
|
364
|
+
throw new Error('authorizationEndpoint is required for custom providers');
|
|
365
|
+
}
|
|
366
|
+
const url = new URL(upstream.authorizationEndpoint);
|
|
367
|
+
url.searchParams.set('client_id', upstream.clientId);
|
|
368
|
+
url.searchParams.set('redirect_uri', params.redirectUri);
|
|
369
|
+
url.searchParams.set('response_type', 'code');
|
|
370
|
+
url.searchParams.set('state', params.state);
|
|
371
|
+
url.searchParams.set('scope', params.scope);
|
|
372
|
+
return url.toString();
|
|
373
|
+
}
|
|
374
|
+
async function exchangeUpstreamCode(upstream, code, redirectUri) {
|
|
375
|
+
if (upstream.provider === 'workos') {
|
|
376
|
+
const response = await fetch('https://api.workos.com/user_management/authenticate', {
|
|
377
|
+
method: 'POST',
|
|
378
|
+
headers: {
|
|
379
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
380
|
+
'Authorization': `Bearer ${upstream.apiKey}`,
|
|
381
|
+
},
|
|
382
|
+
body: new URLSearchParams({
|
|
383
|
+
grant_type: 'authorization_code',
|
|
384
|
+
client_id: upstream.clientId,
|
|
385
|
+
code,
|
|
386
|
+
redirect_uri: redirectUri,
|
|
387
|
+
}).toString(),
|
|
388
|
+
});
|
|
389
|
+
if (!response.ok) {
|
|
390
|
+
const error = await response.text();
|
|
391
|
+
throw new Error(`WorkOS authentication failed: ${response.status} - ${error}`);
|
|
392
|
+
}
|
|
393
|
+
return response.json();
|
|
394
|
+
}
|
|
395
|
+
// Custom provider
|
|
396
|
+
if (!upstream.tokenEndpoint) {
|
|
397
|
+
throw new Error('tokenEndpoint is required for custom providers');
|
|
398
|
+
}
|
|
399
|
+
const response = await fetch(upstream.tokenEndpoint, {
|
|
400
|
+
method: 'POST',
|
|
401
|
+
headers: {
|
|
402
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
403
|
+
},
|
|
404
|
+
body: new URLSearchParams({
|
|
405
|
+
grant_type: 'authorization_code',
|
|
406
|
+
client_id: upstream.clientId,
|
|
407
|
+
client_secret: upstream.apiKey,
|
|
408
|
+
code,
|
|
409
|
+
redirect_uri: redirectUri,
|
|
410
|
+
}).toString(),
|
|
411
|
+
});
|
|
412
|
+
if (!response.ok) {
|
|
413
|
+
const error = await response.text();
|
|
414
|
+
throw new Error(`Token exchange failed: ${response.status} - ${error}`);
|
|
415
|
+
}
|
|
416
|
+
return response.json();
|
|
417
|
+
}
|
|
418
|
+
async function getOrCreateUser(storage, upstreamUser, onUserAuthenticated) {
|
|
419
|
+
// Try to find existing user by email
|
|
420
|
+
let user = await storage.getUserByEmail(upstreamUser.email);
|
|
421
|
+
if (!user) {
|
|
422
|
+
// Create new user
|
|
423
|
+
user = {
|
|
424
|
+
id: upstreamUser.id,
|
|
425
|
+
email: upstreamUser.email,
|
|
426
|
+
name: [upstreamUser.first_name, upstreamUser.last_name].filter(Boolean).join(' ') || undefined,
|
|
427
|
+
organizationId: upstreamUser.organization_id,
|
|
428
|
+
createdAt: Date.now(),
|
|
429
|
+
updatedAt: Date.now(),
|
|
430
|
+
lastLoginAt: Date.now(),
|
|
431
|
+
};
|
|
432
|
+
await storage.saveUser(user);
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
// Update last login
|
|
436
|
+
user.lastLoginAt = Date.now();
|
|
437
|
+
user.updatedAt = Date.now();
|
|
438
|
+
await storage.saveUser(user);
|
|
439
|
+
}
|
|
440
|
+
await onUserAuthenticated?.(user);
|
|
441
|
+
return user;
|
|
442
|
+
}
|
|
443
|
+
async function handleAuthorizationCodeGrant(c, params, storage, accessTokenTtl, refreshTokenTtl, debug) {
|
|
444
|
+
const { code, client_id, redirect_uri, code_verifier } = params;
|
|
445
|
+
if (!code) {
|
|
446
|
+
return c.json({ error: 'invalid_request', error_description: 'code is required' }, 400);
|
|
447
|
+
}
|
|
448
|
+
if (!client_id) {
|
|
449
|
+
return c.json({ error: 'invalid_request', error_description: 'client_id is required' }, 400);
|
|
450
|
+
}
|
|
451
|
+
// Consume authorization code (one-time use)
|
|
452
|
+
const authCode = await storage.consumeAuthorizationCode(code);
|
|
453
|
+
if (!authCode) {
|
|
454
|
+
return c.json({ error: 'invalid_grant', error_description: 'Invalid or expired authorization code' }, 400);
|
|
455
|
+
}
|
|
456
|
+
// Verify client
|
|
457
|
+
if (authCode.clientId !== client_id) {
|
|
458
|
+
return c.json({ error: 'invalid_grant', error_description: 'Client mismatch' }, 400);
|
|
459
|
+
}
|
|
460
|
+
// Verify redirect_uri
|
|
461
|
+
if (redirect_uri && authCode.redirectUri !== redirect_uri) {
|
|
462
|
+
return c.json({ error: 'invalid_grant', error_description: 'redirect_uri mismatch' }, 400);
|
|
463
|
+
}
|
|
464
|
+
// Verify PKCE
|
|
465
|
+
if (authCode.codeChallenge) {
|
|
466
|
+
if (!code_verifier) {
|
|
467
|
+
return c.json({ error: 'invalid_request', error_description: 'code_verifier is required' }, 400);
|
|
468
|
+
}
|
|
469
|
+
const valid = await verifyCodeChallenge(code_verifier, authCode.codeChallenge, authCode.codeChallengeMethod || 'S256');
|
|
470
|
+
if (!valid) {
|
|
471
|
+
return c.json({ error: 'invalid_grant', error_description: 'Invalid code_verifier' }, 400);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
// Check expiration
|
|
475
|
+
if (Date.now() > authCode.expiresAt) {
|
|
476
|
+
return c.json({ error: 'invalid_grant', error_description: 'Authorization code expired' }, 400);
|
|
477
|
+
}
|
|
478
|
+
// Generate tokens
|
|
479
|
+
const accessToken = generateToken(48);
|
|
480
|
+
const refreshToken = generateToken(64);
|
|
481
|
+
const now = Date.now();
|
|
482
|
+
await storage.saveAccessToken({
|
|
483
|
+
token: accessToken,
|
|
484
|
+
tokenType: 'Bearer',
|
|
485
|
+
clientId: authCode.clientId,
|
|
486
|
+
userId: authCode.userId,
|
|
487
|
+
scope: authCode.scope,
|
|
488
|
+
issuedAt: now,
|
|
489
|
+
expiresAt: now + accessTokenTtl * 1000,
|
|
490
|
+
});
|
|
491
|
+
await storage.saveRefreshToken({
|
|
492
|
+
token: refreshToken,
|
|
493
|
+
clientId: authCode.clientId,
|
|
494
|
+
userId: authCode.userId,
|
|
495
|
+
scope: authCode.scope,
|
|
496
|
+
issuedAt: now,
|
|
497
|
+
expiresAt: refreshTokenTtl > 0 ? now + refreshTokenTtl * 1000 : undefined,
|
|
498
|
+
});
|
|
499
|
+
// Save grant
|
|
500
|
+
await storage.saveGrant({
|
|
501
|
+
id: `${authCode.userId}:${authCode.clientId}`,
|
|
502
|
+
userId: authCode.userId,
|
|
503
|
+
clientId: authCode.clientId,
|
|
504
|
+
scope: authCode.scope,
|
|
505
|
+
createdAt: now,
|
|
506
|
+
lastUsedAt: now,
|
|
507
|
+
});
|
|
508
|
+
if (debug) {
|
|
509
|
+
console.log('[OAuth] Tokens issued for user:', authCode.userId);
|
|
510
|
+
}
|
|
511
|
+
const response = {
|
|
512
|
+
access_token: accessToken,
|
|
513
|
+
token_type: 'Bearer',
|
|
514
|
+
expires_in: accessTokenTtl,
|
|
515
|
+
refresh_token: refreshToken,
|
|
516
|
+
scope: authCode.scope,
|
|
517
|
+
};
|
|
518
|
+
return c.json(response);
|
|
519
|
+
}
|
|
520
|
+
async function handleRefreshTokenGrant(c, params, storage, accessTokenTtl, refreshTokenTtl, debug) {
|
|
521
|
+
const { refresh_token, client_id } = params;
|
|
522
|
+
if (!refresh_token) {
|
|
523
|
+
return c.json({ error: 'invalid_request', error_description: 'refresh_token is required' }, 400);
|
|
524
|
+
}
|
|
525
|
+
const storedRefresh = await storage.getRefreshToken(refresh_token);
|
|
526
|
+
if (!storedRefresh) {
|
|
527
|
+
return c.json({ error: 'invalid_grant', error_description: 'Invalid refresh token' }, 400);
|
|
528
|
+
}
|
|
529
|
+
if (storedRefresh.revoked) {
|
|
530
|
+
return c.json({ error: 'invalid_grant', error_description: 'Refresh token has been revoked' }, 400);
|
|
531
|
+
}
|
|
532
|
+
if (storedRefresh.expiresAt && Date.now() > storedRefresh.expiresAt) {
|
|
533
|
+
return c.json({ error: 'invalid_grant', error_description: 'Refresh token expired' }, 400);
|
|
534
|
+
}
|
|
535
|
+
if (client_id && storedRefresh.clientId !== client_id) {
|
|
536
|
+
return c.json({ error: 'invalid_grant', error_description: 'Client mismatch' }, 400);
|
|
537
|
+
}
|
|
538
|
+
// Generate new tokens
|
|
539
|
+
const accessToken = generateToken(48);
|
|
540
|
+
const newRefreshToken = generateToken(64);
|
|
541
|
+
const now = Date.now();
|
|
542
|
+
await storage.saveAccessToken({
|
|
543
|
+
token: accessToken,
|
|
544
|
+
tokenType: 'Bearer',
|
|
545
|
+
clientId: storedRefresh.clientId,
|
|
546
|
+
userId: storedRefresh.userId,
|
|
547
|
+
scope: storedRefresh.scope,
|
|
548
|
+
issuedAt: now,
|
|
549
|
+
expiresAt: now + accessTokenTtl * 1000,
|
|
550
|
+
});
|
|
551
|
+
// Rotate refresh token
|
|
552
|
+
await storage.revokeRefreshToken(refresh_token);
|
|
553
|
+
await storage.saveRefreshToken({
|
|
554
|
+
token: newRefreshToken,
|
|
555
|
+
clientId: storedRefresh.clientId,
|
|
556
|
+
userId: storedRefresh.userId,
|
|
557
|
+
scope: storedRefresh.scope,
|
|
558
|
+
issuedAt: now,
|
|
559
|
+
expiresAt: refreshTokenTtl > 0 ? now + refreshTokenTtl * 1000 : undefined,
|
|
560
|
+
});
|
|
561
|
+
// Update grant last used
|
|
562
|
+
const grant = await storage.getGrant(storedRefresh.userId, storedRefresh.clientId);
|
|
563
|
+
if (grant) {
|
|
564
|
+
grant.lastUsedAt = now;
|
|
565
|
+
await storage.saveGrant(grant);
|
|
566
|
+
}
|
|
567
|
+
if (debug) {
|
|
568
|
+
console.log('[OAuth] Tokens refreshed for user:', storedRefresh.userId);
|
|
569
|
+
}
|
|
570
|
+
const response = {
|
|
571
|
+
access_token: accessToken,
|
|
572
|
+
token_type: 'Bearer',
|
|
573
|
+
expires_in: accessTokenTtl,
|
|
574
|
+
refresh_token: newRefreshToken,
|
|
575
|
+
scope: storedRefresh.scope,
|
|
576
|
+
};
|
|
577
|
+
return c.json(response);
|
|
578
|
+
}
|
|
579
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAWhC,OAAO,EACL,yBAAyB,EACzB,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,QAAQ,CAAA;AA4Bf;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA2B;IAC7D,MAAM,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,EACR,MAAM,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,CAAC,EACzD,cAAc,GAAG,IAAI,EACrB,eAAe,GAAG,OAAO,EACzB,WAAW,GAAG,GAAG,EACjB,yBAAyB,GAAG,IAAI,EAChC,mBAAmB,EACnB,KAAK,GAAG,KAAK,GACd,GAAG,MAAM,CAAA;IAEV,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IAEtB,yBAAyB;IACzB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC;QAChB,MAAM,EAAE,GAAG;QACX,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC;QACxC,YAAY,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;QAC/C,aAAa,EAAE,CAAC,kBAAkB,CAAC;KACpC,CAAC,CAAC,CAAA;IAEH,8EAA8E;IAC9E,uBAAuB;IACvB,8EAA8E;IAE9E;;OAEG;IACH,GAAG,CAAC,GAAG,CAAC,yCAAyC,EAAE,CAAC,CAAC,EAAE,EAAE;QACvD,MAAM,QAAQ,GAAwB;YACpC,MAAM;YACN,sBAAsB,EAAE,GAAG,MAAM,YAAY;YAC7C,cAAc,EAAE,GAAG,MAAM,QAAQ;YACjC,qBAAqB,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAAG,MAAM,WAAW,CAAC,CAAC,CAAC,SAAS;YACnF,mBAAmB,EAAE,GAAG,MAAM,SAAS;YACvC,gBAAgB,EAAE,MAAM;YACxB,wBAAwB,EAAE,CAAC,MAAM,CAAC;YAClC,qBAAqB,EAAE,CAAC,oBAAoB,EAAE,eAAe,CAAC;YAC9D,qCAAqC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,oBAAoB,CAAC;YAC5F,gCAAgC,EAAE,CAAC,MAAM,CAAC;SAC3C,CAAA;QAED,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;IAEF;;OAEG;IACH,GAAG,CAAC,GAAG,CAAC,uCAAuC,EAAE,CAAC,CAAC,EAAE,EAAE;QACrD,MAAM,QAAQ,GAA0B;YACtC,QAAQ,EAAE,MAAM;YAChB,qBAAqB,EAAE,CAAC,MAAM,CAAC;YAC/B,gBAAgB,EAAE,MAAM;YACxB,wBAAwB,EAAE,CAAC,QAAQ,CAAC;SACrC,CAAA;QAED,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;IAEF,8EAA8E;IAC9E,yBAAyB;IACzB,8EAA8E;IAE9E;;;;;;;;;;;;;OAaG;IACH,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAChC,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAA;QAE5B,+BAA+B;QAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAA;QACjC,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAA;QACvC,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,CAAA;QACzC,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,CAAA;QAC3C,MAAM,mBAAmB,GAAG,MAAM,CAAC,qBAAqB,CAAA;QACxD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;QAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;QAE1B,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAA;QAC3F,CAAC;QAED,yBAAyB;QACzB,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YAC5B,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,sCAAsC,EAAgB,EAAE,GAAG,CAAC,CAAA;QACrI,CAAC;QAED,kBAAkB;QAClB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,uBAAuB,EAAgB,EAAE,GAAG,CAAC,CAAA;QAC5G,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QAChD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAgB,EAAE,GAAG,CAAC,CAAA;QACtG,CAAC;QAED,wBAAwB;QACxB,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,0BAA0B,EAAgB,EAAE,GAAG,CAAC,CAAA;QAC/G,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/C,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,6CAA6C,EAAgB,EAAE,GAAG,CAAC,CAAA;QAClI,CAAC;QAED,wCAAwC;QACxC,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,iBAAiB,CAAC,WAAW,EAAE,iBAAiB,EAAE,0CAA0C,EAAE,KAAK,CAAC,CAAA;QAC7G,CAAC;QAED,IAAI,mBAAmB,KAAK,MAAM,EAAE,CAAC;YACnC,OAAO,iBAAiB,CAAC,WAAW,EAAE,iBAAiB,EAAE,oCAAoC,EAAE,KAAK,CAAC,CAAA;QACvG,CAAC;QAED,2DAA2D;QAC3D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAA;QAEvC,6EAA6E;QAC7E,MAAM,OAAO,CAAC,qBAAqB,CAAC;YAClC,IAAI,EAAE,WAAW,aAAa,EAAE;YAChC,QAAQ;YACR,MAAM,EAAE,EAAE,EAAE,qCAAqC;YACjD,WAAW;YACX,KAAK;YACL,aAAa;YACb,mBAAmB,EAAE,MAAM;YAC3B,KAAK;YACL,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;YACpB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,IAAI;SAC3C,CAAC,CAAA;QAEF,mCAAmC;QACnC,MAAM,eAAe,GAAG,oBAAoB,CAAC,QAAQ,EAAE;YACrD,WAAW,EAAE,GAAG,MAAM,WAAW;YACjC,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,KAAK,IAAI,sBAAsB;SACvC,CAAC,CAAA;QAEF,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,eAAe,CAAC,CAAA;QAClE,CAAC;QAED,OAAO,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAA;IACpC,CAAC,CAAC,CAAA;IAEF;;OAEG;IACH,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QAChC,MAAM,aAAa,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC1C,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAClC,MAAM,gBAAgB,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;QAEzD,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAA;QAC1F,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,4CAA4C;YAC5C,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,wBAAwB,CAAC,WAAW,aAAa,EAAE,CAAC,CAAA;YACtF,IAAI,WAAW,EAAE,CAAC;gBAChB,OAAO,iBAAiB,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,EAAE,gBAAgB,EAAE,WAAW,CAAC,KAAK,CAAC,CAAA;YAC/F,CAAC;YACD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAgB,EAAE,GAAG,CAAC,CAAA;QAClF,CAAC;QAED,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC5B,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,uBAAuB,EAAgB,EAAE,GAAG,CAAC,CAAA;QAC5G,CAAC;QAED,iCAAiC;QACjC,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,wBAAwB,CAAC,WAAW,aAAa,EAAE,CAAC,CAAA;QACtF,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,0BAA0B,EAAgB,EAAE,GAAG,CAAC,CAAA;QAC/G,CAAC;QAED,IAAI,CAAC;YACH,uCAAuC;YACvC,MAAM,cAAc,GAAG,MAAM,oBAAoB,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,WAAW,CAAC,CAAA;YAEvF,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,EAAE,cAAc,EAAE,CAAC,CAAC,cAAc,CAAC,YAAY,EAAE,CAAC,CAAA;YACrG,CAAC;YAED,qBAAqB;YACrB,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAA;YAErF,sCAAsC;YACtC,MAAM,QAAQ,GAAG,yBAAyB,EAAE,CAAA;YAE5C,MAAM,OAAO,CAAC,qBAAqB,CAAC;gBAClC,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,WAAW,CAAC,QAAQ;gBAC9B,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,WAAW,EAAE,WAAW,CAAC,WAAW;gBACpC,KAAK,EAAE,WAAW,CAAC,KAAK;gBACxB,aAAa,EAAE,WAAW,CAAC,aAAa;gBACxC,mBAAmB,EAAE,MAAM;gBAC3B,KAAK,EAAE,WAAW,CAAC,KAAK;gBACxB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;gBACpB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,IAAI;aAC3C,CAAC,CAAA;YAEF,wCAAwC;YACxC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,CAAA;YACpD,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;YAC9C,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;gBACtB,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,CAAA;YAC1D,CAAC;YAED,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAA;YACvE,CAAC;YAED,OAAO,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAA;YAC/C,CAAC;YACD,OAAO,iBAAiB,CACtB,WAAW,CAAC,WAAW,EACvB,cAAc,EACd,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,EAC5D,WAAW,CAAC,KAAK,CAClB,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,8EAA8E;IAC9E,iBAAiB;IACjB,8EAA8E;IAE9E;;OAEG;IACH,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC7B,MAAM,WAAW,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;QAChD,IAAI,MAA8B,CAAA;QAElC,IAAI,WAAW,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC9C,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;QAC7B,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;YACxC,MAAM,GAAG,MAAM,CAAC,WAAW,CACzB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CACzD,CAAA;QACH,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAA;QAEnC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;QAClF,CAAC;QAED,IAAI,SAAS,KAAK,oBAAoB,EAAE,CAAC;YACvC,OAAO,4BAA4B,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,KAAK,CAAC,CAAA;QACjG,CAAC;aAAM,IAAI,SAAS,KAAK,eAAe,EAAE,CAAC;YACzC,OAAO,uBAAuB,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,KAAK,CAAC,CAAA;QAC5F,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,gEAAgE,EAAgB,EAAE,GAAG,CAAC,CAAA;QAC5J,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,8EAA8E;IAC9E,8BAA8B;IAC9B,8EAA8E;IAE9E,IAAI,yBAAyB,EAAE,CAAC;QAC9B;;WAEG;QACH,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YAChC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAOzB,CAAA;YAEJ,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,IAAI,CAAC,CAAA;YACnD,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,yBAAyB,EAAgB,EAAE,GAAG,CAAC,CAAA;YACtH,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,2BAA2B,EAAgB,EAAE,GAAG,CAAC,CAAA;YACxH,CAAC;YAED,8BAA8B;YAC9B,MAAM,QAAQ,GAAG,UAAU,aAAa,CAAC,EAAE,CAAC,EAAE,CAAA;YAC9C,MAAM,YAAY,GAAG,aAAa,CAAC,EAAE,CAAC,CAAA;YACtC,MAAM,gBAAgB,GAAG,MAAM,gBAAgB,CAAC,YAAY,CAAC,CAAA;YAE7D,MAAM,MAAM,GAAgB;gBAC1B,QAAQ;gBACR,gBAAgB;gBAChB,UAAU,EAAE,IAAI,CAAC,WAAW;gBAC5B,YAAY,EAAE,IAAI,CAAC,aAAa;gBAChC,UAAU,EAAG,IAAI,CAAC,WAAyC,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAAC;gBACtG,aAAa,EAAG,IAAI,CAAC,cAA+C,IAAI,CAAC,MAAM,CAAC;gBAChF,uBAAuB,EAAG,IAAI,CAAC,0BAAqE,IAAI,qBAAqB;gBAC7H,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAA;YAED,MAAM,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;YAEhC,wDAAwD;YACxD,OAAO,CAAC,CAAC,IAAI,CAAC;gBACZ,SAAS,EAAE,QAAQ;gBACnB,aAAa,EAAE,YAAY;gBAC3B,mBAAmB,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;gBACxD,wBAAwB,EAAE,CAAC,EAAE,gBAAgB;gBAC7C,WAAW,EAAE,MAAM,CAAC,UAAU;gBAC9B,aAAa,EAAE,MAAM,CAAC,YAAY;gBAClC,WAAW,EAAE,MAAM,CAAC,UAAU;gBAC9B,cAAc,EAAE,MAAM,CAAC,aAAa;gBACpC,0BAA0B,EAAE,MAAM,CAAC,uBAAuB;gBAC1D,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB,EAAE,GAAG,CAAC,CAAA;QACT,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,8EAA8E;IAC9E,mBAAmB;IACnB,8EAA8E;IAE9E;;OAEG;IACH,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC9B,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;QACxC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;QAC1C,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,IAAI,EAAE,CAAC,CAAA;QAE5D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAgB,EAAE,GAAG,CAAC,CAAA;QACxG,CAAC;QAED,sCAAsC;QACtC,IAAI,aAAa,KAAK,eAAe,EAAE,CAAC;YACtC,MAAM,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAA;QACxC,CAAC;QAED,4BAA4B;QAC5B,IAAI,aAAa,KAAK,cAAc,EAAE,CAAC;YACrC,MAAM,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAA;QACzC,CAAC;QAED,2DAA2D;QAC3D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IAClC,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,SAAS,iBAAiB,CAAC,WAAmB,EAAE,KAAa,EAAE,WAAoB,EAAE,KAAc;IACjG,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAA;IAChC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IACpC,IAAI,WAAW,EAAE,CAAC;QAChB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;IACxD,CAAC;IACD,IAAI,KAAK,EAAE,CAAC;QACV,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IACtC,CAAC;IACD,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAA;AAC/C,CAAC;AAED,SAAS,oBAAoB,CAC3B,QAA6B,EAC7B,MAA6D;IAE7D,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,kDAAkD,CAAC,CAAA;QACvE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACpD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;QACxD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAA;QAC7C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;QAC3C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;QAC3C,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;IACvB,CAAC;IAED,kBAAkB;IAClB,IAAI,CAAC,QAAQ,CAAC,qBAAqB,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;IAC3E,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAA;IACnD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACpD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;IACxD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAA;IAC7C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAC3C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAC3C,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;AACvB,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,QAA6B,EAC7B,IAAY,EACZ,WAAmB;IAanB,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,qDAAqD,EAAE;YAClF,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,mCAAmC;gBACnD,eAAe,EAAE,UAAU,QAAQ,CAAC,MAAM,EAAE;aAC7C;YACD,IAAI,EAAE,IAAI,eAAe,CAAC;gBACxB,UAAU,EAAE,oBAAoB;gBAChC,SAAS,EAAE,QAAQ,CAAC,QAAQ;gBAC5B,IAAI;gBACJ,YAAY,EAAE,WAAW;aAC1B,CAAC,CAAC,QAAQ,EAAE;SACd,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;YACnC,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,MAAM,MAAM,KAAK,EAAE,CAAC,CAAA;QAChF,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAA;IACxB,CAAC;IAED,kBAAkB;IAClB,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAA;IACnE,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,EAAE;QACnD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,mCAAmC;SACpD;QACD,IAAI,EAAE,IAAI,eAAe,CAAC;YACxB,UAAU,EAAE,oBAAoB;YAChC,SAAS,EAAE,QAAQ,CAAC,QAAQ;YAC5B,aAAa,EAAE,QAAQ,CAAC,MAAM;YAC9B,IAAI;YACJ,YAAY,EAAE,WAAW;SAC1B,CAAC,CAAC,QAAQ,EAAE;KACd,CAAC,CAAA;IAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QACnC,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,MAAM,KAAK,EAAE,CAAC,CAAA;IACzE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAA;AACxB,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,OAAqB,EACrB,YAA8G,EAC9G,mBAA+D;IAE/D,qCAAqC;IACrC,IAAI,IAAI,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;IAE3D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,kBAAkB;QAClB,IAAI,GAAG;YACL,EAAE,EAAE,YAAY,CAAC,EAAE;YACnB,KAAK,EAAE,YAAY,CAAC,KAAK;YACzB,IAAI,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS;YAC9F,cAAc,EAAE,YAAY,CAAC,eAAe;YAC5C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;SACxB,CAAA;QACD,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC;SAAM,CAAC;QACN,oBAAoB;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC3B,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC;IAED,MAAM,mBAAmB,EAAE,CAAC,IAAI,CAAC,CAAA;IAEjC,OAAO,IAAI,CAAA;AACb,CAAC;AAED,KAAK,UAAU,4BAA4B,CACzC,CAAM,EACN,MAA8B,EAC9B,OAAqB,EACrB,cAAsB,EACtB,eAAuB,EACvB,KAAc;IAEd,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,MAAM,CAAA;IAE/D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAgB,EAAE,GAAG,CAAC,CAAA;IACvG,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,uBAAuB,EAAgB,EAAE,GAAG,CAAC,CAAA;IAC5G,CAAC;IAED,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAA;IAC7D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,uCAAuC,EAAgB,EAAE,GAAG,CAAC,CAAA;IAC1H,CAAC;IAED,gBAAgB;IAChB,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAgB,EAAE,GAAG,CAAC,CAAA;IACpG,CAAC;IAED,sBAAsB;IACtB,IAAI,YAAY,IAAI,QAAQ,CAAC,WAAW,KAAK,YAAY,EAAE,CAAC;QAC1D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,uBAAuB,EAAgB,EAAE,GAAG,CAAC,CAAA;IAC1G,CAAC;IAED,cAAc;IACd,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC3B,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,2BAA2B,EAAgB,EAAE,GAAG,CAAC,CAAA;QAChH,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,aAAa,EAAE,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,mBAAmB,IAAI,MAAM,CAAC,CAAA;QACtH,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,uBAAuB,EAAgB,EAAE,GAAG,CAAC,CAAA;QAC1G,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC;QACpC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,4BAA4B,EAAgB,EAAE,GAAG,CAAC,CAAA;IAC/G,CAAC;IAED,kBAAkB;IAClB,MAAM,WAAW,GAAG,aAAa,CAAC,EAAE,CAAC,CAAA;IACrC,MAAM,YAAY,GAAG,aAAa,CAAC,EAAE,CAAC,CAAA;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAEtB,MAAM,OAAO,CAAC,eAAe,CAAC;QAC5B,KAAK,EAAE,WAAW;QAClB,SAAS,EAAE,QAAQ;QACnB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,QAAQ,EAAE,GAAG;QACb,SAAS,EAAE,GAAG,GAAG,cAAc,GAAG,IAAI;KACvC,CAAC,CAAA;IAEF,MAAM,OAAO,CAAC,gBAAgB,CAAC;QAC7B,KAAK,EAAE,YAAY;QACnB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,QAAQ,EAAE,GAAG;QACb,SAAS,EAAE,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS;KAC1E,CAAC,CAAA;IAEF,aAAa;IACb,MAAM,OAAO,CAAC,SAAS,CAAC;QACtB,EAAE,EAAE,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,QAAQ,EAAE;QAC7C,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,SAAS,EAAE,GAAG;QACd,UAAU,EAAE,GAAG;KAChB,CAAC,CAAA;IAEF,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IACjE,CAAC;IAED,MAAM,QAAQ,GAAkB;QAC9B,YAAY,EAAE,WAAW;QACzB,UAAU,EAAE,QAAQ;QACpB,UAAU,EAAE,cAAc;QAC1B,aAAa,EAAE,YAAY;QAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;KACtB,CAAA;IAED,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AACzB,CAAC;AAED,KAAK,UAAU,uBAAuB,CACpC,CAAM,EACN,MAA8B,EAC9B,OAAqB,EACrB,cAAsB,EACtB,eAAuB,EACvB,KAAc;IAEd,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,MAAM,CAAA;IAE3C,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,2BAA2B,EAAgB,EAAE,GAAG,CAAC,CAAA;IAChH,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,CAAA;IAClE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,uBAAuB,EAAgB,EAAE,GAAG,CAAC,CAAA;IAC1G,CAAC;IAED,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;QAC1B,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,gCAAgC,EAAgB,EAAE,GAAG,CAAC,CAAA;IACnH,CAAC;IAED,IAAI,aAAa,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC,SAAS,EAAE,CAAC;QACpE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,uBAAuB,EAAgB,EAAE,GAAG,CAAC,CAAA;IAC1G,CAAC;IAED,IAAI,SAAS,IAAI,aAAa,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACtD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAgB,EAAE,GAAG,CAAC,CAAA;IACpG,CAAC;IAED,sBAAsB;IACtB,MAAM,WAAW,GAAG,aAAa,CAAC,EAAE,CAAC,CAAA;IACrC,MAAM,eAAe,GAAG,aAAa,CAAC,EAAE,CAAC,CAAA;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAEtB,MAAM,OAAO,CAAC,eAAe,CAAC;QAC5B,KAAK,EAAE,WAAW;QAClB,SAAS,EAAE,QAAQ;QACnB,QAAQ,EAAE,aAAa,CAAC,QAAQ;QAChC,MAAM,EAAE,aAAa,CAAC,MAAM;QAC5B,KAAK,EAAE,aAAa,CAAC,KAAK;QAC1B,QAAQ,EAAE,GAAG;QACb,SAAS,EAAE,GAAG,GAAG,cAAc,GAAG,IAAI;KACvC,CAAC,CAAA;IAEF,uBAAuB;IACvB,MAAM,OAAO,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAA;IAC/C,MAAM,OAAO,CAAC,gBAAgB,CAAC;QAC7B,KAAK,EAAE,eAAe;QACtB,QAAQ,EAAE,aAAa,CAAC,QAAQ;QAChC,MAAM,EAAE,aAAa,CAAC,MAAM;QAC5B,KAAK,EAAE,aAAa,CAAC,KAAK;QAC1B,QAAQ,EAAE,GAAG;QACb,SAAS,EAAE,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS;KAC1E,CAAC,CAAA;IAEF,yBAAyB;IACzB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;IAClF,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,CAAC,UAAU,GAAG,GAAG,CAAA;QACtB,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAChC,CAAC;IAED,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACzE,CAAC;IAED,MAAM,QAAQ,GAAkB;QAC9B,YAAY,EAAE,WAAW;QACzB,UAAU,EAAE,QAAQ;QACpB,UAAU,EAAE,cAAc;QAC1B,aAAa,EAAE,eAAe;QAC9B,KAAK,EAAE,aAAa,CAAC,KAAK;KAC3B,CAAA;IAED,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AACzB,CAAC"}
|