@vunexa/lixa 0.0.1-alpha.9 → 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 +263 -143
- package/dist/dao/session-cache.d.ts +11 -0
- package/dist/dao/session-cache.d.ts.map +1 -0
- package/dist/dao/state-cache.d.ts +8 -6
- package/dist/dao/state-cache.d.ts.map +1 -1
- package/dist/dao/types.d.ts +376 -3
- package/dist/dao/types.d.ts.map +1 -1
- package/dist/export-types/index.d.ts +1397 -0
- package/dist/export-types/tsdoc-metadata.json +11 -0
- package/dist/index.cjs +1035 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1361 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +992 -9
- package/dist/index.js.map +1 -1
- package/dist/lixa.d.ts +280 -15
- package/dist/lixa.d.ts.map +1 -1
- package/dist/models/session.d.ts +316 -0
- package/dist/models/session.d.ts.map +1 -0
- package/dist/providers/IProvider.d.ts +127 -4
- package/dist/providers/IProvider.d.ts.map +1 -1
- package/dist/providers/index.d.ts +0 -2
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/types.d.ts +195 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/user-info.d.ts +82 -0
- package/dist/utils/user-info.d.ts.map +1 -0
- package/package.json +15 -10
- package/dist/dao/state-cache.js +0 -18
- package/dist/dao/state-cache.js.map +0 -1
- package/dist/dao/types.js +0 -2
- package/dist/dao/types.js.map +0 -1
- package/dist/lixa.js +0 -244
- package/dist/lixa.js.map +0 -1
- package/dist/providers/IProvider.js +0 -2
- package/dist/providers/IProvider.js.map +0 -1
- package/dist/providers/github.d.ts +0 -9
- package/dist/providers/github.d.ts.map +0 -1
- package/dist/providers/github.js +0 -8
- package/dist/providers/github.js.map +0 -1
- package/dist/providers/google.d.ts +0 -9
- package/dist/providers/google.d.ts.map +0 -1
- package/dist/providers/google.js +0 -8
- package/dist/providers/google.js.map +0 -1
- package/dist/providers/index.js +0 -3
- package/dist/providers/index.js.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/utils/constants.js +0 -4
- package/dist/utils/constants.js.map +0 -1
- package/index.d.ts +0 -229
package/dist/dao/types.d.ts
CHANGED
|
@@ -1,6 +1,379 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { Session } from "../models/session";
|
|
2
|
+
/**
|
|
3
|
+
* OAuth state data structure.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* This structure is used internally by Lixa to store OAuth flow state
|
|
7
|
+
* during the authorization process. It contains the information needed
|
|
8
|
+
* to complete the PKCE flow and route callbacks to the correct provider.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export interface StateData {
|
|
13
|
+
/**
|
|
14
|
+
* Provider name for callback routing.
|
|
15
|
+
* Used to identify which provider configuration to use when handling the callback.
|
|
16
|
+
*
|
|
17
|
+
* @example 'google', 'github', 'custom'
|
|
18
|
+
*/
|
|
19
|
+
provider: string;
|
|
20
|
+
/**
|
|
21
|
+
* PKCE code verifier for secure token exchange.
|
|
22
|
+
* A cryptographically random string (64 hex characters) used in the PKCE flow
|
|
23
|
+
* to prevent authorization code interception attacks.
|
|
24
|
+
*
|
|
25
|
+
* @see RFC 7636 - Proof Key for Code Exchange
|
|
26
|
+
*/
|
|
27
|
+
codeVerifier: string;
|
|
28
|
+
/**
|
|
29
|
+
* Unix timestamp in milliseconds when the state was created.
|
|
30
|
+
* Used for debugging and validation purposes.
|
|
31
|
+
*/
|
|
32
|
+
createdAt: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* State storage operations interface.
|
|
36
|
+
*
|
|
37
|
+
* @remarks
|
|
38
|
+
* Groups all state storage operations together. All methods must be implemented
|
|
39
|
+
* if this interface is provided.
|
|
40
|
+
*
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
export interface StateStorage {
|
|
44
|
+
/**
|
|
45
|
+
* Saves OAuth state with expiration.
|
|
46
|
+
*
|
|
47
|
+
* @param state - The state parameter value (random string for CSRF protection)
|
|
48
|
+
* @param data - State data including provider name and PKCE code verifier
|
|
49
|
+
* @param expiresInSeconds - TTL in seconds (typically 300 for 5 minutes)
|
|
50
|
+
*/
|
|
51
|
+
saveState(state: string, data: StateData, expiresInSeconds: number): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Retrieves OAuth state data.
|
|
54
|
+
*
|
|
55
|
+
* @param state - The state parameter value
|
|
56
|
+
* @returns State data or null if not found or expired
|
|
57
|
+
*/
|
|
58
|
+
getState(state: string): Promise<StateData | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Deletes OAuth state (called after successful validation).
|
|
61
|
+
*
|
|
62
|
+
* @param state - The state parameter value
|
|
63
|
+
*/
|
|
4
64
|
deleteState(state: string): Promise<void>;
|
|
5
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* State handler for OAuth authorization flow.
|
|
68
|
+
*
|
|
69
|
+
* @remarks
|
|
70
|
+
* The StateHandler manages state generation and storage during the OAuth authorization flow.
|
|
71
|
+
*
|
|
72
|
+
* - GenerateState: Optional. Customizes how state parameters and PKCE verifiers are generated.
|
|
73
|
+
* If not provided, uses default implementation (cryptographically secure random strings).
|
|
74
|
+
*
|
|
75
|
+
* - storage: Optional. Provides custom state storage (save/get/delete operations).
|
|
76
|
+
* If not provided, uses in-memory cache (not suitable for production).
|
|
77
|
+
*
|
|
78
|
+
* For production, implement storage with Redis, database, or other distributed cache.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* Full implementation with Redis:
|
|
82
|
+
* ```typescript
|
|
83
|
+
* import { StateHandler, StateData } from '@vunexa/lixa';
|
|
84
|
+
*
|
|
85
|
+
* const stateHandler: StateHandler = {
|
|
86
|
+
* GenerateState: async (provider) => {
|
|
87
|
+
* const state = generateSecureRandomString(32);
|
|
88
|
+
* const codeVerifier = generateSecureRandomString(64);
|
|
89
|
+
* return {
|
|
90
|
+
* state,
|
|
91
|
+
* data: {
|
|
92
|
+
* provider,
|
|
93
|
+
* codeVerifier,
|
|
94
|
+
* createdAt: Date.now()
|
|
95
|
+
* }
|
|
96
|
+
* };
|
|
97
|
+
* },
|
|
98
|
+
*
|
|
99
|
+
* storage: {
|
|
100
|
+
* saveState: async (state, data, expiresInSeconds) => {
|
|
101
|
+
* await redis.setex(`oauth:state:${state}`, expiresInSeconds, JSON.stringify(data));
|
|
102
|
+
* },
|
|
103
|
+
* getState: async (state) => {
|
|
104
|
+
* const data = await redis.get(`oauth:state:${state}`);
|
|
105
|
+
* return data ? JSON.parse(data) : null;
|
|
106
|
+
* },
|
|
107
|
+
* deleteState: async (state) => {
|
|
108
|
+
* await redis.del(`oauth:state:${state}`);
|
|
109
|
+
* }
|
|
110
|
+
* }
|
|
111
|
+
* };
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* Minimal implementation (uses defaults):
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const stateHandler: StateHandler = {
|
|
118
|
+
* storage: {
|
|
119
|
+
* saveState: async (state, data, expiresInSeconds) => {
|
|
120
|
+
* await redis.setex(state, expiresInSeconds, JSON.stringify(data));
|
|
121
|
+
* },
|
|
122
|
+
* getState: async (state) => {
|
|
123
|
+
* const data = await redis.get(state);
|
|
124
|
+
* return data ? JSON.parse(data) : null;
|
|
125
|
+
* },
|
|
126
|
+
* deleteState: async (state) => {
|
|
127
|
+
* await redis.del(state);
|
|
128
|
+
* }
|
|
129
|
+
* }
|
|
130
|
+
* };
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* @public
|
|
134
|
+
*/
|
|
135
|
+
export interface StateHandler {
|
|
136
|
+
/**
|
|
137
|
+
* Generates OAuth state parameter and associated data.
|
|
138
|
+
*
|
|
139
|
+
* @param provider - The provider name for callback routing
|
|
140
|
+
* @returns A Promise that resolves to state string and state data
|
|
141
|
+
*
|
|
142
|
+
* @remarks
|
|
143
|
+
* This method generates:
|
|
144
|
+
* - state: A cryptographically secure random string for CSRF protection
|
|
145
|
+
* - codeVerifier: A PKCE code verifier for secure token exchange
|
|
146
|
+
* - createdAt: Timestamp for debugging
|
|
147
|
+
*
|
|
148
|
+
* If not provided, defaults to generating 32-byte hex strings for state
|
|
149
|
+
* and 64-byte hex strings for code verifier.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* GenerateState: async (provider) => {
|
|
154
|
+
* const state = crypto.randomBytes(16).toString('hex');
|
|
155
|
+
* const codeVerifier = crypto.randomBytes(32).toString('hex');
|
|
156
|
+
* return {
|
|
157
|
+
* state,
|
|
158
|
+
* data: {
|
|
159
|
+
* provider,
|
|
160
|
+
* codeVerifier,
|
|
161
|
+
* createdAt: Date.now()
|
|
162
|
+
* }
|
|
163
|
+
* };
|
|
164
|
+
* }
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
generateState?(provider: string): Promise<{
|
|
168
|
+
state: string;
|
|
169
|
+
data: StateData;
|
|
170
|
+
}>;
|
|
171
|
+
/**
|
|
172
|
+
* State storage operations.
|
|
173
|
+
*
|
|
174
|
+
* @remarks
|
|
175
|
+
* Provides methods for saving, retrieving, and deleting OAuth state.
|
|
176
|
+
* All three methods must be implemented together.
|
|
177
|
+
*
|
|
178
|
+
* If not provided, uses in-memory cache (not suitable for production).
|
|
179
|
+
*/
|
|
180
|
+
stateStorage?: StateStorage;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Session storage operations interface.
|
|
184
|
+
*
|
|
185
|
+
* @remarks
|
|
186
|
+
* Groups all session storage operations together. All methods must be implemented
|
|
187
|
+
* if this interface is provided.
|
|
188
|
+
*
|
|
189
|
+
* @public
|
|
190
|
+
*/
|
|
191
|
+
export interface SessionStorage {
|
|
192
|
+
/**
|
|
193
|
+
* Saves a session with expiration.
|
|
194
|
+
*
|
|
195
|
+
* @param sessionId - Unique session identifier
|
|
196
|
+
* @param session - Session data from GenerateSession()
|
|
197
|
+
* @param expiresInSeconds - TTL in seconds (typically 86400 for 24 hours)
|
|
198
|
+
*/
|
|
199
|
+
saveSession<T extends Session>(sessionId: string, session: T, expiresInSeconds: number): Promise<void>;
|
|
200
|
+
/**
|
|
201
|
+
* Retrieves a session by ID.
|
|
202
|
+
*
|
|
203
|
+
* @param sessionId - Unique session identifier
|
|
204
|
+
* @returns Session data or null if not found or expired
|
|
205
|
+
*/
|
|
206
|
+
getSession<T extends Session>(sessionId: string): Promise<T | null>;
|
|
207
|
+
/**
|
|
208
|
+
* Deletes a session (e.g., on logout).
|
|
209
|
+
*
|
|
210
|
+
* @param sessionId - Unique session identifier
|
|
211
|
+
*/
|
|
212
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
213
|
+
/**
|
|
214
|
+
* Optional helper to retrieve an active session by user email for account linking.
|
|
215
|
+
*
|
|
216
|
+
* @param email - Primary user email
|
|
217
|
+
*/
|
|
218
|
+
getSessionByEmail?<T extends Session>(email: string): Promise<{
|
|
219
|
+
sessionId: string;
|
|
220
|
+
session: T;
|
|
221
|
+
} | null>;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Session handler for OAuth authentication.
|
|
225
|
+
*
|
|
226
|
+
* @remarks
|
|
227
|
+
* The SessionHandler manages session generation and storage after successful OAuth authentication.
|
|
228
|
+
*
|
|
229
|
+
* - GenerateSession: Optional. Customizes how OAuth tokens are converted into session data.
|
|
230
|
+
* If not provided, uses default implementation (access token as session token).
|
|
231
|
+
*
|
|
232
|
+
* - storage: Optional. Provides custom session storage (save/get/delete operations).
|
|
233
|
+
* If not provided, uses in-memory cache (not suitable for production).
|
|
234
|
+
*
|
|
235
|
+
* For production, implement both GenerateSession (for user creation/lookup) and storage
|
|
236
|
+
* (for persistent session storage with Redis, database, etc.).
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* Full implementation with database:
|
|
240
|
+
* ```typescript
|
|
241
|
+
* import { SessionHandler, Session, OAuthTokenResponse, ProviderMetadata, extractUserInfo } from '@vunexa/lixa';
|
|
242
|
+
*
|
|
243
|
+
* const sessionHandler: SessionHandler = {
|
|
244
|
+
* GenerateSession: async (tokenData, providerMetadata) => {
|
|
245
|
+
* // Extract user info and create/retrieve user
|
|
246
|
+
* const { userInfo } = await extractUserInfo(tokenData, providerMetadata);
|
|
247
|
+
* const user = await db.users.upsert({
|
|
248
|
+
* email: userInfo.email,
|
|
249
|
+
* name: userInfo.name
|
|
250
|
+
* });
|
|
251
|
+
*
|
|
252
|
+
* // Return session data (not stored yet)
|
|
253
|
+
* return {
|
|
254
|
+
* token: tokenData.access_token,
|
|
255
|
+
* raw: {
|
|
256
|
+
* ...tokenData,
|
|
257
|
+
* userId: user.id,
|
|
258
|
+
* provider: providerMetadata.name
|
|
259
|
+
* }
|
|
260
|
+
* };
|
|
261
|
+
* },
|
|
262
|
+
*
|
|
263
|
+
* storage: {
|
|
264
|
+
* saveSession: async (sessionId, session, expiresInSeconds) => {
|
|
265
|
+
* const expiresAt = new Date(Date.now() + expiresInSeconds * 1000);
|
|
266
|
+
* await db.sessions.create({
|
|
267
|
+
* id: sessionId,
|
|
268
|
+
* token: session.token,
|
|
269
|
+
* data: session.raw,
|
|
270
|
+
* expiresAt
|
|
271
|
+
* });
|
|
272
|
+
* },
|
|
273
|
+
*
|
|
274
|
+
* getSession: async (sessionId) => {
|
|
275
|
+
* const record = await db.sessions.findOne({
|
|
276
|
+
* id: sessionId,
|
|
277
|
+
* expiresAt: { $gt: new Date() }
|
|
278
|
+
* });
|
|
279
|
+
* return record ? { token: record.token, raw: record.data } : null;
|
|
280
|
+
* },
|
|
281
|
+
*
|
|
282
|
+
* deleteSession: async (sessionId) => {
|
|
283
|
+
* await db.sessions.delete({ id: sessionId });
|
|
284
|
+
* }
|
|
285
|
+
* }
|
|
286
|
+
* };
|
|
287
|
+
* ```
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* Minimal implementation (uses defaults):
|
|
291
|
+
* ```typescript
|
|
292
|
+
* const sessionHandler: SessionHandler = {
|
|
293
|
+
* storage: {
|
|
294
|
+
* saveSession: async (sessionId, session, expiresInSeconds) => {
|
|
295
|
+
* await redis.setex(sessionId, expiresInSeconds, JSON.stringify(session));
|
|
296
|
+
* },
|
|
297
|
+
* getSession: async (sessionId) => {
|
|
298
|
+
* const data = await redis.get(sessionId);
|
|
299
|
+
* return data ? JSON.parse(data) : null;
|
|
300
|
+
* },
|
|
301
|
+
* deleteSession: async (sessionId) => {
|
|
302
|
+
* await redis.del(sessionId);
|
|
303
|
+
* }
|
|
304
|
+
* }
|
|
305
|
+
* };
|
|
306
|
+
* ```
|
|
307
|
+
*
|
|
308
|
+
* @public
|
|
309
|
+
*/
|
|
310
|
+
export interface SessionHandler {
|
|
311
|
+
/**
|
|
312
|
+
* Generates session data from OAuth token data.
|
|
313
|
+
*
|
|
314
|
+
* @param tokenData - The token data received from the OAuth provider's token endpoint
|
|
315
|
+
* @param providerMetadata - Provider metadata including name and endpoints
|
|
316
|
+
* @returns A Promise that resolves to session data
|
|
317
|
+
*
|
|
318
|
+
* @remarks
|
|
319
|
+
* This method is responsible for creating session data from OAuth tokens.
|
|
320
|
+
* It is called after successfully exchanging the authorization code for tokens.
|
|
321
|
+
*
|
|
322
|
+
* Token Data:
|
|
323
|
+
* - access_token: OAuth access token
|
|
324
|
+
* - refresh_token: OAuth refresh token (optional)
|
|
325
|
+
* - expires_in: Token expiration time in seconds
|
|
326
|
+
* - token_type: Token type (usually "Bearer")
|
|
327
|
+
* - id_token: OpenID Connect ID token (for OIDC providers)
|
|
328
|
+
* - scope: Granted scopes
|
|
329
|
+
*
|
|
330
|
+
* Provider Metadata:
|
|
331
|
+
* - name: The provider name (e.g., 'google', 'github')
|
|
332
|
+
* - endpoints: Provider endpoints (authorization, token, userInfo)
|
|
333
|
+
*
|
|
334
|
+
* Your implementation should:
|
|
335
|
+
* 1. Extract user info (using extractUserInfo or decode ID token)
|
|
336
|
+
* 2. Create or lookup users in your database
|
|
337
|
+
* 3. Build and return session data with any custom fields
|
|
338
|
+
*
|
|
339
|
+
* Note: This method should NOT store the session. Storage is handled by the storage object.
|
|
340
|
+
*
|
|
341
|
+
* If not provided, defaults to using the access token as the session token.
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```typescript
|
|
345
|
+
* GenerateSession: async (tokenData, providerMetadata) => {
|
|
346
|
+
* const { userInfo } = await extractUserInfo(tokenData, providerMetadata);
|
|
347
|
+
* const user = await db.users.upsert({ email: userInfo.email });
|
|
348
|
+
*
|
|
349
|
+
* return {
|
|
350
|
+
* token: tokenData.access_token,
|
|
351
|
+
* raw: {
|
|
352
|
+
* ...tokenData,
|
|
353
|
+
* userId: user.id,
|
|
354
|
+
* provider: providerMetadata.name
|
|
355
|
+
* }
|
|
356
|
+
* };
|
|
357
|
+
* }
|
|
358
|
+
* ```
|
|
359
|
+
*/
|
|
360
|
+
generateSession?<T extends Session>(tokenData: import('../models/session').OAuthTokenResponse, providerMetadata: import('../models/session').ProviderMetadata): Promise<T>;
|
|
361
|
+
/**
|
|
362
|
+
* Session storage operations.
|
|
363
|
+
*
|
|
364
|
+
* @remarks
|
|
365
|
+
* Provides methods for saving, retrieving, and deleting sessions.
|
|
366
|
+
* All three methods must be implemented together.
|
|
367
|
+
*
|
|
368
|
+
* If not provided, uses in-memory cache (not suitable for production).
|
|
369
|
+
*/
|
|
370
|
+
sessionStorage?: SessionStorage;
|
|
371
|
+
/**
|
|
372
|
+
* Optional method to generate session data from OAuth tokens.
|
|
373
|
+
*
|
|
374
|
+
* @remarks
|
|
375
|
+
* If not provided, uses default implementation from LocalSessionHandler.
|
|
376
|
+
*/
|
|
377
|
+
generateSession?<T extends Session>(tokenData: import('../models/session').OAuthTokenResponse, providerMetadata: import('../models/session').ProviderMetadata): Promise<T>;
|
|
378
|
+
}
|
|
6
379
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/dao/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dao/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dao/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnF;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAEnD;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,aAAa,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAE9E;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;OAMG;IACH,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvG;;;;;OAKG;IACH,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEpE;;;;OAIG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;;;OAIG;IACH,iBAAiB,CAAC,CAAC,CAAC,SAAS,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CACzG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsFG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgDG;IACH,eAAe,CAAC,CAAC,CAAC,SAAS,OAAO,EAChC,SAAS,EAAE,OAAO,mBAAmB,EAAE,kBAAkB,EACzD,gBAAgB,EAAE,OAAO,mBAAmB,EAAE,gBAAgB,GAC7D,OAAO,CAAC,CAAC,CAAC,CAAC;IAEd;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;;;;OAKG;IACH,eAAe,CAAC,CAAC,CAAC,SAAS,OAAO,EAChC,SAAS,EAAE,OAAO,mBAAmB,EAAE,kBAAkB,EACzD,gBAAgB,EAAE,OAAO,mBAAmB,EAAE,gBAAgB,GAC7D,OAAO,CAAC,CAAC,CAAC,CAAC;CACf"}
|