@veloxts/auth 0.3.3 → 0.3.5

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.
Files changed (66) hide show
  1. package/README.md +1157 -30
  2. package/dist/__integration__/fixtures.d.ts +41 -0
  3. package/dist/__integration__/fixtures.d.ts.map +1 -0
  4. package/dist/__integration__/fixtures.js +79 -0
  5. package/dist/__integration__/fixtures.js.map +1 -0
  6. package/dist/__integration__/setup.d.ts +26 -0
  7. package/dist/__integration__/setup.d.ts.map +1 -0
  8. package/dist/__integration__/setup.js +28 -0
  9. package/dist/__integration__/setup.js.map +1 -0
  10. package/dist/adapter.d.ts +710 -0
  11. package/dist/adapter.d.ts.map +1 -0
  12. package/dist/adapter.js +581 -0
  13. package/dist/adapter.js.map +1 -0
  14. package/dist/adapters/better-auth.d.ts +271 -0
  15. package/dist/adapters/better-auth.d.ts.map +1 -0
  16. package/dist/adapters/better-auth.js +341 -0
  17. package/dist/adapters/better-auth.js.map +1 -0
  18. package/dist/adapters/index.d.ts +28 -0
  19. package/dist/adapters/index.d.ts.map +1 -0
  20. package/dist/adapters/index.js +28 -0
  21. package/dist/adapters/index.js.map +1 -0
  22. package/dist/csrf.d.ts +300 -0
  23. package/dist/csrf.d.ts.map +1 -0
  24. package/dist/csrf.js +402 -0
  25. package/dist/csrf.js.map +1 -0
  26. package/dist/guards.d.ts +142 -0
  27. package/dist/guards.d.ts.map +1 -0
  28. package/dist/guards.js +259 -0
  29. package/dist/guards.js.map +1 -0
  30. package/dist/hash.d.ts +91 -0
  31. package/dist/hash.d.ts.map +1 -0
  32. package/dist/hash.js +236 -0
  33. package/dist/hash.js.map +1 -0
  34. package/dist/index.d.ts +27 -32
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +94 -36
  37. package/dist/index.js.map +1 -1
  38. package/dist/jwt.d.ts +157 -0
  39. package/dist/jwt.d.ts.map +1 -0
  40. package/dist/jwt.js +489 -0
  41. package/dist/jwt.js.map +1 -0
  42. package/dist/middleware.d.ts +99 -0
  43. package/dist/middleware.d.ts.map +1 -0
  44. package/dist/middleware.js +253 -0
  45. package/dist/middleware.js.map +1 -0
  46. package/dist/plugin.d.ts +125 -0
  47. package/dist/plugin.d.ts.map +1 -0
  48. package/dist/plugin.js +193 -0
  49. package/dist/plugin.js.map +1 -0
  50. package/dist/policies.d.ts +137 -0
  51. package/dist/policies.d.ts.map +1 -0
  52. package/dist/policies.js +240 -0
  53. package/dist/policies.js.map +1 -0
  54. package/dist/rate-limit.d.ts +231 -0
  55. package/dist/rate-limit.d.ts.map +1 -0
  56. package/dist/rate-limit.js +352 -0
  57. package/dist/rate-limit.js.map +1 -0
  58. package/dist/session.d.ts +500 -0
  59. package/dist/session.d.ts.map +1 -0
  60. package/dist/session.js +801 -0
  61. package/dist/session.js.map +1 -0
  62. package/dist/types.d.ts +261 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +33 -0
  65. package/dist/types.js.map +1 -0
  66. package/package.json +61 -7
