@revealui/security 0.0.1-pre.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/LICENSE +202 -0
- package/dist/index.js +1841 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/SecurityValidation.ts","../src/RateLimiterService.ts","../src/RateLimitingService.ts","../src/CSRFService.ts","../src/EncryptionService.ts","../src/SecurityMonitoringService.ts","../src/SecurityService.ts","../src/SessionService.ts","../src/TokenService.ts"],"sourcesContent":["/**\r\n * Centralized Security Validation Utilities\r\n *\r\n * Provides consistent security validation across all server actions\r\n */\r\n\r\nimport { z } from 'zod';\r\n\r\n// Environment validation schema\r\nconst EnvironmentSchema = z.object({\r\n PAYLOAD_SECRET: z.string().min(32, 'PAYLOAD_SECRET must be at least 32 characters'),\r\n MCP_ENCRYPTION_KEY: z.string().min(64, 'MCP_ENCRYPTION_KEY must be at least 64 characters'),\r\n TURSO_URL: z.string().url().optional(),\r\n TURSO_AUTH_TOKEN: z.string().optional(),\r\n SUPPORT_EMAIL: z.string().email().optional(),\r\n});\r\n\r\n// Rate limiting configuration\r\nexport interface RateLimitConfig {\r\n windowMs: number;\r\n maxRequests: number;\r\n keyGenerator?: (input: unknown) => string;\r\n}\r\n\r\n// Default rate limiting configurations\r\nexport const RATE_LIMITS = {\r\n CHAT: { windowMs: 60 * 1000, maxRequests: 10 }, // 10 requests per minute\r\n CONTENT: { windowMs: 60 * 1000, maxRequests: 5 }, // 5 requests per minute\r\n CONTACT: { windowMs: 15 * 60 * 1000, maxRequests: 3 }, // 3 requests per 15 minutes\r\n RECOMMENDATIONS: { windowMs: 60 * 1000, maxRequests: 20 }, // 20 requests per minute\r\n} as const;\r\n\r\n// Rate limiting store (in production, use Redis or similar)\r\nconst rateLimitStore = new Map<string, { count: number; resetTime: number }>();\r\n\r\n/**\r\n * Validate environment variables\r\n */\r\nexport async function validateEnvironment(): Promise<void> {\r\n const validation = EnvironmentSchema.safeParse(process.env);\r\n\r\n if (!validation.success) {\r\n const errors = validation.error.issues\r\n .map(issue => `${issue.path.join('.')}: ${issue.message}`)\r\n .join(', ');\r\n\r\n throw new Error(`Environment validation failed: ${errors}`);\r\n }\r\n}\r\n\r\n/**\r\n * Check rate limiting for a given key\r\n */\r\nexport async function checkRateLimit(\r\n key: string,\r\n config: RateLimitConfig\r\n): Promise<{ allowed: boolean; remaining: number; resetTime: number }> {\r\n const now = Date.now();\r\n\r\n // Clean up expired entries\r\n for (const [k, v] of rateLimitStore.entries()) {\r\n if (v.resetTime < now) {\r\n rateLimitStore.delete(k);\r\n }\r\n }\r\n\r\n const entry = rateLimitStore.get(key);\r\n\r\n if (!entry || entry.resetTime < now) {\r\n // New window or first request\r\n rateLimitStore.set(key, { count: 1, resetTime: now + config.windowMs });\r\n return {\r\n allowed: true,\r\n remaining: config.maxRequests - 1,\r\n resetTime: now + config.windowMs,\r\n };\r\n }\r\n\r\n if (entry.count >= config.maxRequests) {\r\n return {\r\n allowed: false,\r\n remaining: 0,\r\n resetTime: entry.resetTime,\r\n };\r\n }\r\n\r\n // Increment counter\r\n entry.count++;\r\n rateLimitStore.set(key, entry);\r\n\r\n return {\r\n allowed: true,\r\n remaining: config.maxRequests - entry.count,\r\n resetTime: entry.resetTime,\r\n };\r\n}\r\n\r\n/**\r\n * Generate rate limit key for user-based limiting\r\n */\r\nexport function generateRateLimitKey(userId: string, action: string): string {\r\n return `rate_limit:${action}:${userId}`;\r\n}\r\n\r\n/**\r\n * Generate rate limit key for IP-based limiting\r\n */\r\nexport function generateIPRateLimitKey(ip: string, action: string): string {\r\n return `rate_limit:${action}:ip:${ip}`;\r\n}\r\n\r\n/**\r\n * Validate CSRF token (basic implementation)\r\n */\r\nexport async function validateCSRFToken(token: string, sessionToken: string): Promise<boolean> {\r\n // In a real implementation, you'd validate against a secure session store\r\n // For now, we'll do a basic comparison\r\n return token === sessionToken && token.length > 0;\r\n}\r\n\r\n/**\r\n * Sanitize input to prevent XSS\r\n * Basic sanitization - in production, use a proper HTML sanitizer library\r\n */\r\nexport function sanitizeInput(input: string): string {\r\n // Basic XSS prevention - remove script tags and event handlers\r\n return input\r\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\r\n .replace(/on\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\r\n .replace(/javascript:/gi, '')\r\n .trim();\r\n}\r\n\r\n/**\r\n * Validate and sanitize user input\r\n */\r\nexport function validateAndSanitizeInput<T>(\r\n input: T,\r\n schema: z.ZodSchema<T>\r\n): { success: true; data: T } | { success: false; error: string } {\r\n try {\r\n const validation = schema.safeParse(input);\r\n\r\n if (!validation.success) {\r\n return {\r\n success: false,\r\n error: validation.error.issues.map(i => i.message).join(', '),\r\n };\r\n }\r\n\r\n // Sanitize string fields\r\n const sanitized = sanitizeObject(validation.data);\r\n\r\n return {\r\n success: true,\r\n data: sanitized,\r\n };\r\n } catch (error) {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : 'Validation failed',\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Recursively sanitize object properties\r\n */\r\nfunction sanitizeObject(obj: unknown): unknown {\r\n if (typeof obj === 'string') {\r\n return sanitizeInput(obj);\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(sanitizeObject);\r\n }\r\n\r\n if (obj && typeof obj === 'object') {\r\n const sanitized: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(obj)) {\r\n sanitized[key] = sanitizeObject(value);\r\n }\r\n return sanitized;\r\n }\r\n\r\n return obj;\r\n}\r\n\r\n/**\r\n * Security headers for responses\r\n */\r\nexport const SECURITY_HEADERS = {\r\n 'X-Content-Type-Options': 'nosniff',\r\n 'X-Frame-Options': 'DENY',\r\n 'X-XSS-Protection': '1; mode=block',\r\n 'Referrer-Policy': 'strict-origin-when-cross-origin',\r\n 'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',\r\n} as const;\r\n\r\n/**\r\n * Log security events\r\n */\r\nexport function logSecurityEvent(\r\n event: string,\r\n details: Record<string, unknown>,\r\n severity: 'low' | 'medium' | 'high' | 'critical' = 'medium'\r\n): void {\r\n console.log(`[SECURITY-${severity.toUpperCase()}] ${event}:`, {\r\n timestamp: new Date().toISOString(),\r\n severity,\r\n ...details,\r\n });\r\n}\r\n\r\n","const devLogger = {\r\n debug: (...args: unknown[]) => console.debug('[security]', ...args),\r\n info: (...args: unknown[]) => console.log('[security]', ...args),\r\n warn: (...args: unknown[]) => console.warn('[security]', ...args),\r\n error: (...args: unknown[]) => console.error('[security]', ...args),\r\n forService: (_name: string) => ({\r\n debug: (...args: unknown[]) => console.debug('[security]', ...args),\r\n info: (...args: unknown[]) => console.log('[security]', ...args),\r\n warn: (...args: unknown[]) => console.warn('[security]', ...args),\r\n error: (...args: unknown[]) => console.error('[security]', ...args),\r\n }),\r\n};\r\nimport type {Payload} from 'payload';\r\n\r\ntype RateLimitConfig = {\r\n windowMs?: number;\r\n maxRequests?: number;\r\n skipSuccessfulRequests?: boolean;\r\n skipFailedRequests?: boolean;\r\n standardHeaders?: boolean;\r\n legacyHeaders?: boolean;\r\n};\r\ntype RateLimitResult = {\r\n allowed: boolean;\r\n remaining: number;\r\n resetTime: number;\r\n retryAfter?: number;\r\n};\r\ntype RateLimitState = {\r\n count: number;\r\n resetTime: number;\r\n lastRequestTime: number;\r\n};\r\n\r\n/**\r\n * Rate Limiter Service using Next.js 15 patterns\r\n * Provides multiple rate limiting algorithms with in-memory storage\r\n * Optimized for Vercel deployment without external dependencies\r\n */\r\nexport class RateLimiterService {\r\n private readonly config: Required<RateLimitConfig>;\r\n private readonly inMemoryStore = new Map<string, RateLimitState>();\r\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n constructor(config: RateLimitConfig) {\r\n this.config = {\r\n windowMs: config.windowMs ?? 15 * 60 * 1000, // 15 minutes\r\n maxRequests: config.maxRequests ?? 100,\r\n skipSuccessfulRequests: config.skipSuccessfulRequests ?? false,\r\n skipFailedRequests: config.skipFailedRequests ?? false,\r\n standardHeaders: config.standardHeaders ?? true,\r\n legacyHeaders: config.legacyHeaders ?? false,\r\n };\r\n\r\n // Start cleanup interval to prevent memory leaks\r\n this.startCleanupInterval();\r\n }\r\n\r\n setPayload(_payload: Payload): void {\r\n // Payload is accepted for compatibility but not currently used.\r\n }\r\n\r\n /**\r\n * Check rate limit using token bucket algorithm\r\n */\r\n checkTokenBucket(\r\n key: string,\r\n tokens: number = 1,\r\n capacity: number = 10,\r\n refillRate: number = 1,\r\n refillTime: number = 100\r\n ): RateLimitResult {\r\n try {\r\n const now = Date.now();\r\n const bucketKey = `rate_limit:token_bucket:${key}`;\r\n const current = this.inMemoryStore.get(bucketKey);\r\n\r\n let currentTokens = capacity;\r\n let lastRefill = now;\r\n\r\n if (current) {\r\n currentTokens = current.count;\r\n lastRefill = current.lastRequestTime;\r\n }\r\n\r\n // Calculate refill\r\n const timePassed = now - lastRefill;\r\n const refillAmount = Math.floor(timePassed / refillTime) * refillRate;\r\n currentTokens = Math.min(capacity, currentTokens + refillAmount);\r\n\r\n // Check if we can consume tokens\r\n if (currentTokens >= tokens) {\r\n currentTokens = currentTokens - tokens;\r\n this.inMemoryStore.set(bucketKey, {\r\n count: currentTokens,\r\n resetTime: now + refillTime,\r\n lastRequestTime: now,\r\n });\r\n\r\n devLogger.debug('Rate limit check', {\r\n key,\r\n algorithm: 'token_bucket',\r\n allowed: true,\r\n remaining: currentTokens,\r\n resetTime: now + refillTime,\r\n tokens,\r\n capacity,\r\n refillRate,\r\n });\r\n\r\n return {\r\n allowed: true,\r\n remaining: currentTokens,\r\n resetTime: now + refillTime,\r\n };\r\n }\r\n const resetTime = lastRefill + refillTime;\r\n devLogger.warn('Rate limit blocked', {\r\n key,\r\n algorithm: 'token_bucket',\r\n remaining: currentTokens,\r\n resetTime,\r\n tokens,\r\n });\r\n\r\n return {\r\n allowed: false,\r\n remaining: currentTokens,\r\n resetTime,\r\n retryAfter: Math.ceil((resetTime - now) / 1000),\r\n };\r\n } catch (error) {\r\n devLogger.error('Rate limiter error', error instanceof Error ? error : undefined, {\r\n key,\r\n algorithm: 'token_bucket',\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n });\r\n // Fail open - allow request if rate limiting fails\r\n return {\r\n allowed: true,\r\n remaining: capacity,\r\n resetTime: Date.now() + refillTime,\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Check rate limit using sliding window algorithm\r\n */\r\n checkSlidingWindow(\r\n key: string,\r\n windowMs: number = this.config.windowMs,\r\n maxRequests: number = this.config.maxRequests\r\n ): RateLimitResult {\r\n try {\r\n const now = Date.now();\r\n const windowKey = `rate_limit:sliding_window:${key}`;\r\n const current = this.inMemoryStore.get(windowKey);\r\n\r\n let requests: number[] = [];\r\n if (current) {\r\n requests = [current.count]; // Simplified - in real implementation, you'd store timestamps\r\n }\r\n\r\n // Remove expired entries (simplified)\r\n const windowStart = now - windowMs;\r\n requests = requests.filter(timestamp => timestamp >= windowStart);\r\n\r\n // Check if we can add another request\r\n if (requests.length < maxRequests) {\r\n requests.push(now);\r\n this.inMemoryStore.set(windowKey, {\r\n count: requests.length,\r\n resetTime: now + windowMs,\r\n lastRequestTime: now,\r\n });\r\n\r\n devLogger.debug('Rate limit check', {\r\n key,\r\n algorithm: 'sliding_window',\r\n allowed: true,\r\n remaining: maxRequests - requests.length,\r\n resetTime: now + windowMs,\r\n });\r\n\r\n return {\r\n allowed: true,\r\n remaining: maxRequests - requests.length,\r\n resetTime: now + windowMs,\r\n };\r\n }\r\n const oldest = Math.min(...requests);\r\n const resetTime = oldest + windowMs;\r\n\r\n devLogger.warn('Rate limit blocked', {\r\n key,\r\n algorithm: 'sliding_window',\r\n remaining: 0,\r\n resetTime,\r\n });\r\n\r\n return {\r\n allowed: false,\r\n remaining: 0,\r\n resetTime,\r\n retryAfter: Math.ceil((resetTime - now) / 1000),\r\n };\r\n } catch (error) {\r\n devLogger.error('Rate limiter error', error instanceof Error ? error : undefined, {\r\n key,\r\n algorithm: 'sliding_window',\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n });\r\n // Fail open - allow request if rate limiting fails\r\n return {\r\n allowed: true,\r\n remaining: maxRequests,\r\n resetTime: Date.now() + windowMs,\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Check rate limit using leaky bucket algorithm\r\n */\r\n checkLeakyBucket(\r\n key: string,\r\n capacity: number = 10,\r\n leakRate: number = 1,\r\n leakTime: number = 100\r\n ): RateLimitResult {\r\n try {\r\n const now = Date.now();\r\n const bucketKey = `rate_limit:leaky_bucket:${key}`;\r\n const current = this.inMemoryStore.get(bucketKey);\r\n\r\n let currentLevel = 0;\r\n let lastLeak = now;\r\n\r\n if (current) {\r\n currentLevel = current.count;\r\n lastLeak = current.lastRequestTime;\r\n }\r\n\r\n // Calculate leak\r\n const timePassed = now - lastLeak;\r\n const leakAmount = Math.floor(timePassed / leakTime) * leakRate;\r\n currentLevel = Math.max(0, currentLevel - leakAmount);\r\n\r\n // Check if we can add to the bucket\r\n if (currentLevel < capacity) {\r\n currentLevel++;\r\n this.inMemoryStore.set(bucketKey, {\r\n count: currentLevel,\r\n resetTime: now + leakTime,\r\n lastRequestTime: now,\r\n });\r\n\r\n devLogger.debug('Rate limit check', {\r\n key,\r\n algorithm: 'leaky_bucket',\r\n allowed: true,\r\n remaining: capacity - currentLevel,\r\n resetTime: now + leakTime,\r\n });\r\n\r\n return {\r\n allowed: true,\r\n remaining: capacity - currentLevel,\r\n resetTime: now + leakTime,\r\n };\r\n }\r\n const resetTime = lastLeak + leakTime;\r\n devLogger.warn('Rate limit blocked', {\r\n key,\r\n algorithm: 'leaky_bucket',\r\n remaining: 0,\r\n resetTime,\r\n });\r\n\r\n return {\r\n allowed: false,\r\n remaining: 0,\r\n resetTime,\r\n retryAfter: Math.ceil((resetTime - now) / 1000),\r\n };\r\n } catch (error) {\r\n devLogger.error('Rate limiter error', error instanceof Error ? error : undefined, {\r\n key,\r\n algorithm: 'leaky_bucket',\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n });\r\n // Fail open - allow request if rate limiting fails\r\n return {\r\n allowed: true,\r\n remaining: capacity,\r\n resetTime: Date.now() + leakTime,\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Reset rate limit for a key\r\n */\r\n resetRateLimit(key: string): void {\r\n const patterns = [\r\n `rate_limit:token_bucket:${key}`,\r\n `rate_limit:sliding_window:${key}`,\r\n `rate_limit:leaky_bucket:${key}`,\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n this.inMemoryStore.delete(pattern);\r\n }\r\n\r\n devLogger.debug('Rate limit reset', { key });\r\n }\r\n\r\n /**\r\n * Get current rate limit state\r\n */\r\n getRateLimitState(key: string): RateLimitState | null {\r\n const patterns = [\r\n `rate_limit:token_bucket:${key}`,\r\n `rate_limit:sliding_window:${key}`,\r\n `rate_limit:leaky_bucket:${key}`,\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const state = this.inMemoryStore.get(pattern);\r\n if (state) {\r\n return state;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Update rate limit state\r\n */\r\n updateRateLimitState(key: string, state: RateLimitState): void {\r\n this.inMemoryStore.set(key, state);\r\n }\r\n\r\n /**\r\n * Get rate limiter statistics\r\n */\r\n getStats(): { totalKeys: number; memoryUsage: number } {\r\n return {\r\n totalKeys: this.inMemoryStore.size,\r\n memoryUsage: this.inMemoryStore.size,\r\n };\r\n }\r\n\r\n /**\r\n * Clean up expired entries\r\n */\r\n cleanup(): void {\r\n const now = Date.now();\r\n const maxAge = 24 * 60 * 60 * 1000; // 24 hours\r\n\r\n for (const [key, state] of this.inMemoryStore.entries()) {\r\n if (now - state.lastRequestTime > maxAge) {\r\n this.inMemoryStore.delete(key);\r\n }\r\n }\r\n\r\n devLogger.debug('Cleaned up expired rate limit entries', {\r\n remaining: this.inMemoryStore.size,\r\n });\r\n }\r\n\r\n /**\r\n * Start cleanup interval\r\n */\r\n private startCleanupInterval(): void {\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n }\r\n\r\n // Clean up every hour\r\n this.cleanupInterval = setInterval(\r\n () => {\r\n this.cleanup();\r\n },\r\n 60 * 60 * 1000\r\n );\r\n }\r\n\r\n /**\r\n * Stop cleanup interval\r\n */\r\n stopCleanupInterval(): void {\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n this.cleanupInterval = null;\r\n }\r\n }\r\n\r\n /**\r\n * Dispose of the service\r\n */\r\n dispose(): void {\r\n this.stopCleanupInterval();\r\n this.inMemoryStore.clear();\r\n }\r\n}\r\n\r\n/**\r\n * Factory function to create RateLimiterService\r\n */\r\nexport const getRateLimiterService = (config?: RateLimitConfig): RateLimiterService => {\r\n return new RateLimiterService(config ?? {});\r\n};\r\n\r\n","/**\r\n * Rate Limiting Middleware for Server Actions\r\n *\r\n * Provides rate limiting functionality for Next.js 16 server actions\r\n */\r\n\r\nimport {headers} from 'next/headers';\r\nconst RATE_LIMITS = { default: { limit: 100, windowMs: 60_000 } } as const;\r\nconst generateRateLimitKey = (id: string) => `rate:${id}`;\r\nconst generateIPRateLimitKey = (ip: string) => `rate:ip:${ip}`;\r\nasync function checkRateLimit(\r\n _key: string,\r\n _limit: number,\r\n _windowMs: number\r\n): Promise<RateLimitResult> {\r\n // No-op in library context; allow\r\n return { allowed: true, remaining: _limit, resetTime: Date.now() + _windowMs };\r\n}\r\n\r\nexport interface RateLimitResult {\r\n allowed: boolean;\r\n remaining: number;\r\n resetTime: number;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Apply rate limiting to server actions\r\n */\r\nexport async function withRateLimit<T extends any[], R>(\r\n action: (...args: T) => Promise<R>,\r\n config: {\r\n type: keyof typeof RATE_LIMITS;\r\n userId?: string;\r\n customKey?: string;\r\n }\r\n) {\r\n return async (...args: T): Promise<R> => {\r\n const headersList = await headers();\r\n const ip = headersList.get('x-forwarded-for') ?? headersList.get('x-real-ip') ?? 'unknown';\r\n\r\n // Generate rate limit key\r\n const key =\r\n config.customKey ??\r\n (config.userId ? generateRateLimitKey(config.userId) : generateIPRateLimitKey(ip));\r\n\r\n // Check rate limit\r\n const rateLimitResult = await checkRateLimit(\r\n key,\r\n RATE_LIMITS[config.type].limit,\r\n RATE_LIMITS[config.type].windowMs\r\n );\r\n\r\n if (!rateLimitResult.allowed) {\r\n throw new Error(\r\n `Rate limit exceeded. Try again in ${Math.ceil((rateLimitResult.resetTime - Date.now()) / 1000)} seconds.`\r\n );\r\n }\r\n\r\n // Execute the action\r\n return await action(...args);\r\n };\r\n}\r\n\r\n/**\r\n * Rate limiting decorator for class methods\r\n */\r\nexport function RateLimited(type: keyof typeof RATE_LIMITS, userId?: string) {\r\n return (_target: object, _propertyKey: string, descriptor: PropertyDescriptor) => {\r\n const originalMethod = descriptor.value;\r\n\r\n descriptor.value = async function (...args: any[]) {\r\n const headersList = await headers();\r\n const ip = headersList.get('x-forwarded-for') ?? headersList.get('x-real-ip') ?? 'unknown';\r\n\r\n const key = userId ? generateRateLimitKey(userId) : generateIPRateLimitKey(ip);\r\n\r\n const rateLimitResult = await checkRateLimit(\r\n key,\r\n RATE_LIMITS[type].limit,\r\n RATE_LIMITS[type].windowMs\r\n );\r\n\r\n if (!rateLimitResult.allowed) {\r\n throw new Error(\r\n `Rate limit exceeded. Try again in ${Math.ceil((rateLimitResult.resetTime - Date.now()) / 1000)} seconds.`\r\n );\r\n }\r\n\r\n return await originalMethod.apply(this, args);\r\n };\r\n\r\n return descriptor;\r\n };\r\n}\r\n\r\n/**\r\n * Get client IP address\r\n */\r\nexport async function getClientIP(): Promise<string> {\r\n const headersList = await headers();\r\n return headersList.get('x-forwarded-for') ?? headersList.get('x-real-ip') ?? 'unknown';\r\n}\r\n\r\n/**\r\n * Check if request is from a trusted source\r\n */\r\nexport async function isTrustedSource(): Promise<boolean> {\r\n const headersList = await headers();\r\n const userAgent = headersList.get('user-agent') || '';\r\n const origin = headersList.get('origin') || '';\r\n\r\n // Check for common bot patterns\r\n const botPatterns = [/bot/i, /crawler/i, /spider/i, /scraper/i, /curl/i, /wget/i];\r\n\r\n const isBot = botPatterns.some(pattern => pattern.test(userAgent));\r\n\r\n // Check for trusted origins (configure as needed)\r\n const trustedOrigins = [\r\n process.env.NEXT_PUBLIC_APP_URL,\r\n 'http://localhost:3000',\r\n 'https://localhost:3000',\r\n ].filter(Boolean);\r\n\r\n const isTrustedOrigin = trustedOrigins.includes(origin);\r\n\r\n return !isBot && isTrustedOrigin;\r\n}\r\n\r\n/**\r\n * Enhanced rate limiting with user context\r\n */\r\nexport async function checkUserRateLimit(\r\n userId: string,\r\n action: keyof typeof RATE_LIMITS,\r\n customConfig?: Partial<(typeof RATE_LIMITS)[keyof typeof RATE_LIMITS]>\r\n): Promise<RateLimitResult> {\r\n const config = { ...RATE_LIMITS[action], ...customConfig };\r\n const key = generateRateLimitKey(userId);\r\n\r\n return await checkRateLimit(key, config.limit, config.windowMs);\r\n}\r\n\r\n/**\r\n * Rate limiting for anonymous users\r\n */\r\nexport async function checkAnonymousRateLimit(\r\n action: keyof typeof RATE_LIMITS,\r\n customConfig?: Partial<(typeof RATE_LIMITS)[keyof typeof RATE_LIMITS]>\r\n): Promise<RateLimitResult> {\r\n const ip = await getClientIP();\r\n const config = { ...RATE_LIMITS[action], ...customConfig };\r\n const key = generateIPRateLimitKey(ip);\r\n\r\n return await checkRateLimit(key, config.limit, config.windowMs);\r\n}\r\n\r\n","type SecurityOptions = {\r\n algorithm?: 'sha256' | 'sha1' | 'sha512';\r\n encoding?: 'hex' | 'base64' | 'base64url';\r\n tokenLength?: number;\r\n tokenExpiry?: number;\r\n};\r\nimport {createHmac,randomBytes} from 'crypto';\r\nimport type {Payload} from 'payload';\r\n\r\nexport class CSRFService {\r\n private readonly options: Required<SecurityOptions>;\r\n\r\n constructor(\r\n private readonly payload: Payload,\r\n options: SecurityOptions = {}\r\n ) {\r\n this.options = {\r\n algorithm: options.algorithm ?? 'sha256',\r\n encoding: options.encoding ?? 'hex',\r\n tokenLength: options.tokenLength ?? 32,\r\n tokenExpiry: options.tokenExpiry ?? 24 * 60 * 60 * 1000, // 24 hours\r\n };\r\n }\r\n\r\n async generateCsrfToken(sessionId: string): Promise<string> {\r\n try {\r\n const token = randomBytes(this.options.tokenLength);\r\n const hmac = createHmac(this.options.algorithm, process.env.PAYLOAD_SECRET ?? '');\r\n\r\n hmac.update(sessionId);\r\n hmac.update(token);\r\n\r\n const signature = hmac.digest(this.options.encoding);\r\n const csrfToken = `${token.toString(this.options.encoding)}.${signature}`;\r\n\r\n this.payload.logger.debug('CSRF token generated successfully');\r\n return csrfToken;\r\n } catch (error) {\r\n this.payload.logger.error('Failed to generate CSRF token', error as Error);\r\n throw error;\r\n }\r\n }\r\n\r\n async validateCsrfToken(token: string, sessionId: string): Promise<boolean> {\r\n try {\r\n const [tokenPart, signature] = token.split('.');\r\n if (!tokenPart || !signature) {\r\n this.payload.logger.warn('Invalid CSRF token format');\r\n return false;\r\n }\r\n\r\n const hmac = createHmac(this.options.algorithm, process.env.PAYLOAD_SECRET ?? '');\r\n hmac.update(sessionId);\r\n hmac.update(Buffer.from(tokenPart, this.options.encoding));\r\n\r\n const expectedSignature = hmac.digest(this.options.encoding);\r\n const isValid = signature === expectedSignature;\r\n\r\n if (isValid) {\r\n this.payload.logger.debug('CSRF token validated successfully');\r\n } else {\r\n this.payload.logger.warn('CSRF token validation failed');\r\n }\r\n\r\n return isValid;\r\n } catch (error) {\r\n this.payload.logger.error('Failed to validate CSRF token', error as Error);\r\n return false;\r\n }\r\n }\r\n}\r\n\r\n","import type {ServiceResult} from '@revealui/core';\r\nimport {InfrastructureService} from '@revealui/core';\r\nimport type {ScryptOptions} from 'crypto';\r\nimport {\r\n createCipheriv,\r\n createDecipheriv,\r\n randomBytes,\r\n scrypt as scryptCallback,\r\n} from 'node:crypto';\r\nimport type {Payload} from 'payload';\r\nimport {promisify} from 'util';\r\n\r\ntype NodeCipher = ReturnType<typeof createCipheriv>;\r\ntype NodeDecipher = ReturnType<typeof createDecipheriv>;\r\n\r\ntype BufferEncodingFormat = 'hex' | 'base64' | 'base64url';\r\n\r\ntype ScryptAsync = (\r\n password: string | Buffer,\r\n salt: Buffer | string,\r\n keylen: number,\r\n options?: ScryptOptions\r\n) => Promise<Buffer>;\r\n\r\nconst scryptAsync: ScryptAsync = promisify(scryptCallback);\r\n\r\ninterface EncryptionMetadata {\r\n algorithm: string;\r\n iv: string;\r\n authTag: string;\r\n salt: string;\r\n}\r\n\r\ninterface EncryptedData {\r\n data: string;\r\n metadata: EncryptionMetadata;\r\n}\r\n\r\ninterface EncryptionOptions {\r\n algorithm?: string;\r\n keyLength?: number;\r\n saltLength?: number;\r\n ivLength?: number;\r\n iterations?: number;\r\n encoding?: BufferEncodingFormat;\r\n}\r\n\r\ntype AuthenticatedCipher = NodeCipher & {\r\n getAuthTag: () => Buffer;\r\n};\r\n\r\ntype AuthenticatedDecipher = NodeDecipher & {\r\n setAuthTag: (buffer: Buffer) => void;\r\n};\r\n\r\n/**\r\n * Type guards using contract types\r\n */\r\nfunction isAuthenticatedCipher(cipher: NodeCipher): cipher is AuthenticatedCipher {\r\n return typeof (cipher as Partial<AuthenticatedCipher>).getAuthTag === 'function';\r\n}\r\n\r\nfunction isAuthenticatedDecipher(decipher: NodeDecipher): decipher is AuthenticatedDecipher {\r\n return typeof (decipher as Partial<AuthenticatedDecipher>).setAuthTag === 'function';\r\n}\r\n\r\n/**\r\n * Encryption Infrastructure Service following DDD and Hexagonal Architecture principles.\r\n *\r\n * Acts as a Secondary/Driven Adapter in the Ports & Adapters architecture,\r\n * providing secure encryption and decryption capabilities for sensitive data.\r\n */\r\nexport class EncryptionService extends InfrastructureService {\r\n private readonly options: Required<EncryptionOptions>;\r\n\r\n constructor(payload: Payload, options: EncryptionOptions = {}) {\r\n super(payload, 'EncryptionService');\r\n\r\n this.options = {\r\n algorithm: options.algorithm ?? 'aes-256-gcm',\r\n keyLength: options.keyLength ?? 32,\r\n saltLength: options.saltLength ?? 16,\r\n ivLength: options.ivLength ?? 12,\r\n iterations: options.iterations ?? 100000,\r\n encoding: options.encoding ?? 'hex',\r\n };\r\n }\r\n\r\n /**\r\n * Encrypts data using the configured algorithm with comprehensive error handling.\r\n */\r\n async encrypt(\r\n data: string,\r\n customOptions?: Partial<EncryptionOptions>\r\n ): Promise<ServiceResult<EncryptedData>> {\r\n return this.executeInfrastructureOperation(async () => {\r\n if (typeof data !== 'string' || data.length === 0) {\r\n throw new Error('Data to encrypt must be a non-empty string');\r\n }\r\n\r\n const effectiveOptions = { ...this.options, ...customOptions };\r\n\r\n this.logger.debug('Starting data encryption', {\r\n algorithm: effectiveOptions.algorithm,\r\n dataLength: data.length,\r\n serviceName: this.serviceName,\r\n operation: 'encrypt',\r\n });\r\n\r\n const salt = randomBytes(effectiveOptions.saltLength);\r\n const iv = randomBytes(effectiveOptions.ivLength);\r\n\r\n const key = await this.deriveKey(salt, effectiveOptions);\r\n const cipher = createCipheriv(effectiveOptions.algorithm, key, iv);\r\n\r\n const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]);\r\n\r\n // Type-safe auth tag extraction\r\n if (isAuthenticatedCipher(cipher) !== true) {\r\n throw new Error('Cipher does not support authentication');\r\n }\r\n const authTag = cipher.getAuthTag();\r\n\r\n const result: EncryptedData = {\r\n data: encrypted.toString(effectiveOptions.encoding),\r\n metadata: {\r\n algorithm: effectiveOptions.algorithm,\r\n iv: iv.toString(effectiveOptions.encoding),\r\n authTag: authTag.toString(effectiveOptions.encoding),\r\n salt: salt.toString(effectiveOptions.encoding),\r\n },\r\n };\r\n\r\n this.logger.debug('Data encrypted successfully', {\r\n algorithm: effectiveOptions.algorithm,\r\n originalLength: data.length,\r\n encryptedLength: result.data.length,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return result;\r\n }, 'encrypt');\r\n }\r\n\r\n /**\r\n * Decrypts data using the metadata provided with comprehensive validation.\r\n */\r\n async decrypt(encryptedData: EncryptedData): Promise<ServiceResult<string>> {\r\n return this.executeInfrastructureOperation(async () => {\r\n if (!encryptedData || !encryptedData.data || !encryptedData.metadata) {\r\n throw new Error('Invalid encrypted data structure');\r\n }\r\n\r\n const { data, metadata } = encryptedData;\r\n\r\n // Validate metadata completeness\r\n const requiredFields = ['algorithm', 'iv', 'authTag', 'salt'];\r\n for (const field of requiredFields) {\r\n const fieldValue = metadata[field as keyof typeof metadata];\r\n if (fieldValue === undefined || fieldValue === null || fieldValue === '') {\r\n throw new Error(`Missing required encryption metadata field: ${field}`);\r\n }\r\n }\r\n\r\n this.logger.debug('Starting data decryption', {\r\n algorithm: metadata.algorithm,\r\n encryptedLength: data.length,\r\n serviceName: this.serviceName,\r\n operation: 'decrypt',\r\n });\r\n\r\n const key = await this.deriveKey(Buffer.from(metadata.salt, this.options.encoding), {\r\n ...this.options,\r\n algorithm: metadata.algorithm,\r\n });\r\n\r\n const decipher = createDecipheriv(\r\n metadata.algorithm,\r\n key,\r\n Buffer.from(metadata.iv, this.options.encoding)\r\n );\r\n\r\n // Type-safe auth tag setting\r\n if (isAuthenticatedDecipher(decipher) !== true) {\r\n throw new Error('Decipher does not support authentication');\r\n }\r\n decipher.setAuthTag(Buffer.from(metadata.authTag, this.options.encoding));\r\n\r\n const decrypted = Buffer.concat([\r\n decipher.update(Buffer.from(data, this.options.encoding)),\r\n decipher.final(),\r\n ]);\r\n\r\n const result = decrypted.toString('utf8');\r\n\r\n this.logger.debug('Data decrypted successfully', {\r\n algorithm: metadata.algorithm,\r\n encryptedLength: data.length,\r\n decryptedLength: result.length,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return result;\r\n }, 'decrypt');\r\n }\r\n\r\n /**\r\n * Encrypts multiple data items in batch with optimized processing.\r\n */\r\n async encryptBatch(\r\n dataItems: string[],\r\n customOptions?: Partial<EncryptionOptions>\r\n ): Promise<\r\n ServiceResult<{\r\n successful: EncryptedData[];\r\n failed: Array<{ data: string; error: string }>;\r\n }>\r\n > {\r\n return this.executeInfrastructureOperation(async () => {\r\n if (!Array.isArray(dataItems) || dataItems.length === 0) {\r\n throw new Error('Data items array must contain at least one item');\r\n }\r\n\r\n this.logger.info('Starting batch encryption', {\r\n itemCount: dataItems.length,\r\n serviceName: this.serviceName,\r\n operation: 'encryptBatch',\r\n });\r\n\r\n const successful: EncryptedData[] = [];\r\n const failed: Array<{ data: string; error: string }> = [];\r\n\r\n // Process items in parallel with controlled concurrency\r\n const encryptionPromises = dataItems.map(async data => {\r\n try {\r\n const result = await this.encrypt(data, customOptions);\r\n if (result.success && result.data) {\r\n successful.push(result.data);\r\n } else {\r\n failed.push({\r\n data,\r\n error: result.error ?? 'Unknown encryption error',\r\n });\r\n }\r\n } catch (error) {\r\n failed.push({\r\n data,\r\n error: error instanceof Error ? error.message : 'Unknown encryption error',\r\n });\r\n }\r\n });\r\n\r\n await Promise.allSettled(encryptionPromises);\r\n\r\n this.logger.info('Batch encryption completed', {\r\n totalItems: dataItems.length,\r\n successful: successful.length,\r\n failed: failed.length,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return { successful, failed };\r\n }, 'encryptBatch');\r\n }\r\n\r\n /**\r\n * Generates cryptographically secure random data.\r\n */\r\n async generateRandomData(\r\n length: number = 32,\r\n encoding: 'hex' | 'base64' | 'base64url' = 'hex'\r\n ): Promise<ServiceResult<string>> {\r\n return this.executeInfrastructureOperation(async () => {\r\n if (length <= 0 || length > 1024) {\r\n throw new Error('Random data length must be between 1 and 1024 bytes');\r\n }\r\n\r\n this.logger.debug('Generating random data', {\r\n length,\r\n encoding,\r\n serviceName: this.serviceName,\r\n operation: 'generateRandomData',\r\n });\r\n\r\n const randomData = randomBytes(length);\r\n const result = randomData.toString(encoding);\r\n\r\n this.logger.debug('Random data generated successfully', {\r\n length,\r\n encoding,\r\n outputLength: result.length,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return result;\r\n }, 'generateRandomData');\r\n }\r\n\r\n /**\r\n * Validates the integrity of encrypted data by attempting decryption.\r\n */\r\n async validateEncryptedData(\r\n encryptedData: EncryptedData\r\n ): Promise<ServiceResult<{ valid: boolean; error?: string | undefined }>> {\r\n return this.executeInfrastructureOperation(async () => {\r\n if (!encryptedData) {\r\n throw new Error('Encrypted data is required');\r\n }\r\n\r\n this.logger.debug('Validating encrypted data integrity', {\r\n algorithm: encryptedData.metadata.algorithm,\r\n serviceName: this.serviceName,\r\n operation: 'validateEncryptedData',\r\n });\r\n\r\n try {\r\n const decryptResult = await this.decrypt(encryptedData);\r\n const valid = decryptResult.success && !!decryptResult.data;\r\n\r\n this.logger.debug('Encrypted data validation completed', {\r\n valid,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return valid\r\n ? { valid, error: undefined }\r\n : {\r\n valid,\r\n error: decryptResult.error ?? 'Decryption failed',\r\n };\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown validation error';\r\n\r\n this.logger.debug('Encrypted data validation failed', {\r\n error: errorMessage,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return { valid: false, error: errorMessage };\r\n }\r\n }, 'validateEncryptedData');\r\n }\r\n\r\n /**\r\n * Derives encryption key from password and salt using PBKDF2.\r\n * @private\r\n */\r\n private async deriveKey(salt: Buffer, options: Partial<EncryptionOptions> = {}): Promise<Buffer> {\r\n const effectiveOptions = { ...this.options, ...options };\r\n\r\n const secret = process.env.PAYLOAD_SECRET;\r\n if (!secret || secret === '') {\r\n throw new Error('PAYLOAD_SECRET environment variable is required for encryption');\r\n }\r\n\r\n return scryptAsync(secret, salt, effectiveOptions.keyLength);\r\n }\r\n\r\n /**\r\n * @inheritdoc\r\n */\r\n protected override async onInitialize(): Promise<void> {\r\n this.logger.info('Initializing EncryptionService', {\r\n algorithm: this.options.algorithm,\r\n keyLength: this.options.keyLength,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n // Verify PAYLOAD_SECRET is available\r\n if (!process.env.PAYLOAD_SECRET) {\r\n throw new Error('PAYLOAD_SECRET environment variable is required for EncryptionService');\r\n }\r\n\r\n // Test encryption/decryption functionality\r\n try {\r\n const testData = 'encryption-test-data';\r\n const encrypted = await this.encrypt(testData);\r\n if (!encrypted.success || !encrypted.data) {\r\n throw new Error('Encryption test failed');\r\n }\r\n\r\n const decrypted = await this.decrypt(encrypted.data);\r\n if (!decrypted.success || decrypted.data !== testData) {\r\n throw new Error('Decryption test failed');\r\n }\r\n\r\n this.logger.debug('EncryptionService initialization test passed', {\r\n serviceName: this.serviceName,\r\n });\r\n } catch (error) {\r\n throw new Error(\r\n `EncryptionService initialization failed: ${error instanceof Error ? error.message : 'Unknown error'}`\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * @inheritdoc\r\n */\r\n protected override async onCleanup(): Promise<void> {\r\n this.logger.info('Cleaning up EncryptionService', {\r\n serviceName: this.serviceName,\r\n });\r\n // Clear any sensitive data from memory if needed\r\n }\r\n\r\n /**\r\n * @inheritdoc\r\n */\r\n protected async onHealthCheck(): Promise<void> {\r\n // Verify encryption/decryption is working\r\n try {\r\n const testData = 'health-check-data';\r\n const encrypted = await this.encrypt(testData);\r\n if (!encrypted.success || !encrypted.data) {\r\n throw new Error('Health check encryption failed');\r\n }\r\n\r\n const decrypted = await this.decrypt(encrypted.data);\r\n if (!decrypted.success || decrypted.data !== testData) {\r\n throw new Error('Health check decryption failed');\r\n }\r\n } catch (error) {\r\n throw new Error(\r\n `EncryptionService health check failed: ${error instanceof Error ? error.message : 'Unknown error'}`\r\n );\r\n }\r\n }\r\n}\r\n\r\n","const devLogger = {\r\n info: (...args: unknown[]) => console.log('[security]', ...args),\r\n warn: (...args: unknown[]) => console.warn('[security]', ...args),\r\n error: (...args: unknown[]) => console.error('[security]', ...args),\r\n};\r\n\r\nexport type SecurityEventType =\r\n | 'authentication'\r\n | 'authorization'\r\n | 'data_access'\r\n | 'system'\r\n | 'policy_violation'\r\n | 'threat_detection';\r\n\r\nexport type SecuritySeverity = 'low' | 'medium' | 'high' | 'critical';\r\n\r\nexport interface SecurityEvent {\r\n id: string;\r\n type: SecurityEventType;\r\n severity: SecuritySeverity;\r\n message: string;\r\n userId?: string;\r\n ipAddress?: string;\r\n userAgent?: string;\r\n timestamp: Date;\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\nexport type SecurityAlertType = 'threshold_exceeded' | 'policy_violation' | 'anomaly_detected';\r\n\r\nexport interface SecurityAlert {\r\n id: string;\r\n type: SecurityAlertType;\r\n severity: SecuritySeverity;\r\n message: string;\r\n timestamp: Date;\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\nexport interface SecurityMetrics {\r\n totalEvents: number;\r\n eventsByType: Record<string, number>;\r\n eventsBySeverity: Record<string, number>;\r\n averageResponseTime: number;\r\n lastEventTime?: Date;\r\n}\r\n\r\n// ======\r\n// PURE FUNCTIONS\r\n// ======\r\n\r\n/**\r\n * Create a security event\r\n */\r\nexport const createSecurityEvent = (\r\n type: SecurityEvent['type'],\r\n severity: SecurityEvent['severity'],\r\n message: string,\r\n options?: {\r\n userId?: string;\r\n ipAddress?: string;\r\n userAgent?: string;\r\n metadata?: Record<string, unknown>;\r\n }\r\n): SecurityEvent => {\r\n const baseEvent: SecurityEvent = {\r\n id: crypto.randomUUID(),\r\n type,\r\n severity,\r\n message,\r\n timestamp: new Date(),\r\n ...(options?.metadata ? { metadata: options.metadata } : {}),\r\n ...(options?.userId !== undefined ? { userId: options.userId } : {}),\r\n ...(options?.ipAddress !== undefined ? { ipAddress: options.ipAddress } : {}),\r\n ...(options?.userAgent !== undefined ? { userAgent: options.userAgent } : {}),\r\n };\r\n\r\n return baseEvent;\r\n};\r\n\r\n/**\r\n * Calculate security metrics from events\r\n */\r\nexport const calculateSecurityMetrics = (events: SecurityEvent[]): SecurityMetrics => {\r\n if (events.length === 0) {\r\n return {\r\n totalEvents: 0,\r\n eventsByType: {},\r\n eventsBySeverity: {},\r\n averageResponseTime: 0,\r\n };\r\n }\r\n\r\n const eventsByType = events.reduce<Record<string, number>>((acc, event) => {\r\n acc[event.type] = (acc[event.type] || 0) + 1;\r\n return acc;\r\n }, {});\r\n\r\n const eventsBySeverity = events.reduce<Record<string, number>>((acc, event) => {\r\n acc[event.severity] = (acc[event.severity] || 0) + 1;\r\n return acc;\r\n }, {});\r\n\r\n const lastEventTime =\r\n events.length > 0 ? new Date(Math.max(...events.map(e => e.timestamp.getTime()))) : undefined;\r\n\r\n return {\r\n totalEvents: events.length,\r\n eventsByType,\r\n eventsBySeverity,\r\n averageResponseTime: 0, // Would be calculated from actual response times\r\n ...(lastEventTime !== undefined ? { lastEventTime } : {}),\r\n };\r\n};\r\n\r\n/**\r\n * Check if an event should trigger an alert\r\n */\r\nexport const shouldTriggerAlert = (\r\n event: SecurityEvent,\r\n thresholds: {\r\n criticalCount: number;\r\n highCount: number;\r\n mediumCount: number;\r\n timeWindowMs: number;\r\n }\r\n): boolean => {\r\n // Check if event severity meets threshold criteria\r\n const now = new Date();\r\n const timeWindowStart = new Date(now.getTime() - thresholds.timeWindowMs);\r\n\r\n // Get recent events within the time window\r\n const recentEvents = events.filter(\r\n event => event.timestamp >= timeWindowStart && event.timestamp <= now\r\n );\r\n\r\n // Count events by severity within the time window\r\n const criticalCount = recentEvents.filter(e => e.severity === 'critical').length;\r\n const highCount = recentEvents.filter(e => e.severity === 'high').length;\r\n const mediumCount = recentEvents.filter(e => e.severity === 'medium').length;\r\n\r\n // Check if thresholds are exceeded\r\n if (criticalCount >= thresholds.criticalCount) return true;\r\n if (highCount >= thresholds.highCount) return true;\r\n if (mediumCount >= thresholds.mediumCount) return true;\r\n\r\n // Also trigger for critical events regardless of count\r\n if (event.severity === 'critical') return true;\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Create a security alert from an event\r\n */\r\nexport const createSecurityAlert = (\r\n event: SecurityEvent,\r\n alertType: SecurityAlert['type'] = 'threshold_exceeded'\r\n): SecurityAlert => ({\r\n id: crypto.randomUUID(),\r\n type: alertType,\r\n severity: event.severity,\r\n message: `Security alert: ${event.message}`,\r\n timestamp: new Date(),\r\n metadata: {\r\n originalEventId: event.id,\r\n originalEventType: event.type,\r\n ...event.metadata,\r\n },\r\n});\r\n\r\n/**\r\n * Filter events by criteria\r\n */\r\nexport const filterEvents = (\r\n events: SecurityEvent[],\r\n criteria: {\r\n type?: SecurityEvent['type'];\r\n severity?: SecurityEvent['severity'];\r\n userId?: string;\r\n timeRange?: { start: Date; end: Date };\r\n }\r\n): SecurityEvent[] => {\r\n return events.filter(event => {\r\n if (criteria.type && event.type !== criteria.type) return false;\r\n if (criteria.severity && event.severity !== criteria.severity) return false;\r\n if (criteria.userId && event.userId !== criteria.userId) return false;\r\n if (criteria.timeRange) {\r\n const eventTime = event.timestamp.getTime();\r\n const startTime = criteria.timeRange.start.getTime();\r\n const endTime = criteria.timeRange.end.getTime();\r\n if (eventTime < startTime || eventTime > endTime) return false;\r\n }\r\n return true;\r\n });\r\n};\r\n\r\n// ======\r\n// STATE MANAGEMENT\r\n// ======\r\n\r\n// In-memory storage (in production, this would be a database)\r\nlet events: SecurityEvent[] = [];\r\nlet alerts: SecurityAlert[] = [];\r\n\r\n/**\r\n * Add an event to the security monitoring system\r\n */\r\nexport const addSecurityEvent = (event: SecurityEvent): void => {\r\n events.push(event);\r\n\r\n // Log the event\r\n devLogger.info('Security event recorded', {\r\n eventId: event.id,\r\n type: event.type,\r\n severity: event.severity,\r\n message: event.message,\r\n userId: event.userId,\r\n timestamp: event.timestamp.toISOString(),\r\n });\r\n\r\n // Check if alert should be triggered\r\n if (\r\n shouldTriggerAlert(event, {\r\n criticalCount: 1,\r\n highCount: 5,\r\n mediumCount: 10,\r\n timeWindowMs: 60000, // 1 minute\r\n })\r\n ) {\r\n const alert = createSecurityAlert(event);\r\n alerts.push(alert);\r\n\r\n devLogger.warn('Security alert triggered', {\r\n alertId: alert.id,\r\n eventId: event.id,\r\n severity: alert.severity,\r\n message: alert.message,\r\n });\r\n }\r\n};\r\n\r\n/**\r\n * Get all security events\r\n */\r\nexport const getSecurityEvents = (): SecurityEvent[] => [...events];\r\n\r\n/**\r\n * Get all security alerts\r\n */\r\nexport const getSecurityAlerts = (): SecurityAlert[] => [...alerts];\r\n\r\n/**\r\n * Get security metrics\r\n */\r\nexport const getSecurityMetrics = (): SecurityMetrics => calculateSecurityMetrics(events);\r\n\r\n/**\r\n * Clear all events and alerts (for testing)\r\n */\r\nexport const clearSecurityData = (): void => {\r\n events = [];\r\n alerts = [];\r\n};\r\n\r\n// ======\r\n// UTILITY FUNCTIONS\r\n// ======\r\n\r\n/**\r\n * Log authentication event\r\n */\r\nexport const logAuthenticationEvent = (\r\n userId: string,\r\n success: boolean,\r\n options?: {\r\n ipAddress?: string;\r\n userAgent?: string;\r\n metadata?: Record<string, unknown>;\r\n }\r\n): void => {\r\n const eventOptions: Parameters<typeof createSecurityEvent>[3] = {\r\n userId,\r\n ...(options?.ipAddress !== undefined ? { ipAddress: options.ipAddress } : {}),\r\n ...(options?.userAgent !== undefined ? { userAgent: options.userAgent } : {}),\r\n metadata: {\r\n success,\r\n ...options?.metadata,\r\n },\r\n };\r\n\r\n const event = createSecurityEvent(\r\n 'authentication',\r\n success ? 'low' : 'high',\r\n `Authentication ${success ? 'successful' : 'failed'} for user ${userId}`,\r\n eventOptions\r\n );\r\n\r\n addSecurityEvent(event);\r\n};\r\n\r\n/**\r\n * Log authorization event\r\n */\r\nexport const logAuthorizationEvent = (\r\n userId: string,\r\n resource: string,\r\n action: string,\r\n granted: boolean,\r\n options?: {\r\n ipAddress?: string;\r\n userAgent?: string;\r\n metadata?: Record<string, unknown>;\r\n }\r\n): void => {\r\n const eventOptions: Parameters<typeof createSecurityEvent>[3] = {\r\n userId,\r\n ...(options?.ipAddress !== undefined ? { ipAddress: options.ipAddress } : {}),\r\n ...(options?.userAgent !== undefined ? { userAgent: options.userAgent } : {}),\r\n metadata: {\r\n resource,\r\n action,\r\n granted,\r\n ...options?.metadata,\r\n },\r\n };\r\n\r\n const event = createSecurityEvent(\r\n 'authorization',\r\n granted ? 'low' : 'medium',\r\n `Authorization ${granted ? 'granted' : 'denied'} for user ${userId} on ${resource}:${action}`,\r\n eventOptions\r\n );\r\n\r\n addSecurityEvent(event);\r\n};\r\n\r\n/**\r\n * Log data access event\r\n */\r\nexport const logDataAccessEvent = (\r\n userId: string,\r\n collection: string,\r\n operation: 'create' | 'read' | 'update' | 'delete',\r\n recordId?: string,\r\n options?: {\r\n ipAddress?: string;\r\n userAgent?: string;\r\n metadata?: Record<string, unknown>;\r\n }\r\n): void => {\r\n const eventOptions: Parameters<typeof createSecurityEvent>[3] = {\r\n userId,\r\n ...(options?.ipAddress !== undefined ? { ipAddress: options.ipAddress } : {}),\r\n ...(options?.userAgent !== undefined ? { userAgent: options.userAgent } : {}),\r\n metadata: {\r\n collection,\r\n operation,\r\n recordId,\r\n ...options?.metadata,\r\n },\r\n };\r\n\r\n const event = createSecurityEvent(\r\n 'data_access',\r\n operation === 'delete' ? 'medium' : 'low',\r\n `Data access: ${operation} on ${collection}${recordId ? ` (${recordId})` : ''} by user ${userId}`,\r\n eventOptions\r\n );\r\n\r\n addSecurityEvent(event);\r\n};\r\n\r\n/**\r\n * Get events for a specific user\r\n */\r\nexport const getUserEvents = (userId: string): SecurityEvent[] => filterEvents(events, { userId });\r\n\r\n/**\r\n * Get events by severity\r\n */\r\nexport const getEventsBySeverity = (severity: SecurityEvent['severity']): SecurityEvent[] =>\r\n filterEvents(events, { severity });\r\n\r\n/**\r\n * Get events in time range\r\n */\r\nexport const getEventsInTimeRange = (start: Date, end: Date): SecurityEvent[] =>\r\n filterEvents(events, { timeRange: { start, end } });\r\n\r\n// ======\r\n// EXPORTED API\r\n// ======\r\n\r\nexport const SecurityMonitoringService = {\r\n // Event management\r\n addEvent: addSecurityEvent,\r\n getEvents: getSecurityEvents,\r\n getUserEvents,\r\n getEventsBySeverity,\r\n getEventsInTimeRange,\r\n\r\n // Alert management\r\n getAlerts: getSecurityAlerts,\r\n\r\n // Metrics\r\n getMetrics: getSecurityMetrics,\r\n\r\n // Utility functions\r\n logAuthenticationEvent,\r\n logAuthorizationEvent,\r\n logDataAccessEvent,\r\n\r\n // Testing utilities\r\n clearData: clearSecurityData,\r\n\r\n // Pure functions for composition\r\n createEvent: createSecurityEvent,\r\n createAlert: createSecurityAlert,\r\n filterEvents,\r\n calculateMetrics: calculateSecurityMetrics,\r\n};\r\n\r\n","import { type NextRequest, NextResponse } from 'next/server';\r\nimport { createHmac } from 'node:crypto';\r\n\r\nasync function getPayloadClient() {\r\n return { logger: console as any };\r\n}\r\n\r\nconst logger = {\r\n info: (message: string, ...args: unknown[]) => console.log(`[SecurityService] ${message}`, ...args),\r\n warn: (message: string, ...args: unknown[]) => console.warn(`[SecurityService] ${message}`, ...args),\r\n error: (message: string, ...args: unknown[]) => console.error(`[SecurityService] ${message}`, ...args),\r\n};\r\n\r\n// PayloadCMS native logging is used via payload.logger\r\n\r\nexport async function securityMiddleware(req: NextRequest): Promise<NextResponse | undefined> {\r\n const response = new NextResponse();\r\n\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.info(`Security middleware started for ${req.method} ${req.url}`);\r\n } catch {\r\n logger.info(`Security middleware started for ${req.method} ${req.url}`);\r\n }\r\n\r\n // Add security headers\r\n response.headers.set('X-Content-Type-Options', 'nosniff');\r\n response.headers.set('X-Frame-Options', 'DENY');\r\n response.headers.set('X-XSS-Protection', '1; mode=block');\r\n response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');\r\n response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');\r\n\r\n // Enhanced CSP based on request context\r\n const isApiRoute = req.nextUrl.pathname.startsWith('/api');\r\n const csp = isApiRoute\r\n ? \"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'\"\r\n : \"default-src 'self'\";\r\n response.headers.set('Content-Security-Policy', csp);\r\n\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.info('Security middleware completed');\r\n } catch {\r\n logger.info('Security middleware completed');\r\n }\r\n\r\n // Let the request continue\r\n return;\r\n}\r\n\r\n// --- Security Factory ---\r\nexport function createSecurity(config: {\r\n csrfSecret: string;\r\n tokenExpiry: { access: number; refresh: number };\r\n}) {\r\n return {\r\n generateCsrfToken(sessionId: string): string {\r\n // Simple HMAC-based CSRF token\r\n return createHmac('sha256', config.csrfSecret).update(sessionId).digest('hex');\r\n },\r\n isTokenExpired(exp: number): boolean {\r\n return Date.now() / 1000 > exp;\r\n },\r\n getAccessTokenExpiry(): number {\r\n return config.tokenExpiry.access;\r\n },\r\n getRefreshTokenExpiry(): number {\r\n return config.tokenExpiry.refresh;\r\n },\r\n };\r\n}\r\n\r\n","const logger = {\r\n info: (message: string, ...args: unknown[]) => console.log(`[SessionService] ${message}`, ...args),\r\n warn: (message: string, ...args: unknown[]) => console.warn(`[SessionService] ${message}`, ...args),\r\n error: (message: string, ...args: unknown[]) => console.error(`[SessionService] ${message}`, ...args),\r\n};\r\n\r\nconst devLogger = {\r\n info: (...args: unknown[]) => logger.info(String(args[0]), ...args.slice(1)),\r\n warn: (...args: unknown[]) => logger.warn(String(args[0]), ...args.slice(1)),\r\n error: (...args: unknown[]) => logger.error(String(args[0]), ...args.slice(1)),\r\n forService: (_name: string) => ({\r\n info: (...args: unknown[]) => logger.info(String(args[0]), ...args.slice(1)),\r\n warn: (...args: unknown[]) => logger.warn(String(args[0]), ...args.slice(1)),\r\n error: (...args: unknown[]) => logger.error(String(args[0]), ...args.slice(1)),\r\n }),\r\n};\r\n\r\ninterface SessionRecord {\r\n id: string;\r\n userId: string;\r\n token: string;\r\n device?: string;\r\n expiresAt: Date;\r\n lastActiveAt?: Date;\r\n isActive: boolean;\r\n updatedAt: Date;\r\n createdAt: Date;\r\n}\r\n\r\n// UserService integration removed - use UserServiceCoordinator directly when needed\r\ntype PayloadStub = {\r\n logger: {\r\n info: (...args: unknown[]) => void;\r\n warn: (...args: unknown[]) => void;\r\n error: (...args: unknown[]) => void;\r\n };\r\n};\r\n\r\nasync function getPayloadClient(): Promise<PayloadStub> {\r\n return {\r\n logger: {\r\n info: (...args: unknown[]) => logger.info(String(args[0]), ...args.slice(1)),\r\n warn: (...args: unknown[]) => logger.warn(String(args[0]), ...args.slice(1)),\r\n error: (...args: unknown[]) => logger.error(String(args[0]), ...args.slice(1)),\r\n },\r\n };\r\n}\r\n\r\nfunction generateUUID(): string {\r\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\r\n return crypto.randomUUID();\r\n }\r\n // Fallback for environments without crypto.randomUUID\r\n return `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g, c => {\r\n const r = (Math.random() * 16) | 0;\r\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\r\n return v.toString(16);\r\n });\r\n}\r\n\r\nclass SessionRepository {\r\n private readonly sessions = new Map<string, SessionRecord>();\r\n\r\n constructor(private readonly payload: PayloadStub) {\r\n void this.payload;\r\n }\r\n\r\n private createSessionId(): string {\r\n try {\r\n return generateUUID();\r\n } catch {\r\n return `session_${Date.now().toString(36)}`;\r\n }\r\n }\r\n\r\n private createToken(): string {\r\n try {\r\n return `token_${generateUUID()}`;\r\n } catch {\r\n return `token_${Date.now().toString(36)}`;\r\n }\r\n }\r\n\r\n async create(data: Partial<SessionRecord>): Promise<ValidationResultData<SessionRecord>> {\r\n if (!data.userId) {\r\n return {\r\n success: false,\r\n errors: [{ message: 'userId is required', path: 'create' }],\r\n };\r\n }\r\n\r\n const now = new Date();\r\n const session: SessionRecord = {\r\n id: data.id ?? this.createSessionId(),\r\n userId: data.userId,\r\n token: data.token ?? this.createToken(),\r\n expiresAt: data.expiresAt\r\n ? new Date(data.expiresAt)\r\n : new Date(now.getTime() + 1000 * 60 * 60),\r\n lastActiveAt: data.lastActiveAt ? new Date(data.lastActiveAt) : now,\r\n isActive: data.isActive ?? true,\r\n updatedAt: now,\r\n createdAt: now,\r\n ...(data.device !== undefined ? { device: data.device } : {}),\r\n };\r\n\r\n this.sessions.set(session.id, session);\r\n\r\n return { success: true, data: session };\r\n }\r\n\r\n async findById(id: string | number): Promise<ValidationResultData<SessionRecord>> {\r\n const session = this.sessions.get(String(id));\r\n if (!session) {\r\n return {\r\n success: false,\r\n errors: [{ message: 'Session not found', path: 'findById' }],\r\n };\r\n }\r\n\r\n return { success: true, data: session };\r\n }\r\n\r\n async delete(id: string | number): Promise<ValidationResultData> {\r\n const key = String(id);\r\n if (!this.sessions.has(key)) {\r\n return {\r\n success: false,\r\n errors: [{ message: 'Session not found', path: 'delete' }],\r\n };\r\n }\r\n\r\n this.sessions.delete(key);\r\n return { success: true };\r\n }\r\n\r\n async revokeAllUserSessions(userId: string): Promise<ValidationResultData> {\r\n let removed = false;\r\n for (const [key, session] of this.sessions.entries()) {\r\n if (session.userId === userId) {\r\n this.sessions.delete(key);\r\n removed = true;\r\n }\r\n }\r\n\r\n if (!removed) {\r\n return {\r\n success: false,\r\n errors: [{ message: 'No sessions found for user', path: 'revokeAllUserSessions' }],\r\n };\r\n }\r\n\r\n return { success: true };\r\n }\r\n\r\n async findAll(): Promise<ValidationResultData<SessionRecord[]>> {\r\n return { success: true, data: Array.from(this.sessions.values()) };\r\n }\r\n\r\n async update(\r\n id: string,\r\n data: Partial<SessionRecord>\r\n ): Promise<ValidationResultData<SessionRecord>> {\r\n const existing = this.sessions.get(id);\r\n if (!existing) {\r\n return {\r\n success: false,\r\n errors: [{ message: 'Session not found', path: 'update' }],\r\n };\r\n }\r\n\r\n const updated: SessionRecord = {\r\n ...existing,\r\n ...(data.userId !== undefined ? { userId: data.userId } : {}),\r\n ...(data.token !== undefined ? { token: data.token } : {}),\r\n ...(data.device !== undefined ? { device: data.device } : {}),\r\n ...(data.expiresAt !== undefined ? { expiresAt: new Date(data.expiresAt) } : {}),\r\n ...(data.lastActiveAt !== undefined ? { lastActiveAt: new Date(data.lastActiveAt) } : {}),\r\n ...(data.isActive !== undefined ? { isActive: data.isActive } : {}),\r\n updatedAt: new Date(),\r\n };\r\n\r\n this.sessions.set(id, updated);\r\n return { success: true, data: updated };\r\n }\r\n}\r\n\r\n/**\r\n * SessionService provides session management logic for user authentication.\r\n * It supports creating, validating, and invalidating sessions, and uses a repository for persistence.\r\n */\r\n\r\n// PayloadCMS native logging is used via payload.logger\r\n\r\ntype UserSession = SessionRecord;\r\ntype ValidationResultError = string | { message: string; path: string };\r\ntype ValidationResultData<T = unknown> = {\r\n success: boolean;\r\n data?: T;\r\n errors?: ValidationResultError[];\r\n};\r\n\r\nexport class SessionService {\r\n private repository: SessionRepository | null = null;\r\n\r\n constructor(repository?: SessionRepository) {\r\n if (repository) {\r\n this.repository = repository;\r\n }\r\n }\r\n\r\n private async getRepository(): Promise<SessionRepository> {\r\n if (!this.repository) {\r\n const payload = await getPayloadClient();\r\n this.repository = new SessionRepository(payload);\r\n }\r\n return this.repository;\r\n }\r\n\r\n /**\r\n * Creates a new session for a user.\r\n */\r\n async createSession(data: Partial<SessionRecord>): Promise<ValidationResultData<SessionRecord>> {\r\n if (!data.userId || typeof data.userId !== 'string') {\r\n return {\r\n success: false,\r\n errors: [\r\n {\r\n message: 'userId is required',\r\n path: 'userId',\r\n },\r\n ],\r\n };\r\n }\r\n const repository = await this.getRepository();\r\n const result = await repository.create(data);\r\n if (!result.success) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.error('Failed to create session', {\r\n errors: result.errors,\r\n });\r\n } catch {\r\n devLogger.error('Failed to create session', { errors: result.errors });\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Validates a session by ID, checks for expiration, and deletes if expired.\r\n */\r\n async validateSession(sessionId: string): Promise<ValidationResultData<UserSession>> {\r\n try {\r\n const repository = await this.getRepository();\r\n const result = await repository.findById(sessionId);\r\n\r\n if (!result.success || !result.data) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.warn('Invalid session', { sessionId, errors: result.errors });\r\n } catch {\r\n devLogger.warn('Invalid session', { sessionId, errors: result.errors });\r\n }\r\n return {\r\n success: false,\r\n errors: result.errors ?? [{ message: 'Session not found', path: 'validateSession' }],\r\n };\r\n }\r\n\r\n const session = result.data;\r\n if (session.expiresAt.getTime() < Date.now()) {\r\n await repository.delete(sessionId);\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.info('Session expired and deleted', { sessionId });\r\n } catch {\r\n devLogger.info('Session expired and deleted', { sessionId });\r\n }\r\n\r\n return {\r\n success: false,\r\n errors: [{ message: 'Session expired', path: 'validateSession' }],\r\n };\r\n }\r\n\r\n // Fetch user data using UserServiceCoordinator\r\n const userResult = { success: true, data: { id: session.userId } } as const;\r\n if (!userResult.success || !userResult.data) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.error('User not found for session', {\r\n sessionId,\r\n userId: session.userId,\r\n });\r\n } catch {\r\n devLogger.error('User not found for session', {\r\n sessionId,\r\n userId: session.userId,\r\n });\r\n }\r\n return {\r\n success: false,\r\n errors: [{ message: 'User not found for session', path: 'validateSession' }],\r\n };\r\n }\r\n\r\n return { success: true, data: session };\r\n } catch (error) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.error('Session validation failed', { error });\r\n } catch {\r\n devLogger.error('Session validation failed', { error });\r\n }\r\n return {\r\n success: false,\r\n errors: [{ message: 'Session validation failed', path: 'validateSession' }],\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Invalidates (deletes) a session by ID.\r\n */\r\n async invalidateSession(sessionId: string): Promise<ValidationResultData> {\r\n try {\r\n const repository = await this.getRepository();\r\n const result = await repository.delete(sessionId);\r\n if (!result.success) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.error('Session invalidation failed', {\r\n errors: result.errors,\r\n });\r\n } catch {\r\n devLogger.error('Session invalidation failed', {\r\n errors: result.errors,\r\n });\r\n }\r\n return result;\r\n }\r\n return result;\r\n } catch (error) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.error('Session invalidation failed', { error });\r\n } catch {\r\n devLogger.error('Session invalidation failed', { error });\r\n }\r\n return {\r\n success: false,\r\n errors: [\r\n {\r\n message: 'Session invalidation failed',\r\n path: 'invalidateSession',\r\n },\r\n ],\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Invalidates (deletes) all sessions for a user by userId.\r\n */\r\n async invalidateAllUserSessions(userId: string): Promise<ValidationResultData> {\r\n try {\r\n const repository = await this.getRepository();\r\n const result = await repository.revokeAllUserSessions(userId);\r\n if (!result.success) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.error('User sessions invalidation failed', {\r\n errors: result.errors,\r\n });\r\n } catch {\r\n devLogger.error('User sessions invalidation failed', {\r\n errors: result.errors,\r\n });\r\n }\r\n return result;\r\n }\r\n return result;\r\n } catch (error) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.error('User sessions invalidation failed', {\r\n error,\r\n });\r\n } catch {\r\n devLogger.error('User sessions invalidation failed', { error });\r\n }\r\n return {\r\n success: false,\r\n errors: [\r\n {\r\n message: 'Failed to invalidate user sessions',\r\n path: 'invalidateAllUserSessions',\r\n },\r\n ],\r\n };\r\n }\r\n }\r\n\r\n async getSessionById(id: string): Promise<ValidationResultData<SessionRecord>> {\r\n const repository = await this.getRepository();\r\n const result = await repository.findById(id);\r\n if (!result.success) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.warn('Session not found', {\r\n errors: result.errors,\r\n });\r\n } catch {\r\n devLogger.warn('Session not found', { errors: result.errors });\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n async getAllSessions(): Promise<ValidationResultData<SessionRecord[]>> {\r\n const repository = await this.getRepository();\r\n const result = await repository.findAll();\r\n if (!result.success) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.error('Failed to fetch sessions', {\r\n errors: result.errors,\r\n });\r\n } catch {\r\n devLogger.error('Failed to fetch sessions', {\r\n errors: result.errors,\r\n });\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n async updateSession(\r\n id: string,\r\n data: Partial<SessionRecord>\r\n ): Promise<ValidationResultData<SessionRecord>> {\r\n const repository = await this.getRepository();\r\n const result = await repository.update(id, data);\r\n if (!result.success) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.error('Failed to update session', {\r\n errors: result.errors,\r\n });\r\n } catch {\r\n devLogger.error('Failed to update session', { errors: result.errors });\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n async deleteSession(id: string): Promise<ValidationResultData> {\r\n const repository = await this.getRepository();\r\n const result = await repository.delete(id);\r\n if (!result.success) {\r\n try {\r\n const payload = await getPayloadClient();\r\n payload.logger.error('Failed to delete session', {\r\n errors: result.errors,\r\n });\r\n } catch {\r\n devLogger.error('Failed to delete session', { errors: result.errors });\r\n }\r\n }\r\n return result;\r\n }\r\n}\r\n\r\nexport const sessionService = new SessionService();\r\n\r\n","import { InfrastructureService } from '@revealui/core';\r\nimport type { Payload, PayloadRequest } from 'payload';\r\n\r\nclass AppError extends Error {\r\n constructor(\r\n public code: string,\r\n message: string,\r\n public cause?: Error\r\n ) {\r\n super(message);\r\n this.name = 'AppError';\r\n if (cause) {\r\n this.cause = cause;\r\n }\r\n }\r\n}\r\n\r\nconst ErrorCode = {\r\n TOKEN_INVALID: 'TOKEN_INVALID',\r\n TOKEN_EXPIRED: 'TOKEN_EXPIRED',\r\n AUTHENTICATION_ERROR: 'AUTHENTICATION_ERROR',\r\n INTERNAL_ERROR: 'INTERNAL_ERROR',\r\n} as const;\r\n\r\n/**\r\n * Token Service using PayloadCMS native authentication\r\n *\r\n * Leverages PayloadCMS built-in JWT handling, authentication,\r\n * and user management instead of custom implementations.\r\n *\r\n * NOTE: This service uses overrideAccess: true for password reset and account unlock\r\n * operations as these are system-level operations that need to bypass normal access control.\r\n * Regular user authentication operations respect normal access control.\r\n */\r\nexport class TokenService extends InfrastructureService {\r\n constructor(protected readonly payload: Payload) {\r\n super(payload, 'TokenService');\r\n }\r\n\r\n /**\r\n * Authenticate user and generate access token using PayloadCMS native login\r\n * @param credentials User login credentials\r\n * @param req Optional PayloadRequest for context\r\n * @returns Login result with user data and token\r\n */\r\n async login(credentials: { email: string; password: string }, req?: PayloadRequest) {\r\n try {\r\n this.logger.debug('Attempting user login', {\r\n email: credentials.email,\r\n serviceName: this.serviceName,\r\n operation: 'login',\r\n });\r\n\r\n const result = await this.payload.login({\r\n collection: 'users',\r\n data: {\r\n email: credentials.email,\r\n password: credentials.password,\r\n },\r\n ...(req && { req }),\r\n });\r\n\r\n this.logger.info('User login successful', {\r\n userId: result.user.id,\r\n email: result.user.email,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return result;\r\n } catch (error) {\r\n this.logger.error('User login failed', {\r\n email: credentials.email,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n serviceName: this.serviceName,\r\n });\r\n throw new AppError(\r\n ErrorCode.AUTHENTICATION_ERROR,\r\n 'Login failed',\r\n error instanceof Error ? error : new Error(String(error))\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Verify user by ID using PayloadCMS native functionality\r\n * @param userId User ID to verify\r\n * @returns User data if exists\r\n */\r\n async verifyUser(userId: string | number) {\r\n try {\r\n this.logger.debug('Verifying user', {\r\n userId,\r\n serviceName: this.serviceName,\r\n operation: 'verifyUser',\r\n });\r\n\r\n // Read operations respect collection-level access control\r\n const user = await this.payload.findByID({\r\n collection: 'users',\r\n id: userId,\r\n });\r\n\r\n this.logger.debug('User verification successful', {\r\n userId: user.id,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return user;\r\n } catch (error) {\r\n this.logger.error('User verification failed', {\r\n userId,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n serviceName: this.serviceName,\r\n });\r\n throw new AppError(\r\n ErrorCode.AUTHENTICATION_ERROR,\r\n 'User verification failed',\r\n error instanceof Error ? error : new Error(String(error))\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Generate password reset token using PayloadCMS native functionality\r\n * @param email User email address\r\n * @returns Password reset token\r\n */\r\n async generatePasswordResetToken(email: string) {\r\n try {\r\n this.logger.debug('Generating password reset token', {\r\n email,\r\n serviceName: this.serviceName,\r\n operation: 'generatePasswordResetToken',\r\n });\r\n\r\n const token = await this.payload.forgotPassword({\r\n collection: 'users',\r\n data: { email },\r\n });\r\n\r\n this.logger.info('Password reset token generated', {\r\n email,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return token;\r\n } catch (error) {\r\n this.logger.error('Password reset token generation failed', {\r\n email,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n serviceName: this.serviceName,\r\n });\r\n throw new AppError(\r\n ErrorCode.INTERNAL_ERROR,\r\n 'Failed to generate password reset token',\r\n error instanceof Error ? error : new Error(String(error))\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Reset user password using PayloadCMS native functionality\r\n * @param token Password reset token\r\n * @param newPassword New password\r\n * @returns Reset result with user and new token\r\n *\r\n * NOTE: Uses overrideAccess: true as this is a system-level password reset operation\r\n * that requires bypassing normal access control for security token validation.\r\n */\r\n async resetPassword(token: string, newPassword: string) {\r\n try {\r\n this.logger.debug('Resetting password', {\r\n serviceName: this.serviceName,\r\n operation: 'resetPassword',\r\n });\r\n\r\n const result = await this.payload.resetPassword({\r\n collection: 'users',\r\n data: {\r\n token,\r\n password: newPassword,\r\n },\r\n overrideAccess: true, // System-level operation for password reset flow\r\n });\r\n\r\n this.logger.info('Password reset successful', {\r\n userId: result.user?.id,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return result;\r\n } catch (error) {\r\n this.logger.error('Password reset failed', {\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n serviceName: this.serviceName,\r\n });\r\n throw new AppError(\r\n ErrorCode.AUTHENTICATION_ERROR,\r\n 'Password reset failed',\r\n error instanceof Error ? error : new Error(String(error))\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Verify email using PayloadCMS native functionality\r\n * @param token Email verification token\r\n * @returns Verification success status\r\n */\r\n async verifyEmail(token: string) {\r\n try {\r\n this.logger.debug('Verifying email', {\r\n serviceName: this.serviceName,\r\n operation: 'verifyEmail',\r\n });\r\n\r\n const result = await this.payload.verifyEmail({\r\n collection: 'users',\r\n token,\r\n });\r\n\r\n this.logger.info('Email verification completed', {\r\n success: result,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return result;\r\n } catch (error) {\r\n this.logger.error('Email verification failed', {\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n serviceName: this.serviceName,\r\n });\r\n throw new AppError(\r\n ErrorCode.AUTHENTICATION_ERROR,\r\n 'Email verification failed',\r\n error instanceof Error ? error : new Error(String(error))\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Unlock user account using PayloadCMS native functionality\r\n * @param email User email address\r\n * @param password User password\r\n * @returns Unlock success status\r\n *\r\n * NOTE: Uses overrideAccess: true as this is a system-level account unlock operation\r\n * that requires bypassing normal access control for account recovery.\r\n */\r\n async unlockUser(email: string, password: string) {\r\n try {\r\n this.logger.debug('Unlocking user account', {\r\n email,\r\n serviceName: this.serviceName,\r\n operation: 'unlockUser',\r\n });\r\n\r\n const result = await this.payload.unlock({\r\n collection: 'users',\r\n data: { email, password },\r\n overrideAccess: true, // System-level operation for account recovery\r\n });\r\n\r\n this.logger.info('User account unlock completed', {\r\n email,\r\n success: result,\r\n serviceName: this.serviceName,\r\n });\r\n\r\n return result;\r\n } catch (error) {\r\n this.logger.error('User account unlock failed', {\r\n email,\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n serviceName: this.serviceName,\r\n });\r\n throw new AppError(\r\n ErrorCode.AUTHENTICATION_ERROR,\r\n 'User account unlock failed',\r\n error instanceof Error ? error : new Error(String(error))\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * @inheritdoc\r\n */\r\n protected onInitialize(): void {\r\n this.logger.info('TokenService initialized with PayloadCMS native auth', {\r\n serviceName: this.serviceName,\r\n });\r\n }\r\n\r\n /**\r\n * @inheritdoc\r\n */\r\n protected onCleanup(): void {\r\n // No cleanup needed as PayloadCMS handles JWT lifecycle\r\n this.logger.info('TokenService cleaned up', {\r\n serviceName: this.serviceName,\r\n });\r\n }\r\n\r\n /**\r\n * @inheritdoc\r\n */\r\n protected onHealthCheck(): void {\r\n // Basic health check - PayloadCMS handles JWT internally\r\n this.logger.debug('TokenService health check passed', {\r\n serviceName: this.serviceName,\r\n });\r\n }\r\n}\r\n\r\n// Export factory function for PayloadCMS integration\r\nexport function createTokenService(payload: Payload): TokenService {\r\n return new TokenService(payload);\r\n}\r\n\r\n"],"mappings":";AAMA,SAAS,SAAS;AAGlB,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACjC,gBAAgB,EAAE,OAAO,EAAE,IAAI,IAAI,+CAA+C;AAAA,EAClF,oBAAoB,EAAE,OAAO,EAAE,IAAI,IAAI,mDAAmD;AAAA,EAC1F,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACrC,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,EACtC,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS;AAC7C,CAAC;AAUM,IAAM,cAAc;AAAA,EACzB,MAAM,EAAE,UAAU,KAAK,KAAM,aAAa,GAAG;AAAA;AAAA,EAC7C,SAAS,EAAE,UAAU,KAAK,KAAM,aAAa,EAAE;AAAA;AAAA,EAC/C,SAAS,EAAE,UAAU,KAAK,KAAK,KAAM,aAAa,EAAE;AAAA;AAAA,EACpD,iBAAiB,EAAE,UAAU,KAAK,KAAM,aAAa,GAAG;AAAA;AAC1D;AAGA,IAAM,iBAAiB,oBAAI,IAAkD;AAK7E,eAAsB,sBAAqC;AACzD,QAAM,aAAa,kBAAkB,UAAU,QAAQ,GAAG;AAE1D,MAAI,CAAC,WAAW,SAAS;AACvB,UAAM,SAAS,WAAW,MAAM,OAC7B,IAAI,WAAS,GAAG,MAAM,KAAK,KAAK,GAAG,CAAC,KAAK,MAAM,OAAO,EAAE,EACxD,KAAK,IAAI;AAEZ,UAAM,IAAI,MAAM,kCAAkC,MAAM,EAAE;AAAA,EAC5D;AACF;AAKA,eAAsB,eACpB,KACA,QACqE;AACrE,QAAM,MAAM,KAAK,IAAI;AAGrB,aAAW,CAAC,GAAG,CAAC,KAAK,eAAe,QAAQ,GAAG;AAC7C,QAAI,EAAE,YAAY,KAAK;AACrB,qBAAe,OAAO,CAAC;AAAA,IACzB;AAAA,EACF;AAEA,QAAM,QAAQ,eAAe,IAAI,GAAG;AAEpC,MAAI,CAAC,SAAS,MAAM,YAAY,KAAK;AAEnC,mBAAe,IAAI,KAAK,EAAE,OAAO,GAAG,WAAW,MAAM,OAAO,SAAS,CAAC;AACtE,WAAO;AAAA,MACL,SAAS;AAAA,MACT,WAAW,OAAO,cAAc;AAAA,MAChC,WAAW,MAAM,OAAO;AAAA,IAC1B;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,OAAO,aAAa;AACrC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,WAAW;AAAA,MACX,WAAW,MAAM;AAAA,IACnB;AAAA,EACF;AAGA,QAAM;AACN,iBAAe,IAAI,KAAK,KAAK;AAE7B,SAAO;AAAA,IACL,SAAS;AAAA,IACT,WAAW,OAAO,cAAc,MAAM;AAAA,IACtC,WAAW,MAAM;AAAA,EACnB;AACF;AAKO,SAAS,qBAAqB,QAAgB,QAAwB;AAC3E,SAAO,cAAc,MAAM,IAAI,MAAM;AACvC;AAKO,SAAS,uBAAuB,IAAY,QAAwB;AACzE,SAAO,cAAc,MAAM,OAAO,EAAE;AACtC;AAKA,eAAsB,kBAAkB,OAAe,cAAwC;AAG7F,SAAO,UAAU,gBAAgB,MAAM,SAAS;AAClD;AAMO,SAAS,cAAc,OAAuB;AAEnD,SAAO,MACJ,QAAQ,uDAAuD,EAAE,EACjE,QAAQ,gCAAgC,EAAE,EAC1C,QAAQ,iBAAiB,EAAE,EAC3B,KAAK;AACV;AAKO,SAAS,yBACd,OACA,QACgE;AAChE,MAAI;AACF,UAAM,aAAa,OAAO,UAAU,KAAK;AAEzC,QAAI,CAAC,WAAW,SAAS;AACvB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,WAAW,MAAM,OAAO,IAAI,OAAK,EAAE,OAAO,EAAE,KAAK,IAAI;AAAA,MAC9D;AAAA,IACF;AAGA,UAAM,YAAY,eAAe,WAAW,IAAI;AAEhD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD;AAAA,EACF;AACF;AAKA,SAAS,eAAe,KAAuB;AAC7C,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO,cAAc,GAAG;AAAA,EAC1B;AAEA,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,WAAO,IAAI,IAAI,cAAc;AAAA,EAC/B;AAEA,MAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,UAAM,YAAqC,CAAC;AAC5C,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,gBAAU,GAAG,IAAI,eAAe,KAAK;AAAA,IACvC;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKO,IAAM,mBAAmB;AAAA,EAC9B,0BAA0B;AAAA,EAC1B,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,sBAAsB;AACxB;AAKO,SAAS,iBACd,OACA,SACA,WAAmD,UAC7C;AACN,UAAQ,IAAI,aAAa,SAAS,YAAY,CAAC,KAAK,KAAK,KAAK;AAAA,IAC5D,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AACH;;;ACpNA,IAAM,YAAY;AAAA,EAChB,OAAO,IAAI,SAAoB,QAAQ,MAAM,cAAc,GAAG,IAAI;AAAA,EAClE,MAAM,IAAI,SAAoB,QAAQ,IAAI,cAAc,GAAG,IAAI;AAAA,EAC/D,MAAM,IAAI,SAAoB,QAAQ,KAAK,cAAc,GAAG,IAAI;AAAA,EAChE,OAAO,IAAI,SAAoB,QAAQ,MAAM,cAAc,GAAG,IAAI;AAAA,EAClE,YAAY,CAAC,WAAmB;AAAA,IAC9B,OAAO,IAAI,SAAoB,QAAQ,MAAM,cAAc,GAAG,IAAI;AAAA,IAClE,MAAM,IAAI,SAAoB,QAAQ,IAAI,cAAc,GAAG,IAAI;AAAA,IAC/D,MAAM,IAAI,SAAoB,QAAQ,KAAK,cAAc,GAAG,IAAI;AAAA,IAChE,OAAO,IAAI,SAAoB,QAAQ,MAAM,cAAc,GAAG,IAAI;AAAA,EACpE;AACF;AA4BO,IAAM,qBAAN,MAAyB;AAAA,EACb;AAAA,EACA,gBAAgB,oBAAI,IAA4B;AAAA,EACzD,kBAAyD;AAAA,EAEjE,YAAY,QAAyB;AACnC,SAAK,SAAS;AAAA,MACZ,UAAU,OAAO,YAAY,KAAK,KAAK;AAAA;AAAA,MACvC,aAAa,OAAO,eAAe;AAAA,MACnC,wBAAwB,OAAO,0BAA0B;AAAA,MACzD,oBAAoB,OAAO,sBAAsB;AAAA,MACjD,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,eAAe,OAAO,iBAAiB;AAAA,IACzC;AAGA,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEA,WAAW,UAAyB;AAAA,EAEpC;AAAA;AAAA;AAAA;AAAA,EAKA,iBACE,KACA,SAAiB,GACjB,WAAmB,IACnB,aAAqB,GACrB,aAAqB,KACJ;AACjB,QAAI;AACF,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,YAAY,2BAA2B,GAAG;AAChD,YAAM,UAAU,KAAK,cAAc,IAAI,SAAS;AAEhD,UAAI,gBAAgB;AACpB,UAAI,aAAa;AAEjB,UAAI,SAAS;AACX,wBAAgB,QAAQ;AACxB,qBAAa,QAAQ;AAAA,MACvB;AAGA,YAAM,aAAa,MAAM;AACzB,YAAM,eAAe,KAAK,MAAM,aAAa,UAAU,IAAI;AAC3D,sBAAgB,KAAK,IAAI,UAAU,gBAAgB,YAAY;AAG/D,UAAI,iBAAiB,QAAQ;AAC3B,wBAAgB,gBAAgB;AAChC,aAAK,cAAc,IAAI,WAAW;AAAA,UAChC,OAAO;AAAA,UACP,WAAW,MAAM;AAAA,UACjB,iBAAiB;AAAA,QACnB,CAAC;AAED,kBAAU,MAAM,oBAAoB;AAAA,UAClC;AAAA,UACA,WAAW;AAAA,UACX,SAAS;AAAA,UACT,WAAW;AAAA,UACX,WAAW,MAAM;AAAA,UACjB;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAED,eAAO;AAAA,UACL,SAAS;AAAA,UACT,WAAW;AAAA,UACX,WAAW,MAAM;AAAA,QACnB;AAAA,MACF;AACA,YAAM,YAAY,aAAa;AAC/B,gBAAU,KAAK,sBAAsB;AAAA,QACnC;AAAA,QACA,WAAW;AAAA,QACX,WAAW;AAAA,QACX;AAAA,QACA;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW;AAAA,QACX;AAAA,QACA,YAAY,KAAK,MAAM,YAAY,OAAO,GAAI;AAAA,MAChD;AAAA,IACF,SAAS,OAAO;AACd,gBAAU,MAAM,sBAAsB,iBAAiB,QAAQ,QAAQ,QAAW;AAAA,QAChF;AAAA,QACA,WAAW;AAAA,QACX,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD,CAAC;AAED,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW;AAAA,QACX,WAAW,KAAK,IAAI,IAAI;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,mBACE,KACA,WAAmB,KAAK,OAAO,UAC/B,cAAsB,KAAK,OAAO,aACjB;AACjB,QAAI;AACF,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,YAAY,6BAA6B,GAAG;AAClD,YAAM,UAAU,KAAK,cAAc,IAAI,SAAS;AAEhD,UAAI,WAAqB,CAAC;AAC1B,UAAI,SAAS;AACX,mBAAW,CAAC,QAAQ,KAAK;AAAA,MAC3B;AAGA,YAAM,cAAc,MAAM;AAC1B,iBAAW,SAAS,OAAO,eAAa,aAAa,WAAW;AAGhE,UAAI,SAAS,SAAS,aAAa;AACjC,iBAAS,KAAK,GAAG;AACjB,aAAK,cAAc,IAAI,WAAW;AAAA,UAChC,OAAO,SAAS;AAAA,UAChB,WAAW,MAAM;AAAA,UACjB,iBAAiB;AAAA,QACnB,CAAC;AAED,kBAAU,MAAM,oBAAoB;AAAA,UAClC;AAAA,UACA,WAAW;AAAA,UACX,SAAS;AAAA,UACT,WAAW,cAAc,SAAS;AAAA,UAClC,WAAW,MAAM;AAAA,QACnB,CAAC;AAED,eAAO;AAAA,UACL,SAAS;AAAA,UACT,WAAW,cAAc,SAAS;AAAA,UAClC,WAAW,MAAM;AAAA,QACnB;AAAA,MACF;AACA,YAAM,SAAS,KAAK,IAAI,GAAG,QAAQ;AACnC,YAAM,YAAY,SAAS;AAE3B,gBAAU,KAAK,sBAAsB;AAAA,QACnC;AAAA,QACA,WAAW;AAAA,QACX,WAAW;AAAA,QACX;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW;AAAA,QACX;AAAA,QACA,YAAY,KAAK,MAAM,YAAY,OAAO,GAAI;AAAA,MAChD;AAAA,IACF,SAAS,OAAO;AACd,gBAAU,MAAM,sBAAsB,iBAAiB,QAAQ,QAAQ,QAAW;AAAA,QAChF;AAAA,QACA,WAAW;AAAA,QACX,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD,CAAC;AAED,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW;AAAA,QACX,WAAW,KAAK,IAAI,IAAI;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBACE,KACA,WAAmB,IACnB,WAAmB,GACnB,WAAmB,KACF;AACjB,QAAI;AACF,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,YAAY,2BAA2B,GAAG;AAChD,YAAM,UAAU,KAAK,cAAc,IAAI,SAAS;AAEhD,UAAI,eAAe;AACnB,UAAI,WAAW;AAEf,UAAI,SAAS;AACX,uBAAe,QAAQ;AACvB,mBAAW,QAAQ;AAAA,MACrB;AAGA,YAAM,aAAa,MAAM;AACzB,YAAM,aAAa,KAAK,MAAM,aAAa,QAAQ,IAAI;AACvD,qBAAe,KAAK,IAAI,GAAG,eAAe,UAAU;AAGpD,UAAI,eAAe,UAAU;AAC3B;AACA,aAAK,cAAc,IAAI,WAAW;AAAA,UAChC,OAAO;AAAA,UACP,WAAW,MAAM;AAAA,UACjB,iBAAiB;AAAA,QACnB,CAAC;AAED,kBAAU,MAAM,oBAAoB;AAAA,UAClC;AAAA,UACA,WAAW;AAAA,UACX,SAAS;AAAA,UACT,WAAW,WAAW;AAAA,UACtB,WAAW,MAAM;AAAA,QACnB,CAAC;AAED,eAAO;AAAA,UACL,SAAS;AAAA,UACT,WAAW,WAAW;AAAA,UACtB,WAAW,MAAM;AAAA,QACnB;AAAA,MACF;AACA,YAAM,YAAY,WAAW;AAC7B,gBAAU,KAAK,sBAAsB;AAAA,QACnC;AAAA,QACA,WAAW;AAAA,QACX,WAAW;AAAA,QACX;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW;AAAA,QACX;AAAA,QACA,YAAY,KAAK,MAAM,YAAY,OAAO,GAAI;AAAA,MAChD;AAAA,IACF,SAAS,OAAO;AACd,gBAAU,MAAM,sBAAsB,iBAAiB,QAAQ,QAAQ,QAAW;AAAA,QAChF;AAAA,QACA,WAAW;AAAA,QACX,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD,CAAC;AAED,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW;AAAA,QACX,WAAW,KAAK,IAAI,IAAI;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,KAAmB;AAChC,UAAM,WAAW;AAAA,MACf,2BAA2B,GAAG;AAAA,MAC9B,6BAA6B,GAAG;AAAA,MAChC,2BAA2B,GAAG;AAAA,IAChC;AAEA,eAAW,WAAW,UAAU;AAC9B,WAAK,cAAc,OAAO,OAAO;AAAA,IACnC;AAEA,cAAU,MAAM,oBAAoB,EAAE,IAAI,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,KAAoC;AACpD,UAAM,WAAW;AAAA,MACf,2BAA2B,GAAG;AAAA,MAC9B,6BAA6B,GAAG;AAAA,MAChC,2BAA2B,GAAG;AAAA,IAChC;AAEA,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,KAAK,cAAc,IAAI,OAAO;AAC5C,UAAI,OAAO;AACT,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAqB,KAAa,OAA6B;AAC7D,SAAK,cAAc,IAAI,KAAK,KAAK;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAuD;AACrD,WAAO;AAAA,MACL,WAAW,KAAK,cAAc;AAAA,MAC9B,aAAa,KAAK,cAAc;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,SAAS,KAAK,KAAK,KAAK;AAE9B,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,cAAc,QAAQ,GAAG;AACvD,UAAI,MAAM,MAAM,kBAAkB,QAAQ;AACxC,aAAK,cAAc,OAAO,GAAG;AAAA,MAC/B;AAAA,IACF;AAEA,cAAU,MAAM,yCAAyC;AAAA,MACvD,WAAW,KAAK,cAAc;AAAA,IAChC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAA6B;AACnC,QAAI,KAAK,iBAAiB;AACxB,oBAAc,KAAK,eAAe;AAAA,IACpC;AAGA,SAAK,kBAAkB;AAAA,MACrB,MAAM;AACJ,aAAK,QAAQ;AAAA,MACf;AAAA,MACA,KAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,sBAA4B;AAC1B,QAAI,KAAK,iBAAiB;AACxB,oBAAc,KAAK,eAAe;AAClC,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,SAAK,oBAAoB;AACzB,SAAK,cAAc,MAAM;AAAA,EAC3B;AACF;AAKO,IAAM,wBAAwB,CAAC,WAAiD;AACrF,SAAO,IAAI,mBAAmB,UAAU,CAAC,CAAC;AAC5C;;;ACxZA,SAAQ,eAAc;AACtB,IAAMA,eAAc,EAAE,SAAS,EAAE,OAAO,KAAK,UAAU,IAAO,EAAE;AAChE,IAAMC,wBAAuB,CAAC,OAAe,QAAQ,EAAE;AACvD,IAAMC,0BAAyB,CAAC,OAAe,WAAW,EAAE;AAC5D,eAAeC,gBACb,MACA,QACA,WAC0B;AAE1B,SAAO,EAAE,SAAS,MAAM,WAAW,QAAQ,WAAW,KAAK,IAAI,IAAI,UAAU;AAC/E;AAYA,eAAsB,cACpB,QACA,QAKA;AACA,SAAO,UAAU,SAAwB;AACvC,UAAM,cAAc,MAAM,QAAQ;AAClC,UAAM,KAAK,YAAY,IAAI,iBAAiB,KAAK,YAAY,IAAI,WAAW,KAAK;AAGjF,UAAM,MACJ,OAAO,cACN,OAAO,SAASF,sBAAqB,OAAO,MAAM,IAAIC,wBAAuB,EAAE;AAGlF,UAAM,kBAAkB,MAAMC;AAAA,MAC5B;AAAA,MACAH,aAAY,OAAO,IAAI,EAAE;AAAA,MACzBA,aAAY,OAAO,IAAI,EAAE;AAAA,IAC3B;AAEA,QAAI,CAAC,gBAAgB,SAAS;AAC5B,YAAM,IAAI;AAAA,QACR,qCAAqC,KAAK,MAAM,gBAAgB,YAAY,KAAK,IAAI,KAAK,GAAI,CAAC;AAAA,MACjG;AAAA,IACF;AAGA,WAAO,MAAM,OAAO,GAAG,IAAI;AAAA,EAC7B;AACF;AAKO,SAAS,YAAY,MAAgC,QAAiB;AAC3E,SAAO,CAAC,SAAiB,cAAsB,eAAmC;AAChF,UAAM,iBAAiB,WAAW;AAElC,eAAW,QAAQ,kBAAmB,MAAa;AACjD,YAAM,cAAc,MAAM,QAAQ;AAClC,YAAM,KAAK,YAAY,IAAI,iBAAiB,KAAK,YAAY,IAAI,WAAW,KAAK;AAEjF,YAAM,MAAM,SAASC,sBAAqB,MAAM,IAAIC,wBAAuB,EAAE;AAE7E,YAAM,kBAAkB,MAAMC;AAAA,QAC5B;AAAA,QACAH,aAAY,IAAI,EAAE;AAAA,QAClBA,aAAY,IAAI,EAAE;AAAA,MACpB;AAEA,UAAI,CAAC,gBAAgB,SAAS;AAC5B,cAAM,IAAI;AAAA,UACR,qCAAqC,KAAK,MAAM,gBAAgB,YAAY,KAAK,IAAI,KAAK,GAAI,CAAC;AAAA,QACjG;AAAA,MACF;AAEA,aAAO,MAAM,eAAe,MAAM,MAAM,IAAI;AAAA,IAC9C;AAEA,WAAO;AAAA,EACT;AACF;AAKA,eAAsB,cAA+B;AACnD,QAAM,cAAc,MAAM,QAAQ;AAClC,SAAO,YAAY,IAAI,iBAAiB,KAAK,YAAY,IAAI,WAAW,KAAK;AAC/E;AAKA,eAAsB,kBAAoC;AACxD,QAAM,cAAc,MAAM,QAAQ;AAClC,QAAM,YAAY,YAAY,IAAI,YAAY,KAAK;AACnD,QAAM,SAAS,YAAY,IAAI,QAAQ,KAAK;AAG5C,QAAM,cAAc,CAAC,QAAQ,YAAY,WAAW,YAAY,SAAS,OAAO;AAEhF,QAAM,QAAQ,YAAY,KAAK,aAAW,QAAQ,KAAK,SAAS,CAAC;AAGjE,QAAM,iBAAiB;AAAA,IACrB,QAAQ,IAAI;AAAA,IACZ;AAAA,IACA;AAAA,EACF,EAAE,OAAO,OAAO;AAEhB,QAAM,kBAAkB,eAAe,SAAS,MAAM;AAEtD,SAAO,CAAC,SAAS;AACnB;AAKA,eAAsB,mBACpB,QACA,QACA,cAC0B;AAC1B,QAAM,SAAS,EAAE,GAAGA,aAAY,MAAM,GAAG,GAAG,aAAa;AACzD,QAAM,MAAMC,sBAAqB,MAAM;AAEvC,SAAO,MAAME,gBAAe,KAAK,OAAO,OAAO,OAAO,QAAQ;AAChE;AAKA,eAAsB,wBACpB,QACA,cAC0B;AAC1B,QAAM,KAAK,MAAM,YAAY;AAC7B,QAAM,SAAS,EAAE,GAAGH,aAAY,MAAM,GAAG,GAAG,aAAa;AACzD,QAAM,MAAME,wBAAuB,EAAE;AAErC,SAAO,MAAMC,gBAAe,KAAK,OAAO,OAAO,OAAO,QAAQ;AAChE;;;ACrJA,SAAQ,YAAW,mBAAkB;AAG9B,IAAM,cAAN,MAAkB;AAAA,EAGvB,YACmB,SACjB,UAA2B,CAAC,GAC5B;AAFiB;AAGjB,SAAK,UAAU;AAAA,MACb,WAAW,QAAQ,aAAa;AAAA,MAChC,UAAU,QAAQ,YAAY;AAAA,MAC9B,aAAa,QAAQ,eAAe;AAAA,MACpC,aAAa,QAAQ,eAAe,KAAK,KAAK,KAAK;AAAA;AAAA,IACrD;AAAA,EACF;AAAA,EAZiB;AAAA,EAcjB,MAAM,kBAAkB,WAAoC;AAC1D,QAAI;AACF,YAAM,QAAQ,YAAY,KAAK,QAAQ,WAAW;AAClD,YAAM,OAAO,WAAW,KAAK,QAAQ,WAAW,QAAQ,IAAI,kBAAkB,EAAE;AAEhF,WAAK,OAAO,SAAS;AACrB,WAAK,OAAO,KAAK;AAEjB,YAAM,YAAY,KAAK,OAAO,KAAK,QAAQ,QAAQ;AACnD,YAAM,YAAY,GAAG,MAAM,SAAS,KAAK,QAAQ,QAAQ,CAAC,IAAI,SAAS;AAEvE,WAAK,QAAQ,OAAO,MAAM,mCAAmC;AAC7D,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,QAAQ,OAAO,MAAM,iCAAiC,KAAc;AACzE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,OAAe,WAAqC;AAC1E,QAAI;AACF,YAAM,CAAC,WAAW,SAAS,IAAI,MAAM,MAAM,GAAG;AAC9C,UAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,aAAK,QAAQ,OAAO,KAAK,2BAA2B;AACpD,eAAO;AAAA,MACT;AAEA,YAAM,OAAO,WAAW,KAAK,QAAQ,WAAW,QAAQ,IAAI,kBAAkB,EAAE;AAChF,WAAK,OAAO,SAAS;AACrB,WAAK,OAAO,OAAO,KAAK,WAAW,KAAK,QAAQ,QAAQ,CAAC;AAEzD,YAAM,oBAAoB,KAAK,OAAO,KAAK,QAAQ,QAAQ;AAC3D,YAAM,UAAU,cAAc;AAE9B,UAAI,SAAS;AACX,aAAK,QAAQ,OAAO,MAAM,mCAAmC;AAAA,MAC/D,OAAO;AACL,aAAK,QAAQ,OAAO,KAAK,8BAA8B;AAAA,MACzD;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,QAAQ,OAAO,MAAM,iCAAiC,KAAc;AACzE,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACrEA,SAAQ,6BAA4B;AAEpC;AAAA,EACI;AAAA,EACA;AAAA,EACA,eAAAC;AAAA,EACA,UAAU;AAAA,OACP;AAEP,SAAQ,iBAAgB;AAcxB,IAAM,cAA2B,UAAU,cAAc;AAkCzD,SAAS,sBAAsB,QAAmD;AAChF,SAAO,OAAQ,OAAwC,eAAe;AACxE;AAEA,SAAS,wBAAwB,UAA2D;AAC1F,SAAO,OAAQ,SAA4C,eAAe;AAC5E;AAQO,IAAM,oBAAN,cAAgC,sBAAsB;AAAA,EAC1C;AAAA,EAEjB,YAAY,SAAkB,UAA6B,CAAC,GAAG;AAC7D,UAAM,SAAS,mBAAmB;AAElC,SAAK,UAAU;AAAA,MACb,WAAW,QAAQ,aAAa;AAAA,MAChC,WAAW,QAAQ,aAAa;AAAA,MAChC,YAAY,QAAQ,cAAc;AAAA,MAClC,UAAU,QAAQ,YAAY;AAAA,MAC9B,YAAY,QAAQ,cAAc;AAAA,MAClC,UAAU,QAAQ,YAAY;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QACJ,MACA,eACuC;AACvC,WAAO,KAAK,+BAA+B,YAAY;AACrD,UAAI,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG;AACjD,cAAM,IAAI,MAAM,4CAA4C;AAAA,MAC9D;AAEA,YAAM,mBAAmB,EAAE,GAAG,KAAK,SAAS,GAAG,cAAc;AAE7D,WAAK,OAAO,MAAM,4BAA4B;AAAA,QAC5C,WAAW,iBAAiB;AAAA,QAC5B,YAAY,KAAK;AAAA,QACjB,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAED,YAAM,OAAOA,aAAY,iBAAiB,UAAU;AACpD,YAAM,KAAKA,aAAY,iBAAiB,QAAQ;AAEhD,YAAM,MAAM,MAAM,KAAK,UAAU,MAAM,gBAAgB;AACvD,YAAM,SAAS,eAAe,iBAAiB,WAAW,KAAK,EAAE;AAEjE,YAAM,YAAY,OAAO,OAAO,CAAC,OAAO,OAAO,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,CAAC;AAG7E,UAAI,sBAAsB,MAAM,MAAM,MAAM;AAC1C,cAAM,IAAI,MAAM,wCAAwC;AAAA,MAC1D;AACA,YAAM,UAAU,OAAO,WAAW;AAElC,YAAM,SAAwB;AAAA,QAC5B,MAAM,UAAU,SAAS,iBAAiB,QAAQ;AAAA,QAClD,UAAU;AAAA,UACR,WAAW,iBAAiB;AAAA,UAC5B,IAAI,GAAG,SAAS,iBAAiB,QAAQ;AAAA,UACzC,SAAS,QAAQ,SAAS,iBAAiB,QAAQ;AAAA,UACnD,MAAM,KAAK,SAAS,iBAAiB,QAAQ;AAAA,QAC/C;AAAA,MACF;AAEA,WAAK,OAAO,MAAM,+BAA+B;AAAA,QAC/C,WAAW,iBAAiB;AAAA,QAC5B,gBAAgB,KAAK;AAAA,QACrB,iBAAiB,OAAO,KAAK;AAAA,QAC7B,aAAa,KAAK;AAAA,MACpB,CAAC;AAED,aAAO;AAAA,IACT,GAAG,SAAS;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQ,eAA8D;AAC1E,WAAO,KAAK,+BAA+B,YAAY;AACrD,UAAI,CAAC,iBAAiB,CAAC,cAAc,QAAQ,CAAC,cAAc,UAAU;AACpE,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AAEA,YAAM,EAAE,MAAM,SAAS,IAAI;AAG3B,YAAM,iBAAiB,CAAC,aAAa,MAAM,WAAW,MAAM;AAC5D,iBAAW,SAAS,gBAAgB;AAClC,cAAM,aAAa,SAAS,KAA8B;AAC1D,YAAI,eAAe,UAAa,eAAe,QAAQ,eAAe,IAAI;AACxE,gBAAM,IAAI,MAAM,+CAA+C,KAAK,EAAE;AAAA,QACxE;AAAA,MACF;AAEA,WAAK,OAAO,MAAM,4BAA4B;AAAA,QAC5C,WAAW,SAAS;AAAA,QACpB,iBAAiB,KAAK;AAAA,QACtB,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAED,YAAM,MAAM,MAAM,KAAK,UAAU,OAAO,KAAK,SAAS,MAAM,KAAK,QAAQ,QAAQ,GAAG;AAAA,QAClF,GAAG,KAAK;AAAA,QACR,WAAW,SAAS;AAAA,MACtB,CAAC;AAED,YAAM,WAAW;AAAA,QACf,SAAS;AAAA,QACT;AAAA,QACA,OAAO,KAAK,SAAS,IAAI,KAAK,QAAQ,QAAQ;AAAA,MAChD;AAGA,UAAI,wBAAwB,QAAQ,MAAM,MAAM;AAC9C,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC5D;AACA,eAAS,WAAW,OAAO,KAAK,SAAS,SAAS,KAAK,QAAQ,QAAQ,CAAC;AAExE,YAAM,YAAY,OAAO,OAAO;AAAA,QAC9B,SAAS,OAAO,OAAO,KAAK,MAAM,KAAK,QAAQ,QAAQ,CAAC;AAAA,QACxD,SAAS,MAAM;AAAA,MACjB,CAAC;AAED,YAAM,SAAS,UAAU,SAAS,MAAM;AAExC,WAAK,OAAO,MAAM,+BAA+B;AAAA,QAC/C,WAAW,SAAS;AAAA,QACpB,iBAAiB,KAAK;AAAA,QACtB,iBAAiB,OAAO;AAAA,QACxB,aAAa,KAAK;AAAA,MACpB,CAAC;AAED,aAAO;AAAA,IACT,GAAG,SAAS;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aACJ,WACA,eAMA;AACA,WAAO,KAAK,+BAA+B,YAAY;AACrD,UAAI,CAAC,MAAM,QAAQ,SAAS,KAAK,UAAU,WAAW,GAAG;AACvD,cAAM,IAAI,MAAM,iDAAiD;AAAA,MACnE;AAEA,WAAK,OAAO,KAAK,6BAA6B;AAAA,QAC5C,WAAW,UAAU;AAAA,QACrB,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAED,YAAM,aAA8B,CAAC;AACrC,YAAM,SAAiD,CAAC;AAGxD,YAAM,qBAAqB,UAAU,IAAI,OAAM,SAAQ;AACrD,YAAI;AACF,gBAAM,SAAS,MAAM,KAAK,QAAQ,MAAM,aAAa;AACrD,cAAI,OAAO,WAAW,OAAO,MAAM;AACjC,uBAAW,KAAK,OAAO,IAAI;AAAA,UAC7B,OAAO;AACL,mBAAO,KAAK;AAAA,cACV;AAAA,cACA,OAAO,OAAO,SAAS;AAAA,YACzB,CAAC;AAAA,UACH;AAAA,QACF,SAAS,OAAO;AACd,iBAAO,KAAK;AAAA,YACV;AAAA,YACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAClD,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAED,YAAM,QAAQ,WAAW,kBAAkB;AAE3C,WAAK,OAAO,KAAK,8BAA8B;AAAA,QAC7C,YAAY,UAAU;AAAA,QACtB,YAAY,WAAW;AAAA,QACvB,QAAQ,OAAO;AAAA,QACf,aAAa,KAAK;AAAA,MACpB,CAAC;AAED,aAAO,EAAE,YAAY,OAAO;AAAA,IAC9B,GAAG,cAAc;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACJ,SAAiB,IACjB,WAA2C,OACX;AAChC,WAAO,KAAK,+BAA+B,YAAY;AACrD,UAAI,UAAU,KAAK,SAAS,MAAM;AAChC,cAAM,IAAI,MAAM,qDAAqD;AAAA,MACvE;AAEA,WAAK,OAAO,MAAM,0BAA0B;AAAA,QAC1C;AAAA,QACA;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAED,YAAM,aAAaA,aAAY,MAAM;AACrC,YAAM,SAAS,WAAW,SAAS,QAAQ;AAE3C,WAAK,OAAO,MAAM,sCAAsC;AAAA,QACtD;AAAA,QACA;AAAA,QACA,cAAc,OAAO;AAAA,QACrB,aAAa,KAAK;AAAA,MACpB,CAAC;AAED,aAAO;AAAA,IACT,GAAG,oBAAoB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,sBACJ,eACwE;AACxE,WAAO,KAAK,+BAA+B,YAAY;AACrD,UAAI,CAAC,eAAe;AAClB,cAAM,IAAI,MAAM,4BAA4B;AAAA,MAC9C;AAEA,WAAK,OAAO,MAAM,uCAAuC;AAAA,QACvD,WAAW,cAAc,SAAS;AAAA,QAClC,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAED,UAAI;AACF,cAAM,gBAAgB,MAAM,KAAK,QAAQ,aAAa;AACtD,cAAM,QAAQ,cAAc,WAAW,CAAC,CAAC,cAAc;AAEvD,aAAK,OAAO,MAAM,uCAAuC;AAAA,UACvD;AAAA,UACA,aAAa,KAAK;AAAA,QACpB,CAAC;AAED,eAAO,QACH,EAAE,OAAO,OAAO,OAAU,IAC1B;AAAA,UACE;AAAA,UACA,OAAO,cAAc,SAAS;AAAA,QAChC;AAAA,MACN,SAAS,OAAO;AACd,cAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAE9D,aAAK,OAAO,MAAM,oCAAoC;AAAA,UACpD,OAAO;AAAA,UACP,aAAa,KAAK;AAAA,QACpB,CAAC;AAED,eAAO,EAAE,OAAO,OAAO,OAAO,aAAa;AAAA,MAC7C;AAAA,IACF,GAAG,uBAAuB;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,UAAU,MAAc,UAAsC,CAAC,GAAoB;AAC/F,UAAM,mBAAmB,EAAE,GAAG,KAAK,SAAS,GAAG,QAAQ;AAEvD,UAAM,SAAS,QAAQ,IAAI;AAC3B,QAAI,CAAC,UAAU,WAAW,IAAI;AAC5B,YAAM,IAAI,MAAM,gEAAgE;AAAA,IAClF;AAEA,WAAO,YAAY,QAAQ,MAAM,iBAAiB,SAAS;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAyB,eAA8B;AACrD,SAAK,OAAO,KAAK,kCAAkC;AAAA,MACjD,WAAW,KAAK,QAAQ;AAAA,MACxB,WAAW,KAAK,QAAQ;AAAA,MACxB,aAAa,KAAK;AAAA,IACpB,CAAC;AAGD,QAAI,CAAC,QAAQ,IAAI,gBAAgB;AAC/B,YAAM,IAAI,MAAM,uEAAuE;AAAA,IACzF;AAGA,QAAI;AACF,YAAM,WAAW;AACjB,YAAM,YAAY,MAAM,KAAK,QAAQ,QAAQ;AAC7C,UAAI,CAAC,UAAU,WAAW,CAAC,UAAU,MAAM;AACzC,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAEA,YAAM,YAAY,MAAM,KAAK,QAAQ,UAAU,IAAI;AACnD,UAAI,CAAC,UAAU,WAAW,UAAU,SAAS,UAAU;AACrD,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAEA,WAAK,OAAO,MAAM,gDAAgD;AAAA,QAChE,aAAa,KAAK;AAAA,MACpB,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,4CAA4C,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,MACtG;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAyB,YAA2B;AAClD,SAAK,OAAO,KAAK,iCAAiC;AAAA,MAChD,aAAa,KAAK;AAAA,IACpB,CAAC;AAAA,EAEH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,gBAA+B;AAE7C,QAAI;AACF,YAAM,WAAW;AACjB,YAAM,YAAY,MAAM,KAAK,QAAQ,QAAQ;AAC7C,UAAI,CAAC,UAAU,WAAW,CAAC,UAAU,MAAM;AACzC,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AAEA,YAAM,YAAY,MAAM,KAAK,QAAQ,UAAU,IAAI;AACnD,UAAI,CAAC,UAAU,WAAW,UAAU,SAAS,UAAU;AACrD,cAAM,IAAI,MAAM,gCAAgC;AAAA,MAClD;AAAA,IACF,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,0CAA0C,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,MACpG;AAAA,IACF;AAAA,EACF;AACF;;;AC5aA,IAAMC,aAAY;AAAA,EAChB,MAAM,IAAI,SAAoB,QAAQ,IAAI,cAAc,GAAG,IAAI;AAAA,EAC/D,MAAM,IAAI,SAAoB,QAAQ,KAAK,cAAc,GAAG,IAAI;AAAA,EAChE,OAAO,IAAI,SAAoB,QAAQ,MAAM,cAAc,GAAG,IAAI;AACpE;AAkDO,IAAM,sBAAsB,CACjC,MACA,UACA,SACA,YAMkB;AAClB,QAAM,YAA2B;AAAA,IAC/B,IAAI,OAAO,WAAW;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,oBAAI,KAAK;AAAA,IACpB,GAAI,SAAS,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,IAC1D,GAAI,SAAS,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,IAClE,GAAI,SAAS,cAAc,SAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,IAC3E,GAAI,SAAS,cAAc,SAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,EAC7E;AAEA,SAAO;AACT;AAKO,IAAM,2BAA2B,CAACC,YAA6C;AACpF,MAAIA,QAAO,WAAW,GAAG;AACvB,WAAO;AAAA,MACL,aAAa;AAAA,MACb,cAAc,CAAC;AAAA,MACf,kBAAkB,CAAC;AAAA,MACnB,qBAAqB;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,eAAeA,QAAO,OAA+B,CAAC,KAAK,UAAU;AACzE,QAAI,MAAM,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,KAAK;AAC3C,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,mBAAmBA,QAAO,OAA+B,CAAC,KAAK,UAAU;AAC7E,QAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,KAAK,KAAK;AACnD,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,gBACJA,QAAO,SAAS,IAAI,IAAI,KAAK,KAAK,IAAI,GAAGA,QAAO,IAAI,OAAK,EAAE,UAAU,QAAQ,CAAC,CAAC,CAAC,IAAI;AAEtF,SAAO;AAAA,IACL,aAAaA,QAAO;AAAA,IACpB;AAAA,IACA;AAAA,IACA,qBAAqB;AAAA;AAAA,IACrB,GAAI,kBAAkB,SAAY,EAAE,cAAc,IAAI,CAAC;AAAA,EACzD;AACF;AAKO,IAAM,qBAAqB,CAChC,OACA,eAMY;AAEZ,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,kBAAkB,IAAI,KAAK,IAAI,QAAQ,IAAI,WAAW,YAAY;AAGxE,QAAM,eAAe,OAAO;AAAA,IAC1B,CAAAC,WAASA,OAAM,aAAa,mBAAmBA,OAAM,aAAa;AAAA,EACpE;AAGA,QAAM,gBAAgB,aAAa,OAAO,OAAK,EAAE,aAAa,UAAU,EAAE;AAC1E,QAAM,YAAY,aAAa,OAAO,OAAK,EAAE,aAAa,MAAM,EAAE;AAClE,QAAM,cAAc,aAAa,OAAO,OAAK,EAAE,aAAa,QAAQ,EAAE;AAGtE,MAAI,iBAAiB,WAAW,cAAe,QAAO;AACtD,MAAI,aAAa,WAAW,UAAW,QAAO;AAC9C,MAAI,eAAe,WAAW,YAAa,QAAO;AAGlD,MAAI,MAAM,aAAa,WAAY,QAAO;AAE1C,SAAO;AACT;AAKO,IAAM,sBAAsB,CACjC,OACA,YAAmC,0BAChB;AAAA,EACnB,IAAI,OAAO,WAAW;AAAA,EACtB,MAAM;AAAA,EACN,UAAU,MAAM;AAAA,EAChB,SAAS,mBAAmB,MAAM,OAAO;AAAA,EACzC,WAAW,oBAAI,KAAK;AAAA,EACpB,UAAU;AAAA,IACR,iBAAiB,MAAM;AAAA,IACvB,mBAAmB,MAAM;AAAA,IACzB,GAAG,MAAM;AAAA,EACX;AACF;AAKO,IAAM,eAAe,CAC1BD,SACA,aAMoB;AACpB,SAAOA,QAAO,OAAO,WAAS;AAC5B,QAAI,SAAS,QAAQ,MAAM,SAAS,SAAS,KAAM,QAAO;AAC1D,QAAI,SAAS,YAAY,MAAM,aAAa,SAAS,SAAU,QAAO;AACtE,QAAI,SAAS,UAAU,MAAM,WAAW,SAAS,OAAQ,QAAO;AAChE,QAAI,SAAS,WAAW;AACtB,YAAM,YAAY,MAAM,UAAU,QAAQ;AAC1C,YAAM,YAAY,SAAS,UAAU,MAAM,QAAQ;AACnD,YAAM,UAAU,SAAS,UAAU,IAAI,QAAQ;AAC/C,UAAI,YAAY,aAAa,YAAY,QAAS,QAAO;AAAA,IAC3D;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAOA,IAAI,SAA0B,CAAC;AAC/B,IAAI,SAA0B,CAAC;AAKxB,IAAM,mBAAmB,CAAC,UAA+B;AAC9D,SAAO,KAAK,KAAK;AAGjB,EAAAD,WAAU,KAAK,2BAA2B;AAAA,IACxC,SAAS,MAAM;AAAA,IACf,MAAM,MAAM;AAAA,IACZ,UAAU,MAAM;AAAA,IAChB,SAAS,MAAM;AAAA,IACf,QAAQ,MAAM;AAAA,IACd,WAAW,MAAM,UAAU,YAAY;AAAA,EACzC,CAAC;AAGD,MACE,mBAAmB,OAAO;AAAA,IACxB,eAAe;AAAA,IACf,WAAW;AAAA,IACX,aAAa;AAAA,IACb,cAAc;AAAA;AAAA,EAChB,CAAC,GACD;AACA,UAAM,QAAQ,oBAAoB,KAAK;AACvC,WAAO,KAAK,KAAK;AAEjB,IAAAA,WAAU,KAAK,4BAA4B;AAAA,MACzC,SAAS,MAAM;AAAA,MACf,SAAS,MAAM;AAAA,MACf,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM;AAAA,IACjB,CAAC;AAAA,EACH;AACF;AAKO,IAAM,oBAAoB,MAAuB,CAAC,GAAG,MAAM;AAK3D,IAAM,oBAAoB,MAAuB,CAAC,GAAG,MAAM;AAK3D,IAAM,qBAAqB,MAAuB,yBAAyB,MAAM;AAKjF,IAAM,oBAAoB,MAAY;AAC3C,WAAS,CAAC;AACV,WAAS,CAAC;AACZ;AASO,IAAM,yBAAyB,CACpC,QACA,SACA,YAKS;AACT,QAAM,eAA0D;AAAA,IAC9D;AAAA,IACA,GAAI,SAAS,cAAc,SAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,IAC3E,GAAI,SAAS,cAAc,SAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,IAC3E,UAAU;AAAA,MACR;AAAA,MACA,GAAG,SAAS;AAAA,IACd;AAAA,EACF;AAEA,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,UAAU,QAAQ;AAAA,IAClB,kBAAkB,UAAU,eAAe,QAAQ,aAAa,MAAM;AAAA,IACtE;AAAA,EACF;AAEA,mBAAiB,KAAK;AACxB;AAKO,IAAM,wBAAwB,CACnC,QACA,UACA,QACA,SACA,YAKS;AACT,QAAM,eAA0D;AAAA,IAC9D;AAAA,IACA,GAAI,SAAS,cAAc,SAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,IAC3E,GAAI,SAAS,cAAc,SAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,IAC3E,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG,SAAS;AAAA,IACd;AAAA,EACF;AAEA,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,UAAU,QAAQ;AAAA,IAClB,iBAAiB,UAAU,YAAY,QAAQ,aAAa,MAAM,OAAO,QAAQ,IAAI,MAAM;AAAA,IAC3F;AAAA,EACF;AAEA,mBAAiB,KAAK;AACxB;AAKO,IAAM,qBAAqB,CAChC,QACA,YACA,WACA,UACA,YAKS;AACT,QAAM,eAA0D;AAAA,IAC9D;AAAA,IACA,GAAI,SAAS,cAAc,SAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,IAC3E,GAAI,SAAS,cAAc,SAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,IAC3E,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG,SAAS;AAAA,IACd;AAAA,EACF;AAEA,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,cAAc,WAAW,WAAW;AAAA,IACpC,gBAAgB,SAAS,OAAO,UAAU,GAAG,WAAW,KAAK,QAAQ,MAAM,EAAE,YAAY,MAAM;AAAA,IAC/F;AAAA,EACF;AAEA,mBAAiB,KAAK;AACxB;AAKO,IAAM,gBAAgB,CAAC,WAAoC,aAAa,QAAQ,EAAE,OAAO,CAAC;AAK1F,IAAM,sBAAsB,CAAC,aAClC,aAAa,QAAQ,EAAE,SAAS,CAAC;AAK5B,IAAM,uBAAuB,CAAC,OAAa,QAChD,aAAa,QAAQ,EAAE,WAAW,EAAE,OAAO,IAAI,EAAE,CAAC;AAM7C,IAAM,4BAA4B;AAAA;AAAA,EAEvC,UAAU;AAAA,EACV,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA,WAAW;AAAA;AAAA,EAGX,YAAY;AAAA;AAAA,EAGZ;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA,WAAW;AAAA;AAAA,EAGX,aAAa;AAAA,EACb,aAAa;AAAA,EACb;AAAA,EACA,kBAAkB;AACpB;;;ACraA,SAA2B,oBAAoB;AAC/C,SAAS,cAAAG,mBAAkB;AAE3B,eAAe,mBAAmB;AAChC,SAAO,EAAE,QAAQ,QAAe;AAClC;AAEA,IAAM,SAAS;AAAA,EACb,MAAM,CAAC,YAAoB,SAAoB,QAAQ,IAAI,qBAAqB,OAAO,IAAI,GAAG,IAAI;AAAA,EAClG,MAAM,CAAC,YAAoB,SAAoB,QAAQ,KAAK,qBAAqB,OAAO,IAAI,GAAG,IAAI;AAAA,EACnG,OAAO,CAAC,YAAoB,SAAoB,QAAQ,MAAM,qBAAqB,OAAO,IAAI,GAAG,IAAI;AACvG;AAIA,eAAsB,mBAAmB,KAAqD;AAC5F,QAAM,WAAW,IAAI,aAAa;AAElC,MAAI;AACF,UAAM,UAAU,MAAM,iBAAiB;AACvC,YAAQ,OAAO,KAAK,mCAAmC,IAAI,MAAM,IAAI,IAAI,GAAG,EAAE;AAAA,EAChF,QAAQ;AACN,WAAO,KAAK,mCAAmC,IAAI,MAAM,IAAI,IAAI,GAAG,EAAE;AAAA,EACxE;AAGA,WAAS,QAAQ,IAAI,0BAA0B,SAAS;AACxD,WAAS,QAAQ,IAAI,mBAAmB,MAAM;AAC9C,WAAS,QAAQ,IAAI,oBAAoB,eAAe;AACxD,WAAS,QAAQ,IAAI,mBAAmB,iCAAiC;AACzE,WAAS,QAAQ,IAAI,6BAA6B,qCAAqC;AAGvF,QAAM,aAAa,IAAI,QAAQ,SAAS,WAAW,MAAM;AACzD,QAAM,MAAM,aACR,4FACA;AACJ,WAAS,QAAQ,IAAI,2BAA2B,GAAG;AAEnD,MAAI;AACF,UAAM,UAAU,MAAM,iBAAiB;AACvC,YAAQ,OAAO,KAAK,+BAA+B;AAAA,EACrD,QAAQ;AACN,WAAO,KAAK,+BAA+B;AAAA,EAC7C;AAGA;AACF;AAGO,SAAS,eAAe,QAG5B;AACD,SAAO;AAAA,IACL,kBAAkB,WAA2B;AAE3C,aAAOA,YAAW,UAAU,OAAO,UAAU,EAAE,OAAO,SAAS,EAAE,OAAO,KAAK;AAAA,IAC/E;AAAA,IACA,eAAe,KAAsB;AACnC,aAAO,KAAK,IAAI,IAAI,MAAO;AAAA,IAC7B;AAAA,IACA,uBAA+B;AAC7B,aAAO,OAAO,YAAY;AAAA,IAC5B;AAAA,IACA,wBAAgC;AAC9B,aAAO,OAAO,YAAY;AAAA,IAC5B;AAAA,EACF;AACF;;;ACtEA,IAAMC,UAAS;AAAA,EACb,MAAM,CAAC,YAAoB,SAAoB,QAAQ,IAAI,oBAAoB,OAAO,IAAI,GAAG,IAAI;AAAA,EACjG,MAAM,CAAC,YAAoB,SAAoB,QAAQ,KAAK,oBAAoB,OAAO,IAAI,GAAG,IAAI;AAAA,EAClG,OAAO,CAAC,YAAoB,SAAoB,QAAQ,MAAM,oBAAoB,OAAO,IAAI,GAAG,IAAI;AACtG;AAEA,IAAMC,aAAY;AAAA,EAChB,MAAM,IAAI,SAAoBD,QAAO,KAAK,OAAO,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,EAC3E,MAAM,IAAI,SAAoBA,QAAO,KAAK,OAAO,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,EAC3E,OAAO,IAAI,SAAoBA,QAAO,MAAM,OAAO,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,EAC7E,YAAY,CAAC,WAAmB;AAAA,IAC9B,MAAM,IAAI,SAAoBA,QAAO,KAAK,OAAO,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,IAC3E,MAAM,IAAI,SAAoBA,QAAO,KAAK,OAAO,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,IAC3E,OAAO,IAAI,SAAoBA,QAAO,MAAM,OAAO,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,EAC/E;AACF;AAuBA,eAAeE,oBAAyC;AACtD,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,MAAM,IAAI,SAAoBF,QAAO,KAAK,OAAO,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,MAC3E,MAAM,IAAI,SAAoBA,QAAO,KAAK,OAAO,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,MAC3E,OAAO,IAAI,SAAoBA,QAAO,MAAM,OAAO,KAAK,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,IAC/E;AAAA,EACF;AACF;AAEA,SAAS,eAAuB;AAC9B,MAAI,OAAO,WAAW,eAAe,OAAO,YAAY;AACtD,WAAO,OAAO,WAAW;AAAA,EAC3B;AAEA,SAAO,uCAAuC,QAAQ,SAAS,OAAK;AAClE,UAAM,IAAK,KAAK,OAAO,IAAI,KAAM;AACjC,UAAM,IAAI,MAAM,MAAM,IAAK,IAAI,IAAO;AACtC,WAAO,EAAE,SAAS,EAAE;AAAA,EACtB,CAAC;AACH;AAEA,IAAM,oBAAN,MAAwB;AAAA,EAGtB,YAA6B,SAAsB;AAAtB;AAC3B,SAAK,KAAK;AAAA,EACZ;AAAA,EAJiB,WAAW,oBAAI,IAA2B;AAAA,EAMnD,kBAA0B;AAChC,QAAI;AACF,aAAO,aAAa;AAAA,IACtB,QAAQ;AACN,aAAO,WAAW,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC;AAAA,IAC3C;AAAA,EACF;AAAA,EAEQ,cAAsB;AAC5B,QAAI;AACF,aAAO,SAAS,aAAa,CAAC;AAAA,IAChC,QAAQ;AACN,aAAO,SAAS,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,MAA4E;AACvF,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,CAAC,EAAE,SAAS,sBAAsB,MAAM,SAAS,CAAC;AAAA,MAC5D;AAAA,IACF;AAEA,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,UAAyB;AAAA,MAC7B,IAAI,KAAK,MAAM,KAAK,gBAAgB;AAAA,MACpC,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK,SAAS,KAAK,YAAY;AAAA,MACtC,WAAW,KAAK,YACZ,IAAI,KAAK,KAAK,SAAS,IACvB,IAAI,KAAK,IAAI,QAAQ,IAAI,MAAO,KAAK,EAAE;AAAA,MAC3C,cAAc,KAAK,eAAe,IAAI,KAAK,KAAK,YAAY,IAAI;AAAA,MAChE,UAAU,KAAK,YAAY;AAAA,MAC3B,WAAW;AAAA,MACX,WAAW;AAAA,MACX,GAAI,KAAK,WAAW,SAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,IAC7D;AAEA,SAAK,SAAS,IAAI,QAAQ,IAAI,OAAO;AAErC,WAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,EACxC;AAAA,EAEA,MAAM,SAAS,IAAmE;AAChF,UAAM,UAAU,KAAK,SAAS,IAAI,OAAO,EAAE,CAAC;AAC5C,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,CAAC,EAAE,SAAS,qBAAqB,MAAM,WAAW,CAAC;AAAA,MAC7D;AAAA,IACF;AAEA,WAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,EACxC;AAAA,EAEA,MAAM,OAAO,IAAoD;AAC/D,UAAM,MAAM,OAAO,EAAE;AACrB,QAAI,CAAC,KAAK,SAAS,IAAI,GAAG,GAAG;AAC3B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,CAAC,EAAE,SAAS,qBAAqB,MAAM,SAAS,CAAC;AAAA,MAC3D;AAAA,IACF;AAEA,SAAK,SAAS,OAAO,GAAG;AACxB,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,sBAAsB,QAA+C;AACzE,QAAI,UAAU;AACd,eAAW,CAAC,KAAK,OAAO,KAAK,KAAK,SAAS,QAAQ,GAAG;AACpD,UAAI,QAAQ,WAAW,QAAQ;AAC7B,aAAK,SAAS,OAAO,GAAG;AACxB,kBAAU;AAAA,MACZ;AAAA,IACF;AAEA,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,CAAC,EAAE,SAAS,8BAA8B,MAAM,wBAAwB,CAAC;AAAA,MACnF;AAAA,IACF;AAEA,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,UAA0D;AAC9D,WAAO,EAAE,SAAS,MAAM,MAAM,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC,EAAE;AAAA,EACnE;AAAA,EAEA,MAAM,OACJ,IACA,MAC8C;AAC9C,UAAM,WAAW,KAAK,SAAS,IAAI,EAAE;AACrC,QAAI,CAAC,UAAU;AACb,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,CAAC,EAAE,SAAS,qBAAqB,MAAM,SAAS,CAAC;AAAA,MAC3D;AAAA,IACF;AAEA,UAAM,UAAyB;AAAA,MAC7B,GAAG;AAAA,MACH,GAAI,KAAK,WAAW,SAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,MAC3D,GAAI,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,MACxD,GAAI,KAAK,WAAW,SAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,MAC3D,GAAI,KAAK,cAAc,SAAY,EAAE,WAAW,IAAI,KAAK,KAAK,SAAS,EAAE,IAAI,CAAC;AAAA,MAC9E,GAAI,KAAK,iBAAiB,SAAY,EAAE,cAAc,IAAI,KAAK,KAAK,YAAY,EAAE,IAAI,CAAC;AAAA,MACvF,GAAI,KAAK,aAAa,SAAY,EAAE,UAAU,KAAK,SAAS,IAAI,CAAC;AAAA,MACjE,WAAW,oBAAI,KAAK;AAAA,IACtB;AAEA,SAAK,SAAS,IAAI,IAAI,OAAO;AAC7B,WAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,EACxC;AACF;AAiBO,IAAM,iBAAN,MAAqB;AAAA,EAClB,aAAuC;AAAA,EAE/C,YAAY,YAAgC;AAC1C,QAAI,YAAY;AACd,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAc,gBAA4C;AACxD,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,UAAU,MAAME,kBAAiB;AACvC,WAAK,aAAa,IAAI,kBAAkB,OAAO;AAAA,IACjD;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,MAA4E;AAC9F,QAAI,CAAC,KAAK,UAAU,OAAO,KAAK,WAAW,UAAU;AACnD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,UACN;AAAA,YACE,SAAS;AAAA,YACT,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,UAAM,aAAa,MAAM,KAAK,cAAc;AAC5C,UAAM,SAAS,MAAM,WAAW,OAAO,IAAI;AAC3C,QAAI,CAAC,OAAO,SAAS;AACnB,UAAI;AACF,cAAM,UAAU,MAAMA,kBAAiB;AACvC,gBAAQ,OAAO,MAAM,4BAA4B;AAAA,UAC/C,QAAQ,OAAO;AAAA,QACjB,CAAC;AAAA,MACH,QAAQ;AACN,QAAAD,WAAU,MAAM,4BAA4B,EAAE,QAAQ,OAAO,OAAO,CAAC;AAAA,MACvE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,WAA+D;AACnF,QAAI;AACF,YAAM,aAAa,MAAM,KAAK,cAAc;AAC5C,YAAM,SAAS,MAAM,WAAW,SAAS,SAAS;AAElD,UAAI,CAAC,OAAO,WAAW,CAAC,OAAO,MAAM;AACnC,YAAI;AACF,gBAAM,UAAU,MAAMC,kBAAiB;AACvC,kBAAQ,OAAO,KAAK,mBAAmB,EAAE,WAAW,QAAQ,OAAO,OAAO,CAAC;AAAA,QAC7E,QAAQ;AACN,UAAAD,WAAU,KAAK,mBAAmB,EAAE,WAAW,QAAQ,OAAO,OAAO,CAAC;AAAA,QACxE;AACA,eAAO;AAAA,UACL,SAAS;AAAA,UACT,QAAQ,OAAO,UAAU,CAAC,EAAE,SAAS,qBAAqB,MAAM,kBAAkB,CAAC;AAAA,QACrF;AAAA,MACF;AAEA,YAAM,UAAU,OAAO;AACvB,UAAI,QAAQ,UAAU,QAAQ,IAAI,KAAK,IAAI,GAAG;AAC5C,cAAM,WAAW,OAAO,SAAS;AACjC,YAAI;AACF,gBAAM,UAAU,MAAMC,kBAAiB;AACvC,kBAAQ,OAAO,KAAK,+BAA+B,EAAE,UAAU,CAAC;AAAA,QAClE,QAAQ;AACN,UAAAD,WAAU,KAAK,+BAA+B,EAAE,UAAU,CAAC;AAAA,QAC7D;AAEA,eAAO;AAAA,UACL,SAAS;AAAA,UACT,QAAQ,CAAC,EAAE,SAAS,mBAAmB,MAAM,kBAAkB,CAAC;AAAA,QAClE;AAAA,MACF;AAGA,YAAM,aAAa,EAAE,SAAS,MAAM,MAAM,EAAE,IAAI,QAAQ,OAAO,EAAE;AACjE,UAAI,CAAC,WAAW,WAAW,CAAC,WAAW,MAAM;AAC3C,YAAI;AACF,gBAAM,UAAU,MAAMC,kBAAiB;AACvC,kBAAQ,OAAO,MAAM,8BAA8B;AAAA,YACjD;AAAA,YACA,QAAQ,QAAQ;AAAA,UAClB,CAAC;AAAA,QACH,QAAQ;AACN,UAAAD,WAAU,MAAM,8BAA8B;AAAA,YAC5C;AAAA,YACA,QAAQ,QAAQ;AAAA,UAClB,CAAC;AAAA,QACH;AACA,eAAO;AAAA,UACL,SAAS;AAAA,UACT,QAAQ,CAAC,EAAE,SAAS,8BAA8B,MAAM,kBAAkB,CAAC;AAAA,QAC7E;AAAA,MACF;AAEA,aAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,IACxC,SAAS,OAAO;AACd,UAAI;AACF,cAAM,UAAU,MAAMC,kBAAiB;AACvC,gBAAQ,OAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC;AAAA,MAC7D,QAAQ;AACN,QAAAD,WAAU,MAAM,6BAA6B,EAAE,MAAM,CAAC;AAAA,MACxD;AACA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,CAAC,EAAE,SAAS,6BAA6B,MAAM,kBAAkB,CAAC;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,WAAkD;AACxE,QAAI;AACF,YAAM,aAAa,MAAM,KAAK,cAAc;AAC5C,YAAM,SAAS,MAAM,WAAW,OAAO,SAAS;AAChD,UAAI,CAAC,OAAO,SAAS;AACnB,YAAI;AACF,gBAAM,UAAU,MAAMC,kBAAiB;AACvC,kBAAQ,OAAO,MAAM,+BAA+B;AAAA,YAClD,QAAQ,OAAO;AAAA,UACjB,CAAC;AAAA,QACH,QAAQ;AACN,UAAAD,WAAU,MAAM,+BAA+B;AAAA,YAC7C,QAAQ,OAAO;AAAA,UACjB,CAAC;AAAA,QACH;AACA,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI;AACF,cAAM,UAAU,MAAMC,kBAAiB;AACvC,gBAAQ,OAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC;AAAA,MAC/D,QAAQ;AACN,QAAAD,WAAU,MAAM,+BAA+B,EAAE,MAAM,CAAC;AAAA,MAC1D;AACA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,UACN;AAAA,YACE,SAAS;AAAA,YACT,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,0BAA0B,QAA+C;AAC7E,QAAI;AACF,YAAM,aAAa,MAAM,KAAK,cAAc;AAC5C,YAAM,SAAS,MAAM,WAAW,sBAAsB,MAAM;AAC5D,UAAI,CAAC,OAAO,SAAS;AACnB,YAAI;AACF,gBAAM,UAAU,MAAMC,kBAAiB;AACvC,kBAAQ,OAAO,MAAM,qCAAqC;AAAA,YACxD,QAAQ,OAAO;AAAA,UACjB,CAAC;AAAA,QACH,QAAQ;AACN,UAAAD,WAAU,MAAM,qCAAqC;AAAA,YACnD,QAAQ,OAAO;AAAA,UACjB,CAAC;AAAA,QACH;AACA,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI;AACF,cAAM,UAAU,MAAMC,kBAAiB;AACvC,gBAAQ,OAAO,MAAM,qCAAqC;AAAA,UACxD;AAAA,QACF,CAAC;AAAA,MACH,QAAQ;AACN,QAAAD,WAAU,MAAM,qCAAqC,EAAE,MAAM,CAAC;AAAA,MAChE;AACA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,UACN;AAAA,YACE,SAAS;AAAA,YACT,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,IAA0D;AAC7E,UAAM,aAAa,MAAM,KAAK,cAAc;AAC5C,UAAM,SAAS,MAAM,WAAW,SAAS,EAAE;AAC3C,QAAI,CAAC,OAAO,SAAS;AACnB,UAAI;AACF,cAAM,UAAU,MAAMC,kBAAiB;AACvC,gBAAQ,OAAO,KAAK,qBAAqB;AAAA,UACvC,QAAQ,OAAO;AAAA,QACjB,CAAC;AAAA,MACH,QAAQ;AACN,QAAAD,WAAU,KAAK,qBAAqB,EAAE,QAAQ,OAAO,OAAO,CAAC;AAAA,MAC/D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,iBAAiE;AACrE,UAAM,aAAa,MAAM,KAAK,cAAc;AAC5C,UAAM,SAAS,MAAM,WAAW,QAAQ;AACxC,QAAI,CAAC,OAAO,SAAS;AACnB,UAAI;AACF,cAAM,UAAU,MAAMC,kBAAiB;AACvC,gBAAQ,OAAO,MAAM,4BAA4B;AAAA,UAC/C,QAAQ,OAAO;AAAA,QACjB,CAAC;AAAA,MACH,QAAQ;AACN,QAAAD,WAAU,MAAM,4BAA4B;AAAA,UAC1C,QAAQ,OAAO;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cACJ,IACA,MAC8C;AAC9C,UAAM,aAAa,MAAM,KAAK,cAAc;AAC5C,UAAM,SAAS,MAAM,WAAW,OAAO,IAAI,IAAI;AAC/C,QAAI,CAAC,OAAO,SAAS;AACnB,UAAI;AACF,cAAM,UAAU,MAAMC,kBAAiB;AACvC,gBAAQ,OAAO,MAAM,4BAA4B;AAAA,UAC/C,QAAQ,OAAO;AAAA,QACjB,CAAC;AAAA,MACH,QAAQ;AACN,QAAAD,WAAU,MAAM,4BAA4B,EAAE,QAAQ,OAAO,OAAO,CAAC;AAAA,MACvE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,IAA2C;AAC7D,UAAM,aAAa,MAAM,KAAK,cAAc;AAC5C,UAAM,SAAS,MAAM,WAAW,OAAO,EAAE;AACzC,QAAI,CAAC,OAAO,SAAS;AACnB,UAAI;AACF,cAAM,UAAU,MAAMC,kBAAiB;AACvC,gBAAQ,OAAO,MAAM,4BAA4B;AAAA,UAC/C,QAAQ,OAAO;AAAA,QACjB,CAAC;AAAA,MACH,QAAQ;AACN,QAAAD,WAAU,MAAM,4BAA4B,EAAE,QAAQ,OAAO,OAAO,CAAC;AAAA,MACvE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAEO,IAAM,iBAAiB,IAAI,eAAe;;;AC1djD,SAAS,yBAAAE,8BAA6B;AAGtC,IAAM,WAAN,cAAuB,MAAM;AAAA,EAC3B,YACS,MACP,SACO,OACP;AACA,UAAM,OAAO;AAJN;AAEA;AAGP,SAAK,OAAO;AACZ,QAAI,OAAO;AACT,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AACF;AAEA,IAAM,YAAY;AAAA,EAChB,eAAe;AAAA,EACf,eAAe;AAAA,EACf,sBAAsB;AAAA,EACtB,gBAAgB;AAClB;AAYO,IAAM,eAAN,cAA2BA,uBAAsB;AAAA,EACtD,YAA+B,SAAkB;AAC/C,UAAM,SAAS,cAAc;AADA;AAAA,EAE/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAM,aAAkD,KAAsB;AAClF,QAAI;AACF,WAAK,OAAO,MAAM,yBAAyB;AAAA,QACzC,OAAO,YAAY;AAAA,QACnB,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAED,YAAM,SAAS,MAAM,KAAK,QAAQ,MAAM;AAAA,QACtC,YAAY;AAAA,QACZ,MAAM;AAAA,UACJ,OAAO,YAAY;AAAA,UACnB,UAAU,YAAY;AAAA,QACxB;AAAA,QACA,GAAI,OAAO,EAAE,IAAI;AAAA,MACnB,CAAC;AAED,WAAK,OAAO,KAAK,yBAAyB;AAAA,QACxC,QAAQ,OAAO,KAAK;AAAA,QACpB,OAAO,OAAO,KAAK;AAAA,QACnB,aAAa,KAAK;AAAA,MACpB,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,qBAAqB;AAAA,QACrC,OAAO,YAAY;AAAA,QACnB,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAChD,aAAa,KAAK;AAAA,MACpB,CAAC;AACD,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAW,QAAyB;AACxC,QAAI;AACF,WAAK,OAAO,MAAM,kBAAkB;AAAA,QAClC;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAGD,YAAM,OAAO,MAAM,KAAK,QAAQ,SAAS;AAAA,QACvC,YAAY;AAAA,QACZ,IAAI;AAAA,MACN,CAAC;AAED,WAAK,OAAO,MAAM,gCAAgC;AAAA,QAChD,QAAQ,KAAK;AAAA,QACb,aAAa,KAAK;AAAA,MACpB,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,4BAA4B;AAAA,QAC5C;AAAA,QACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAChD,aAAa,KAAK;AAAA,MACpB,CAAC;AACD,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,2BAA2B,OAAe;AAC9C,QAAI;AACF,WAAK,OAAO,MAAM,mCAAmC;AAAA,QACnD;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAED,YAAM,QAAQ,MAAM,KAAK,QAAQ,eAAe;AAAA,QAC9C,YAAY;AAAA,QACZ,MAAM,EAAE,MAAM;AAAA,MAChB,CAAC;AAED,WAAK,OAAO,KAAK,kCAAkC;AAAA,QACjD;AAAA,QACA,aAAa,KAAK;AAAA,MACpB,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,0CAA0C;AAAA,QAC1D;AAAA,QACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAChD,aAAa,KAAK;AAAA,MACpB,CAAC;AACD,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,cAAc,OAAe,aAAqB;AACtD,QAAI;AACF,WAAK,OAAO,MAAM,sBAAsB;AAAA,QACtC,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAED,YAAM,SAAS,MAAM,KAAK,QAAQ,cAAc;AAAA,QAC9C,YAAY;AAAA,QACZ,MAAM;AAAA,UACJ;AAAA,UACA,UAAU;AAAA,QACZ;AAAA,QACA,gBAAgB;AAAA;AAAA,MAClB,CAAC;AAED,WAAK,OAAO,KAAK,6BAA6B;AAAA,QAC5C,QAAQ,OAAO,MAAM;AAAA,QACrB,aAAa,KAAK;AAAA,MACpB,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,yBAAyB;AAAA,QACzC,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAChD,aAAa,KAAK;AAAA,MACpB,CAAC;AACD,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,YAAY,OAAe;AAC/B,QAAI;AACF,WAAK,OAAO,MAAM,mBAAmB;AAAA,QACnC,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAED,YAAM,SAAS,MAAM,KAAK,QAAQ,YAAY;AAAA,QAC5C,YAAY;AAAA,QACZ;AAAA,MACF,CAAC;AAED,WAAK,OAAO,KAAK,gCAAgC;AAAA,QAC/C,SAAS;AAAA,QACT,aAAa,KAAK;AAAA,MACpB,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,6BAA6B;AAAA,QAC7C,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAChD,aAAa,KAAK;AAAA,MACpB,CAAC;AACD,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,WAAW,OAAe,UAAkB;AAChD,QAAI;AACF,WAAK,OAAO,MAAM,0BAA0B;AAAA,QAC1C;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,WAAW;AAAA,MACb,CAAC;AAED,YAAM,SAAS,MAAM,KAAK,QAAQ,OAAO;AAAA,QACvC,YAAY;AAAA,QACZ,MAAM,EAAE,OAAO,SAAS;AAAA,QACxB,gBAAgB;AAAA;AAAA,MAClB,CAAC;AAED,WAAK,OAAO,KAAK,iCAAiC;AAAA,QAChD;AAAA,QACA,SAAS;AAAA,QACT,aAAa,KAAK;AAAA,MACpB,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,8BAA8B;AAAA,QAC9C;AAAA,QACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAChD,aAAa,KAAK;AAAA,MACpB,CAAC;AACD,YAAM,IAAI;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKU,eAAqB;AAC7B,SAAK,OAAO,KAAK,wDAAwD;AAAA,MACvE,aAAa,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKU,YAAkB;AAE1B,SAAK,OAAO,KAAK,2BAA2B;AAAA,MAC1C,aAAa,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKU,gBAAsB;AAE9B,SAAK,OAAO,MAAM,oCAAoC;AAAA,MACpD,aAAa,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AACF;AAGO,SAAS,mBAAmB,SAAgC;AACjE,SAAO,IAAI,aAAa,OAAO;AACjC;","names":["RATE_LIMITS","generateRateLimitKey","generateIPRateLimitKey","checkRateLimit","randomBytes","devLogger","events","event","createHmac","logger","devLogger","getPayloadClient","InfrastructureService"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@revealui/security",
|
|
3
|
+
"version": "0.0.1-pre.0",
|
|
4
|
+
"description": "Security services including rate limiting, encryption, CSRF protection, and token management",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"security",
|
|
11
|
+
"rate-limiting",
|
|
12
|
+
"encryption",
|
|
13
|
+
"csrf",
|
|
14
|
+
"tokens",
|
|
15
|
+
"authentication",
|
|
16
|
+
"authorization"
|
|
17
|
+
],
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"publishable": true,
|
|
20
|
+
"author": "RevealUI Team",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/RevealUIStudio/reveal.git",
|
|
24
|
+
"directory": "packages/security"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/RevealUIStudio/reveal/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://revealui.com",
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@revealui/core": "^0.0.1-pre.0",
|
|
35
|
+
"zod": "^4.1.13"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"next": "^16.0.0",
|
|
39
|
+
"payload": "^3.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"typescript": "^5.9.3",
|
|
43
|
+
"vitest": "^4.0.14",
|
|
44
|
+
"rimraf": "^6.1.2"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=22.0.0"
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"dist",
|
|
51
|
+
"README.md",
|
|
52
|
+
"LICENSE"
|
|
53
|
+
],
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "pnpm exec tsup",
|
|
56
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
57
|
+
"clean": "rm -rf dist",
|
|
58
|
+
"test": "vitest run"
|
|
59
|
+
}
|
|
60
|
+
}
|