@drmhse/sso-sdk 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/dist/index.d.mts +4598 -4465
- package/dist/index.d.mts.map +1 -0
- package/dist/index.d.ts +4598 -4465
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4554 -4979
- package/dist/index.mjs +4539 -4937
- package/dist/index.mjs.map +1 -0
- package/package.json +5 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/errors.ts","../src/http.ts","../src/session.ts","../src/storage.ts","../src/modules/analytics.ts","../src/modules/auth.ts","../src/modules/user.ts","../src/modules/organizations/audit.ts","../src/modules/organizations/webhooks.ts","../src/modules/organizations/upstream-providers.ts","../src/modules/organizations.ts","../src/modules/services.ts","../src/modules/invitations.ts","../src/modules/platform.ts","../src/modules/serviceApi.ts","../src/modules/permissions.ts","../src/modules/passkeys.ts","../src/modules/magic.ts","../src/modules/privacy.ts","../src/client.ts"],"sourcesContent":["/**\n * Standard authentication error codes returned by the AuthOS API.\n * Use these to reliably switch UI states based on error type.\n */\nexport enum AuthErrorCodes {\n /** Multi-factor authentication is required to complete login */\n MFA_REQUIRED = 'MFA_REQUIRED',\n /** User must select or create an organization */\n ORG_REQUIRED = 'ORG_REQUIRED',\n /** The provided credentials are invalid */\n INVALID_CREDENTIALS = 'INVALID_CREDENTIALS',\n /** The refresh token is invalid or has been revoked */\n REFRESH_TOKEN_INVALID = 'REFRESH_TOKEN_INVALID',\n /** The requested resource was not found */\n NOT_FOUND = 'NOT_FOUND',\n /** The user is not authorized to perform this action */\n UNAUTHORIZED = 'UNAUTHORIZED',\n /** The user does not have permission for this resource */\n FORBIDDEN = 'FORBIDDEN',\n /** The JWT token has expired */\n TOKEN_EXPIRED = 'TOKEN_EXPIRED',\n /** The request failed validation */\n VALIDATION_ERROR = 'VALIDATION_ERROR',\n /** The email address is already registered */\n EMAIL_ALREADY_EXISTS = 'EMAIL_ALREADY_EXISTS',\n /** Email verification is required */\n EMAIL_NOT_VERIFIED = 'EMAIL_NOT_VERIFIED',\n /** The account has been suspended */\n ACCOUNT_SUSPENDED = 'ACCOUNT_SUSPENDED',\n /** The organization has been suspended */\n ORG_SUSPENDED = 'ORG_SUSPENDED',\n /** The request failed validation or is malformed */\n BAD_REQUEST = 'BAD_REQUEST',\n /** A resource with this information already exists */\n DUPLICATE_CONSTRAINT = 'DUPLICATE_CONSTRAINT',\n /** Organization is pending approval or suspended */\n ORGANIZATION_NOT_ACTIVE = 'ORGANIZATION_NOT_ACTIVE',\n /** Service creation limit reached for organization tier */\n SERVICE_LIMIT_EXCEEDED = 'SERVICE_LIMIT_EXCEEDED',\n /** Team member limit reached for organization tier */\n TEAM_LIMIT_EXCEEDED = 'TEAM_LIMIT_EXCEEDED',\n /** Invitation link has expired */\n INVITATION_EXPIRED = 'INVITATION_EXPIRED',\n /** The magic link or verification token has expired */\n LINK_EXPIRED = 'LINK_EXPIRED',\n /** Device code for headless authentication has expired */\n DEVICE_CODE_EXPIRED = 'DEVICE_CODE_EXPIRED',\n /** Authorization is still pending (device flow) */\n AUTHORIZATION_PENDING = 'AUTHORIZATION_PENDING',\n DEVICE_CODE_PENDING = 'DEVICE_CODE_PENDING',\n /** Feature not available in organization's current tier */\n FEATURE_NOT_AVAILABLE_IN_TIER = 'FEATURE_NOT_AVAILABLE_IN_TIER',\n /** Rate limit exceeded */\n RATE_LIMITED = 'RATE_LIMITED',\n TOO_MANY_REQUESTS = 'TOO_MANY_REQUESTS',\n /** The password does not meet requirements */\n WEAK_PASSWORD = 'WEAK_PASSWORD',\n /** The MFA code is invalid */\n INVALID_MFA_CODE = 'INVALID_MFA_CODE',\n /** Malformed or invalid JWT token */\n JWT_ERROR = 'JWT_ERROR',\n /** Unexpected server error */\n INTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR',\n /** OAuth provider communication failed */\n OAUTH_ERROR = 'OAUTH_ERROR',\n /** The passkey authentication failed */\n PASSKEY_ERROR = 'PASSKEY_ERROR',\n /** Billing system error */\n STRIPE_ERROR = 'STRIPE_ERROR',\n /** General database operation failed */\n DATABASE_ERROR = 'DATABASE_ERROR',\n /** General system error */\n GENERIC_ERROR = 'GENERIC_ERROR',\n}\n\n/**\n * Custom error class for SSO API errors.\n * Provides structured error information from the API.\n */\nexport class SsoApiError extends Error {\n /**\n * The HTTP status code of the error response.\n */\n public readonly statusCode: number;\n\n /**\n * The specific error code returned by the API.\n */\n public readonly errorCode: string;\n\n /**\n * ISO 8601 timestamp when the error occurred.\n */\n public readonly timestamp: string;\n\n constructor(message: string, statusCode: number, errorCode: string, timestamp: string) {\n super(message);\n this.name = 'SsoApiError';\n this.statusCode = statusCode;\n this.errorCode = errorCode;\n this.timestamp = timestamp;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, SsoApiError);\n }\n }\n\n /**\n * Check if the error is a specific error code.\n */\n public is(errorCode: string): boolean {\n return this.errorCode === errorCode;\n }\n\n /**\n * Check if the error is an authentication error.\n */\n public isAuthError(): boolean {\n return this.statusCode === 401 || this.errorCode === 'UNAUTHORIZED' || this.errorCode === 'TOKEN_EXPIRED';\n }\n\n /**\n * Check if the error is a permission error.\n */\n public isForbidden(): boolean {\n return this.statusCode === 403 || this.errorCode === 'FORBIDDEN';\n }\n\n /**\n * Check if the error is a not found error.\n */\n public isNotFound(): boolean {\n return this.statusCode === 404 || this.errorCode === 'NOT_FOUND';\n }\n}\n","import { SsoApiError } from './errors';\nimport { SessionManager } from './session';\n\n/**\n * HTTP request options\n */\ninterface RequestOptions {\n method: string;\n headers?: Record<string, string>;\n body?: any;\n params?: Record<string, any>;\n timeout?: number;\n _retry?: boolean;\n}\n\n/**\n * HTTP response wrapper\n */\ninterface HttpResponse<T = any> {\n data: T;\n status: number;\n headers: Headers;\n}\n\n/**\n * HTTP client defaults\n */\ninterface HttpDefaults {\n baseURL: string;\n headers: {\n common: Record<string, string>;\n };\n timeout: number;\n}\n\n/**\n * Custom HTTP client using native fetch API.\n * Provides an interface similar to Axios for easy migration.\n */\nexport class HttpClient {\n public defaults: HttpDefaults;\n private sessionManager?: SessionManager;\n\n constructor(baseURL: string) {\n this.defaults = {\n baseURL,\n headers: {\n common: {\n 'Content-Type': 'application/json',\n },\n },\n timeout: 30000,\n };\n }\n\n /**\n * Allow injecting session manager after construction to avoid circular dep\n */\n public setSessionManager(manager: SessionManager) {\n this.sessionManager = manager;\n }\n\n /**\n * Build query string from params object\n */\n private buildQueryString(params?: Record<string, any>): string {\n if (!params) return '';\n\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n\n const queryString = searchParams.toString();\n return queryString ? `?${queryString}` : '';\n }\n\n /**\n * Build full URL from path and params\n */\n private buildUrl(path: string, params?: Record<string, any>): string {\n const baseUrl = this.defaults.baseURL.replace(/\\/$/, '');\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n const queryString = this.buildQueryString(params);\n return `${baseUrl}${cleanPath}${queryString}`;\n }\n\n /**\n * Make HTTP request with timeout support\n */\n private async request<T = any>(path: string, options: RequestOptions): Promise<HttpResponse<T>> {\n const url = this.buildUrl(path, options.params);\n const timeout = options.timeout ?? this.defaults.timeout;\n\n // Merge headers\n const headers = {\n ...this.defaults.headers.common,\n ...options.headers,\n };\n\n // Auto-inject token\n if (this.sessionManager) {\n const token = await this.sessionManager.getToken();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n }\n\n\n\n // Setup abort controller for timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method: options.method,\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Automatic Token Refresh Logic\n if (\n response.status === 401 &&\n this.sessionManager &&\n !options._retry &&\n !path.includes('/auth/login') &&\n !path.includes('/auth/refresh')\n ) {\n try {\n const newToken = await this.sessionManager.refreshSession();\n // Retry original request with new token\n return this.request<T>(path, {\n ...options,\n _retry: true,\n headers: { ...options.headers, Authorization: `Bearer ${newToken}` },\n });\n } catch (refreshError) {\n // Refresh failed, session is already cleared by manager, proceed to throw original 401\n }\n }\n\n // Parse response body\n let data: any;\n const contentType = response.headers.get('content-type');\n\n if (contentType?.includes('application/json')) {\n data = await response.json();\n } else {\n const text = await response.text();\n data = text || undefined;\n }\n\n // Handle error responses\n if (!response.ok) {\n if (data && data.error_code && data.error && data.timestamp) {\n throw new SsoApiError(data.error, response.status, data.error_code, data.timestamp);\n }\n\n // Fallback error\n throw new SsoApiError(\n data?.message || `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n 'UNKNOWN_ERROR',\n new Date().toISOString()\n );\n }\n\n return {\n data,\n status: response.status,\n headers: response.headers,\n };\n } catch (error: any) {\n clearTimeout(timeoutId);\n\n // Handle timeout\n if (error.name === 'AbortError') {\n throw new SsoApiError('Request timeout', 408, 'TIMEOUT', new Date().toISOString());\n }\n\n // Handle network errors\n if (error instanceof TypeError && error.message.includes('fetch')) {\n throw new SsoApiError(\n 'Network error - unable to reach the server',\n 0,\n 'NETWORK_ERROR',\n new Date().toISOString()\n );\n }\n\n // Re-throw SsoApiError\n if (error instanceof SsoApiError) {\n throw error;\n }\n\n // Wrap any other errors\n throw new SsoApiError(\n error.message || 'An unexpected error occurred',\n 500,\n 'UNKNOWN_ERROR',\n new Date().toISOString()\n );\n }\n }\n\n /**\n * GET request\n */\n public async get<T = any>(\n path: string,\n config?: { params?: Record<string, any>; headers?: Record<string, string> }\n ): Promise<HttpResponse<T>> {\n return this.request<T>(path, {\n method: 'GET',\n params: config?.params,\n headers: config?.headers,\n });\n }\n\n /**\n * POST request\n */\n public async post<T = any>(\n path: string,\n data?: any,\n config?: { headers?: Record<string, string> }\n ): Promise<HttpResponse<T>> {\n return this.request<T>(path, {\n method: 'POST',\n body: data,\n headers: config?.headers,\n });\n }\n\n /**\n * PUT request\n */\n public async put<T = any>(\n path: string,\n data?: any,\n config?: { headers?: Record<string, string> }\n ): Promise<HttpResponse<T>> {\n return this.request<T>(path, {\n method: 'PUT',\n body: data,\n headers: config?.headers,\n });\n }\n\n /**\n * PATCH request\n */\n public async patch<T = any>(\n path: string,\n data?: any,\n config?: { headers?: Record<string, string> }\n ): Promise<HttpResponse<T>> {\n return this.request<T>(path, {\n method: 'PATCH',\n body: data,\n headers: config?.headers,\n });\n }\n\n /**\n * DELETE request\n */\n public async delete<T = any>(\n path: string,\n data?: any,\n config?: { headers?: Record<string, string> }\n ): Promise<HttpResponse<T>> {\n const requestConfig =\n data && typeof data === 'object' && 'headers' in data && !config\n ? data\n : config;\n const body = requestConfig === data ? undefined : data;\n\n return this.request<T>(path, {\n method: 'DELETE',\n body,\n headers: requestConfig?.headers,\n });\n }\n}\n\n/**\n * Creates a configured HTTP client instance.\n * @param baseURL The base URL of the SSO API service\n * @returns Configured HTTP client instance\n */\nexport function createHttpAgent(baseURL: string): HttpClient {\n return new HttpClient(baseURL);\n}\n","import { TokenStorage } from './storage';\nimport { RefreshTokenResponse } from './types';\n\ninterface SessionConfig {\n storageKeyPrefix?: string;\n autoRefresh?: boolean;\n minValiditySeconds?: number;\n}\n\n/**\n * Snapshot of the current authentication state.\n * Useful for hydration in SSR frameworks.\n */\nexport interface AuthSnapshot {\n isAuthenticated: boolean;\n token: string | null;\n}\n\nconst DEFAULT_MIN_VALIDITY_SECONDS = 30;\n\nfunction decodeJwtExpiration(token: string): number | null {\n const [, payload] = token.split('.');\n if (!payload) {\n return null;\n }\n\n try {\n const normalized = payload.replace(/-/g, '+').replace(/_/g, '/');\n const padded = normalized.padEnd(normalized.length + ((4 - (normalized.length % 4)) % 4), '=');\n const decoded = globalThis.atob(padded);\n const parsed = JSON.parse(decoded) as { exp?: unknown };\n return typeof parsed.exp === 'number' && Number.isFinite(parsed.exp) ? parsed.exp : null;\n } catch {\n return null;\n }\n}\n\nexport class SessionManager {\n private accessToken: string | null = null;\n private refreshToken: string | null = null;\n private refreshPromise: Promise<string> | null = null;\n private sessionVersion = 0;\n private listeners: Array<(isAuthenticated: boolean) => void> = [];\n\n constructor(\n private storage: TokenStorage,\n private refreshHandler: (token: string) => Promise<RefreshTokenResponse>,\n private config: SessionConfig = { storageKeyPrefix: 'sso_' }\n ) {}\n\n /**\n * Initialize session from storage\n */\n public async loadSession(): Promise<void> {\n const version = this.sessionVersion;\n const accessToken = await this.storage.getItem(`${this.config.storageKeyPrefix}access_token`);\n const refreshToken = await this.storage.getItem(`${this.config.storageKeyPrefix}refresh_token`);\n\n if (version !== this.sessionVersion) {\n return;\n }\n\n this.accessToken = accessToken;\n this.refreshToken = refreshToken;\n }\n\n /**\n * Set the session data (used after login/register)\n */\n public async setSession(tokens: { access_token: string; refresh_token?: string }) {\n this.sessionVersion += 1;\n this.accessToken = tokens.access_token;\n await this.storage.setItem(`${this.config.storageKeyPrefix}access_token`, tokens.access_token);\n\n if (tokens.refresh_token) {\n this.refreshToken = tokens.refresh_token;\n await this.storage.setItem(`${this.config.storageKeyPrefix}refresh_token`, tokens.refresh_token);\n }\n\n this.notifyListeners(true);\n }\n\n /**\n * Clear session (logout)\n */\n public async clearSession() {\n this.sessionVersion += 1;\n this.accessToken = null;\n this.refreshToken = null;\n await this.storage.removeItem(`${this.config.storageKeyPrefix}access_token`);\n await this.storage.removeItem(`${this.config.storageKeyPrefix}refresh_token`);\n this.notifyListeners(false);\n }\n\n /**\n * Get the current access token, refreshing it if necessary/possible\n */\n public async getToken(): Promise<string | null> {\n if (!this.accessToken) {\n return null;\n }\n\n const expiresAt = decodeJwtExpiration(this.accessToken);\n if (expiresAt === null) {\n return this.accessToken;\n }\n\n const secondsUntilExpiry = expiresAt - Math.floor(Date.now() / 1000);\n const minValiditySeconds = this.config.minValiditySeconds ?? DEFAULT_MIN_VALIDITY_SECONDS;\n\n if (secondsUntilExpiry <= 0 && !this.refreshToken) {\n await this.clearSession();\n return null;\n }\n\n if (secondsUntilExpiry <= minValiditySeconds && this.refreshToken) {\n try {\n return await this.refreshSession();\n } catch {\n return null;\n }\n }\n\n return this.accessToken;\n }\n\n /**\n * Handle logic for when a 401 occurs\n */\n public async refreshSession(): Promise<string> {\n if (!this.refreshToken) {\n throw new Error('No refresh token available');\n }\n\n // Deduplicate refresh requests (mutex)\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = (async () => {\n try {\n const tokens = await this.refreshHandler(this.refreshToken!);\n await this.setSession(tokens);\n return tokens.access_token;\n } catch (err) {\n await this.clearSession();\n throw err;\n } finally {\n this.refreshPromise = null;\n }\n })();\n\n return this.refreshPromise;\n }\n\n public isAuthenticated(): boolean {\n return !!this.accessToken;\n }\n\n /**\n * Get a synchronous snapshot of the current auth state.\n * Useful for SSR hydration and initial state.\n */\n public getSnapshot(): AuthSnapshot {\n return {\n isAuthenticated: !!this.accessToken,\n token: this.accessToken,\n };\n }\n\n /**\n * Subscribe to auth state changes (useful for UI updates).\n * The listener is immediately called with the current state upon subscription.\n */\n public subscribe(listener: (isAuthenticated: boolean) => void) {\n this.listeners.push(listener);\n // Emit initial state immediately upon subscription\n listener(this.isAuthenticated());\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n private notifyListeners(isAuth: boolean) {\n this.listeners.forEach((l) => l(isAuth));\n }\n}\n","/**\n * Abstract storage interface for persisting tokens\n */\nexport interface TokenStorage {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\n/**\n * In-memory storage (Default for Node/Server)\n */\nexport class MemoryStorage implements TokenStorage {\n private store = new Map<string, string>();\n\n getItem(key: string) {\n return this.store.get(key) || null;\n }\n\n setItem(key: string, value: string) {\n this.store.set(key, value);\n }\n\n removeItem(key: string) {\n this.store.delete(key);\n }\n}\n\n/**\n * Browser LocalStorage adapter\n */\nexport class BrowserStorage implements TokenStorage {\n getItem(key: string) {\n return typeof window !== 'undefined' ? window.localStorage.getItem(key) : null;\n }\n\n setItem(key: string, value: string) {\n if (typeof window !== 'undefined') window.localStorage.setItem(key, value);\n }\n\n removeItem(key: string) {\n if (typeof window !== 'undefined') window.localStorage.removeItem(key);\n }\n}\n\n/**\n * Browser Cookie adapter for SSR frameworks (Next.js, Nuxt, etc.)\n *\n * Uses document.cookie for client-side access. Works with server-side\n * middleware that can read the same cookies.\n *\n * For Next.js App Router, pair this with cookies() from 'next/headers'\n * in server components to pass the initial token.\n */\nexport class CookieStorage implements TokenStorage {\n constructor(\n private options: {\n domain?: string;\n path?: string;\n secure?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n maxAge?: number; // In seconds\n } = {}\n ) {}\n\n private getCookie(name: string): string | null {\n if (typeof window === 'undefined') return null;\n\n const value = `; ${document.cookie}`;\n const parts = value.split(`; ${name}=`);\n if (parts.length === 2) {\n return parts.pop()?.split(';').shift() || null;\n }\n return null;\n }\n\n private setCookie(name: string, value: string): void {\n if (typeof window === 'undefined') return;\n\n let cookie = `${name}=${value}`;\n\n if (this.options.path) {\n cookie += `; Path=${this.options.path}`;\n }\n\n if (this.options.domain) {\n cookie += `; Domain=${this.options.domain}`;\n }\n\n if (this.options.secure !== false) {\n // Default to secure for auth tokens\n cookie += '; Secure';\n }\n\n if (this.options.sameSite ?? 'lax') {\n cookie += `; SameSite=${this.options.sameSite ?? 'lax'}`;\n }\n\n if (this.options.maxAge) {\n cookie += `; Max-Age=${this.options.maxAge}`;\n }\n\n document.cookie = cookie;\n }\n\n private deleteCookie(name: string): void {\n if (typeof window === 'undefined') return;\n\n let cookie = `${name}=; Expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n\n if (this.options.path) {\n cookie += `; Path=${this.options.path}`;\n }\n\n if (this.options.domain) {\n cookie += `; Domain=${this.options.domain}`;\n }\n\n document.cookie = cookie;\n }\n\n getItem(key: string): string | null {\n return this.getCookie(key);\n }\n\n setItem(key: string, value: string): void {\n this.setCookie(key, value);\n }\n\n removeItem(key: string): void {\n this.deleteCookie(key);\n }\n}\n\n/**\n * Storage Factory\n */\nexport function resolveStorage(userStorage?: TokenStorage): TokenStorage {\n if (userStorage) return userStorage;\n if (typeof window !== 'undefined' && window.localStorage) return new BrowserStorage();\n return new MemoryStorage();\n}\n","import { HttpClient } from '../http';\nimport {\n LoginTrendPoint,\n LoginsByService,\n LoginsByProvider,\n RecentLogin,\n AnalyticsQuery,\n} from '../types';\n\n/**\n * Analytics and login tracking methods\n */\nexport class AnalyticsModule {\n constructor(private http: HttpClient) {}\n\n /**\n * Get login trends over time.\n * Returns daily login counts grouped by date.\n *\n * @param orgSlug Organization slug\n * @param params Optional query parameters (date range)\n * @returns Array of login trend data points\n *\n * @example\n * ```typescript\n * const trends = await sso.analytics.getLoginTrends('acme-corp', {\n * start_date: '2025-01-01',\n * end_date: '2025-01-31'\n * });\n * trends.forEach(point => console.log(point.date, point.count));\n * ```\n */\n public async getLoginTrends(\n orgSlug: string,\n params?: AnalyticsQuery\n ): Promise<LoginTrendPoint[]> {\n const response = await this.http.get<LoginTrendPoint[]>(\n `/api/organizations/${orgSlug}/analytics/login-trends`,\n { params }\n );\n return response.data;\n }\n\n /**\n * Get login counts grouped by service.\n * Shows which services have the most authentication activity.\n *\n * @param orgSlug Organization slug\n * @param params Optional query parameters (date range)\n * @returns Array of login counts per service\n *\n * @example\n * ```typescript\n * const byService = await sso.analytics.getLoginsByService('acme-corp', {\n * start_date: '2025-01-01',\n * end_date: '2025-01-31'\n * });\n * byService.forEach(s => console.log(s.service_name, s.count));\n * ```\n */\n public async getLoginsByService(\n orgSlug: string,\n params?: AnalyticsQuery\n ): Promise<LoginsByService[]> {\n const response = await this.http.get<LoginsByService[]>(\n `/api/organizations/${orgSlug}/analytics/logins-by-service`,\n { params }\n );\n return response.data;\n }\n\n /**\n * Get login counts grouped by OAuth provider.\n * Shows which authentication providers are being used (GitHub, Google, Microsoft).\n *\n * @param orgSlug Organization slug\n * @param params Optional query parameters (date range)\n * @returns Array of login counts per provider\n *\n * @example\n * ```typescript\n * const byProvider = await sso.analytics.getLoginsByProvider('acme-corp', {\n * start_date: '2025-01-01',\n * end_date: '2025-01-31'\n * });\n * byProvider.forEach(p => console.log(p.provider, p.count));\n * ```\n */\n public async getLoginsByProvider(\n orgSlug: string,\n params?: AnalyticsQuery\n ): Promise<LoginsByProvider[]> {\n const response = await this.http.get<LoginsByProvider[]>(\n `/api/organizations/${orgSlug}/analytics/logins-by-provider`,\n { params }\n );\n return response.data;\n }\n\n /**\n * Get the most recent login events.\n *\n * @param orgSlug Organization slug\n * @param params Optional query parameters (limit)\n * @returns Array of recent login events\n *\n * @example\n * ```typescript\n * const recentLogins = await sso.analytics.getRecentLogins('acme-corp', {\n * limit: 10\n * });\n * recentLogins.forEach(login => {\n * console.log(login.user_id, login.provider, login.created_at);\n * });\n * ```\n */\n public async getRecentLogins(\n orgSlug: string,\n params?: AnalyticsQuery\n ): Promise<RecentLogin[]> {\n const response = await this.http.get<RecentLogin[]>(\n `/api/organizations/${orgSlug}/analytics/recent-logins`,\n { params }\n );\n return response.data;\n }\n}\n","import { HttpClient } from '../http';\nimport { SessionManager } from '../session';\nimport {\n OAuthProvider,\n DeviceCodeRequest,\n DeviceCodeResponse,\n DeviceVerifyResponse,\n TokenRequest,\n TokenResponse,\n LoginUrlParams,\n AdminLoginUrlParams,\n ProviderToken,\n RefreshTokenResponse,\n RegisterRequest,\n RegisterResponse,\n LoginRequest,\n ForgotPasswordRequest,\n ForgotPasswordResponse,\n ResetPasswordRequest,\n ResetPasswordResponse,\n MfaVerificationResponse,\n LookupEmailResponse,\n ResendVerificationRequest,\n ResendVerificationResponse,\n AuthorizeUrlParams,\n AccountSecurityUrlParams,\n AuthContextRequest,\n AuthContextResponse,\n} from '../types';\n\n/**\n * Authentication and OAuth flow methods\n */\nexport class AuthModule {\n constructor(\n private http: HttpClient,\n private session: SessionManager\n ) { }\n\n /**\n * Constructs the hosted AuthOS login URL for an end-user application.\n * AuthOS owns provider selection, HRD, password, magic-link, passkey, MFA,\n * recovery, and callback token delivery for this flow.\n *\n * @param params Hosted authorize parameters (org, service, redirect_uri)\n * @returns The full URL to redirect the user to\n *\n * @example\n * ```typescript\n * window.location.href = sso.auth.getAuthorizeUrl({\n * org: 'acme-corp',\n * service: 'main-app',\n * redirect_uri: 'https://app.acme.com/callback'\n * });\n * ```\n */\n public getAuthorizeUrl(params: AuthorizeUrlParams): string {\n const baseURL = (this.http.defaults.baseURL || '').replace(/\\/+$/, '');\n const searchParams = new URLSearchParams({\n org: params.org,\n service: params.service,\n redirect_uri: params.redirect_uri,\n });\n if (params.state) searchParams.append('state', params.state);\n\n return `${baseURL}/authorize?${searchParams.toString()}`;\n }\n\n /**\n * Constructs the hosted account-security URL for managing user factors.\n * Use this for AuthOS-owned MFA, passkeys, backup codes, and trusted devices.\n *\n * @param params Optional tenant/application context and return URL\n * @returns The full URL to open for account security management\n */\n public getAccountSecurityUrl(params: AccountSecurityUrlParams = {}): string {\n const baseURL = (this.http.defaults.baseURL || '').replace(/\\/+$/, '');\n const searchParams = new URLSearchParams();\n\n if (params.org) searchParams.append('org', params.org);\n if (params.service) searchParams.append('service', params.service);\n if (params.return_to) searchParams.append('return_to', params.return_to);\n\n const query = searchParams.toString();\n return `${baseURL}/app/account-security${query ? `?${query}` : ''}`;\n }\n\n /**\n * Constructs the OAuth login URL for end-users.\n * This does not perform the redirect; the consuming application\n * should redirect the user's browser to this URL.\n *\n * @param provider The OAuth provider to use\n * @param params Login parameters (org, service, redirect_uri, connection_id)\n * @returns The full URL to redirect the user to\n *\n * @example\n * ```typescript\n * // Standard OAuth login\n * const url = sso.auth.getLoginUrl('github', {\n * org: 'acme-corp',\n * service: 'main-app',\n * redirect_uri: 'https://app.acme.com/callback'\n * });\n * window.location.href = url;\n *\n * // Enterprise IdP login (after HRD lookup)\n * const hrd = await sso.auth.lookupEmail('user@enterprise.com');\n * if (hrd.connection_id) {\n * const url = sso.auth.getLoginUrl('github', {\n * org: 'acme-corp',\n * service: 'main-app',\n * connection_id: hrd.connection_id\n * });\n * window.location.href = url;\n * }\n * ```\n */\n public getLoginUrl(provider: OAuthProvider, params: LoginUrlParams): string {\n const baseURL = this.http.defaults.baseURL || '';\n const searchParams = new URLSearchParams({\n org: params.org,\n service: params.service,\n });\n\n if (params.redirect_uri) {\n searchParams.append('redirect_uri', params.redirect_uri);\n }\n if (params.state) {\n searchParams.append('state', params.state);\n }\n\n if (params.user_code) {\n searchParams.append('user_code', params.user_code);\n }\n\n if (params.connection_id) {\n searchParams.append('connection_id', params.connection_id);\n }\n\n return `${baseURL}/auth/${provider}?${searchParams.toString()}`;\n }\n\n /**\n * Constructs the OAuth login URL for platform/organization admins.\n * This uses the platform's dedicated OAuth credentials.\n *\n * @param provider The OAuth provider to use\n * @param params Optional admin login parameters\n * @returns The full URL to redirect the admin to\n *\n * @example\n * ```typescript\n * const url = sso.auth.getAdminLoginUrl('github', {\n * org_slug: 'acme-corp'\n * });\n * window.location.href = url;\n * ```\n */\n public getAdminLoginUrl(provider: OAuthProvider, params?: AdminLoginUrlParams): string {\n const baseURL = this.http.defaults.baseURL || '';\n const searchParams = new URLSearchParams();\n\n if (params?.org_slug) {\n searchParams.append('org_slug', params.org_slug);\n }\n\n if (params?.user_code) {\n searchParams.append('user_code', params.user_code);\n }\n\n if (params?.return_to) {\n searchParams.append('return_to', params.return_to);\n }\n\n const queryString = searchParams.toString();\n return `${baseURL}/auth/admin/${provider}${queryString ? `?${queryString}` : ''}`;\n }\n\n /**\n * Device Flow: Request a device code for CLI/device authentication.\n *\n * @param payload Device code request payload\n * @returns Device code response with user code and verification URI\n *\n * @example\n * ```typescript\n * const response = await sso.auth.deviceCode.request({\n * client_id: 'service-client-id',\n * org: 'acme-corp',\n * service: 'acme-cli'\n * });\n * console.log(`Visit ${response.verification_uri} and enter code: ${response.user_code}`);\n * ```\n */\n public deviceCode = {\n /**\n * Request a device code\n */\n request: async (payload: DeviceCodeRequest): Promise<DeviceCodeResponse> => {\n const response = await this.http.post<DeviceCodeResponse>('/auth/device/code', payload);\n return response.data;\n },\n\n /**\n * Verify a user code and get the context (org_slug, service_slug)\n * needed for the UI to initiate the appropriate OAuth flow.\n *\n * @param userCode The user-friendly code displayed on the device\n * @returns Context with organization and service information\n *\n * @example\n * ```typescript\n * const context = await sso.auth.deviceCode.verify('ABCD-1234');\n * // Use context.org_slug and context.service_slug to determine which OAuth flow to initiate\n * ```\n */\n verify: async (userCode: string): Promise<DeviceVerifyResponse> => {\n const response = await this.http.post<DeviceVerifyResponse>('/auth/device/verify', {\n user_code: userCode\n });\n return response.data;\n },\n\n /**\n * Exchange a device code for a JWT token.\n * This should be polled by the device/CLI after displaying the user code.\n * Note: This returns a TokenResponse (not RefreshTokenResponse) and typically\n * only includes access_token. For device flows that need persistence,\n * manually call sso.session.setSession() if needed.\n *\n * @param payload Token request payload\n * @returns Token response with JWT\n *\n * @example\n * ```typescript\n * // Poll every 5 seconds\n * const interval = setInterval(async () => {\n * try {\n * const token = await sso.auth.deviceCode.exchangeToken({\n * grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n * device_code: deviceCode,\n * client_id: 'service-client-id'\n * });\n * clearInterval(interval);\n * // Session is automatically configured\n * } catch (error) {\n * if (error.errorCode !== 'authorization_pending') {\n * clearInterval(interval);\n * throw error;\n * }\n * }\n * }, 5000);\n * ```\n */\n exchangeToken: async (payload: TokenRequest): Promise<TokenResponse> => {\n const response = await this.http.post<TokenResponse>('/auth/token', payload);\n return response.data;\n },\n };\n\n /**\n * Logout the current user by revoking their JWT.\n * Automatically clears the session and tokens from storage.\n *\n * @example\n * ```typescript\n * await sso.auth.logout();\n * // Session is automatically cleared - no need for manual cleanup\n * ```\n */\n public async logout(): Promise<void> {\n try {\n await this.http.post('/api/auth/logout');\n } finally {\n // MAGIC HAPPENS HERE: Auto-clear tokens\n await this.session.clearSession();\n }\n }\n\n /**\n * Refresh an expired JWT access token using a refresh token.\n * This implements token rotation - both the access token and refresh token\n * will be renewed with each call.\n *\n * The refresh token must be stored securely on the client side.\n * After a successful refresh, update both tokens in storage and call\n * `sso.setAuthToken(newAccessToken)`.\n *\n * @param refreshToken The refresh token obtained during login\n * @returns New access token and refresh token pair\n *\n * @example\n * ```typescript\n * try {\n * const tokens = await sso.auth.refreshToken(storedRefreshToken);\n * sso.setAuthToken(tokens.access_token);\n * localStorage.setItem('sso_access_token', tokens.access_token);\n * localStorage.setItem('sso_refresh_token', tokens.refresh_token);\n * } catch (error) {\n * // Refresh failed - redirect to login\n * window.location.href = '/login';\n * }\n * ```\n */\n public async refreshToken(refreshToken: string): Promise<RefreshTokenResponse> {\n const response = await this.http.post<RefreshTokenResponse>('/api/auth/refresh', {\n refresh_token: refreshToken,\n });\n return response.data;\n }\n\n /**\n * Get a fresh provider access token for the authenticated user.\n * This will automatically refresh the token if it's expired.\n *\n * @param provider The OAuth provider\n * @returns Fresh provider token\n *\n * @example\n * ```typescript\n * const token = await sso.auth.getProviderToken('github');\n * // Use token.access_token to make GitHub API calls\n * ```\n */\n public async getProviderToken(provider: OAuthProvider): Promise<ProviderToken> {\n const response = await this.http.get<ProviderToken>(`/api/provider-token/${provider}`);\n return response.data;\n }\n\n // ============================================================================\n // PASSWORD AUTHENTICATION\n // ============================================================================\n\n /**\n * Register a new user with email and password.\n * After registration, the user will receive a verification email.\n *\n * @param payload Registration details (email and password)\n * @returns Registration confirmation message\n *\n * @example\n * ```typescript\n * const response = await sso.auth.register({\n * email: 'user@example.com',\n * password: 'SecurePassword123!'\n * });\n * console.log(response.message);\n * ```\n */\n public async register(payload: RegisterRequest): Promise<RegisterResponse> {\n const response = await this.http.post<RegisterResponse>('/api/auth/register', payload);\n return response.data;\n }\n\n /**\n * Verify an email address using the token from the verification email.\n *\n * @param token Verification token\n * @returns HTML success page string\n *\n * @example\n * ```typescript\n * const html = await sso.auth.verifyEmail('token-from-email');\n * ```\n */\n public async verifyEmail(token: string): Promise<string> {\n const response = await this.http.get<string>('/auth/verify-email', {\n params: { token }\n });\n return response.data;\n }\n\n /**\n * Resend verification email to a user.\n * Returns success regardless of whether the email exists (to prevent email enumeration).\n *\n * @param payload Resend verification request (email address)\n * @returns Confirmation message\n *\n * @example\n * ```typescript\n * const response = await sso.auth.resendVerification({\n * email: 'user@example.com'\n * });\n * console.log(response.message);\n * ```\n */\n public async resendVerification(payload: ResendVerificationRequest): Promise<ResendVerificationResponse> {\n const response = await this.http.post<ResendVerificationResponse>('/api/auth/resend-verification', payload);\n return response.data;\n }\n\n /**\n * Login with email and password.\n * Automatically persists the session once authentication is complete.\n *\n * @param payload Login credentials (email and password)\n * @returns Access token, refresh token, and expiration info\n *\n * @example\n * ```typescript\n * const tokens = await sso.auth.login({\n * email: 'user@example.com',\n * password: 'SecurePassword123!'\n * });\n * // Session is automatically saved unless MFA is required\n * ```\n */\n public async login(payload: LoginRequest): Promise<RefreshTokenResponse> {\n const response = await this.http.post<RefreshTokenResponse>('/api/auth/login', payload);\n\n if (response.data.refresh_token) {\n await this.session.setSession({\n access_token: response.data.access_token,\n refresh_token: response.data.refresh_token,\n });\n }\n\n return response.data;\n }\n\n /**\n * Verify MFA code and complete authentication.\n * This method should be called after login when the user has MFA enabled.\n * The login will return a pre-auth token with a short expiration (5 minutes).\n * Exchange the pre-auth token and TOTP code for a full session.\n * Automatically persists the session after successful MFA verification.\n *\n * @param preauthToken The pre-authentication token received from login\n * @param code The TOTP code from the user's authenticator app or a backup code\n * @returns Full session tokens (access_token and refresh_token)\n *\n * @example\n * ```typescript\n * // After login, if MFA is enabled:\n * const loginResponse = await sso.auth.login({\n * email: 'user@example.com',\n * password: 'password'\n * });\n *\n * // Check if this is a pre-auth token (expires_in will be 300 seconds = 5 minutes)\n * if (loginResponse.expires_in === 300) {\n * // User needs to provide MFA code\n * const mfaCode = prompt('Enter your 6-digit code from authenticator app');\n * const tokens = await sso.auth.verifyMfa(loginResponse.access_token, mfaCode);\n * // Session is automatically saved - no need for manual token management\n * }\n * ```\n */\n public async verifyMfa(\n preauthToken: string,\n code: string,\n deviceCodeId?: string\n ): Promise<MfaVerificationResponse> {\n const response = await this.http.post<MfaVerificationResponse>('/api/auth/mfa/verify', {\n preauth_token: preauthToken,\n code,\n ...(deviceCodeId && { device_code_id: deviceCodeId }),\n });\n\n // Auto-save tokens after MFA verification\n await this.session.setSession({\n access_token: response.data.access_token,\n refresh_token: response.data.refresh_token,\n });\n\n return response.data;\n }\n\n /**\n * Request a password reset for a user account.\n * If the email exists, a reset link will be sent to the user.\n * Returns success regardless of whether the email exists (to prevent email enumeration).\n *\n * @param payload Forgot password request (email address)\n * @returns Confirmation message\n *\n * @example\n * ```typescript\n * const response = await sso.auth.requestPasswordReset({\n * email: 'user@example.com'\n * });\n * console.log(response.message);\n * ```\n */\n public async requestPasswordReset(payload: ForgotPasswordRequest): Promise<ForgotPasswordResponse> {\n const response = await this.http.post<ForgotPasswordResponse>('/api/auth/forgot-password', payload);\n return response.data;\n }\n\n /**\n * Reset a user's password using a reset token from email.\n * The token is obtained from the password reset email link.\n *\n * @param payload Reset password request (token and new password)\n * @returns Confirmation message\n *\n * @example\n * ```typescript\n * const response = await sso.auth.resetPassword({\n * token: 'reset-token-from-email',\n * new_password: 'NewSecurePassword123!'\n * });\n * console.log(response.message);\n * ```\n */\n public async resetPassword(payload: ResetPasswordRequest): Promise<ResetPasswordResponse> {\n const response = await this.http.post<ResetPasswordResponse>('/api/auth/reset-password', payload);\n return response.data;\n }\n\n // ============================================================================\n // HOME REALM DISCOVERY (HRD)\n // ============================================================================\n\n /**\n * Lookup an email address to determine which authentication method to use.\n * This implements Home Realm Discovery (HRD), allowing users to simply enter\n * their email address and be automatically routed to the correct identity provider.\n *\n * The system will:\n * 1. Extract the domain from the email address\n * 2. Check if the domain is verified and mapped to an enterprise IdP\n * 3. Return routing information (connection_id) if found\n * 4. Otherwise, indicate to use default authentication (password or OAuth)\n *\n * @param email The user's email address\n * @returns HRD response with routing information\n *\n * @example\n * ```typescript\n * // Lookup email to determine authentication flow\n * const result = await sso.auth.lookupEmail('john@acmecorp.com');\n *\n * if (result.auth_method === 'upstream' && result.connection_id) {\n * // Route to enterprise IdP\n * console.log(`Redirecting to ${result.provider_name}`);\n * const url = sso.auth.getLoginUrl('github', {\n * org: 'acme-corp',\n * service: 'main-app',\n * connection_id: result.connection_id\n * });\n * window.location.href = url;\n * } else if (result.auth_method === 'password') {\n * // Show password login form\n * showPasswordForm();\n * } else {\n * // Show default OAuth provider buttons (GitHub, Google, Microsoft)\n * showOAuthButtons();\n * }\n * ```\n */\n public async lookupEmail(email: string): Promise<LookupEmailResponse> {\n const response = await this.http.post<LookupEmailResponse>('/api/auth/lookup-email', {\n email\n });\n return response.data;\n }\n\n /**\n * Fetch public hosted-auth context for an organization/service login.\n */\n public async getContext(params: AuthContextRequest = {}): Promise<AuthContextResponse> {\n const searchParams = new URLSearchParams();\n if (params.org) searchParams.append('org', params.org);\n if (params.service) searchParams.append('service', params.service);\n if (params.redirect_uri) searchParams.append('redirect_uri', params.redirect_uri);\n\n const query = searchParams.toString();\n const response = await this.http.get<AuthContextResponse>(\n `/api/auth/context${query ? `?${query}` : ''}`\n );\n return response.data;\n }\n}\n","import { HttpClient } from '../http';\nimport { UserProfile, UpdateUserProfilePayload, Subscription, Identity, StartLinkResponse, ChangePasswordRequest, ChangePasswordResponse, SetPasswordRequest, SetPasswordResponse, MfaStatusResponse, MfaSetupResponse, MfaVerifyResponse, BackupCodesResponse, UserDevice, ListDevicesResponse, RevokeDeviceResponse, LinkedAccountsResponse, GrantLinkedAccountRequest, LinkedAccountGrant, ProviderTokenRequestDetails, CompleteProviderTokenRequestPayload, CompleteProviderTokenRequestResponse } from '../types';\n\n/**\n * Identity (social account linking) methods\n */\nclass IdentitiesModule {\n constructor(private http: HttpClient) {}\n\n /**\n * List all social accounts linked to the authenticated user.\n *\n * @returns Array of linked identities\n *\n * @example\n * ```typescript\n * const identities = await sso.user.identities.list();\n * console.log(identities); // [{ provider: 'github' }, { provider: 'google' }]\n * ```\n */\n public async list(): Promise<Identity[]> {\n const response = await this.http.get<Identity[]>('/api/user/identities');\n return response.data;\n }\n\n /**\n * Start linking a new social account to the authenticated user.\n * Returns an authorization URL that the user should be redirected to.\n *\n * @param provider The OAuth provider to link (e.g., 'github', 'google', 'microsoft')\n * @returns Object containing the authorization URL\n *\n * @example\n * ```typescript\n * const { authorization_url } = await sso.user.identities.startLink('github');\n * window.location.href = authorization_url; // Redirect user to complete OAuth\n * ```\n */\n public async startLink(provider: string): Promise<StartLinkResponse> {\n const response = await this.http.post<StartLinkResponse>(`/api/user/identities/${provider}/link`, {});\n return response.data;\n }\n\n /**\n * Unlink a social account from the authenticated user.\n * Note: Cannot unlink the last remaining identity to prevent account lockout.\n *\n * @param provider The OAuth provider to unlink (e.g., 'github', 'google', 'microsoft')\n *\n * @example\n * ```typescript\n * await sso.user.identities.unlink('google');\n * ```\n */\n public async unlink(provider: string): Promise<void> {\n await this.http.delete(`/api/user/identities/${provider}`);\n }\n}\n\nclass LinkedAccountsModule {\n constructor(private http: HttpClient) {}\n\n public async list(): Promise<LinkedAccountsResponse> {\n const response = await this.http.get<LinkedAccountsResponse>('/api/user/linked-accounts');\n return response.data;\n }\n\n public async startLink(provider: string): Promise<StartLinkResponse> {\n const response = await this.http.post<StartLinkResponse>(`/api/user/linked-accounts/${provider}/link`, {});\n return response.data;\n }\n\n public async grant(accountId: string, payload: GrantLinkedAccountRequest): Promise<LinkedAccountGrant> {\n const response = await this.http.post<LinkedAccountGrant>(`/api/user/linked-accounts/${accountId}/grants`, payload);\n return response.data;\n }\n\n public async revokeGrant(accountId: string, serviceId: string): Promise<void> {\n await this.http.delete(`/api/user/linked-accounts/${accountId}/grants/${serviceId}`);\n }\n\n public async unlink(accountId: string): Promise<void> {\n await this.http.delete(`/api/user/linked-accounts/${accountId}`);\n }\n\n public async getProviderTokenRequest(state: string): Promise<ProviderTokenRequestDetails> {\n const response = await this.http.get<ProviderTokenRequestDetails>(`/api/user/provider-token-requests/${state}`);\n return response.data;\n }\n\n public async completeProviderTokenRequest(\n state: string,\n payload: CompleteProviderTokenRequestPayload = {},\n ): Promise<CompleteProviderTokenRequestResponse> {\n const response = await this.http.post<CompleteProviderTokenRequestResponse>(`/api/user/provider-token-requests/${state}/complete`, payload);\n return response.data;\n }\n\n public async startProviderTokenRequestLink(state: string): Promise<StartLinkResponse> {\n const response = await this.http.post<StartLinkResponse>(`/api/user/provider-token-requests/${state}/link`, {});\n return response.data;\n }\n}\n\n/**\n * Multi-Factor Authentication (MFA) methods\n */\nclass MfaModule {\n constructor(private http: HttpClient) {}\n\n /**\n * Get the current MFA status for the authenticated user.\n *\n * @returns MFA status\n *\n * @example\n * ```typescript\n * const status = await sso.user.mfa.getStatus();\n * console.log(status.enabled); // false\n * ```\n */\n public async getStatus(): Promise<MfaStatusResponse> {\n const response = await this.http.get<MfaStatusResponse>('/api/user/mfa/status');\n return response.data;\n }\n\n /**\n * Initiate MFA setup. Generates a TOTP secret and QR code.\n * The user must complete setup by calling verify() with a code from their authenticator app.\n *\n * @returns MFA setup details including QR code\n *\n * @example\n * ```typescript\n * const setup = await sso.user.mfa.setup();\n * console.log(setup.qr_code_svg); // Display this QR code to the user\n * // User scans QR code with authenticator app and enters code to verify\n * ```\n */\n public async setup(): Promise<MfaSetupResponse> {\n const response = await this.http.post<MfaSetupResponse>('/api/user/mfa/setup', {});\n return response.data;\n }\n\n /**\n * Verify TOTP code and enable MFA.\n * Returns backup codes that must be stored securely by the user.\n *\n * @param code TOTP code from authenticator app\n * @returns Verification response with backup codes\n *\n * @example\n * ```typescript\n * const result = await sso.user.mfa.verify('123456');\n * console.log(result.backup_codes); // Store these securely!\n * ```\n */\n public async verify(code: string): Promise<MfaVerifyResponse> {\n const response = await this.http.post<MfaVerifyResponse>('/api/user/mfa/verify', { code });\n return response.data;\n }\n\n /**\n * Disable MFA for the authenticated user.\n *\n * @example\n * ```typescript\n * await sso.user.mfa.disable();\n * ```\n */\n public async disable(): Promise<{ success: boolean; message: string }> {\n const response = await this.http.delete<{ success: boolean; message: string }>('/api/user/mfa');\n return response.data;\n }\n\n /**\n * Regenerate backup codes.\n * Invalidates all previous backup codes and returns new ones.\n *\n * @returns New backup codes\n *\n * @example\n * ```typescript\n * const { backup_codes } = await sso.user.mfa.regenerateBackupCodes();\n * console.log(backup_codes); // Store these securely!\n * ```\n */\n public async regenerateBackupCodes(): Promise<BackupCodesResponse> {\n const response = await this.http.post<BackupCodesResponse>('/api/user/mfa/backup-codes/regenerate', {});\n return response.data;\n }\n}\n\n/**\n * Device management methods\n */\nclass DevicesModule {\n constructor(private http: HttpClient) {}\n\n /**\n * List all devices associated with the authenticated user.\n *\n * @param options Optional query parameters for pagination\n * @returns Array of user devices\n *\n * @example\n * ```typescript\n * const { devices, total } = await sso.user.devices.list();\n * console.log(devices); // Array of trusted devices\n * ```\n */\n public async list(options?: {\n page?: number;\n limit?: number;\n sort_by?: 'first_seen_at' | 'last_used_at' | 'device_name';\n sort_order?: 'asc' | 'desc';\n }): Promise<ListDevicesResponse> {\n const params = new URLSearchParams();\n\n if (options?.page) params.append('page', options.page.toString());\n if (options?.limit) params.append('limit', options.limit.toString());\n if (options?.sort_by) params.append('sort_by', options.sort_by);\n if (options?.sort_order) params.append('sort_order', options.sort_order);\n\n const query = params.toString();\n const url = `/api/user/devices${query ? `?${query}` : ''}`;\n\n const response = await this.http.get<ListDevicesResponse>(url);\n return response.data;\n }\n\n /**\n * Get details for a specific device.\n *\n * @param deviceId The device ID to retrieve\n * @returns Device details\n *\n * @example\n * ```typescript\n * const device = await sso.user.devices.get('device-123');\n * console.log(device.device_name, device.is_trusted);\n * ```\n */\n public async get(deviceId: string): Promise<UserDevice> {\n const response = await this.http.get<UserDevice>(`/api/user/devices/${deviceId}`);\n return response.data;\n }\n\n /**\n * Revoke access for a specific device.\n * This will remove the device's trust and require re-authentication.\n *\n * @param deviceId The device ID to revoke\n * @param reason Optional reason for revocation\n * @returns Confirmation message\n *\n * @example\n * ```typescript\n * const result = await sso.user.devices.revoke('device-123', 'Device lost');\n * console.log(result.message);\n * ```\n */\n public async revoke(deviceId: string, reason?: string): Promise<RevokeDeviceResponse> {\n const payload = reason ? { reason } : {};\n const response = await this.http.post<RevokeDeviceResponse>(`/api/user/devices/${deviceId}/revoke`, payload);\n return response.data;\n }\n\n /**\n * Revoke all devices except the current one.\n * This is useful when you suspect account compromise or want to force re-authentication on all devices.\n *\n * @returns Confirmation message\n *\n * @example\n * ```typescript\n * const result = await sso.user.devices.revokeAll();\n * console.log(result.message); // \"All other devices have been revoked\"\n * ```\n */\n public async revokeAll(): Promise<RevokeDeviceResponse> {\n const response = await this.http.post<RevokeDeviceResponse>('/api/user/devices/revoke-all', {});\n return response.data;\n }\n\n /**\n * Update the name of a device.\n *\n * @param deviceId The device ID to update\n * @param deviceName New device name\n * @returns Updated device information\n *\n * @example\n * ```typescript\n * const device = await sso.user.devices.updateName('device-123', 'My Laptop');\n * console.log(device.device_name); // \"My Laptop\"\n * ```\n */\n public async updateName(deviceId: string, deviceName: string): Promise<UserDevice> {\n const response = await this.http.patch<UserDevice>(`/api/user/devices/${deviceId}`, {\n device_name: deviceName\n });\n return response.data;\n }\n\n /**\n * Mark a device as trusted manually.\n * This is useful for devices that you want to explicitly trust regardless of risk assessment.\n *\n * @param deviceId The device ID to trust\n * @returns Updated device information\n *\n * @example\n * ```typescript\n * const device = await sso.user.devices.trust('device-123');\n * console.log(device.is_trusted); // true\n * ```\n */\n public async trust(deviceId: string): Promise<UserDevice> {\n const response = await this.http.post<UserDevice>(`/api/user/devices/${deviceId}/trust`, {});\n return response.data;\n }\n}\n\n/**\n * User profile and subscription methods\n */\nexport class UserModule {\n public readonly identities: IdentitiesModule;\n public readonly linkedAccounts: LinkedAccountsModule;\n public readonly mfa: MfaModule;\n public readonly devices: DevicesModule;\n\n constructor(private http: HttpClient) {\n this.identities = new IdentitiesModule(http);\n this.linkedAccounts = new LinkedAccountsModule(http);\n this.mfa = new MfaModule(http);\n this.devices = new DevicesModule(http);\n }\n\n /**\n * Get the profile of the currently authenticated user.\n * The response includes context from the JWT (org, service).\n *\n * @returns User profile\n *\n * @example\n * ```typescript\n * const profile = await sso.user.getProfile();\n * console.log(profile.email, profile.org, profile.service);\n * ```\n */\n public async getProfile(): Promise<UserProfile> {\n const response = await this.http.get<UserProfile>('/api/user');\n return response.data;\n }\n\n /**\n * Update the authenticated user's profile.\n *\n * @param payload Update payload\n * @returns Updated user profile\n *\n * @example\n * ```typescript\n * const updated = await sso.user.updateProfile({\n * email: 'newemail@example.com'\n * });\n * ```\n */\n public async updateProfile(payload: UpdateUserProfilePayload): Promise<UserProfile> {\n const response = await this.http.patch<UserProfile>('/api/user', payload);\n return response.data;\n }\n\n /**\n * Get the current user's subscription details for the service in their JWT.\n *\n * @returns Subscription details\n *\n * @example\n * ```typescript\n * const subscription = await sso.user.getSubscription();\n * console.log(subscription.plan, subscription.features);\n * ```\n */\n public async getSubscription(): Promise<Subscription> {\n const response = await this.http.get<Subscription>('/api/subscription');\n return response.data;\n }\n\n /**\n * Change the authenticated user's password.\n * Requires the current password for verification.\n *\n * @param payload Change password request (current and new password)\n * @returns Confirmation message\n *\n * @example\n * ```typescript\n * const response = await sso.user.changePassword({\n * current_password: 'OldPassword123!',\n * new_password: 'NewSecurePassword456!'\n * });\n * console.log(response.message);\n * ```\n */\n public async changePassword(payload: ChangePasswordRequest): Promise<ChangePasswordResponse> {\n const response = await this.http.post<ChangePasswordResponse>('/api/user/change-password', payload);\n return response.data;\n }\n\n /**\n * Set a password for the authenticated user (OAuth users only).\n * This endpoint is for OAuth users who don't have a password yet.\n * If a password is already set, this will return an error.\n *\n * @param payload Set password request (new password only)\n * @returns Confirmation message\n *\n * @example\n * ```typescript\n * const response = await sso.user.setPassword({\n * new_password: 'MyNewSecurePassword123!'\n * });\n * console.log(response.message); // \"Password set successfully\"\n * ```\n */\n public async setPassword(payload: SetPasswordRequest): Promise<SetPasswordResponse> {\n const response = await this.http.post<SetPasswordResponse>('/api/user/set-password', payload);\n return response.data;\n }\n}\n","import { HttpClient } from '../../http';\nimport {\n AuditLogResponse,\n EventTypeInfo,\n AuditLogQueryParams,\n} from '../../types';\n\n/**\n * Organization audit logs management methods\n */\nexport class AuditLogsModule {\n constructor(private http: HttpClient) {}\n\n /**\n * Get audit logs for an organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param params Optional query parameters for filtering and pagination\n * @returns Paginated audit log response\n *\n * @example\n * ```typescript\n * // Get all audit logs\n * const logs = await sso.organizations.auditLogs.get('acme-corp');\n *\n * // Filter by specific action\n * const userLogs = await sso.organizations.auditLogs.get('acme-corp', {\n * action: 'user.role_updated',\n * page: 1,\n * limit: 20\n * });\n *\n * // Filter by target\n * const serviceLogs = await sso.organizations.auditLogs.get('acme-corp', {\n * target_type: 'service',\n * target_id: 'service-123'\n * });\n * ```\n */\n public async get(\n orgSlug: string,\n params?: AuditLogQueryParams\n ): Promise<AuditLogResponse> {\n const response = await this.http.get<AuditLogResponse>(\n `/api/organizations/${orgSlug}/audit-log`,\n { params }\n );\n return response.data;\n }\n\n /**\n * Get available audit event types for filtering.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @returns Array of event type information\n *\n * @example\n * ```typescript\n * const eventTypes = await sso.organizations.auditLogs.getEventTypes('acme-corp');\n *\n * // Group by category for UI display\n * const byCategory = eventTypes.reduce((acc, event) => {\n * if (!acc[event.category]) {\n * acc[event.category] = [];\n * }\n * acc[event.category].push(event);\n * return acc;\n * }, {});\n * ```\n */\n public async getEventTypes(orgSlug: string): Promise<EventTypeInfo[]> {\n const response = await this.http.get<EventTypeInfo[]>(\n `/api/organizations/${orgSlug}/audit-log/event-types`\n );\n return response.data;\n }\n}","import { HttpClient } from '../../http';\nimport {\n WebhookResponse,\n WebhookListResponse,\n CreateWebhookRequest,\n UpdateWebhookRequest,\n WebhookDeliveryListResponse,\n WebhookDeliveryQueryParams,\n EventTypeInfo,\n} from '../../types';\n\n/**\n * Organization webhooks management methods\n */\nexport class WebhooksModule {\n constructor(private http: HttpClient) {}\n\n /**\n * Create a new webhook for an organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param webhook Webhook creation payload\n * @returns Created webhook details\n *\n * @example\n * ```typescript\n * const webhook = await sso.organizations.webhooks.create('acme-corp', {\n * name: 'User Activity',\n * url: 'https://api.example.com/webhooks',\n * events: ['user.invited', 'user.joined', 'user.removed']\n * });\n * console.log('Created webhook:', webhook.id);\n * ```\n */\n public async create(\n orgSlug: string,\n webhook: CreateWebhookRequest\n ): Promise<WebhookResponse> {\n const response = await this.http.post<WebhookResponse>(\n `/api/organizations/${orgSlug}/webhooks`,\n webhook\n );\n return response.data;\n }\n\n /**\n * List all webhooks for an organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @returns List of webhooks with total count\n *\n * @example\n * ```typescript\n * const { webhooks, total } = await sso.organizations.webhooks.list('acme-corp');\n * console.log(`Found ${total} webhooks`);\n * webhooks.forEach(w => console.log(w.name, w.is_active));\n * ```\n */\n public async list(orgSlug: string): Promise<WebhookListResponse> {\n const response = await this.http.get<WebhookListResponse>(\n `/api/organizations/${orgSlug}/webhooks`\n );\n return response.data;\n }\n\n /**\n * Get a specific webhook by ID.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param webhookId Webhook ID\n * @returns Webhook details\n *\n * @example\n * ```typescript\n * const webhook = await sso.organizations.webhooks.get('acme-corp', 'webhook-123');\n * console.log('Webhook URL:', webhook.url);\n * console.log('Subscribed events:', webhook.events);\n * ```\n */\n public async get(orgSlug: string, webhookId: string): Promise<WebhookResponse> {\n const response = await this.http.get<WebhookResponse>(\n `/api/organizations/${orgSlug}/webhooks/${webhookId}`\n );\n return response.data;\n }\n\n /**\n * Update an existing webhook.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param webhookId Webhook ID\n * @param updates Partial webhook update payload\n * @returns Updated webhook details\n *\n * @example\n * ```typescript\n * // Update webhook URL and add new events\n * const updated = await sso.organizations.webhooks.update('acme-corp', 'webhook-123', {\n * url: 'https://api.example.com/webhooks/v2',\n * events: ['user.invited', 'user.joined', 'user.removed', 'user.role_updated']\n * });\n *\n * // Deactivate webhook temporarily\n * await sso.organizations.webhooks.update('acme-corp', 'webhook-123', {\n * is_active: false\n * });\n * ```\n */\n public async update(\n orgSlug: string,\n webhookId: string,\n updates: UpdateWebhookRequest\n ): Promise<WebhookResponse> {\n const response = await this.http.patch<WebhookResponse>(\n `/api/organizations/${orgSlug}/webhooks/${webhookId}`,\n updates\n );\n return response.data;\n }\n\n /**\n * Delete a webhook.\n * Requires 'owner' or 'admin' role.\n * This will also delete all delivery history for this webhook.\n *\n * @param orgSlug Organization slug\n * @param webhookId Webhook ID\n *\n * @example\n * ```typescript\n * await sso.organizations.webhooks.delete('acme-corp', 'webhook-123');\n * console.log('Webhook deleted successfully');\n * ```\n */\n public async delete(orgSlug: string, webhookId: string): Promise<void> {\n await this.http.delete(\n `/api/organizations/${orgSlug}/webhooks/${webhookId}`\n );\n }\n\n /**\n * Get delivery history for a specific webhook.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param webhookId Webhook ID\n * @param params Optional query parameters for filtering and pagination\n * @returns Paginated webhook delivery response\n *\n * @example\n * ```typescript\n * // Get all delivery attempts\n * const deliveries = await sso.organizations.webhooks.getDeliveries('acme-corp', 'webhook-123');\n *\n * // Get only failed deliveries\n * const failed = await sso.organizations.webhooks.getDeliveries('acme-corp', 'webhook-123', {\n * delivered: false,\n * page: 1,\n * limit: 20\n * });\n *\n * // Get deliveries for specific event type\n * const userEvents = await sso.organizations.webhooks.getDeliveries('acme-corp', 'webhook-123', {\n * event_type: 'user.invited'\n * });\n * ```\n */\n public async getDeliveries(\n orgSlug: string,\n webhookId: string,\n params?: WebhookDeliveryQueryParams\n ): Promise<WebhookDeliveryListResponse> {\n const response = await this.http.get<WebhookDeliveryListResponse>(\n `/api/organizations/${orgSlug}/webhooks/${webhookId}/deliveries`,\n { params }\n );\n return response.data;\n }\n\n /**\n * Get available webhook event types that can be subscribed to.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @returns Array of available event types with categories\n *\n * @example\n * ```typescript\n * const eventTypes = await sso.organizations.webhooks.getEventTypes('acme-corp');\n *\n * // Group events by category for UI display\n * const byCategory = eventTypes.reduce((acc, event) => {\n * if (!acc[event.category]) {\n * acc[event.category] = [];\n * }\n * acc[event.category].push(event);\n * return acc;\n * }, {});\n *\n * // Display available events\n * Object.entries(byCategory).forEach(([category, events]) => {\n * console.log(`\\n${category}:`);\n * events.forEach(e => console.log(` - ${e.label} (${e.value})`));\n * });\n * ```\n */\n public async getEventTypes(orgSlug: string): Promise<EventTypeInfo[]> {\n const response = await this.http.get<EventTypeInfo[]>(\n `/api/organizations/${orgSlug}/webhooks/event-types`\n );\n return response.data;\n }\n\n /**\n * Trigger a test event for a specific webhook (owner/admin only).\n * Generates a \"webhook.test.ping\" event to verify connectivity.\n *\n * @param orgSlug Organization slug\n * @param webhookId Webhook ID\n * @returns Result including delivery ID\n *\n * @example\n * ```typescript\n * const result = await sso.organizations.webhooks.test('acme-corp', 'webhook-123');\n * console.log('Test event sent, delivery ID:', result.delivery_id);\n * ```\n */\n public async test(orgSlug: string, webhookId: string): Promise<{ success: boolean; job_id: string; delivery_id: string }> {\n const response = await this.http.post<{ success: boolean; job_id: string; delivery_id: string }>(\n `/api/organizations/${orgSlug}/webhooks/${webhookId}/test`\n );\n return response.data;\n }\n}","import { HttpClient } from '../../http';\nimport {\n UpstreamProvider,\n CreateUpstreamProviderPayload,\n UpdateUpstreamProviderPayload,\n} from '../../types';\n\n/**\n * Upstream Provider (Enterprise SSO) management methods\n */\nexport class UpstreamProvidersModule {\n constructor(private http: HttpClient) {}\n\n /**\n * List all upstream providers for an organization.\n *\n * @param orgSlug Organization slug\n * @returns Array of upstream providers\n */\n public async list(orgSlug: string): Promise<UpstreamProvider[]> {\n const response = await this.http.get<UpstreamProvider[]>(\n `/api/organizations/${orgSlug}/upstream-providers`\n );\n return response.data;\n }\n\n /**\n * Get a specific upstream provider.\n *\n * @param orgSlug Organization slug\n * @param providerId Provider ID or connection_id\n * @returns Upstream provider details\n */\n public async get(orgSlug: string, providerId: string): Promise<UpstreamProvider> {\n const response = await this.http.get<UpstreamProvider>(\n `/api/organizations/${orgSlug}/upstream-providers/${providerId}`\n );\n return response.data;\n }\n\n /**\n * Create a new upstream provider.\n *\n * @param orgSlug Organization slug\n * @param payload Provider configuration\n * @returns Created upstream provider\n */\n public async create(\n orgSlug: string,\n payload: CreateUpstreamProviderPayload\n ): Promise<UpstreamProvider> {\n const response = await this.http.post<UpstreamProvider>(\n `/api/organizations/${orgSlug}/upstream-providers`,\n payload\n );\n return response.data;\n }\n\n /**\n * Update an existing upstream provider.\n *\n * @param orgSlug Organization slug\n * @param providerId Provider ID or connection_id\n * @param payload Update payload\n * @returns Updated upstream provider\n */\n public async update(\n orgSlug: string,\n providerId: string,\n payload: UpdateUpstreamProviderPayload\n ): Promise<UpstreamProvider> {\n const response = await this.http.patch<UpstreamProvider>(\n `/api/organizations/${orgSlug}/upstream-providers/${providerId}`,\n payload\n );\n return response.data;\n }\n\n /**\n * Delete an upstream provider.\n *\n * @param orgSlug Organization slug\n * @param providerId Provider ID or connection_id\n */\n public async delete(orgSlug: string, providerId: string): Promise<void> {\n await this.http.delete(`/api/organizations/${orgSlug}/upstream-providers/${providerId}`);\n }\n}\n","import { HttpClient } from '../http';\nimport {\n OAuthProvider,\n OrganizationResponse,\n CreateOrganizationPayload,\n CreateOrganizationResponse,\n SelectOrganizationResponse,\n UpdateOrganizationPayload,\n ListOrganizationsParams,\n OrganizationMember,\n MemberListResponse,\n MemberServiceAccess,\n UpdateMemberRolePayload,\n UpdateMemberServiceAccessPayload,\n TransferOwnershipPayload,\n SetOAuthCredentialsPayload,\n OAuthCredentials,\n EndUserListResponse,\n EndUserDetailResponse,\n ListEndUsersParams,\n RevokeSessionsResponse,\n SetSmtpRequest,\n SmtpConfigResponse,\n DomainConfiguration,\n SetCustomDomainRequest,\n DomainVerificationResponse,\n DomainVerificationResult,\n BrandingConfiguration,\n UpdateBrandingRequest,\n GetRiskSettingsResponse,\n UpdateRiskSettingsRequest,\n UpdateRiskSettingsResponse,\n CreateSiemConfigRequest,\n UpdateSiemConfigRequest,\n SiemConfigResponse,\n ListSiemConfigsResponse,\n TestConnectionResponse,\n CreateScimTokenRequest,\n ScimTokenResponse,\n ListScimTokensResponse,\n Invitation,\n CreateInvitationPayload,\n RiskEventResponse,\n RiskEventsQuery,\n RoleResponse,\n CreateRoleRequest,\n UpdateRoleRequest,\n} from '../types';\nimport { AuditLogsModule } from './organizations/audit';\nimport { WebhooksModule } from './organizations/webhooks';\nimport { UpstreamProvidersModule } from './organizations/upstream-providers';\n\n/**\n * Organization management methods\n */\nexport class OrganizationsModule {\n constructor(private http: HttpClient) {\n this.auditLogs = new AuditLogsModule(http);\n this.webhooks = new WebhooksModule(http);\n this.upstreamProviders = new UpstreamProvidersModule(http);\n }\n\n /**\n * Audit logs management\n */\n public auditLogs: AuditLogsModule;\n\n /**\n * Webhooks management\n */\n public webhooks: WebhooksModule;\n\n /**\n * Upstream provider (Enterprise SSO) management\n */\n public upstreamProviders: UpstreamProvidersModule;\n\n /**\n * Create a new organization (requires authentication).\n * The authenticated user becomes the organization owner.\n * Returns JWT tokens with organization context, eliminating the need to re-authenticate.\n *\n * @param payload Organization creation payload\n * @returns Created organization with owner, membership, and JWT tokens\n *\n * @example\n * ```typescript\n * const result = await sso.organizations.create({\n * slug: 'acme-corp',\n * name: 'Acme Corporation'\n * });\n * // Store the new tokens with org context\n * authStore.setTokens(result.access_token, result.refresh_token);\n * ```\n */\n public async create(payload: CreateOrganizationPayload): Promise<CreateOrganizationResponse> {\n const response = await this.http.post<CreateOrganizationResponse>('/api/organizations', payload);\n return response.data;\n }\n\n /**\n * List all organizations the authenticated user is a member of.\n *\n * @param params Optional query parameters for filtering and pagination\n * @returns Array of organization responses\n *\n * @example\n * ```typescript\n * const orgs = await sso.organizations.list({\n * status: 'active',\n * page: 1,\n * limit: 20\n * });\n * ```\n */\n public async list(params?: ListOrganizationsParams): Promise<OrganizationResponse[]> {\n const response = await this.http.get<OrganizationResponse[]>('/api/organizations', { params });\n return response.data;\n }\n\n /**\n * Get detailed information for a specific organization.\n *\n * @param orgSlug Organization slug\n * @returns Organization details\n *\n * @example\n * ```typescript\n * const org = await sso.organizations.get('acme-corp');\n * console.log(org.organization.name, org.membership_count);\n * ```\n */\n public async get(orgSlug: string): Promise<OrganizationResponse> {\n const response = await this.http.get<OrganizationResponse>(`/api/organizations/${orgSlug}`);\n return response.data;\n }\n\n /**\n * Select/switch to a different organization context.\n * Issues a new JWT token with the organization context.\n *\n * This allows users to seamlessly switch between organizations\n * they are members of without re-authenticating.\n *\n * @param orgSlug Organization slug to switch to\n * @returns New tokens with organization context\n *\n * @example\n * ```typescript\n * // Switch to a different organization\n * const result = await sso.organizations.select('acme-corp');\n *\n * // The SDK automatically updates the session with new tokens\n * // API calls will now be made in the context of 'acme-corp'\n * ```\n */\n public async select(orgSlug: string): Promise<SelectOrganizationResponse> {\n const response = await this.http.post<SelectOrganizationResponse>(\n `/api/organizations/${orgSlug}/select`\n );\n return response.data;\n }\n\n /**\n * Update organization details.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param payload Update payload\n * @returns Updated organization details\n *\n * @example\n * ```typescript\n * const updated = await sso.organizations.update('acme-corp', {\n * name: 'Acme Corporation Inc.',\n * max_services: 20\n * });\n * ```\n */\n public async update(orgSlug: string, payload: UpdateOrganizationPayload): Promise<OrganizationResponse> {\n const response = await this.http.patch<OrganizationResponse>(\n `/api/organizations/${orgSlug}`,\n payload\n );\n return response.data;\n }\n\n /**\n * Delete an organization and all its associated data.\n * This is a destructive operation that cannot be undone.\n * Requires 'owner' role.\n *\n * All related data will be cascaded deleted including:\n * - Members and invitations\n * - Services and plans\n * - Subscriptions\n * - OAuth credentials\n * - Audit logs\n *\n * @param orgSlug Organization slug\n *\n * @example\n * ```typescript\n * await sso.organizations.delete('acme-corp');\n * ```\n */\n public async delete(orgSlug: string): Promise<void> {\n await this.http.delete(`/api/organizations/${orgSlug}`);\n }\n\n /**\n * SCIM token management methods\n */\n public scim = {\n /**\n * Create a new SCIM token.\n * The token is only returned once upon creation.\n */\n createToken: async (\n orgSlug: string,\n payload: CreateScimTokenRequest\n ): Promise<ScimTokenResponse> => {\n const response = await this.http.post<ScimTokenResponse>(\n `/api/organizations/${orgSlug}/scim-tokens`,\n payload\n );\n return response.data;\n },\n\n /**\n * List all SCIM tokens.\n */\n listTokens: async (orgSlug: string): Promise<ListScimTokensResponse> => {\n const response = await this.http.get<ListScimTokensResponse>(\n `/api/organizations/${orgSlug}/scim-tokens`\n );\n return response.data;\n },\n\n /**\n * Revoke a SCIM token.\n */\n revokeToken: async (orgSlug: string, tokenId: string): Promise<void> => {\n await this.http.post(`/api/organizations/${orgSlug}/scim-tokens/${tokenId}/revoke`);\n },\n\n /**\n * Delete a SCIM token.\n */\n deleteToken: async (orgSlug: string, tokenId: string): Promise<void> => {\n await this.http.delete(`/api/organizations/${orgSlug}/scim-tokens/${tokenId}`);\n },\n };\n\n /**\n * Member management methods\n */\n public members = {\n /**\n * List all members of an organization.\n *\n * @param orgSlug Organization slug\n * @returns Member list response with pagination metadata\n *\n * @example\n * ```typescript\n * const result = await sso.organizations.members.list('acme-corp');\n * console.log(`Total members: ${result.total}`);\n * result.members.forEach(m => console.log(m.email, m.role));\n * ```\n */\n list: async (orgSlug: string): Promise<MemberListResponse> => {\n const response = await this.http.get<MemberListResponse>(\n `/api/organizations/${orgSlug}/members`\n );\n return response.data;\n },\n\n /**\n * Add a member to the organization (Invite + Accept).\n * This is a convenience method that creates an invitation and immediately accepts it.\n * Useful for testing and admin operations.\n *\n * @param orgSlug Organization slug\n * @param payload Member details (email, role)\n * @returns The created invitation\n */\n add: async (\n orgSlug: string,\n payload: CreateInvitationPayload\n ): Promise<Invitation> => {\n // 1. Create invitation\n const response = await this.http.post<Invitation>(\n `/api/organizations/${orgSlug}/invitations`,\n payload\n );\n\n const invitation = response.data;\n\n // 2. Accept invitation\n await this.http.post(\n `/api/organizations/${orgSlug}/invitations/${invitation.id}/accept`\n );\n\n return invitation;\n },\n\n /**\n * Update a member's role.\n * Requires 'owner' role.\n *\n * @param orgSlug Organization slug\n * @param userId User ID to update\n * @param payload Role update payload\n * @returns Updated member details\n *\n * @example\n * ```typescript\n * await sso.organizations.members.updateRole('acme-corp', 'user-id', {\n * role: 'admin'\n * });\n * ```\n */\n updateRole: async (\n orgSlug: string,\n userId: string,\n payload: UpdateMemberRolePayload\n ): Promise<OrganizationMember> => {\n const response = await this.http.patch<OrganizationMember>(\n `/api/organizations/${orgSlug}/members/${userId}`,\n payload\n );\n return response.data;\n },\n\n /**\n * Remove a member from the organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param userId User ID to remove\n *\n * @example\n * ```typescript\n * await sso.organizations.members.remove('acme-corp', 'user-id');\n * ```\n */\n remove: async (orgSlug: string, userId: string): Promise<void> => {\n await this.http.post(`/api/organizations/${orgSlug}/members/${userId}`);\n },\n\n /**\n * List a member's direct per-service access grants.\n */\n listServiceAccess: async (\n orgSlug: string,\n userId: string\n ): Promise<MemberServiceAccess[]> => {\n const response = await this.http.get<MemberServiceAccess[]>(\n `/api/organizations/${orgSlug}/members/${userId}/service-access`\n );\n return response.data;\n },\n\n /**\n * Replace a member's direct per-service access grants.\n */\n updateServiceAccess: async (\n orgSlug: string,\n userId: string,\n payload: UpdateMemberServiceAccessPayload\n ): Promise<MemberServiceAccess[]> => {\n const response = await this.http.put<MemberServiceAccess[]>(\n `/api/organizations/${orgSlug}/members/${userId}/service-access`,\n payload\n );\n return response.data;\n },\n\n /**\n * Transfer organization ownership to another member.\n * Requires 'owner' role.\n *\n * @param orgSlug Organization slug\n * @param payload Transfer payload with new owner ID\n *\n * @example\n * ```typescript\n * await sso.organizations.members.transferOwnership('acme-corp', {\n * new_owner_user_id: 'new-owner-id'\n * });\n * ```\n */\n transferOwnership: async (orgSlug: string, payload: TransferOwnershipPayload): Promise<void> => {\n await this.http.post(`/api/organizations/${orgSlug}/members/transfer-ownership`, payload);\n },\n };\n\n /**\n * End-user management methods\n * Manage organization's customers (end-users with subscriptions)\n */\n public endUsers = {\n /**\n * List all end-users for an organization.\n * Returns users who have identities (logged in) or subscriptions for the organization's services.\n *\n * @param orgSlug Organization slug\n * @param params Optional query parameters for pagination and filtering\n * @param params.service_slug Optional service slug to filter users by a specific service\n * @returns Paginated list of end-users with their subscriptions and identities\n *\n * @example\n * ```typescript\n * // List all end-users across all services\n * const allUsers = await sso.organizations.endUsers.list('acme-corp', {\n * page: 1,\n * limit: 20\n * });\n *\n * // Filter by specific service\n * const serviceUsers = await sso.organizations.endUsers.list('acme-corp', {\n * service_slug: 'my-app',\n * page: 1,\n * limit: 20\n * });\n * console.log(`Total end-users: ${allUsers.total}`);\n * ```\n */\n list: async (\n orgSlug: string,\n params?: ListEndUsersParams\n ): Promise<EndUserListResponse> => {\n const response = await this.http.get<EndUserListResponse>(\n `/api/organizations/${orgSlug}/users`,\n { params }\n );\n return response.data;\n },\n\n /**\n * Get detailed information about a specific end-user.\n *\n * @param orgSlug Organization slug\n * @param userId User ID\n * @returns End-user details with subscriptions, identities, and session count\n *\n * @example\n * ```typescript\n * const endUser = await sso.organizations.endUsers.get('acme-corp', 'user-id');\n * console.log(`Active sessions: ${endUser.session_count}`);\n * ```\n */\n get: async (orgSlug: string, userId: string): Promise<EndUserDetailResponse> => {\n const response = await this.http.get<EndUserDetailResponse>(\n `/api/organizations/${orgSlug}/users/${userId}`\n );\n return response.data;\n },\n\n /**\n * Revoke all active sessions for an end-user.\n * Requires admin or owner role.\n * This will force the user to re-authenticate.\n *\n * @param orgSlug Organization slug\n * @param userId User ID\n * @returns Response with number of revoked sessions\n *\n * @example\n * ```typescript\n * const result = await sso.organizations.endUsers.revokeSessions('acme-corp', 'user-id');\n * console.log(`Revoked ${result.revoked_count} sessions`);\n * ```\n */\n revokeSessions: async (\n orgSlug: string,\n userId: string\n ): Promise<RevokeSessionsResponse> => {\n const response = await this.http.delete<RevokeSessionsResponse>(\n `/api/organizations/${orgSlug}/users/${userId}/sessions`\n );\n return response.data;\n },\n };\n\n /**\n * BYOO (Bring Your Own OAuth) credential management\n */\n public oauthCredentials = {\n /**\n * Set or update custom OAuth credentials for a provider.\n * This enables white-labeled authentication using the organization's\n * own OAuth application.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param provider OAuth provider\n * @param payload OAuth credentials\n * @returns Created/updated credentials (without secret)\n *\n * @example\n * ```typescript\n * await sso.organizations.oauthCredentials.set('acme-corp', 'github', {\n * client_id: 'Iv1.abc123',\n * client_secret: 'secret-value'\n * });\n * ```\n */\n set: async (\n orgSlug: string,\n provider: OAuthProvider,\n payload: SetOAuthCredentialsPayload\n ): Promise<OAuthCredentials> => {\n const response = await this.http.post<OAuthCredentials>(\n `/api/organizations/${orgSlug}/oauth-credentials/${provider}`,\n payload\n );\n return response.data;\n },\n\n /**\n * Get the configured OAuth credentials for a provider.\n * The secret is never returned.\n *\n * @param orgSlug Organization slug\n * @param provider OAuth provider\n * @returns OAuth credentials (without secret)\n *\n * @example\n * ```typescript\n * const creds = await sso.organizations.oauthCredentials.get('acme-corp', 'github');\n * console.log(creds.client_id);\n * ```\n */\n get: async (orgSlug: string, provider: OAuthProvider): Promise<OAuthCredentials> => {\n const response = await this.http.get<OAuthCredentials>(\n `/api/organizations/${orgSlug}/oauth-credentials/${provider}`\n );\n return response.data;\n },\n };\n\n // ============================================================================\n // SMTP MANAGEMENT\n // ============================================================================\n\n /**\n * Configure SMTP settings for an organization.\n * Only owners and admins can configure SMTP.\n * The organization will use these settings for sending transactional emails\n * (registration, password reset, etc.).\n *\n * @param orgSlug Organization slug\n * @param config SMTP configuration\n * @returns Success message\n *\n * @example\n * ```typescript\n * await sso.organizations.setSmtp('acme-corp', {\n * host: 'smtp.gmail.com',\n * port: 587,\n * username: 'notifications@acme.com',\n * password: 'your-app-password',\n * from_email: 'notifications@acme.com',\n * from_name: 'Acme Corp'\n * });\n * ```\n */\n public async setSmtp(orgSlug: string, config: SetSmtpRequest): Promise<{ message: string }> {\n const response = await this.http.post<{ message: string }>(\n `/api/organizations/${orgSlug}/smtp`,\n config\n );\n return response.data;\n }\n\n /**\n * Get SMTP configuration for an organization.\n * Only owners and admins can view SMTP settings.\n * Password is never returned for security reasons.\n *\n * @param orgSlug Organization slug\n * @returns SMTP configuration (without password)\n *\n * @example\n * ```typescript\n * const config = await sso.organizations.getSmtp('acme-corp');\n * if (config.configured) {\n * console.log('SMTP host:', config.host);\n * }\n * ```\n */\n public async getSmtp(orgSlug: string): Promise<SmtpConfigResponse> {\n const response = await this.http.get<SmtpConfigResponse>(\n `/api/organizations/${orgSlug}/smtp`\n );\n return response.data;\n }\n\n /**\n * Delete SMTP configuration for an organization.\n * The organization will revert to using platform-level SMTP.\n * Only owners and admins can delete SMTP settings.\n *\n * @param orgSlug Organization slug\n * @returns Success message\n *\n * @example\n * ```typescript\n * await sso.organizations.deleteSmtp('acme-corp');\n * // Organization now uses platform SMTP\n * ```\n */\n public async deleteSmtp(orgSlug: string): Promise<{ message: string }> {\n const response = await this.http.delete<{ message: string }>(\n `/api/organizations/${orgSlug}/smtp`\n );\n return response.data;\n }\n\n // ============================================================================\n // CUSTOM DOMAINS & BRANDING\n // ============================================================================\n\n /**\n * Set a custom domain for an organization.\n * This enables white-labeling by allowing the organization to use their own domain\n * (e.g., auth.acme.com) instead of the platform's domain.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param request Custom domain request\n * @returns Domain verification instructions\n *\n * @example\n * ```typescript\n * const verification = await sso.organizations.setCustomDomain('acme-corp', {\n * domain: 'auth.acme.com'\n * });\n * console.log('Verification token:', verification.verification_token);\n * verification.verification_methods.forEach(method => {\n * console.log(method.method, method.instructions);\n * });\n * ```\n */\n public async setCustomDomain(\n orgSlug: string,\n request: SetCustomDomainRequest\n ): Promise<DomainVerificationResponse> {\n const response = await this.http.post<DomainVerificationResponse>(\n `/api/organizations/${orgSlug}/domain`,\n request\n );\n return response.data;\n }\n\n /**\n * Verify a custom domain by checking DNS TXT record or HTTP file.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @returns Verification result\n *\n * @example\n * ```typescript\n * const result = await sso.organizations.verifyCustomDomain('acme-corp');\n * if (result.verified) {\n * console.log('Domain verified successfully!');\n * } else {\n * console.log('Verification failed:', result.message);\n * }\n * ```\n */\n public async verifyCustomDomain(orgSlug: string): Promise<DomainVerificationResult> {\n const response = await this.http.post<DomainVerificationResult>(\n `/api/organizations/${orgSlug}/domain/verify`\n );\n return response.data;\n }\n\n /**\n * Get custom domain configuration for an organization.\n *\n * @param orgSlug Organization slug\n * @returns Domain configuration\n *\n * @example\n * ```typescript\n * const config = await sso.organizations.getDomainConfiguration('acme-corp');\n * if (config.custom_domain && config.domain_verified) {\n * console.log('Custom domain active:', config.custom_domain);\n * }\n * ```\n */\n public async getDomainConfiguration(orgSlug: string): Promise<DomainConfiguration> {\n const response = await this.http.get<DomainConfiguration>(\n `/api/organizations/${orgSlug}/domain`\n );\n return response.data;\n }\n\n /**\n * Delete custom domain configuration.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n *\n * @example\n * ```typescript\n * await sso.organizations.deleteCustomDomain('acme-corp');\n * // Organization reverts to using platform domain\n * ```\n */\n public async deleteCustomDomain(orgSlug: string): Promise<void> {\n await this.http.delete(`/api/organizations/${orgSlug}/domain`);\n }\n\n /**\n * Update branding configuration (logo and primary color).\n * This controls the visual appearance of authentication pages.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param request Branding configuration\n * @returns Updated branding configuration\n *\n * @example\n * ```typescript\n * await sso.organizations.updateBranding('acme-corp', {\n * logo_url: 'https://cdn.acme.com/logo.png',\n * primary_color: '#FF5733'\n * });\n * ```\n */\n public async updateBranding(\n orgSlug: string,\n request: UpdateBrandingRequest\n ): Promise<BrandingConfiguration> {\n const response = await this.http.patch<BrandingConfiguration>(\n `/api/organizations/${orgSlug}/branding`,\n request\n );\n return response.data;\n }\n\n /**\n * Get branding configuration for an organization.\n *\n * @param orgSlug Organization slug\n * @returns Branding configuration\n *\n * @example\n * ```typescript\n * const branding = await sso.organizations.getBranding('acme-corp');\n * if (branding.logo_url) {\n * console.log('Logo URL:', branding.logo_url);\n * }\n * ```\n */\n public async getBranding(orgSlug: string): Promise<BrandingConfiguration> {\n const response = await this.http.get<BrandingConfiguration>(\n `/api/organizations/${orgSlug}/branding`\n );\n return response.data;\n }\n\n /**\n * Get public branding configuration (no authentication required).\n * This endpoint is used by login pages to display organization branding.\n *\n * @param orgSlug Organization slug\n * @returns Branding configuration\n *\n * @example\n * ```typescript\n * // Can be called without authentication\n * const branding = await sso.organizations.getPublicBranding('acme-corp');\n * ```\n */\n public async getPublicBranding(orgSlug: string): Promise<BrandingConfiguration> {\n const response = await this.http.get<BrandingConfiguration>(\n `/api/organizations/${orgSlug}/branding/public`\n );\n return response.data;\n }\n\n // ============================================================================\n // RISK SETTINGS\n // ============================================================================\n\n /**\n * Risk settings management methods\n */\n public riskSettings = {\n /**\n * Get risk settings for an organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @returns Risk settings configuration\n *\n * @example\n * ```typescript\n * const settings = await sso.organizations.riskSettings.get('acme-corp');\n * console.log('Enforcement mode:', settings.enforcement_mode);\n * console.log('Low threshold:', settings.low_threshold);\n * ```\n */\n get: async (orgSlug: string): Promise<GetRiskSettingsResponse> => {\n const response = await this.http.get<GetRiskSettingsResponse>(\n `/api/organizations/${orgSlug}/risk-settings`\n );\n return response.data;\n },\n\n /**\n * Update risk settings for an organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param payload Risk settings update payload\n * @returns Updated risk settings\n *\n * @example\n * ```typescript\n * const result = await sso.organizations.riskSettings.update('acme-corp', {\n * enforcement_mode: 'challenge',\n * low_threshold: 30,\n * medium_threshold: 70,\n * new_device_score: 20,\n * impossible_travel_score: 50\n * });\n * console.log(result.message);\n * ```\n */\n update: async (\n orgSlug: string,\n payload: UpdateRiskSettingsRequest\n ): Promise<UpdateRiskSettingsResponse> => {\n const response = await this.http.put<UpdateRiskSettingsResponse>(\n `/api/organizations/${orgSlug}/risk-settings`,\n payload\n );\n return response.data;\n },\n\n /**\n * Reset risk settings to default values.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @returns Reset confirmation with default values\n *\n * @example\n * ```typescript\n * const result = await sso.organizations.riskSettings.reset('acme-corp');\n * console.log('Risk settings reset to defaults');\n * ```\n */\n reset: async (orgSlug: string): Promise<UpdateRiskSettingsResponse> => {\n const response = await this.http.post<UpdateRiskSettingsResponse>(\n `/api/organizations/${orgSlug}/risk-settings/reset`\n );\n return response.data;\n },\n };\n\n // ============================================================================\n // SIEM CONFIGURATIONS\n // ============================================================================\n\n /**\n * SIEM (Security Information and Event Management) configuration methods\n */\n public siem = {\n /**\n * Create a new SIEM configuration.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param payload SIEM configuration payload\n * @returns Created SIEM configuration\n *\n * @example\n * ```typescript\n * const config = await sso.organizations.siem.create('acme-corp', {\n * name: 'Datadog Integration',\n * provider_type: 'Datadog',\n * endpoint_url: 'https://http-intake.logs.datadoghq.com/v1/input',\n * api_key: 'dd-api-key',\n * batch_size: 100\n * });\n * ```\n */\n create: async (\n orgSlug: string,\n payload: CreateSiemConfigRequest\n ): Promise<SiemConfigResponse> => {\n const response = await this.http.post<SiemConfigResponse>(\n `/api/organizations/${orgSlug}/siem-configs`,\n payload\n );\n return response.data;\n },\n\n /**\n * List all SIEM configurations for an organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @returns List of SIEM configurations\n *\n * @example\n * ```typescript\n * const result = await sso.organizations.siem.list('acme-corp');\n * console.log(`Total SIEM configs: ${result.total}`);\n * result.siem_configs.forEach(config => {\n * console.log(config.name, config.provider_type, config.enabled);\n * });\n * ```\n */\n list: async (orgSlug: string): Promise<ListSiemConfigsResponse> => {\n const response = await this.http.get<ListSiemConfigsResponse>(\n `/api/organizations/${orgSlug}/siem-configs`\n );\n return response.data;\n },\n\n /**\n * Get a specific SIEM configuration.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param configId SIEM configuration ID\n * @returns SIEM configuration\n *\n * @example\n * ```typescript\n * const config = await sso.organizations.siem.get('acme-corp', 'config-id');\n * console.log(config.name, config.endpoint_url);\n * ```\n */\n get: async (orgSlug: string, configId: string): Promise<SiemConfigResponse> => {\n const response = await this.http.get<SiemConfigResponse>(\n `/api/organizations/${orgSlug}/siem-configs/${configId}`\n );\n return response.data;\n },\n\n /**\n * Update a SIEM configuration.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param configId SIEM configuration ID\n * @param payload Update payload\n * @returns Updated SIEM configuration\n *\n * @example\n * ```typescript\n * const updated = await sso.organizations.siem.update('acme-corp', 'config-id', {\n * enabled: false,\n * batch_size: 200\n * });\n * ```\n */\n update: async (\n orgSlug: string,\n configId: string,\n payload: UpdateSiemConfigRequest\n ): Promise<SiemConfigResponse> => {\n const response = await this.http.patch<SiemConfigResponse>(\n `/api/organizations/${orgSlug}/siem-configs/${configId}`,\n payload\n );\n return response.data;\n },\n\n /**\n * Delete a SIEM configuration.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param configId SIEM configuration ID\n *\n * @example\n * ```typescript\n * await sso.organizations.siem.delete('acme-corp', 'config-id');\n * console.log('SIEM configuration deleted');\n * ```\n */\n delete: async (orgSlug: string, configId: string): Promise<void> => {\n await this.http.delete(`/api/organizations/${orgSlug}/siem-configs/${configId}`);\n },\n\n /**\n * Test connection to a SIEM endpoint.\n * Sends a test event to verify the configuration.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param configId SIEM configuration ID\n * @returns Test result\n *\n * @example\n * ```typescript\n * const result = await sso.organizations.siem.test('acme-corp', 'config-id');\n * if (result.success) {\n * console.log('Connection successful:', result.message);\n * } else {\n * console.error('Connection failed:', result.message);\n * }\n * ```\n */\n test: async (orgSlug: string, configId: string): Promise<TestConnectionResponse> => {\n const response = await this.http.post<TestConnectionResponse>(\n `/api/organizations/${orgSlug}/siem-configs/${configId}/test`\n );\n return response.data;\n },\n };\n\n // ============================================================================\n // BILLING\n // ============================================================================\n\n /**\n * Billing and subscription management methods\n */\n public billing = {\n /**\n * Get billing information for an organization.\n * Returns whether a billing account exists and which provider is being used.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @returns Billing information\n *\n * @example\n * ```typescript\n * const info = await sso.organizations.billing.getInfo('acme-corp');\n * if (info.has_billing_account) {\n * console.log('Billing provider:', info.provider);\n * }\n * ```\n */\n getInfo: async (orgSlug: string): Promise<{ has_billing_account: boolean; provider: string | null }> => {\n const response = await this.http.get<{ has_billing_account: boolean; provider: string | null }>(\n `/api/organizations/${orgSlug}/billing/info`\n );\n return response.data;\n },\n\n /**\n * Create a billing portal session.\n * Redirects the user to the billing provider's self-service portal to manage their subscription,\n * update payment methods, view invoices, etc.\n * Requires 'owner' role.\n *\n * @param orgSlug Organization slug\n * @param returnUrl URL to redirect the user to after they leave the portal\n * @returns Object containing the portal session URL\n *\n * @example\n * ```typescript\n * const session = await sso.organizations.billing.createPortalSession('acme-corp', {\n * return_url: 'https://app.acme.com/billing'\n * });\n * // Redirect user to billing portal\n * window.location.href = session.url;\n * ```\n */\n createPortalSession: async (\n orgSlug: string,\n payload: { return_url: string }\n ): Promise<{ url: string }> => {\n const response = await this.http.post<{ url: string }>(\n `/api/organizations/${orgSlug}/billing/portal`,\n payload\n );\n return response.data;\n },\n };\n\n /**\n * Security & Risk insights\n */\n public security = {\n /**\n * Get risk events for an organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param params Query parameters\n */\n getRiskEvents: async (\n orgSlug: string,\n params?: RiskEventsQuery\n ): Promise<RiskEventResponse[]> => {\n const response = await this.http.get<RiskEventResponse[]>(\n `/api/organizations/${orgSlug}/risk-events`,\n { params }\n );\n return response.data;\n },\n };\n\n /**\n * Role management methods\n */\n public roles = {\n /**\n * List all custom roles for an organization.\n */\n list: async (orgSlug: string): Promise<RoleResponse[]> => {\n const response = await this.http.get<RoleResponse[]>(\n `/api/organizations/${orgSlug}/roles`\n );\n return response.data;\n },\n\n /**\n * Get details of a specific role.\n */\n get: async (orgSlug: string, roleId: string): Promise<RoleResponse> => {\n const response = await this.http.get<RoleResponse>(\n `/api/organizations/${orgSlug}/roles/${roleId}`\n );\n return response.data;\n },\n\n /**\n * Create a new custom role.\n */\n create: async (orgSlug: string, payload: CreateRoleRequest): Promise<RoleResponse> => {\n const response = await this.http.post<RoleResponse>(\n `/api/organizations/${orgSlug}/roles`,\n payload\n );\n return response.data;\n },\n\n /**\n * Update an existing role.\n */\n update: async (\n orgSlug: string,\n roleId: string,\n payload: UpdateRoleRequest\n ): Promise<RoleResponse> => {\n const response = await this.http.put<RoleResponse>(\n `/api/organizations/${orgSlug}/roles/${roleId}`,\n payload\n );\n return response.data;\n },\n\n /**\n * Delete a role.\n */\n delete: async (orgSlug: string, roleId: string): Promise<void> => {\n await this.http.delete(`/api/organizations/${orgSlug}/roles/${roleId}`);\n },\n };\n\n // ============================================================================\n // BYOP - BRING YOUR OWN PAYMENT\n // ============================================================================\n\n /**\n * BYOP (Bring Your Own Payment) credential management.\n * Allows organizations to configure their own billing provider credentials\n * to charge their end-users directly.\n */\n public billingCredentials = {\n /**\n * Get the status of billing credentials for a provider.\n * Returns whether credentials are configured and the mode (test/live).\n * Requires 'owner' role.\n *\n * @param orgSlug Organization slug\n * @param provider Billing provider ('stripe' or 'polar')\n * @returns Credential configuration status\n *\n * @example\n * ```typescript\n * const status = await sso.organizations.billingCredentials.get('acme-corp', 'stripe');\n * if (status.configured) {\n * console.log('Mode:', status.mode); // 'test' or 'live'\n * console.log('Enabled:', status.enabled);\n * }\n * ```\n */\n get: async (\n orgSlug: string,\n provider: 'stripe' | 'polar'\n ): Promise<{\n configured: boolean;\n provider: string;\n mode: 'test' | 'live' | null;\n enabled: boolean;\n }> => {\n const response = await this.http.get<{\n configured: boolean;\n provider: string;\n mode: 'test' | 'live' | null;\n enabled: boolean;\n }>(`/api/organizations/${orgSlug}/billing-credentials/${provider}`);\n return response.data;\n },\n\n /**\n * Set or update billing credentials for a provider.\n * Enables the organization to charge their end-users using their own\n * payment provider account.\n * Requires 'owner' role.\n *\n * @param orgSlug Organization slug\n * @param provider Billing provider ('stripe' or 'polar')\n * @param payload Billing credentials\n *\n * @example\n * ```typescript\n * await sso.organizations.billingCredentials.set('acme-corp', 'stripe', {\n * api_key: 'sk_live_...',\n * webhook_secret: 'whsec_...',\n * mode: 'live'\n * });\n * ```\n */\n set: async (\n orgSlug: string,\n provider: 'stripe' | 'polar',\n payload: {\n api_key: string;\n webhook_secret: string;\n mode: 'test' | 'live';\n }\n ): Promise<void> => {\n await this.http.post(\n `/api/organizations/${orgSlug}/billing-credentials/${provider}`,\n payload\n );\n },\n\n /**\n * Delete billing credentials for a provider.\n * The organization will no longer be able to charge end-users directly.\n * Requires 'owner' role.\n *\n * @param orgSlug Organization slug\n * @param provider Billing provider ('stripe' or 'polar')\n *\n * @example\n * ```typescript\n * await sso.organizations.billingCredentials.delete('acme-corp', 'stripe');\n * ```\n */\n delete: async (\n orgSlug: string,\n provider: 'stripe' | 'polar'\n ): Promise<void> => {\n await this.http.delete(\n `/api/organizations/${orgSlug}/billing-credentials/${provider}`\n );\n },\n };\n}\n","import { HttpClient } from '../http';\nimport {\n Service,\n ServiceListResponse,\n CreateServicePayload,\n CreateServiceResponse,\n RotateServiceSecretResponse,\n UpdateServicePayload,\n PlanResponse,\n CreatePlanPayload,\n UpdatePlanPayload,\n ApiKey,\n ApiKeyCreateResponse,\n CreateApiKeyPayload,\n ListApiKeysResponse,\n SamlConfig,\n ConfigureSamlPayload,\n ConfigureSamlResponse,\n SamlCertificate,\n CreateCheckoutPayload,\n CreateCheckoutResponse,\n} from '../types';\n\n/**\n * Service management methods\n */\nexport class ServicesModule {\n constructor(private http: HttpClient) { }\n\n /**\n * Create a new service for an organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param payload Service creation payload\n * @returns Created service with details\n *\n * @example\n * ```typescript\n * const result = await sso.services.create('acme-corp', {\n * slug: 'main-app',\n * name: 'Main Application',\n * service_type: 'web',\n * github_scopes: ['user:email', 'read:org'],\n * redirect_uris: ['https://app.acme.com/callback']\n * });\n * console.log(result.service.client_id);\n * ```\n */\n public async create(orgSlug: string, payload: CreateServicePayload): Promise<CreateServiceResponse> {\n const response = await this.http.post<CreateServiceResponse>(\n `/api/organizations/${orgSlug}/services`,\n payload\n );\n return response.data;\n }\n\n /**\n * List all services for an organization.\n *\n * @param orgSlug Organization slug\n * @returns Service list response with usage metadata\n *\n * @example\n * ```typescript\n * const result = await sso.services.list('acme-corp');\n * console.log(`Using ${result.usage.current_services} of ${result.usage.max_services} services`);\n * result.services.forEach(svc => console.log(svc.name, svc.client_id));\n * ```\n */\n public async list(orgSlug: string): Promise<ServiceListResponse> {\n const response = await this.http.get<ServiceListResponse>(`/api/organizations/${orgSlug}/services`);\n return response.data;\n }\n\n /**\n * Get detailed information for a specific service.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @returns Service details\n *\n * @example\n * ```typescript\n * const service = await sso.services.get('acme-corp', 'main-app');\n * console.log(service.name, service.client_id);\n * ```\n */\n public async get(orgSlug: string, serviceSlug: string): Promise<Service> {\n const response = await this.http.get<Service>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}`\n );\n return response.data;\n }\n\n /**\n * Update service configuration.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @param payload Update payload\n * @returns Updated service\n *\n * @example\n * ```typescript\n * const updated = await sso.services.update('acme-corp', 'main-app', {\n * name: 'Main Application v2',\n * redirect_uris: ['https://app.acme.com/callback', 'https://app.acme.com/oauth']\n * });\n * ```\n */\n public async update(\n orgSlug: string,\n serviceSlug: string,\n payload: UpdateServicePayload\n ): Promise<Service> {\n const response = await this.http.patch<Service>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}`,\n payload\n );\n return response.data;\n }\n\n /**\n * Delete a service.\n * Requires 'owner' role.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n *\n * @example\n * ```typescript\n * await sso.services.delete('acme-corp', 'old-app');\n * ```\n */\n public async delete(orgSlug: string, serviceSlug: string): Promise<void> {\n await this.http.delete(`/api/organizations/${orgSlug}/services/${serviceSlug}`);\n }\n\n /**\n * Rotate a service client secret.\n * The new secret is returned once and cannot be retrieved later.\n */\n public async rotateSecret(\n orgSlug: string,\n serviceSlug: string\n ): Promise<RotateServiceSecretResponse> {\n const response = await this.http.post<RotateServiceSecretResponse>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/secret/rotate`,\n {}\n );\n return response.data;\n }\n\n /**\n * Plan management methods\n */\n public plans = {\n /**\n * Create a new subscription plan for a service.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @param payload Plan creation payload\n * @returns Created plan with subscription count\n *\n * @example\n * ```typescript\n * const result = await sso.services.plans.create('acme-corp', 'main-app', {\n * name: 'pro',\n * price_cents: 2999,\n * currency: 'usd',\n * features: ['api-access', 'advanced-analytics', 'priority-support']\n * });\n * console.log(result.plan.name, result.subscription_count);\n * ```\n */\n create: async (\n orgSlug: string,\n serviceSlug: string,\n payload: CreatePlanPayload\n ): Promise<PlanResponse> => {\n const response = await this.http.post<PlanResponse>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/plans`,\n payload\n );\n return response.data;\n },\n\n /**\n * List all plans for a service.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @returns Array of plans with subscription counts\n *\n * @example\n * ```typescript\n * const plans = await sso.services.plans.list('acme-corp', 'main-app');\n * plans.forEach(p => console.log(p.plan.name, p.subscription_count));\n * ```\n */\n list: async (orgSlug: string, serviceSlug: string): Promise<PlanResponse[]> => {\n const response = await this.http.get<PlanResponse[]>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/plans`\n );\n return response.data;\n },\n\n /**\n * Update a subscription plan.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @param planId Plan ID\n * @param payload Plan update payload\n * @returns Updated plan with subscription count\n *\n * @example\n * ```typescript\n * const result = await sso.services.plans.update('acme-corp', 'main-app', 'plan_123', {\n * name: 'Pro Plus',\n * price_cents: 3999,\n * currency: 'usd',\n * features: ['api-access', 'advanced-analytics', 'priority-support', 'custom-integrations']\n * });\n * console.log('Updated plan:', result.plan.name);\n * ```\n */\n update: async (\n orgSlug: string,\n serviceSlug: string,\n planId: string,\n payload: UpdatePlanPayload\n ): Promise<PlanResponse> => {\n const response = await this.http.patch<PlanResponse>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/plans/${planId}`,\n payload\n );\n return response.data;\n },\n\n /**\n * Delete a subscription plan.\n * Requires 'owner' or 'admin' role.\n *\n * WARNING: This will fail if the plan has active subscriptions.\n * You must migrate or cancel all subscriptions before deleting a plan.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @param planId Plan ID\n *\n * @example\n * ```typescript\n * try {\n * await sso.services.plans.delete('acme-corp', 'main-app', 'plan_123');\n * console.log('Plan deleted successfully');\n * } catch (error) {\n * console.error('Cannot delete plan with active subscriptions');\n * }\n * ```\n */\n delete: async (orgSlug: string, serviceSlug: string, planId: string): Promise<void> => {\n await this.http.delete(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/plans/${planId}`\n );\n },\n };\n\n /**\n * API Key management methods for service-to-service authentication\n */\n public apiKeys = {\n /**\n * Create a new API key for a service.\n * Requires 'owner' or 'admin' role.\n *\n * IMPORTANT: The full API key is only returned once upon creation.\n * Store it securely as it cannot be retrieved again.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @param payload API key creation payload\n * @returns Created API key with the full key value\n *\n * @example\n * ```typescript\n * const apiKey = await sso.services.apiKeys.create('acme-corp', 'main-app', {\n * name: 'Production Backend',\n * permissions: ['read:users', 'write:subscriptions'],\n * expires_in_days: 90\n * });\n *\n * // IMPORTANT: Store this key securely - it won't be shown again\n * console.log('API Key:', apiKey.key);\n * console.log('Prefix:', apiKey.prefix);\n * ```\n */\n create: async (\n orgSlug: string,\n serviceSlug: string,\n payload: CreateApiKeyPayload\n ): Promise<ApiKeyCreateResponse> => {\n const response = await this.http.post<ApiKeyCreateResponse>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/api-keys`,\n payload\n );\n return response.data;\n },\n\n /**\n * List all API keys for a service.\n * Note: The full key values are not included in this response.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @param options Optional query parameters for pagination\n * @returns List of API keys with metadata\n *\n * @example\n * ```typescript\n * const result = await sso.services.apiKeys.list('acme-corp', 'main-app', {\n * limit: 50,\n * offset: 0\n * });\n *\n * console.log(`Total API keys: ${result.total}`);\n * result.api_keys.forEach(key => {\n * console.log(`${key.name} (${key.prefix})`);\n * console.log(`Permissions: ${key.permissions.join(', ')}`);\n * console.log(`Last used: ${key.last_used_at || 'Never'}`);\n * });\n * ```\n */\n list: async (\n orgSlug: string,\n serviceSlug: string,\n options?: { limit?: number; offset?: number }\n ): Promise<ListApiKeysResponse> => {\n const queryParams = new URLSearchParams();\n if (options?.limit) queryParams.set('limit', options.limit.toString());\n if (options?.offset) queryParams.set('offset', options.offset.toString());\n\n const query = queryParams.toString() ? `?${queryParams.toString()}` : '';\n const response = await this.http.get<ListApiKeysResponse>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/api-keys${query}`\n );\n return response.data;\n },\n\n /**\n * Get details for a specific API key.\n * Note: The full key value is not included in this response.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @param apiKeyId API key ID\n * @returns API key details\n *\n * @example\n * ```typescript\n * const apiKey = await sso.services.apiKeys.get('acme-corp', 'main-app', 'key_abc123');\n * console.log(`Name: ${apiKey.name}`);\n * console.log(`Permissions: ${apiKey.permissions.join(', ')}`);\n * console.log(`Expires: ${apiKey.expires_at || 'Never'}`);\n * ```\n */\n get: async (\n orgSlug: string,\n serviceSlug: string,\n apiKeyId: string\n ): Promise<ApiKey> => {\n const response = await this.http.get<ApiKey>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/api-keys/${apiKeyId}`\n );\n return response.data;\n },\n\n /**\n * Delete an API key.\n * Requires 'owner' or 'admin' role.\n *\n * WARNING: This action is immediate and cannot be undone.\n * Any services using this key will lose access immediately.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @param apiKeyId API key ID\n *\n * @example\n * ```typescript\n * await sso.services.apiKeys.delete('acme-corp', 'main-app', 'key_abc123');\n * console.log('API key deleted successfully');\n * ```\n */\n delete: async (\n orgSlug: string,\n serviceSlug: string,\n apiKeyId: string\n ): Promise<void> => {\n await this.http.delete(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/api-keys/${apiKeyId}`\n );\n },\n };\n\n /**\n * SAML 2.0 Identity Provider (IdP) management methods\n *\n * Configure your service as a SAML IdP to enable SSO into third-party applications\n * (Salesforce, AWS, Google Workspace, etc.)\n */\n public saml = {\n /**\n * Configure SAML IdP settings for a service.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @param payload SAML configuration payload\n * @returns Configuration success response\n *\n * @example\n * ```typescript\n * const result = await sso.services.saml.configure('acme-corp', 'main-app', {\n * enabled: true,\n * entity_id: 'https://salesforce.example.com',\n * acs_url: 'https://salesforce.example.com/saml/acs',\n * name_id_format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',\n * attribute_mapping: {\n * email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'\n * },\n * sign_assertions: true,\n * sign_response: true\n * });\n * ```\n */\n configure: async (\n orgSlug: string,\n serviceSlug: string,\n payload: ConfigureSamlPayload\n ): Promise<ConfigureSamlResponse> => {\n const response = await this.http.post<ConfigureSamlResponse>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/saml`,\n payload\n );\n return response.data;\n },\n\n /**\n * Get current SAML IdP configuration for a service.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @returns Current SAML configuration\n *\n * @example\n * ```typescript\n * const config = await sso.services.saml.getConfig('acme-corp', 'main-app');\n * if (config.enabled && config.has_certificate) {\n * console.log('SAML IdP is ready');\n * console.log('Entity ID:', config.entity_id);\n * console.log('ACS URL:', config.acs_url);\n * }\n * ```\n */\n getConfig: async (orgSlug: string, serviceSlug: string): Promise<SamlConfig> => {\n const response = await this.http.get<SamlConfig>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/saml`\n );\n return response.data;\n },\n\n /**\n * Delete SAML IdP configuration and deactivate all certificates.\n * Requires 'owner' or 'admin' role.\n *\n * WARNING: This will break SSO for all third-party applications using this IdP.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n *\n * @example\n * ```typescript\n * await sso.services.saml.deleteConfig('acme-corp', 'main-app');\n * console.log('SAML IdP configuration deleted');\n * ```\n */\n deleteConfig: async (orgSlug: string, serviceSlug: string): Promise<ConfigureSamlResponse> => {\n const response = await this.http.delete<ConfigureSamlResponse>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/saml`\n );\n return response.data;\n },\n\n /**\n * Initiate an IdP-initiated SAML login.\n * Returns an HTML page with an auto-submitting form that POSTs the SAML assertion to the Service Provider.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @returns HTML page with auto-submitting form\n *\n * @example\n * ```typescript\n * const html = await sso.services.saml.initiateLogin('acme-corp', 'salesforce');\n * document.body.innerHTML = html; // Auto-submits\n * ```\n */\n initiateLogin: async (orgSlug: string, serviceSlug: string): Promise<string> => {\n const response = await this.http.get<string>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/saml/login`\n );\n return response.data;\n },\n\n /**\n * Generate a new SAML signing certificate for the IdP.\n * Requires 'owner' or 'admin' role.\n *\n * IMPORTANT: This automatically deactivates any existing active certificates.\n * Provide the returned certificate to your Service Provider during SAML setup.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @returns Certificate information including public key\n *\n * @example\n * ```typescript\n * const cert = await sso.services.saml.generateCertificate('acme-corp', 'main-app');\n * console.log('Certificate generated, valid until:', cert.valid_until);\n * console.log('Public certificate:\\n', cert.public_key);\n * // Provide cert.public_key to your Service Provider\n * ```\n */\n generateCertificate: async (\n orgSlug: string,\n serviceSlug: string\n ): Promise<SamlCertificate> => {\n const response = await this.http.post<SamlCertificate>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/saml/certificate`,\n {}\n );\n return response.data;\n },\n\n /**\n * Get the active SAML signing certificate.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @returns Active certificate information\n *\n * @example\n * ```typescript\n * try {\n * const cert = await sso.services.saml.getCertificate('acme-corp', 'main-app');\n * console.log('Certificate expires:', cert.valid_until);\n * } catch (error) {\n * console.log('No active certificate - generate one first');\n * }\n * ```\n */\n getCertificate: async (orgSlug: string, serviceSlug: string): Promise<SamlCertificate> => {\n const response = await this.http.get<SamlCertificate>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/saml/certificate`\n );\n return response.data;\n },\n\n /**\n * Get the SAML IdP metadata URL for this service.\n * This URL can be provided to Service Providers for automatic configuration.\n *\n * @param baseURL SSO platform base URL\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @returns Metadata URL\n *\n * @example\n * ```typescript\n * const metadataUrl = sso.services.saml.getMetadataUrl(\n * 'https://sso.example.com',\n * 'acme-corp',\n * 'main-app'\n * );\n * console.log('Provide this URL to your SP:', metadataUrl);\n * // https://sso.example.com/saml/acme-corp/main-app/metadata\n * ```\n */\n getMetadataUrl: (baseURL: string, orgSlug: string, serviceSlug: string): string => {\n return `${baseURL}/saml/${orgSlug}/${serviceSlug}/metadata`;\n },\n\n /**\n * Get the SAML SSO endpoint URL for this service.\n * This is where Service Providers should redirect users to initiate SSO.\n *\n * @param baseURL SSO platform base URL\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @returns SSO endpoint URL\n *\n * @example\n * ```typescript\n * const ssoUrl = sso.services.saml.getSsoUrl(\n * 'https://sso.example.com',\n * 'acme-corp',\n * 'main-app'\n * );\n * console.log('SSO endpoint:', ssoUrl);\n * // https://sso.example.com/saml/acme-corp/main-app/sso\n * ```\n */\n getSsoUrl: (baseURL: string, orgSlug: string, serviceSlug: string): string => {\n return `${baseURL}/saml/${orgSlug}/${serviceSlug}/sso`;\n },\n };\n\n /**\n * Stripe billing and checkout methods\n */\n public billing = {\n /**\n * Create a Stripe checkout session for the authenticated user to subscribe to a plan.\n * Requires organization membership.\n *\n * IMPORTANT: The plan must have a `stripe_price_id` configured to be available for purchase.\n *\n * @param orgSlug Organization slug\n * @param serviceSlug Service slug\n * @param payload Checkout payload containing plan_id and redirect URLs\n * @returns Checkout session with URL to redirect user to\n *\n * @example\n * ```typescript\n * const checkout = await sso.services.billing.createCheckout('acme-corp', 'main-app', {\n * plan_id: 'plan_pro',\n * success_url: 'https://app.acme.com/billing/success?session_id={CHECKOUT_SESSION_ID}',\n * cancel_url: 'https://app.acme.com/billing/cancel'\n * });\n *\n * // Redirect user to Stripe checkout\n * window.location.href = checkout.checkout_url;\n * ```\n */\n createCheckout: async (\n orgSlug: string,\n serviceSlug: string,\n payload: CreateCheckoutPayload\n ): Promise<CreateCheckoutResponse> => {\n const response = await this.http.post<CreateCheckoutResponse>(\n `/api/organizations/${orgSlug}/services/${serviceSlug}/checkout`,\n payload\n );\n return response.data;\n },\n };\n}\n","import { HttpClient } from '../http';\nimport {\n Invitation,\n InvitationWithOrg,\n CreateInvitationPayload,\n AcceptInvitationPayload,\n DeclineInvitationPayload,\n} from '../types';\n\n/**\n * Invitation management methods\n */\nexport class InvitationsModule {\n constructor(private http: HttpClient) { }\n\n /**\n * Create and send an invitation to join an organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param payload Invitation payload with email and role\n * @returns Created invitation\n *\n * @example\n * ```typescript\n * const invitation = await sso.invitations.create('acme-corp', {\n * email: 'newuser@example.com',\n * role: 'member'\n * });\n * ```\n */\n public async create(orgSlug: string, payload: CreateInvitationPayload): Promise<Invitation> {\n const response = await this.http.post<Invitation>(\n `/api/organizations/${orgSlug}/invitations`,\n payload\n );\n return response.data;\n }\n\n /**\n * List all invitations for an organization.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @returns Array of invitations\n *\n * @example\n * ```typescript\n * const invitations = await sso.invitations.listForOrg('acme-corp');\n * invitations.forEach(inv => console.log(inv.invitee_email, inv.status));\n * ```\n */\n public async listForOrg(orgSlug: string): Promise<Invitation[]> {\n const response = await this.http.get<Invitation[]>(\n `/api/organizations/${orgSlug}/invitations`\n );\n return response.data;\n }\n\n /**\n * Cancel a pending invitation.\n * Requires 'owner' or 'admin' role.\n *\n * @param orgSlug Organization slug\n * @param invitationId Invitation ID to cancel\n *\n * @example\n * ```typescript\n * await sso.invitations.cancel('acme-corp', 'invitation-id');\n * ```\n */\n public async cancel(orgSlug: string, invitationId: string): Promise<void> {\n await this.http.post(`/api/organizations/${orgSlug}/invitations/${invitationId}`);\n }\n\n /**\n * List invitations received by the current authenticated user.\n *\n * @returns Array of invitations with organization details\n *\n * @example\n * ```typescript\n * const myInvitations = await sso.invitations.listForUser();\n * myInvitations.forEach(inv => {\n * console.log(`Invited to ${inv.organization_name} as ${inv.role}`);\n * });\n * ```\n */\n public async listForUser(): Promise<InvitationWithOrg[]> {\n const response = await this.http.get<InvitationWithOrg[]>('/api/invitations');\n return response.data;\n }\n\n /**\n * Accept an invitation using its token.\n *\n * @param token Invitation token\n *\n * @example\n * ```typescript\n * await sso.invitations.accept('invitation-token-from-email');\n * ```\n */\n public async accept(token: string): Promise<void> {\n const payload: AcceptInvitationPayload = { token };\n await this.http.post('/api/invitations/accept', payload);\n }\n\n /**\n * Accept one of the current user's invitations by invitation ID.\n *\n * @param invitationId Invitation ID\n */\n public async acceptById(invitationId: string): Promise<void> {\n await this.http.post(`/api/invitations/${invitationId}/accept`);\n }\n\n /**\n * Decline an invitation using its token.\n *\n * @param token Invitation token\n *\n * @example\n * ```typescript\n * await sso.invitations.decline('invitation-token-from-email');\n * ```\n */\n public async decline(token: string): Promise<void> {\n const payload: DeclineInvitationPayload = { token };\n await this.http.post('/api/invitations/decline', payload);\n }\n\n /**\n * Decline one of the current user's invitations by invitation ID.\n *\n * @param invitationId Invitation ID\n */\n public async declineById(invitationId: string): Promise<void> {\n await this.http.post(`/api/invitations/${invitationId}/decline`);\n }\n}\n","import { HttpClient } from '../http';\nimport {\n Organization,\n OrganizationTier,\n PlatformOrganizationsListResponse,\n ListPlatformOrganizationsParams,\n ApproveOrganizationPayload,\n RejectOrganizationPayload,\n UpdateOrganizationTierPayload,\n PromotePlatformOwnerPayload,\n AuditLogEntry,\n GetAuditLogParams,\n PlatformOverviewMetrics,\n OrganizationStatusBreakdown,\n GrowthTrendPoint,\n LoginActivityPoint,\n TopOrganization,\n RecentOrganization,\n PlatformAnalyticsDateRangeParams,\n ImpersonateRequest,\n ImpersonateResponse,\n} from '../types';\n\n/**\n * Platform owner administration methods.\n * All methods require a Platform Owner JWT.\n */\nexport class PlatformModule {\n constructor(private http: HttpClient) { }\n\n /**\n * List all available organization tiers.\n *\n * @returns Array of organization tiers\n *\n * @example\n * ```typescript\n * const tiers = await sso.platform.getTiers();\n * console.log(tiers); // [{ id: 'tier_free', display_name: 'Free Tier', ... }]\n * ```\n */\n public async getTiers(): Promise<OrganizationTier[]> {\n const response = await this.http.get<OrganizationTier[]>('/api/platform/tiers');\n return response.data;\n }\n\n /**\n * Organization management for platform owners\n */\n public organizations = {\n /**\n * List all organizations on the platform with optional filters.\n *\n * @param params Optional query parameters for filtering\n * @returns Platform organizations list with pagination info\n *\n * @example\n * ```typescript\n * const result = await sso.platform.organizations.list({\n * status: 'pending',\n * page: 1,\n * limit: 50\n * });\n * console.log(result.total, result.organizations);\n * ```\n */\n list: async (params?: ListPlatformOrganizationsParams): Promise<PlatformOrganizationsListResponse> => {\n const response = await this.http.get<PlatformOrganizationsListResponse>(\n '/api/platform/organizations',\n { params }\n );\n return response.data;\n },\n\n /**\n * Approve a pending organization and assign it a tier.\n *\n * @param orgId Organization ID\n * @param payload Approval payload with tier assignment\n * @returns Approved organization\n *\n * @example\n * ```typescript\n * const approved = await sso.platform.organizations.approve('org-id', {\n * tier_id: 'tier-starter'\n * });\n * ```\n */\n approve: async (\n orgId: string,\n payload: ApproveOrganizationPayload\n ): Promise<Organization> => {\n const response = await this.http.post<Organization>(\n `/api/platform/organizations/${orgId}/approve`,\n payload\n );\n return response.data;\n },\n\n /**\n * Reject a pending organization with a reason.\n *\n * @param orgId Organization ID\n * @param payload Rejection payload with reason\n * @returns Rejected organization\n *\n * @example\n * ```typescript\n * await sso.platform.organizations.reject('org-id', {\n * reason: 'Does not meet platform requirements'\n * });\n * ```\n */\n reject: async (\n orgId: string,\n payload: RejectOrganizationPayload\n ): Promise<Organization> => {\n const response = await this.http.post<Organization>(\n `/api/platform/organizations/${orgId}/reject`,\n payload\n );\n return response.data;\n },\n\n /**\n * Suspend an active organization.\n *\n * @param orgId Organization ID\n * @returns Suspended organization\n *\n * @example\n * ```typescript\n * await sso.platform.organizations.suspend('org-id');\n * ```\n */\n suspend: async (orgId: string): Promise<Organization> => {\n const response = await this.http.post<Organization>(\n `/api/platform/organizations/${orgId}/suspend`\n );\n return response.data;\n },\n\n /**\n * Re-activate a suspended organization.\n *\n * @param orgId Organization ID\n * @returns Activated organization\n *\n * @example\n * ```typescript\n * await sso.platform.organizations.activate('org-id');\n * ```\n */\n activate: async (orgId: string): Promise<Organization> => {\n const response = await this.http.post<Organization>(\n `/api/platform/organizations/${orgId}/activate`\n );\n return response.data;\n },\n\n /**\n * Update an organization's tier and resource limits.\n *\n * @param orgId Organization ID\n * @param payload Tier update payload\n * @returns Updated organization\n *\n * @example\n * ```typescript\n * await sso.platform.organizations.updateTier('org-id', {\n * tier_id: 'tier-pro',\n * max_services: 20,\n * max_users: 100\n * });\n * ```\n */\n updateTier: async (\n orgId: string,\n payload: UpdateOrganizationTierPayload\n ): Promise<Organization> => {\n const response = await this.http.patch<Organization>(\n `/api/platform/organizations/${orgId}/tier`,\n payload\n );\n return response.data;\n },\n\n /**\n * Update an organization's feature overrides.\n *\n * @param orgId Organization ID\n * @param payload Feature override flags\n * @returns Updated organization\n *\n * @example\n * ```typescript\n * await sso.platform.organizations.updateFeatures('org-id', {\n * allow_saml: true,\n * allow_scim: false,\n * allow_custom_domain: true,\n * allow_custom_branding: false\n * });\n * ```\n */\n updateFeatures: async (\n orgId: string,\n payload: {\n allow_saml?: boolean;\n allow_saml_idp?: boolean;\n allow_scim?: boolean;\n allow_custom_domain?: boolean;\n allow_custom_branding?: boolean;\n allow_branding?: boolean;\n allow_advanced_risk_engine?: boolean;\n allow_siem_integration?: boolean;\n allow_siem?: boolean;\n allow_webhooks?: boolean;\n allow_passkeys?: boolean;\n allow_overage?: boolean;\n }\n ): Promise<Organization> => {\n const response = await this.http.patch<Organization>(\n `/api/platform/organizations/${orgId}/features`,\n payload\n );\n return response.data;\n },\n\n /**\n * Delete an organization and all its associated data.\n * This is a destructive operation that cannot be undone.\n * Only platform owners can delete organizations.\n *\n * All related data will be cascaded deleted including:\n * - Members and invitations\n * - Services and plans\n * - Subscriptions\n * - OAuth credentials\n * - Audit logs\n *\n * @param orgId Organization ID\n * @returns Success confirmation\n *\n * @example\n * ```typescript\n * const result = await sso.platform.organizations.delete('org-id');\n * console.log(result.message); // 'Organization deleted successfully'\n * ```\n */\n delete: async (orgId: string): Promise<{ success: boolean, message: string }> => {\n const response = await this.http.delete<{ success: boolean, message: string }>(\n `/api/platform/organizations/${orgId}`\n );\n return response.data;\n },\n };\n\n /**\n * Promote an existing user to platform owner.\n *\n * @param payload Promotion payload with user ID\n *\n * @example\n * ```typescript\n * await sso.platform.promoteOwner({\n * user_id: 'user-uuid-here'\n * });\n * ```\n */\n public async promoteOwner(payload: PromotePlatformOwnerPayload): Promise<void> {\n await this.http.post('/api/platform/owners', payload);\n }\n\n /**\n * Demote a platform owner to regular user.\n *\n * @param userId The ID of the user to demote\n *\n * @example\n * ```typescript\n * await sso.platform.demoteOwner('user-uuid-here');\n * ```\n */\n public async demoteOwner(userId: string): Promise<void> {\n await this.http.delete(`/api/platform/owners/${userId}`);\n }\n\n /**\n * User MFA management methods for platform administrators\n */\n public users = {\n /**\n * Get MFA status for a specific user.\n *\n * @param userId The ID of the user\n * @returns MFA status information\n *\n * @example\n * ```typescript\n * const mfaStatus = await sso.platform.users.getMfaStatus('user-uuid-here');\n * console.log(mfaStatus.enabled, mfaStatus.has_backup_codes);\n * ```\n */\n getMfaStatus: async (userId: string): Promise<{ enabled: boolean, has_backup_codes: boolean }> => {\n const response = await this.http.get<{ enabled: boolean, has_backup_codes: boolean }>(`/api/platform/users/${userId}/mfa/status`);\n return response.data;\n },\n\n /**\n * List all users on the platform with pagination.\n *\n * @param options Pagination options\n * @returns List of users and total count\n *\n * @example\n * ```typescript\n * const result = await sso.platform.users.list({ limit: 10, offset: 0 });\n * console.log(result.users);\n * ```\n */\n list: async (options?: { limit?: number; offset?: number }): Promise<import('../types/platform').PlatformUserListResponse> => {\n const response = await this.http.get<import('../types/platform').PlatformUserListResponse>('/api/platform/users', { params: options });\n return response.data;\n },\n\n /**\n * Get a single platform user by ID.\n */\n get: async (userId: string): Promise<{\n id: string;\n email: string;\n is_platform_owner: boolean;\n created_at: string;\n }> => {\n const response = await this.http.get<{\n id: string;\n email: string;\n is_platform_owner: boolean;\n created_at: string;\n }>(`/api/platform/users/${userId}`);\n return response.data;\n },\n\n /**\n * Search users by email address or user ID.\n *\n * @param query The search query (email or user ID)\n * @param limit Optional maximum number of results (default: 10, max: 50)\n * @returns Array of matching users\n *\n * @example\n * ```typescript\n * const users = await sso.platform.users.search('john@example.com');\n * console.log(users); // [{ id: 'user-uuid', email: 'john@example.com', ... }]\n *\n * // Search by user ID\n * const users = await sso.platform.users.search('user-uuid-here');\n *\n * // Limit results\n * const users = await sso.platform.users.search('john@', { limit: 5 });\n * ```\n */\n search: async (query: string, options?: { limit?: number }): Promise<Array<{\n id: string;\n email: string;\n is_platform_owner: boolean;\n created_at: string;\n }>> => {\n const params = {\n q: query.trim(),\n limit: options?.limit ? Math.min(options.limit, 50) : undefined\n };\n\n const response = await this.http.get<Array<{\n id: string;\n email: string;\n is_platform_owner: boolean;\n created_at: string;\n }>>('/api/platform/users/search', { params });\n\n return response.data;\n },\n\n /**\n * Force disable MFA for a user (emergency access).\n *\n * @param userId The ID of the user\n * @returns Success confirmation\n *\n * @example\n * ```typescript\n * await sso.platform.users.forceDisableMfa('user-uuid-here');\n * console.log('MFA disabled for user');\n * ```\n */\n forceDisableMfa: async (userId: string): Promise<{ success: boolean, message: string }> => {\n const response = await this.http.delete<{ success: boolean, message: string }>(`/api/platform/users/${userId}/mfa`);\n return response.data;\n },\n };\n\n /**\n * Retrieve the platform-wide audit log with optional filters.\n *\n * @param params Optional query parameters for filtering\n * @returns Array of audit log entries\n *\n * @example\n * ```typescript\n * const logs = await sso.platform.getAuditLog({\n * action: 'organization.approved',\n * start_date: '2024-01-01',\n * limit: 100\n * });\n * ```\n */\n public async getAuditLog(params?: GetAuditLogParams): Promise<AuditLogEntry[]> {\n const response = await this.http.get<AuditLogEntry[]>('/api/platform/audit-log', { params });\n return response.data;\n }\n\n /**\n * Platform analytics methods\n */\n public analytics = {\n /**\n * Get platform overview metrics.\n *\n * @returns Platform overview metrics\n *\n * @example\n * ```typescript\n * const metrics = await sso.platform.analytics.getOverview();\n * console.log(metrics.total_organizations, metrics.total_users);\n * ```\n */\n getOverview: async (): Promise<PlatformOverviewMetrics> => {\n const response = await this.http.get<PlatformOverviewMetrics>('/api/platform/analytics/overview');\n return response.data;\n },\n\n /**\n * Get organization status breakdown.\n *\n * @returns Organization count by status\n *\n * @example\n * ```typescript\n * const breakdown = await sso.platform.analytics.getOrganizationStatus();\n * console.log(breakdown.pending, breakdown.active);\n * ```\n */\n getOrganizationStatus: async (): Promise<OrganizationStatusBreakdown> => {\n const response = await this.http.get<OrganizationStatusBreakdown>(\n '/api/platform/analytics/organization-status'\n );\n return response.data;\n },\n\n /**\n * Get platform growth trends over time.\n *\n * @param params Optional date range parameters\n * @returns Array of growth trend data points\n *\n * @example\n * ```typescript\n * const trends = await sso.platform.analytics.getGrowthTrends({\n * start_date: '2024-01-01',\n * end_date: '2024-01-31'\n * });\n * ```\n */\n getGrowthTrends: async (params?: PlatformAnalyticsDateRangeParams): Promise<GrowthTrendPoint[]> => {\n const response = await this.http.get<GrowthTrendPoint[]>(\n '/api/platform/analytics/growth-trends',\n { params }\n );\n return response.data;\n },\n\n /**\n * Get platform-wide login activity trends.\n *\n * @param params Optional date range parameters\n * @returns Array of login activity data points\n *\n * @example\n * ```typescript\n * const activity = await sso.platform.analytics.getLoginActivity({\n * start_date: '2024-01-01',\n * end_date: '2024-01-31'\n * });\n * ```\n */\n getLoginActivity: async (params?: PlatformAnalyticsDateRangeParams): Promise<LoginActivityPoint[]> => {\n const response = await this.http.get<LoginActivityPoint[]>(\n '/api/platform/analytics/login-activity',\n { params }\n );\n return response.data;\n },\n\n /**\n * Get top organizations by activity.\n *\n * @returns Array of top organizations\n *\n * @example\n * ```typescript\n * const topOrgs = await sso.platform.analytics.getTopOrganizations();\n * console.log(topOrgs[0].login_count_30d);\n * ```\n */\n getTopOrganizations: async (): Promise<TopOrganization[]> => {\n const response = await this.http.get<TopOrganization[]>(\n '/api/platform/analytics/top-organizations'\n );\n return response.data;\n },\n\n /**\n * Get recently created organizations.\n *\n * @param params Optional query parameters\n * @returns Array of recent organizations\n *\n * @example\n * ```typescript\n * const recent = await sso.platform.analytics.getRecentOrganizations({\n * limit: 10\n * });\n * ```\n */\n getRecentOrganizations: async (params?: GetAuditLogParams): Promise<RecentOrganization[]> => {\n const response = await this.http.get<RecentOrganization[]>(\n '/api/platform/analytics/recent-organizations',\n { params }\n );\n return response.data;\n },\n };\n\n /**\n * Impersonate a user (Platform Owner or Org Admin only).\n * Returns a short-lived JWT (15 minutes) that allows acting as the target user.\n *\n * Security:\n * - Platform Owners can impersonate any user\n * - Organization Admins can only impersonate users within their organization\n * - All impersonation actions are logged to the platform audit log with HIGH severity\n * - Tokens contain RFC 8693 actor claim for full audit trail\n *\n * @param payload Impersonation details (user_id and reason)\n * @returns Impersonation token and user context\n *\n * @example\n * ```typescript\n * const result = await sso.platform.impersonateUser({\n * user_id: 'user-uuid-123',\n * reason: 'Investigating support ticket #456'\n * });\n *\n * // Use the returned token to create a new client acting as the user\n * const userClient = new SsoClient({\n * baseURL: 'https://sso.example.com',\n * token: result.token\n * });\n *\n * // Now all requests with userClient are made as the target user\n * const profile = await userClient.user.getProfile();\n * console.log('Acting as:', result.target_user.email);\n * ```\n */\n public async impersonateUser(payload: ImpersonateRequest): Promise<ImpersonateResponse> {\n const response = await this.http.post<ImpersonateResponse>('/api/platform/impersonate', payload);\n return response.data;\n }\n\n /**\n * Get platform operational counters for jobs, webhooks, and SIEM delivery.\n */\n public async getOperationsStatus(): Promise<{\n jobs_pending: number;\n jobs_running: number;\n jobs_failed: number;\n webhook_deliveries_failed: number;\n siem_configs_enabled: number;\n siem_configs_with_failures: number;\n }> {\n const response = await this.http.get<{\n jobs_pending: number;\n jobs_running: number;\n jobs_failed: number;\n webhook_deliveries_failed: number;\n siem_configs_enabled: number;\n siem_configs_with_failures: number;\n }>('/api/platform/operations/status');\n return response.data;\n }\n}\n","import { HttpClient } from '../http';\n\n/**\n * Request body for creating a user\n */\nexport interface CreateUserRequest {\n email: string;\n}\n\n/**\n * Request body for updating a user\n */\nexport interface UpdateUserRequest {\n email?: string;\n}\n\n/**\n * Request body for creating a subscription\n */\nexport interface CreateSubscriptionRequest {\n user_id: string;\n plan_id: string;\n status?: string;\n current_period_end?: string;\n}\n\n/**\n * Request body for updating a subscription\n */\nexport interface UpdateSubscriptionRequest {\n status?: string;\n current_period_end?: string;\n}\n\n/**\n * Request body for updating service info\n */\nexport interface UpdateServiceInfoRequest {\n name?: string;\n}\n\n/**\n * Service API User response\n */\nexport interface ServiceApiUser {\n id: string;\n email: string;\n created_at: string;\n}\n\n/**\n * Service API Subscription response\n */\nexport interface ServiceApiSubscription {\n id: string;\n user_id: string;\n plan_id: string;\n plan_name: string;\n status: string;\n current_period_end: string;\n}\n\n/**\n * Service API info response\n */\nexport interface ServiceApiInfo {\n id: string;\n name: string;\n slug: string;\n service_type: string;\n created_at: string;\n}\n\n/**\n * Response for list users endpoint\n */\nexport interface ListUsersResponse {\n users: ServiceApiUser[];\n total: number;\n}\n\n/**\n * Response for list subscriptions endpoint\n */\nexport interface ListSubscriptionsResponse {\n subscriptions: ServiceApiSubscription[];\n total: number;\n}\n\n/**\n * Service analytics response\n */\nexport interface ServiceAnalytics {\n total_users: number;\n active_subscriptions: number;\n [key: string]: any;\n}\n\nexport interface ProviderTokenRequest {\n user_id: string;\n provider: string;\n scopes?: string[];\n redirect_uri?: string;\n state?: string;\n}\n\nexport interface ProviderTokenAccount {\n id: string;\n provider_user_id: string;\n email?: string;\n display_name?: string;\n}\n\nexport type ProviderTokenResult =\n | {\n status: 'ok';\n access_token: string;\n expires_at?: string;\n scopes: string[];\n provider: string;\n account: ProviderTokenAccount;\n }\n | {\n status: 'action_required';\n code: 'PROVIDER_LINK_REQUIRED' | 'PROVIDER_GRANT_REQUIRED' | 'PROVIDER_SCOPE_CONSENT_REQUIRED' | 'PROVIDER_REAUTH_REQUIRED' | string;\n reauth_url: string;\n missing_scopes: string[];\n provider: string;\n };\n\n/**\n * Service API module for API key-based service-to-service operations.\n * Provides operations for managing users, subscriptions, and service configuration.\n *\n * @example\n * ```typescript\n * const sso = new SsoClient({\n * baseURL: 'https://sso.example.com',\n * apiKey: 'sk_live_abcd1234...'\n * });\n *\n * // List users\n * const { users, total } = await sso.serviceApi.listUsers({ limit: 50 });\n *\n * // Create a user\n * const user = await sso.serviceApi.createUser({ email: 'user@example.com' });\n *\n * // Create a subscription\n * const subscription = await sso.serviceApi.createSubscription({\n * user_id: user.id,\n * plan_id: 'plan_123',\n * status: 'active'\n * });\n *\n * // Update user\n * await sso.serviceApi.updateUser(user.id, { email: 'newemail@example.com' });\n * ```\n */\nexport class ServiceApiModule {\n constructor(private http: HttpClient) { }\n\n /**\n * List all users for the service\n * Requires 'read:users' permission on the API key\n *\n * @param params Optional pagination parameters\n * @returns List of users with total count\n */\n async listUsers(params?: { limit?: number; offset?: number }): Promise<ListUsersResponse> {\n const queryParams = new URLSearchParams();\n if (params?.limit) queryParams.set('limit', params.limit.toString());\n if (params?.offset) queryParams.set('offset', params.offset.toString());\n\n const query = queryParams.toString() ? `?${queryParams.toString()}` : '';\n const response = await this.http.get<ListUsersResponse>(`/api/service/users${query}`);\n return response.data;\n }\n\n /**\n * Get a specific user by ID\n * Requires 'read:users' permission on the API key\n *\n * @param userId User ID to retrieve\n * @returns User details\n */\n async getUser(userId: string): Promise<ServiceApiUser> {\n const response = await this.http.get<ServiceApiUser>(`/api/service/users/${userId}`);\n return response.data;\n }\n\n /**\n * List all subscriptions for the service\n * Requires 'read:subscriptions' permission on the API key\n *\n * @param params Optional pagination parameters\n * @returns List of subscriptions with total count\n */\n async listSubscriptions(params?: { limit?: number; offset?: number }): Promise<ListSubscriptionsResponse> {\n const queryParams = new URLSearchParams();\n if (params?.limit) queryParams.set('limit', params.limit.toString());\n if (params?.offset) queryParams.set('offset', params.offset.toString());\n\n const query = queryParams.toString() ? `?${queryParams.toString()}` : '';\n const response = await this.http.get<ListSubscriptionsResponse>(`/api/service/subscriptions${query}`);\n return response.data;\n }\n\n /**\n * Get subscription for a specific user\n * Requires 'read:subscriptions' permission on the API key\n *\n * @param userId User ID whose subscription to retrieve\n * @returns User's subscription\n */\n async getSubscription(userId: string): Promise<ServiceApiSubscription> {\n const response = await this.http.get<ServiceApiSubscription>(`/api/service/subscriptions/${userId}`);\n return response.data;\n }\n\n /**\n * Get analytics for the service\n * Requires 'read:analytics' permission on the API key\n *\n * @returns Service analytics data\n */\n async getAnalytics(): Promise<ServiceAnalytics> {\n const response = await this.http.get<ServiceAnalytics>('/api/service/analytics');\n return response.data;\n }\n\n /**\n * Get service information\n * Requires 'read:service' permission on the API key\n *\n * @returns Service information\n */\n async getServiceInfo(): Promise<ServiceApiInfo> {\n const response = await this.http.get<ServiceApiInfo>('/api/service/info');\n return response.data;\n }\n\n /**\n * Request a backend-only third-party provider access token for an AuthOS user.\n * Requires `read:provider_tokens` or `read:provider_tokens:{provider}` on the API key.\n */\n async requestProviderToken(request: ProviderTokenRequest): Promise<ProviderTokenResult> {\n const response = await this.http.post<ProviderTokenResult>('/api/service/provider-tokens', {\n ...request,\n scopes: request.scopes ?? [],\n });\n return response.data;\n }\n\n /**\n * Create a new user\n * Requires 'write:users' permission on the API key\n *\n * @param request User creation request\n * @returns Created user\n */\n async createUser(request: CreateUserRequest): Promise<ServiceApiUser> {\n const response = await this.http.post<ServiceApiUser>('/api/service/users', request);\n return response.data;\n }\n\n /**\n * Update user details\n * Requires 'write:users' permission on the API key\n *\n * @param userId User ID to update\n * @param request User update request\n * @returns Updated user\n */\n async updateUser(userId: string, request: UpdateUserRequest): Promise<ServiceApiUser> {\n const response = await this.http.patch<ServiceApiUser>(`/api/service/users/${userId}`, request);\n return response.data;\n }\n\n /**\n * Create a new subscription for a user\n * Requires 'write:subscriptions' permission on the API key\n *\n * @param request Subscription creation request\n * @returns Created subscription\n */\n async createSubscription(request: CreateSubscriptionRequest): Promise<ServiceApiSubscription> {\n const response = await this.http.post<ServiceApiSubscription>('/api/service/subscriptions', request);\n return response.data;\n }\n\n /**\n * Update a subscription for a user\n * Requires 'write:subscriptions' permission on the API key\n *\n * @param userId User ID whose subscription to update\n * @param request Subscription update request\n * @returns Updated subscription\n */\n async updateSubscription(userId: string, request: UpdateSubscriptionRequest): Promise<ServiceApiSubscription> {\n const response = await this.http.patch<ServiceApiSubscription>(`/api/service/subscriptions/${userId}`, request);\n return response.data;\n }\n\n /**\n * Update service configuration\n * Requires 'write:service' permission on the API key\n *\n * @param request Service update request\n * @returns Updated service info\n */\n async updateServiceInfo(request: UpdateServiceInfoRequest): Promise<ServiceApiInfo> {\n const response = await this.http.patch<ServiceApiInfo>('/api/service/info', request);\n return response.data;\n }\n\n /**\n * Delete a user\n * Requires 'delete:users' permission on the API key\n *\n * @param userId User ID to delete\n */\n async deleteUser(userId: string): Promise<void> {\n await this.http.delete(`/api/service/users/${userId}`);\n }\n\n /**\n * Delete a subscription for a user\n * Requires 'delete:subscriptions' permission on the API key\n *\n * @param userId User ID whose subscription to delete\n */\n async deleteSubscription(userId: string): Promise<void> {\n await this.http.delete(`/api/service/subscriptions/${userId}`);\n }\n}\n","import { HttpClient } from '../http';\nimport { JwtClaims } from '../types';\n\n/**\n * Permission checking and management methods\n *\n * This module provides utilities for working with ReBAC (Relationship-Based Access Control)\n * permissions. Permissions use Zanzibar-style relation tuples and are now fetched from the\n * API instead of being embedded in JWT tokens (for improved security and smaller token size).\n */\nexport class PermissionsModule {\n constructor(private http: HttpClient) {}\n\n /**\n * Check if user has a specific permission.\n * Fetches from user profile API (which uses cached permissions).\n *\n * @param permission Permission in format \"namespace:object_id#relation\"\n * @returns true if the permission is present\n *\n * @example\n * ```typescript\n * const hasAccess = await sso.permissions.hasPermission('organization:acme#owner');\n * ```\n */\n public async hasPermission(permission: string): Promise<boolean> {\n const response = await this.http.get<{ permissions: string[] }>('/api/user');\n return response.data.permissions.includes(permission);\n }\n\n /**\n * Get all user permissions.\n * Fetches from user profile API (which uses cached permissions).\n *\n * @returns Array of permission strings\n *\n * @example\n * ```typescript\n * const permissions = await sso.permissions.listPermissions();\n * // [\"organization:acme#owner\", \"service:api#admin\"]\n * ```\n */\n public async listPermissions(): Promise<string[]> {\n const response = await this.http.get<{ permissions: string[] }>('/api/user');\n return response.data.permissions;\n }\n\n /**\n * Check if user has access to a feature.\n *\n * @param feature Feature name to check\n * @returns true if the feature is available\n *\n * @example\n * ```typescript\n * const canExport = await sso.permissions.hasFeature('advanced-export');\n * ```\n */\n public async hasFeature(feature: string): Promise<boolean> {\n const response = await this.http.get<{ features: string[] | null }>('/api/user');\n return response.data.features?.includes(feature) ?? false;\n }\n\n /**\n * Get current plan name.\n *\n * @returns Current plan name or null if not in org/service context\n *\n * @example\n * ```typescript\n * const plan = await sso.permissions.getPlan();\n * console.log(plan); // \"pro\", \"enterprise\", etc.\n * ```\n */\n public async getPlan(): Promise<string | null> {\n const response = await this.http.get<{ plan: string | null }>('/api/user');\n return response.data.plan;\n }\n\n /**\n * Check if user has a specific permission on a resource.\n *\n * @param namespace The permission namespace (e.g., \"organization\", \"service\")\n * @param objectId The object ID (e.g., organization slug, service slug)\n * @param relation The relation type (e.g., \"owner\", \"admin\", \"member\")\n * @returns true if the user has the permission\n *\n * @example\n * ```typescript\n * const isOwner = await sso.permissions.can('organization', 'acme-corp', 'owner');\n * ```\n */\n public async can(namespace: string, objectId: string, relation: string): Promise<boolean> {\n return this.hasPermission(`${namespace}:${objectId}#${relation}`);\n }\n\n /**\n * Check if user is a member of an organization.\n *\n * @param orgId The organization ID or slug\n * @returns true if the user is a member\n *\n * @example\n * ```typescript\n * if (await sso.permissions.isOrgMember('acme-corp')) {\n * // User is a member\n * }\n * ```\n */\n public async isOrgMember(orgId: string): Promise<boolean> {\n return this.hasPermission(`organization:${orgId}#member`);\n }\n\n /**\n * Check if user is an admin of an organization.\n *\n * @param orgId The organization ID or slug\n * @returns true if the user is an admin\n *\n * @example\n * ```typescript\n * if (await sso.permissions.isOrgAdmin('acme-corp')) {\n * // User is an admin\n * }\n * ```\n */\n public async isOrgAdmin(orgId: string): Promise<boolean> {\n return this.hasPermission(`organization:${orgId}#admin`);\n }\n\n /**\n * Check if user is an owner of an organization.\n *\n * @param orgId The organization ID or slug\n * @returns true if the user is an owner\n *\n * @example\n * ```typescript\n * if (await sso.permissions.isOrgOwner('acme-corp')) {\n * // User is an owner\n * }\n * ```\n */\n public async isOrgOwner(orgId: string): Promise<boolean> {\n return this.hasPermission(`organization:${orgId}#owner`);\n }\n\n /**\n * Check if user has access to a service.\n *\n * @param serviceId The service ID or slug\n * @returns true if the user has access\n *\n * @example\n * ```typescript\n * if (await sso.permissions.hasServiceAccess('api-service')) {\n * // User has access to the service\n * }\n * ```\n */\n public async hasServiceAccess(serviceId: string): Promise<boolean> {\n return this.hasPermission(`service:${serviceId}#member`);\n }\n\n /**\n * Filter permissions by namespace.\n *\n * @param namespace The namespace to filter by (e.g., \"organization\", \"service\")\n * @returns Array of permissions matching the namespace\n *\n * @example\n * ```typescript\n * const orgPermissions = await sso.permissions.getPermissionsByNamespace('organization');\n * ```\n */\n public async getPermissionsByNamespace(namespace: string): Promise<string[]> {\n const allPermissions = await this.listPermissions();\n return allPermissions.filter((p) => p.startsWith(`${namespace}:`));\n }\n\n // ============================================================================\n // DEPRECATED METHODS - Token-based permission checking (legacy)\n // ============================================================================\n\n /**\n * @deprecated Use `hasPermission()` instead (without token parameter)\n * Decode a JWT token to extract claims (including permissions)\n * Note: This does NOT verify the signature - it only decodes the payload\n *\n * @param token The JWT access token\n * @returns The decoded JWT claims\n * @throws Error if the token is malformed\n */\n public decodeToken(token: string): JwtClaims {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid JWT format');\n }\n\n const payload = parts[1];\n const decoded = atob(payload.replace(/-/g, '+').replace(/_/g, '/'));\n return JSON.parse(decoded) as JwtClaims;\n } catch (error) {\n throw new Error(`Failed to decode JWT: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n /**\n * @deprecated JWT tokens no longer contain permissions. Use `hasPermission(permission)` instead.\n * Check if a JWT token contains a specific permission\n *\n * @param token The JWT access token (ignored)\n * @param permission Permission in format \"namespace:object_id#relation\"\n * @returns true if the permission is present in the token\n */\n public hasPermissionFromToken(token: string, permission: string): boolean {\n const claims = this.decodeToken(token);\n return claims.permissions?.includes(permission) ?? false;\n }\n\n /**\n * @deprecated JWT tokens no longer contain permissions. Use `can(namespace, objectId, relation)` instead.\n * Check if a user has a specific permission on a resource\n *\n * @param token The JWT access token (ignored)\n * @param namespace The permission namespace (e.g., \"organization\", \"service\")\n * @param objectId The object ID (e.g., organization slug, service slug)\n * @param relation The relation type (e.g., \"owner\", \"admin\", \"member\")\n * @returns true if the user has the permission\n */\n public canFromToken(token: string, namespace: string, objectId: string, relation: string): boolean {\n return this.hasPermissionFromToken(token, `${namespace}:${objectId}#${relation}`);\n }\n\n /**\n * @deprecated JWT tokens no longer contain permissions. Use `isOrgMember(orgId)` instead.\n * Check if user is a member of an organization\n *\n * @param token The JWT access token (ignored)\n * @param orgId The organization ID or slug\n * @returns true if the user is a member\n */\n public isOrgMemberFromToken(token: string, orgId: string): boolean {\n return this.hasPermissionFromToken(token, `organization:${orgId}#member`);\n }\n\n /**\n * @deprecated JWT tokens no longer contain permissions. Use `isOrgAdmin(orgId)` instead.\n * Check if user is an admin of an organization\n *\n * @param token The JWT access token (ignored)\n * @param orgId The organization ID or slug\n * @returns true if the user is an admin\n */\n public isOrgAdminFromToken(token: string, orgId: string): boolean {\n return this.hasPermissionFromToken(token, `organization:${orgId}#admin`);\n }\n\n /**\n * @deprecated JWT tokens no longer contain permissions. Use `isOrgOwner(orgId)` instead.\n * Check if user is an owner of an organization\n *\n * @param token The JWT access token (ignored)\n * @param orgId The organization ID or slug\n * @returns true if the user is an owner\n */\n public isOrgOwnerFromToken(token: string, orgId: string): boolean {\n return this.hasPermissionFromToken(token, `organization:${orgId}#owner`);\n }\n\n /**\n * @deprecated JWT tokens no longer contain permissions. Use `hasServiceAccess(serviceId)` instead.\n * Check if user has access to a service\n *\n * @param token The JWT access token (ignored)\n * @param serviceId The service ID or slug\n * @returns true if the user has access\n */\n public hasServiceAccessFromToken(token: string, serviceId: string): boolean {\n return this.hasPermissionFromToken(token, `service:${serviceId}#member`);\n }\n\n /**\n * @deprecated JWT tokens no longer contain permissions. Use `listPermissions()` instead.\n * Get all permissions from a JWT token\n *\n * @param token The JWT access token\n * @returns Array of permission strings, or empty array if none\n */\n public getAllPermissionsFromToken(token: string): string[] {\n const claims = this.decodeToken(token);\n return claims.permissions ?? [];\n }\n\n /**\n * Parse a permission string into its components\n *\n * @param permission Permission string in format \"namespace:object_id#relation\"\n * @returns Parsed permission components or null if invalid format\n *\n * @example\n * ```typescript\n * const parsed = sso.permissions.parsePermission('organization:acme#owner');\n * // { namespace: 'organization', objectId: 'acme', relation: 'owner' }\n * ```\n */\n public parsePermission(permission: string): {\n namespace: string;\n objectId: string;\n relation: string;\n } | null {\n const match = permission.match(/^([^:]+):([^#]+)#(.+)$/);\n if (!match) {\n return null;\n }\n\n return {\n namespace: match[1],\n objectId: match[2],\n relation: match[3],\n };\n }\n\n /**\n * @deprecated JWT tokens no longer contain permissions. Use `getPermissionsByNamespace(namespace)` instead.\n * Filter permissions by namespace\n *\n * @param token The JWT access token (ignored)\n * @param namespace The namespace to filter by (e.g., \"organization\", \"service\")\n * @returns Array of permissions matching the namespace\n */\n public getPermissionsByNamespaceFromToken(token: string, namespace: string): string[] {\n const allPermissions = this.getAllPermissionsFromToken(token);\n return allPermissions.filter((p) => p.startsWith(`${namespace}:`));\n }\n}\n","import { HttpClient } from '../http';\nimport {\n PasskeyRegisterStartResponse,\n PasskeyRegisterFinishResponse,\n PasskeyAuthStartResponse,\n PasskeyAuthFinishResponse,\n UserPasskey,\n PasskeyActionResponse,\n RegistrationResponseJSON,\n AuthenticationResponseJSON,\n} from '../types/passkeys';\n\n// WebAuthn types are only available in browser contexts\ndeclare const window: any;\ndeclare const PublicKeyCredential: any;\ndeclare const navigator: any;\ndeclare const AuthenticatorAttestationResponse: any;\ndeclare const AuthenticatorAssertionResponse: any;\ndeclare type CredentialCreationOptions = any;\ndeclare type CredentialRequestOptions = any;\n\n/**\n * WebAuthn/Passkey authentication module\n *\n * Provides methods for registering and authenticating with FIDO2 passkeys.\n * Requires a browser environment with WebAuthn support.\n *\n * @example\n * ```typescript\n * // Register a new passkey (requires authenticated session)\n * await sso.passkeys.register();\n *\n * // Login with passkey\n * const { token } = await sso.passkeys.login('user@example.com');\n * sso.setToken(token);\n * ```\n */\nexport class PasskeysModule {\n constructor(private http: HttpClient) { }\n\n /**\n * Check if WebAuthn is supported in the current browser\n */\n isSupported(): boolean {\n return (\n typeof window !== 'undefined' &&\n window.PublicKeyCredential !== undefined &&\n typeof window.PublicKeyCredential === 'function'\n );\n }\n\n /**\n * Check if platform authenticator (like Touch ID, Face ID, Windows Hello) is available\n */\n async isPlatformAuthenticatorAvailable(): Promise<boolean> {\n if (!this.isSupported()) {\n return false;\n }\n return PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n }\n\n /**\n * Register a new passkey for the authenticated user\n *\n * This method requires an authenticated session (JWT token must be set).\n * It starts the WebAuthn registration ceremony, prompts the user to create\n * a passkey using their device's authenticator (e.g., Touch ID, Face ID,\n * Windows Hello, or hardware security key), and stores the credential.\n *\n * @param displayName Optional display name for the passkey\n * @returns Promise resolving to the registered passkey ID\n * @throws {Error} If WebAuthn is not supported or registration fails\n *\n * @example\n * ```typescript\n * try {\n * const passkeyId = await sso.passkeys.register('My MacBook Pro');\n * console.log('Passkey registered:', passkeyId);\n * } catch (error) {\n * console.error('Passkey registration failed:', error);\n * }\n * ```\n */\n /**\n * Start the passkey registration ceremony.\n * returns the options required to create credentials in the browser.\n */\n async registerStart(displayName?: string): Promise<PasskeyRegisterStartResponse> {\n const response = await this.http.post<PasskeyRegisterStartResponse>(\n '/api/auth/passkeys/register/start',\n { name: displayName }\n );\n return response.data;\n }\n\n /**\n * List registered passkeys for the authenticated user.\n */\n async list(): Promise<UserPasskey[]> {\n const response = await this.http.get<UserPasskey[]>('/api/auth/passkeys');\n return response.data;\n }\n\n /**\n * Rename a passkey for the authenticated user.\n */\n async updateName(passkeyId: string, name: string): Promise<UserPasskey> {\n const response = await this.http.patch<UserPasskey>(`/api/auth/passkeys/${passkeyId}`, {\n name,\n });\n return response.data;\n }\n\n /**\n * Delete a passkey for the authenticated user.\n */\n async delete(passkeyId: string): Promise<PasskeyActionResponse> {\n const response = await this.http.delete<PasskeyActionResponse>(`/api/auth/passkeys/${passkeyId}`);\n return response.data;\n }\n\n /**\n * Finish the passkey registration ceremony.\n * Verifies the credential created by the browser.\n */\n async registerFinish(challengeId: string, credential: RegistrationResponseJSON): Promise<PasskeyRegisterFinishResponse> {\n const response = await this.http.post<PasskeyRegisterFinishResponse>(\n '/api/auth/passkeys/register/finish',\n {\n challenge_id: challengeId,\n credential,\n }\n );\n return response.data;\n }\n\n /**\n * Register a new passkey for the authenticated user\n * ...\n */\n async register(displayName?: string): Promise<string> {\n if (!this.isSupported()) {\n throw new Error('WebAuthn is not supported in this browser');\n }\n\n // Start registration ceremony\n const startData = await this.registerStart(displayName);\n\n // Convert server options to browser format\n const createOptions: CredentialCreationOptions = {\n publicKey: {\n ...startData.options,\n challenge: this.base64UrlToUint8Array(startData.options.challenge as unknown as string),\n user: {\n ...startData.options.user,\n id: this.base64UrlToUint8Array(startData.options.user.id as unknown as string),\n },\n excludeCredentials: startData.options.excludeCredentials?.map((cred: any) => ({\n ...cred,\n id: this.base64UrlToUint8Array(cred.id as unknown as string),\n })),\n },\n };\n\n // Call WebAuthn API\n const credential = await navigator.credentials.create(createOptions);\n\n if (!credential || !(credential instanceof PublicKeyCredential)) {\n throw new Error('Failed to create passkey');\n }\n\n if (!(credential.response instanceof AuthenticatorAttestationResponse)) {\n throw new Error('Invalid credential response type');\n }\n\n // Convert credential to JSON\n const credentialJSON: RegistrationResponseJSON = {\n id: credential.id,\n rawId: this.uint8ArrayToBase64Url(new Uint8Array(credential.rawId)),\n response: {\n clientDataJSON: this.uint8ArrayToBase64Url(new Uint8Array(credential.response.clientDataJSON)),\n attestationObject: this.uint8ArrayToBase64Url(new Uint8Array(credential.response.attestationObject)),\n transports: credential.response.getTransports?.() as string[],\n },\n authenticatorAttachment: credential.authenticatorAttachment as ('platform' | 'cross-platform') | undefined,\n clientExtensionResults: credential.getClientExtensionResults(),\n type: credential.type as 'public-key',\n };\n\n // Finish registration\n const finishResponse = await this.registerFinish(startData.challenge_id, credentialJSON);\n\n return finishResponse.passkey_id;\n }\n\n /**\n * Authenticate with a passkey and obtain a JWT token\n *\n * This method prompts the user to authenticate using their passkey.\n * Upon successful authentication, a JWT token is returned which can\n * be used to make authenticated API requests.\n *\n * @param email User's email address\n * @returns Promise resolving to authentication response with JWT token\n * @throws {Error} If WebAuthn is not supported or authentication fails\n *\n * @example\n * ```typescript\n * try {\n * const { token, user_id } = await sso.passkeys.login('user@example.com');\n * sso.setToken(token);\n * console.log('Logged in as:', user_id);\n * } catch (error) {\n * console.error('Passkey login failed:', error);\n * }\n * ```\n */\n /**\n * Start the passkey authentication ceremony.\n * Returns the options required to get credentials from the browser.\n */\n async authenticateStart(email: string, context?: {\n org_slug?: string;\n service_slug?: string;\n redirect_uri?: string;\n state?: string;\n }): Promise<PasskeyAuthStartResponse> {\n const response = await this.http.post<PasskeyAuthStartResponse>(\n '/api/auth/passkeys/authenticate/start',\n { email, ...context }\n );\n return response.data;\n }\n\n /**\n * Finish the passkey authentication ceremony.\n * Verifies the assertion returned by the browser.\n */\n async authenticateFinish(challengeId: string, credential: AuthenticationResponseJSON): Promise<PasskeyAuthFinishResponse> {\n const response = await this.http.post<PasskeyAuthFinishResponse>(\n '/api/auth/passkeys/authenticate/finish',\n {\n challenge_id: challengeId,\n credential,\n }\n );\n return response.data;\n }\n\n /**\n * Authenticate with a passkey and obtain a JWT token\n * ...\n */\n async login(email: string, context?: {\n org_slug?: string;\n service_slug?: string;\n redirect_uri?: string;\n state?: string;\n }): Promise<PasskeyAuthFinishResponse> {\n if (!this.isSupported()) {\n throw new Error('WebAuthn is not supported in this browser');\n }\n\n // Start authentication ceremony\n const startData = await this.authenticateStart(email, context);\n\n // Convert server options to browser format\n const getOptions: CredentialRequestOptions = {\n publicKey: {\n ...startData.options,\n challenge: this.base64UrlToUint8Array(startData.options.challenge as unknown as string),\n allowCredentials: startData.options.allowCredentials?.map((cred: any) => ({\n ...cred,\n id: this.base64UrlToUint8Array(cred.id as unknown as string),\n })),\n },\n };\n\n // Call WebAuthn API\n const credential = await navigator.credentials.get(getOptions);\n\n if (!credential || !(credential instanceof PublicKeyCredential)) {\n throw new Error('Failed to get passkey');\n }\n\n if (!(credential.response instanceof AuthenticatorAssertionResponse)) {\n throw new Error('Invalid credential response type');\n }\n\n // Convert credential to JSON\n const credentialJSON: AuthenticationResponseJSON = {\n id: credential.id,\n rawId: this.uint8ArrayToBase64Url(new Uint8Array(credential.rawId)),\n response: {\n clientDataJSON: this.uint8ArrayToBase64Url(new Uint8Array(credential.response.clientDataJSON)),\n authenticatorData: this.uint8ArrayToBase64Url(new Uint8Array(credential.response.authenticatorData)),\n signature: this.uint8ArrayToBase64Url(new Uint8Array(credential.response.signature)),\n userHandle: credential.response.userHandle\n ? this.uint8ArrayToBase64Url(new Uint8Array(credential.response.userHandle))\n : undefined,\n },\n authenticatorAttachment: credential.authenticatorAttachment as ('platform' | 'cross-platform') | undefined,\n clientExtensionResults: credential.getClientExtensionResults(),\n type: credential.type as 'public-key',\n };\n\n // Finish authentication\n return this.authenticateFinish(startData.challenge_id, credentialJSON);\n }\n\n /**\n * Convert Base64URL string to Uint8Array\n */\n private base64UrlToUint8Array(base64url: string): Uint8Array {\n // Add padding if needed\n const padding = '='.repeat((4 - (base64url.length % 4)) % 4);\n const base64 = base64url.replace(/-/g, '+').replace(/_/g, '/') + padding;\n\n const rawData = atob(base64);\n const outputArray = new Uint8Array(rawData.length);\n\n for (let i = 0; i < rawData.length; ++i) {\n outputArray[i] = rawData.charCodeAt(i);\n }\n\n return outputArray;\n }\n\n /**\n * Convert Uint8Array to Base64URL string\n */\n private uint8ArrayToBase64Url(array: Uint8Array): string {\n let binary = '';\n for (let i = 0; i < array.byteLength; i++) {\n binary += String.fromCharCode(array[i]);\n }\n\n const base64 = btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n }\n}\n","import { HttpClient } from '../http';\n\n/**\n * Magic link request payload\n */\nexport interface MagicLinkRequest {\n /** Email address to send the magic link to */\n email: string;\n /** Optional organization context */\n org_slug?: string;\n orgSlug?: string;\n /** Optional service context */\n service_slug?: string;\n /** Optional service callback URI */\n redirect_uri?: string;\n /** Optional caller state to return to hosted service callbacks */\n state?: string;\n}\n\n/**\n * Magic link response\n */\nexport interface MagicLinkResponse {\n /** Success message */\n message: string;\n}\n\n/**\n * Magic link verification query parameters\n */\nexport interface MagicLinkVerifyQuery {\n /** The magic link token */\n token: string;\n /** Optional where to redirect after successful verification */\n redirectUri?: string;\n /** Optional caller state to return to hosted service callbacks */\n state?: string;\n}\n\n/**\n * Magic links module for passwordless authentication\n */\nexport class MagicLinks {\n constructor(private http: HttpClient) {}\n\n /**\n * Request a magic link to be sent to the user's email\n *\n * @param data Magic link request data\n * @returns Promise resolving to magic link response\n */\n async request(data: MagicLinkRequest): Promise<MagicLinkResponse> {\n const response = await this.http.post('/api/auth/magic-link/request', {\n ...data,\n org_slug: data.org_slug || data.orgSlug,\n });\n return response.data;\n }\n\n /**\n * Verify a magic link token and complete authentication\n * Note: This is typically handled by redirecting to the magic link URL\n * The backend will handle verification and either redirect or return tokens\n *\n * @param token The magic link token to verify\n * @param redirectUri Optional where to redirect after success\n * @returns URL to redirect to for verification\n */\n getVerificationUrl(token: string, redirectUri?: string, state?: string): string {\n const params = new URLSearchParams({ token });\n if (redirectUri) {\n params.append('redirect_uri', redirectUri);\n }\n if (state) {\n params.append('state', state);\n }\n return `/api/auth/magic-link/verify?${params.toString()}`;\n }\n\n /**\n * Verify a magic link token via API call\n * This is an alternative to redirect-based verification\n *\n * @param token The magic link token\n * @param redirectUri Optional redirect URI\n * @returns Promise resolving to authentication response\n */\n async verify(token: string, redirectUri?: string, state?: string): Promise<any> {\n const params = new URLSearchParams({ token });\n if (redirectUri) {\n params.append('redirect_uri', redirectUri);\n }\n if (state) {\n params.append('state', state);\n }\n\n const response = await this.http.get(`/api/auth/magic-link/verify?${params.toString()}`);\n return response.data;\n }\n\n /**\n * Construct the complete magic link URL that would be sent via email\n *\n * @param token The magic link token\n * @param redirectUri Optional redirect URI\n * @returns Complete magic link URL\n */\n constructMagicLink(token: string, redirectUri?: string, state?: string): string {\n return this.getVerificationUrl(token, redirectUri, state);\n }\n}\n\n/**\n * Convenience function to create a MagicLinks module instance\n *\n * @param http HTTP client instance\n * @returns MagicLinks module instance\n */\nexport function createMagicLinks(http: HttpClient): MagicLinks {\n return new MagicLinks(http);\n}\n","import { HttpClient } from '../http';\nimport { ExportUserDataResponse, ForgetUserRequest, ForgetUserResponse } from '../types';\n\n/**\n * Privacy and GDPR compliance methods\n */\nexport class PrivacyModule {\n constructor(private http: HttpClient) {}\n\n /**\n * Export all user data (GDPR Right to Access).\n * Users can export their own data, or organization owners can export their members' data.\n *\n * @param userId User ID to export data for\n * @returns Complete user data export including memberships, login events, identities, MFA events, and passkeys\n *\n * @example\n * ```typescript\n * const userData = await sso.privacy.exportData('user-id');\n * console.log(`Exported ${userData.login_events_count} login events`);\n * console.log(`User has ${userData.memberships.length} organization memberships`);\n * ```\n */\n public async exportData(userId: string): Promise<ExportUserDataResponse> {\n const response = await this.http.get<ExportUserDataResponse>(`/api/privacy/export/${userId}`);\n return response.data;\n }\n\n /**\n * Anonymize user data (GDPR Right to be Forgotten).\n * Requires organization owner permission for all organizations the user is a member of.\n * Platform owners cannot be anonymized.\n *\n * This operation:\n * - Soft-deletes the user account\n * - Hard-deletes PII from identities and passkeys tables\n * - Preserves audit logs for compliance\n *\n * @param userId User ID to anonymize\n * @returns Anonymization confirmation response\n *\n * @example\n * ```typescript\n * const result = await sso.privacy.forgetUser('user-id');\n * console.log(result.message);\n * // \"User data has been anonymized. PII has been removed while preserving audit logs.\"\n * ```\n */\n public async forgetUser(\n userId: string,\n payload: ForgetUserRequest = {}\n ): Promise<ForgetUserResponse> {\n const response = await this.http.delete<ForgetUserResponse>(\n `/api/privacy/forget/${userId}`,\n payload\n );\n return response.data;\n }\n}\n","import { HttpClient, createHttpAgent } from './http';\nimport { SessionManager } from './session';\nimport { TokenStorage, resolveStorage } from './storage';\nimport { AnalyticsModule } from './modules/analytics';\nimport { AuthModule } from './modules/auth';\nimport { UserModule } from './modules/user';\nimport { OrganizationsModule } from './modules/organizations';\nimport { ServicesModule } from './modules/services';\nimport { InvitationsModule } from './modules/invitations';\nimport { PlatformModule } from './modules/platform';\nimport { ServiceApiModule } from './modules/serviceApi';\nimport { PermissionsModule } from './modules/permissions';\nimport { PasskeysModule } from './modules/passkeys';\nimport { MagicLinks } from './modules/magic';\nimport { PrivacyModule } from './modules/privacy';\n\n/**\n * Configuration options for the SSO client\n */\nexport interface SsoClientOptions {\n /**\n * Base URL of the SSO API service\n */\n baseURL: string;\n\n /**\n * Optional JWT token to initialize with (for user authentication)\n */\n token?: string;\n\n /**\n * Optional API key for service-to-service authentication\n */\n apiKey?: string;\n\n /**\n * Custom storage provider (optional).\n * Defaults to localStorage in browser, Memory in Node.\n */\n storage?: TokenStorage;\n\n /**\n * Prefix for storage keys. Default: 'sso_'\n */\n storagePrefix?: string;\n\n /**\n * Refresh access tokens this many seconds before expiry. Default: 30.\n */\n tokenRefreshMinValiditySeconds?: number;\n}\n\n/**\n * Main SSO client class.\n * This is the entry point for all SDK operations.\n *\n * @example\n * ```typescript\n * const sso = new SsoClient({\n * baseURL: 'https://sso.example.com',\n * token: localStorage.getItem('sso_access_token')\n * });\n *\n * // Use the modules\n * const user = await sso.user.getProfile();\n * const orgs = await sso.organizations.list();\n * ```\n */\nexport class SsoClient {\n public http: HttpClient;\n private session: SessionManager;\n\n /**\n * Analytics and login tracking methods\n */\n public readonly analytics: AnalyticsModule;\n\n /**\n * Authentication and OAuth flow methods\n */\n public readonly auth: AuthModule;\n\n /**\n * User profile and subscription methods\n */\n public readonly user: UserModule;\n\n /**\n * Organization management methods\n */\n public readonly organizations: OrganizationsModule;\n\n /**\n * Service management methods\n */\n public readonly services: ServicesModule;\n\n /**\n * Invitation management methods\n */\n public readonly invitations: InvitationsModule;\n\n /**\n * Platform owner administration methods\n */\n public readonly platform: PlatformModule;\n\n /**\n * Service API methods (requires API key authentication)\n */\n public readonly serviceApi: ServiceApiModule;\n\n /**\n * Permission checking and management methods\n */\n public readonly permissions: PermissionsModule;\n\n /**\n * WebAuthn/Passkey authentication methods\n */\n public readonly passkeys: PasskeysModule;\n\n /**\n * Magic link authentication methods\n */\n public readonly magicLinks: MagicLinks;\n\n /**\n * Privacy and GDPR compliance methods\n */\n public readonly privacy: PrivacyModule;\n\n constructor(options: SsoClientOptions) {\n this.http = createHttpAgent(options.baseURL);\n\n // Initialize Session Manager\n this.session = new SessionManager(\n resolveStorage(options.storage),\n async (refreshToken) => {\n const res = await this.http.post('/api/auth/refresh', { refresh_token: refreshToken });\n return res.data;\n },\n {\n storageKeyPrefix: options.storagePrefix || 'sso_',\n minValiditySeconds: options.tokenRefreshMinValiditySeconds,\n }\n );\n\n // Link HTTP client to Session Manager\n this.http.setSessionManager(this.session);\n\n // Instantiate all modules\n // Note: Pass 'this.session' to AuthModule so login can update state directly\n this.analytics = new AnalyticsModule(this.http);\n this.auth = new AuthModule(this.http, this.session);\n this.user = new UserModule(this.http);\n this.organizations = new OrganizationsModule(this.http);\n this.services = new ServicesModule(this.http);\n this.invitations = new InvitationsModule(this.http);\n this.platform = new PlatformModule(this.http);\n this.serviceApi = new ServiceApiModule(this.http);\n this.permissions = new PermissionsModule(this.http);\n this.passkeys = new PasskeysModule(this.http);\n this.magicLinks = new MagicLinks(this.http);\n this.privacy = new PrivacyModule(this.http);\n\n // Handle initial configuration\n if (options.apiKey) {\n this.setApiKey(options.apiKey);\n }\n\n // Async init - if we have a token in options, set it, otherwise try load from storage\n if (options.token) {\n this.session.setSession({ access_token: options.token });\n } else {\n // We can't await in constructor, but we kick it off\n this.session.loadSession().catch(console.error);\n }\n }\n\n /**\n * Sets the JWT for all subsequent authenticated requests.\n * Pass null to clear the token.\n *\n * NOTE: For OAuth callback flows, prefer using setSession() which properly\n * updates the SessionManager. This method updates both the HTTP headers\n * AND the SessionManager for backward compatibility.\n *\n * @param token The JWT string, or null to clear\n *\n * @example\n * ```typescript\n * // Set token\n * sso.setAuthToken(jwt);\n *\n * // Clear token\n * sso.setAuthToken(null);\n * ```\n */\n public setAuthToken(token: string | null): void {\n if (token) {\n this.http.defaults.headers.common['Authorization'] = `Bearer ${token}`;\n // Also update SessionManager so getToken() returns the correct value\n this.session.setSession({ access_token: token });\n } else {\n delete this.http.defaults.headers.common['Authorization'];\n this.session.clearSession();\n }\n }\n\n /**\n * Sets the session tokens for OAuth callback flows.\n * This properly updates the SessionManager and persists tokens to storage.\n *\n * @param tokens Object containing access_token and optionally refresh_token\n *\n * @example\n * ```typescript\n * // After OAuth callback\n * await sso.setSession({\n * access_token: accessToken,\n * refresh_token: refreshToken\n * });\n * ```\n */\n public async setSession(tokens: { access_token: string; refresh_token?: string }): Promise<void> {\n await this.session.setSession(tokens);\n }\n\n /**\n * Sets the API key for service-to-service authentication.\n * Pass null to clear the API key.\n *\n * @param apiKey The API key string, or null to clear\n *\n * @example\n * ```typescript\n * // Set API key\n * sso.setApiKey('sk_live_abcd1234...');\n *\n * // Clear API key\n * sso.setApiKey(null);\n * ```\n */\n public setApiKey(apiKey: string | null): void {\n if (apiKey) {\n this.http.defaults.headers.common['X-Api-Key'] = apiKey;\n } else {\n delete this.http.defaults.headers.common['X-Api-Key'];\n }\n }\n\n /**\n * Gets the current base URL\n */\n public getBaseURL(): string {\n return this.http.defaults.baseURL || '';\n }\n\n /**\n * Gets the JWKS (JSON Web Key Set) URL for JWT verification.\n * Use this for stateless token verification in edge functions or middleware.\n *\n * @returns The full URL to the .well-known/jwks.json endpoint\n *\n * @example\n * ```typescript\n * const jwksUrl = sso.getJwksUrl();\n * // Returns: \"https://sso.example.com/.well-known/jwks.json\"\n * ```\n */\n public getJwksUrl(): string {\n const baseUrl = this.getBaseURL().replace(/\\/$/, '');\n return `${baseUrl}/.well-known/jwks.json`;\n }\n\n /**\n * Check if the user is currently authenticated\n */\n public isAuthenticated(): boolean {\n return this.session.isAuthenticated();\n }\n\n /**\n * Subscribe to authentication state changes.\n * Useful for updating UI when login/logout/expiration occurs.\n *\n * @param listener Callback function that receives the authentication state\n * @returns Unsubscribe function\n *\n * @example\n * ```typescript\n * const unsubscribe = sso.onAuthStateChange((isAuth) => {\n * console.log(isAuth ? 'User is logged in' : 'User is logged out');\n * });\n *\n * // Later, to stop listening\n * unsubscribe();\n * ```\n */\n public onAuthStateChange(listener: (isAuthenticated: boolean) => void) {\n return this.session.subscribe(listener);\n }\n\n /**\n * Manually retrieve the current access token\n *\n * @returns The current access token, or null if not authenticated\n */\n public async getToken(): Promise<string | null> {\n return this.session.getToken();\n }\n}\n"],"mappings":";;;;;AAIA,IAAY,iBAAL,yBAAA,gBAAA;;CAEL,eAAA,kBAAA;;CAEA,eAAA,kBAAA;;CAEA,eAAA,yBAAA;;CAEA,eAAA,2BAAA;;CAEA,eAAA,eAAA;;CAEA,eAAA,kBAAA;;CAEA,eAAA,eAAA;;CAEA,eAAA,mBAAA;;CAEA,eAAA,sBAAA;;CAEA,eAAA,0BAAA;;CAEA,eAAA,wBAAA;;CAEA,eAAA,uBAAA;;CAEA,eAAA,mBAAA;;CAEA,eAAA,iBAAA;;CAEA,eAAA,0BAAA;;CAEA,eAAA,6BAAA;;CAEA,eAAA,4BAAA;;CAEA,eAAA,yBAAA;;CAEA,eAAA,wBAAA;;CAEA,eAAA,kBAAA;;CAEA,eAAA,yBAAA;;CAEA,eAAA,2BAAA;CACA,eAAA,yBAAA;;CAEA,eAAA,mCAAA;;CAEA,eAAA,kBAAA;CACA,eAAA,uBAAA;;CAEA,eAAA,mBAAA;;CAEA,eAAA,sBAAA;;CAEA,eAAA,eAAA;;CAEA,eAAA,2BAAA;;CAEA,eAAA,iBAAA;;CAEA,eAAA,mBAAA;;CAEA,eAAA,kBAAA;;CAEA,eAAA,oBAAA;;CAEA,eAAA,mBAAA;;AACF,EAAA,CAAA,CAAA;;;;;AAMA,IAAa,cAAb,MAAa,oBAAoB,MAAM;CAgBrC,YAAY,SAAiB,YAAoB,WAAmB,WAAmB;EACrF,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,aAAa;EAClB,KAAK,YAAY;EACjB,KAAK,YAAY;EAGjB,IAAI,MAAM,mBACR,MAAM,kBAAkB,MAAM,WAAW;CAE7C;;;;CAKA,GAAU,WAA4B;EACpC,OAAO,KAAK,cAAc;CAC5B;;;;CAKA,cAA8B;EAC5B,OAAO,KAAK,eAAe,OAAO,KAAK,cAAc,kBAAkB,KAAK,cAAc;CAC5F;;;;CAKA,cAA8B;EAC5B,OAAO,KAAK,eAAe,OAAO,KAAK,cAAc;CACvD;;;;CAKA,aAA6B;EAC3B,OAAO,KAAK,eAAe,OAAO,KAAK,cAAc;CACvD;AACF;;;;;;;AChGA,IAAa,aAAb,MAAwB;CAItB,YAAY,SAAiB;EAC3B,KAAK,WAAW;GACd;GACA,SAAS,EACP,QAAQ,EACN,gBAAgB,mBAClB,EACF;GACA,SAAS;EACX;CACF;;;;CAKA,kBAAyB,SAAyB;EAChD,KAAK,iBAAiB;CACxB;;;;CAKA,iBAAyB,QAAsC;EAC7D,IAAI,CAAC,QAAQ,OAAO;EAEpB,MAAM,eAAe,IAAI,gBAAgB;EACzC,OAAO,QAAQ,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,WAAW;GAC/C,IAAI,UAAU,KAAA,KAAa,UAAU,MACnC,aAAa,OAAO,KAAK,OAAO,KAAK,CAAC;EAE1C,CAAC;EAED,MAAM,cAAc,aAAa,SAAS;EAC1C,OAAO,cAAc,IAAI,gBAAgB;CAC3C;;;;CAKA,SAAiB,MAAc,QAAsC;EAInE,OAAO,GAHS,KAAK,SAAS,QAAQ,QAAQ,OAAO,EAGrC,IAFE,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,SAChC,KAAK,iBAAiB,MACA;CAC5C;;;;CAKA,MAAc,QAAiB,MAAc,SAAmD;EAC9F,MAAM,MAAM,KAAK,SAAS,MAAM,QAAQ,MAAM;EAC9C,MAAM,UAAU,QAAQ,WAAW,KAAK,SAAS;EAGjD,MAAM,UAAU;GACd,GAAG,KAAK,SAAS,QAAQ;GACzB,GAAG,QAAQ;EACb;EAGA,IAAI,KAAK,gBAAgB;GACvB,MAAM,QAAQ,MAAM,KAAK,eAAe,SAAS;GACjD,IAAI,OACF,QAAQ,mBAAmB,UAAU;EAEzC;EAKA,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,YAAY,iBAAiB,WAAW,MAAM,GAAG,OAAO;EAE9D,IAAI;GACF,MAAM,WAAW,MAAM,MAAM,KAAK;IAChC,QAAQ,QAAQ;IAChB;IACA,MAAM,QAAQ,OAAO,KAAK,UAAU,QAAQ,IAAI,IAAI,KAAA;IACpD,QAAQ,WAAW;GACrB,CAAC;GAED,aAAa,SAAS;GAGtB,IACE,SAAS,WAAW,OACpB,KAAK,kBACL,CAAC,QAAQ,UACT,CAAC,KAAK,SAAS,aAAa,KAC5B,CAAC,KAAK,SAAS,eAAe,GAE9B,IAAI;IACF,MAAM,WAAW,MAAM,KAAK,eAAe,eAAe;IAE1D,OAAO,KAAK,QAAW,MAAM;KAC3B,GAAG;KACH,QAAQ;KACR,SAAS;MAAE,GAAG,QAAQ;MAAS,eAAe,UAAU;KAAW;IACrE,CAAC;GACH,SAAS,cAAc,CAEvB;GAIF,IAAI;GAGJ,IAFoB,SAAS,QAAQ,IAAI,cAE3B,CAAC,EAAE,SAAS,kBAAkB,GAC1C,OAAO,MAAM,SAAS,KAAK;QAG3B,OAAO,MADY,SAAS,KAAK,KAClB,KAAA;GAIjB,IAAI,CAAC,SAAS,IAAI;IAChB,IAAI,QAAQ,KAAK,cAAc,KAAK,SAAS,KAAK,WAChD,MAAM,IAAI,YAAY,KAAK,OAAO,SAAS,QAAQ,KAAK,YAAY,KAAK,SAAS;IAIpF,MAAM,IAAI,YACR,MAAM,WAAW,QAAQ,SAAS,OAAO,IAAI,SAAS,cACtD,SAAS,QACT,kCACA,IAAI,KAAK,EAAA,CAAE,YAAY,CACzB;GACF;GAEA,OAAO;IACL;IACA,QAAQ,SAAS;IACjB,SAAS,SAAS;GACpB;EACF,SAAS,OAAY;GACnB,aAAa,SAAS;GAGtB,IAAI,MAAM,SAAS,cACjB,MAAM,IAAI,YAAY,mBAAmB,KAAK,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY,CAAC;GAInF,IAAI,iBAAiB,aAAa,MAAM,QAAQ,SAAS,OAAO,GAC9D,MAAM,IAAI,YACR,8CACA,GACA,kCACA,IAAI,KAAK,EAAA,CAAE,YAAY,CACzB;GAIF,IAAI,iBAAiB,aACnB,MAAM;GAIR,MAAM,IAAI,YACR,MAAM,WAAW,gCACjB,KACA,kCACA,IAAI,KAAK,EAAA,CAAE,YAAY,CACzB;EACF;CACF;;;;CAKA,MAAa,IACX,MACA,QAC0B;EAC1B,OAAO,KAAK,QAAW,MAAM;GAC3B,QAAQ;GACR,QAAQ,QAAQ;GAChB,SAAS,QAAQ;EACnB,CAAC;CACH;;;;CAKA,MAAa,KACX,MACA,MACA,QAC0B;EAC1B,OAAO,KAAK,QAAW,MAAM;GAC3B,QAAQ;GACR,MAAM;GACN,SAAS,QAAQ;EACnB,CAAC;CACH;;;;CAKA,MAAa,IACX,MACA,MACA,QAC0B;EAC1B,OAAO,KAAK,QAAW,MAAM;GAC3B,QAAQ;GACR,MAAM;GACN,SAAS,QAAQ;EACnB,CAAC;CACH;;;;CAKA,MAAa,MACX,MACA,MACA,QAC0B;EAC1B,OAAO,KAAK,QAAW,MAAM;GAC3B,QAAQ;GACR,MAAM;GACN,SAAS,QAAQ;EACnB,CAAC;CACH;;;;CAKA,MAAa,OACX,MACA,MACA,QAC0B;EAC1B,MAAM,gBACJ,QAAQ,OAAO,SAAS,YAAY,aAAa,QAAQ,CAAC,SACtD,OACA;EACN,MAAM,OAAO,kBAAkB,OAAO,KAAA,IAAY;EAElD,OAAO,KAAK,QAAW,MAAM;GAC3B,QAAQ;GACR;GACA,SAAS,eAAe;EAC1B,CAAC;CACH;AACF;;;;;;AAOA,SAAgB,gBAAgB,SAA6B;CAC3D,OAAO,IAAI,WAAW,OAAO;AAC/B;;;ACzRA,MAAM,+BAA+B;AAErC,SAAS,oBAAoB,OAA8B;CACzD,MAAM,GAAG,WAAW,MAAM,MAAM,GAAG;CACnC,IAAI,CAAC,SACH,OAAO;CAGT,IAAI;EACF,MAAM,aAAa,QAAQ,QAAQ,MAAM,GAAG,CAAC,CAAC,QAAQ,MAAM,GAAG;EAC/D,MAAM,SAAS,WAAW,OAAO,WAAW,UAAW,IAAK,WAAW,SAAS,KAAM,GAAI,GAAG;EAC7F,MAAM,UAAU,WAAW,KAAK,MAAM;EACtC,MAAM,SAAS,KAAK,MAAM,OAAO;EACjC,OAAO,OAAO,OAAO,QAAQ,YAAY,OAAO,SAAS,OAAO,GAAG,IAAI,OAAO,MAAM;CACtF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,IAAa,iBAAb,MAA4B;CAO1B,YACE,SACA,gBACA,SAAgC,EAAE,kBAAkB,OAAO,GAC3D;EAHQ,KAAA,UAAA;EACA,KAAA,iBAAA;EACA,KAAA,SAAA;qBAT2B;sBACC;wBACW;wBACxB;mBACsC,CAAC;CAM7D;;;;CAKH,MAAa,cAA6B;EACxC,MAAM,UAAU,KAAK;EACrB,MAAM,cAAc,MAAM,KAAK,QAAQ,QAAQ,GAAG,KAAK,OAAO,iBAAiB,aAAa;EAC5F,MAAM,eAAe,MAAM,KAAK,QAAQ,QAAQ,GAAG,KAAK,OAAO,iBAAiB,cAAc;EAE9F,IAAI,YAAY,KAAK,gBACnB;EAGF,KAAK,cAAc;EACnB,KAAK,eAAe;CACtB;;;;CAKA,MAAa,WAAW,QAA0D;EAChF,KAAK,kBAAkB;EACvB,KAAK,cAAc,OAAO;EAC1B,MAAM,KAAK,QAAQ,QAAQ,GAAG,KAAK,OAAO,iBAAiB,eAAe,OAAO,YAAY;EAE7F,IAAI,OAAO,eAAe;GACxB,KAAK,eAAe,OAAO;GAC3B,MAAM,KAAK,QAAQ,QAAQ,GAAG,KAAK,OAAO,iBAAiB,gBAAgB,OAAO,aAAa;EACjG;EAEA,KAAK,gBAAgB,IAAI;CAC3B;;;;CAKA,MAAa,eAAe;EAC1B,KAAK,kBAAkB;EACvB,KAAK,cAAc;EACnB,KAAK,eAAe;EACpB,MAAM,KAAK,QAAQ,WAAW,GAAG,KAAK,OAAO,iBAAiB,aAAa;EAC3E,MAAM,KAAK,QAAQ,WAAW,GAAG,KAAK,OAAO,iBAAiB,cAAc;EAC5E,KAAK,gBAAgB,KAAK;CAC5B;;;;CAKA,MAAa,WAAmC;EAC9C,IAAI,CAAC,KAAK,aACR,OAAO;EAGT,MAAM,YAAY,oBAAoB,KAAK,WAAW;EACtD,IAAI,cAAc,MAChB,OAAO,KAAK;EAGd,MAAM,qBAAqB,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;EACnE,MAAM,qBAAqB,KAAK,OAAO,sBAAsB;EAE7D,IAAI,sBAAsB,KAAK,CAAC,KAAK,cAAc;GACjD,MAAM,KAAK,aAAa;GACxB,OAAO;EACT;EAEA,IAAI,sBAAsB,sBAAsB,KAAK,cACnD,IAAI;GACF,OAAO,MAAM,KAAK,eAAe;EACnC,QAAQ;GACN,OAAO;EACT;EAGF,OAAO,KAAK;CACd;;;;CAKA,MAAa,iBAAkC;EAC7C,IAAI,CAAC,KAAK,cACR,MAAM,IAAI,MAAM,4BAA4B;EAI9C,IAAI,KAAK,gBACP,OAAO,KAAK;EAGd,KAAK,kBAAkB,YAAY;GACjC,IAAI;IACF,MAAM,SAAS,MAAM,KAAK,eAAe,KAAK,YAAa;IAC3D,MAAM,KAAK,WAAW,MAAM;IAC5B,OAAO,OAAO;GAChB,SAAS,KAAK;IACZ,MAAM,KAAK,aAAa;IACxB,MAAM;GACR,UAAU;IACR,KAAK,iBAAiB;GACxB;EACF,EAAA,CAAG;EAEH,OAAO,KAAK;CACd;CAEA,kBAAkC;EAChC,OAAO,CAAC,CAAC,KAAK;CAChB;;;;;CAMA,cAAmC;EACjC,OAAO;GACL,iBAAiB,CAAC,CAAC,KAAK;GACxB,OAAO,KAAK;EACd;CACF;;;;;CAMA,UAAiB,UAA8C;EAC7D,KAAK,UAAU,KAAK,QAAQ;EAE5B,SAAS,KAAK,gBAAgB,CAAC;EAC/B,aAAa;GACX,KAAK,YAAY,KAAK,UAAU,QAAQ,MAAM,MAAM,QAAQ;EAC9D;CACF;CAEA,gBAAwB,QAAiB;EACvC,KAAK,UAAU,SAAS,MAAM,EAAE,MAAM,CAAC;CACzC;AACF;;;;;;AC9KA,IAAa,gBAAb,MAAmD;;+BACjC,IAAI,IAAoB;;CAExC,QAAQ,KAAa;EACnB,OAAO,KAAK,MAAM,IAAI,GAAG,KAAK;CAChC;CAEA,QAAQ,KAAa,OAAe;EAClC,KAAK,MAAM,IAAI,KAAK,KAAK;CAC3B;CAEA,WAAW,KAAa;EACtB,KAAK,MAAM,OAAO,GAAG;CACvB;AACF;;;;AAKA,IAAa,iBAAb,MAAoD;CAClD,QAAQ,KAAa;EACnB,OAAO,OAAO,WAAW,cAAc,OAAO,aAAa,QAAQ,GAAG,IAAI;CAC5E;CAEA,QAAQ,KAAa,OAAe;EAClC,IAAI,OAAO,WAAW,aAAa,OAAO,aAAa,QAAQ,KAAK,KAAK;CAC3E;CAEA,WAAW,KAAa;EACtB,IAAI,OAAO,WAAW,aAAa,OAAO,aAAa,WAAW,GAAG;CACvE;AACF;;;;;;;;;;AAWA,IAAa,gBAAb,MAAmD;CACjD,YACE,UAMI,CAAC,GACL;EAPQ,KAAA,UAAA;CAOP;CAEH,UAAkB,MAA6B;EAC7C,IAAI,OAAO,WAAW,aAAa,OAAO;EAG1C,MAAM,QAAQ,KADK,SAAS,SACR,MAAM,KAAK,KAAK,EAAE;EACtC,IAAI,MAAM,WAAW,GACnB,OAAO,MAAM,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,MAAM,KAAK;EAE5C,OAAO;CACT;CAEA,UAAkB,MAAc,OAAqB;EACnD,IAAI,OAAO,WAAW,aAAa;EAEnC,IAAI,SAAS,GAAG,KAAK,GAAG;EAExB,IAAI,KAAK,QAAQ,MACf,UAAU,UAAU,KAAK,QAAQ;EAGnC,IAAI,KAAK,QAAQ,QACf,UAAU,YAAY,KAAK,QAAQ;EAGrC,IAAI,KAAK,QAAQ,WAAW,OAE1B,UAAU;EAGZ,IAAI,KAAK,QAAQ,YAAY,OAC3B,UAAU,cAAc,KAAK,QAAQ,YAAY;EAGnD,IAAI,KAAK,QAAQ,QACf,UAAU,aAAa,KAAK,QAAQ;EAGtC,SAAS,SAAS;CACpB;CAEA,aAAqB,MAAoB;EACvC,IAAI,OAAO,WAAW,aAAa;EAEnC,IAAI,SAAS,GAAG,KAAK;EAErB,IAAI,KAAK,QAAQ,MACf,UAAU,UAAU,KAAK,QAAQ;EAGnC,IAAI,KAAK,QAAQ,QACf,UAAU,YAAY,KAAK,QAAQ;EAGrC,SAAS,SAAS;CACpB;CAEA,QAAQ,KAA4B;EAClC,OAAO,KAAK,UAAU,GAAG;CAC3B;CAEA,QAAQ,KAAa,OAAqB;EACxC,KAAK,UAAU,KAAK,KAAK;CAC3B;CAEA,WAAW,KAAmB;EAC5B,KAAK,aAAa,GAAG;CACvB;AACF;;;;AAKA,SAAgB,eAAe,aAA0C;CACvE,IAAI,aAAa,OAAO;CACxB,IAAI,OAAO,WAAW,eAAe,OAAO,cAAc,OAAO,IAAI,eAAe;CACpF,OAAO,IAAI,cAAc;AAC3B;;;;;;ACjIA,IAAa,kBAAb,MAA6B;CAC3B,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;;;;;;;;;;;;;;;;;;CAmBvC,MAAa,eACX,SACA,QAC4B;EAK5B,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,0BAC9B,EAAE,OAAO,CACX,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;;CAmBA,MAAa,mBACX,SACA,QAC4B;EAK5B,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,+BAC9B,EAAE,OAAO,CACX,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;;CAmBA,MAAa,oBACX,SACA,QAC6B;EAK7B,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,gCAC9B,EAAE,OAAO,CACX,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;;CAmBA,MAAa,gBACX,SACA,QACwB;EAKxB,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,2BAC9B,EAAE,OAAO,CACX,EAAA,CACgB;CAClB;AACF;;;;;;AC7FA,IAAa,aAAb,MAAwB;CACtB,YACE,MACA,SACA;EAFQ,KAAA,OAAA;EACA,KAAA,UAAA;oBA+JU;;;;GAIlB,SAAS,OAAO,YAA4D;IAE1E,QAAO,MADgB,KAAK,KAAK,KAAyB,qBAAqB,OAAO,EAAA,CACtE;GAClB;;;;;;;;;;;;;;GAeA,QAAQ,OAAO,aAAoD;IAIjE,QAAO,MAHgB,KAAK,KAAK,KAA2B,uBAAuB,EACjF,WAAW,SACb,CAAC,EAAA,CACe;GAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCA,eAAe,OAAO,YAAkD;IAEtE,QAAO,MADgB,KAAK,KAAK,KAAoB,eAAe,OAAO,EAAA,CAC3D;GAClB;EACF;CA9NI;;;;;;;;;;;;;;;;;;CAmBJ,gBAAuB,QAAoC;EACzD,MAAM,WAAW,KAAK,KAAK,SAAS,WAAW,GAAA,CAAI,QAAQ,QAAQ,EAAE;EACrE,MAAM,eAAe,IAAI,gBAAgB;GACvC,KAAK,OAAO;GACZ,SAAS,OAAO;GAChB,cAAc,OAAO;EACvB,CAAC;EACD,IAAI,OAAO,OAAO,aAAa,OAAO,SAAS,OAAO,KAAK;EAE3D,OAAO,GAAG,QAAQ,aAAa,aAAa,SAAS;CACvD;;;;;;;;CASA,sBAA6B,SAAmC,CAAC,GAAW;EAC1E,MAAM,WAAW,KAAK,KAAK,SAAS,WAAW,GAAA,CAAI,QAAQ,QAAQ,EAAE;EACrE,MAAM,eAAe,IAAI,gBAAgB;EAEzC,IAAI,OAAO,KAAK,aAAa,OAAO,OAAO,OAAO,GAAG;EACrD,IAAI,OAAO,SAAS,aAAa,OAAO,WAAW,OAAO,OAAO;EACjE,IAAI,OAAO,WAAW,aAAa,OAAO,aAAa,OAAO,SAAS;EAEvE,MAAM,QAAQ,aAAa,SAAS;EACpC,OAAO,GAAG,QAAQ,uBAAuB,QAAQ,IAAI,UAAU;CACjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCA,YAAmB,UAAyB,QAAgC;EAC1E,MAAM,UAAU,KAAK,KAAK,SAAS,WAAW;EAC9C,MAAM,eAAe,IAAI,gBAAgB;GACvC,KAAK,OAAO;GACZ,SAAS,OAAO;EAClB,CAAC;EAED,IAAI,OAAO,cACT,aAAa,OAAO,gBAAgB,OAAO,YAAY;EAEzD,IAAI,OAAO,OACT,aAAa,OAAO,SAAS,OAAO,KAAK;EAG3C,IAAI,OAAO,WACT,aAAa,OAAO,aAAa,OAAO,SAAS;EAGnD,IAAI,OAAO,eACT,aAAa,OAAO,iBAAiB,OAAO,aAAa;EAG3D,OAAO,GAAG,QAAQ,QAAQ,SAAS,GAAG,aAAa,SAAS;CAC9D;;;;;;;;;;;;;;;;;CAkBA,iBAAwB,UAAyB,QAAsC;EACrF,MAAM,UAAU,KAAK,KAAK,SAAS,WAAW;EAC9C,MAAM,eAAe,IAAI,gBAAgB;EAEzC,IAAI,QAAQ,UACV,aAAa,OAAO,YAAY,OAAO,QAAQ;EAGjD,IAAI,QAAQ,WACV,aAAa,OAAO,aAAa,OAAO,SAAS;EAGnD,IAAI,QAAQ,WACV,aAAa,OAAO,aAAa,OAAO,SAAS;EAGnD,MAAM,cAAc,aAAa,SAAS;EAC1C,OAAO,GAAG,QAAQ,cAAc,WAAW,cAAc,IAAI,gBAAgB;CAC/E;;;;;;;;;;;CA8FA,MAAa,SAAwB;EACnC,IAAI;GACF,MAAM,KAAK,KAAK,KAAK,kBAAkB;EACzC,UAAU;GAER,MAAM,KAAK,QAAQ,aAAa;EAClC;CACF;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BA,MAAa,aAAa,cAAqD;EAI7E,QAAO,MAHgB,KAAK,KAAK,KAA2B,qBAAqB,EAC/E,eAAe,aACjB,CAAC,EAAA,CACe;CAClB;;;;;;;;;;;;;;CAeA,MAAa,iBAAiB,UAAiD;EAE7E,QAAO,MADgB,KAAK,KAAK,IAAmB,uBAAuB,UAAU,EAAA,CACrE;CAClB;;;;;;;;;;;;;;;;;CAsBA,MAAa,SAAS,SAAqD;EAEzE,QAAO,MADgB,KAAK,KAAK,KAAuB,sBAAsB,OAAO,EAAA,CACrE;CAClB;;;;;;;;;;;;CAaA,MAAa,YAAY,OAAgC;EAIvD,QAAO,MAHgB,KAAK,KAAK,IAAY,sBAAsB,EACjE,QAAQ,EAAE,MAAM,EAClB,CAAC,EAAA,CACe;CAClB;;;;;;;;;;;;;;;;CAiBA,MAAa,mBAAmB,SAAyE;EAEvG,QAAO,MADgB,KAAK,KAAK,KAAiC,iCAAiC,OAAO,EAAA,CAC1F;CAClB;;;;;;;;;;;;;;;;;CAkBA,MAAa,MAAM,SAAsD;EACvE,MAAM,WAAW,MAAM,KAAK,KAAK,KAA2B,mBAAmB,OAAO;EAEtF,IAAI,SAAS,KAAK,eAChB,MAAM,KAAK,QAAQ,WAAW;GAC5B,cAAc,SAAS,KAAK;GAC5B,eAAe,SAAS,KAAK;EAC/B,CAAC;EAGH,OAAO,SAAS;CAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BA,MAAa,UACX,cACA,MACA,cACkC;EAClC,MAAM,WAAW,MAAM,KAAK,KAAK,KAA8B,wBAAwB;GACrF,eAAe;GACf;GACA,GAAI,gBAAgB,EAAE,gBAAgB,aAAa;EACrD,CAAC;EAGD,MAAM,KAAK,QAAQ,WAAW;GAC5B,cAAc,SAAS,KAAK;GAC5B,eAAe,SAAS,KAAK;EAC/B,CAAC;EAED,OAAO,SAAS;CAClB;;;;;;;;;;;;;;;;;CAkBA,MAAa,qBAAqB,SAAiE;EAEjG,QAAO,MADgB,KAAK,KAAK,KAA6B,6BAA6B,OAAO,EAAA,CAClF;CAClB;;;;;;;;;;;;;;;;;CAkBA,MAAa,cAAc,SAA+D;EAExF,QAAO,MADgB,KAAK,KAAK,KAA4B,4BAA4B,OAAO,EAAA,CAChF;CAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CA,MAAa,YAAY,OAA6C;EAIpE,QAAO,MAHgB,KAAK,KAAK,KAA0B,0BAA0B,EACnF,MACF,CAAC,EAAA,CACe;CAClB;;;;CAKA,MAAa,WAAW,SAA6B,CAAC,GAAiC;EACrF,MAAM,eAAe,IAAI,gBAAgB;EACzC,IAAI,OAAO,KAAK,aAAa,OAAO,OAAO,OAAO,GAAG;EACrD,IAAI,OAAO,SAAS,aAAa,OAAO,WAAW,OAAO,OAAO;EACjE,IAAI,OAAO,cAAc,aAAa,OAAO,gBAAgB,OAAO,YAAY;EAEhF,MAAM,QAAQ,aAAa,SAAS;EAIpC,QAAO,MAHgB,KAAK,KAAK,IAC/B,oBAAoB,QAAQ,IAAI,UAAU,IAC5C,EAAA,CACgB;CAClB;AACF;;;;;;ACzjBA,IAAM,mBAAN,MAAuB;CACrB,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;;;;;;;;;;;;CAavC,MAAa,OAA4B;EAEvC,QAAO,MADgB,KAAK,KAAK,IAAgB,sBAAsB,EAAA,CACvD;CAClB;;;;;;;;;;;;;;CAeA,MAAa,UAAU,UAA8C;EAEnE,QAAO,MADgB,KAAK,KAAK,KAAwB,wBAAwB,SAAS,QAAQ,CAAC,CAAC,EAAA,CACpF;CAClB;;;;;;;;;;;;CAaA,MAAa,OAAO,UAAiC;EACnD,MAAM,KAAK,KAAK,OAAO,wBAAwB,UAAU;CAC3D;AACF;AAEA,IAAM,uBAAN,MAA2B;CACzB,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;CAEvC,MAAa,OAAwC;EAEnD,QAAO,MADgB,KAAK,KAAK,IAA4B,2BAA2B,EAAA,CACxE;CAClB;CAEA,MAAa,UAAU,UAA8C;EAEnE,QAAO,MADgB,KAAK,KAAK,KAAwB,6BAA6B,SAAS,QAAQ,CAAC,CAAC,EAAA,CACzF;CAClB;CAEA,MAAa,MAAM,WAAmB,SAAiE;EAErG,QAAO,MADgB,KAAK,KAAK,KAAyB,6BAA6B,UAAU,UAAU,OAAO,EAAA,CAClG;CAClB;CAEA,MAAa,YAAY,WAAmB,WAAkC;EAC5E,MAAM,KAAK,KAAK,OAAO,6BAA6B,UAAU,UAAU,WAAW;CACrF;CAEA,MAAa,OAAO,WAAkC;EACpD,MAAM,KAAK,KAAK,OAAO,6BAA6B,WAAW;CACjE;CAEA,MAAa,wBAAwB,OAAqD;EAExF,QAAO,MADgB,KAAK,KAAK,IAAiC,qCAAqC,OAAO,EAAA,CAC9F;CAClB;CAEA,MAAa,6BACX,OACA,UAA+C,CAAC,GACD;EAE/C,QAAO,MADgB,KAAK,KAAK,KAA2C,qCAAqC,MAAM,YAAY,OAAO,EAAA,CAC1H;CAClB;CAEA,MAAa,8BAA8B,OAA2C;EAEpF,QAAO,MADgB,KAAK,KAAK,KAAwB,qCAAqC,MAAM,QAAQ,CAAC,CAAC,EAAA,CAC9F;CAClB;AACF;;;;AAKA,IAAM,YAAN,MAAgB;CACd,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;;;;;;;;;;;;CAavC,MAAa,YAAwC;EAEnD,QAAO,MADgB,KAAK,KAAK,IAAuB,sBAAsB,EAAA,CAC9D;CAClB;;;;;;;;;;;;;;CAeA,MAAa,QAAmC;EAE9C,QAAO,MADgB,KAAK,KAAK,KAAuB,uBAAuB,CAAC,CAAC,EAAA,CACjE;CAClB;;;;;;;;;;;;;;CAeA,MAAa,OAAO,MAA0C;EAE5D,QAAO,MADgB,KAAK,KAAK,KAAwB,wBAAwB,EAAE,KAAK,CAAC,EAAA,CACzE;CAClB;;;;;;;;;CAUA,MAAa,UAA0D;EAErE,QAAO,MADgB,KAAK,KAAK,OAA8C,eAAe,EAAA,CAC9E;CAClB;;;;;;;;;;;;;CAcA,MAAa,wBAAsD;EAEjE,QAAO,MADgB,KAAK,KAAK,KAA0B,yCAAyC,CAAC,CAAC,EAAA,CACtF;CAClB;AACF;;;;AAKA,IAAM,gBAAN,MAAoB;CAClB,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;;;;;;;;;;;;;CAcvC,MAAa,KAAK,SAKe;EAC/B,MAAM,SAAS,IAAI,gBAAgB;EAEnC,IAAI,SAAS,MAAM,OAAO,OAAO,QAAQ,QAAQ,KAAK,SAAS,CAAC;EAChE,IAAI,SAAS,OAAO,OAAO,OAAO,SAAS,QAAQ,MAAM,SAAS,CAAC;EACnE,IAAI,SAAS,SAAS,OAAO,OAAO,WAAW,QAAQ,OAAO;EAC9D,IAAI,SAAS,YAAY,OAAO,OAAO,cAAc,QAAQ,UAAU;EAEvE,MAAM,QAAQ,OAAO,SAAS;EAC9B,MAAM,MAAM,oBAAoB,QAAQ,IAAI,UAAU;EAGtD,QAAO,MADgB,KAAK,KAAK,IAAyB,GAAG,EAAA,CAC7C;CAClB;;;;;;;;;;;;;CAcA,MAAa,IAAI,UAAuC;EAEtD,QAAO,MADgB,KAAK,KAAK,IAAgB,qBAAqB,UAAU,EAAA,CAChE;CAClB;;;;;;;;;;;;;;;CAgBA,MAAa,OAAO,UAAkB,QAAgD;EACpF,MAAM,UAAU,SAAS,EAAE,OAAO,IAAI,CAAC;EAEvC,QAAO,MADgB,KAAK,KAAK,KAA2B,qBAAqB,SAAS,UAAU,OAAO,EAAA,CAC3F;CAClB;;;;;;;;;;;;;CAcA,MAAa,YAA2C;EAEtD,QAAO,MADgB,KAAK,KAAK,KAA2B,gCAAgC,CAAC,CAAC,EAAA,CAC9E;CAClB;;;;;;;;;;;;;;CAeA,MAAa,WAAW,UAAkB,YAAyC;EAIjF,QAAO,MAHgB,KAAK,KAAK,MAAkB,qBAAqB,YAAY,EAClF,aAAa,WACf,CAAC,EAAA,CACe;CAClB;;;;;;;;;;;;;;CAeA,MAAa,MAAM,UAAuC;EAExD,QAAO,MADgB,KAAK,KAAK,KAAiB,qBAAqB,SAAS,SAAS,CAAC,CAAC,EAAA,CAC3E;CAClB;AACF;;;;AAKA,IAAa,aAAb,MAAwB;CAMtB,YAAY,MAA0B;EAAlB,KAAA,OAAA;EAClB,KAAK,aAAa,IAAI,iBAAiB,IAAI;EAC3C,KAAK,iBAAiB,IAAI,qBAAqB,IAAI;EACnD,KAAK,MAAM,IAAI,UAAU,IAAI;EAC7B,KAAK,UAAU,IAAI,cAAc,IAAI;CACvC;;;;;;;;;;;;;CAcA,MAAa,aAAmC;EAE9C,QAAO,MADgB,KAAK,KAAK,IAAiB,WAAW,EAAA,CAC7C;CAClB;;;;;;;;;;;;;;CAeA,MAAa,cAAc,SAAyD;EAElF,QAAO,MADgB,KAAK,KAAK,MAAmB,aAAa,OAAO,EAAA,CACxD;CAClB;;;;;;;;;;;;CAaA,MAAa,kBAAyC;EAEpD,QAAO,MADgB,KAAK,KAAK,IAAkB,mBAAmB,EAAA,CACtD;CAClB;;;;;;;;;;;;;;;;;CAkBA,MAAa,eAAe,SAAiE;EAE3F,QAAO,MADgB,KAAK,KAAK,KAA6B,6BAA6B,OAAO,EAAA,CAClF;CAClB;;;;;;;;;;;;;;;;;CAkBA,MAAa,YAAY,SAA2D;EAElF,QAAO,MADgB,KAAK,KAAK,KAA0B,0BAA0B,OAAO,EAAA,CAC5E;CAClB;AACF;;;;;;ACtaA,IAAa,kBAAb,MAA6B;CAC3B,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BvC,MAAa,IACX,SACA,QAC2B;EAK3B,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,aAC9B,EAAE,OAAO,CACX,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;;;;;;CAuBA,MAAa,cAAc,SAA2C;EAIpE,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,uBAChC,EAAA,CACgB;CAClB;AACF;;;;;;AChEA,IAAa,iBAAb,MAA4B;CAC1B,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;;;;;;;;;;;;;;;;;;;CAoBvC,MAAa,OACX,SACA,SAC0B;EAK1B,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,YAC9B,OACF,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;CAgBA,MAAa,KAAK,SAA+C;EAI/D,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,UAChC,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;CAiBA,MAAa,IAAI,SAAiB,WAA6C;EAI7E,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,YAAY,WAC5C,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;;;;;;;;CAyBA,MAAa,OACX,SACA,WACA,SAC0B;EAK1B,QAAO,MAJgB,KAAK,KAAK,MAC/B,sBAAsB,QAAQ,YAAY,aAC1C,OACF,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;CAgBA,MAAa,OAAO,SAAiB,WAAkC;EACrE,MAAM,KAAK,KAAK,OACd,sBAAsB,QAAQ,YAAY,WAC5C;CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BA,MAAa,cACX,SACA,WACA,QACsC;EAKtC,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,YAAY,UAAU,cACpD,EAAE,OAAO,CACX,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BA,MAAa,cAAc,SAA2C;EAIpE,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,sBAChC,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;CAgBA,MAAa,KAAK,SAAiB,WAAuF;EAIxH,QAAO,MAHgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,YAAY,UAAU,MACtD,EAAA,CACgB;CAClB;AACF;;;;;;ACnOA,IAAa,0BAAb,MAAqC;CACnC,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;;;;;;;CAQvC,MAAa,KAAK,SAA8C;EAI9D,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,oBAChC,EAAA,CACgB;CAClB;;;;;;;;CASA,MAAa,IAAI,SAAiB,YAA+C;EAI/E,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,sBAAsB,YACtD,EAAA,CACgB;CAClB;;;;;;;;CASA,MAAa,OACX,SACA,SAC2B;EAK3B,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,sBAC9B,OACF,EAAA,CACgB;CAClB;;;;;;;;;CAUA,MAAa,OACX,SACA,YACA,SAC2B;EAK3B,QAAO,MAJgB,KAAK,KAAK,MAC/B,sBAAsB,QAAQ,sBAAsB,cACpD,OACF,EAAA,CACgB;CAClB;;;;;;;CAQA,MAAa,OAAO,SAAiB,YAAmC;EACtE,MAAM,KAAK,KAAK,OAAO,sBAAsB,QAAQ,sBAAsB,YAAY;CACzF;AACF;;;;;;AChCA,IAAa,sBAAb,MAAiC;CAC/B,YAAY,MAA0B;EAAlB,KAAA,OAAA;cA6JN;;;;;GAKZ,aAAa,OACX,SACA,YAC+B;IAK/B,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,eAC9B,OACF,EAAA,CACgB;GAClB;;;;GAKA,YAAY,OAAO,YAAqD;IAItE,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,aAChC,EAAA,CACgB;GAClB;;;;GAKA,aAAa,OAAO,SAAiB,YAAmC;IACtE,MAAM,KAAK,KAAK,KAAK,sBAAsB,QAAQ,eAAe,QAAQ,QAAQ;GACpF;;;;GAKA,aAAa,OAAO,SAAiB,YAAmC;IACtE,MAAM,KAAK,KAAK,OAAO,sBAAsB,QAAQ,eAAe,SAAS;GAC/E;EACF;iBAKiB;;;;;;;;;;;;;;GAcf,MAAM,OAAO,YAAiD;IAI5D,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,SAChC,EAAA,CACgB;GAClB;;;;;;;;;;GAWA,KAAK,OACH,SACA,YACwB;IAOxB,MAAM,cAAa,MALI,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,eAC9B,OACF,EAAA,CAE4B;IAG5B,MAAM,KAAK,KAAK,KACd,sBAAsB,QAAQ,eAAe,WAAW,GAAG,QAC7D;IAEA,OAAO;GACT;;;;;;;;;;;;;;;;;GAkBA,YAAY,OACV,SACA,QACA,YACgC;IAKhC,QAAO,MAJgB,KAAK,KAAK,MAC/B,sBAAsB,QAAQ,WAAW,UACzC,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;GAcA,QAAQ,OAAO,SAAiB,WAAkC;IAChE,MAAM,KAAK,KAAK,KAAK,sBAAsB,QAAQ,WAAW,QAAQ;GACxE;;;;GAKA,mBAAmB,OACjB,SACA,WACmC;IAInC,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,WAAW,OAAO,gBAClD,EAAA,CACgB;GAClB;;;;GAKA,qBAAqB,OACnB,SACA,QACA,YACmC;IAKnC,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,WAAW,OAAO,kBAChD,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;GAgBA,mBAAmB,OAAO,SAAiB,YAAqD;IAC9F,MAAM,KAAK,KAAK,KAAK,sBAAsB,QAAQ,8BAA8B,OAAO;GAC1F;EACF;kBAMkB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BhB,MAAM,OACJ,SACA,WACiC;IAKjC,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,SAC9B,EAAE,OAAO,CACX,EAAA,CACgB;GAClB;;;;;;;;;;;;;;GAeA,KAAK,OAAO,SAAiB,WAAmD;IAI9E,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,SAAS,QACzC,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;GAiBA,gBAAgB,OACd,SACA,WACoC;IAIpC,QAAO,MAHgB,KAAK,KAAK,OAC/B,sBAAsB,QAAQ,SAAS,OAAO,UAChD,EAAA,CACgB;GAClB;EACF;0BAK0B;;;;;;;;;;;;;;;;;;;;GAoBxB,KAAK,OACH,SACA,UACA,YAC8B;IAK9B,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,qBAAqB,YACnD,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;GAgBA,KAAK,OAAO,SAAiB,aAAuD;IAIlF,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,qBAAqB,UACrD,EAAA,CACgB;GAClB;EACF;sBA6PsB;;;;;;;;;;;;;;;GAepB,KAAK,OAAO,YAAsD;IAIhE,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,eAChC,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;;;;GAsBA,QAAQ,OACN,SACA,YACwC;IAKxC,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,iBAC9B,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;GAeA,OAAO,OAAO,YAAyD;IAIrE,QAAO,MAHgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,qBAChC,EAAA,CACgB;GAClB;EACF;cASc;;;;;;;;;;;;;;;;;;;;GAoBZ,QAAQ,OACN,SACA,YACgC;IAKhC,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,gBAC9B,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;GAkBA,MAAM,OAAO,YAAsD;IAIjE,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,cAChC,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;GAgBA,KAAK,OAAO,SAAiB,aAAkD;IAI7E,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,gBAAgB,UAChD,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;GAmBA,QAAQ,OACN,SACA,UACA,YACgC;IAKhC,QAAO,MAJgB,KAAK,KAAK,MAC/B,sBAAsB,QAAQ,gBAAgB,YAC9C,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;GAeA,QAAQ,OAAO,SAAiB,aAAoC;IAClE,MAAM,KAAK,KAAK,OAAO,sBAAsB,QAAQ,gBAAgB,UAAU;GACjF;;;;;;;;;;;;;;;;;;;;GAqBA,MAAM,OAAO,SAAiB,aAAsD;IAIlF,QAAO,MAHgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,gBAAgB,SAAS,MACzD,EAAA,CACgB;GAClB;EACF;iBASiB;;;;;;;;;;;;;;;;;GAiBf,SAAS,OAAO,YAAwF;IAItG,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,cAChC,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;;;GAqBA,qBAAqB,OACnB,SACA,YAC6B;IAK7B,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,kBAC9B,OACF,EAAA,CACgB;GAClB;EACF;kBAKkB;;;;;;;;AAQhB,eAAe,OACb,SACA,WACiC;GAKjC,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,eAC9B,EAAE,OAAO,CACX,EAAA,CACgB;EAClB,EACF;eAKe;;;;GAIb,MAAM,OAAO,YAA6C;IAIxD,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,OAChC,EAAA,CACgB;GAClB;;;;GAKA,KAAK,OAAO,SAAiB,WAA0C;IAIrE,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,SAAS,QACzC,EAAA,CACgB;GAClB;;;;GAKA,QAAQ,OAAO,SAAiB,YAAsD;IAKpF,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,SAC9B,OACF,EAAA,CACgB;GAClB;;;;GAKA,QAAQ,OACN,SACA,QACA,YAC0B;IAK1B,QAAO,MAJgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,SAAS,UACvC,OACF,EAAA,CACgB;GAClB;;;;GAKA,QAAQ,OAAO,SAAiB,WAAkC;IAChE,MAAM,KAAK,KAAK,OAAO,sBAAsB,QAAQ,SAAS,QAAQ;GACxE;EACF;4BAW4B;;;;;;;;;;;;;;;;;;;GAmB1B,KAAK,OACH,SACA,aAMI;IAOJ,QAAO,MANgB,KAAK,KAAK,IAK9B,sBAAsB,QAAQ,uBAAuB,UAAU,EAAA,CAClD;GAClB;;;;;;;;;;;;;;;;;;;;GAqBA,KAAK,OACH,SACA,UACA,YAKkB;IAClB,MAAM,KAAK,KAAK,KACd,sBAAsB,QAAQ,uBAAuB,YACrD,OACF;GACF;;;;;;;;;;;;;;GAeA,QAAQ,OACN,SACA,aACkB;IAClB,MAAM,KAAK,KAAK,OACd,sBAAsB,QAAQ,uBAAuB,UACvD;GACF;EACF;EA1rCE,KAAK,YAAY,IAAI,gBAAgB,IAAI;EACzC,KAAK,WAAW,IAAI,eAAe,IAAI;EACvC,KAAK,oBAAoB,IAAI,wBAAwB,IAAI;CAC3D;;;;;;;;;;;;;;;;;;;CAmCA,MAAa,OAAO,SAAyE;EAE3F,QAAO,MADgB,KAAK,KAAK,KAAiC,sBAAsB,OAAO,EAAA,CAC/E;CAClB;;;;;;;;;;;;;;;;CAiBA,MAAa,KAAK,QAAmE;EAEnF,QAAO,MADgB,KAAK,KAAK,IAA4B,sBAAsB,EAAE,OAAO,CAAC,EAAA,CAC7E;CAClB;;;;;;;;;;;;;CAcA,MAAa,IAAI,SAAgD;EAE/D,QAAO,MADgB,KAAK,KAAK,IAA0B,sBAAsB,SAAS,EAAA,CAC1E;CAClB;;;;;;;;;;;;;;;;;;;;CAqBA,MAAa,OAAO,SAAsD;EAIxE,QAAO,MAHgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,QAChC,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;CAkBA,MAAa,OAAO,SAAiB,SAAmE;EAKtG,QAAO,MAJgB,KAAK,KAAK,MAC/B,sBAAsB,WACtB,OACF,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;;;;CAqBA,MAAa,OAAO,SAAgC;EAClD,MAAM,KAAK,KAAK,OAAO,sBAAsB,SAAS;CACxD;;;;;;;;;;;;;;;;;;;;;;;CAyWA,MAAa,QAAQ,SAAiB,QAAsD;EAK1F,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,QAC9B,MACF,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;CAkBA,MAAa,QAAQ,SAA8C;EAIjE,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,MAChC,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;CAgBA,MAAa,WAAW,SAA+C;EAIrE,QAAO,MAHgB,KAAK,KAAK,OAC/B,sBAAsB,QAAQ,MAChC,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;;;;;;CA2BA,MAAa,gBACX,SACA,SACqC;EAKrC,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,UAC9B,OACF,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;;CAmBA,MAAa,mBAAmB,SAAoD;EAIlF,QAAO,MAHgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,eAChC,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;CAgBA,MAAa,uBAAuB,SAA+C;EAIjF,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,QAChC,EAAA,CACgB;CAClB;;;;;;;;;;;;;CAcA,MAAa,mBAAmB,SAAgC;EAC9D,MAAM,KAAK,KAAK,OAAO,sBAAsB,QAAQ,QAAQ;CAC/D;;;;;;;;;;;;;;;;;;CAmBA,MAAa,eACX,SACA,SACgC;EAKhC,QAAO,MAJgB,KAAK,KAAK,MAC/B,sBAAsB,QAAQ,YAC9B,OACF,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;CAgBA,MAAa,YAAY,SAAiD;EAIxE,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,UAChC,EAAA,CACgB;CAClB;;;;;;;;;;;;;;CAeA,MAAa,kBAAkB,SAAiD;EAI9E,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,iBAChC,EAAA,CACgB;CAClB;AAmeF;;;;;;AC1tCA,IAAa,iBAAb,MAA4B;CAC1B,YAAY,MAA0B;EAAlB,KAAA,OAAA;eAmIL;;;;;;;;;;;;;;;;;;;;;GAqBb,QAAQ,OACN,SACA,aACA,YAC0B;IAK1B,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,YAAY,YAAY,SACtD,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;GAeA,MAAM,OAAO,SAAiB,gBAAiD;IAI7E,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,YAAY,YAAY,OACxD,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;;;;;GAuBA,QAAQ,OACN,SACA,aACA,QACA,YAC0B;IAK1B,QAAO,MAJgB,KAAK,KAAK,MAC/B,sBAAsB,QAAQ,YAAY,YAAY,SAAS,UAC/D,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;;;;;GAuBA,QAAQ,OAAO,SAAiB,aAAqB,WAAkC;IACrF,MAAM,KAAK,KAAK,OACd,sBAAsB,QAAQ,YAAY,YAAY,SAAS,QACjE;GACF;EACF;iBAKiB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0Bf,QAAQ,OACN,SACA,aACA,YACkC;IAKlC,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,YAAY,YAAY,YACtD,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;;;;;;;;GA0BA,MAAM,OACJ,SACA,aACA,YACiC;IACjC,MAAM,cAAc,IAAI,gBAAgB;IACxC,IAAI,SAAS,OAAO,YAAY,IAAI,SAAS,QAAQ,MAAM,SAAS,CAAC;IACrE,IAAI,SAAS,QAAQ,YAAY,IAAI,UAAU,QAAQ,OAAO,SAAS,CAAC;IAExE,MAAM,QAAQ,YAAY,SAAS,IAAI,IAAI,YAAY,SAAS,MAAM;IAItE,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,YAAY,YAAY,WAAW,OACnE,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;GAmBA,KAAK,OACH,SACA,aACA,aACoB;IAIpB,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,YAAY,YAAY,YAAY,UACpE,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;GAmBA,QAAQ,OACN,SACA,aACA,aACkB;IAClB,MAAM,KAAK,KAAK,OACd,sBAAsB,QAAQ,YAAY,YAAY,YAAY,UACpE;GACF;EACF;cAQc;;;;;;;;;;;;;;;;;;;;;;;;;GAyBZ,WAAW,OACT,SACA,aACA,YACmC;IAKnC,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,YAAY,YAAY,QACtD,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;GAmBA,WAAW,OAAO,SAAiB,gBAA6C;IAI9E,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,YAAY,YAAY,MACxD,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;GAiBA,cAAc,OAAO,SAAiB,gBAAwD;IAI5F,QAAO,MAHgB,KAAK,KAAK,OAC/B,sBAAsB,QAAQ,YAAY,YAAY,MACxD,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;GAgBA,eAAe,OAAO,SAAiB,gBAAyC;IAI9E,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,YAAY,YAAY,YACxD,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;;;GAqBA,qBAAqB,OACnB,SACA,gBAC6B;IAK7B,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,YAAY,YAAY,oBACtD,CAAC,CACH,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;GAmBA,gBAAgB,OAAO,SAAiB,gBAAkD;IAIxF,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,YAAY,YAAY,kBACxD,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;;;;GAsBA,iBAAiB,SAAiB,SAAiB,gBAAgC;IACjF,OAAO,GAAG,QAAQ,QAAQ,QAAQ,GAAG,YAAY;GACnD;;;;;;;;;;;;;;;;;;;;;GAsBA,YAAY,SAAiB,SAAiB,gBAAgC;IAC5E,OAAO,GAAG,QAAQ,QAAQ,QAAQ,GAAG,YAAY;GACnD;EACF;iBAKiB;;;;;;;;;;;;;;;;;;;;;;;;AAwBf,gBAAgB,OACd,SACA,aACA,YACoC;GAKpC,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,YAAY,YAAY,YACtD,OACF,EAAA,CACgB;EAClB,EACF;CA1nBwC;;;;;;;;;;;;;;;;;;;;;CAsBxC,MAAa,OAAO,SAAiB,SAA+D;EAKlG,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,YAC9B,OACF,EAAA,CACgB;CAClB;;;;;;;;;;;;;;CAeA,MAAa,KAAK,SAA+C;EAE/D,QAAO,MADgB,KAAK,KAAK,IAAyB,sBAAsB,QAAQ,UAAU,EAAA,CAClF;CAClB;;;;;;;;;;;;;;CAeA,MAAa,IAAI,SAAiB,aAAuC;EAIvE,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,YAAY,aAC5C,EAAA,CACgB;CAClB;;;;;;;;;;;;;;;;;;CAmBA,MAAa,OACX,SACA,aACA,SACkB;EAKlB,QAAO,MAJgB,KAAK,KAAK,MAC/B,sBAAsB,QAAQ,YAAY,eAC1C,OACF,EAAA,CACgB;CAClB;;;;;;;;;;;;;CAcA,MAAa,OAAO,SAAiB,aAAoC;EACvE,MAAM,KAAK,KAAK,OAAO,sBAAsB,QAAQ,YAAY,aAAa;CAChF;;;;;CAMA,MAAa,aACX,SACA,aACsC;EAKtC,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,YAAY,YAAY,iBACtD,CAAC,CACH,EAAA,CACgB;CAClB;AA6fF;;;;;;AC1oBA,IAAa,oBAAb,MAA+B;CAC7B,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAoB;;;;;;;;;;;;;;;;;CAkBxC,MAAa,OAAO,SAAiB,SAAuD;EAK1F,QAAO,MAJgB,KAAK,KAAK,KAC/B,sBAAsB,QAAQ,eAC9B,OACF,EAAA,CACgB;CAClB;;;;;;;;;;;;;;CAeA,MAAa,WAAW,SAAwC;EAI9D,QAAO,MAHgB,KAAK,KAAK,IAC/B,sBAAsB,QAAQ,aAChC,EAAA,CACgB;CAClB;;;;;;;;;;;;;CAcA,MAAa,OAAO,SAAiB,cAAqC;EACxE,MAAM,KAAK,KAAK,KAAK,sBAAsB,QAAQ,eAAe,cAAc;CAClF;;;;;;;;;;;;;;CAeA,MAAa,cAA4C;EAEvD,QAAO,MADgB,KAAK,KAAK,IAAyB,kBAAkB,EAAA,CAC5D;CAClB;;;;;;;;;;;CAYA,MAAa,OAAO,OAA8B;EAChD,MAAM,UAAmC,EAAE,MAAM;EACjD,MAAM,KAAK,KAAK,KAAK,2BAA2B,OAAO;CACzD;;;;;;CAOA,MAAa,WAAW,cAAqC;EAC3D,MAAM,KAAK,KAAK,KAAK,oBAAoB,aAAa,QAAQ;CAChE;;;;;;;;;;;CAYA,MAAa,QAAQ,OAA8B;EACjD,MAAM,UAAoC,EAAE,MAAM;EAClD,MAAM,KAAK,KAAK,KAAK,4BAA4B,OAAO;CAC1D;;;;;;CAOA,MAAa,YAAY,cAAqC;EAC5D,MAAM,KAAK,KAAK,KAAK,oBAAoB,aAAa,SAAS;CACjE;AACF;;;;;;;ACjHA,IAAa,iBAAb,MAA4B;CAC1B,YAAY,MAA0B;EAAlB,KAAA,OAAA;uBAqBG;;;;;;;;;;;;;;;;;GAiBrB,MAAM,OAAO,WAAyF;IAKpG,QAAO,MAJgB,KAAK,KAAK,IAC/B,+BACA,EAAE,OAAO,CACX,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;GAgBA,SAAS,OACP,OACA,YAC0B;IAK1B,QAAO,MAJgB,KAAK,KAAK,KAC/B,+BAA+B,MAAM,WACrC,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;GAgBA,QAAQ,OACN,OACA,YAC0B;IAK1B,QAAO,MAJgB,KAAK,KAAK,KAC/B,+BAA+B,MAAM,UACrC,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;GAaA,SAAS,OAAO,UAAyC;IAIvD,QAAO,MAHgB,KAAK,KAAK,KAC/B,+BAA+B,MAAM,SACvC,EAAA,CACgB;GAClB;;;;;;;;;;;;GAaA,UAAU,OAAO,UAAyC;IAIxD,QAAO,MAHgB,KAAK,KAAK,KAC/B,+BAA+B,MAAM,UACvC,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;GAkBA,YAAY,OACV,OACA,YAC0B;IAK1B,QAAO,MAJgB,KAAK,KAAK,MAC/B,+BAA+B,MAAM,QACrC,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;GAmBA,gBAAgB,OACd,OACA,YAc0B;IAK1B,QAAO,MAJgB,KAAK,KAAK,MAC/B,+BAA+B,MAAM,YACrC,OACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;;;;;;;;GAuBA,QAAQ,OAAO,UAAkE;IAI/E,QAAO,MAHgB,KAAK,KAAK,OAC/B,+BAA+B,OACjC,EAAA,CACgB;GAClB;EACF;eAmCe;;;;;;;;;;;;;GAab,cAAc,OAAO,WAA6E;IAEhG,QAAO,MADgB,KAAK,KAAK,IAAqD,uBAAuB,OAAO,YAAY,EAAA,CAChH;GAClB;;;;;;;;;;;;;GAcA,MAAM,OAAO,YAAiH;IAE5H,QAAO,MADgB,KAAK,KAAK,IAA0D,uBAAuB,EAAE,QAAQ,QAAQ,CAAC,EAAA,CACrH;GAClB;;;;GAKA,KAAK,OAAO,WAKN;IAOJ,QAAO,MANgB,KAAK,KAAK,IAK9B,uBAAuB,QAAQ,EAAA,CAClB;GAClB;;;;;;;;;;;;;;;;;;;;GAqBA,QAAQ,OAAO,OAAe,YAKvB;IACL,MAAM,SAAS;KACb,GAAG,MAAM,KAAK;KACd,OAAO,SAAS,QAAQ,KAAK,IAAI,QAAQ,OAAO,EAAE,IAAI,KAAA;IACxD;IASA,QAAO,MAPgB,KAAK,KAAK,IAK7B,8BAA8B,EAAE,OAAO,CAAC,EAAA,CAE5B;GAClB;;;;;;;;;;;;;GAcA,iBAAiB,OAAO,WAAmE;IAEzF,QAAO,MADgB,KAAK,KAAK,OAA8C,uBAAuB,OAAO,KAAK,EAAA,CAClG;GAClB;EACF;mBAyBmB;;;;;;;;;;;;GAYjB,aAAa,YAA8C;IAEzD,QAAO,MADgB,KAAK,KAAK,IAA6B,kCAAkC,EAAA,CAChF;GAClB;;;;;;;;;;;;GAaA,uBAAuB,YAAkD;IAIvE,QAAO,MAHgB,KAAK,KAAK,IAC/B,6CACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;GAgBA,iBAAiB,OAAO,WAA2E;IAKjG,QAAO,MAJgB,KAAK,KAAK,IAC/B,yCACA,EAAE,OAAO,CACX,EAAA,CACgB;GAClB;;;;;;;;;;;;;;;GAgBA,kBAAkB,OAAO,WAA6E;IAKpG,QAAO,MAJgB,KAAK,KAAK,IAC/B,0CACA,EAAE,OAAO,CACX,EAAA,CACgB;GAClB;;;;;;;;;;;;GAaA,qBAAqB,YAAwC;IAI3D,QAAO,MAHgB,KAAK,KAAK,IAC/B,2CACF,EAAA,CACgB;GAClB;;;;;;;;;;;;;;GAeA,wBAAwB,OAAO,WAA8D;IAK3F,QAAO,MAJgB,KAAK,KAAK,IAC/B,gDACA,EAAE,OAAO,CACX,EAAA,CACgB;GAClB;EACF;CAjgBwC;;;;;;;;;;;;CAaxC,MAAa,WAAwC;EAEnD,QAAO,MADgB,KAAK,KAAK,IAAwB,qBAAqB,EAAA,CAC9D;CAClB;;;;;;;;;;;;;CAiOA,MAAa,aAAa,SAAqD;EAC7E,MAAM,KAAK,KAAK,KAAK,wBAAwB,OAAO;CACtD;;;;;;;;;;;CAYA,MAAa,YAAY,QAA+B;EACtD,MAAM,KAAK,KAAK,OAAO,wBAAwB,QAAQ;CACzD;;;;;;;;;;;;;;;;CAmIA,MAAa,YAAY,QAAsD;EAE7E,QAAO,MADgB,KAAK,KAAK,IAAqB,2BAA2B,EAAE,OAAO,CAAC,EAAA,CAC3E;CAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2JA,MAAa,gBAAgB,SAA2D;EAEtF,QAAO,MADgB,KAAK,KAAK,KAA0B,6BAA6B,OAAO,EAAA,CAC/E;CAClB;;;;CAKA,MAAa,sBAOV;EASD,QAAO,MARgB,KAAK,KAAK,IAO9B,iCAAiC,EAAA,CACpB;CAClB;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1bA,IAAa,mBAAb,MAA8B;CAC5B,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAoB;;;;;;;;CASxC,MAAM,UAAU,QAA0E;EACxF,MAAM,cAAc,IAAI,gBAAgB;EACxC,IAAI,QAAQ,OAAO,YAAY,IAAI,SAAS,OAAO,MAAM,SAAS,CAAC;EACnE,IAAI,QAAQ,QAAQ,YAAY,IAAI,UAAU,OAAO,OAAO,SAAS,CAAC;EAEtE,MAAM,QAAQ,YAAY,SAAS,IAAI,IAAI,YAAY,SAAS,MAAM;EAEtE,QAAO,MADgB,KAAK,KAAK,IAAuB,qBAAqB,OAAO,EAAA,CACpE;CAClB;;;;;;;;CASA,MAAM,QAAQ,QAAyC;EAErD,QAAO,MADgB,KAAK,KAAK,IAAoB,sBAAsB,QAAQ,EAAA,CACnE;CAClB;;;;;;;;CASA,MAAM,kBAAkB,QAAkF;EACxG,MAAM,cAAc,IAAI,gBAAgB;EACxC,IAAI,QAAQ,OAAO,YAAY,IAAI,SAAS,OAAO,MAAM,SAAS,CAAC;EACnE,IAAI,QAAQ,QAAQ,YAAY,IAAI,UAAU,OAAO,OAAO,SAAS,CAAC;EAEtE,MAAM,QAAQ,YAAY,SAAS,IAAI,IAAI,YAAY,SAAS,MAAM;EAEtE,QAAO,MADgB,KAAK,KAAK,IAA+B,6BAA6B,OAAO,EAAA,CACpF;CAClB;;;;;;;;CASA,MAAM,gBAAgB,QAAiD;EAErE,QAAO,MADgB,KAAK,KAAK,IAA4B,8BAA8B,QAAQ,EAAA,CACnF;CAClB;;;;;;;CAQA,MAAM,eAA0C;EAE9C,QAAO,MADgB,KAAK,KAAK,IAAsB,wBAAwB,EAAA,CAC/D;CAClB;;;;;;;CAQA,MAAM,iBAA0C;EAE9C,QAAO,MADgB,KAAK,KAAK,IAAoB,mBAAmB,EAAA,CACxD;CAClB;;;;;CAMA,MAAM,qBAAqB,SAA6D;EAKtF,QAAO,MAJgB,KAAK,KAAK,KAA0B,gCAAgC;GACzF,GAAG;GACH,QAAQ,QAAQ,UAAU,CAAC;EAC7B,CAAC,EAAA,CACe;CAClB;;;;;;;;CASA,MAAM,WAAW,SAAqD;EAEpE,QAAO,MADgB,KAAK,KAAK,KAAqB,sBAAsB,OAAO,EAAA,CACnE;CAClB;;;;;;;;;CAUA,MAAM,WAAW,QAAgB,SAAqD;EAEpF,QAAO,MADgB,KAAK,KAAK,MAAsB,sBAAsB,UAAU,OAAO,EAAA,CAC9E;CAClB;;;;;;;;CASA,MAAM,mBAAmB,SAAqE;EAE5F,QAAO,MADgB,KAAK,KAAK,KAA6B,8BAA8B,OAAO,EAAA,CACnF;CAClB;;;;;;;;;CAUA,MAAM,mBAAmB,QAAgB,SAAqE;EAE5G,QAAO,MADgB,KAAK,KAAK,MAA8B,8BAA8B,UAAU,OAAO,EAAA,CAC9F;CAClB;;;;;;;;CASA,MAAM,kBAAkB,SAA4D;EAElF,QAAO,MADgB,KAAK,KAAK,MAAsB,qBAAqB,OAAO,EAAA,CACnE;CAClB;;;;;;;CAQA,MAAM,WAAW,QAA+B;EAC9C,MAAM,KAAK,KAAK,OAAO,sBAAsB,QAAQ;CACvD;;;;;;;CAQA,MAAM,mBAAmB,QAA+B;EACtD,MAAM,KAAK,KAAK,OAAO,8BAA8B,QAAQ;CAC/D;AACF;;;;;;;;;;ACpUA,IAAa,oBAAb,MAA+B;CAC7B,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;;;;;;;;;;;;;CAcvC,MAAa,cAAc,YAAsC;EAE/D,QAAO,MADgB,KAAK,KAAK,IAA+B,WAAW,EAAA,CAC3D,KAAK,YAAY,SAAS,UAAU;CACtD;;;;;;;;;;;;;CAcA,MAAa,kBAAqC;EAEhD,QAAO,MADgB,KAAK,KAAK,IAA+B,WAAW,EAAA,CAC3D,KAAK;CACvB;;;;;;;;;;;;CAaA,MAAa,WAAW,SAAmC;EAEzD,QAAO,MADgB,KAAK,KAAK,IAAmC,WAAW,EAAA,CAC/D,KAAK,UAAU,SAAS,OAAO,KAAK;CACtD;;;;;;;;;;;;CAaA,MAAa,UAAkC;EAE7C,QAAO,MADgB,KAAK,KAAK,IAA6B,WAAW,EAAA,CACzD,KAAK;CACvB;;;;;;;;;;;;;;CAeA,MAAa,IAAI,WAAmB,UAAkB,UAAoC;EACxF,OAAO,KAAK,cAAc,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU;CAClE;;;;;;;;;;;;;;CAeA,MAAa,YAAY,OAAiC;EACxD,OAAO,KAAK,cAAc,gBAAgB,MAAM,QAAQ;CAC1D;;;;;;;;;;;;;;CAeA,MAAa,WAAW,OAAiC;EACvD,OAAO,KAAK,cAAc,gBAAgB,MAAM,OAAO;CACzD;;;;;;;;;;;;;;CAeA,MAAa,WAAW,OAAiC;EACvD,OAAO,KAAK,cAAc,gBAAgB,MAAM,OAAO;CACzD;;;;;;;;;;;;;;CAeA,MAAa,iBAAiB,WAAqC;EACjE,OAAO,KAAK,cAAc,WAAW,UAAU,QAAQ;CACzD;;;;;;;;;;;;CAaA,MAAa,0BAA0B,WAAsC;EAE3E,QAAO,MADsB,KAAK,gBAAgB,EAAA,CAC5B,QAAQ,MAAM,EAAE,WAAW,GAAG,UAAU,EAAE,CAAC;CACnE;;;;;;;;;;CAeA,YAAmB,OAA0B;EAC3C,IAAI;GACF,MAAM,QAAQ,MAAM,MAAM,GAAG;GAC7B,IAAI,MAAM,WAAW,GACnB,MAAM,IAAI,MAAM,oBAAoB;GAGtC,MAAM,UAAU,MAAM;GACtB,MAAM,UAAU,KAAK,QAAQ,QAAQ,MAAM,GAAG,CAAC,CAAC,QAAQ,MAAM,GAAG,CAAC;GAClE,OAAO,KAAK,MAAM,OAAO;EAC3B,SAAS,OAAO;GACd,MAAM,IAAI,MAAM,yBAAyB,iBAAiB,QAAQ,MAAM,UAAU,iBAAiB;EACrG;CACF;;;;;;;;;CAUA,uBAA8B,OAAe,YAA6B;EAExE,OADe,KAAK,YAAY,KACpB,CAAC,CAAC,aAAa,SAAS,UAAU,KAAK;CACrD;;;;;;;;;;;CAYA,aAAoB,OAAe,WAAmB,UAAkB,UAA2B;EACjG,OAAO,KAAK,uBAAuB,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU;CAClF;;;;;;;;;CAUA,qBAA4B,OAAe,OAAwB;EACjE,OAAO,KAAK,uBAAuB,OAAO,gBAAgB,MAAM,QAAQ;CAC1E;;;;;;;;;CAUA,oBAA2B,OAAe,OAAwB;EAChE,OAAO,KAAK,uBAAuB,OAAO,gBAAgB,MAAM,OAAO;CACzE;;;;;;;;;CAUA,oBAA2B,OAAe,OAAwB;EAChE,OAAO,KAAK,uBAAuB,OAAO,gBAAgB,MAAM,OAAO;CACzE;;;;;;;;;CAUA,0BAAiC,OAAe,WAA4B;EAC1E,OAAO,KAAK,uBAAuB,OAAO,WAAW,UAAU,QAAQ;CACzE;;;;;;;;CASA,2BAAkC,OAAyB;EAEzD,OADe,KAAK,YAAY,KACpB,CAAC,CAAC,eAAe,CAAC;CAChC;;;;;;;;;;;;;CAcA,gBAAuB,YAId;EACP,MAAM,QAAQ,WAAW,MAAM,wBAAwB;EACvD,IAAI,CAAC,OACH,OAAO;EAGT,OAAO;GACL,WAAW,MAAM;GACjB,UAAU,MAAM;GAChB,UAAU,MAAM;EAClB;CACF;;;;;;;;;CAUA,mCAA0C,OAAe,WAA6B;EAEpF,OADuB,KAAK,2BAA2B,KACnC,CAAC,CAAC,QAAQ,MAAM,EAAE,WAAW,GAAG,UAAU,EAAE,CAAC;CACnE;AACF;;;;;;;;;;;;;;;;;;;AC3SA,IAAa,iBAAb,MAA4B;CAC1B,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAoB;;;;CAKxC,cAAuB;EACrB,OACE,OAAO,WAAW,eAClB,OAAO,wBAAwB,KAAA,KAC/B,OAAO,OAAO,wBAAwB;CAE1C;;;;CAKA,MAAM,mCAAqD;EACzD,IAAI,CAAC,KAAK,YAAY,GACpB,OAAO;EAET,OAAO,oBAAoB,8CAA8C;CAC3E;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BA,MAAM,cAAc,aAA6D;EAK/E,QAAO,MAJgB,KAAK,KAAK,KAC/B,qCACA,EAAE,MAAM,YAAY,CACtB,EAAA,CACgB;CAClB;;;;CAKA,MAAM,OAA+B;EAEnC,QAAO,MADgB,KAAK,KAAK,IAAmB,oBAAoB,EAAA,CACxD;CAClB;;;;CAKA,MAAM,WAAW,WAAmB,MAAoC;EAItE,QAAO,MAHgB,KAAK,KAAK,MAAmB,sBAAsB,aAAa,EACrF,KACF,CAAC,EAAA,CACe;CAClB;;;;CAKA,MAAM,OAAO,WAAmD;EAE9D,QAAO,MADgB,KAAK,KAAK,OAA8B,sBAAsB,WAAW,EAAA,CAChF;CAClB;;;;;CAMA,MAAM,eAAe,aAAqB,YAA8E;EAQtH,QAAO,MAPgB,KAAK,KAAK,KAC/B,sCACA;GACE,cAAc;GACd;EACF,CACF,EAAA,CACgB;CAClB;;;;;CAMA,MAAM,SAAS,aAAuC;EACpD,IAAI,CAAC,KAAK,YAAY,GACpB,MAAM,IAAI,MAAM,2CAA2C;EAI7D,MAAM,YAAY,MAAM,KAAK,cAAc,WAAW;EAGtD,MAAM,gBAA2C,EAC/C,WAAW;GACT,GAAG,UAAU;GACb,WAAW,KAAK,sBAAsB,UAAU,QAAQ,SAA8B;GACtF,MAAM;IACJ,GAAG,UAAU,QAAQ;IACrB,IAAI,KAAK,sBAAsB,UAAU,QAAQ,KAAK,EAAuB;GAC/E;GACA,oBAAoB,UAAU,QAAQ,oBAAoB,KAAK,UAAe;IAC5E,GAAG;IACH,IAAI,KAAK,sBAAsB,KAAK,EAAuB;GAC7D,EAAE;EACJ,EACF;EAGA,MAAM,aAAa,MAAM,UAAU,YAAY,OAAO,aAAa;EAEnE,IAAI,CAAC,cAAc,EAAE,sBAAsB,sBACzC,MAAM,IAAI,MAAM,0BAA0B;EAG5C,IAAI,EAAE,WAAW,oBAAoB,mCACnC,MAAM,IAAI,MAAM,kCAAkC;EAIpD,MAAM,iBAA2C;GAC/C,IAAI,WAAW;GACf,OAAO,KAAK,sBAAsB,IAAI,WAAW,WAAW,KAAK,CAAC;GAClE,UAAU;IACR,gBAAgB,KAAK,sBAAsB,IAAI,WAAW,WAAW,SAAS,cAAc,CAAC;IAC7F,mBAAmB,KAAK,sBAAsB,IAAI,WAAW,WAAW,SAAS,iBAAiB,CAAC;IACnG,YAAY,WAAW,SAAS,gBAAgB;GAClD;GACA,yBAAyB,WAAW;GACpC,wBAAwB,WAAW,0BAA0B;GAC7D,MAAM,WAAW;EACnB;EAKA,QAAO,MAFsB,KAAK,eAAe,UAAU,cAAc,cAAc,EAAA,CAEjE;CACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BA,MAAM,kBAAkB,OAAe,SAKD;EAKpC,QAAO,MAJgB,KAAK,KAAK,KAC/B,yCACA;GAAE;GAAO,GAAG;EAAQ,CACtB,EAAA,CACgB;CAClB;;;;;CAMA,MAAM,mBAAmB,aAAqB,YAA4E;EAQxH,QAAO,MAPgB,KAAK,KAAK,KAC/B,0CACA;GACE,cAAc;GACd;EACF,CACF,EAAA,CACgB;CAClB;;;;;CAMA,MAAM,MAAM,OAAe,SAKY;EACrC,IAAI,CAAC,KAAK,YAAY,GACpB,MAAM,IAAI,MAAM,2CAA2C;EAI7D,MAAM,YAAY,MAAM,KAAK,kBAAkB,OAAO,OAAO;EAG7D,MAAM,aAAuC,EAC3C,WAAW;GACT,GAAG,UAAU;GACb,WAAW,KAAK,sBAAsB,UAAU,QAAQ,SAA8B;GACtF,kBAAkB,UAAU,QAAQ,kBAAkB,KAAK,UAAe;IACxE,GAAG;IACH,IAAI,KAAK,sBAAsB,KAAK,EAAuB;GAC7D,EAAE;EACJ,EACF;EAGA,MAAM,aAAa,MAAM,UAAU,YAAY,IAAI,UAAU;EAE7D,IAAI,CAAC,cAAc,EAAE,sBAAsB,sBACzC,MAAM,IAAI,MAAM,uBAAuB;EAGzC,IAAI,EAAE,WAAW,oBAAoB,iCACnC,MAAM,IAAI,MAAM,kCAAkC;EAIpD,MAAM,iBAA6C;GACjD,IAAI,WAAW;GACf,OAAO,KAAK,sBAAsB,IAAI,WAAW,WAAW,KAAK,CAAC;GAClE,UAAU;IACR,gBAAgB,KAAK,sBAAsB,IAAI,WAAW,WAAW,SAAS,cAAc,CAAC;IAC7F,mBAAmB,KAAK,sBAAsB,IAAI,WAAW,WAAW,SAAS,iBAAiB,CAAC;IACnG,WAAW,KAAK,sBAAsB,IAAI,WAAW,WAAW,SAAS,SAAS,CAAC;IACnF,YAAY,WAAW,SAAS,aAC5B,KAAK,sBAAsB,IAAI,WAAW,WAAW,SAAS,UAAU,CAAC,IACzE,KAAA;GACN;GACA,yBAAyB,WAAW;GACpC,wBAAwB,WAAW,0BAA0B;GAC7D,MAAM,WAAW;EACnB;EAGA,OAAO,KAAK,mBAAmB,UAAU,cAAc,cAAc;CACvE;;;;CAKA,sBAA8B,WAA+B;EAE3D,MAAM,UAAU,IAAI,QAAQ,IAAK,UAAU,SAAS,KAAM,CAAC;EAC3D,MAAM,SAAS,UAAU,QAAQ,MAAM,GAAG,CAAC,CAAC,QAAQ,MAAM,GAAG,IAAI;EAEjE,MAAM,UAAU,KAAK,MAAM;EAC3B,MAAM,cAAc,IAAI,WAAW,QAAQ,MAAM;EAEjD,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,EAAE,GACpC,YAAY,KAAK,QAAQ,WAAW,CAAC;EAGvC,OAAO;CACT;;;;CAKA,sBAA8B,OAA2B;EACvD,IAAI,SAAS;EACb,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,YAAY,KACpC,UAAU,OAAO,aAAa,MAAM,EAAE;EAIxC,OADe,KAAK,MACR,CAAC,CAAC,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,MAAM,EAAE;CACxE;AACF;;;;;;AC1SA,IAAa,aAAb,MAAwB;CACtB,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;;;;;;;CAQvC,MAAM,QAAQ,MAAoD;EAKhE,QAAO,MAJgB,KAAK,KAAK,KAAK,gCAAgC;GACpE,GAAG;GACH,UAAU,KAAK,YAAY,KAAK;EAClC,CAAC,EAAA,CACe;CAClB;;;;;;;;;;CAWA,mBAAmB,OAAe,aAAsB,OAAwB;EAC9E,MAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,CAAC;EAC5C,IAAI,aACF,OAAO,OAAO,gBAAgB,WAAW;EAE3C,IAAI,OACF,OAAO,OAAO,SAAS,KAAK;EAE9B,OAAO,+BAA+B,OAAO,SAAS;CACxD;;;;;;;;;CAUA,MAAM,OAAO,OAAe,aAAsB,OAA8B;EAC9E,MAAM,SAAS,IAAI,gBAAgB,EAAE,MAAM,CAAC;EAC5C,IAAI,aACF,OAAO,OAAO,gBAAgB,WAAW;EAE3C,IAAI,OACF,OAAO,OAAO,SAAS,KAAK;EAI9B,QAAO,MADgB,KAAK,KAAK,IAAI,+BAA+B,OAAO,SAAS,GAAG,EAAA,CACvE;CAClB;;;;;;;;CASA,mBAAmB,OAAe,aAAsB,OAAwB;EAC9E,OAAO,KAAK,mBAAmB,OAAO,aAAa,KAAK;CAC1D;AACF;;;;;;ACxGA,IAAa,gBAAb,MAA2B;CACzB,YAAY,MAA0B;EAAlB,KAAA,OAAA;CAAmB;;;;;;;;;;;;;;;CAgBvC,MAAa,WAAW,QAAiD;EAEvE,QAAO,MADgB,KAAK,KAAK,IAA4B,uBAAuB,QAAQ,EAAA,CAC5E;CAClB;;;;;;;;;;;;;;;;;;;;;CAsBA,MAAa,WACX,QACA,UAA6B,CAAC,GACD;EAK7B,QAAO,MAJgB,KAAK,KAAK,OAC/B,uBAAuB,UACvB,OACF,EAAA,CACgB;CAClB;AACF;;;;;;;;;;;;;;;;;;;ACUA,IAAa,YAAb,MAAuB;CAgErB,YAAY,SAA2B;EACrC,KAAK,OAAO,gBAAgB,QAAQ,OAAO;EAG3C,KAAK,UAAU,IAAI,eACjB,eAAe,QAAQ,OAAO,GAC9B,OAAO,iBAAiB;GAEtB,QAAO,MADW,KAAK,KAAK,KAAK,qBAAqB,EAAE,eAAe,aAAa,CAAC,EAAA,CAC1E;EACb,GACA;GACE,kBAAkB,QAAQ,iBAAiB;GAC3C,oBAAoB,QAAQ;EAC9B,CACF;EAGA,KAAK,KAAK,kBAAkB,KAAK,OAAO;EAIxC,KAAK,YAAY,IAAI,gBAAgB,KAAK,IAAI;EAC9C,KAAK,OAAO,IAAI,WAAW,KAAK,MAAM,KAAK,OAAO;EAClD,KAAK,OAAO,IAAI,WAAW,KAAK,IAAI;EACpC,KAAK,gBAAgB,IAAI,oBAAoB,KAAK,IAAI;EACtD,KAAK,WAAW,IAAI,eAAe,KAAK,IAAI;EAC5C,KAAK,cAAc,IAAI,kBAAkB,KAAK,IAAI;EAClD,KAAK,WAAW,IAAI,eAAe,KAAK,IAAI;EAC5C,KAAK,aAAa,IAAI,iBAAiB,KAAK,IAAI;EAChD,KAAK,cAAc,IAAI,kBAAkB,KAAK,IAAI;EAClD,KAAK,WAAW,IAAI,eAAe,KAAK,IAAI;EAC5C,KAAK,aAAa,IAAI,WAAW,KAAK,IAAI;EAC1C,KAAK,UAAU,IAAI,cAAc,KAAK,IAAI;EAG1C,IAAI,QAAQ,QACV,KAAK,UAAU,QAAQ,MAAM;EAI/B,IAAI,QAAQ,OACV,KAAK,QAAQ,WAAW,EAAE,cAAc,QAAQ,MAAM,CAAC;OAGvD,KAAK,QAAQ,YAAY,CAAC,CAAC,MAAM,QAAQ,KAAK;CAElD;;;;;;;;;;;;;;;;;;;;CAqBA,aAAoB,OAA4B;EAC9C,IAAI,OAAO;GACT,KAAK,KAAK,SAAS,QAAQ,OAAO,mBAAmB,UAAU;GAE/D,KAAK,QAAQ,WAAW,EAAE,cAAc,MAAM,CAAC;EACjD,OAAO;GACL,OAAO,KAAK,KAAK,SAAS,QAAQ,OAAO;GACzC,KAAK,QAAQ,aAAa;EAC5B;CACF;;;;;;;;;;;;;;;;CAiBA,MAAa,WAAW,QAAyE;EAC/F,MAAM,KAAK,QAAQ,WAAW,MAAM;CACtC;;;;;;;;;;;;;;;;CAiBA,UAAiB,QAA6B;EAC5C,IAAI,QACF,KAAK,KAAK,SAAS,QAAQ,OAAO,eAAe;OAEjD,OAAO,KAAK,KAAK,SAAS,QAAQ,OAAO;CAE7C;;;;CAKA,aAA4B;EAC1B,OAAO,KAAK,KAAK,SAAS,WAAW;CACvC;;;;;;;;;;;;;CAcA,aAA4B;EAE1B,OAAO,GADS,KAAK,WAAW,CAAC,CAAC,QAAQ,OAAO,EACjC,EAAE;CACpB;;;;CAKA,kBAAkC;EAChC,OAAO,KAAK,QAAQ,gBAAgB;CACtC;;;;;;;;;;;;;;;;;;CAmBA,kBAAyB,UAA8C;EACrE,OAAO,KAAK,QAAQ,UAAU,QAAQ;CACxC;;;;;;CAOA,MAAa,WAAmC;EAC9C,OAAO,KAAK,QAAQ,SAAS;CAC/B;AACF"}
|