@@ -0,0 +1,352 @@
1
+ /**
2
+ * Authentication-specific rate limiting
3
+ *
4
+ * Provides specialized rate limiters for authentication endpoints with:
5
+ * - Per-email+IP tracking (prevents brute force on specific accounts)
6
+ * - Account lockout detection
7
+ * - Separate limits for login, register, and password reset
8
+ * - Progressive backoff support
9
+ *
10
+ * @module auth/rate-limit
11
+ */
12
+ import { AuthError } from './types.js';
13
+ // ============================================================================
14
+ // Rate Limit Store
15
+ // ============================================================================
16
+ /**
17
+ * In-memory rate limit store
18
+ *
19
+ * PRODUCTION NOTE: Replace with Redis for horizontal scaling:
20
+ * ```typescript
21
+ * import Redis from 'ioredis';
22
+ * const redis = new Redis(process.env.REDIS_URL);
23
+ *
24
+ * // Store entry as JSON with TTL
25
+ * await redis.setex(`ratelimit:${key}`, ttlSeconds, JSON.stringify(entry));
26
+ *
27
+ * // Get entry
28
+ * const data = await redis.get(`ratelimit:${key}`);
29
+ * const entry = data ? JSON.parse(data) : null;
30
+ * ```
31
+ */
32
+ const authRateLimitStore = new Map();
33
+ /**
34
+ * Cleanup interval reference
35
+ */
36
+ let cleanupInterval = null;
37
+ /**
38
+ * Start periodic cleanup of expired entries
39
+ */
40
+ function startCleanup() {
41
+ if (cleanupInterval)
42
+ return;
43
+ cleanupInterval = setInterval(() => {
44
+ const now = Date.now();
45
+ for (const [key, entry] of authRateLimitStore.entries()) {
46
+ // Remove if both window and lockout have expired
47
+ const windowExpired = entry.windowResetAt <= now;
48
+ const lockoutExpired = !entry.lockoutUntil || entry.lockoutUntil <= now;
49
+ if (windowExpired && lockoutExpired) {
50
+ authRateLimitStore.delete(key);
51
+ }
52
+ }
53
+ }, 60000); // Run every minute
54
+ }
55
+ /**
56
+ * Stop cleanup interval (for testing)
57
+ */
58
+ export function stopAuthRateLimitCleanup() {
59
+ if (cleanupInterval) {
60
+ clearInterval(cleanupInterval);
61
+ cleanupInterval = null;
62
+ }
63
+ }
64
+ /**
65
+ * Clear all rate limit entries (for testing)
66
+ */
67
+ export function clearAuthRateLimitStore() {
68
+ authRateLimitStore.clear();
69
+ }
70
+ // Start cleanup on module load
71
+ startCleanup();
72
+ // ============================================================================
73
+ // Auth Rate Limiter
74
+ // ============================================================================
75
+ /**
76
+ * Creates an authentication rate limiter
77
+ *
78
+ * This factory returns rate limit middlewares configured for different
79
+ * auth operations with sensible defaults.
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const authRateLimiter = createAuthRateLimiter({
84
+ * login: { maxAttempts: 5, windowMs: 15 * 60 * 1000 },
85
+ * register: { maxAttempts: 3, windowMs: 60 * 60 * 1000 },
86
+ * });
87
+ *
88
+ * // Apply to procedures
89
+ * const login = procedure()
90
+ * .use(authRateLimiter.login(ctx => ctx.input.email))
91
+ * .mutation(loginHandler);
92
+ *
93
+ * const register = procedure()
94
+ * .use(authRateLimiter.register())
95
+ * .mutation(registerHandler);
96
+ * ```
97
+ */
98
+ export function createAuthRateLimiter(config = {}) {
99
+ // Default configurations
100
+ const loginConfig = {
101
+ maxAttempts: config.login?.maxAttempts ?? 5,
102
+ windowMs: config.login?.windowMs ?? 15 * 60 * 1000, // 15 minutes
103
+ lockoutDurationMs: config.login?.lockoutDurationMs ?? 15 * 60 * 1000,
104
+ keyGenerator: config.login?.keyGenerator ?? defaultKeyGenerator,
105
+ message: config.login?.message ?? 'Too many login attempts. Please try again later.',
106
+ progressiveBackoff: config.login?.progressiveBackoff ?? true,
107
+ };
108
+ const registerConfig = {
109
+ maxAttempts: config.register?.maxAttempts ?? 3,
110
+ windowMs: config.register?.windowMs ?? 60 * 60 * 1000, // 1 hour
111
+ lockoutDurationMs: config.register?.lockoutDurationMs ?? 60 * 60 * 1000,
112
+ keyGenerator: config.register?.keyGenerator ?? ((ctx) => ctx.request.ip ?? 'unknown'),
113
+ message: config.register?.message ?? 'Too many registration attempts. Please try again later.',
114
+ progressiveBackoff: config.register?.progressiveBackoff ?? false,
115
+ };
116
+ const passwordResetConfig = {
117
+ maxAttempts: config.passwordReset?.maxAttempts ?? 3,
118
+ windowMs: config.passwordReset?.windowMs ?? 60 * 60 * 1000, // 1 hour
119
+ lockoutDurationMs: config.passwordReset?.lockoutDurationMs ?? 60 * 60 * 1000,
120
+ keyGenerator: config.passwordReset?.keyGenerator ?? ((ctx) => ctx.request.ip ?? 'unknown'),
121
+ message: config.passwordReset?.message ?? 'Too many password reset attempts. Please try again later.',
122
+ progressiveBackoff: config.passwordReset?.progressiveBackoff ?? false,
123
+ };
124
+ const refreshConfig = {
125
+ maxAttempts: config.refresh?.maxAttempts ?? 10,
126
+ windowMs: config.refresh?.windowMs ?? 60 * 1000, // 1 minute
127
+ lockoutDurationMs: config.refresh?.lockoutDurationMs ?? 60 * 1000,
128
+ keyGenerator: config.refresh?.keyGenerator ?? ((ctx) => ctx.request.ip ?? 'unknown'),
129
+ message: config.refresh?.message ?? 'Too many token refresh attempts. Please try again later.',
130
+ progressiveBackoff: config.refresh?.progressiveBackoff ?? false,
131
+ };
132
+ return {
133
+ /**
134
+ * Rate limiter for login attempts
135
+ *
136
+ * @param identifierFn - Function to extract identifier (email) from context
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * login: procedure()
141
+ * .use(authRateLimiter.login((ctx) => (ctx.input as { email: string }).email))
142
+ * .input(LoginSchema)
143
+ * .mutation(handler)
144
+ * ```
145
+ */
146
+ login: (identifierFn) => {
147
+ return createRateLimitMiddleware(loginConfig, 'login', identifierFn);
148
+ },
149
+ /**
150
+ * Rate limiter for registration attempts
151
+ * Uses IP-only by default (no identifier needed)
152
+ */
153
+ register: () => {
154
+ return createRateLimitMiddleware(registerConfig, 'register');
155
+ },
156
+ /**
157
+ * Rate limiter for password reset requests
158
+ *
159
+ * @param identifierFn - Optional function to extract identifier (email)
160
+ */
161
+ passwordReset: (identifierFn) => {
162
+ return createRateLimitMiddleware(passwordResetConfig, 'password-reset', identifierFn);
163
+ },
164
+ /**
165
+ * Rate limiter for token refresh
166
+ */
167
+ refresh: () => {
168
+ return createRateLimitMiddleware(refreshConfig, 'refresh');
169
+ },
170
+ /**
171
+ * Record a failed attempt (call after authentication fails)
172
+ *
173
+ * This allows tracking failures even when rate limit hasn't been hit,
174
+ * enabling account lockout after X failed passwords.
175
+ *
176
+ * @param key - Rate limit key (usually IP:email or IP)
177
+ * @param operation - Operation type for key namespacing
178
+ */
179
+ recordFailure: (key, operation) => {
180
+ const fullKey = `auth:${operation}:${key}`;
181
+ const config = operation === 'login'
182
+ ? loginConfig
183
+ : operation === 'register'
184
+ ? registerConfig
185
+ : passwordResetConfig;
186
+ const now = Date.now();
187
+ const entry = authRateLimitStore.get(fullKey);
188
+ if (!entry || entry.windowResetAt <= now) {
189
+ // Start new window
190
+ authRateLimitStore.set(fullKey, {
191
+ attempts: 1,
192
+ windowResetAt: now + config.windowMs,
193
+ lockoutUntil: null,
194
+ lockoutCount: entry?.lockoutCount ?? 0,
195
+ });
196
+ }
197
+ else {
198
+ // Increment in current window
199
+ entry.attempts++;
200
+ // Check if lockout should trigger
201
+ if (entry.attempts >= config.maxAttempts) {
202
+ const lockoutMultiplier = config.progressiveBackoff ? 2 ** entry.lockoutCount : 1;
203
+ entry.lockoutUntil = now + config.lockoutDurationMs * lockoutMultiplier;
204
+ entry.lockoutCount++;
205
+ }
206
+ }
207
+ },
208
+ /**
209
+ * Reset rate limit for a key (call after successful auth)
210
+ */
211
+ resetLimit: (key, operation) => {
212
+ const fullKey = `auth:${operation}:${key}`;
213
+ authRateLimitStore.delete(fullKey);
214
+ },
215
+ /**
216
+ * Check if a key is currently locked out
217
+ */
218
+ isLockedOut: (key, operation) => {
219
+ const fullKey = `auth:${operation}:${key}`;
220
+ const entry = authRateLimitStore.get(fullKey);
221
+ if (!entry || !entry.lockoutUntil)
222
+ return false;
223
+ if (entry.lockoutUntil <= Date.now()) {
224
+ // Lockout expired
225
+ return false;
226
+ }
227
+ return true;
228
+ },
229
+ /**
230
+ * Get remaining attempts for a key
231
+ */
232
+ getRemainingAttempts: (key, operation) => {
233
+ const fullKey = `auth:${operation}:${key}`;
234
+ const config = operation === 'login'
235
+ ? loginConfig
236
+ : operation === 'register'
237
+ ? registerConfig
238
+ : operation === 'refresh'
239
+ ? refreshConfig
240
+ : passwordResetConfig;
241
+ const entry = authRateLimitStore.get(fullKey);
242
+ if (!entry || entry.windowResetAt <= Date.now()) {
243
+ return config.maxAttempts;
244
+ }
245
+ return Math.max(0, config.maxAttempts - entry.attempts);
246
+ },
247
+ };
248
+ }
249
+ // ============================================================================
250
+ // Internal Helpers
251
+ // ============================================================================
252
+ /**
253
+ * Default key generator combining IP and identifier
254
+ */
255
+ function defaultKeyGenerator(ctx, identifier) {
256
+ const ip = ctx.request.ip ?? 'unknown';
257
+ return identifier ? `${ip}:${identifier.toLowerCase()}` : ip;
258
+ }
259
+ /**
260
+ * Creates the actual rate limit middleware
261
+ */
262
+ function createRateLimitMiddleware(config, operation, identifierFn) {
263
+ return async ({ ctx, input, next }) => {
264
+ const now = Date.now();
265
+ // Generate rate limit key
266
+ const identifier = identifierFn ? identifierFn({ ...ctx, input }) : undefined;
267
+ const baseKey = config.keyGenerator(ctx, identifier);
268
+ const key = `auth:${operation}:${baseKey}`;
269
+ // Get or create entry
270
+ let entry = authRateLimitStore.get(key);
271
+ // Check if currently locked out
272
+ if (entry?.lockoutUntil && entry.lockoutUntil > now) {
273
+ const retryAfter = Math.ceil((entry.lockoutUntil - now) / 1000);
274
+ // Set headers
275
+ ctx.reply.header('X-RateLimit-Limit', String(config.maxAttempts));
276
+ ctx.reply.header('X-RateLimit-Remaining', '0');
277
+ ctx.reply.header('X-RateLimit-Reset', String(Math.ceil(entry.lockoutUntil / 1000)));
278
+ ctx.reply.header('Retry-After', String(retryAfter));
279
+ throw new AuthError(`${config.message} Try again in ${formatDuration(retryAfter * 1000)}.`, 429, 'RATE_LIMIT_EXCEEDED');
280
+ }
281
+ // Clean up expired window
282
+ if (entry && entry.windowResetAt <= now) {
283
+ // Preserve lockout count for progressive backoff
284
+ const lockoutCount = entry.lockoutCount;
285
+ entry = {
286
+ attempts: 0,
287
+ windowResetAt: now + config.windowMs,
288
+ lockoutUntil: null,
289
+ lockoutCount,
290
+ };
291
+ authRateLimitStore.set(key, entry);
292
+ }
293
+ // Initialize if no entry
294
+ if (!entry) {
295
+ entry = {
296
+ attempts: 0,
297
+ windowResetAt: now + config.windowMs,
298
+ lockoutUntil: null,
299
+ lockoutCount: 0,
300
+ };
301
+ authRateLimitStore.set(key, entry);
302
+ }
303
+ // Increment attempt count
304
+ entry.attempts++;
305
+ // Set rate limit headers
306
+ const remaining = Math.max(0, config.maxAttempts - entry.attempts);
307
+ ctx.reply.header('X-RateLimit-Limit', String(config.maxAttempts));
308
+ ctx.reply.header('X-RateLimit-Remaining', String(remaining));
309
+ ctx.reply.header('X-RateLimit-Reset', String(Math.ceil(entry.windowResetAt / 1000)));
310
+ // Check if limit exceeded
311
+ if (entry.attempts > config.maxAttempts) {
312
+ // Apply lockout
313
+ const lockoutMultiplier = config.progressiveBackoff ? 2 ** entry.lockoutCount : 1;
314
+ entry.lockoutUntil = now + config.lockoutDurationMs * lockoutMultiplier;
315
+ entry.lockoutCount++;
316
+ const retryAfter = Math.ceil((entry.lockoutUntil - now) / 1000);
317
+ ctx.reply.header('Retry-After', String(retryAfter));
318
+ throw new AuthError(`${config.message} Try again in ${formatDuration(retryAfter * 1000)}.`, 429, 'RATE_LIMIT_EXCEEDED');
319
+ }
320
+ return next();
321
+ };
322
+ }
323
+ /**
324
+ * Format duration in human-readable form
325
+ */
326
+ function formatDuration(ms) {
327
+ const seconds = Math.ceil(ms / 1000);
328
+ if (seconds < 60)
329
+ return `${seconds} second${seconds !== 1 ? 's' : ''}`;
330
+ const minutes = Math.ceil(seconds / 60);
331
+ if (minutes < 60)
332
+ return `${minutes} minute${minutes !== 1 ? 's' : ''}`;
333
+ const hours = Math.ceil(minutes / 60);
334
+ return `${hours} hour${hours !== 1 ? 's' : ''}`;
335
+ }
336
+ // ============================================================================
337
+ // Convenience Export
338
+ // ============================================================================
339
+ /**
340
+ * Pre-configured auth rate limiter with sensible defaults
341
+ *
342
+ * @example
343
+ * ```typescript
344
+ * import { authRateLimiter } from '@veloxts/auth';
345
+ *
346
+ * const login = procedure()
347
+ * .use(authRateLimiter.login((ctx) => ctx.input.email))
348
+ * .mutation(handler);
349
+ * ```
350
+ */
351
+ export const authRateLimiter = createAuthRateLimiter();
352
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA0FvC,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;;;;;;;;;;;;;;GAeG;AACH,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA0B,CAAC;AAE7D;;GAEG;AACH,IAAI,eAAe,GAA0B,IAAI,CAAC;AAElD;;GAEG;AACH,SAAS,YAAY;IACnB,IAAI,eAAe;QAAE,OAAO;IAE5B,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,kBAAkB,CAAC,OAAO,EAAE,EAAE,CAAC;YACxD,iDAAiD;YACjD,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,IAAI,GAAG,CAAC;YACjD,MAAM,cAAc,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,IAAI,GAAG,CAAC;YAExE,IAAI,aAAa,IAAI,cAAc,EAAE,CAAC;gBACpC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,mBAAmB;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB;IACtC,IAAI,eAAe,EAAE,CAAC;QACpB,aAAa,CAAC,eAAe,CAAC,CAAC;QAC/B,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,kBAAkB,CAAC,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED,+BAA+B;AAC/B,YAAY,EAAE,CAAC;AAEf,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAAgC,EAAE;IACtE,yBAAyB;IACzB,MAAM,WAAW,GAAkC;QACjD,WAAW,EAAE,MAAM,CAAC,KAAK,EAAE,WAAW,IAAI,CAAC;QAC3C,QAAQ,EAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;QACjE,iBAAiB,EAAE,MAAM,CAAC,KAAK,EAAE,iBAAiB,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;QACpE,YAAY,EAAE,MAAM,CAAC,KAAK,EAAE,YAAY,IAAI,mBAAmB;QAC/D,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,kDAAkD;QACpF,kBAAkB,EAAE,MAAM,CAAC,KAAK,EAAE,kBAAkB,IAAI,IAAI;KAC7D,CAAC;IAEF,MAAM,cAAc,GAAkC;QACpD,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,IAAI,CAAC;QAC9C,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,SAAS;QAChE,iBAAiB,EAAE,MAAM,CAAC,QAAQ,EAAE,iBAAiB,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;QACvE,YAAY,EAAE,MAAM,CAAC,QAAQ,EAAE,YAAY,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC;QACrF,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,IAAI,yDAAyD;QAC9F,kBAAkB,EAAE,MAAM,CAAC,QAAQ,EAAE,kBAAkB,IAAI,KAAK;KACjE,CAAC;IAEF,MAAM,mBAAmB,GAAkC;QACzD,WAAW,EAAE,MAAM,CAAC,aAAa,EAAE,WAAW,IAAI,CAAC;QACnD,QAAQ,EAAE,MAAM,CAAC,aAAa,EAAE,QAAQ,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,SAAS;QACrE,iBAAiB,EAAE,MAAM,CAAC,aAAa,EAAE,iBAAiB,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;QAC5E,YAAY,EAAE,MAAM,CAAC,aAAa,EAAE,YAAY,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC;QAC1F,OAAO,EACL,MAAM,CAAC,aAAa,EAAE,OAAO,IAAI,2DAA2D;QAC9F,kBAAkB,EAAE,MAAM,CAAC,aAAa,EAAE,kBAAkB,IAAI,KAAK;KACtE,CAAC;IAEF,MAAM,aAAa,GAAkC;QACnD,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,IAAI,EAAE;QAC9C,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,GAAG,IAAI,EAAE,WAAW;QAC5D,iBAAiB,EAAE,MAAM,CAAC,OAAO,EAAE,iBAAiB,IAAI,EAAE,GAAG,IAAI;QACjE,YAAY,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC;QACpF,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,IAAI,0DAA0D;QAC9F,kBAAkB,EAAE,MAAM,CAAC,OAAO,EAAE,kBAAkB,IAAI,KAAK;KAChE,CAAC;IAEF,OAAO;QACL;;;;;;;;;;;;WAYG;QACH,KAAK,EAAE,CACL,YAA8D,EACL,EAAE;YAC3D,OAAO,yBAAyB,CAAC,WAAW,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;QACvE,CAAC;QAED;;;WAGG;QACH,QAAQ,EAAE,GAKR,EAAE;YACF,OAAO,yBAAyB,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;QAC/D,CAAC;QAED;;;;WAIG;QACH,aAAa,EAAE,CACb,YAA8D,EACL,EAAE;YAC3D,OAAO,yBAAyB,CAAC,mBAAmB,EAAE,gBAAgB,EAAE,YAAY,CAAC,CAAC;QACxF,CAAC;QAED;;WAEG;QACH,OAAO,EAAE,GAKP,EAAE;YACF,OAAO,yBAAyB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QAC7D,CAAC;QAED;;;;;;;;WAQG;QACH,aAAa,EAAE,CAAC,GAAW,EAAE,SAAkD,EAAE,EAAE;YACjF,MAAM,OAAO,GAAG,QAAQ,SAAS,IAAI,GAAG,EAAE,CAAC;YAC3C,MAAM,MAAM,GACV,SAAS,KAAK,OAAO;gBACnB,CAAC,CAAC,WAAW;gBACb,CAAC,CAAC,SAAS,KAAK,UAAU;oBACxB,CAAC,CAAC,cAAc;oBAChB,CAAC,CAAC,mBAAmB,CAAC;YAE5B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAE9C,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,aAAa,IAAI,GAAG,EAAE,CAAC;gBACzC,mBAAmB;gBACnB,kBAAkB,CAAC,GAAG,CAAC,OAAO,EAAE;oBAC9B,QAAQ,EAAE,CAAC;oBACX,aAAa,EAAE,GAAG,GAAG,MAAM,CAAC,QAAQ;oBACpC,YAAY,EAAE,IAAI;oBAClB,YAAY,EAAE,KAAK,EAAE,YAAY,IAAI,CAAC;iBACvC,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,8BAA8B;gBAC9B,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAEjB,kCAAkC;gBAClC,IAAI,KAAK,CAAC,QAAQ,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;oBACzC,MAAM,iBAAiB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;oBAClF,KAAK,CAAC,YAAY,GAAG,GAAG,GAAG,MAAM,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;oBACxE,KAAK,CAAC,YAAY,EAAE,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC;QAED;;WAEG;QACH,UAAU,EAAE,CAAC,GAAW,EAAE,SAAkD,EAAE,EAAE;YAC9E,MAAM,OAAO,GAAG,QAAQ,SAAS,IAAI,GAAG,EAAE,CAAC;YAC3C,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;QAED;;WAEG;QACH,WAAW,EAAE,CAAC,GAAW,EAAE,SAAkD,EAAW,EAAE;YACxF,MAAM,OAAO,GAAG,QAAQ,SAAS,IAAI,GAAG,EAAE,CAAC;YAC3C,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAE9C,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,YAAY;gBAAE,OAAO,KAAK,CAAC;YAChD,IAAI,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBACrC,kBAAkB;gBAClB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED;;WAEG;QACH,oBAAoB,EAAE,CACpB,GAAW,EACX,SAA8D,EACtD,EAAE;YACV,MAAM,OAAO,GAAG,QAAQ,SAAS,IAAI,GAAG,EAAE,CAAC;YAC3C,MAAM,MAAM,GACV,SAAS,KAAK,OAAO;gBACnB,CAAC,CAAC,WAAW;gBACb,CAAC,CAAC,SAAS,KAAK,UAAU;oBACxB,CAAC,CAAC,cAAc;oBAChB,CAAC,CAAC,SAAS,KAAK,SAAS;wBACvB,CAAC,CAAC,aAAa;wBACf,CAAC,CAAC,mBAAmB,CAAC;YAE9B,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9C,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,aAAa,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAChD,OAAO,MAAM,CAAC,WAAW,CAAC;YAC5B,CAAC;YACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC1D,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;GAEG;AACH,SAAS,mBAAmB,CAAC,GAAgB,EAAE,UAAmB;IAChE,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC;IACvC,OAAO,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,SAAS,yBAAyB,CAChC,MAAqC,EACrC,SAAiB,EACjB,YAA8D;IAE9D,OAAO,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,0BAA0B;QAC1B,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9E,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACrD,MAAM,GAAG,GAAG,QAAQ,SAAS,IAAI,OAAO,EAAE,CAAC;QAE3C,sBAAsB;QACtB,IAAI,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAExC,gCAAgC;QAChC,IAAI,KAAK,EAAE,YAAY,IAAI,KAAK,CAAC,YAAY,GAAG,GAAG,EAAE,CAAC;YACpD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAEhE,cAAc;YACd,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;YAClE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;YAC/C,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACpF,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;YAEpD,MAAM,IAAI,SAAS,CACjB,GAAG,MAAM,CAAC,OAAO,iBAAiB,cAAc,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EACtE,GAAG,EACH,qBAAqB,CACtB,CAAC;QACJ,CAAC;QAED,0BAA0B;QAC1B,IAAI,KAAK,IAAI,KAAK,CAAC,aAAa,IAAI,GAAG,EAAE,CAAC;YACxC,iDAAiD;YACjD,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;YACxC,KAAK,GAAG;gBACN,QAAQ,EAAE,CAAC;gBACX,aAAa,EAAE,GAAG,GAAG,MAAM,CAAC,QAAQ;gBACpC,YAAY,EAAE,IAAI;gBAClB,YAAY;aACb,CAAC;YACF,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QAED,yBAAyB;QACzB,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG;gBACN,QAAQ,EAAE,CAAC;gBACX,aAAa,EAAE,GAAG,GAAG,MAAM,CAAC,QAAQ;gBACpC,YAAY,EAAE,IAAI;gBAClB,YAAY,EAAE,CAAC;aAChB,CAAC;YACF,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QAED,0BAA0B;QAC1B,KAAK,CAAC,QAAQ,EAAE,CAAC;QAEjB,yBAAyB;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QACnE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAClE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7D,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErF,0BAA0B;QAC1B,IAAI,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;YACxC,gBAAgB;YAChB,MAAM,iBAAiB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YAClF,KAAK,CAAC,YAAY,GAAG,GAAG,GAAG,MAAM,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;YACxE,KAAK,CAAC,YAAY,EAAE,CAAC;YAErB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAChE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;YAEpD,MAAM,IAAI,SAAS,CACjB,GAAG,MAAM,CAAC,OAAO,iBAAiB,cAAc,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EACtE,GAAG,EACH,qBAAqB,CACtB,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,EAAU;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACrC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAExE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACxC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAExE,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACtC,OAAO,GAAG,KAAK,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAClD,CAAC;AAED,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,EAAE,CAAC"}